From 023ed4d30f44105b3284f28245bac4dc5d364320 Mon Sep 17 00:00:00 2001 From: Khafra Date: Mon, 29 Jan 2024 00:12:09 -0500 Subject: [PATCH 1/3] perf_hooks: add deliveryType and responseStatus fields --- lib/internal/perf/resource_timing.js | 34 ++++++++++++++++++- .../test-perf-hooks-resourcetiming.js | 24 +++++++++++-- ...st-performance-resourcetimingbufferfull.js | 27 ++++++++++----- ...st-performance-resourcetimingbuffersize.js | 17 +++++++--- test/wpt/status/resource-timing.json | 4 --- test/wpt/test-performance-timeline.js | 2 +- test/wpt/test-resource-timing.js | 2 +- 7 files changed, 87 insertions(+), 23 deletions(-) diff --git a/lib/internal/perf/resource_timing.js b/lib/internal/perf/resource_timing.js index e7c2f1fa448864..a037d5c0945ecf 100644 --- a/lib/internal/perf/resource_timing.js +++ b/lib/internal/perf/resource_timing.js @@ -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); diff --git a/test/parallel/test-perf-hooks-resourcetiming.js b/test/parallel/test-perf-hooks-resourcetiming.js index f9574e90022f86..67893ca9741967 100644 --- a/test/parallel/test-perf-hooks-resourcetiming.js +++ b/test/parallel/test-perf-hooks-resourcetiming.js @@ -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); diff --git a/test/parallel/test-performance-resourcetimingbufferfull.js b/test/parallel/test-performance-resourcetimingbufferfull.js index 9c595610a676cf..d962bdf8cfd7e2 100644 --- a/test/parallel/test-performance-resourcetimingbufferfull.js +++ b/test/parallel/test-performance-resourcetimingbufferfull.js @@ -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) => { diff --git a/test/parallel/test-performance-resourcetimingbuffersize.js b/test/parallel/test-performance-resourcetimingbuffersize.js index 3b9e77799b3b25..c9c84dc9416f68 100644 --- a/test/parallel/test-performance-resourcetimingbuffersize.js +++ b/test/parallel/test-performance-resourcetimingbuffersize.js @@ -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); } diff --git a/test/wpt/status/resource-timing.json b/test/wpt/status/resource-timing.json index db5154260227b3..f40f8fe51da117 100644 --- a/test/wpt/status/resource-timing.json +++ b/test/wpt/status/resource-timing.json @@ -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" diff --git a/test/wpt/test-performance-timeline.js b/test/wpt/test-performance-timeline.js index dddce0dab8a7da..78a1f5b3e7cf51 100644 --- a/test/wpt/test-performance-timeline.js +++ b/test/wpt/test-performance-timeline.js @@ -27,7 +27,7 @@ runner.setInitScript(` finalNetworkResponseStartTime: 0, encodedBodySize: 0, decodedBodySize: 0, - }, 'https://nodejs.org', '', global, ''); + }, 'https://nodejs.org', '', global, '', {}, 200, ''); `); runner.runJsTests(); diff --git a/test/wpt/test-resource-timing.js b/test/wpt/test-resource-timing.js index 9f9aab55dc498f..f30c7b2e44d5f5 100644 --- a/test/wpt/test-resource-timing.js +++ b/test/wpt/test-resource-timing.js @@ -25,7 +25,7 @@ runner.setInitScript(` finalNetworkResponseStartTime: 0, encodedBodySize: 0, decodedBodySize: 0, - }, 'https://nodejs.org', '', global, ''); + }, 'https://nodejs.org', '', global, '', {}, 200, ''); `); runner.runJsTests(); From 98426cf8a2471c379bada71c4dde46496e81a81f Mon Sep 17 00:00:00 2001 From: Khafra Date: Mon, 29 Jan 2024 10:42:54 -0500 Subject: [PATCH 2/3] fixup --- doc/api/perf_hooks.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/api/perf_hooks.md b/doc/api/perf_hooks.md index 040b8eaa52027b..3f77356716c470 100644 --- a/doc/api/perf_hooks.md +++ b/doc/api/perf_hooks.md @@ -246,7 +246,7 @@ 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])` * `timingInfo` {Object} [Fetch Timing Info][]