chrome-devtools-frontend 1.0.1558690 → 1.0.1561080
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/front_end/Images/src/container.svg +4 -0
- package/front_end/core/common/Gzip.ts +15 -0
- package/front_end/core/host/InspectorFrontendHostStub.ts +0 -3
- package/front_end/core/platform/ArrayUtilities.ts +13 -0
- package/front_end/core/root/Runtime.ts +0 -5
- package/front_end/core/sdk/CSSMetadata.ts +6 -6
- package/front_end/core/sdk/CSSModel.ts +2 -2
- package/front_end/core/sdk/DOMModel.ts +15 -3
- package/front_end/core/sdk/NetworkManager.ts +4 -0
- package/front_end/core/sdk/NetworkRequest.ts +9 -0
- package/front_end/core/sdk/OverlayModel.ts +20 -9
- package/front_end/entrypoints/main/MainImpl.ts +2 -1
- package/front_end/generated/InspectorBackendCommands.ts +6 -3
- package/front_end/generated/SupportedCSSProperties.js +64 -32
- package/front_end/generated/protocol-mapping.d.ts +16 -0
- package/front_end/generated/protocol-proxy-api.d.ts +12 -0
- package/front_end/generated/protocol.ts +38 -1
- package/front_end/models/ai_assistance/agents/StylingAgent.ts +1 -1
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +11 -7
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +23 -22
- package/front_end/models/badges/UserBadges.ts +48 -16
- package/front_end/models/greendev/Prototypes.ts +6 -1
- package/front_end/models/trace/LanternComputationData.ts +4 -3
- package/front_end/models/trace/Processor.ts +6 -5
- package/front_end/models/trace/Styles.ts +10 -1
- package/front_end/models/trace/extras/TraceTree.ts +1 -1
- package/front_end/models/trace/handlers/LargestImagePaintHandler.ts +2 -2
- package/front_end/models/trace/handlers/MetaHandler.ts +14 -0
- package/front_end/models/trace/handlers/PageLoadMetricsHandler.ts +59 -34
- package/front_end/models/trace/helpers/Timing.ts +8 -1
- package/front_end/models/trace/insights/Common.ts +1 -1
- package/front_end/models/trace/insights/LCPBreakdown.ts +4 -4
- package/front_end/models/trace/insights/LCPDiscovery.ts +3 -3
- package/front_end/models/trace/insights/RenderBlocking.ts +1 -1
- package/front_end/models/trace/insights/types.ts +1 -1
- package/front_end/models/trace/types/TraceEvents.ts +62 -10
- package/front_end/panels/ai_assistance/AiAssistancePanel.ts +11 -142
- package/front_end/panels/ai_assistance/PatchWidget.ts +90 -72
- package/front_end/panels/ai_assistance/ai_assistance.ts +1 -0
- package/front_end/panels/ai_assistance/components/ChatInput.ts +701 -0
- package/front_end/panels/ai_assistance/components/ChatView.ts +71 -1268
- package/front_end/panels/ai_assistance/components/UserActionRow.ts +514 -31
- package/front_end/panels/ai_assistance/components/chatInput.css +387 -0
- package/front_end/panels/ai_assistance/components/chatView.css +38 -599
- package/front_end/panels/ai_assistance/components/userActionRow.css +230 -0
- package/front_end/panels/autofill/AutofillView.ts +2 -2
- package/front_end/panels/changes/ChangesView.ts +15 -1
- package/front_end/panels/changes/changesView.css +6 -0
- package/front_end/panels/common/AiCodeGenerationTeaser.ts +48 -12
- package/front_end/panels/common/BadgeNotification.ts +44 -58
- package/front_end/panels/common/CopyChangesToPrompt.ts +233 -0
- package/front_end/panels/common/aiCodeGenerationTeaser.css +14 -0
- package/front_end/panels/common/common.ts +2 -1
- package/front_end/panels/console/consoleView.css +1 -1
- package/front_end/panels/elements/CSSRuleValidator.ts +38 -0
- package/front_end/panels/elements/ElementsTreeElement.ts +222 -377
- package/front_end/panels/elements/ElementsTreeOutline.ts +0 -23
- package/front_end/panels/elements/ShortcutTreeElement.ts +57 -50
- package/front_end/panels/elements/StylePropertiesSection.ts +1 -3
- package/front_end/panels/elements/StylesSidebarPane.ts +15 -4
- package/front_end/panels/elements/components/AdornerManager.ts +5 -149
- package/front_end/panels/issues/HiddenIssuesRow.ts +1 -2
- package/front_end/panels/issues/IssueKindView.ts +2 -4
- package/front_end/panels/issues/IssueView.ts +2 -4
- package/front_end/panels/network/NetworkDataGridNode.ts +65 -1
- package/front_end/panels/network/NetworkLogView.ts +2 -4
- package/front_end/panels/network/NetworkLogViewColumns.ts +9 -0
- package/front_end/panels/screencast/ScreencastApp.ts +1 -0
- package/front_end/panels/settings/SettingsScreen.ts +3 -2
- package/front_end/panels/timeline/CompatibilityTracksAppender.ts +14 -1
- package/front_end/panels/timeline/StatusDialog.ts +4 -3
- package/front_end/panels/timeline/ThirdPartyTreeView.ts +1 -4
- package/front_end/panels/timeline/TimelineController.ts +185 -3
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +52 -25
- package/front_end/panels/timeline/TimelineFlameChartNetworkDataProvider.ts +3 -16
- package/front_end/panels/timeline/TimelineFlameChartView.ts +65 -21
- package/front_end/panels/timeline/TimelinePanel.ts +86 -126
- package/front_end/panels/timeline/TimelineTreeView.ts +1 -0
- package/front_end/panels/timeline/TimelineUIUtils.ts +28 -2
- package/front_end/panels/timeline/TimingsTrackAppender.ts +3 -1
- package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +1 -1
- package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +2 -2
- package/front_end/panels/timeline/components/insights/RenderBlocking.ts +6 -4
- package/front_end/panels/timeline/components/insights/Table.ts +3 -3
- package/front_end/panels/timeline/overlays/OverlaysImpl.ts +4 -0
- package/front_end/panels/timeline/timelinePanel.css +8 -1
- package/front_end/panels/timeline/utils/EntryNodes.ts +2 -1
- package/front_end/panels/whats_new/ReleaseNoteText.ts +15 -9
- package/front_end/panels/whats_new/resources/WNDT.md +6 -6
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/codemirror.next/rebuild.sh +1 -1
- package/front_end/third_party/lit/rebuild.sh +1 -1
- package/front_end/third_party/puppeteer/README.chromium +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts +2 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.js +9 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPRequest.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.d.ts +3 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.js +9 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/HTTPResponse.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.d.ts +3 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.js +10 -0
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/core/Request.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js +8 -4
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/injected.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +10 -1
- package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +13 -7
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts +2 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.js +9 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPRequest.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.d.ts +3 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.js +9 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/HTTPResponse.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.d.ts +3 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.js +10 -0
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/core/Request.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js +8 -4
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.d.ts.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/injected.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.d.ts +1 -1
- package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/util/version.js +1 -1
- package/front_end/third_party/puppeteer/package/lib/types.d.ts +10 -1
- package/front_end/third_party/puppeteer/package/package.json +3 -3
- package/front_end/third_party/puppeteer/package/src/api/Page.ts +2 -3
- package/front_end/third_party/puppeteer/package/src/bidi/HTTPRequest.ts +13 -0
- package/front_end/third_party/puppeteer/package/src/bidi/HTTPResponse.ts +10 -0
- package/front_end/third_party/puppeteer/package/src/bidi/core/Request.ts +15 -0
- package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +9 -4
- package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
- package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
- package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
- package/front_end/ui/components/adorners/Adorner.ts +8 -68
- package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +70 -28
- package/front_end/ui/legacy/SearchableView.ts +11 -5
- package/front_end/ui/legacy/SplitWidget.ts +1 -1
- package/front_end/ui/legacy/TabbedPane.ts +1 -1
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +43 -9
- package/front_end/ui/visual_logging/KnownContextValues.ts +16 -0
- package/package.json +2 -1
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* This handler stores page load metrics, including web vitals,
|
|
7
7
|
* and exports them in the shape of a map with the following shape:
|
|
8
|
-
* Map(FrameId -> Map(
|
|
8
|
+
* Map(FrameId -> Map(navigation -> metrics) )
|
|
9
|
+
*
|
|
10
|
+
* Includes soft navigations.
|
|
9
11
|
*
|
|
10
12
|
* It also exports all markers in a trace in an array.
|
|
11
13
|
*
|
|
@@ -22,14 +24,15 @@ import type {HandlerName} from './types.js';
|
|
|
22
24
|
|
|
23
25
|
// Small helpers to make the below type easier to read.
|
|
24
26
|
type FrameId = string;
|
|
25
|
-
type
|
|
27
|
+
type AnyNavigationStart = Types.Events.NavigationStart|Types.Events.SoftNavigationStart;
|
|
28
|
+
|
|
26
29
|
/**
|
|
27
30
|
* This represents the metric scores for all navigations, for all frames in a trace.
|
|
28
31
|
* Given a frame id, the map points to another map from navigation id to metric scores.
|
|
29
32
|
* The metric scores include the event related to the metric as well as the data regarding
|
|
30
33
|
* the score itself.
|
|
31
34
|
*/
|
|
32
|
-
let metricScoresByFrameId = new Map<FrameId, Map<
|
|
35
|
+
let metricScoresByFrameId = new Map<FrameId, Map<AnyNavigationStart, Map<MetricName, MetricScore>>>();
|
|
33
36
|
|
|
34
37
|
/**
|
|
35
38
|
* Page load events with no associated duration that happened in the
|
|
@@ -54,7 +57,7 @@ let pageLoadEventsArray: Types.Events.PageLoadEvent[] = [];
|
|
|
54
57
|
// trace, we store that and delete the prior event. When we've parsed the
|
|
55
58
|
// entire trace this set will contain all the LCP events that were used - e.g.
|
|
56
59
|
// the candidates that were the actual LCP events.
|
|
57
|
-
let selectedLCPCandidateEvents = new Set<Types.Events.
|
|
60
|
+
let selectedLCPCandidateEvents = new Set<Types.Events.AnyLargestContentfulPaintCandidate>();
|
|
58
61
|
|
|
59
62
|
export function handleEvent(event: Types.Events.Event): void {
|
|
60
63
|
if (!Types.Events.eventIsPageLoadEvent(event)) {
|
|
@@ -64,11 +67,7 @@ export function handleEvent(event: Types.Events.Event): void {
|
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
function storePageLoadMetricAgainstNavigationId(
|
|
67
|
-
navigation:
|
|
68
|
-
const navigationId = navigation.args.data?.navigationId;
|
|
69
|
-
if (!navigationId) {
|
|
70
|
-
throw new Error('Navigation event unexpectedly had no navigation ID.');
|
|
71
|
-
}
|
|
70
|
+
navigation: AnyNavigationStart, event: Types.Events.PageLoadEvent): void {
|
|
72
71
|
const frameId = getFrameIdForPageLoadEvent(event);
|
|
73
72
|
const {rendererProcessesByFrame} = metaHandlerData();
|
|
74
73
|
|
|
@@ -95,7 +94,7 @@ function storePageLoadMetricAgainstNavigationId(
|
|
|
95
94
|
const fcpTime = Types.Timing.Micro(event.ts - navigation.ts);
|
|
96
95
|
const classification = scoreClassificationForFirstContentfulPaint(fcpTime);
|
|
97
96
|
const metricScore = {event, metricName: MetricName.FCP, classification, navigation, timing: fcpTime};
|
|
98
|
-
storeMetricScore(frameId,
|
|
97
|
+
storeMetricScore(frameId, navigation, metricScore);
|
|
99
98
|
return;
|
|
100
99
|
}
|
|
101
100
|
|
|
@@ -103,7 +102,7 @@ function storePageLoadMetricAgainstNavigationId(
|
|
|
103
102
|
const paintTime = Types.Timing.Micro(event.ts - navigation.ts);
|
|
104
103
|
const classification = ScoreClassification.UNCLASSIFIED;
|
|
105
104
|
const metricScore = {event, metricName: MetricName.FP, classification, navigation, timing: paintTime};
|
|
106
|
-
storeMetricScore(frameId,
|
|
105
|
+
storeMetricScore(frameId, navigation, metricScore);
|
|
107
106
|
return;
|
|
108
107
|
}
|
|
109
108
|
|
|
@@ -116,7 +115,7 @@ function storePageLoadMetricAgainstNavigationId(
|
|
|
116
115
|
navigation,
|
|
117
116
|
timing: dclTime,
|
|
118
117
|
};
|
|
119
|
-
storeMetricScore(frameId,
|
|
118
|
+
storeMetricScore(frameId, navigation, metricScore);
|
|
120
119
|
return;
|
|
121
120
|
}
|
|
122
121
|
|
|
@@ -129,7 +128,7 @@ function storePageLoadMetricAgainstNavigationId(
|
|
|
129
128
|
navigation,
|
|
130
129
|
timing: ttiValue,
|
|
131
130
|
};
|
|
132
|
-
storeMetricScore(frameId,
|
|
131
|
+
storeMetricScore(frameId, navigation, tti);
|
|
133
132
|
|
|
134
133
|
const tbtValue = Helpers.Timing.milliToMicro(Types.Timing.Milli(event.args.args.total_blocking_time_ms));
|
|
135
134
|
const tbt = {
|
|
@@ -139,7 +138,7 @@ function storePageLoadMetricAgainstNavigationId(
|
|
|
139
138
|
navigation,
|
|
140
139
|
timing: tbtValue,
|
|
141
140
|
};
|
|
142
|
-
storeMetricScore(frameId,
|
|
141
|
+
storeMetricScore(frameId, navigation, tbt);
|
|
143
142
|
return;
|
|
144
143
|
}
|
|
145
144
|
|
|
@@ -152,11 +151,11 @@ function storePageLoadMetricAgainstNavigationId(
|
|
|
152
151
|
navigation,
|
|
153
152
|
timing: loadTime,
|
|
154
153
|
};
|
|
155
|
-
storeMetricScore(frameId,
|
|
154
|
+
storeMetricScore(frameId, navigation, metricScore);
|
|
156
155
|
return;
|
|
157
156
|
}
|
|
158
157
|
|
|
159
|
-
if (Types.Events.
|
|
158
|
+
if (Types.Events.isAnyLargestContentfulPaintCandidate(event)) {
|
|
160
159
|
const candidateIndex = event.args.data?.candidateIndex;
|
|
161
160
|
if (!candidateIndex) {
|
|
162
161
|
throw new Error('Largest Contentful Paint unexpectedly had no candidateIndex.');
|
|
@@ -170,16 +169,16 @@ function storePageLoadMetricAgainstNavigationId(
|
|
|
170
169
|
timing: lcpTime,
|
|
171
170
|
};
|
|
172
171
|
const metricsByNavigation = Platform.MapUtilities.getWithDefault(metricScoresByFrameId, frameId, () => new Map());
|
|
173
|
-
const metrics = Platform.MapUtilities.getWithDefault(metricsByNavigation,
|
|
172
|
+
const metrics = Platform.MapUtilities.getWithDefault(metricsByNavigation, navigation, () => new Map());
|
|
174
173
|
const lastLCPCandidate = metrics.get(MetricName.LCP);
|
|
175
174
|
if (lastLCPCandidate === undefined) {
|
|
176
175
|
selectedLCPCandidateEvents.add(lcp.event);
|
|
177
|
-
storeMetricScore(frameId,
|
|
176
|
+
storeMetricScore(frameId, navigation, lcp);
|
|
178
177
|
return;
|
|
179
178
|
}
|
|
180
179
|
const lastLCPCandidateEvent = lastLCPCandidate.event;
|
|
181
180
|
|
|
182
|
-
if (!Types.Events.
|
|
181
|
+
if (!Types.Events.isAnyLargestContentfulPaintCandidate(lastLCPCandidateEvent)) {
|
|
183
182
|
return;
|
|
184
183
|
}
|
|
185
184
|
const lastCandidateIndex = lastLCPCandidateEvent.args.data?.candidateIndex;
|
|
@@ -192,19 +191,22 @@ function storePageLoadMetricAgainstNavigationId(
|
|
|
192
191
|
if (lastCandidateIndex < candidateIndex) {
|
|
193
192
|
selectedLCPCandidateEvents.delete(lastLCPCandidateEvent);
|
|
194
193
|
selectedLCPCandidateEvents.add(lcp.event);
|
|
195
|
-
storeMetricScore(frameId,
|
|
194
|
+
storeMetricScore(frameId, navigation, lcp);
|
|
196
195
|
}
|
|
197
196
|
return;
|
|
198
197
|
}
|
|
199
198
|
if (Types.Events.isLayoutShift(event)) {
|
|
200
199
|
return;
|
|
201
200
|
}
|
|
201
|
+
if (Types.Events.isSoftNavigationStart(event)) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
202
204
|
return Platform.assertNever(event, `Unexpected event type: ${event}`);
|
|
203
205
|
}
|
|
204
206
|
|
|
205
|
-
function storeMetricScore(frameId: string,
|
|
207
|
+
function storeMetricScore(frameId: string, navigation: AnyNavigationStart, metricScore: MetricScore): void {
|
|
206
208
|
const metricsByNavigation = Platform.MapUtilities.getWithDefault(metricScoresByFrameId, frameId, () => new Map());
|
|
207
|
-
const metrics = Platform.MapUtilities.getWithDefault(metricsByNavigation,
|
|
209
|
+
const metrics = Platform.MapUtilities.getWithDefault(metricsByNavigation, navigation, () => new Map());
|
|
208
210
|
// If an entry with that metric name is present, delete it so that the new entry that
|
|
209
211
|
// will replace it is added at the end of the map. This way we guarantee the map entries
|
|
210
212
|
// are ordered in ASC manner by timestamp.
|
|
@@ -214,8 +216,9 @@ function storeMetricScore(frameId: string, navigationId: string, metricScore: Me
|
|
|
214
216
|
|
|
215
217
|
export function getFrameIdForPageLoadEvent(event: Types.Events.PageLoadEvent): string {
|
|
216
218
|
if (Types.Events.isFirstContentfulPaint(event) || Types.Events.isInteractiveTime(event) ||
|
|
217
|
-
Types.Events.
|
|
218
|
-
Types.Events.
|
|
219
|
+
Types.Events.isAnyLargestContentfulPaintCandidate(event) || Types.Events.isNavigationStart(event) ||
|
|
220
|
+
Types.Events.isSoftNavigationStart(event) || Types.Events.isLayoutShift(event) ||
|
|
221
|
+
Types.Events.isFirstPaint(event)) {
|
|
219
222
|
return event.args.frame;
|
|
220
223
|
}
|
|
221
224
|
if (Types.Events.isMarkDOMContent(event) || Types.Events.isMarkLoad(event)) {
|
|
@@ -228,15 +231,27 @@ export function getFrameIdForPageLoadEvent(event: Types.Events.PageLoadEvent): s
|
|
|
228
231
|
Platform.assertNever(event, `Unexpected event type: ${event}`);
|
|
229
232
|
}
|
|
230
233
|
|
|
231
|
-
function getNavigationForPageLoadEvent(event: Types.Events.PageLoadEvent):
|
|
232
|
-
if (Types.Events.isFirstContentfulPaint(event) || Types.Events.
|
|
234
|
+
function getNavigationForPageLoadEvent(event: Types.Events.PageLoadEvent): AnyNavigationStart|null {
|
|
235
|
+
if (Types.Events.isFirstContentfulPaint(event) || Types.Events.isAnyLargestContentfulPaintCandidate(event) ||
|
|
233
236
|
Types.Events.isFirstPaint(event)) {
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
+
const {navigationsByNavigationId, softNavigationsById} = metaHandlerData();
|
|
238
|
+
|
|
239
|
+
let navigation;
|
|
240
|
+
if (event.name === Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION &&
|
|
241
|
+
event.args.data?.performanceTimelineNavigationId) {
|
|
242
|
+
navigation = softNavigationsById.get(event.args.data.performanceTimelineNavigationId);
|
|
243
|
+
if (!navigation) {
|
|
244
|
+
// The most recent soft navigation must have been before the trace started.
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
} else {
|
|
248
|
+
const navigationId = event.args.data?.navigationId;
|
|
249
|
+
if (!navigationId) {
|
|
250
|
+
throw new Error(`Trace event unexpectedly had no navigation ID: ${JSON.stringify(event, null, 2)}`);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
navigation = navigationsByNavigationId.get(navigationId);
|
|
237
254
|
}
|
|
238
|
-
const {navigationsByNavigationId} = metaHandlerData();
|
|
239
|
-
const navigation = navigationsByNavigationId.get(navigationId);
|
|
240
255
|
|
|
241
256
|
if (!navigation) {
|
|
242
257
|
// This event's navigation has been filtered out by the meta handler as a noise event.
|
|
@@ -245,6 +260,11 @@ function getNavigationForPageLoadEvent(event: Types.Events.PageLoadEvent): Types
|
|
|
245
260
|
return navigation;
|
|
246
261
|
}
|
|
247
262
|
|
|
263
|
+
if (Types.Events.isSoftNavigationStart(event)) {
|
|
264
|
+
const {softNavigationsById} = metaHandlerData();
|
|
265
|
+
return softNavigationsById.get(event.args.context.performanceTimelineNavigationId) ?? null;
|
|
266
|
+
}
|
|
267
|
+
|
|
248
268
|
if (Types.Events.isMarkDOMContent(event) || Types.Events.isInteractiveTime(event) ||
|
|
249
269
|
Types.Events.isLayoutShift(event) || Types.Events.isMarkLoad(event)) {
|
|
250
270
|
const frameId = getFrameIdForPageLoadEvent(event);
|
|
@@ -378,7 +398,8 @@ export async function finalize(): Promise<void> {
|
|
|
378
398
|
const allFinalLCPEvents = gatherFinalLCPEvents();
|
|
379
399
|
const mainFrame = metaHandlerData().mainFrameId;
|
|
380
400
|
// Filter out LCP candidates to use only definitive LCP values
|
|
381
|
-
const allEventsButLCP =
|
|
401
|
+
const allEventsButLCP =
|
|
402
|
+
pageLoadEventsArray.filter(event => !Types.Events.isAnyLargestContentfulPaintCandidate(event));
|
|
382
403
|
const markerEvents = [...allFinalLCPEvents, ...allEventsButLCP].filter(Types.Events.isMarkerEvent);
|
|
383
404
|
// Filter by main frame and sort.
|
|
384
405
|
allMarkerEvents =
|
|
@@ -391,8 +412,10 @@ export interface PageLoadMetricsData {
|
|
|
391
412
|
* Given a frame id, the map points to another map from navigation id to metric scores.
|
|
392
413
|
* The metric scores include the event related to the metric as well as the data regarding
|
|
393
414
|
* the score itself.
|
|
415
|
+
*
|
|
416
|
+
* Includes soft navigations.
|
|
394
417
|
*/
|
|
395
|
-
metricScoresByFrameId: Map<string, Map<
|
|
418
|
+
metricScoresByFrameId: Map<string, Map<AnyNavigationStart, Map<MetricName, MetricScore>>>;
|
|
396
419
|
/**
|
|
397
420
|
* Page load events with no associated duration that happened in the
|
|
398
421
|
* main frame.
|
|
@@ -437,6 +460,8 @@ export const enum MetricName {
|
|
|
437
460
|
CLS = 'CLS',
|
|
438
461
|
// Navigation
|
|
439
462
|
NAV = 'Nav',
|
|
463
|
+
// Soft Navigation (just "Nav" b/c space is limited in flame chart)
|
|
464
|
+
SOFT_NAV = 'Nav',
|
|
440
465
|
// Note: INP is handled in UserInteractionsHandler
|
|
441
466
|
}
|
|
442
467
|
|
|
@@ -445,7 +470,7 @@ export interface MetricScore {
|
|
|
445
470
|
classification: ScoreClassification;
|
|
446
471
|
event?: Types.Events.PageLoadEvent;
|
|
447
472
|
// The last navigation that occurred before this metric score.
|
|
448
|
-
navigation?:
|
|
473
|
+
navigation?: AnyNavigationStart;
|
|
449
474
|
estimated?: boolean;
|
|
450
475
|
timing: Types.Timing.Micro;
|
|
451
476
|
}
|
|
@@ -22,10 +22,17 @@ export function timeStampForEventAdjustedByClosestNavigation(
|
|
|
22
22
|
event: Types.Events.Event,
|
|
23
23
|
traceBounds: Types.Timing.TraceWindowMicro,
|
|
24
24
|
navigationsByNavigationId: Map<string, Types.Events.NavigationStart>,
|
|
25
|
+
softNavigationsById: Map<number, Types.Events.SoftNavigationStart>,
|
|
25
26
|
navigationsByFrameId: Map<string, Types.Events.NavigationStart[]>,
|
|
26
27
|
): Types.Timing.Micro {
|
|
27
28
|
let eventTimeStamp = event.ts - traceBounds.min;
|
|
28
|
-
if (event.
|
|
29
|
+
if (event.name === Types.Events.Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION &&
|
|
30
|
+
event.args?.data?.performanceTimelineNavigationId) {
|
|
31
|
+
const navigationForEvent = softNavigationsById.get(event.args.data.performanceTimelineNavigationId);
|
|
32
|
+
if (navigationForEvent) {
|
|
33
|
+
eventTimeStamp = event.ts - navigationForEvent.ts;
|
|
34
|
+
}
|
|
35
|
+
} else if (event.args?.data?.navigationId) {
|
|
29
36
|
const navigationForEvent = navigationsByNavigationId.get(event.args.data.navigationId);
|
|
30
37
|
if (navigationForEvent) {
|
|
31
38
|
eventTimeStamp = event.ts - navigationForEvent.ts;
|
|
@@ -27,7 +27,7 @@ export function getInsight<InsightName extends keyof InsightModels>(
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export function getLCP(insightSet: InsightSet):
|
|
30
|
-
{value: Types.Timing.Micro, event: Types.Events.
|
|
30
|
+
{value: Types.Timing.Micro, event: Types.Events.AnyLargestContentfulPaintCandidate}|null {
|
|
31
31
|
const insight = getInsight(InsightKeys.LCP_BREAKDOWN, insightSet);
|
|
32
32
|
if (!insight || !insight.lcpMs || !insight.lcpEvent) {
|
|
33
33
|
return null;
|
|
@@ -95,7 +95,7 @@ export function isLCPBreakdownInsight(model: InsightModel): model is LCPBreakdow
|
|
|
95
95
|
export type LCPBreakdownInsightModel = InsightModel<typeof UIStrings, {
|
|
96
96
|
lcpMs?: Types.Timing.Milli,
|
|
97
97
|
lcpTs?: Types.Timing.Milli,
|
|
98
|
-
lcpEvent?: Types.Events.
|
|
98
|
+
lcpEvent?: Types.Events.AnyLargestContentfulPaintCandidate,
|
|
99
99
|
/** The network request for the LCP image, if there was one. */
|
|
100
100
|
lcpRequest?: Types.Events.SyntheticNetworkRequest,
|
|
101
101
|
subparts?: LCPSubparts,
|
|
@@ -112,7 +112,7 @@ function anyValuesNaN(...values: number[]): boolean {
|
|
|
112
112
|
*/
|
|
113
113
|
function determineSubparts(
|
|
114
114
|
nav: Types.Events.NavigationStart, docRequest: Types.Events.SyntheticNetworkRequest,
|
|
115
|
-
lcpEvent: Types.Events.
|
|
115
|
+
lcpEvent: Types.Events.AnyLargestContentfulPaintCandidate,
|
|
116
116
|
lcpRequest: Types.Events.SyntheticNetworkRequest|undefined): LCPSubparts|null {
|
|
117
117
|
const firstDocByteTs = calculateDocFirstByteTs(docRequest);
|
|
118
118
|
if (firstDocByteTs === null) {
|
|
@@ -218,13 +218,13 @@ export function generateInsight(
|
|
|
218
218
|
throw new Error('no frame metrics');
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
-
const navMetrics = frameMetrics.get(context.
|
|
221
|
+
const navMetrics = frameMetrics.get(context.navigation);
|
|
222
222
|
if (!navMetrics) {
|
|
223
223
|
throw new Error('no navigation metrics');
|
|
224
224
|
}
|
|
225
225
|
const metricScore = navMetrics.get(Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);
|
|
226
226
|
const lcpEvent = metricScore?.event;
|
|
227
|
-
if (!lcpEvent || !Types.Events.
|
|
227
|
+
if (!lcpEvent || !Types.Events.isAnyLargestContentfulPaintCandidate(lcpEvent)) {
|
|
228
228
|
return finalize({warnings: [InsightWarning.NO_LCP]});
|
|
229
229
|
}
|
|
230
230
|
|
|
@@ -66,7 +66,7 @@ export function isLCPDiscoveryInsight(model: InsightModel): model is LCPDiscover
|
|
|
66
66
|
return model.insightKey === 'LCPDiscovery';
|
|
67
67
|
}
|
|
68
68
|
export type LCPDiscoveryInsightModel = InsightModel<typeof UIStrings, {
|
|
69
|
-
lcpEvent?: Types.Events.
|
|
69
|
+
lcpEvent?: Types.Events.AnyLargestContentfulPaintCandidate,
|
|
70
70
|
/** The network request for the LCP image, if there was one. */
|
|
71
71
|
lcpRequest?: Types.Events.SyntheticNetworkRequest,
|
|
72
72
|
earliestDiscoveryTimeTs?: Types.Timing.Micro,
|
|
@@ -108,13 +108,13 @@ export function generateInsight(
|
|
|
108
108
|
throw new Error('no frame metrics');
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
const navMetrics = frameMetrics.get(context.
|
|
111
|
+
const navMetrics = frameMetrics.get(context.navigation);
|
|
112
112
|
if (!navMetrics) {
|
|
113
113
|
throw new Error('no navigation metrics');
|
|
114
114
|
}
|
|
115
115
|
const metricScore = navMetrics.get(Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);
|
|
116
116
|
const lcpEvent = metricScore?.event;
|
|
117
|
-
if (!lcpEvent || !Types.Events.
|
|
117
|
+
if (!lcpEvent || !Types.Events.isAnyLargestContentfulPaintCandidate(lcpEvent)) {
|
|
118
118
|
return finalize({warnings: [InsightWarning.NO_LCP]});
|
|
119
119
|
}
|
|
120
120
|
|
|
@@ -185,7 +185,7 @@ export function generateInsight(
|
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
const firstPaintTs = data.PageLoadMetrics.metricScoresByFrameId.get(context.frameId)
|
|
188
|
-
?.get(context.
|
|
188
|
+
?.get(context.navigation)
|
|
189
189
|
?.get(Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP)
|
|
190
190
|
?.event?.ts;
|
|
191
191
|
if (!firstPaintTs) {
|
|
@@ -96,7 +96,7 @@ export type InsightModel<UIStrings extends Record<string, string> = Record<strin
|
|
|
96
96
|
/**
|
|
97
97
|
* If this insight is attached to a navigation, this stores its ID.
|
|
98
98
|
*/
|
|
99
|
-
|
|
99
|
+
navigation?: Types.Events.NavigationStart,
|
|
100
100
|
/** This is lazily-generated because some insights may create many overlays. */
|
|
101
101
|
createOverlays?: () => Types.Overlays.Overlay[],
|
|
102
102
|
};
|
|
@@ -100,6 +100,8 @@ export interface ArgsData {
|
|
|
100
100
|
sampleTraceId?: number;
|
|
101
101
|
url?: string;
|
|
102
102
|
navigationId?: string;
|
|
103
|
+
/** For soft navs. */
|
|
104
|
+
performanceTimelineNavigationId?: number;
|
|
103
105
|
frame?: string;
|
|
104
106
|
}
|
|
105
107
|
|
|
@@ -702,6 +704,29 @@ export interface NavigationStart extends Mark {
|
|
|
702
704
|
};
|
|
703
705
|
}
|
|
704
706
|
|
|
707
|
+
export interface SoftNavigationStart extends Event {
|
|
708
|
+
name: Name.SOFT_NAVIGATION_START;
|
|
709
|
+
ph: Phase.ASYNC_NESTABLE_INSTANT;
|
|
710
|
+
args: Args&{
|
|
711
|
+
frame: string,
|
|
712
|
+
context: {
|
|
713
|
+
softNavContextId: number,
|
|
714
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
715
|
+
URL: string,
|
|
716
|
+
timeOrigin: number,
|
|
717
|
+
domModifications: number,
|
|
718
|
+
firstContentfulPaint: number,
|
|
719
|
+
paintedArea: number,
|
|
720
|
+
performanceTimelineNavigationId: number,
|
|
721
|
+
repaintedArea: number,
|
|
722
|
+
},
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
export function isSoftNavigationStart(event: Event): event is SoftNavigationStart {
|
|
727
|
+
return event.name === Name.SOFT_NAVIGATION_START;
|
|
728
|
+
}
|
|
729
|
+
|
|
705
730
|
export interface FirstContentfulPaint extends Mark {
|
|
706
731
|
name: Name.MARK_FCP;
|
|
707
732
|
args: Args&{
|
|
@@ -722,27 +747,30 @@ export interface FirstPaint extends Mark {
|
|
|
722
747
|
};
|
|
723
748
|
}
|
|
724
749
|
|
|
725
|
-
export type PageLoadEvent = FirstContentfulPaint|MarkDOMContent|InteractiveTime|
|
|
726
|
-
LayoutShift|FirstPaint|MarkLoad|NavigationStart;
|
|
750
|
+
export type PageLoadEvent = FirstContentfulPaint|MarkDOMContent|InteractiveTime|AnyLargestContentfulPaintCandidate|
|
|
751
|
+
LayoutShift|FirstPaint|MarkLoad|NavigationStart|SoftNavigationStart;
|
|
727
752
|
|
|
728
753
|
const markerTypeGuards = [
|
|
729
754
|
isMarkDOMContent,
|
|
730
755
|
isMarkLoad,
|
|
731
756
|
isFirstPaint,
|
|
732
757
|
isFirstContentfulPaint,
|
|
733
|
-
|
|
758
|
+
isAnyLargestContentfulPaintCandidate,
|
|
734
759
|
isNavigationStart,
|
|
760
|
+
isSoftNavigationStart,
|
|
735
761
|
];
|
|
736
762
|
|
|
737
|
-
export const MarkerName =
|
|
738
|
-
|
|
763
|
+
export const MarkerName = [
|
|
764
|
+
'MarkDOMContent', 'MarkLoad', 'firstPaint', 'firstContentfulPaint', 'largestContentfulPaint::Candidate',
|
|
765
|
+
'largestContentfulPaint::CandidateForSoftNavigation'
|
|
766
|
+
] as const;
|
|
739
767
|
|
|
740
768
|
export interface MarkerEvent extends Event {
|
|
741
769
|
name: typeof MarkerName[number];
|
|
742
770
|
}
|
|
743
771
|
|
|
744
772
|
export function isMarkerEvent(event: Event): event is MarkerEvent {
|
|
745
|
-
if (event.ph === Phase.INSTANT || event.ph === Phase.MARK) {
|
|
773
|
+
if (event.ph === Phase.INSTANT || Phase.ASYNC_NESTABLE_INSTANT || event.ph === Phase.MARK) {
|
|
746
774
|
return markerTypeGuards.some(fn => fn(event));
|
|
747
775
|
}
|
|
748
776
|
return false;
|
|
@@ -754,7 +782,7 @@ const pageLoadEventTypeGuards = [
|
|
|
754
782
|
];
|
|
755
783
|
|
|
756
784
|
export function eventIsPageLoadEvent(event: Event): event is PageLoadEvent {
|
|
757
|
-
if (event.ph === Phase.INSTANT || event.ph === Phase.MARK) {
|
|
785
|
+
if (event.ph === Phase.INSTANT || Phase.ASYNC_NESTABLE_INSTANT || event.ph === Phase.MARK) {
|
|
758
786
|
return pageLoadEventTypeGuards.some(fn => fn(event));
|
|
759
787
|
}
|
|
760
788
|
return false;
|
|
@@ -777,6 +805,28 @@ export interface LargestContentfulPaintCandidate extends Mark {
|
|
|
777
805
|
},
|
|
778
806
|
};
|
|
779
807
|
}
|
|
808
|
+
|
|
809
|
+
export interface LargestContentfulPaintCandidateForSoftNavigation extends Mark {
|
|
810
|
+
name: Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION;
|
|
811
|
+
args: Args&{
|
|
812
|
+
frame: string,
|
|
813
|
+
data?: ArgsData&{
|
|
814
|
+
candidateIndex: number,
|
|
815
|
+
isOutermostMainFrame: boolean,
|
|
816
|
+
isMainFrame: boolean,
|
|
817
|
+
nodeId: Protocol.DOM.BackendNodeId,
|
|
818
|
+
loadingAttr: string,
|
|
819
|
+
performanceTimelineNavigationId: number,
|
|
820
|
+
type?: string,
|
|
821
|
+
// Landed in Chrome M140: crrev.com/c/6702010
|
|
822
|
+
nodeName?: string,
|
|
823
|
+
},
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
export type AnyLargestContentfulPaintCandidate =
|
|
828
|
+
LargestContentfulPaintCandidate|LargestContentfulPaintCandidateForSoftNavigation;
|
|
829
|
+
|
|
780
830
|
export interface LargestImagePaintCandidate extends Mark {
|
|
781
831
|
name: 'LargestImagePaint::Candidate';
|
|
782
832
|
args: Args&{
|
|
@@ -2209,8 +2259,8 @@ export function isFirstContentfulPaint(event: Event): event is FirstContentfulPa
|
|
|
2209
2259
|
return event.name === 'firstContentfulPaint';
|
|
2210
2260
|
}
|
|
2211
2261
|
|
|
2212
|
-
export function
|
|
2213
|
-
return event.name === Name.MARK_LCP_CANDIDATE;
|
|
2262
|
+
export function isAnyLargestContentfulPaintCandidate(event: Event): event is AnyLargestContentfulPaintCandidate {
|
|
2263
|
+
return event.name === Name.MARK_LCP_CANDIDATE || event.name === Name.MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION;
|
|
2214
2264
|
}
|
|
2215
2265
|
export function isLargestImagePaintCandidate(event: Event): event is LargestImagePaintCandidate {
|
|
2216
2266
|
return event.name === 'LargestImagePaint::Candidate';
|
|
@@ -2336,7 +2386,7 @@ export function isPrePaint(
|
|
|
2336
2386
|
|
|
2337
2387
|
/** A VALID navigation start (as it has a populated documentLoaderURL) */
|
|
2338
2388
|
export function isNavigationStart(event: Event): event is NavigationStart {
|
|
2339
|
-
return event.name ===
|
|
2389
|
+
return event.name === Name.NAVIGATION_START && (event as NavigationStart).args?.data?.documentLoaderURL !== '';
|
|
2340
2390
|
}
|
|
2341
2391
|
|
|
2342
2392
|
export interface DidCommitSameDocumentNavigation extends Complete {
|
|
@@ -3089,8 +3139,10 @@ export const enum Name {
|
|
|
3089
3139
|
MARK_FIRST_PAINT = 'firstPaint',
|
|
3090
3140
|
MARK_FCP = 'firstContentfulPaint',
|
|
3091
3141
|
MARK_LCP_CANDIDATE = 'largestContentfulPaint::Candidate',
|
|
3142
|
+
MARK_LCP_CANDIDATE_FOR_SOFT_NAVIGATION = 'largestContentfulPaint::CandidateForSoftNavigation',
|
|
3092
3143
|
MARK_LCP_INVALIDATE = 'largestContentfulPaint::Invalidate',
|
|
3093
3144
|
NAVIGATION_START = 'navigationStart',
|
|
3145
|
+
SOFT_NAVIGATION_START = 'SoftNavigationStart',
|
|
3094
3146
|
CONSOLE_TIME = 'ConsoleTime',
|
|
3095
3147
|
USER_TIMING = 'UserTiming',
|
|
3096
3148
|
INTERACTIVE_TIME = 'InteractiveTime',
|