@paulirish/trace_engine 0.0.36 → 0.0.38
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/tsconfig.tsbuildinfo +1 -1
- package/core/platform/NumberUtilities.d.ts +0 -1
- package/core/platform/NumberUtilities.js +0 -17
- package/core/platform/NumberUtilities.js.map +1 -1
- package/core/platform/PromiseUtilities.d.ts +10 -0
- package/core/platform/PromiseUtilities.js +18 -0
- package/core/platform/PromiseUtilities.js.map +1 -0
- package/core/platform/SetUtilities.d.ts +2 -0
- package/core/platform/SetUtilities.js +23 -0
- package/core/platform/SetUtilities.js.map +1 -0
- package/generated/protocol.d.ts +57 -11
- package/models/trace/EntriesFilter.d.ts +72 -0
- package/models/trace/EntriesFilter.js +296 -0
- package/models/trace/EntriesFilter.js.map +1 -0
- package/models/trace/LegacyTracingModel.js.map +1 -0
- package/models/trace/Processor.d.ts +1 -1
- package/models/trace/Processor.js +4 -4
- package/models/trace/Processor.js.map +1 -1
- package/models/trace/extras/Metadata.d.ts +2 -1
- package/models/trace/extras/Metadata.js +23 -4
- package/models/trace/extras/Metadata.js.map +1 -1
- package/models/trace/extras/TimelineJSProfile.d.ts +13 -0
- package/models/trace/extras/TimelineJSProfile.js +55 -0
- package/models/trace/extras/TimelineJSProfile.js.map +1 -0
- package/models/trace/extras/TraceFilter.d.ts +21 -0
- package/models/trace/extras/TraceFilter.js +51 -0
- package/models/trace/extras/TraceFilter.js.map +1 -0
- package/models/trace/extras/TraceTree.d.ts +94 -0
- package/models/trace/extras/TraceTree.js +530 -0
- package/models/trace/extras/TraceTree.js.map +1 -0
- package/models/trace/extras/URLForEntry.d.ts +6 -5
- package/models/trace/extras/URLForEntry.js +6 -5
- package/models/trace/extras/URLForEntry.js.map +1 -1
- package/models/trace/extras/extras-tsconfig.json +3 -0
- package/models/trace/extras/extras.js.map +1 -1
- package/models/trace/handlers/EnhancedTracesHandler.d.ts +48 -0
- package/models/trace/handlers/EnhancedTracesHandler.js +165 -0
- package/models/trace/handlers/EnhancedTracesHandler.js.map +1 -0
- package/models/trace/handlers/FlowsHandler.d.ts +7 -0
- package/models/trace/handlers/FlowsHandler.js +157 -0
- package/models/trace/handlers/FlowsHandler.js.map +1 -0
- package/models/trace/handlers/ImagePaintingHandler.d.ts +1 -0
- package/models/trace/handlers/ImagePaintingHandler.js +8 -0
- package/models/trace/handlers/ImagePaintingHandler.js.map +1 -1
- package/models/trace/handlers/LargestImagePaintHandler.d.ts +7 -1
- package/models/trace/handlers/LargestImagePaintHandler.js +43 -1
- package/models/trace/handlers/LargestImagePaintHandler.js.map +1 -1
- package/models/trace/handlers/MetaHandler.js +2 -3
- package/models/trace/handlers/MetaHandler.js.map +1 -1
- package/models/trace/handlers/ModelHandlers.d.ts +1 -0
- package/models/trace/handlers/ModelHandlers.js +1 -0
- package/models/trace/handlers/ModelHandlers.js.map +1 -1
- package/models/trace/handlers/NetworkRequestsHandler.js +2 -0
- package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
- package/models/trace/handlers/PageLoadMetricsHandler.d.ts +2 -1
- package/models/trace/handlers/PageLoadMetricsHandler.js.map +1 -1
- package/models/trace/handlers/handlers-tsconfig.json +1 -0
- package/models/trace/helpers/Timing.d.ts +1 -0
- package/models/trace/helpers/Timing.js +7 -0
- package/models/trace/helpers/Timing.js.map +1 -1
- package/models/trace/insights/CLSCulprits.d.ts +57 -0
- package/models/trace/insights/CLSCulprits.js +364 -0
- package/models/trace/insights/CLSCulprits.js.map +1 -0
- package/models/trace/insights/Common.d.ts +2 -10
- package/models/trace/insights/Common.js +1 -36
- package/models/trace/insights/Common.js.map +1 -1
- package/models/trace/insights/CumulativeLayoutShift.d.ts +13 -36
- package/models/trace/insights/CumulativeLayoutShift.js +73 -199
- package/models/trace/insights/CumulativeLayoutShift.js.map +1 -1
- package/models/trace/insights/DocumentLatency.d.ts +3 -3
- package/models/trace/insights/DocumentLatency.js +31 -3
- package/models/trace/insights/DocumentLatency.js.map +1 -1
- package/models/trace/insights/FontDisplay.d.ts +3 -3
- package/models/trace/insights/FontDisplay.js +23 -2
- package/models/trace/insights/FontDisplay.js.map +1 -1
- package/models/trace/insights/ImageDelivery.d.ts +23 -0
- package/models/trace/insights/ImageDelivery.js +130 -0
- package/models/trace/insights/ImageDelivery.js.map +1 -0
- package/models/trace/insights/InsightRunners.d.ts +0 -3
- package/models/trace/insights/InsightRunners.js +0 -3
- package/models/trace/insights/InsightRunners.js.map +1 -1
- package/models/trace/insights/InteractionToNextPaint.d.ts +3 -3
- package/models/trace/insights/InteractionToNextPaint.js +26 -3
- package/models/trace/insights/InteractionToNextPaint.js.map +1 -1
- package/models/trace/insights/LCPDiscovery.d.ts +13 -0
- package/models/trace/insights/LCPDiscovery.js +87 -0
- package/models/trace/insights/LCPDiscovery.js.map +1 -0
- package/models/trace/insights/LCPPhases.d.ts +34 -0
- package/models/trace/insights/LCPPhases.js +129 -0
- package/models/trace/insights/LCPPhases.js.map +1 -0
- package/models/trace/insights/LargestContentfulPaint.d.ts +7 -20
- package/models/trace/insights/LargestContentfulPaint.js +37 -57
- package/models/trace/insights/LargestContentfulPaint.js.map +1 -1
- package/models/trace/insights/Models.d.ts +11 -0
- package/models/trace/insights/Models.js +15 -0
- package/models/trace/insights/Models.js.map +1 -0
- package/models/trace/insights/RenderBlocking.d.ts +4 -4
- package/models/trace/insights/RenderBlocking.js +32 -23
- package/models/trace/insights/RenderBlocking.js.map +1 -1
- package/models/trace/insights/SlowCSSSelector.d.ts +3 -3
- package/models/trace/insights/SlowCSSSelector.js +27 -4
- package/models/trace/insights/SlowCSSSelector.js.map +1 -1
- package/models/trace/insights/{ThirdPartyWeb.d.ts → ThirdParties.d.ts} +3 -3
- package/models/trace/insights/{ThirdPartyWeb.js → ThirdParties.js} +26 -3
- package/models/trace/insights/ThirdParties.js.map +1 -0
- package/models/trace/insights/Viewport.d.ts +3 -3
- package/models/trace/insights/Viewport.js +27 -7
- package/models/trace/insights/Viewport.js.map +1 -1
- package/models/trace/insights/insights-tsconfig.json +6 -4
- package/models/trace/insights/insights.d.ts +1 -1
- package/models/trace/insights/insights.js +1 -1
- package/models/trace/insights/insights.js.map +1 -1
- package/models/trace/insights/types.d.ts +21 -9
- package/models/trace/insights/types.js +7 -0
- package/models/trace/insights/types.js.map +1 -1
- package/models/trace/lantern/BaseNode.d.ts +91 -0
- package/models/trace/lantern/BaseNode.js +268 -0
- package/models/trace/lantern/BaseNode.js.map +1 -0
- package/models/trace/lantern/CPUNode.d.ts +24 -0
- package/models/trace/lantern/CPUNode.js +64 -0
- package/models/trace/lantern/CPUNode.js.map +1 -0
- package/models/trace/lantern/LanternError.d.ts +3 -0
- package/models/trace/lantern/LanternError.js +7 -0
- package/models/trace/lantern/LanternError.js.map +1 -0
- package/models/trace/lantern/MetricsModule.d.ts +11 -0
- package/models/trace/lantern/MetricsModule.js +14 -0
- package/models/trace/lantern/MetricsModule.js.map +1 -0
- package/models/trace/lantern/NetworkNode.d.ts +22 -0
- package/models/trace/lantern/NetworkNode.js +83 -0
- package/models/trace/lantern/NetworkNode.js.map +1 -0
- package/models/trace/lantern/PageDependencyGraph.d.ts +43 -0
- package/models/trace/lantern/PageDependencyGraph.js +509 -0
- package/models/trace/lantern/PageDependencyGraph.js.map +1 -0
- package/models/trace/lantern/SimulationModule.d.ts +17 -0
- package/models/trace/lantern/SimulationModule.js +13 -0
- package/models/trace/lantern/SimulationModule.js.map +1 -0
- package/models/trace/lantern/simulation/NetworkAnalyzer.d.ts +112 -0
- package/models/trace/lantern/simulation/NetworkAnalyzer.js +486 -0
- package/models/trace/lantern/simulation/NetworkAnalyzer.js.map +1 -0
- package/models/trace/trace-tsconfig.json +6 -0
- package/models/trace/types/File.d.ts +5 -0
- package/models/trace/types/File.js +3 -0
- package/models/trace/types/File.js.map +1 -1
- package/models/trace/types/TraceEvents.d.ts +27 -5
- package/models/trace/types/TraceEvents.js +17 -5
- package/models/trace/types/TraceEvents.js.map +1 -1
- package/models/trace/types/types-tsconfig.json +6 -0
- package/package.json +1 -1
- package/test/test-trace-engine.mjs +9 -7
- package/.tmp/tsbuildinfo/models/trace/LanternComputationData.d.ts +0 -46
- package/.tmp/tsbuildinfo/models/trace/LanternComputationData.d.ts.map +0 -1
- package/.tmp/tsbuildinfo/models/trace/LegacyTracingModel.d.ts +0 -2
- package/.tmp/tsbuildinfo/models/trace/LegacyTracingModel.d.ts.map +0 -1
- package/.tmp/tsbuildinfo/models/trace/ModelImpl.d.ts +0 -72
- package/.tmp/tsbuildinfo/models/trace/ModelImpl.d.ts.map +0 -1
- package/.tmp/tsbuildinfo/models/trace/Processor.d.ts +0 -25
- package/.tmp/tsbuildinfo/models/trace/Processor.d.ts.map +0 -1
- package/.tmp/tsbuildinfo/models/trace/TracingManager.d.ts +0 -2
- package/.tmp/tsbuildinfo/models/trace/TracingManager.d.ts.map +0 -1
- package/.tmp/tsbuildinfo/models/trace/trace.d.ts +0 -13
- package/.tmp/tsbuildinfo/models/trace/trace.d.ts.map +0 -1
- package/models/trace/insights/ThirdPartyWeb.js.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as Types from '../types/types.js';
|
|
2
|
-
import type
|
|
2
|
+
import { type InsightModel, type InsightSetContext, type RequiredData } from './types.js';
|
|
3
3
|
export declare function deps(): ['SelectorStats'];
|
|
4
|
-
export type
|
|
4
|
+
export type SlowCSSSelectorInsightModel = InsightModel<{
|
|
5
5
|
totalElapsedMs: Types.Timing.MilliSeconds;
|
|
6
6
|
totalMatchAttempts: number;
|
|
7
7
|
totalMatchCount: number;
|
|
8
8
|
topElapsedMs: Types.Events.SelectorTiming[];
|
|
9
9
|
topMatchAttempts: Types.Events.SelectorTiming[];
|
|
10
10
|
}>;
|
|
11
|
-
export declare function generateInsight(parsedTrace: RequiredData<typeof deps>, context: InsightSetContext):
|
|
11
|
+
export declare function generateInsight(parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): SlowCSSSelectorInsightModel;
|
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
// Copyright 2024 The Chromium Authors. All rights reserved.
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
|
+
// import * as i18n from '../../../core/i18n/i18n.js';
|
|
4
5
|
import * as Helpers from '../helpers/helpers.js';
|
|
5
6
|
import { SelectorTimingsKey } from '../types/TraceEvents.js';
|
|
6
7
|
import * as Types from '../types/types.js';
|
|
8
|
+
import { InsightCategory } from './types.js';
|
|
9
|
+
const UIStrings = {
|
|
10
|
+
/**
|
|
11
|
+
*@description Title of an insight that provides details about slow CSS selectors.
|
|
12
|
+
*/
|
|
13
|
+
title: 'CSS Selector costs',
|
|
14
|
+
/**
|
|
15
|
+
* @description Text to describe how to improve the performance of CSS selectors.
|
|
16
|
+
*/
|
|
17
|
+
description: 'If Recalculate Style costs remain high, selector optimization can reduce them. [Optimize the selectors](https://developer.chrome.com/docs/devtools/performance/selector-stats) with both high elapsed time and high slow-path %. Simpler selectors, fewer selectors, a smaller DOM, and a shallower DOM will all reduce matching costs.',
|
|
18
|
+
};
|
|
19
|
+
// const str_ = i18n.i18n.registerUIStrings('models/trace/insights/SlowCSSSelector.ts', UIStrings);
|
|
20
|
+
const i18nString = string => string; // i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
7
21
|
export function deps() {
|
|
8
22
|
return ['SelectorStats'];
|
|
9
23
|
}
|
|
@@ -32,6 +46,15 @@ function aggregateSelectorStats(data, context) {
|
|
|
32
46
|
}
|
|
33
47
|
return [...selectorMap.values()];
|
|
34
48
|
}
|
|
49
|
+
function finalize(partialModel) {
|
|
50
|
+
return {
|
|
51
|
+
title: i18nString(UIStrings.title),
|
|
52
|
+
description: i18nString(UIStrings.description),
|
|
53
|
+
category: InsightCategory.ALL,
|
|
54
|
+
shouldShow: partialModel.topElapsedMs.length !== 0 && partialModel.topMatchAttempts.length !== 0,
|
|
55
|
+
...partialModel,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
35
58
|
export function generateInsight(parsedTrace, context) {
|
|
36
59
|
const selectorStatsData = parsedTrace.SelectorStats;
|
|
37
60
|
if (!selectorStatsData) {
|
|
@@ -47,14 +70,14 @@ export function generateInsight(parsedTrace, context) {
|
|
|
47
70
|
totalMatchCount += timing[SelectorTimingsKey.MatchCount];
|
|
48
71
|
});
|
|
49
72
|
// sort by elapsed time
|
|
50
|
-
const sortByElapsedMs = selectorTimings.
|
|
73
|
+
const sortByElapsedMs = [...selectorTimings].sort((a, b) => {
|
|
51
74
|
return b[SelectorTimingsKey.Elapsed] - a[SelectorTimingsKey.Elapsed];
|
|
52
75
|
});
|
|
53
76
|
// sort by match attempts
|
|
54
|
-
const sortByMatchAttempts = selectorTimings.
|
|
77
|
+
const sortByMatchAttempts = [...selectorTimings].sort((a, b) => {
|
|
55
78
|
return b[SelectorTimingsKey.MatchAttempts] - a[SelectorTimingsKey.MatchAttempts];
|
|
56
79
|
});
|
|
57
|
-
return {
|
|
80
|
+
return finalize({
|
|
58
81
|
// TODO: should we identify UpdateLayout events as linked to this insight?
|
|
59
82
|
relatedEvents: [],
|
|
60
83
|
totalElapsedMs: Types.Timing.MilliSeconds(totalElapsedUs / 1000.0),
|
|
@@ -62,6 +85,6 @@ export function generateInsight(parsedTrace, context) {
|
|
|
62
85
|
totalMatchCount,
|
|
63
86
|
topElapsedMs: sortByElapsedMs.slice(0, 3),
|
|
64
87
|
topMatchAttempts: sortByMatchAttempts.slice(0, 3),
|
|
65
|
-
};
|
|
88
|
+
});
|
|
66
89
|
}
|
|
67
90
|
//# sourceMappingURL=SlowCSSSelector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SlowCSSSelector.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/SlowCSSSelector.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAsB,kBAAkB,EAAC,MAAM,yBAAyB,CAAC;AAChF,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"SlowCSSSelector.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/SlowCSSSelector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\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 i18n from '../../../core/i18n/i18n.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport {type SelectorTiming, SelectorTimingsKey} from '../types/TraceEvents.js';\nimport * as Types from '../types/types.js';\n\nimport {InsightCategory, type InsightModel, type InsightSetContext, type RequiredData} from './types.js';\n\nconst UIStrings = {\n /**\n *@description Title of an insight that provides details about slow CSS selectors.\n */\n title: 'CSS Selector costs',\n\n /**\n * @description Text to describe how to improve the performance of CSS selectors.\n */\n description:\n 'If Recalculate Style costs remain high, selector optimization can reduce them. [Optimize the selectors](https://developer.chrome.com/docs/devtools/performance/selector-stats) with both high elapsed time and high slow-path %. Simpler selectors, fewer selectors, a smaller DOM, and a shallower DOM will all reduce matching costs.',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/SlowCSSSelector.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function deps(): ['SelectorStats'] {\n return ['SelectorStats'];\n}\n\nexport type SlowCSSSelectorInsightModel = InsightModel<{\n totalElapsedMs: Types.Timing.MilliSeconds,\n totalMatchAttempts: number,\n totalMatchCount: number,\n topElapsedMs: Types.Events.SelectorTiming[],\n topMatchAttempts: Types.Events.SelectorTiming[],\n}>;\n\nfunction aggregateSelectorStats(\n data: Map<Types.Events.UpdateLayoutTree, {\n timings: Types.Events.SelectorTiming[],\n }>,\n context: InsightSetContext): SelectorTiming[] {\n const selectorMap = new Map<String, SelectorTiming>();\n\n for (const [event, value] of data) {\n if (event.args.beginData?.frame !== context.frameId) {\n continue;\n }\n if (!Helpers.Timing.eventIsInBounds(event, context.bounds)) {\n continue;\n }\n for (const timing of value.timings) {\n const key = timing[SelectorTimingsKey.Selector] + '_' + timing[SelectorTimingsKey.StyleSheetId];\n const findTiming = selectorMap.get(key);\n if (findTiming !== undefined) {\n findTiming[SelectorTimingsKey.Elapsed] += timing[SelectorTimingsKey.Elapsed];\n findTiming[SelectorTimingsKey.FastRejectCount] += timing[SelectorTimingsKey.FastRejectCount];\n findTiming[SelectorTimingsKey.MatchAttempts] += timing[SelectorTimingsKey.MatchAttempts];\n findTiming[SelectorTimingsKey.MatchCount] += timing[SelectorTimingsKey.MatchCount];\n } else {\n selectorMap.set(key, {...timing});\n }\n }\n }\n\n return [...selectorMap.values()];\n}\n\nfunction finalize(partialModel: Omit<SlowCSSSelectorInsightModel, 'title'|'description'|'category'|'shouldShow'>):\n SlowCSSSelectorInsightModel {\n return {\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.ALL,\n shouldShow: partialModel.topElapsedMs.length !== 0 && partialModel.topMatchAttempts.length !== 0,\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): SlowCSSSelectorInsightModel {\n const selectorStatsData = parsedTrace.SelectorStats;\n\n if (!selectorStatsData) {\n throw new Error('no selector stats data');\n }\n\n const selectorTimings = aggregateSelectorStats(selectorStatsData.dataForUpdateLayoutEvent, context);\n\n let totalElapsedUs = 0;\n let totalMatchAttempts = 0;\n let totalMatchCount = 0;\n\n selectorTimings.map(timing => {\n totalElapsedUs += timing[SelectorTimingsKey.Elapsed];\n totalMatchAttempts += timing[SelectorTimingsKey.MatchAttempts];\n totalMatchCount += timing[SelectorTimingsKey.MatchCount];\n });\n\n // sort by elapsed time\n const sortByElapsedMs = [...selectorTimings].sort((a, b) => {\n return b[SelectorTimingsKey.Elapsed] - a[SelectorTimingsKey.Elapsed];\n });\n\n // sort by match attempts\n const sortByMatchAttempts = [...selectorTimings].sort((a, b) => {\n return b[SelectorTimingsKey.MatchAttempts] - a[SelectorTimingsKey.MatchAttempts];\n });\n\n return finalize({\n // TODO: should we identify UpdateLayout events as linked to this insight?\n relatedEvents: [],\n totalElapsedMs: Types.Timing.MilliSeconds(totalElapsedUs / 1000.0),\n totalMatchAttempts,\n totalMatchCount,\n topElapsedMs: sortByElapsedMs.slice(0, 3),\n topMatchAttempts: sortByMatchAttempts.slice(0, 3),\n });\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as Extras from '../extras/extras.js';
|
|
2
2
|
import type * as Types from '../types/types.js';
|
|
3
|
-
import type
|
|
3
|
+
import { type InsightModel, type InsightSetContext, type RequiredData } from './types.js';
|
|
4
4
|
export declare function deps(): ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'];
|
|
5
|
-
export type
|
|
5
|
+
export type ThirdPartiesInsightModel = InsightModel<{
|
|
6
6
|
entityByRequest: Map<Types.Events.SyntheticNetworkRequest, Extras.ThirdParties.Entity>;
|
|
7
7
|
requestsByEntity: Map<Extras.ThirdParties.Entity, Types.Events.SyntheticNetworkRequest[]>;
|
|
8
8
|
summaryByRequest: Map<Types.Events.SyntheticNetworkRequest, Extras.ThirdParties.Summary>;
|
|
@@ -10,4 +10,4 @@ export type ThirdPartyWebInsightResult = InsightResult<{
|
|
|
10
10
|
/** The entity for this navigation's URL. Any other entity is from a third party. */
|
|
11
11
|
firstPartyEntity?: Extras.ThirdParties.Entity;
|
|
12
12
|
}>;
|
|
13
|
-
export declare function generateInsight(parsedTrace: RequiredData<typeof deps>, context: InsightSetContext):
|
|
13
|
+
export declare function generateInsight(parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): ThirdPartiesInsightModel;
|
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
// Copyright 2024 The Chromium Authors. All rights reserved.
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
|
+
// import * as i18n from '../../../core/i18n/i18n.js';
|
|
4
5
|
import * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';
|
|
5
6
|
import * as Extras from '../extras/extras.js';
|
|
6
7
|
import * as Helpers from '../helpers/helpers.js';
|
|
8
|
+
import { InsightCategory } from './types.js';
|
|
9
|
+
const UIStrings = {
|
|
10
|
+
/** Title of an insight that provides details about the code on a web page that the user doesn't control (referred to as "third-party code"). */
|
|
11
|
+
title: 'Third parties',
|
|
12
|
+
/**
|
|
13
|
+
* @description Description of a DevTools insight that identifies the code on the page that the user doesn't control.
|
|
14
|
+
* This is displayed after a user expands the section to see more. No character length limits.
|
|
15
|
+
*/
|
|
16
|
+
description: 'Third party code can significantly impact load performance. ' +
|
|
17
|
+
'[Reduce and defer loading of third party code](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/) to prioritize your page\'s content.',
|
|
18
|
+
};
|
|
19
|
+
// const str_ = i18n.i18n.registerUIStrings('models/trace/insights/ThirdParties.ts', UIStrings);
|
|
20
|
+
const i18nString = string => string; // i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
7
21
|
export function deps() {
|
|
8
22
|
return ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'];
|
|
9
23
|
}
|
|
@@ -16,6 +30,15 @@ function getRelatedEvents(summaries, firstPartyEntity) {
|
|
|
16
30
|
}
|
|
17
31
|
return events;
|
|
18
32
|
}
|
|
33
|
+
function finalize(partialModel) {
|
|
34
|
+
return {
|
|
35
|
+
title: i18nString(UIStrings.title),
|
|
36
|
+
description: i18nString(UIStrings.description),
|
|
37
|
+
category: InsightCategory.ALL,
|
|
38
|
+
shouldShow: Boolean([...partialModel.summaryByEntity.entries()].find(kv => kv[0] !== partialModel.firstPartyEntity)),
|
|
39
|
+
...partialModel,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
19
42
|
export function generateInsight(parsedTrace, context) {
|
|
20
43
|
const networkRequests = parsedTrace.NetworkRequests.byTime.filter(event => {
|
|
21
44
|
if (!context.navigation) {
|
|
@@ -30,13 +53,13 @@ export function generateInsight(parsedTrace, context) {
|
|
|
30
53
|
const firstPartyUrl = context.navigation?.args.data?.documentLoaderURL ?? parsedTrace.Meta.mainFrameURL;
|
|
31
54
|
const firstPartyEntity = ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) ||
|
|
32
55
|
Extras.ThirdParties.makeUpEntity(madeUpEntityCache, firstPartyUrl);
|
|
33
|
-
return {
|
|
56
|
+
return finalize({
|
|
34
57
|
relatedEvents: getRelatedEvents(summaries, firstPartyEntity),
|
|
35
58
|
entityByRequest,
|
|
36
59
|
requestsByEntity: summaries.requestsByEntity,
|
|
37
60
|
summaryByRequest: summaries.byRequest,
|
|
38
61
|
summaryByEntity: summaries.byEntity,
|
|
39
62
|
firstPartyEntity,
|
|
40
|
-
};
|
|
63
|
+
});
|
|
41
64
|
}
|
|
42
|
-
//# sourceMappingURL=
|
|
65
|
+
//# sourceMappingURL=ThirdParties.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThirdParties.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/ThirdParties.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\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 i18n from '../../../core/i18n/i18n.js';\nimport * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';\nimport * as Extras from '../extras/extras.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {InsightCategory, type InsightModel, type InsightSetContext, type RequiredData} from './types.js';\n\nconst UIStrings = {\n /** Title of an insight that provides details about the code on a web page that the user doesn't control (referred to as \"third-party code\"). */\n title: 'Third parties',\n /**\n * @description Description of a DevTools insight that identifies the code on the page that the user doesn't control.\n * This is displayed after a user expands the section to see more. No character length limits.\n */\n description: 'Third party code can significantly impact load performance. ' +\n '[Reduce and defer loading of third party code](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/) to prioritize your page\\'s content.',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/ThirdParties.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function deps(): ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'] {\n return ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'];\n}\n\nexport type ThirdPartiesInsightModel = InsightModel<{\n entityByRequest: Map<Types.Events.SyntheticNetworkRequest, Extras.ThirdParties.Entity>,\n requestsByEntity: Map<Extras.ThirdParties.Entity, Types.Events.SyntheticNetworkRequest[]>,\n summaryByRequest: Map<Types.Events.SyntheticNetworkRequest, Extras.ThirdParties.Summary>,\n summaryByEntity: Map<Extras.ThirdParties.Entity, Extras.ThirdParties.Summary>,\n /** The entity for this navigation's URL. Any other entity is from a third party. */\n firstPartyEntity?: Extras.ThirdParties.Entity,\n}>;\n\nfunction getRelatedEvents(\n summaries: Extras.ThirdParties.SummaryMaps,\n firstPartyEntity: Extras.ThirdParties.Entity|undefined): Types.Events.Event[] {\n const events = [];\n\n for (const [entity, requests] of summaries.requestsByEntity.entries()) {\n if (entity !== firstPartyEntity) {\n events.push(...requests);\n }\n }\n\n return events;\n}\n\nfunction finalize(partialModel: Omit<ThirdPartiesInsightModel, 'title'|'description'|'category'|'shouldShow'>):\n ThirdPartiesInsightModel {\n return {\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.ALL,\n shouldShow:\n Boolean([...partialModel.summaryByEntity.entries()].find(kv => kv[0] !== partialModel.firstPartyEntity)),\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): ThirdPartiesInsightModel {\n const networkRequests = parsedTrace.NetworkRequests.byTime.filter(event => {\n if (!context.navigation) {\n return false;\n }\n\n if (event.args.data.frame !== context.frameId) {\n return false;\n }\n\n return Helpers.Timing.eventIsInBounds(event, context.bounds);\n });\n\n const {entityByRequest, madeUpEntityCache, summaries} = Extras.ThirdParties.getSummariesAndEntitiesForTraceBounds(\n parsedTrace as Handlers.Types.ParsedTrace, context.bounds, networkRequests);\n\n const firstPartyUrl = context.navigation?.args.data?.documentLoaderURL ?? parsedTrace.Meta.mainFrameURL;\n const firstPartyEntity = ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) ||\n Extras.ThirdParties.makeUpEntity(madeUpEntityCache, firstPartyUrl);\n\n return finalize({\n relatedEvents: getRelatedEvents(summaries, firstPartyEntity),\n entityByRequest,\n requestsByEntity: summaries.requestsByEntity,\n summaryByRequest: summaries.byRequest,\n summaryByEntity: summaries.byEntity,\n firstPartyEntity,\n });\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type * as Types from '../types/types.js';
|
|
2
|
-
import { type
|
|
2
|
+
import { type InsightModel, type InsightSetContext, type RequiredData } from './types.js';
|
|
3
3
|
export declare function deps(): ['Meta', 'UserInteractions'];
|
|
4
|
-
export type
|
|
4
|
+
export type ViewportInsightModel = InsightModel<{
|
|
5
5
|
mobileOptimized: boolean | null;
|
|
6
6
|
viewportEvent?: Types.Events.ParseMetaViewport;
|
|
7
7
|
}>;
|
|
8
|
-
export declare function generateInsight(parsedTrace: RequiredData<typeof deps>, context: InsightSetContext):
|
|
8
|
+
export declare function generateInsight(parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): ViewportInsightModel;
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
// Copyright 2024 The Chromium Authors. All rights reserved.
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
|
+
// import * as i18n from '../../../core/i18n/i18n.js';
|
|
4
5
|
import * as Helpers from '../helpers/helpers.js';
|
|
5
|
-
import { InsightWarning } from './types.js';
|
|
6
|
+
import { InsightCategory, InsightWarning, } from './types.js';
|
|
7
|
+
const UIStrings = {
|
|
8
|
+
/** Title of an insight that provides details about if the page's viewport is optimized for mobile viewing. */
|
|
9
|
+
title: 'Viewport not optimized for mobile',
|
|
10
|
+
/**
|
|
11
|
+
* @description Text to tell the user how a viewport meta element can improve performance. \xa0 is a non-breaking space
|
|
12
|
+
*/
|
|
13
|
+
description: 'The page\'s viewport is not mobile-optimized, so tap interactions may be [delayed by up to 300\xA0ms](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/).',
|
|
14
|
+
};
|
|
15
|
+
// const str_ = i18n.i18n.registerUIStrings('models/trace/insights/Viewport.ts', UIStrings);
|
|
16
|
+
const i18nString = string => string; // i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
6
17
|
export function deps() {
|
|
7
18
|
return ['Meta', 'UserInteractions'];
|
|
8
19
|
}
|
|
20
|
+
function finalize(partialModel) {
|
|
21
|
+
return {
|
|
22
|
+
title: i18nString(UIStrings.title),
|
|
23
|
+
description: i18nString(UIStrings.description),
|
|
24
|
+
category: InsightCategory.INP,
|
|
25
|
+
shouldShow: partialModel.mobileOptimized === false,
|
|
26
|
+
...partialModel,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
9
29
|
export function generateInsight(parsedTrace, context) {
|
|
10
30
|
const compositorEvents = parsedTrace.UserInteractions.beginCommitCompositorFrameEvents.filter(event => {
|
|
11
31
|
if (event.args.frame !== context.frameId) {
|
|
@@ -15,10 +35,10 @@ export function generateInsight(parsedTrace, context) {
|
|
|
15
35
|
});
|
|
16
36
|
if (!compositorEvents.length) {
|
|
17
37
|
// Trace doesn't have the data we need.
|
|
18
|
-
return {
|
|
38
|
+
return finalize({
|
|
19
39
|
mobileOptimized: null,
|
|
20
40
|
warnings: [InsightWarning.NO_LAYOUT],
|
|
21
|
-
};
|
|
41
|
+
});
|
|
22
42
|
}
|
|
23
43
|
const viewportEvent = parsedTrace.UserInteractions.parseMetaViewportEvents.find(event => {
|
|
24
44
|
if (event.args.data.frame !== context.frameId) {
|
|
@@ -29,16 +49,16 @@ export function generateInsight(parsedTrace, context) {
|
|
|
29
49
|
// Returns true only if all events are mobile optimized.
|
|
30
50
|
for (const event of compositorEvents) {
|
|
31
51
|
if (!event.args.is_mobile_optimized) {
|
|
32
|
-
return {
|
|
52
|
+
return finalize({
|
|
33
53
|
mobileOptimized: false,
|
|
34
54
|
viewportEvent,
|
|
35
55
|
metricSavings: { INP: 300 },
|
|
36
|
-
};
|
|
56
|
+
});
|
|
37
57
|
}
|
|
38
58
|
}
|
|
39
|
-
return {
|
|
59
|
+
return finalize({
|
|
40
60
|
mobileOptimized: true,
|
|
41
61
|
viewportEvent,
|
|
42
|
-
};
|
|
62
|
+
});
|
|
43
63
|
}
|
|
44
64
|
//# sourceMappingURL=Viewport.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Viewport.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/Viewport.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAGjD,OAAO,
|
|
1
|
+
{"version":3,"file":"Viewport.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/Viewport.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,4BAA4B,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EACL,eAAe,EAGf,cAAc,GAEf,MAAM,YAAY,CAAC;AAEpB,MAAM,SAAS,GAAG;IAChB,8GAA8G;IAC9G,KAAK,EAAE,mCAAmC;IAC1C;;OAEG;IACH,WAAW,EACP,sKAAsK;CAC3K,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,mCAAmC,EAAE,SAAS,CAAC,CAAC;AACzF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AACtC,CAAC;AAOD,SAAS,QAAQ,CAAC,YAAuF;IAEvG,OAAO;QACL,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC;QAClC,WAAW,EAAE,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC;QAC9C,QAAQ,EAAE,eAAe,CAAC,GAAG;QAC7B,UAAU,EAAE,YAAY,CAAC,eAAe,KAAK,KAAK;QAClD,GAAG,YAAY;KAChB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAC3B,WAAsC,EAAE,OAA0B;IACpE,MAAM,gBAAgB,GAAG,WAAW,CAAC,gBAAgB,CAAC,gCAAgC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACpG,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YACzC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC;QAC7B,uCAAuC;QACvC,OAAO,QAAQ,CAAC;YACd,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;SACrC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,aAAa,GAAG,WAAW,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;QACtF,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YAC9C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,wDAAwD;IACxD,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACpC,OAAO,QAAQ,CAAC;gBACd,eAAe,EAAE,KAAK;gBACtB,aAAa;gBACb,aAAa,EAAE,EAAC,GAAG,EAAE,GAAgC,EAAC;aACvD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;QACd,eAAe,EAAE,IAAI;QACrB,aAAa;KACd,CAAC,CAAC;AACL,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\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 i18n from '../../../core/i18n/i18n.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {\n InsightCategory,\n type InsightModel,\n type InsightSetContext,\n InsightWarning,\n type RequiredData,\n} from './types.js';\n\nconst UIStrings = {\n /** Title of an insight that provides details about if the page's viewport is optimized for mobile viewing. */\n title: 'Viewport not optimized for mobile',\n /**\n * @description Text to tell the user how a viewport meta element can improve performance. \\xa0 is a non-breaking space\n */\n description:\n 'The page\\'s viewport is not mobile-optimized, so tap interactions may be [delayed by up to 300\\xA0ms](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/).',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('models/trace/insights/Viewport.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function deps(): ['Meta', 'UserInteractions'] {\n return ['Meta', 'UserInteractions'];\n}\n\nexport type ViewportInsightModel = InsightModel<{\n mobileOptimized: boolean | null,\n viewportEvent?: Types.Events.ParseMetaViewport,\n}>;\n\nfunction finalize(partialModel: Omit<ViewportInsightModel, 'title'|'description'|'category'|'shouldShow'>):\n ViewportInsightModel {\n return {\n title: i18nString(UIStrings.title),\n description: i18nString(UIStrings.description),\n category: InsightCategory.INP,\n shouldShow: partialModel.mobileOptimized === false,\n ...partialModel,\n };\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): ViewportInsightModel {\n const compositorEvents = parsedTrace.UserInteractions.beginCommitCompositorFrameEvents.filter(event => {\n if (event.args.frame !== context.frameId) {\n return false;\n }\n\n return Helpers.Timing.eventIsInBounds(event, context.bounds);\n });\n\n if (!compositorEvents.length) {\n // Trace doesn't have the data we need.\n return finalize({\n mobileOptimized: null,\n warnings: [InsightWarning.NO_LAYOUT],\n });\n }\n\n const viewportEvent = parsedTrace.UserInteractions.parseMetaViewportEvents.find(event => {\n if (event.args.data.frame !== context.frameId) {\n return false;\n }\n\n return Helpers.Timing.eventIsInBounds(event, context.bounds);\n });\n\n // Returns true only if all events are mobile optimized.\n for (const event of compositorEvents) {\n if (!event.args.is_mobile_optimized) {\n return finalize({\n mobileOptimized: false,\n viewportEvent,\n metricSavings: {INP: 300 as Types.Timing.MilliSeconds},\n });\n }\n }\n\n return finalize({\n mobileOptimized: true,\n viewportEvent,\n });\n}\n"]}
|
|
@@ -29,16 +29,18 @@
|
|
|
29
29
|
"useUnknownInCatchVariables": false
|
|
30
30
|
},
|
|
31
31
|
"files": [
|
|
32
|
+
"../../../../../../../front_end/models/trace/insights/CLSCulprits.ts",
|
|
32
33
|
"../../../../../../../front_end/models/trace/insights/Common.ts",
|
|
33
|
-
"../../../../../../../front_end/models/trace/insights/CumulativeLayoutShift.ts",
|
|
34
34
|
"../../../../../../../front_end/models/trace/insights/DocumentLatency.ts",
|
|
35
35
|
"../../../../../../../front_end/models/trace/insights/FontDisplay.ts",
|
|
36
|
-
"../../../../../../../front_end/models/trace/insights/
|
|
36
|
+
"../../../../../../../front_end/models/trace/insights/ImageDelivery.ts",
|
|
37
37
|
"../../../../../../../front_end/models/trace/insights/InteractionToNextPaint.ts",
|
|
38
|
-
"../../../../../../../front_end/models/trace/insights/
|
|
38
|
+
"../../../../../../../front_end/models/trace/insights/LCPDiscovery.ts",
|
|
39
|
+
"../../../../../../../front_end/models/trace/insights/LCPPhases.ts",
|
|
40
|
+
"../../../../../../../front_end/models/trace/insights/Models.ts",
|
|
39
41
|
"../../../../../../../front_end/models/trace/insights/RenderBlocking.ts",
|
|
40
42
|
"../../../../../../../front_end/models/trace/insights/SlowCSSSelector.ts",
|
|
41
|
-
"../../../../../../../front_end/models/trace/insights/
|
|
43
|
+
"../../../../../../../front_end/models/trace/insights/ThirdParties.ts",
|
|
42
44
|
"../../../../../../../front_end/models/trace/insights/Viewport.ts",
|
|
43
45
|
"../../../../../../../front_end/models/trace/insights/types.ts",
|
|
44
46
|
"../../../../../../../front_end/legacy/legacy-defs.d.ts",
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
export * as Common from './Common.js';
|
|
5
|
-
export * as
|
|
5
|
+
export * as Models from './Models.js';
|
|
6
6
|
export * as Types from './types.js';
|
|
7
7
|
//# sourceMappingURL=insights.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"insights.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/insights.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"insights.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/insights.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nexport * as Common from './Common.js';\nexport * as Models from './Models.js';\nexport * as Types from './types.js';\n"]}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
// import type * as Common from '../../../core/common/common.js';
|
|
1
2
|
import type * as Handlers from '../handlers/handlers.js';
|
|
2
3
|
import type * as Lantern from '../lantern/lantern.js';
|
|
3
4
|
import type * as Types from '../types/types.js';
|
|
4
|
-
import type * as
|
|
5
|
+
import type * as Models from './Models.js';
|
|
5
6
|
/**
|
|
6
7
|
* Context for the portion of the trace an insight should look at.
|
|
7
8
|
*/
|
|
@@ -23,7 +24,7 @@ export interface LanternContext {
|
|
|
23
24
|
simulator: Lantern.Simulation.Simulator<Types.Events.SyntheticNetworkRequest>;
|
|
24
25
|
metrics: Record<string, Lantern.Metrics.MetricResult>;
|
|
25
26
|
}
|
|
26
|
-
export type
|
|
27
|
+
export type InsightModelsType = typeof Models;
|
|
27
28
|
export declare enum InsightWarning {
|
|
28
29
|
NO_FP = "NO_FP",
|
|
29
30
|
NO_LCP = "NO_LCP",
|
|
@@ -37,7 +38,18 @@ export interface MetricSavings {
|
|
|
37
38
|
CLS?: number;
|
|
38
39
|
INP?: Types.Timing.MilliSeconds;
|
|
39
40
|
}
|
|
40
|
-
export
|
|
41
|
+
export declare enum InsightCategory {
|
|
42
|
+
ALL = "All",
|
|
43
|
+
INP = "INP",
|
|
44
|
+
LCP = "LCP",
|
|
45
|
+
CLS = "CLS"
|
|
46
|
+
}
|
|
47
|
+
export type InsightModel<R extends Record<string, unknown>> = R & {
|
|
48
|
+
title: string;
|
|
49
|
+
description: string;
|
|
50
|
+
category: InsightCategory;
|
|
51
|
+
/** True if there is anything of interest to display to the user. */
|
|
52
|
+
shouldShow: boolean;
|
|
41
53
|
relatedEvents?: Types.Events.Event[];
|
|
42
54
|
warnings?: InsightWarning[];
|
|
43
55
|
metricSavings?: MetricSavings;
|
|
@@ -47,21 +59,21 @@ export type InsightResult<R extends Record<string, unknown>> = R & {
|
|
|
47
59
|
* this could instead represent the duration from the beginning of the trace up to the first recorded
|
|
48
60
|
* navigation (or the end of the trace).
|
|
49
61
|
*/
|
|
50
|
-
export type
|
|
62
|
+
export type InsightSet = {
|
|
51
63
|
/** If for a navigation, this is the navigationId. Else it is Trace.Types.Events.NO_NAVIGATION. */
|
|
52
64
|
id: Types.Events.NavigationId;
|
|
53
65
|
/** The URL to show in the accordion list. */
|
|
54
66
|
url: URL;
|
|
55
67
|
frameId: string;
|
|
56
68
|
bounds: Types.Timing.TraceWindowMicroSeconds;
|
|
57
|
-
|
|
69
|
+
model: InsightModels;
|
|
58
70
|
navigation?: Types.Events.NavigationStart;
|
|
59
71
|
};
|
|
60
72
|
/**
|
|
61
|
-
* Contains insights for a specific
|
|
73
|
+
* Contains insights for a specific insight set.
|
|
62
74
|
*/
|
|
63
|
-
export type
|
|
64
|
-
[I in keyof
|
|
75
|
+
export type InsightModels = {
|
|
76
|
+
[I in keyof InsightModelsType]: ReturnType<InsightModelsType[I]['generateInsight']>;
|
|
65
77
|
};
|
|
66
78
|
/**
|
|
67
79
|
* Contains insights for the entire trace. Insights are mostly grouped by `navigationId`, with one exception:
|
|
@@ -69,7 +81,7 @@ export type InsightResults = {
|
|
|
69
81
|
* If the analyzed trace started after the navigation, and has meaningful work with that span, there is no
|
|
70
82
|
* navigation to map it to. In this case `Types.Events.NO_NAVIGATION` is used for the key.
|
|
71
83
|
*/
|
|
72
|
-
export type TraceInsightSets = Map<Types.Events.NavigationId,
|
|
84
|
+
export type TraceInsightSets = Map<Types.Events.NavigationId, InsightSet>;
|
|
73
85
|
/**
|
|
74
86
|
* Represents the narrow set of dependencies defined by an insight's `deps()` function. `Meta` is always included regardless of `deps()`.
|
|
75
87
|
*/
|
|
@@ -9,4 +9,11 @@ export var InsightWarning;
|
|
|
9
9
|
InsightWarning["NO_DOCUMENT_REQUEST"] = "NO_DOCUMENT_REQUEST";
|
|
10
10
|
InsightWarning["NO_LAYOUT"] = "NO_LAYOUT";
|
|
11
11
|
})(InsightWarning || (InsightWarning = {}));
|
|
12
|
+
export var InsightCategory;
|
|
13
|
+
(function (InsightCategory) {
|
|
14
|
+
InsightCategory["ALL"] = "All";
|
|
15
|
+
InsightCategory["INP"] = "INP";
|
|
16
|
+
InsightCategory["LCP"] = "LCP";
|
|
17
|
+
InsightCategory["CLS"] = "CLS";
|
|
18
|
+
})(InsightCategory || (InsightCategory = {}));
|
|
12
19
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/types.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/types.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAoC7B,MAAM,CAAN,IAAY,cAMX;AAND,WAAY,cAAc;IACxB,iCAAe,CAAA;IACf,mCAAiB,CAAA;IACjB,uEAAuE;IACvE,6DAA2C,CAAA;IAC3C,yCAAuB,CAAA;AACzB,CAAC,EANW,cAAc,KAAd,cAAc,QAMzB;AAYD,MAAM,CAAN,IAAY,eAKX;AALD,WAAY,eAAe;IACzB,8BAAW,CAAA;IACX,8BAAW,CAAA;IACX,8BAAW,CAAA;IACX,8BAAW,CAAA;AACb,CAAC,EALW,eAAe,KAAf,eAAe,QAK1B","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Common from '../../../core/common/common.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport type * as Lantern from '../lantern/lantern.js';\nimport type * as Types from '../types/types.js';\n\nimport type * as Models from './Models.js';\n\n/**\n * Context for the portion of the trace an insight should look at.\n */\nexport type InsightSetContext = InsightSetContextWithoutNavigation|InsightSetContextWithNavigation;\n\nexport interface InsightSetContextWithoutNavigation {\n bounds: Types.Timing.TraceWindowMicroSeconds;\n frameId: string;\n navigation?: never;\n}\n\nexport interface InsightSetContextWithNavigation {\n bounds: Types.Timing.TraceWindowMicroSeconds;\n frameId: string;\n navigation: Types.Events.NavigationStart;\n navigationId: string;\n lantern?: LanternContext;\n}\n\nexport interface LanternContext {\n graph: Lantern.Graph.Node<Types.Events.SyntheticNetworkRequest>;\n simulator: Lantern.Simulation.Simulator<Types.Events.SyntheticNetworkRequest>;\n metrics: Record<string, Lantern.Metrics.MetricResult>;\n}\n\nexport type InsightModelsType = typeof Models;\n\nexport enum InsightWarning {\n NO_FP = 'NO_FP',\n NO_LCP = 'NO_LCP',\n // No network request could be identified as the primary HTML document.\n NO_DOCUMENT_REQUEST = 'NO_DOCUMENT_REQUEST',\n NO_LAYOUT = 'NO_LAYOUT',\n}\n\nexport interface MetricSavings {\n /* eslint-disable @typescript-eslint/naming-convention */\n FCP?: Types.Timing.MilliSeconds;\n LCP?: Types.Timing.MilliSeconds;\n TBT?: Types.Timing.MilliSeconds;\n CLS?: number;\n INP?: Types.Timing.MilliSeconds;\n /* eslint-enable @typescript-eslint/naming-convention */\n}\n\nexport enum InsightCategory {\n ALL = 'All',\n INP = 'INP',\n LCP = 'LCP',\n CLS = 'CLS',\n}\n\nexport type InsightModel<R extends Record<string, unknown>> = R&{\n title: Common.UIString.LocalizedString,\n description: Common.UIString.LocalizedString,\n category: InsightCategory,\n /** True if there is anything of interest to display to the user. */\n shouldShow: boolean,\n relatedEvents?: Types.Events.Event[],\n warnings?: InsightWarning[],\n metricSavings?: MetricSavings,\n};\n\n/**\n * Contains insights for a specific navigation. If a trace began after a navigation already started,\n * this could instead represent the duration from the beginning of the trace up to the first recorded\n * navigation (or the end of the trace).\n */\nexport type InsightSet = {\n /** If for a navigation, this is the navigationId. Else it is Trace.Types.Events.NO_NAVIGATION. */\n id: Types.Events.NavigationId,\n /** The URL to show in the accordion list. */\n url: URL,\n frameId: string,\n bounds: Types.Timing.TraceWindowMicroSeconds,\n model: InsightModels,\n navigation?: Types.Events.NavigationStart,\n};\n\n/**\n * Contains insights for a specific insight set.\n */\nexport type InsightModels = {\n [I in keyof InsightModelsType]: ReturnType<InsightModelsType[I]['generateInsight']>;\n};\n\n/**\n * Contains insights for the entire trace. Insights are mostly grouped by `navigationId`, with one exception:\n *\n * If the analyzed trace started after the navigation, and has meaningful work with that span, there is no\n * navigation to map it to. In this case `Types.Events.NO_NAVIGATION` is used for the key.\n */\nexport type TraceInsightSets = Map<Types.Events.NavigationId, InsightSet>;\n\n/**\n * Represents the narrow set of dependencies defined by an insight's `deps()` function. `Meta` is always included regardless of `deps()`.\n */\nexport type RequiredData<D extends() => Array<keyof typeof Handlers.ModelHandlers>> =\n Handlers.Types.EnabledHandlerDataWithMeta<Pick<typeof Handlers.ModelHandlers, ReturnType<D>[number]>>;\n"]}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { type CPUNode } from './CPUNode.js';
|
|
2
|
+
import { type NetworkNode } from './NetworkNode.js';
|
|
3
|
+
import type * as Lantern from './types/lantern.js';
|
|
4
|
+
/**
|
|
5
|
+
* A union of all types derived from BaseNode, allowing type check discrimination
|
|
6
|
+
* based on `node.type`. If a new node type is created, it should be added here.
|
|
7
|
+
*/
|
|
8
|
+
export type Node<T = Lantern.AnyNetworkObject> = CPUNode<T> | NetworkNode<T>;
|
|
9
|
+
/**
|
|
10
|
+
* @fileoverview This class encapsulates logic for handling resources and tasks used to model the
|
|
11
|
+
* execution dependency graph of the page. A node has a unique identifier and can depend on other
|
|
12
|
+
* nodes/be depended on. The construction of the graph maintains some important invariants that are
|
|
13
|
+
* inherent to the model:
|
|
14
|
+
*
|
|
15
|
+
* 1. The graph is a DAG, there are no cycles.
|
|
16
|
+
* 2. There is always a root node upon which all other nodes eventually depend.
|
|
17
|
+
*
|
|
18
|
+
* This allows particular optimizations in this class so that we do no need to check for cycles as
|
|
19
|
+
* these methods are called and we can always start traversal at the root node.
|
|
20
|
+
*/
|
|
21
|
+
declare class BaseNode<T = Lantern.AnyNetworkObject> {
|
|
22
|
+
static types: {
|
|
23
|
+
readonly NETWORK: "network";
|
|
24
|
+
readonly CPU: "cpu";
|
|
25
|
+
};
|
|
26
|
+
_id: string;
|
|
27
|
+
_isMainDocument: boolean;
|
|
28
|
+
_dependents: Node[];
|
|
29
|
+
_dependencies: Node[];
|
|
30
|
+
constructor(id: string);
|
|
31
|
+
get id(): string;
|
|
32
|
+
get type(): 'network' | 'cpu';
|
|
33
|
+
/**
|
|
34
|
+
* In microseconds
|
|
35
|
+
*/
|
|
36
|
+
get startTime(): number;
|
|
37
|
+
/**
|
|
38
|
+
* In microseconds
|
|
39
|
+
*/
|
|
40
|
+
get endTime(): number;
|
|
41
|
+
setIsMainDocument(value: boolean): void;
|
|
42
|
+
isMainDocument(): boolean;
|
|
43
|
+
getDependents(): Node[];
|
|
44
|
+
getNumberOfDependents(): number;
|
|
45
|
+
getDependencies(): Node[];
|
|
46
|
+
getNumberOfDependencies(): number;
|
|
47
|
+
getRootNode(): Node<T>;
|
|
48
|
+
addDependent(node: Node): void;
|
|
49
|
+
addDependency(node: Node): void;
|
|
50
|
+
removeDependent(node: Node): void;
|
|
51
|
+
removeDependency(node: Node): void;
|
|
52
|
+
removeAllDependencies(): void;
|
|
53
|
+
/**
|
|
54
|
+
* Computes whether the given node is anywhere in the dependency graph of this node.
|
|
55
|
+
* While this method can prevent cycles, it walks the graph and should be used sparingly.
|
|
56
|
+
* Nodes are always considered dependent on themselves for the purposes of cycle detection.
|
|
57
|
+
*/
|
|
58
|
+
isDependentOn(node: BaseNode<T>): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Clones the node's information without adding any dependencies/dependents.
|
|
61
|
+
*/
|
|
62
|
+
cloneWithoutRelationships(): Node<T>;
|
|
63
|
+
/**
|
|
64
|
+
* Clones the entire graph connected to this node filtered by the optional predicate. If a node is
|
|
65
|
+
* included by the predicate, all nodes along the paths between the node and the root will be included. If the
|
|
66
|
+
* node this was called on is not included in the resulting filtered graph, the method will throw.
|
|
67
|
+
*/
|
|
68
|
+
cloneWithRelationships(predicate?: (arg0: Node) => boolean): Node;
|
|
69
|
+
/**
|
|
70
|
+
* Traverses all connected nodes in BFS order, calling `callback` exactly once
|
|
71
|
+
* on each. `traversalPath` is the shortest (though not necessarily unique)
|
|
72
|
+
* path from `node` to the root of the iteration.
|
|
73
|
+
*
|
|
74
|
+
* The `getNextNodes` function takes a visited node and returns which nodes to
|
|
75
|
+
* visit next. It defaults to returning the node's dependents.
|
|
76
|
+
*/
|
|
77
|
+
traverse(callback: (node: Node<T>, traversalPath: Node<T>[]) => void, getNextNodes?: (arg0: Node<T>) => Node<T>[]): void;
|
|
78
|
+
/**
|
|
79
|
+
* @see BaseNode.traverse
|
|
80
|
+
*/
|
|
81
|
+
traverseGenerator(getNextNodes?: (arg0: Node) => Node[]): Generator<{
|
|
82
|
+
node: Node;
|
|
83
|
+
traversalPath: Node[];
|
|
84
|
+
}, void, unknown>;
|
|
85
|
+
/**
|
|
86
|
+
* Returns whether the given node has a cycle in its dependent graph by performing a DFS.
|
|
87
|
+
*/
|
|
88
|
+
static hasCycle(node: Node, direction?: 'dependents' | 'dependencies' | 'both'): boolean;
|
|
89
|
+
canDependOn(node: Node): boolean;
|
|
90
|
+
}
|
|
91
|
+
export { BaseNode };
|