@paulirish/trace_engine 0.0.25 → 0.0.26
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/core/platform/TypedArrayUtilities.d.ts +7 -0
- package/core/platform/TypedArrayUtilities.js +41 -0
- package/core/platform/TypedArrayUtilities.js.map +1 -1
- package/core/platform/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/core/platform/platform-tsconfig.json +0 -1
- package/generated/protocol.d.ts +36 -2
- package/models/cpu_profile/cpu_profile-tsconfig.json +0 -1
- package/models/cpu_profile/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/LanternComputationData.d.ts +8 -0
- package/models/trace/LanternComputationData.js +368 -0
- package/models/trace/LanternComputationData.js.map +1 -0
- package/models/trace/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/extras/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/extras/extras-tsconfig.json +0 -1
- package/models/trace/handlers/EnhancedTracesHandler.d.ts +46 -0
- package/models/trace/handlers/EnhancedTracesHandler.js +137 -0
- package/models/trace/handlers/EnhancedTracesHandler.js.map +1 -0
- package/models/trace/handlers/LayoutShiftsHandler.d.ts +1 -1
- package/models/trace/handlers/LayoutShiftsHandler.js +1 -1
- package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
- package/models/trace/handlers/ModelHandlers.d.ts +1 -0
- package/models/trace/handlers/ModelHandlers.js +1 -0
- package/models/trace/handlers/ModelHandlers.js.map +1 -1
- package/models/trace/handlers/UserInteractionsHandler.d.ts +6 -0
- package/models/trace/handlers/UserInteractionsHandler.js +15 -0
- package/models/trace/handlers/UserInteractionsHandler.js.map +1 -1
- package/models/trace/handlers/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/handlers/handlers-tsconfig.json +1 -1
- package/models/trace/helpers/Timing.d.ts +0 -6
- package/models/trace/helpers/Timing.js +0 -76
- package/models/trace/helpers/Timing.js.map +1 -1
- package/models/trace/helpers/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/helpers/helpers-tsconfig.json +0 -1
- package/models/trace/insights/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/insights/insights-tsconfig.json +0 -1
- package/models/trace/lantern/BaseNode.d.ts +91 -0
- package/models/trace/lantern/BaseNode.js +268 -0
- package/models/trace/lantern/BaseNode.js.map +1 -0
- package/models/trace/lantern/CPUNode.d.ts +24 -0
- package/models/trace/lantern/CPUNode.js +64 -0
- package/models/trace/lantern/CPUNode.js.map +1 -0
- package/models/trace/lantern/LanternError.d.ts +3 -0
- package/models/trace/lantern/LanternError.js +7 -0
- package/models/trace/lantern/LanternError.js.map +1 -0
- package/models/trace/lantern/MetricsModule.d.ts +11 -0
- package/models/trace/lantern/MetricsModule.js +14 -0
- package/models/trace/lantern/MetricsModule.js.map +1 -0
- package/models/trace/lantern/NetworkNode.d.ts +22 -0
- package/models/trace/lantern/NetworkNode.js +83 -0
- package/models/trace/lantern/NetworkNode.js.map +1 -0
- package/models/trace/lantern/PageDependencyGraph.d.ts +43 -0
- package/models/trace/lantern/PageDependencyGraph.js +509 -0
- package/models/trace/lantern/PageDependencyGraph.js.map +1 -0
- package/models/trace/lantern/SimulationModule.d.ts +17 -0
- package/models/trace/lantern/SimulationModule.js +13 -0
- package/models/trace/lantern/SimulationModule.js.map +1 -0
- package/models/trace/lantern/bundle-tsconfig.json +1 -0
- package/models/trace/lantern/devtools_entrypoint-bundle-typescript-tsconfig.json +42 -0
- package/models/trace/lantern/lantern-tsconfig.json +64 -0
- package/models/trace/lantern/lantern.d.ts +29 -0
- package/models/trace/lantern/lantern.js +33 -0
- package/models/trace/lantern/lantern.js.map +1 -0
- package/models/trace/lantern/metrics/FirstContentfulPaint.d.ts +42 -0
- package/models/trace/lantern/metrics/FirstContentfulPaint.js +137 -0
- package/models/trace/lantern/metrics/FirstContentfulPaint.js.map +1 -0
- package/models/trace/lantern/metrics/Interactive.d.ts +12 -0
- package/models/trace/lantern/metrics/Interactive.js +68 -0
- package/models/trace/lantern/metrics/Interactive.js.map +1 -0
- package/models/trace/lantern/metrics/LargestContentfulPaint.d.ts +16 -0
- package/models/trace/lantern/metrics/LargestContentfulPaint.js +70 -0
- package/models/trace/lantern/metrics/LargestContentfulPaint.js.map +1 -0
- package/models/trace/lantern/metrics/MaxPotentialFID.d.ts +14 -0
- package/models/trace/lantern/metrics/MaxPotentialFID.js +49 -0
- package/models/trace/lantern/metrics/MaxPotentialFID.js.map +1 -0
- package/models/trace/lantern/metrics/Metric.d.ts +26 -0
- package/models/trace/lantern/metrics/Metric.js +71 -0
- package/models/trace/lantern/metrics/Metric.js.map +1 -0
- package/models/trace/lantern/metrics/SpeedIndex.d.ts +25 -0
- package/models/trace/lantern/metrics/SpeedIndex.js +102 -0
- package/models/trace/lantern/metrics/SpeedIndex.js.map +1 -0
- package/models/trace/lantern/metrics/TBTUtils.d.ts +31 -0
- package/models/trace/lantern/metrics/TBTUtils.js +65 -0
- package/models/trace/lantern/metrics/TBTUtils.js.map +1 -0
- package/models/trace/lantern/metrics/TotalBlockingTime.d.ts +16 -0
- package/models/trace/lantern/metrics/TotalBlockingTime.js +79 -0
- package/models/trace/lantern/metrics/TotalBlockingTime.js.map +1 -0
- package/models/trace/lantern/metrics/metrics.d.ts +15 -0
- package/models/trace/lantern/metrics/metrics.js +12 -0
- package/models/trace/lantern/metrics/metrics.js.map +1 -0
- package/models/trace/lantern/simulation/ConnectionPool.d.ts +26 -0
- package/models/trace/lantern/simulation/ConnectionPool.js +116 -0
- package/models/trace/lantern/simulation/ConnectionPool.js.map +1 -0
- package/models/trace/lantern/simulation/Constants.d.ts +31 -0
- package/models/trace/lantern/simulation/Constants.js +43 -0
- package/models/trace/lantern/simulation/Constants.js.map +1 -0
- package/models/trace/lantern/simulation/DNSCache.d.ts +22 -0
- package/models/trace/lantern/simulation/DNSCache.js +48 -0
- package/models/trace/lantern/simulation/DNSCache.js.map +1 -0
- package/models/trace/lantern/simulation/NetworkAnalyzer.d.ts +112 -0
- package/models/trace/lantern/simulation/NetworkAnalyzer.js +486 -0
- package/models/trace/lantern/simulation/NetworkAnalyzer.js.map +1 -0
- package/models/trace/lantern/simulation/SimulationTimingMap.d.ts +71 -0
- package/models/trace/lantern/simulation/SimulationTimingMap.js +134 -0
- package/models/trace/lantern/simulation/SimulationTimingMap.js.map +1 -0
- package/models/trace/lantern/simulation/Simulator.d.ts +82 -0
- package/models/trace/lantern/simulation/Simulator.js +449 -0
- package/models/trace/lantern/simulation/Simulator.js.map +1 -0
- package/models/trace/lantern/simulation/TCPConnection.d.ts +48 -0
- package/models/trace/lantern/simulation/TCPConnection.js +158 -0
- package/models/trace/lantern/simulation/TCPConnection.js.map +1 -0
- package/models/trace/lantern/simulation/simulation.d.ts +21 -0
- package/models/trace/lantern/simulation/simulation.js +11 -0
- package/models/trace/lantern/simulation/simulation.js.map +1 -0
- package/models/trace/lantern/types/lantern.d.ts +205 -0
- package/models/trace/lantern/types/lantern.js +5 -0
- package/models/trace/lantern/types/lantern.js.map +1 -0
- package/models/trace/root-causes/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/root-causes/root-causes-tsconfig.json +0 -1
- package/models/trace/trace-tsconfig.json +4 -1
- package/models/trace/trace.d.ts +3 -1
- package/models/trace/trace.js +3 -1
- package/models/trace/trace.js.map +1 -1
- package/models/trace/types/Extensions.d.ts +2 -3
- package/models/trace/types/Extensions.js +2 -11
- package/models/trace/types/Extensions.js.map +1 -1
- package/models/trace/types/File.d.ts +1 -0
- package/models/trace/types/File.js.map +1 -1
- package/models/trace/types/TraceEvents.d.ts +49 -0
- package/models/trace/types/TraceEvents.js +33 -0
- package/models/trace/types/TraceEvents.js.map +1 -1
- package/models/trace/types/devtools_entrypoint-bundle-typescript-tsconfig.json +0 -1
- package/models/trace/types/types-tsconfig.json +0 -1
- package/package.json +1 -1
- package/PAUL.readme.md +0 -5
|
@@ -24,3 +24,10 @@ export declare function createExpandableBigUint32Array(): BigUint32Array;
|
|
|
24
24
|
* asUint32ArrayOrFail will succeed. Otherwise, it will throw an exception.
|
|
25
25
|
*/
|
|
26
26
|
export declare function createFixedBigUint32Array(length: number, maxLengthForTesting?: number): BigUint32Array;
|
|
27
|
+
export interface BitVector {
|
|
28
|
+
getBit(index: number): boolean;
|
|
29
|
+
setBit(index: number): void;
|
|
30
|
+
clearBit(index: number): void;
|
|
31
|
+
previous(index: number): number;
|
|
32
|
+
}
|
|
33
|
+
export declare function createBitVector(length: number): BitVector;
|
|
@@ -108,4 +108,45 @@ class ExpandableBigUint32ArrayImpl extends Array {
|
|
|
108
108
|
return this;
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
+
export function createBitVector(length) {
|
|
112
|
+
return new BitVectorImpl(length);
|
|
113
|
+
}
|
|
114
|
+
class BitVectorImpl extends Uint8Array {
|
|
115
|
+
constructor(length) {
|
|
116
|
+
super(Math.ceil(length / 8));
|
|
117
|
+
}
|
|
118
|
+
getBit(index) {
|
|
119
|
+
const value = this[index >> 3] & (1 << (index & 7));
|
|
120
|
+
return value !== 0;
|
|
121
|
+
}
|
|
122
|
+
setBit(index) {
|
|
123
|
+
this[index >> 3] |= (1 << (index & 7));
|
|
124
|
+
}
|
|
125
|
+
clearBit(index) {
|
|
126
|
+
this[index >> 3] &= ~(1 << (index & 7));
|
|
127
|
+
}
|
|
128
|
+
previous(index) {
|
|
129
|
+
// First, check for more bits in the current byte.
|
|
130
|
+
while (index !== ((index >> 3) << 3)) {
|
|
131
|
+
--index;
|
|
132
|
+
if (this.getBit(index)) {
|
|
133
|
+
return index;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Next, iterate by bytes to skip over ranges of zeros.
|
|
137
|
+
let byteIndex;
|
|
138
|
+
for (byteIndex = (index >> 3) - 1; byteIndex >= 0 && this[byteIndex] === 0; --byteIndex) {
|
|
139
|
+
}
|
|
140
|
+
if (byteIndex < 0) {
|
|
141
|
+
return -1;
|
|
142
|
+
}
|
|
143
|
+
// Finally, iterate the nonzero byte to find the highest bit.
|
|
144
|
+
for (index = (byteIndex << 3) + 7; index >= (byteIndex << 3); --index) {
|
|
145
|
+
if (this.getBit(index)) {
|
|
146
|
+
return index;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
throw new Error('Unreachable');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
111
152
|
//# sourceMappingURL=TypedArrayUtilities.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TypedArrayUtilities.js","sourceRoot":"","sources":["../../../../../../front_end/core/platform/TypedArrayUtilities.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\n/**\n * An object which provides functionality similar to Uint32Array. It may be\n * implemented as:\n * 1. A Uint32Array,\n * 2. An array of Uint32Arrays, to support more data than Uint32Array, or\n * 3. A plain array, in which case the length may change by setting values.\n */\nexport interface BigUint32Array {\n get length(): number;\n getValue(index: number): number;\n setValue(index: number, value: number): void;\n asUint32ArrayOrFail(): Uint32Array;\n asArrayOrFail(): number[];\n}\n\n/**\n * @returns A BigUint32Array implementation which is based on Array.\n * This means that its length automatically expands to include the highest index\n * used, and asArrayOrFail will succeed.\n */\nexport function createExpandableBigUint32Array(): BigUint32Array {\n return new ExpandableBigUint32ArrayImpl();\n}\n\n/**\n * @returns A BigUint32Array implementation which is based on Uint32Array.\n * If the length is small enough to fit in a single Uint32Array, then\n * asUint32ArrayOrFail will succeed. Otherwise, it will throw an exception.\n */\nexport function createFixedBigUint32Array(length: number, maxLengthForTesting?: number): BigUint32Array {\n try {\n if (maxLengthForTesting !== undefined && length > maxLengthForTesting) {\n // Simulate allocation failure.\n throw new RangeError();\n }\n return new BasicBigUint32ArrayImpl(length);\n } catch {\n // We couldn't allocate a big enough ArrayBuffer.\n return new SplitBigUint32ArrayImpl(length, maxLengthForTesting);\n }\n}\n\nclass BasicBigUint32ArrayImpl extends Uint32Array implements BigUint32Array {\n getValue(index: number): number {\n return this[index];\n }\n setValue(index: number, value: number): void {\n this[index] = value;\n }\n asUint32ArrayOrFail(): Uint32Array {\n return this;\n }\n asArrayOrFail(): number[] {\n throw new Error('Not an array');\n }\n}\n\nclass SplitBigUint32ArrayImpl implements BigUint32Array {\n #data: Uint32Array[];\n #partLength: number;\n length: number;\n\n constructor(length: number, maxLengthForTesting?: number) {\n this.#data = [];\n this.length = length;\n let partCount = 1;\n while (true) {\n partCount *= 2;\n this.#partLength = Math.ceil(length / partCount);\n try {\n if (maxLengthForTesting !== undefined && this.#partLength > maxLengthForTesting) {\n // Simulate allocation failure.\n throw new RangeError();\n }\n for (let i = 0; i < partCount; ++i) {\n this.#data[i] = new Uint32Array(this.#partLength);\n }\n return;\n } catch (e) {\n if (this.#partLength < 1e6) {\n // The length per part is already small, so continuing to subdivide it\n // will probably not help.\n throw e;\n }\n }\n }\n }\n\n getValue(index: number): number {\n if (index >= 0 && index < this.length) {\n const partLength = this.#partLength;\n return this.#data[Math.floor(index / partLength)][index % partLength];\n }\n // On out-of-bounds accesses, match the behavior of Uint32Array: return an\n // undefined value that's incorrectly typed as number.\n return this.#data[0][-1];\n }\n\n setValue(index: number, value: number): void {\n if (index >= 0 && index < this.length) {\n const partLength = this.#partLength;\n this.#data[Math.floor(index / partLength)][index % partLength] = value;\n }\n // Attempting to set a value out of bounds does nothing, like Uint32Array.\n }\n\n asUint32ArrayOrFail(): Uint32Array {\n throw new Error('Not a Uint32Array');\n }\n asArrayOrFail(): number[] {\n throw new Error('Not an array');\n }\n}\n\nclass ExpandableBigUint32ArrayImpl extends Array<number> implements BigUint32Array {\n getValue(index: number): number {\n return this[index];\n }\n setValue(index: number, value: number): void {\n this[index] = value;\n }\n asUint32ArrayOrFail(): Uint32Array {\n throw new Error('Not a Uint32Array');\n }\n asArrayOrFail(): number[] {\n return this;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TypedArrayUtilities.js","sourceRoot":"","sources":["../../../../../../front_end/core/platform/TypedArrayUtilities.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\n/**\n * An object which provides functionality similar to Uint32Array. It may be\n * implemented as:\n * 1. A Uint32Array,\n * 2. An array of Uint32Arrays, to support more data than Uint32Array, or\n * 3. A plain array, in which case the length may change by setting values.\n */\nexport interface BigUint32Array {\n get length(): number;\n getValue(index: number): number;\n setValue(index: number, value: number): void;\n asUint32ArrayOrFail(): Uint32Array;\n asArrayOrFail(): number[];\n}\n\n/**\n * @returns A BigUint32Array implementation which is based on Array.\n * This means that its length automatically expands to include the highest index\n * used, and asArrayOrFail will succeed.\n */\nexport function createExpandableBigUint32Array(): BigUint32Array {\n return new ExpandableBigUint32ArrayImpl();\n}\n\n/**\n * @returns A BigUint32Array implementation which is based on Uint32Array.\n * If the length is small enough to fit in a single Uint32Array, then\n * asUint32ArrayOrFail will succeed. Otherwise, it will throw an exception.\n */\nexport function createFixedBigUint32Array(length: number, maxLengthForTesting?: number): BigUint32Array {\n try {\n if (maxLengthForTesting !== undefined && length > maxLengthForTesting) {\n // Simulate allocation failure.\n throw new RangeError();\n }\n return new BasicBigUint32ArrayImpl(length);\n } catch {\n // We couldn't allocate a big enough ArrayBuffer.\n return new SplitBigUint32ArrayImpl(length, maxLengthForTesting);\n }\n}\n\nclass BasicBigUint32ArrayImpl extends Uint32Array implements BigUint32Array {\n getValue(index: number): number {\n return this[index];\n }\n setValue(index: number, value: number): void {\n this[index] = value;\n }\n asUint32ArrayOrFail(): Uint32Array {\n return this;\n }\n asArrayOrFail(): number[] {\n throw new Error('Not an array');\n }\n}\n\nclass SplitBigUint32ArrayImpl implements BigUint32Array {\n #data: Uint32Array[];\n #partLength: number;\n length: number;\n\n constructor(length: number, maxLengthForTesting?: number) {\n this.#data = [];\n this.length = length;\n let partCount = 1;\n while (true) {\n partCount *= 2;\n this.#partLength = Math.ceil(length / partCount);\n try {\n if (maxLengthForTesting !== undefined && this.#partLength > maxLengthForTesting) {\n // Simulate allocation failure.\n throw new RangeError();\n }\n for (let i = 0; i < partCount; ++i) {\n this.#data[i] = new Uint32Array(this.#partLength);\n }\n return;\n } catch (e) {\n if (this.#partLength < 1e6) {\n // The length per part is already small, so continuing to subdivide it\n // will probably not help.\n throw e;\n }\n }\n }\n }\n\n getValue(index: number): number {\n if (index >= 0 && index < this.length) {\n const partLength = this.#partLength;\n return this.#data[Math.floor(index / partLength)][index % partLength];\n }\n // On out-of-bounds accesses, match the behavior of Uint32Array: return an\n // undefined value that's incorrectly typed as number.\n return this.#data[0][-1];\n }\n\n setValue(index: number, value: number): void {\n if (index >= 0 && index < this.length) {\n const partLength = this.#partLength;\n this.#data[Math.floor(index / partLength)][index % partLength] = value;\n }\n // Attempting to set a value out of bounds does nothing, like Uint32Array.\n }\n\n asUint32ArrayOrFail(): Uint32Array {\n throw new Error('Not a Uint32Array');\n }\n asArrayOrFail(): number[] {\n throw new Error('Not an array');\n }\n}\n\nclass ExpandableBigUint32ArrayImpl extends Array<number> implements BigUint32Array {\n getValue(index: number): number {\n return this[index];\n }\n setValue(index: number, value: number): void {\n this[index] = value;\n }\n asUint32ArrayOrFail(): Uint32Array {\n throw new Error('Not a Uint32Array');\n }\n asArrayOrFail(): number[] {\n return this;\n }\n}\n\nexport interface BitVector {\n getBit(index: number): boolean;\n setBit(index: number): void;\n clearBit(index: number): void;\n // Returns the last bit before `index` which is set, or -1 if there are none.\n previous(index: number): number;\n}\n\nexport function createBitVector(length: number): BitVector {\n return new BitVectorImpl(length);\n}\n\nclass BitVectorImpl extends Uint8Array {\n constructor(length: number) {\n super(Math.ceil(length / 8));\n }\n getBit(index: number): boolean {\n const value = this[index >> 3] & (1 << (index & 7));\n return value !== 0;\n }\n setBit(index: number): void {\n this[index >> 3] |= (1 << (index & 7));\n }\n clearBit(index: number): void {\n this[index >> 3] &= ~(1 << (index & 7));\n }\n previous(index: number): number {\n // First, check for more bits in the current byte.\n while (index !== ((index >> 3) << 3)) {\n --index;\n if (this.getBit(index)) {\n return index;\n }\n }\n // Next, iterate by bytes to skip over ranges of zeros.\n let byteIndex: number;\n for (byteIndex = (index >> 3) - 1; byteIndex >= 0 && this[byteIndex] === 0; --byteIndex) {\n }\n if (byteIndex < 0) {\n return -1;\n }\n // Finally, iterate the nonzero byte to find the highest bit.\n for (index = (byteIndex << 3) + 7; index >= (byteIndex << 3); --index) {\n if (this.getBit(index)) {\n return index;\n }\n }\n throw new Error('Unreachable');\n }\n}\n"]}
|
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
"../../../../../../front_end/core/platform/platform.ts",
|
|
33
33
|
"../../../../../../front_end/legacy/legacy-defs.d.ts",
|
|
34
34
|
"../../../../../../front_end/global_typings/global_defs.d.ts",
|
|
35
|
-
"../../../../../../front_end/global_typings/request_idle_callback.d.ts",
|
|
36
35
|
"../../../../../../node_modules/@types/filesystem/index.d.ts"
|
|
37
36
|
],
|
|
38
37
|
"references": [
|
|
@@ -48,7 +48,6 @@
|
|
|
48
48
|
"../../../../../../front_end/core/platform/UserVisibleError.ts",
|
|
49
49
|
"../../../../../../front_end/legacy/legacy-defs.d.ts",
|
|
50
50
|
"../../../../../../front_end/global_typings/global_defs.d.ts",
|
|
51
|
-
"../../../../../../front_end/global_typings/request_idle_callback.d.ts",
|
|
52
51
|
"../../../../../../node_modules/@types/filesystem/index.d.ts"
|
|
53
52
|
]
|
|
54
53
|
}
|
package/generated/protocol.d.ts
CHANGED
|
@@ -201,7 +201,8 @@ export declare namespace Accessibility {
|
|
|
201
201
|
Errormessage = "errormessage",
|
|
202
202
|
Flowto = "flowto",
|
|
203
203
|
Labelledby = "labelledby",
|
|
204
|
-
Owns = "owns"
|
|
204
|
+
Owns = "owns",
|
|
205
|
+
Url = "url"
|
|
205
206
|
}
|
|
206
207
|
/**
|
|
207
208
|
* A node in the accessibility tree.
|
|
@@ -1097,7 +1098,9 @@ export declare namespace Audits {
|
|
|
1097
1098
|
ClientMetadataNoResponse = "ClientMetadataNoResponse",
|
|
1098
1099
|
ClientMetadataInvalidResponse = "ClientMetadataInvalidResponse",
|
|
1099
1100
|
ClientMetadataInvalidContentType = "ClientMetadataInvalidContentType",
|
|
1101
|
+
IdpNotPotentiallyTrustworthy = "IdpNotPotentiallyTrustworthy",
|
|
1100
1102
|
DisabledInSettings = "DisabledInSettings",
|
|
1103
|
+
DisabledInFlags = "DisabledInFlags",
|
|
1101
1104
|
ErrorFetchingSignin = "ErrorFetchingSignin",
|
|
1102
1105
|
InvalidSigninResponse = "InvalidSigninResponse",
|
|
1103
1106
|
AccountsHttpNotFound = "AccountsHttpNotFound",
|
|
@@ -1120,6 +1123,7 @@ export declare namespace Audits {
|
|
|
1120
1123
|
NotSignedInWithIdp = "NotSignedInWithIdp",
|
|
1121
1124
|
MissingTransientUserActivation = "MissingTransientUserActivation",
|
|
1122
1125
|
ReplacedByButtonMode = "ReplacedByButtonMode",
|
|
1126
|
+
InvalidFieldsSpecified = "InvalidFieldsSpecified",
|
|
1123
1127
|
RelyingPartyOriginIsOpaque = "RelyingPartyOriginIsOpaque",
|
|
1124
1128
|
TypeNotMatching = "TypeNotMatching"
|
|
1125
1129
|
}
|
|
@@ -1669,6 +1673,10 @@ export declare namespace Browser {
|
|
|
1669
1673
|
* For "clipboard" permission, may specify allowWithoutSanitization.
|
|
1670
1674
|
*/
|
|
1671
1675
|
allowWithoutSanitization?: boolean;
|
|
1676
|
+
/**
|
|
1677
|
+
* For "fullscreen" permission, must specify allowWithoutGesture:true.
|
|
1678
|
+
*/
|
|
1679
|
+
allowWithoutGesture?: boolean;
|
|
1672
1680
|
/**
|
|
1673
1681
|
* For "camera" permission, may specify panTiltZoom.
|
|
1674
1682
|
*/
|
|
@@ -13348,7 +13356,8 @@ export declare namespace Storage {
|
|
|
13348
13356
|
DestinationBothLimitsReached = "destinationBothLimitsReached",
|
|
13349
13357
|
ReportingOriginsPerSiteLimitReached = "reportingOriginsPerSiteLimitReached",
|
|
13350
13358
|
ExceedsMaxChannelCapacity = "exceedsMaxChannelCapacity",
|
|
13351
|
-
ExceedsMaxTriggerStateCardinality = "exceedsMaxTriggerStateCardinality"
|
|
13359
|
+
ExceedsMaxTriggerStateCardinality = "exceedsMaxTriggerStateCardinality",
|
|
13360
|
+
DestinationPerDayReportingLimitReached = "destinationPerDayReportingLimitReached"
|
|
13352
13361
|
}
|
|
13353
13362
|
const enum AttributionReportingSourceRegistrationTimeConfig {
|
|
13354
13363
|
Include = "include",
|
|
@@ -15987,6 +15996,13 @@ export declare namespace PWA {
|
|
|
15987
15996
|
accepts: FileHandlerAccept[];
|
|
15988
15997
|
displayName: string;
|
|
15989
15998
|
}
|
|
15999
|
+
/**
|
|
16000
|
+
* If user prefers opening the app in browser or an app window.
|
|
16001
|
+
*/
|
|
16002
|
+
const enum DisplayMode {
|
|
16003
|
+
Standalone = "standalone",
|
|
16004
|
+
Browser = "browser"
|
|
16005
|
+
}
|
|
15990
16006
|
interface GetOsAppStateRequest {
|
|
15991
16007
|
/**
|
|
15992
16008
|
* The id from the webapp's manifest file, commonly it's the url of the
|
|
@@ -16033,6 +16049,24 @@ export declare namespace PWA {
|
|
|
16033
16049
|
interface OpenCurrentPageInAppRequest {
|
|
16034
16050
|
manifestId: string;
|
|
16035
16051
|
}
|
|
16052
|
+
interface ChangeAppUserSettingsRequest {
|
|
16053
|
+
manifestId: string;
|
|
16054
|
+
/**
|
|
16055
|
+
* If user allows the links clicked on by the user in the app's scope, or
|
|
16056
|
+
* extended scope if the manifest has scope extensions and the flags
|
|
16057
|
+
* `DesktopPWAsLinkCapturingWithScopeExtensions` and
|
|
16058
|
+
* `WebAppEnableScopeExtensions` are enabled.
|
|
16059
|
+
*
|
|
16060
|
+
* Note, the API does not support resetting the linkCapturing to the
|
|
16061
|
+
* initial value, uninstalling and installing the web app again will reset
|
|
16062
|
+
* it.
|
|
16063
|
+
*
|
|
16064
|
+
* TODO(crbug.com/339453269): Setting this value on ChromeOS is not
|
|
16065
|
+
* supported yet.
|
|
16066
|
+
*/
|
|
16067
|
+
linkCapturing?: boolean;
|
|
16068
|
+
displayMode?: DisplayMode;
|
|
16069
|
+
}
|
|
16036
16070
|
}
|
|
16037
16071
|
/**
|
|
16038
16072
|
* Debugger domain exposes JavaScript debugging capabilities. It allows setting and removing
|
|
@@ -33,7 +33,6 @@
|
|
|
33
33
|
"../../../../../../front_end/models/cpu_profile/ProfileTreeModel.ts",
|
|
34
34
|
"../../../../../../front_end/legacy/legacy-defs.d.ts",
|
|
35
35
|
"../../../../../../front_end/global_typings/global_defs.d.ts",
|
|
36
|
-
"../../../../../../front_end/global_typings/request_idle_callback.d.ts",
|
|
37
36
|
"../../../../../../node_modules/@types/filesystem/index.d.ts"
|
|
38
37
|
],
|
|
39
38
|
"references": [
|
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
"../../../../../../front_end/models/cpu_profile/cpu_profile.ts",
|
|
33
33
|
"../../../../../../front_end/legacy/legacy-defs.d.ts",
|
|
34
34
|
"../../../../../../front_end/global_typings/global_defs.d.ts",
|
|
35
|
-
"../../../../../../front_end/global_typings/request_idle_callback.d.ts",
|
|
36
35
|
"../../../../../../node_modules/@types/filesystem/index.d.ts"
|
|
37
36
|
],
|
|
38
37
|
"references": [
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as Handlers from './handlers/handlers.js';
|
|
2
|
+
import * as Lantern from './lantern/lantern.js';
|
|
3
|
+
import type * as Types from './types/types.js';
|
|
4
|
+
type NetworkRequest = Lantern.NetworkRequest<Types.TraceEvents.SyntheticNetworkRequest>;
|
|
5
|
+
declare function createProcessedNavigation(traceEngineData: Handlers.Types.TraceParseData): Lantern.Simulation.ProcessedNavigation;
|
|
6
|
+
declare function createNetworkRequests(trace: Lantern.Trace, traceEngineData: Handlers.Types.TraceParseData): NetworkRequest[];
|
|
7
|
+
declare function createGraph(requests: Lantern.NetworkRequest[], trace: Lantern.Trace, traceEngineData: Handlers.Types.TraceParseData, url?: Lantern.Simulation.URL): Lantern.Node<Types.TraceEvents.SyntheticNetworkRequest>;
|
|
8
|
+
export { createProcessedNavigation, createNetworkRequests, createGraph, };
|
|
@@ -0,0 +1,368 @@
|
|
|
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
|
+
import * as Handlers from './handlers/handlers.js';
|
|
5
|
+
import * as Lantern from './lantern/lantern.js';
|
|
6
|
+
function createProcessedNavigation(traceEngineData) {
|
|
7
|
+
const Meta = traceEngineData.Meta;
|
|
8
|
+
const frameId = Meta.mainFrameId;
|
|
9
|
+
const scoresByNav = traceEngineData.PageLoadMetrics.metricScoresByFrameId.get(frameId);
|
|
10
|
+
if (!scoresByNav) {
|
|
11
|
+
throw new Error('missing metric scores for main frame');
|
|
12
|
+
}
|
|
13
|
+
const lastNavigationId = Meta.mainFrameNavigations.at(-1)?.args.data?.navigationId;
|
|
14
|
+
const scores = lastNavigationId && scoresByNav.get(lastNavigationId);
|
|
15
|
+
if (!scores) {
|
|
16
|
+
throw new Error('missing metric scores for specified navigation');
|
|
17
|
+
}
|
|
18
|
+
const getTimestampOrUndefined = (metric) => {
|
|
19
|
+
const metricScore = scores.get(metric);
|
|
20
|
+
if (!metricScore?.event) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
return metricScore.event.ts;
|
|
24
|
+
};
|
|
25
|
+
const getTimestamp = (metric) => {
|
|
26
|
+
const metricScore = scores.get(metric);
|
|
27
|
+
if (!metricScore?.event) {
|
|
28
|
+
throw new Error(`missing metric: ${metric}`);
|
|
29
|
+
}
|
|
30
|
+
return metricScore.event.ts;
|
|
31
|
+
};
|
|
32
|
+
return {
|
|
33
|
+
timestamps: {
|
|
34
|
+
firstContentfulPaint: getTimestamp("FCP" /* Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP */),
|
|
35
|
+
largestContentfulPaint: getTimestampOrUndefined("LCP" /* Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */),
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function createParsedUrl(url) {
|
|
40
|
+
if (typeof url === 'string') {
|
|
41
|
+
url = new URL(url);
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
scheme: url.protocol.split(':')[0],
|
|
45
|
+
// Intentional, DevTools uses different terminology
|
|
46
|
+
host: url.hostname,
|
|
47
|
+
securityOrigin: url.origin,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Returns a map of `pid` -> `tid[]`.
|
|
52
|
+
*/
|
|
53
|
+
function findWorkerThreads(trace) {
|
|
54
|
+
// TODO: WorkersHandler in TraceEngine needs to be updated to also include `pid` (only had `tid`).
|
|
55
|
+
const workerThreads = new Map();
|
|
56
|
+
const workerCreationEvents = ['ServiceWorker thread', 'DedicatedWorker thread'];
|
|
57
|
+
for (const event of trace.traceEvents) {
|
|
58
|
+
if (event.name !== 'thread_name' || !event.args.name) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (!workerCreationEvents.includes(event.args.name)) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const tids = workerThreads.get(event.pid);
|
|
65
|
+
if (tids) {
|
|
66
|
+
tids.push(event.tid);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
workerThreads.set(event.pid, [event.tid]);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return workerThreads;
|
|
73
|
+
}
|
|
74
|
+
function createLanternRequest(traceEngineData, workerThreads, request) {
|
|
75
|
+
if (request.args.data.connectionId === undefined || request.args.data.connectionReused === undefined) {
|
|
76
|
+
throw new Error('Trace is too old');
|
|
77
|
+
}
|
|
78
|
+
let url;
|
|
79
|
+
try {
|
|
80
|
+
url = new URL(request.args.data.url);
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const timing = request.args.data.timing ? {
|
|
86
|
+
// These two timings are not included in the trace.
|
|
87
|
+
workerFetchStart: -1,
|
|
88
|
+
workerRespondWithSettled: -1,
|
|
89
|
+
...request.args.data.timing,
|
|
90
|
+
} :
|
|
91
|
+
undefined;
|
|
92
|
+
const networkRequestTime = timing ? timing.requestTime * 1000 : request.args.data.syntheticData.downloadStart / 1000;
|
|
93
|
+
let fromWorker = false;
|
|
94
|
+
const tids = workerThreads.get(request.pid);
|
|
95
|
+
if (tids?.includes(request.tid)) {
|
|
96
|
+
fromWorker = true;
|
|
97
|
+
}
|
|
98
|
+
// TraceEngine collects worker thread ids in a different manner than `workerThreads` does.
|
|
99
|
+
// AFAIK these should be equivalent, but in case they are not let's also check this for now.
|
|
100
|
+
if (traceEngineData.Workers.workerIdByThread.has(request.tid)) {
|
|
101
|
+
fromWorker = true;
|
|
102
|
+
}
|
|
103
|
+
// `initiator` in the trace does not contain the stack trace for JS-initiated
|
|
104
|
+
// requests. Instead, that is stored in the `stackTrace` property of the SyntheticNetworkRequest.
|
|
105
|
+
// There are some minor differences in the fields, accounted for here.
|
|
106
|
+
// Most importantly, there seems to be fewer frames in the trace than the equivalent
|
|
107
|
+
// events over the CDP. This results in less accuracy in determining the initiator request,
|
|
108
|
+
// which means less edges in the graph, which mean worse results.
|
|
109
|
+
// TODO: Should fix in Chromium.
|
|
110
|
+
const initiator = request.args.data.initiator ?? { type: "other" /* Protocol.Network.InitiatorType.Other */ };
|
|
111
|
+
if (request.args.data.stackTrace) {
|
|
112
|
+
const callFrames = request.args.data.stackTrace.map(f => {
|
|
113
|
+
return {
|
|
114
|
+
scriptId: String(f.scriptId),
|
|
115
|
+
url: f.url,
|
|
116
|
+
lineNumber: f.lineNumber - 1,
|
|
117
|
+
columnNumber: f.columnNumber - 1,
|
|
118
|
+
functionName: f.functionName,
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
initiator.stack = { callFrames };
|
|
122
|
+
// Note: there is no `parent` to set ...
|
|
123
|
+
}
|
|
124
|
+
let resourceType = request.args.data.resourceType;
|
|
125
|
+
if (request.args.data.initiator?.fetchType === 'xmlhttprequest') {
|
|
126
|
+
// @ts-expect-error yes XHR is a valid ResourceType. TypeScript const enums are so unhelpful.
|
|
127
|
+
resourceType = 'XHR';
|
|
128
|
+
}
|
|
129
|
+
else if (request.args.data.initiator?.fetchType === 'fetch') {
|
|
130
|
+
// @ts-expect-error yes Fetch is a valid ResourceType. TypeScript const enums are so unhelpful.
|
|
131
|
+
resourceType = 'Fetch';
|
|
132
|
+
}
|
|
133
|
+
// TODO: set decodedBodyLength for data urls in Trace Engine.
|
|
134
|
+
let resourceSize = request.args.data.decodedBodyLength ?? 0;
|
|
135
|
+
if (url.protocol === 'data:' && resourceSize === 0) {
|
|
136
|
+
const needle = 'base64,';
|
|
137
|
+
const index = url.pathname.indexOf(needle);
|
|
138
|
+
if (index !== -1) {
|
|
139
|
+
resourceSize = atob(url.pathname.substring(index + needle.length)).length;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
rawRequest: request,
|
|
144
|
+
requestId: request.args.data.requestId,
|
|
145
|
+
connectionId: request.args.data.connectionId,
|
|
146
|
+
connectionReused: request.args.data.connectionReused,
|
|
147
|
+
url: request.args.data.url,
|
|
148
|
+
protocol: request.args.data.protocol,
|
|
149
|
+
parsedURL: createParsedUrl(url),
|
|
150
|
+
documentURL: request.args.data.requestingFrameUrl,
|
|
151
|
+
rendererStartTime: request.ts / 1000,
|
|
152
|
+
networkRequestTime,
|
|
153
|
+
responseHeadersEndTime: request.args.data.syntheticData.downloadStart / 1000,
|
|
154
|
+
networkEndTime: request.args.data.syntheticData.finishTime / 1000,
|
|
155
|
+
transferSize: request.args.data.encodedDataLength,
|
|
156
|
+
resourceSize,
|
|
157
|
+
fromDiskCache: request.args.data.syntheticData.isDiskCached,
|
|
158
|
+
fromMemoryCache: request.args.data.syntheticData.isMemoryCached,
|
|
159
|
+
isLinkPreload: request.args.data.isLinkPreload,
|
|
160
|
+
finished: request.args.data.finished,
|
|
161
|
+
failed: request.args.data.failed,
|
|
162
|
+
statusCode: request.args.data.statusCode,
|
|
163
|
+
initiator,
|
|
164
|
+
timing,
|
|
165
|
+
resourceType,
|
|
166
|
+
mimeType: request.args.data.mimeType,
|
|
167
|
+
priority: request.args.data.priority,
|
|
168
|
+
frameId: request.args.data.frame,
|
|
169
|
+
fromWorker,
|
|
170
|
+
// Set later.
|
|
171
|
+
redirects: undefined,
|
|
172
|
+
redirectSource: undefined,
|
|
173
|
+
redirectDestination: undefined,
|
|
174
|
+
initiatorRequest: undefined,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* @param request The request to find the initiator of
|
|
179
|
+
*/
|
|
180
|
+
function chooseInitiatorRequest(request, requestsByURL) {
|
|
181
|
+
if (request.redirectSource) {
|
|
182
|
+
return request.redirectSource;
|
|
183
|
+
}
|
|
184
|
+
const initiatorURL = Lantern.PageDependencyGraph.getNetworkInitiators(request)[0];
|
|
185
|
+
let candidates = requestsByURL.get(initiatorURL) || [];
|
|
186
|
+
// The (valid) initiator must come before the initiated request.
|
|
187
|
+
candidates = candidates.filter(c => {
|
|
188
|
+
return c.responseHeadersEndTime <= request.rendererStartTime && c.finished && !c.failed;
|
|
189
|
+
});
|
|
190
|
+
if (candidates.length > 1) {
|
|
191
|
+
// Disambiguate based on prefetch. Prefetch requests have type 'Other' and cannot
|
|
192
|
+
// initiate requests, so we drop them here.
|
|
193
|
+
const nonPrefetchCandidates = candidates.filter(cand => cand.resourceType !== Lantern.NetworkRequestTypes.Other);
|
|
194
|
+
if (nonPrefetchCandidates.length) {
|
|
195
|
+
candidates = nonPrefetchCandidates;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (candidates.length > 1) {
|
|
199
|
+
// Disambiguate based on frame. It's likely that the initiator comes from the same frame.
|
|
200
|
+
const sameFrameCandidates = candidates.filter(cand => cand.frameId === request.frameId);
|
|
201
|
+
if (sameFrameCandidates.length) {
|
|
202
|
+
candidates = sameFrameCandidates;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (candidates.length > 1 && request.initiator.type === 'parser') {
|
|
206
|
+
// Filter to just Documents when initiator type is parser.
|
|
207
|
+
const documentCandidates = candidates.filter(cand => cand.resourceType === Lantern.NetworkRequestTypes.Document);
|
|
208
|
+
if (documentCandidates.length) {
|
|
209
|
+
candidates = documentCandidates;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (candidates.length > 1) {
|
|
213
|
+
// If all real loads came from successful preloads (url preloaded and
|
|
214
|
+
// loads came from the cache), filter to link rel=preload request(s).
|
|
215
|
+
const linkPreloadCandidates = candidates.filter(c => c.isLinkPreload);
|
|
216
|
+
if (linkPreloadCandidates.length) {
|
|
217
|
+
const nonPreloadCandidates = candidates.filter(c => !c.isLinkPreload);
|
|
218
|
+
const allPreloaded = nonPreloadCandidates.every(c => c.fromDiskCache || c.fromMemoryCache);
|
|
219
|
+
if (nonPreloadCandidates.length && allPreloaded) {
|
|
220
|
+
candidates = linkPreloadCandidates;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Only return an initiator if the result is unambiguous.
|
|
225
|
+
return candidates.length === 1 ? candidates[0] : null;
|
|
226
|
+
}
|
|
227
|
+
function linkInitiators(lanternRequests) {
|
|
228
|
+
const requestsByURL = new Map();
|
|
229
|
+
for (const request of lanternRequests) {
|
|
230
|
+
const requests = requestsByURL.get(request.url) || [];
|
|
231
|
+
requests.push(request);
|
|
232
|
+
requestsByURL.set(request.url, requests);
|
|
233
|
+
}
|
|
234
|
+
for (const request of lanternRequests) {
|
|
235
|
+
const initiatorRequest = chooseInitiatorRequest(request, requestsByURL);
|
|
236
|
+
if (initiatorRequest) {
|
|
237
|
+
request.initiatorRequest = initiatorRequest;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function createNetworkRequests(trace, traceEngineData) {
|
|
242
|
+
const workerThreads = findWorkerThreads(trace);
|
|
243
|
+
const lanternRequests = [];
|
|
244
|
+
for (const request of traceEngineData.NetworkRequests.byTime) {
|
|
245
|
+
const lanternRequest = createLanternRequest(traceEngineData, workerThreads, request);
|
|
246
|
+
if (lanternRequest) {
|
|
247
|
+
lanternRequests.push(lanternRequest);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// TraceEngine consolidates all redirects into a single request object, but lantern needs
|
|
251
|
+
// an entry for each redirected request.
|
|
252
|
+
for (const request of [...lanternRequests]) {
|
|
253
|
+
if (!request.rawRequest) {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
const redirects = request.rawRequest.args.data.redirects;
|
|
257
|
+
if (!redirects.length) {
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
const requestChain = [];
|
|
261
|
+
for (const redirect of redirects) {
|
|
262
|
+
const redirectedRequest = structuredClone(request);
|
|
263
|
+
redirectedRequest.networkRequestTime = redirect.ts / 1000;
|
|
264
|
+
redirectedRequest.rendererStartTime = redirectedRequest.networkRequestTime;
|
|
265
|
+
redirectedRequest.networkEndTime = (redirect.ts + redirect.dur) / 1000;
|
|
266
|
+
redirectedRequest.responseHeadersEndTime = redirectedRequest.networkEndTime;
|
|
267
|
+
redirectedRequest.timing = {
|
|
268
|
+
requestTime: redirectedRequest.networkRequestTime / 1000,
|
|
269
|
+
receiveHeadersStart: redirectedRequest.responseHeadersEndTime,
|
|
270
|
+
receiveHeadersEnd: redirectedRequest.responseHeadersEndTime,
|
|
271
|
+
proxyStart: -1,
|
|
272
|
+
proxyEnd: -1,
|
|
273
|
+
dnsStart: -1,
|
|
274
|
+
dnsEnd: -1,
|
|
275
|
+
connectStart: -1,
|
|
276
|
+
connectEnd: -1,
|
|
277
|
+
sslStart: -1,
|
|
278
|
+
sslEnd: -1,
|
|
279
|
+
sendStart: -1,
|
|
280
|
+
sendEnd: -1,
|
|
281
|
+
workerStart: -1,
|
|
282
|
+
workerReady: -1,
|
|
283
|
+
workerFetchStart: -1,
|
|
284
|
+
workerRespondWithSettled: -1,
|
|
285
|
+
pushStart: -1,
|
|
286
|
+
pushEnd: -1,
|
|
287
|
+
};
|
|
288
|
+
redirectedRequest.url = redirect.url;
|
|
289
|
+
redirectedRequest.parsedURL = createParsedUrl(redirect.url);
|
|
290
|
+
// TODO: TraceEngine is not retaining the actual status code.
|
|
291
|
+
redirectedRequest.statusCode = 302;
|
|
292
|
+
redirectedRequest.resourceType = undefined;
|
|
293
|
+
// TODO: TraceEngine is not retaining transfer size of redirected request.
|
|
294
|
+
redirectedRequest.transferSize = 400;
|
|
295
|
+
requestChain.push(redirectedRequest);
|
|
296
|
+
lanternRequests.push(redirectedRequest);
|
|
297
|
+
}
|
|
298
|
+
requestChain.push(request);
|
|
299
|
+
for (let i = 0; i < requestChain.length; i++) {
|
|
300
|
+
const request = requestChain[i];
|
|
301
|
+
if (i > 0) {
|
|
302
|
+
request.redirectSource = requestChain[i - 1];
|
|
303
|
+
request.redirects = requestChain.slice(0, i);
|
|
304
|
+
}
|
|
305
|
+
if (i !== requestChain.length - 1) {
|
|
306
|
+
request.redirectDestination = requestChain[i + 1];
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// Apply the `:redirect` requestId convention: only redirects[0].requestId is the actual
|
|
310
|
+
// requestId, all the rest have n occurences of `:redirect` as a suffix.
|
|
311
|
+
for (let i = 1; i < requestChain.length; i++) {
|
|
312
|
+
requestChain[i].requestId = `${requestChain[i - 1].requestId}:redirect`;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
linkInitiators(lanternRequests);
|
|
316
|
+
// This would already be sorted by rendererStartTime, if not for the redirect unwrapping done
|
|
317
|
+
// above.
|
|
318
|
+
return lanternRequests.sort((a, b) => a.rendererStartTime - b.rendererStartTime);
|
|
319
|
+
}
|
|
320
|
+
function collectMainThreadEvents(trace, traceEngineData) {
|
|
321
|
+
const Meta = traceEngineData.Meta;
|
|
322
|
+
const mainFramePids = Meta.mainFrameNavigations.length ? new Set(Meta.mainFrameNavigations.map(nav => nav.pid)) :
|
|
323
|
+
Meta.topLevelRendererIds;
|
|
324
|
+
const rendererPidToTid = new Map();
|
|
325
|
+
for (const pid of mainFramePids) {
|
|
326
|
+
const threads = Meta.threadsInProcess.get(pid) ?? [];
|
|
327
|
+
let found = false;
|
|
328
|
+
for (const [tid, thread] of threads) {
|
|
329
|
+
if (thread.args.name === 'CrRendererMain') {
|
|
330
|
+
rendererPidToTid.set(pid, tid);
|
|
331
|
+
found = true;
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
if (found) {
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
// `CrRendererMain` can be missing if chrome is launched with the `--single-process` flag.
|
|
339
|
+
// In this case, page tasks will be run in the browser thread.
|
|
340
|
+
for (const [tid, thread] of threads) {
|
|
341
|
+
if (thread.args.name === 'CrBrowserMain') {
|
|
342
|
+
rendererPidToTid.set(pid, tid);
|
|
343
|
+
found = true;
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return trace.traceEvents.filter(e => rendererPidToTid.get(e.pid) === e.tid);
|
|
349
|
+
}
|
|
350
|
+
function createGraph(requests, trace, traceEngineData, url) {
|
|
351
|
+
const mainThreadEvents = collectMainThreadEvents(trace, traceEngineData);
|
|
352
|
+
// url defines the initial request that the Lantern graph starts at (the root node) and the
|
|
353
|
+
// main document request. These are equal if there are no redirects.
|
|
354
|
+
if (!url) {
|
|
355
|
+
url = {
|
|
356
|
+
requestedUrl: requests[0].url,
|
|
357
|
+
mainDocumentUrl: '',
|
|
358
|
+
};
|
|
359
|
+
let request = requests[0];
|
|
360
|
+
while (request.redirectDestination) {
|
|
361
|
+
request = request.redirectDestination;
|
|
362
|
+
}
|
|
363
|
+
url.mainDocumentUrl = request.url;
|
|
364
|
+
}
|
|
365
|
+
return Lantern.PageDependencyGraph.createGraph(mainThreadEvents, requests, url);
|
|
366
|
+
}
|
|
367
|
+
export { createProcessedNavigation, createNetworkRequests, createGraph, };
|
|
368
|
+
//# sourceMappingURL=LanternComputationData.js.map
|