browsertime 27.4.1 → 28.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/bin/browsertime.js +28 -4
  3. package/lib/chrome/coverage.js +89 -19
  4. package/lib/chrome/mediawikiResourceLoader.js +223 -0
  5. package/lib/chrome/parseCpuTrace.js +87 -2
  6. package/lib/chrome/trace/blocking-time.js +189 -0
  7. package/lib/chrome/trace/domain-breakdown.js +86 -0
  8. package/lib/chrome/trace/frame-stability.js +135 -0
  9. package/lib/chrome/trace/function-costs.js +281 -0
  10. package/lib/chrome/trace/index.js +7 -0
  11. package/lib/chrome/trace/module-costs.js +137 -0
  12. package/lib/chrome/trace/non-composited-animations.js +50 -5
  13. package/lib/chrome/trace/selector-stats.js +110 -0
  14. package/lib/chrome/trace/style-invalidations.js +162 -0
  15. package/lib/chrome/trace/task-groups.js +28 -2
  16. package/lib/chrome/trace/timer-costs.js +183 -0
  17. package/lib/chrome/webdriver/chromium.js +114 -0
  18. package/lib/chrome/webdriver/traceUtilities.js +11 -1
  19. package/lib/core/engine/collector.js +12 -0
  20. package/lib/core/engine/index.js +6 -0
  21. package/lib/core/engine/iteration.js +5 -0
  22. package/lib/support/cli.js +1 -1
  23. package/lib/support/har/index.js +44 -1
  24. package/package.json +6 -6
  25. package/types/chrome/mediawikiResourceLoader.d.ts +11 -0
  26. package/types/chrome/mediawikiResourceLoader.d.ts.map +1 -0
  27. package/types/chrome/parseCpuTrace.d.ts +1 -26
  28. package/types/chrome/parseCpuTrace.d.ts.map +1 -1
  29. package/types/chrome/trace/blocking-time.d.ts +7 -0
  30. package/types/chrome/trace/blocking-time.d.ts.map +1 -0
  31. package/types/chrome/trace/domain-breakdown.d.ts +11 -0
  32. package/types/chrome/trace/domain-breakdown.d.ts.map +1 -0
  33. package/types/chrome/trace/frame-stability.d.ts +11 -0
  34. package/types/chrome/trace/frame-stability.d.ts.map +1 -0
  35. package/types/chrome/trace/function-costs.d.ts +6 -0
  36. package/types/chrome/trace/function-costs.d.ts.map +1 -0
  37. package/types/chrome/trace/index.d.ts +7 -0
  38. package/types/chrome/trace/index.d.ts.map +1 -1
  39. package/types/chrome/trace/module-costs.d.ts +20 -0
  40. package/types/chrome/trace/module-costs.d.ts.map +1 -0
  41. package/types/chrome/trace/non-composited-animations.d.ts +1 -25
  42. package/types/chrome/trace/non-composited-animations.d.ts.map +1 -1
  43. package/types/chrome/trace/selector-stats.d.ts +8 -0
  44. package/types/chrome/trace/selector-stats.d.ts.map +1 -0
  45. package/types/chrome/trace/style-invalidations.d.ts +9 -0
  46. package/types/chrome/trace/style-invalidations.d.ts.map +1 -0
  47. package/types/chrome/trace/task-groups.d.ts.map +1 -1
  48. package/types/chrome/trace/timer-costs.d.ts +10 -0
  49. package/types/chrome/trace/timer-costs.d.ts.map +1 -0
  50. package/types/chrome/webdriver/traceUtilities.d.ts.map +1 -1
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Timer pressure per script — how much setTimeout/setInterval churn
3
+ * a page runs, from trace events already collected with
4
+ * --chrome.timeline.
5
+ *
6
+ * Two sides are joined per URL:
7
+ * - TimerInstall events (instant): who schedules timers, how many,
8
+ * how many with timeout 0 (the "yield" pattern that turns into
9
+ * main-thread machine-gunning) and how many recurring
10
+ * (setInterval / singleShot: false). Attribution from the
11
+ * innermost stack frame with a URL.
12
+ * - TimerFire tasks from the main-thread task tree: what running
13
+ * those timers actually cost. main-thread-tasks.js already chains
14
+ * TimerFire back to the installing script's URLs, so the cost
15
+ * lands on the script that scheduled the timer even when the
16
+ * callback is anonymous.
17
+ *
18
+ * Polling loops show up as a high install/fire count with recurring
19
+ * installs on one URL; oversliced work shows up as hundreds of
20
+ * timeout-0 installs. Fire time is inclusive task duration — what
21
+ * the main thread was occupied with when the timer ran.
22
+ *
23
+ * Returns undefined when the trace has no timer events. Otherwise:
24
+ * { installs, fires, fireTime, timeoutZeroInstalls,
25
+ * recurringInstalls,
26
+ * byUrl: [{ url, installs, fires, fireTime,
27
+ * timeoutZeroInstalls, recurringInstalls }, …],
28
+ * sites: [{ url, line?, column?, functionName?, timeout,
29
+ * recurring, installs, fires, fireTime }, …] }
30
+ * fireTime in ms with one decimal; byUrl sorted by fireTime desc,
31
+ * capped at 10 entries with sub-0.1 ms/zero-install rows dropped.
32
+ * `sites` lists the individual timers grouped by install site
33
+ * (installer source position + timeout + kind) — the closest thing
34
+ * to a timer's identity the trace offers — top 10 by fire time.
35
+ * Positions are 1-based (trace stack-frame convention).
36
+ */
37
+
38
+ import { compute } from './main-thread-tasks.js';
39
+
40
+ const MAX_URLS = 10;
41
+ const MAX_SITES = 10;
42
+ const UNKNOWN = 'unknown';
43
+
44
+ function round(ms) {
45
+ return Math.round(ms * 10) / 10;
46
+ }
47
+
48
+ function installFrame(data) {
49
+ for (const frame of data.stackTrace || []) {
50
+ if (frame.url) return frame;
51
+ }
52
+ }
53
+
54
+ export function computeTimerCosts(trace) {
55
+ const byUrl = new Map();
56
+ // Individual timers grouped by install site (installer source
57
+ // position + timeout + kind): a polling loop reinstalling from the
58
+ // same line collapses into one row with its install/fire counts.
59
+ const bySite = new Map();
60
+ const siteForTimerId = new Map();
61
+ let installs = 0;
62
+ let fires = 0;
63
+ let fireTimeMs = 0;
64
+ let timeoutZeroInstalls = 0;
65
+ let recurringInstalls = 0;
66
+
67
+ function entryFor(url) {
68
+ let entry = byUrl.get(url);
69
+ if (!entry) {
70
+ entry = {
71
+ url,
72
+ installs: 0,
73
+ fires: 0,
74
+ fireTimeMs: 0,
75
+ timeoutZeroInstalls: 0,
76
+ recurringInstalls: 0
77
+ };
78
+ byUrl.set(url, entry);
79
+ }
80
+ return entry;
81
+ }
82
+
83
+ for (const event of trace.traceEvents) {
84
+ if (event.name !== 'TimerInstall') continue;
85
+ const data = (event.args && event.args.data) || {};
86
+ const frame = installFrame(data);
87
+ const entry = entryFor(frame ? frame.url : UNKNOWN);
88
+ installs++;
89
+ entry.installs++;
90
+ const timeout = data.timeout || 0;
91
+ if (timeout === 0) {
92
+ timeoutZeroInstalls++;
93
+ entry.timeoutZeroInstalls++;
94
+ }
95
+ const recurring = data.singleShot === false;
96
+ if (recurring) {
97
+ recurringInstalls++;
98
+ entry.recurringInstalls++;
99
+ }
100
+
101
+ const siteKey = frame
102
+ ? `${frame.url}|${frame.lineNumber}|${frame.columnNumber}|${timeout}|${recurring}`
103
+ : `${UNKNOWN}|${timeout}|${recurring}`;
104
+ let site = bySite.get(siteKey);
105
+ if (!site) {
106
+ site = {
107
+ url: frame ? frame.url : UNKNOWN,
108
+ timeout,
109
+ recurring,
110
+ installs: 0,
111
+ fires: 0,
112
+ fireTimeMs: 0
113
+ };
114
+ if (frame) {
115
+ site.line = frame.lineNumber;
116
+ site.column = frame.columnNumber;
117
+ if (frame.functionName) site.functionName = frame.functionName;
118
+ }
119
+ bySite.set(siteKey, site);
120
+ }
121
+ site.installs++;
122
+ if (data.timerId !== undefined) siteForTimerId.set(data.timerId, site);
123
+ }
124
+
125
+ const tasks = compute(trace);
126
+ for (const task of tasks) {
127
+ if (task.event.name !== 'TimerFire') continue;
128
+ const entry = entryFor(task.attributableURLs.at(-1) || UNKNOWN);
129
+ fires++;
130
+ fireTimeMs += task.duration;
131
+ entry.fires++;
132
+ entry.fireTimeMs += task.duration;
133
+ const fireData = (task.event.args && task.event.args.data) || {};
134
+ const site = siteForTimerId.get(fireData.timerId);
135
+ if (site) {
136
+ site.fires++;
137
+ site.fireTimeMs += task.duration;
138
+ }
139
+ }
140
+
141
+ if (installs === 0 && fires === 0) return;
142
+
143
+ const urls = [...byUrl.values()]
144
+ .filter(entry => entry.fireTimeMs >= 0.1 || entry.installs > 0)
145
+ .toSorted((a, b) => b.fireTimeMs - a.fireTimeMs || b.installs - a.installs)
146
+ .slice(0, MAX_URLS)
147
+ .map(entry => ({
148
+ url: entry.url,
149
+ installs: entry.installs,
150
+ fires: entry.fires,
151
+ fireTime: round(entry.fireTimeMs),
152
+ timeoutZeroInstalls: entry.timeoutZeroInstalls,
153
+ recurringInstalls: entry.recurringInstalls
154
+ }));
155
+
156
+ const sites = [...bySite.values()]
157
+ .toSorted((a, b) => b.fireTimeMs - a.fireTimeMs || b.installs - a.installs)
158
+ .slice(0, MAX_SITES)
159
+ .map(site => {
160
+ const published = {
161
+ url: site.url,
162
+ timeout: site.timeout,
163
+ recurring: site.recurring,
164
+ installs: site.installs,
165
+ fires: site.fires,
166
+ fireTime: round(site.fireTimeMs)
167
+ };
168
+ if (site.line !== undefined) published.line = site.line;
169
+ if (site.column !== undefined) published.column = site.column;
170
+ if (site.functionName) published.functionName = site.functionName;
171
+ return published;
172
+ });
173
+
174
+ return {
175
+ installs,
176
+ fires,
177
+ fireTime: round(fireTimeMs),
178
+ timeoutZeroInstalls,
179
+ recurringInstalls,
180
+ byUrl: urls,
181
+ sites
182
+ };
183
+ }
@@ -7,6 +7,10 @@ const log = getLogger('browsertime.chrome');
7
7
  const { Type } = logging;
