Skip to content

Commit 3fa962c

Browse files
authored
Merge branch 'main' into workbox-cli
2 parents 0f30a98 + 723ef00 commit 3fa962c

File tree

10 files changed

+102
-131
lines changed

10 files changed

+102
-131
lines changed

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"runtimeExecutable": "yarn",
99
"runtimeArgs": ["test"],
1010
"program": "${workspaceFolder}/node_modules/jest/bin/jest",
11-
"args": ["--runInBand", "${file}"],
11+
"args": ["--runInBand", "--testTimeout=300000", "${file}"],
1212
"cwd": "${workspaceFolder}",
1313
"internalConsoleOptions": "openOnSessionStart",
1414
"request": "launch",

jest.config.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
module.exports = {
6+
testMatch: ['<rootDir>/src/**/*.test.{js,jsx,ts,tsx}'],
7+
moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx'],
8+
9+
testEnvironment: './src/test/custom-environment',
10+
setupFilesAfterEnv: ['jest-extended/all', './src/test/setup.ts'],
11+
12+
collectCoverageFrom: [
13+
'src/**/*.{js,jsx,ts,tsx}',
14+
'!**/node_modules/**',
15+
'!src/types/libdef/**',
16+
],
17+
18+
// Transform ESM modules to CommonJS for Jest
19+
// These packages ship as pure ESM and need to be transformed by Babel
20+
transformIgnorePatterns: [
21+
'/node_modules/(?!(query-string|decode-uri-component|iongraph-web|split-on-first|filter-obj|fetch-mock)/)',
22+
],
23+
24+
// Mock static assets (images, CSS, etc.)
25+
moduleNameMapper: {
26+
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|ftl)$':
27+
'<rootDir>/src/test/fixtures/mocks/file-mock.ts',
28+
'\\.(css|less)$': '<rootDir>/src/test/fixtures/mocks/style-mock.ts',
29+
},
30+
31+
globals: {
32+
AVAILABLE_STAGING_LOCALES: null,
33+
},
34+
35+
snapshotFormat: {
36+
escapeString: true,
37+
printBasicPrototype: true,
38+
},
39+
verbose: false,
40+
};

