From c66d993fc725a8918d931297f4c4772874b914b0 Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Mon, 12 Dec 2022 14:29:23 +0100 Subject: [PATCH 001/114] Update all development Yarn dependencies (2022-12-12) (PR #4365) Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com> --- package.json | 10 ++++----- yarn.lock | 62 ++++++++++++++++++++++++++-------------------------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/package.json b/package.json index 800feffa99..e1dea8a802 100644 --- a/package.json +++ b/package.json @@ -116,18 +116,18 @@ "css-loader": "^6.7.2", "cssnano": "^5.1.14", "devtools-license-check": "^0.9.0", - "eslint": "^8.27.0", + "eslint": "^8.29.0", "eslint-config-prettier": "^8.5.0", "eslint-import-resolver-alias": "^1.1.2", "eslint-plugin-flowtype": "^8.0.3", "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jest": "^27.1.5", + "eslint-plugin-jest": "^27.1.6", "eslint-plugin-jest-dom": "^4.0.3", "eslint-plugin-jest-formatting": "^3.1.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.31.11", "eslint-plugin-testing-library": "^5.9.1", - "fake-indexeddb": "^4.0.0", + "fake-indexeddb": "^4.0.1", "fetch-mock-jest": "^1.5.1", "file-loader": "^6.2.0", "flow-bin": "^0.96.0", @@ -146,12 +146,12 @@ "node-fetch": "^2.6.7", "npm-run-all": "^4.1.5", "postcss": "^8.4.16", - "postcss-loader": "^7.0.1", + "postcss-loader": "^7.0.2", "prettier": "^2.8.0", "raw-loader": "^4.0.2", "rimraf": "^3.0.2", "style-loader": "^3.3.1", - "stylelint": "^14.15.0", + "stylelint": "^14.16.0", "stylelint-config-idiomatic-order": "^9.0.0", "stylelint-config-prettier": "^9.0.4", "stylelint-config-standard": "^29.0.0", diff --git a/yarn.lock b/yarn.lock index b7950daf4b..fe0ced8b9c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4677,10 +4677,10 @@ eslint-plugin-jest-formatting@^3.1.0: resolved "https://registry.yarnpkg.com/eslint-plugin-jest-formatting/-/eslint-plugin-jest-formatting-3.1.0.tgz#b26dd5a40f432b642dcc880021a771bb1c93dcd2" integrity sha512-XyysraZ1JSgGbLSDxjj5HzKKh0glgWf+7CkqxbTqb7zEhW7X2WHo5SBQ8cGhnszKN+2Lj3/oevBlHNbHezoc/A== -eslint-plugin-jest@^27.1.5: - version "27.1.5" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.1.5.tgz#16fad619cfee6cdf73d56098fbed0761e1f653ce" - integrity sha512-CK2dekZ5VBdzsOSOH5Fc1rwC+cWXjkcyrmf1RV714nDUDKu+o73TTJiDxpbILG8PtPPpAAl3ywzh5QA7Ft0mjA== +eslint-plugin-jest@^27.1.6: + version "27.1.6" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.1.6.tgz#361d943f07d1978838e6b852c44a579f3879e332" + integrity sha512-XA7RFLSrlQF9IGtAmhddkUkBuICCTuryfOTfCSWcZHiHb69OilIH05oozH2XA6CEOtztnOd0vgXyvxZodkxGjg== dependencies: "@typescript-eslint/utils" "^5.10.0" @@ -4812,10 +4812,10 @@ eslint@^6.0.1: text-table "^0.2.0" v8-compile-cache "^2.0.3" -eslint@^8.27.0: - version "8.27.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.27.0.tgz#d547e2f7239994ad1faa4bb5d84e5d809db7cf64" - integrity sha512-0y1bfG2ho7mty+SiILVf9PfuRA49ek4Nc60Wmmu62QlobNR+CeXa4xXIJgcuwSQgZiWaPH+5BDsctpIW0PR/wQ== +eslint@^8.29.0: + version "8.29.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.29.0.tgz#d74a88a20fb44d59c51851625bc4ee8d0ec43f87" + integrity sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg== dependencies: "@eslint/eslintrc" "^1.3.3" "@humanwhocodes/config-array" "^0.11.6" @@ -5044,10 +5044,10 @@ external-editor@^3.0.3: iconv-lite "^0.4.24" tmp "^0.0.33" -fake-indexeddb@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fake-indexeddb/-/fake-indexeddb-4.0.0.tgz#1dfb2023a3be175e35a6d84975218b432041934d" - integrity sha512-oCfWSJ/qvQn1XPZ8SHX6kY3zr1t+bN7faZ/lltGY0SBGhFOPXnWf0+pbO/MOAgfMx6khC2gK3S/bvAgQpuQHDQ== +fake-indexeddb@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/fake-indexeddb/-/fake-indexeddb-4.0.1.tgz#09bb2468e21d0832b2177e894765fb109edac8fb" + integrity sha512-hFRyPmvEZILYgdcLBxVdHLik4Tj3gDTu/g7s9ZDOiU3sTNiGx+vEu1ri/AMsFJUZ/1sdRbAVrEcKndh3sViBcA== dependencies: realistic-structured-clone "^3.0.0" @@ -6217,10 +6217,10 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.0.0, ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== +ignore@^5.0.0, ignore@^5.2.0, ignore@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.1.tgz#c2b1f76cb999ede1502f3a226a9310fdfe88d46c" + integrity sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA== immediate@~3.0.5: version "3.0.6" @@ -9565,14 +9565,14 @@ postcss-discard-overridden@^5.1.0: resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e" integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw== -postcss-loader@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.0.1.tgz#4c883cc0a1b2bfe2074377b7a74c1cd805684395" - integrity sha512-VRviFEyYlLjctSM93gAZtcJJ/iSkPZ79zWbN/1fSH+NisBByEiVLqpdVDrPLVSi8DX0oJo12kL/GppTBdKVXiQ== +postcss-loader@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.0.2.tgz#b53ff44a26fba3688eee92a048c7f2d4802e23bb" + integrity sha512-fUJzV/QH7NXUAqV8dWJ9Lg4aTkDCezpTS5HgJ2DvqznexTbSTxgi/dTECvTZ15BwKTtk8G/bqI/QTu2HPd3ZCg== dependencies: cosmiconfig "^7.0.0" klona "^2.0.5" - semver "^7.3.7" + semver "^7.3.8" postcss-media-query-parser@^0.2.3: version "0.2.3" @@ -9753,10 +9753,10 @@ postcss-safe-parser@^6.0.0: resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz#bb4c29894171a94bc5c996b9a30317ef402adaa1" integrity sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ== -postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: - version "6.0.10" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" - integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== +postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: + version "6.0.11" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz#2e41dc39b7ad74046e1615185185cd0b17d0c8dc" + integrity sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" @@ -11541,10 +11541,10 @@ stylelint-prettier@^2.0.0: dependencies: prettier-linter-helpers "^1.0.0" -stylelint@^14.15.0: - version "14.15.0" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-14.15.0.tgz#4df55078e734869f81f6b85bbec2d56a4b478ece" - integrity sha512-JOgDAo5QRsqiOZPZO+B9rKJvBm64S0xasbuRPAbPs6/vQDgDCnZLIiw6XcAS6GQKk9k1sBWR6rmH3Mfj8OknKg== +stylelint@^14.16.0: + version "14.16.0" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-14.16.0.tgz#8e1a424f4b9852e59089f95de306734d70e5048b" + integrity sha512-X6uTi9DcxjzLV8ZUAjit1vsRtSwcls0nl07c9rqOPzvpA8IvTX/xWEkBRowS0ffevRrqkHa/ThDEu86u73FQDg== dependencies: "@csstools/selector-specificity" "^2.0.2" balanced-match "^2.0.0" @@ -11559,7 +11559,7 @@ stylelint@^14.15.0: globby "^11.1.0" globjoin "^0.1.4" html-tags "^3.2.0" - ignore "^5.2.0" + ignore "^5.2.1" import-lazy "^4.0.0" imurmurhash "^0.1.4" is-plain-object "^5.0.0" @@ -11573,7 +11573,7 @@ stylelint@^14.15.0: postcss-media-query-parser "^0.2.3" postcss-resolve-nested-selector "^0.1.1" postcss-safe-parser "^6.0.0" - postcss-selector-parser "^6.0.10" + postcss-selector-parser "^6.0.11" postcss-value-parser "^4.2.0" resolve-from "^5.0.0" string-width "^4.2.3" From c9b532e58aa7d8af5f0a88480f61828407168d06 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Tue, 13 Dec 2022 15:22:07 +0100 Subject: [PATCH 002/114] Add some more content to the home page, about Android profiling as well as opening files from 3rd party tools (PR #4360) Fixes #4351 --- locales/en-US/app.ftl | 16 ++- src/components/app/Home.js | 76 +++++++++++++- .../__snapshots__/Home.test.js.snap | 99 ++++++++++++++++++- 3 files changed, 184 insertions(+), 7 deletions(-) diff --git a/locales/en-US/app.ftl b/locales/en-US/app.ftl index 833b51b6a4..36feb53c0c 100644 --- a/locales/en-US/app.ftl +++ b/locales/en-US/app.ftl @@ -12,6 +12,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox for Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly @@ -257,6 +258,11 @@ Home--menu-button-instructions = Enable the profiler menu button to start recording a performance profile in { -firefox-brand-name }, then analyze it and share it with profiler.firefox.com. +Home--profile-firefox-android-instructions = + You can also profile { -firefox-android-brand-name }. For more + information, please consult this documentation: + Profiling { -firefox-android-brand-name } directly on device. + # The word WebChannel should not be translated. # This message can be seen on https://main--perf-html.netlify.app/ in the tooltip # of the "Enable Firefox Profiler menu button" button. @@ -277,7 +283,6 @@ Home--record-instructions = keyboard shortcuts. The icon is blue when a profile is recording. Hit Capture to load the data into profiler.firefox.com. -Home--instructions-title = How to view and record profiles Home--instructions-content = Recording performance profiles requires { -firefox-brand-name }. However, existing profiles can be viewed in any modern browser. @@ -290,6 +295,15 @@ Home--additional-content-content = You can drag and drop a prof Home--compare-recordings-info = You can also compare recordings. Open the comparing interface. Home--your-recent-uploaded-recordings-title = Your recent uploaded recordings +# We replace the elements such as and with links to the +# documentation to use these tools. +Home--load-files-from-other-tools = + The { -profiler-brand-name } can also import profiles from other profilers, such as + Linux perf, Android SimplePerf, the + Chrome performance panel, Android Studio, or + any file using the dhat format. Learn how to write your + own importer. + ## IdleSearchField ## The component that is used for all the search inputs in the application. diff --git a/src/components/app/Home.js b/src/components/app/Home.js index 492c82e1ef..94f06dc81f 100644 --- a/src/components/app/Home.js +++ b/src/components/app/Home.js @@ -355,6 +355,20 @@ class HomeImpl extends React.PureComponent {

)} + + ), + }} + > +

+ You can also profile Firefox for Android. For more information, + please consult this documentation:{' '} + Profiling Firefox for Android directly on device. +

+
{/* end of grid container */} @@ -393,6 +407,20 @@ class HomeImpl extends React.PureComponent {

{this._renderShortcuts()} + + ), + }} + > +

+ You can also profile Firefox for Android. For more information, + please consult this documentation:{' '} + Profiling Firefox for Android directly on device. +

+
{/* end of grid container */} @@ -417,9 +445,6 @@ class HomeImpl extends React.PureComponent { {/* Right column: instructions */}
- -

How to view and record profiles

-
{ browser.

+ + ), + }} + > +

+ You can also profile Firefox for Android. For more information, + please consult this documentation:{' '} + Profiling Firefox for Android directly on device. +

+
{/* end of grid container */} @@ -514,6 +553,37 @@ class HomeImpl extends React.PureComponent { } /> + + ), + simpleperf: ( + + ), + androidstudio: ( + + ), + dhat: ( + + ), + write: ( + + ), + }} + > +

+ The Firefox Profiler can also import profiles from other + profilers, such as Linux perf, + Android SimplePerf, the Chrome + performance panel,{' '} + Android Studio, or any file + using the dhat format.{' '} + Learn how to write your own importer. +

+
+ +

+ You can also profile ⁨Firefox for Android⁩. For more +information, please consult this documentation: + + + Profiling ⁨Firefox for Android⁩ directly on device + + . +

@@ -141,6 +152,43 @@ profile in ⁨Firefox⁩, then analyze it and share it with profiler.firefox.com +

+ The ⁨Firefox Profiler⁩ can also import profiles from other profilers, such as + + + Linux perf + + , + + Android SimplePerf + + , the +Chrome performance panel, + + Android Studio + + , or +any file using the + + dhat format + + . + + Learn how to write your +own importer + + . +

You can also compare recordings. Documentation -

- How to view and record profiles -

Recording performance profiles requires +

+ You can also profile ⁨Firefox for Android⁩. For more +information, please consult this documentation: + + + Profiling ⁨Firefox for Android⁩ directly on device + + . +

@@ -332,6 +388,43 @@ However, existing profiles can be viewed in any modern browser. +

+ The ⁨Firefox Profiler⁩ can also import profiles from other profilers, such as + + + Linux perf + + , + + Android SimplePerf + + , the +Chrome performance panel, + + Android Studio + + , or +any file using the + + dhat format + + . + + Learn how to write your +own importer + + . +

You can also compare recordings. Date: Wed, 14 Dec 2022 08:33:52 +0000 Subject: [PATCH 003/114] Pontoon: Update Frisian (fy-NL) localization of Firefox Profiler Co-authored-by: Fjoerfoks --- locales/fy-NL/app.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/fy-NL/app.ftl b/locales/fy-NL/app.ftl index 05b3327de9..9267c6b5c5 100644 --- a/locales/fy-NL/app.ftl +++ b/locales/fy-NL/app.ftl @@ -15,6 +15,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox foar Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly @@ -260,7 +261,6 @@ Home--record-instructions = Klik om te starten mei it meitsjen fan in profyl op de profylknop of brûk de fluchtoetsen. It piktogram is blau as der in profyl opnommen wurdt. Klik op Fêstlizze om de gegevens yn profiler.firefox.com te laden. -Home--instructions-title = Profilen besjen en opnimme Home--instructions-content = It opnimmen fan prestaasjeprofilen fereasket { -firefox-brand-name }. Besteande profilen kinne echter besjoen wurde yn elke moderne browser. From de4555c165308343319af4e3486b30fe3b1292fa Mon Sep 17 00:00:00 2001 From: Fjoerfoks Date: Wed, 14 Dec 2022 08:33:55 +0000 Subject: [PATCH 004/114] Pontoon: Update Dutch (nl) localization of Firefox Profiler Co-authored-by: Fjoerfoks --- locales/nl/app.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/nl/app.ftl b/locales/nl/app.ftl index 1257cdd784..be14213c81 100644 --- a/locales/nl/app.ftl +++ b/locales/nl/app.ftl @@ -15,6 +15,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox voor Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly @@ -260,7 +261,6 @@ Home--record-instructions = Klik om te starten met het maken van een profiel op de profielknop of gebruik de sneltoetsen. Het pictogram is blauw als er een profiel wordt opgenomen. Klik op Vastleggen om de gegevens in profiler.firefox.com te laden. -Home--instructions-title = Profielen bekijken en opnemen Home--instructions-content = Het opnemen van prestatieprofielen vereist { -firefox-brand-name }. Bestaande profielen kunnen echter bekeken worden in elke moderne browser. From f7e0dd761b49f432790a16b6b12160dea25d46ca Mon Sep 17 00:00:00 2001 From: Fjoerfoks Date: Wed, 14 Dec 2022 08:43:14 +0000 Subject: [PATCH 005/114] Pontoon: Update Frisian (fy-NL) localization of Firefox Profiler Co-authored-by: Fjoerfoks --- locales/fy-NL/app.ftl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/locales/fy-NL/app.ftl b/locales/fy-NL/app.ftl index 9267c6b5c5..bf72168f0c 100644 --- a/locales/fy-NL/app.ftl +++ b/locales/fy-NL/app.ftl @@ -244,6 +244,10 @@ Home--menu-button = Menuknop { -profiler-brand-name } ynskeakelje Home--menu-button-instructions = Skeakelje de menuknop Profiler yn om te begjinnen mei it opnimmen fan in prestaasjeprofyl yn { -firefox-brand-name }, analysearje dit en diel it mei profiler.firefox.com. +Home--profile-firefox-android-instructions = + Jo kinne { -firefox-android-brand-name } ek profilearje. Foar mear + ynformaasje, lês dizze dokumintaasje: + { -firefox-android-brand-name } daliks op apparaat profilearje. # The word WebChannel should not be translated. # This message can be seen on https://main--perf-html.netlify.app/ in the tooltip # of the "Enable Firefox Profiler menu button" button. @@ -271,6 +275,14 @@ Home--additional-content-title = Besteande profilen lade Home--additional-content-content = Jo kinne in profylbestân hjirhinne fersleepje om it te laden, of: Home--compare-recordings-info = Jo kinne ek opnamen fergelykje. De fergelikingsinterface iepenje. Home--your-recent-uploaded-recordings-title = Jo resint opladen opnamen +# We replace the elements such as and with links to the +# documentation to use these tools. +Home--load-files-from-other-tools = + De { -profiler-brand-name } kin ek profilen fan oare profilers ymportearje, lykas + Linux-perf, Android SimplePerf, it + Chrome-prestaasjespaniel, Android Studio, of + elk bestân mei it dhat-formaat. Lês hoe’t jo jo + eigen ymportearder skriuwe. ## IdleSearchField ## The component that is used for all the search inputs in the application. From 6dd784964ea8163eeb26287fa156a60144f56cc5 Mon Sep 17 00:00:00 2001 From: Jim Spentzos Date: Wed, 14 Dec 2022 09:43:11 +0000 Subject: [PATCH 006/114] Pontoon: Update Greek (el) localization of Firefox Profiler Co-authored-by: Jim Spentzos --- locales/el/app.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/el/app.ftl b/locales/el/app.ftl index c54435fcb2..e13cead6ac 100644 --- a/locales/el/app.ftl +++ b/locales/el/app.ftl @@ -15,6 +15,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox για Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly @@ -260,7 +261,6 @@ Home--record-instructions = Για να αρχίσει η καταγραφή προφίλ, κάντε κλικ στο αντίστοιχο κουμπί ή χρησιμοποιήστε τις συντομεύσεις πληκτρολογίου. Το εικονίδιο είναι μπλε κατά την καταγραφή ενός προφίλ. Πατήστε το Καταγραφή για να φορτώσετε τα δεδομένα στο profiler.firefox.com. -Home--instructions-title = Τρόπος προβολής και καταγραφής προφίλ Home--instructions-content = Η καταγραφή των προφίλ επιδόσεων απαιτεί το { -firefox-brand-name }. Ωστόσο, τα υπάρχοντα προφίλ μπορούν να προβληθούν σε όλα τα σύγχρονα προγράμματα περιήγησης. From 544ca815249f2de88410e708ee779d4fe616c00d Mon Sep 17 00:00:00 2001 From: "Francesco Lodolo [:flod]" Date: Wed, 14 Dec 2022 09:43:13 +0000 Subject: [PATCH 007/114] Pontoon: Update Italian (it) localization of Firefox Profiler Co-authored-by: Francesco Lodolo [:flod] --- locales/it/app.ftl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/locales/it/app.ftl b/locales/it/app.ftl index 052137329e..4f47858d1d 100644 --- a/locales/it/app.ftl +++ b/locales/it/app.ftl @@ -184,6 +184,7 @@ Home--load-from-url-submit-button = Home--documentation-button = Documentazione Home--menu-button = Attiva il pulsante { -profiler-brand-name } nel menu Home--menu-button-instructions = Attiva il pulsante Profiler nel menu per avviare la registrazione di un profilo delle prestazioni di { -firefox-brand-name }, poi analizzalo e condividilo su profiler.firefox.com. +Home--profile-firefox-android-instructions = È anche possibile creare profili per { -firefox-android-brand-name }. Per ulteriori informazioni, consultare la documentazione Creare un profilo di { -firefox-android-brand-name } direttamente sul dispositivo. # The word WebChannel should not be translated. # This message can be seen on https://main--perf-html.netlify.app/ in the tooltip # of the "Enable Firefox Profiler menu button" button. @@ -193,7 +194,6 @@ Home--enable-button-unavailable = # This message can be seen on https://main--perf-html.netlify.app/ . Home--web-channel-unavailable = Questa istanza del profiler non è stata in grado di connettersi al WebChannel. Normalmente significa che è in esecuzione su un host diverso da quello specificato nell’impostazione devtools.performance.recording.ui-base-url. Se vuoi catturare nuovi profili con questa istanza e assegnarle il controllo programmatico del pulsante del menu del profiler, apri about:config e modifica questa impostazione. Home--record-instructions = Per avviare la profilazione, fai clic sul pulsante per avviare la registrazione oppure utilizza le scorciatoie da tastiera. L’icona diventa blu quando è attiva la registrazione di un profilo. Premi Cattura per caricare i dati su profiler.firefox.com. -Home--instructions-title = Come visualizzare e registrare profili Home--instructions-content = La registrazione dei profili è possibile solo con { -firefox-brand-name }. I profili esistenti possono essere visualizzati con qualsiasi browser. Home--record-instructions-start-stop = Interrompi e avvia la profilatura Home--record-instructions-capture-load = Cattura e carica profilo @@ -202,6 +202,11 @@ Home--additional-content-title = Carica profili esistenti Home--additional-content-content = È possibile trascinare e rilasciare qui un profilo per caricarlo, oppure: Home--compare-recordings-info = È anche possibile confrontare diverse registrazioni. Apri l’interfaccia per il confronto. Home--your-recent-uploaded-recordings-title = Le tue registrazioni caricate di recente +# We replace the elements such as and with links to the +# documentation to use these tools. +Home--load-files-from-other-tools = + { -profiler-brand-name } può anche importare profili da altri profiler, come Linux perf, Android SimplePerf, il + pannello prestazioni di Chrome, Android Studio o qualsiasi file che utilizzi il formato dhat. write>Scopri come creare uno strumento di importazione. ## IdleSearchField ## The component that is used for all the search inputs in the application. From cb152ae8055e05c53820102473e16a152998b126 Mon Sep 17 00:00:00 2001 From: Benoit Leseul Date: Wed, 14 Dec 2022 10:04:55 +0000 Subject: [PATCH 008/114] Pontoon: Update French (fr) localization of Firefox Profiler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Théo Chevalier Co-authored-by: Benoit Leseul --- locales/fr/app.ftl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/locales/fr/app.ftl b/locales/fr/app.ftl index cdfc6087ed..88ce70d9af 100644 --- a/locales/fr/app.ftl +++ b/locales/fr/app.ftl @@ -15,6 +15,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox pour Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly @@ -188,6 +189,10 @@ Home--load-from-url-submit-button = Home--documentation-button = Documentation Home--menu-button = Activer le bouton de menu { -profiler-brand-name } Home--menu-button-instructions = Activez le bouton de menu du profileur pour commencer à enregistrer un profil des performances dans { -firefox-brand-name }, puis analysez-le et partagez-le avec profiler.firefox.com. +Home--profile-firefox-android-instructions = + Vous pouvez également profiler { -firefox-android-brand-name }. + Pour plus d’informations, veuillez consulter cette documentation : + Profilage de { -firefox-android-brand-name } directement sur l’appareil. # The word WebChannel should not be translated. # This message can be seen on https://main--perf-html.netlify.app/ in the tooltip # of the "Enable Firefox Profiler menu button" button. @@ -197,7 +202,6 @@ Home--enable-button-unavailable = # This message can be seen on https://main--perf-html.netlify.app/ . Home--web-channel-unavailable = Cette instance du profileur n’a pas pu se connecter à WebChannel. Généralement, cela signifie qu’il s’exécute sur un hôte différent de celui spécifié dans la préférence devtools.performance.recording.ui-base-url. Si vous souhaitez capturer de nouveaux profils avec cette instance, et lui donner par programmation le contrôle du bouton de menu du profileur, vous pouvez ouvrir about:config et modifier la préférence. Home--record-instructions = Pour démarrer le profilage, cliquez sur le bouton de profilage ou utilisez le raccourci clavier. L’icône est bleue lorsqu’un profil est en cours d’enregistrement. Appuyez sur Capturer pour charger les données dans profiler.firefox.com. -Home--instructions-title = Comment afficher et enregistrer des profils Home--instructions-content = L’enregistrement de profils de performances nécessite { -firefox-brand-name }. Cependant, les profils existants peuvent être consultés dans n’importe quel navigateur moderne. @@ -208,6 +212,14 @@ Home--additional-content-title = Charger des profils existants Home--additional-content-content = Vous pouvez glisser-déposer un fichier de profil ici pour le charger, ou : Home--compare-recordings-info = Vous pouvez également comparer des enregistrements. Ouvrir l’interface de comparaison. Home--your-recent-uploaded-recordings-title = Vos enregistrements récemment envoyés +# We replace the elements such as and with links to the +# documentation to use these tools. +Home--load-files-from-other-tools = + Le { -profiler-brand-name } peut également importer des profils d’autres profileurs, dont + Linux perf, Android SimplePerf, le + Panneau de performances Chrome, Android Studio, ou + tout fichier utilisant le format dhat. Apprenez à écrire votre + propre importateur. ## IdleSearchField ## The component that is used for all the search inputs in the application. From fca810562a0ebd2e6bd9d235904b2233af06b407 Mon Sep 17 00:00:00 2001 From: "Francesco Lodolo [:flod]" Date: Wed, 14 Dec 2022 10:43:33 +0000 Subject: [PATCH 009/114] Pontoon: Update Italian (it) localization of Firefox Profiler Co-authored-by: Francesco Lodolo [:flod] --- locales/it/app.ftl | 1 + 1 file changed, 1 insertion(+) diff --git a/locales/it/app.ftl b/locales/it/app.ftl index 4f47858d1d..a15a3b119a 100644 --- a/locales/it/app.ftl +++ b/locales/it/app.ftl @@ -15,6 +15,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox per Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly From 60a7680258c4cdcfecd7299442c21d7019d5b85b Mon Sep 17 00:00:00 2001 From: Fjoerfoks Date: Wed, 14 Dec 2022 11:53:38 +0000 Subject: [PATCH 010/114] Pontoon: Update Dutch (nl) localization of Firefox Profiler Co-authored-by: Fjoerfoks --- locales/nl/app.ftl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/locales/nl/app.ftl b/locales/nl/app.ftl index be14213c81..6473e17680 100644 --- a/locales/nl/app.ftl +++ b/locales/nl/app.ftl @@ -244,6 +244,10 @@ Home--menu-button = Menuknop { -profiler-brand-name } inschakelen Home--menu-button-instructions = Schakel de menuknop Profiler in om te beginnen met het opnemen van een prestatieprofiel in { -firefox-brand-name }, analyseer dit en deel het met profiler.firefox.com. +Home--profile-firefox-android-instructions = + U kunt ook { -firefox-android-brand-name } profileren. Voor meer + informatie kunt u deze documentatie raadplegen: + { -firefox-android-brand-name } rechtstreeks op apparaat profileren. # The word WebChannel should not be translated. # This message can be seen on https://main--perf-html.netlify.app/ in the tooltip # of the "Enable Firefox Profiler menu button" button. @@ -271,6 +275,14 @@ Home--additional-content-title = Bestaande profielen laden Home--additional-content-content = U kunt een profielbestand hierheen verslepen om het te laden, of: Home--compare-recordings-info = U kunt ook opnamen vergelijken. De vergelijkingsinterface openen. Home--your-recent-uploaded-recordings-title = Uw onlangs geüploade opnamen +# We replace the elements such as and with links to the +# documentation to use these tools. +Home--load-files-from-other-tools = + De { -profiler-brand-name } kan ook profielen van andere profilers importeren, zoals + Linux-perf, Android SimplePerf, het + Chrome-prestatiepaneel, Android Studio of + elk bestand dat de dhat-indeling gebruikt. Leer hoe u uw + eigen importeerder kunt schrijven. ## IdleSearchField ## The component that is used for all the search inputs in the application. From 945ef8b7d3aadf4ad4552a45d20399ed367920a0 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Wed, 14 Dec 2022 14:23:46 +0100 Subject: [PATCH 011/114] Prevent ctrl+wheel events in timeline (PR #4350) --- src/components/shared/Reorderable.js | 14 +++- src/components/timeline/ActiveTabTimeline.js | 12 +++- src/components/timeline/FullTimeline.js | 15 ++++- src/components/timeline/OriginsTimeline.js | 42 +++++++----- src/components/timeline/index.js | 67 +++++++++++++++++++- 5 files changed, 122 insertions(+), 28 deletions(-) diff --git a/src/components/shared/Reorderable.js b/src/components/shared/Reorderable.js index 752bb88482..309a2acbd2 100644 --- a/src/components/shared/Reorderable.js +++ b/src/components/shared/Reorderable.js @@ -27,6 +27,9 @@ type Props = {| // See https://flow.org/en/docs/react/children/ for more information. // Be careful: children need to handle a `style` property. children: React.ChildrenArray>, + // If present, this will be attached to the container added for these + // children. As a reminder, the container will use the tagName defined above. + innerElementRef?: React.Ref, |}; type State = {| @@ -240,7 +243,7 @@ export class Reorderable extends React.PureComponent { } render() { - const { className, order } = this.props; + const { className, order, innerElementRef } = this.props; const children = React.Children.toArray(this.props.children); const orderedChildren = order.map((childIndex) => children[childIndex]); const TagName = this.props.tagName; @@ -248,7 +251,11 @@ export class Reorderable extends React.PureComponent { if (this.state.phase === 'RESTING') { return ( - + {orderedChildren} ); @@ -261,8 +268,9 @@ export class Reorderable extends React.PureComponent { adjustPrecedingBy, adjustSucceedingBy, } = this.state; + return ( - + {orderedChildren.map((child, childIndex) => { const style = { transition: '200ms ease-in-out transform', diff --git a/src/components/timeline/ActiveTabTimeline.js b/src/components/timeline/ActiveTabTimeline.js index 02cc5cabcc..c848698460 100644 --- a/src/components/timeline/ActiveTabTimeline.js +++ b/src/components/timeline/ActiveTabTimeline.js @@ -33,6 +33,11 @@ import type { import type { ConnectedProps } from 'firefox-profiler/utils/connect'; +type OwnProps = {| + // This ref will be added to the inner container. + +innerElementRef?: React.Ref, +|}; + type StateProps = {| +committedRange: StartEndRange, +globalTracks: ActiveTabGlobalTrack[], @@ -43,7 +48,7 @@ type StateProps = {| type Props = {| ...SizeProps, - ...ConnectedProps<{||}, StateProps, {||}>, + ...ConnectedProps, |}; type State = {| @@ -85,6 +90,7 @@ class ActiveTabTimelineImpl extends React.PureComponent { panelLayoutGeneration, globalTracks, globalTrackReferences, + innerElementRef, } = this.props; return ( @@ -102,7 +108,7 @@ class ActiveTabTimelineImpl extends React.PureComponent { initialSelected={this.state.initialSelected} forceLayoutGeneration={this.state.forceLayoutGeneration} > -

    +
      {globalTracks.map((globalTrack, trackIndex) => ( { } } -export const ActiveTabTimeline = explicitConnect<{||}, StateProps, {||}>({ +export const ActiveTabTimeline = explicitConnect({ mapStateToProps: (state) => ({ globalTracks: getActiveTabGlobalTracks(state), globalTrackReferences: getActiveTabGlobalTrackReferences(state), diff --git a/src/components/timeline/FullTimeline.js b/src/components/timeline/FullTimeline.js index afe545fe90..f9ee35a5a0 100644 --- a/src/components/timeline/FullTimeline.js +++ b/src/components/timeline/FullTimeline.js @@ -47,6 +47,11 @@ import type { import type { ConnectedProps } from 'firefox-profiler/utils/connect'; +type OwnProps = {| + // This ref will be added to the inner container. + +innerElementRef?: React.Ref, +|}; + type StateProps = {| +committedRange: StartEndRange, +globalTracks: GlobalTrack[], @@ -64,7 +69,7 @@ type DispatchProps = {| type Props = {| ...SizeProps, - ...ConnectedProps<{||}, StateProps, DispatchProps>, + ...ConnectedProps, |}; type State = {| @@ -144,6 +149,7 @@ class FullTimelineImpl extends React.PureComponent { panelLayoutGeneration, hiddenTrackCount, changeRightClickedTrack, + innerElementRef, } = this.props; return ( @@ -173,6 +179,7 @@ class FullTimelineImpl extends React.PureComponent { order={globalTrackOrder} orient="vertical" onChangeOrder={changeGlobalTrackOrder} + innerElementRef={innerElementRef} > {globalTracks.map((globalTrack, trackIndex) => ( { } } -export const FullTimeline = explicitConnect<{||}, StateProps, DispatchProps>({ +export const FullTimeline = explicitConnect< + OwnProps, + StateProps, + DispatchProps +>({ mapStateToProps: (state) => ({ globalTracks: getGlobalTracks(state), globalTrackOrder: getGlobalTrackOrder(state), diff --git a/src/components/timeline/OriginsTimeline.js b/src/components/timeline/OriginsTimeline.js index b87d6f954f..fe3cba7c36 100644 --- a/src/components/timeline/OriginsTimeline.js +++ b/src/components/timeline/OriginsTimeline.js @@ -37,6 +37,11 @@ import type { ConnectedProps } from 'firefox-profiler/utils/connect'; import './OriginsTimeline.css'; +type OwnProps = {| + // This ref will be added to the inner container. + +innerElementRef?: React.Ref, +|}; + type StateProps = {| +committedRange: StartEndRange, +panelLayoutGeneration: number, @@ -51,7 +56,7 @@ type DispatchProps = {| type Props = {| ...SizeProps, - ...ConnectedProps<{||}, StateProps, DispatchProps>, + ...ConnectedProps, |}; type State = {| @@ -145,6 +150,7 @@ class OriginsTimelineView extends React.PureComponent { width, panelLayoutGeneration, originsTimeline, + innerElementRef, } = this.props; return ( @@ -161,7 +167,7 @@ class OriginsTimelineView extends React.PureComponent { panelLayoutGeneration={panelLayoutGeneration} initialSelected={this.state.initialSelected} > -
        +
          {originsTimeline.map(this.renderTrack)}
        @@ -171,18 +177,20 @@ class OriginsTimelineView extends React.PureComponent { } } -export const TimelineOrigins = explicitConnect<{||}, StateProps, DispatchProps>( - { - mapStateToProps: (state) => ({ - threads: getThreads(state), - committedRange: getCommittedRange(state), - zeroAt: getZeroAt(state), - panelLayoutGeneration: getPanelLayoutGeneration(state), - originsTimeline: getOriginsTimeline(state), - }), - mapDispatchToProps: { - changeSelectedThreads, - }, - component: withSize(OriginsTimelineView), - } -); +export const TimelineOrigins = explicitConnect< + OwnProps, + StateProps, + DispatchProps +>({ + mapStateToProps: (state) => ({ + threads: getThreads(state), + committedRange: getCommittedRange(state), + zeroAt: getZeroAt(state), + panelLayoutGeneration: getPanelLayoutGeneration(state), + originsTimeline: getOriginsTimeline(state), + }), + mapDispatchToProps: { + changeSelectedThreads, + }, + component: withSize(OriginsTimelineView), +}); diff --git a/src/components/timeline/index.js b/src/components/timeline/index.js index 19965139d9..3f342538d5 100644 --- a/src/components/timeline/index.js +++ b/src/components/timeline/index.js @@ -22,15 +22,76 @@ type StateProps = {| type Props = ConnectedProps<{||}, StateProps, {||}>; class TimelineImpl extends React.PureComponent { + // This may contain a function that's called whenever we want to remove the + // "wheel" listener. + _removeWheelListener: null | (() => mixed) = null; + + // This effectively disable the pinch-to-zoom as well as ctrl+mousewheel + // gestures. Indeed in the timeline it is confusing. In the future we'll want + // to couple this with the preview selection like in the Viewport HOC. + preventPinchToZoom(e: WheelEvent) { + if (e.ctrlKey) { + e.preventDefault(); + } + } + + // This will be registered as a ref property to the DOM element displaying the + // tracks. We use this solution of registering the wheel event in this ref + // listener because: + // * we can't use React's event handling, because it doesn't allow us to use + // the "passive: false" way of registering the event handler. But we need this + // if we want to be able to prevent the default action of page zooming. + // * we want to be sure to register it whenever the element changes. + _onTimelineMountWithRef = (ref: HTMLElement | null) => { + if (this._removeWheelListener) { + this._removeWheelListener(); + this._removeWheelListener = null; + } + + if (!ref) { + return; + } + + // without pinning to a const variable, Flow isn't sure that we don't change + // the `ref` variable in some of the function calls below, and therefore + // that it won't be null. + const existingRef = ref; + + // Disable pinch-to-zoom and ctrl + wheel otherwise, on the timeline. + // Indeed the users are used to this gesture to zoom in in our charts, and + // may use the same gesture elsewhere because of their habits, however this + // doesn't do what they expect and instead zooms in the page, which is distracting. + existingRef.addEventListener('wheel', this.preventPinchToZoom, { + passive: false, + }); + + this._removeWheelListener = () => { + existingRef.removeEventListener('wheel', this.preventPinchToZoom, { + passive: false, + }); + }; + }; + + componentWillUnmount() { + if (this._removeWheelListener) { + this._removeWheelListener(); + this._removeWheelListener = null; + } + } + render() { const { timelineTrackOrganization } = this.props; switch (timelineTrackOrganization.type) { case 'full': - return ; + return ; case 'active-tab': - return ; + return ( + + ); case 'origins': - return ; + return ( + + ); default: throw assertExhaustiveCheck( timelineTrackOrganization, From 838b5aca324b2fa14a436e78ae9b411912831bdc Mon Sep 17 00:00:00 2001 From: Melo46 Date: Wed, 14 Dec 2022 13:34:36 +0000 Subject: [PATCH 012/114] Pontoon: Update Interlingua (ia) localization of Firefox Profiler Co-authored-by: Melo46 --- locales/ia/app.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/ia/app.ftl b/locales/ia/app.ftl index af9d59b2f6..679e7c42b4 100644 --- a/locales/ia/app.ftl +++ b/locales/ia/app.ftl @@ -15,6 +15,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox pro Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly @@ -257,7 +258,6 @@ Home--record-instructions = Pro initiar profilar, clicca sur le button profila o usa le vias breve de claviero. Le icone es blau quando un profilo es in registration. Pulsa Capturar pro cargar le datos in profiler.firefox.com. -Home--instructions-title = Como vider e registrar profilos Home--instructions-content = Registrar profilos de prestation require { -firefox-brand-name }. Totevia, le profilos existente pote esser vidite in ulle moderne navigator. From 3e31de716f7b08fdc0b719b34c0ba2d7b2b7a473 Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Wed, 14 Dec 2022 14:36:39 +0100 Subject: [PATCH 013/114] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Update=20@codemirr?= =?UTF-8?q?or/lang-javascript=20to=20version=206.1.2=20(PR=20#4371)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index e1dea8a802..94bce2ea05 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ }, "dependencies": { "@codemirror/lang-cpp": "^6.0.2", - "@codemirror/lang-javascript": "^6.1.1", + "@codemirror/lang-javascript": "^6.1.2", "@codemirror/lang-rust": "^6.0.1", "@codemirror/language": "^6.3.1", "@codemirror/state": "^6.1.4", diff --git a/yarn.lock b/yarn.lock index fe0ced8b9c..2ab4b0ecc0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1073,10 +1073,10 @@ "@codemirror/language" "^6.0.0" "@lezer/cpp" "^1.0.0" -"@codemirror/lang-javascript@^6.1.1": - version "6.1.1" - resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-6.1.1.tgz#f920192db30531927a02b8a1af9cf3c3d895101c" - integrity sha512-F4+kiuC5d5dUSJmff96tJQwpEXs/tX/4bapMRnZWW6bHKK1Fx6MunTzopkCUWRa9bF87GPmb9m7Qtg7Yv8f3uQ== +"@codemirror/lang-javascript@^6.1.2": + version "6.1.2" + resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-6.1.2.tgz#a11812ca1d21301cdeb80e51b4c007edcf55f813" + integrity sha512-OcwLfZXdQ1OHrLiIcKCn7MqZ7nx205CMKlhe+vL88pe2ymhT9+2P+QhwkYGxMICj8TDHyp8HFKVwpiisUT7iEQ== dependencies: "@codemirror/autocomplete" "^6.0.0" "@codemirror/language" "^6.0.0" From 8dd2cf8402bea82fa0764185d7ac0e666309e716 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Wed, 14 Dec 2022 15:56:55 +0100 Subject: [PATCH 014/114] Make more explicit the fact that MarkerPayload is nullable (PR #4368) --- src/profile-logic/marker-data.js | 6 ++--- src/profile-logic/process-profile.js | 27 ++++++++++++------- src/profile-logic/profile-data.js | 4 +-- src/test/fixtures/profiles/gecko-profile.js | 2 +- .../fixtures/profiles/processed-profile.js | 6 ++--- src/types/gecko-profile.js | 4 +-- src/types/markers.js | 7 ++--- src/types/profile-derived.js | 2 +- src/types/profile.js | 2 +- 9 files changed, 32 insertions(+), 28 deletions(-) diff --git a/src/profile-logic/marker-data.js b/src/profile-logic/marker-data.js index 7887d3628a..3d31ed39aa 100644 --- a/src/profile-logic/marker-data.js +++ b/src/profile-logic/marker-data.js @@ -496,9 +496,9 @@ export function deriveMarkersFromRawMarkerTable( // In the case of separate markers for the start and end of an interval, // merge the payloads together, with the end data overriding the start. function mergeIntervalData( - startData: MarkerPayload, - endData: MarkerPayload - ): MarkerPayload { + startData: MarkerPayload | null, + endData: MarkerPayload | null + ): MarkerPayload | null { if (!startData && !endData) { return null; } diff --git a/src/profile-logic/process-profile.js b/src/profile-logic/process-profile.js index 53add8a524..14541240fa 100644 --- a/src/profile-logic/process-profile.js +++ b/src/profile-logic/process-profile.js @@ -661,13 +661,16 @@ function _processStackTable( * synchronous stack. Otherwise, if it happened before, it was an async stack, and is * most likely some event that happened in the past that triggered the marker. */ -function _convertStackToCause(data: any): any { +function _convertStackToCause(data: MarkerPayload_Gecko) { if ('stack' in data && data.stack && data.stack.samples.data.length > 0) { const { stack, ...newData } = data; const stackIndex = stack.samples.data[0][stack.samples.schema.stack]; const time = stack.samples.data[0][stack.samples.schema.time]; if (stackIndex !== null) { - newData.cause = { tid: stack.tid, time, stack: stackIndex }; + return { + ...newData, + cause: { tid: stack.tid, time, stack: stackIndex }, + }; } return newData; } @@ -679,7 +682,7 @@ function _convertStackToCause(data: any): any { * from a gecko payload. */ function _convertPayloadStackToIndex( - data: MarkerPayload_Gecko + data: MarkerPayload_Gecko | null ): IndexIntoStackTable | null { if (!data) { return null; @@ -714,7 +717,7 @@ function _processMarkers(geckoMarkers: GeckoMarkerStruct): {| let hasMemoryAddresses; for (let markerIndex = 0; markerIndex < geckoMarkers.length; markerIndex++) { - const geckoPayload: MarkerPayload_Gecko = geckoMarkers.data[markerIndex]; + const geckoPayload = geckoMarkers.data[markerIndex]; if (geckoPayload) { switch (geckoPayload.type) { @@ -844,8 +847,8 @@ function convertPhaseTimes( * the GC information. */ function _processMarkerPayload( - geckoPayload: MarkerPayload_Gecko -): MarkerPayload { + geckoPayload: MarkerPayload_Gecko | null +): MarkerPayload | null { if (!geckoPayload) { return null; } @@ -904,10 +907,14 @@ function _processMarkerPayload( } } default: - // Coerce the payload into a MarkerPayload. This doesn't really provide - // any more type safety, but it shows the intent of going from an object - // without much type safety, to a specific type definition. - return (payload: MarkerPayload); + // `payload` is currently typed as the result of _convertStackToCause, which + // is MarkerPayload_Gecko where `stack` has been replaced with `cause`. This + // should be reasonably close to `MarkerPayload`, but Flow doesn't work well + // with our MarkerPayload type. So we're coerce this return value to `any` + // here, and then to `MarkerPayload` as the return value for this function. + // This doesn't provide type safety but it shows the intent of going from an + // object without much type safety, to a specific type definition. + return (payload: any); } } diff --git a/src/profile-logic/profile-data.js b/src/profile-logic/profile-data.js index 992b8f0a3c..f7535ffa4a 100644 --- a/src/profile-logic/profile-data.js +++ b/src/profile-logic/profile-data.js @@ -3091,8 +3091,8 @@ export function replaceStackReferences( // Markers function replaceStackReferenceInMarkerPayload( - oldData: MarkerPayload - ): MarkerPayload { + oldData: MarkerPayload | null + ): MarkerPayload | null { if (oldData && 'cause' in oldData && oldData.cause) { // Replace the cause with the right stack index. // Use (...: any) because our current version of Flow has trouble with diff --git a/src/test/fixtures/profiles/gecko-profile.js b/src/test/fixtures/profiles/gecko-profile.js index 9d7d86bfb3..2ec9204c65 100644 --- a/src/test/fixtures/profiles/gecko-profile.js +++ b/src/test/fixtures/profiles/gecko-profile.js @@ -336,7 +336,7 @@ type TestDefinedGeckoMarker = {| +endTime: Milliseconds | null, +phase: MarkerPhase, +category?: IndexIntoCategoryList, - +data?: MarkerPayload_Gecko, + +data?: MarkerPayload_Gecko | null, |}; function _createGeckoThreadWithMarkers( diff --git a/src/test/fixtures/profiles/processed-profile.js b/src/test/fixtures/profiles/processed-profile.js index e7b046d046..a10cbddcac 100644 --- a/src/test/fixtures/profiles/processed-profile.js +++ b/src/test/fixtures/profiles/processed-profile.js @@ -75,7 +75,7 @@ export type TestDefinedMarkers = Array< MarkerName, MarkerTime, // start time MarkerTime | null, // end time - MarkerPayload | MockPayload + MarkerPayload | MockPayload | null ] >; @@ -86,7 +86,7 @@ export type TestDefinedRawMarker = {| +endTime: Milliseconds | null, +phase: MarkerPhase, +category?: IndexIntoCategoryList, - +data?: MarkerPayload, + +data?: MarkerPayload | null, |}; export type TestDefinedJsTracerEvent = [ @@ -131,7 +131,7 @@ export function addMarkersToThreadWithCorrespondingSamples( const startTime = tuple[1]; // Flow doesn't support variadic tuple types. const maybeEndTime = (tuple: any)[2] || null; - const payload: MarkerPayload = (tuple: any)[3] || null; + const payload: MarkerPayload | null = (tuple: any)[3] || null; markersTable.name.push(stringTable.indexForString(name)); if (maybeEndTime === null) { diff --git a/src/types/gecko-profile.js b/src/types/gecko-profile.js index 54337729d5..dd5b05ef2d 100644 --- a/src/types/gecko-profile.js +++ b/src/types/gecko-profile.js @@ -44,7 +44,7 @@ export type GeckoMarkerTuple = [ Milliseconds | null, MarkerPhase, IndexIntoCategoryList, - MarkerPayload_Gecko + MarkerPayload_Gecko | null ]; export type GeckoMarkers = { @@ -70,7 +70,7 @@ export type GeckoMarkerStruct = {| startTime: Milliseconds[], endTime: Milliseconds[], phase: MarkerPhase[], - data: MarkerPayload_Gecko[], + data: Array, category: IndexIntoCategoryList[], length: number, |}; diff --git a/src/types/markers.js b/src/types/markers.js index a996bd64c6..e8c2921343 100644 --- a/src/types/markers.js +++ b/src/types/markers.js @@ -766,8 +766,7 @@ export type MarkerPayload = | MediaSampleMarkerPayload | JankPayload | BrowsertimeMarkerPayload - | NoPayloadUserData - | null; + | NoPayloadUserData; export type MarkerPayload_Gecko = | GPUMarkerPayload @@ -795,6 +794,4 @@ export type MarkerPayload_Gecko = | $ReplaceCauseWithStack | $ReplaceCauseWithStack | $ReplaceCauseWithStack - | $ReplaceCauseWithStack - // Payloads can be null. - | null; + | $ReplaceCauseWithStack; diff --git a/src/types/profile-derived.js b/src/types/profile-derived.js index 2b86b325a6..d8f413437c 100644 --- a/src/types/profile-derived.js +++ b/src/types/profile-derived.js @@ -197,7 +197,7 @@ export type Marker = {| name: string, category: IndexIntoCategoryList, threadId: Tid | null, - data: MarkerPayload, + data: MarkerPayload | null, incomplete?: boolean, |}; diff --git a/src/types/profile.js b/src/types/profile.js index ff995f28fa..4638e1acc0 100644 --- a/src/types/profile.js +++ b/src/types/profile.js @@ -253,7 +253,7 @@ export type ProfilerMarkerPayload = { * it into a structured marker. */ export type RawMarkerTable = {| - data: MarkerPayload[], + data: Array, name: IndexIntoStringTable[], startTime: Array, endTime: Array, From 9ab6a31ab363bf95d838ffb31a2312e8023aeb8c Mon Sep 17 00:00:00 2001 From: robovoice Date: Wed, 14 Dec 2022 15:33:32 +0000 Subject: [PATCH 015/114] Pontoon: Update German (de) localization of Firefox Profiler Co-authored-by: robovoice --- locales/de/app.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/de/app.ftl b/locales/de/app.ftl index da342f84fd..2b9e4388b1 100644 --- a/locales/de/app.ftl +++ b/locales/de/app.ftl @@ -15,6 +15,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox für Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly @@ -245,7 +246,6 @@ Home--record-instructions = Um die Profilerstellung zu starten, klicken Sie auf die Schaltfläche Profilerstellung oder verwenden Sie die Tastatürkürzel. Das Symbol ist blau, wenn ein Profil aufzeichnet. Drücken Sie Aufzeichnen, um die Daten in profiler.firefox.com zu laden. -Home--instructions-title = So können Sie Profile anzeigen und aufzeichnen Home--instructions-content = Das Aufzeichnen von Leistungsprofilen benötigt { -firefox-brand-name }. Vorhandene Profile können jedoch in jedem modernen Browser angezeigt werden. From eb0167d570ca61cd61ba7d19ca072c637a2d3ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20K=C3=B6hler?= Date: Wed, 14 Dec 2022 15:43:23 +0000 Subject: [PATCH 016/114] Pontoon: Update German (de) localization of Firefox Profiler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michael Köhler --- locales/de/app.ftl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/locales/de/app.ftl b/locales/de/app.ftl index 2b9e4388b1..27504c44c4 100644 --- a/locales/de/app.ftl +++ b/locales/de/app.ftl @@ -234,6 +234,7 @@ Home--menu-button = { -profiler-brand-name }-Menüschaltfläche aktivieren Home--menu-button-instructions = Aktivieren Sie die Profiler-Menüschaltfläche, um Leistung in einem Profil von { -firefox-brand-name } aufzuzeichnen, dann analysieren Sie sie und teilen Sie das Ergebnis auf profiler.firefox.com. +Home--profile-firefox-android-instructions = Sie können auch Leistungsprofile für { -firefox-android-brand-name } erstellen. Weitere Informationen finden Sie in der Dokumentation Profiling { -firefox-android-brand-name } directly on device. # The word WebChannel should not be translated. # This message can be seen on https://main--perf-html.netlify.app/ in the tooltip # of the "Enable Firefox Profiler menu button" button. @@ -256,6 +257,13 @@ Home--additional-content-title = Bestehende Profile laden Home--additional-content-content = Sie können eine Profildatei per Ziehen und Ablegen hierher bewegen, um sie zu laden, oder: Home--compare-recordings-info = Sie können auch Aufnahmen vergleichen. Öffnen Sie die Vergleichsschnittstelle. Home--your-recent-uploaded-recordings-title = Ihre kürzlich hochgeladenen Aufzeichnungen +# We replace the elements such as and with links to the +# documentation to use these tools. +Home--load-files-from-other-tools = + Der { -profiler-brand-name } kann auch Leistungsprofile von anderen Profilern importieren, wie z. B. + Linux perf, Android SimplePerf, die + Chrome Performance Panel, Android Studio oder + eine Datei im dhat-Format. Erfahren Sie, wie Sie Ihren eigenen Importeur schreiben. ## IdleSearchField ## The component that is used for all the search inputs in the application. From bbead24a812abf72bb6c44437f72a9d3e203aaad Mon Sep 17 00:00:00 2001 From: ravmn Date: Wed, 14 Dec 2022 19:43:20 +0000 Subject: [PATCH 017/114] Pontoon: Update Spanish (Chile) (es-CL) localization of Firefox Profiler Co-authored-by: ravmn --- locales/es-CL/app.ftl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/locales/es-CL/app.ftl b/locales/es-CL/app.ftl index b873973e2a..439f43ad3d 100644 --- a/locales/es-CL/app.ftl +++ b/locales/es-CL/app.ftl @@ -15,6 +15,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox para Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly @@ -196,6 +197,10 @@ Home--load-from-url-submit-button = Home--documentation-button = Documentación Home--menu-button = Activar botón de menú de { -profiler-brand-name } Home--menu-button-instructions = Habilita el botón de menú del perfilador para comenzar a registrar un perfil de rendimiento en { -firefox-brand-name }, luego analízalo y compártelo con profiler.firefox.com. +Home--profile-firefox-android-instructions = + También puede perfilar { -firefox-android-brand-name }. Para más + información, consulta esta documentación: + Perfilando { -firefox-android-brand-name } directamente en el dispositivo. # The word WebChannel should not be translated. # This message can be seen on https://main--perf-html.netlify.app/ in the tooltip # of the "Enable Firefox Profiler menu button" button. @@ -205,7 +210,6 @@ Home--enable-button-unavailable = # This message can be seen on https://main--perf-html.netlify.app/ . Home--web-channel-unavailable = Esta instancia del perfilador no pudo conectarse a WebChannel. Esto usualmente significa que está ejecutándose en un servidor diferente del especificado en la preferencia devtools.performance.recording.ui-base-url. Si quieres capturar nuevos perfiles con esta instancia, y otorgarle control programático del botón del menú del perfilador, puedes ir a about:config y cambiar la preferencia. Home--record-instructions = Para empezar a perfilar, haz clic en el botón de perfilado o utiliza los atajos del teclado. El icono se torna azul cuando se está grabando un perfil. Pulsa Capturar para cargar los datos en profiler.firefox.com. -Home--instructions-title = Cómo ver y registrar perfiles Home--instructions-content = Registrar perfiles de rendimiento requiere de { -firefox-brand-name }. Sin embargo, los perfiles existentes pueden ser vistos en cualquier navegador moderno. @@ -216,6 +220,14 @@ Home--additional-content-title = Cargar perfiles existentes Home--additional-content-content = Puedes arrastrar y soltar un archivo de perfil aquí para cargarlo, o: Home--compare-recordings-info = También puedes comparar los registros. Abre la interfaz de comparación. Home--your-recent-uploaded-recordings-title = Tus registros subidos recientemente +# We replace the elements such as and with links to the +# documentation to use these tools. +Home--load-files-from-other-tools = + { -profiler-brand-name } también puede importar perfiles de otros generadores de perfiles, tales como + Linux perf, Android SimplePerf, el + panel de rendimiento de Chrome, Android Studio, o + cualquier archivo usando el formato dhat. Aprende a escribir tu + propio importador. ## IdleSearchField ## The component that is used for all the search inputs in the application. From 5fa3a2caa4554bee242007812ff873e2da46eaef Mon Sep 17 00:00:00 2001 From: Mark Heijl Date: Wed, 14 Dec 2022 21:33:41 +0000 Subject: [PATCH 018/114] Pontoon: Update Dutch (nl) localization of Firefox Profiler Co-authored-by: Mark Heijl --- locales/nl/app.ftl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/locales/nl/app.ftl b/locales/nl/app.ftl index 6473e17680..0d5a878396 100644 --- a/locales/nl/app.ftl +++ b/locales/nl/app.ftl @@ -279,10 +279,10 @@ Home--your-recent-uploaded-recordings-title = Uw onlangs geüploade opnamen # documentation to use these tools. Home--load-files-from-other-tools = De { -profiler-brand-name } kan ook profielen van andere profilers importeren, zoals - Linux-perf, Android SimplePerf, het + Linux perf, Android SimplePerf, het Chrome-prestatiepaneel, Android Studio of - elk bestand dat de dhat-indeling gebruikt. Leer hoe u uw - eigen importeerder kunt schrijven. + elk bestand dat de dhat-indeling gebruikt. Ontdek hoe u uw + eigen importroutine schrijft. ## IdleSearchField ## The component that is used for all the search inputs in the application. From 366e023b8c140d0bffa77a64b8f652c39beb890c Mon Sep 17 00:00:00 2001 From: Ian Neal Date: Wed, 14 Dec 2022 22:43:41 +0000 Subject: [PATCH 019/114] Pontoon: Update English (Great Britain) (en-GB) localization of Firefox Profiler Co-authored-by: Ian Neal --- locales/en-GB/app.ftl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/locales/en-GB/app.ftl b/locales/en-GB/app.ftl index a98455cd1e..fb1361563e 100644 --- a/locales/en-GB/app.ftl +++ b/locales/en-GB/app.ftl @@ -15,6 +15,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox for Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly @@ -247,6 +248,10 @@ Home--menu-button = Enable { -profiler-brand-name } Menu Button Home--menu-button-instructions = Enable the profiler menu button to start recording a performance profile in { -firefox-brand-name }, then analyse it and share it with profiler.firefox.com. +Home--profile-firefox-android-instructions = + You can also profile { -firefox-android-brand-name }. For more + information, please consult this documentation: + Profiling { -firefox-android-brand-name } directly on device. # The word WebChannel should not be translated. # This message can be seen on https://main--perf-html.netlify.app/ in the tooltip # of the "Enable Firefox Profiler menu button" button. @@ -264,7 +269,6 @@ Home--record-instructions = To start profiling, click on the profiling button, or use the keyboard shortcuts. The icon is blue when a profile is recording. Hit Capture to load the data into profiler.firefox.com. -Home--instructions-title = How to view and record profiles Home--instructions-content = Recording performance profiles requires { -firefox-brand-name }. However, existing profiles can be viewed in any modern browser. @@ -275,6 +279,14 @@ Home--additional-content-title = Load existing profiles Home--additional-content-content = You can drag and drop a profile file here to load it, or: Home--compare-recordings-info = You can also compare recordings. Open the comparing interface. Home--your-recent-uploaded-recordings-title = Your recent uploaded recordings +# We replace the elements such as and with links to the +# documentation to use these tools. +Home--load-files-from-other-tools = + The { -profiler-brand-name } can also import profiles from other profilers, such as + Linux perf, Android SimplePerf, the + Chrome performance panel, Android Studio, or + any file using the dhat format. Learn how to write your + own importer. ## IdleSearchField ## The component that is used for all the search inputs in the application. From af0541051d227ce2f1850dec678739903460b21d Mon Sep 17 00:00:00 2001 From: Marcelo Ghelman Date: Wed, 14 Dec 2022 23:33:40 +0000 Subject: [PATCH 020/114] Pontoon: Update Portuguese (Brazil) (pt-BR) localization of Firefox Profiler Co-authored-by: Marcelo Ghelman --- locales/pt-BR/app.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/pt-BR/app.ftl b/locales/pt-BR/app.ftl index 61d60a9e3f..10fb85c779 100644 --- a/locales/pt-BR/app.ftl +++ b/locales/pt-BR/app.ftl @@ -15,6 +15,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox para Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly @@ -197,7 +198,6 @@ Home--enable-button-unavailable = # This message can be seen on https://main--perf-html.netlify.app/ . Home--web-channel-unavailable = Esta instância do profiler não conseguiu se conectar ao WebChannel. Isso geralmente significa que está sendo executado em um host diferente daquele especificado na preferência devtools.performance.recording.ui-base-url. Se você quiser capturar novos profiles com esta instância e dar a ela controle programático do botão de menu do profiler, pode ir em about: config e alterar a preferência. Home--record-instructions = Para iniciar a gravação de um profile, clique no botão de gravação de profile ou use os atalhos de teclado. O ícone fica azul quando um profile está sendo gravado. Use Capturar para carregar os dados no profiler.firefox.com. -Home--instructions-title = Como ver e gravar profiles Home--instructions-content = A gravação de profiles de desempenho requer o { -firefox-brand-name }. No entanto, profiles existentes podem ser vistos em qualquer navegador moderno. From d5f4339b686ea88ea87f4ec531220287ef979055 Mon Sep 17 00:00:00 2001 From: Marcelo Ghelman Date: Wed, 14 Dec 2022 23:44:13 +0000 Subject: [PATCH 021/114] Pontoon: Update Portuguese (Brazil) (pt-BR) localization of Firefox Profiler Co-authored-by: Marcelo Ghelman --- locales/pt-BR/app.ftl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/locales/pt-BR/app.ftl b/locales/pt-BR/app.ftl index 10fb85c779..94ca8c804b 100644 --- a/locales/pt-BR/app.ftl +++ b/locales/pt-BR/app.ftl @@ -189,6 +189,10 @@ Home--menu-button = Ativar botão de menu do { -profiler-brand-name } Home--menu-button-instructions = Ative o botão de menu do profiler para iniciar a gravação de um profile de desempenho no { -firefox-brand-name }, depois analisar e compartilhar com profiler.firefox.com. +Home--profile-firefox-android-instructions = + Você também pode criar profile pelo { -firefox-android-brand-name }. + Para mais informações, consulte esta documentação: + Como criar profile do { -firefox-android-brand-name } diretamente no dispositivo. # The word WebChannel should not be translated. # This message can be seen on https://main--perf-html.netlify.app/ in the tooltip # of the "Enable Firefox Profiler menu button" button. @@ -208,6 +212,9 @@ Home--additional-content-title = Carregar profiles existentes Home--additional-content-content = Você pode arrastar e soltar aqui um arquivo de profile para carregar, ou: Home--compare-recordings-info = Você também pode comparar gravações. Abra a interface de comparação. Home--your-recent-uploaded-recordings-title = Suas gravações enviadas recentemente +# We replace the elements such as and with links to the +# documentation to use these tools. +Home--load-files-from-other-tools = O { -profiler-brand-name } também pode importar profiles de outros criadores de profile, como o Linux perf, o Android SimplePerf, o painel de desempenho do Chrome, o Android Studio ou qualquer arquivo no formato dhat. Saiba como escrever seu próprio importador. ## IdleSearchField ## The component that is used for all the search inputs in the application. From 75f7be1f79a31febbba0aafe0dbc80fc04ec5007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=86hor=20Hordiichuk?= Date: Thu, 15 Dec 2022 06:44:30 +0000 Subject: [PATCH 022/114] Pontoon: Update Ukrainian (uk) localization of Firefox Profiler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Іhor Hordiichuk --- locales/uk/app.ftl | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/locales/uk/app.ftl b/locales/uk/app.ftl index 8d0082293c..2e2cf2914a 100644 --- a/locales/uk/app.ftl +++ b/locales/uk/app.ftl @@ -15,6 +15,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox для Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly @@ -239,6 +240,10 @@ Home--menu-button = Увімкнути кнопку меню { -profiler-brand-n Home--menu-button-instructions = Увімкніть кнопку меню профайлера, щоб почати запис швидкодії профілю у { -firefox-brand-name }, потім аналізуйте його та оприлюдніть на profiler.firefox.com. +Home--profile-firefox-android-instructions = + Ви також можете створити профіль { -firefox-android-brand-name }. За + подробицями зверніться до цієї документації: + Профілювання { -firefox-android-brand-name } безпосередньо на пристрої. # The word WebChannel should not be translated. # This message can be seen on https://main--perf-html.netlify.app/ in the tooltip # of the "Enable Firefox Profiler menu button" button. @@ -256,7 +261,6 @@ Home--record-instructions = Щоб розпочати запис профілю, натисніть кнопку запису або скористайтеся комбінацією клавіш. Під час запису профілю піктограма стає синього кольору. Натисніть Захопити, щоб завантажити дані на profiler.firefox.com. -Home--instructions-title = Як переглядати та записувати профілі Home--instructions-content = Для запису профілів швидкодії потрібен { -firefox-brand-name }. Однак, наявні профілі можна переглядати в будь-якому сучасному браузері. @@ -267,6 +271,14 @@ Home--additional-content-title = Завантажити наявні профі Home--additional-content-content = Ви можете перетягнути файл профілю сюди, щоб завантажити його, або: Home--compare-recordings-info = Ви також можете порівняти записи. Відкрити інтерфейс порівняння. Home--your-recent-uploaded-recordings-title = Ваші недавно вивантажені записи +# We replace the elements such as and with links to the +# documentation to use these tools. +Home--load-files-from-other-tools = + { -profiler-brand-name } також може імпортувати профілі з інших профайлерів, наприклад + Linux perf, Android SimplePerf, + Панель швидкодії Chrome, Android Studio або + будь-який файл у форматі dhat. Навчіться записувати свій + власний імпортер. ## IdleSearchField ## The component that is used for all the search inputs in the application. From a83df4aac8b76a7053238bbf4dddd4a66860b3c3 Mon Sep 17 00:00:00 2001 From: Jim Spentzos Date: Thu, 15 Dec 2022 07:42:46 +0000 Subject: [PATCH 023/114] Pontoon: Update Greek (el) localization of Firefox Profiler Co-authored-by: Jim Spentzos --- locales/el/app.ftl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/locales/el/app.ftl b/locales/el/app.ftl index e13cead6ac..46590ff9a3 100644 --- a/locales/el/app.ftl +++ b/locales/el/app.ftl @@ -244,6 +244,10 @@ Home--menu-button = Ενεργοποίηση κουμπιού μενού του Home--menu-button-instructions = Ενεργοποιήστε το κουμπί του μενού του εργαλείου καταγραφής για να ξεκινήσετε ένα προφίλ επιδόσεων στο { -firefox-brand-name } και έπειτα, να το αναλύσετε και να το μοιραστείτε με το profiler.firefox.com. +Home--profile-firefox-android-instructions = + Μπορείτε επίσης να καταγράψετε προφίλ για το { -firefox-android-brand-name }. + Για περισσότερες πληροφορίες, παρακαλούμε συμβουλευτείτε την τεκμηρίωση: + Καταγραφή προφίλ του { -firefox-android-brand-name } απευθείας στη συσκευή. # The word WebChannel should not be translated. # This message can be seen on https://main--perf-html.netlify.app/ in the tooltip # of the "Enable Firefox Profiler menu button" button. From f9c4bdbbc0a3d62f4e6d325dfa33244b269d52e9 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 15 Dec 2022 17:03:39 +0100 Subject: [PATCH 024/114] Unselect the current node when clicking outside of the activity graph --- src/actions/profile-view.js | 25 +++++++++++++------ src/components/shared/thread/ActivityGraph.js | 6 ++--- src/components/timeline/TrackThread.js | 2 +- .../components/ThreadActivityGraph.test.js | 4 +++ 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/actions/profile-view.js b/src/actions/profile-view.js index 81e77f36fc..31e51e6413 100644 --- a/src/actions/profile-view.js +++ b/src/actions/profile-view.js @@ -148,20 +148,24 @@ export function changeRightClickedCallNode( */ export function selectLeafCallNode( threadsKey: ThreadsKey, - sampleIndex: IndexIntoSamplesTable + sampleIndex: IndexIntoSamplesTable | null ): ThunkAction { return (dispatch, getState) => { const threadSelectors = getThreadSelectorsFromThreadsKey(threadsKey); const filteredThread = threadSelectors.getFilteredThread(getState()); const callNodeInfo = threadSelectors.getCallNodeInfo(getState()); - // The newSelectedStack could be undefined if there are 0 samples. - const newSelectedStack = filteredThread.samples.stack[sampleIndex]; + let newSelectedCallNode = -1; + if (sampleIndex !== null) { + // The newSelectedStack could be undefined if there are 0 samples. + const newSelectedStack = filteredThread.samples.stack[sampleIndex]; + + if (newSelectedStack !== null && newSelectedStack !== undefined) { + newSelectedCallNode = + callNodeInfo.stackIndexToCallNodeIndex[newSelectedStack]; + } + } - const newSelectedCallNode = - newSelectedStack === null || newSelectedStack === undefined - ? -1 - : callNodeInfo.stackIndexToCallNodeIndex[newSelectedStack]; dispatch( changeSelectedCallNode( threadsKey, @@ -180,15 +184,20 @@ export function selectLeafCallNode( */ export function selectRootCallNode( threadsKey: ThreadsKey, - sampleIndex: IndexIntoSamplesTable + sampleIndex: IndexIntoSamplesTable | null ): ThunkAction { return (dispatch, getState) => { const threadSelectors = getThreadSelectorsFromThreadsKey(threadsKey); const filteredThread = threadSelectors.getFilteredThread(getState()); const callNodeInfo = threadSelectors.getCallNodeInfo(getState()); + if (sampleIndex === null) { + dispatch(changeSelectedCallNode(threadsKey, [])); + return; + } const newSelectedStack = filteredThread.samples.stack[sampleIndex]; if (newSelectedStack === null || newSelectedStack === undefined) { + dispatch(changeSelectedCallNode(threadsKey, [])); return; } const newSelectedCallNode = diff --git a/src/components/shared/thread/ActivityGraph.js b/src/components/shared/thread/ActivityGraph.js index e9ab1cd886..b0794fbb6d 100644 --- a/src/components/shared/thread/ActivityGraph.js +++ b/src/components/shared/thread/ActivityGraph.js @@ -44,7 +44,7 @@ export type Props = {| +sampleIndexOffset: number, +onSampleClick: ( event: SyntheticMouseEvent<>, - sampleIndex: IndexIntoSamplesTable + sampleIndex: IndexIntoSamplesTable | null ) => void, +categories: CategoryList, +samplesSelectedStates: null | SelectedState[], @@ -145,9 +145,7 @@ class ThreadActivityGraphImpl extends React.PureComponent { _onClick = (event: SyntheticMouseEvent) => { const sampleState = this._getSampleAtMouseEvent(event); - if (sampleState !== null) { - this.props.onSampleClick(event, sampleState.sample); - } + this.props.onSampleClick(event, sampleState ? sampleState.sample : null); }; _takeContainerRef = (el: HTMLElement | null) => { diff --git a/src/components/timeline/TrackThread.js b/src/components/timeline/TrackThread.js index 3682ab67e5..b1b00d91c1 100644 --- a/src/components/timeline/TrackThread.js +++ b/src/components/timeline/TrackThread.js @@ -122,7 +122,7 @@ class TimelineTrackThreadImpl extends PureComponent { */ _onSampleClick = ( event: SyntheticMouseEvent<>, - sampleIndex: IndexIntoSamplesTable + sampleIndex: IndexIntoSamplesTable | null ) => { const modifiers = getTrackSelectionModifiers(event); if (modifiers.ctrlOrMeta || modifiers.shift) { diff --git a/src/test/components/ThreadActivityGraph.test.js b/src/test/components/ThreadActivityGraph.test.js index d49dade982..3d984ad97e 100644 --- a/src/test/components/ThreadActivityGraph.test.js +++ b/src/test/components/ThreadActivityGraph.test.js @@ -255,6 +255,10 @@ describe('ThreadActivityGraph', function () { // A -> B -> H -> I clickActivityGraph(1, 0.8); expect(getCallNodePath()).toEqual(['A', 'B', 'H', 'I']); + + // There's no sample at this location. + clickActivityGraph(0, 1); + expect(getCallNodePath()).toEqual([]); }); it('will redraw even when there are no samples in range', function () { From 963697accba6092519605952151f9bcd6c8048b1 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 15 Dec 2022 17:20:04 +0100 Subject: [PATCH 025/114] Scroll the treeview to the top when the selection is empty --- src/components/shared/TreeView.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/components/shared/TreeView.js b/src/components/shared/TreeView.js index e8e01d8021..fa0c0a03ce 100644 --- a/src/components/shared/TreeView.js +++ b/src/components/shared/TreeView.js @@ -448,11 +448,15 @@ export class TreeView extends React.PureComponent< /* eslint-disable-next-line react/no-unused-class-component-methods */ scrollSelectionIntoView() { const { selectedNodeId, tree } = this.props; - if (this._list && selectedNodeId !== null) { - const list = this._list; // this temp variable so that flow knows that it's non-null - const rowIndex = this._getAllVisibleRows().indexOf(selectedNodeId); - const depth = tree.getDepth(selectedNodeId); - list.scrollItemIntoView(rowIndex, depth * 10); + const list = this._list; // this temp variable so that flow knows that it's non-null later + if (list) { + if (selectedNodeId === null) { + list.scrollItemIntoView(0, 0); + } else { + const rowIndex = this._getAllVisibleRows().indexOf(selectedNodeId); + const depth = tree.getDepth(selectedNodeId); + list.scrollItemIntoView(rowIndex, depth * 10); + } } } From 44db42781179e6bd1160430afc303793514a740b Mon Sep 17 00:00:00 2001 From: "Francesco Lodolo [:flod]" Date: Thu, 15 Dec 2022 17:23:41 +0000 Subject: [PATCH 026/114] Pontoon: Update Italian (it) localization of Firefox Profiler Co-authored-by: Francesco Lodolo [:flod] --- locales/it/app.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/it/app.ftl b/locales/it/app.ftl index a15a3b119a..6a12ab10ae 100644 --- a/locales/it/app.ftl +++ b/locales/it/app.ftl @@ -207,7 +207,7 @@ Home--your-recent-uploaded-recordings-title = Le tue registrazioni caricate di r # documentation to use these tools. Home--load-files-from-other-tools = { -profiler-brand-name } può anche importare profili da altri profiler, come Linux perf, Android SimplePerf, il - pannello prestazioni di Chrome, Android Studio o qualsiasi file che utilizzi il formato dhat. write>Scopri come creare uno strumento di importazione. + pannello prestazioni di Chrome, Android Studio o qualsiasi file che utilizzi il formato dhat. Scopri come creare uno strumento di importazione. ## IdleSearchField ## The component that is used for all the search inputs in the application. From 07fc282e75421bea9f624ea76f09686b3324deb1 Mon Sep 17 00:00:00 2001 From: ZiriSut Date: Thu, 15 Dec 2022 17:33:30 +0000 Subject: [PATCH 027/114] Pontoon: Update Kabyle (kab) localization of Firefox Profiler Co-authored-by: ZiriSut --- locales/kab/app.ftl | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/locales/kab/app.ftl b/locales/kab/app.ftl index e33701e6aa..1548a4ade0 100644 --- a/locales/kab/app.ftl +++ b/locales/kab/app.ftl @@ -15,6 +15,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox i Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly @@ -129,13 +130,13 @@ Home--load-from-url-submit-button = .value = Sali Home--documentation-button = Tasemlit Home--menu-button = Rmed taqeffalt n wumuɣ { -profiler-brand-name } -Home--instructions-title = Amek ara twaliḍ akked ad teskelseḍ imuɣna Home--record-instructions-start-stop = Seḥbes neɣ bdu timeɣna Home--record-instructions-capture-load = Ṭṭef neɣ sali amaɣnu Home--profiler-motto = Ṭṭef amaɣnu n temlellit. Sleḍ-it. Bḍu-t. Err web d arurad. Home--additional-content-title = Sali imuɣna yellan Home--additional-content-content = Tzemreḍ ad tzuɣreḍ syen sers afaylu n umaɣnu da i usali-ines, neɣ: Home--compare-recordings-info = Tzemreḍ daɣen ad tsenmehleḍ iseklasen. Ldi agrudem n usnemhel. +Home--your-recent-uploaded-recordings-title = Iseklasen-ik·im i d-yulin melmi kan ## IdleSearchField ## The component that is used for all the search inputs in the application. @@ -226,7 +227,6 @@ MenuButtons--index--profile-info-uploaded-label = Yuli-d: MenuButtons--index--profile-info-uploaded-actions = Kkes MenuButtons--index--metaInfo-subtitle = Talɣut n umaɣnu MenuButtons--metaInfo--symbols = Izamulen: -MenuButtons--metaInfo--cpu = CPU: MenuButtons--metaInfo--main-process-started = Asesfer agejdan yebda: MenuButtons--metaInfo--main-process-ended = Asesfer agejdan yekfa: MenuButtons--metaInfo--interval = Azilal: @@ -429,7 +429,7 @@ TrackNameButton--hide-process = TrackMemoryGraph--relative-memory-at-this-time = takatut tamassaɣt deg wakud-a -## TrackPowerGraph +## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. ## It's not displayed by default in the UI, but an example can be found at @@ -480,11 +480,6 @@ TransformNavigator--merge-function = Smezdi: { $item } # Variables: # $item (String) - Name of the function that transform applied to. TransformNavigator--drop-function = Sers: { $item } -# "Collapse direct recursion" transform. -# See: https://profiler.firefox.com/docs/#/./guide-filtering-call-trees?id=collapse -# Variables: -# $item (String) - Name of the function that transform applied to. -TransformNavigator--collapse-direct-recursion = Fneẓ asniles: { $item } ## Source code view in a box at the bottom of the UI. From 29f1cdc8a8ae457072c54992f6354e56f131bbb4 Mon Sep 17 00:00:00 2001 From: ZiriSut Date: Thu, 15 Dec 2022 17:53:31 +0000 Subject: [PATCH 028/114] Pontoon: Update Kabyle (kab) localization of Firefox Profiler Co-authored-by: ZiriSut --- locales/kab/app.ftl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/kab/app.ftl b/locales/kab/app.ftl index 1548a4ade0..17bd9c25ce 100644 --- a/locales/kab/app.ftl +++ b/locales/kab/app.ftl @@ -227,6 +227,8 @@ MenuButtons--index--profile-info-uploaded-label = Yuli-d: MenuButtons--index--profile-info-uploaded-actions = Kkes MenuButtons--index--metaInfo-subtitle = Talɣut n umaɣnu MenuButtons--metaInfo--symbols = Izamulen: +MenuButtons--index--show-moreInfo-button = Sken ugar +MenuButtons--index--hide-moreInfo-button = Sken drus MenuButtons--metaInfo--main-process-started = Asesfer agejdan yebda: MenuButtons--metaInfo--main-process-ended = Asesfer agejdan yekfa: MenuButtons--metaInfo--interval = Azilal: From 9fed8931b5738d980414f88903a5d46ad87308f1 Mon Sep 17 00:00:00 2001 From: Luna Jernberg Date: Fri, 16 Dec 2022 04:43:55 +0000 Subject: [PATCH 029/114] Pontoon: Update Swedish (sv-SE) localization of Firefox Profiler Co-authored-by: Luna Jernberg --- locales/sv-SE/app.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/sv-SE/app.ftl b/locales/sv-SE/app.ftl index f059ddb6f6..1e23dfe775 100644 --- a/locales/sv-SE/app.ftl +++ b/locales/sv-SE/app.ftl @@ -15,6 +15,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox för Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly @@ -259,7 +260,6 @@ Home--record-instructions = För att starta profilering, klicka på profileringsknappen eller använd kortkommandona. Ikonen är blå när en profil spelas in. Tryck på Fånga för att ladda data till profiler.firefox.com. -Home--instructions-title = Hur man visar och spelar in profiler Home--instructions-content = För att spela in prestandaprofiler krävs { -firefox-brand-name }. Befintliga profiler kan dock visas i vilken modern webbläsare som helst. From 335c3db0cb83c3c003d116670edec83ee1b43c62 Mon Sep 17 00:00:00 2001 From: ZiriSut Date: Fri, 16 Dec 2022 08:52:34 +0000 Subject: [PATCH 030/114] Pontoon: Update Kabyle (kab) localization of Firefox Profiler Co-authored-by: ZiriSut --- locales/kab/app.ftl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/kab/app.ftl b/locales/kab/app.ftl index 17bd9c25ce..0fc58bc2b5 100644 --- a/locales/kab/app.ftl +++ b/locales/kab/app.ftl @@ -84,6 +84,8 @@ CallTreeSidebar--select-a-node = Fren takerrist i uskan n talɣut fell-as. CompareHome--instruction-title = Sekcem URLs n umaɣnu i tebɣiḍ ad tsenmehleḍ CompareHome--form-label-profile1 = Amaɣnu 1: CompareHome--form-label-profile2 = Amaɣnu 2: +CompareHome--submit-button = + .value = Err-d imaɣunen ## DebugWarning ## This is displayed at the top of the analysis page when the loaded profile is From 4d7944577e142c55d28b69ecdaa4ba9fc5e1eee4 Mon Sep 17 00:00:00 2001 From: Fershad Irani <27988517+fershad@users.noreply.github.com> Date: Tue, 13 Dec 2022 12:01:06 +0800 Subject: [PATCH 031/114] Add carbon metrics values information to the power usage tooltip --- locales/en-US/app.ftl | 18 ++++++---- package.json | 1 + src/components/tooltip/TrackPower.js | 34 ++++++++++++++----- .../__snapshots__/TrackPower.test.js.snap | 2 +- src/types/libdef/npm/@tgwf/co2_vx.x.x.js | 18 ++++++++++ yarn.lock | 7 ++++ 6 files changed, 65 insertions(+), 15 deletions(-) create mode 100644 src/types/libdef/npm/@tgwf/co2_vx.x.x.js diff --git a/locales/en-US/app.ftl b/locales/en-US/app.ftl index 36feb53c0c..3127d3dfde 100644 --- a/locales/en-US/app.ftl +++ b/locales/en-US/app.ftl @@ -790,42 +790,48 @@ TrackPower--tooltip-power-milliwatt = { $value } mW # watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-watthour = { $value } Wh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Wh ({ $carbonValue } g CO₂e) .label = Energy used in the visible range # This is used in the tooltip when the energy used in the current range uses the # milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-milliwatthour = { $value } mWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) .label = Energy used in the visible range # This is used in the tooltip when the energy used in the current range uses the # microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-microwatthour = { $value } µWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) .label = Energy used in the visible range # This is used in the tooltip when the energy used in the current preview # selection uses the watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-watthour = { $value } Wh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-preview-watthour = { $value } Wh ({ $carbonValue } g CO₂e) .label = Energy used in the current selection # This is used in the tooltip when the energy used in the current preview # selection uses the milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-milliwatthour = { $value } mWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) .label = Energy used in the current selection # This is used in the tooltip when the energy used in the current preview # selection uses the microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-microwatthour = { $value } µWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) .label = Energy used in the current selection ## TrackSearchField diff --git a/package.json b/package.json index 94bce2ea05..1cd02a7d00 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "@fluent/langneg": "^0.6.2", "@fluent/react": "^0.14.1", "@lezer/highlight": "^1.1.3", + "@tgwf/co2": "^0.11.4", "array-move": "^3.0.1", "array-range": "^1.0.1", "clamp": "^1.0.1", diff --git a/src/components/tooltip/TrackPower.js b/src/components/tooltip/TrackPower.js index cf7ee8fe71..97fbe754f8 100644 --- a/src/components/tooltip/TrackPower.js +++ b/src/components/tooltip/TrackPower.js @@ -8,6 +8,8 @@ import * as React from 'react'; import { Localized } from '@fluent/react'; import memoize from 'memoize-one'; +import { averageIntensity } from '@tgwf/co2'; + import explicitConnect from 'firefox-profiler/utils/connect'; import { formatNumber } from 'firefox-profiler/utils/format-numbers'; import { @@ -63,6 +65,13 @@ class TooltipTrackPowerImpl extends React.PureComponent { return sum * 1e-12; } + _computeCO2eFromPower(power: number): number { + // total energy Wh to kWh + const energy = power / 1000; + const { WORLD } = averageIntensity.data; + return energy * WORLD; + } + _computePowerSumForCommittedRange = memoize( ({ start, end }: StartEndRange): number => this._computePowerSumForRange(start, end) @@ -85,23 +94,32 @@ class TooltipTrackPowerImpl extends React.PureComponent { l10nIdMilliUnit, l10nIdMicroUnit ): Localized { - let value, l10nId; + let value, l10nId, carbonValue; + const carbon = this._computeCO2eFromPower(power); if (power > 1) { value = formatNumber(power, 3); + carbonValue = formatNumber(carbon, 3); l10nId = l10nIdUnit; } else if (power === 0) { value = 0; + carbonValue = 0; l10nId = l10nIdUnit; } else if (power < 0.001 && l10nIdMicroUnit) { value = formatNumber(power * 1000000); + carbonValue = formatNumber(carbon * 1000); l10nId = l10nIdMicroUnit; } else { value = formatNumber(power * 1000); + carbonValue = formatNumber(carbon * 1000); l10nId = l10nIdMilliUnit; } return ( - + {value} ); @@ -139,16 +157,16 @@ class TooltipTrackPowerImpl extends React.PureComponent { {previewSelection.hasSelection ? this._formatPowerValue( this._computePowerSumForPreviewRange(previewSelection), - 'TrackPower--tooltip-energy-used-in-preview-watthour', - 'TrackPower--tooltip-energy-used-in-preview-milliwatthour', - 'TrackPower--tooltip-energy-used-in-preview-microwatthour' + 'TrackPower--tooltip-energy-carbon-used-in-preview-watthour', + 'TrackPower--tooltip-energy-carbon-used-in-preview-milliwatthour', + 'TrackPower--tooltip-energy-carbon-used-in-preview-microwatthour' ) : null} {this._formatPowerValue( this._computePowerSumForCommittedRange(committedRange), - 'TrackPower--tooltip-energy-used-in-range-watthour', - 'TrackPower--tooltip-energy-used-in-range-milliwatthour', - 'TrackPower--tooltip-energy-used-in-range-microwatthour' + 'TrackPower--tooltip-energy-carbon-used-in-range-watthour', + 'TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour', + 'TrackPower--tooltip-energy-carbon-used-in-range-microwatthour' )} diff --git a/src/test/components/__snapshots__/TrackPower.test.js.snap b/src/test/components/__snapshots__/TrackPower.test.js.snap index baeb177d6c..9c8b7ca90f 100644 --- a/src/test/components/__snapshots__/TrackPower.test.js.snap +++ b/src/test/components/__snapshots__/TrackPower.test.js.snap @@ -27,7 +27,7 @@ exports[`TrackPower has a tooltip that matches the snapshot 1`] = ` Energy used in the visible range : - ⁨7.2⁩ µWh + ⁨7.2⁩ µWh (⁨0.003⁩ mg CO₂e) `; diff --git a/src/types/libdef/npm/@tgwf/co2_vx.x.x.js b/src/types/libdef/npm/@tgwf/co2_vx.x.x.js new file mode 100644 index 0000000000..ceedac16bc --- /dev/null +++ b/src/types/libdef/npm/@tgwf/co2_vx.x.x.js @@ -0,0 +1,18 @@ +// flow-typed signature: b2f76cdf45a9f020ccc81f4258e36209 +// flow-typed version: <>/@tgwf/co2_v0.11.4/flow_v0.96.0 + +/** + * This is an autogenerated libdef stub for: + * + * '@tgwf/co2' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module '@tgwf/co2' { + declare module.exports: any; +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 2ab4b0ecc0..fde1476fcb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1832,6 +1832,13 @@ "@testing-library/dom" "^8.5.0" "@types/react-dom" "^18.0.0" +"@tgwf/co2@^0.11.4": + version "0.11.4" + resolved "https://registry.yarnpkg.com/@tgwf/co2/-/co2-0.11.4.tgz#1e919364a3b1ce5ed835fb6449f78a7c7277e3f4" + integrity sha512-I6e+WzdDpVbKLkTDJXAA0kJvOJQg1TNfTOu7PA5+FfxLEix9EqdigVK0Qd4flC82fLgTKSw4upuh+nCm4fFCaQ== + dependencies: + debug "^4.3.4" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" From fce7bd5ad06249a65104d8011a15156d550cddf5 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Tue, 13 Dec 2022 16:06:39 +0100 Subject: [PATCH 032/114] =?UTF-8?q?Add=20a=20comment=20expliciting=20that?= =?UTF-8?q?=20the=20carbon=20value=20is=20in=20mg=20even=20when=20the=20po?= =?UTF-8?q?wer=20value=20is=20in=20=C2=B5Wh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/tooltip/TrackPower.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/tooltip/TrackPower.js b/src/components/tooltip/TrackPower.js index 97fbe754f8..27bbdb3537 100644 --- a/src/components/tooltip/TrackPower.js +++ b/src/components/tooltip/TrackPower.js @@ -106,6 +106,8 @@ class TooltipTrackPowerImpl extends React.PureComponent { l10nId = l10nIdUnit; } else if (power < 0.001 && l10nIdMicroUnit) { value = formatNumber(power * 1000000); + // Note: even though the power value is expressed in µWh, the carbon value + // is still expressed in mg. carbonValue = formatNumber(carbon * 1000); l10nId = l10nIdMicroUnit; } else { From 714950dbb778a383d7835cad3b0966b41a6e4e3e Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Wed, 14 Dec 2022 15:55:47 +0100 Subject: [PATCH 033/114] Add some more explanation about what CO2 equivalent is --- locales/en-US/app.ftl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/locales/en-US/app.ftl b/locales/en-US/app.ftl index 3127d3dfde..0355ed418f 100644 --- a/locales/en-US/app.ftl +++ b/locales/en-US/app.ftl @@ -771,8 +771,12 @@ TrackMemoryGraph--operations-since-the-previous-sample = operations since the pr ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. # This is used in the tooltip when the power value uses the watt unit. # Variables: From be7568ab655861501667814d7dc9300efb2f1a43 Mon Sep 17 00:00:00 2001 From: Jim Spentzos Date: Sat, 17 Dec 2022 10:23:43 +0000 Subject: [PATCH 034/114] Pontoon: Update Greek (el) localization of Firefox Profiler Co-authored-by: Jim Spentzos --- locales/el/app.ftl | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/locales/el/app.ftl b/locales/el/app.ftl index 46590ff9a3..5b81152355 100644 --- a/locales/el/app.ftl +++ b/locales/el/app.ftl @@ -704,8 +704,12 @@ TrackMemoryGraph--operations-since-the-previous-sample = λειτουργίες ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. # This is used in the tooltip when the power value uses the watt unit. # Variables: @@ -721,38 +725,16 @@ TrackPower--tooltip-power-milliwatt = { $value } mW # watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-watthour = { $value } Wh - .label = Ενέργεια που χρησιμοποιείται στο ορατό εύρος +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Wh ({ $carbonValue } g CO₂e) + .label = Η ενέργεια που χρησιμοποιείται στο ορατό εύρος # This is used in the tooltip when the energy used in the current range uses the # milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-milliwatthour = { $value } mWh - .label = Ενέργεια που χρησιμοποιείται στο ορατό εύρος -# This is used in the tooltip when the energy used in the current range uses the -# microwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-microwatthour = { $value } µWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) .label = Η ενέργεια που χρησιμοποιείται στο ορατό εύρος -# This is used in the tooltip when the energy used in the current preview -# selection uses the watt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-watthour = { $value } Wh - .label = Ενέργεια που χρησιμοποιείται στην τρέχουσα επιλογή -# This is used in the tooltip when the energy used in the current preview -# selection uses the milliwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-milliwatthour = { $value } mWh - .label = Ενέργεια που χρησιμοποιείται στην τρέχουσα επιλογή -# This is used in the tooltip when the energy used in the current preview -# selection uses the microwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-microwatthour = { $value } µWh - .label = Η ενέργεια που χρησιμοποιείται στην τρέχουσα επιλογή ## TrackSearchField ## The component that is used for the search input in the track context menu. From 39f59f5f3a8cfd980b0fb7c0015b3fc1404301da Mon Sep 17 00:00:00 2001 From: Fjoerfoks Date: Sat, 17 Dec 2022 13:43:46 +0000 Subject: [PATCH 035/114] Pontoon: Update Frisian (fy-NL) localization of Firefox Profiler Co-authored-by: Fjoerfoks --- locales/fy-NL/app.ftl | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/locales/fy-NL/app.ftl b/locales/fy-NL/app.ftl index bf72168f0c..fb55cd6d9e 100644 --- a/locales/fy-NL/app.ftl +++ b/locales/fy-NL/app.ftl @@ -712,8 +712,12 @@ TrackMemoryGraph--operations-since-the-previous-sample = bewurkingen sûnt de fo ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. # This is used in the tooltip when the power value uses the watt unit. # Variables: @@ -729,38 +733,44 @@ TrackPower--tooltip-power-milliwatt = { $value } mW # watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-watthour = { $value } Wh - .label = Ferbrûkte enerzjy yn it sichtbere berik +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Wh ({ $carbonValue } g CO₂e) + .label = Enerzjy brûkt yn it sichtbere berik # This is used in the tooltip when the energy used in the current range uses the # milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-milliwatthour = { $value } mWh - .label = Ferbrûkte enerzjy yn it sichtbere berik +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) + .label = Enerzjy brûkt yn it sichtbere berik # This is used in the tooltip when the energy used in the current range uses the # microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-microwatthour = { $value } µWh - .label = Ferbrûkte enerzjy yn it sichtbere berik +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) + .label = Enerzjy brûkt yn it sichtbere berik # This is used in the tooltip when the energy used in the current preview # selection uses the watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-watthour = { $value } Wh - .label = Ferbrûkte enerzjy yn de aktuele seleksje +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-preview-watthour = { $value } Wh ({ $carbonValue } g CO₂e) + .label = Enerzjy brûkt yn de aktuele seleksje # This is used in the tooltip when the energy used in the current preview # selection uses the milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-milliwatthour = { $value } mWh - .label = Ferbrûkte enerzjy yn de aktuele seleksje +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) + .label = Enerzjy brûkt yn de aktuele seleksje # This is used in the tooltip when the energy used in the current preview # selection uses the microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-microwatthour = { $value } µWh - .label = Ferbrûkte enerzjy yn de aktuele seleksje +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) + .label = Enerzjy brûkt yn de aktuele seleksje ## TrackSearchField ## The component that is used for the search input in the track context menu. From 51ee7fff2adf56fd33cf0edab047f7d42c04f1da Mon Sep 17 00:00:00 2001 From: Fjoerfoks Date: Sat, 17 Dec 2022 13:43:48 +0000 Subject: [PATCH 036/114] Pontoon: Update Dutch (nl) localization of Firefox Profiler Co-authored-by: Fjoerfoks --- locales/nl/app.ftl | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/locales/nl/app.ftl b/locales/nl/app.ftl index 0d5a878396..252490ef84 100644 --- a/locales/nl/app.ftl +++ b/locales/nl/app.ftl @@ -712,8 +712,12 @@ TrackMemoryGraph--operations-since-the-previous-sample = bewerkingen sinds de vo ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. # This is used in the tooltip when the power value uses the watt unit. # Variables: @@ -729,38 +733,44 @@ TrackPower--tooltip-power-milliwatt = { $value } mW # watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-watthour = { $value } Wh - .label = Verbruikte energie in het zichtbare bereik +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Wh ({ $carbonValue } g CO₂e) + .label = Energie gebruikt in het zichtbare bereik # This is used in the tooltip when the energy used in the current range uses the # milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-milliwatthour = { $value } mWh - .label = Verbruikte energie in het zichtbare bereik +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) + .label = Energie gebruikt in het zichtbare bereik # This is used in the tooltip when the energy used in the current range uses the # microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-microwatthour = { $value } µWh - .label = Verbruikte energie in het zichtbare bereik +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) + .label = Energie gebruikt in het zichtbare bereik # This is used in the tooltip when the energy used in the current preview # selection uses the watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-watthour = { $value } Wh - .label = Verbruikte energie in de huidige selectie +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-preview-watthour = { $value } Wh ({ $carbonValue } g CO₂e) + .label = Energie gebruikt in de huidige selectie # This is used in the tooltip when the energy used in the current preview # selection uses the milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-milliwatthour = { $value } mWh - .label = Verbruikte energie in de huidige selectie +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) + .label = Energie gebruikt in de huidige selectie # This is used in the tooltip when the energy used in the current preview # selection uses the microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-microwatthour = { $value } µWh - .label = Verbruikte energie in de huidige selectie +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) + .label = Energie gebruikt in de huidige selectie ## TrackSearchField ## The component that is used for the search input in the track context menu. From 2772361fbea893ee32378e7ffaf7568a22ba8722 Mon Sep 17 00:00:00 2001 From: "Francesco Lodolo [:flod]" Date: Sat, 17 Dec 2022 14:34:04 +0000 Subject: [PATCH 037/114] Pontoon: Update Italian (it) localization of Firefox Profiler Co-authored-by: Francesco Lodolo [:flod] --- locales/it/app.ftl | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/locales/it/app.ftl b/locales/it/app.ftl index 6a12ab10ae..f6c027ef83 100644 --- a/locales/it/app.ftl +++ b/locales/it/app.ftl @@ -637,8 +637,12 @@ TrackMemoryGraph--operations-since-the-previous-sample = operazioni dal campione ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. # This is used in the tooltip when the power value uses the watt unit. # Variables: @@ -654,37 +658,43 @@ TrackPower--tooltip-power-milliwatt = { $value } mW # watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-watthour = { $value } Wh - .label = Energia utilizzata nell’intervallo visualizzato +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Wh ({ $carbonValue } g CO₂e) + .label = Energia utiizzata nell’intervallo visibile # This is used in the tooltip when the energy used in the current range uses the # milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-milliwatthour = { $value } mWh - .label = Energia utilizzata nell’intervallo visualizzato +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) + .label = Energia utiizzata nell’intervallo visibile # This is used in the tooltip when the energy used in the current range uses the # microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-microwatthour = { $value } µWh - .label = Energia utilizzata nell’intervallo visualizzato +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) + .label = Energia utilizzata nell’intervallo visibile # This is used in the tooltip when the energy used in the current preview # selection uses the watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-watthour = { $value } Wh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-preview-watthour = { $value } Wh ({ $carbonValue } g CO₂e) .label = Energia utilizzata nella selezione corrente # This is used in the tooltip when the energy used in the current preview # selection uses the milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-milliwatthour = { $value } mWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) .label = Energia utilizzata nella selezione corrente # This is used in the tooltip when the energy used in the current preview # selection uses the microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-microwatthour = { $value } µWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) .label = Energia utilizzata nella selezione corrente ## TrackSearchField From 8acf0a058ad1dfe947d068672bfe5933f0034cec Mon Sep 17 00:00:00 2001 From: Andreas Pettersson Date: Sat, 17 Dec 2022 14:34:06 +0000 Subject: [PATCH 038/114] Pontoon: Update Swedish (sv-SE) localization of Firefox Profiler Co-authored-by: Andreas Pettersson --- locales/sv-SE/app.ftl | 54 ++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 37 deletions(-) diff --git a/locales/sv-SE/app.ftl b/locales/sv-SE/app.ftl index 1e23dfe775..ada8bc573d 100644 --- a/locales/sv-SE/app.ftl +++ b/locales/sv-SE/app.ftl @@ -243,6 +243,10 @@ Home--menu-button = Aktivera { -profiler-brand-name } menyknapp Home--menu-button-instructions = Aktivera profil-menyknappen för att börja spela in en prestandaprofil i { -firefox-brand-name }, analysera den och dela den med profiler.firefox.com. +Home--profile-firefox-android-instructions = + Du kan också profilera { -firefox-android-brand-name }. För mer + information, se denna dokumentation: + Profilering av { -firefox-android-brand-name } direkt på enheten. # The word WebChannel should not be translated. # This message can be seen on https://main--perf-html.netlify.app/ in the tooltip # of the "Enable Firefox Profiler menu button" button. @@ -270,6 +274,14 @@ Home--additional-content-title = Ladda befintliga profiler Home--additional-content-content = Du kan dra och släppa en profilfil här för att ladda den, eller: Home--compare-recordings-info = Du kan också jämföra inspelningar.Öppna gränssnitt för att jämföra. Home--your-recent-uploaded-recordings-title = Dina senaste uppladdade inspelningar +# We replace the elements such as and with links to the +# documentation to use these tools. +Home--load-files-from-other-tools = + { -profiler-brand-name } kan också importera profiler från andra profilerare, t.ex + Linux perf, Android SimplePerf, + Chrome prestandapanel, Android Studio eller + vilken fil som helst som använder dhat-formatet. Lär dig hur du skriver din + egen importör. ## IdleSearchField ## The component that is used for all the search inputs in the application. @@ -699,8 +711,12 @@ TrackMemoryGraph--operations-since-the-previous-sample = operationer sedan före ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. # This is used in the tooltip when the power value uses the watt unit. # Variables: @@ -712,42 +728,6 @@ TrackPower--tooltip-power-watt = { $value } W # $value (String) - the power value at this location TrackPower--tooltip-power-milliwatt = { $value } mW .label = Effekt -# This is used in the tooltip when the energy used in the current range uses the -# watt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-watthour = { $value } Wh - .label = Energi som används i det synliga området -# This is used in the tooltip when the energy used in the current range uses the -# milliwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-milliwatthour = { $value } mWh - .label = Energi som används i det synliga området -# This is used in the tooltip when the energy used in the current range uses the -# microwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-microwatthour = { $value } µWh - .label = Energi som används i det synliga området -# This is used in the tooltip when the energy used in the current preview -# selection uses the watt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-watthour = { $value } Wh - .label = Energi som används i det aktuella urvalet -# This is used in the tooltip when the energy used in the current preview -# selection uses the milliwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-milliwatthour = { $value } mWh - .label = Energi som används i det aktuella urvalet -# This is used in the tooltip when the energy used in the current preview -# selection uses the microwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-microwatthour = { $value } µWh - .label = Energi som används i det aktuella urvalet ## TrackSearchField ## The component that is used for the search input in the track context menu. From df5a8912f925fb4d86546e4bba5205bfd003d7ee Mon Sep 17 00:00:00 2001 From: "Francesco Lodolo [:flod]" Date: Sat, 17 Dec 2022 14:43:34 +0000 Subject: [PATCH 039/114] Pontoon: Update Italian (it) localization of Firefox Profiler Co-authored-by: Francesco Lodolo [:flod] --- locales/it/app.ftl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/it/app.ftl b/locales/it/app.ftl index f6c027ef83..052287be0e 100644 --- a/locales/it/app.ftl +++ b/locales/it/app.ftl @@ -660,14 +660,14 @@ TrackPower--tooltip-power-milliwatt = { $value } mW # $value (String) - the energy value for this range # $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Wh ({ $carbonValue } g CO₂e) - .label = Energia utiizzata nell’intervallo visibile + .label = Energia utilizzata nell’intervallo visibile # This is used in the tooltip when the energy used in the current range uses the # milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range # $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) - .label = Energia utiizzata nell’intervallo visibile + .label = Energia utilizzata nell’intervallo visibile # This is used in the tooltip when the energy used in the current range uses the # microwatt-hour unit. # Variables: From e60dc6916881849a1353301364e2de01580ad6b9 Mon Sep 17 00:00:00 2001 From: Andreas Pettersson Date: Sat, 17 Dec 2022 14:43:35 +0000 Subject: [PATCH 040/114] Pontoon: Update Swedish (sv-SE) localization of Firefox Profiler Co-authored-by: Andreas Pettersson --- locales/sv-SE/app.ftl | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/locales/sv-SE/app.ftl b/locales/sv-SE/app.ftl index ada8bc573d..51ac118bae 100644 --- a/locales/sv-SE/app.ftl +++ b/locales/sv-SE/app.ftl @@ -728,6 +728,48 @@ TrackPower--tooltip-power-watt = { $value } W # $value (String) - the power value at this location TrackPower--tooltip-power-milliwatt = { $value } mW .label = Effekt +# This is used in the tooltip when the energy used in the current range uses the +# watt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Wh ({ $carbonValue } g CO₂e) + .label = Energi som används i det synliga området +# This is used in the tooltip when the energy used in the current range uses the +# milliwatt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) + .label = Energi som används i det synliga området +# This is used in the tooltip when the energy used in the current range uses the +# microwatt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) + .label = Energi som används i det synliga området +# This is used in the tooltip when the energy used in the current preview +# selection uses the watt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-preview-watthour = { $value } Wh ({ $carbonValue } g CO₂e) + .label = Energi som används i det aktuella urvalet +# This is used in the tooltip when the energy used in the current preview +# selection uses the milliwatt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) + .label = Energi som används i det aktuella urvalet +# This is used in the tooltip when the energy used in the current preview +# selection uses the microwatt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) + .label = Energi som används i det aktuella urvalet ## TrackSearchField ## The component that is used for the search input in the track context menu. From 49eb6c8890e7996fcb7b118c9b51fd903ec7f6a4 Mon Sep 17 00:00:00 2001 From: robovoice Date: Sat, 17 Dec 2022 21:10:34 +0000 Subject: [PATCH 041/114] Pontoon: Update German (de) localization of Firefox Profiler Co-authored-by: robovoice --- locales/de/app.ftl | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/locales/de/app.ftl b/locales/de/app.ftl index 27504c44c4..9762b9304d 100644 --- a/locales/de/app.ftl +++ b/locales/de/app.ftl @@ -693,8 +693,12 @@ TrackMemoryGraph--operations-since-the-previous-sample = Operationen seit der vo ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. # This is used in the tooltip when the power value uses the watt unit. # Variables: @@ -710,38 +714,44 @@ TrackPower--tooltip-power-milliwatt = { $value } mW # watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-watthour = { $value } Wh - .label = Im sichtbaren Bereich verbrauchte Energie +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Wh ({ $carbonValue } g CO₂e) + .label = Im sichtbaren Bereich verwendete Energie # This is used in the tooltip when the energy used in the current range uses the # milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-milliwatthour = { $value } mWh - .label = Im sichtbaren Bereich verbrauchte Energie +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) + .label = Im sichtbaren Bereich verwendete Energie # This is used in the tooltip when the energy used in the current range uses the # microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-microwatthour = { $value } µWh - .label = Im sichtbaren Bereich verbrauchte Energie +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) + .label = Im sichtbaren Bereich verwendete Energie # This is used in the tooltip when the energy used in the current preview # selection uses the watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-watthour = { $value } Wh - .label = In der aktuellen Auswahl verbrauchte Energie +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-preview-watthour = { $value } Wh ({ $carbonValue } g CO₂e) + .label = In der aktuellen Auswahl verwendete Energie # This is used in the tooltip when the energy used in the current preview # selection uses the milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-milliwatthour = { $value } mWh - .label = In der aktuellen Auswahl verbrauchte Energie +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) + .label = In der aktuellen Auswahl verwendete Energie # This is used in the tooltip when the energy used in the current preview # selection uses the microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-microwatthour = { $value } µWh - .label = Im ausgewählten Bereich verbrauchte Energie +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) + .label = In der aktuellen Auswahl verwendete Energie ## TrackSearchField ## The component that is used for the search input in the track context menu. From c4aaf5fb29f10e9f802620ddd606cc6b50c791ea Mon Sep 17 00:00:00 2001 From: ravmn Date: Sat, 17 Dec 2022 23:13:57 +0000 Subject: [PATCH 042/114] Pontoon: Update Spanish (Chile) (es-CL) localization of Firefox Profiler Co-authored-by: ravmn --- locales/es-CL/app.ftl | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/locales/es-CL/app.ftl b/locales/es-CL/app.ftl index 439f43ad3d..0b96825e9c 100644 --- a/locales/es-CL/app.ftl +++ b/locales/es-CL/app.ftl @@ -653,8 +653,12 @@ TrackMemoryGraph--operations-since-the-previous-sample = operaciones desde la mu ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. # This is used in the tooltip when the power value uses the watt unit. # Variables: @@ -670,38 +674,44 @@ TrackPower--tooltip-power-milliwatt = { $value } mW # watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-watthour = { $value } Wh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Wh ({ $carbonValue } g CO₂e) .label = Energía usada en el rango visible # This is used in the tooltip when the energy used in the current range uses the # milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-milliwatthour = { $value } mWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) .label = Energía usada en el rango visible # This is used in the tooltip when the energy used in the current range uses the # microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-microwatthour = { $value } µWh - .label = Energía utilizada en el rango visible +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) + .label = Energía usada en el rango visible # This is used in the tooltip when the energy used in the current preview # selection uses the watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-watthour = { $value } Wh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-preview-watthour = { $value } Wh ({ $carbonValue } g CO₂e) .label = Energía usada en la selección actual # This is used in the tooltip when the energy used in the current preview # selection uses the milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-milliwatthour = { $value } mWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) .label = Energía usada en la selección actual # This is used in the tooltip when the energy used in the current preview # selection uses the microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-microwatthour = { $value } µWh - .label = Energía utilizada en la selección actual +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) + .label = Energía usada en la selección actual ## TrackSearchField ## The component that is used for the search input in the track context menu. From e6f0363665afa5979fb1932339d3dd75ee8f84c6 Mon Sep 17 00:00:00 2001 From: Melo46 Date: Sat, 17 Dec 2022 23:53:58 +0000 Subject: [PATCH 043/114] Pontoon: Update Interlingua (ia) localization of Firefox Profiler Co-authored-by: Melo46 --- locales/ia/app.ftl | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/locales/ia/app.ftl b/locales/ia/app.ftl index 679e7c42b4..4b10cbf3e9 100644 --- a/locales/ia/app.ftl +++ b/locales/ia/app.ftl @@ -695,8 +695,12 @@ TrackMemoryGraph--operations-since-the-previous-sample = operationes depost le p ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. # This is used in the tooltip when the power value uses the watt unit. # Variables: @@ -712,37 +716,43 @@ TrackPower--tooltip-power-milliwatt = { $value } mW # watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-watthour = { $value } Wh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Wh ({ $carbonValue } g CO₂e) .label = Energia usate in le campo visibile # This is used in the tooltip when the energy used in the current range uses the # milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-milliwatthour = { $value } mWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) .label = Energia usate in le campo visibile # This is used in the tooltip when the energy used in the current range uses the # microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-microwatthour = { $value } µWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) .label = Energia usate in le campo visibile # This is used in the tooltip when the energy used in the current preview # selection uses the watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-watthour = { $value } Wh - .label = Energia usate in le campo visibile +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-preview-watthour = { $value } Wh ({ $carbonValue } g CO₂e) + .label = Energia usate in le selection actual # This is used in the tooltip when the energy used in the current preview # selection uses the milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-milliwatthour = { $value } mWh - .label = Energia usate in le campo visibile +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) + .label = Energia usate in le selection actual # This is used in the tooltip when the energy used in the current preview # selection uses the microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-microwatthour = { $value } µWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) .label = Energia usate in le selection actual ## TrackSearchField From f9c1183d588bb52d64f0db419722f98041434ae0 Mon Sep 17 00:00:00 2001 From: Ian Neal Date: Sun, 18 Dec 2022 02:34:04 +0000 Subject: [PATCH 044/114] Pontoon: Update English (Great Britain) (en-GB) localization of Firefox Profiler Co-authored-by: Ian Neal --- locales/en-GB/app.ftl | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/locales/en-GB/app.ftl b/locales/en-GB/app.ftl index fb1361563e..95efce0f9b 100644 --- a/locales/en-GB/app.ftl +++ b/locales/en-GB/app.ftl @@ -716,8 +716,12 @@ TrackMemoryGraph--operations-since-the-previous-sample = operations since the pr ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. # This is used in the tooltip when the power value uses the watt unit. # Variables: @@ -733,37 +737,43 @@ TrackPower--tooltip-power-milliwatt = { $value } mW # watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-watthour = { $value } Wh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Wh ({ $carbonValue } g CO₂e) .label = Energy used in the visible range # This is used in the tooltip when the energy used in the current range uses the # milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-milliwatthour = { $value } mWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) .label = Energy used in the visible range # This is used in the tooltip when the energy used in the current range uses the # microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-microwatthour = { $value } µWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) .label = Energy used in the visible range # This is used in the tooltip when the energy used in the current preview # selection uses the watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-watthour = { $value } Wh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-preview-watthour = { $value } Wh ({ $carbonValue } g CO₂e) .label = Energy used in the current selection # This is used in the tooltip when the energy used in the current preview # selection uses the milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-milliwatthour = { $value } mWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) .label = Energy used in the current selection # This is used in the tooltip when the energy used in the current preview # selection uses the microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-microwatthour = { $value } µWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) .label = Energy used in the current selection ## TrackSearchField From 5d1d224b8dbc0e8841a2dc8c0a687d27b09e141d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=86hor=20Hordiichuk?= Date: Sun, 18 Dec 2022 20:34:06 +0000 Subject: [PATCH 045/114] Pontoon: Update Ukrainian (uk) localization of Firefox Profiler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Іhor Hordiichuk --- locales/uk/app.ftl | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/locales/uk/app.ftl b/locales/uk/app.ftl index 2e2cf2914a..3bcc12735e 100644 --- a/locales/uk/app.ftl +++ b/locales/uk/app.ftl @@ -714,8 +714,12 @@ TrackMemoryGraph--operations-since-the-previous-sample = операції, по ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. # This is used in the tooltip when the power value uses the watt unit. # Variables: @@ -731,38 +735,44 @@ TrackPower--tooltip-power-milliwatt = { $value } мВт # watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-watthour = { $value } Вт·год - .label = Використовувана у видимому діапазоні енергія +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Вт·год ({ $carbonValue } г CO₂e) + .label = Спожита у видимому діапазоні енергія # This is used in the tooltip when the energy used in the current range uses the # milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-milliwatthour = { $value } мВт·год - .label = Використовувана у видимому діапазоні енергія +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour = { $value } мВт·год ({ $carbonValue } мг CO₂е) + .label = Спожита у видимому діапазоні енергія # This is used in the tooltip when the energy used in the current range uses the # microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-microwatthour = { $value } µВт·год - .label = Використовувана енергія у видимому діапазоні +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-microwatthour = { $value } мкВт·год ({ $carbonValue } мг CO₂e) + .label = Спожита у видимому діапазоні енергія # This is used in the tooltip when the energy used in the current preview # selection uses the watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-watthour = { $value } Вт·год - .label = Використовувана в поточному виборі енергія +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-preview-watthour = { $value } Вт·год ({ $carbonValue } г CO₂e) + .label = Спожита у поточній вибірці енергія # This is used in the tooltip when the energy used in the current preview # selection uses the milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-milliwatthour = { $value } Вт·год - .label = Використовувана в поточному виборі енергія +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-milliwatthour = { $value } мВт·год ({ $carbonValue } мг CO₂е) + .label = Спожита у поточній вибірці енергія # This is used in the tooltip when the energy used in the current preview # selection uses the microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-microwatthour = { $value } µВт·год - .label = Використана в поточній вибірці енергія +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-microwatthour = { $value } мкВт·год ({ $carbonValue } мг CO₂e) + .label = Спожита у поточній вибірці енергія ## TrackSearchField ## The component that is used for the search input in the track context menu. From e0166472b9eab865cb9181010bee0d97be7e728e Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Mon, 19 Dec 2022 10:57:47 +0100 Subject: [PATCH 046/114] Update all development Yarn dependencies (2022-12-19) (PR #4379) Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com> --- package.json | 6 +++--- yarn.lock | 54 ++++++++++++++++++++++++++-------------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index 1cd02a7d00..6473f62336 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "babel-loader": "^9.1.0", "babel-plugin-module-resolver": "^4.1.0", "browserslist": "^4.21.4", - "caniuse-lite": "^1.0.30001431", + "caniuse-lite": "^1.0.30001439", "circular-dependency-plugin": "^5.2.1", "codecov": "^3.8.3", "copy-webpack-plugin": "^11.0.0", @@ -146,7 +146,7 @@ "mkdirp": "^1.0.4", "node-fetch": "^2.6.7", "npm-run-all": "^4.1.5", - "postcss": "^8.4.16", + "postcss": "^8.4.20", "postcss-loader": "^7.0.2", "prettier": "^2.8.0", "raw-loader": "^4.0.2", @@ -158,7 +158,7 @@ "stylelint-config-standard": "^29.0.0", "stylelint-prettier": "^2.0.0", "webpack": "^5.75.0", - "webpack-cli": "^5.0.0", + "webpack-cli": "^5.0.1", "webpack-dev-server": "^4.11.1", "workbox-webpack-plugin": "^6.5.4" }, diff --git a/yarn.lock b/yarn.lock index fde1476fcb..b2e1a06897 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2480,20 +2480,20 @@ "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" -"@webpack-cli/configtest@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.0.0.tgz#5e1bc37064c7d00e1330641fa523f8ff85a39513" - integrity sha512-war4OU8NGjBqU3DP3bx6ciODXIh7dSXcpQq+P4K2Tqyd8L5OjZ7COx9QXx/QdCIwL2qoX09Wr4Cwf7uS4qdEng== +"@webpack-cli/configtest@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.0.1.tgz#a69720f6c9bad6aef54a8fa6ba9c3533e7ef4c7f" + integrity sha512-njsdJXJSiS2iNbQVS0eT8A/KPnmyH4pv1APj2K0d1wrZcBLw+yppxOy4CGqa0OxDJkzfL/XELDhD8rocnIwB5A== -"@webpack-cli/info@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.0.tgz#5a58476b129ee9b462117b23393596e726bf3b80" - integrity sha512-NNxDgbo4VOkNhOlTgY0Elhz3vKpOJq4/PKeKg7r8cmYM+GQA9vDofLYyup8jS6EpUvhNmR30cHTCEIyvXpskwA== +"@webpack-cli/info@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.1.tgz#eed745799c910d20081e06e5177c2b2569f166c0" + integrity sha512-fE1UEWTwsAxRhrJNikE7v4EotYflkEhBL7EbajfkPlf6E37/2QshOy/D48Mw8G5XMFlQtS6YV42vtbG9zBpIQA== -"@webpack-cli/serve@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.0.tgz#f08ea194e01ed45379383a8886e8c85a65a5f26a" - integrity sha512-Rumq5mHvGXamnOh3O8yLk1sjx8dB30qF1OeR6VC00DIR6SLJ4bwwUGKC4pE7qBFoQyyh0H9sAg3fikYgAqVR0w== +"@webpack-cli/serve@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.1.tgz#34bdc31727a1889198855913db2f270ace6d7bf8" + integrity sha512-0G7tNyS+yW8TdgHwZKlDWYXFA6OJQnoLCQvYKkQP0Q2X205PSQ6RNUj0M+1OB/9gRQaUZ/ccYfaxd0nhaWKfjw== "@xtuc/ieee754@^1.2.0": version "1.2.0" @@ -3324,10 +3324,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001426, caniuse-lite@^1.0.30001431: - version "1.0.30001431" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz#e7c59bd1bc518fae03a4656be442ce6c4887a795" - integrity sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001426, caniuse-lite@^1.0.30001439: + version "1.0.30001439" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz#ab7371faeb4adff4b74dad1718a6fd122e45d9cb" + integrity sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A== ccount@^2.0.0: version "2.0.1" @@ -9793,10 +9793,10 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.3.11, postcss@^8.4.16, postcss@^8.4.18, postcss@^8.4.19: - version "8.4.19" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.19.tgz#61178e2add236b17351897c8bcc0b4c8ecab56fc" - integrity sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA== +postcss@^8.3.11, postcss@^8.4.18, postcss@^8.4.19, postcss@^8.4.20: + version "8.4.20" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.20.tgz#64c52f509644cecad8567e949f4081d98349dc56" + integrity sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g== dependencies: nanoid "^3.3.4" picocolors "^1.0.0" @@ -12589,15 +12589,15 @@ webidl-conversions@^7.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== -webpack-cli@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.0.0.tgz#bd380a9653e0cd1a08916c4ff1adea17201ef68f" - integrity sha512-AACDTo20yG+xn6HPW5xjbn2Be4KUzQPebWXsDMHwPPyKh9OnTOJgZN2Nc+g/FZKV3ObRTYsGvibAvc+5jAUrVA== +webpack-cli@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.0.1.tgz#95fc0495ac4065e9423a722dec9175560b6f2d9a" + integrity sha512-S3KVAyfwUqr0Mo/ur3NzIp6jnerNpo7GUO6so51mxLi1spqsA17YcMXy0WOIJtBSnj748lthxC6XLbNKh/ZC+A== dependencies: "@discoveryjs/json-ext" "^0.5.0" - "@webpack-cli/configtest" "^2.0.0" - "@webpack-cli/info" "^2.0.0" - "@webpack-cli/serve" "^2.0.0" + "@webpack-cli/configtest" "^2.0.1" + "@webpack-cli/info" "^2.0.1" + "@webpack-cli/serve" "^2.0.1" colorette "^2.0.14" commander "^9.4.1" cross-spawn "^7.0.3" From 43f87a72d739783ff9e74df2f1549fdd20d07862 Mon Sep 17 00:00:00 2001 From: Marcelo Ghelman Date: Mon, 19 Dec 2022 11:03:44 +0000 Subject: [PATCH 047/114] Pontoon: Update Portuguese (Brazil) (pt-BR) localization of Firefox Profiler Co-authored-by: Marcelo Ghelman --- locales/pt-BR/app.ftl | 41 ++++++++--------------------------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/locales/pt-BR/app.ftl b/locales/pt-BR/app.ftl index 94ca8c804b..7d61bb30ed 100644 --- a/locales/pt-BR/app.ftl +++ b/locales/pt-BR/app.ftl @@ -644,8 +644,12 @@ TrackMemoryGraph--operations-since-the-previous-sample = operações desde a amo ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. # This is used in the tooltip when the power value uses the watt unit. # Variables: @@ -661,38 +665,9 @@ TrackPower--tooltip-power-milliwatt = { $value } mW # watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-watthour = { $value } Wh - .label = Energia usada na escala visível -# This is used in the tooltip when the energy used in the current range uses the -# milliwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-milliwatthour = { $value } mWh - .label = Energia usada na escala visível -# This is used in the tooltip when the energy used in the current range uses the -# microwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-microwatthour = { $value } µWh - .label = Energia usada na escala visível -# This is used in the tooltip when the energy used in the current preview -# selection uses the watt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-watthour = { $value } Wh - .label = Energia usada na seleção atual -# This is used in the tooltip when the energy used in the current preview -# selection uses the milliwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-milliwatthour = { $value } mWh - .label = Energia usada na seleção atual -# This is used in the tooltip when the energy used in the current preview -# selection uses the microwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-microwatthour = { $value } µWh - .label = Energia usada na seleção atual +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Wh ({ $carbonValue } g CO₂e) + .label = Energia usada no intervalo visível ## TrackSearchField ## The component that is used for the search input in the track context menu. From e10263cae42c46261b4d5e344c0de83514f15429 Mon Sep 17 00:00:00 2001 From: Marcelo Ghelman Date: Mon, 19 Dec 2022 11:13:07 +0000 Subject: [PATCH 048/114] Pontoon: Update Portuguese (Brazil) (pt-BR) localization of Firefox Profiler Co-authored-by: Marcelo Ghelman --- locales/pt-BR/app.ftl | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/locales/pt-BR/app.ftl b/locales/pt-BR/app.ftl index 7d61bb30ed..b38d9c54c2 100644 --- a/locales/pt-BR/app.ftl +++ b/locales/pt-BR/app.ftl @@ -668,6 +668,41 @@ TrackPower--tooltip-power-milliwatt = { $value } mW # $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Wh ({ $carbonValue } g CO₂e) .label = Energia usada no intervalo visível +# This is used in the tooltip when the energy used in the current range uses the +# milliwatt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) + .label = Energia usada no intervalo visível +# This is used in the tooltip when the energy used in the current range uses the +# microwatt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) + .label = Energia usada no intervalo visível +# This is used in the tooltip when the energy used in the current preview +# selection uses the watt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-preview-watthour = { $value } Wh ({ $carbonValue } g CO₂e) + .label = Energia usada na seleção atual +# This is used in the tooltip when the energy used in the current preview +# selection uses the milliwatt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-milliwatthour = { $value } mWh ({ $carbonValue } mg CO₂e) + .label = Energia usada na seleção atual +# This is used in the tooltip when the energy used in the current preview +# selection uses the microwatt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-microwatthour = { $value } µWh ({ $carbonValue } mg CO₂e) + .label = Energia usada na seleção atual ## TrackSearchField ## The component that is used for the search input in the track context menu. From 33c4861e507b8dcda6528b7dab6cfad39914a2ab Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Mon, 19 Dec 2022 14:25:28 +0100 Subject: [PATCH 049/114] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Update=20@codemirr?= =?UTF-8?q?or/view=20to=20version=206.7.1=20(PR=20#4380)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 6473f62336..6ef071407a 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "@codemirror/lang-rust": "^6.0.1", "@codemirror/language": "^6.3.1", "@codemirror/state": "^6.1.4", - "@codemirror/view": "^6.5.1", + "@codemirror/view": "^6.7.1", "@firefox-devtools/react-contextmenu": "^5.1.0", "@fluent/bundle": "^0.17.1", "@fluent/langneg": "^0.6.2", diff --git a/yarn.lock b/yarn.lock index b2e1a06897..be6da3b612 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1120,10 +1120,10 @@ resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.1.4.tgz#2b654ae233ac4f41ee89ce095509ea35ecdf1031" integrity sha512-g+3OJuRylV5qsXuuhrc6Cvs1NQluNioepYMM2fhnpYkNk7NgX+j0AFuevKSVKzTDmDyt9+Puju+zPdHNECzCNQ== -"@codemirror/view@^6.0.0", "@codemirror/view@^6.5.1": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.5.1.tgz#f4533cd796f0569508822d0012bee9a15dc4b3f9" - integrity sha512-xBKP8N3AXOs06VcKvIuvIQoUlGs7Hb78ftJWahLaRX909jKPMgGxR5XjvrawzTTZMSTU3DzdjDNPwG6fPM/ypQ== +"@codemirror/view@^6.0.0", "@codemirror/view@^6.7.1": + version "6.7.1" + resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.7.1.tgz#370e95d6f001e7f5cadc459807974b4f0a6eb225" + integrity sha512-kYtS+uqYw/q/0ytYxpkqE1JVuK5NsbmBklWYhwLFTKO9gVuTdh/kDEeZPKorbqHcJ+P+ucrhcsS1czVweOpT2g== dependencies: "@codemirror/state" "^6.1.4" style-mod "^4.0.0" From 1583680d6f6eb34afff8704545082c5e2d3c4576 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Mon, 12 Dec 2022 18:28:35 +0100 Subject: [PATCH 050/114] Make getMarkerSchemaName take the marker name and payload in two different arguments This is useful so that we can use this function from the raw marker table as well. --- src/components/marker-table/index.js | 6 ++++- src/components/tooltip/Marker.js | 6 ++++- src/profile-logic/marker-data.js | 10 ++++++-- src/profile-logic/marker-schema.js | 37 +++++++++++++++++----------- 4 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/components/marker-table/index.js b/src/components/marker-table/index.js index 6928167fd2..1f85812064 100644 --- a/src/components/marker-table/index.js +++ b/src/components/marker-table/index.js @@ -123,7 +123,11 @@ class MarkerTree { start: _formatStart(marker.start, this._zeroAt), duration, name, - type: getMarkerSchemaName(this._markerSchemaByName, marker), + type: getMarkerSchemaName( + this._markerSchemaByName, + marker.name, + marker.data + ), }; this._displayDataByIndex.set(markerIndex, displayData); } diff --git a/src/components/tooltip/Marker.js b/src/components/tooltip/Marker.js index 672a5cb391..acd35d5778 100644 --- a/src/components/tooltip/Marker.js +++ b/src/components/tooltip/Marker.js @@ -230,7 +230,11 @@ class MarkerTooltipContents extends React.PureComponent { if (data) { // Add the details for the markers based on their Marker schema. - const schema = getSchemaFromMarker(markerSchemaByName, marker); + const schema = getSchemaFromMarker( + markerSchemaByName, + marker.name, + marker.data + ); if (schema) { for (const schemaData of schema.data) { // Check for a schema that is looking up and formatting a value from diff --git a/src/profile-logic/marker-data.js b/src/profile-logic/marker-data.js index 3d31ed39aa..f61c1b20a6 100644 --- a/src/profile-logic/marker-data.js +++ b/src/profile-logic/marker-data.js @@ -161,7 +161,11 @@ export function getSearchFilteredMarkerIndexes( } // Now check the schema for the marker payload for searchable - const markerSchema = getSchemaFromMarker(markerSchemaByName, marker); + const markerSchema = getSchemaFromMarker( + markerSchemaByName, + marker.name, + marker.data + ); if ( markerSchema && markerPayloadMatchesSearch(markerSchema, marker, regExp) @@ -1362,7 +1366,9 @@ export function filterMarkerByDisplayLocation( return additionalResult; } - return markerTypes.has(getMarkerSchemaName(markerSchemaByName, marker)); + return markerTypes.has( + getMarkerSchemaName(markerSchemaByName, marker.name, marker.data) + ); }); } diff --git a/src/profile-logic/marker-schema.js b/src/profile-logic/marker-schema.js index f8c8d7c029..01c8d499f4 100644 --- a/src/profile-logic/marker-schema.js +++ b/src/profile-logic/marker-schema.js @@ -22,6 +22,7 @@ import type { MarkerSchemaByName, Marker, MarkerIndex, + MarkerPayload, } from 'firefox-profiler/types'; /** @@ -86,34 +87,33 @@ export const markerSchemaFrontEndOnly: MarkerSchema[] = [ */ export function getMarkerSchemaName( markerSchemaByName: MarkerSchemaByName, - marker: Marker + markerName: string, + markerData: MarkerPayload | null ): string { - const { data, name } = marker; - // Fall back to using the name if no payload exists. - - if (data) { - const { type } = data; - if (type === 'tracing' && data.category) { + if (markerData) { + const { type } = markerData; + if (type === 'tracing' && markerData.category) { // TODO - Tracing markers have a duplicate "category" field. // See issue #2749 // Does a marker schema for the "category" exist? - return markerSchemaByName[data.category] === undefined + return markerSchemaByName[markerData.category] === undefined ? // If not, default back to tracing 'tracing' : // If so, use the category as the schema name. - data.category; + markerData.category; } if (type === 'Text') { // Text markers are a cheap and easy way to create markers with // a category. Check for schema if it exists, if not, fallback to // a Text type marker. - return markerSchemaByName[name] === undefined ? 'Text' : name; + return markerSchemaByName[markerName] === undefined ? 'Text' : markerName; } - return data.type; + return markerData.type; } - return name; + // Fall back to using the name if no payload exists. + return markerName; } /** @@ -122,10 +122,13 @@ export function getMarkerSchemaName( */ export function getSchemaFromMarker( markerSchemaByName: MarkerSchemaByName, - marker: Marker + markerName: string, + markerData: MarkerPayload | null ): MarkerSchema | null { return ( - markerSchemaByName[getMarkerSchemaName(markerSchemaByName, marker)] || null + markerSchemaByName[ + getMarkerSchemaName(markerSchemaByName, markerName, markerData) + ] || null ); } @@ -349,7 +352,11 @@ export function getLabelGetter( // No label exists, it will have to be generated for the first time. if (label === undefined) { const marker = getMarker(markerIndex); - const schemaName = getMarkerSchemaName(markerSchemaByName, marker); + const schemaName = getMarkerSchemaName( + markerSchemaByName, + marker.name, + marker.data + ); const applyLabel = labelFns.get(schemaName); label = applyLabel From 04ca59a3595e868c9ccc7c7a01addc9025ddeba9 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Wed, 14 Dec 2022 11:36:52 +0100 Subject: [PATCH 051/114] Isolate the marker operations relative to URLs in their own block --- src/profile-logic/sanitize.js | 57 +++++++++++++++-------------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/src/profile-logic/sanitize.js b/src/profile-logic/sanitize.js index 7b0f93e42a..7c4c93c9c0 100644 --- a/src/profile-logic/sanitize.js +++ b/src/profile-logic/sanitize.js @@ -274,40 +274,33 @@ function sanitizeThreadPII( markerTable.data[i] = removePrefMarkerPreferenceValues(currentMarker); } - // Remove the all network URLs if user wants to remove them. - if ( - PIIToBeRemoved.shouldRemoveUrls && - currentMarker && - currentMarker.type === 'Network' - ) { - // Remove the URI fields from marker payload. - markerTable.data[i] = removeNetworkMarkerURLs(currentMarker); - - // Strip the URL from the marker name - const stringIndex = markerTable.name[i]; - stringArray[stringIndex] = stringArray[stringIndex].replace(/:.*/, ''); - } + if (currentMarker && PIIToBeRemoved.shouldRemoveUrls) { + // Remove the all network URLs if user wants to remove them. + if (currentMarker.type === 'Network') { + // Remove the URI fields from marker payload. + markerTable.data[i] = removeNetworkMarkerURLs(currentMarker); + + // Strip the URL from the marker name + const stringIndex = markerTable.name[i]; + stringArray[stringIndex] = stringArray[stringIndex].replace( + /:.*/, + '' + ); + } - // Remove the all OS paths from FileIO markers if user wants to remove them. - if ( - PIIToBeRemoved.shouldRemoveUrls && - currentMarker && - currentMarker.type === 'FileIO' - ) { - // Remove the filename path from marker payload. - markerTable.data[i] = sanitizeFileIOMarkerFilenamePath(currentMarker); - } + // Remove the all OS paths from FileIO markers if user wants to remove them. + if (currentMarker.type === 'FileIO') { + // Remove the filename path from marker payload. + markerTable.data[i] = sanitizeFileIOMarkerFilenamePath(currentMarker); + } - if ( - PIIToBeRemoved.shouldRemoveUrls && - currentMarker && - currentMarker.type === 'Text' - ) { - // Sanitize all the name fields of text markers in case they contain URLs. - markerTable.data[i] = sanitizeTextMarker(currentMarker); - // Re-assign the value of currentMarker as the marker may be - // sanitized again to remove extension ids. - currentMarker = markerTable.data[i]; + if (currentMarker.type === 'Text') { + // Sanitize all the name fields of text markers in case they contain URLs. + markerTable.data[i] = sanitizeTextMarker(currentMarker); + // Re-assign the value of currentMarker as the marker may be + // sanitized again to remove extension ids. + currentMarker = markerTable.data[i]; + } } if ( From 65cab038aae9f60c575a4c503d61d6ff7a27c740 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Mon, 12 Dec 2022 18:36:48 +0100 Subject: [PATCH 052/114] Implement sanitization using the marker schema Fixes #2757 Fixes #4107 --- src/profile-logic/marker-data.js | 35 +++++++++++++++++++++++++++++++ src/profile-logic/sanitize.js | 29 +++++++++++++++++++++---- src/selectors/publish.js | 2 ++ src/test/unit/sanitize.test.js | 36 +++++++++++++++++++++++++++++++- 4 files changed, 97 insertions(+), 5 deletions(-) diff --git a/src/profile-logic/marker-data.js b/src/profile-logic/marker-data.js index f61c1b20a6..1bfa209f5b 100644 --- a/src/profile-logic/marker-data.js +++ b/src/profile-logic/marker-data.js @@ -1320,6 +1320,41 @@ export function sanitizeExtensionTextMarker( return payload; } +export function sanitizeFromMarkerSchema( + markerSchema: MarkerSchema, + markerPayload: MarkerPayload +): MarkerPayload { + for (const propertyDescription of markerSchema.data) { + if ( + propertyDescription.key !== undefined && + propertyDescription.format !== undefined + ) { + const key = propertyDescription.key; + const format = propertyDescription.format; + if (!(key in markerPayload)) { + continue; + } + + // We're typing the result of the sanitization with `any` because Flow + // doesn't like much our enormous enum of non-exact objects that's used as + // MarkerPayload type, and this code is too generic for Flow in this context. + if (format === 'url') { + markerPayload = ({ + ...markerPayload, + [key]: removeURLs(markerPayload[key]), + }: any); + } else if (format === 'file-path') { + markerPayload = ({ + ...markerPayload, + [key]: removeFilePath(markerPayload[key]), + }: any); + } + } + } + + return markerPayload; +} + /** * Markers can be filtered by display area using the marker schema. Get a list of * marker "types" (the type field in the Payload) for a specific location. diff --git a/src/profile-logic/sanitize.js b/src/profile-logic/sanitize.js index 7c4c93c9c0..01996584aa 100644 --- a/src/profile-logic/sanitize.js +++ b/src/profile-logic/sanitize.js @@ -18,7 +18,9 @@ import { filterRawMarkerTableToRangeWithMarkersToDelete, sanitizeExtensionTextMarker, sanitizeTextMarker, + sanitizeFromMarkerSchema, } from './marker-data'; +import { getSchemaFromMarker } from './marker-schema'; import { filterThreadSamplesToRange } from './profile-data'; import type { Profile, @@ -30,6 +32,7 @@ import type { IndexIntoFrameTable, IndexIntoFuncTable, InnerWindowID, + MarkerSchemaByName, } from 'firefox-profiler/types'; export type SanitizeProfileResult = {| @@ -47,7 +50,8 @@ export type SanitizeProfileResult = {| export function sanitizePII( profile: Profile, derivedMarkerInfoForAllThreads: DerivedMarkerInfo[], - maybePIIToBeRemoved: RemoveProfileInformation | null + maybePIIToBeRemoved: RemoveProfileInformation | null, + markerSchemaByName: MarkerSchemaByName ): SanitizeProfileResult { if (maybePIIToBeRemoved === null) { // Nothing is sanitized. @@ -133,7 +137,8 @@ export function sanitizePII( threadIndex, PIIToBeRemoved, windowIdFromPrivateBrowsing, - windowIdFromActiveTab + windowIdFromActiveTab, + markerSchemaByName ); // Filtering out the current thread if it's null. @@ -227,7 +232,8 @@ function sanitizeThreadPII( threadIndex: number, PIIToBeRemoved: RemoveProfileInformation, windowIdFromPrivateBrowsing: Set, - windowIdFromActiveTab: Set + windowIdFromActiveTab: Set, + markerSchemaByName: MarkerSchemaByName ): Thread | null { if (PIIToBeRemoved.shouldRemoveThreads.has(threadIndex)) { // If this is a hidden thread, remove the thread immediately. @@ -275,7 +281,22 @@ function sanitizeThreadPII( } if (currentMarker && PIIToBeRemoved.shouldRemoveUrls) { - // Remove the all network URLs if user wants to remove them. + // Use the schema to find some properties that need to be sanitized. + const markerNameIndex = markerTable.name[i]; + const markerName = thread.stringTable.getString(markerNameIndex); + const markerSchema = getSchemaFromMarker( + markerSchemaByName, + markerName, + currentMarker + ); + if (markerSchema) { + currentMarker = markerTable.data[i] = sanitizeFromMarkerSchema( + markerSchema, + currentMarker + ); + } + + // Remove the network URLs if user wants to remove them. if (currentMarker.type === 'Network') { // Remove the URI fields from marker payload. markerTable.data[i] = removeNetworkMarkerURLs(currentMarker); diff --git a/src/selectors/publish.js b/src/selectors/publish.js index 23d9ad0dd5..914b222679 100644 --- a/src/selectors/publish.js +++ b/src/selectors/publish.js @@ -16,6 +16,7 @@ import { getContainsPrivateBrowsingInformation, getThreads, getActiveTabID, + getMarkerSchemaByName, } from './profile'; import { compress } from '../utils/gz'; import { serializeProfile } from '../profile-logic/process-profile'; @@ -222,6 +223,7 @@ export const getSanitizedProfile: Selector = getProfile, getDerivedMarkerInfoForAllThreads, getRemoveProfileInformation, + getMarkerSchemaByName, sanitizePII ); diff --git a/src/test/unit/sanitize.test.js b/src/test/unit/sanitize.test.js index 87e6337769..899645748d 100644 --- a/src/test/unit/sanitize.test.js +++ b/src/test/unit/sanitize.test.js @@ -65,10 +65,44 @@ describe('sanitizePII', function () { } ); + const markerSchemaByName = { + FileIO: { + name: 'FileIO', + display: ['marker-chart', 'marker-table', 'timeline-fileio'], + data: [ + { + key: 'operation', + label: 'Operation', + format: 'string', + searchable: true, + }, + { + key: 'source', + label: 'Source', + format: 'string', + searchable: true, + }, + { + key: 'filename', + label: 'Filename', + format: 'file-path', + searchable: true, + }, + { + key: 'threadId', + label: 'Thread ID', + format: 'string', + searchable: true, + }, + ], + }, + }; + const sanitizedProfile = sanitizePII( originalProfile, derivedMarkerInfoForAllThreads, - PIIToRemove + PIIToRemove, + markerSchemaByName ).profile; return { From 2caeef66af7afc61ab6542e2505f771fdec6b7d5 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Mon, 12 Dec 2022 18:35:02 +0100 Subject: [PATCH 053/114] Remove the special handling for FileIO markers as this is now handled by the marker schema generic handling --- src/profile-logic/marker-data.js | 17 ----------------- src/profile-logic/sanitize.js | 7 ------- 2 files changed, 24 deletions(-) diff --git a/src/profile-logic/marker-data.js b/src/profile-logic/marker-data.js index 1bfa209f5b..4ea8a869f6 100644 --- a/src/profile-logic/marker-data.js +++ b/src/profile-logic/marker-data.js @@ -35,7 +35,6 @@ import type { IPCMarkerPayload, NetworkPayload, PrefMarkerPayload, - FileIoPayload, TextMarkerPayload, StartEndRange, IndexedArray, @@ -1268,22 +1267,6 @@ export function removePrefMarkerPreferenceValues( return { ...payload, prefValue: '' }; } -/** - * Sanitize FileIO marker's filename property if it's non-empty. - */ -export function sanitizeFileIOMarkerFilenamePath( - payload: FileIoPayload -): FileIoPayload { - if (!payload.filename) { - return payload; - } - - return { - ...payload, - filename: removeFilePath(payload.filename), - }; -} - /** * Sanitize Text marker's name property for potential URLs. */ diff --git a/src/profile-logic/sanitize.js b/src/profile-logic/sanitize.js index 01996584aa..e19f85b770 100644 --- a/src/profile-logic/sanitize.js +++ b/src/profile-logic/sanitize.js @@ -14,7 +14,6 @@ import { removeURLs } from '../utils/string'; import { removeNetworkMarkerURLs, removePrefMarkerPreferenceValues, - sanitizeFileIOMarkerFilenamePath, filterRawMarkerTableToRangeWithMarkersToDelete, sanitizeExtensionTextMarker, sanitizeTextMarker, @@ -309,12 +308,6 @@ function sanitizeThreadPII( ); } - // Remove the all OS paths from FileIO markers if user wants to remove them. - if (currentMarker.type === 'FileIO') { - // Remove the filename path from marker payload. - markerTable.data[i] = sanitizeFileIOMarkerFilenamePath(currentMarker); - } - if (currentMarker.type === 'Text') { // Sanitize all the name fields of text markers in case they contain URLs. markerTable.data[i] = sanitizeTextMarker(currentMarker); From 4b37ed11d78d751edc9823dc90c085b4826387e0 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Mon, 12 Dec 2022 18:35:20 +0100 Subject: [PATCH 054/114] Remove outdated comments now that this is implemented --- src/types/markers.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/types/markers.js b/src/types/markers.js index e8c2921343..ab2982317b 100644 --- a/src/types/markers.js +++ b/src/types/markers.js @@ -20,9 +20,7 @@ export type MarkerFormatType = // String types. // Show the URL, and handle PII sanitization - // TODO Handle PII sanitization. Issue #2757 | 'url' - // TODO Handle PII sanitization. Issue #2757 // Show the file path, and handle PII sanitization. | 'file-path' // Important, do not put URL or file path information here, as it will not be From cde1a3ae3125102e3e18ec94f4b55279f8136430 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Wed, 14 Dec 2022 11:01:58 +0100 Subject: [PATCH 055/114] Add a new test about sanitizing a marker with a Url payload --- src/test/unit/merge-compare.test.js | 2 +- src/test/unit/sanitize.test.js | 43 +++++++++++++++++++++++++++++ src/types/markers.js | 9 +++++- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/test/unit/merge-compare.test.js b/src/test/unit/merge-compare.test.js index 57fd303484..a35983e0d3 100644 --- a/src/test/unit/merge-compare.test.js +++ b/src/test/unit/merge-compare.test.js @@ -481,7 +481,7 @@ describe('mergeThreads function', function () { // Check if we properly merged the string tables and have the correct url fields. const markerUrlsAfterMerge = mergedMarkers.data.map((markerData) => - markerData && 'url' in markerData && markerData.url + markerData && 'url' in markerData && typeof markerData.url === 'number' ? markerData.url : null ); diff --git a/src/test/unit/sanitize.test.js b/src/test/unit/sanitize.test.js index 899645748d..8265d53d18 100644 --- a/src/test/unit/sanitize.test.js +++ b/src/test/unit/sanitize.test.js @@ -96,6 +96,17 @@ describe('sanitizePII', function () { }, ], }, + Url: { + name: 'Url', + tableLabel: '{marker.name} - {marker.data.url}', + display: ['marker-chart', 'marker-table'], + data: [ + { + key: 'url', + format: 'url', + }, + ], + }, }; const sanitizedProfile = sanitizePII( @@ -582,6 +593,38 @@ describe('sanitizePII', function () { expect(marker2.filename).toBe('\\' + marker2File); }); + it('should sanitize the URL properties in markers', function () { + const { sanitizedProfile } = setup( + { + shouldRemoveUrls: true, + }, + getProfileWithMarkers([ + [ + 'SpeculativeConnect', + 1, + 2, + { + type: 'Url', + url: 'https://img-getpocket.cdn.mozilla.net', + }, + ], + ]) + ); + expect(sanitizedProfile.threads.length).toEqual(1); + const thread = sanitizedProfile.threads[0]; + expect(thread.markers.length).toEqual(1); + + const marker = thread.markers.data[0]; + + // The url fields should still be there + if (!marker || !marker.url) { + throw new Error('Failed to find url property in the payload'); + } + + // Now check the url fields and make sure they are sanitized. + expect(marker.url).toBe('https://'); + }); + it('should sanitize the eTLD+1 field if urls are supposed to be sanitized', function () { // Create a simple profile with eTLD+1 field in its thread. const { profile } = getProfileFromTextSamples('A'); diff --git a/src/types/markers.js b/src/types/markers.js index ab2982317b..2d9ee679a7 100644 --- a/src/types/markers.js +++ b/src/types/markers.js @@ -732,6 +732,11 @@ export type NoPayloadUserData = {| innerWindowID?: number, |}; +export type UrlMarkerPayload = {| + type: 'Url', + url: string, +|}; + /** * The union of all the different marker payloads that profiler.firefox.com knows about, * this is not guaranteed to be all the payloads that we actually get from the Gecko @@ -764,7 +769,8 @@ export type MarkerPayload = | MediaSampleMarkerPayload | JankPayload | BrowsertimeMarkerPayload - | NoPayloadUserData; + | NoPayloadUserData + | UrlMarkerPayload; export type MarkerPayload_Gecko = | GPUMarkerPayload @@ -786,6 +792,7 @@ export type MarkerPayload_Gecko = | IPCMarkerPayload_Gecko | MediaSampleMarkerPayload | NoPayloadUserData + | UrlMarkerPayload // The following payloads come in with a stack property. During the profile processing // the "stack" property is are converted into a "cause". See the CauseBacktrace type // for more information. From cfa3a80b5fba8268f8515dede1bfd8ccdcd3a911 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Mon, 19 Dec 2022 17:03:54 +0100 Subject: [PATCH 056/114] Do not hide tracks in the compare view Fixes #3838 --- src/profile-logic/merge-compare.js | 6 ++++++ src/test/store/receive-profile.test.js | 27 +++++++++++++++++++++----- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/profile-logic/merge-compare.js b/src/profile-logic/merge-compare.js index 2355652599..90c34b3bce 100644 --- a/src/profile-logic/merge-compare.js +++ b/src/profile-logic/merge-compare.js @@ -265,6 +265,12 @@ export function mergeProfilesForDiffing( ); } + // In merged profiles, we don't want to hide any threads: either they've been + // explicitely selected by the user, or it's the diffing track. + resultProfile.meta.initialVisibleThreads = resultProfile.threads.map( + (_, i) => i + ); + return { profile: resultProfile, implementationFilters, transformStacks }; } diff --git a/src/test/store/receive-profile.test.js b/src/test/store/receive-profile.test.js index 452023d21d..ad2c456ec2 100644 --- a/src/test/store/receive-profile.test.js +++ b/src/test/store/receive-profile.test.js @@ -3,9 +3,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // @flow -import type { Profile } from 'firefox-profiler/types'; - import { oneLineTrim } from 'common-tags'; +import JSZip from 'jszip'; +import { indexedDB } from 'fake-indexeddb'; import { ensureExists } from 'firefox-profiler/utils/flow'; import { @@ -14,7 +14,6 @@ import { } from '../../profile-logic/data-structures'; import { getTimeRangeForThread } from '../../profile-logic/profile-data'; import { viewProfileFromPathInZipFile } from '../../actions/zipped-profiles'; -import { blankStore } from '../fixtures/stores'; import * as ProfileViewSelectors from '../../selectors/profile'; import * as ZippedProfilesSelectors from '../../selectors/zipped-profiles'; import * as UrlStateSelectors from '../../selectors/url-state'; @@ -35,10 +34,9 @@ import { changeTimelineTrackOrganization, } from '../../actions/receive-profile'; import { SymbolsNotFoundError } from '../../profile-logic/errors'; -import { indexedDB } from 'fake-indexeddb'; import { createGeckoProfile } from '../fixtures/profiles/gecko-profile'; -import JSZip from 'jszip'; +import { blankStore, storeWithProfile } from '../fixtures/stores'; import { makeProfileSerializable, processGeckoProfile, @@ -46,6 +44,7 @@ import { } from '../../profile-logic/process-profile'; import { getProfileFromTextSamples, + getMergedProfileFromTextSamples, addMarkersToThreadWithCorrespondingSamples, getProfileWithMarkers, getProfileWithThreadCPUDelta, @@ -58,6 +57,8 @@ import { waitUntilState } from '../fixtures/utils'; import { compress } from '../../utils/gz'; +import type { Profile } from 'firefox-profiler/types'; + // Mocking SymbolStoreDB. By default the functions will return undefined, which // will make the symbolication move forward with some bogus information. // If you need to simulate that it doesn't have the information, use the @@ -397,6 +398,22 @@ describe('actions/receive-profile', function () { ]); }); + it(`won't hide any tracks in a profile resulting from a compare operation`, () => { + const { profile } = getMergedProfileFromTextSamples( + 'A', + 'A '.repeat(100) + ); + + const store = storeWithProfile(profile); + + store.dispatch(viewProfile(profile)); + expect(getHumanReadableTracks(store.getState())).toEqual([ + 'show [thread Empty default] SELECTED', + 'show [thread Empty default]', + 'show [thread Diff between 1 and 2 comparison]', + ]); + }); + describe('with threadCPUDelta', function () { it('will show a thread when the relative CPU usage is above 10%', function () { const store = blankStore(); From 9b6e7debce0d898ae7e1a8a13cd15f534f7f2ba7 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Mon, 19 Dec 2022 17:03:54 +0100 Subject: [PATCH 057/114] When hiding tracks automatically, do not compute using the CPU values if there's no sampleUnits information --- src/profile-logic/tracks.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/profile-logic/tracks.js b/src/profile-logic/tracks.js index 687dc1b9c1..cb6d41f262 100644 --- a/src/profile-logic/tracks.js +++ b/src/profile-logic/tracks.js @@ -993,7 +993,7 @@ function _computeThreadSampleScore( { samples, stackTable }: Thread, maxCpuDeltaPerInterval: number | null ): number { - if (samples.threadCPUDelta) { + if (meta.sampleUnits && samples.threadCPUDelta) { // Sum up all CPU deltas in this thread, to compute a total // CPU time for this thread (or a total CPU cycle count). return samples.threadCPUDelta.reduce( From af8b66bdd929d890c16f6eda68abb33a50329271 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Mon, 19 Dec 2022 18:12:58 +0100 Subject: [PATCH 058/114] Make getMergedProfileFromTextSamples take an array directly instead of rest arguments --- src/test/components/CallTreeSidebar.test.js | 6 ++--- .../fixtures/profiles/processed-profile.js | 2 +- src/test/store/profile-view.test.js | 26 +++++++++---------- src/test/store/receive-profile.test.js | 6 ++--- src/test/store/useful-tabs.test.js | 2 +- src/test/unit/profile-tree.test.js | 20 +++++++------- 6 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/test/components/CallTreeSidebar.test.js b/src/test/components/CallTreeSidebar.test.js index ce0c34341d..9154eb29d2 100644 --- a/src/test/components/CallTreeSidebar.test.js +++ b/src/test/components/CallTreeSidebar.test.js @@ -158,7 +158,7 @@ describe('CallTreeSidebar', function () { getAllByText, funcNamesDict: { A, B, D }, } = setup( - getMergedProfileFromTextSamples( + getMergedProfileFromTextSamples([ ` A A A B B C @@ -168,8 +168,8 @@ describe('CallTreeSidebar', function () { A A A B B B G I E - ` - ) + `, + ]) ); dispatch(changeSelectedThreads(new Set([2]))); diff --git a/src/test/fixtures/profiles/processed-profile.js b/src/test/fixtures/profiles/processed-profile.js index a10cbddcac..5c5f91657e 100644 --- a/src/test/fixtures/profiles/processed-profile.js +++ b/src/test/fixtures/profiles/processed-profile.js @@ -1042,7 +1042,7 @@ function _buildThreadFromTextOnlyStacks( /** * This returns a merged profile from a number of profile strings. */ -export function getMergedProfileFromTextSamples(...profileStrings: string[]): { +export function getMergedProfileFromTextSamples(profileStrings: string[]): { profile: Profile, funcNamesPerThread: Array, funcNamesDictPerThread: Array<{ [funcName: string]: number }>, diff --git a/src/test/store/profile-view.test.js b/src/test/store/profile-view.test.js index 5d02a43a8f..a80f9020ac 100644 --- a/src/test/store/profile-view.test.js +++ b/src/test/store/profile-view.test.js @@ -540,10 +540,10 @@ describe('actions/ProfileView', function () { trackIndex: 2, }; - const { profile } = getMergedProfileFromTextSamples( + const { profile } = getMergedProfileFromTextSamples([ 'A B C', - 'A B B' - ); + 'A B B', + ]); const { getState, dispatch } = storeWithProfile(profile); dispatch(App.changeSelectedTab('flame-graph')); @@ -2900,18 +2900,18 @@ describe('getTimingsForSidebar', () => { describe('for a diffing track', function () { function setup() { const { profile, funcNamesDictPerThread } = - getMergedProfileFromTextSamples( + getMergedProfileFromTextSamples([ ` - A A A - B B C - D[cat:Layout] E F - `, + A A A + B B C + D[cat:Layout] E F + `, ` - A A A - B B B - Gjs I E - ` - ); + A A A + B B B + Gjs I E + `, + ]); const store = storeWithProfile(profile); store.dispatch(ProfileView.changeSelectedThreads(new Set([2]))); diff --git a/src/test/store/receive-profile.test.js b/src/test/store/receive-profile.test.js index ad2c456ec2..dbcb745455 100644 --- a/src/test/store/receive-profile.test.js +++ b/src/test/store/receive-profile.test.js @@ -399,10 +399,10 @@ describe('actions/receive-profile', function () { }); it(`won't hide any tracks in a profile resulting from a compare operation`, () => { - const { profile } = getMergedProfileFromTextSamples( + const { profile } = getMergedProfileFromTextSamples([ 'A', - 'A '.repeat(100) - ); + 'A '.repeat(100), + ]); const store = storeWithProfile(profile); diff --git a/src/test/store/useful-tabs.test.js b/src/test/store/useful-tabs.test.js index 70fe17e467..96a2a890f8 100644 --- a/src/test/store/useful-tabs.test.js +++ b/src/test/store/useful-tabs.test.js @@ -51,7 +51,7 @@ describe('getUsefulTabs', function () { }); it('shows only the call tree when a diffing track is selected', function () { - const { profile } = getMergedProfileFromTextSamples('A B C', 'A B B'); + const { profile } = getMergedProfileFromTextSamples(['A B C', 'A B B']); const { getState, dispatch } = storeWithProfile(profile); expect(selectedThreadSelectors.getUsefulTabs(getState())).toEqual([ 'calltree', diff --git a/src/test/unit/profile-tree.test.js b/src/test/unit/profile-tree.test.js index 12a242ff21..284e4a4f6e 100644 --- a/src/test/unit/profile-tree.test.js +++ b/src/test/unit/profile-tree.test.js @@ -562,18 +562,18 @@ describe('inverted call tree', function () { describe('diffing trees', function () { function getProfile() { - const { profile } = getMergedProfileFromTextSamples( + const { profile } = getMergedProfileFromTextSamples([ ` - A A A - B B C - D E F - `, + A A A + B B C + D E F + `, ` - A A A - B B B - G I E - ` - ); + A A A + B B B + G I E + `, + ]); return profile; } From 205d227b2ba3d18769da3c57ea2cc594e44f317c Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Mon, 19 Dec 2022 18:43:04 +0100 Subject: [PATCH 059/114] Add a test for diff profiles with cpu delta information --- .../fixtures/profiles/processed-profile.js | 18 ++++++++++++- src/test/store/receive-profile.test.js | 25 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/test/fixtures/profiles/processed-profile.js b/src/test/fixtures/profiles/processed-profile.js index 5c5f91657e..8678958473 100644 --- a/src/test/fixtures/profiles/processed-profile.js +++ b/src/test/fixtures/profiles/processed-profile.js @@ -1042,7 +1042,13 @@ function _buildThreadFromTextOnlyStacks( /** * This returns a merged profile from a number of profile strings. */ -export function getMergedProfileFromTextSamples(profileStrings: string[]): { +export function getMergedProfileFromTextSamples( + profileStrings: string[], + cpuValuesPerProfile: Array<{| + threadCPUDelta: Array, + threadCPUDeltaUnit: ThreadCPUDeltaUnit, + |} | null> = [] +): { profile: Profile, funcNamesPerThread: Array, funcNamesDictPerThread: Array<{ [funcName: string]: number }>, @@ -1051,6 +1057,16 @@ export function getMergedProfileFromTextSamples(profileStrings: string[]): { getProfileFromTextSamples(str) ); const profiles = profilesAndFuncNames.map(({ profile }) => profile); + cpuValuesPerProfile.forEach((cpuValues, profileIndex) => { + if (cpuValues) { + addCpuUsageValues( + profiles[profileIndex], + cpuValues.threadCPUDelta, + cpuValues.threadCPUDeltaUnit + ); + } + }); + const profileState = stateFromLocation({ pathname: '/public/fakehash1/', search: '?thread=0&v=3', diff --git a/src/test/store/receive-profile.test.js b/src/test/store/receive-profile.test.js index dbcb745455..4b353a557c 100644 --- a/src/test/store/receive-profile.test.js +++ b/src/test/store/receive-profile.test.js @@ -491,6 +491,31 @@ describe('actions/receive-profile', function () { ' - show [thread Thread with 10% CPU] SELECTED', // <- Ensure this thread is not hidden. ]); }); + + it(`won't hide any tracks in a profile resulting from a compare operation`, () => { + const { profile } = getMergedProfileFromTextSamples( + ['A A A A', 'B B B B'], + [ + { + threadCPUDelta: [10, 10, 10, 10_000_000], + threadCPUDeltaUnit: 'ns', + }, + { + threadCPUDelta: [10, 10_000_000, 10, 25], + threadCPUDeltaUnit: 'ns', + }, + ] + ); + + const store = storeWithProfile(profile); + + store.dispatch(viewProfile(profile)); + expect(getHumanReadableTracks(store.getState())).toEqual([ + 'show [thread Empty default] SELECTED', + 'show [thread Empty default]', + 'show [thread Diff between 1 and 2 comparison]', + ]); + }); }); describe('too many threads', function () { From b935b1bff293195b6a1e404bbe8a63d97b2c4759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Chevalier?= Date: Tue, 20 Dec 2022 10:13:20 +0000 Subject: [PATCH 060/114] Pontoon: Update French (fr) localization of Firefox Profiler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Théo Chevalier --- locales/fr/app.ftl | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/locales/fr/app.ftl b/locales/fr/app.ftl index 88ce70d9af..8dad3a236d 100644 --- a/locales/fr/app.ftl +++ b/locales/fr/app.ftl @@ -645,8 +645,12 @@ TrackMemoryGraph--operations-since-the-previous-sample = opérations depuis l’ ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. # This is used in the tooltip when the power value uses the watt unit. # Variables: @@ -662,38 +666,44 @@ TrackPower--tooltip-power-milliwatt = { $value } mW # watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-watthour = { $value } Wh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Wh ({ $carbonValue } g eqCO₂) .label = Énergie consommée dans l’intervalle visible # This is used in the tooltip when the energy used in the current range uses the # milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-milliwatthour = { $value } mWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour = { $value } mWh ({ $carbonValue } mg eqCO₂) .label = Énergie consommée dans l’intervalle visible # This is used in the tooltip when the energy used in the current range uses the # microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-microwatthour = { $value } µWh +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-microwatthour = { $value } µWh ({ $carbonValue } mg eqCO₂) .label = Énergie consommée dans l’intervalle visible # This is used in the tooltip when the energy used in the current preview # selection uses the watt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-watthour = { $value } Wh - .label = Énergie consommée dans la sélection actuelle +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-preview-watthour = { $value } Wh ({ $carbonValue } g eqCO₂) + .label = Énergie consommée dans la sélection courante # This is used in the tooltip when the energy used in the current preview # selection uses the milliwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-milliwatthour = { $value } mWh - .label = Énergie consommée dans la sélection actuelle +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-milliwatthour = { $value } mWh ({ $carbonValue } mg eqCO₂) + .label = Énergie consommée dans la sélection courante # This is used in the tooltip when the energy used in the current preview # selection uses the microwatt-hour unit. # Variables: # $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-microwatthour = { $value } µWh - .label = Énergie consommée dans la sélection actuelle +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-microwatthour = { $value } µWh ({ $carbonValue } mg eqCO₂) + .label = Énergie consommée dans la sélection courante ## TrackSearchField ## The component that is used for the search input in the track context menu. From 5acabe11c447ee3054355946ff5a79fd316e5104 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Tue, 20 Dec 2022 15:26:56 +0100 Subject: [PATCH 061/114] Remove the unused functions about selecting the "best ancestor call node" in the call tree (PR #4374) The last usage for this function was removed in the PR #2435. --- src/actions/profile-view.js | 68 +---------------- src/profile-logic/profile-data.js | 118 ------------------------------ 2 files changed, 1 insertion(+), 185 deletions(-) diff --git a/src/actions/profile-view.js b/src/actions/profile-view.js index 81e77f36fc..3bbd6f6b65 100644 --- a/src/actions/profile-view.js +++ b/src/actions/profile-view.js @@ -36,12 +36,7 @@ import { getInvertCallstack, getHash, } from 'firefox-profiler/selectors/url-state'; -import { - getCallNodePathFromIndex, - getSampleIndexToCallNodeIndex, - getSampleCategories, - findBestAncestorCallNode, -} from 'firefox-profiler/profile-logic/profile-data'; +import { getCallNodePathFromIndex } from 'firefox-profiler/profile-logic/profile-data'; import { assertExhaustiveCheck, getFirstItemFromSet, @@ -206,67 +201,6 @@ export function selectRootCallNode( }; } -/** - * This function provides a different strategy for selecting call nodes. It selects - * a "best" ancestor call node, but also expands out its children nodes to the - * actual call node that was clicked. See findBestAncestorCallNode for more - * on the "best" call node. - */ -export function selectBestAncestorCallNodeAndExpandCallTree( - threadsKey: ThreadsKey, - sampleIndex: IndexIntoSamplesTable -): ThunkAction { - return (dispatch, getState) => { - const threadSelectors = getThreadSelectorsFromThreadsKey(threadsKey); - const fullThread = threadSelectors.getRangeFilteredThread(getState()); - const filteredThread = threadSelectors.getFilteredThread(getState()); - const unfilteredStack = fullThread.samples.stack[sampleIndex]; - const callNodeInfo = threadSelectors.getCallNodeInfo(getState()); - - if (unfilteredStack === null) { - return false; - } - - const { callNodeTable, stackIndexToCallNodeIndex } = callNodeInfo; - const sampleIndexToCallNodeIndex = getSampleIndexToCallNodeIndex( - filteredThread.samples.stack, - stackIndexToCallNodeIndex - ); - const clickedCallNode = sampleIndexToCallNodeIndex[sampleIndex]; - const clickedCategory = fullThread.stackTable.category[unfilteredStack]; - - if (clickedCallNode === null) { - return false; - } - - const sampleCategories = getSampleCategories( - fullThread.samples, - fullThread.stackTable - ); - const bestAncestorCallNode = findBestAncestorCallNode( - callNodeInfo, - sampleIndexToCallNodeIndex, - sampleCategories, - clickedCallNode, - clickedCategory - ); - - // In one dispatch, change the selected call node to the best ancestor call node, but - // also expand out to the clicked call node. - dispatch( - changeSelectedCallNode( - threadsKey, - // Select the best ancestor call node. - getCallNodePathFromIndex(bestAncestorCallNode, callNodeTable), - // Also expand the children nodes out further below it to what was actually - // clicked. - getCallNodePathFromIndex(clickedCallNode, callNodeTable) - ) - ); - return true; - }; -} - /** * This selects a set of thread from thread indexes. * Please use it in tests only. diff --git a/src/profile-logic/profile-data.js b/src/profile-logic/profile-data.js index f7535ffa4a..78001b7e8b 100644 --- a/src/profile-logic/profile-data.js +++ b/src/profile-logic/profile-data.js @@ -2447,124 +2447,6 @@ export function getTreeOrderComparator( }; } -/** - * This is the root-most call node for which, if selected, only the clicked category - * is highlighted in the thread activity graph. In other words, it's the root-most call - * node which only 'contains' samples whose sample category is the clicked category. - */ -export function findBestAncestorCallNode( - callNodeInfo: CallNodeInfo, - sampleCallNodes: Array, - sampleCategories: Array, - clickedCallNode: IndexIntoCallNodeTable, - clickedCategory: IndexIntoCategoryList -): IndexIntoCallNodeTable { - const { callNodeTable } = callNodeInfo; - if (callNodeTable.category[clickedCallNode] !== clickedCategory) { - return clickedCallNode; - } - - // Compute the callNodesOnSameCategoryPath. - // Given a call node path with some arbitrary categories, e.g. A, B, C - // - // Categories: A -> A -> B -> B -> C -> C -> C - // Node Indexes: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 - - // This loop will select the leaf-most call nodes that match the leaf call-node's - // category. Running the above path through this loop would produce the list: - // - // Categories: [C, C, C] - // Node Indexes: [6, 5, 4] (note the reverse order) - const callNodesOnSameCategoryPath = [clickedCallNode]; - let callNode = clickedCallNode; - while (true) { - const parentCallNode = callNodeTable.prefix[callNode]; - if (parentCallNode === -1) { - // The entire call path is just clickedCategory. - return clickedCallNode; // TODO: is this a useful behavior? - } - if (callNodeTable.category[parentCallNode] !== clickedCategory) { - break; - } - callNodesOnSameCategoryPath.push(parentCallNode); - callNode = parentCallNode; - } - - // Now find the callNode in callNodesOnSameCategoryPath with the lowest depth - // such that selecting it will not highlight any samples whose unfiltered - // category is different from clickedCategory. If no such callNode exists, - // return clickedCallNode. - - const clickedDepth = callNodeTable.depth[clickedCallNode]; - // The handledCallNodes is used as a Map. - const handledCallNodes = new Uint8Array(callNodeTable.length); - - function limitSameCategoryPathToCommonAncestor(callNode) { - // The callNode argument is the leaf call node of a sample whose sample category is a - // different category than clickedCategory. If callNode's ancestor path crosses - // callNodesOnSameCategoryPath, that implies that callNode would be highlighted - // if we were to select the root-most node in callNodesOnSameCategoryPath. - // If that is the case, we need to truncate callNodesOnSameCategoryPath in such - // a way that the root-most node in that list is no longer an ancestor of callNode. - const walkUpToDepth = - clickedDepth - (callNodesOnSameCategoryPath.length - 1); - let depth = callNodeTable.depth[callNode]; - - // Go from leaf to root in the call nodes. - while (depth >= walkUpToDepth) { - if (handledCallNodes[callNode]) { - // This call node was already handled. Stop checking. - return; - } - handledCallNodes[callNode] = 1; - if (depth <= clickedDepth) { - // This call node's depth is less than the clicked depth, it needs to be - // checked to see if the call node is in the callNodesOnSameCategoryPath. - if (callNode === callNodesOnSameCategoryPath[clickedDepth - depth]) { - // Remove some of the call nodes, as they are not on the same path. - // This is done by shortening the array length. Keep in mind that this - // array is in the opposite order of a CallNodePath, with the leaf-most - // nodes first, and the root-most last. - callNodesOnSameCategoryPath.length = clickedDepth - depth; - return; - } - } - callNode = callNodeTable.prefix[callNode]; - depth--; - } - } - - // Go through every sample and look at each sample's call node. - for (let sample = 0; sample < sampleCallNodes.length; sample++) { - if ( - sampleCategories[sample] !== clickedCategory && - sampleCallNodes[sample] !== null - ) { - // This sample's category is a different one than the one clicked. Make - // sure to limit the callNodesOnSameCategoryPath to just the call nodes - // that share the same common ancestor. - limitSameCategoryPathToCommonAncestor(sampleCallNodes[sample]); - } - } - - if (callNodesOnSameCategoryPath.length > 0) { - // The last call node in this list will be the root-most call node that has - // the same category on the path as the clicked call node. - return callNodesOnSameCategoryPath[callNodesOnSameCategoryPath.length - 1]; - } - return clickedCallNode; -} - -/** - * Look at the leaf-most stack for every sample, and take its category. - */ -export function getSampleCategories( - samples: SamplesTable, - stackTable: StackTable -): Array { - return samples.stack.map((s) => (s !== null ? stackTable.category[s] : null)); -} - export function getFriendlyStackTypeName( implementation: StackImplementation ): string { From 64cdd7ebba89f73944e1f709420f2647bcfa90f7 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Tue, 20 Dec 2022 15:30:46 +0100 Subject: [PATCH 062/114] Do not show a tooltip when the stack index of the hovered sample is null, instead of crashing (PR #4376) Fixes #4363 --- src/components/shared/thread/ActivityGraphFills.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/shared/thread/ActivityGraphFills.js b/src/components/shared/thread/ActivityGraphFills.js index 6f0f785deb..82e52a2acc 100644 --- a/src/components/shared/thread/ActivityGraphFills.js +++ b/src/components/shared/thread/ActivityGraphFills.js @@ -405,7 +405,6 @@ export class ActivityFillGraphQuerier { ): HoveredPixelState | null { const { rangeFilteredThread: { samples, stackTable }, - greyCategoryIndex, } = this.renderedComponentSettings; const { devicePixelRatio } = window; const deviceX = Math.round(cssX * devicePixelRatio); @@ -437,10 +436,13 @@ export class ActivityFillGraphQuerier { // iteration - in the first iteration, yPercentage can be == categoryLowerEdge.) for (const { sample, contribution } of candidateSamples) { const stackIndex = samples.stack[sample]; - const sampleCategory = - stackIndex !== null - ? stackTable.category[stackIndex] - : greyCategoryIndex; + if (stackIndex === null) { + console.error( + `Stack index was null for sample index ${sample}, this shouldn't happen normally, please fix your source of data.` + ); + continue; + } + const sampleCategory = stackTable.category[stackIndex]; const upperEdgeOfThisSample = upperEdgeOfPreviousSample + contribution; // Checking the sample category here because there are samples with different // categories that has y percentage is lower than the upperEdgeOfThisSample. From 72fe4d6325a19f6505afc80dc0b373e737a9787c Mon Sep 17 00:00:00 2001 From: CipherGirl Date: Mon, 26 Oct 2020 21:18:17 +0600 Subject: [PATCH 063/114] Update hoverLocation to use mouseTimePosition redux state --- src/components/timeline/Selection.js | 46 ++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/components/timeline/Selection.js b/src/components/timeline/Selection.js index e04a815660..44c447f836 100644 --- a/src/components/timeline/Selection.js +++ b/src/components/timeline/Selection.js @@ -11,10 +11,12 @@ import { getPreviewSelection, getCommittedRange, getZeroAt, + getMouseTimePosition, } from 'firefox-profiler/selectors/profile'; import { updatePreviewSelection, commitRange, + changeMouseTimePosition, } from 'firefox-profiler/actions/profile-view'; import explicitConnect from 'firefox-profiler/utils/connect'; import classNames from 'classnames'; @@ -43,20 +45,18 @@ type StateProps = {| +previewSelection: PreviewSelection, +committedRange: StartEndRange, +zeroAt: Milliseconds, + +mouseTimePosition: Milliseconds | null, |}; type DispatchProps = {| +commitRange: typeof commitRange, +updatePreviewSelection: typeof updatePreviewSelection, + +changeMouseTimePosition: typeof changeMouseTimePosition, |}; type Props = ConnectedProps; -type State = {| - hoverLocation: null | CssPixels, -|}; - -class TimelineRulerAndSelection extends React.PureComponent { +class TimelineRulerAndSelection extends React.PureComponent { _handlers: ?{| mouseMoveHandler: MouseHandler, mouseClickHandler: MouseHandler, @@ -64,10 +64,6 @@ class TimelineRulerAndSelection extends React.PureComponent { _container: ?HTMLElement; - state = { - hoverLocation: null, - }; - _containerCreated = (element: HTMLElement | null) => { this._container = element; }; @@ -246,6 +242,7 @@ class TimelineRulerAndSelection extends React.PureComponent { if (!this._container) { return; } + const { width, committedRange, changeMouseTimePosition } = this.props; const rect = getContentRect(this._container); if ( @@ -254,9 +251,15 @@ class TimelineRulerAndSelection extends React.PureComponent { event.pageY < rect.top || event.pageY >= rect.bottom ) { - this.setState({ hoverLocation: null }); + changeMouseTimePosition(null); } else { - this.setState({ hoverLocation: event.pageX - rect.left }); + const hoverPositionInPixels = event.pageX - rect.left; + const pixelsToMouseTimePosition = Math.round( + ((committedRange.end - committedRange.start) * hoverPositionInPixels) / + width + + committedRange.start + ); + changeMouseTimePosition(pixelsToMouseTimePosition); } }; @@ -386,8 +389,23 @@ class TimelineRulerAndSelection extends React.PureComponent { } render() { - const { children, previewSelection, className } = this.props; - const { hoverLocation } = this.state; + const { + children, + previewSelection, + className, + mouseTimePosition, + width, + committedRange, + } = this.props; + + let hoverLocation = null; + + if (mouseTimePosition !== null) { + // If the mouseTimePosition exists, convert it to CssPixels. + hoverLocation = + (width * (mouseTimePosition - committedRange.start)) / + (committedRange.end - committedRange.start); + } return (
        Date: Tue, 20 Dec 2022 18:59:07 +0100 Subject: [PATCH 064/114] Tests for using mouseTimePosition to draw hoverline in timeline area --- src/test/components/Timeline.test.js | 131 ++++++- .../__snapshots__/Timeline.test.js.snap | 331 ++++++++++++++++++ src/test/fixtures/mocks/domrect.js | 2 +- 3 files changed, 450 insertions(+), 14 deletions(-) create mode 100644 src/test/components/__snapshots__/Timeline.test.js.snap diff --git a/src/test/components/Timeline.test.js b/src/test/components/Timeline.test.js index ae8f002e63..6021b17d88 100644 --- a/src/test/components/Timeline.test.js +++ b/src/test/components/Timeline.test.js @@ -6,13 +6,19 @@ import * as React from 'react'; import { Provider } from 'react-redux'; -import { render, screen } from 'firefox-profiler/test/fixtures/testing-library'; +import { + render, + fireEvent, + screen, +} from 'firefox-profiler/test/fixtures/testing-library'; import { Timeline } from '../../components/timeline'; import { selectedThreadSelectors, getRightClickedTrack, + getMouseTimePosition, } from 'firefox-profiler/selectors'; -import { ensureExists } from '../../utils/flow'; +import { FULL_TRACK_SCREENSHOT_HEIGHT } from 'firefox-profiler/app-logic/constants'; +import { ensureExists } from 'firefox-profiler/utils/flow'; import { storeWithProfile } from '../fixtures/stores'; import { @@ -27,6 +33,7 @@ import { getElementWithFixedSize, } from '../fixtures/mocks/element-size'; import { + getMouseEvent, fireFullClick, fireFullKeyPress, fireFullContextMenu, @@ -41,12 +48,24 @@ import { autoMockIntersectionObserver } from '../fixtures/mocks/intersection-obs import type { Profile, ThreadIndex } from 'firefox-profiler/types'; -describe('Timeline multiple thread selection', function () { - autoMockDomRect(); - autoMockCanvasContext(); - autoMockElementSize({ width: 200, height: 300 }); - autoMockIntersectionObserver(); +// Mock out the element size to have a 400 pixel width and some left/top +// positioning. +const TRACK_WIDTH = 400; +const LEFT = 100; +const TOP = 7; +const INITIAL_ELEMENT_SIZE = { + width: TRACK_WIDTH, + height: FULL_TRACK_SCREENSHOT_HEIGHT, + offsetX: LEFT, + offsetY: TOP, +}; + +autoMockDomRect(); +autoMockCanvasContext(); +autoMockElementSize(INITIAL_ELEMENT_SIZE); +autoMockIntersectionObserver(); +describe('Timeline multiple thread selection', function () { function setup(profile = getProfileWithNiceTracks()) { const store = storeWithProfile(profile); @@ -169,7 +188,10 @@ describe('Timeline multiple thread selection', function () { null ); - fireFullClick(activityGraph, { offsetX: 50, offsetY: 50 }); + fireFullClick(activityGraph, { + offsetX: TRACK_WIDTH / 2, + offsetY: (FULL_TRACK_SCREENSHOT_HEIGHT * 3) / 4, + }); expect(getHumanReadableTracks(getState())).toEqual([ 'show [thread GeckoMain default]', @@ -1192,11 +1214,6 @@ function _getProfileWithDroppedSamples(): Profile { } describe('Timeline', function () { - autoMockCanvasContext(); - autoMockElementSize({ width: 200, height: 300 }); - autoMockIntersectionObserver(); - autoMockDomRect(); - beforeEach(() => { jest .spyOn(ReactDOM, 'findDOMNode') @@ -1358,3 +1375,91 @@ describe('Timeline', function () { }); }); }); + +describe('TimelineSelection', () => { + function setup() { + const flushRafCalls = mockRaf(); + const profileLength = 10; + // There are 10 samples in this profile. + const { profile } = getProfileFromTextSamples('A '.repeat(profileLength)); + + // getBoundingClientRect is already mocked by autoMockElementSize. + jest + .spyOn(HTMLElement.prototype, 'getClientRects') + .mockImplementation(() => { + const result = [ + new DOMRect(LEFT, TOP, TRACK_WIDTH, FULL_TRACK_SCREENSHOT_HEIGHT), + ]; + return result; + }); + + const store = storeWithProfile(profile); + render( + + + + ); + + // This is necessary to make sure the sizing is correct. + flushRafCalls(); + + function moveMouseOnThreadCanvas(mouseEventOptions) { + const threadCanvas = ensureExists( + document.querySelector('.threadActivityGraphCanvas'), + 'Expected that a thread activity graph canvas is present.' + ); + + fireEvent(threadCanvas, getMouseEvent('mousemove', mouseEventOptions)); + } + + function getTimePositionLinePosition() { + const positionLine = ensureExists( + document.querySelector('.timelineSelectionHoverLine'), + 'Expected that the vertical line indicating the time position is present.' + ); + return parseInt(positionLine.style.left); + } + + return { + ...store, + profileLength, + flushRafCalls, + moveMouseOnThreadCanvas, + getTimePositionLinePosition, + }; + } + + it('renders the vertical line indicating the time position from the mouse cursor', () => { + const { + moveMouseOnThreadCanvas, + getState, + profileLength, + getTimePositionLinePosition, + } = setup(); + let samplePosition = 3; + + moveMouseOnThreadCanvas({ + pageX: LEFT + (TRACK_WIDTH * samplePosition) / profileLength, + pageY: TOP + 1, + }); + + expect(getMouseTimePosition(getState())).toBe(samplePosition); + expect(getTimePositionLinePosition()).toBe( + (TRACK_WIDTH * samplePosition) / profileLength + ); + expect(document.body).toMatchSnapshot(); + + // Move the mouse in another position. + samplePosition = 6; + + moveMouseOnThreadCanvas({ + pageX: LEFT + (TRACK_WIDTH * samplePosition) / profileLength, + pageY: TOP + 1, + }); + + expect(getMouseTimePosition(getState())).toBe(samplePosition); + expect(getTimePositionLinePosition()).toBe( + (TRACK_WIDTH * samplePosition) / profileLength + ); + }); +}); diff --git a/src/test/components/__snapshots__/Timeline.test.js.snap b/src/test/components/__snapshots__/Timeline.test.js.snap new file mode 100644 index 0000000000..77465d5312 --- /dev/null +++ b/src/test/components/__snapshots__/Timeline.test.js.snap @@ -0,0 +1,331 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TimelineSelection renders the vertical line indicating the time position from the mouse cursor 1`] = ` + +
        +
        +
        + +
        +
          +
        1. + + 0.000s + +
        2. +
        3. + + 0.002s + +
        4. +
        5. + + 0.004s + +
        6. +
        7. + + 0.006s + +
        8. +
        9. + + 0.008s + +
        10. +
        11. + + 0.010s + +
        12. +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +
          +
        1. +
          +
          + +
          +
          +
          +
          +
          +
            +
          1. +
            +
            + +
            +
            +
            +
            +
            +
            + +
            +
            +
            +
            +
            + +

            + Activity Graph for + Empty +

            +

            + This graph shows a visual chart of thread activity. +

            +
            +
            +
            +
            +
            + +

            + Stack Graph for + Empty +

            +

            + This graph charts the stack height of each sample. +

            +
            +
            +
            +
            +
            +
            +
            +
          2. +
          +
        2. +
        +
        +
        +
        +
        +
        + +
        + +`; diff --git a/src/test/fixtures/mocks/domrect.js b/src/test/fixtures/mocks/domrect.js index 6bd930ed82..1cee7af459 100644 --- a/src/test/fixtures/mocks/domrect.js +++ b/src/test/fixtures/mocks/domrect.js @@ -16,7 +16,7 @@ class DOMRect { height: number; constructor(x: number, y: number, width: number, height: number) { - this.x = y; + this.x = x; this.y = y; this.width = width; this.height = height; From 71cf26c72a0fdbc04869f2db7b3f24c9fa77c3b6 Mon Sep 17 00:00:00 2001 From: Melo46 Date: Wed, 21 Dec 2022 11:33:16 +0000 Subject: [PATCH 065/114] Pontoon: Update Interlingua (ia) localization of Firefox Profiler Co-authored-by: Melo46 --- locales/ia/app.ftl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/locales/ia/app.ftl b/locales/ia/app.ftl index 4b10cbf3e9..b5d2297dab 100644 --- a/locales/ia/app.ftl +++ b/locales/ia/app.ftl @@ -246,6 +246,10 @@ Home--menu-button = Activar le button { -profiler-brand-name } del menu Home--menu-button-instructions = Activa le button de menu profilator pro initiar registrar un profilo de prestation in { -firefox-brand-name }, pois analysa lo e comparti lo con profiler.firefox.com. +Home--profile-firefox-android-instructions = + Tu pote equalmente profilar { -firefox-android-brand-name }. + Pro saper plus, consulta iste documentation: + Profilage de { -firefox-android-brand-name } directemente sur le apparato. # The word WebChannel should not be translated. # This message can be seen on https://main--perf-html.netlify.app/ in the tooltip # of the "Enable Firefox Profiler menu button" button. From 0fd216b3f5593f964b3d79884e5b920e75be1905 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Wed, 21 Dec 2022 14:07:43 +0100 Subject: [PATCH 066/114] Do not trigger transforms when searching in the stack chart (PR #4387) --- src/components/stack-chart/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/stack-chart/index.js b/src/components/stack-chart/index.js index c5d6637ade..3ae0949c70 100644 --- a/src/components/stack-chart/index.js +++ b/src/components/stack-chart/index.js @@ -192,7 +192,6 @@ class StackChartImpl extends React.PureComponent { id="stack-chart-tab" role="tabpanel" aria-labelledby="stack-chart-tab-button" - onKeyDown={this._handleKeyDown} > @@ -205,7 +204,7 @@ class StackChartImpl extends React.PureComponent { className: 'treeViewContextMenu', }} > -
        +
        Date: Wed, 21 Dec 2022 14:04:03 +0000 Subject: [PATCH 067/114] Pontoon: Update Chinese (Taiwan) (zh-TW) localization of Firefox Profiler Co-authored-by: Pin-guang Chen --- locales/zh-TW/app.ftl | 44 ++++++------------------------------------- 1 file changed, 6 insertions(+), 38 deletions(-) diff --git a/locales/zh-TW/app.ftl b/locales/zh-TW/app.ftl index edf537c239..642b76b832 100644 --- a/locales/zh-TW/app.ftl +++ b/locales/zh-TW/app.ftl @@ -15,6 +15,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox for Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly @@ -193,7 +194,6 @@ Home--enable-button-unavailable = # This message can be seen on https://main--perf-html.netlify.app/ . Home--web-channel-unavailable = 此檢測器無法連線到 WebChannel。通常是因為執行檢測器的主機與 devtools.performance.recording.ui-base-url 偏好設定當中指定的主機不同。若您想要使用此檢測器捕捉新的效能檢測檔,並可程式化控制檢測器選單按鈕,可到 about:config 調整該偏好設定。 Home--record-instructions = 請點擊檢測按鈕或按下鍵盤快速鍵即可開始進行檢測。進行效能紀錄時,此圖示將會顯示成藍色。按下捕捉即可將資料載入到 profiler.firefox.com。 -Home--instructions-title = 如何檢視並記錄檢測檔 Home--instructions-content = 需要使用 { -firefox-brand-name } 紀錄效能檢測檔。但可以使用任何現代瀏覽器檢視現有的檢測檔。 Home--record-instructions-start-stop = 停止並開始檢測 Home--record-instructions-capture-load = 捕捉並載入檢測檔 @@ -625,8 +625,12 @@ TrackMemoryGraph--operations-since-the-previous-sample = 自前一次取樣以 ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. # This is used in the tooltip when the power value uses the watt unit. # Variables: @@ -638,42 +642,6 @@ TrackPower--tooltip-power-watt = { $value } W # $value (String) - the power value at this location TrackPower--tooltip-power-milliwatt = { $value } mW .label = 功率 -# This is used in the tooltip when the energy used in the current range uses the -# watt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-watthour = { $value } Wh - .label = 可見範圍內消耗的能源 -# This is used in the tooltip when the energy used in the current range uses the -# milliwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-milliwatthour = { $value } mWh - .label = 可見範圍內消耗的能源 -# This is used in the tooltip when the energy used in the current range uses the -# microwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-microwatthour = { $value } µWh - .label = 目前選擇範圍內消耗的能源 -# This is used in the tooltip when the energy used in the current preview -# selection uses the watt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-watthour = { $value } Wh - .label = 目前選擇範圍內消耗的能源 -# This is used in the tooltip when the energy used in the current preview -# selection uses the milliwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-milliwatthour = { $value } mWh - .label = 目前選擇範圍內消耗的能源 -# This is used in the tooltip when the energy used in the current preview -# selection uses the microwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-microwatthour = { $value } µWh - .label = 目前選擇範圍內消耗的能源 ## TrackSearchField ## The component that is used for the search input in the track context menu. From 433b855179a5cbbc6367a455bec78d2a224c4796 Mon Sep 17 00:00:00 2001 From: Melo46 Date: Wed, 21 Dec 2022 16:12:45 +0000 Subject: [PATCH 068/114] Pontoon: Update Interlingua (ia) localization of Firefox Profiler Co-authored-by: Melo46 --- locales/ia/app.ftl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/locales/ia/app.ftl b/locales/ia/app.ftl index b5d2297dab..68772a4038 100644 --- a/locales/ia/app.ftl +++ b/locales/ia/app.ftl @@ -272,6 +272,14 @@ Home--additional-content-title = Cargar profilos existente Home--additional-content-content = Tu pote traher e deponer hic un file profilo pro cargar lo, o: Home--compare-recordings-info = Tu pote alsi comparar registrationes. Aperir le interfacie de comparation. Home--your-recent-uploaded-recordings-title = Tu registrationes incargate recentemente +# We replace the elements such as and with links to the +# documentation to use these tools. +Home--load-files-from-other-tools = + { -profiler-brand-name } pote alsi importar profilos de altere profilatores, tal como + Linux perf, Android SimplePerf, + Chrome performance panel, Android Studio, o + ulle file que usa le formato dhat. Apprende a scriber tu + proprie importator. ## IdleSearchField ## The component that is used for all the search inputs in the application. From 78ec11c57527c8bcda231a5b55e3737ec61e4627 Mon Sep 17 00:00:00 2001 From: Pin-guang Chen Date: Thu, 22 Dec 2022 05:12:51 +0000 Subject: [PATCH 069/114] Pontoon: Update Chinese (Taiwan) (zh-TW) localization of Firefox Profiler Co-authored-by: Pin-guang Chen --- locales/zh-TW/app.ftl | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/locales/zh-TW/app.ftl b/locales/zh-TW/app.ftl index 642b76b832..cd871aae3e 100644 --- a/locales/zh-TW/app.ftl +++ b/locales/zh-TW/app.ftl @@ -642,6 +642,34 @@ TrackPower--tooltip-power-watt = { $value } W # $value (String) - the power value at this location TrackPower--tooltip-power-milliwatt = { $value } mW .label = 功率 +# This is used in the tooltip when the energy used in the current range uses the +# watt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-range-watthour = { $value } Wh({ $carbonValue } g CO₂e) + .label = 可見範圍中消耗的能源 +# This is used in the tooltip when the energy used in the current range uses the +# milliwatt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-milliwatthour = { $value } mWh({ $carbonValue } mg CO₂e) + .label = 可見範圍中消耗的能源 +# This is used in the tooltip when the energy used in the current range uses the +# microwatt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-range-microwatthour = { $value } µWh({ $carbonValue } mg CO₂e) + .label = 可見範圍中消耗的能源 +# This is used in the tooltip when the energy used in the current preview +# selection uses the watt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) +TrackPower--tooltip-energy-carbon-used-in-preview-watthour = { $value } Wh({ $carbonValue } g CO₂e) + .label = 目前選擇範圍中消耗的能源 ## TrackSearchField ## The component that is used for the search input in the track context menu. From 2a3c202d49b6f787b65576edd1373519eff25599 Mon Sep 17 00:00:00 2001 From: Pin-guang Chen Date: Thu, 22 Dec 2022 05:22:44 +0000 Subject: [PATCH 070/114] Pontoon: Update Chinese (Taiwan) (zh-TW) localization of Firefox Profiler Co-authored-by: Pin-guang Chen --- locales/zh-TW/app.ftl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/locales/zh-TW/app.ftl b/locales/zh-TW/app.ftl index cd871aae3e..0f9fe12cc1 100644 --- a/locales/zh-TW/app.ftl +++ b/locales/zh-TW/app.ftl @@ -185,6 +185,7 @@ Home--load-from-url-submit-button = Home--documentation-button = 文件 Home--menu-button = 開啟 { -profiler-brand-name } 選單按鈕 Home--menu-button-instructions = 開啟 { -firefox-brand-name } 當中的檢測器選單按鈕開始紀錄效能,然後進行分析並分享到 profiler.firefox.com。 +Home--profile-firefox-android-instructions = 您也可以對 { -firefox-android-brand-name } 進行效能檢測。若需更多資訊請參考下列文件:直接於裝置上檢測 { -firefox-android-brand-name } 效能。 # The word WebChannel should not be translated. # This message can be seen on https://main--perf-html.netlify.app/ in the tooltip # of the "Enable Firefox Profiler menu button" button. @@ -202,6 +203,9 @@ Home--additional-content-title = 載入現有檢測檔 Home--additional-content-content = 您可以將效能檢測檔拖曳到此處,或: Home--compare-recordings-info = 您也可以比較紀錄內容。開啟比較介面。 Home--your-recent-uploaded-recordings-title = 您近期上傳的紀錄 +# We replace the elements such as and with links to the +# documentation to use these tools. +Home--load-files-from-other-tools = { -profiler-brand-name } 也可以匯入其他效能檢測器,例如 Linux perfAndroid SimplePerf、Chrome 效能面板、Android Studio 所產生的效能檢測檔,或任何使用 dhat 格式儲存的效能檢測檔。點擊此處了解如何撰寫您自己的匯入程式。 ## IdleSearchField ## The component that is used for all the search inputs in the application. @@ -670,6 +674,20 @@ TrackPower--tooltip-energy-carbon-used-in-range-microwatthour = { $value } µWh # $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (grams) TrackPower--tooltip-energy-carbon-used-in-preview-watthour = { $value } Wh({ $carbonValue } g CO₂e) .label = 目前選擇範圍中消耗的能源 +# This is used in the tooltip when the energy used in the current preview +# selection uses the milliwatt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-milliwatthour = { $value } mWh({ $carbonValue } mg CO₂e) + .label = 目前選擇範圍中消耗的能源 +# This is used in the tooltip when the energy used in the current preview +# selection uses the microwatt-hour unit. +# Variables: +# $value (String) - the energy value for this range +# $carbonValue (string) - the carbon dioxide equivalent (CO₂e) value (milligrams) +TrackPower--tooltip-energy-carbon-used-in-preview-microwatthour = { $value } µWh({ $carbonValue } mg CO₂e) + .label = 目前選擇範圍中消耗的能源 ## TrackSearchField ## The component that is used for the search input in the track context menu. From bea697e4ecd70989d14e5586bb83b0c225ea3158 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 22 Dec 2022 11:43:25 +0100 Subject: [PATCH 071/114] Procure a selection also when the components update (for example when changing threads) (PR #4382) --- src/components/calltree/CallTree.js | 32 +++++++----- .../components/ProfileCallTreeView.test.js | 52 ++++++++++++++----- 2 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/components/calltree/CallTree.js b/src/components/calltree/CallTree.js index cdfbda64eb..7e52202b11 100644 --- a/src/components/calltree/CallTree.js +++ b/src/components/calltree/CallTree.js @@ -144,27 +144,29 @@ class CallTreeImpl extends PureComponent { componentDidMount() { this.focus(); - if (this.props.selectedCallNodeIndex === null) { - this.procureInterestingInitialSelection(); - } else if (this._treeView) { + this.maybeProcureInterestingInitialSelection(); + + if (this.props.selectedCallNodeIndex === null && this._treeView) { this._treeView.scrollSelectionIntoView(); } } componentDidUpdate(prevProps) { if ( - this.props.scrollToSelectionGeneration > - prevProps.scrollToSelectionGeneration + this.props.focusCallTreeGeneration > prevProps.focusCallTreeGeneration ) { - if (this._treeView) { - this._treeView.scrollSelectionIntoView(); - } + this.focus(); } + this.maybeProcureInterestingInitialSelection(); + if ( - this.props.focusCallTreeGeneration > prevProps.focusCallTreeGeneration + this.props.selectedCallNodeIndex !== null && + this.props.scrollToSelectionGeneration > + prevProps.scrollToSelectionGeneration && + this._treeView ) { - this.focus(); + this._treeView.scrollSelectionIntoView(); } } @@ -228,10 +230,16 @@ class CallTreeImpl extends PureComponent { openSourceView(file, 'calltree'); }; - procureInterestingInitialSelection() { + maybeProcureInterestingInitialSelection() { // Expand the heaviest callstack up to a certain depth and select the frame // at that depth. - const { tree, expandedCallNodeIndexes } = this.props; + const { tree, expandedCallNodeIndexes, selectedCallNodeIndex } = this.props; + + if (selectedCallNodeIndex !== null || expandedCallNodeIndexes.length > 0) { + // Let's not change some existing state. + return; + } + const newExpandedCallNodeIndexes = expandedCallNodeIndexes.slice(); const maxInterestingDepth = 17; // scientifically determined let currentCallNodeIndex = tree.getRoots()[0]; diff --git a/src/test/components/ProfileCallTreeView.test.js b/src/test/components/ProfileCallTreeView.test.js index 9e9ed6cf3a..b34583a37b 100644 --- a/src/test/components/ProfileCallTreeView.test.js +++ b/src/test/components/ProfileCallTreeView.test.js @@ -25,6 +25,7 @@ import { changeInvertCallstack, commitRange, addTransformToStack, + selectTrackWithModifiers, } from '../../actions/profile-view'; import { autoMockCanvasContext } from '../fixtures/mocks/canvas-context'; @@ -74,11 +75,12 @@ describe('calltree/ProfileCallTreeView', function () { ); const { container } = renderResult; - const getRowElement = (functionName) => - ensureExists( - screen.getByText(functionName).closest('.treeViewRow'), - `Couldn't find the row for node ${functionName}.` - ); + const getRowElement = (functionName, modifiers = {}) => + screen.getByRole('treeitem', { + name: new RegExp(`^${functionName}`), + ...modifiers, + }); + const getContextMenu = () => ensureExists( container.querySelector('.react-contextmenu'), @@ -273,14 +275,38 @@ describe('calltree/ProfileCallTreeView', function () { expect(getRowElement('A')).not.toHaveClass('isRightClicked'); }); - it('selects the heaviest stack if it is not idle', () => { - const { profile } = getProfileFromTextSamples(` - A A A A A - B C C C D - E E - `); - const { getRowElement } = setup(profile); - expect(getRowElement('C')).toHaveClass('isSelected'); + it('procures an interesting selection, also when switching threads', () => { + const { profile } = getProfileFromTextSamples( + ` + A A A A A + B C C C D + E E + `, + ` + G G G G G + H H I I I + J J K L + ` + ); + // Assign values so that these threads are considered global processes. + Object.assign(profile.threads[0], { + pid: 111, + tid: 111, + name: 'GeckoMain', + }); + Object.assign(profile.threads[1], { + pid: 112, + tid: 112, + name: 'GeckoMain', + }); + const { getRowElement, dispatch } = setup(profile); + expect(getRowElement('C', { selected: true })).toHaveClass('isSelected'); + expect(getRowElement('A', { expanded: true })).toBeInTheDocument(); + + // now switch to the other thread + dispatch(selectTrackWithModifiers({ type: 'global', trackIndex: 1 })); + expect(getRowElement('K', { selected: true })).toHaveClass('isSelected'); + expect(getRowElement('I', { expanded: true })).toBeInTheDocument(); }); it('does not select the heaviest stack if it is idle', () => { From dad1f34ea7512975f8880b6080558b34c9c4c63f Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 22 Dec 2022 11:54:42 +0100 Subject: [PATCH 072/114] Skip idle nodes when procuring an initial selection in the call tree (PR #4383) --- src/components/calltree/CallTree.js | 31 ++++++++++++++++--- .../components/ProfileCallTreeView.test.js | 5 +-- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/components/calltree/CallTree.js b/src/components/calltree/CallTree.js index 7e52202b11..464efc9bf1 100644 --- a/src/components/calltree/CallTree.js +++ b/src/components/calltree/CallTree.js @@ -20,6 +20,7 @@ import { getScrollToSelectionGeneration, getFocusCallTreeGeneration, getPreviewSelection, + getCategories, } from 'firefox-profiler/selectors/profile'; import { selectedThreadSelectors } from 'firefox-profiler/selectors/per-thread'; import { @@ -37,6 +38,7 @@ import type { ImplementationFilter, ThreadsKey, CallNodeInfo, + CategoryList, IndexIntoCallNodeTable, CallNodeDisplayData, WeightType, @@ -54,6 +56,7 @@ type StateProps = {| +focusCallTreeGeneration: number, +tree: CallTreeType, +callNodeInfo: CallNodeInfo, + +categories: CategoryList, +selectedCallNodeIndex: IndexIntoCallNodeTable | null, +rightClickedCallNodeIndex: IndexIntoCallNodeTable | null, +expandedCallNodeIndexes: Array, @@ -233,13 +236,23 @@ class CallTreeImpl extends PureComponent { maybeProcureInterestingInitialSelection() { // Expand the heaviest callstack up to a certain depth and select the frame // at that depth. - const { tree, expandedCallNodeIndexes, selectedCallNodeIndex } = this.props; + const { + tree, + expandedCallNodeIndexes, + selectedCallNodeIndex, + callNodeInfo: { callNodeTable }, + categories, + } = this.props; if (selectedCallNodeIndex !== null || expandedCallNodeIndexes.length > 0) { // Let's not change some existing state. return; } + const idleCategoryIndex = categories.findIndex( + (category) => category.name === 'Idle' + ); + const newExpandedCallNodeIndexes = expandedCallNodeIndexes.slice(); const maxInterestingDepth = 17; // scientifically determined let currentCallNodeIndex = tree.getRoots()[0]; @@ -253,13 +266,22 @@ class CallTreeImpl extends PureComponent { if (children.length === 0) { break; } - currentCallNodeIndex = children[0]; + + // Let's find if there's a non idle children. + const firstNonIdleNode = children.find( + (nodeIndex) => callNodeTable.category[nodeIndex] !== idleCategoryIndex + ); + + // If there's a non idle children, use it; otherwise use the first + // children (that will be idle). + currentCallNodeIndex = + firstNonIdleNode !== undefined ? firstNonIdleNode : children[0]; newExpandedCallNodeIndexes.push(currentCallNodeIndex); } this._onExpandedCallNodesChange(newExpandedCallNodeIndexes); - const category = tree.getDisplayData(currentCallNodeIndex).categoryName; - if (category !== 'Idle') { + const categoryIndex = callNodeTable.category[currentCallNodeIndex]; + if (categoryIndex !== idleCategoryIndex) { // If we selected the call node with a "idle" category, we'd have a // completely dimmed activity graph because idle stacks are not drawn in // this graph. Because this isn't probably what the average user wants we @@ -316,6 +338,7 @@ export const CallTree = explicitConnect<{||}, StateProps, DispatchProps>({ focusCallTreeGeneration: getFocusCallTreeGeneration(state), tree: selectedThreadSelectors.getCallTree(state), callNodeInfo: selectedThreadSelectors.getCallNodeInfo(state), + categories: getCategories(state), selectedCallNodeIndex: selectedThreadSelectors.getSelectedCallNodeIndex(state), rightClickedCallNodeIndex: diff --git a/src/test/components/ProfileCallTreeView.test.js b/src/test/components/ProfileCallTreeView.test.js index b34583a37b..c20103221d 100644 --- a/src/test/components/ProfileCallTreeView.test.js +++ b/src/test/components/ProfileCallTreeView.test.js @@ -315,8 +315,9 @@ describe('calltree/ProfileCallTreeView', function () { B C[cat:Idle] C[cat:Idle] C[cat:Idle] D E E `); - const { container } = setup(profile); - expect(container.querySelector('.treeViewRow.isSelected')).toBeFalsy(); + const { getRowElement } = setup(profile); + expect(getRowElement('E', { selected: true })).toHaveClass('isSelected'); + expect(getRowElement('B', { expanded: true })).toBeInTheDocument(); }); }); From 60d46afa72865636c9c7852afea9a3a4d4df91ef Mon Sep 17 00:00:00 2001 From: Johannes Bechberger Date: Mon, 24 Oct 2022 17:41:12 +0200 Subject: [PATCH 073/114] Implement table resize --- src/actions/profile-view.js | 12 + src/components/app/ZipFileViewer.js | 2 + src/components/calltree/CallTree.css | 15 - src/components/calltree/CallTree.js | 59 +- src/components/marker-table/index.js | 39 +- src/components/shared/TreeView.css | 26 +- src/components/shared/TreeView.js | 315 +- src/reducers/profile-view.js | 46 + src/selectors/profile.js | 12 + .../__snapshots__/MarkerTable.test.js.snap | 216 ++ .../ProfileCallTreeView.test.js.snap | 2713 ++++++++++++++++- src/types/actions.js | 6 + src/types/state.js | 7 + 13 files changed, 3392 insertions(+), 76 deletions(-) diff --git a/src/actions/profile-view.js b/src/actions/profile-view.js index 643c6e6dec..73d3018bcf 100644 --- a/src/actions/profile-view.js +++ b/src/actions/profile-view.js @@ -73,6 +73,7 @@ import type { Tid, GlobalTrack, KeyboardModifiers, + TableViewOptions, } from 'firefox-profiler/types'; import { funcHasDirectRecursiveCall, @@ -1924,6 +1925,17 @@ export function changeMouseTimePosition( }; } +export function changeTableViewOptions( + tab: TabSlug, + tableViewOptions: TableViewOptions +): Action { + return { + type: 'CHANGE_TABLE_VIEW_OPTIONS', + tab, + tableViewOptions, + }; +} + export function openSourceView(file: string, currentTab: TabSlug): Action { return { type: 'OPEN_SOURCE_VIEW', diff --git a/src/components/app/ZipFileViewer.js b/src/components/app/ZipFileViewer.js index 228b4ed457..550eeb34e4 100644 --- a/src/components/app/ZipFileViewer.js +++ b/src/components/app/ZipFileViewer.js @@ -24,6 +24,7 @@ import { import { getPathInZipFileFromUrl } from 'firefox-profiler/selectors/url-state'; import { TreeView } from 'firefox-profiler/components/shared/TreeView'; import { ProfileViewer } from './ProfileViewer'; +import { defaultTableViewOptions } from 'firefox-profiler/reducers/profile-view'; import type { ConnectedProps } from 'firefox-profiler/utils/connect'; import type { ZipFileState } from 'firefox-profiler/types'; @@ -269,6 +270,7 @@ class ZipFileViewerImpl extends React.PureComponent { rowHeight={30} indentWidth={15} onEnterKey={this._onEnterKey} + viewOptions={defaultTableViewOptions} />
        diff --git a/src/components/calltree/CallTree.css b/src/components/calltree/CallTree.css index 7134a4daa8..3f5702c346 100644 --- a/src/components/calltree/CallTree.css +++ b/src/components/calltree/CallTree.css @@ -7,20 +7,6 @@ text-align: right; } -.treeViewFixedColumn.total { - width: 70px; -} - -/* The header for the total column spans both totalPercent and total columns */ -.treeViewHeaderColumn.total { - width: 120px; -} - -.treeViewFixedColumn.totalPercent { - width: 50px; - border-right: none; -} - /* The header for the totalPercent column is not visible */ .treeViewHeaderColumn.totalPercent { display: none; @@ -32,7 +18,6 @@ .treeViewFixedColumn.icon { display: flex; - width: 19px; flex-flow: column nowrap; align-items: center; } diff --git a/src/components/calltree/CallTree.js b/src/components/calltree/CallTree.js index 464efc9bf1..c737b03bb4 100644 --- a/src/components/calltree/CallTree.js +++ b/src/components/calltree/CallTree.js @@ -21,6 +21,7 @@ import { getFocusCallTreeGeneration, getPreviewSelection, getCategories, + getCurrentTableViewOptions, } from 'firefox-profiler/selectors/profile'; import { selectedThreadSelectors } from 'firefox-profiler/selectors/per-thread'; import { @@ -30,6 +31,7 @@ import { addTransformToStack, handleCallNodeTransformShortcut, openSourceView, + changeTableViewOptions, } from 'firefox-profiler/actions/profile-view'; import { assertExhaustiveCheck } from 'firefox-profiler/utils/flow'; @@ -42,6 +44,7 @@ import type { IndexIntoCallNodeTable, CallNodeDisplayData, WeightType, + TableViewOptions, } from 'firefox-profiler/types'; import type { CallTree as CallTreeType } from 'firefox-profiler/profile-logic/call-tree'; @@ -66,6 +69,7 @@ type StateProps = {| +implementationFilter: ImplementationFilter, +callNodeMaxDepth: number, +weightType: WeightType, + +tableViewOptions: TableViewOptions, |}; type DispatchProps = {| @@ -75,6 +79,7 @@ type DispatchProps = {| +addTransformToStack: typeof addTransformToStack, +handleCallNodeTransformShortcut: typeof handleCallNodeTransformShortcut, +openSourceView: typeof openSourceView, + +onTableViewOptionsChange: (TableViewOptions) => any, |}; type Props = ConnectedProps<{||}, StateProps, DispatchProps>; @@ -100,40 +105,81 @@ class CallTreeImpl extends PureComponent { switch (weightType) { case 'tracing-ms': return [ - { propName: 'totalPercent', titleL10nId: '' }, + { + propName: 'totalPercent', + titleL10nId: '', + initialWidth: 50, + hideDividerAfter: true, + }, { propName: 'total', titleL10nId: 'CallTree--tracing-ms-total', + minWidth: 30, + initialWidth: 70, + resizable: true, + headerWidthAdjustment: 50, }, { propName: 'self', titleL10nId: 'CallTree--tracing-ms-self', + minWidth: 30, + initialWidth: 70, + resizable: true, }, { propName: 'icon', titleL10nId: '', component: Icon }, ]; case 'samples': return [ - { propName: 'totalPercent', titleL10nId: '' }, + { + propName: 'totalPercent', + titleL10nId: '', + initialWidth: 50, + hideDividerAfter: true, + }, { propName: 'total', titleL10nId: 'CallTree--samples-total', + minWidth: 30, + initialWidth: 70, + resizable: true, + headerWidthAdjustment: 50, }, { propName: 'self', titleL10nId: 'CallTree--samples-self', + minWidth: 30, + initialWidth: 70, + resizable: true, + }, + { + propName: 'icon', + titleL10nId: '', + component: Icon, + initialWidth: 10, }, - { propName: 'icon', titleL10nId: '', component: Icon }, ]; case 'bytes': return [ - { propName: 'totalPercent', titleL10nId: '' }, + { + propName: 'totalPercent', + titleL10nId: '', + initialWidth: 50, + hideDividerAfter: true, + }, { propName: 'total', titleL10nId: 'CallTree--bytes-total', + minWidth: 30, + initialWidth: 140, + resizable: true, + headerWidthAdjustment: 50, }, { propName: 'self', titleL10nId: 'CallTree--bytes-self', + minWidth: 30, + initialWidth: 90, + resizable: true, }, { propName: 'icon', titleL10nId: '', component: Icon }, ]; @@ -326,6 +372,8 @@ class CallTreeImpl extends PureComponent { onKeyDown={this._onKeyDown} onEnterKey={this._onEnterOrDoubleClick} onDoubleClick={this._onEnterOrDoubleClick} + viewOptions={this.props.tableViewOptions} + onViewOptionsChange={this.props.onTableViewOptionsChange} /> ); } @@ -355,6 +403,7 @@ export const CallTree = explicitConnect<{||}, StateProps, DispatchProps>({ callNodeMaxDepth: selectedThreadSelectors.getFilteredCallNodeMaxDepth(state), weightType: selectedThreadSelectors.getWeightTypeForCallTree(state), + tableViewOptions: getCurrentTableViewOptions(state), }), mapDispatchToProps: { changeSelectedCallNode, @@ -363,6 +412,8 @@ export const CallTree = explicitConnect<{||}, StateProps, DispatchProps>({ addTransformToStack, handleCallNodeTransformShortcut, openSourceView, + onTableViewOptionsChange: (options: TableViewOptions) => + changeTableViewOptions('calltree', options), }, component: CallTreeImpl, }); diff --git a/src/components/marker-table/index.js b/src/components/marker-table/index.js index 1f85812064..b222efeafb 100644 --- a/src/components/marker-table/index.js +++ b/src/components/marker-table/index.js @@ -14,12 +14,14 @@ import { getZeroAt, getScrollToSelectionGeneration, getMarkerSchemaByName, + getCurrentTableViewOptions, } from '../../selectors/profile'; import { selectedThreadSelectors } from '../../selectors/per-thread'; import { getSelectedThreadsKey } from '../../selectors/url-state'; import { changeSelectedMarker, changeRightClickedMarker, + changeTableViewOptions, } from '../../actions/profile-view'; import { MarkerSettings } from '../shared/MarkerSettings'; import { formatSeconds, formatTimestamp } from '../../utils/format-numbers'; @@ -32,6 +34,7 @@ import type { MarkerIndex, Milliseconds, MarkerSchemaByName, + TableViewOptions, } from 'firefox-profiler/types'; import type { ConnectedProps } from '../../utils/connect'; @@ -149,20 +152,40 @@ type StateProps = {| +scrollToSelectionGeneration: number, +markerSchemaByName: MarkerSchemaByName, +getMarkerLabel: (MarkerIndex) => string, + +tableViewOptions: TableViewOptions, |}; type DispatchProps = {| +changeSelectedMarker: typeof changeSelectedMarker, +changeRightClickedMarker: typeof changeRightClickedMarker, + +onTableViewOptionsChange: (TableViewOptions) => any, |}; type Props = ConnectedProps<{||}, StateProps, DispatchProps>; class MarkerTableImpl extends PureComponent { _fixedColumns = [ - { propName: 'start', titleL10nId: 'MarkerTable--start' }, - { propName: 'duration', titleL10nId: 'MarkerTable--duration' }, - { propName: 'type', titleL10nId: 'MarkerTable--type' }, + { + propName: 'start', + titleL10nId: 'MarkerTable--start', + minWidth: 30, + initialWidth: 90, + resizable: true, + }, + { + propName: 'duration', + titleL10nId: 'MarkerTable--duration', + minWidth: 30, + initialWidth: 80, + resizable: true, + }, + { + propName: 'type', + titleL10nId: 'MarkerTable--type', + minWidth: 30, + initialWidth: 150, + resizable: true, + }, ]; _mainColumn = { propName: 'name', titleL10nId: 'MarkerTable--description' }; _expandedNodeIds: Array = []; @@ -247,6 +270,8 @@ class MarkerTableImpl extends PureComponent { contextMenuId="MarkerContextMenu" rowHeight={16} indentWidth={10} + viewOptions={this.props.tableViewOptions} + onViewOptionsChange={this.props.onTableViewOptionsChange} /> )}
        @@ -266,7 +291,13 @@ export const MarkerTable = explicitConnect<{||}, StateProps, DispatchProps>({ zeroAt: getZeroAt(state), markerSchemaByName: getMarkerSchemaByName(state), getMarkerLabel: selectedThreadSelectors.getMarkerTableLabelGetter(state), + tableViewOptions: getCurrentTableViewOptions(state), }), - mapDispatchToProps: { changeSelectedMarker, changeRightClickedMarker }, + mapDispatchToProps: { + changeSelectedMarker, + changeRightClickedMarker, + onTableViewOptionsChange: (tableViewOptions) => + changeTableViewOptions('marker-table', tableViewOptions), + }, component: MarkerTableImpl, }); diff --git a/src/components/shared/TreeView.css b/src/components/shared/TreeView.css index dda999b6ad..75413faa23 100644 --- a/src/components/shared/TreeView.css +++ b/src/components/shared/TreeView.css @@ -77,29 +77,37 @@ .treeViewHeaderColumn { position: relative; - box-sizing: border-box; - padding: 0 5px; line-height: 15px; white-space: nowrap; } .treeViewFixedColumn { overflow: hidden; - padding: 0 5px; text-overflow: ellipsis; } +.treeViewColumnDivider { + width: 20px; + text-align: center; + display: inline-block; + flex: none; + margin-left: -5px; + margin-right: -5px; +} +.treeViewColumnDivider[resize=true]:hover { + cursor: col-resize; +} + +.treeViewColumnDivider span { + border-right: 1px solid var(--grey-30); + box-sizing: border-box; +} + .treeViewHeaderColumn.treeViewFixedColumn { /* The fixed columns in the row don't shrink because they're positioning using * position: sticky, therefore we prevent shrinking for the columns in the * header too. */ flex: none; - border-right: 1px solid #e2e2e2; -} - -.treeViewRowColumn.treeViewFixedColumn { - box-sizing: border-box; - border-right: 1px solid var(--grey-30); } .treeBadge { diff --git a/src/components/shared/TreeView.js b/src/components/shared/TreeView.js index fa0c0a03ce..dc3a5d5950 100644 --- a/src/components/shared/TreeView.js +++ b/src/components/shared/TreeView.js @@ -16,7 +16,7 @@ import { VirtualList } from './VirtualList'; import { ContextMenuTrigger } from './ContextMenuTrigger'; -import type { CssPixels } from 'firefox-profiler/types'; +import type { CssPixels, TableViewOptions } from 'firefox-profiler/types'; import './TreeView.css'; @@ -51,42 +51,109 @@ export type Column = {| +component?: React.ComponentType<{| displayData: DisplayData, |}>, + /** defaults to initialWidth */ + +minWidth?: CssPixels, + /** has only to be present in resizable columns */ + +initialWidth?: CssPixels, + /** found width + adjustment = width of header column */ + +headerWidthAdjustment?: CssPixels, + // false by default + +resizable?: boolean, + +hideDividerAfter?: boolean, |}; type TreeViewHeaderProps = {| +fixedColumns: Column[], +mainColumn: Column, + +viewOptions: TableViewOptions, + // called when the users moves the divider right of the column, + // passes the column index and the start x coordinate + +onColumnWidthChangeStart: (number, CssPixels) => void, + +onColumnWidthReset: (number) => void, |}; -const TreeViewHeader = ({ - fixedColumns, - mainColumn, -}: TreeViewHeaderProps) => { - if (fixedColumns.length === 0 && !mainColumn.titleL10nId) { - // If there is nothing to display in the header, do not render it. - return null; - } - return ( -
        - {fixedColumns.map((col) => ( +class TreeViewHeader extends React.PureComponent< + TreeViewHeaderProps +> { + _onDividerMouseDown = (event: SyntheticMouseEvent<>) => { + this.props.onColumnWidthChangeStart( + // $FlowExpectError - we know that the target has this field + Number(event.target.attributes.columnIndex.value), + event.clientX + ); + event.stopPropagation(); + }; + + _onDividerDoubleClick = (event: SyntheticMouseEvent<>) => { + this.props.onColumnWidthReset( + // $FlowExpectError - we know that the target has this field + Number(event.target.attributes.columnIndex.value) + ); + event.stopPropagation(); + }; + + render() { + const { fixedColumns, mainColumn, viewOptions } = this.props; + const columnWidths = viewOptions.fixedColumnWidths; + if (fixedColumns.length === 0 && !mainColumn.titleL10nId) { + // If there is nothing to display in the header, do not render it. + return null; + } + return ( +
        + {fixedColumns.map((col, i) => { + const style = + columnWidths || col.initialWidth + ? { + width: + (columnWidths ? columnWidths[i] : col.initialWidth) + + (col.headerWidthAdjustment || 0), + } + : {}; + return ( + <> + + + + {col.hideDividerAfter !== true ? ( + + + + ) : null} + + ); + })} - ))} - - - -
        - ); -}; +
        + ); + } +} function reactStringWithHighlightedSubstrings( string: string, @@ -130,6 +197,11 @@ type TreeViewRowFixedColumnsProps = {| +onClick: (NodeIndex, SyntheticMouseEvent<>) => mixed, +highlightRegExp: RegExp | null, +rowHeightStyle: { height: CssPixels, lineHeight: string }, + +viewOptions: TableViewOptions, + // called when the users moves the divider right of the column, + // passes the column index and the start x coordinate + +onColumnWidthChangeStart: (number, CssPixels) => void, + +onColumnWidthReset: (number) => void, |}; class TreeViewRowFixedColumns extends React.PureComponent< @@ -140,16 +212,35 @@ class TreeViewRowFixedColumns extends React.PureComponent< onClick(nodeId, event); }; + _onDividerMouseDown = (event: SyntheticMouseEvent<>) => { + this.props.onColumnWidthChangeStart( + // $FlowExpectError - we know that the target has this field + Number(event.target.attributes.columnIndex.value), + event.clientX + ); + event.stopPropagation(); + }; + + _onDividerDoubleClick = (event: SyntheticMouseEvent<>) => { + this.props.onColumnWidthReset( + // $FlowExpectError - we know that the target has this field + Number(event.target.attributes.columnIndex.value) + ); + event.stopPropagation(); + }; + render() { const { displayData, columns, + viewOptions, index, isSelected, isRightClicked, highlightRegExp, rowHeightStyle, } = this.props; + const columnWidths = viewOptions.fixedColumnWidths; return (
        extends React.PureComponent< style={rowHeightStyle} onMouseDown={this._onClick} > - {columns.map((col) => { + {columns.map((col, i) => { const RenderComponent = col.component; const text = displayData[col.propName] || ''; - + const style = + columnWidths || col.initialWidth + ? { + width: columnWidths ? columnWidths[i] : col.initialWidth, + } + : {}; return ( - - {RenderComponent ? ( - - ) : ( - reactStringWithHighlightedSubstrings( - text, - highlightRegExp, - 'treeViewHighlighting' - ) - )} - + <> + + {RenderComponent ? ( + + ) : ( + reactStringWithHighlightedSubstrings( + text, + highlightRegExp, + 'treeViewHighlighting' + ) + )} + + {col.hideDividerAfter !== true ? ( + + + + ) : null} + ); })}
        @@ -393,13 +509,25 @@ type TreeViewProps = {| +rowHeight: CssPixels, +indentWidth: CssPixels, +onKeyDown?: (SyntheticKeyboardEvent<>) => void, + +viewOptions: TableViewOptions, + +onViewOptionsChange?: (TableViewOptions) => void, +|}; + +type TreeViewState = {| + +fixedColumnWidths?: Array, |}; export class TreeView extends React.PureComponent< - TreeViewProps + TreeViewProps, + TreeViewState > { _list: VirtualList | null = null; _takeListRef = (list: VirtualList | null) => (this._list = list); + _currentMovedColumnState: { columnIndex: number, lastX: CssPixels } | null = + null; + state = { + fixedColumnWidths: undefined, + }; // The tuple `specialItems` always contains 2 elements: the first element is // the selected node id (if any), and the second element is the right clicked @@ -421,6 +549,97 @@ export class TreeView extends React.PureComponent< { limit: 1 } ); + _getCurrentFixedColumnWidths = (): Array => { + const widths = + this.state.fixedColumnWidths || + this.props.viewOptions.fixedColumnWidths || + this.props.fixedColumns.map((c) => c.initialWidth); + if (widths === undefined) { + throw new Error('The fixed column widths should be defined.'); + } + // $FlowExpectError - Flow doesn't understand that we checked that widths is defined. + return widths; + }; + + _getCurrentViewOptions = (): TableViewOptions => { + const widths = this._getCurrentFixedColumnWidths(); + return { + ...this.props.viewOptions, + fixedColumnWidths: widths, + }; + }; + + _onColumnWidthChangeStart = (columnIndex: number, startX: CssPixels) => { + this._currentMovedColumnState = { columnIndex, lastX: startX }; + window.addEventListener('mousemove', this._onColumnWidthChangeMouseMove); + window.addEventListener('mouseup', this._onColumnWidthChangeMouseUp); + }; + + _onColumnWidthChangeMouseMove = (event: MouseEvent) => { + const columnState = this._currentMovedColumnState; + if (columnState !== null) { + const { columnIndex, lastX } = columnState; + const column = this.props.fixedColumns[columnIndex]; + const fixedColumnWidths = this._getCurrentFixedColumnWidths(); + columnState.lastX = event.clientX; + const diff = event.clientX - lastX; + if (column.minWidth === undefined) { + console.warn( + "Minimal width is undefined for the column '" + JSON.stringify(column) + ); + } + const newWidth = Math.max( + fixedColumnWidths[columnIndex] + diff, + column.minWidth || 0 + ); + this.setState((prevState) => { + const newFixedColumnWidths = ( + prevState.fixedColumnWidths || fixedColumnWidths + ).slice(); + newFixedColumnWidths[columnIndex] = newWidth; + return { + fixedColumnWidths: newFixedColumnWidths, + }; + }); + event.stopPropagation(); + } + }; + + _onColumnWidthChangeMouseUp = (event: MouseEvent) => { + window.removeEventListener('mousemove', this._onColumnWidthChangeMouseMove); + window.removeEventListener('mouseup', this._onColumnWidthChangeMouseUp); + this._currentMovedColumnState = null; + this._propagateColumnWidthChange(this._getCurrentFixedColumnWidths()); + event.stopPropagation(); + }; + + _onColumnWidthReset = (columnIndex: number) => { + const column = this.props.fixedColumns[columnIndex]; + const fixedColumnWidths = + this.state.fixedColumnWidths || this.props.viewOptions.fixedColumnWidths; + if (fixedColumnWidths) { + if (column.initialWidth === undefined) { + console.warn( + "Can't reset the width of a column without an initial width." + ); + } else { + fixedColumnWidths[columnIndex] = column.initialWidth; + } + this._propagateColumnWidthChange(fixedColumnWidths); + } + }; + + // triggers a re-render + _propagateColumnWidthChange = (fixedColumnWidths: Array) => { + const { onViewOptionsChange, viewOptions } = this.props; + if (onViewOptionsChange) { + onViewOptionsChange({ + ...viewOptions, + fixedColumnWidths, + }); + } + }; + _computeAllVisibleRowsMemoized = memoize( (tree: Tree, expandedNodes: Set) => { function _addVisibleRowsFromNode(tree, expandedNodes, arr, nodeId) { @@ -482,6 +701,7 @@ export class TreeView extends React.PureComponent< extends React.PureComponent< onClick={this._onRowClicked} highlightRegExp={highlightRegExp || null} rowHeightStyle={rowHeightStyle} + onColumnWidthChangeStart={this._onColumnWidthChangeStart} + onColumnWidthReset={this._onColumnWidthReset} /> ); } @@ -749,7 +971,13 @@ export class TreeView extends React.PureComponent< } = this.props; return (
        - + extends React.PureComponent< // at 3000 wide. containerWidth={Math.max(3000, maxNodeDepth * 10 + 2000)} ref={this._takeListRef} + key={JSON.stringify(this._getCurrentViewOptions())} /> {contextMenu} diff --git a/src/reducers/profile-view.js b/src/reducers/profile-view.js index 6474fcd0f1..311fc0af64 100644 --- a/src/reducers/profile-view.js +++ b/src/reducers/profile-view.js @@ -24,17 +24,20 @@ import type { SymbolicationStatus, ThreadViewOptions, ThreadViewOptionsPerThreads, + TableViewOptionsPerTab, RightClickedCallNode, MarkerReference, ActiveTabTimeline, CallNodePath, ThreadsKey, Milliseconds, + TableViewOptions, } from 'firefox-profiler/types'; import { applyFuncSubstitutionToCallPath, applyFuncSubstitutionToPathSetAndIncludeNewAncestors, } from '../profile-logic/symbolication'; +import type { TabSlug } from '../app-logic/tabs-handling'; import { objectMap } from '../utils/flow'; @@ -405,6 +408,48 @@ const viewOptionsPerThread: Reducer = ( } }; +export const defaultTableViewOptions: TableViewOptions = { + fixedColumnWidths: null, +}; + +function _getTableViewOptions(state: TableViewOptionsPerTab, tab: TabSlug) { + const options = state[tab]; + if (options) { + return options; + } + return defaultThreadViewOptions; +} + +function _updateTableViewOptions( + state: TableViewOptionsPerTab, + tab: TabSlug, + updates: $Shape +): TableViewOptionsPerTab { + const newState = { ...state }; + newState[tab] = { + ..._getTableViewOptions(state, tab), + ...updates, + }; + return newState; +} + +const tableViewOptionsPerTab: Reducer = ( + state = ({}: TableViewOptionsPerTab), + action +): TableViewOptionsPerTab => { + console.log(action); + switch (action.type) { + case 'CHANGE_TABLE_VIEW_OPTIONS': + return _updateTableViewOptions( + state, + action.tab, + action.tableViewOptions + ); + default: + return state; + } +}; + const waitingForLibs: Reducer> = ( state = new Set(), action @@ -721,6 +766,7 @@ const profileViewReducer: Reducer = wrapReducerInResetter( rightClickedMarker, hoveredMarker, mouseTimePosition, + perTable: tableViewOptionsPerTab, }), profile, full: combineReducers({ diff --git a/src/selectors/profile.js b/src/selectors/profile.js index 5b819ca7ab..8401e3a9df 100644 --- a/src/selectors/profile.js +++ b/src/selectors/profile.js @@ -21,6 +21,8 @@ import { } from '../profile-logic/marker-data'; import { markerSchemaFrontEndOnly } from '../profile-logic/marker-schema'; import { getDefaultCategories } from 'firefox-profiler/profile-logic/data-structures'; +import { defaultTableViewOptions } from '../reducers/profile-view'; +import type { TabSlug } from '../app-logic/tabs-handling'; import type { Profile, @@ -75,6 +77,7 @@ import type { SampleUnits, IndexIntoSamplesTable, ExtraProfileInfoSection, + TableViewOptions, } from 'firefox-profiler/types'; export const getProfileView: Selector = (state) => @@ -93,6 +96,9 @@ export const getOriginsProfileView: Selector = (state) => export const getProfileViewOptions: Selector< $PropertyType > = (state) => getProfileView(state).viewOptions; +export const getCurrentTableViewOptions: Selector = (state) => + getProfileViewOptions(state).perTable[UrlState.getSelectedTab(state)] || + defaultTableViewOptions; export const getProfileRootRange: Selector = (state) => getProfileViewOptions(state).rootRange; export const getSymbolicationStatus: Selector = (state) => @@ -122,6 +128,12 @@ export const getCommittedRange: Selector = createSelector( export const getMouseTimePosition: Selector = (state) => getProfileViewOptions(state).mouseTimePosition; +export const getTableViewOptionSelectors: (TabSlug) => Selector = + (tab) => (state) => { + const options = getProfileViewOptions(state).perTable[tab]; + return options || defaultTableViewOptions; + }; + export const getPreviewSelection: Selector = (state) => getProfileViewOptions(state).previewSelection; diff --git a/src/test/components/__snapshots__/MarkerTable.test.js.snap b/src/test/components/__snapshots__/MarkerTable.test.js.snap index a46aaa6901..601754d870 100644 --- a/src/test/components/__snapshots__/MarkerTable.test.js.snap +++ b/src/test/components/__snapshots__/MarkerTable.test.js.snap @@ -88,19 +88,46 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` > Start + + + Duration + + + Type + + + @@ -136,22 +163,49 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` > 0.000s + + + 0s + + + UserTiming + + +
        0.002s + + + + + + Paint + + +
        0.108s + + + unknown + + + IPC + + +
        0.153s + + + 584.00ns + + + Text + + +
        0.153s + + + 584.00ns + + + Text + + +
        0.158s + + + + + + Log + + +
        0.162s + + + 1ms + + + FileIO + + +
        diff --git a/src/test/components/__snapshots__/ProfileCallTreeView.test.js.snap b/src/test/components/__snapshots__/ProfileCallTreeView.test.js.snap index 53f3829e06..c97f4c50a5 100644 --- a/src/test/components/__snapshots__/ProfileCallTreeView.test.js.snap +++ b/src/test/components/__snapshots__/ProfileCallTreeView.test.js.snap @@ -150,9 +150,11 @@ exports[`ProfileCallTreeView with JS Allocations matches the snapshot for JS all > Total Size (bytes) + + + Self (bytes) + + + + + + @@ -207,22 +235,41 @@ allocated or deallocated in the program." > 100% 15 + + + + + + + + +
        100% 15 + + + + + + + + +
        80% 12 + + + + + + + + +
        80% 12 + + + 5 + + + + + +
        47% 7 + + + + + + + + +
        47% 7 + + + 7 + + + + + +
        20% 3 + + + + + + + + +
        @@ -821,9 +1038,11 @@ exports[`ProfileCallTreeView with balanced native allocations matches the snapsh > Total Size (bytes) + + + Self (bytes) + + + + + + @@ -878,22 +1123,41 @@ allocated or deallocated in the program." > -100% -15 + + + + + + + + +
        -100% -15 + + + + + + + + +
        -80% -12 + + + + + + + + +
        -80% -12 + + + -5 + + + + + +
        -47% -7 + + + + + + + + +
        -47% -7 + + + -7 + + + + + +
        -20% -3 + + + + + + + + +
        @@ -1492,9 +1926,11 @@ exports[`ProfileCallTreeView with balanced native allocations matches the snapsh > Total Size (bytes) + + + Self (bytes) + + + + + + @@ -1549,22 +2011,41 @@ allocated or deallocated in the program." > 100% 41 + + + + + + + + +
        100% 41 + + + + + + + + +
        73% 30 + + + + + + + + +
        73% 30 + + + 13 + + + + + +
        41% 17 + + + + + + + + +
        41% 17 + + + 17 + + + + + +
        27% 11 + + + + + + + + +
        @@ -2151,9 +2802,11 @@ exports[`ProfileCallTreeView with unbalanced native allocations matches the snap > Total Size (bytes) + + + Self (bytes) + + + + + + @@ -2208,22 +2887,41 @@ allocated or deallocated in the program." > 100% 15 + + + + + + + + +
        100% 15 + + + + + + + + +
        80% 12 + + + + + + + + +
        80% 12 + + + 5 + + + + + +
        47% 7 + + + + + + + + +
        47% 7 + + + 7 + + + + + +
        20% 3 + + + + + + + + +
        @@ -2810,9 +3678,11 @@ exports[`ProfileCallTreeView with unbalanced native allocations matches the snap > Total Size (bytes) + + + Self (bytes) + + + + + + @@ -2867,22 +3763,41 @@ allocated or deallocated in the program." > -100% -41 + + + + + + + + +
        -100% -41 + + + + + + + + +
        -59% -24 + + + + + + + + +
        -41% -17 + + + + + + + + +
        -41% -17 + + + -17 + + + + + +
        @@ -3765,9 +4796,11 @@ exports[`calltree/ProfileCallTreeView renders an inverted call tree 1`] = ` > Total (samples) + + + Self + + + + + + @@ -3821,30 +4880,58 @@ for understanding where time was actually spent in a program." > 67% 2 + + + 2 + + +
        + + +
        67% 2 + + + + + +
        + + +
        67% 2 + + + + + +
        + + +
        33% 1 + + + + + +
        + + +
        33% 1 + + + + + +
        + + +
        33% 1 + + + + + +
        + + +
        33% 1 + + + 1 + + +
        + + +
        @@ -4391,9 +5646,11 @@ exports[`calltree/ProfileCallTreeView renders an unfiltered call tree 1`] = ` > Total (samples) + + + Self + + + + + + @@ -4447,30 +5730,58 @@ for understanding where time was actually spent in a program." > 100% 3 + + + + + +
        + + +
        100% 3 + + + + + +
        + + +
        67% 2 + + + + + +
        + + +
        33% 1 + + + + + +
        -
        + + + +
        33% 1 + + + 1 + + +
        + + +
        33% 1 + + + + + +
        + + +
        33% 1 + + + + + +
        + + +
        @@ -5017,9 +6496,11 @@ exports[`calltree/ProfileCallTreeView renders an unfiltered call tree with filen > Total (samples) + + + Self + + + + + + @@ -5073,30 +6580,58 @@ for understanding where time was actually spent in a program." > 100% 1 + + + + + +
        + + +
        100% 1 + + + + + +
        + + +
        100% 1 + + + + + +
        + + +
        100% 1 + + + 1 + + +
        + + +
        @@ -5466,9 +7085,11 @@ exports[`calltree/ProfileCallTreeView renders call tree with some search strings > Total (samples) + + + Self + + + + + + @@ -5522,30 +7169,58 @@ for understanding where time was actually spent in a program." > 100% 3 + + + + + +
        + + +
        100% 3 + + + + + +
        + + +
        67% 2 + + + + + +
        + + +
        33% 1 + + + + + +
        + + +
        33% 1 + + + 1 + + +
        + + +
        33% 1 + + + + + +
        + + +
        33% 1 + + + + + +
        + + +
        @@ -6092,9 +7935,11 @@ exports[`calltree/ProfileCallTreeView renders call tree with some search strings > Total (samples) + + + Self + + + + + + @@ -6148,30 +8019,58 @@ for understanding where time was actually spent in a program." > 100% 2 + + + + + +
        + + +
        100% 2 + + + + + +
        + + +
        100% 2 + + + + + +
        + + +
        50% 1 + + + + + +
        + + +
        50% 1 + + + 1 + + +
        + + +
        50% 1 + + + + + +
        + + +
        @@ -6659,9 +8698,11 @@ exports[`calltree/ProfileCallTreeView renders call tree with some search strings > Total (samples) + + + Self + + + + + + @@ -6715,30 +8782,58 @@ for understanding where time was actually spent in a program." > 100% 2 + + + + + +
        + + +
        100% 2 + + + + + +
        + + +
        100% 2 + + + + + +
        + + +
        50% 1 + + + + + +
        + + +
        50% 1 + + + 1 + + +
        + + +
        50% 1 + + + + + +
        + + +
        @@ -7226,9 +9461,11 @@ exports[`calltree/ProfileCallTreeView renders call tree with some search strings > Total (samples) + + + Self + + + + + + @@ -7282,30 +9545,58 @@ for understanding where time was actually spent in a program." > 100% 1 + + + + + +
        + + +
        100% 1 + + + + + +
        + + +
        100% 1 + + + + + +
        + + +
        100% 1 + + + + + +
        + + +
        @@ -7676,9 +10051,11 @@ exports[`calltree/ProfileCallTreeView renders call tree with some search strings > Total (samples) + + + Self + + + + + + @@ -7732,30 +10135,58 @@ for understanding where time was actually spent in a program." > 100% 1 + + + + + +
        + + +
        100% 1 + + + + + +
        + + +
        100% 1 + + + + + +
        + + +
        100% 1 + + + + + +
        + + +
        @@ -8126,9 +10641,11 @@ exports[`calltree/ProfileCallTreeView renders call tree with some search strings > Total (samples) + + + Self + + + + + + @@ -8182,30 +10725,58 @@ for understanding where time was actually spent in a program." > 100% 2 + + + + + +
        + + +
        100% 2 + + + + + +
        + + +
        100% 2 + + + + + +
        + + +
        50% 1 + + + + + +
        + + +
        50% 1 + + + 1 + + +
        + + +
        50% 1 + + + + + +
        + + +
        diff --git a/src/types/actions.js b/src/types/actions.js index fbdc6ca10a..599d5b3b72 100644 --- a/src/types/actions.js +++ b/src/types/actions.js @@ -37,6 +37,7 @@ import type { State, UploadedProfileInformation, SourceLoadingError, + TableViewOptions, } from './state'; import type { CssPixels, StartEndRange, Milliseconds } from './units'; import type { BrowserConnectionStatus } from '../app-logic/browser-connection'; @@ -503,6 +504,11 @@ type UrlStateAction = +type: 'CHANGE_MOUSE_TIME_POSITION', +mouseTimePosition: Milliseconds | null, |} + | {| + +type: 'CHANGE_TABLE_VIEW_OPTIONS', + +tab: TabSlug, + +tableViewOptions: TableViewOptions, + |} | {| +type: 'TOGGLE_RESOURCES_PANEL', +selectedThreadIndexes: Set, diff --git a/src/types/state.js b/src/types/state.js index 9cd8fb2a23..0801e3c175 100644 --- a/src/types/state.js +++ b/src/types/state.js @@ -57,6 +57,12 @@ export type ThreadViewOptions = {| export type ThreadViewOptionsPerThreads = { [ThreadsKey]: ThreadViewOptions }; +export type TableViewOptions = {| + +fixedColumnWidths: Array | null, +|}; + +export type TableViewOptionsPerTab = { [TabSlug]: TableViewOptions }; + export type RightClickedCallNode = {| +threadsKey: ThreadsKey, +callNodePath: CallNodePath, @@ -108,6 +114,7 @@ export type ProfileViewState = { rightClickedMarker: MarkerReference | null, hoveredMarker: MarkerReference | null, mouseTimePosition: Milliseconds | null, + perTable: TableViewOptionsPerTab, |}, +profile: Profile | null, +full: FullProfileViewState, From 14c927f0ca175f00cbba15dc7baea4657091c5c5 Mon Sep 17 00:00:00 2001 From: Johannes Bechberger Date: Tue, 20 Dec 2022 15:17:30 +0100 Subject: [PATCH 074/114] Update src/types/state.js Co-authored-by: Julien Wajsberg --- src/types/state.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/state.js b/src/types/state.js index 0801e3c175..6c423b4984 100644 --- a/src/types/state.js +++ b/src/types/state.js @@ -114,7 +114,7 @@ export type ProfileViewState = { rightClickedMarker: MarkerReference | null, hoveredMarker: MarkerReference | null, mouseTimePosition: Milliseconds | null, - perTable: TableViewOptionsPerTab, + perTab: TableViewOptionsPerTab, |}, +profile: Profile | null, +full: FullProfileViewState, From d75cae8c292758d72e3cde9357554944bdba6aca Mon Sep 17 00:00:00 2001 From: Johannes Bechberger Date: Tue, 20 Dec 2022 15:19:45 +0100 Subject: [PATCH 075/114] Update src/reducers/profile-view.js Co-authored-by: Julien Wajsberg --- src/reducers/profile-view.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reducers/profile-view.js b/src/reducers/profile-view.js index 311fc0af64..65e96a784e 100644 --- a/src/reducers/profile-view.js +++ b/src/reducers/profile-view.js @@ -427,7 +427,7 @@ function _updateTableViewOptions( ): TableViewOptionsPerTab { const newState = { ...state }; newState[tab] = { - ..._getTableViewOptions(state, tab), + ...(state[tab] ?? defaultTableViewOptions), ...updates, }; return newState; From 3fe0bb502baf3f7862067a3ef41da606b22e17d0 Mon Sep 17 00:00:00 2001 From: Johannes Bechberger Date: Wed, 21 Dec 2022 11:45:16 +0100 Subject: [PATCH 076/114] Fix suggestions --- src/components/calltree/CallTree.js | 6 +- src/components/shared/TreeView.css | 15 +- src/components/shared/TreeView.js | 155 +- src/reducers/profile-view.js | 11 +- src/selectors/profile.js | 4 +- src/test/components/SourceView.test.js | 1 + .../__snapshots__/MarkerTable.test.js.snap | 195 +- .../ProfileCallTreeView.test.js.snap | 2513 +++++------------ 8 files changed, 881 insertions(+), 2019 deletions(-) diff --git a/src/components/calltree/CallTree.js b/src/components/calltree/CallTree.js index c737b03bb4..5042ff6a59 100644 --- a/src/components/calltree/CallTree.js +++ b/src/components/calltree/CallTree.js @@ -346,6 +346,8 @@ class CallTreeImpl extends PureComponent { disableOverscan, callNodeMaxDepth, weightType, + tableViewOptions, + onTableViewOptionsChange, } = this.props; if (tree.getRoots().length === 0) { return ; @@ -372,8 +374,8 @@ class CallTreeImpl extends PureComponent { onKeyDown={this._onKeyDown} onEnterKey={this._onEnterOrDoubleClick} onDoubleClick={this._onEnterOrDoubleClick} - viewOptions={this.props.tableViewOptions} - onViewOptionsChange={this.props.onTableViewOptionsChange} + viewOptions={tableViewOptions} + onViewOptionsChange={onTableViewOptionsChange} /> ); } diff --git a/src/components/shared/TreeView.css b/src/components/shared/TreeView.css index 75413faa23..efac4bd6b9 100644 --- a/src/components/shared/TreeView.css +++ b/src/components/shared/TreeView.css @@ -87,20 +87,23 @@ } .treeViewColumnDivider { - width: 20px; - text-align: center; display: inline-block; + width: 20px; flex: none; - margin-left: -5px; margin-right: -5px; + margin-left: -5px; + text-align: center; } -.treeViewColumnDivider[resize=true]:hover { + +.treeViewColumnDivider[data-resize='true']:hover { cursor: col-resize; } -.treeViewColumnDivider span { +.treeViewColumnDivider::before { + border-top: 2px solid var(--grey-30); border-right: 1px solid var(--grey-30); - box-sizing: border-box; + border-bottom: 2px solid var(--grey-30); + content: ''; } .treeViewHeaderColumn.treeViewFixedColumn { diff --git a/src/components/shared/TreeView.js b/src/components/shared/TreeView.js index dc3a5d5950..9305469744 100644 --- a/src/components/shared/TreeView.js +++ b/src/components/shared/TreeView.js @@ -59,6 +59,7 @@ export type Column = {| +headerWidthAdjustment?: CssPixels, // false by default +resizable?: boolean, + // is the divider after the column hidden? false by default +hideDividerAfter?: boolean, |}; @@ -75,21 +76,17 @@ type TreeViewHeaderProps = {| class TreeViewHeader extends React.PureComponent< TreeViewHeaderProps > { - _onDividerMouseDown = (event: SyntheticMouseEvent<>) => { + _onDividerMouseDown = (event: SyntheticMouseEvent) => { this.props.onColumnWidthChangeStart( - // $FlowExpectError - we know that the target has this field - Number(event.target.attributes.columnIndex.value), + Number(event.currentTarget.dataset.columnIndex), event.clientX ); - event.stopPropagation(); }; - _onDividerDoubleClick = (event: SyntheticMouseEvent<>) => { + _onDividerDoubleClick = (event: SyntheticMouseEvent) => { this.props.onColumnWidthReset( - // $FlowExpectError - we know that the target has this field - Number(event.target.attributes.columnIndex.value) + Number(event.currentTarget.dataset.columnIndex) ); - event.stopPropagation(); }; render() { @@ -111,12 +108,8 @@ class TreeViewHeader extends React.PureComponent< } : {}; return ( - <> - + + extends React.PureComponent< onDoubleClick={ col.resizable ? this._onDividerDoubleClick : undefined } - columnIndex={i} - column={col.propName} - resize={String(col.resizable || false)} - > - - + data-column-index={i} + // required for the CSS selector, to trigger the cursor change on hover + data-resize={String(col.resizable || false)} + > ) : null} - + ); })} = {| +highlightRegExp: RegExp | null, +rowHeightStyle: { height: CssPixels, lineHeight: string }, +viewOptions: TableViewOptions, - // called when the users moves the divider right of the column, - // passes the column index and the start x coordinate - +onColumnWidthChangeStart: (number, CssPixels) => void, - +onColumnWidthReset: (number) => void, |}; class TreeViewRowFixedColumns extends React.PureComponent< @@ -212,23 +199,6 @@ class TreeViewRowFixedColumns extends React.PureComponent< onClick(nodeId, event); }; - _onDividerMouseDown = (event: SyntheticMouseEvent<>) => { - this.props.onColumnWidthChangeStart( - // $FlowExpectError - we know that the target has this field - Number(event.target.attributes.columnIndex.value), - event.clientX - ); - event.stopPropagation(); - }; - - _onDividerDoubleClick = (event: SyntheticMouseEvent<>) => { - this.props.onColumnWidthReset( - // $FlowExpectError - we know that the target has this field - Number(event.target.attributes.columnIndex.value) - ); - event.stopPropagation(); - }; - render() { const { displayData, @@ -262,12 +232,12 @@ class TreeViewRowFixedColumns extends React.PureComponent< } : {}; return ( - <> + {RenderComponent ? ( @@ -280,23 +250,9 @@ class TreeViewRowFixedColumns extends React.PureComponent< )} {col.hideDividerAfter !== true ? ( - - - + ) : null} - + ); })}
        @@ -514,7 +470,7 @@ type TreeViewProps = {| |}; type TreeViewState = {| - +fixedColumnWidths?: Array, + +fixedColumnWidths: Array | null, |}; export class TreeView extends React.PureComponent< @@ -523,11 +479,15 @@ export class TreeView extends React.PureComponent< > { _list: VirtualList | null = null; _takeListRef = (list: VirtualList | null) => (this._list = list); - _currentMovedColumnState: { columnIndex: number, lastX: CssPixels } | null = - null; + _currentMovedColumnState: {| + columnIndex: number, + lastX: CssPixels, + initialWidth: CssPixels, + |} | null = null; state = { - fixedColumnWidths: undefined, + fixedColumnWidths: null, }; + _stateCounter: number = 0; // The tuple `specialItems` always contains 2 elements: the first element is // the selected node id (if any), and the second element is the right clicked @@ -557,7 +517,7 @@ export class TreeView extends React.PureComponent< if (widths === undefined) { throw new Error('The fixed column widths should be defined.'); } - // $FlowExpectError - Flow doesn't understand that we checked that widths is defined. + // $FlowExpectError - Flow doesn't understand that we're checking for undefined above. return widths; }; @@ -569,30 +529,41 @@ export class TreeView extends React.PureComponent< }; }; + _getTreeTabChildren = () => { + const treeTab = document.getElementById('calltree-tab'); + if (treeTab) { + return treeTab.childNodes; + } + return []; + }; + _onColumnWidthChangeStart = (columnIndex: number, startX: CssPixels) => { - this._currentMovedColumnState = { columnIndex, lastX: startX }; + this._currentMovedColumnState = { + columnIndex, + lastX: startX, + initialWidth: this._getCurrentFixedColumnWidths()[columnIndex], + }; window.addEventListener('mousemove', this._onColumnWidthChangeMouseMove); window.addEventListener('mouseup', this._onColumnWidthChangeMouseUp); + for (const elem of this._getTreeTabChildren()) { + // $FlowExpectError - we know that these are HTML nodes + elem.style.setProperty('cursor', 'col-resize'); + } }; _onColumnWidthChangeMouseMove = (event: MouseEvent) => { const columnState = this._currentMovedColumnState; if (columnState !== null) { - const { columnIndex, lastX } = columnState; + const { columnIndex, lastX, initialWidth } = columnState; const column = this.props.fixedColumns[columnIndex]; const fixedColumnWidths = this._getCurrentFixedColumnWidths(); - columnState.lastX = event.clientX; const diff = event.clientX - lastX; - if (column.minWidth === undefined) { - console.warn( - "Minimal width is undefined for the column '" + JSON.stringify(column) - ); + if (diff === 0) { + return; } - const newWidth = Math.max( - fixedColumnWidths[columnIndex] + diff, - column.minWidth || 0 - ); + const newWidth = Math.max(initialWidth + diff, column.minWidth || 10); this.setState((prevState) => { + this._stateCounter++; const newFixedColumnWidths = ( prevState.fixedColumnWidths || fixedColumnWidths ).slice(); @@ -601,16 +572,26 @@ export class TreeView extends React.PureComponent< fixedColumnWidths: newFixedColumnWidths, }; }); - event.stopPropagation(); } }; - _onColumnWidthChangeMouseUp = (event: MouseEvent) => { + _cleanUpMouseHandlersAndResetCursor = () => { window.removeEventListener('mousemove', this._onColumnWidthChangeMouseMove); window.removeEventListener('mouseup', this._onColumnWidthChangeMouseUp); + for (const elem of this._getTreeTabChildren()) { + // $FlowExpectError - we know that these are HTML nodes + elem.style.removeProperty('cursor'); + } + }; + + _onColumnWidthChangeMouseUp = () => { + this._cleanUpMouseHandlersAndResetCursor(); this._currentMovedColumnState = null; this._propagateColumnWidthChange(this._getCurrentFixedColumnWidths()); - event.stopPropagation(); + }; + + componentWillUnmount = () => { + this._cleanUpMouseHandlersAndResetCursor(); }; _onColumnWidthReset = (columnIndex: number) => { @@ -618,13 +599,7 @@ export class TreeView extends React.PureComponent< const fixedColumnWidths = this.state.fixedColumnWidths || this.props.viewOptions.fixedColumnWidths; if (fixedColumnWidths) { - if (column.initialWidth === undefined) { - console.warn( - "Can't reset the width of a column without an initial width." - ); - } else { - fixedColumnWidths[columnIndex] = column.initialWidth; - } + fixedColumnWidths[columnIndex] = column.initialWidth || 10; this._propagateColumnWidthChange(fixedColumnWidths); } }; @@ -709,8 +684,6 @@ export class TreeView extends React.PureComponent< onClick={this._onRowClicked} highlightRegExp={highlightRegExp || null} rowHeightStyle={rowHeightStyle} - onColumnWidthChangeStart={this._onColumnWidthChangeStart} - onColumnWidthReset={this._onColumnWidthReset} /> ); } @@ -999,13 +972,15 @@ export class TreeView extends React.PureComponent< focusable={true} onKeyDown={this._onKeyDown} specialItems={this._getSpecialItems()} - disableOverscan={!!disableOverscan} + disableOverscan={ + !!disableOverscan || this._currentMovedColumnState === null + } onCopy={this._onCopy} // If there is a deep call node depth, expand the width, or else keep it // at 3000 wide. containerWidth={Math.max(3000, maxNodeDepth * 10 + 2000)} ref={this._takeListRef} - key={JSON.stringify(this._getCurrentViewOptions())} + forceRender={this._stateCounter} /> {contextMenu} diff --git a/src/reducers/profile-view.js b/src/reducers/profile-view.js index 65e96a784e..ee85da8795 100644 --- a/src/reducers/profile-view.js +++ b/src/reducers/profile-view.js @@ -412,14 +412,6 @@ export const defaultTableViewOptions: TableViewOptions = { fixedColumnWidths: null, }; -function _getTableViewOptions(state: TableViewOptionsPerTab, tab: TabSlug) { - const options = state[tab]; - if (options) { - return options; - } - return defaultThreadViewOptions; -} - function _updateTableViewOptions( state: TableViewOptionsPerTab, tab: TabSlug, @@ -437,7 +429,6 @@ const tableViewOptionsPerTab: Reducer = ( state = ({}: TableViewOptionsPerTab), action ): TableViewOptionsPerTab => { - console.log(action); switch (action.type) { case 'CHANGE_TABLE_VIEW_OPTIONS': return _updateTableViewOptions( @@ -766,7 +757,7 @@ const profileViewReducer: Reducer = wrapReducerInResetter( rightClickedMarker, hoveredMarker, mouseTimePosition, - perTable: tableViewOptionsPerTab, + perTab: tableViewOptionsPerTab, }), profile, full: combineReducers({ diff --git a/src/selectors/profile.js b/src/selectors/profile.js index 8401e3a9df..1d6614acd9 100644 --- a/src/selectors/profile.js +++ b/src/selectors/profile.js @@ -97,7 +97,7 @@ export const getProfileViewOptions: Selector< $PropertyType > = (state) => getProfileView(state).viewOptions; export const getCurrentTableViewOptions: Selector = (state) => - getProfileViewOptions(state).perTable[UrlState.getSelectedTab(state)] || + getProfileViewOptions(state).perTab[UrlState.getSelectedTab(state)] || defaultTableViewOptions; export const getProfileRootRange: Selector = (state) => getProfileViewOptions(state).rootRange; @@ -130,7 +130,7 @@ export const getMouseTimePosition: Selector = (state) => export const getTableViewOptionSelectors: (TabSlug) => Selector = (tab) => (state) => { - const options = getProfileViewOptions(state).perTable[tab]; + const options = getProfileViewOptions(state).perTab[tab]; return options || defaultTableViewOptions; }; diff --git a/src/test/components/SourceView.test.js b/src/test/components/SourceView.test.js index 407649b1d2..cc9c337bc1 100644 --- a/src/test/components/SourceView.test.js +++ b/src/test/components/SourceView.test.js @@ -101,6 +101,7 @@ describe('SourceView', () => { const { sourceView } = setup(); const frameElement = screen.getByRole('treeitem', { name: /^A/ }); + fireFullClick(frameElement); fireFullClick(frameElement, { detail: 2 }); expect(sourceView()).toBeInTheDocument(); diff --git a/src/test/components/__snapshots__/MarkerTable.test.js.snap b/src/test/components/__snapshots__/MarkerTable.test.js.snap index 601754d870..7ab96c3f9c 100644 --- a/src/test/components/__snapshots__/MarkerTable.test.js.snap +++ b/src/test/components/__snapshots__/MarkerTable.test.js.snap @@ -94,12 +94,9 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = `
        - - + data-column-index="0" + data-resize="true" + /> - - + data-column-index="1" + data-resize="true" + /> - - + data-column-index="2" + data-resize="true" + /> @@ -163,6 +154,7 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` > @@ -170,14 +162,10 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + /> @@ -185,14 +173,10 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + /> @@ -200,12 +184,7 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + />
        @@ -220,27 +200,19 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + /> - - + /> @@ -248,12 +220,7 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + />
        @@ -268,14 +236,10 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + /> @@ -283,14 +247,10 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + /> @@ -298,12 +258,7 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + />
        @@ -318,14 +274,10 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + /> @@ -333,14 +285,10 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + /> @@ -348,12 +296,7 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + />
        @@ -368,14 +312,10 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + /> @@ -383,14 +323,10 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + /> @@ -398,12 +334,7 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + />
        @@ -418,27 +350,19 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + /> - - + /> @@ -446,12 +370,7 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + />
        @@ -466,14 +386,10 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + /> @@ -481,14 +397,10 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + /> @@ -496,12 +408,7 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` - - + />
        diff --git a/src/test/components/__snapshots__/ProfileCallTreeView.test.js.snap b/src/test/components/__snapshots__/ProfileCallTreeView.test.js.snap index c97f4c50a5..21a80502ca 100644 --- a/src/test/components/__snapshots__/ProfileCallTreeView.test.js.snap +++ b/src/test/components/__snapshots__/ProfileCallTreeView.test.js.snap @@ -164,12 +164,9 @@ bytes of the callers from this function."
        - - + data-column-index="1" + data-resize="true" + /> - - + data-column-index="2" + data-resize="true" + /> - - + data-column-index="3" + data-resize="false" + /> @@ -235,6 +226,7 @@ allocated or deallocated in the program." > @@ -242,6 +234,7 @@ allocated or deallocated in the program." @@ -249,14 +242,10 @@ allocated or deallocated in the program." - - + /> @@ -264,14 +253,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -300,6 +282,7 @@ allocated or deallocated in the program." @@ -307,14 +290,10 @@ allocated or deallocated in the program." - - + /> @@ -322,14 +301,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -358,6 +330,7 @@ allocated or deallocated in the program." @@ -365,14 +338,10 @@ allocated or deallocated in the program." - - + /> @@ -380,14 +349,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -416,6 +378,7 @@ allocated or deallocated in the program." @@ -423,14 +386,10 @@ allocated or deallocated in the program." - - + /> @@ -438,14 +397,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -474,6 +426,7 @@ allocated or deallocated in the program." @@ -481,14 +434,10 @@ allocated or deallocated in the program." - - + /> @@ -496,14 +445,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -532,6 +474,7 @@ allocated or deallocated in the program." @@ -539,14 +482,10 @@ allocated or deallocated in the program." - - + /> @@ -554,14 +493,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -590,6 +522,7 @@ allocated or deallocated in the program." @@ -597,14 +530,10 @@ allocated or deallocated in the program." - - + /> @@ -612,14 +541,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -1052,12 +973,9 @@ bytes of the callers from this function."
        - - + data-column-index="1" + data-resize="true" + /> - - + data-column-index="2" + data-resize="true" + /> - - + data-column-index="3" + data-resize="false" + /> @@ -1123,6 +1035,7 @@ allocated or deallocated in the program." > @@ -1130,6 +1043,7 @@ allocated or deallocated in the program." @@ -1137,14 +1051,10 @@ allocated or deallocated in the program." - - + /> @@ -1152,14 +1062,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -1188,6 +1091,7 @@ allocated or deallocated in the program." @@ -1195,14 +1099,10 @@ allocated or deallocated in the program." - - + /> @@ -1210,14 +1110,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -1246,6 +1139,7 @@ allocated or deallocated in the program." @@ -1253,14 +1147,10 @@ allocated or deallocated in the program." - - + /> @@ -1268,14 +1158,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -1304,6 +1187,7 @@ allocated or deallocated in the program." @@ -1311,14 +1195,10 @@ allocated or deallocated in the program." - - + /> @@ -1326,14 +1206,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -1362,6 +1235,7 @@ allocated or deallocated in the program." @@ -1369,14 +1243,10 @@ allocated or deallocated in the program." - - + /> @@ -1384,14 +1254,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -1420,6 +1283,7 @@ allocated or deallocated in the program." @@ -1427,14 +1291,10 @@ allocated or deallocated in the program." - - + /> @@ -1442,14 +1302,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -1478,6 +1331,7 @@ allocated or deallocated in the program." @@ -1485,14 +1339,10 @@ allocated or deallocated in the program." - - + /> @@ -1500,14 +1350,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -1940,12 +1782,9 @@ bytes of the callers from this function."
        - - + data-column-index="1" + data-resize="true" + /> - - + data-column-index="2" + data-resize="true" + /> - - + data-column-index="3" + data-resize="false" + /> @@ -2011,6 +1844,7 @@ allocated or deallocated in the program." > @@ -2018,6 +1852,7 @@ allocated or deallocated in the program." @@ -2025,14 +1860,10 @@ allocated or deallocated in the program." - - + /> @@ -2040,14 +1871,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -2076,6 +1900,7 @@ allocated or deallocated in the program." @@ -2083,14 +1908,10 @@ allocated or deallocated in the program." - - + /> @@ -2098,14 +1919,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -2134,6 +1948,7 @@ allocated or deallocated in the program." @@ -2141,14 +1956,10 @@ allocated or deallocated in the program." - - + /> @@ -2156,14 +1967,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -2192,6 +1996,7 @@ allocated or deallocated in the program." @@ -2199,14 +2004,10 @@ allocated or deallocated in the program." - - + /> @@ -2214,14 +2015,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -2250,6 +2044,7 @@ allocated or deallocated in the program." @@ -2257,14 +2052,10 @@ allocated or deallocated in the program." - - + /> @@ -2272,14 +2063,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -2308,6 +2092,7 @@ allocated or deallocated in the program." @@ -2315,14 +2100,10 @@ allocated or deallocated in the program." - - + /> @@ -2330,14 +2111,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -2366,6 +2140,7 @@ allocated or deallocated in the program." @@ -2373,14 +2148,10 @@ allocated or deallocated in the program." - - + /> @@ -2388,14 +2159,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -2816,12 +2579,9 @@ bytes of the callers from this function."
        - - + data-column-index="1" + data-resize="true" + /> - - + data-column-index="2" + data-resize="true" + /> - - + data-column-index="3" + data-resize="false" + /> @@ -2887,6 +2641,7 @@ allocated or deallocated in the program." > @@ -2894,6 +2649,7 @@ allocated or deallocated in the program." @@ -2901,14 +2657,10 @@ allocated or deallocated in the program." - - + /> @@ -2916,14 +2668,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -2952,6 +2697,7 @@ allocated or deallocated in the program." @@ -2959,14 +2705,10 @@ allocated or deallocated in the program." - - + /> @@ -2974,14 +2716,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -3010,6 +2745,7 @@ allocated or deallocated in the program." @@ -3017,14 +2753,10 @@ allocated or deallocated in the program." - - + /> @@ -3032,14 +2764,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -3068,6 +2793,7 @@ allocated or deallocated in the program." @@ -3075,14 +2801,10 @@ allocated or deallocated in the program." - - + /> @@ -3090,14 +2812,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -3126,6 +2841,7 @@ allocated or deallocated in the program." @@ -3133,14 +2849,10 @@ allocated or deallocated in the program." - - + /> @@ -3148,14 +2860,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -3184,6 +2889,7 @@ allocated or deallocated in the program." @@ -3191,14 +2897,10 @@ allocated or deallocated in the program." - - + /> @@ -3206,14 +2908,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -3242,6 +2937,7 @@ allocated or deallocated in the program." @@ -3249,14 +2945,10 @@ allocated or deallocated in the program." - - + /> @@ -3264,14 +2956,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -3692,12 +3376,9 @@ bytes of the callers from this function."
        - - + data-column-index="1" + data-resize="true" + /> - - + data-column-index="2" + data-resize="true" + /> - - + data-column-index="3" + data-resize="false" + /> @@ -3763,6 +3438,7 @@ allocated or deallocated in the program." > @@ -3770,6 +3446,7 @@ allocated or deallocated in the program." @@ -3777,14 +3454,10 @@ allocated or deallocated in the program." - - + /> @@ -3792,14 +3465,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -3828,6 +3494,7 @@ allocated or deallocated in the program." @@ -3835,14 +3502,10 @@ allocated or deallocated in the program." - - + /> @@ -3850,14 +3513,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -3886,6 +3542,7 @@ allocated or deallocated in the program." @@ -3893,14 +3550,10 @@ allocated or deallocated in the program." - - + /> @@ -3908,14 +3561,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -3944,6 +3590,7 @@ allocated or deallocated in the program." @@ -3951,14 +3598,10 @@ allocated or deallocated in the program." - - + /> @@ -3966,14 +3609,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -4002,6 +3638,7 @@ allocated or deallocated in the program." @@ -4009,14 +3646,10 @@ allocated or deallocated in the program." - - + /> @@ -4024,14 +3657,11 @@ allocated or deallocated in the program." - - + />
        - - + />
        @@ -4810,12 +4435,9 @@ function."
        - - + data-column-index="1" + data-resize="true" + /> - - + data-column-index="2" + data-resize="true" + /> - - + data-column-index="3" + data-resize="false" + /> @@ -4880,6 +4496,7 @@ for understanding where time was actually spent in a program." > @@ -4887,6 +4504,7 @@ for understanding where time was actually spent in a program." @@ -4894,14 +4512,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -4909,14 +4523,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -4926,12 +4536,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -4946,6 +4552,7 @@ for understanding where time was actually spent in a program." @@ -4953,14 +4560,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -4968,14 +4571,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -4985,12 +4584,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -5005,21 +4600,18 @@ for understanding where time was actually spent in a program." 2 - - + class="treeViewColumnDivider" + /> @@ -5027,14 +4619,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5044,12 +4632,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -5064,6 +4648,7 @@ for understanding where time was actually spent in a program." @@ -5071,14 +4656,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5086,14 +4667,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5103,12 +4680,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -5123,6 +4696,7 @@ for understanding where time was actually spent in a program." @@ -5130,14 +4704,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5145,14 +4715,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5162,12 +4728,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -5182,6 +4744,7 @@ for understanding where time was actually spent in a program." @@ -5189,14 +4752,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5204,14 +4763,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5221,12 +4776,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -5241,6 +4792,7 @@ for understanding where time was actually spent in a program." @@ -5248,14 +4800,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5263,14 +4811,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5280,12 +4824,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -5660,12 +5199,9 @@ function."
        - - + data-column-index="1" + data-resize="true" + /> - - + data-column-index="2" + data-resize="true" + /> - - + data-column-index="3" + data-resize="false" + /> @@ -5730,6 +5260,7 @@ for understanding where time was actually spent in a program." > @@ -5737,6 +5268,7 @@ for understanding where time was actually spent in a program." @@ -5744,14 +5276,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5759,14 +5287,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5776,12 +5300,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -5796,6 +5316,7 @@ for understanding where time was actually spent in a program." @@ -5803,14 +5324,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5818,14 +5335,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5835,12 +5348,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -5855,6 +5364,7 @@ for understanding where time was actually spent in a program." @@ -5862,14 +5372,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5877,14 +5383,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5894,12 +5396,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -5914,6 +5412,7 @@ for understanding where time was actually spent in a program." @@ -5921,14 +5420,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5936,14 +5431,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5953,12 +5444,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -5973,6 +5460,7 @@ for understanding where time was actually spent in a program." @@ -5980,14 +5468,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -5995,14 +5479,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -6012,12 +5492,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -6032,6 +5508,7 @@ for understanding where time was actually spent in a program." @@ -6039,14 +5516,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -6054,14 +5527,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -6071,12 +5540,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -6091,6 +5556,7 @@ for understanding where time was actually spent in a program." @@ -6098,14 +5564,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -6113,14 +5575,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -6130,12 +5588,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -6510,12 +5963,9 @@ function."
        - - + data-column-index="1" + data-resize="true" + /> - - + data-column-index="2" + data-resize="true" + /> - - + data-column-index="3" + data-resize="false" + /> @@ -6580,6 +6024,7 @@ for understanding where time was actually spent in a program." > @@ -6587,6 +6032,7 @@ for understanding where time was actually spent in a program." @@ -6594,14 +6040,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -6609,14 +6051,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -6626,12 +6064,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -6646,6 +6080,7 @@ for understanding where time was actually spent in a program." @@ -6653,14 +6088,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -6668,14 +6099,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -6685,12 +6112,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -6705,6 +6128,7 @@ for understanding where time was actually spent in a program." @@ -6712,14 +6136,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -6727,14 +6147,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -6744,12 +6160,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -6764,6 +6176,7 @@ for understanding where time was actually spent in a program." @@ -6771,14 +6184,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -6786,14 +6195,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -6803,12 +6208,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -7099,12 +6499,9 @@ function."
        - - + data-column-index="1" + data-resize="true" + /> - - + data-column-index="2" + data-resize="true" + /> - - + data-column-index="3" + data-resize="false" + /> @@ -7169,6 +6560,7 @@ for understanding where time was actually spent in a program." > @@ -7176,6 +6568,7 @@ for understanding where time was actually spent in a program." @@ -7183,14 +6576,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -7198,14 +6587,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -7215,12 +6600,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -7235,6 +6616,7 @@ for understanding where time was actually spent in a program." @@ -7242,14 +6624,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -7257,14 +6635,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -7274,12 +6648,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -7294,6 +6664,7 @@ for understanding where time was actually spent in a program." @@ -7301,14 +6672,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -7316,14 +6683,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -7333,12 +6696,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -7353,6 +6712,7 @@ for understanding where time was actually spent in a program." @@ -7360,14 +6720,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -7375,14 +6731,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -7392,12 +6744,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -7412,6 +6760,7 @@ for understanding where time was actually spent in a program." @@ -7419,14 +6768,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -7434,14 +6779,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -7451,12 +6792,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -7471,6 +6808,7 @@ for understanding where time was actually spent in a program." @@ -7478,14 +6816,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -7493,14 +6827,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -7510,12 +6840,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -7530,6 +6856,7 @@ for understanding where time was actually spent in a program." @@ -7537,14 +6864,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -7552,14 +6875,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -7569,12 +6888,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -7949,12 +7263,9 @@ function."
        - - + data-column-index="1" + data-resize="true" + /> - - + data-column-index="2" + data-resize="true" + /> - - + data-column-index="3" + data-resize="false" + /> @@ -8019,6 +7324,7 @@ for understanding where time was actually spent in a program." > @@ -8026,6 +7332,7 @@ for understanding where time was actually spent in a program." @@ -8033,14 +7340,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8048,14 +7351,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8065,12 +7364,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -8085,6 +7380,7 @@ for understanding where time was actually spent in a program." @@ -8092,14 +7388,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8107,14 +7399,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8124,12 +7412,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -8144,6 +7428,7 @@ for understanding where time was actually spent in a program." @@ -8151,14 +7436,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8166,14 +7447,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8183,12 +7460,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -8203,6 +7476,7 @@ for understanding where time was actually spent in a program." @@ -8210,14 +7484,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8225,14 +7495,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8242,12 +7508,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -8262,6 +7524,7 @@ for understanding where time was actually spent in a program." @@ -8269,14 +7532,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8284,14 +7543,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8301,12 +7556,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -8321,6 +7572,7 @@ for understanding where time was actually spent in a program." @@ -8328,14 +7580,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8343,14 +7591,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8360,12 +7604,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -8712,12 +7951,9 @@ function."
        - - + data-column-index="1" + data-resize="true" + /> - - + data-column-index="2" + data-resize="true" + /> - - + data-column-index="3" + data-resize="false" + /> @@ -8782,6 +8012,7 @@ for understanding where time was actually spent in a program." > @@ -8789,6 +8020,7 @@ for understanding where time was actually spent in a program." @@ -8796,14 +8028,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8811,14 +8039,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8828,12 +8052,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -8848,6 +8068,7 @@ for understanding where time was actually spent in a program." @@ -8855,14 +8076,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8870,14 +8087,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8887,12 +8100,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -8907,6 +8116,7 @@ for understanding where time was actually spent in a program." @@ -8914,14 +8124,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8929,14 +8135,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8946,12 +8148,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -8966,6 +8164,7 @@ for understanding where time was actually spent in a program." @@ -8973,14 +8172,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -8988,14 +8183,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -9005,12 +8196,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -9025,6 +8212,7 @@ for understanding where time was actually spent in a program." @@ -9032,14 +8220,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -9047,14 +8231,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -9064,12 +8244,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -9084,6 +8260,7 @@ for understanding where time was actually spent in a program." @@ -9091,14 +8268,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -9106,14 +8279,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -9123,12 +8292,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -9475,12 +8639,9 @@ function."
        - - + data-column-index="1" + data-resize="true" + /> - - + data-column-index="2" + data-resize="true" + /> - - + data-column-index="3" + data-resize="false" + /> @@ -9545,6 +8700,7 @@ for understanding where time was actually spent in a program." > @@ -9552,6 +8708,7 @@ for understanding where time was actually spent in a program." @@ -9559,14 +8716,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -9574,14 +8727,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -9591,12 +8740,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -9611,6 +8756,7 @@ for understanding where time was actually spent in a program." @@ -9618,14 +8764,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -9633,14 +8775,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -9650,12 +8788,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -9670,6 +8804,7 @@ for understanding where time was actually spent in a program." @@ -9677,14 +8812,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -9692,14 +8823,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -9709,12 +8836,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -9729,6 +8852,7 @@ for understanding where time was actually spent in a program." @@ -9736,14 +8860,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -9751,14 +8871,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -9768,12 +8884,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -10065,12 +9176,9 @@ function."
        - - + data-column-index="1" + data-resize="true" + /> - - + data-column-index="2" + data-resize="true" + /> - - + data-column-index="3" + data-resize="false" + /> @@ -10135,6 +9237,7 @@ for understanding where time was actually spent in a program." > @@ -10142,6 +9245,7 @@ for understanding where time was actually spent in a program." @@ -10149,14 +9253,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10164,14 +9264,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10181,12 +9277,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -10201,6 +9293,7 @@ for understanding where time was actually spent in a program." @@ -10208,14 +9301,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10223,14 +9312,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10240,12 +9325,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -10260,6 +9341,7 @@ for understanding where time was actually spent in a program." @@ -10267,14 +9349,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10282,14 +9360,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10299,12 +9373,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -10319,6 +9389,7 @@ for understanding where time was actually spent in a program." @@ -10326,14 +9397,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10341,14 +9408,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10358,12 +9421,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -10655,12 +9713,9 @@ function."
        - - + data-column-index="1" + data-resize="true" + /> - - + data-column-index="2" + data-resize="true" + /> - - + data-column-index="3" + data-resize="false" + /> @@ -10725,6 +9774,7 @@ for understanding where time was actually spent in a program." > @@ -10732,6 +9782,7 @@ for understanding where time was actually spent in a program." @@ -10739,14 +9790,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10754,14 +9801,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10771,12 +9814,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -10791,6 +9830,7 @@ for understanding where time was actually spent in a program." @@ -10798,14 +9838,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10813,14 +9849,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10830,12 +9862,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -10850,6 +9878,7 @@ for understanding where time was actually spent in a program." @@ -10857,14 +9886,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10872,14 +9897,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10889,12 +9910,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -10909,6 +9926,7 @@ for understanding where time was actually spent in a program." @@ -10916,14 +9934,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10931,14 +9945,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10948,12 +9958,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -10968,6 +9974,7 @@ for understanding where time was actually spent in a program." @@ -10975,14 +9982,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -10990,14 +9993,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -11007,12 +10006,7 @@ for understanding where time was actually spent in a program." - - + />
        @@ -11027,6 +10022,7 @@ for understanding where time was actually spent in a program." @@ -11034,14 +10030,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -11049,14 +10041,10 @@ for understanding where time was actually spent in a program." - - + /> @@ -11066,12 +10054,7 @@ for understanding where time was actually spent in a program." - - + />
        From 565b55e8c0006a19bf6fa245e7c8fe1712bdcd3e Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 22 Dec 2022 17:07:56 +0100 Subject: [PATCH 077/114] Make initialWidth mandatory for the fixed columns, as well as remove resize-relevant properties for the other columns --- src/components/calltree/CallTree.js | 21 +++++++++++++++++---- src/components/shared/TreeView.js | 15 +++++++++------ 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/components/calltree/CallTree.js b/src/components/calltree/CallTree.js index 5042ff6a59..c23189f6b1 100644 --- a/src/components/calltree/CallTree.js +++ b/src/components/calltree/CallTree.js @@ -48,7 +48,10 @@ import type { } from 'firefox-profiler/types'; import type { CallTree as CallTreeType } from 'firefox-profiler/profile-logic/call-tree'; -import type { Column } from 'firefox-profiler/components/shared/TreeView'; +import type { + Column, + MaybeResizableColumn, +} from 'firefox-profiler/components/shared/TreeView'; import type { ConnectedProps } from 'firefox-profiler/utils/connect'; import './CallTree.css'; @@ -101,7 +104,7 @@ class CallTreeImpl extends PureComponent { * appropriate labels for the call tree based on this weight. */ _weightTypeToColumns = memoize( - (weightType: WeightType): Column[] => { + (weightType: WeightType): MaybeResizableColumn[] => { switch (weightType) { case 'tracing-ms': return [ @@ -126,7 +129,12 @@ class CallTreeImpl extends PureComponent { initialWidth: 70, resizable: true, }, - { propName: 'icon', titleL10nId: '', component: Icon }, + { + propName: 'icon', + titleL10nId: '', + component: Icon, + initialWidth: 10, + }, ]; case 'samples': return [ @@ -181,7 +189,12 @@ class CallTreeImpl extends PureComponent { initialWidth: 90, resizable: true, }, - { propName: 'icon', titleL10nId: '', component: Icon }, + { + propName: 'icon', + titleL10nId: '', + component: Icon, + initialWidth: 10, + }, ]; default: throw assertExhaustiveCheck(weightType, 'Unhandled WeightType.'); diff --git a/src/components/shared/TreeView.js b/src/components/shared/TreeView.js index 9305469744..baf9040408 100644 --- a/src/components/shared/TreeView.js +++ b/src/components/shared/TreeView.js @@ -51,10 +51,14 @@ export type Column = {| +component?: React.ComponentType<{| displayData: DisplayData, |}>, +|}; + +export type MaybeResizableColumn = {| + ...Column, /** defaults to initialWidth */ +minWidth?: CssPixels, - /** has only to be present in resizable columns */ - +initialWidth?: CssPixels, + /** This is the initial width, this can be changed in resizable columns */ + +initialWidth: CssPixels, /** found width + adjustment = width of header column */ +headerWidthAdjustment?: CssPixels, // false by default @@ -64,7 +68,7 @@ export type Column = {| |}; type TreeViewHeaderProps = {| - +fixedColumns: Column[], + +fixedColumns: MaybeResizableColumn[], +mainColumn: Column, +viewOptions: TableViewOptions, // called when the users moves the divider right of the column, @@ -181,7 +185,7 @@ function reactStringWithHighlightedSubstrings( type TreeViewRowFixedColumnsProps = {| +displayData: DisplayData, +nodeId: NodeIndex, - +columns: Column[], + +columns: MaybeResizableColumn[], +index: number, +isSelected: boolean, +isRightClicked: boolean, @@ -445,7 +449,7 @@ interface Tree { } type TreeViewProps = {| - +fixedColumns: Column[], + +fixedColumns: MaybeResizableColumn[], +mainColumn: Column, +tree: Tree, +expandedNodeIds: Array, @@ -517,7 +521,6 @@ export class TreeView extends React.PureComponent< if (widths === undefined) { throw new Error('The fixed column widths should be defined.'); } - // $FlowExpectError - Flow doesn't understand that we're checking for undefined above. return widths; }; From f8c079a34c648829621e694b1e254eb7f9045dd3 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 22 Dec 2022 17:15:15 +0100 Subject: [PATCH 078/114] Use a class instead of a data attribute to trigger the resize mouse cursor --- src/components/shared/TreeView.css | 2 +- src/components/shared/TreeView.js | 6 +- .../__snapshots__/MarkerTable.test.js.snap | 9 +- .../ProfileCallTreeView.test.js.snap | 164 +++++++----------- 4 files changed, 68 insertions(+), 113 deletions(-) diff --git a/src/components/shared/TreeView.css b/src/components/shared/TreeView.css index efac4bd6b9..9f07fc974a 100644 --- a/src/components/shared/TreeView.css +++ b/src/components/shared/TreeView.css @@ -95,7 +95,7 @@ text-align: center; } -.treeViewColumnDivider[data-resize='true']:hover { +.treeViewColumnDivider.isResizable { cursor: col-resize; } diff --git a/src/components/shared/TreeView.js b/src/components/shared/TreeView.js index baf9040408..1589334b11 100644 --- a/src/components/shared/TreeView.js +++ b/src/components/shared/TreeView.js @@ -122,7 +122,9 @@ class TreeViewHeader extends React.PureComponent< {col.hideDividerAfter !== true ? ( extends React.PureComponent< col.resizable ? this._onDividerDoubleClick : undefined } data-column-index={i} - // required for the CSS selector, to trigger the cursor change on hover - data-resize={String(col.resizable || false)} > ) : null} diff --git a/src/test/components/__snapshots__/MarkerTable.test.js.snap b/src/test/components/__snapshots__/MarkerTable.test.js.snap index 7ab96c3f9c..35b18201a1 100644 --- a/src/test/components/__snapshots__/MarkerTable.test.js.snap +++ b/src/test/components/__snapshots__/MarkerTable.test.js.snap @@ -93,9 +93,8 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` Start
        Date: Thu, 22 Dec 2022 17:40:40 +0100 Subject: [PATCH 079/114] Use a more generic way to keep the cursor while resizing the column --- src/components/shared/TreeView.css | 3 ++- src/components/shared/TreeView.js | 29 +++++++++-------------------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/components/shared/TreeView.css b/src/components/shared/TreeView.css index 9f07fc974a..c4c2af181c 100644 --- a/src/components/shared/TreeView.css +++ b/src/components/shared/TreeView.css @@ -95,7 +95,8 @@ text-align: center; } -.treeViewColumnDivider.isResizable { +.treeViewColumnDivider.isResizable, +.treeView.isResizingColumns { cursor: col-resize; } diff --git a/src/components/shared/TreeView.js b/src/components/shared/TreeView.js index 1589334b11..dbd54b2df7 100644 --- a/src/components/shared/TreeView.js +++ b/src/components/shared/TreeView.js @@ -475,6 +475,7 @@ type TreeViewProps = {| type TreeViewState = {| +fixedColumnWidths: Array | null, + +isResizingColumns: boolean, |}; export class TreeView extends React.PureComponent< @@ -490,6 +491,7 @@ export class TreeView extends React.PureComponent< |} | null = null; state = { fixedColumnWidths: null, + isResizingColumns: false, }; _stateCounter: number = 0; @@ -532,26 +534,15 @@ export class TreeView extends React.PureComponent< }; }; - _getTreeTabChildren = () => { - const treeTab = document.getElementById('calltree-tab'); - if (treeTab) { - return treeTab.childNodes; - } - return []; - }; - _onColumnWidthChangeStart = (columnIndex: number, startX: CssPixels) => { this._currentMovedColumnState = { columnIndex, lastX: startX, initialWidth: this._getCurrentFixedColumnWidths()[columnIndex], }; + this.setState({ isResizingColumns: true }); window.addEventListener('mousemove', this._onColumnWidthChangeMouseMove); window.addEventListener('mouseup', this._onColumnWidthChangeMouseUp); - for (const elem of this._getTreeTabChildren()) { - // $FlowExpectError - we know that these are HTML nodes - elem.style.setProperty('cursor', 'col-resize'); - } }; _onColumnWidthChangeMouseMove = (event: MouseEvent) => { @@ -578,23 +569,20 @@ export class TreeView extends React.PureComponent< } }; - _cleanUpMouseHandlersAndResetCursor = () => { + _cleanUpMouseHandlers = () => { window.removeEventListener('mousemove', this._onColumnWidthChangeMouseMove); window.removeEventListener('mouseup', this._onColumnWidthChangeMouseUp); - for (const elem of this._getTreeTabChildren()) { - // $FlowExpectError - we know that these are HTML nodes - elem.style.removeProperty('cursor'); - } }; _onColumnWidthChangeMouseUp = () => { - this._cleanUpMouseHandlersAndResetCursor(); + this.setState({ isResizingColumns: false }); + this._cleanUpMouseHandlers(); this._currentMovedColumnState = null; this._propagateColumnWidthChange(this._getCurrentFixedColumnWidths()); }; componentWillUnmount = () => { - this._cleanUpMouseHandlersAndResetCursor(); + this._cleanUpMouseHandlers(); }; _onColumnWidthReset = (columnIndex: number) => { @@ -945,8 +933,9 @@ export class TreeView extends React.PureComponent< rowHeight, selectedNodeId, } = this.props; + const { isResizingColumns } = this.state; return ( -
        +
        Date: Thu, 22 Dec 2022 18:22:59 +0100 Subject: [PATCH 080/114] Improve the divider's CSS so that it has the right height --- src/components/shared/TreeView.css | 7 +- src/components/shared/TreeView.js | 1 - .../__snapshots__/MarkerTable.test.js.snap | 21 -- .../ProfileCallTreeView.test.js.snap | 336 ------------------ 4 files changed, 3 insertions(+), 362 deletions(-) diff --git a/src/components/shared/TreeView.css b/src/components/shared/TreeView.css index c4c2af181c..9c8d56d8f6 100644 --- a/src/components/shared/TreeView.css +++ b/src/components/shared/TreeView.css @@ -87,12 +87,13 @@ } .treeViewColumnDivider { - display: inline-block; + display: flex; width: 20px; flex: none; + align-items: stretch; + justify-content: center; margin-right: -5px; margin-left: -5px; - text-align: center; } .treeViewColumnDivider.isResizable, @@ -101,9 +102,7 @@ } .treeViewColumnDivider::before { - border-top: 2px solid var(--grey-30); border-right: 1px solid var(--grey-30); - border-bottom: 2px solid var(--grey-30); content: ''; } diff --git a/src/components/shared/TreeView.js b/src/components/shared/TreeView.js index dbd54b2df7..17fb2fa5f7 100644 --- a/src/components/shared/TreeView.js +++ b/src/components/shared/TreeView.js @@ -241,7 +241,6 @@ class TreeViewRowFixedColumns extends React.PureComponent< className={`treeViewRowColumn treeViewFixedColumn ${col.propName}`} title={text} style={style} - data-divider={col.hideDividerAfter !== true} > {RenderComponent ? ( diff --git a/src/test/components/__snapshots__/MarkerTable.test.js.snap b/src/test/components/__snapshots__/MarkerTable.test.js.snap index 35b18201a1..cb1fe477d0 100644 --- a/src/test/components/__snapshots__/MarkerTable.test.js.snap +++ b/src/test/components/__snapshots__/MarkerTable.test.js.snap @@ -151,7 +151,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` > @@ -162,7 +161,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` /> @@ -173,7 +171,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` /> @@ -189,7 +186,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` > @@ -200,7 +196,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` /> @@ -209,7 +204,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` /> @@ -225,7 +219,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` > @@ -236,7 +229,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` /> @@ -247,7 +239,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` /> @@ -263,7 +254,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` > @@ -274,7 +264,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` /> @@ -285,7 +274,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` /> @@ -301,7 +289,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` > @@ -312,7 +299,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` /> @@ -323,7 +309,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` /> @@ -339,7 +324,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` > @@ -350,7 +334,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` /> @@ -359,7 +342,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` /> @@ -375,7 +357,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` > @@ -386,7 +367,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` /> @@ -397,7 +377,6 @@ exports[`MarkerTable renders some basic markers and updates when needed 1`] = ` /> diff --git a/src/test/components/__snapshots__/ProfileCallTreeView.test.js.snap b/src/test/components/__snapshots__/ProfileCallTreeView.test.js.snap index 94f9f34c5b..25b2329a40 100644 --- a/src/test/components/__snapshots__/ProfileCallTreeView.test.js.snap +++ b/src/test/components/__snapshots__/ProfileCallTreeView.test.js.snap @@ -223,7 +223,6 @@ allocated or deallocated in the program." > @@ -231,7 +230,6 @@ allocated or deallocated in the program." @@ -242,7 +240,6 @@ allocated or deallocated in the program." /> @@ -253,7 +250,6 @@ allocated or deallocated in the program." /> @@ -271,7 +267,6 @@ allocated or deallocated in the program." > @@ -279,7 +274,6 @@ allocated or deallocated in the program." @@ -290,7 +284,6 @@ allocated or deallocated in the program." /> @@ -301,7 +294,6 @@ allocated or deallocated in the program." /> @@ -319,7 +311,6 @@ allocated or deallocated in the program." > @@ -327,7 +318,6 @@ allocated or deallocated in the program." @@ -338,7 +328,6 @@ allocated or deallocated in the program." /> @@ -349,7 +338,6 @@ allocated or deallocated in the program." /> @@ -367,7 +355,6 @@ allocated or deallocated in the program." > @@ -375,7 +362,6 @@ allocated or deallocated in the program." @@ -386,7 +372,6 @@ allocated or deallocated in the program." /> @@ -397,7 +382,6 @@ allocated or deallocated in the program." /> @@ -415,7 +399,6 @@ allocated or deallocated in the program." > @@ -423,7 +406,6 @@ allocated or deallocated in the program." @@ -434,7 +416,6 @@ allocated or deallocated in the program." /> @@ -445,7 +426,6 @@ allocated or deallocated in the program." /> @@ -463,7 +443,6 @@ allocated or deallocated in the program." > @@ -471,7 +450,6 @@ allocated or deallocated in the program." @@ -482,7 +460,6 @@ allocated or deallocated in the program." /> @@ -493,7 +470,6 @@ allocated or deallocated in the program." /> @@ -511,7 +487,6 @@ allocated or deallocated in the program." > @@ -519,7 +494,6 @@ allocated or deallocated in the program." @@ -530,7 +504,6 @@ allocated or deallocated in the program." /> @@ -541,7 +514,6 @@ allocated or deallocated in the program." /> @@ -1029,7 +1001,6 @@ allocated or deallocated in the program." > @@ -1037,7 +1008,6 @@ allocated or deallocated in the program." @@ -1048,7 +1018,6 @@ allocated or deallocated in the program." /> @@ -1059,7 +1028,6 @@ allocated or deallocated in the program." /> @@ -1077,7 +1045,6 @@ allocated or deallocated in the program." > @@ -1085,7 +1052,6 @@ allocated or deallocated in the program." @@ -1096,7 +1062,6 @@ allocated or deallocated in the program." /> @@ -1107,7 +1072,6 @@ allocated or deallocated in the program." /> @@ -1125,7 +1089,6 @@ allocated or deallocated in the program." > @@ -1133,7 +1096,6 @@ allocated or deallocated in the program." @@ -1144,7 +1106,6 @@ allocated or deallocated in the program." /> @@ -1155,7 +1116,6 @@ allocated or deallocated in the program." /> @@ -1173,7 +1133,6 @@ allocated or deallocated in the program." > @@ -1181,7 +1140,6 @@ allocated or deallocated in the program." @@ -1192,7 +1150,6 @@ allocated or deallocated in the program." /> @@ -1203,7 +1160,6 @@ allocated or deallocated in the program." /> @@ -1221,7 +1177,6 @@ allocated or deallocated in the program." > @@ -1229,7 +1184,6 @@ allocated or deallocated in the program." @@ -1240,7 +1194,6 @@ allocated or deallocated in the program." /> @@ -1251,7 +1204,6 @@ allocated or deallocated in the program." /> @@ -1269,7 +1221,6 @@ allocated or deallocated in the program." > @@ -1277,7 +1228,6 @@ allocated or deallocated in the program." @@ -1288,7 +1238,6 @@ allocated or deallocated in the program." /> @@ -1299,7 +1248,6 @@ allocated or deallocated in the program." /> @@ -1317,7 +1265,6 @@ allocated or deallocated in the program." > @@ -1325,7 +1272,6 @@ allocated or deallocated in the program." @@ -1336,7 +1282,6 @@ allocated or deallocated in the program." /> @@ -1347,7 +1292,6 @@ allocated or deallocated in the program." /> @@ -1835,7 +1779,6 @@ allocated or deallocated in the program." > @@ -1843,7 +1786,6 @@ allocated or deallocated in the program." @@ -1854,7 +1796,6 @@ allocated or deallocated in the program." /> @@ -1865,7 +1806,6 @@ allocated or deallocated in the program." /> @@ -1883,7 +1823,6 @@ allocated or deallocated in the program." > @@ -1891,7 +1830,6 @@ allocated or deallocated in the program." @@ -1902,7 +1840,6 @@ allocated or deallocated in the program." /> @@ -1913,7 +1850,6 @@ allocated or deallocated in the program." /> @@ -1931,7 +1867,6 @@ allocated or deallocated in the program." > @@ -1939,7 +1874,6 @@ allocated or deallocated in the program." @@ -1950,7 +1884,6 @@ allocated or deallocated in the program." /> @@ -1961,7 +1894,6 @@ allocated or deallocated in the program." /> @@ -1979,7 +1911,6 @@ allocated or deallocated in the program." > @@ -1987,7 +1918,6 @@ allocated or deallocated in the program." @@ -1998,7 +1928,6 @@ allocated or deallocated in the program." /> @@ -2009,7 +1938,6 @@ allocated or deallocated in the program." /> @@ -2027,7 +1955,6 @@ allocated or deallocated in the program." > @@ -2035,7 +1962,6 @@ allocated or deallocated in the program." @@ -2046,7 +1972,6 @@ allocated or deallocated in the program." /> @@ -2057,7 +1982,6 @@ allocated or deallocated in the program." /> @@ -2075,7 +1999,6 @@ allocated or deallocated in the program." > @@ -2083,7 +2006,6 @@ allocated or deallocated in the program." @@ -2094,7 +2016,6 @@ allocated or deallocated in the program." /> @@ -2105,7 +2026,6 @@ allocated or deallocated in the program." /> @@ -2123,7 +2043,6 @@ allocated or deallocated in the program." > @@ -2131,7 +2050,6 @@ allocated or deallocated in the program." @@ -2142,7 +2060,6 @@ allocated or deallocated in the program." /> @@ -2153,7 +2070,6 @@ allocated or deallocated in the program." /> @@ -2629,7 +2545,6 @@ allocated or deallocated in the program." > @@ -2637,7 +2552,6 @@ allocated or deallocated in the program." @@ -2648,7 +2562,6 @@ allocated or deallocated in the program." /> @@ -2659,7 +2572,6 @@ allocated or deallocated in the program." /> @@ -2677,7 +2589,6 @@ allocated or deallocated in the program." > @@ -2685,7 +2596,6 @@ allocated or deallocated in the program." @@ -2696,7 +2606,6 @@ allocated or deallocated in the program." /> @@ -2707,7 +2616,6 @@ allocated or deallocated in the program." /> @@ -2725,7 +2633,6 @@ allocated or deallocated in the program." > @@ -2733,7 +2640,6 @@ allocated or deallocated in the program." @@ -2744,7 +2650,6 @@ allocated or deallocated in the program." /> @@ -2755,7 +2660,6 @@ allocated or deallocated in the program." /> @@ -2773,7 +2677,6 @@ allocated or deallocated in the program." > @@ -2781,7 +2684,6 @@ allocated or deallocated in the program." @@ -2792,7 +2694,6 @@ allocated or deallocated in the program." /> @@ -2803,7 +2704,6 @@ allocated or deallocated in the program." /> @@ -2821,7 +2721,6 @@ allocated or deallocated in the program." > @@ -2829,7 +2728,6 @@ allocated or deallocated in the program." @@ -2840,7 +2738,6 @@ allocated or deallocated in the program." /> @@ -2851,7 +2748,6 @@ allocated or deallocated in the program." /> @@ -2869,7 +2765,6 @@ allocated or deallocated in the program." > @@ -2877,7 +2772,6 @@ allocated or deallocated in the program." @@ -2888,7 +2782,6 @@ allocated or deallocated in the program." /> @@ -2899,7 +2792,6 @@ allocated or deallocated in the program." /> @@ -2917,7 +2809,6 @@ allocated or deallocated in the program." > @@ -2925,7 +2816,6 @@ allocated or deallocated in the program." @@ -2936,7 +2826,6 @@ allocated or deallocated in the program." /> @@ -2947,7 +2836,6 @@ allocated or deallocated in the program." /> @@ -3423,7 +3311,6 @@ allocated or deallocated in the program." > @@ -3431,7 +3318,6 @@ allocated or deallocated in the program." @@ -3442,7 +3328,6 @@ allocated or deallocated in the program." /> @@ -3453,7 +3338,6 @@ allocated or deallocated in the program." /> @@ -3471,7 +3355,6 @@ allocated or deallocated in the program." > @@ -3479,7 +3362,6 @@ allocated or deallocated in the program." @@ -3490,7 +3372,6 @@ allocated or deallocated in the program." /> @@ -3501,7 +3382,6 @@ allocated or deallocated in the program." /> @@ -3519,7 +3399,6 @@ allocated or deallocated in the program." > @@ -3527,7 +3406,6 @@ allocated or deallocated in the program." @@ -3538,7 +3416,6 @@ allocated or deallocated in the program." /> @@ -3549,7 +3426,6 @@ allocated or deallocated in the program." /> @@ -3567,7 +3443,6 @@ allocated or deallocated in the program." > @@ -3575,7 +3450,6 @@ allocated or deallocated in the program." @@ -3586,7 +3460,6 @@ allocated or deallocated in the program." /> @@ -3597,7 +3470,6 @@ allocated or deallocated in the program." /> @@ -3615,7 +3487,6 @@ allocated or deallocated in the program." > @@ -3623,7 +3494,6 @@ allocated or deallocated in the program." @@ -3634,7 +3504,6 @@ allocated or deallocated in the program." /> @@ -3645,7 +3514,6 @@ allocated or deallocated in the program." /> @@ -4478,7 +4346,6 @@ for understanding where time was actually spent in a program." > @@ -4486,7 +4353,6 @@ for understanding where time was actually spent in a program." @@ -4497,7 +4363,6 @@ for understanding where time was actually spent in a program." /> @@ -4508,7 +4373,6 @@ for understanding where time was actually spent in a program." /> @@ -4526,7 +4390,6 @@ for understanding where time was actually spent in a program." > @@ -4534,7 +4397,6 @@ for understanding where time was actually spent in a program." @@ -4545,7 +4407,6 @@ for understanding where time was actually spent in a program." /> @@ -4556,7 +4417,6 @@ for understanding where time was actually spent in a program." /> @@ -4574,7 +4434,6 @@ for understanding where time was actually spent in a program." > @@ -4582,7 +4441,6 @@ for understanding where time was actually spent in a program." @@ -4593,7 +4451,6 @@ for understanding where time was actually spent in a program." /> @@ -4604,7 +4461,6 @@ for understanding where time was actually spent in a program." /> @@ -4622,7 +4478,6 @@ for understanding where time was actually spent in a program." > @@ -4630,7 +4485,6 @@ for understanding where time was actually spent in a program." @@ -4641,7 +4495,6 @@ for understanding where time was actually spent in a program." /> @@ -4652,7 +4505,6 @@ for understanding where time was actually spent in a program." /> @@ -4670,7 +4522,6 @@ for understanding where time was actually spent in a program." > @@ -4678,7 +4529,6 @@ for understanding where time was actually spent in a program." @@ -4689,7 +4539,6 @@ for understanding where time was actually spent in a program." /> @@ -4700,7 +4549,6 @@ for understanding where time was actually spent in a program." /> @@ -4718,7 +4566,6 @@ for understanding where time was actually spent in a program." > @@ -4726,7 +4573,6 @@ for understanding where time was actually spent in a program." @@ -4737,7 +4583,6 @@ for understanding where time was actually spent in a program." /> @@ -4748,7 +4593,6 @@ for understanding where time was actually spent in a program." /> @@ -4766,7 +4610,6 @@ for understanding where time was actually spent in a program." > @@ -4774,7 +4617,6 @@ for understanding where time was actually spent in a program." @@ -4785,7 +4627,6 @@ for understanding where time was actually spent in a program." /> @@ -4796,7 +4637,6 @@ for understanding where time was actually spent in a program." /> @@ -5239,7 +5079,6 @@ for understanding where time was actually spent in a program." > @@ -5247,7 +5086,6 @@ for understanding where time was actually spent in a program." @@ -5258,7 +5096,6 @@ for understanding where time was actually spent in a program." /> @@ -5269,7 +5106,6 @@ for understanding where time was actually spent in a program." /> @@ -5287,7 +5123,6 @@ for understanding where time was actually spent in a program." > @@ -5295,7 +5130,6 @@ for understanding where time was actually spent in a program." @@ -5306,7 +5140,6 @@ for understanding where time was actually spent in a program." /> @@ -5317,7 +5150,6 @@ for understanding where time was actually spent in a program." /> @@ -5335,7 +5167,6 @@ for understanding where time was actually spent in a program." > @@ -5343,7 +5174,6 @@ for understanding where time was actually spent in a program." @@ -5354,7 +5184,6 @@ for understanding where time was actually spent in a program." /> @@ -5365,7 +5194,6 @@ for understanding where time was actually spent in a program." /> @@ -5383,7 +5211,6 @@ for understanding where time was actually spent in a program." > @@ -5391,7 +5218,6 @@ for understanding where time was actually spent in a program." @@ -5402,7 +5228,6 @@ for understanding where time was actually spent in a program." /> @@ -5413,7 +5238,6 @@ for understanding where time was actually spent in a program." /> @@ -5431,7 +5255,6 @@ for understanding where time was actually spent in a program." > @@ -5439,7 +5262,6 @@ for understanding where time was actually spent in a program." @@ -5450,7 +5272,6 @@ for understanding where time was actually spent in a program." /> @@ -5461,7 +5282,6 @@ for understanding where time was actually spent in a program." /> @@ -5479,7 +5299,6 @@ for understanding where time was actually spent in a program." > @@ -5487,7 +5306,6 @@ for understanding where time was actually spent in a program." @@ -5498,7 +5316,6 @@ for understanding where time was actually spent in a program." /> @@ -5509,7 +5326,6 @@ for understanding where time was actually spent in a program." /> @@ -5527,7 +5343,6 @@ for understanding where time was actually spent in a program." > @@ -5535,7 +5350,6 @@ for understanding where time was actually spent in a program." @@ -5546,7 +5360,6 @@ for understanding where time was actually spent in a program." /> @@ -5557,7 +5370,6 @@ for understanding where time was actually spent in a program." /> @@ -6000,7 +5812,6 @@ for understanding where time was actually spent in a program." > @@ -6008,7 +5819,6 @@ for understanding where time was actually spent in a program." @@ -6019,7 +5829,6 @@ for understanding where time was actually spent in a program." /> @@ -6030,7 +5839,6 @@ for understanding where time was actually spent in a program." /> @@ -6048,7 +5856,6 @@ for understanding where time was actually spent in a program." > @@ -6056,7 +5863,6 @@ for understanding where time was actually spent in a program." @@ -6067,7 +5873,6 @@ for understanding where time was actually spent in a program." /> @@ -6078,7 +5883,6 @@ for understanding where time was actually spent in a program." /> @@ -6096,7 +5900,6 @@ for understanding where time was actually spent in a program." > @@ -6104,7 +5907,6 @@ for understanding where time was actually spent in a program." @@ -6115,7 +5917,6 @@ for understanding where time was actually spent in a program." /> @@ -6126,7 +5927,6 @@ for understanding where time was actually spent in a program." /> @@ -6144,7 +5944,6 @@ for understanding where time was actually spent in a program." > @@ -6152,7 +5951,6 @@ for understanding where time was actually spent in a program." @@ -6163,7 +5961,6 @@ for understanding where time was actually spent in a program." /> @@ -6174,7 +5971,6 @@ for understanding where time was actually spent in a program." /> @@ -6533,7 +6329,6 @@ for understanding where time was actually spent in a program." > @@ -6541,7 +6336,6 @@ for understanding where time was actually spent in a program." @@ -6552,7 +6346,6 @@ for understanding where time was actually spent in a program." /> @@ -6563,7 +6356,6 @@ for understanding where time was actually spent in a program." /> @@ -6581,7 +6373,6 @@ for understanding where time was actually spent in a program." > @@ -6589,7 +6380,6 @@ for understanding where time was actually spent in a program." @@ -6600,7 +6390,6 @@ for understanding where time was actually spent in a program." /> @@ -6611,7 +6400,6 @@ for understanding where time was actually spent in a program." /> @@ -6629,7 +6417,6 @@ for understanding where time was actually spent in a program." > @@ -6637,7 +6424,6 @@ for understanding where time was actually spent in a program." @@ -6648,7 +6434,6 @@ for understanding where time was actually spent in a program." /> @@ -6659,7 +6444,6 @@ for understanding where time was actually spent in a program." /> @@ -6677,7 +6461,6 @@ for understanding where time was actually spent in a program." > @@ -6685,7 +6468,6 @@ for understanding where time was actually spent in a program." @@ -6696,7 +6478,6 @@ for understanding where time was actually spent in a program." /> @@ -6707,7 +6488,6 @@ for understanding where time was actually spent in a program." /> @@ -6725,7 +6505,6 @@ for understanding where time was actually spent in a program." > @@ -6733,7 +6512,6 @@ for understanding where time was actually spent in a program." @@ -6744,7 +6522,6 @@ for understanding where time was actually spent in a program." /> @@ -6755,7 +6532,6 @@ for understanding where time was actually spent in a program." /> @@ -6773,7 +6549,6 @@ for understanding where time was actually spent in a program." > @@ -6781,7 +6556,6 @@ for understanding where time was actually spent in a program." @@ -6792,7 +6566,6 @@ for understanding where time was actually spent in a program." /> @@ -6803,7 +6576,6 @@ for understanding where time was actually spent in a program." /> @@ -6821,7 +6593,6 @@ for understanding where time was actually spent in a program." > @@ -6829,7 +6600,6 @@ for understanding where time was actually spent in a program." @@ -6840,7 +6610,6 @@ for understanding where time was actually spent in a program." /> @@ -6851,7 +6620,6 @@ for understanding where time was actually spent in a program." /> @@ -7294,7 +7062,6 @@ for understanding where time was actually spent in a program." > @@ -7302,7 +7069,6 @@ for understanding where time was actually spent in a program." @@ -7313,7 +7079,6 @@ for understanding where time was actually spent in a program." /> @@ -7324,7 +7089,6 @@ for understanding where time was actually spent in a program." /> @@ -7342,7 +7106,6 @@ for understanding where time was actually spent in a program." > @@ -7350,7 +7113,6 @@ for understanding where time was actually spent in a program." @@ -7361,7 +7123,6 @@ for understanding where time was actually spent in a program." /> @@ -7372,7 +7133,6 @@ for understanding where time was actually spent in a program." /> @@ -7390,7 +7150,6 @@ for understanding where time was actually spent in a program." > @@ -7398,7 +7157,6 @@ for understanding where time was actually spent in a program." @@ -7409,7 +7167,6 @@ for understanding where time was actually spent in a program." /> @@ -7420,7 +7177,6 @@ for understanding where time was actually spent in a program." /> @@ -7438,7 +7194,6 @@ for understanding where time was actually spent in a program." > @@ -7446,7 +7201,6 @@ for understanding where time was actually spent in a program." @@ -7457,7 +7211,6 @@ for understanding where time was actually spent in a program." /> @@ -7468,7 +7221,6 @@ for understanding where time was actually spent in a program." /> @@ -7486,7 +7238,6 @@ for understanding where time was actually spent in a program." > @@ -7494,7 +7245,6 @@ for understanding where time was actually spent in a program." @@ -7505,7 +7255,6 @@ for understanding where time was actually spent in a program." /> @@ -7516,7 +7265,6 @@ for understanding where time was actually spent in a program." /> @@ -7534,7 +7282,6 @@ for understanding where time was actually spent in a program." > @@ -7542,7 +7289,6 @@ for understanding where time was actually spent in a program." @@ -7553,7 +7299,6 @@ for understanding where time was actually spent in a program." /> @@ -7564,7 +7309,6 @@ for understanding where time was actually spent in a program." /> @@ -7979,7 +7723,6 @@ for understanding where time was actually spent in a program." > @@ -7987,7 +7730,6 @@ for understanding where time was actually spent in a program." @@ -7998,7 +7740,6 @@ for understanding where time was actually spent in a program." /> @@ -8009,7 +7750,6 @@ for understanding where time was actually spent in a program." /> @@ -8027,7 +7767,6 @@ for understanding where time was actually spent in a program." > @@ -8035,7 +7774,6 @@ for understanding where time was actually spent in a program." @@ -8046,7 +7784,6 @@ for understanding where time was actually spent in a program." /> @@ -8057,7 +7794,6 @@ for understanding where time was actually spent in a program." /> @@ -8075,7 +7811,6 @@ for understanding where time was actually spent in a program." > @@ -8083,7 +7818,6 @@ for understanding where time was actually spent in a program." @@ -8094,7 +7828,6 @@ for understanding where time was actually spent in a program." /> @@ -8105,7 +7838,6 @@ for understanding where time was actually spent in a program." /> @@ -8123,7 +7855,6 @@ for understanding where time was actually spent in a program." > @@ -8131,7 +7862,6 @@ for understanding where time was actually spent in a program." @@ -8142,7 +7872,6 @@ for understanding where time was actually spent in a program." /> @@ -8153,7 +7882,6 @@ for understanding where time was actually spent in a program." /> @@ -8171,7 +7899,6 @@ for understanding where time was actually spent in a program." > @@ -8179,7 +7906,6 @@ for understanding where time was actually spent in a program." @@ -8190,7 +7916,6 @@ for understanding where time was actually spent in a program." /> @@ -8201,7 +7926,6 @@ for understanding where time was actually spent in a program." /> @@ -8219,7 +7943,6 @@ for understanding where time was actually spent in a program." > @@ -8227,7 +7950,6 @@ for understanding where time was actually spent in a program." @@ -8238,7 +7960,6 @@ for understanding where time was actually spent in a program." /> @@ -8249,7 +7970,6 @@ for understanding where time was actually spent in a program." /> @@ -8664,7 +8384,6 @@ for understanding where time was actually spent in a program." > @@ -8672,7 +8391,6 @@ for understanding where time was actually spent in a program." @@ -8683,7 +8401,6 @@ for understanding where time was actually spent in a program." /> @@ -8694,7 +8411,6 @@ for understanding where time was actually spent in a program." /> @@ -8712,7 +8428,6 @@ for understanding where time was actually spent in a program." > @@ -8720,7 +8435,6 @@ for understanding where time was actually spent in a program." @@ -8731,7 +8445,6 @@ for understanding where time was actually spent in a program." /> @@ -8742,7 +8455,6 @@ for understanding where time was actually spent in a program." /> @@ -8760,7 +8472,6 @@ for understanding where time was actually spent in a program." > @@ -8768,7 +8479,6 @@ for understanding where time was actually spent in a program." @@ -8779,7 +8489,6 @@ for understanding where time was actually spent in a program." /> @@ -8790,7 +8499,6 @@ for understanding where time was actually spent in a program." /> @@ -8808,7 +8516,6 @@ for understanding where time was actually spent in a program." > @@ -8816,7 +8523,6 @@ for understanding where time was actually spent in a program." @@ -8827,7 +8533,6 @@ for understanding where time was actually spent in a program." /> @@ -8838,7 +8543,6 @@ for understanding where time was actually spent in a program." /> @@ -9198,7 +8902,6 @@ for understanding where time was actually spent in a program." > @@ -9206,7 +8909,6 @@ for understanding where time was actually spent in a program." @@ -9217,7 +8919,6 @@ for understanding where time was actually spent in a program." /> @@ -9228,7 +8929,6 @@ for understanding where time was actually spent in a program." /> @@ -9246,7 +8946,6 @@ for understanding where time was actually spent in a program." > @@ -9254,7 +8953,6 @@ for understanding where time was actually spent in a program." @@ -9265,7 +8963,6 @@ for understanding where time was actually spent in a program." /> @@ -9276,7 +8973,6 @@ for understanding where time was actually spent in a program." /> @@ -9294,7 +8990,6 @@ for understanding where time was actually spent in a program." > @@ -9302,7 +8997,6 @@ for understanding where time was actually spent in a program." @@ -9313,7 +9007,6 @@ for understanding where time was actually spent in a program." /> @@ -9324,7 +9017,6 @@ for understanding where time was actually spent in a program." /> @@ -9342,7 +9034,6 @@ for understanding where time was actually spent in a program." > @@ -9350,7 +9041,6 @@ for understanding where time was actually spent in a program." @@ -9361,7 +9051,6 @@ for understanding where time was actually spent in a program." /> @@ -9372,7 +9061,6 @@ for understanding where time was actually spent in a program." /> @@ -9732,7 +9420,6 @@ for understanding where time was actually spent in a program." > @@ -9740,7 +9427,6 @@ for understanding where time was actually spent in a program." @@ -9751,7 +9437,6 @@ for understanding where time was actually spent in a program." /> @@ -9762,7 +9447,6 @@ for understanding where time was actually spent in a program." /> @@ -9780,7 +9464,6 @@ for understanding where time was actually spent in a program." > @@ -9788,7 +9471,6 @@ for understanding where time was actually spent in a program." @@ -9799,7 +9481,6 @@ for understanding where time was actually spent in a program." /> @@ -9810,7 +9491,6 @@ for understanding where time was actually spent in a program." /> @@ -9828,7 +9508,6 @@ for understanding where time was actually spent in a program." > @@ -9836,7 +9515,6 @@ for understanding where time was actually spent in a program." @@ -9847,7 +9525,6 @@ for understanding where time was actually spent in a program." /> @@ -9858,7 +9535,6 @@ for understanding where time was actually spent in a program." /> @@ -9876,7 +9552,6 @@ for understanding where time was actually spent in a program." > @@ -9884,7 +9559,6 @@ for understanding where time was actually spent in a program." @@ -9895,7 +9569,6 @@ for understanding where time was actually spent in a program." /> @@ -9906,7 +9579,6 @@ for understanding where time was actually spent in a program." /> @@ -9924,7 +9596,6 @@ for understanding where time was actually spent in a program." > @@ -9932,7 +9603,6 @@ for understanding where time was actually spent in a program." @@ -9943,7 +9613,6 @@ for understanding where time was actually spent in a program." /> @@ -9954,7 +9623,6 @@ for understanding where time was actually spent in a program." /> @@ -9972,7 +9640,6 @@ for understanding where time was actually spent in a program." > @@ -9980,7 +9647,6 @@ for understanding where time was actually spent in a program." @@ -9991,7 +9657,6 @@ for understanding where time was actually spent in a program." /> @@ -10002,7 +9667,6 @@ for understanding where time was actually spent in a program." /> From 185a6506c630c09300e7bdc942e68adcd0b5e2fa Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 22 Dec 2022 18:24:00 +0100 Subject: [PATCH 081/114] Remove extraneous if block --- src/components/shared/TreeView.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/shared/TreeView.js b/src/components/shared/TreeView.js index 17fb2fa5f7..b372806f84 100644 --- a/src/components/shared/TreeView.js +++ b/src/components/shared/TreeView.js @@ -551,9 +551,6 @@ export class TreeView extends React.PureComponent< const column = this.props.fixedColumns[columnIndex]; const fixedColumnWidths = this._getCurrentFixedColumnWidths(); const diff = event.clientX - lastX; - if (diff === 0) { - return; - } const newWidth = Math.max(initialWidth + diff, column.minWidth || 10); this.setState((prevState) => { this._stateCounter++; From 0a1fc2c4abd0bbcbaf4d166a00ec28f85723b563 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 22 Dec 2022 18:33:58 +0100 Subject: [PATCH 082/114] Fix the doubleclick gesture to reset the column width --- src/components/shared/TreeView.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/components/shared/TreeView.js b/src/components/shared/TreeView.js index b372806f84..115291fbbe 100644 --- a/src/components/shared/TreeView.js +++ b/src/components/shared/TreeView.js @@ -583,12 +583,12 @@ export class TreeView extends React.PureComponent< _onColumnWidthReset = (columnIndex: number) => { const column = this.props.fixedColumns[columnIndex]; - const fixedColumnWidths = - this.state.fixedColumnWidths || this.props.viewOptions.fixedColumnWidths; - if (fixedColumnWidths) { - fixedColumnWidths[columnIndex] = column.initialWidth || 10; - this._propagateColumnWidthChange(fixedColumnWidths); - } + const fixedColumnWidths = this._getCurrentFixedColumnWidths(); + const newFixedColumnWidths = fixedColumnWidths.slice(); + newFixedColumnWidths[columnIndex] = column.initialWidth || 10; + this._stateCounter++; + this.setState({ fixedColumnWidths: newFixedColumnWidths }); + this._propagateColumnWidthChange(newFixedColumnWidths); }; // triggers a re-render @@ -960,9 +960,7 @@ export class TreeView extends React.PureComponent< focusable={true} onKeyDown={this._onKeyDown} specialItems={this._getSpecialItems()} - disableOverscan={ - !!disableOverscan || this._currentMovedColumnState === null - } + disableOverscan={!!disableOverscan || isResizingColumns} onCopy={this._onCopy} // If there is a deep call node depth, expand the width, or else keep it // at 3000 wide. From 36f6a02a5e266dc71d53598cbbaec0e1d4e84e2b Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 22 Dec 2022 18:37:15 +0100 Subject: [PATCH 083/114] Use a double border for the dividers that are manipulable --- src/components/shared/TreeView.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/shared/TreeView.css b/src/components/shared/TreeView.css index 9c8d56d8f6..684def6524 100644 --- a/src/components/shared/TreeView.css +++ b/src/components/shared/TreeView.css @@ -106,6 +106,11 @@ content: ''; } +.treeViewColumnDivider.isResizable::before { + width: 1px; + border-left: 1px solid var(--grey-30); +} + .treeViewHeaderColumn.treeViewFixedColumn { /* The fixed columns in the row don't shrink because they're positioning using * position: sticky, therefore we prevent shrinking for the columns in the From 0a0df25deaa4dd38f412d498bec51081d47b85ab Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 22 Dec 2022 18:55:00 +0100 Subject: [PATCH 084/114] Rename some variables, simplify a few functions, move functions around and add comments --- src/components/shared/TreeView.js | 82 +++++++++++++++---------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/src/components/shared/TreeView.js b/src/components/shared/TreeView.js index 115291fbbe..1426c62e69 100644 --- a/src/components/shared/TreeView.js +++ b/src/components/shared/TreeView.js @@ -44,6 +44,9 @@ function PermissiveLocalized(props: React.ElementConfig) { // See https://github.com/facebook/flow/issues/4099 type RegExpResult = null | ({ index: number, input: string } & string[]); type NodeIndex = number; +type TableViewOptionsWithDefault = {| + fixedColumnWidths: Array, +|}; export type Column = {| +propName: string, @@ -70,7 +73,7 @@ export type MaybeResizableColumn = {| type TreeViewHeaderProps = {| +fixedColumns: MaybeResizableColumn[], +mainColumn: Column, - +viewOptions: TableViewOptions, + +viewOptions: TableViewOptionsWithDefault, // called when the users moves the divider right of the column, // passes the column index and the start x coordinate +onColumnWidthChangeStart: (number, CssPixels) => void, @@ -103,19 +106,12 @@ class TreeViewHeader extends React.PureComponent< return (
        {fixedColumns.map((col, i) => { - const style = - columnWidths || col.initialWidth - ? { - width: - (columnWidths ? columnWidths[i] : col.initialWidth) + - (col.headerWidthAdjustment || 0), - } - : {}; + const width = columnWidths[i] + (col.headerWidthAdjustment || 0); return ( @@ -192,7 +188,7 @@ type TreeViewRowFixedColumnsProps = {| +onClick: (NodeIndex, SyntheticMouseEvent<>) => mixed, +highlightRegExp: RegExp | null, +rowHeightStyle: { height: CssPixels, lineHeight: string }, - +viewOptions: TableViewOptions, + +viewOptions: TableViewOptionsWithDefault, |}; class TreeViewRowFixedColumns extends React.PureComponent< @@ -229,18 +225,12 @@ class TreeViewRowFixedColumns extends React.PureComponent< {columns.map((col, i) => { const RenderComponent = col.component; const text = displayData[col.propName] || ''; - const style = - columnWidths || col.initialWidth - ? { - width: columnWidths ? columnWidths[i] : col.initialWidth, - } - : {}; return ( {RenderComponent ? ( @@ -483,16 +473,25 @@ export class TreeView extends React.PureComponent< > { _list: VirtualList | null = null; _takeListRef = (list: VirtualList | null) => (this._list = list); + + // This contains the information about the current column resizing happening currently. _currentMovedColumnState: {| columnIndex: number, - lastX: CssPixels, + startX: CssPixels, initialWidth: CssPixels, |} | null = null; + state = { + // This contains the current widths, while or after the user resizes them. fixedColumnWidths: null, + + // This is true when the user is currently resizing a column. isResizingColumns: false, }; - _stateCounter: number = 0; + + // This is incremented when a column changed its size. We use this to force a + // rerender of the VirtualList component. + _columnSizeChangedCounter: number = 0; // The tuple `specialItems` always contains 2 elements: the first element is // the selected node id (if any), and the second element is the right clicked @@ -514,29 +513,30 @@ export class TreeView extends React.PureComponent< { limit: 1 } ); + // This returns the column widths from several possible sources, in this order: + // * the current state (this means the user changed them recently, or is + // currently changing them) + // * the view options (this comes from the redux state, this means the user + // changed them in the past) + // * or finally the initial values from the fixedColumns information. _getCurrentFixedColumnWidths = (): Array => { - const widths = + return ( this.state.fixedColumnWidths || this.props.viewOptions.fixedColumnWidths || - this.props.fixedColumns.map((c) => c.initialWidth); - if (widths === undefined) { - throw new Error('The fixed column widths should be defined.'); - } - return widths; + this.props.fixedColumns.map((c) => c.initialWidth) + ); }; - _getCurrentViewOptions = (): TableViewOptions => { - const widths = this._getCurrentFixedColumnWidths(); + _getCurrentViewOptions = (): TableViewOptionsWithDefault => { return { - ...this.props.viewOptions, - fixedColumnWidths: widths, + fixedColumnWidths: this._getCurrentFixedColumnWidths(), }; }; _onColumnWidthChangeStart = (columnIndex: number, startX: CssPixels) => { this._currentMovedColumnState = { columnIndex, - lastX: startX, + startX, initialWidth: this._getCurrentFixedColumnWidths()[columnIndex], }; this.setState({ isResizingColumns: true }); @@ -544,16 +544,21 @@ export class TreeView extends React.PureComponent< window.addEventListener('mouseup', this._onColumnWidthChangeMouseUp); }; + _cleanUpMouseHandlers = () => { + window.removeEventListener('mousemove', this._onColumnWidthChangeMouseMove); + window.removeEventListener('mouseup', this._onColumnWidthChangeMouseUp); + }; + _onColumnWidthChangeMouseMove = (event: MouseEvent) => { const columnState = this._currentMovedColumnState; if (columnState !== null) { - const { columnIndex, lastX, initialWidth } = columnState; + const { columnIndex, startX, initialWidth } = columnState; const column = this.props.fixedColumns[columnIndex]; const fixedColumnWidths = this._getCurrentFixedColumnWidths(); - const diff = event.clientX - lastX; + const diff = event.clientX - startX; const newWidth = Math.max(initialWidth + diff, column.minWidth || 10); this.setState((prevState) => { - this._stateCounter++; + this._columnSizeChangedCounter++; const newFixedColumnWidths = ( prevState.fixedColumnWidths || fixedColumnWidths ).slice(); @@ -565,11 +570,6 @@ export class TreeView extends React.PureComponent< } }; - _cleanUpMouseHandlers = () => { - window.removeEventListener('mousemove', this._onColumnWidthChangeMouseMove); - window.removeEventListener('mouseup', this._onColumnWidthChangeMouseUp); - }; - _onColumnWidthChangeMouseUp = () => { this.setState({ isResizingColumns: false }); this._cleanUpMouseHandlers(); @@ -586,7 +586,7 @@ export class TreeView extends React.PureComponent< const fixedColumnWidths = this._getCurrentFixedColumnWidths(); const newFixedColumnWidths = fixedColumnWidths.slice(); newFixedColumnWidths[columnIndex] = column.initialWidth || 10; - this._stateCounter++; + this._columnSizeChangedCounter++; this.setState({ fixedColumnWidths: newFixedColumnWidths }); this._propagateColumnWidthChange(newFixedColumnWidths); }; @@ -966,7 +966,7 @@ export class TreeView extends React.PureComponent< // at 3000 wide. containerWidth={Math.max(3000, maxNodeDepth * 10 + 2000)} ref={this._takeListRef} - forceRender={this._stateCounter} + forceRender={this._columnSizeChangedCounter} /> {contextMenu} From e9fb4cf35349546bcc4cea940e8a040ec6790d7d Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 22 Dec 2022 19:51:10 +0100 Subject: [PATCH 085/114] Memoize the initial widths so that we don't get a new array at each render --- src/components/shared/TreeView.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/shared/TreeView.js b/src/components/shared/TreeView.js index 1426c62e69..72a3fbd2f0 100644 --- a/src/components/shared/TreeView.js +++ b/src/components/shared/TreeView.js @@ -513,6 +513,11 @@ export class TreeView extends React.PureComponent< { limit: 1 } ); + _computeInitialColumnWidthsMemoized = memoize( + (fixedColumns: Array>): CssPixels[] => + fixedColumns.map((c) => c.initialWidth) + ); + // This returns the column widths from several possible sources, in this order: // * the current state (this means the user changed them recently, or is // currently changing them) @@ -523,7 +528,7 @@ export class TreeView extends React.PureComponent< return ( this.state.fixedColumnWidths || this.props.viewOptions.fixedColumnWidths || - this.props.fixedColumns.map((c) => c.initialWidth) + this._computeInitialColumnWidthsMemoized(this.props.fixedColumns) ); }; From e938fd487791be0a3150cc0d02d56dce48bf7dcb Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 22 Dec 2022 19:35:54 +0100 Subject: [PATCH 086/114] Add a test --- src/test/components/MarkerTable.test.js | 59 ++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/src/test/components/MarkerTable.test.js b/src/test/components/MarkerTable.test.js index ba67e6a2d7..2d70401c1c 100644 --- a/src/test/components/MarkerTable.test.js +++ b/src/test/components/MarkerTable.test.js @@ -9,7 +9,11 @@ import { stripIndent } from 'common-tags'; // This module is mocked. import copy from 'copy-to-clipboard'; -import { render, screen } from 'firefox-profiler/test/fixtures/testing-library'; +import { + render, + screen, + fireEvent, +} from 'firefox-profiler/test/fixtures/testing-library'; import { MarkerTable } from '../../components/marker-table'; import { MaybeMarkerContextMenu } from '../../components/shared/MarkerContextMenu'; import { @@ -19,6 +23,7 @@ import { hideLocalTrack, selectTrackWithModifiers, } from '../../actions/profile-view'; +import { changeSelectedTab } from 'firefox-profiler/actions/app'; import { ensureExists } from '../../utils/flow'; import { getEmptyThread } from 'firefox-profiler/profile-logic/data-structures'; @@ -420,6 +425,58 @@ describe('MarkerTable', function () { expect(screen.queryByText(/Select the/)).not.toBeInTheDocument(); }); }); + + describe('column resizing', () => { + it('can resize a column, then move it back to its initial size', () => { + const store = storeWithProfile(getMarkerTableProfile()); + store.dispatch(changeSelectedTab('marker-table')); + const { unmount } = render( + + + + ); + + let dividerForFirstColumn = ensureExists( + document.querySelector('.treeViewColumnDivider') + ); + let firstColumn = screen.getByText('Start'); + expect(firstColumn).toHaveStyle({ width: '90px' }); + fireEvent.mouseDown(dividerForFirstColumn, { clientX: 90 }); + + const body = ensureExists(document.body); + + // Move right + fireEvent.mouseMove(body, { clientX: 100 }); + expect(firstColumn).toHaveStyle({ width: '100px' }); + + // Move left + fireEvent.mouseMove(body, { clientX: 80 }); + expect(firstColumn).toHaveStyle({ width: '80px' }); + + // Release the mouse -> still the same style + fireEvent.mouseUp(body); + expect(firstColumn).toHaveStyle({ width: '80px' }); + + // Now we'll unmount and render again. + unmount(); + render( + + + + ); + + // Make sure the first column kept its width + firstColumn = screen.getByText('Start'); + expect(firstColumn).toHaveStyle({ width: '80px' }); + + // Now double click to reset the style. + dividerForFirstColumn = ensureExists( + document.querySelector('.treeViewColumnDivider') + ); + fireEvent.dblClick(dividerForFirstColumn, { detail: 2 }); + expect(firstColumn).toHaveStyle({ width: '90px' }); + }); + }); }); function getReflowMarker( From ab05d5a78042f5ac7afe0abc635ac507676c4411 Mon Sep 17 00:00:00 2001 From: "Francesco Lodolo [:flod]" Date: Fri, 23 Dec 2022 08:16:05 +0000 Subject: [PATCH 087/114] Pontoon: Update Interlingua (ia) localization of Firefox Profiler Co-authored-by: Francesco Lodolo [:flod] --- locales/ia/app.ftl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/ia/app.ftl b/locales/ia/app.ftl index 68772a4038..75a41448d5 100644 --- a/locales/ia/app.ftl +++ b/locales/ia/app.ftl @@ -278,8 +278,8 @@ Home--load-files-from-other-tools = { -profiler-brand-name } pote alsi importar profilos de altere profilatores, tal como Linux perf, Android SimplePerf, Chrome performance panel, Android Studio, o - ulle file que usa le formato dhat. Apprende a scriber tu - proprie importator. + ulle file que usa le formato dhat. Apprende a scriber tu + proprie importator. ## IdleSearchField ## The component that is used for all the search inputs in the application. From eabe27938347b1fa7dbe16208b417d58335571f0 Mon Sep 17 00:00:00 2001 From: Khairul Azhar Kasmiran Date: Fri, 23 Dec 2022 21:56:35 +0800 Subject: [PATCH 088/114] Add development note on Flow (PR #4391) --- CONTRIBUTING.md | 2 ++ README.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 781a3aa6dc..b33925edd9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -44,6 +44,8 @@ To get started clone the repo and get the web application started. 5. Point your browser to [http://localhost:4242](http://localhost:4242). 6. If port `4242` is taken, then you can run the web app on a different port: `FX_PROFILER_PORT=1234 yarn start` +[Flow](https://flow.org/) is used for type checking. VSCode users can install the ["Flow Language Support" extension](https://marketplace.visualstudio.com/items?itemName=flowtype.flow-for-vscode), and disable VSCode's built-in TypeScript extension in the workspace via the [setup instructions here](https://github.com/flow/flow-for-vscode#setup). + ## Using Gitpod Alternatively, you can also develop the Firefox Profiler online in a pre-configured development environment: diff --git a/README.md b/README.md index df2ebbd1cf..c34e33a2cc 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,8 @@ yarn install yarn start ``` +[Flow](https://flow.org/) is used for type checking. VSCode users can install the ["Flow Language Support" extension](https://marketplace.visualstudio.com/items?itemName=flowtype.flow-for-vscode), and disable VSCode's built-in TypeScript extension in the workspace via the [setup instructions here](https://github.com/flow/flow-for-vscode#setup). + You can also develop the Firefox Profiler online in a pre-configured development environment. [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/firefox-devtools/profiler) From d8e1057d43b05af62d625831d3cb9db780ba378f Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Fri, 23 Dec 2022 15:39:20 +0100 Subject: [PATCH 089/114] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Update=20@codemirr?= =?UTF-8?q?or/language=20to=20version=206.3.2=20(PR=20#4390)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 6ef071407a..c701143253 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "@codemirror/lang-cpp": "^6.0.2", "@codemirror/lang-javascript": "^6.1.2", "@codemirror/lang-rust": "^6.0.1", - "@codemirror/language": "^6.3.1", + "@codemirror/language": "^6.3.2", "@codemirror/state": "^6.1.4", "@codemirror/view": "^6.7.1", "@firefox-devtools/react-contextmenu": "^5.1.0", diff --git a/yarn.lock b/yarn.lock index be6da3b612..435f659341 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1094,10 +1094,10 @@ "@codemirror/language" "^6.0.0" "@lezer/rust" "^1.0.0" -"@codemirror/language@^6.0.0", "@codemirror/language@^6.3.1": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.3.1.tgz#1d61f33aa5de9aa74a713ee1f5ce600adc74df6b" - integrity sha512-MK+G1QKaGfSEUg9YEFaBkMBI6j1ge4VMBPZv9fDYotw7w695c42x5Ba1mmwBkesYnzYFBfte6Hh9TDcKa6xORQ== +"@codemirror/language@^6.0.0", "@codemirror/language@^6.3.2": + version "6.3.2" + resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.3.2.tgz#a3d5796d17a2cd3110bac0f5126db67c7e90a0f3" + integrity sha512-g42uHhOcEMAXjmozGG+rdom5UsbyfMxQFh7AbkeoaNImddL6Xt4cQDL0+JxmG7+as18rUAvZaqzP/TjsciVIrA== dependencies: "@codemirror/state" "^6.0.0" "@codemirror/view" "^6.0.0" From fa4bed6f50ed5ea9b44d39a653ce76e8a9e7e123 Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Fri, 30 Dec 2022 18:25:58 +0000 Subject: [PATCH 090/114] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Update=20query-str?= =?UTF-8?q?ing=20to=20version=208.1.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- yarn.lock | 44 +++++++++++++++++++------------------------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index c701143253..2c8d6c7c62 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "mixedtuplemap": "^1.0.0", "namedtuplemap": "^1.0.0", "photon-colors": "^3.3.2", - "query-string": "^7.1.3", + "query-string": "^8.1.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-intersection-observer": "^9.4.1", diff --git a/yarn.lock b/yarn.lock index 435f659341..9554b20d53 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4135,10 +4135,10 @@ decode-named-character-reference@^1.0.0: dependencies: character-entities "^2.0.0" -decode-uri-component@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" - integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== +decode-uri-component@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.4.1.tgz#2ac4859663c704be22bf7db760a1494a49ab2cc5" + integrity sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ== decompress-response@^6.0.0: version "6.0.0" @@ -5195,10 +5195,10 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -filter-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" - integrity sha1-mzERErxsYSehbgFsbF1/GeCAXFs= +filter-obj@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-5.1.0.tgz#5bd89676000a713d7db2e197f660274428e524ed" + integrity sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng== finalhandler@1.2.0: version "1.2.0" @@ -9994,15 +9994,14 @@ qs@6.10.3, qs@^6.5.2: dependencies: side-channel "^1.0.4" -query-string@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" - integrity sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg== +query-string@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-8.1.0.tgz#e7f95367737219544cd360a11a4f4ca03836e115" + integrity sha512-BFQeWxJOZxZGix7y+SByG3F36dA0AbTy9o6pSmKFcFz7DAj0re9Frkty3saBn3nHo3D0oZJ/+rx3r8H8r8Jbpw== dependencies: - decode-uri-component "^0.2.2" - filter-obj "^1.1.0" - split-on-first "^1.0.0" - strict-uri-encode "^2.0.0" + decode-uri-component "^0.4.1" + filter-obj "^5.1.0" + split-on-first "^3.0.0" querystring@0.2.0: version "0.2.0" @@ -11195,10 +11194,10 @@ spdy@^4.0.2: select-hose "^2.0.0" spdy-transport "^3.0.0" -split-on-first@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" - integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== +split-on-first@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-3.0.0.tgz#f04959c9ea8101b9b0bbf35a61b9ebea784a23e7" + integrity sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA== split-transform-stream@0.1.1: version "0.1.1" @@ -11288,11 +11287,6 @@ streaming-json-stringify@3: json-stringify-safe "5" readable-stream "2" -strict-uri-encode@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" - integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= - string-length@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.1.tgz#4a973bf31ef77c4edbceadd6af2611996985f8a1" From 99cd850d648e6d6c537883e6fc7b39366e58ce59 Mon Sep 17 00:00:00 2001 From: Dzmitry Date: Sat, 31 Dec 2022 16:10:33 +0000 Subject: [PATCH 091/114] Pontoon: Update Belarusian (be) localization of Firefox Profiler Co-authored-by: Dzmitry --- locales/be/app.ftl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/locales/be/app.ftl b/locales/be/app.ftl index c8420d3f0d..fdc4f76287 100644 --- a/locales/be/app.ftl +++ b/locales/be/app.ftl @@ -15,6 +15,7 @@ ## The following feature names must be treated as a brand. They cannot be translated. -firefox-brand-name = Firefox +-firefox-android-brand-name = Firefox для Android -profiler-brand-name = Firefox Profiler -profiler-brand-short-name = Profiler -firefox-nightly-brand-name = Firefox Nightly @@ -138,7 +139,6 @@ Home--menu-button = Уключыць кнопку меню { -profiler-brand-nam Home--menu-button-instructions = Уключыце кнопку меню прафайлера, каб пачаць запіс профілю прадукцыйнасці у { -firefox-brand-name }, затым прааналізуйце яго і падзяліцеся з profiler.firefox.com. -Home--instructions-title = Як праглядаць і запісваць профілі Home--instructions-content = Для запісу профіляў прадукцыйнасці патрабуецца { -firefox-brand-name }. Аднак існуючыя профілі можна праглядаць у любым сучасным браўзеры. @@ -314,6 +314,7 @@ MenuButtons--metaOverheadStatistics-profiled-duration = Працягласць ## Publish panel ## These strings are used in the publishing panel. +MenuButtons--publish--renderCheckbox-label-include-other-tabs = Уключыць даныя з іншых картак MenuButtons--publish--renderCheckbox-label-extension = Уключыць інфармацыю аб пашырэнні MenuButtons--publish--renderCheckbox-label-private-browsing = Уключыць даныя з вокнаў прыватнага прагляду MenuButtons--publish--renderCheckbox-label-private-browsing-warning-image = @@ -448,8 +449,12 @@ TrackContextMenu--hide-track = Схаваць “{ $trackName }” ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. ## TrackSearchField From e26ececef92e6e57a94ff580a921583cddd02ae5 Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 12:56:23 +0100 Subject: [PATCH 092/114] Update all development Yarn dependencies (2022-12-26) (PR #4394) Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com> --- package.json | 6 +++--- yarn.lock | 28 ++++++++++++++-------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index c701143253..044964ede2 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,7 @@ "codecov": "^3.8.3", "copy-webpack-plugin": "^11.0.0", "cross-env": "^7.0.3", - "css-loader": "^6.7.2", + "css-loader": "^6.7.3", "cssnano": "^5.1.14", "devtools-license-check": "^0.9.0", "eslint": "^8.29.0", @@ -122,7 +122,7 @@ "eslint-import-resolver-alias": "^1.1.2", "eslint-plugin-flowtype": "^8.0.3", "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jest": "^27.1.6", + "eslint-plugin-jest": "^27.1.7", "eslint-plugin-jest-dom": "^4.0.3", "eslint-plugin-jest-formatting": "^3.1.0", "eslint-plugin-prettier": "^4.2.1", @@ -148,7 +148,7 @@ "npm-run-all": "^4.1.5", "postcss": "^8.4.20", "postcss-loader": "^7.0.2", - "prettier": "^2.8.0", + "prettier": "^2.8.1", "raw-loader": "^4.0.2", "rimraf": "^3.0.2", "style-loader": "^3.3.1", diff --git a/yarn.lock b/yarn.lock index 435f659341..5436f8581d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3906,13 +3906,13 @@ css-functions-list@^3.1.0: resolved "https://registry.yarnpkg.com/css-functions-list/-/css-functions-list-3.1.0.tgz#cf5b09f835ad91a00e5959bcfc627cd498e1321b" integrity sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w== -css-loader@^6.7.2: - version "6.7.2" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.2.tgz#26bc22401b5921686a10fbeba75d124228302304" - integrity sha512-oqGbbVcBJkm8QwmnNzrFrWTnudnRZC+1eXikLJl0n4ljcfotgRifpg2a1lKy8jTrc4/d9A/ap1GFq1jDKG7J+Q== +css-loader@^6.7.3: + version "6.7.3" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.3.tgz#1e8799f3ccc5874fdd55461af51137fcc5befbcd" + integrity sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ== dependencies: icss-utils "^5.1.0" - postcss "^8.4.18" + postcss "^8.4.19" postcss-modules-extract-imports "^3.0.0" postcss-modules-local-by-default "^4.0.0" postcss-modules-scope "^3.0.0" @@ -4684,10 +4684,10 @@ eslint-plugin-jest-formatting@^3.1.0: resolved "https://registry.yarnpkg.com/eslint-plugin-jest-formatting/-/eslint-plugin-jest-formatting-3.1.0.tgz#b26dd5a40f432b642dcc880021a771bb1c93dcd2" integrity sha512-XyysraZ1JSgGbLSDxjj5HzKKh0glgWf+7CkqxbTqb7zEhW7X2WHo5SBQ8cGhnszKN+2Lj3/oevBlHNbHezoc/A== -eslint-plugin-jest@^27.1.6: - version "27.1.6" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.1.6.tgz#361d943f07d1978838e6b852c44a579f3879e332" - integrity sha512-XA7RFLSrlQF9IGtAmhddkUkBuICCTuryfOTfCSWcZHiHb69OilIH05oozH2XA6CEOtztnOd0vgXyvxZodkxGjg== +eslint-plugin-jest@^27.1.7: + version "27.1.7" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.1.7.tgz#0351e904afb8d66b7f70452929556dfdc8daba0d" + integrity sha512-0QVzf+og4YI1Qr3UoprkqqhezAZjFffdi62b0IurkCXMqPtRW84/UT4CKsYT80h/D82LA9avjO/80Ou1LdgbaQ== dependencies: "@typescript-eslint/utils" "^5.10.0" @@ -9793,7 +9793,7 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.3.11, postcss@^8.4.18, postcss@^8.4.19, postcss@^8.4.20: +postcss@^8.3.11, postcss@^8.4.19, postcss@^8.4.20: version "8.4.20" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.20.tgz#64c52f509644cecad8567e949f4081d98349dc56" integrity sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g== @@ -9824,10 +9824,10 @@ prettier@^1.19.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== -prettier@^2.0.5, prettier@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.0.tgz#c7df58393c9ba77d6fba3921ae01faf994fb9dc9" - integrity sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA== +prettier@^2.0.5, prettier@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.1.tgz#4e1fd11c34e2421bc1da9aea9bd8127cd0a35efc" + integrity sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg== pretty-bytes@^5.3.0, pretty-bytes@^5.4.1: version "5.6.0" From baec1b5fd6a35c657154a4b6751420446287990f Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 15:57:56 +0100 Subject: [PATCH 093/114] Update all development Yarn dependencies (2023-01-03) (PR #4398) Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com> --- package.json | 10 +-- yarn.lock | 241 +++++++++++++++++++++++++++------------------------ 2 files changed, 132 insertions(+), 119 deletions(-) diff --git a/package.json b/package.json index 044964ede2..b41b478ca8 100644 --- a/package.json +++ b/package.json @@ -92,15 +92,15 @@ "workbox-window": "^6.5.4" }, "devDependencies": { - "@babel/cli": "^7.19.3", - "@babel/core": "^7.20.5", + "@babel/cli": "^7.20.7", + "@babel/core": "^7.20.7", "@babel/eslint-parser": "^7.19.1", "@babel/eslint-plugin": "^7.19.1", "@babel/plugin-proposal-class-properties": "^7.18.6", "@babel/preset-env": "^7.20.2", "@babel/preset-flow": "^7.18.6", "@babel/preset-react": "^7.18.6", - "@testing-library/dom": "^8.19.0", + "@testing-library/dom": "^8.19.1", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "alex": "^11.0.0", @@ -117,7 +117,7 @@ "css-loader": "^6.7.3", "cssnano": "^5.1.14", "devtools-license-check": "^0.9.0", - "eslint": "^8.29.0", + "eslint": "^8.30.0", "eslint-config-prettier": "^8.5.0", "eslint-import-resolver-alias": "^1.1.2", "eslint-plugin-flowtype": "^8.0.3", @@ -142,7 +142,7 @@ "jest-extended": "^3.2.0", "json-loader": "^0.5.7", "local-web-server": "^5.2.1", - "lockfile-lint": "^4.9.6", + "lockfile-lint": "^4.10.0", "mkdirp": "^1.0.4", "node-fetch": "^2.6.7", "npm-run-all": "^4.1.5", diff --git a/yarn.lock b/yarn.lock index 5436f8581d..da1f2a89ae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -31,10 +31,10 @@ jsonpointer "^5.0.0" leven "^3.1.0" -"@babel/cli@^7.19.3": - version "7.19.3" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.19.3.tgz#55914ed388e658e0b924b3a95da1296267e278e2" - integrity sha512-643/TybmaCAe101m2tSVHi9UKpETXP9c/Ff4mD2tAwkdP6esKIfaauZFc67vGEM6r9fekbEGid+sZhbEnSe3dg== +"@babel/cli@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.20.7.tgz#8fc12e85c744a1a617680eacb488fab1fcd35b7c" + integrity sha512-WylgcELHB66WwQqItxNILsMlaTd8/SO6SgTTjMp4uCI7P4QyH1r3nqgFmO3BfM4AtfniHgFMH3EpYFj/zynBkQ== dependencies: "@jridgewell/trace-mapping" "^0.3.8" commander "^4.0.1" @@ -54,26 +54,26 @@ dependencies: "@babel/highlight" "^7.18.6" -"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.0", "@babel/compat-data@^7.20.1": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.1.tgz#f2e6ef7790d8c8dbf03d379502dcc246dcce0b30" - integrity sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ== +"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.1", "@babel/compat-data@^7.20.5": + version "7.20.10" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.10.tgz#9d92fa81b87542fff50e848ed585b4212c1d34ec" + integrity sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg== -"@babel/core@^7.0.0", "@babel/core@^7.11.1", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.20.5": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.5.tgz#45e2114dc6cd4ab167f81daf7820e8fa1250d113" - integrity sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ== +"@babel/core@^7.0.0", "@babel/core@^7.11.1", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.7.tgz#37072f951bd4d28315445f66e0ec9f6ae0c8c35f" + integrity sha512-t1ZjCluspe5DW24bn2Rr1CDb2v9rn/hROtg9a2tmd0+QYf4bsloYfLQzjG4qHPNMhWtKdGC33R5AxGR2Af2cBw== dependencies: "@ampproject/remapping" "^2.1.0" "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.5" - "@babel/helper-compilation-targets" "^7.20.0" - "@babel/helper-module-transforms" "^7.20.2" - "@babel/helpers" "^7.20.5" - "@babel/parser" "^7.20.5" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.5" - "@babel/types" "^7.20.5" + "@babel/generator" "^7.20.7" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-module-transforms" "^7.20.7" + "@babel/helpers" "^7.20.7" + "@babel/parser" "^7.20.7" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.7" + "@babel/types" "^7.20.7" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -96,12 +96,12 @@ dependencies: eslint-rule-composer "^0.3.0" -"@babel/generator@^7.20.5", "@babel/generator@^7.7.2": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.5.tgz#cb25abee3178adf58d6814b68517c62bdbfdda95" - integrity sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA== +"@babel/generator@^7.20.7", "@babel/generator@^7.7.2": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.7.tgz#f8ef57c8242665c5929fe2e8d82ba75460187b4a" + integrity sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw== dependencies: - "@babel/types" "^7.20.5" + "@babel/types" "^7.20.7" "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" @@ -120,14 +120,15 @@ "@babel/helper-explode-assignable-expression" "^7.18.6" "@babel/types" "^7.18.6" -"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.0": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz#6bf5374d424e1b3922822f1d9bdaa43b1a139d0a" - integrity sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ== +"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.0", "@babel/helper-compilation-targets@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz#a6cd33e93629f5eb473b021aac05df62c4cd09bb" + integrity sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ== dependencies: - "@babel/compat-data" "^7.20.0" + "@babel/compat-data" "^7.20.5" "@babel/helper-validator-option" "^7.18.6" browserslist "^4.21.3" + lru-cache "^5.1.1" semver "^6.3.0" "@babel/helper-create-class-features-plugin@^7.18.6": @@ -204,19 +205,19 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.6", "@babel/helper-module-transforms@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz#ac53da669501edd37e658602a21ba14c08748712" - integrity sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA== +"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.6", "@babel/helper-module-transforms@^7.20.7": + version "7.20.11" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz#df4c7af713c557938c50ea3ad0117a7944b2f1b0" + integrity sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg== dependencies: "@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-module-imports" "^7.18.6" "@babel/helper-simple-access" "^7.20.2" "@babel/helper-split-export-declaration" "^7.18.6" "@babel/helper-validator-identifier" "^7.19.1" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.1" - "@babel/types" "^7.20.2" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.10" + "@babel/types" "^7.20.7" "@babel/helper-optimise-call-expression@^7.18.6": version "7.18.6" @@ -297,14 +298,14 @@ "@babel/traverse" "^7.18.11" "@babel/types" "^7.18.10" -"@babel/helpers@^7.20.5": - version "7.20.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.6.tgz#e64778046b70e04779dfbdf924e7ebb45992c763" - integrity sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w== +"@babel/helpers@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.7.tgz#04502ff0feecc9f20ecfaad120a18f011a8e6dce" + integrity sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA== dependencies: - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.5" - "@babel/types" "^7.20.5" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.7" + "@babel/types" "^7.20.7" "@babel/highlight@^7.18.6", "@babel/highlight@^7.9.0": version "7.18.6" @@ -315,10 +316,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.18.10", "@babel/parser@^7.20.5", "@babel/parser@^7.7.0": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.5.tgz#7f3c7335fe417665d929f34ae5dceae4c04015e8" - integrity sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.7.0": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.7.tgz#66fe23b3c8569220817d5feb8b9dcdc95bb4f71b" + integrity sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" @@ -1016,35 +1017,35 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.18.10", "@babel/template@^7.3.3": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" - integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== +"@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.3.3": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" + integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== dependencies: "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.18.10" - "@babel/types" "^7.18.10" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" -"@babel/traverse@^7.18.11", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1", "@babel/traverse@^7.20.5", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.5.tgz#78eb244bea8270fdda1ef9af22a5d5e5b7e57133" - integrity sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ== +"@babel/traverse@^7.18.11", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.10", "@babel/traverse@^7.20.7", "@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2": + version "7.20.10" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.10.tgz#2bf98239597fcec12f842756f186a9dde6d09230" + integrity sha512-oSf1juCgymrSez8NI4A2sr4+uB/mFd9MXplYGPEBnfAuWmmyeVcHa6xLPiaRBcXkcb/28bgxmQLTVwFKE1yfsg== dependencies: "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.5" + "@babel/generator" "^7.20.7" "@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-function-name" "^7.19.0" "@babel/helper-hoist-variables" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.20.5" - "@babel/types" "^7.20.5" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.5.tgz#e206ae370b5393d94dfd1d04cd687cace53efa84" - integrity sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg== +"@babel/types@^7.0.0", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.2", "@babel/types@^7.20.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f" + integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg== dependencies: "@babel/helper-string-parser" "^7.19.4" "@babel/helper-validator-identifier" "^7.19.1" @@ -1139,15 +1140,15 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@eslint/eslintrc@^1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.3.tgz#2b044ab39fdfa75b4688184f9e573ce3c5b0ff95" - integrity sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg== +"@eslint/eslintrc@^1.4.0": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e" + integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA== dependencies: ajv "^6.12.4" debug "^4.3.2" espree "^9.4.0" - globals "^13.15.0" + globals "^13.19.0" ignore "^5.2.0" import-fresh "^3.2.1" js-yaml "^4.1.0" @@ -1185,10 +1186,10 @@ resolved "https://registry.yarnpkg.com/@fluent/sequence/-/sequence-0.7.0.tgz#2fbfa872e87293cca209ba4a586d1a8fbaa2e5c4" integrity sha512-aH1xMwX8DFvKOQSKUKpB3zMsnJ2rRKt7MajLNnx/r3V3DWDo2nzEfm21d7UyOgwEckPIjPmhxdW1MEmsGUxYIw== -"@humanwhocodes/config-array@^0.11.6": - version "0.11.7" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.7.tgz#38aec044c6c828f6ed51d5d7ae3d9b9faf6dbb0f" - integrity sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw== +"@humanwhocodes/config-array@^0.11.8": + version "0.11.8" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" + integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" @@ -1794,14 +1795,14 @@ dependencies: defer-to-connect "^2.0.1" -"@testing-library/dom@^8.11.1", "@testing-library/dom@^8.19.0", "@testing-library/dom@^8.5.0": - version "8.19.0" - resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.19.0.tgz#bd3f83c217ebac16694329e413d9ad5fdcfd785f" - integrity sha512-6YWYPPpxG3e/xOo6HIWwB/58HukkwIVTOaZ0VwdMVjhRUX/01E4FtQbck9GazOOj7MXHc5RBzMrU86iBJHbI+A== +"@testing-library/dom@^8.11.1", "@testing-library/dom@^8.19.1", "@testing-library/dom@^8.5.0": + version "8.19.1" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.19.1.tgz#0e2dafd281dedb930bb235eac1045470b4129d0e" + integrity sha512-P6iIPyYQ+qH8CvGauAqanhVnjrnRe0IZFSYCeGkSRW9q3u8bdVn2NPI+lasFyVsEQn1J/IFmp5Aax41+dAP9wg== dependencies: "@babel/code-frame" "^7.10.4" "@babel/runtime" "^7.12.5" - "@types/aria-query" "^4.2.0" + "@types/aria-query" "^5.0.1" aria-query "^5.0.0" chalk "^4.1.0" dom-accessibility-api "^0.5.9" @@ -1861,10 +1862,10 @@ dependencies: "@types/estree" "*" -"@types/aria-query@^4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0" - integrity sha512-iIgQNzCm0v7QMhhe4Jjn9uRh+I6GoPmt03CbEtwx3ao8/EfoQcmgtqH4vQ5Db/lxiIGaWDv6nwvunuh0RyX0+A== +"@types/aria-query@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.1.tgz#3286741fb8f1e1580ac28784add4c7a1d49bdfbc" + integrity sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q== "@types/babel__core@^7.1.14": version "7.1.14" @@ -2505,13 +2506,13 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -"@yarnpkg/parsers@^3.0.0-rc.6": - version "3.0.0-rc.9" - resolved "https://registry.yarnpkg.com/@yarnpkg/parsers/-/parsers-3.0.0-rc.9.tgz#2d284e4e0c79b1c4e410465e217fa303d98b7be3" - integrity sha512-JMBE+6OJoNN9AXBzZ72u22/t9M25K8KgUWZIjvk8CU/NsE/m946l8D7SqMhbi3ZaUfYa5QitqCqVWTTFtysGJQ== +"@yarnpkg/parsers@^3.0.0-rc.32": + version "3.0.0-rc.34" + resolved "https://registry.yarnpkg.com/@yarnpkg/parsers/-/parsers-3.0.0-rc.34.tgz#db1d16e082e167db6dbc67f1c264639e0b4c5e1a" + integrity sha512-NhEA0BusInyk7EiJ7i7qF1Mkrb6gGjZcQQ/W1xxGazxapubEmGO7v5WSll6hWxFXE2ngtLj8lflq1Ff5VtqEww== dependencies: js-yaml "^3.10.0" - tslib "^1.13.0" + tslib "^2.4.0" JSONStream@^1.3.5: version "1.3.5" @@ -4819,13 +4820,13 @@ eslint@^6.0.1: text-table "^0.2.0" v8-compile-cache "^2.0.3" -eslint@^8.29.0: - version "8.29.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.29.0.tgz#d74a88a20fb44d59c51851625bc4ee8d0ec43f87" - integrity sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg== +eslint@^8.30.0: + version "8.30.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.30.0.tgz#83a506125d089eef7c5b5910eeea824273a33f50" + integrity sha512-MGADB39QqYuzEGov+F/qb18r4i7DohCDOfatHaxI2iGlPuC65bwG2gxgO+7DkyL38dRFaRH7RaRAgU6JKL9rMQ== dependencies: - "@eslint/eslintrc" "^1.3.3" - "@humanwhocodes/config-array" "^0.11.6" + "@eslint/eslintrc" "^1.4.0" + "@humanwhocodes/config-array" "^0.11.8" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" ajv "^6.10.0" @@ -4844,7 +4845,7 @@ eslint@^8.29.0: file-entry-cache "^6.0.1" find-up "^5.0.0" glob-parent "^6.0.2" - globals "^13.15.0" + globals "^13.19.0" grapheme-splitter "^1.0.4" ignore "^5.2.0" import-fresh "^3.0.0" @@ -5678,10 +5679,10 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" -globals@^13.15.0: - version "13.15.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.15.0.tgz#38113218c907d2f7e98658af246cef8b77e90bac" - integrity sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog== +globals@^13.19.0: + version "13.19.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.19.0.tgz#7a42de8e6ad4f7242fbcca27ea5b23aca367b5c8" + integrity sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ== dependencies: type-fest "^0.20.2" @@ -7651,22 +7652,22 @@ locate-path@^7.1.0: dependencies: p-locate "^6.0.0" -lockfile-lint-api@^5.4.6: - version "5.4.6" - resolved "https://registry.yarnpkg.com/lockfile-lint-api/-/lockfile-lint-api-5.4.6.tgz#9ab5252df1e1383061dbaa58f06c94bdb19710c6" - integrity sha512-3Sp01oBI0LWZNvKfGQ04G03+dXkjAvEvRiAQNZsvdVmCGP6vOXPCuPEimStf+RSo8PnjApdb65RAUh6aSZXsVQ== +lockfile-lint-api@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/lockfile-lint-api/-/lockfile-lint-api-5.5.0.tgz#9eab162f597121d8fdae13debe553abe1279c7c6" + integrity sha512-L/Jk109tOSmTCPHjUEQSH/bYDRt7rgT1E2NN8/p3tmAwJuKwuWplJliVzZ+bBiIRWKmtXBDcfHnXJ9yT1shevQ== dependencies: - "@yarnpkg/parsers" "^3.0.0-rc.6" + "@yarnpkg/parsers" "^3.0.0-rc.32" object-hash "^3.0.0" -lockfile-lint@^4.9.6: - version "4.9.6" - resolved "https://registry.yarnpkg.com/lockfile-lint/-/lockfile-lint-4.9.6.tgz#e0204b7eb9767c96fe59672c3fbb53fe9a12ca49" - integrity sha512-qPI3QcEflvGylCtXyxTh0anhi1oYxD12L3ZwQYaxLjxpWUI73+EbFMsl9esqcbgSKAh4wes5y6fbG8hbQTgjyg== +lockfile-lint@^4.10.0: + version "4.10.0" + resolved "https://registry.yarnpkg.com/lockfile-lint/-/lockfile-lint-4.10.0.tgz#388224241426dbfa6e632e96a539e4dfca088a6d" + integrity sha512-OM11m0txImBLFzC8DVoNx+Oca11K8jXndwQV9WLwXgMeLDJtlXGbLwRBFINjyo1YQr/STrdsx3OBth3cee+41A== dependencies: cosmiconfig "^7.0.1" debug "^4.1.1" - lockfile-lint-api "^5.4.6" + lockfile-lint-api "^5.5.0" yargs "^16.0.0" lodash.assignwith@^4.2.0: @@ -7753,6 +7754,13 @@ lowercase-keys@^3.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -11942,15 +11950,15 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.3: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +tslib@^2.0.3, tslib@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" + integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== tsscmp@1.0.6: version "1.0.6" @@ -13093,6 +13101,11 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18" integrity sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg== +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" From 5f96758bd705b99fa9f9be3ef4e0f0b5aee3ea22 Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 16:09:36 +0100 Subject: [PATCH 094/114] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Update=20core-js?= =?UTF-8?q?=20to=20version=203.27.1=20(PR=20#4396)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index b41b478ca8..a907c7e672 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "classnames": "^2.3.2", "common-tags": "^1.8.2", "copy-to-clipboard": "^3.3.3", - "core-js": "^3.26.1", + "core-js": "^3.27.1", "escape-string-regexp": "^4.0.0", "gecko-profiler-demangle": "^0.3.3", "idb": "^7.1.1", diff --git a/yarn.lock b/yarn.lock index da1f2a89ae..567ba4226a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3817,10 +3817,10 @@ core-js-compat@^3.25.1: dependencies: browserslist "^4.21.4" -core-js@^3.0.0, core-js@^3.26.1: - version "3.26.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.26.1.tgz#7a9816dabd9ee846c1c0fe0e8fcad68f3709134e" - integrity sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA== +core-js@^3.0.0, core-js@^3.27.1: + version "3.27.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.27.1.tgz#23cc909b315a6bb4e418bf40a52758af2103ba46" + integrity sha512-GutwJLBChfGCpwwhbYoqfv03LAfmiz7e7D/BNxzeMxwQf10GRSzqiOjx7AmtEk+heiD/JWmBuyBPgFtx0Sg1ww== core-util-is@~1.0.0: version "1.0.3" From 8468d62f12fc1ecd9bb85f6f5aab289ba83ded49 Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 16:13:14 +0100 Subject: [PATCH 095/114] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Update=20@codemirr?= =?UTF-8?q?or/state=20to=20version=206.2.0=20(PR=20#4397)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a907c7e672..412924d498 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "@codemirror/lang-javascript": "^6.1.2", "@codemirror/lang-rust": "^6.0.1", "@codemirror/language": "^6.3.2", - "@codemirror/state": "^6.1.4", + "@codemirror/state": "^6.2.0", "@codemirror/view": "^6.7.1", "@firefox-devtools/react-contextmenu": "^5.1.0", "@fluent/bundle": "^0.17.1", diff --git a/yarn.lock b/yarn.lock index 567ba4226a..ee64d7752d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1116,10 +1116,10 @@ "@codemirror/view" "^6.0.0" crelt "^1.0.5" -"@codemirror/state@^6.0.0", "@codemirror/state@^6.1.4": - version "6.1.4" - resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.1.4.tgz#2b654ae233ac4f41ee89ce095509ea35ecdf1031" - integrity sha512-g+3OJuRylV5qsXuuhrc6Cvs1NQluNioepYMM2fhnpYkNk7NgX+j0AFuevKSVKzTDmDyt9+Puju+zPdHNECzCNQ== +"@codemirror/state@^6.0.0", "@codemirror/state@^6.1.4", "@codemirror/state@^6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.2.0.tgz#a0fb08403ced8c2a68d1d0acee926bd20be922f2" + integrity sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA== "@codemirror/view@^6.0.0", "@codemirror/view@^6.7.1": version "6.7.1" From c44d45aece7c1f478bd81c99047bc711d9a44ce0 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Tue, 3 Jan 2023 18:10:10 +0100 Subject: [PATCH 096/114] Ensure that the new esm dependencies are processed by babel when run by jest --- .babelrc => babel.config.json | 0 package.json | 4 +--- 2 files changed, 1 insertion(+), 3 deletions(-) rename .babelrc => babel.config.json (100%) diff --git a/.babelrc b/babel.config.json similarity index 100% rename from .babelrc rename to babel.config.json diff --git a/package.json b/package.json index 2c8d6c7c62..5afced8ab2 100644 --- a/package.json +++ b/package.json @@ -172,9 +172,7 @@ "js", "jsx" ], - "moduleDirectories": [ - "node_modules" - ], + "transformIgnorePatterns": ["/node_modules/(?!(query-string|decode-uri-component|split-on-first|filter-obj)/)"], "moduleNameMapper": { "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|ftl)$": "/src/test/fixtures/mocks/file-mock.js", "\\.(css|less)$": "/src/test/fixtures/mocks/style-mock.js" From b674b6bc58d9fdec071a45ba6913f9222208ab6b Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Wed, 4 Jan 2023 11:11:12 +0100 Subject: [PATCH 097/114] Scroll the network chart at mount time if there's a selected item (PR #4385) --- src/components/network-chart/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/network-chart/index.js b/src/components/network-chart/index.js index 7d81de1919..d8b2fb9722 100644 --- a/src/components/network-chart/index.js +++ b/src/components/network-chart/index.js @@ -91,6 +91,7 @@ class NetworkChartImpl extends React.PureComponent { componentDidMount() { this.focus(); + this.scrollSelectionIntoView(); } componentDidUpdate(prevProps) { From 98bc139f347c545e29fdd34fb7334898b79148ce Mon Sep 17 00:00:00 2001 From: Krishna Ravishankar <25255817+krsh732@users.noreply.github.com> Date: Wed, 4 Jan 2023 09:47:24 -0500 Subject: [PATCH 098/114] Handle copy gesture for flame graph and stack chart (PR #4392) Fixes #3695 --- src/components/app/KeyboardShortcut.js | 5 ++++ src/components/flame-graph/FlameGraph.js | 26 +++++++++++++++++++ src/components/stack-chart/index.js | 23 ++++++++++++++++ .../KeyboardShortcut.test.js.snap | 19 ++++++++++++++ 4 files changed, 73 insertions(+) diff --git a/src/components/app/KeyboardShortcut.js b/src/components/app/KeyboardShortcut.js index 30602fc26a..d310b8bfe5 100644 --- a/src/components/app/KeyboardShortcut.js +++ b/src/components/app/KeyboardShortcut.js @@ -186,6 +186,11 @@ export class KeyboardShortcut extends React.PureComponent { +

        Marker Table

        ; class FlameGraphImpl extends React.PureComponent { _viewport: HTMLDivElement | null = null; + componentDidMount() { + document.addEventListener('copy', this._onCopy, false); + } + + componentWillUnmount() { + document.removeEventListener('copy', this._onCopy, false); + } + _onSelectedCallNodeChange = ( callNodeIndex: IndexIntoCallNodeTable | null ) => { @@ -301,6 +309,24 @@ class FlameGraphImpl extends React.PureComponent { } }; + _onCopy = (event: ClipboardEvent) => { + if (document.activeElement === this._viewport) { + event.preventDefault(); + const { + callNodeInfo: { callNodeTable }, + selectedCallNodeIndex, + thread, + } = this.props; + if (selectedCallNodeIndex !== null) { + const funcIndex = callNodeTable.func[selectedCallNodeIndex]; + const funcName = thread.stringTable.getString( + thread.funcTable.name[funcIndex] + ); + event.clipboardData.setData('text/plain', funcName); + } + } + }; + render() { const { thread, diff --git a/src/components/stack-chart/index.js b/src/components/stack-chart/index.js index 3ae0949c70..4b1d7e5e9c 100644 --- a/src/components/stack-chart/index.js +++ b/src/components/stack-chart/index.js @@ -158,10 +158,33 @@ class StackChartImpl extends React.PureComponent { handleCallNodeTransformShortcut(event, threadsKey, nodeIndex); }; + _onCopy = (event: ClipboardEvent) => { + if (document.activeElement === this._viewport) { + event.preventDefault(); + const { + callNodeInfo: { callNodeTable }, + selectedCallNodeIndex, + thread, + } = this.props; + if (selectedCallNodeIndex !== null) { + const funcIndex = callNodeTable.func[selectedCallNodeIndex]; + const funcName = thread.stringTable.getString( + thread.funcTable.name[funcIndex] + ); + event.clipboardData.setData('text/plain', funcName); + } + } + }; + componentDidMount() { + document.addEventListener('copy', this._onCopy, false); this._focusViewport(); } + componentWillUnmount() { + document.removeEventListener('copy', this._onCopy, false); + } + render() { const { thread, diff --git a/src/test/components/__snapshots__/KeyboardShortcut.test.js.snap b/src/test/components/__snapshots__/KeyboardShortcut.test.js.snap index db73498a83..048259aaa3 100644 --- a/src/test/components/__snapshots__/KeyboardShortcut.test.js.snap +++ b/src/test/components/__snapshots__/KeyboardShortcut.test.js.snap @@ -225,6 +225,25 @@ exports[`app/KeyboardShortcut matches the snapshot when open 1`] = ` ArrowRight
        +
        +
        + Copy call node label +
        + + ctrl + + + c + +

        Marker Table

        From 80420ecdda8dd287bfc0bea956b2e70272ad36fd Mon Sep 17 00:00:00 2001 From: Dzmitry Date: Thu, 5 Jan 2023 08:52:58 +0000 Subject: [PATCH 099/114] Pontoon: Update Belarusian (be) localization of Firefox Profiler Co-authored-by: Dzmitry --- locales/be/app.ftl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/locales/be/app.ftl b/locales/be/app.ftl index fdc4f76287..4ae4e451a9 100644 --- a/locales/be/app.ftl +++ b/locales/be/app.ftl @@ -309,6 +309,10 @@ MenuButtons--metaInfo-renderRowOfList-label-extensions = Пашырэнні: MenuButtons--metaOverheadStatistics-mean = Сярэдняе MenuButtons--metaOverheadStatistics-max = Макс MenuButtons--metaOverheadStatistics-min = Мін +MenuButtons--metaOverheadStatistics-statkeys-counter = Лічыльнік + .title = Час збору ўсіх лічыльнікаў +MenuButtons--metaOverheadStatistics-statkeys-interval = Інтэрвал + .title = Зафіксаваны інтэрвал паміж двума ўзорамі MenuButtons--metaOverheadStatistics-profiled-duration = Працягласць запісу профілю: ## Publish panel From c9079fc9e430d918bb3fcbf9b3d3bc0cc7b54322 Mon Sep 17 00:00:00 2001 From: Dzmitry Date: Thu, 5 Jan 2023 09:13:30 +0000 Subject: [PATCH 100/114] Pontoon: Update Belarusian (be) localization of Firefox Profiler Co-authored-by: Dzmitry --- locales/be/app.ftl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/be/app.ftl b/locales/be/app.ftl index 4ae4e451a9..c9227c934e 100644 --- a/locales/be/app.ftl +++ b/locales/be/app.ftl @@ -75,6 +75,8 @@ CallTree--tracing-ms-total = Час працы (мс) на працягу якога гэта функцыя знаходзілася ў стэку. Сюды ўваходзіць час, на працягу якога функцыя фактычна выконвалася, а таксама час выканання функцый, якія вызвала гэта функцыі. +CallTree--samples-total = Усяго (узоры) + .title = Лічыльнік “Усяго (узоры)” уключае ў сабе суму кожнага ўзору, у якога гэтая функцыя была выяўлена ў стэку. Сюды ўваходзіць час фактычнай працы функцыі, а таксама час, чакання вызаваў, якія рабіла гэтая функцыя. ## Call tree "badges" (icons) with tooltips ## From dccb1d5fee1128114e52233816b24cf32ab8eab5 Mon Sep 17 00:00:00 2001 From: Khairul Azhar Kasmiran Date: Thu, 5 Jan 2023 18:58:40 +0800 Subject: [PATCH 101/114] Add VSCode settings.json to bypass flow-bin `SHASUM256.txt.sign` check (PR #4393) --- .vscode/settings.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..6a30a53a52 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + // Bypass check for node_modules/flow-bin/SHASUM256.txt.sign since it + // doesn't exist in flow-bin 0.96.0. + "flow.useNPMPackagedFlow": false, + "flow.pathToFlow": "${workspaceFolder}/node_modules/.bin/flow", +} From fb9ff03ab8b98d9e7c29e36314080fae555bbe78 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Thu, 5 Jan 2023 18:01:19 +0100 Subject: [PATCH 102/114] Do not scroll the various views as a result of a pointer click (PR #4386) Fixes #4381 --- src/actions/profile-view.js | 18 ++++++-- src/components/calltree/CallTree.js | 11 +++-- src/components/marker-table/index.js | 8 +++- .../network-chart/NetworkChartRow.js | 1 - src/components/network-chart/index.js | 37 ++++++++++------- src/components/shared/TreeView.js | 41 +++++++++++-------- src/reducers/profile-view.js | 13 ++++-- src/test/components/MarkerTable.test.js | 9 +++- src/test/components/NetworkChart.test.js | 22 ++++++++-- .../components/ProfileCallTreeView.test.js | 20 ++++++++- src/types/actions.js | 12 ++++++ 11 files changed, 143 insertions(+), 49 deletions(-) diff --git a/src/actions/profile-view.js b/src/actions/profile-view.js index 73d3018bcf..9d78b10029 100644 --- a/src/actions/profile-view.js +++ b/src/actions/profile-view.js @@ -74,6 +74,7 @@ import type { GlobalTrack, KeyboardModifiers, TableViewOptions, + SelectionContext, } from 'firefox-profiler/types'; import { funcHasDirectRecursiveCall, @@ -99,6 +100,7 @@ import { intersectSets } from 'firefox-profiler/utils/set'; export function changeSelectedCallNode( threadsKey: ThreadsKey, selectedCallNodePath: CallNodePath, + context: SelectionContext = { source: 'auto' }, optionalExpandedToCallNodePath?: CallNodePath ): Action { if (optionalExpandedToCallNodePath) { @@ -119,6 +121,7 @@ export function changeSelectedCallNode( selectedCallNodePath, optionalExpandedToCallNodePath, threadsKey, + context, }; } @@ -206,7 +209,12 @@ export function selectRootCallNode( const rootCallNodePath = [selectedCallNodePath[0]]; dispatch( - changeSelectedCallNode(threadsKey, rootCallNodePath, selectedCallNodePath) + changeSelectedCallNode( + threadsKey, + rootCallNodePath, + { source: 'auto' }, + selectedCallNodePath + ) ); }; } @@ -1635,22 +1643,26 @@ export function changeExpandedCallNodes( export function changeSelectedMarker( threadsKey: ThreadsKey, - selectedMarker: MarkerIndex | null + selectedMarker: MarkerIndex | null, + context: SelectionContext = { source: 'auto' } ): Action { return { type: 'CHANGE_SELECTED_MARKER', selectedMarker, threadsKey, + context, }; } export function changeSelectedNetworkMarker( threadsKey: ThreadsKey, - selectedNetworkMarker: MarkerIndex | null + selectedNetworkMarker: MarkerIndex | null, + context: SelectionContext = { source: 'auto' } ): Action { return { type: 'CHANGE_SELECTED_NETWORK_MARKER', selectedNetworkMarker, threadsKey, + context, }; } diff --git a/src/components/calltree/CallTree.js b/src/components/calltree/CallTree.js index c23189f6b1..6191a7cc09 100644 --- a/src/components/calltree/CallTree.js +++ b/src/components/calltree/CallTree.js @@ -45,6 +45,7 @@ import type { CallNodeDisplayData, WeightType, TableViewOptions, + SelectionContext, } from 'firefox-profiler/types'; import type { CallTree as CallTreeType } from 'firefox-profiler/profile-logic/call-tree'; @@ -238,11 +239,15 @@ class CallTreeImpl extends PureComponent { } } - _onSelectedCallNodeChange = (newSelectedCallNode: IndexIntoCallNodeTable) => { + _onSelectedCallNodeChange = ( + newSelectedCallNode: IndexIntoCallNodeTable, + context: SelectionContext + ) => { const { callNodeInfo, threadsKey, changeSelectedCallNode } = this.props; changeSelectedCallNode( threadsKey, - getCallNodePathFromIndex(newSelectedCallNode, callNodeInfo.callNodeTable) + getCallNodePathFromIndex(newSelectedCallNode, callNodeInfo.callNodeTable), + context ); }; @@ -345,7 +350,7 @@ class CallTreeImpl extends PureComponent { // completely dimmed activity graph because idle stacks are not drawn in // this graph. Because this isn't probably what the average user wants we // do it only when the category is something different. - this._onSelectedCallNodeChange(currentCallNodeIndex); + this._onSelectedCallNodeChange(currentCallNodeIndex, { source: 'auto' }); } } diff --git a/src/components/marker-table/index.js b/src/components/marker-table/index.js index b222efeafb..eb6fbfc2ab 100644 --- a/src/components/marker-table/index.js +++ b/src/components/marker-table/index.js @@ -35,6 +35,7 @@ import type { Milliseconds, MarkerSchemaByName, TableViewOptions, + SelectionContext, } from 'firefox-profiler/types'; import type { ConnectedProps } from '../../utils/connect'; @@ -217,9 +218,12 @@ class MarkerTableImpl extends PureComponent { } } - _onSelectionChange = (selectedMarker: MarkerIndex) => { + _onSelectionChange = ( + selectedMarker: MarkerIndex, + context: SelectionContext + ) => { const { threadsKey, changeSelectedMarker } = this.props; - changeSelectedMarker(threadsKey, selectedMarker); + changeSelectedMarker(threadsKey, selectedMarker, context); }; _onRightClickSelection = (selectedMarker: MarkerIndex) => { diff --git a/src/components/network-chart/NetworkChartRow.js b/src/components/network-chart/NetworkChartRow.js index 88e2f44123..a26d0d114c 100644 --- a/src/components/network-chart/NetworkChartRow.js +++ b/src/components/network-chart/NetworkChartRow.js @@ -324,7 +324,6 @@ type NetworkChartRowProps = {| +isRightClicked: boolean, +isSelected: boolean, +isHoveredFromState: boolean, - +select: (MarkerIndex) => mixed, +onLeftClick?: (MarkerIndex) => mixed, +onRightClick?: (MarkerIndex) => mixed, +onHover?: (MarkerIndex | null) => mixed, diff --git a/src/components/network-chart/index.js b/src/components/network-chart/index.js index d8b2fb9722..f9f3e4860c 100644 --- a/src/components/network-chart/index.js +++ b/src/components/network-chart/index.js @@ -34,6 +34,7 @@ import type { MarkerIndex, StartEndRange, ThreadsKey, + SelectionContext, } from 'firefox-profiler/types'; import type { ConnectedProps } from '../../utils/connect'; @@ -162,7 +163,7 @@ class NetworkChartImpl extends React.PureComponent { if (selected === null || selectedRowIndex === -1) { // the first condition is redundant, but it makes flow happy - this._select(allRows[0]); + this._selectWithKeyboard(allRows[0]); return; } if (isNavigationKey) { @@ -170,30 +171,30 @@ class NetworkChartImpl extends React.PureComponent { case 'ArrowUp': { if (event.metaKey) { // On MacOS this is a common shortcut for the Home gesture - this._select(allRows[0]); + this._selectWithKeyboard(allRows[0]); break; } if (selectedRowIndex > 0) { - this._select(allRows[selectedRowIndex - 1]); + this._selectWithKeyboard(allRows[selectedRowIndex - 1]); } break; } case 'ArrowDown': { if (event.metaKey) { // On MacOS this is a common shortcut for the End gesture - this._select(allRows[allRows.length - 1]); + this._selectWithKeyboard(allRows[allRows.length - 1]); break; } if (selectedRowIndex < allRows.length - 1) { - this._select(allRows[selectedRowIndex + 1]); + this._selectWithKeyboard(allRows[selectedRowIndex + 1]); } break; } case 'PageUp': { if (selectedRowIndex > 0) { const nextRow = Math.max(0, selectedRowIndex - ROW_HEIGHT); - this._select(allRows[nextRow]); + this._selectWithKeyboard(allRows[nextRow]); } break; } @@ -203,16 +204,16 @@ class NetworkChartImpl extends React.PureComponent { allRows.length - 1, selectedRowIndex + ROW_HEIGHT ); - this._select(allRows[nextRow]); + this._selectWithKeyboard(allRows[nextRow]); } break; } case 'Home': { - this._select(allRows[0]); + this._selectWithKeyboard(allRows[0]); break; } case 'End': { - this._select(allRows[allRows.length - 1]); + this._selectWithKeyboard(allRows[allRows.length - 1]); break; } default: @@ -227,16 +228,23 @@ class NetworkChartImpl extends React.PureComponent { }; _onLeftClick = (selectedNetworkMarkerIndex: MarkerIndex) => { - this._onSelectionChange(selectedNetworkMarkerIndex); + this._onSelectionChange(selectedNetworkMarkerIndex, { source: 'pointer' }); }; - _select(selectedNetworkMarkerIndex: MarkerIndex) { - this._onSelectionChange(selectedNetworkMarkerIndex); + _selectWithKeyboard(selectedNetworkMarkerIndex: MarkerIndex) { + this._onSelectionChange(selectedNetworkMarkerIndex, { source: 'keyboard' }); } - _onSelectionChange = (selectedNetworkMarkerIndex: MarkerIndex) => { + _onSelectionChange = ( + selectedNetworkMarkerIndex: MarkerIndex, + context: SelectionContext + ) => { const { threadsKey, changeSelectedNetworkMarker } = this.props; - changeSelectedNetworkMarker(threadsKey, selectedNetworkMarkerIndex); + changeSelectedNetworkMarker( + threadsKey, + selectedNetworkMarkerIndex, + context + ); }; _onRowHovered = (hoveredMarkerIndex: MarkerIndex | null) => { @@ -289,7 +297,6 @@ class NetworkChartImpl extends React.PureComponent { isHoveredFromState={hoveredMarkerIndexFromState === markerIndex} onRightClick={this._onRightClick} isSelected={selectedNetworkMarkerIndex === markerIndex} - select={this._select} onLeftClick={this._onLeftClick} onHover={this._onRowHovered} /> diff --git a/src/components/shared/TreeView.js b/src/components/shared/TreeView.js index 72a3fbd2f0..cee9fd73bf 100644 --- a/src/components/shared/TreeView.js +++ b/src/components/shared/TreeView.js @@ -451,7 +451,10 @@ type TreeViewProps = {| +contextMenu?: React.Element, +contextMenuId?: string, +maxNodeDepth: number, - +onSelectionChange: (NodeIndex) => mixed, + +onSelectionChange: ( + NodeIndex, + {| source: 'keyboard' | 'pointer' |} + ) => mixed, +onRightClickSelection?: (NodeIndex) => mixed, +onEnterKey?: (NodeIndex) => mixed, +onDoubleClick?: (NodeIndex) => mixed, @@ -751,21 +754,21 @@ export class TreeView extends React.PureComponent< this._toggle(nodeId, newExpanded, true); } - _select(nodeId: NodeIndex) { - this.props.onSelectionChange(nodeId); + _selectWithMouse(nodeId: NodeIndex) { + this.props.onSelectionChange(nodeId, { source: 'pointer' }); } _rightClickSelect(nodeId: NodeIndex) { if (this.props.onRightClickSelection) { this.props.onRightClickSelection(nodeId); } else { - this._select(nodeId); + this._selectWithMouse(nodeId); } } _onRowClicked = (nodeId: NodeIndex, event: SyntheticMouseEvent<>) => { if (event.button === 0) { - this._select(nodeId); + this._selectWithMouse(nodeId); } else if (event.button === 2) { this._rightClickSelect(nodeId); } @@ -790,6 +793,10 @@ export class TreeView extends React.PureComponent< } }; + _selectWithKeyboard(nodeId: NodeIndex) { + this.props.onSelectionChange(nodeId, { source: 'keyboard' }); + } + _onKeyDown = (event: SyntheticKeyboardEvent<>) => { if (this.props.onKeyDown) { this.props.onKeyDown(event); @@ -819,7 +826,7 @@ export class TreeView extends React.PureComponent< if (selected === null || selectedRowIndex === -1) { // the first condition is redundant, but it makes flow happy - this._select(visibleRows[0]); + this._selectWithKeyboard(visibleRows[0]); return; } @@ -828,31 +835,31 @@ export class TreeView extends React.PureComponent< case 'ArrowUp': { if (event.metaKey) { // On MacOS this is a common shortcut for the Home gesture - this._select(visibleRows[0]); + this._selectWithKeyboard(visibleRows[0]); break; } if (selectedRowIndex > 0) { - this._select(visibleRows[selectedRowIndex - 1]); + this._selectWithKeyboard(visibleRows[selectedRowIndex - 1]); } break; } case 'ArrowDown': { if (event.metaKey) { // On MacOS this is a common shortcut for the End gesture - this._select(visibleRows[visibleRows.length - 1]); + this._selectWithKeyboard(visibleRows[visibleRows.length - 1]); break; } if (selectedRowIndex < visibleRows.length - 1) { - this._select(visibleRows[selectedRowIndex + 1]); + this._selectWithKeyboard(visibleRows[selectedRowIndex + 1]); } break; } case 'PageUp': { if (selectedRowIndex > 0) { const nextRow = Math.max(0, selectedRowIndex - PAGE_KEYS_DELTA); - this._select(visibleRows[nextRow]); + this._selectWithKeyboard(visibleRows[nextRow]); } break; } @@ -862,16 +869,16 @@ export class TreeView extends React.PureComponent< visibleRows.length - 1, selectedRowIndex + PAGE_KEYS_DELTA ); - this._select(visibleRows[nextRow]); + this._selectWithKeyboard(visibleRows[nextRow]); } break; } case 'Home': { - this._select(visibleRows[0]); + this._selectWithKeyboard(visibleRows[0]); break; } case 'End': { - this._select(visibleRows[visibleRows.length - 1]); + this._selectWithKeyboard(visibleRows[visibleRows.length - 1]); break; } case 'ArrowLeft': { @@ -881,7 +888,7 @@ export class TreeView extends React.PureComponent< } else { const parent = this.props.tree.getParent(selected); if (parent !== -1) { - this._select(parent); + this._selectWithKeyboard(parent); } } break; @@ -893,7 +900,9 @@ export class TreeView extends React.PureComponent< } else { // Do KEY_DOWN only if the next element is a child if (this.props.tree.hasChildren(selected)) { - this._select(this.props.tree.getChildren(selected)[0]); + this._selectWithKeyboard( + this.props.tree.getChildren(selected)[0] + ); } } break; diff --git a/src/reducers/profile-view.js b/src/reducers/profile-view.js index ee85da8795..a2d2ee89b3 100644 --- a/src/reducers/profile-view.js +++ b/src/reducers/profile-view.js @@ -485,18 +485,25 @@ const previewSelection: Reducer = ( const scrollToSelectionGeneration: Reducer = (state = 0, action) => { switch (action.type) { case 'CHANGE_INVERT_CALLSTACK': - case 'CHANGE_SELECTED_CALL_NODE': case 'CHANGE_SELECTED_THREAD': case 'SELECT_TRACK': case 'HIDE_GLOBAL_TRACK': case 'HIDE_LOCAL_TRACK': case 'HIDE_PROVIDED_TRACKS': - case 'CHANGE_SELECTED_MARKER': - case 'CHANGE_SELECTED_NETWORK_MARKER': case 'CHANGE_CALL_TREE_SEARCH_STRING': case 'CHANGE_MARKER_SEARCH_STRING': case 'CHANGE_NETWORK_SEARCH_STRING': return state + 1; + case 'CHANGE_SELECTED_CALL_NODE': + case 'CHANGE_SELECTED_MARKER': + case 'CHANGE_SELECTED_NETWORK_MARKER': + if (action.context.source === 'pointer') { + // If the call node was changed as a result of a pointer click, do not + // scroll the table. Indeed this is disturbing and prevents double + // clicks. + return state; + } + return state + 1; default: return state; } diff --git a/src/test/components/MarkerTable.test.js b/src/test/components/MarkerTable.test.js index 2d70401c1c..76e9b450fb 100644 --- a/src/test/components/MarkerTable.test.js +++ b/src/test/components/MarkerTable.test.js @@ -42,6 +42,7 @@ import { getHumanReadableTracks, } from '../fixtures/profiles/tracks'; import * as UrlStateSelectors from '../../selectors/url-state'; +import { getScrollToSelectionGeneration } from 'firefox-profiler/selectors/profile'; import type { CauseBacktrace } from 'firefox-profiler/types'; @@ -109,14 +110,20 @@ describe('MarkerTable', function () { }); it('selects a row when left clicking', () => { - const { getByText, getRowElement } = setup(); + const { getByText, getRowElement, getState } = setup(); + const initialScrollGeneration = getScrollToSelectionGeneration(getState()); fireFullClick(getByText(/setTimeout/)); expect(getRowElement(/setTimeout/)).toHaveClass('isSelected'); fireFullClick(getByText('foobar')); expect(getRowElement(/setTimeout/)).not.toHaveClass('isSelected'); expect(getRowElement('foobar')).toHaveClass('isSelected'); + + // The scroll generation hasn't moved. + expect(getScrollToSelectionGeneration(getState())).toEqual( + initialScrollGeneration + ); }); it('displays a context menu when right clicking', () => { diff --git a/src/test/components/NetworkChart.test.js b/src/test/components/NetworkChart.test.js index 870438858f..d71a215813 100644 --- a/src/test/components/NetworkChart.test.js +++ b/src/test/components/NetworkChart.test.js @@ -25,6 +25,7 @@ import { TIMELINE_MARGIN_RIGHT, } from '../../app-logic/constants'; import { selectedThreadSelectors } from 'firefox-profiler/selectors/per-thread'; +import { getScrollToSelectionGeneration } from 'firefox-profiler/selectors/profile'; import { storeWithProfile } from '../fixtures/stores'; import { @@ -679,12 +680,13 @@ describe('calltree/ProfileCallTreeView navigation keys', () => { afterEach(removeRootOverlayElement); function setup(markers) { - const { container } = setupWithPayload(markers); + const { container, getState } = setupWithPayload(markers); const renderedRows = container.querySelectorAll('.networkChartRowItem'); expect(renderedRows.length).toEqual(48); return { + getState, // take either a key as a string, or a full event if we need more // information like modifier keys. simulateKey: (param: string | { key: string }) => { @@ -708,10 +710,16 @@ describe('calltree/ProfileCallTreeView navigation keys', () => { } it('selects row on left click', () => { - const { rowItem } = setupWithPayload(getNetworkMarkers()); + const { rowItem, getState } = setupWithPayload(getNetworkMarkers()); + const initialScrollGeneration = getScrollToSelectionGeneration(getState()); fireFullClick(rowItem()); expect(rowItem()).toHaveClass('isSelected'); + + // The scroll generation hasn't moved. + expect(getScrollToSelectionGeneration(getState())).toEqual( + initialScrollGeneration + ); }); it('reacts properly to up/down navigation keys', () => { @@ -732,7 +740,9 @@ describe('calltree/ProfileCallTreeView navigation keys', () => { return [].concat(...arrayOfNetworkMarkers); })(); - const { simulateKey, selectedText } = setup(markers); + const { simulateKey, selectedText, getState } = setup(markers); + + const initialScrollGeneration = getScrollToSelectionGeneration(getState()); simulateKey('ArrowDown'); expect(selectedText()).toBe(`https://mozilla.org/1`); @@ -752,5 +762,11 @@ describe('calltree/ProfileCallTreeView navigation keys', () => { expect(selectedText()).toBe(`https://mozilla.org/48`); simulateKey({ key: 'ArrowUp', metaKey: true }); expect(selectedText()).toBe(`https://mozilla.org/1`); + + // Now we expect that the scroll generation increased, because scroll should + // be triggered with the keyboard navigation. + expect(getScrollToSelectionGeneration(getState())).toBeGreaterThan( + initialScrollGeneration + ); }); }); diff --git a/src/test/components/ProfileCallTreeView.test.js b/src/test/components/ProfileCallTreeView.test.js index c20103221d..ead86c57dd 100644 --- a/src/test/components/ProfileCallTreeView.test.js +++ b/src/test/components/ProfileCallTreeView.test.js @@ -11,6 +11,7 @@ import copy from 'copy-to-clipboard'; import { render, screen } from 'firefox-profiler/test/fixtures/testing-library'; import { selectedThreadSelectors } from '../../selectors/per-thread'; +import { getScrollToSelectionGeneration } from 'firefox-profiler/selectors/profile'; import { ProfileCallTreeView } from '../../components/calltree/ProfileCallTreeView'; import { CallNodeContextMenu } from '../../components/shared/CallNodeContextMenu'; import { processGeckoProfile } from '../../profile-logic/process-profile'; @@ -171,14 +172,20 @@ describe('calltree/ProfileCallTreeView', function () { }); it('selects a node when left clicking', () => { - const { getByText, getRowElement } = setup(); + const { getByText, getRowElement, getState } = setup(); + const initialScrollGeneration = getScrollToSelectionGeneration(getState()); fireFullClick(getByText('A')); expect(getRowElement('A')).toHaveClass('isSelected'); fireFullClick(getByText('B')); expect(getRowElement('A')).not.toHaveClass('isSelected'); expect(getRowElement('B')).toHaveClass('isSelected'); + + // The scroll generation hasn't moved. + expect(getScrollToSelectionGeneration(getState())).toEqual( + initialScrollGeneration + ); }); it('displays a context menu when right clicking', () => { @@ -379,6 +386,7 @@ describe('calltree/ProfileCallTreeView navigation keys', () => { expect(renderedRows.length).toBe(expectedRowsLength); return { + ...store, // take either a key as a string, or a full event if we need more // information like modifier keys. simulateKey: (param: string | { key: string }) => { @@ -415,7 +423,9 @@ describe('calltree/ProfileCallTreeView navigation keys', () => { '' ); - const { simulateKey, selectedText } = setup(profileString, 100); + const { simulateKey, selectedText, getState } = setup(profileString, 100); + + const initialScrollGeneration = getScrollToSelectionGeneration(getState()); expect(selectedText()).toBe('name1'); simulateKey('ArrowDown'); @@ -436,6 +446,12 @@ describe('calltree/ProfileCallTreeView navigation keys', () => { expect(selectedText()).toBe('name100'); simulateKey({ key: 'ArrowUp', metaKey: true }); expect(selectedText()).toBe('name1'); + + // Now we expect that the scroll generation increased, because scroll should + // be triggered with the keyboard navigation. + expect(getScrollToSelectionGeneration(getState())).toBeGreaterThan( + initialScrollGeneration + ); }); }); diff --git a/src/types/actions.js b/src/types/actions.js index 599d5b3b72..17435ba2c8 100644 --- a/src/types/actions.js +++ b/src/types/actions.js @@ -171,6 +171,15 @@ export type Localization = ReactLocalization; // stored in the same property to accommodate all OSes. export type KeyboardModifiers = {| ctrlOrMeta: boolean, shift: boolean |}; +/** + * This type gives some context about the action leading to a selection. + */ +export type SelectionContext = {| + // This is the source for this selection: is it a keyboard or a pointer event, + // or is it the result of some automatic selection. + +source: 'keyboard' | 'pointer' | 'auto', +|}; + type ProfileAction = | {| +type: 'ROUTE_NOT_FOUND', @@ -186,6 +195,7 @@ type ProfileAction = +threadsKey: ThreadsKey, +selectedCallNodePath: CallNodePath, +optionalExpandedToCallNodePath: ?CallNodePath, + +context: SelectionContext, |} | {| +type: 'UPDATE_TRACK_THREAD_HEIGHT', @@ -209,11 +219,13 @@ type ProfileAction = +type: 'CHANGE_SELECTED_MARKER', +threadsKey: ThreadsKey, +selectedMarker: MarkerIndex | null, + +context: SelectionContext, |} | {| +type: 'CHANGE_SELECTED_NETWORK_MARKER', +threadsKey: ThreadsKey, +selectedNetworkMarker: MarkerIndex | null, + +context: SelectionContext, |} | {| +type: 'CHANGE_RIGHT_CLICKED_MARKER', From 3b6bd2ac8ab96bb7b25e693de4ef56c29f2d4230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Wed, 4 Jan 2023 10:16:21 +0100 Subject: [PATCH 103/114] Do not throw an error when browsertime provides null timestamps incorrectly --- src/profile-logic/process-profile.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/profile-logic/process-profile.js b/src/profile-logic/process-profile.js index 14541240fa..505600fe71 100644 --- a/src/profile-logic/process-profile.js +++ b/src/profile-logic/process-profile.js @@ -1778,6 +1778,12 @@ export function processVisualMetrics( continue; } + if (metric.every((m) => m.timestamp === null)) { + // Skip it if we don't have any timestamps. + // This is due to https://github.com/sitespeedio/browsertime/issues/1746. + continue; + } + const startTime = navigationStartTime ?? metric[0].timestamp; const endTime = metric[metric.length - 1].timestamp; @@ -1798,6 +1804,11 @@ export function processVisualMetrics( const changeMarkerName = `${metricName} Change`; for (const { timestamp, percent } of metric) { + if (timestamp === null) { + // Skip it if we don't have a timestamp. + // This might be due to https://github.com/sitespeedio/browsertime/issues/1746. + continue; + } const payload = { type: 'VisualMetricProgress', // 'percentage' type expects a value between 0 and 1. From f047982c90a05918bdf894e3092f195efb0ee5c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Wed, 4 Jan 2023 10:33:52 +0100 Subject: [PATCH 104/114] Add a test for null metric timestamps --- src/test/unit/process-profile.test.js | 62 +++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/test/unit/process-profile.test.js b/src/test/unit/process-profile.test.js index 1ffe854ded..84a637a17b 100644 --- a/src/test/unit/process-profile.test.js +++ b/src/test/unit/process-profile.test.js @@ -664,8 +664,14 @@ describe('profile meta processing', function () { }); describe('visualMetrics processing', function () { - function checkVisualMetricsForThread(thread: Thread) { - const metrics = [ + function checkVisualMetricsForThread( + thread: Thread, + expectedMetricMarkers?: Array<{| + name: string, + changeMarkerLength: number, + |}> + ) { + const metrics = expectedMetricMarkers ?? [ { name: 'Visual', changeMarkerLength: 7 }, { name: 'ContentfulSpeedIndex', changeMarkerLength: 6 }, { name: 'PerceptualSpeedIndex', changeMarkerLength: 6 }, @@ -679,7 +685,12 @@ describe('visualMetrics processing', function () { const metricProgressMarker = thread.markers.name.find( (name) => name === metricProgressMarkerIndex ); - expect(metricProgressMarker).toBeTruthy(); + + if (changeMarkerLength > 0) { + expect(metricProgressMarker).toBeTruthy(); + } else { + expect(metricProgressMarker).toBeFalsy(); + } // Check the visual metric change markers. const metricChangeMarkerIndex = thread.stringTable.indexForString( @@ -736,4 +747,49 @@ describe('visualMetrics processing', function () { checkVisualMetricsForThread(tabProcessMainThread); }); + + it('does not add markers to the parent process if metric timestamps are null', function () { + const geckoProfile = createGeckoProfile(); + const visualMetrics = getVisualMetrics(); + + // Make all the VisualProgress timestamps null on purpose. + // Flow doesn't like null because it thinks that the timestamp can't be null. + // But this is a bug on browsertime. + visualMetrics.VisualProgress = visualMetrics.VisualProgress.map( + (progress) => ({ ...progress, timestamp: (null: any) }) + ); + // Make only one ContentfulSpeedIndexProgress timestamp null on purpose. + // Flow doesn't like null because it thinks that the timestamp can't be null. + // But this is a bug on browsertime. + ensureExists(visualMetrics.ContentfulSpeedIndexProgress)[0].timestamp = + (null: any); + + // Add the visual metrics to the profile. + geckoProfile.meta.visualMetrics = visualMetrics; + // Make sure that the visual metrics are not changed. + expect(visualMetrics.VisualProgress).toHaveLength(7); + expect(visualMetrics.ContentfulSpeedIndexProgress).toHaveLength(6); + expect(visualMetrics.PerceptualSpeedIndexProgress).toHaveLength(6); + + // Processing the profile. + const processedProfile = processGeckoProfile(geckoProfile); + const parentProcessMainThread = processedProfile.threads.find( + (thread) => + thread.name === 'GeckoMain' && thread.processType === 'default' + ); + + if (!parentProcessMainThread) { + throw new Error('Could not find the parent process main thread.'); + } + + checkVisualMetricsForThread(parentProcessMainThread, [ + // Instead of 7, we should have 0 markers for Visual because we made all + // the timestamps null. + { name: 'Visual', changeMarkerLength: 0 }, + // Instead of 6, we should have 5 markers for ContentfulSpeedIndex. + { name: 'ContentfulSpeedIndex', changeMarkerLength: 5 }, + // We didn't change the PerceptualSpeedIndexProgress, so we should have 6. + { name: 'PerceptualSpeedIndex', changeMarkerLength: 6 }, + ]); + }); }); From 4ce0d46b942b06997cdbb0bbe79e1e2316cdda6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Wed, 4 Jan 2023 15:42:07 +0100 Subject: [PATCH 105/114] Make the visual progress graph timestamp nullable because of the browsertime bug --- .../timeline/TrackVisualProgressGraph.js | 14 ++++++++------ src/test/unit/process-profile.test.js | 8 ++------ src/types/profile.js | 3 ++- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/components/timeline/TrackVisualProgressGraph.js b/src/components/timeline/TrackVisualProgressGraph.js index decbb0422c..41f6cde3d0 100644 --- a/src/components/timeline/TrackVisualProgressGraph.js +++ b/src/components/timeline/TrackVisualProgressGraph.js @@ -102,7 +102,7 @@ class TrackVisualProgressCanvas extends React.PureComponent { // Create a path for the top of the chart. This is the line that will have // a stroke applied to it. x = - (deviceWidth * (progressGraphData[i].timestamp - rangeStart)) / + (deviceWidth * ((progressGraphData[i].timestamp ?? 0) - rangeStart)) / rangeLength; // Add on half the stroke's line width so that it won't be cut off the edge // of the graph. @@ -133,7 +133,7 @@ class TrackVisualProgressCanvas extends React.PureComponent { // of the canvas. ctx.lineTo(x + interval, deviceHeight); ctx.lineTo( - (deviceWidth * (progressGraphData[0].timestamp - rangeStart)) / + (deviceWidth * ((progressGraphData[0].timestamp ?? 0) - rangeStart)) / rangeLength + interval, deviceHeight @@ -221,15 +221,16 @@ class TrackVisualProgressGraphImpl extends React.PureComponent { const rangeLength = rangeEnd - rangeStart; const timeAtMouse = rangeStart + ((mouseX - left) / width) * rangeLength; if ( - timeAtMouse < progressGraphData[0].timestamp || + timeAtMouse < (progressGraphData[0].timestamp ?? 0) || timeAtMouse > - progressGraphData[progressGraphData.length - 1].timestamp + interval + (progressGraphData[progressGraphData.length - 1].timestamp ?? 0) + + interval ) { // We are outside the range of the samples, do not display hover information. this.setState({ hoveredVisualProgress: null }); } else { const graphTimestamps = progressGraphData.map( - ({ timestamp }) => timestamp + ({ timestamp }) => timestamp ?? 0 ); let hoveredVisualProgress = bisectionRight(graphTimestamps, timeAtMouse); if (hoveredVisualProgress === progressGraphData.length) { @@ -277,7 +278,8 @@ class TrackVisualProgressGraphImpl extends React.PureComponent { } = this.props; const rangeLength = rangeEnd - rangeStart; const left = - (width * (progressGraphData[graphDataIndex].timestamp - rangeStart)) / + (width * + ((progressGraphData[graphDataIndex].timestamp ?? 0) - rangeStart)) / rangeLength; const unitSampleCount = progressGraphData[graphDataIndex].percent / 100; diff --git a/src/test/unit/process-profile.test.js b/src/test/unit/process-profile.test.js index 84a637a17b..5b76f6f63f 100644 --- a/src/test/unit/process-profile.test.js +++ b/src/test/unit/process-profile.test.js @@ -753,16 +753,12 @@ describe('visualMetrics processing', function () { const visualMetrics = getVisualMetrics(); // Make all the VisualProgress timestamps null on purpose. - // Flow doesn't like null because it thinks that the timestamp can't be null. - // But this is a bug on browsertime. visualMetrics.VisualProgress = visualMetrics.VisualProgress.map( - (progress) => ({ ...progress, timestamp: (null: any) }) + (progress) => ({ ...progress, timestamp: null }) ); // Make only one ContentfulSpeedIndexProgress timestamp null on purpose. - // Flow doesn't like null because it thinks that the timestamp can't be null. - // But this is a bug on browsertime. ensureExists(visualMetrics.ContentfulSpeedIndexProgress)[0].timestamp = - (null: any); + null; // Add the visual metrics to the profile. geckoProfile.meta.visualMetrics = visualMetrics; diff --git a/src/types/profile.js b/src/types/profile.js index 4638e1acc0..e57a2d92be 100644 --- a/src/types/profile.js +++ b/src/types/profile.js @@ -681,7 +681,8 @@ export type ProgressGraphData = {| // A percentage that describes the visual completeness of the webpage, ranging from 0% - 100% percent: number, // The time in milliseconds which the sample was taken. - timestamp: Milliseconds, + // This can be null due to https://github.com/sitespeedio/browsertime/issues/1746. + timestamp: Milliseconds | null, |}; /** From 7b58cc003cf431d28b8f9c53165d6f53763b218a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Thu, 5 Jan 2023 11:43:20 +0100 Subject: [PATCH 106/114] Refactor the browsertime marker tests --- src/test/unit/process-profile.test.js | 55 ++++++++++++++++++++------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/src/test/unit/process-profile.test.js b/src/test/unit/process-profile.test.js index 5b76f6f63f..d95b7169cc 100644 --- a/src/test/unit/process-profile.test.js +++ b/src/test/unit/process-profile.test.js @@ -666,18 +666,13 @@ describe('profile meta processing', function () { describe('visualMetrics processing', function () { function checkVisualMetricsForThread( thread: Thread, - expectedMetricMarkers?: Array<{| + metrics: Array<{| name: string, + hasProgressMarker: boolean, changeMarkerLength: number, |}> ) { - const metrics = expectedMetricMarkers ?? [ - { name: 'Visual', changeMarkerLength: 7 }, - { name: 'ContentfulSpeedIndex', changeMarkerLength: 6 }, - { name: 'PerceptualSpeedIndex', changeMarkerLength: 6 }, - ]; - - for (const { name, changeMarkerLength } of metrics) { + for (const { name, hasProgressMarker, changeMarkerLength } of metrics) { // Check the visual metric progress markers. const metricProgressMarkerIndex = thread.stringTable.indexForString( `${name} Progress` @@ -686,7 +681,7 @@ describe('visualMetrics processing', function () { (name) => name === metricProgressMarkerIndex ); - if (changeMarkerLength > 0) { + if (hasProgressMarker) { expect(metricProgressMarker).toBeTruthy(); } else { expect(metricProgressMarker).toBeFalsy(); @@ -723,7 +718,19 @@ describe('visualMetrics processing', function () { throw new Error('Could not find the parent process main thread.'); } - checkVisualMetricsForThread(parentProcessMainThread); + checkVisualMetricsForThread(parentProcessMainThread, [ + { name: 'Visual', hasProgressMarker: true, changeMarkerLength: 7 }, + { + name: 'ContentfulSpeedIndex', + hasProgressMarker: true, + changeMarkerLength: 6, + }, + { + name: 'PerceptualSpeedIndex', + hasProgressMarker: true, + changeMarkerLength: 6, + }, + ]); }); it('adds markers to the tab process', function () { @@ -745,7 +752,19 @@ describe('visualMetrics processing', function () { throw new Error('Could not find the tab process main thread.'); } - checkVisualMetricsForThread(tabProcessMainThread); + checkVisualMetricsForThread(tabProcessMainThread, [ + { name: 'Visual', hasProgressMarker: true, changeMarkerLength: 7 }, + { + name: 'ContentfulSpeedIndex', + hasProgressMarker: true, + changeMarkerLength: 6, + }, + { + name: 'PerceptualSpeedIndex', + hasProgressMarker: true, + changeMarkerLength: 6, + }, + ]); }); it('does not add markers to the parent process if metric timestamps are null', function () { @@ -781,11 +800,19 @@ describe('visualMetrics processing', function () { checkVisualMetricsForThread(parentProcessMainThread, [ // Instead of 7, we should have 0 markers for Visual because we made all // the timestamps null. - { name: 'Visual', changeMarkerLength: 0 }, + { name: 'Visual', hasProgressMarker: false, changeMarkerLength: 0 }, // Instead of 6, we should have 5 markers for ContentfulSpeedIndex. - { name: 'ContentfulSpeedIndex', changeMarkerLength: 5 }, + { + name: 'ContentfulSpeedIndex', + hasProgressMarker: true, + changeMarkerLength: 5, + }, // We didn't change the PerceptualSpeedIndexProgress, so we should have 6. - { name: 'PerceptualSpeedIndex', changeMarkerLength: 6 }, + { + name: 'PerceptualSpeedIndex', + hasProgressMarker: true, + changeMarkerLength: 6, + }, ]); }); }); From 7fb305d8211afe7df6b583f85128a452275d36d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Thu, 5 Jan 2023 12:01:24 +0100 Subject: [PATCH 107/114] Make the null timestmap checks more generic for the metric markers --- src/profile-logic/process-profile.js | 49 +++++++++++++++------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/src/profile-logic/process-profile.js b/src/profile-logic/process-profile.js index 505600fe71..238deb726f 100644 --- a/src/profile-logic/process-profile.js +++ b/src/profile-logic/process-profile.js @@ -28,6 +28,7 @@ import { isArtTraceFormat, convertArtTraceProfile } from './import/art-trace'; import { PROCESSED_PROFILE_VERSION, INTERVAL, + INTERVAL_END, INSTANT, } from '../app-logic/constants'; import { @@ -87,6 +88,7 @@ import type { PageList, ThreadIndex, BrowsertimeMarkerPayload, + MarkerPhase, } from 'firefox-profiler/types'; type RegExpResult = null | string[]; @@ -1736,18 +1738,30 @@ export function processVisualMetrics( (cat) => cat.name === 'Test' ); - function addMetricMarker( + function maybeAddMetricMarker( thread: Thread, name: string, - startTime: number, - endTime?: number, + phase: MarkerPhase, + startTime: number | null, + endTime: number | null, payload?: BrowsertimeMarkerPayload ) { + if ( + // All phases except INTERVAL_END should have a start time. + (phase !== INTERVAL_END && startTime === null) || + // Only INTERVAL and INTERVAL_END should have an end time. + ((phase === INTERVAL || phase === INTERVAL_END) && endTime === null) + ) { + // Do not add if some timestamps we expect are missing. + // This should ideally never happen but timestamps could be null due to + // browsertime bug here: https://github.com/sitespeedio/browsertime/issues/1746. + return; + } // Add the marker to the given thread. thread.markers.name.push(thread.stringTable.indexForString(name)); thread.markers.startTime.push(startTime); - thread.markers.endTime.push(endTime ? endTime : 0); - thread.markers.phase.push(endTime ? INTERVAL : INSTANT); + thread.markers.endTime.push(endTime); + thread.markers.phase.push(phase); thread.markers.category.push(testingCategoryIdx); thread.markers.data.push(payload ?? null); thread.markers.length++; @@ -1778,20 +1792,14 @@ export function processVisualMetrics( continue; } - if (metric.every((m) => m.timestamp === null)) { - // Skip it if we don't have any timestamps. - // This is due to https://github.com/sitespeedio/browsertime/issues/1746. - continue; - } - const startTime = navigationStartTime ?? metric[0].timestamp; const endTime = metric[metric.length - 1].timestamp; // Add the progress marker to the parent process main thread. const markerName = `${metricName} Progress`; - addMetricMarker(mainThread, markerName, startTime, endTime); + maybeAddMetricMarker(mainThread, markerName, INTERVAL, startTime, endTime); // Add the progress marker to the tab process main thread. - addMetricMarker(tabThread, markerName, startTime, endTime); + maybeAddMetricMarker(tabThread, markerName, INTERVAL, startTime, endTime); // Add progress markers for every visual progress change for more fine grained information. const progressMarkerSchema = { @@ -1804,11 +1812,6 @@ export function processVisualMetrics( const changeMarkerName = `${metricName} Change`; for (const { timestamp, percent } of metric) { - if (timestamp === null) { - // Skip it if we don't have a timestamp. - // This might be due to https://github.com/sitespeedio/browsertime/issues/1746. - continue; - } const payload = { type: 'VisualMetricProgress', // 'percentage' type expects a value between 0 and 1. @@ -1816,19 +1819,21 @@ export function processVisualMetrics( }; // Add it to the parent process main thread. - addMetricMarker( + maybeAddMetricMarker( mainThread, changeMarkerName, + INSTANT, timestamp, - undefined, // endTime + null, // endTime payload ); // Add it to the tab process main thread. - addMetricMarker( + maybeAddMetricMarker( tabThread, changeMarkerName, + INSTANT, timestamp, - undefined, // endTime + null, // endTime payload ); } From 4fb5501a3d5de06fb06e7866a7674713bf845113 Mon Sep 17 00:00:00 2001 From: Khairul Azhar Kasmiran Date: Fri, 6 Jan 2023 20:33:58 +0800 Subject: [PATCH 108/114] Chrome importer: Add 1 to line numbers of cpu profile --- src/profile-logic/import/chrome.js | 5 + .../profile-conversion.test.js.snap | 208 +++++++++--------- 2 files changed, 109 insertions(+), 104 deletions(-) diff --git a/src/profile-logic/import/chrome.js b/src/profile-logic/import/chrome.js index f9bcc6e735..2aebec6e77 100644 --- a/src/profile-logic/import/chrome.js +++ b/src/profile-logic/import/chrome.js @@ -517,6 +517,7 @@ async function processTracingEvents( threadInfo; let profileChunks = []; + let lineNumberAdjustment = 0; if (profileEvent.name === 'Profile') { threadInfo.lastSeenTime = (profileEvent.args.data.startTime: any) / 1000; const { id, pid } = profileEvent; @@ -529,6 +530,7 @@ async function processTracingEvents( threadInfo.lastSeenTime = (profileEvent.args.data.cpuProfile.startTime: any) / 1000; profileChunks = [profileEvent]; + lineNumberAdjustment = +1; } for (const profileChunk of profileChunks) { @@ -571,6 +573,9 @@ async function processTracingEvents( if (lineNumber === -1) { lineNumber = undefined; } + if (lineNumber !== undefined) { + lineNumber += lineNumberAdjustment; + } if (columnNumber === -1) { columnNumber = undefined; } diff --git a/src/test/unit/__snapshots__/profile-conversion.test.js.snap b/src/test/unit/__snapshots__/profile-conversion.test.js.snap index 942d87f59a..be24115ae1 100644 --- a/src/test/unit/__snapshots__/profile-conversion.test.js.snap +++ b/src/test/unit/__snapshots__/profile-conversion.test.js.snap @@ -444467,50 +444467,50 @@ Object { "line": Array [ null, null, - 3338, + 3339, null, null, null, null, null, - 75674, - 75624, - 65, + 75675, + 75625, + 66, null, - 70, - 73232, - 73084, - 72908, - 74574, - 74061, - 74281, + 71, + 73233, + 73085, + 72909, + 74575, + 74062, + 74282, null, null, null, - 27197, - 27498, + 27198, + 27499, null, - 26821, - 27773, - 28117, + 26822, + 27774, + 28118, null, null, null, - 137, + 138, null, null, - 32, - 73232, - 73084, - 74281, - 74613, - 13073, - 79762, - 74085, - 73822, + 33, + 73233, + 73085, + 74282, + 74614, + 13074, + 79763, + 74086, + 73823, null, - 13073, - 13382, + 13074, + 13383, null, ], "nativeSymbol": Array [ @@ -444795,45 +444795,45 @@ Object { "lineNumber": Array [ null, null, - 3338, + 3339, null, null, null, null, - 75674, - 75624, - 65, + 75675, + 75625, + 66, null, - 70, - 73232, - 73084, - 72908, - 74574, - 74061, - 74281, + 71, + 73233, + 73085, + 72909, + 74575, + 74062, + 74282, null, null, null, null, - 27197, - 27498, + 27198, + 27499, null, - 26821, - 27773, - 28117, + 26822, + 27774, + 28118, null, null, null, - 137, + 138, null, null, - 32, - 74613, - 13073, - 79762, - 74085, - 73822, - 13382, + 33, + 74614, + 13074, + 79763, + 74086, + 73823, + 13383, ], "name": Array [ 0, @@ -447500,50 +447500,50 @@ Object { "line": Array [ null, null, - 3338, + 3339, null, null, null, null, null, - 75674, - 75624, - 65, + 75675, + 75625, + 66, null, - 70, - 73232, - 73084, - 72908, - 74574, - 74061, - 74281, + 71, + 73233, + 73085, + 72909, + 74575, + 74062, + 74282, null, null, null, - 27197, - 27498, + 27198, + 27499, null, - 26821, - 27773, - 28117, + 26822, + 27774, + 28118, null, null, null, - 137, + 138, null, null, - 32, - 73232, - 73084, - 74281, - 74613, - 13073, - 79762, - 74085, - 73822, + 33, + 73233, + 73085, + 74282, + 74614, + 13074, + 79763, + 74086, + 73823, null, - 13073, - 13382, + 13074, + 13383, null, ], "nativeSymbol": Array [ @@ -447828,45 +447828,45 @@ Object { "lineNumber": Array [ null, null, - 3338, + 3339, null, null, null, null, - 75674, - 75624, - 65, + 75675, + 75625, + 66, null, - 70, - 73232, - 73084, - 72908, - 74574, - 74061, - 74281, + 71, + 73233, + 73085, + 72909, + 74575, + 74062, + 74282, null, null, null, null, - 27197, - 27498, + 27198, + 27499, null, - 26821, - 27773, - 28117, + 26822, + 27774, + 28118, null, null, null, - 137, + 138, null, null, - 32, - 74613, - 13073, - 79762, - 74085, - 73822, - 13382, + 33, + 74614, + 13074, + 79763, + 74086, + 73823, + 13383, ], "name": Array [ 0, From fb5c866af5776e4fec760f4ca39b31848a10706b Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Fri, 6 Jan 2023 15:50:20 +0100 Subject: [PATCH 109/114] Rotate the SSH key used for the l10n synchronize script (PR #4404) --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 93060d4d78..bd3e9d4c51 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -96,7 +96,7 @@ jobs: steps: - add_ssh_keys: fingerprints: - - "20:8e:de:d1:dd:ed:41:a9:9c:f0:32:20:0a:f0:1b:2e" + - "92:e1:5d:84:70:96:c5:19:76:55:1c:b1:7a:12:9e:53" - checkout - run: git config user.email "perf-html@mozilla.com" - run: git config user.name "Firefox Profiler [bot]" From aa4b2e07623d5022287c49ccf380588da929e002 Mon Sep 17 00:00:00 2001 From: Olvcpr423 Date: Mon, 9 Jan 2023 04:13:31 +0000 Subject: [PATCH 110/114] Pontoon: Update Chinese (China) (zh-CN) localization of Firefox Profiler Co-authored-by: Olvcpr423 --- locales/zh-CN/app.ftl | 47 +++++++------------------------------------ 1 file changed, 7 insertions(+), 40 deletions(-) diff --git a/locales/zh-CN/app.ftl b/locales/zh-CN/app.ftl index b9eba98c38..f448c1d117 100644 --- a/locales/zh-CN/app.ftl +++ b/locales/zh-CN/app.ftl @@ -38,8 +38,8 @@ AppViewRouter--error-compare = 无法获取分析记录。 # This error message is displayed when a Safari-specific error state is encountered. # Importing profiles from URLs such as http://127.0.0.1:someport/ is not possible in Safari. # https://profiler.firefox.com/from-url/http%3A%2F%2F127.0.0.1%3A3000%2Fprofile.json/ -AppViewRouter--error-from-localhost-url-safari = 由于 Safari 的特殊限制,{ -profiler-brand-name } 无法使用此浏览器从本地导入分析记录。请在 { -firefox-brand-name } 或 Chrome 中打开此页面。 - .title = Safari 无法导入本地性能分析记录 +AppViewRouter--error-from-localhost-url-safari = 由于 Safari 浏览器的特殊限制,{ -profiler-brand-name } 无法使用此浏览器从本地导入分析记录。请在 { -firefox-brand-name } 或 Chrome 中打开此页面。 + .title = Safari 浏览器无法导入本地性能分析记录 AppViewRouter--route-not-found--home = .specialMessage = 无法识别您尝试访问的 URL。 @@ -184,7 +184,6 @@ Home--enable-button-unavailable = # This message can be seen on https://main--perf-html.netlify.app/ . Home--web-channel-unavailable = 此分析器无法连接至 WebChannel。通常是因为运行分析器的主机与 devtools.performance.recording.ui-base-url 首选项中指定的主机不同。若您想要使用此分析器捕捉新的性能分析记录,并可程序化控制分析器菜单按钮,可到 about:config 调整该首选项。 Home--record-instructions = 要进行分析,请点击“分析”按钮,或使用键盘快捷键。在性能记录时,此图标将会变为蓝色。按下捕捉即可将数据加载至 profiler.firefox.com。 -Home--instructions-title = 如何查看并记录分析结果 Home--instructions-content = 需使用 { -firefox-brand-name } 记录性能分析信息。但可以使用任何现代浏览器查看现有分析记录。 Home--record-instructions-start-stop = 停止并开始分析 Home--record-instructions-capture-load = 捕捉并加载分析记录 @@ -615,8 +614,12 @@ TrackMemoryGraph--operations-since-the-previous-sample = 自前一次采样以 ## TrackPower ## This is used to show the power used by the CPU and other chips in a computer, ## graphed over time. -## It's not displayed by default in the UI, but an example can be found at +## It's not always displayed in the UI, but an example can be found at ## https://share.firefox.dev/3a1fiT7. +## For the strings in this group, the carbon dioxide equivalent is computed from +## the used energy, using the carbon dioxide equivalent for electricity +## consumption. The carbon dioxide equivalent represents the equivalent amount +## of CO₂ to achieve the same level of global warming potential. # This is used in the tooltip when the power value uses the watt unit. # Variables: @@ -628,42 +631,6 @@ TrackPower--tooltip-power-watt = { $value } W # $value (String) - the power value at this location TrackPower--tooltip-power-milliwatt = { $value } mW .label = 功率 -# This is used in the tooltip when the energy used in the current range uses the -# watt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-watthour = { $value } Wh - .label = 可见范围内的功耗 -# This is used in the tooltip when the energy used in the current range uses the -# milliwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-milliwatthour = { $value } mWh - .label = 可见范围内的功耗 -# This is used in the tooltip when the energy used in the current range uses the -# microwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-range-microwatthour = { $value } µWh - .label = 可见范围内的功耗 -# This is used in the tooltip when the energy used in the current preview -# selection uses the watt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-watthour = { $value } Wh - .label = 当前选择范围内的功耗 -# This is used in the tooltip when the energy used in the current preview -# selection uses the milliwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-milliwatthour = { $value } mWh - .label = 当前选择范围内的功耗 -# This is used in the tooltip when the energy used in the current preview -# selection uses the microwatt-hour unit. -# Variables: -# $value (String) - the energy value for this range -TrackPower--tooltip-energy-used-in-preview-microwatthour = { $value } µWh - .label = 当前选择范围内的功耗 ## TrackSearchField ## The component that is used for the search input in the track context menu. From 98785ff43d48e7c4e6ff1ae694ef071c50983470 Mon Sep 17 00:00:00 2001 From: Julien Wajsberg Date: Mon, 9 Jan 2023 13:55:27 +0100 Subject: [PATCH 111/114] Add 1 to line and column numbers for all v8-based profiles --- src/profile-logic/import/chrome.js | 16 +- .../profile-conversion.test.js.snap | 288 +++++++++--------- 2 files changed, 155 insertions(+), 149 deletions(-) diff --git a/src/profile-logic/import/chrome.js b/src/profile-logic/import/chrome.js index 2aebec6e77..92b874ae31 100644 --- a/src/profile-logic/import/chrome.js +++ b/src/profile-logic/import/chrome.js @@ -517,7 +517,6 @@ async function processTracingEvents( threadInfo; let profileChunks = []; - let lineNumberAdjustment = 0; if (profileEvent.name === 'Profile') { threadInfo.lastSeenTime = (profileEvent.args.data.startTime: any) / 1000; const { id, pid } = profileEvent; @@ -530,7 +529,6 @@ async function processTracingEvents( threadInfo.lastSeenTime = (profileEvent.args.data.cpuProfile.startTime: any) / 1000; profileChunks = [profileEvent]; - lineNumberAdjustment = +1; } for (const profileChunk of profileChunks) { @@ -573,12 +571,20 @@ async function processTracingEvents( if (lineNumber === -1) { lineNumber = undefined; } - if (lineNumber !== undefined) { - lineNumber += lineNumberAdjustment; - } + if (columnNumber === -1) { columnNumber = undefined; } + + // Line and column number are zero-based in chrome profiles, but + // 1-based in the firefox profiler. + if (lineNumber !== undefined) { + lineNumber++; + } + if (columnNumber !== undefined) { + columnNumber++; + } + if (url === '') { url = undefined; } diff --git a/src/test/unit/__snapshots__/profile-conversion.test.js.snap b/src/test/unit/__snapshots__/profile-conversion.test.js.snap index be24115ae1..9b27ebba3a 100644 --- a/src/test/unit/__snapshots__/profile-conversion.test.js.snap +++ b/src/test/unit/__snapshots__/profile-conversion.test.js.snap @@ -402777,14 +402777,14 @@ Object { ], "column": Array [ null, - 1757, + 1758, null, null, - 1363, - 1783, - 3420, - 463, - 1783, + 1364, + 1784, + 3421, + 464, + 1784, null, null, null, @@ -402793,14 +402793,14 @@ Object { null, null, null, - 4543, - 1326, + 4544, + 1327, null, - 29, + 30, null, - 5197, - 5375, - 296, + 5198, + 5376, + 297, null, ], "func": Array [ @@ -402891,14 +402891,14 @@ Object { "length": 26, "line": Array [ null, - 1, + 2, null, null, - 1, - 25, - 25, - 1, - 25, + 2, + 26, + 26, + 2, + 26, null, null, null, @@ -402907,14 +402907,14 @@ Object { null, null, null, - 25, - 28, + 26, + 29, null, - 1, + 2, null, - 25, - 25, - 1, + 26, + 26, + 2, null, ], "nativeSymbol": Array [ @@ -403005,13 +403005,13 @@ Object { "funcTable": Object { "columnNumber": Array [ null, - 1757, + 1758, null, null, - 1363, - 1783, - 3420, - 463, + 1364, + 1784, + 3421, + 464, null, null, null, @@ -403020,14 +403020,14 @@ Object { null, null, null, - 4543, - 1326, + 4544, + 1327, null, - 29, + 30, null, - 5197, - 5375, - 296, + 5198, + 5376, + 297, null, ], "fileName": Array [ @@ -403087,13 +403087,13 @@ Object { "length": 25, "lineNumber": Array [ null, - 1, + 2, null, null, - 1, - 25, - 25, - 1, + 2, + 26, + 26, + 2, null, null, null, @@ -403102,14 +403102,14 @@ Object { null, null, null, - 25, - 28, + 26, + 29, null, - 1, + 2, null, - 25, - 25, - 1, + 26, + 26, + 2, null, ], "name": Array [ @@ -444269,50 +444269,50 @@ Object { "column": Array [ null, null, - 32, + 33, null, null, null, null, null, - 22, - 22, - 16, + 23, + 23, + 17, null, - 34, - 22, - 20, - 20, - 26, - 52, - 29, + 35, + 23, + 21, + 21, + 27, + 53, + 30, null, null, null, + 26, 25, - 24, null, - 37, - 21, - 32, + 38, + 22, + 33, null, null, null, - 16, + 17, null, null, - 16, - 22, - 20, - 29, - 18, + 17, + 23, + 21, 30, - 18, - 74, - 24, + 19, + 31, + 19, + 75, + 25, null, - 30, - 30, + 31, + 31, null, ], "func": Array [ @@ -444665,45 +444665,45 @@ Object { "columnNumber": Array [ null, null, - 32, + 33, null, null, null, null, - 22, - 22, - 16, + 23, + 23, + 17, null, - 34, - 22, - 20, - 20, - 26, - 52, - 29, + 35, + 23, + 21, + 21, + 27, + 53, + 30, null, null, null, null, + 26, 25, - 24, null, - 37, - 21, - 32, + 38, + 22, + 33, null, null, null, - 16, + 17, null, null, - 16, - 18, - 30, - 18, - 74, - 24, - 30, + 17, + 19, + 31, + 19, + 75, + 25, + 31, ], "fileName": Array [ null, @@ -447302,50 +447302,50 @@ Object { "column": Array [ null, null, - 32, + 33, null, null, null, null, null, - 22, - 22, - 16, + 23, + 23, + 17, null, - 34, - 22, - 20, - 20, - 26, - 52, - 29, + 35, + 23, + 21, + 21, + 27, + 53, + 30, null, null, null, + 26, 25, - 24, null, - 37, - 21, - 32, + 38, + 22, + 33, null, null, null, - 16, + 17, null, null, - 16, - 22, - 20, - 29, - 18, + 17, + 23, + 21, 30, - 18, - 74, - 24, + 19, + 31, + 19, + 75, + 25, null, - 30, - 30, + 31, + 31, null, ], "func": Array [ @@ -447698,45 +447698,45 @@ Object { "columnNumber": Array [ null, null, - 32, + 33, null, null, null, null, - 22, - 22, - 16, + 23, + 23, + 17, null, - 34, - 22, - 20, - 20, - 26, - 52, - 29, + 35, + 23, + 21, + 21, + 27, + 53, + 30, null, null, null, null, + 26, 25, - 24, null, - 37, - 21, - 32, + 38, + 22, + 33, null, null, null, - 16, + 17, null, null, - 16, - 18, - 30, - 18, - 74, - 24, - 30, + 17, + 19, + 31, + 19, + 75, + 25, + 31, ], "fileName": Array [ null, From 7bdff3a1eda122cd65b285629945ca2073ea62ac Mon Sep 17 00:00:00 2001 From: "depfu[bot]" <23717796+depfu[bot]@users.noreply.github.com> Date: Mon, 9 Jan 2023 15:52:57 +0100 Subject: [PATCH 112/114] Update all development Yarn dependencies (2023-01-09) (PR #4407) Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com> --- package.json | 6 ++++-- yarn.lock | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 0204c0860f..8a1b8abc96 100644 --- a/package.json +++ b/package.json @@ -152,7 +152,7 @@ "raw-loader": "^4.0.2", "rimraf": "^3.0.2", "style-loader": "^3.3.1", - "stylelint": "^14.16.0", + "stylelint": "^14.16.1", "stylelint-config-idiomatic-order": "^9.0.0", "stylelint-config-prettier": "^9.0.4", "stylelint-config-standard": "^29.0.0", @@ -172,7 +172,9 @@ "js", "jsx" ], - "transformIgnorePatterns": ["/node_modules/(?!(query-string|decode-uri-component|split-on-first|filter-obj)/)"], + "transformIgnorePatterns": [ + "/node_modules/(?!(query-string|decode-uri-component|split-on-first|filter-obj)/)" + ], "moduleNameMapper": { "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|ftl)$": "/src/test/fixtures/mocks/file-mock.js", "\\.(css|less)$": "/src/test/fixtures/mocks/style-mock.js" diff --git a/yarn.lock b/yarn.lock index cb3c0a985f..be90746f4a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11550,10 +11550,10 @@ stylelint-prettier@^2.0.0: dependencies: prettier-linter-helpers "^1.0.0" -stylelint@^14.16.0: - version "14.16.0" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-14.16.0.tgz#8e1a424f4b9852e59089f95de306734d70e5048b" - integrity sha512-X6uTi9DcxjzLV8ZUAjit1vsRtSwcls0nl07c9rqOPzvpA8IvTX/xWEkBRowS0ffevRrqkHa/ThDEu86u73FQDg== +stylelint@^14.16.1: + version "14.16.1" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-14.16.1.tgz#b911063530619a1bbe44c2b875fd8181ebdc742d" + integrity sha512-ErlzR/T3hhbV+a925/gbfc3f3Fep9/bnspMiJPorfGEmcBbXdS+oo6LrVtoUZ/w9fqD6o6k7PtUlCOsCRdjX/A== dependencies: "@csstools/selector-specificity" "^2.0.2" balanced-match "^2.0.0" From edd7300af3e99523a843f40a7cdc19d57b818607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20H=C3=B6ner?= Date: Mon, 9 Jan 2023 19:08:56 +0100 Subject: [PATCH 113/114] linux perf: fix parsing frames with whitespaces in the path (PR #4410) Co-authored-by: Julien Wajsberg --- src/profile-logic/import/linux-perf.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/profile-logic/import/linux-perf.js b/src/profile-logic/import/linux-perf.js index 89f28f01dd..13d6cf6401 100644 --- a/src/profile-logic/import/linux-perf.js +++ b/src/profile-logic/import/linux-perf.js @@ -304,7 +304,9 @@ export function convertPerfScriptProfile( } // 23fe921 _ZN7mozilla3ipc14MessageChannel11MessageTask3RunEv (/home/mstange/Desktop/firefox/libxul.so) - const stackFrameMatch = /^\s*(\w+)\s*(.+) \((\S*)\)/.exec(stackFrameLine); + const stackFrameMatch = /^\s*(\w+)\s*(.+) \(([^)]*)\)/.exec( + stackFrameLine + ); if (stackFrameMatch) { // const pc = stackFrameMatch[1]; let rawFunc = stackFrameMatch[2]; From 7731900514821e0fbe8fc32f540b037c557ccf52 Mon Sep 17 00:00:00 2001 From: Johannes Bechberger Date: Tue, 10 Jan 2023 13:38:05 +0100 Subject: [PATCH 114/114] Make cause.time optional (PR #4408) --- src/components/tooltip/Marker.js | 2 +- src/profile-logic/process-profile.js | 2 +- src/profile-logic/processed-profile-versioning.js | 3 ++- src/types/markers.js | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/tooltip/Marker.js b/src/components/tooltip/Marker.js index acd35d5778..bf8f4a5850 100644 --- a/src/components/tooltip/Marker.js +++ b/src/components/tooltip/Marker.js @@ -414,7 +414,7 @@ class MarkerTooltipContents extends React.PureComponent { const { data, start } = marker; if (data && 'cause' in data && data.cause) { const { cause } = data; - const causeAge = start - cause.time; + const causeAge = cause.time !== undefined ? start - cause.time : 0; return [ , diff --git a/src/profile-logic/process-profile.js b/src/profile-logic/process-profile.js index 238deb726f..3a57062606 100644 --- a/src/profile-logic/process-profile.js +++ b/src/profile-logic/process-profile.js @@ -1287,7 +1287,7 @@ export function adjustMarkerTimestamps( if (typeof newData.endTime === 'number') { newData.endTime += delta; } - if (newData.cause) { + if (newData.cause && newData.cause.time !== undefined) { newData.cause.time += delta; } if (newData.type === 'Network') { diff --git a/src/profile-logic/processed-profile-versioning.js b/src/profile-logic/processed-profile-versioning.js index bfc5f0c397..9caf9be846 100644 --- a/src/profile-logic/processed-profile-versioning.js +++ b/src/profile-logic/processed-profile-versioning.js @@ -1715,7 +1715,8 @@ const _upgraders = { data && data.type !== 'tracing' && data.type !== 'Styles' && - data.cause + data.cause && + data.cause.time !== undefined ) { data.cause.time += delta; } diff --git a/src/types/markers.js b/src/types/markers.js index 2d9ee679a7..bfe9c1b383 100644 --- a/src/types/markers.js +++ b/src/types/markers.js @@ -134,7 +134,7 @@ export type CauseBacktrace = {| // `tid` is optional because older processed profiles may not have it. // No upgrader was written for this change. tid?: Tid, - time: Milliseconds, + time?: Milliseconds, stack: IndexIntoStackTable, |};