8
8
  import { longTaskMetrics } from '../longTaskMetrics.js';
9
9
  import { parseCPUTrace } from '../parseCpuTrace.js';
10
+ import { computeModuleCosts } from '../trace/module-costs.js';
11
+ import { computeFunctionCosts } from '../trace/function-costs.js';
12
+ import { computeStyleInvalidations } from '../trace/style-invalidations.js';
13
+ import { labelForUrl } from '../mediawikiResourceLoader.js';
10
14
  import { getHar } from '../har.js';
11
15
  import { getEmptyHAR, mergeHars } from '../../support/har/index.js';
12
16
  import { toArray } from '../../support/util.js';
@@ -335,6 +339,12 @@ export class Chromium {
335
339
  const coverage = await this.coverage.collect();
336
340
  this.coverage = undefined;
337
341
  if (coverage) {
342
+ // Bundle location resolvers are plumbing for the CPU trace
343
+ // parser (per-module CPU attribution), not part of the
344
+ // coverage result contract — lift them off before the
345
+ // coverage object is serialized.
346
+ this.resourceLoaderBundles = coverage.resourceLoaderBundles;
347
+ delete coverage.resourceLoaderBundles;
338
348
  result.coverage = coverage;
339
349
  }
340
350
  }
@@ -416,6 +426,110 @@ export class Chromium {
416
426
  result.extraJson[name] = trace;
417
427
 
418
428
  const cpu = await parseCPUTrace(trace, result.url);
429
+
430
+ // Per-module CPU inside concatenated bundles (MediaWiki
431
+ // ResourceLoader). The only analysis that needs both the trace
432
+ // and the bundle boundaries from the coverage path, so it runs
433
+ // here where the two meet — only when coverage found bundles on
434
+ // the page, otherwise zero cost and no output key.
435
+ if (this.resourceLoaderBundles && this.resourceLoaderBundles.size > 0) {
436
+ try {
437
+ const moduleCosts = computeModuleCosts(
438
+ trace,
439
+ this.resourceLoaderBundles
440
+ );
441
+ if (moduleCosts.length > 0) {
442
+ for (const bundle of moduleCosts) {
443
+ const label = labelForUrl(bundle.url);
444
+ if (label) {
445
+ bundle.label = label;
446
+ }
447
+ }
448
+ cpu.moduleCosts = moduleCosts;
449
+ }
450
+ } catch (error) {
451
+ log.debug('computeModuleCosts failed: %s', error.message);
452
+ }
453
+ }
454
+ // Per-function self/total time from the V8 sampling profiler —
455
+ // only produces output on runs with the cpu_profiler trace
456
+ // category (--enableProfileRun). Reuses the bundle resolvers so
457
+ // functions inside concatenated bundles get a module name.
458
+ try {
459
+ const functionCosts = computeFunctionCosts(
460
+ trace,
461
+ this.resourceLoaderBundles
462
+ );
463
+ if (functionCosts.length > 0) {
464
+ for (const functionCost of functionCosts) {
465
+ const label = labelForUrl(functionCost.url);
466
+ if (label) {
467
+ functionCost.label = label;
468
+ }
469
+ for (const callee of functionCost.callees || []) {
470
+ const calleeLabel = labelForUrl(callee.url);
471
+ if (calleeLabel) {
472
+ callee.label = calleeLabel;
473
+ }
474
+ }
475
+ }
476
+ cpu.functionCosts = functionCosts;
477
+ }
478
+ } catch (error) {
479
+ log.debug('computeFunctionCosts failed: %s', error.message);
480
+ }
481
+ // Invalidation sources resolve to modules the same way —
482
+ // thousands of invalidations from one giant load.php URL say
483
+ // nothing, the per-module split says whose code churns the
484
+ // DOM. Recomputing with the bundles replaces the unresolved
485
+ // sources parseCpuTrace produced.
486
+ if (
487
+ cpu.styleInvalidations &&
488
+ this.resourceLoaderBundles &&
489
+ this.resourceLoaderBundles.size > 0
490
+ ) {
491
+ try {
492
+ const enriched = computeStyleInvalidations(
493
+ trace,
494
+ this.resourceLoaderBundles
495
+ );
496
+ if (enriched) {
497
+ for (const source of enriched.sources) {
498
+ const label = labelForUrl(source.url);
499
+ if (label) {
500
+ source.label = label;
501
+ }
502
+ }
503
+ cpu.styleInvalidations = enriched;
504
+ }
505
+ } catch (error) {
506
+ log.debug(
507
+ 'computeStyleInvalidations with bundles failed: %s',
508
+ error.message
509
+ );
510
+ }
511
+ }
512
+ // Timer install sites inside concatenated bundles resolve to
513
+ // the owning module — "load.php[scripts]:418" says nothing,
514
+ // the module name says whose timer it is. Trace stack-frame
515
+ // positions are 1-based, matching the resolvers.
516
+ if (
517
+ cpu.timers &&
518
+ cpu.timers.sites &&
519
+ this.resourceLoaderBundles &&
520
+ this.resourceLoaderBundles.size > 0
521
+ ) {
522
+ for (const site of cpu.timers.sites) {
523
+ if (site.line === undefined) continue;
524
+ const resolver = this.resourceLoaderBundles.get(site.url);
525
+ if (!resolver) continue;
526
+ const module_ = resolver.resolve(site.line, site.column);
527
+ if (module_) {
528
+ site.module = module_.name;
529
+ }
530
+ }
531
+ }
532
+ this.resourceLoaderBundles = undefined;
419
533
  result.cpu = cpu;
420
534
 
421
535
  // Collect render blocking info
@@ -52,12 +52,22 @@ function getRecalculateStyleElementsAndTimeBefore(traceEvents, timestamp) {
52
52
  );
53
53
  let elements = 0;
54
54
  let duration = 0;
55
+ let maxElements = 0;
56
+ let maxDuration = 0;
55
57
  for (let a of updateLayoutTree) {
56
58
  elements += a.args.elementCount;
57
59
  duration += a.dur;
60
+ maxElements = Math.max(maxElements, a.args.elementCount);
61
+ maxDuration = Math.max(maxDuration, a.dur);
58
62
  }
59
63
 
60
- return { elements, durationInMillis: duration / 1000 };
64
+ return {
65
+ count: updateLayoutTree.length,
66
+ elements,
67
+ durationInMillis: duration / 1000,
68
+ maxElements,
69
+ maxDurationInMillis: maxDuration / 1000
70
+ };
61
71
  }
