@paulirish/trace_engine 0.0.26 → 0.0.28
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/models/trace/LanternComputationData.d.ts +4 -4
- package/models/trace/LanternComputationData.js +4 -4
- package/models/trace/LanternComputationData.js.map +1 -1
- package/models/trace/lantern/core/LanternError.d.ts +3 -0
- package/models/trace/lantern/core/LanternError.js +7 -0
- package/models/trace/lantern/core/LanternError.js.map +1 -0
- package/models/trace/lantern/core/NetworkAnalyzer.d.ts +112 -0
- package/models/trace/lantern/core/NetworkAnalyzer.js +486 -0
- package/models/trace/lantern/core/NetworkAnalyzer.js.map +1 -0
- package/models/trace/lantern/core/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/core/core-tsconfig.json +43 -0
- package/models/trace/lantern/core/core.d.ts +2 -0
- package/models/trace/lantern/core/core.js +6 -0
- package/models/trace/lantern/core/core.js.map +1 -0
- package/models/trace/lantern/core/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/graph/BaseNode.d.ts +91 -0
- package/models/trace/lantern/graph/BaseNode.js +268 -0
- package/models/trace/lantern/graph/BaseNode.js.map +1 -0
- package/models/trace/lantern/graph/CPUNode.d.ts +24 -0
- package/models/trace/lantern/graph/CPUNode.js +64 -0
- package/models/trace/lantern/graph/CPUNode.js.map +1 -0
- package/models/trace/lantern/graph/NetworkNode.d.ts +22 -0
- package/models/trace/lantern/graph/NetworkNode.js +83 -0
- package/models/trace/lantern/graph/NetworkNode.js.map +1 -0
- package/models/trace/lantern/graph/PageDependencyGraph.d.ts +43 -0
- package/models/trace/lantern/graph/PageDependencyGraph.js +509 -0
- package/models/trace/lantern/graph/PageDependencyGraph.js.map +1 -0
- package/models/trace/lantern/graph/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/graph/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/graph/graph-tsconfig.json +48 -0
- package/models/trace/lantern/graph/graph.d.ts +4 -0
- package/models/trace/lantern/graph/graph.js +8 -0
- package/models/trace/lantern/graph/graph.js.map +1 -0
- package/models/trace/lantern/lantern-tsconfig.json +13 -24
- package/models/trace/lantern/lantern.d.ts +6 -29
- package/models/trace/lantern/lantern.js +6 -29
- package/models/trace/lantern/lantern.js.map +1 -1
- package/models/trace/lantern/metrics/FirstContentfulPaint.d.ts +10 -12
- package/models/trace/lantern/metrics/FirstContentfulPaint.js +3 -3
- package/models/trace/lantern/metrics/FirstContentfulPaint.js.map +1 -1
- package/models/trace/lantern/metrics/Interactive.d.ts +9 -9
- package/models/trace/lantern/metrics/Interactive.js +4 -5
- package/models/trace/lantern/metrics/Interactive.js.map +1 -1
- package/models/trace/lantern/metrics/LargestContentfulPaint.d.ts +10 -9
- package/models/trace/lantern/metrics/LargestContentfulPaint.js +4 -5
- package/models/trace/lantern/metrics/LargestContentfulPaint.js.map +1 -1
- package/models/trace/lantern/metrics/MaxPotentialFID.d.ts +9 -9
- package/models/trace/lantern/metrics/MaxPotentialFID.js +3 -4
- package/models/trace/lantern/metrics/MaxPotentialFID.js.map +1 -1
- package/models/trace/lantern/metrics/Metric.d.ts +31 -13
- package/models/trace/lantern/metrics/Metric.js +2 -3
- package/models/trace/lantern/metrics/Metric.js.map +1 -1
- package/models/trace/lantern/metrics/SpeedIndex.d.ts +10 -10
- package/models/trace/lantern/metrics/SpeedIndex.js +3 -4
- package/models/trace/lantern/metrics/SpeedIndex.js.map +1 -1
- package/models/trace/lantern/metrics/TotalBlockingTime.d.ts +9 -9
- package/models/trace/lantern/metrics/TotalBlockingTime.js +3 -4
- package/models/trace/lantern/metrics/TotalBlockingTime.js.map +1 -1
- package/models/trace/lantern/metrics/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/metrics/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/metrics/metrics-tsconfig.json +58 -0
- package/models/trace/lantern/metrics/metrics.d.ts +7 -14
- package/models/trace/lantern/metrics/metrics.js +7 -7
- package/models/trace/lantern/metrics/metrics.js.map +1 -1
- package/models/trace/lantern/simulation/ConnectionPool.d.ts +1 -1
- package/models/trace/lantern/simulation/ConnectionPool.js +3 -3
- package/models/trace/lantern/simulation/ConnectionPool.js.map +1 -1
- package/models/trace/lantern/simulation/DNSCache.d.ts +1 -1
- package/models/trace/lantern/simulation/DNSCache.js.map +1 -1
- package/models/trace/lantern/simulation/SimulationTimingMap.d.ts +15 -17
- package/models/trace/lantern/simulation/SimulationTimingMap.js +2 -2
- package/models/trace/lantern/simulation/SimulationTimingMap.js.map +1 -1
- package/models/trace/lantern/simulation/Simulator.d.ts +24 -22
- package/models/trace/lantern/simulation/Simulator.js +10 -10
- package/models/trace/lantern/simulation/Simulator.js.map +1 -1
- package/models/trace/lantern/simulation/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/simulation/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/simulation/simulation-tsconfig.json +50 -0
- package/models/trace/lantern/simulation/simulation.d.ts +6 -21
- package/models/trace/lantern/simulation/simulation.js +6 -7
- package/models/trace/lantern/simulation/simulation.js.map +1 -1
- package/models/trace/lantern/types/{lantern.d.ts → Lantern.d.ts} +21 -27
- package/models/trace/lantern/types/Lantern.js +24 -0
- package/models/trace/lantern/types/Lantern.js.map +1 -0
- package/models/trace/lantern/types/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/types/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/types/types-tsconfig.json +42 -0
- package/models/trace/lantern/types/types.d.ts +1 -0
- package/models/trace/lantern/types/{lantern.js → types.js} +2 -2
- package/models/trace/lantern/types/types.js.map +1 -0
- package/package.json +1 -1
- package/models/trace/lantern/types/lantern.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"compilerOptions":{"composite":true,"outDir":".","baseUrl":".","rootDir":"../../../../../../../../front_end/models/trace/lantern/graph"},"files":["../../../../../../../../front_end/models/trace/lantern/graph/graph.ts"],"references":[{"path":"./graph-tsconfig.json"}]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowJs": true,
|
|
4
|
+
"checkJs": true,
|
|
5
|
+
"composite": true,
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"experimentalDecorators": true,
|
|
8
|
+
"forceConsistentCasingInFileNames": true,
|
|
9
|
+
"inlineSources": true,
|
|
10
|
+
"lib": [
|
|
11
|
+
"esnext",
|
|
12
|
+
"dom",
|
|
13
|
+
"dom.iterable"
|
|
14
|
+
],
|
|
15
|
+
"module": "esnext",
|
|
16
|
+
"noEmitOnError": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
|
+
"noImplicitOverride": true,
|
|
19
|
+
"noImplicitReturns": true,
|
|
20
|
+
"noUnusedLocals": false,
|
|
21
|
+
"outDir": ".",
|
|
22
|
+
"rootDir": "../../../../../../../../front_end/models/trace/lantern/graph",
|
|
23
|
+
"skipLibCheck": true,
|
|
24
|
+
"sourceMap": true,
|
|
25
|
+
"strict": true,
|
|
26
|
+
"target": "esnext",
|
|
27
|
+
"tsBuildInfoFile": "devtools_entrypoint-bundle-typescript-tsconfig.json.tsbuildinfo",
|
|
28
|
+
"typeRoots": [],
|
|
29
|
+
"useUnknownInCatchVariables": false
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"../../../../../../../../front_end/models/trace/lantern/graph/graph.ts",
|
|
33
|
+
"../../../../../../../../front_end/legacy/legacy-defs.d.ts",
|
|
34
|
+
"../../../../../../../../front_end/global_typings/global_defs.d.ts",
|
|
35
|
+
"../../../../../../../../node_modules/@types/filesystem/index.d.ts"
|
|
36
|
+
],
|
|
37
|
+
"references": [
|
|
38
|
+
{
|
|
39
|
+
"path": "./graph-tsconfig.json"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowJs": true,
|
|
4
|
+
"checkJs": true,
|
|
5
|
+
"composite": true,
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"experimentalDecorators": true,
|
|
8
|
+
"forceConsistentCasingInFileNames": true,
|
|
9
|
+
"inlineSources": true,
|
|
10
|
+
"lib": [
|
|
11
|
+
"esnext",
|
|
12
|
+
"dom",
|
|
13
|
+
"dom.iterable"
|
|
14
|
+
],
|
|
15
|
+
"module": "esnext",
|
|
16
|
+
"noEmitOnError": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
|
+
"noImplicitOverride": true,
|
|
19
|
+
"noImplicitReturns": true,
|
|
20
|
+
"noUnusedLocals": false,
|
|
21
|
+
"outDir": ".",
|
|
22
|
+
"rootDir": "../../../../../../../../front_end/models/trace/lantern/graph",
|
|
23
|
+
"skipLibCheck": true,
|
|
24
|
+
"sourceMap": true,
|
|
25
|
+
"strict": true,
|
|
26
|
+
"target": "esnext",
|
|
27
|
+
"tsBuildInfoFile": "graph-tsconfig.json.tsbuildinfo",
|
|
28
|
+
"typeRoots": [],
|
|
29
|
+
"useUnknownInCatchVariables": false
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"../../../../../../../../front_end/models/trace/lantern/graph/BaseNode.ts",
|
|
33
|
+
"../../../../../../../../front_end/models/trace/lantern/graph/CPUNode.ts",
|
|
34
|
+
"../../../../../../../../front_end/models/trace/lantern/graph/NetworkNode.ts",
|
|
35
|
+
"../../../../../../../../front_end/models/trace/lantern/graph/PageDependencyGraph.ts",
|
|
36
|
+
"../../../../../../../../front_end/legacy/legacy-defs.d.ts",
|
|
37
|
+
"../../../../../../../../front_end/global_typings/global_defs.d.ts",
|
|
38
|
+
"../../../../../../../../node_modules/@types/filesystem/index.d.ts"
|
|
39
|
+
],
|
|
40
|
+
"references": [
|
|
41
|
+
{
|
|
42
|
+
"path": "../core/bundle-tsconfig.json"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"path": "../types/bundle-tsconfig.json"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Copyright 2024 The Chromium Authors. All rights reserved.
|
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
|
3
|
+
// found in the LICENSE file.
|
|
4
|
+
export * from './BaseNode.js';
|
|
5
|
+
export * from './CPUNode.js';
|
|
6
|
+
export * from './NetworkNode.js';
|
|
7
|
+
export * from './PageDependencyGraph.js';
|
|
8
|
+
//# sourceMappingURL=graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/graph/graph.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,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 * from './BaseNode.js';\nexport * from './CPUNode.js';\nexport * from './NetworkNode.js';\nexport * from './PageDependencyGraph.js';\n"]}
|
|
@@ -29,36 +29,25 @@
|
|
|
29
29
|
"useUnknownInCatchVariables": false
|
|
30
30
|
},
|
|
31
31
|
"files": [
|
|
32
|
-
"../../../../../../../front_end/models/trace/lantern/BaseNode.ts",
|
|
33
|
-
"../../../../../../../front_end/models/trace/lantern/CPUNode.ts",
|
|
34
|
-
"../../../../../../../front_end/models/trace/lantern/LanternError.ts",
|
|
35
|
-
"../../../../../../../front_end/models/trace/lantern/MetricsModule.ts",
|
|
36
|
-
"../../../../../../../front_end/models/trace/lantern/NetworkNode.ts",
|
|
37
|
-
"../../../../../../../front_end/models/trace/lantern/PageDependencyGraph.ts",
|
|
38
|
-
"../../../../../../../front_end/models/trace/lantern/SimulationModule.ts",
|
|
39
|
-
"../../../../../../../front_end/models/trace/lantern/metrics/FirstContentfulPaint.ts",
|
|
40
|
-
"../../../../../../../front_end/models/trace/lantern/metrics/Interactive.ts",
|
|
41
|
-
"../../../../../../../front_end/models/trace/lantern/metrics/LargestContentfulPaint.ts",
|
|
42
|
-
"../../../../../../../front_end/models/trace/lantern/metrics/MaxPotentialFID.ts",
|
|
43
|
-
"../../../../../../../front_end/models/trace/lantern/metrics/Metric.ts",
|
|
44
|
-
"../../../../../../../front_end/models/trace/lantern/metrics/SpeedIndex.ts",
|
|
45
|
-
"../../../../../../../front_end/models/trace/lantern/metrics/TBTUtils.ts",
|
|
46
|
-
"../../../../../../../front_end/models/trace/lantern/metrics/TotalBlockingTime.ts",
|
|
47
|
-
"../../../../../../../front_end/models/trace/lantern/simulation/ConnectionPool.ts",
|
|
48
|
-
"../../../../../../../front_end/models/trace/lantern/simulation/Constants.ts",
|
|
49
|
-
"../../../../../../../front_end/models/trace/lantern/simulation/DNSCache.ts",
|
|
50
|
-
"../../../../../../../front_end/models/trace/lantern/simulation/NetworkAnalyzer.ts",
|
|
51
|
-
"../../../../../../../front_end/models/trace/lantern/simulation/SimulationTimingMap.ts",
|
|
52
|
-
"../../../../../../../front_end/models/trace/lantern/simulation/Simulator.ts",
|
|
53
|
-
"../../../../../../../front_end/models/trace/lantern/simulation/TCPConnection.ts",
|
|
54
|
-
"../../../../../../../front_end/models/trace/lantern/types/lantern.ts",
|
|
55
32
|
"../../../../../../../front_end/legacy/legacy-defs.d.ts",
|
|
56
33
|
"../../../../../../../front_end/global_typings/global_defs.d.ts",
|
|
57
34
|
"../../../../../../../node_modules/@types/filesystem/index.d.ts"
|
|
58
35
|
],
|
|
59
36
|
"references": [
|
|
60
37
|
{
|
|
61
|
-
"path": "
|
|
38
|
+
"path": "core/bundle-tsconfig.json"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"path": "graph/bundle-tsconfig.json"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"path": "metrics/bundle-tsconfig.json"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"path": "simulation/bundle-tsconfig.json"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"path": "types/bundle-tsconfig.json"
|
|
62
51
|
}
|
|
63
52
|
]
|
|
64
53
|
}
|
|
@@ -1,29 +1,6 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import * as
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export {
|
|
7
|
-
export { PageDependencyGraph } from './PageDependencyGraph.js';
|
|
8
|
-
export type { NetworkRequest, ParsedURL, ResourcePriority, ResourceTiming, ResourceType, Trace, TraceEvent, } from './types/lantern.js';
|
|
9
|
-
export declare const NetworkRequestTypes: {
|
|
10
|
-
readonly XHR: "XHR";
|
|
11
|
-
readonly Fetch: "Fetch";
|
|
12
|
-
readonly EventSource: "EventSource";
|
|
13
|
-
readonly Script: "Script";
|
|
14
|
-
readonly Stylesheet: "Stylesheet";
|
|
15
|
-
readonly Image: "Image";
|
|
16
|
-
readonly Media: "Media";
|
|
17
|
-
readonly Font: "Font";
|
|
18
|
-
readonly Document: "Document";
|
|
19
|
-
readonly TextTrack: "TextTrack";
|
|
20
|
-
readonly WebSocket: "WebSocket";
|
|
21
|
-
readonly Other: "Other";
|
|
22
|
-
readonly Manifest: "Manifest";
|
|
23
|
-
readonly SignedExchange: "SignedExchange";
|
|
24
|
-
readonly Ping: "Ping";
|
|
25
|
-
readonly Preflight: "Preflight";
|
|
26
|
-
readonly CSPViolationReport: "CSPViolationReport";
|
|
27
|
-
readonly Prefetch: "Prefetch";
|
|
28
|
-
};
|
|
29
|
-
export { Metrics, Simulation, };
|
|
1
|
+
import * as Core from './core/core.js';
|
|
2
|
+
import * as Graph from './graph/graph.js';
|
|
3
|
+
import * as Metrics from './metrics/metrics.js';
|
|
4
|
+
import * as Simulation from './simulation/simulation.js';
|
|
5
|
+
import * as Types from './types/types.js';
|
|
6
|
+
export { Core, Graph, Metrics, Simulation, Types, };
|
|
@@ -1,33 +1,10 @@
|
|
|
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
|
-
|
|
5
|
-
import * as
|
|
6
|
-
import * as
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export {
|
|
10
|
-
export { NetworkNode } from './NetworkNode.js';
|
|
11
|
-
export { PageDependencyGraph } from './PageDependencyGraph.js';
|
|
12
|
-
export const NetworkRequestTypes = {
|
|
13
|
-
XHR: 'XHR',
|
|
14
|
-
Fetch: 'Fetch',
|
|
15
|
-
EventSource: 'EventSource',
|
|
16
|
-
Script: 'Script',
|
|
17
|
-
Stylesheet: 'Stylesheet',
|
|
18
|
-
Image: 'Image',
|
|
19
|
-
Media: 'Media',
|
|
20
|
-
Font: 'Font',
|
|
21
|
-
Document: 'Document',
|
|
22
|
-
TextTrack: 'TextTrack',
|
|
23
|
-
WebSocket: 'WebSocket',
|
|
24
|
-
Other: 'Other',
|
|
25
|
-
Manifest: 'Manifest',
|
|
26
|
-
SignedExchange: 'SignedExchange',
|
|
27
|
-
Ping: 'Ping',
|
|
28
|
-
Preflight: 'Preflight',
|
|
29
|
-
CSPViolationReport: 'CSPViolationReport',
|
|
30
|
-
Prefetch: 'Prefetch',
|
|
31
|
-
};
|
|
32
|
-
export { Metrics, Simulation, };
|
|
4
|
+
import * as Core from './core/core.js';
|
|
5
|
+
import * as Graph from './graph/graph.js';
|
|
6
|
+
import * as Metrics from './metrics/metrics.js';
|
|
7
|
+
import * as Simulation from './simulation/simulation.js';
|
|
8
|
+
import * as Types from './types/types.js';
|
|
9
|
+
export { Core, Graph, Metrics, Simulation, Types, };
|
|
33
10
|
//# sourceMappingURL=lantern.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lantern.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/lantern/lantern.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,
|
|
1
|
+
{"version":3,"file":"lantern.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/lantern/lantern.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC;AAC1C,OAAO,KAAK,OAAO,MAAM,sBAAsB,CAAC;AAChD,OAAO,KAAK,UAAU,MAAM,4BAA4B,CAAC;AACzD,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EACL,IAAI,EACJ,KAAK,EACL,OAAO,EACP,UAAU,EACV,KAAK,GACN,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 Core from './core/core.js';\nimport * as Graph from './graph/graph.js';\nimport * as Metrics from './metrics/metrics.js';\nimport * as Simulation from './simulation/simulation.js';\nimport * as Types from './types/types.js';\n\nexport {\n Core,\n Graph,\n Metrics,\n Simulation,\n Types,\n};\n"]}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { type
|
|
4
|
-
import type * as Lantern from '../types/lantern.js';
|
|
5
|
-
import { Metric } from './Metric.js';
|
|
1
|
+
import * as Graph from '../graph/graph.js';
|
|
2
|
+
import type * as Types from '../types/types.js';
|
|
3
|
+
import { Metric, type MetricCoefficients } from './Metric.js';
|
|
6
4
|
interface FirstPaintBasedGraphOpts<T> {
|
|
7
5
|
/**
|
|
8
6
|
* The timestamp used to filter out tasks that occured after our paint of interest.
|
|
@@ -13,30 +11,30 @@ interface FirstPaintBasedGraphOpts<T> {
|
|
|
13
11
|
* The function that determines which resources should be considered *possibly*
|
|
14
12
|
* render-blocking.
|
|
15
13
|
*/
|
|
16
|
-
treatNodeAsRenderBlocking: (node: NetworkNode<T>) => boolean;
|
|
14
|
+
treatNodeAsRenderBlocking: (node: Graph.NetworkNode<T>) => boolean;
|
|
17
15
|
/**
|
|
18
16
|
* The function that determines which CPU nodes should also be included in our
|
|
19
17
|
* blocking node IDs set, beyond what getRenderBlockingNodeData() already includes.
|
|
20
18
|
*/
|
|
21
|
-
additionalCpuNodesToTreatAsRenderBlocking?: (node: CPUNode) => boolean;
|
|
19
|
+
additionalCpuNodesToTreatAsRenderBlocking?: (node: Graph.CPUNode) => boolean;
|
|
22
20
|
}
|
|
23
21
|
declare class FirstContentfulPaint extends Metric {
|
|
24
|
-
static get coefficients():
|
|
22
|
+
static get coefficients(): MetricCoefficients;
|
|
25
23
|
/**
|
|
26
24
|
* Computes the set of URLs that *appeared* to be render-blocking based on our filter,
|
|
27
25
|
* *but definitely were not* render-blocking based on the timing of their EvaluateScript task.
|
|
28
26
|
* It also computes the set of corresponding CPU node ids that were needed for the paint at the
|
|
29
27
|
* given timestamp.
|
|
30
28
|
*/
|
|
31
|
-
static getRenderBlockingNodeData<T = unknown>(graph: Node, { cutoffTimestamp, treatNodeAsRenderBlocking, additionalCpuNodesToTreatAsRenderBlocking }: FirstPaintBasedGraphOpts<T>): {
|
|
29
|
+
static getRenderBlockingNodeData<T = unknown>(graph: Graph.Node, { cutoffTimestamp, treatNodeAsRenderBlocking, additionalCpuNodesToTreatAsRenderBlocking }: FirstPaintBasedGraphOpts<T>): {
|
|
32
30
|
definitelyNotRenderBlockingScriptUrls: Set<string>;
|
|
33
31
|
renderBlockingCpuNodeIds: Set<string>;
|
|
34
32
|
};
|
|
35
33
|
/**
|
|
36
34
|
* Computes the graph required for the first paint of interest.
|
|
37
35
|
*/
|
|
38
|
-
static getFirstPaintBasedGraph<T>(dependencyGraph: Node, { cutoffTimestamp, treatNodeAsRenderBlocking, additionalCpuNodesToTreatAsRenderBlocking }: FirstPaintBasedGraphOpts<T>): Node<T>;
|
|
39
|
-
static getOptimisticGraph<T>(dependencyGraph: Node<T>, processedNavigation:
|
|
40
|
-
static getPessimisticGraph<T>(dependencyGraph: Node<T>, processedNavigation:
|
|
36
|
+
static getFirstPaintBasedGraph<T>(dependencyGraph: Graph.Node, { cutoffTimestamp, treatNodeAsRenderBlocking, additionalCpuNodesToTreatAsRenderBlocking }: FirstPaintBasedGraphOpts<T>): Graph.Node<T>;
|
|
37
|
+
static getOptimisticGraph<T>(dependencyGraph: Graph.Node<T>, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node<T>;
|
|
38
|
+
static getPessimisticGraph<T>(dependencyGraph: Graph.Node<T>, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node<T>;
|
|
41
39
|
}
|
|
42
40
|
export { FirstContentfulPaint };
|
|
@@ -1,7 +1,7 @@
|
|
|
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
|
|
4
|
+
import * as Graph from '../graph/graph.js';
|
|
5
5
|
import { Metric } from './Metric.js';
|
|
6
6
|
class FirstContentfulPaint extends Metric {
|
|
7
7
|
static get coefficients() {
|
|
@@ -22,7 +22,7 @@ class FirstContentfulPaint extends Metric {
|
|
|
22
22
|
const scriptUrlToNodeMap = new Map();
|
|
23
23
|
const cpuNodes = [];
|
|
24
24
|
graph.traverse(node => {
|
|
25
|
-
if (node.type === BaseNode.types.CPU) {
|
|
25
|
+
if (node.type === Graph.BaseNode.types.CPU) {
|
|
26
26
|
// A task is *possibly* render blocking if it *started* before cutoffTimestamp.
|
|
27
27
|
// We use startTime here because the paint event can be *inside* the task that was render blocking.
|
|
28
28
|
if (node.startTime <= cutoffTimestamp) {
|
|
@@ -98,7 +98,7 @@ class FirstContentfulPaint extends Metric {
|
|
|
98
98
|
});
|
|
99
99
|
const { definitelyNotRenderBlockingScriptUrls, renderBlockingCpuNodeIds } = rbData;
|
|
100
100
|
return dependencyGraph.cloneWithRelationships(node => {
|
|
101
|
-
if (node.type === BaseNode.types.NETWORK) {
|
|
101
|
+
if (node.type === Graph.BaseNode.types.NETWORK) {
|
|
102
102
|
// Exclude all nodes that ended after cutoffTimestamp (except for the main document which we always consider necessary)
|
|
103
103
|
// endTime is negative if request does not finish, make sure startTime isn't after cutoffTimestamp in this case.
|
|
104
104
|
const endedAfterPaint = node.endTime > cutoffTimestamp || node.startTime > cutoffTimestamp;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FirstContentfulPaint.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/FirstContentfulPaint.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,QAAQ,EAAY,MAAM,gBAAgB,CAAC;AAKnD,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAoBnC,MAAM,oBAAqB,SAAQ,MAAM;IACvC,MAAM,KAAc,YAAY;QAC9B,OAAO;YACL,SAAS,EAAE,CAAC;YACZ,UAAU,EAAE,GAAG;YACf,WAAW,EAAE,GAAG;SACjB,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,yBAAyB,CAC5B,KAAW,EACX,EAAC,eAAe,EAAE,yBAAyB,EAAE,yCAAyC,EACvD;QAEjC,iGAAiG;QACjG,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAmB,CAAC;QAEtD,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YACpB,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;gBACrC,+EAA+E;gBAC/E,mGAAmG;gBACnG,IAAI,IAAI,CAAC,SAAS,IAAI,eAAe,EAAE,CAAC;oBACtC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACtB,CAAC;gBAED,0EAA0E;gBAC1E,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAChD,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;oBAC7B,qCAAqC;oBACrC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;oBACrD,kBAAkB,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;gBACrF,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QAEnD,wFAAwF;QACxF,MAAM,gCAAgC,GAAG,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE;YAC1E,6FAA6F;YAC7F,wFAAwF;YACxF,+DAA+D;YAC/D,OAAO,IAAI,CAAC,OAAO,IAAI,eAAe,IAAI,yBAAyB,CAAC,IAAI,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;QAEH,yGAAyG;QACzG,MAAM,qCAAqC,GAAG,IAAI,GAAG,EAAU,CAAC;QAChE,MAAM,wBAAwB,GAAG,IAAI,GAAG,EAAU,CAAC;QACnD,KAAK,MAAM,GAAG,IAAI,gCAAgC,EAAE,CAAC;YACnD,yEAAyE;YACzE,MAAM,aAAa,GAAG,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAElD,2EAA2E;YAC3E,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,SAAS;YACX,CAAC;YAED,kIAAkI;YAClI,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;gBACrC,wBAAwB,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;gBAC/C,SAAS;YACX,CAAC;YAED,6FAA6F;YAC7F,iDAAiD;YACjD,qCAAqC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjD,CAAC;QAED,kGAAkG;QAClG,wCAAwC;QACxC,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACnE,IAAI,WAAW,EAAE,CAAC;YAChB,wBAAwB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC;QACzF,IAAI,UAAU,EAAE,CAAC;YACf,wBAAwB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAC9C,CAAC;QACD,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC;QAC7F,IAAI,UAAU,EAAE,CAAC;YACf,wBAAwB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAC9C,CAAC;QAED,4EAA4E;QAC5E,IAAI,yCAAyC,EAAE,CAAC;YAC9C,QAAQ,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,wBAAwB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACpH,CAAC;QAED,OAAO;YACL,qCAAqC;YACrC,wBAAwB;SACzB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,uBAAuB,CAC1B,eAAqB,EACrB,EAAC,eAAe,EAAE,yBAAyB,EAAE,yCAAyC,EACvD;QAEjC,MAAM,MAAM,GAAG,IAAI,CAAC,yBAAyB,CAAC,eAAe,EAAE;YAC7D,eAAe;YACf,yBAAyB;YACzB,yCAAyC;SAC1C,CAAC,CAAC;QACH,MAAM,EAAC,qCAAqC,EAAE,wBAAwB,EAAC,GAAG,MAAM,CAAC;QAEjF,OAAO,eAAe,CAAC,sBAAsB,CAAC,IAAI,CAAC,EAAE;YACnD,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;gBACzC,uHAAuH;gBACvH,gHAAgH;gBAChH,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,GAAG,eAAe,IAAI,IAAI,CAAC,SAAS,GAAG,eAAe,CAAC;gBAC3F,IAAI,eAAe,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;oBAC9C,OAAO,KAAK,CAAC;gBACf,CAAC;gBAED,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;gBAC7B,sEAAsE;gBACtE,IAAI,qCAAqC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACnD,OAAO,KAAK,CAAC;gBACf,CAAC;gBAED,0EAA0E;gBAC1E,OAAO,yBAAyB,CAAC,IAAI,CAAC,CAAC;YACzC,CAAC;YACD,qDAAqD;YACrD,OAAO,wBAAwB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAU,kBAAkB,CAC9B,eAAwB,EAAE,mBAA2D;QACvF,OAAO,IAAI,CAAC,uBAAuB,CAAC,eAAe,EAAE;YACnD,eAAe,EAAE,mBAAmB,CAAC,UAAU,CAAC,oBAAoB;YACpE,4FAA4F;YAC5F,6FAA6F;YAC7F,+FAA+F;YAC/F,yBAAyB,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,yBAAyB,EAAE,IAAI,IAAI,CAAC,aAAa,KAAK,QAAQ;SACvG,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAU,mBAAmB,CAC/B,eAAwB,EAAE,mBAA2D;QACvF,OAAO,IAAI,CAAC,uBAAuB,CAAC,eAAe,EAAE;YACnD,eAAe,EAAE,mBAAmB,CAAC,UAAU,CAAC,oBAAoB;YACpE,yBAAyB,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,yBAAyB,EAAE;SACpE,CAAC,CAAC;IACL,CAAC;CACF;AAED,OAAO,EAAC,oBAAoB,EAAC,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 {BaseNode, type Node} from '../BaseNode.js';\nimport {type CPUNode} from '../CPUNode.js';\nimport {type NetworkNode} from '../NetworkNode.js';\nimport type * as Lantern from '../types/lantern.js';\n\nimport {Metric} from './Metric.js';\n\ninterface FirstPaintBasedGraphOpts<T> {\n /**\n * The timestamp used to filter out tasks that occured after our paint of interest.\n * Typically this is First Contentful Paint or First Meaningful Paint.\n */\n cutoffTimestamp: number;\n /**\n * The function that determines which resources should be considered *possibly*\n * render-blocking.\n */\n treatNodeAsRenderBlocking: (node: NetworkNode<T>) => boolean;\n /**\n * The function that determines which CPU nodes should also be included in our\n * blocking node IDs set, beyond what getRenderBlockingNodeData() already includes.\n */\n additionalCpuNodesToTreatAsRenderBlocking?: (node: CPUNode) => boolean;\n}\n\nclass FirstContentfulPaint extends Metric {\n static override get coefficients(): Lantern.Simulation.MetricCoefficients {\n return {\n intercept: 0,\n optimistic: 0.5,\n pessimistic: 0.5,\n };\n }\n\n /**\n * Computes the set of URLs that *appeared* to be render-blocking based on our filter,\n * *but definitely were not* render-blocking based on the timing of their EvaluateScript task.\n * It also computes the set of corresponding CPU node ids that were needed for the paint at the\n * given timestamp.\n */\n static getRenderBlockingNodeData<T = unknown>(\n graph: Node,\n {cutoffTimestamp, treatNodeAsRenderBlocking, additionalCpuNodesToTreatAsRenderBlocking}:\n FirstPaintBasedGraphOpts<T>,\n ): {definitelyNotRenderBlockingScriptUrls: Set<string>, renderBlockingCpuNodeIds: Set<string>} {\n /** A map of blocking script URLs to the earliest EvaluateScript task node that executed them. */\n const scriptUrlToNodeMap = new Map<string, CPUNode>();\n\n const cpuNodes: CPUNode[] = [];\n graph.traverse(node => {\n if (node.type === BaseNode.types.CPU) {\n // A task is *possibly* render blocking if it *started* before cutoffTimestamp.\n // We use startTime here because the paint event can be *inside* the task that was render blocking.\n if (node.startTime <= cutoffTimestamp) {\n cpuNodes.push(node);\n }\n\n // Build our script URL map to find the earliest EvaluateScript task node.\n const scriptUrls = node.getEvaluateScriptURLs();\n for (const url of scriptUrls) {\n // Use the earliest CPU node we find.\n const existing = scriptUrlToNodeMap.get(url) || node;\n scriptUrlToNodeMap.set(url, node.startTime < existing.startTime ? node : existing);\n }\n }\n });\n\n cpuNodes.sort((a, b) => a.startTime - b.startTime);\n\n // A script is *possibly* render blocking if it finished loading before cutoffTimestamp.\n const possiblyRenderBlockingScriptUrls = Metric.getScriptUrls(graph, node => {\n // The optimistic LCP treatNodeAsRenderBlocking fn wants to exclude some images in the graph,\n // but here it only receives scripts to evaluate. It's a no-op in this case, but it will\n // matter below in the getFirstPaintBasedGraph clone operation.\n return node.endTime <= cutoffTimestamp && treatNodeAsRenderBlocking(node);\n });\n\n // A script is *definitely not* render blocking if its EvaluateScript task started after cutoffTimestamp.\n const definitelyNotRenderBlockingScriptUrls = new Set<string>();\n const renderBlockingCpuNodeIds = new Set<string>();\n for (const url of possiblyRenderBlockingScriptUrls) {\n // Lookup the CPU node that had the earliest EvaluateScript for this URL.\n const cpuNodeForUrl = scriptUrlToNodeMap.get(url);\n\n // If we can't find it at all, we can't conclude anything, so just skip it.\n if (!cpuNodeForUrl) {\n continue;\n }\n\n // If we found it and it was in our `cpuNodes` set that means it finished before cutoffTimestamp, so it really is render-blocking.\n if (cpuNodes.includes(cpuNodeForUrl)) {\n renderBlockingCpuNodeIds.add(cpuNodeForUrl.id);\n continue;\n }\n\n // We couldn't find the evaluate script in the set of CPU nodes that ran before our paint, so\n // it must not have been necessary for the paint.\n definitelyNotRenderBlockingScriptUrls.add(url);\n }\n\n // The first layout, first paint, and first ParseHTML are almost always necessary for first paint,\n // so we always include those CPU nodes.\n const firstLayout = cpuNodes.find(node => node.didPerformLayout());\n if (firstLayout) {\n renderBlockingCpuNodeIds.add(firstLayout.id);\n }\n const firstPaint = cpuNodes.find(node => node.childEvents.some(e => e.name === 'Paint'));\n if (firstPaint) {\n renderBlockingCpuNodeIds.add(firstPaint.id);\n }\n const firstParse = cpuNodes.find(node => node.childEvents.some(e => e.name === 'ParseHTML'));\n if (firstParse) {\n renderBlockingCpuNodeIds.add(firstParse.id);\n }\n\n // If a CPU filter was passed in, we also want to include those extra nodes.\n if (additionalCpuNodesToTreatAsRenderBlocking) {\n cpuNodes.filter(additionalCpuNodesToTreatAsRenderBlocking).forEach(node => renderBlockingCpuNodeIds.add(node.id));\n }\n\n return {\n definitelyNotRenderBlockingScriptUrls,\n renderBlockingCpuNodeIds,\n };\n }\n\n /**\n * Computes the graph required for the first paint of interest.\n */\n static getFirstPaintBasedGraph<T>(\n dependencyGraph: Node,\n {cutoffTimestamp, treatNodeAsRenderBlocking, additionalCpuNodesToTreatAsRenderBlocking}:\n FirstPaintBasedGraphOpts<T>,\n ): Node<T> {\n const rbData = this.getRenderBlockingNodeData(dependencyGraph, {\n cutoffTimestamp,\n treatNodeAsRenderBlocking,\n additionalCpuNodesToTreatAsRenderBlocking,\n });\n const {definitelyNotRenderBlockingScriptUrls, renderBlockingCpuNodeIds} = rbData;\n\n return dependencyGraph.cloneWithRelationships(node => {\n if (node.type === BaseNode.types.NETWORK) {\n // Exclude all nodes that ended after cutoffTimestamp (except for the main document which we always consider necessary)\n // endTime is negative if request does not finish, make sure startTime isn't after cutoffTimestamp in this case.\n const endedAfterPaint = node.endTime > cutoffTimestamp || node.startTime > cutoffTimestamp;\n if (endedAfterPaint && !node.isMainDocument()) {\n return false;\n }\n\n const url = node.request.url;\n // If the URL definitely wasn't render-blocking then we filter it out.\n if (definitelyNotRenderBlockingScriptUrls.has(url)) {\n return false;\n }\n\n // Lastly, build up the FCP graph of all nodes we consider render blocking\n return treatNodeAsRenderBlocking(node);\n }\n // If it's a CPU node, just check if it was blocking.\n return renderBlockingCpuNodeIds.has(node.id);\n });\n }\n\n static override getOptimisticGraph<T>(\n dependencyGraph: Node<T>, processedNavigation: Lantern.Simulation.ProcessedNavigation): Node<T> {\n return this.getFirstPaintBasedGraph(dependencyGraph, {\n cutoffTimestamp: processedNavigation.timestamps.firstContentfulPaint,\n // In the optimistic graph we exclude resources that appeared to be render blocking but were\n // initiated by a script. While they typically have a very high importance and tend to have a\n // significant impact on the page's content, these resources don't technically block rendering.\n treatNodeAsRenderBlocking: node => node.hasRenderBlockingPriority() && node.initiatorType !== 'script',\n });\n }\n\n static override getPessimisticGraph<T>(\n dependencyGraph: Node<T>, processedNavigation: Lantern.Simulation.ProcessedNavigation): Node<T> {\n return this.getFirstPaintBasedGraph(dependencyGraph, {\n cutoffTimestamp: processedNavigation.timestamps.firstContentfulPaint,\n treatNodeAsRenderBlocking: node => node.hasRenderBlockingPriority(),\n });\n }\n}\n\nexport {FirstContentfulPaint};\n"]}
|
|
1
|
+
{"version":3,"file":"FirstContentfulPaint.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/FirstContentfulPaint.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 Graph from '../graph/graph.js';\nimport type * as Types from '../types/types.js';\n\nimport {Metric, type MetricCoefficients} from './Metric.js';\n\ninterface FirstPaintBasedGraphOpts<T> {\n /**\n * The timestamp used to filter out tasks that occured after our paint of interest.\n * Typically this is First Contentful Paint or First Meaningful Paint.\n */\n cutoffTimestamp: number;\n /**\n * The function that determines which resources should be considered *possibly*\n * render-blocking.\n */\n treatNodeAsRenderBlocking: (node: Graph.NetworkNode<T>) => boolean;\n /**\n * The function that determines which CPU nodes should also be included in our\n * blocking node IDs set, beyond what getRenderBlockingNodeData() already includes.\n */\n additionalCpuNodesToTreatAsRenderBlocking?: (node: Graph.CPUNode) => boolean;\n}\n\nclass FirstContentfulPaint extends Metric {\n static override get coefficients(): MetricCoefficients {\n return {\n intercept: 0,\n optimistic: 0.5,\n pessimistic: 0.5,\n };\n }\n\n /**\n * Computes the set of URLs that *appeared* to be render-blocking based on our filter,\n * *but definitely were not* render-blocking based on the timing of their EvaluateScript task.\n * It also computes the set of corresponding CPU node ids that were needed for the paint at the\n * given timestamp.\n */\n static getRenderBlockingNodeData<T = unknown>(\n graph: Graph.Node,\n {cutoffTimestamp, treatNodeAsRenderBlocking, additionalCpuNodesToTreatAsRenderBlocking}:\n FirstPaintBasedGraphOpts<T>,\n ): {definitelyNotRenderBlockingScriptUrls: Set<string>, renderBlockingCpuNodeIds: Set<string>} {\n /** A map of blocking script URLs to the earliest EvaluateScript task node that executed them. */\n const scriptUrlToNodeMap = new Map<string, Graph.CPUNode>();\n\n const cpuNodes: Graph.CPUNode[] = [];\n graph.traverse(node => {\n if (node.type === Graph.BaseNode.types.CPU) {\n // A task is *possibly* render blocking if it *started* before cutoffTimestamp.\n // We use startTime here because the paint event can be *inside* the task that was render blocking.\n if (node.startTime <= cutoffTimestamp) {\n cpuNodes.push(node);\n }\n\n // Build our script URL map to find the earliest EvaluateScript task node.\n const scriptUrls = node.getEvaluateScriptURLs();\n for (const url of scriptUrls) {\n // Use the earliest CPU node we find.\n const existing = scriptUrlToNodeMap.get(url) || node;\n scriptUrlToNodeMap.set(url, node.startTime < existing.startTime ? node : existing);\n }\n }\n });\n\n cpuNodes.sort((a, b) => a.startTime - b.startTime);\n\n // A script is *possibly* render blocking if it finished loading before cutoffTimestamp.\n const possiblyRenderBlockingScriptUrls = Metric.getScriptUrls(graph, node => {\n // The optimistic LCP treatNodeAsRenderBlocking fn wants to exclude some images in the graph,\n // but here it only receives scripts to evaluate. It's a no-op in this case, but it will\n // matter below in the getFirstPaintBasedGraph clone operation.\n return node.endTime <= cutoffTimestamp && treatNodeAsRenderBlocking(node);\n });\n\n // A script is *definitely not* render blocking if its EvaluateScript task started after cutoffTimestamp.\n const definitelyNotRenderBlockingScriptUrls = new Set<string>();\n const renderBlockingCpuNodeIds = new Set<string>();\n for (const url of possiblyRenderBlockingScriptUrls) {\n // Lookup the CPU node that had the earliest EvaluateScript for this URL.\n const cpuNodeForUrl = scriptUrlToNodeMap.get(url);\n\n // If we can't find it at all, we can't conclude anything, so just skip it.\n if (!cpuNodeForUrl) {\n continue;\n }\n\n // If we found it and it was in our `cpuNodes` set that means it finished before cutoffTimestamp, so it really is render-blocking.\n if (cpuNodes.includes(cpuNodeForUrl)) {\n renderBlockingCpuNodeIds.add(cpuNodeForUrl.id);\n continue;\n }\n\n // We couldn't find the evaluate script in the set of CPU nodes that ran before our paint, so\n // it must not have been necessary for the paint.\n definitelyNotRenderBlockingScriptUrls.add(url);\n }\n\n // The first layout, first paint, and first ParseHTML are almost always necessary for first paint,\n // so we always include those CPU nodes.\n const firstLayout = cpuNodes.find(node => node.didPerformLayout());\n if (firstLayout) {\n renderBlockingCpuNodeIds.add(firstLayout.id);\n }\n const firstPaint = cpuNodes.find(node => node.childEvents.some(e => e.name === 'Paint'));\n if (firstPaint) {\n renderBlockingCpuNodeIds.add(firstPaint.id);\n }\n const firstParse = cpuNodes.find(node => node.childEvents.some(e => e.name === 'ParseHTML'));\n if (firstParse) {\n renderBlockingCpuNodeIds.add(firstParse.id);\n }\n\n // If a CPU filter was passed in, we also want to include those extra nodes.\n if (additionalCpuNodesToTreatAsRenderBlocking) {\n cpuNodes.filter(additionalCpuNodesToTreatAsRenderBlocking).forEach(node => renderBlockingCpuNodeIds.add(node.id));\n }\n\n return {\n definitelyNotRenderBlockingScriptUrls,\n renderBlockingCpuNodeIds,\n };\n }\n\n /**\n * Computes the graph required for the first paint of interest.\n */\n static getFirstPaintBasedGraph<T>(\n dependencyGraph: Graph.Node,\n {cutoffTimestamp, treatNodeAsRenderBlocking, additionalCpuNodesToTreatAsRenderBlocking}:\n FirstPaintBasedGraphOpts<T>,\n ): Graph.Node<T> {\n const rbData = this.getRenderBlockingNodeData(dependencyGraph, {\n cutoffTimestamp,\n treatNodeAsRenderBlocking,\n additionalCpuNodesToTreatAsRenderBlocking,\n });\n const {definitelyNotRenderBlockingScriptUrls, renderBlockingCpuNodeIds} = rbData;\n\n return dependencyGraph.cloneWithRelationships(node => {\n if (node.type === Graph.BaseNode.types.NETWORK) {\n // Exclude all nodes that ended after cutoffTimestamp (except for the main document which we always consider necessary)\n // endTime is negative if request does not finish, make sure startTime isn't after cutoffTimestamp in this case.\n const endedAfterPaint = node.endTime > cutoffTimestamp || node.startTime > cutoffTimestamp;\n if (endedAfterPaint && !node.isMainDocument()) {\n return false;\n }\n\n const url = node.request.url;\n // If the URL definitely wasn't render-blocking then we filter it out.\n if (definitelyNotRenderBlockingScriptUrls.has(url)) {\n return false;\n }\n\n // Lastly, build up the FCP graph of all nodes we consider render blocking\n return treatNodeAsRenderBlocking(node);\n }\n // If it's a CPU node, just check if it was blocking.\n return renderBlockingCpuNodeIds.has(node.id);\n });\n }\n\n static override getOptimisticGraph<T>(\n dependencyGraph: Graph.Node<T>, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node<T> {\n return this.getFirstPaintBasedGraph(dependencyGraph, {\n cutoffTimestamp: processedNavigation.timestamps.firstContentfulPaint,\n // In the optimistic graph we exclude resources that appeared to be render blocking but were\n // initiated by a script. While they typically have a very high importance and tend to have a\n // significant impact on the page's content, these resources don't technically block rendering.\n treatNodeAsRenderBlocking: node => node.hasRenderBlockingPriority() && node.initiatorType !== 'script',\n });\n }\n\n static override getPessimisticGraph<T>(\n dependencyGraph: Graph.Node<T>, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node<T> {\n return this.getFirstPaintBasedGraph(dependencyGraph, {\n cutoffTimestamp: processedNavigation.timestamps.firstContentfulPaint,\n treatNodeAsRenderBlocking: node => node.hasRenderBlockingPriority(),\n });\n }\n}\n\nexport {FirstContentfulPaint};\n"]}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type * as
|
|
3
|
-
import { type Extras, Metric } from './Metric.js';
|
|
1
|
+
import * as Graph from '../graph/graph.js';
|
|
2
|
+
import type * as Simulation from '../simulation/simulation.js';
|
|
3
|
+
import { type Extras, Metric, type MetricCoefficients, type MetricComputationDataInput, type MetricResult } from './Metric.js';
|
|
4
4
|
declare class Interactive extends Metric {
|
|
5
|
-
static get coefficients():
|
|
6
|
-
static getOptimisticGraph<T>(dependencyGraph: Node<T>): Node<T>;
|
|
7
|
-
static getPessimisticGraph<T>(dependencyGraph: Node<T>): Node<T>;
|
|
8
|
-
static getEstimateFromSimulation(simulationResult:
|
|
9
|
-
static compute(data:
|
|
10
|
-
static getLastLongTaskEndTime(nodeTimings:
|
|
5
|
+
static get coefficients(): MetricCoefficients;
|
|
6
|
+
static getOptimisticGraph<T>(dependencyGraph: Graph.Node<T>): Graph.Node<T>;
|
|
7
|
+
static getPessimisticGraph<T>(dependencyGraph: Graph.Node<T>): Graph.Node<T>;
|
|
8
|
+
static getEstimateFromSimulation(simulationResult: Simulation.Result, extras: Extras): Simulation.Result;
|
|
9
|
+
static compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>): Promise<MetricResult>;
|
|
10
|
+
static getLastLongTaskEndTime(nodeTimings: Simulation.Result['nodeTimings'], duration?: number): number;
|
|
11
11
|
}
|
|
12
12
|
export { Interactive };
|
|
@@ -1,12 +1,11 @@
|
|
|
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
|
|
5
|
-
import { Metric } from './Metric.js';
|
|
4
|
+
import * as Graph from '../graph/graph.js';
|
|
5
|
+
import { Metric, } from './Metric.js';
|
|
6
6
|
// Any CPU task of 20 ms or more will end up being a critical long task on mobile
|
|
7
7
|
const CRITICAL_LONG_TASK_THRESHOLD = 20;
|
|
8
8
|
class Interactive extends Metric {
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
10
9
|
static get coefficients() {
|
|
11
10
|
return {
|
|
12
11
|
intercept: 0,
|
|
@@ -19,7 +18,7 @@ class Interactive extends Metric {
|
|
|
19
18
|
const minimumCpuTaskDuration = CRITICAL_LONG_TASK_THRESHOLD * 1000;
|
|
20
19
|
return dependencyGraph.cloneWithRelationships(node => {
|
|
21
20
|
// Include everything that might be a long task
|
|
22
|
-
if (node.type === BaseNode.types.CPU) {
|
|
21
|
+
if (node.type === Graph.BaseNode.types.CPU) {
|
|
23
22
|
return node.duration > minimumCpuTaskDuration;
|
|
24
23
|
}
|
|
25
24
|
// Include all scripts and high priority requests, exclude all images
|
|
@@ -55,7 +54,7 @@ class Interactive extends Metric {
|
|
|
55
54
|
static getLastLongTaskEndTime(nodeTimings, duration = 50) {
|
|
56
55
|
return Array.from(nodeTimings.entries())
|
|
57
56
|
.filter(([node, timing]) => {
|
|
58
|
-
if (node.type !== BaseNode.types.CPU) {
|
|
57
|
+
if (node.type !== Graph.BaseNode.types.CPU) {
|
|
59
58
|
return false;
|
|
60
59
|
}
|
|
61
60
|
return timing.duration > duration;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Interactive.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/Interactive.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,
|
|
1
|
+
{"version":3,"file":"Interactive.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/Interactive.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EAEL,MAAM,GAIP,MAAM,aAAa,CAAC;AAErB,iFAAiF;AACjF,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAExC,MAAM,WAAY,SAAQ,MAAM;IAC9B,MAAM,KAAc,YAAY;QAC9B,OAAO;YACL,SAAS,EAAE,CAAC;YACZ,UAAU,EAAE,IAAI;YAChB,WAAW,EAAE,IAAI;SAClB,CAAC;IACJ,CAAC;IAED,MAAM,CAAU,kBAAkB,CAAI,eAA8B;QAClE,2DAA2D;QAC3D,MAAM,sBAAsB,GAAG,4BAA4B,GAAG,IAAI,CAAC;QAEnE,OAAO,eAAe,CAAC,sBAAsB,CAAC,IAAI,CAAC,EAAE;YACnD,+CAA+C;YAC/C,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;gBAC3C,OAAO,IAAI,CAAC,QAAQ,GAAG,sBAAsB,CAAC;YAChD,CAAC;YAED,qEAAqE;YACrE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,KAAK,OAAO,CAAC;YACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,KAAK,QAAQ,CAAC;YACxD,OAAO,CAAC,CAAC,OAAO,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC;QAC9G,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAU,mBAAmB,CAAI,eAA8B;QACnE,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,MAAM,CAAU,yBAAyB,CAAC,gBAAmC,EAAE,MAAc;QAC3F,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,UAAU,GAAG,WAAW,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACpF,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;YAC9C,MAAM,CAAC,SAAS,CAAC,mBAAmB,CAAC,QAAQ,CAAC;QACtF,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,UAAU,CAAC;YAC3C,WAAW,EAAE,gBAAgB,CAAC,WAAW;SAC1C,CAAC;IACJ,CAAC;IAED,MAAM,CAAU,KAAK,CAAC,OAAO,CAAC,IAAgC,EAAE,MAAmC;QAEjG,MAAM,SAAS,GAAG,MAAM,EAAE,SAAS,CAAC;QACpC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvD,YAAY,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;QACtE,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,MAAM,CAAC,sBAAsB,CAAC,WAA6C,EAAE,QAAQ,GAAG,EAAE;QACxF,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;aACnC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;YACzB,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;gBAC3C,OAAO,KAAK,CAAC;YACf,CAAC;YACD,OAAO,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACpC,CAAC,CAAC;aACD,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;aACpC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACzD,CAAC;CACF;AAED,OAAO,EAAC,WAAW,EAAC,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 Graph from '../graph/graph.js';\nimport type * as Simulation from '../simulation/simulation.js';\n\nimport {\n type Extras,\n Metric,\n type MetricCoefficients,\n type MetricComputationDataInput,\n type MetricResult,\n} from './Metric.js';\n\n// Any CPU task of 20 ms or more will end up being a critical long task on mobile\nconst CRITICAL_LONG_TASK_THRESHOLD = 20;\n\nclass Interactive extends Metric {\n static override get coefficients(): MetricCoefficients {\n return {\n intercept: 0,\n optimistic: 0.45,\n pessimistic: 0.55,\n };\n }\n\n static override getOptimisticGraph<T>(dependencyGraph: Graph.Node<T>): Graph.Node<T> {\n // Adjust the critical long task threshold for microseconds\n const minimumCpuTaskDuration = CRITICAL_LONG_TASK_THRESHOLD * 1000;\n\n return dependencyGraph.cloneWithRelationships(node => {\n // Include everything that might be a long task\n if (node.type === Graph.BaseNode.types.CPU) {\n return node.duration > minimumCpuTaskDuration;\n }\n\n // Include all scripts and high priority requests, exclude all images\n const isImage = node.request.resourceType === 'Image';\n const isScript = node.request.resourceType === 'Script';\n return (!isImage && (isScript || node.request.priority === 'High' || node.request.priority === 'VeryHigh'));\n });\n }\n\n static override getPessimisticGraph<T>(dependencyGraph: Graph.Node<T>): Graph.Node<T> {\n return dependencyGraph;\n }\n\n static override getEstimateFromSimulation(simulationResult: Simulation.Result, extras: Extras): Simulation.Result {\n if (!extras.lcpResult) {\n throw new Error('missing lcpResult');\n }\n\n const lastTaskAt = Interactive.getLastLongTaskEndTime(simulationResult.nodeTimings);\n const minimumTime = extras.optimistic ? extras.lcpResult.optimisticEstimate.timeInMs :\n extras.lcpResult.pessimisticEstimate.timeInMs;\n return {\n timeInMs: Math.max(minimumTime, lastTaskAt),\n nodeTimings: simulationResult.nodeTimings,\n };\n }\n\n static override async compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>):\n Promise<MetricResult> {\n const lcpResult = extras?.lcpResult;\n if (!lcpResult) {\n throw new Error('LCP is required to calculate the Interactive metric');\n }\n\n const metricResult = await super.compute(data, extras);\n metricResult.timing = Math.max(metricResult.timing, lcpResult.timing);\n return metricResult;\n }\n\n static getLastLongTaskEndTime(nodeTimings: Simulation.Result['nodeTimings'], duration = 50): number {\n return Array.from(nodeTimings.entries())\n .filter(([node, timing]) => {\n if (node.type !== Graph.BaseNode.types.CPU) {\n return false;\n }\n return timing.duration > duration;\n })\n .map(([_, timing]) => timing.endTime)\n .reduce((max, x) => Math.max(max || 0, x || 0), 0);\n }\n}\n\nexport {Interactive};\n"]}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type * as
|
|
3
|
-
import
|
|
1
|
+
import type * as Graph from '../graph/graph.js';
|
|
2
|
+
import type * as Simulation from '../simulation/simulation.js';
|
|
3
|
+
import type * as Types from '../types/types.js';
|
|
4
|
+
import { type Extras, Metric, type MetricCoefficients, type MetricComputationDataInput, type MetricResult } from './Metric.js';
|
|
4
5
|
declare class LargestContentfulPaint extends Metric {
|
|
5
|
-
static get coefficients():
|
|
6
|
+
static get coefficients(): MetricCoefficients;
|
|
6
7
|
/**
|
|
7
8
|
* Low priority image nodes are usually offscreen and very unlikely to be the
|
|
8
9
|
* resource that is required for LCP. Our LCP graphs include everything except for these images.
|
|
9
10
|
*/
|
|
10
|
-
static isNotLowPriorityImageNode(node: Node): boolean;
|
|
11
|
-
static getOptimisticGraph(dependencyGraph: Node, processedNavigation:
|
|
12
|
-
static getPessimisticGraph(dependencyGraph: Node, processedNavigation:
|
|
13
|
-
static getEstimateFromSimulation(simulationResult:
|
|
14
|
-
static compute(data:
|
|
11
|
+
static isNotLowPriorityImageNode(node: Graph.Node): boolean;
|
|
12
|
+
static getOptimisticGraph(dependencyGraph: Graph.Node, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node;
|
|
13
|
+
static getPessimisticGraph(dependencyGraph: Graph.Node, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node;
|
|
14
|
+
static getEstimateFromSimulation(simulationResult: Simulation.Result): Simulation.Result;
|
|
15
|
+
static compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>): Promise<MetricResult>;
|
|
15
16
|
}
|
|
16
17
|
export { LargestContentfulPaint };
|
|
@@ -1,11 +1,10 @@
|
|
|
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
|
|
4
|
+
import * as Core from '../core/core.js';
|
|
5
5
|
import { FirstContentfulPaint } from './FirstContentfulPaint.js';
|
|
6
|
-
import { Metric } from './Metric.js';
|
|
6
|
+
import { Metric, } from './Metric.js';
|
|
7
7
|
class LargestContentfulPaint extends Metric {
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
9
8
|
static get coefficients() {
|
|
10
9
|
return {
|
|
11
10
|
intercept: 0,
|
|
@@ -28,7 +27,7 @@ class LargestContentfulPaint extends Metric {
|
|
|
28
27
|
static getOptimisticGraph(dependencyGraph, processedNavigation) {
|
|
29
28
|
const lcp = processedNavigation.timestamps.largestContentfulPaint;
|
|
30
29
|
if (!lcp) {
|
|
31
|
-
throw new LanternError('NO_LCP');
|
|
30
|
+
throw new Core.LanternError('NO_LCP');
|
|
32
31
|
}
|
|
33
32
|
return FirstContentfulPaint.getFirstPaintBasedGraph(dependencyGraph, {
|
|
34
33
|
cutoffTimestamp: lcp,
|
|
@@ -38,7 +37,7 @@ class LargestContentfulPaint extends Metric {
|
|
|
38
37
|
static getPessimisticGraph(dependencyGraph, processedNavigation) {
|
|
39
38
|
const lcp = processedNavigation.timestamps.largestContentfulPaint;
|
|
40
39
|
if (!lcp) {
|
|
41
|
-
throw new LanternError('NO_LCP');
|
|
40
|
+
throw new Core.LanternError('NO_LCP');
|
|
42
41
|
}
|
|
43
42
|
return FirstContentfulPaint.getFirstPaintBasedGraph(dependencyGraph, {
|
|
44
43
|
cutoffTimestamp: lcp,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LargestContentfulPaint.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/LargestContentfulPaint.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;
|
|
1
|
+
{"version":3,"file":"LargestContentfulPaint.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/metrics/LargestContentfulPaint.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 Core from '../core/core.js';\nimport type * as Graph from '../graph/graph.js';\nimport type * as Simulation from '../simulation/simulation.js';\nimport type * as Types from '../types/types.js';\n\nimport {FirstContentfulPaint} from './FirstContentfulPaint.js';\nimport {\n type Extras,\n Metric,\n type MetricCoefficients,\n type MetricComputationDataInput,\n type MetricResult,\n} from './Metric.js';\n\nclass LargestContentfulPaint extends Metric {\n static override get coefficients(): MetricCoefficients {\n return {\n intercept: 0,\n optimistic: 0.5,\n pessimistic: 0.5,\n };\n }\n\n /**\n * Low priority image nodes are usually offscreen and very unlikely to be the\n * resource that is required for LCP. Our LCP graphs include everything except for these images.\n */\n static isNotLowPriorityImageNode(node: Graph.Node): boolean {\n if (node.type !== 'network') {\n return true;\n }\n const isImage = node.request.resourceType === 'Image';\n const isLowPriority = node.request.priority === 'Low' || node.request.priority === 'VeryLow';\n return !isImage || !isLowPriority;\n }\n\n static override getOptimisticGraph(\n dependencyGraph: Graph.Node, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node {\n const lcp = processedNavigation.timestamps.largestContentfulPaint;\n if (!lcp) {\n throw new Core.LanternError('NO_LCP');\n }\n\n return FirstContentfulPaint.getFirstPaintBasedGraph(dependencyGraph, {\n cutoffTimestamp: lcp,\n treatNodeAsRenderBlocking: LargestContentfulPaint.isNotLowPriorityImageNode,\n });\n }\n\n static override getPessimisticGraph(\n dependencyGraph: Graph.Node, processedNavigation: Types.Simulation.ProcessedNavigation): Graph.Node {\n const lcp = processedNavigation.timestamps.largestContentfulPaint;\n if (!lcp) {\n throw new Core.LanternError('NO_LCP');\n }\n\n return FirstContentfulPaint.getFirstPaintBasedGraph(dependencyGraph, {\n cutoffTimestamp: lcp,\n treatNodeAsRenderBlocking: _ => true,\n // For pessimistic LCP we'll include *all* layout nodes\n additionalCpuNodesToTreatAsRenderBlocking: node => node.didPerformLayout(),\n });\n }\n\n static override getEstimateFromSimulation(simulationResult: Simulation.Result): Simulation.Result {\n const nodeTimesNotOffscreenImages = Array.from(simulationResult.nodeTimings.entries())\n .filter(entry => LargestContentfulPaint.isNotLowPriorityImageNode(entry[0]))\n .map(entry => entry[1].endTime);\n\n return {\n timeInMs: Math.max(...nodeTimesNotOffscreenImages),\n nodeTimings: simulationResult.nodeTimings,\n };\n }\n\n static override async compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>):\n Promise<MetricResult> {\n const fcpResult = extras?.fcpResult;\n if (!fcpResult) {\n throw new Error('FCP is required to calculate the LCP metric');\n }\n\n const metricResult = await super.compute(data, extras);\n metricResult.timing = Math.max(metricResult.timing, fcpResult.timing);\n return metricResult;\n }\n}\n\nexport {LargestContentfulPaint};\n"]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type * as
|
|
3
|
-
import { type Extras, Metric } from './Metric.js';
|
|
1
|
+
import * as Graph from '../graph/graph.js';
|
|
2
|
+
import type * as Simulation from '../simulation/simulation.js';
|
|
3
|
+
import { type Extras, Metric, type MetricCoefficients, type MetricComputationDataInput, type MetricResult } from './Metric.js';
|
|
4
4
|
declare class MaxPotentialFID extends Metric {
|
|
5
|
-
static get coefficients():
|
|
6
|
-
static getOptimisticGraph(dependencyGraph: Node): Node;
|
|
7
|
-
static getPessimisticGraph(dependencyGraph: Node): Node;
|
|
8
|
-
static getEstimateFromSimulation(simulation:
|
|
9
|
-
static compute(data:
|
|
10
|
-
static getTimingsAfterFCP(nodeTimings:
|
|
5
|
+
static get coefficients(): MetricCoefficients;
|
|
6
|
+
static getOptimisticGraph(dependencyGraph: Graph.Node): Graph.Node;
|
|
7
|
+
static getPessimisticGraph(dependencyGraph: Graph.Node): Graph.Node;
|
|
8
|
+
static getEstimateFromSimulation(simulation: Simulation.Result, extras: Extras): Simulation.Result;
|
|
9
|
+
static compute(data: MetricComputationDataInput, extras?: Omit<Extras, 'optimistic'>): Promise<MetricResult>;
|
|
10
|
+
static getTimingsAfterFCP(nodeTimings: Simulation.Result['nodeTimings'], fcpTimeInMs: number): Array<{
|
|
11
11
|
duration: number;
|
|
12
12
|
}>;
|
|
13
13
|
}
|