-
Notifications
You must be signed in to change notification settings - Fork 4
/
purrformance.js
125 lines (108 loc) · 3.58 KB
/
purrformance.js
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
122
123
124
125
/**
* Checks if a method needs to be vendor prefixed.
*
* @param {Object} where Object where we check if prop exists.
* @param {String} prop Name of the property to check.
* @returns {String|Undefined} Correct name of the property to use.
* @private
*/
export function prefix(where = {}, prop) {
if (prop in where) return prop;
const prefixes = ['webkit', 'ms', 'moz'];
for (let i = 0; i < prefixes.length; i++) {
const vendor = prefixes[i];
const prefixed = vendor + prop.slice(0, 1).toUpperCase() + prop.slice(1);
if (prefixed in where) return prefixed;
}
}
/**
* In order to correctly calculate the when a resource in the ResourceAPI
* was made we need to know when the high resolution timer started at 0.
* New browsers support the `timeOrigin` property that contains the EPOCH
* of when the timer started. For older browsers we default to the first
* known timing event, `navigationStart`.
*
* @returns {Number} Epoch of when the high resolution timers were inititlized
* @public
*/
export function timeOrigin() {
const origin = purrformance('timeOrigin');
return origin || (purrformance('timing') || {}).navigationStart;
}
/**
* Find an resource entry that matches a given Regular Expression for the entry
* name.
*
* @param {Array} resources All resources.
* @param {RegExp} regexp The regexp that needs to match.
* @returns {Object|Undefined} The entry that is found.
*/
export function find(resources = [], regexp) {
for (let i = 0; i < resources.length; i++) {
const entry = resources[i];
if (entry && entry.name && regexp.test(entry.name)) {
return entry;
}
}
}
/**
* Get all entries that happend during the navigation cycle.
*
* @param {Object} between Start and end range where the request is made.
* @returns {Resources} Resources that were gathered.
* @public
*/
export function entries({ start, end }, resources = purrformance('getEntriesByType', 'resource')) {
const origin = timeOrigin();
const contains = [
'Start', // transform keys like: responseStart, redirectStart etc
'Time', // transform the startTime
'End' // and all responseEnd
];
return (resources || []).sort((a, b) => {
if (a.fetchStart !== b.fetchStart) return a.fetchStart - b.fetchStart;
return (a.responseStart || a.responseEnd) - (b.responseStart || b.responseEnd);
}).map(entry => {
const data = {};
for (let key in entry) {
data[key] = entry[key];
//
// Normalize the high precision timers to EPOCH values as that is what
// the navigation timing is using.
//
if (contains.some(check => !!~key.indexOf(check))) {
data[key] = origin + data[key];
}
}
return data;
}).filter(({ startTime }) => {
return startTime >= start && startTime <= end;
});
}
/**
* Small helper function that allows us to safely interact with the
* performance API that is exposed in browsers.
*
* @param {String} method Name of the method we want to invoke.
* @param {Arguments} args Rest of the arguments that should be applied.
* @returns {Mixed} What ever the API returns.
* @private
*/
export default function purrformance(method, ...args) {
const perf = global[prefix(global, 'performance')];
if (perf) {
const name = prefix(perf, method);
if (typeof perf[name] === 'function') {
return perf[name](...args);
} else {
return perf[name];
}
}
}
//
// Expose all methods on the purrformance method as well for easier exports.
//
purrformance.find = find;
purrformance.prefix = prefix;
purrformance.entries = entries;
purrformance.timeOrigin = timeOrigin;