62
72
 
63
73
  export async function getRenderBlocking(trace) {
@@ -136,6 +136,18 @@ export class Collector {
136
136
  }
137
137
  }
138
138
 
139
+ // Header values are strings so they are kept out of the statistics.
140
+ addMainDocument(url, mainDocument) {
141
+ const results =
142
+ this.allResults[url] || this.allResults[this.urlAndActualUrl[url]];
143
+ if (results) {
144
+ if (!results.mainDocument) {
145
+ results.mainDocument = [];
146
+ }
147
+ results.mainDocument.push(mainDocument);
148
+ }
149
+ }
150
+
139
151
  /**
140
152
  * Collect all individual runs, add it to the statistics, and store
141
153
  * data that needs to be on disk (trace logs, sceenshots etc).
@@ -18,6 +18,7 @@ import {
18
18
  import {
19
19
  getFullyLoaded,
20
20
  getMainDocumentTimings,
21
+ getMainDocuments,
21
22
  addExtraFieldsToHar
22
23
  } from '../../support/har/index.js';
23
24
  import { XVFB } from '../../support/xvfb.js';
@@ -374,6 +375,11 @@ export class Engine {
374
375
  for (let timing of timings) {
375
376
  collector.addMainDocumentTimings(timing.url, timing.timings);
376
377
  }
378
+
379
+ const mainDocuments = getMainDocuments(extras.har);
380
+ for (let document of mainDocuments) {
381
+ collector.addMainDocument(document.url, document.mainDocument);
382
+ }
377
383
  }
378
384
  }
379
385
 
@@ -278,6 +278,11 @@ export class Iteration {
278
278
  try {
279
279
  await navigationScript(context, commands, this.postURLScripts);
280
280
  } catch (error) {
281
+ const lastUrl = context.result.at(-1) && context.result.at(-1).url;
282
+ const where = lastUrl
283
+ ? ` while testing ${lastUrl} (iteration ${context.index})`
284
+ : ` (iteration ${context.index})`;
285
+ error.message = `${error.message}${where}`;
281
286
  commands.error(error.message);
282
287
  commands.markAsFailure(error.message);
283
288
  throw error;
@@ -51,7 +51,7 @@ function hasbin(bin) {
51
51
  function validateInput(argv) {
52
52
  // Check NodeJS major version
53
53
  const fullVersion = process.versions.node;
54
- const minVersion = 20;
54
+ const minVersion = 22;
55
55
  const majorVersion = fullVersion.split('.')[0];
56
56
  if (majorVersion < minVersion) {
57
57
  return (
@@ -269,6 +269,45 @@ export function getMainDocumentTimings(har) {
269
269
  return [];
270
270
  }
271
271
  }
272
+ export function getMainDocuments(har) {
273
+ // Sometimes the HAR is dirty
274
+ try {
275
+ const mainDocuments = [];
276
+ for (let page of har.log.pages) {
277
+ const url = page._url;
278
+ if (url === undefined) continue;
279
+
280
+ const requests = getDocumentRequests(har.log.entries, page.id);
281
+ const finalEntry = requests.at(-1);
282
+ if (!finalEntry) continue;
283
+
284
+ const headers = {};
285
+ for (let header of finalEntry.response.headers || []) {
286
+ const name = header.name.toLowerCase();
287
+ // Always drop sensitive headers (the same list as
288
+ // --cleanSensitiveHeaders uses) since browsertime.json often ends
289
+ // up in dashboards even when the HAR stays local.
290
+ if (isSensitiveHeader(name)) continue;
291
+ headers[name] =
292
+ name in headers ? headers[name] + ', ' + header.value : header.value;
293
+ }
294
+
295
+ mainDocuments.push({
296
+ url,
297
+ mainDocument: {
298
+ url: finalEntry.request.url,
299
+ status: finalEntry.response.status,
300
+ redirects: requests.length - 1,
301
+ headers
302
+ }
303
+ });
304
+ }
305
+ return mainDocuments;
306
+ } catch (error) {
307
+ log.error('Could not get main document headers ' + error);
308
+ return [];
309
+ }
310
+ }
272
311
  export function getFullyLoaded(har) {
273
312
  const fullyLoaded = [];
274
313
  const entries = [...har.log.entries];
@@ -464,8 +503,12 @@ export function addExtraFieldsToHar(totalResults, har, options) {
464
503
  }
465
504
  }
466
505
 
506
+ export function isSensitiveHeader(name) {
507
+ return sensitiveHeaders.has(name.toLowerCase());
508
+ }
509
+
467
510
  export function cleanSensitiveHeaders(name, value) {
468
- if (sensitiveHeaders.has(name.toLowerCase())) {
511
+ if (isSensitiveHeader(name)) {
469
512
  return '[REMOVED]';
470
513
  }
471
514
  return value;
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "browsertime",
3
3
  "description": "Get performance metrics from your web page using Browsertime.",
4
- "version": "27.4.1",
4
+ "version": "28.0.0",
5
5
  "bin": "./bin/browsertime.js",
6
6
  "type": "module",
7
7
  "types": "./scripting.d.ts",
8
8
  "dependencies": {
9
9
  "@devicefarmer/adbkit": "3.3.8",
10
- "@sitespeed.io/chromedriver": "148.0.7778",
11
- "@sitespeed.io/edgedriver": "148.0.3967",
10
+ "@sitespeed.io/chromedriver": "149.0.7827",
11
+ "@sitespeed.io/edgedriver": "149.0.4022",
12
12
  "@sitespeed.io/geckodriver": "0.36.2",
13
13
  "@sitespeed.io/log": "2.0.0",
14
- "@sitespeed.io/throttle": "6.0.0",
14
+ "@sitespeed.io/throttle": "6.0.1",
15
15
  "chrome-har": "1.3.1",
16
16
  "chrome-remote-interface": "0.34.0",
17
17
  "execa": "9.6.1",
@@ -40,7 +40,7 @@
40
40
  "typescript": "5.9.3"
41
41
  },
42
42
  "engines": {
43
- "node": ">=20.0.0"
43
+ "node": ">=22.0.0"
44
44
  },
45
45
  "files": [
46
46
  "CHANGELOG.md",
@@ -92,7 +92,7 @@
92
92
  "url": "https://github.com/sitespeedio/browsertime.git"
93
93
  },
94
94
  "homepage": "https://www.sitespeed.io/documentation/browsertime/",
95
- "license": "MIT",
95
+ "license": "Apache-2.0",
96
96
  "ava": {
97
97
  "files": [
98
98
  "test/**/*",
