resourcetiming-compression
Advanced tools
Comparing version 1.2.4 to 1.3.0
@@ -6,3 +6,3 @@ { | ||
"author": "Nic Jansma", | ||
"version": "1.2.4", | ||
"version": "1.3.0", | ||
"repository": { | ||
@@ -9,0 +9,0 @@ "type": "git", |
# resourcetiming-compression.js | ||
v1.2.4 | ||
v1.3.0 | ||
@@ -133,11 +133,12 @@ [http://nicj.net](http://nicj.net) | ||
* `e`: `encodedBodySize` is the [Base36](https://en.wikipedia.org/wiki/Base36) decoded value (`encodedBodySize = parseInt(e, 36)`) | ||
* `e`: | ||
* If a [Base36](https://en.wikipedia.org/wiki/Base36) encoded number, `e` is the value of `encodedBodySize` (`encodedBodySize = parseInt(e, 36)`) | ||
* If missing, `encodedBodySize` was `0` (no body, just headers) | ||
* `t`: | ||
* If a Base36 encoded number, `t` is the `transferSize` increase in size over `encodedBodySize` (`transferSize = parseInt(e, 36) + parseInt(t, 36)`) | ||
* If the value of `"_"`, `transferSize` is `0` | ||
* If missing, `transferSize` was either `0` or `undefined` | ||
* If a [Base36](https://en.wikipedia.org/wiki/Base36) encoded number, `t` is the `transferSize` increase in size over `encodedBodySize` (`transferSize = parseInt(e, 36) + parseInt(t, 36)`) | ||
* If the value of `"_"`, `transferSize` is `0` (cached) | ||
* If missing, `transferSize` was either `0` (cached) or `undefined` (unknown) | ||
* `d`: | ||
* If a Base36 encoded number, `d` is the `decodedBodySize` increase in size over `encodedBodySize` (`decodedBodySize = parseInt(e, 36) + parseInt(d, 36)`) | ||
* If `0`, `encodedBodySize` is `0` | ||
* If missing, `encodedBodySize` was either `0` or `undefined` | ||
* If a [Base36](https://en.wikipedia.org/wiki/Base36) encoded number, `d` is the `decodedBodySize` increase in size over `encodedBodySize` (`decodedBodySize = parseInt(e, 36) + parseInt(d, 36)`) | ||
* If missing, `decodedBodySize` was equal to `encodedBodySize` (the request was not encoded) | ||
@@ -257,2 +258,5 @@ Taking the following example: | ||
* v1.3.0 - 2020-0709 | ||
* Support for namespaced data | ||
* Support for Service Worker Start timing | ||
* v1.2.4 - 2019-07-16 | ||
@@ -259,0 +263,0 @@ * Optional `skipDimensions` for `getResourceTiming()` and `compressResourceTiming()` |
@@ -123,2 +123,7 @@ // | ||
// Namespaced data | ||
ResourceTimingCompression.SPECIAL_DATA_NAMESPACED_TYPE = "5"; | ||
// Service worker type | ||
ResourceTimingCompression.SPECIAL_DATA_SERVICE_WORKER_TYPE = "6"; | ||
/** | ||
@@ -167,2 +172,16 @@ * These are the only `rel` types that might be reference-able from | ||
/** | ||
* Rounds up the timing value | ||
* | ||
* @param {number} time Time | ||
* @returns {number} Rounded up timestamp | ||
*/ | ||
ResourceTimingCompression.roundUpTiming = function(time) { | ||
if (typeof time !== "number") { | ||
time = 0; | ||
} | ||
return Math.ceil(time ? time : 0); | ||
}; | ||
/** | ||
* Converts entries to a Trie: | ||
@@ -1038,4 +1057,4 @@ * http://en.wikipedia.org/wiki/Trie | ||
var lookupKey = ResourceTimingCompression.identifyServerTimingEntry( | ||
serverTiming.indexed[entry.name].index, | ||
serverTiming.indexed[entry.name].descriptions[entry.description]); | ||
serverTiming.indexed[entry.name].index, | ||
serverTiming.indexed[entry.name].descriptions[entry.description]); | ||
stData += (entryIndex > 0 ? "," : "") + duration + lookupKey; | ||
@@ -1046,2 +1065,20 @@ return stData; | ||
if (e.workerStart && typeof e.workerStart === "number" && e.workerStart !== 0) { | ||
// Has Service worker timing data that's non zero. Resource request not intercepted | ||
// by Service worker always return 0 as per MDN | ||
// https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/workerStart | ||
// Lets round it and offset from startTime. We are going to round up the workerStart | ||
// timing specifically. We are doing this to avoid the issue where the case of Service | ||
// worker timestamps being sub-milliseconds more than startTime getting incorrectly | ||
// marked as 0ms (due to round down). | ||
// We feel marking such cases as 0ms, after rounding down, for workerStart would present | ||
// more incorrect indication to the user. Hence the decision to round up. | ||
var wsRoudedUp = ResourceTimingCompression.roundUpTiming(e.workerStart); | ||
var workerStartOffset = this.trimTiming(wsRoudedUp, e.startTime); | ||
data += ResourceTimingCompression.SPECIAL_DATA_PREFIX | ||
+ ResourceTimingCompression.SPECIAL_DATA_SERVICE_WORKER_TYPE | ||
+ this.toBase36(workerStartOffset); | ||
} | ||
finalUrl = url = this.trimUrl(e.name, this.trimUrls); | ||
@@ -1052,19 +1089,42 @@ if (ResourceTimingCompression.HOSTNAMES_REVERSED) { | ||
// if this entry already exists, add a pipe as a separator | ||
if (results[finalUrl] !== undefined) { | ||
results[finalUrl] += "|" + data; | ||
} else if (visibleEntries[url] !== undefined) { | ||
// For the first time we see this URL, add resource dimensions if we have them | ||
// We use * as an additional separator to indicate it is not a new resource entry | ||
// The following characters will not be URL encoded: | ||
// *!-.()~_ but - and . are special to number representation so we don't use them | ||
// After the *, the type of special data (ResourceTiming = 0) is added | ||
results[finalUrl] = | ||
ResourceTimingCompression.SPECIAL_DATA_PREFIX + | ||
ResourceTimingCompression.SPECIAL_DATA_DIMENSION_TYPE + | ||
visibleEntries[url].map(this.toBase36).join(",").replace(/,+$/, "") | ||
+ "|" | ||
+ data; | ||
if (!e.hasOwnProperty("_data")) { | ||
// if this entry already exists, add a pipe as a separator | ||
if (results[finalUrl] !== undefined) { | ||
results[finalUrl] += "|" + data; | ||
} else if (visibleEntries[url] !== undefined) { | ||
// For the first time we see this URL, add resource dimensions if we have them | ||
// We use * as an additional separator to indicate it is not a new resource entry | ||
// The following characters will not be URL encoded: | ||
// *!-.()~_ but - and . are special to number representation so we don't use them | ||
// After the *, the type of special data (ResourceTiming = 0) is added | ||
results[finalUrl] = | ||
ResourceTimingCompression.SPECIAL_DATA_PREFIX + | ||
ResourceTimingCompression.SPECIAL_DATA_DIMENSION_TYPE + | ||
visibleEntries[url].map(this.toBase36).join(",").replace(/,+$/, "") | ||
+ "|" | ||
+ data; | ||
} else { | ||
results[finalUrl] = data; | ||
} | ||
} else { | ||
results[finalUrl] = data; | ||
var namespacedData = ""; | ||
for (var key in e._data) { | ||
if (e._data.hasOwnProperty(key)) { | ||
namespacedData += ResourceTimingCompression.SPECIAL_DATA_PREFIX | ||
+ ResourceTimingCompression.SPECIAL_DATA_NAMESPACED_TYPE | ||
+ key | ||
+ ":" | ||
+ e._data[key]; | ||
} | ||
} | ||
if (typeof results[url] === "undefined") { | ||
// we haven't seen this resource yet, treat this potential stub as the canonical version | ||
results[url] = data + namespacedData; | ||
} else { | ||
// we have seen this resource before | ||
// forget the timing data of `e`, just supplement the previous entry with the new `namespacedData` | ||
results[url] += namespacedData; | ||
} | ||
} | ||
@@ -1175,6 +1235,6 @@ } | ||
/* eslint no-inline-comments:0 */ | ||
/* eslint no-inline-comments:0 */ | ||
array.push(sorted.length === 1 && sorted[0] === "" ? | ||
name : // special case: no non-empty descriptions | ||
[name].concat(sorted)); | ||
name : // special case: no non-empty descriptions | ||
[name].concat(sorted)); | ||
return array; | ||
@@ -1181,0 +1241,0 @@ }, []); |
@@ -186,2 +186,5 @@ // | ||
// Service worker type | ||
ResourceTimingDecompression.SPECIAL_DATA_SERVICE_WORKER_TYPE = "6"; | ||
// Regular Expression to parse a URL | ||
@@ -848,2 +851,20 @@ ResourceTimingDecompression.HOSTNAME_REGEX = /^(https?:\/\/)([^\/]+)(.*)/; | ||
/** | ||
* Decompresses service worker data | ||
* | ||
* @param {string} compressed Compressed string | ||
* @param {ResourceTiming} resource ResourceTiming object | ||
* @returns {ResourceTiming} ResourceTiming object with decompressed special data | ||
*/ | ||
ResourceTimingDecompression.decompressServiceWorkerData = function(compressed, resource) { | ||
resource = resource || {}; | ||
if (typeof compressed === "string") { | ||
var offset = parseInt(compressed, 36); | ||
resource.workerStart = resource.startTime + offset; | ||
} | ||
return resource; | ||
}; | ||
/** | ||
* Decompresses special data such as resource size or script type into the given resource. | ||
@@ -877,2 +898,4 @@ * | ||
resource = this.decompressNamespacedData(compressed, resource); | ||
} else if (dataType === ResourceTimingDecompression.SPECIAL_DATA_SERVICE_WORKER_TYPE) { | ||
resource = this.decompressServiceWorkerData(compressed, resource); | ||
} | ||
@@ -879,0 +902,0 @@ |
103515
2134
325