Skip to content

Commit 9765995

Browse files
authored
Deploy May 15, 2025 (#5461)
[Julien Wajsberg] Relax the check about chrome profiles (#5439) [Julien Wajsberg] Do not fail when the input isn't valid UTF-8 (#5426) [Markus Stange] Add the marker field types "flow-id" and "terminating-flow-id" to the set of types that store indexes in the string table (#5447) [Markus Stange] Retain platform-specific timestamp field that are being added in bug 1961012. (#5446) [Julien Wajsberg] Use the right allocations call tree when an allocations summary is selected (#5456) [Julien Wajsberg] Do not use a link to display the sourceURL if it's not a proper URL (#5454) And for locales: kab: ZiriSut zh-CN: Olvcpr423
2 parents d41d6e9 + 223a11c commit 9765995

File tree

22 files changed

+7069
-918
lines changed

22 files changed

+7069
-918
lines changed

locales/kab/app.ftl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ Home--additional-content-title = Sali imuɣna yellan
164164
Home--additional-content-content = Tzemreḍ <strong>ad tzuɣreḍ syen sers</strong> afaylu n umaɣnu da i usali-ines, neɣ:
165165
Home--compare-recordings-info = Tzemreḍ daɣen ad tsenmehleḍ iseklasen. <a>Ldi agrudem n usnemhel.</a>
166166
Home--your-recent-uploaded-recordings-title = Iseklasen-ik·im i d-yulin melmi kan
167+
Home--install-chrome-extension = Sbedd aseɣẓan n Chrome
167168
168169
## IdleSearchField
169170
## The component that is used for all the search inputs in the application.
@@ -259,6 +260,7 @@ MenuButtons--index--profile-info-uploaded-label = Yuli-d:
259260
MenuButtons--index--profile-info-uploaded-actions = Kkes
260261
MenuButtons--index--metaInfo-subtitle = Talɣut n umaɣnu
261262
MenuButtons--metaInfo--symbols = Izamulen:
263+
MenuButtons--metaInfo--main-memory = Takatut tagejdant:
262264
MenuButtons--index--show-moreInfo-button = Sken ugar
263265
MenuButtons--index--hide-moreInfo-button = Sken drus
264266
MenuButtons--metaInfo--profiling-started = Asekles yebda:
@@ -360,6 +362,8 @@ NumberFormat--short-date = { SHORTDATE($date) }
360362

361363
## Profile Name Button
362364

365+
ProfileName--edit-profile-name-button =
366+
.title = Ẓreg isem n umaɣnu
363367
364368
## Profile Delete Button
365369

@@ -541,6 +545,11 @@ TransformNavigator--merge-function = Smezdi: { $item }
541545
# Variables:
542546
# $item (String) - Name of the function that transform applied to.
543547
TransformNavigator--drop-function = Sers: { $item }
548+
# "Collapse recursion" transform.
549+
# See: https://profiler.firefox.com/docs/#/./guide-filtering-call-trees?id=collapse
550+
# Variables:
551+
# $item (String) - Name of the function that transform applied to.
552+
TransformNavigator--collapse-recursion = Fneẓ asniles: { $item }
544553
545554
## "Bottom box" - a view which contains the source view and the assembly view,
546555
## at the bottom of the profiler UI

locales/zh-CN/app.ftl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ Home--your-recent-uploaded-recordings-title = 您最近上传的记录
264264
# documentation to use these tools.
265265
Home--load-files-from-other-tools2 = { -profiler-brand-name } 也可以从其他分析器导入记录,例如 <perf>Linux perf</perf>、<simpleperf>Android SimplePerf</simpleperf>、Chrome 性能面板、<androidstudio>Android Studio</androidstudio>,支持直接导入 <dhat>dhat</dhat>、<traceevent>Google 的 Trace Event</traceevent> 格式保存的分析记录。<write>点此了解如何编写您自己的导入程序</write>。
266266
Home--install-chrome-extension = 安装 Chrome 扩展
267-
Home--chrome-extension-instructions = 使用 <a>Chrome 版 { -profiler-brand-name } 扩展</a>,在 Chrome 中捕获性能分析记录,并通过 { -profiler-brand-name } 分析。可到 Chrome 应用商店安装扩展。
267+
Home--chrome-extension-instructions = 使用 <a>Chrome 版 { -profiler-brand-name } 扩展</a>,在 Chrome 中捕捉性能分析记录,并通过 { -profiler-brand-name } 分析。可到 Chrome 应用商店安装扩展。
268268
Home--chrome-extension-recording-instructions = 安装后,即可使用扩展的工具栏图标和快捷键来开始或停止分析,也可以导出分析记录并在此处加载以进行详细分析。
269269
270270
## IdleSearchField
@@ -405,9 +405,10 @@ MenuButtons--index--hide-moreInfo-button = 显示更少
405405
# $physicalCPUs (Number), $logicalCPUs (Number) - Number of Physical and Logical CPU Cores
406406
MenuButtons--metaInfo--physical-and-logical-cpu =
407407
{ $physicalCPUs ->
408-
*[other] 物理核心 × { $physicalCPUs }
409-
}{ $logicalCPUs ->
410-
*[other] 逻辑核心 × { $logicalCPUs }
408+
*[other]
409+
{ $logicalCPUs ->
410+
*[other] 物理核心 × { $physicalCPUs }、逻辑核心 × { $logicalCPUs }
411+
}
411412
}
412413
# This string is used when we only have the information about the number of
413414
# physical CPU cores.

package.json

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -67,33 +67,33 @@
6767
"@codemirror/lang-rust": "^6.0.1",
6868
"@codemirror/language": "^6.11.0",
6969
"@codemirror/state": "^6.5.2",
70-
"@codemirror/view": "^6.36.4",
70+
"@codemirror/view": "^6.36.7",
7171
"@firefox-devtools/react-contextmenu": "^5.2.2",
72-
"@fluent/bundle": "^0.18.0",
72+
"@fluent/bundle": "^0.19.1",
7373
"@fluent/langneg": "^0.7.0",
7474
"@fluent/react": "^0.15.2",
7575
"@lezer/highlight": "^1.2.1",
76-
"@tgwf/co2": "^0.16.6",
76+
"@tgwf/co2": "^0.16.7",
7777
"array-move": "^3.0.1",
7878
"array-range": "^1.0.1",
7979
"clamp": "^1.0.1",
8080
"classnames": "^2.5.1",
8181
"common-tags": "^1.8.2",
8282
"copy-to-clipboard": "^3.3.3",
83-
"core-js": "^3.41.0",
83+
"core-js": "^3.42.0",
8484
"escape-string-regexp": "^4.0.0",
8585
"gecko-profiler-demangle": "^0.3.3",
8686
"idb": "^8.0.2",
8787
"jszip": "^3.10.1",
88-
"long": "^5.3.1",
88+
"long": "^5.3.2",
8989
"memoize-immutable": "^3.0.0",
9090
"memoize-one": "^6.0.0",
9191
"minimist": "^1.2.8",
9292
"mixedtuplemap": "^1.0.0",
9393
"namedtuplemap": "^1.0.0",
9494
"photon-colors": "^3.3.2",
95-
"protobufjs": "^7.4.0",
96-
"query-string": "^9.1.1",
95+
"protobufjs": "^7.5.0",
96+
"query-string": "^9.1.2",
9797
"react": "^18.3.1",
9898
"react-dom": "^18.3.1",
9999
"react-intersection-observer": "^9.16.0",
@@ -109,24 +109,24 @@
109109
"workbox-window": "^7.3.0"
110110
},
111111
"devDependencies": {
112-
"@babel/cli": "^7.27.0",
113-
"@babel/core": "^7.26.10",
114-
"@babel/eslint-parser": "^7.26.10",
115-
"@babel/eslint-plugin": "^7.26.10",
112+
"@babel/cli": "^7.27.2",
113+
"@babel/core": "^7.27.1",
114+
"@babel/eslint-parser": "^7.27.1",
115+
"@babel/eslint-plugin": "^7.27.1",
116116
"@babel/plugin-proposal-class-properties": "^7.18.6",
117-
"@babel/preset-env": "^7.26.9",
118-
"@babel/preset-flow": "^7.25.9",
119-
"@babel/preset-react": "^7.26.3",
117+
"@babel/preset-env": "^7.27.2",
118+
"@babel/preset-flow": "^7.27.1",
119+
"@babel/preset-react": "^7.27.1",
120120
"@testing-library/dom": "^10.4.0",
121121
"@testing-library/jest-dom": "^6.6.3",
122-
"@testing-library/react": "^16.2.0",
122+
"@testing-library/react": "^16.3.0",
123123
"alex": "^11.0.1",
124124
"autoprefixer": "^10.4.21",
125125
"babel-jest": "^29.7.0",
126126
"babel-loader": "^10.0.0",
127127
"babel-plugin-module-resolver": "^5.0.2",
128-
"browserslist": "^4.24.4",
129-
"caniuse-lite": "^1.0.30001699",
128+
"browserslist": "^4.24.5",
129+
"caniuse-lite": "^1.0.30001715",
130130
"circular-dependency-plugin": "^5.2.1",
131131
"codecov": "^3.8.3",
132132
"copy-webpack-plugin": "^13.0.0",
@@ -135,45 +135,45 @@
135135
"cssnano": "^7.0.6",
136136
"devtools-license-check": "^0.9.0",
137137
"eslint": "^8.57.1",
138-
"eslint-config-prettier": "^10.1.1",
138+
"eslint-config-prettier": "^10.1.2",
139139
"eslint-import-resolver-alias": "^1.1.2",
140140
"eslint-plugin-flowtype": "^8.0.3",
141141
"eslint-plugin-import": "^2.31.0",
142142
"eslint-plugin-jest": "^28.11.0",
143143
"eslint-plugin-jest-dom": "^5.5.0",
144144
"eslint-plugin-jest-formatting": "^3.1.0",
145-
"eslint-plugin-react": "^7.37.4",
145+
"eslint-plugin-react": "^7.37.5",
146146
"eslint-plugin-testing-library": "^7.1.1",
147147
"espree": "^10.3.0",
148148
"fake-indexeddb": "^6.0.0",
149149
"fetch-mock-jest": "^1.5.1",
150150
"file-loader": "^6.2.0",
151151
"flow-bin": "^0.96.0",
152-
"glob": "^10.4.5",
152+
"glob": "^11.0.2",
153153
"html-webpack-plugin": "^5.6.3",
154154
"husky": "^4.3.8",
155155
"jest": "^29.7.0",
156156
"jest-environment-jsdom": "^29.7.0",
157157
"jest-extended": "^4.0.2",
158158
"json-loader": "^0.5.7",
159159
"local-web-server": "^5.4.0",
160-
"lockfile-lint": "^4.14.0",
160+
"lockfile-lint": "^4.14.1",
161161
"mkdirp": "^3.0.1",
162162
"node-fetch": "^2.6.11",
163-
"npm-run-all2": "^7.0.2",
164-
"open": "^10.1.0",
163+
"npm-run-all2": "^8.0.1",
164+
"open": "^10.1.1",
165165
"postcss": "^8.5.3",
166166
"postcss-loader": "^8.1.1",
167167
"prettier": "^3.5.3",
168168
"raw-loader": "^4.0.2",
169169
"rimraf": "^5.0.10",
170170
"style-loader": "^4.0.0",
171-
"stylelint": "^16.15.0",
171+
"stylelint": "^16.19.1",
172172
"stylelint-config-idiomatic-order": "^10.0.0",
173-
"stylelint-config-standard": "^37.0.0",
174-
"webpack": "^5.98.0",
173+
"stylelint-config-standard": "^38.0.0",
174+
"webpack": "^5.99.8",
175175
"webpack-cli": "^6.0.1",
176-
"webpack-dev-server": "^5.2.0",
176+
"webpack-dev-server": "^5.2.1",
177177
"workbox-webpack-plugin": "^7.3.0",
178178
"yargs": "^17.7.2"
179179
},

src/components/app/MenuButtons/MetaInfo.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ class MetaInfoPanelImpl extends React.PureComponent<Props, State> {
363363
Build ID:
364364
</Localized>
365365
</span>
366-
{meta.sourceURL ? (
366+
{meta.sourceURL && /^https?:\/\//i.test(meta.sourceURL) ? (
367367
<a
368368
href={meta.sourceURL}
369369
title={meta.sourceURL}

src/profile-logic/import/chrome.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -215,14 +215,12 @@ export function attemptToConvertChromeProfile(
215215

216216
if (Array.isArray(json)) {
217217
// Chrome profiles come as a list of events.
218-
const event: mixed = json[0];
219-
// Lightly check that some properties exist that are in the TracingEvent.
218+
const firstEvents = json.slice(0, 5);
219+
// Lightly check that the first items look like a TracingEvent.
220220
if (
221-
event &&
222-
typeof event === 'object' &&
223-
'ph' in event &&
224-
'cat' in event &&
225-
'args' in event
221+
firstEvents.every(
222+
(event) => event && typeof event === 'object' && 'ph' in event
223+
)
226224
) {
227225
events = coerce<mixed[], TracingEventUnion[]>(json);
228226
}

src/profile-logic/marker-schema.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,12 @@ export function computeStringIndexMarkerFieldsByDataType(
679679
const { name, fields } = schema;
680680
const stringIndexFields = [];
681681
for (const field of fields) {
682-
if (field.format === 'unique-string' && field.key) {
682+
if (
683+
(field.format === 'unique-string' ||
684+
field.format === 'flow-id' ||
685+
field.format === 'terminating-flow-id') &&
686+
field.key
687+
) {
683688
stringIndexFields.push(field.key);
684689
}
685690
}

src/profile-logic/process-profile.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1697,6 +1697,12 @@ export function processGeckoProfile(geckoProfile: GeckoProfile): Profile {
16971697
const meta: ProfileMeta = {
16981698
interval: geckoProfile.meta.interval,
16991699
startTime: geckoProfile.meta.startTime,
1700+
startTimeAsClockMonotonicNanosecondsSinceBoot:
1701+
geckoProfile.meta.startTimeAsClockMonotonicNanosecondsSinceBoot,
1702+
startTimeAsMachAbsoluteTimeNanoseconds:
1703+
geckoProfile.meta.startTimeAsMachAbsoluteTimeNanoseconds,
1704+
startTimeAsQueryPerformanceCounterValue:
1705+
geckoProfile.meta.startTimeAsQueryPerformanceCounterValue,
17001706
abi: geckoProfile.meta.abi,
17011707
extensions: extensions,
17021708
misc: geckoProfile.meta.misc,
@@ -1896,7 +1902,7 @@ export async function unserializeProfileOfArbitraryFormat(
18961902
arbitraryFormat = convertSimpleperfTraceProfile(arrayBuffer);
18971903
} else {
18981904
try {
1899-
const textDecoder = new TextDecoder('utf-8', { fatal: true });
1905+
const textDecoder = new TextDecoder();
19001906
arbitraryFormat = await textDecoder.decode(arrayBuffer);
19011907
} catch (e) {
19021908
console.error('Source exception:', e);

src/selectors/per-thread/stack-sample.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -230,36 +230,36 @@ export function getStackAndSampleSelectorsPerThread(
230230
)
231231
);
232232

233-
const _getPreviewFilteredCtssSampleIndexToNonInvertedCallNodeIndex: Selector<
233+
const _getSampleIndexToNonInvertedCallNodeIndexForPreviewFilteredCtssThread: Selector<
234234
Array<IndexIntoCallNodeTable | null>,
235235
> = createSelector(
236236
(state) => threadSelectors.getPreviewFilteredCtssSamples(state).stack,
237237
(state) => getCallNodeInfo(state).getStackIndexToNonInvertedCallNodeIndex(),
238238
ProfileData.getSampleIndexToCallNodeIndex
239239
);
240240

241+
const _getSampleIndexToNonInvertedCallNodeIndexForFilteredCtssThread: Selector<
242+
Array<IndexIntoCallNodeTable | null>,
243+
> = createSelector(
244+
(state) => threadSelectors.getFilteredCtssSamples(state).stack,
245+
(state) => getCallNodeInfo(state).getStackIndexToNonInvertedCallNodeIndex(),
246+
ProfileData.getSampleIndexToCallNodeIndex
247+
);
248+
241249
const getSampleIndexToNonInvertedCallNodeIndexForFilteredThread: Selector<
242250
Array<IndexIntoCallNodeTable | null>,
243251
> = createSelector(
244252
(state) => threadSelectors.getFilteredThread(state).samples.stack,
245253
(state) => getCallNodeInfo(state).getStackIndexToNonInvertedCallNodeIndex(),
246-
(filteredThreadSampleStacks, stackIndexToNonInvertedCallNodeIndex) =>
247-
ProfileData.getSampleIndexToCallNodeIndex(
248-
filteredThreadSampleStacks,
249-
stackIndexToNonInvertedCallNodeIndex
250-
)
254+
ProfileData.getSampleIndexToCallNodeIndex
251255
);
252256

253257
const _getSampleIndexToNonInvertedCallNodeIndexForTabFilteredThread: Selector<
254258
Array<IndexIntoCallNodeTable | null>,
255259
> = createSelector(
256260
(state) => threadSelectors.getTabFilteredThread(state).samples.stack,
257261
(state) => getCallNodeInfo(state).getStackIndexToNonInvertedCallNodeIndex(),
258-
(tabFilteredThreadSampleStacks, stackIndexToNonInvertedCallNodeIndex) =>
259-
ProfileData.getSampleIndexToCallNodeIndex(
260-
tabFilteredThreadSampleStacks,
261-
stackIndexToNonInvertedCallNodeIndex
262-
)
262+
ProfileData.getSampleIndexToCallNodeIndex
263263
);
264264

265265
const getSamplesSelectedStatesInFilteredThread: Selector<
@@ -313,7 +313,7 @@ export function getStackAndSampleSelectorsPerThread(
313313
const getCallNodeSelfAndSummary: Selector<CallNodeSelfAndSummary> =
314314
createSelector(
315315
threadSelectors.getPreviewFilteredCtssSamples,
316-
_getPreviewFilteredCtssSampleIndexToNonInvertedCallNodeIndex,
316+
_getSampleIndexToNonInvertedCallNodeIndexForPreviewFilteredCtssThread,
317317
getCallNodeInfo,
318318
(samples, sampleIndexToCallNodeIndex, callNodeInfo) => {
319319
return CallTree.computeCallNodeSelfAndSummary(
@@ -362,7 +362,7 @@ export function getStackAndSampleSelectorsPerThread(
362362
const getTracedTiming: Selector<CallTree.CallTreeTimings | null> =
363363
createSelector(
364364
threadSelectors.getPreviewFilteredCtssSamples,
365-
_getPreviewFilteredCtssSampleIndexToNonInvertedCallNodeIndex,
365+
_getSampleIndexToNonInvertedCallNodeIndexForPreviewFilteredCtssThread,
366366
getCallNodeInfo,
367367
ProfileSelectors.getProfileInterval,
368368
(samples, sampleIndexToCallNodeIndex, callNodeInfo, interval) => {
@@ -403,7 +403,7 @@ export function getStackAndSampleSelectorsPerThread(
403403
const getStackTimingByDepth: Selector<StackTiming.StackTimingByDepth> =
404404
createSelector(
405405
threadSelectors.getFilteredCtssSamples,
406-
getSampleIndexToNonInvertedCallNodeIndexForFilteredThread, // Bug! #5327
406+
_getSampleIndexToNonInvertedCallNodeIndexForFilteredCtssThread,
407407
getCallNodeInfo,
408408
getFilteredCallNodeMaxDepthPlusOne,
409409
ProfileSelectors.getProfileInterval,

src/test/components/MenuButtons.test.js

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ import { MenuButtons } from 'firefox-profiler/components/app/MenuButtons';
1717
import { CurrentProfileUploadedInformationLoader } from 'firefox-profiler/components/app/CurrentProfileUploadedInformationLoader';
1818

1919
import { stateFromLocation } from 'firefox-profiler/app-logic/url-handling';
20-
import { processGeckoProfile } from 'firefox-profiler/profile-logic/process-profile';
20+
import {
21+
processGeckoProfile,
22+
unserializeProfileOfArbitraryFormat,
23+
} from 'firefox-profiler/profile-logic/process-profile';
2124
import {
2225
persistUploadedProfileInformationToDb,
2326
retrieveUploadedProfileInformationFromDb,
@@ -612,6 +615,45 @@ describe('app/MenuButtons', function () {
612615
expect(moreInfoPart).toMatchSnapshot();
613616
});
614617

618+
it('Does display a link for the build if there is a URL', async () => {
619+
const { profile } = getProfileFromTextSamples('A');
620+
profile.meta.sourceURL =
621+
'https://hg.mozilla.org/mozilla-central/rev/6be6a06991d7a2123d4b51f4ce384c6bce92f859';
622+
const buildID = '20250402094810';
623+
profile.meta.appBuildID = buildID;
624+
625+
const unserializedProfile =
626+
await unserializeProfileOfArbitraryFormat(profile);
627+
const { displayMetaInfoPanel } =
628+
await setupForMetaInfoPanel(unserializedProfile);
629+
await displayMetaInfoPanel();
630+
631+
const buildIdElement = ensureExists(
632+
screen.getByText(/Build ID:/).nextSibling
633+
);
634+
expect(buildIdElement).toBeInstanceOf(HTMLAnchorElement);
635+
expect(buildIdElement).toHaveTextContent(buildID);
636+
expect((buildIdElement: any).href).toBe(profile.meta.sourceURL);
637+
});
638+
639+
it('does not display a link for the build ID if there is no URL', async () => {
640+
const { profile } = getProfileFromTextSamples('A');
641+
profile.meta.sourceURL = 'unknown';
642+
const buildID = '20250402094810';
643+
profile.meta.appBuildID = buildID;
644+
const unserializedProfile =
645+
await unserializeProfileOfArbitraryFormat(profile);
646+
const { displayMetaInfoPanel } =
647+
await setupForMetaInfoPanel(unserializedProfile);
648+
await displayMetaInfoPanel();
649+
650+
const buildIdElement = ensureExists(
651+
screen.getByText(/Build ID:/).nextSibling
652+
);
653+
expect(buildIdElement).toBeInstanceOf(Text);
654+
expect(buildIdElement).toHaveTextContent(buildID);
655+
});
656+
615657
describe('deleting a profile', () => {
616658
const FAKE_HASH = 'FAKE_HASH';
617659
const FAKE_PROFILE_DATA = {

0 commit comments

Comments
 (0)