nstdlib-nightly
Version:
Node.js standard library converted to runtime-agnostic ES modules.
269 lines (231 loc) • 8.31 kB
JavaScript
// Source: https://github.com/nodejs/node/blob/65eff1eb/lib/internal/perf/resource_timing.js
import { codes as __codes__ } from "nstdlib/lib/internal/errors";
import {
PerformanceEntry,
kSkipThrow,
} from "nstdlib/lib/internal/perf/performance_entry";
import * as assert from "nstdlib/lib/internal/assert";
import {
enqueue,
bufferResourceTiming,
} from "nstdlib/lib/internal/perf/observe";
import { validateInternalField } from "nstdlib/lib/internal/validators";
import { kEnumerableProperty } from "nstdlib/lib/internal/util";
// https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming
const { ERR_ILLEGAL_CONSTRUCTOR } = __codes__;
const kCacheMode = Symbol("kCacheMode");
const kRequestedUrl = Symbol("kRequestedUrl");
const kTimingInfo = Symbol("kTimingInfo");
const kInitiatorType = Symbol("kInitiatorType");
const kDeliveryType = Symbol("kDeliveryType");
const kResponseStatus = Symbol("kResponseStatus");
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;
}
get deliveryType() {
validateInternalField(this, kTimingInfo, "PerformanceResourceTiming");
return this[kDeliveryType];
}
get responseStatus() {
validateInternalField(this, kTimingInfo, "PerformanceResourceTiming");
return this[kResponseStatus];
}
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,
deliveryType: this.deliveryType,
responseStatus: this.responseStatus,
};
}
}
Object.defineProperties(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,
deliveryType: kEnumerableProperty,
responseStatus: kEnumerableProperty,
toJSON: kEnumerableProperty,
[Symbol.toStringTag]: {
__proto__: null,
configurable: true,
value: "PerformanceResourceTiming",
},
});
function createPerformanceResourceTiming(
requestedUrl,
initiatorType,
timingInfo,
cacheMode = "",
bodyInfo,
responseStatus,
deliveryType,
) {
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;
resourceTiming[kDeliveryType] = deliveryType;
resourceTiming[kResponseStatus] = responseStatus;
return resourceTiming;
}
// https://w3c.github.io/resource-timing/#dfn-mark-resource-timing
function markResourceTiming(
timingInfo,
requestedUrl,
initiatorType,
global,
cacheMode,
bodyInfo,
responseStatus,
deliveryType = "",
) {
// 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,
bodyInfo,
responseStatus,
deliveryType,
);
enqueue(resource);
bufferResourceTiming(resource);
return resource;
}
export { PerformanceResourceTiming };
export { markResourceTiming };