-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathperformance.ts
More file actions
121 lines (100 loc) · 3.89 KB
/
Copy pathperformance.ts
File metadata and controls
121 lines (100 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import { floor } from "./math";
import * as PROPS from "./minification";
import scriptStartTime from "./start-marker";
// If the various performance APIs aren't available, we export an empty object to
// prevent having to make regular typeof checks.
export const performance = window.performance || {};
export const timing = performance.timing || {
activationStart: 0,
// If performance.timing isn't available, we attempt to polyfill the navigationStart value.
// Our first attempt is from LUX.ns, which is the time that the snippet execution began. If this
// is not available, we fall back to the time that the current script execution began.
navigationStart: window.LUX?.ns || scriptStartTime,
};
// Older PerformanceTiming implementations allow for arbitrary keys to exist on the timing object
export type PerfTimingKey = keyof Omit<PerformanceTiming, "toJSON">;
export function navigationType(): number | undefined {
if (performance.navigation && typeof performance.navigation.type !== "undefined") {
return performance.navigation.type;
}
return undefined;
}
/**
* Returns the delivery type for the current document. To differentiate between the valid empty
* string value and browsers that don't support PerformanceResourceTiming.deliveryType, we convert
* the empty string value to "(empty string)". Browsers that don't support deliveryType will return
* null. Despite straying from the spec, this allows us to differentiate between the two cases.
*
* @see https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-deliverytype
*/
export function deliveryType(): string | undefined {
const navEntry = getNavigationEntry();
if ("deliveryType" in navEntry) {
return navEntry.deliveryType || "(empty string)";
}
return undefined;
}
export type PolyfilledNavigationTiming = Partial<PerformanceNavigationTiming> & {
[key: string]: number | string;
navigationStart: number;
activationStart: number;
startTime: number;
type: PerformanceNavigationTiming["type"];
};
export function getNavigationEntry(): PolyfilledNavigationTiming {
const navEntries = getEntriesByType("navigation") as PerformanceNavigationTiming[];
if (navEntries[PROPS.length]) {
const nativeEntry = navEntries.pop()!.toJSON();
const entry = {
navigationStart: 0,
activationStart: 0,
} as PolyfilledNavigationTiming;
for (const key in nativeEntry) {
entry[key] = nativeEntry[key];
}
return entry;
}
const navType = navigationType();
const entry: PolyfilledNavigationTiming = {
navigationStart: 0,
activationStart: 0,
startTime: 0,
type: navType == 2 ? "back_forward" : navType === 1 ? "reload" : "navigate",
};
if (__ENABLE_POLYFILLS) {
for (const key in timing) {
if (typeof timing[key as PerfTimingKey] === "number" && key !== PROPS.navigationStart) {
entry[key] = floor(timing[key as PerfTimingKey] - timing[PROPS.navigationStart]);
}
}
}
return entry;
}
/**
* Simple wrapper around performance.getEntriesByType to provide fallbacks for
* legacy browsers, and work around edge cases where undefined is returned instead
* of an empty PerformanceEntryList.
*/
export function getEntriesByType(type: string): PerformanceEntryList {
if (typeof performance.getEntriesByType === "function") {
const entries = performance.getEntriesByType(type);
if (entries && entries[PROPS.length]) {
return entries;
}
}
return [];
}
/**
* Simple wrapper around performance.getEntriesByName to provide fallbacks for
* legacy browsers, and work around edge cases where undefined is returned instead
* of an empty PerformanceEntryList.
*/
export function getEntriesByName(type: string): PerformanceEntryList {
if (typeof performance.getEntriesByName === "function") {
const entries = performance.getEntriesByName(type);
if (entries && entries[PROPS.length]) {
return entries;
}
}
return [];
}