@@ -0,0 +1,11 @@
1
+ export function isResourceLoaderBundle(url: any, source: any): any;
2
+ export function labelForUrl(url: any): string;
3
+ export function labelForStyleAttributes(attributes: any): any;
4
+ export function resourceLoaderLocationResolver(source: any): {
5
+ resolve(lineNumber: any, columnNumber: any): {
6
+ name: any;
7
+ version: any;
8
+ };
9
+ };
10
+ export function resourceLoaderModuleCoverage(source: any, painted: any): any;
11
+ //# sourceMappingURL=mediawikiResourceLoader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediawikiResourceLoader.d.ts","sourceRoot":"","sources":["../../lib/chrome/mediawikiResourceLoader.js"],"names":[],"mappings":"AAmBA,mEAEC;AA6DD,8CAuBC;AAcD,8DAUC;AAwBD;;;;;EAkCC;AAOD,6EA4BC"}
@@ -1,27 +1,2 @@
1
- export function parseCPUTrace(tracelog: any, url: any): Promise<{
2
- categories: {
3
- parseHTML: number;
4
- styleLayout: number;
5
- paintCompositeRender: number;
6
- scriptParseCompile: number;
7
- scriptEvaluation: number;
8
- garbageCollection: number;
9
- other: number;
10
- };
11
- events: {};
12
- urls: {
13
- url: string;
14
- value: number;
15
- }[];
16
- scriptCosts: any[];
17
- forcedReflows: any[];
18
- nonCompositedAnimations: any[];
19
- } | {
20
- categories?: undefined;
21
- events?: undefined;
22
- urls?: undefined;
23
- scriptCosts?: undefined;
24
- forcedReflows?: undefined;
25
- nonCompositedAnimations?: undefined;
26
- }>;
1
+ export function parseCPUTrace(tracelog: any, url: any): Promise<{}>;
27
2
  //# sourceMappingURL=parseCpuTrace.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parseCpuTrace.d.ts","sourceRoot":"","sources":["../../lib/chrome/parseCpuTrace.js"],"names":[],"mappings":"AAkBA;;;;;;;;;;;;;;;;;;;;;;;;;GA2GC"}
