perf_hooks: add deliveryType and responseStatus fields

PR-URL: https://github.com/nodejs/node/pull/51589
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
This commit is contained in:
Khafra 2024-05-12 14:02:48 -04:00 committed by GitHub
parent 7b2dc79437
commit e2697c1a64
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 96 additions and 24 deletions

View File

@ -246,12 +246,16 @@ and can be queried with `performance.getEntries`,
observation is performed, the entries should be cleared from the global
Performance Timeline manually with `performance.clearMarks`.
### `performance.markResourceTiming(timingInfo, requestedUrl, initiatorType, global, cacheMode)`
### `performance.markResourceTiming(timingInfo, requestedUrl, initiatorType, global, cacheMode, bodyInfo, responseStatus[, deliveryType])`
<!-- YAML
added:
- v18.2.0
- v16.17.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/51589
description: Added bodyInfo, responseStatus, and deliveryType arguments.
-->
* `timingInfo` {Object} [Fetch Timing Info][]
@ -259,6 +263,9 @@ added:
* `initiatorType` {string} The initiator name, e.g: 'fetch'
* `global` {Object}
* `cacheMode` {string} The cache mode must be an empty string ('') or 'local'
* `bodyInfo` {Object} [Fetch Response Body Info][]
* `responseStatus` {number} The response's status code
* `deliveryType` {string} The delivery type. **Default:** `''`.
_This property is an extension by Node.js. It is not available in Web browsers._
@ -1911,6 +1918,7 @@ dns.promises.resolve('localhost');
```
[Async Hooks]: async_hooks.md
[Fetch Response Body Info]: https://fetch.spec.whatwg.org/#response-body-info
[Fetch Timing Info]: https://fetch.spec.whatwg.org/#fetch-timing-info
[High Resolution Time]: https://www.w3.org/TR/hr-time-2
[Performance Timeline]: https://w3c.github.io/performance-timeline/

View File

@ -21,6 +21,8 @@ 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) {
@ -136,6 +138,16 @@ class PerformanceResourceTiming extends PerformanceEntry {
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 {
@ -160,6 +172,8 @@ class PerformanceResourceTiming extends PerformanceEntry {
transferSize: this.transferSize,
encodedBodySize: this.encodedBodySize,
decodedBodySize: this.decodedBodySize,
deliveryType: this.deliveryType,
responseStatus: this.responseStatus,
};
}
}
@ -182,6 +196,8 @@ ObjectDefineProperties(PerformanceResourceTiming.prototype, {
transferSize: kEnumerableProperty,
encodedBodySize: kEnumerableProperty,
decodedBodySize: kEnumerableProperty,
deliveryType: kEnumerableProperty,
responseStatus: kEnumerableProperty,
toJSON: kEnumerableProperty,
[SymbolToStringTag]: {
__proto__: null,
@ -190,7 +206,15 @@ ObjectDefineProperties(PerformanceResourceTiming.prototype, {
},
});
function createPerformanceResourceTiming(requestedUrl, initiatorType, timingInfo, cacheMode = '') {
function createPerformanceResourceTiming(
requestedUrl,
initiatorType,
timingInfo,
cacheMode = '',
bodyInfo,
responseStatus,
deliveryType,
) {
const resourceTiming = new PerformanceResourceTiming(kSkipThrow, requestedUrl, 'resource');
resourceTiming[kInitiatorType] = initiatorType;
@ -200,6 +224,8 @@ function createPerformanceResourceTiming(requestedUrl, initiatorType, timingInfo
// 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;
}
@ -211,6 +237,9 @@ function markResourceTiming(
initiatorType,
global,
cacheMode,
bodyInfo,
responseStatus,
deliveryType = '',
) {
// https://w3c.github.io/resource-timing/#dfn-setup-the-resource-timing-entry
assert(
@ -222,6 +251,9 @@ function markResourceTiming(
initiatorType,
timingInfo,
cacheMode,
bodyInfo,
responseStatus,
deliveryType,
);
enqueue(resource);

View File

@ -86,6 +86,9 @@ function createTimingInfo({
initiatorType,
customGlobal,
cacheMode,
{},
200,
'',
);
assert(resource instanceof PerformanceEntry);
@ -128,6 +131,9 @@ function createTimingInfo({
initiatorType,
customGlobal,
cacheMode,
{},
200,
'',
);
assert(resource instanceof PerformanceEntry);
@ -155,6 +161,8 @@ function createTimingInfo({
assert.strictEqual(resource.encodedBodySize, 0);
assert.strictEqual(resource.decodedBodySize, 0);
assert.strictEqual(resource.transferSize, 0);
assert.strictEqual(resource.deliveryType, '');
assert.strictEqual(resource.responseStatus, 200);
assert.deepStrictEqual(resource.toJSON(), {
name: requestedUrl,
entryType: 'resource',
@ -177,6 +185,8 @@ function createTimingInfo({
transferSize: 0,
encodedBodySize: 0,
decodedBodySize: 0,
responseStatus: 200,
deliveryType: '',
});
assert.strictEqual(util.inspect(performance.getEntries()), `[
PerformanceResourceTiming {
@ -200,7 +210,9 @@ function createTimingInfo({
responseEnd: 0,
transferSize: 0,
encodedBodySize: 0,
decodedBodySize: 0
decodedBodySize: 0,
deliveryType: '',
responseStatus: 200
}
]`);
assert.strictEqual(util.inspect(resource), `PerformanceResourceTiming {
@ -224,7 +236,9 @@ function createTimingInfo({
responseEnd: 0,
transferSize: 0,
encodedBodySize: 0,
decodedBodySize: 0
decodedBodySize: 0,
deliveryType: '',
responseStatus: 200
}`);
assert(resource instanceof PerformanceEntry);
@ -252,6 +266,9 @@ function createTimingInfo({
initiatorType,
customGlobal,
cacheMode,
{},
200,
'',
);
assert(resource instanceof PerformanceEntry);
@ -307,6 +324,9 @@ function createTimingInfo({
initiatorType,
customGlobal,
cacheMode,
{},
200,
''
);
assert(resource instanceof PerformanceEntry);

View File

@ -34,10 +34,19 @@ const cacheMode = '';
async function main() {
performance.setResourceTimingBufferSize(1);
performance.markResourceTiming(createTimingInfo(1), requestedUrl, initiatorType, globalThis, cacheMode);
const args = [
requestedUrl,
initiatorType,
globalThis,
cacheMode,
{}, // body info
200,
'',
];
performance.markResourceTiming(createTimingInfo(1), ...args);
// Trigger a resourcetimingbufferfull event.
performance.markResourceTiming(createTimingInfo(2), requestedUrl, initiatorType, globalThis, cacheMode);
performance.markResourceTiming(createTimingInfo(3), requestedUrl, initiatorType, globalThis, cacheMode);
performance.markResourceTiming(createTimingInfo(2), ...args);
performance.markResourceTiming(createTimingInfo(3), ...args);
assert.strictEqual(performance.getEntriesByType('resource').length, 1);
// Clear resource timings on resourcetimingbufferfull event.
@ -65,10 +74,10 @@ async function main() {
performance.clearResourceTimings();
performance.setResourceTimingBufferSize(1);
performance.markResourceTiming(createTimingInfo(4), requestedUrl, initiatorType, globalThis, cacheMode);
performance.markResourceTiming(createTimingInfo(4), ...args);
// Trigger a resourcetimingbufferfull event.
performance.markResourceTiming(createTimingInfo(5), requestedUrl, initiatorType, globalThis, cacheMode);
performance.markResourceTiming(createTimingInfo(6), requestedUrl, initiatorType, globalThis, cacheMode);
performance.markResourceTiming(createTimingInfo(5), ...args);
performance.markResourceTiming(createTimingInfo(6), ...args);
// Increase the buffer size on resourcetimingbufferfull event.
await new Promise((resolve) => {
@ -96,10 +105,10 @@ async function main() {
performance.clearResourceTimings();
performance.setResourceTimingBufferSize(2);
performance.markResourceTiming(createTimingInfo(7), requestedUrl, initiatorType, globalThis, cacheMode);
performance.markResourceTiming(createTimingInfo(8), requestedUrl, initiatorType, globalThis, cacheMode);
performance.markResourceTiming(createTimingInfo(7), ...args);
performance.markResourceTiming(createTimingInfo(8), ...args);
// Trigger a resourcetimingbufferfull event.
performance.markResourceTiming(createTimingInfo(9), requestedUrl, initiatorType, globalThis, cacheMode);
performance.markResourceTiming(createTimingInfo(9), ...args);
// Decrease the buffer size on resourcetimingbufferfull event.
await new Promise((resolve) => {

View File

@ -30,11 +30,18 @@ const initiatorType = '';
const cacheMode = '';
async function main() {
const args = [
timingInfo,
requestedUrl,
initiatorType,
globalThis,
cacheMode,
];
// Invalid buffer size values are converted to 0.
const invalidValues = [ null, undefined, true, false, -1, 0.5, Infinity, NaN, '', 'foo', {}, [], () => {} ];
for (const value of invalidValues) {
performance.setResourceTimingBufferSize(value);
performance.markResourceTiming(timingInfo, requestedUrl, initiatorType, globalThis, cacheMode);
performance.markResourceTiming(...args);
assert.strictEqual(performance.getEntriesByType('resource').length, 0);
performance.clearResourceTimings();
}
@ -42,9 +49,9 @@ async function main() {
await waitBufferFullEvent();
performance.setResourceTimingBufferSize(1);
performance.markResourceTiming(timingInfo, requestedUrl, initiatorType, globalThis, cacheMode);
performance.markResourceTiming(...args);
// Trigger a resourcetimingbufferfull event.
performance.markResourceTiming(timingInfo, requestedUrl, initiatorType, globalThis, cacheMode);
performance.markResourceTiming(...args);
assert.strictEqual(performance.getEntriesByType('resource').length, 1);
await waitBufferFullEvent();
@ -56,14 +63,14 @@ async function main() {
performance.clearResourceTimings();
assert.strictEqual(performance.getEntriesByType('resource').length, 0);
// Trigger a resourcetimingbufferfull event.
performance.markResourceTiming(timingInfo, requestedUrl, initiatorType, globalThis, cacheMode);
performance.markResourceTiming(...args);
// New entry is not added to the global buffer.
assert.strictEqual(performance.getEntriesByType('resource').length, 0);
await waitBufferFullEvent();
// Apply a new buffer size limit
performance.setResourceTimingBufferSize(1);
performance.markResourceTiming(timingInfo, requestedUrl, initiatorType, globalThis, cacheMode);
performance.markResourceTiming(...args);
assert.strictEqual(performance.getEntriesByType('resource').length, 1);
}

View File

@ -23,14 +23,10 @@
"idlharness.any.js": {
"fail": {
"expected": [
"PerformanceResourceTiming interface: attribute deliveryType",
"PerformanceResourceTiming interface: attribute firstInterimResponseStart",
"PerformanceResourceTiming interface: attribute responseStatus",
"PerformanceResourceTiming interface: attribute renderBlockingStatus",
"PerformanceResourceTiming interface: attribute contentType",
"PerformanceResourceTiming interface: resource must inherit property \"deliveryType\" with the proper type",
"PerformanceResourceTiming interface: resource must inherit property \"firstInterimResponseStart\" with the proper type",
"PerformanceResourceTiming interface: resource must inherit property \"responseStatus\" with the proper type",
"PerformanceResourceTiming interface: resource must inherit property \"renderBlockingStatus\" with the proper type",
"PerformanceResourceTiming interface: resource must inherit property \"contentType\" with the proper type",
"PerformanceResourceTiming interface: default toJSON operation on resource"

View File

@ -27,7 +27,7 @@ runner.setInitScript(`
finalNetworkResponseStartTime: 0,
encodedBodySize: 0,
decodedBodySize: 0,
}, 'https://nodejs.org', '', global, '');
}, 'https://nodejs.org', '', global, '', {}, 200, '');
`);
runner.runJsTests();

View File

@ -25,7 +25,7 @@ runner.setInitScript(`
finalNetworkResponseStartTime: 0,
encodedBodySize: 0,
decodedBodySize: 0,
}, 'https://nodejs.org', '', global, '');
}, 'https://nodejs.org', '', global, '', {}, 200, '');
`);
runner.runJsTests();