package.json

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@
166166
"husky": "^4.3.8",
167167
"jest": "^30.2.0",
168168
"jest-environment-jsdom": "^30.2.0",
169-
"jest-extended": "^6.0.0",
169+
"jest-extended": "^7.0.0",
170170
"json-loader": "^0.5.7",
171171
"local-web-server": "^5.4.0",
172172
"lockfile-lint": "^4.14.1",
@@ -195,39 +195,6 @@
195195
"@types/react-splitter-layout/@types/react": "^18.3.26",
196196
"@types/trusted-types": "^2.0.7"
197197
},
198-
"jest": {
199-
"collectCoverageFrom": [
200-
"src/**/*.{js,jsx,ts,tsx}",
201-
"!**/node_modules/**",
202-
"!src/types/libdef/**"
203-
],
204-
"moduleFileExtensions": [
205-
"js",
206-
"jsx",
207-
"ts",
208-
"tsx"
209-
],
210-
"transformIgnorePatterns": [
211-
"/node_modules/(?!(query-string|decode-uri-component|iongraph-web|split-on-first|filter-obj|fetch-mock)/)"
212-
],
213-
"moduleNameMapper": {
214-
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|ftl)$": "<rootDir>/src/test/fixtures/mocks/file-mock.ts",
215-
"\\.(css|less)$": "<rootDir>/src/test/fixtures/mocks/style-mock.ts"
216-
},
217-
"setupFilesAfterEnv": [
218-
"jest-extended/all",
219-
"./src/test/setup.ts"
220-
],
221-
"globals": {
222-
"AVAILABLE_STAGING_LOCALES": null
223-
},
224-
"snapshotFormat": {
225-
"escapeString": true,
226-
"printBasicPrototype": true
227-
},
228-
"testEnvironment": "./src/test/custom-environment",
229-
"verbose": false
230-
},
231198
"husky": {
232199
"hooks": {
233200
"post-checkout": "node bin/post-checkout.js",

src/profile-logic/import/art-trace.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -194,12 +194,12 @@ type ArtTrace = {
194194
};
195195

196196
function detectArtTraceFormat(
197-
traceBuffer: ArrayBufferLike
197+
traceBuffer: Uint8Array
198198
): 'regular' | 'streaming' | 'unrecognized' {
199199
try {
200200
const lengthOfExpectedFirstTwoLinesOfSummarySection = '*version\nX\n'
201201
.length;
202-
const firstTwoLinesBuffer = traceBuffer.slice(
202+
const firstTwoLinesBuffer = traceBuffer.subarray(
203203
0,
204204
lengthOfExpectedFirstTwoLinesOfSummarySection
205205
);
@@ -213,7 +213,11 @@ function detectArtTraceFormat(
213213
}
214214

215215
try {
216-
const dataView = new DataView(traceBuffer);
216+
const dataView = new DataView(
217+
traceBuffer.buffer,
218+
traceBuffer.byteOffset,
219+
traceBuffer.byteLength
220+
);
217221
const magic = dataView.getUint32(0, true);
218222
if (magic === TRACE_MAGIC) {
219223
return 'streaming';
@@ -523,9 +527,9 @@ function parseStreamingFormat(reader: ByteReader) {
523527
};
524528
}
525529

526-
function parseArtTrace(buffer: ArrayBufferLike): ArtTrace {
530+
function parseArtTrace(buffer: Uint8Array): ArtTrace {
527531
try {
528-
const reader = new ByteReader(new Uint8Array(buffer));
532+
const reader = new ByteReader(buffer);
529533
switch (detectArtTraceFormat(buffer)) {
530534
case 'regular':
531535
return parseRegularFormat(reader);
@@ -915,13 +919,13 @@ class ThreadBuilder {
915919
}
916920
}
917921

918-
export function isArtTraceFormat(traceBuffer: ArrayBufferLike) {
922+
export function isArtTraceFormat(traceBuffer: Uint8Array) {
919923
return detectArtTraceFormat(traceBuffer) !== 'unrecognized';
920924
}
921925

922926
// Convert an ART trace to the Gecko profile format.
923927
export function convertArtTraceProfile(
924-
traceBuffer: ArrayBufferLike
928+
traceBuffer: Uint8Array
925929
): GeckoProfileVersion11 {
926930
const trace = parseArtTrace(traceBuffer);
927931
const originalIntervalInUsec = procureSamplingInterval(trace);

src/profile-logic/import/simpleperf.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -474,13 +474,17 @@ class FirefoxProfile {
474474
}
475475

476476
export class SimpleperfReportConverter {
477-
buffer: ArrayBufferLike;
477+
buffer: Uint8Array;
478478
bufferView: DataView;
479479
bufferOffset: number = 0;
480480

481-
constructor(buffer: ArrayBufferLike) {
481+
constructor(buffer: Uint8Array) {
482482
this.buffer = buffer;
483-
this.bufferView = new DataView(buffer);
483+
this.bufferView = new DataView(
484+
buffer.buffer,
485+
buffer.byteOffset,
486+
buffer.byteLength
487+
);
484488
}
485489

486490
readUint16LE() {
@@ -509,11 +513,10 @@ export class SimpleperfReportConverter {
509513
}
510514

511515
readRecord(recordSize: number): report.Record {
512-
const recordBuffer = this.buffer.slice(
516+
const recordArray = this.buffer.subarray(
513517
this.bufferOffset,
514518
this.bufferOffset + recordSize
515519
);
516-
const recordArray = new Uint8Array(recordBuffer);
517520
this.bufferOffset += recordSize;
518521

519522
return report.Record.decode(recordArray);
@@ -577,7 +580,7 @@ export class SimpleperfReportConverter {
577580
}
578581

579582
export function convertSimpleperfTraceProfile(
580-
traceBuffer: ArrayBufferLike
583+
traceBuffer: Uint8Array
581584
): Profile {
582585
return new SimpleperfReportConverter(traceBuffer).process();
583586
}

src/profile-logic/process-profile.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1965,27 +1965,33 @@ export async function unserializeProfileOfArbitraryFormat(
19651965
// object is constructed from an ArrayBuffer in a different context... which
19661966
// happens in our tests.
19671967
if (String(arbitraryFormat) === '[object ArrayBuffer]') {
1968-
let arrayBuffer = arbitraryFormat as ArrayBuffer;
1968+
const arrayBuffer = arbitraryFormat as ArrayBuffer;
1969+
arbitraryFormat = new Uint8Array(arrayBuffer);
1970+
}
19691971

1972+
// Handle binary formats.
1973+
if (
1974+
arbitraryFormat instanceof Uint8Array ||
1975+
(globalThis.Buffer && arbitraryFormat instanceof globalThis.Buffer)
1976+
) {
19701977
// Check for the gzip magic number in the header. If we find it, decompress
19711978
// the data first.
1972-
const profileBytes = new Uint8Array(arrayBuffer);
1979+
let profileBytes = arbitraryFormat as Uint8Array<ArrayBuffer>;
19731980
if (isGzip(profileBytes)) {
1974-
const decompressedProfile = await decompress(profileBytes);
1975-
arrayBuffer = decompressedProfile.buffer;
1981+
profileBytes = await decompress(profileBytes);
19761982
}
19771983

1978-
if (isArtTraceFormat(arrayBuffer)) {
1979-
arbitraryFormat = convertArtTraceProfile(arrayBuffer);
1980-
} else if (verifyMagic(SIMPLEPERF_MAGIC, arrayBuffer)) {
1984+
if (isArtTraceFormat(profileBytes)) {
1985+
arbitraryFormat = convertArtTraceProfile(profileBytes);
1986+
} else if (verifyMagic(SIMPLEPERF_MAGIC, profileBytes)) {
19811987
const { convertSimpleperfTraceProfile } = await import(
19821988
'./import/simpleperf'
19831989
);
1984-
arbitraryFormat = convertSimpleperfTraceProfile(arrayBuffer);
1990+
arbitraryFormat = convertSimpleperfTraceProfile(profileBytes);
19851991
} else {
19861992
try {
19871993
const textDecoder = new TextDecoder(undefined, { fatal: true });
1988-
arbitraryFormat = await textDecoder.decode(arrayBuffer);
1994+
arbitraryFormat = await textDecoder.decode(profileBytes);
19891995
} catch (e) {
19901996
console.error('Source exception:', e);
19911997
throw new Error(

src/symbolicator-cli/index.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,8 @@ export async function run(options: CliOptions) {
8585
// by our importers.
8686
const bytes = fs.readFileSync(options.input, null);
8787

88-
// bytes is a Uint8Array whose underlying ArrayBuffer can be longer than bytes.length.
89-
// Copy the contents into a new ArrayBuffer which is sized correctly, so that we
90-
// don't include uninitialized data from the extra parts of the underlying buffer.
91-
// Alternatively, we could make unserializeProfileOfArbitraryFormat support
92-
// Uint8Array or Buffer in addition to ArrayBuffer.
93-
const byteBufferCopy = Uint8Array.prototype.slice.call(bytes).buffer;
94-
9588
// Load the profile.
96-
const profile = await unserializeProfileOfArbitraryFormat(byteBufferCopy);
89+
const profile = await unserializeProfileOfArbitraryFormat(bytes);
9790
if (profile === undefined) {
9891
throw new Error('Unable to parse the profile.');
9992
}

src/test/unit/profile-conversion.test.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,8 @@ describe('converting Google Chrome profile', function () {
245245
'src/test/fixtures/upgrades/chrome-tracing.json.gz'
246246
);
247247
const decompressedBuffer = zlib.gunzipSync(compressedBuffer);
248-
const profile = await unserializeProfileOfArbitraryFormat(
249-
decompressedBuffer.buffer
250-
);
248+
const profile =
249+
await unserializeProfileOfArbitraryFormat(decompressedBuffer);
251250
if (profile === undefined) {
252251
throw new Error('Unable to parse the profile.');
253252
}
@@ -263,9 +262,8 @@ describe('converting Google Chrome profile', function () {
263262
'src/test/fixtures/upgrades/chrome-trace-issue-5429.json.gz'
264263
);
265264
const decompressedBuffer = zlib.gunzipSync(compressedBuffer);
266-
const profile = await unserializeProfileOfArbitraryFormat(
267-
decompressedBuffer.buffer
268-
);
265+
const profile =
266+
await unserializeProfileOfArbitraryFormat(decompressedBuffer);
269267
if (profile === undefined) {
270268
throw new Error('Unable to parse the profile.');
271269
}
@@ -425,8 +423,9 @@ describe('converting ART trace', function () {
425423
const buffer = fs.readFileSync(
426424
'src/test/fixtures/upgrades/art-trace-regular.trace.gz'
427425
);
428-
const arrayBuffer = zlib.gunzipSync(buffer).buffer;
429-
const profile = await unserializeProfileOfArbitraryFormat(arrayBuffer);
426+
const uncompressedBytes = zlib.gunzipSync(buffer);
427+
const profile =
428+
await unserializeProfileOfArbitraryFormat(uncompressedBytes);
430429
if (profile === undefined) {
431430
throw new Error('Unable to parse the profile.');
432431
}
@@ -440,8 +439,9 @@ describe('converting ART trace', function () {
440439
const buffer = fs.readFileSync(
441440
'src/test/fixtures/upgrades/art-trace-streaming.trace.gz'
442441
);
443-
const arrayBuffer = zlib.gunzipSync(buffer).buffer;
444-
const profile = await unserializeProfileOfArbitraryFormat(arrayBuffer);
442+
const uncompressedBytes = zlib.gunzipSync(buffer);
443+
const profile =
444+
await unserializeProfileOfArbitraryFormat(uncompressedBytes);
445445
if (profile === undefined) {
446446
throw new Error('Unable to parse the profile.');
447447
}
@@ -457,8 +457,9 @@ describe('converting Simpleperf trace', function () {
457457
const buffer = fs.readFileSync(
458458
'src/test/fixtures/upgrades/simpleperf-task-clock.trace.gz'
459459
);
460-
const arrayBuffer = zlib.gunzipSync(buffer).buffer;
461-
const profile = await unserializeProfileOfArbitraryFormat(arrayBuffer);
460+
const uncompressedBytes = zlib.gunzipSync(buffer);
461+
const profile =
462+
await unserializeProfileOfArbitraryFormat(uncompressedBytes);
462463
if (profile === undefined) {
463464
throw new Error('Unable to parse the profile.');
464465
}
@@ -472,8 +473,9 @@ describe('converting Simpleperf trace', function () {
472473
const buffer = fs.readFileSync(
473474
'src/test/fixtures/upgrades/simpleperf-cpu-clock.trace.gz'
474475
);
475-
const arrayBuffer = zlib.gunzipSync(buffer).buffer;
476-
const profile = await unserializeProfileOfArbitraryFormat(arrayBuffer);
476+
const uncompressedBytes = zlib.gunzipSync(buffer);
477+
const profile =
478+
await unserializeProfileOfArbitraryFormat(uncompressedBytes);
477479
if (profile === undefined) {
478480
throw new Error('Unable to parse the profile.');
479481
}

src/utils/magic.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
export const SIMPLEPERF = 'SIMPLEPERF';
22

3-
export function verifyMagic(
4-
magic: string,
5-
traceBuffer: ArrayBufferLike
6-
): boolean {
3+
export function verifyMagic(magic: string, traceBuffer: Uint8Array): boolean {
74
return (
85
new TextDecoder('utf8').decode(traceBuffer.slice(0, magic.length)) === magic
96
);

0 commit comments

Comments
 (0)