1
+ {"version":3,"file":"parseCpuTrace.d.ts","sourceRoot":"","sources":["../../lib/chrome/parseCpuTrace.js"],"names":[],"mappings":"AAoCA,oEA8KC"}
@@ -0,0 +1,7 @@
1
+ export function computeBlockingTime(trace: any): {
2
+ totalBlockingTime: number;
3
+ tasks: any;
4
+ urls: any[];
5
+ kinds: {};
6
+ };
7
+ //# sourceMappingURL=blocking-time.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocking-time.d.ts","sourceRoot":"","sources":["../../../lib/chrome/trace/blocking-time.js"],"names":[],"mappings":"AAqJA;;;;;EAuCC"}
@@ -0,0 +1,11 @@
1
+ export function computeDomainBreakdown(trace: any, pageUrl: any): {
2
+ firstPartyDomain: any;
3
+ firstParty: number;
4
+ thirdParty: number;
5
+ domains: {
6
+ domain: any;
7
+ value: number;
8
+ firstParty: boolean;
9
+ }[];
10
+ };
11
+ //# sourceMappingURL=domain-breakdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain-breakdown.d.ts","sourceRoot":"","sources":["../../../lib/chrome/trace/domain-breakdown.js"],"names":[],"mappings":"AAmDA;;;;;;;;;EAkCC"}
@@ -0,0 +1,11 @@
1
+ export function computeFrameStability(trace: any): {
2
+ presented: number;
3
+ partial: number;
4
+ dropped: number;
5
+ effectiveFps: number;
6
+ longestGap: {
7
+ duration: number;
8
+ startTime: number;
9
+ };
10
+ };
11
+ //# sourceMappingURL=frame-stability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-stability.d.ts","sourceRoot":"","sources":["../../../lib/chrome/trace/frame-stability.js"],"names":[],"mappings":"AAwDA;;;;;;;;;EA8EC"}
@@ -0,0 +1,6 @@
1
+ export function computeFunctionCosts(trace: any, bundles: any): {
2
+ functionName: any;
3
+ selfTime: number;
4
+ totalTime: number;
5
+ }[];
6
+ //# sourceMappingURL=function-costs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"function-costs.d.ts","sourceRoot":"","sources":["../../../lib/chrome/trace/function-costs.js"],"names":[],"mappings":"AAyFA;;;;IA+LC"}
@@ -16,4 +16,11 @@ export function computeMainThreadTasks(trace: any, options?: {
16
16
  export { computeScriptCosts } from "./script-costs.js";
17
17
  export { computeForcedReflows } from "./forced-reflows.js";
18
18
  export { computeNonCompositedAnimations } from "./non-composited-animations.js";
19
+ export { computeFrameStability } from "./frame-stability.js";
20
+ export { computeFunctionCosts } from "./function-costs.js";
21
+ export { computeStyleInvalidations } from "./style-invalidations.js";
22
+ export { computeSelectorStats } from "./selector-stats.js";
23
+ export { computeTimerCosts } from "./timer-costs.js";
24
+ export { computeBlockingTime } from "./blocking-time.js";
25
+ export { computeDomainBreakdown } from "./domain-breakdown.js";
19
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/chrome/trace/index.js"],"names":[],"mappings":"AAkBA;;;;;;;;;;;GAWG;AACH,6DAJG;IAA0B,OAAO,GAAzB,OAAO;CAEf,GAAU,KAAK,KAAQ,CAYzB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/chrome/trace/index.js"],"names":[],"mappings":"AAyBA;;;;;;;;;;;GAWG;AACH,6DAJG;IAA0B,OAAO,GAAzB,OAAO;CAEf,GAAU,KAAK,KAAQ,CAYzB"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @param {Object} trace Parsed Chrome trace.json (with .traceEvents).
3
+ * @param {Map<string, {resolve: Function}>} bundles Bundle URL →
4
+ * location resolver, built while collecting coverage.
5
+ * @returns {Array<{url:string,
6
+ * modules:Array<{name:string, version:string, selfTime:number}>,
7
+ * otherTime:number}>}
8
+ */
9
+ export function computeModuleCosts(trace: any, bundles: Map<string, {
10
+ resolve: Function;
11
+ }>): Array<{
12
+ url: string;
13
+ modules: Array<{
14
+ name: string;
15
+ version: string;
16
+ selfTime: number;
17
+ }>;
18
+ otherTime: number;
19
+ }>;
20
+ //# sourceMappingURL=module-costs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-costs.d.ts","sourceRoot":"","sources":["../../../lib/chrome/trace/module-costs.js"],"names":[],"mappings":"AAqFA;;;;;;;GAOG;AACH,wDANW,GAAG,CAAC,MAAM,EAAE;IAAC,OAAO,WAAU;CAAC,CAAC,GAE9B,KAAK,CAAC;IAAC,GAAG,EAAC,MAAM,CAAC;IAC1B,OAAO,EAAC,KAAK,CAAC;QAAC,IAAI,EAAC,MAAM,CAAC;QAAC,OAAO,EAAC,MAAM,CAAC;QAAC,QAAQ,EAAC,MAAM,CAAA;KAAC,CAAC,CAAC;IAC9D,SAAS,EAAC,MAAM,CAAA;CAAC,CAAC,CA6CtB"}