mirror of
https://github.com/nodejs/node.git
synced 2025-05-03 02:06:12 +00:00

PR-URL: https://github.com/nodejs/node/pull/49837 Reviewed-By: Stephen Belanger <admin@stephenbelanger.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
236 lines
7.3 KiB
JavaScript
236 lines
7.3 KiB
JavaScript
'use strict';
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming
|
|
|
|
const {
|
|
ObjectDefineProperties,
|
|
Symbol,
|
|
SymbolToStringTag,
|
|
} = primordials;
|
|
const {
|
|
codes: {
|
|
ERR_ILLEGAL_CONSTRUCTOR,
|
|
},
|
|
} = require('internal/errors');
|
|
const { PerformanceEntry, kSkipThrow } = require('internal/perf/performance_entry');
|
|
const assert = require('internal/assert');
|
|
const { enqueue, bufferResourceTiming } = require('internal/perf/observe');
|
|
const { validateInternalField } = require('internal/validators');
|
|
const { kEnumerableProperty } = require('internal/util');
|
|
|
|
const kCacheMode = Symbol('kCacheMode');
|
|
const kRequestedUrl = Symbol('kRequestedUrl');
|
|
const kTimingInfo = Symbol('kTimingInfo');
|
|
const kInitiatorType = Symbol('kInitiatorType');
|
|
|
|
class PerformanceResourceTiming extends PerformanceEntry {
|
|
constructor(skipThrowSymbol = undefined, name = undefined, type = undefined) {
|
|
if (skipThrowSymbol !== kSkipThrow) {
|
|
throw new ERR_ILLEGAL_CONSTRUCTOR();
|
|
}
|
|
|
|
super(skipThrowSymbol, name, type);
|
|
}
|
|
|
|
get name() {
|
|
validateInternalField(this, kRequestedUrl, 'PerformanceResourceTiming');
|
|
return this[kRequestedUrl];
|
|
}
|
|
|
|
get startTime() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo].startTime;
|
|
}
|
|
|
|
get duration() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo].endTime - this[kTimingInfo].startTime;
|
|
}
|
|
|
|
get initiatorType() {
|
|
validateInternalField(this, kInitiatorType, 'PerformanceResourceTiming');
|
|
return this[kInitiatorType];
|
|
}
|
|
|
|
get workerStart() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo].finalServiceWorkerStartTime;
|
|
}
|
|
|
|
get redirectStart() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo].redirectStartTime;
|
|
}
|
|
|
|
get redirectEnd() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo].redirectEndTime;
|
|
}
|
|
|
|
get fetchStart() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo].postRedirectStartTime;
|
|
}
|
|
|
|
get domainLookupStart() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo].finalConnectionTimingInfo?.domainLookupStartTime;
|
|
}
|
|
|
|
get domainLookupEnd() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo].finalConnectionTimingInfo?.domainLookupEndTime;
|
|
}
|
|
|
|
get connectStart() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo].finalConnectionTimingInfo?.connectionStartTime;
|
|
}
|
|
|
|
get connectEnd() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo].finalConnectionTimingInfo?.connectionEndTime;
|
|
}
|
|
|
|
get secureConnectionStart() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo]
|
|
.finalConnectionTimingInfo?.secureConnectionStartTime;
|
|
}
|
|
|
|
get nextHopProtocol() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo]
|
|
.finalConnectionTimingInfo?.ALPNNegotiatedProtocol;
|
|
}
|
|
|
|
get requestStart() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo].finalNetworkRequestStartTime;
|
|
}
|
|
|
|
get responseStart() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo].finalNetworkResponseStartTime;
|
|
}
|
|
|
|
get responseEnd() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo].endTime;
|
|
}
|
|
|
|
get encodedBodySize() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo].encodedBodySize;
|
|
}
|
|
|
|
get decodedBodySize() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
return this[kTimingInfo].decodedBodySize;
|
|
}
|
|
|
|
get transferSize() {
|
|
validateInternalField(this, kTimingInfo, 'PerformanceResourceTiming');
|
|
if (this[kCacheMode] === 'local') return 0;
|
|
if (this[kCacheMode] === 'validated') return 300;
|
|
|
|
return this[kTimingInfo].encodedBodySize + 300;
|
|
}
|
|
|
|
toJSON() {
|
|
validateInternalField(this, kInitiatorType, 'PerformanceResourceTiming');
|
|
return {
|
|
name: this.name,
|
|
entryType: this.entryType,
|
|
startTime: this.startTime,
|
|
duration: this.duration,
|
|
initiatorType: this[kInitiatorType],
|
|
nextHopProtocol: this.nextHopProtocol,
|
|
workerStart: this.workerStart,
|
|
redirectStart: this.redirectStart,
|
|
redirectEnd: this.redirectEnd,
|
|
fetchStart: this.fetchStart,
|
|
domainLookupStart: this.domainLookupStart,
|
|
domainLookupEnd: this.domainLookupEnd,
|
|
connectStart: this.connectStart,
|
|
connectEnd: this.connectEnd,
|
|
secureConnectionStart: this.secureConnectionStart,
|
|
requestStart: this.requestStart,
|
|
responseStart: this.responseStart,
|
|
responseEnd: this.responseEnd,
|
|
transferSize: this.transferSize,
|
|
encodedBodySize: this.encodedBodySize,
|
|
decodedBodySize: this.decodedBodySize,
|
|
};
|
|
}
|
|
}
|
|
|
|
ObjectDefineProperties(PerformanceResourceTiming.prototype, {
|
|
initiatorType: kEnumerableProperty,
|
|
nextHopProtocol: kEnumerableProperty,
|
|
workerStart: kEnumerableProperty,
|
|
redirectStart: kEnumerableProperty,
|
|
redirectEnd: kEnumerableProperty,
|
|
fetchStart: kEnumerableProperty,
|
|
domainLookupStart: kEnumerableProperty,
|
|
domainLookupEnd: kEnumerableProperty,
|
|
connectStart: kEnumerableProperty,
|
|
connectEnd: kEnumerableProperty,
|
|
secureConnectionStart: kEnumerableProperty,
|
|
requestStart: kEnumerableProperty,
|
|
responseStart: kEnumerableProperty,
|
|
responseEnd: kEnumerableProperty,
|
|
transferSize: kEnumerableProperty,
|
|
encodedBodySize: kEnumerableProperty,
|
|
decodedBodySize: kEnumerableProperty,
|
|
toJSON: kEnumerableProperty,
|
|
[SymbolToStringTag]: {
|
|
__proto__: null,
|
|
configurable: true,
|
|
value: 'PerformanceResourceTiming',
|
|
},
|
|
});
|
|
|
|
function createPerformanceResourceTiming(requestedUrl, initiatorType, timingInfo, cacheMode = '') {
|
|
const resourceTiming = new PerformanceResourceTiming(kSkipThrow, requestedUrl, 'resource');
|
|
|
|
resourceTiming[kInitiatorType] = initiatorType;
|
|
resourceTiming[kRequestedUrl] = requestedUrl;
|
|
// https://fetch.spec.whatwg.org/#fetch-timing-info
|
|
// This class is using timingInfo assuming it's already validated.
|
|
// The spec doesn't say to validate it in the class construction.
|
|
resourceTiming[kTimingInfo] = timingInfo;
|
|
resourceTiming[kCacheMode] = cacheMode;
|
|
|
|
return resourceTiming;
|
|
}
|
|
|
|
// https://w3c.github.io/resource-timing/#dfn-mark-resource-timing
|
|
function markResourceTiming(
|
|
timingInfo,
|
|
requestedUrl,
|
|
initiatorType,
|
|
global,
|
|
cacheMode,
|
|
) {
|
|
// https://w3c.github.io/resource-timing/#dfn-setup-the-resource-timing-entry
|
|
assert(
|
|
cacheMode === '' || cacheMode === 'local',
|
|
'cache must be an empty string or \'local\'',
|
|
);
|
|
const resource = createPerformanceResourceTiming(
|
|
requestedUrl,
|
|
initiatorType,
|
|
timingInfo,
|
|
cacheMode,
|
|
);
|
|
|
|
enqueue(resource);
|
|
bufferResourceTiming(resource);
|
|
return resource;
|
|
}
|
|
|
|
module.exports = {
|
|
PerformanceResourceTiming,
|
|
markResourceTiming,
|
|
};
|