@paulirish/trace_engine 0.0.61 → 0.0.62
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.
- package/.tmp/tsbuildinfo/analyze-trace.d.mts.map +1 -1
- package/.tmp/tsbuildinfo/tsconfig.tsbuildinfo +1 -1
- package/analyze-inspector-issues.mjs +1 -1
- package/analyze-trace.mjs +1 -2
- package/core/platform/ArrayUtilities.d.ts +2 -0
- package/core/platform/ArrayUtilities.js +11 -1
- package/core/platform/ArrayUtilities.js.map +1 -1
- package/core/platform/HostRuntime.d.ts +4 -0
- package/core/platform/HostRuntime.js +25 -0
- package/core/platform/HostRuntime.js.map +1 -0
- package/core/platform/KeyboardUtilities.d.ts +6 -2
- package/core/platform/KeyboardUtilities.js.map +1 -1
- package/core/platform/StringUtilities.d.ts +2 -0
- package/core/platform/StringUtilities.js +64 -13
- package/core/platform/StringUtilities.js.map +1 -1
- package/core/platform/api/HostRuntime.d.ts +36 -0
- package/core/platform/api/HostRuntime.js +5 -0
- package/core/platform/api/HostRuntime.js.map +1 -0
- package/core/platform/api/api-tsconfig.json +43 -0
- package/core/platform/api/api.d.ts +2 -0
- package/core/platform/api/api.js +6 -0
- package/core/platform/api/api.js.map +1 -0
- package/core/platform/api/api_node_typecheck-tsconfig.json +48 -0
- package/core/platform/api/bundle-tsconfig.json +1 -0
- package/core/platform/api/devtools_entrypoint-bundle-typescript-tsconfig.json +48 -0
- package/core/platform/browser/HostRuntime.d.ts +2 -0
- package/core/platform/browser/HostRuntime.js +64 -0
- package/core/platform/browser/HostRuntime.js.map +1 -0
- package/core/platform/browser/browser-tsconfig.json +48 -0
- package/core/platform/browser/browser.d.ts +2 -0
- package/core/platform/browser/browser.js +6 -0
- package/core/platform/browser/browser.js.map +1 -0
- package/core/platform/browser/bundle-tsconfig.json +1 -0
- package/core/platform/browser/devtools_entrypoint-bundle-typescript-tsconfig.json +48 -0
- package/core/platform/devtools_entrypoint-bundle-typescript-tsconfig.json +4 -3
- package/core/platform/node/HostRuntime.d.ts +2 -0
- package/core/platform/node/HostRuntime.js +73 -0
- package/core/platform/node/HostRuntime.js.map +1 -0
- package/core/platform/node/bundle-tsconfig.json +1 -0
- package/core/platform/node/devtools_entrypoint-bundle-typescript-tsconfig.json +48 -0
- package/core/platform/node/node-tsconfig.json +52 -0
- package/core/platform/node/node.d.ts +2 -0
- package/core/platform/node/node.js +6 -0
- package/core/platform/node/node.js.map +1 -0
- package/core/platform/platform-tsconfig.json +17 -5
- package/core/platform/platform.d.ts +2 -2
- package/core/platform/platform.js +2 -2
- package/core/platform/platform.js.map +1 -1
- package/core/platform/platform_node_typecheck-tsconfig.json +74 -0
- package/generated/protocol.d.ts +1507 -583
- package/locales/af.json +74 -38
- package/locales/am.json +73 -37
- package/locales/ar.json +72 -36
- package/locales/as.json +74 -38
- package/locales/az.json +73 -37
- package/locales/be.json +72 -36
- package/locales/bg.json +72 -36
- package/locales/bn.json +74 -38
- package/locales/bs.json +72 -36
- package/locales/ca.json +72 -36
- package/locales/cs.json +72 -36
- package/locales/cy.json +73 -37
- package/locales/da.json +74 -38
- package/locales/de.json +72 -36
- package/locales/el.json +73 -37
- package/locales/en-GB.json +74 -38
- package/locales/en-US.json +86 -17
- package/locales/en-XL.json +86 -17
- package/locales/es-419.json +72 -36
- package/locales/es.json +73 -37
- package/locales/et.json +74 -38
- package/locales/eu.json +72 -36
- package/locales/fa.json +73 -37
- package/locales/fi.json +72 -36
- package/locales/fil.json +74 -38
- package/locales/fr-CA.json +72 -36
- package/locales/fr.json +162 -126
- package/locales/gl.json +73 -37
- package/locales/gu.json +73 -37
- package/locales/he.json +74 -38
- package/locales/hi.json +73 -37
- package/locales/hr.json +72 -36
- package/locales/hu.json +73 -37
- package/locales/hy.json +73 -37
- package/locales/id.json +74 -38
- package/locales/is.json +73 -37
- package/locales/it.json +72 -36
- package/locales/ja.json +72 -36
- package/locales/ka.json +73 -37
- package/locales/kk.json +72 -36
- package/locales/km.json +73 -37
- package/locales/kn.json +72 -36
- package/locales/ko.json +72 -36
- package/locales/ky.json +72 -36
- package/locales/lo.json +72 -36
- package/locales/lt.json +72 -36
- package/locales/lv.json +72 -36
- package/locales/mk.json +75 -39
- package/locales/ml.json +72 -36
- package/locales/mn.json +73 -37
- package/locales/mr.json +74 -38
- package/locales/ms.json +72 -36
- package/locales/my.json +72 -36
- package/locales/ne.json +73 -37
- package/locales/nl.json +73 -37
- package/locales/no.json +72 -36
- package/locales/or.json +72 -36
- package/locales/pa.json +72 -36
- package/locales/pl.json +72 -36
- package/locales/pt-PT.json +72 -36
- package/locales/pt.json +74 -38
- package/locales/ro.json +72 -36
- package/locales/ru.json +72 -36
- package/locales/si.json +72 -36
- package/locales/sk.json +72 -36
- package/locales/sl.json +72 -36
- package/locales/sq.json +72 -36
- package/locales/sr-Latn.json +73 -37
- package/locales/sr.json +73 -37
- package/locales/sv.json +75 -39
- package/locales/sw.json +74 -38
- package/locales/ta.json +73 -37
- package/locales/te.json +72 -36
- package/locales/th.json +73 -37
- package/locales/tr.json +72 -36
- package/locales/uk.json +72 -36
- package/locales/ur.json +72 -36
- package/locales/uz.json +73 -37
- package/locales/vi.json +74 -38
- package/locales/zh-HK.json +72 -36
- package/locales/zh-TW.json +74 -38
- package/locales/zh.json +75 -39
- package/locales/zu.json +73 -37
- package/models/cpu_profile/CPUProfileDataModel.d.ts +9 -0
- package/models/cpu_profile/CPUProfileDataModel.js +9 -7
- package/models/cpu_profile/CPUProfileDataModel.js.map +1 -1
- package/models/cpu_profile/ProfileTreeModel.d.ts +3 -2
- package/models/cpu_profile/ProfileTreeModel.js +6 -7
- package/models/cpu_profile/ProfileTreeModel.js.map +1 -1
- package/models/cpu_profile/cpu_profile-tsconfig.json +4 -3
- package/models/cpu_profile/devtools_entrypoint-bundle-typescript-tsconfig.json +4 -3
- package/models/trace/EntityMapper.d.ts +1 -0
- package/models/trace/EntityMapper.js +10 -0
- package/models/trace/EntityMapper.js.map +1 -1
- package/models/trace/EventsSerializer.js +10 -2
- package/models/trace/EventsSerializer.js.map +1 -1
- package/models/trace/LanternComputationData.d.ts +1 -1
- package/models/trace/LanternComputationData.js +3 -8
- package/models/trace/LanternComputationData.js.map +1 -1
- package/models/trace/ModelImpl.d.ts +1 -0
- package/models/trace/ModelImpl.js +9 -6
- package/models/trace/ModelImpl.js.map +1 -1
- package/models/trace/Processor.js +23 -23
- package/models/trace/Processor.js.map +1 -1
- package/models/trace/Styles.js +13 -5
- package/models/trace/Styles.js.map +1 -1
- package/models/trace/devtools_entrypoint-bundle-typescript-tsconfig.json +4 -3
- package/models/trace/extras/Initiators.d.ts +12 -0
- package/models/trace/extras/Initiators.js +47 -0
- package/models/trace/extras/Initiators.js.map +1 -0
- package/models/trace/extras/TraceTree.js +13 -5
- package/models/trace/extras/TraceTree.js.map +1 -1
- package/models/trace/extras/devtools_entrypoint-bundle-typescript-tsconfig.json +4 -3
- package/models/trace/extras/extras-tsconfig.json +11 -3
- package/models/trace/extras/extras.d.ts +0 -1
- package/models/trace/extras/extras.js +0 -1
- package/models/trace/extras/extras.js.map +1 -1
- package/models/trace/handlers/LargestImagePaintHandler.js +2 -2
- package/models/trace/handlers/LargestImagePaintHandler.js.map +1 -1
- package/models/trace/handlers/LayoutShiftsHandler.js +1 -1
- package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
- package/models/trace/handlers/MetaHandler.d.ts +12 -1
- package/models/trace/handlers/MetaHandler.js +10 -1
- package/models/trace/handlers/MetaHandler.js.map +1 -1
- package/models/trace/handlers/NetworkRequestsHandler.d.ts +8 -1
- package/models/trace/handlers/NetworkRequestsHandler.js +22 -4
- package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
- package/models/trace/handlers/PageLoadMetricsHandler.d.ts +13 -3
- package/models/trace/handlers/PageLoadMetricsHandler.js +71 -27
- package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
- package/models/trace/handlers/SamplesHandler.js +59 -6
- package/models/trace/handlers/SamplesHandler.js.map +1 -1
- package/models/trace/handlers/ScriptsHandler.js +24 -0
- package/models/trace/handlers/ScriptsHandler.js.map +1 -1
- package/models/trace/handlers/devtools_entrypoint-bundle-typescript-tsconfig.json +4 -3
- package/models/trace/handlers/handlers-tsconfig.json +13 -3
- package/models/trace/helpers/Network.js +1 -1
- package/models/trace/helpers/Network.js.map +1 -1
- package/models/trace/helpers/SamplesIntegrator.js +1 -8
- package/models/trace/helpers/SamplesIntegrator.js.map +1 -1
- package/models/trace/helpers/Timing.d.ts +1 -1
- package/models/trace/helpers/Timing.js +9 -2
- package/models/trace/helpers/Timing.js.map +1 -1
- package/models/trace/helpers/Trace.d.ts +1 -0
- package/models/trace/helpers/Trace.js +12 -5
- package/models/trace/helpers/Trace.js.map +1 -1
- package/models/trace/helpers/devtools_entrypoint-bundle-typescript-tsconfig.json +4 -3
- package/models/trace/helpers/helpers-tsconfig.json +7 -3
- package/models/trace/insights/CharacterSet.d.ts +49 -0
- package/models/trace/insights/CharacterSet.js +132 -0
- package/models/trace/insights/CharacterSet.js.map +1 -0
- package/models/trace/insights/Common.d.ts +2 -2
- package/models/trace/insights/Common.js +1 -6
- package/models/trace/insights/Common.js.map +1 -1
- package/models/trace/insights/ForcedReflow.d.ts +1 -1
- package/models/trace/insights/ForcedReflow.js +1 -1
- package/models/trace/insights/ForcedReflow.js.map +1 -1
- package/models/trace/insights/LCPBreakdown.d.ts +1 -1
- package/models/trace/insights/LCPBreakdown.js +2 -2
- package/models/trace/insights/LCPBreakdown.js.map +1 -1
- package/models/trace/insights/LCPDiscovery.d.ts +7 -3
- package/models/trace/insights/LCPDiscovery.js +16 -10
- package/models/trace/insights/LCPDiscovery.js.map +1 -1
- package/models/trace/insights/Models.d.ts +1 -0
- package/models/trace/insights/Models.js +1 -0
- package/models/trace/insights/Models.js.map +1 -1
- package/models/trace/insights/NetworkDependencyTree.js +4 -3
- package/models/trace/insights/NetworkDependencyTree.js.map +1 -1
- package/models/trace/insights/RenderBlocking.d.ts +2 -2
- package/models/trace/insights/RenderBlocking.js +6 -6
- package/models/trace/insights/RenderBlocking.js.map +1 -1
- package/models/trace/insights/devtools_entrypoint-bundle-typescript-tsconfig.json +4 -3
- package/models/trace/insights/insights-tsconfig.json +26 -3
- package/models/trace/insights/types.d.ts +15 -5
- package/models/trace/insights/types.js +1 -0
- package/models/trace/insights/types.js.map +1 -1
- package/models/trace/lantern/core/core-tsconfig.json +4 -3
- package/models/trace/lantern/core/devtools_entrypoint-bundle-typescript-tsconfig.json +4 -3
- package/models/trace/lantern/devtools_entrypoint-bundle-typescript-tsconfig.json +4 -3
- package/models/trace/lantern/graph/devtools_entrypoint-bundle-typescript-tsconfig.json +4 -3
- package/models/trace/lantern/graph/graph-tsconfig.json +4 -3
- package/models/trace/lantern/lantern-tsconfig.json +4 -3
- package/models/trace/lantern/metrics/FirstContentfulPaint.js +6 -6
- package/models/trace/lantern/metrics/FirstContentfulPaint.js.map +1 -1
- package/models/trace/lantern/metrics/devtools_entrypoint-bundle-typescript-tsconfig.json +4 -3
- package/models/trace/lantern/metrics/metrics-tsconfig.json +4 -3
- package/models/trace/lantern/simulation/devtools_entrypoint-bundle-typescript-tsconfig.json +4 -3
- package/models/trace/lantern/simulation/simulation-tsconfig.json +4 -3
- package/models/trace/lantern/types/Lantern.d.ts +7 -7
- package/models/trace/lantern/types/Lantern.js.map +1 -1
- package/models/trace/lantern/types/devtools_entrypoint-bundle-typescript-tsconfig.json +4 -3
- package/models/trace/lantern/types/types-tsconfig.json +4 -3
- package/models/trace/trace-tsconfig.json +7 -3
- package/models/trace/types/Configuration.d.ts +1 -4
- package/models/trace/types/Configuration.js +0 -1
- package/models/trace/types/Configuration.js.map +1 -1
- package/models/trace/types/File.d.ts +8 -0
- package/models/trace/types/File.js.map +1 -1
- package/models/trace/types/TraceEvents.d.ts +97 -15
- package/models/trace/types/TraceEvents.js +44 -11
- package/models/trace/types/TraceEvents.js.map +1 -1
- package/models/trace/types/devtools_entrypoint-bundle-typescript-tsconfig.json +4 -3
- package/models/trace/types/types-tsconfig.json +10 -3
- package/package.json +1 -1
- package/test/test-trace-engine.mjs +8 -9
- package/.tmp/tsbuildinfo/models/trace/extras/polyfills.d.ts +0 -4
- package/.tmp/tsbuildinfo/models/trace/extras/polyfills.d.ts.map +0 -1
- package/core/platform/DOMUtilities.d.ts +0 -16
- package/core/platform/DOMUtilities.js +0 -123
- package/core/platform/DOMUtilities.js.map +0 -1
|
@@ -212,7 +212,7 @@ export class TraceProcessor extends EventTarget {
|
|
|
212
212
|
}
|
|
213
213
|
return this.#insights;
|
|
214
214
|
}
|
|
215
|
-
#createLanternContext(data, traceEvents, frameId,
|
|
215
|
+
#createLanternContext(data, traceEvents, frameId, navigation, options) {
|
|
216
216
|
// Check for required handlers.
|
|
217
217
|
if (!data.NetworkRequests || !data.Workers || !data.PageLoadMetrics) {
|
|
218
218
|
return;
|
|
@@ -221,7 +221,7 @@ export class TraceProcessor extends EventTarget {
|
|
|
221
221
|
throw new Lantern.Core.LanternError('No network requests found in trace');
|
|
222
222
|
}
|
|
223
223
|
const navStarts = data.Meta.navigationsByFrameId.get(frameId);
|
|
224
|
-
const navStartIndex = navStarts?.findIndex(n => n
|
|
224
|
+
const navStartIndex = navStarts?.findIndex(n => n === navigation);
|
|
225
225
|
if (!navStarts || navStartIndex === undefined || navStartIndex === -1) {
|
|
226
226
|
throw new Lantern.Core.LanternError('Could not find navigation start');
|
|
227
227
|
}
|
|
@@ -235,7 +235,7 @@ export class TraceProcessor extends EventTarget {
|
|
|
235
235
|
};
|
|
236
236
|
const requests = LanternComputationData.createNetworkRequests(trace, data, startTime, endTime);
|
|
237
237
|
const graph = LanternComputationData.createGraph(requests, trace, data);
|
|
238
|
-
const processedNavigation = LanternComputationData.createProcessedNavigation(data, frameId,
|
|
238
|
+
const processedNavigation = LanternComputationData.createProcessedNavigation(data, frameId, navigation);
|
|
239
239
|
const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests);
|
|
240
240
|
if (!networkAnalysis) {
|
|
241
241
|
return;
|
|
@@ -285,6 +285,7 @@ export class TraceProcessor extends EventTarget {
|
|
|
285
285
|
SlowCSSSelector: null,
|
|
286
286
|
ForcedReflow: null,
|
|
287
287
|
Cache: null,
|
|
288
|
+
CharacterSet: null,
|
|
288
289
|
ModernHTTP: null,
|
|
289
290
|
LegacyJavaScript: null,
|
|
290
291
|
};
|
|
@@ -304,10 +305,10 @@ export class TraceProcessor extends EventTarget {
|
|
|
304
305
|
const observedInpScore = Insights.Common.evaluateINPMetricScore(observedInp);
|
|
305
306
|
const observedClsScore = Insights.Common.evaluateCLSMetricScore(observedCls);
|
|
306
307
|
const insightToSortingRank = new Map();
|
|
307
|
-
for (const [name,
|
|
308
|
-
const lcp =
|
|
309
|
-
const inp =
|
|
310
|
-
const cls =
|
|
308
|
+
for (const [name, insight] of Object.entries(insightSet.model)) {
|
|
309
|
+
const lcp = insight.metricSavings?.LCP ?? 0;
|
|
310
|
+
const inp = insight.metricSavings?.INP ?? 0;
|
|
311
|
+
const cls = insight.metricSavings?.CLS ?? 0;
|
|
311
312
|
const lcpPostSavings = observedLcp !== undefined ? Math.max(0, observedLcp - lcp) : undefined;
|
|
312
313
|
const inpPostSavings = Math.max(0, observedInp - inp);
|
|
313
314
|
const clsPostSavings = Math.max(0, observedCls - cls);
|
|
@@ -351,9 +352,12 @@ export class TraceProcessor extends EventTarget {
|
|
|
351
352
|
}
|
|
352
353
|
#computeInsightSet(data, context) {
|
|
353
354
|
const logger = context.options.logger;
|
|
355
|
+
if (!this.#insights) {
|
|
356
|
+
this.#insights = new Map();
|
|
357
|
+
}
|
|
354
358
|
let id, urlString, navigation;
|
|
355
359
|
if (context.navigation) {
|
|
356
|
-
id =
|
|
360
|
+
id = `NAVIGATION_${this.#insights.size}`;
|
|
357
361
|
urlString = data.Meta.finalDisplayUrlByNavigationId.get(context.navigationId) ?? data.Meta.mainFrameURL;
|
|
358
362
|
navigation = context.navigation;
|
|
359
363
|
}
|
|
@@ -362,28 +366,28 @@ export class TraceProcessor extends EventTarget {
|
|
|
362
366
|
urlString = data.Meta.finalDisplayUrlByNavigationId.get('') ?? data.Meta.mainFrameURL;
|
|
363
367
|
}
|
|
364
368
|
const insightSetModel = {};
|
|
369
|
+
const insightSetModelErrors = {};
|
|
365
370
|
for (const [name, insight] of Object.entries(_a.getInsightRunners())) {
|
|
366
|
-
let model;
|
|
367
371
|
try {
|
|
368
372
|
logger?.start(`insights:${name}`);
|
|
369
|
-
model = insight.generateInsight(data, context);
|
|
373
|
+
const model = insight.generateInsight(data, context);
|
|
370
374
|
model.frameId = context.frameId;
|
|
371
375
|
const navId = context.navigation?.args.data?.navigationId;
|
|
372
376
|
if (navId) {
|
|
373
|
-
model.
|
|
377
|
+
model.navigation = context.navigation;
|
|
374
378
|
}
|
|
375
379
|
model.createOverlays = () => {
|
|
376
380
|
// @ts-expect-error: model is a union of all possible insight model types.
|
|
377
381
|
return insight.createOverlays(model);
|
|
378
382
|
};
|
|
383
|
+
Object.assign(insightSetModel, { [name]: model });
|
|
379
384
|
}
|
|
380
385
|
catch (err) {
|
|
381
|
-
|
|
386
|
+
Object.assign(insightSetModelErrors, { [name]: err });
|
|
382
387
|
}
|
|
383
388
|
finally {
|
|
384
389
|
logger?.end(`insights:${name}`);
|
|
385
390
|
}
|
|
386
|
-
Object.assign(insightSetModel, { [name]: model });
|
|
387
391
|
}
|
|
388
392
|
// We may choose to exclude the insightSet if it's trivial. Trivial means:
|
|
389
393
|
// 1. There's no navigation (it's an initial trace period)
|
|
@@ -393,12 +397,10 @@ export class TraceProcessor extends EventTarget {
|
|
|
393
397
|
// Generally, these cases are the short time ranges before a page reload starts.
|
|
394
398
|
const isNavigation = id === Types.Events.NO_NAVIGATION;
|
|
395
399
|
const trivialThreshold = Helpers.Timing.milliToMicro(Types.Timing.Milli(5000));
|
|
396
|
-
const everyInsightPasses = Object.values(insightSetModel)
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
const
|
|
400
|
-
const noInp = !insightSetModel.INPBreakdown.longestInteractionEvent;
|
|
401
|
-
const noLayoutShifts = insightSetModel.CLSCulprits.shifts?.size === 0;
|
|
400
|
+
const everyInsightPasses = Object.values(insightSetModel).every(model => model && model.state === 'pass');
|
|
401
|
+
const noLcp = !insightSetModel.LCPBreakdown?.lcpEvent;
|
|
402
|
+
const noInp = !insightSetModel.INPBreakdown?.longestInteractionEvent;
|
|
403
|
+
const noLayoutShifts = insightSetModel.CLSCulprits?.shifts?.size === 0;
|
|
402
404
|
const shouldExclude = isNavigation && context.bounds.range < trivialThreshold && everyInsightPasses && noLcp &&
|
|
403
405
|
noInp && noLayoutShifts;
|
|
404
406
|
if (shouldExclude) {
|
|
@@ -420,10 +422,8 @@ export class TraceProcessor extends EventTarget {
|
|
|
420
422
|
frameId: context.frameId,
|
|
421
423
|
bounds: context.bounds,
|
|
422
424
|
model: insightSetModel,
|
|
425
|
+
modelErrors: insightSetModelErrors,
|
|
423
426
|
};
|
|
424
|
-
if (!this.#insights) {
|
|
425
|
-
this.#insights = new Map();
|
|
426
|
-
}
|
|
427
427
|
this.#insights.set(insightSet.id, insightSet);
|
|
428
428
|
this.sortInsightSet(insightSet, context.options.metadata ?? null);
|
|
429
429
|
}
|
|
@@ -474,7 +474,7 @@ export class TraceProcessor extends EventTarget {
|
|
|
474
474
|
let lantern;
|
|
475
475
|
try {
|
|
476
476
|
options.logger?.start('insights:createLanternContext');
|
|
477
|
-
lantern = this.#createLanternContext(data, traceEvents, frameId,
|
|
477
|
+
lantern = this.#createLanternContext(data, traceEvents, frameId, navigation, options);
|
|
478
478
|
}
|
|
479
479
|
catch (e) {
|
|
480
480
|
// Handle Lantern errors gracefully
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Processor.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/Processor.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,yEAAyE;AACzE,6BAA6B;;AAE7B,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,sBAAsB,CAAC;AAChD,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,sBAAsB,CAAC;AAChD,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AAEtE,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC;AAS1C,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAE7B;IADnB,MAAM,CAAU,SAAS,GAAG,oBAAoB,CAAC;IACjD,YAAmB,IAAuC,EAAE,OAAkB,EAAC,OAAO,EAAE,IAAI,EAAC;QAC3F,KAAK,CAAC,uBAAuB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAD9B,SAAI,GAAJ,IAAI,CAAmC;IAE1D,CAAC;;AAeH,SAAS,iBAAiB,CAAC,KAAa,EAAE,KAAoB;IAC5D,wCAAwC;IACxC,IAAI,KAAK,qCAA2B,EAAE,CAAC;QACrC,OAAO,CAAC,KAAK,GAAG,CAAC,uEAAmD,CAAC,CAAC,uCAA6B,CAAC;IACtG,CAAC;IACD,OAAO,KAAK,GAAG,KAAK,CAAC;AACvB,CAAC;AAQD,MAAM,OAAO,cAAe,SAAQ,WAAW;IAC7C,6EAA6E;IAC7E,8DAA8D;IACrD,cAAc,CAAmC;IAC1D,OAAO,4BAAe;IACtB,mBAAmB,GAAG,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;IACrD,KAAK,GAAoC,IAAI,CAAC;IAC9C,SAAS,GAAyC,IAAI,CAAC;IAEvD,MAAM,CAAC,qBAAqB;QAC1B,OAAO,IAAI,EAAc,CAAC,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,CAAC;IACpF,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,iBAAiB;QACtB,OAAO,EAAC,GAAG,QAAQ,CAAC,MAAM,EAAC,CAAC;IAC9B,CAAC;IAED,YAAY,aAA+C,EAAE,kBAAsD;QACjH,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;QACpC,IAAI,CAAC,cAAc,GAAG;YACpB,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,IAAI;YACjC,GAAG,aAAa;SACjB,CAAC;QACF,IAAI,kBAAkB,EAAE,CAAC;YACvB,IAAI,CAAC,mBAAmB,GAAG,kBAAkB,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,qBAAqB,EAAE,CAAC;IAC/B,CAAC;IAED,qBAAqB;QACnB,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;YACzD,yEAAyE;YACzE,4DAA4D;YAC5D,IAAI,kBAAkB,IAAI,OAAO,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;gBAC9D,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;QAMI;IACJ,eAAe,CAAC,gBAAkD;QAChE,2EAA2E;QAC3E,wEAAwE;QACxE,0EAA0E;QAC1E,uEAAuE;QACvE,0BAA0B;QAC1B,IAAI,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,MAAM,EAAE,CAAC;YACxF,OAAO;QACT,CAAC;QACD,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAA8B,CAAC;QAClE,KAAK,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACtE,mBAAmB,CAAC,GAAG,CAAC,WAAyC,CAAC,CAAC;YACnE,MAAM,IAAI,GAAG,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrD,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;gBAC3B,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAED,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;QACnE,mEAAmE;QACnE,2EAA2E;QAC3E,qCAAqC;QACrC,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAEnC,KAAK,MAAM,WAAW,IAAI,mBAAmB,EAAE,CAAC;YAC9C,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC1C,MAAM,IAAI,KAAK,CAAC,oBAAoB,WAAW,gBAAgB,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,OAAO,mCAAmB,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACpD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,OAAO,2BAAc,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,WAA0C,EAAE,OAAyC;QAC/F,IAAI,IAAI,CAAC,OAAO,6BAAgB,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,qEAAqE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACvG,CAAC;QAED,IAAI,OAAO,OAAO,CAAC,YAAY,KAAK,WAAW,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACpE,OAAO,CAAC,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,UAAU,KAAK,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QAC3F,CAAC;QAED,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,CAAC;YACH,IAAI,CAAC,OAAO,iCAAiB,CAAC;YAC9B,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAC/B,MAAM,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACrD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;YAC7B,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAE,iDAAiD;gBAC3F,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;gBAClC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;gBACxD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;YAClC,CAAC;YACD,IAAI,CAAC,OAAO,mDAA0B,CAAC;QACzC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,OAAO,6DAA+B,CAAC;YAC5C,MAAM,CAAC,CAAC;QACV,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,mBAAmB,CAAC,WAA0C,EAAE,OAAyC;QAE7G;;;;;;;WAOG;QACH,MAAM,cAAc,GAAG,MAAM,CAAC;QAC9B,+EAA+E;QAC/E,MAAM,cAAc,GAAG,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAExE,SAAS;QACT,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,cAAc,EAAE,CAAC;YACzC,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;QAED,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAE3C,qBAAqB;QACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;YAC5C,iDAAiD;YACjD,IAAI,CAAC,GAAG,cAAc,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClC,wDAAwD;gBACxD,MAAM,OAAO,GAAG,iBAAiB,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,uCAA6B,CAAC;gBACtF,IAAI,CAAC,aAAa,CAAC,IAAI,uBAAuB,CAAC,EAAC,OAAO,EAAC,CAAC,CAAC,CAAC;gBAC3D,qHAAqH;gBACrH,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YACvD,CAAC;YACD,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;gBAC/C,MAAM,CAAC,EAAE,OAAO,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;gBACtC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QAED,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,mBAAmB,CAAC,CAAC;QAEzC,YAAY;QACZ,MAAM,eAAe,GAAmC;YACtD,GAAG,OAAO;YACV,cAAc,EAAE,WAAW;SAC5B,CAAC;QACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;YAC1C,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACrB,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,IAAI,WAAW,CAAC,CAAC;gBAChD,4DAA4D;gBAC5D,yHAAyH;gBACzH,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;gBACrD,MAAM,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;gBACxC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,SAAS,IAAI,WAAW,CAAC,CAAC;YAChD,CAAC;YACD,MAAM,OAAO,GAAG,iBAAiB,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,mCAAyB,CAAC;YACrF,IAAI,CAAC,aAAa,CAAC,IAAI,uBAAuB,CAAC,EAAC,OAAO,EAAC,CAAC,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC9C,MAAM,WAAW,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;YAClE,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,EAAC,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,EAAE,EAAC,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,sBAAsB,CAAC,CAAC;QAE5C,IAAI,CAAC,aAAa,CAAC,IAAI,uBAAuB,CAAC,EAAC,OAAO,6BAAqB,EAAC,CAAC,CAAC,CAAC;QAEhF,IAAI,CAAC,KAAK,GAAG,WAAyC,CAAC;IACzD,CAAC;IAED,IAAI,IAAI;QACN,IAAI,IAAI,CAAC,OAAO,qDAA4B,EAAE,CAAC;YAC7C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,IAAI,QAAQ;QACV,IAAI,IAAI,CAAC,OAAO,qDAA4B,EAAE,CAAC;YAC7C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,qBAAqB,CACjB,IAAgC,EAAE,WAA0C,EAAE,OAAe,EAC7F,YAAoB,EAAE,OAAyC;QACjE,+BAA+B;QAC/B,IAAI,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YACpE,OAAO;QACT,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACxC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,oCAAoC,CAAC,CAAC;QAC5E,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC9D,MAAM,aAAa,GAAG,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,KAAK,YAAY,CAAC,CAAC;QAC5F,IAAI,CAAC,SAAS,IAAI,aAAa,KAAK,SAAS,IAAI,aAAa,KAAK,CAAC,CAAC,EAAE,CAAC;YACtE,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,iCAAiC,CAAC,CAAC;QACzE,CAAC;QAED,MAAM,SAAS,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAG,aAAa,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;QAClH,MAAM,kBAAkB,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,SAAS,IAAI,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC;QAExF,qEAAqE;QACrE,4GAA4G;QAC5G,MAAM,KAAK,GAAwB;YACjC,WAAW,EAAE,kBAA2D;SACzE,CAAC;QAEF,MAAM,QAAQ,GAAG,sBAAsB,CAAC,qBAAqB,CAAC,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAC/F,MAAM,KAAK,GAAG,sBAAsB,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QACxE,MAAM,mBAAmB,GAAG,sBAAsB,CAAC,yBAAyB,CAAC,IAAI,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;QAE1G,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACvE,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QAED,MAAM,eAAe,GAAsC;YACzD,+FAA+F;YAC/F,uDAAuD;YACvD,eAAe;YACf,gBAAgB,EAAE,UAAU;YAC5B,GAAG,OAAO,CAAC,eAAe;SAC3B,CAAC;QACF,MAAM,SAAS,GACX,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;QAElE,MAAM,WAAW,GAAG,EAAC,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC5E,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,WAAW,EAAE,EAAC,SAAS,EAAC,CAAC,CAAC;QAC3F,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,EAAC,SAAS,EAAC,CAAC,CAAC;QACxF,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,WAAW,EAAE,EAAC,SAAS,EAAE,iBAAiB,EAAC,CAAC,CAAC;QACzG,MAAM,OAAO,GAAG;YACd,oBAAoB,EAAE,SAAS;YAC/B,WAAW,EAAE,iBAAiB;YAC9B,sBAAsB,EAAE,SAAS;YACjC,iBAAiB,EAAE,SAAS;SAC7B,CAAC;QAEF,OAAO,EAAC,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAC,CAAC;IAC/C,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,UAAqC,EAAE,QAAkC;QACtF,2GAA2G;QAC3G,iFAAiF;QACjF,MAAM,aAAa,GAAqD;YACtE,YAAY,EAAE,IAAI;YAClB,YAAY,EAAE,IAAI;YAClB,YAAY,EAAE,IAAI;YAClB,WAAW,EAAE,IAAI;YACjB,cAAc,EAAE,IAAI;YACpB,qBAAqB,EAAE,IAAI;YAC3B,aAAa,EAAE,IAAI;YACnB,eAAe,EAAE,IAAI;YACrB,WAAW,EAAE,IAAI;YACjB,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,IAAI;YACb,YAAY,EAAE,IAAI;YAClB,oBAAoB,EAAE,IAAI;YAC1B,eAAe,EAAE,IAAI;YACrB,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,IAAI;YAChB,gBAAgB,EAAE,IAAI;SACvB,CAAC;QAEF,oHAAoH;QACpH,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,gCAAgC,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAEvF,sFAAsF;QACtF,+EAA+E;QAC/E,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC;QACnE,MAAM,WAAW,GAAG,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC7G,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC;QAE7D,mGAAmG;QACnG,mGAAmG;QACnG,wCAAwC;QACxC,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC;QACnE,MAAM,WAAW,GAAG,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAE/G,MAAM,gBAAgB,GAClB,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAChG,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC;QAC7E,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC;QAE7E,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAkB,CAAC;QACvD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7D,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,CAAC;YAC1C,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,CAAC;YAC1C,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,CAAC;YAE1C,MAAM,cAAc,GAChB,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,GAAG,CAAuB,CAAC,CAAC,CAAC,SAAS,CAAC;YACjG,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,GAAG,CAAuB,CAAC;YAC5E,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,GAAG,GAAG,CAAC,CAAC;YAEtD,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,IAAI,OAAO,CAAC,GAAG,IAAI,GAAG,IAAI,gBAAgB,KAAK,SAAS,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;gBACzF,KAAK,IAAI,OAAO,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CAAC,cAAc,CAAC,GAAG,gBAAgB,CAAC,CAAC;YACrG,CAAC;YACD,IAAI,OAAO,CAAC,GAAG,IAAI,GAAG,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;gBACzD,KAAK,IAAI,OAAO,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CAAC,cAAc,CAAC,GAAG,gBAAgB,CAAC,CAAC;YACrG,CAAC;YACD,IAAI,OAAO,CAAC,GAAG,IAAI,GAAG,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;gBACzD,KAAK,IAAI,OAAO,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CAAC,cAAc,CAAC,GAAG,gBAAgB,CAAC,CAAC;YACrG,CAAC;YAED,oBAAoB,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACxC,CAAC;QAED,kCAAkC;QAClC,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACrD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAClD,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACxB,MAAM,EAAE,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACxC,MAAM,EAAE,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACxC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;gBACvB,OAAO,EAAE,GAAG,EAAE,CAAC;YACjB,CAAC;YACD,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;gBACZ,OAAO,CAAC,CAAC,CAAC;YACZ,CAAC;YACD,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;gBACZ,OAAO,CAAC,CAAC;YACX,CAAC;YACD,OAAO,CAAC,CAAC;QACX,CAAC,CAAC,CAAC;QACH,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAEpG,MAAM,QAAQ,GAAG,EAAkC,CAAC;QACpD,KAAK,MAAM,GAAG,IAAI,WAAwD,EAAE,CAAC;YAC3E,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACpC,oFAAoF;YACpF,QAAQ,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACxB,CAAC;QACD,UAAU,CAAC,KAAK,GAAG,QAAQ,CAAC;IAC9B,CAAC;IAED,kBAAkB,CAAC,IAAgC,EAAE,OAAyC;QAC5F,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;QAEtC,IAAI,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC;QAC9B,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;YAC1B,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,6BAA6B,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC;YACxG,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC;YAChC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,6BAA6B,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC;QACxF,CAAC;QAED,MAAM,eAAe,GAAG,EAAwC,CAAC;QAEjE,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,EAAc,CAAC,iBAAiB,EAAE,CAAC,EAAE,CAAC;YACjF,IAAI,KAAwC,CAAC;YAC7C,IAAI,CAAC;gBACH,MAAM,EAAE,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;gBAClC,KAAK,GAAG,OAAO,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBAC/C,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;gBAChC,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;gBAC1D,IAAI,KAAK,EAAE,CAAC;oBACV,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC;gBAC7B,CAAC;gBACD,KAAK,CAAC,cAAc,GAAG,GAAG,EAAE;oBAC1B,0EAA0E;oBAC1E,OAAO,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;gBACvC,CAAC,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,KAAK,GAAG,GAAG,CAAC;YACd,CAAC;oBAAS,CAAC;gBACT,MAAM,EAAE,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;YAClC,CAAC;YACD,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,EAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAC,CAAC,CAAC;QAClD,CAAC;QAED,0EAA0E;QAC1E,4DAA4D;QAC5D,8BAA8B;QAC9B,uEAAuE;QACvE,6EAA6E;QAC7E,gFAAgF;QAChF,MAAM,YAAY,GAAG,EAAE,KAAK,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC;QACvD,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/E,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC;aACzB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC;aAC1C,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC;QAEvE,MAAM,KAAK,GAAG,CAAC,eAAe,CAAC,YAAY,CAAC,QAAQ,CAAC;QACrD,MAAM,KAAK,GAAG,CAAC,eAAe,CAAC,YAAY,CAAC,uBAAuB,CAAC;QACpE,MAAM,cAAc,GAAG,eAAe,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,CAAC;QACtE,MAAM,aAAa,GAAG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,gBAAgB,IAAI,kBAAkB,IAAI,KAAK;YACxG,KAAK,IAAI,cAAc,CAAC;QAC5B,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC;QACR,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,2FAA2F;YAC3F,0BAA0B;YAC1B,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAA8B;YAC5C,EAAE;YACF,GAAG;YACH,UAAU;YACV,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,KAAK,EAAE,eAAe;SACvB,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,EAAE,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QAC9C,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC;IACpE,CAAC;IAED;;OAEG;IACH,gBAAgB,CACZ,IAAgC,EAAE,WAA0C,EAC5E,OAAyC;QAC3C,6DAA6D;QAC7D,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,EAAE,CAAC;QAE3B,kGAAkG;QAClG,uJAAuJ;QACvJ,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CACrD,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QAE/E,IAAI,CAAC,qCAAqC,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;QAEvE,KAAK,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;YACxD,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,CAAC;YAC1B,yFAAyF;YACzF,MAAM,GAAG,GAAG,KAAK,GAAG,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;YACnG,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACpE,IAAI,CAAC,6BAA6B,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;IAED;;OAEG;IACH,qCAAqC,CACjC,IAAgC,EAAE,WAAoD,EACtF,OAAyC;QAC3C,4HAA4H;QAC5H,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACnC,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1F,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC;QAE1B,MAAM,OAAO,GAAqC;YAChD,OAAO;YACP,MAAM;YACN,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW;YAC9B,iFAAiF;SAClF,CAAC;QACF,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,6BAA6B,CACzB,UAAwC,EAAE,MAAqC,EAAE,IAAgC,EACjH,WAA0C,EAAE,OAAyC;QACvF,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;QACtC,+CAA+C;QAC/C,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,YAAsB,CAAC;QAElE,qFAAqF;QACrF,2GAA2G;QAC3G,4EAA4E;QAC5E,IAAI,OAAgD,CAAC;QACrD,IAAI,CAAC;YACH,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,+BAA+B,CAAC,CAAC;YACvD,OAAO,GAAG,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;QAC1F,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,mCAAmC;YACnC,oGAAoG;YACpG,uFAAuF;YACvF,2DAA2D;YAC3D,MAAM,cAAc,GAAG;gBACrB,+BAA+B;gBAC/B,sCAAsC;gBACtC,qBAAqB;gBACrB,qBAAqB;gBACrB,oCAAoC;gBACpC,kBAAkB;aACnB,CAAC;YACF,IAAI,CAAC,CAAC,CAAC,YAAY,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC9C,yFAAyF;gBACzF,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACnB,CAAC;iBAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,GAAG,CAAC,EAAE,CAAC;gBAC1D,kGAAkG;gBAClG,gDAAgD;gBAChD,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,+BAA+B,CAAC,CAAC;QACvD,CAAC;QAED,MAAM,OAAO,GAAqC;YAChD,OAAO;YACP,MAAM;YACN,OAAO;YACP,UAAU;YACV,YAAY;YACZ,OAAO;SACR,CAAC;QACF,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;CACF;;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,aAAkF;IAE7G,MAAM,SAAS,GAAG,IAAI,GAAG,EAAsD,CAAC;IAChF,MAAM,OAAO,GAAG,IAAI,GAAG,EAA8B,CAAC;IACtD,MAAM,YAAY,GAAG,CAAC,WAAuC,EAAQ,EAAE;QACrE,IAAI,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/B,OAAO;QACT,CAAC;QACD,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,IAAI,SAAS,GAAG,EAAE,CAAC;YACnB,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;gBAC9B,IAAI,SAAS,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;oBACzC,SAAS,IAAI,GAAG,OAAO,IAAI,CAAC;gBAC9B,CAAC;YACH,CAAC;YACD,SAAS,IAAI,WAAW,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,mDAAmD,SAAS,EAAE,CAAC,CAAC;QAClF,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACzB,MAAM,OAAO,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;QAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QAC9B,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAC7B,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC,CAAC;IAEF,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;QACrD,YAAY,CAAC,WAAyC,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Handlers from './handlers/handlers.js';\nimport * as Helpers from './helpers/helpers.js';\nimport * as Insights from './insights/insights.js';\nimport * as Lantern from './lantern/lantern.js';\nimport * as LanternComputationData from './LanternComputationData.js';\nimport type * as Model from './ModelImpl.js';\nimport * as Types from './types/types.js';\n\nconst enum Status {\n IDLE = 'IDLE',\n PARSING = 'PARSING',\n FINISHED_PARSING = 'FINISHED_PARSING',\n ERRORED_WHILE_PARSING = 'ERRORED_WHILE_PARSING',\n}\n\nexport class TraceParseProgressEvent extends Event {\n static readonly eventName = 'traceparseprogress';\n constructor(public data: Model.TraceParseEventProgressData, init: EventInit = {bubbles: true}) {\n super(TraceParseProgressEvent.eventName, init);\n }\n}\n\n/**\n * Parsing a trace can take time. On large traces we see a breakdown of time like so:\n * - handleEvent() loop: ~20%\n * - finalize() loop: ~60%\n * - shallowClone calls: ~20%\n * The numbers below are set so we can report a progress percentage of [0...1]\n */\nconst enum ProgressPhase {\n HANDLE_EVENT = 0.2,\n FINALIZE = 0.8,\n CLONE = 1.0,\n}\nfunction calculateProgress(value: number, phase: ProgressPhase): number {\n // Finalize values should be [0.2...0.8]\n if (phase === ProgressPhase.FINALIZE) {\n return (value * (ProgressPhase.FINALIZE - ProgressPhase.HANDLE_EVENT)) + ProgressPhase.HANDLE_EVENT;\n }\n return value * phase;\n}\n\ndeclare global {\n interface HTMLElementEventMap {\n [TraceParseProgressEvent.eventName]: TraceParseProgressEvent;\n }\n}\n\nexport class TraceProcessor extends EventTarget {\n // We force the Meta handler to be enabled, so the TraceHandlers type here is\n // the model handlers the user passes in and the Meta handler.\n readonly #traceHandlers: Partial<Handlers.Types.Handlers>;\n #status = Status.IDLE;\n #modelConfiguration = Types.Configuration.defaults();\n #data: Handlers.Types.HandlerData|null = null;\n #insights: Insights.Types.TraceInsightSets|null = null;\n\n static createWithAllHandlers(): TraceProcessor {\n return new TraceProcessor(Handlers.ModelHandlers, Types.Configuration.defaults());\n }\n\n /**\n * This function is kept for testing with `stub`.\n */\n static getInsightRunners(): Insights.Types.InsightModelsType {\n return {...Insights.Models};\n }\n\n constructor(traceHandlers: Partial<Handlers.Types.Handlers>, modelConfiguration?: Types.Configuration.Configuration) {\n super();\n\n this.#verifyHandlers(traceHandlers);\n this.#traceHandlers = {\n Meta: Handlers.ModelHandlers.Meta,\n ...traceHandlers,\n };\n if (modelConfiguration) {\n this.#modelConfiguration = modelConfiguration;\n }\n this.#passConfigToHandlers();\n }\n\n #passConfigToHandlers(): void {\n for (const handler of Object.values(this.#traceHandlers)) {\n // Bit of an odd double check, but without this TypeScript refuses to let\n // you call the function as it thinks it might be undefined.\n if ('handleUserConfig' in handler && handler.handleUserConfig) {\n handler.handleUserConfig(this.#modelConfiguration);\n }\n }\n }\n\n /**\n * When the user passes in a set of handlers, we want to ensure that we have all\n * the required handlers. Handlers can depend on other handlers, so if the user\n * passes in FooHandler which depends on BarHandler, they must also pass in\n * BarHandler too. This method verifies that all dependencies are met, and\n * throws if not.\n **/\n #verifyHandlers(providedHandlers: Partial<Handlers.Types.Handlers>): void {\n // Tiny optimisation: if the amount of provided handlers matches the amount\n // of handlers in the Handlers.ModelHandlers object, that means that the\n // user has passed in every handler we have. So therefore they cannot have\n // missed any, and there is no need to iterate through the handlers and\n // check the dependencies.\n if (Object.keys(providedHandlers).length === Object.keys(Handlers.ModelHandlers).length) {\n return;\n }\n const requiredHandlerKeys = new Set<Handlers.Types.HandlerName>();\n for (const [handlerName, handler] of Object.entries(providedHandlers)) {\n requiredHandlerKeys.add(handlerName as Handlers.Types.HandlerName);\n const deps = 'deps' in handler ? handler.deps() : [];\n for (const depName of deps) {\n requiredHandlerKeys.add(depName);\n }\n }\n\n const providedHandlerKeys = new Set(Object.keys(providedHandlers));\n // We always force the Meta handler to be enabled when creating the\n // Processor, so if it is missing from the set the user gave us that is OK,\n // as we will have enabled it anyway.\n requiredHandlerKeys.delete('Meta');\n\n for (const requiredKey of requiredHandlerKeys) {\n if (!providedHandlerKeys.has(requiredKey)) {\n throw new Error(`Required handler ${requiredKey} not provided.`);\n }\n }\n }\n\n reset(): void {\n if (this.#status === Status.PARSING) {\n throw new Error('Trace processor can\\'t reset while parsing.');\n }\n\n const handlers = Object.values(this.#traceHandlers);\n for (const handler of handlers) {\n handler.reset();\n }\n\n this.#data = null;\n this.#insights = null;\n this.#status = Status.IDLE;\n }\n\n async parse(traceEvents: readonly Types.Events.Event[], options: Types.Configuration.ParseOptions): Promise<void> {\n if (this.#status !== Status.IDLE) {\n throw new Error(`Trace processor can't start parsing when not idle. Current state: ${this.#status}`);\n }\n\n if (typeof options.isCPUProfile === 'undefined' && options.metadata) {\n options.isCPUProfile = options.metadata.dataOrigin === Types.File.DataOrigin.CPU_PROFILE;\n }\n\n options.logger?.start('total');\n try {\n this.#status = Status.PARSING;\n options.logger?.start('parse');\n await this.#computeParsedTrace(traceEvents, options);\n options.logger?.end('parse');\n if (this.#data && !options.isCPUProfile) { // We do not calculate insights for CPU Profiles.\n options.logger?.start('insights');\n this.#computeInsights(this.#data, traceEvents, options);\n options.logger?.end('insights');\n }\n this.#status = Status.FINISHED_PARSING;\n } catch (e) {\n this.#status = Status.ERRORED_WHILE_PARSING;\n throw e;\n } finally {\n options.logger?.end('total');\n }\n }\n\n /**\n * Run all the handlers and set the result to `#data`.\n */\n async #computeParsedTrace(traceEvents: readonly Types.Events.Event[], options: Types.Configuration.ParseOptions):\n Promise<void> {\n /**\n * We want to yield regularly to maintain responsiveness. If we yield too often, we're wasting idle time.\n * We could do this by checking `performance.now()` regularly, but it's an expensive call in such a hot loop.\n * `eventsPerChunk` is an approximated proxy metric.\n * But how big a chunk? We're aiming for long tasks that are no smaller than 100ms and not bigger than 200ms.\n * It's CPU dependent, so it should be calibrated on oldish hardware.\n * Illustration of a previous change to `eventsPerChunk`: https://imgur.com/wzp8BnR\n */\n const eventsPerChunk = 50_000;\n // Convert to array so that we are able to iterate all handlers multiple times.\n const sortedHandlers = [...sortHandlers(this.#traceHandlers).entries()];\n\n // Reset.\n for (const [, handler] of sortedHandlers) {\n handler.reset();\n }\n\n options.logger?.start('parse:handleEvent');\n\n // Handle each event.\n for (let i = 0; i < traceEvents.length; ++i) {\n // Every so often we take a break just to render.\n if (i % eventsPerChunk === 0 && i) {\n // Take the opportunity to provide status update events.\n const percent = calculateProgress(i / traceEvents.length, ProgressPhase.HANDLE_EVENT);\n this.dispatchEvent(new TraceParseProgressEvent({percent}));\n // TODO(paulirish): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n }\n const event = traceEvents[i];\n for (let j = 0; j < sortedHandlers.length; ++j) {\n const [, handler] = sortedHandlers[j];\n handler.handleEvent(event);\n }\n }\n\n options.logger?.end('parse:handleEvent');\n\n // Finalize.\n const finalizeOptions: Handlers.Types.FinalizeOptions = {\n ...options,\n allTraceEvents: traceEvents,\n };\n for (let i = 0; i < sortedHandlers.length; i++) {\n const [name, handler] = sortedHandlers[i];\n if (handler.finalize) {\n options.logger?.start(`parse:${name}:finalize`);\n // Yield to the UI because finalize() calls can be expensive\n // TODO(jacktfranklin): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n await handler.finalize(finalizeOptions);\n options.logger?.end(`parse:${name}:finalize`);\n }\n const percent = calculateProgress(i / sortedHandlers.length, ProgressPhase.FINALIZE);\n this.dispatchEvent(new TraceParseProgressEvent({percent}));\n }\n\n options.logger?.start('parse:handler.data()');\n const parsedTrace = {};\n for (const [name, handler] of Object.entries(this.#traceHandlers)) {\n Object.assign(parsedTrace, {[name]: handler.data()});\n }\n options.logger?.end('parse:handler.data()');\n\n this.dispatchEvent(new TraceParseProgressEvent({percent: ProgressPhase.CLONE}));\n\n this.#data = parsedTrace as Handlers.Types.HandlerData;\n }\n\n get data(): Handlers.Types.HandlerData|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n return this.#data;\n }\n\n get insights(): Insights.Types.TraceInsightSets|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n return this.#insights;\n }\n\n #createLanternContext(\n data: Handlers.Types.HandlerData, traceEvents: readonly Types.Events.Event[], frameId: string,\n navigationId: string, options: Types.Configuration.ParseOptions): Insights.Types.LanternContext|undefined {\n // Check for required handlers.\n if (!data.NetworkRequests || !data.Workers || !data.PageLoadMetrics) {\n return;\n }\n if (!data.NetworkRequests.byTime.length) {\n throw new Lantern.Core.LanternError('No network requests found in trace');\n }\n\n const navStarts = data.Meta.navigationsByFrameId.get(frameId);\n const navStartIndex = navStarts?.findIndex(n => n.args.data?.navigationId === navigationId);\n if (!navStarts || navStartIndex === undefined || navStartIndex === -1) {\n throw new Lantern.Core.LanternError('Could not find navigation start');\n }\n\n const startTime = navStarts[navStartIndex].ts;\n const endTime = navStartIndex + 1 < navStarts.length ? navStarts[navStartIndex + 1].ts : Number.POSITIVE_INFINITY;\n const boundedTraceEvents = traceEvents.filter(e => e.ts >= startTime && e.ts < endTime);\n\n // Lantern.Types.TraceEvent and Types.Events.Event represent the same\n // object - a trace event - but one is more flexible than the other. It should be safe to cast between them.\n const trace: Lantern.Types.Trace = {\n traceEvents: boundedTraceEvents as unknown as Lantern.Types.TraceEvent[],\n };\n\n const requests = LanternComputationData.createNetworkRequests(trace, data, startTime, endTime);\n const graph = LanternComputationData.createGraph(requests, trace, data);\n const processedNavigation = LanternComputationData.createProcessedNavigation(data, frameId, navigationId);\n\n const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests);\n if (!networkAnalysis) {\n return;\n }\n\n const lanternSettings: Lantern.Types.Simulation.Settings = {\n // TODO(crbug.com/372674229): if devtools throttling was on, does this network analysis capture\n // that? Do we need to set 'devtools' throttlingMethod?\n networkAnalysis,\n throttlingMethod: 'provided',\n ...options.lanternSettings,\n };\n const simulator: Lantern.Simulation.Simulator<Types.Events.SyntheticNetworkRequest> =\n Lantern.Simulation.Simulator.createSimulator(lanternSettings);\n\n const computeData = {graph, simulator, processedNavigation};\n const fcpResult = Lantern.Metrics.FirstContentfulPaint.compute(computeData);\n const lcpResult = Lantern.Metrics.LargestContentfulPaint.compute(computeData, {fcpResult});\n const interactiveResult = Lantern.Metrics.Interactive.compute(computeData, {lcpResult});\n const tbtResult = Lantern.Metrics.TotalBlockingTime.compute(computeData, {fcpResult, interactiveResult});\n const metrics = {\n firstContentfulPaint: fcpResult,\n interactive: interactiveResult,\n largestContentfulPaint: lcpResult,\n totalBlockingTime: tbtResult,\n };\n\n return {requests, graph, simulator, metrics};\n }\n\n /**\n * Sort the insight models based on the impact of each insight's estimated savings, additionally weighted by the\n * worst metrics according to field data (if present).\n */\n sortInsightSet(insightSet: Insights.Types.InsightSet, metadata: Types.File.MetaData|null): void {\n // The initial order of the insights is alphabetical, based on `front_end/models/trace/insights/Models.ts`.\n // The order here provides a baseline that groups insights in a more logical way.\n const baselineOrder: Record<keyof Insights.Types.InsightModels, null> = {\n INPBreakdown: null,\n LCPBreakdown: null,\n LCPDiscovery: null,\n CLSCulprits: null,\n RenderBlocking: null,\n NetworkDependencyTree: null,\n ImageDelivery: null,\n DocumentLatency: null,\n FontDisplay: null,\n Viewport: null,\n DOMSize: null,\n ThirdParties: null,\n DuplicatedJavaScript: null,\n SlowCSSSelector: null,\n ForcedReflow: null,\n Cache: null,\n ModernHTTP: null,\n LegacyJavaScript: null,\n };\n\n // Determine the weights for each metric based on field data, utilizing the same scoring curve that Lighthouse uses.\n const weights = Insights.Common.calculateMetricWeightsForSorting(insightSet, metadata);\n\n // Normalize the estimated savings to a single number, weighted by its relative impact\n // to the page experience based on the same scoring curve that Lighthouse uses.\n const observedLcpMicro = Insights.Common.getLCP(insightSet)?.value;\n const observedLcp = observedLcpMicro ? Helpers.Timing.microToMilli(observedLcpMicro) : Types.Timing.Milli(0);\n const observedCls = Insights.Common.getCLS(insightSet).value;\n\n // INP is special - if users did not interact with the page, we'll have no INP, but we should still\n // be able to prioritize insights based on this metric. When we observe no interaction, instead use\n // a default value for the baseline INP.\n const observedInpMicro = Insights.Common.getINP(insightSet)?.value;\n const observedInp = observedInpMicro ? Helpers.Timing.microToMilli(observedInpMicro) : Types.Timing.Milli(200);\n\n const observedLcpScore =\n observedLcp !== undefined ? Insights.Common.evaluateLCPMetricScore(observedLcp) : undefined;\n const observedInpScore = Insights.Common.evaluateINPMetricScore(observedInp);\n const observedClsScore = Insights.Common.evaluateCLSMetricScore(observedCls);\n\n const insightToSortingRank = new Map<string, number>();\n for (const [name, model] of Object.entries(insightSet.model)) {\n const lcp = model.metricSavings?.LCP ?? 0;\n const inp = model.metricSavings?.INP ?? 0;\n const cls = model.metricSavings?.CLS ?? 0;\n\n const lcpPostSavings =\n observedLcp !== undefined ? Math.max(0, observedLcp - lcp) as Types.Timing.Milli : undefined;\n const inpPostSavings = Math.max(0, observedInp - inp) as Types.Timing.Milli;\n const clsPostSavings = Math.max(0, observedCls - cls);\n\n let score = 0;\n if (weights.lcp && lcp && observedLcpScore !== undefined && lcpPostSavings !== undefined) {\n score += weights.lcp * (Insights.Common.evaluateLCPMetricScore(lcpPostSavings) - observedLcpScore);\n }\n if (weights.inp && inp && observedInpScore !== undefined) {\n score += weights.inp * (Insights.Common.evaluateINPMetricScore(inpPostSavings) - observedInpScore);\n }\n if (weights.cls && cls && observedClsScore !== undefined) {\n score += weights.cls * (Insights.Common.evaluateCLSMetricScore(clsPostSavings) - observedClsScore);\n }\n\n insightToSortingRank.set(name, score);\n }\n\n // Now perform the actual sorting.\n const baselineOrderKeys = Object.keys(baselineOrder);\n const orderedKeys = Object.keys(insightSet.model);\n orderedKeys.sort((a, b) => {\n const a1 = baselineOrderKeys.indexOf(a);\n const b1 = baselineOrderKeys.indexOf(b);\n if (a1 >= 0 && b1 >= 0) {\n return a1 - b1;\n }\n if (a1 >= 0) {\n return -1;\n }\n if (b1 >= 0) {\n return 1;\n }\n return 0;\n });\n orderedKeys.sort((a, b) => (insightToSortingRank.get(b) ?? 0) - (insightToSortingRank.get(a) ?? 0));\n\n const newModel = {} as Insights.Types.InsightModels;\n for (const key of orderedKeys as Array<keyof Insights.Types.InsightModels>) {\n const model = insightSet.model[key];\n // @ts-expect-error Maybe someday typescript will be powerful enough to handle this.\n newModel[key] = model;\n }\n insightSet.model = newModel;\n }\n\n #computeInsightSet(data: Handlers.Types.HandlerData, context: Insights.Types.InsightSetContext): void {\n const logger = context.options.logger;\n\n let id, urlString, navigation;\n if (context.navigation) {\n id = context.navigationId;\n urlString = data.Meta.finalDisplayUrlByNavigationId.get(context.navigationId) ?? data.Meta.mainFrameURL;\n navigation = context.navigation;\n } else {\n id = Types.Events.NO_NAVIGATION;\n urlString = data.Meta.finalDisplayUrlByNavigationId.get('') ?? data.Meta.mainFrameURL;\n }\n\n const insightSetModel = {} as Insights.Types.InsightSet['model'];\n\n for (const [name, insight] of Object.entries(TraceProcessor.getInsightRunners())) {\n let model: Insights.Types.InsightModel|Error;\n try {\n logger?.start(`insights:${name}`);\n model = insight.generateInsight(data, context);\n model.frameId = context.frameId;\n const navId = context.navigation?.args.data?.navigationId;\n if (navId) {\n model.navigationId = navId;\n }\n model.createOverlays = () => {\n // @ts-expect-error: model is a union of all possible insight model types.\n return insight.createOverlays(model);\n };\n } catch (err) {\n model = err;\n } finally {\n logger?.end(`insights:${name}`);\n }\n Object.assign(insightSetModel, {[name]: model});\n }\n\n // We may choose to exclude the insightSet if it's trivial. Trivial means:\n // 1. There's no navigation (it's an initial trace period)\n // 2. The duration is short.\n // 3. All the insights are passing (aka no insights to show the user)\n // 4. It has no metrics to report (apart from a CLS of 0, which is default)\n // Generally, these cases are the short time ranges before a page reload starts.\n const isNavigation = id === Types.Events.NO_NAVIGATION;\n const trivialThreshold = Helpers.Timing.milliToMicro(Types.Timing.Milli(5000));\n const everyInsightPasses = Object.values(insightSetModel)\n .filter(model => !(model instanceof Error))\n .every(model => model.state === 'pass');\n\n const noLcp = !insightSetModel.LCPBreakdown.lcpEvent;\n const noInp = !insightSetModel.INPBreakdown.longestInteractionEvent;\n const noLayoutShifts = insightSetModel.CLSCulprits.shifts?.size === 0;\n const shouldExclude = isNavigation && context.bounds.range < trivialThreshold && everyInsightPasses && noLcp &&\n noInp && noLayoutShifts;\n if (shouldExclude) {\n return;\n }\n\n let url;\n try {\n url = new URL(urlString);\n } catch {\n // We're pretty sure this only happens for our test fixture: missing-url.json.gz. Shouldn't\n // happen for real traces.\n return;\n }\n\n const insightSet: Insights.Types.InsightSet = {\n id,\n url,\n navigation,\n frameId: context.frameId,\n bounds: context.bounds,\n model: insightSetModel,\n };\n if (!this.#insights) {\n this.#insights = new Map();\n }\n this.#insights.set(insightSet.id, insightSet);\n this.sortInsightSet(insightSet, context.options.metadata ?? null);\n }\n\n /**\n * Run all the insights and set the result to `#insights`.\n */\n #computeInsights(\n data: Handlers.Types.HandlerData, traceEvents: readonly Types.Events.Event[],\n options: Types.Configuration.ParseOptions): void {\n // This insights map will be populated by the helper methods.\n this.#insights = new Map();\n\n // Filter main frame navigations to those that have the necessary data (frameId and navigationId).\n // TODO(cjamcl): Does this filtering makes the \"use the next nav as the end time\" logic potentially broken? Are navs without nav id or frame even real?\n const navigations = data.Meta.mainFrameNavigations.filter(\n navigation => navigation.args.frame && navigation.args.data?.navigationId);\n\n this.#computeInsightsForInitialTracePeriod(data, navigations, options);\n\n for (const [index, navigation] of navigations.entries()) {\n const min = navigation.ts;\n // Use trace end for the last navigation, otherwise use the start of the next navigation.\n const max = index + 1 < navigations.length ? navigations[index + 1].ts : data.Meta.traceBounds.max;\n const bounds = Helpers.Timing.traceWindowFromMicroSeconds(min, max);\n this.#computeInsightsForNavigation(navigation, bounds, data, traceEvents, options);\n }\n }\n\n /**\n * Computes insights for the period before the first navigation, or for the entire trace if no navigations exist.\n */\n #computeInsightsForInitialTracePeriod(\n data: Handlers.Types.HandlerData, navigations: readonly Types.Events.NavigationStart[],\n options: Types.Configuration.ParseOptions): void {\n // Determine bounds: Use the period before the first navigation if navigations exist, otherwise use the entire trace bounds.\n const bounds = navigations.length > 0 ?\n Helpers.Timing.traceWindowFromMicroSeconds(data.Meta.traceBounds.min, navigations[0].ts) :\n data.Meta.traceBounds;\n\n const context: Insights.Types.InsightSetContext = {\n options,\n bounds,\n frameId: data.Meta.mainFrameId,\n // No navigation or lantern context applies to this initial/no-navigation period.\n };\n this.#computeInsightSet(data, context);\n }\n\n /**\n * Computes insights for a specific navigation event.\n */\n #computeInsightsForNavigation(\n navigation: Types.Events.NavigationStart, bounds: Types.Timing.TraceWindowMicro, data: Handlers.Types.HandlerData,\n traceEvents: readonly Types.Events.Event[], options: Types.Configuration.ParseOptions): void {\n const frameId = navigation.args.frame;\n // Guaranteed by the filter in #computeInsights\n const navigationId = navigation.args.data?.navigationId as string;\n\n // The lantern sub-context is optional on InsightSetContext, so not setting it is OK.\n // This is also a hedge against an error inside Lantern resulting in breaking the entire performance panel.\n // Additionally, many trace fixtures are too old to be processed by Lantern.\n let lantern: Insights.Types.LanternContext|undefined;\n try {\n options.logger?.start('insights:createLanternContext');\n lantern = this.#createLanternContext(data, traceEvents, frameId, navigationId, options);\n } catch (e) {\n // Handle Lantern errors gracefully\n // Don't allow an error in constructing the Lantern graphs to break the rest of the trace processor.\n // Log unexpected errors, but suppress anything that occurs from a trace being too old.\n // Otherwise tests using old fixtures become way too noisy.\n const expectedErrors = [\n 'mainDocumentRequest not found',\n 'missing metric scores for main frame',\n 'missing metric: FCP',\n 'missing metric: LCP',\n 'No network requests found in trace',\n 'Trace is too old',\n ];\n if (!(e instanceof Lantern.Core.LanternError)) {\n // If this wasn't a managed LanternError, the stack trace is likely needed for debugging.\n console.error(e);\n } else if (!expectedErrors.some(err => e.message === err)) {\n // To reduce noise from tests, only print errors that are not expected to occur because a trace is\n // too old (for which there is no single check).\n console.error(e);\n }\n } finally {\n options.logger?.end('insights:createLanternContext');\n }\n\n const context: Insights.Types.InsightSetContext = {\n options,\n bounds,\n frameId,\n navigation,\n navigationId,\n lantern,\n };\n this.#computeInsightSet(data, context);\n }\n}\n\n/**\n * Some Handlers need data provided by others. Dependencies of a handler handler are\n * declared in the `deps` field.\n * @returns A map from trace event handler name to trace event handler whose entries\n * iterate in such a way that each handler is visited after its dependencies.\n */\nexport function sortHandlers(traceHandlers: Partial<Record<Handlers.Types.HandlerName, Handlers.Types.Handler>>):\n Map<Handlers.Types.HandlerName, Handlers.Types.Handler> {\n const sortedMap = new Map<Handlers.Types.HandlerName, Handlers.Types.Handler>();\n const visited = new Set<Handlers.Types.HandlerName>();\n const visitHandler = (handlerName: Handlers.Types.HandlerName): void => {\n if (sortedMap.has(handlerName)) {\n return;\n }\n if (visited.has(handlerName)) {\n let stackPath = '';\n for (const handler of visited) {\n if (stackPath || handler === handlerName) {\n stackPath += `${handler}->`;\n }\n }\n stackPath += handlerName;\n throw new Error(`Found dependency cycle in trace event handlers: ${stackPath}`);\n }\n visited.add(handlerName);\n const handler = traceHandlers[handlerName];\n if (!handler) {\n return;\n }\n const deps = handler.deps?.();\n if (deps) {\n deps.forEach(visitHandler);\n }\n sortedMap.set(handlerName, handler);\n };\n\n for (const handlerName of Object.keys(traceHandlers)) {\n visitHandler(handlerName as Handlers.Types.HandlerName);\n }\n return sortedMap;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Processor.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/Processor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Handlers from './handlers/handlers.js';\nimport * as Helpers from './helpers/helpers.js';\nimport * as Insights from './insights/insights.js';\nimport * as Lantern from './lantern/lantern.js';\nimport * as LanternComputationData from './LanternComputationData.js';\nimport type * as Model from './ModelImpl.js';\nimport * as Types from './types/types.js';\n\nconst enum Status {\n IDLE = 'IDLE',\n PARSING = 'PARSING',\n FINISHED_PARSING = 'FINISHED_PARSING',\n ERRORED_WHILE_PARSING = 'ERRORED_WHILE_PARSING',\n}\n\nexport class TraceParseProgressEvent extends Event {\n static readonly eventName = 'traceparseprogress';\n constructor(public data: Model.TraceParseEventProgressData, init: EventInit = {bubbles: true}) {\n super(TraceParseProgressEvent.eventName, init);\n }\n}\n\n/**\n * Parsing a trace can take time. On large traces we see a breakdown of time like so:\n * - handleEvent() loop: ~20%\n * - finalize() loop: ~60%\n * - shallowClone calls: ~20%\n * The numbers below are set so we can report a progress percentage of [0...1]\n */\nconst enum ProgressPhase {\n HANDLE_EVENT = 0.2,\n FINALIZE = 0.8,\n CLONE = 1.0,\n}\nfunction calculateProgress(value: number, phase: ProgressPhase): number {\n // Finalize values should be [0.2...0.8]\n if (phase === ProgressPhase.FINALIZE) {\n return (value * (ProgressPhase.FINALIZE - ProgressPhase.HANDLE_EVENT)) + ProgressPhase.HANDLE_EVENT;\n }\n return value * phase;\n}\n\ndeclare global {\n interface HTMLElementEventMap {\n [TraceParseProgressEvent.eventName]: TraceParseProgressEvent;\n }\n}\n\nexport class TraceProcessor extends EventTarget {\n // We force the Meta handler to be enabled, so the TraceHandlers type here is\n // the model handlers the user passes in and the Meta handler.\n readonly #traceHandlers: Partial<Handlers.Types.Handlers>;\n #status = Status.IDLE;\n #modelConfiguration = Types.Configuration.defaults();\n #data: Handlers.Types.HandlerData|null = null;\n #insights: Insights.Types.TraceInsightSets|null = null;\n\n static createWithAllHandlers(): TraceProcessor {\n return new TraceProcessor(Handlers.ModelHandlers, Types.Configuration.defaults());\n }\n\n /**\n * This function is kept for testing with `stub`.\n */\n static getInsightRunners(): Insights.Types.InsightModelsType {\n return {...Insights.Models};\n }\n\n constructor(traceHandlers: Partial<Handlers.Types.Handlers>, modelConfiguration?: Types.Configuration.Configuration) {\n super();\n\n this.#verifyHandlers(traceHandlers);\n this.#traceHandlers = {\n Meta: Handlers.ModelHandlers.Meta,\n ...traceHandlers,\n };\n if (modelConfiguration) {\n this.#modelConfiguration = modelConfiguration;\n }\n this.#passConfigToHandlers();\n }\n\n #passConfigToHandlers(): void {\n for (const handler of Object.values(this.#traceHandlers)) {\n // Bit of an odd double check, but without this TypeScript refuses to let\n // you call the function as it thinks it might be undefined.\n if ('handleUserConfig' in handler && handler.handleUserConfig) {\n handler.handleUserConfig(this.#modelConfiguration);\n }\n }\n }\n\n /**\n * When the user passes in a set of handlers, we want to ensure that we have all\n * the required handlers. Handlers can depend on other handlers, so if the user\n * passes in FooHandler which depends on BarHandler, they must also pass in\n * BarHandler too. This method verifies that all dependencies are met, and\n * throws if not.\n **/\n #verifyHandlers(providedHandlers: Partial<Handlers.Types.Handlers>): void {\n // Tiny optimisation: if the amount of provided handlers matches the amount\n // of handlers in the Handlers.ModelHandlers object, that means that the\n // user has passed in every handler we have. So therefore they cannot have\n // missed any, and there is no need to iterate through the handlers and\n // check the dependencies.\n if (Object.keys(providedHandlers).length === Object.keys(Handlers.ModelHandlers).length) {\n return;\n }\n const requiredHandlerKeys = new Set<Handlers.Types.HandlerName>();\n for (const [handlerName, handler] of Object.entries(providedHandlers)) {\n requiredHandlerKeys.add(handlerName as Handlers.Types.HandlerName);\n const deps = 'deps' in handler ? handler.deps() : [];\n for (const depName of deps) {\n requiredHandlerKeys.add(depName);\n }\n }\n\n const providedHandlerKeys = new Set(Object.keys(providedHandlers));\n // We always force the Meta handler to be enabled when creating the\n // Processor, so if it is missing from the set the user gave us that is OK,\n // as we will have enabled it anyway.\n requiredHandlerKeys.delete('Meta');\n\n for (const requiredKey of requiredHandlerKeys) {\n if (!providedHandlerKeys.has(requiredKey)) {\n throw new Error(`Required handler ${requiredKey} not provided.`);\n }\n }\n }\n\n reset(): void {\n if (this.#status === Status.PARSING) {\n throw new Error('Trace processor can\\'t reset while parsing.');\n }\n\n const handlers = Object.values(this.#traceHandlers);\n for (const handler of handlers) {\n handler.reset();\n }\n\n this.#data = null;\n this.#insights = null;\n this.#status = Status.IDLE;\n }\n\n async parse(traceEvents: readonly Types.Events.Event[], options: Types.Configuration.ParseOptions): Promise<void> {\n if (this.#status !== Status.IDLE) {\n throw new Error(`Trace processor can't start parsing when not idle. Current state: ${this.#status}`);\n }\n\n if (typeof options.isCPUProfile === 'undefined' && options.metadata) {\n options.isCPUProfile = options.metadata.dataOrigin === Types.File.DataOrigin.CPU_PROFILE;\n }\n\n options.logger?.start('total');\n try {\n this.#status = Status.PARSING;\n options.logger?.start('parse');\n await this.#computeParsedTrace(traceEvents, options);\n options.logger?.end('parse');\n if (this.#data && !options.isCPUProfile) { // We do not calculate insights for CPU Profiles.\n options.logger?.start('insights');\n this.#computeInsights(this.#data, traceEvents, options);\n options.logger?.end('insights');\n }\n this.#status = Status.FINISHED_PARSING;\n } catch (e) {\n this.#status = Status.ERRORED_WHILE_PARSING;\n throw e;\n } finally {\n options.logger?.end('total');\n }\n }\n\n /**\n * Run all the handlers and set the result to `#data`.\n */\n async #computeParsedTrace(traceEvents: readonly Types.Events.Event[], options: Types.Configuration.ParseOptions):\n Promise<void> {\n /**\n * We want to yield regularly to maintain responsiveness. If we yield too often, we're wasting idle time.\n * We could do this by checking `performance.now()` regularly, but it's an expensive call in such a hot loop.\n * `eventsPerChunk` is an approximated proxy metric.\n * But how big a chunk? We're aiming for long tasks that are no smaller than 100ms and not bigger than 200ms.\n * It's CPU dependent, so it should be calibrated on oldish hardware.\n * Illustration of a previous change to `eventsPerChunk`: https://imgur.com/wzp8BnR\n */\n const eventsPerChunk = 50_000;\n // Convert to array so that we are able to iterate all handlers multiple times.\n const sortedHandlers = [...sortHandlers(this.#traceHandlers).entries()];\n\n // Reset.\n for (const [, handler] of sortedHandlers) {\n handler.reset();\n }\n\n options.logger?.start('parse:handleEvent');\n\n // Handle each event.\n for (let i = 0; i < traceEvents.length; ++i) {\n // Every so often we take a break just to render.\n if (i % eventsPerChunk === 0 && i) {\n // Take the opportunity to provide status update events.\n const percent = calculateProgress(i / traceEvents.length, ProgressPhase.HANDLE_EVENT);\n this.dispatchEvent(new TraceParseProgressEvent({percent}));\n // TODO(paulirish): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n }\n const event = traceEvents[i];\n for (let j = 0; j < sortedHandlers.length; ++j) {\n const [, handler] = sortedHandlers[j];\n handler.handleEvent(event);\n }\n }\n\n options.logger?.end('parse:handleEvent');\n\n // Finalize.\n const finalizeOptions: Handlers.Types.FinalizeOptions = {\n ...options,\n allTraceEvents: traceEvents,\n };\n for (let i = 0; i < sortedHandlers.length; i++) {\n const [name, handler] = sortedHandlers[i];\n if (handler.finalize) {\n options.logger?.start(`parse:${name}:finalize`);\n // Yield to the UI because finalize() calls can be expensive\n // TODO(jacktfranklin): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n await handler.finalize(finalizeOptions);\n options.logger?.end(`parse:${name}:finalize`);\n }\n const percent = calculateProgress(i / sortedHandlers.length, ProgressPhase.FINALIZE);\n this.dispatchEvent(new TraceParseProgressEvent({percent}));\n }\n\n options.logger?.start('parse:handler.data()');\n const parsedTrace = {};\n for (const [name, handler] of Object.entries(this.#traceHandlers)) {\n Object.assign(parsedTrace, {[name]: handler.data()});\n }\n options.logger?.end('parse:handler.data()');\n\n this.dispatchEvent(new TraceParseProgressEvent({percent: ProgressPhase.CLONE}));\n\n this.#data = parsedTrace as Handlers.Types.HandlerData;\n }\n\n get data(): Handlers.Types.HandlerData|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n return this.#data;\n }\n\n get insights(): Insights.Types.TraceInsightSets|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n return this.#insights;\n }\n\n #createLanternContext(\n data: Handlers.Types.HandlerData, traceEvents: readonly Types.Events.Event[], frameId: string,\n navigation: Types.Events.NavigationStart,\n options: Types.Configuration.ParseOptions): Insights.Types.LanternContext|undefined {\n // Check for required handlers.\n if (!data.NetworkRequests || !data.Workers || !data.PageLoadMetrics) {\n return;\n }\n if (!data.NetworkRequests.byTime.length) {\n throw new Lantern.Core.LanternError('No network requests found in trace');\n }\n\n const navStarts = data.Meta.navigationsByFrameId.get(frameId);\n const navStartIndex = navStarts?.findIndex(n => n === navigation);\n if (!navStarts || navStartIndex === undefined || navStartIndex === -1) {\n throw new Lantern.Core.LanternError('Could not find navigation start');\n }\n\n const startTime = navStarts[navStartIndex].ts;\n const endTime = navStartIndex + 1 < navStarts.length ? navStarts[navStartIndex + 1].ts : Number.POSITIVE_INFINITY;\n const boundedTraceEvents = traceEvents.filter(e => e.ts >= startTime && e.ts < endTime);\n\n // Lantern.Types.TraceEvent and Types.Events.Event represent the same\n // object - a trace event - but one is more flexible than the other. It should be safe to cast between them.\n const trace: Lantern.Types.Trace = {\n traceEvents: boundedTraceEvents as unknown as Lantern.Types.TraceEvent[],\n };\n\n const requests = LanternComputationData.createNetworkRequests(trace, data, startTime, endTime);\n const graph = LanternComputationData.createGraph(requests, trace, data);\n const processedNavigation = LanternComputationData.createProcessedNavigation(data, frameId, navigation);\n\n const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests);\n if (!networkAnalysis) {\n return;\n }\n\n const lanternSettings: Lantern.Types.Simulation.Settings = {\n // TODO(crbug.com/372674229): if devtools throttling was on, does this network analysis capture\n // that? Do we need to set 'devtools' throttlingMethod?\n networkAnalysis,\n throttlingMethod: 'provided',\n ...options.lanternSettings,\n };\n const simulator: Lantern.Simulation.Simulator<Types.Events.SyntheticNetworkRequest> =\n Lantern.Simulation.Simulator.createSimulator(lanternSettings);\n\n const computeData = {graph, simulator, processedNavigation};\n const fcpResult = Lantern.Metrics.FirstContentfulPaint.compute(computeData);\n const lcpResult = Lantern.Metrics.LargestContentfulPaint.compute(computeData, {fcpResult});\n const interactiveResult = Lantern.Metrics.Interactive.compute(computeData, {lcpResult});\n const tbtResult = Lantern.Metrics.TotalBlockingTime.compute(computeData, {fcpResult, interactiveResult});\n const metrics = {\n firstContentfulPaint: fcpResult,\n interactive: interactiveResult,\n largestContentfulPaint: lcpResult,\n totalBlockingTime: tbtResult,\n };\n\n return {requests, graph, simulator, metrics};\n }\n\n /**\n * Sort the insight models based on the impact of each insight's estimated savings, additionally weighted by the\n * worst metrics according to field data (if present).\n */\n sortInsightSet(insightSet: Insights.Types.InsightSet, metadata: Types.File.MetaData|null): void {\n // The initial order of the insights is alphabetical, based on `front_end/models/trace/insights/Models.ts`.\n // The order here provides a baseline that groups insights in a more logical way.\n const baselineOrder: Record<keyof Insights.Types.InsightModels, null> = {\n INPBreakdown: null,\n LCPBreakdown: null,\n LCPDiscovery: null,\n CLSCulprits: null,\n RenderBlocking: null,\n NetworkDependencyTree: null,\n ImageDelivery: null,\n DocumentLatency: null,\n FontDisplay: null,\n Viewport: null,\n DOMSize: null,\n ThirdParties: null,\n DuplicatedJavaScript: null,\n SlowCSSSelector: null,\n ForcedReflow: null,\n Cache: null,\n CharacterSet: null,\n ModernHTTP: null,\n LegacyJavaScript: null,\n };\n\n // Determine the weights for each metric based on field data, utilizing the same scoring curve that Lighthouse uses.\n const weights = Insights.Common.calculateMetricWeightsForSorting(insightSet, metadata);\n\n // Normalize the estimated savings to a single number, weighted by its relative impact\n // to the page experience based on the same scoring curve that Lighthouse uses.\n const observedLcpMicro = Insights.Common.getLCP(insightSet)?.value;\n const observedLcp = observedLcpMicro ? Helpers.Timing.microToMilli(observedLcpMicro) : Types.Timing.Milli(0);\n const observedCls = Insights.Common.getCLS(insightSet).value;\n\n // INP is special - if users did not interact with the page, we'll have no INP, but we should still\n // be able to prioritize insights based on this metric. When we observe no interaction, instead use\n // a default value for the baseline INP.\n const observedInpMicro = Insights.Common.getINP(insightSet)?.value;\n const observedInp = observedInpMicro ? Helpers.Timing.microToMilli(observedInpMicro) : Types.Timing.Milli(200);\n\n const observedLcpScore =\n observedLcp !== undefined ? Insights.Common.evaluateLCPMetricScore(observedLcp) : undefined;\n const observedInpScore = Insights.Common.evaluateINPMetricScore(observedInp);\n const observedClsScore = Insights.Common.evaluateCLSMetricScore(observedCls);\n\n const insightToSortingRank = new Map<string, number>();\n for (const [name, insight] of Object.entries(insightSet.model)) {\n const lcp = insight.metricSavings?.LCP ?? 0;\n const inp = insight.metricSavings?.INP ?? 0;\n const cls = insight.metricSavings?.CLS ?? 0;\n\n const lcpPostSavings =\n observedLcp !== undefined ? Math.max(0, observedLcp - lcp) as Types.Timing.Milli : undefined;\n const inpPostSavings = Math.max(0, observedInp - inp) as Types.Timing.Milli;\n const clsPostSavings = Math.max(0, observedCls - cls);\n\n let score = 0;\n if (weights.lcp && lcp && observedLcpScore !== undefined && lcpPostSavings !== undefined) {\n score += weights.lcp * (Insights.Common.evaluateLCPMetricScore(lcpPostSavings) - observedLcpScore);\n }\n if (weights.inp && inp && observedInpScore !== undefined) {\n score += weights.inp * (Insights.Common.evaluateINPMetricScore(inpPostSavings) - observedInpScore);\n }\n if (weights.cls && cls && observedClsScore !== undefined) {\n score += weights.cls * (Insights.Common.evaluateCLSMetricScore(clsPostSavings) - observedClsScore);\n }\n\n insightToSortingRank.set(name, score);\n }\n\n // Now perform the actual sorting.\n const baselineOrderKeys = Object.keys(baselineOrder);\n const orderedKeys = Object.keys(insightSet.model);\n orderedKeys.sort((a, b) => {\n const a1 = baselineOrderKeys.indexOf(a);\n const b1 = baselineOrderKeys.indexOf(b);\n if (a1 >= 0 && b1 >= 0) {\n return a1 - b1;\n }\n if (a1 >= 0) {\n return -1;\n }\n if (b1 >= 0) {\n return 1;\n }\n return 0;\n });\n orderedKeys.sort((a, b) => (insightToSortingRank.get(b) ?? 0) - (insightToSortingRank.get(a) ?? 0));\n\n const newModel = {} as Insights.Types.InsightModels;\n for (const key of orderedKeys as Array<keyof Insights.Types.InsightModels>) {\n const model = insightSet.model[key];\n // @ts-expect-error Maybe someday typescript will be powerful enough to handle this.\n newModel[key] = model;\n }\n insightSet.model = newModel;\n }\n\n #computeInsightSet(data: Handlers.Types.HandlerData, context: Insights.Types.InsightSetContext): void {\n const logger = context.options.logger;\n\n if (!this.#insights) {\n this.#insights = new Map();\n }\n\n let id, urlString, navigation;\n if (context.navigation) {\n id = `NAVIGATION_${this.#insights.size}`;\n urlString = data.Meta.finalDisplayUrlByNavigationId.get(context.navigationId) ?? data.Meta.mainFrameURL;\n navigation = context.navigation;\n } else {\n id = Types.Events.NO_NAVIGATION;\n urlString = data.Meta.finalDisplayUrlByNavigationId.get('') ?? data.Meta.mainFrameURL;\n }\n\n const insightSetModel = {} as Insights.Types.InsightModels;\n const insightSetModelErrors: Insights.Types.InsightModelErrors = {};\n\n for (const [name, insight] of Object.entries(TraceProcessor.getInsightRunners())) {\n try {\n logger?.start(`insights:${name}`);\n const model = insight.generateInsight(data, context);\n model.frameId = context.frameId;\n const navId = context.navigation?.args.data?.navigationId;\n if (navId) {\n model.navigation = context.navigation;\n }\n model.createOverlays = () => {\n // @ts-expect-error: model is a union of all possible insight model types.\n return insight.createOverlays(model);\n };\n Object.assign(insightSetModel, {[name]: model});\n } catch (err) {\n Object.assign(insightSetModelErrors, {[name]: err});\n } finally {\n logger?.end(`insights:${name}`);\n }\n }\n\n // We may choose to exclude the insightSet if it's trivial. Trivial means:\n // 1. There's no navigation (it's an initial trace period)\n // 2. The duration is short.\n // 3. All the insights are passing (aka no insights to show the user)\n // 4. It has no metrics to report (apart from a CLS of 0, which is default)\n // Generally, these cases are the short time ranges before a page reload starts.\n const isNavigation = id === Types.Events.NO_NAVIGATION;\n const trivialThreshold = Helpers.Timing.milliToMicro(Types.Timing.Milli(5000));\n const everyInsightPasses = Object.values(insightSetModel).every(model => model && model.state === 'pass');\n\n const noLcp = !insightSetModel.LCPBreakdown?.lcpEvent;\n const noInp = !insightSetModel.INPBreakdown?.longestInteractionEvent;\n const noLayoutShifts = insightSetModel.CLSCulprits?.shifts?.size === 0;\n const shouldExclude = isNavigation && context.bounds.range < trivialThreshold && everyInsightPasses && noLcp &&\n noInp && noLayoutShifts;\n if (shouldExclude) {\n return;\n }\n\n let url;\n try {\n url = new URL(urlString);\n } catch {\n // We're pretty sure this only happens for our test fixture: missing-url.json.gz. Shouldn't\n // happen for real traces.\n return;\n }\n\n const insightSet: Insights.Types.InsightSet = {\n id,\n url,\n navigation,\n frameId: context.frameId,\n bounds: context.bounds,\n model: insightSetModel,\n modelErrors: insightSetModelErrors,\n };\n this.#insights.set(insightSet.id, insightSet);\n this.sortInsightSet(insightSet, context.options.metadata ?? null);\n }\n\n /**\n * Run all the insights and set the result to `#insights`.\n */\n #computeInsights(\n data: Handlers.Types.HandlerData, traceEvents: readonly Types.Events.Event[],\n options: Types.Configuration.ParseOptions): void {\n // This insights map will be populated by the helper methods.\n this.#insights = new Map();\n\n // Filter main frame navigations to those that have the necessary data (frameId and navigationId).\n // TODO(cjamcl): Does this filtering makes the \"use the next nav as the end time\" logic potentially broken? Are navs without nav id or frame even real?\n const navigations = data.Meta.mainFrameNavigations.filter(\n navigation => navigation.args.frame && navigation.args.data?.navigationId);\n\n this.#computeInsightsForInitialTracePeriod(data, navigations, options);\n\n for (const [index, navigation] of navigations.entries()) {\n const min = navigation.ts;\n // Use trace end for the last navigation, otherwise use the start of the next navigation.\n const max = index + 1 < navigations.length ? navigations[index + 1].ts : data.Meta.traceBounds.max;\n const bounds = Helpers.Timing.traceWindowFromMicroSeconds(min, max);\n this.#computeInsightsForNavigation(navigation, bounds, data, traceEvents, options);\n }\n }\n\n /**\n * Computes insights for the period before the first navigation, or for the entire trace if no navigations exist.\n */\n #computeInsightsForInitialTracePeriod(\n data: Handlers.Types.HandlerData, navigations: readonly Types.Events.NavigationStart[],\n options: Types.Configuration.ParseOptions): void {\n // Determine bounds: Use the period before the first navigation if navigations exist, otherwise use the entire trace bounds.\n const bounds = navigations.length > 0 ?\n Helpers.Timing.traceWindowFromMicroSeconds(data.Meta.traceBounds.min, navigations[0].ts) :\n data.Meta.traceBounds;\n\n const context: Insights.Types.InsightSetContext = {\n options,\n bounds,\n frameId: data.Meta.mainFrameId,\n // No navigation or lantern context applies to this initial/no-navigation period.\n };\n this.#computeInsightSet(data, context);\n }\n\n /**\n * Computes insights for a specific navigation event.\n */\n #computeInsightsForNavigation(\n navigation: Types.Events.NavigationStart, bounds: Types.Timing.TraceWindowMicro, data: Handlers.Types.HandlerData,\n traceEvents: readonly Types.Events.Event[], options: Types.Configuration.ParseOptions): void {\n const frameId = navigation.args.frame;\n // Guaranteed by the filter in #computeInsights\n const navigationId = navigation.args.data?.navigationId as string;\n\n // The lantern sub-context is optional on InsightSetContext, so not setting it is OK.\n // This is also a hedge against an error inside Lantern resulting in breaking the entire performance panel.\n // Additionally, many trace fixtures are too old to be processed by Lantern.\n let lantern: Insights.Types.LanternContext|undefined;\n try {\n options.logger?.start('insights:createLanternContext');\n lantern = this.#createLanternContext(data, traceEvents, frameId, navigation, options);\n } catch (e) {\n // Handle Lantern errors gracefully\n // Don't allow an error in constructing the Lantern graphs to break the rest of the trace processor.\n // Log unexpected errors, but suppress anything that occurs from a trace being too old.\n // Otherwise tests using old fixtures become way too noisy.\n const expectedErrors = [\n 'mainDocumentRequest not found',\n 'missing metric scores for main frame',\n 'missing metric: FCP',\n 'missing metric: LCP',\n 'No network requests found in trace',\n 'Trace is too old',\n ];\n if (!(e instanceof Lantern.Core.LanternError)) {\n // If this wasn't a managed LanternError, the stack trace is likely needed for debugging.\n console.error(e);\n } else if (!expectedErrors.some(err => e.message === err)) {\n // To reduce noise from tests, only print errors that are not expected to occur because a trace is\n // too old (for which there is no single check).\n console.error(e);\n }\n } finally {\n options.logger?.end('insights:createLanternContext');\n }\n\n const context: Insights.Types.InsightSetContext = {\n options,\n bounds,\n frameId,\n navigation,\n navigationId,\n lantern,\n };\n this.#computeInsightSet(data, context);\n }\n}\n\n/**\n * Some Handlers need data provided by others. Dependencies of a handler handler are\n * declared in the `deps` field.\n * @returns A map from trace event handler name to trace event handler whose entries\n * iterate in such a way that each handler is visited after its dependencies.\n */\nexport function sortHandlers(traceHandlers: Partial<Record<Handlers.Types.HandlerName, Handlers.Types.Handler>>):\n Map<Handlers.Types.HandlerName, Handlers.Types.Handler> {\n const sortedMap = new Map<Handlers.Types.HandlerName, Handlers.Types.Handler>();\n const visited = new Set<Handlers.Types.HandlerName>();\n const visitHandler = (handlerName: Handlers.Types.HandlerName): void => {\n if (sortedMap.has(handlerName)) {\n return;\n }\n if (visited.has(handlerName)) {\n let stackPath = '';\n for (const handler of visited) {\n if (stackPath || handler === handlerName) {\n stackPath += `${handler}->`;\n }\n }\n stackPath += handlerName;\n throw new Error(`Found dependency cycle in trace event handlers: ${stackPath}`);\n }\n visited.add(handlerName);\n const handler = traceHandlers[handlerName];\n if (!handler) {\n return;\n }\n const deps = handler.deps?.();\n if (deps) {\n deps.forEach(visitHandler);\n }\n sortedMap.set(handlerName, handler);\n };\n\n for (const handlerName of Object.keys(traceHandlers)) {\n visitHandler(handlerName as Handlers.Types.HandlerName);\n }\n return sortedMap;\n}\n"]}
|
package/models/trace/Styles.js
CHANGED
|
@@ -307,6 +307,10 @@ const UIStrings = {
|
|
|
307
307
|
* @description Text in Timeline UIUtils of the Performance panel
|
|
308
308
|
*/
|
|
309
309
|
largestContentfulPaint: 'Largest Contentful Paint',
|
|
310
|
+
/**
|
|
311
|
+
* @description Text in Timeline UIUtils of the Performance panel
|
|
312
|
+
*/
|
|
313
|
+
softLargestContentfulPaint: 'Soft Largest Contentful Paint',
|
|
310
314
|
/**
|
|
311
315
|
* @description Text for timestamps of items
|
|
312
316
|
*/
|
|
@@ -428,7 +432,7 @@ const UIStrings = {
|
|
|
428
432
|
/**
|
|
429
433
|
* @description Event category in the Performance panel for time spent to perform Garbage Collection for C++: https://chromium.googlesource.com/v8/v8/+/main/include/cppgc/README.md
|
|
430
434
|
*/
|
|
431
|
-
cppGc: '
|
|
435
|
+
cppGc: 'C++ GC',
|
|
432
436
|
/**
|
|
433
437
|
* @description Event category in the Performance panel for time spent to perform encryption
|
|
434
438
|
*/
|
|
@@ -684,6 +688,7 @@ export function maybeInitSylesMap() {
|
|
|
684
688
|
[Types.Events.Name.MARK_FIRST_PAINT]: new TimelineRecordStyle(i18nString(UIStrings.firstPaint), defaultCategoryStyles.painting, true),
|
|
685
689
|
[Types.Events.Name.MARK_FCP]: new TimelineRecordStyle(i18nString(UIStrings.firstContentfulPaint), defaultCategoryStyles.rendering, true),
|
|
686
690
|
[Types.Events.Name.MARK_LCP_CANDIDATE]: new TimelineRecordStyle(i18nString(UIStrings.largestContentfulPaint), defaultCategoryStyles.rendering, true),
|
|
691
|
+
[Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION]: new TimelineRecordStyle(i18nString(UIStrings.softLargestContentfulPaint), defaultCategoryStyles.rendering, true),
|
|
687
692
|
[Types.Events.Name.TIME_STAMP]: new TimelineRecordStyle(i18nString(UIStrings.timestamp), defaultCategoryStyles.scripting),
|
|
688
693
|
[Types.Events.Name.CONSOLE_TIME]: new TimelineRecordStyle(i18nString(UIStrings.consoleTime), defaultCategoryStyles.scripting),
|
|
689
694
|
[Types.Events.Name.USER_TIMING]: new TimelineRecordStyle(i18nString(UIStrings.userTiming), defaultCategoryStyles.scripting),
|
|
@@ -795,13 +800,16 @@ export function markerDetailsForEvent(event) {
|
|
|
795
800
|
color = 'var(--sys-color-green-bright)';
|
|
796
801
|
title = Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP;
|
|
797
802
|
}
|
|
798
|
-
if (Types.Events.
|
|
803
|
+
if (Types.Events.isAnyLargestContentfulPaintCandidate(event)) {
|
|
799
804
|
color = 'var(--sys-color-green)';
|
|
800
|
-
title =
|
|
805
|
+
title = Types.Events.isSoftLargestContentfulPaintCandidate(event) ?
|
|
806
|
+
Handlers.ModelHandlers.PageLoadMetrics.MetricName.SOFT_LCP :
|
|
807
|
+
Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP;
|
|
801
808
|
}
|
|
802
|
-
if (Types.Events.isNavigationStart(event)) {
|
|
809
|
+
if (Types.Events.isNavigationStart(event) || Types.Events.isSoftNavigationStart(event)) {
|
|
803
810
|
color = 'var(--color-text-primary)';
|
|
804
|
-
title = Handlers.ModelHandlers.PageLoadMetrics.MetricName.
|
|
811
|
+
title = Types.Events.isSoftNavigationStart(event) ? Handlers.ModelHandlers.PageLoadMetrics.MetricName.SOFT_NAV :
|
|
812
|
+
Handlers.ModelHandlers.PageLoadMetrics.MetricName.NAV;
|
|
805
813
|
}
|
|
806
814
|
if (Types.Events.isMarkDOMContent(event)) {
|
|
807
815
|
color = 'var(--color-text-disabled)';
|