From 007fea0f82e57108de57f2eeedb1558af937ecbb Mon Sep 17 00:00:00 2001 From: Peter Hedenskog Date: Tue, 12 May 2026 14:29:53 +0200 Subject: [PATCH 1/2] Expose page-level style recalculation on renderBlocking Sitespeed.io / browsertime records how many elements the browser re-styled and how long that took on the way to FCP and LCP, but the data is parked on the HAR's page-level _renderBlocking field and never reaches consumers. Surface it as renderBlocking.recalculateStyle.{beforeFCP, beforeLCP} so compare and the sitespeed.io HTML report can render it alongside the existing blocking / potentially-blocking counts. Initialize the parent renderBlocking object lazily because the per-request loop only creates it when at least one entry carries a flag. Co-authored-by: Claude Opus 4.7 (1M context) noreply@anthropic.com --- lib/sitespeed.js | 21 ++++++++++++ .../browsertime-recalculate-style.har | 1 + test/renderBlockingTest.js | 33 +++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 test/files/sitespeed/browsertime-recalculate-style.har create mode 100644 test/renderBlockingTest.js diff --git a/lib/sitespeed.js b/lib/sitespeed.js index 89d112f..e13b9bc 100644 --- a/lib/sitespeed.js +++ b/lib/sitespeed.js @@ -24,6 +24,27 @@ module.exports = { if (harPage._googleWebVitals) { pageXrayPage.googleWebVitals = harPage._googleWebVitals; } + + // Page-level style recalculation work captured by sitespeed.io + // /browsertime (elements touched + duration before FCP/LCP). + // The counts in `renderBlocking` come from iterating entries + // in index.js, so the parent object may not exist yet for HARs + // that have no per-request render-blocking flags — initialize + // it before attaching the recalculation block. + if ( + harPage._renderBlocking && + harPage._renderBlocking.recalculateStyle + ) { + if (!pageXrayPage.renderBlocking) { + pageXrayPage.renderBlocking = { + blocking: 0, + potentiallyBlocking: 0, + in_body_parser_blocking: 0 + }; + } + pageXrayPage.renderBlocking.recalculateStyle = + harPage._renderBlocking.recalculateStyle; + } } } } diff --git a/test/files/sitespeed/browsertime-recalculate-style.har b/test/files/sitespeed/browsertime-recalculate-style.har new file mode 100644 index 0000000..cd43a31 --- /dev/null +++ b/test/files/sitespeed/browsertime-recalculate-style.har @@ -0,0 +1 @@ +{"log":{"version":"1.2","creator":{"name":"chrome-har","version":"1.3.0","comment":"https://github.com/sitespeedio/chrome-har"},"pages":[{"id":"page_1","startedDateTime":"2026-05-12T12:16:34.091Z","title":"https://www.wikpedia.org run 1","pageTimings":{"onContentLoad":900.073,"onLoad":901.564,"_firstPaint":1016,"_largestContentfulPaint":1016,"_firstContentfulPaint":1016,"_domInteractiveTime":900,"_domContentLoadedTime":900,"_longTasks":[[764.9000000059605,878.9000000059605]]},"_url":"https://www.wikpedia.org","_renderBlocking":{"recalculateStyle":{"beforeFCP":{"elements":1998,"durationInMillis":17.099},"beforeLCP":{"elements":1998,"durationInMillis":17.099}}},"_meta":{"connectivity":"native"},"_visualMetrics":{},"_cpu":{"categories":{"parseHTML":15,"styleLayout":101,"paintCompositeRender":55,"scriptParseCompile":1,"scriptEvaluation":19,"garbageCollection":15,"other":100},"events":{"RunTask":74.792,"PrePaint":19.983,"Commit":15.295,"UpdateLayoutTree":20.204,"LatencyInfo.Flow":24.67,"Layout":79.471,"HitTest":13.886},"urls":[],"scriptCosts":[{"url":"https://www.wikipedia.org/portal/wikipedia.org/assets/js/index-34f340e24a.js","parse":0,"compile":0,"execute":0.9,"total":0.9},{"url":"https://www.wikipedia.org/","parse":0,"compile":0.1,"execute":0.3,"total":0.4},{"url":"https://www.wikipedia.org/portal/wikipedia.org/assets/js/gt-ie9-507b16b6be.js","parse":0,"compile":0,"execute":0,"total":0}],"forcedReflows":[],"nonCompositedAnimations":[{"name":"","id":"","compositeFailed":8224,"unsupportedProperties":["border-bottom-color"],"startTime":80707593641},{"name":"","id":"","compositeFailed":8224,"unsupportedProperties":["border-left-color"],"startTime":80707593645},{"name":"","id":"","compositeFailed":8224,"unsupportedProperties":["box-shadow"],"startTime":80707593646},{"name":"","id":"","compositeFailed":8224,"unsupportedProperties":["border-right-color"],"startTime":80707593647}],"longTasks":{"tasks":1,"totalDuration":114,"totalBlockingTime":0,"maxPotentialFid":0,"lastLongTask":765,"beforeFirstPaint":{"tasks":1,"totalDuration":114},"beforeFirstContentfulPaint":{"tasks":1,"totalDuration":114},"beforeLargestContentfulPaint":{"tasks":1,"totalDuration":114},"afterLoadEventEnd":{"tasks":0,"totalDuration":0}}},"_googleWebVitals":{"cumulativeLayoutShift":0.00009003411552449943,"ttfb":731,"largestContentfulPaint":1016,"firstContentfulPaint":1016,"firstInputDelay":0,"totalBlockingTime":0}}],"entries":[{"cache":{},"startedDateTime":"2026-05-12T12:16:34.092Z","_requestId":"058E1B56062207FEC0C471DEBE0F5AB7r","_initialPriority":"VeryHigh","_priority":"VeryHigh","pageref":"page_1","request":{"method":"GET","url":"https://www.wikpedia.org/","queryString":[],"headersSize":-1,"bodySize":0,"cookies":[],"headers":[{"name":"Upgrade-Insecure-Requests","value":"1"},{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36"},{"name":"sec-ch-ua","value":"\"Chromium\";v=\"148\", \"Google Chrome\";v=\"148\", \"Not/A)Brand\";v=\"99\""},{"name":"sec-ch-ua-mobile","value":"?0"},{"name":"sec-ch-ua-platform","value":"\"macOS\""},{"name":":authority","value":"www.wikpedia.org"},{"name":":method","value":"GET"},{"name":":path","value":"/"},{"name":":scheme","value":"https"},{"name":"accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"},{"name":"accept-encoding","value":"gzip, deflate, br, zstd"},{"name":"accept-language","value":"en-US,en;q=0.9"},{"name":"priority","value":"u=0, i"},{"name":"sec-ch-ua","value":"\"Chromium\";v=\"148\", \"Google Chrome\";v=\"148\", \"Not/A)Brand\";v=\"99\""},{"name":"sec-ch-ua-mobile","value":"?0"},{"name":"sec-ch-ua-platform","value":"\"macOS\""},{"name":"sec-fetch-dest","value":"document"},{"name":"sec-fetch-mode","value":"navigate"},{"name":"sec-fetch-site","value":"cross-site"},{"name":"upgrade-insecure-requests","value":"1"},{"name":"user-agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36"}],"httpVersion":"h2"},"time":528.229,"_initiator_detail":"{\"stack\":{\"callFrames\":[{\"columnNumber\":29,\"functionName\":\"eval\",\"lineNumber\":9,\"scriptId\":\"12\",\"url\":\"\"}]},\"type\":\"script\"}","_initiator_type":"script","_resourceType":"document","_initiator":"","_initiator_line":10,"_initiator_column":30,"_initiator_function_name":"eval","_initiator_script_id":"12","response":{"httpVersion":"h2","redirectURL":"https://www.wikipedia.org/","status":301,"statusText":"","content":{"mimeType":"text/html","charset":"","size":0},"headersSize":-1,"bodySize":-1,"cookies":[],"headers":[{"name":"content-length","value":"169"},{"name":"content-type","value":"text/html"},{"name":"date","value":"Tue, 12 May 2026 12:16:34 GMT"},{"name":"location","value":"https://www.wikipedia.org/"},{"name":"server","value":"nginx/1.22.1"},{"name":"strict-transport-security","value":"max-age=106384710; includeSubDomains; preload"}],"_transferSize":139,"fromDiskCache":false,"fromEarlyHints":false,"fromServiceWorker":false,"fromPrefetchCache":false},"connection":"99","serverIPAddress":"185.15.59.226","timings":{"blocked":0,"dns":441.353,"connect":62.684,"send":0.2,"wait":23.992,"receive":0,"ssl":37.276,"_queued":0.836},"_requestTime":80706.717916,"_documentURL":"https://www.wikpedia.org"},{"cache":{},"startedDateTime":"2026-05-12T12:16:34.627Z","_requestId":"058E1B56062207FEC0C471DEBE0F5AB7","_initialPriority":"VeryHigh","_priority":"VeryHigh","pageref":"page_1","request":{"method":"GET","url":"https://www.wikipedia.org/","queryString":[],"headersSize":-1,"bodySize":0,"cookies":[],"headers":[{"name":"Upgrade-Insecure-Requests","value":"1"},{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36"},{"name":"sec-ch-ua","value":"\"Chromium\";v=\"148\", \"Google Chrome\";v=\"148\", \"Not/A)Brand\";v=\"99\""},{"name":"sec-ch-ua-mobile","value":"?0"},{"name":"sec-ch-ua-platform","value":"\"macOS\""},{"name":":authority","value":"www.wikipedia.org"},{"name":":method","value":"GET"},{"name":":path","value":"/"},{"name":":scheme","value":"https"},{"name":"accept","value":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"},{"name":"accept-encoding","value":"gzip, deflate, br, zstd"},{"name":"accept-language","value":"en-US,en;q=0.9"},{"name":"priority","value":"u=0, i"},{"name":"sec-ch-ua","value":"\"Chromium\";v=\"148\", \"Google Chrome\";v=\"148\", \"Not/A)Brand\";v=\"99\""},{"name":"sec-ch-ua-mobile","value":"?0"},{"name":"sec-ch-ua-platform","value":"\"macOS\""},{"name":"sec-fetch-dest","value":"document"},{"name":"sec-fetch-mode","value":"navigate"},{"name":"sec-fetch-site","value":"cross-site"},{"name":"upgrade-insecure-requests","value":"1"},{"name":"user-agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36"}],"httpVersion":"h2"},"time":218.716,"_initiator_detail":"{\"stack\":{\"callFrames\":[{\"columnNumber\":29,\"functionName\":\"eval\",\"lineNumber\":9,\"scriptId\":\"12\",\"url\":\"\"}]},\"type\":\"script\"}","_initiator_type":"script","_resourceType":"document","_initiator":"","_initiator_line":10,"_initiator_column":30,"_initiator_function_name":"eval","_initiator_script_id":"12","response":{"httpVersion":"h2","redirectURL":"","status":200,"statusText":"","content":{"mimeType":"text/html","charset":"","size":120318,"compression":88341},"headersSize":-1,"bodySize":31977,"cookies":[],"headers":[{"name":"content-length","value":"169"},{"name":"content-type","value":"text/html"},{"name":"date","value":"Tue, 12 May 2026 12:16:34 GMT"},{"name":"location","value":"https://www.wikipedia.org/"},{"name":"server","value":"nginx/1.22.1"},{"name":"strict-transport-security","value":"max-age=106384710; includeSubDomains; preload"}],"_transferSize":31977,"fromDiskCache":false,"fromEarlyHints":false,"fromServiceWorker":false,"fromPrefetchCache":false},"connection":"115","serverIPAddress":"185.15.59.224","timings":{"blocked":0.218,"dns":11.12,"connect":147.029,"send":0.311,"wait":34.827,"receive":25.211,"ssl":122.252,"_queued":0.856},"_requestTime":80707.252906,"_chunks":[{"ts":742.156,"bytes":61083},{"ts":754.984,"bytes":59235}]},{"cache":{},"startedDateTime":"2026-05-12T12:16:34.854Z","_requestId":"35371.4","_initialPriority":"Low","_priority":"High","pageref":"page_1","request":{"method":"GET","url":"https://www.wikipedia.org/portal/wikipedia.org/assets/img/Wikipedia-logo-v2@2x.png","queryString":[],"headersSize":-1,"bodySize":0,"cookies":[],"headers":[{"name":"Referer","value":"https://www.wikipedia.org/"},{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36"},{"name":"sec-ch-ua","value":"\"Chromium\";v=\"148\", \"Google Chrome\";v=\"148\", \"Not/A)Brand\";v=\"99\""},{"name":"sec-ch-ua-mobile","value":"?0"},{"name":"sec-ch-ua-platform","value":"\"macOS\""}],"httpVersion":"h2"},"time":47.44200000000001,"_initiator_detail":"{\"columnNumber\":9,\"lineNumber\":940,\"type\":\"parser\",\"url\":\"https://www.wikipedia.org/\"}","_initiator_type":"parser","_resourceType":"image","_initiator":"https://www.wikipedia.org/","_initiator_line":941,"response":{"httpVersion":"h2","redirectURL":"","status":200,"statusText":"","content":{"mimeType":"image/png","charset":"","size":37479},"headersSize":-1,"bodySize":38469,"cookies":[],"headers":[{"name":"accept-ranges","value":"bytes"},{"name":"access-control-allow-origin","value":"*"},{"name":"age","value":"55622"},{"name":"cache-control","value":"s-maxage=86400, max-age=86400"},{"name":"content-length","value":"37479"},{"name":"content-type","value":"image/png"},{"name":"date","value":"Mon, 11 May 2026 20:49:32 GMT"},{"name":"etag","value":"\"9267-64df1c7836c80\""},{"name":"expires","value":"Tue, 11 May 2027 20:49:32 GMT"},{"name":"last-modified","value":"Thu, 26 Mar 2026 18:44:50 GMT"},{"name":"nel","value":"{ \"report_to\": \"wm_nel\", \"max_age\": 604800, \"failure_fraction\": 0.05, \"success_fraction\": 0.0}"},{"name":"report-to","value":"{ \"group\": \"wm_nel\", \"max_age\": 604800, \"endpoints\": [{ \"url\": \"https://intake-logging.wikimedia.org/v1/events?stream=w3c.reportingapi.network_error&schema_uri=/w3c/reportingapi/network_error/1.0.0\" }] }"},{"name":"server","value":"mw-web.eqiad.main-57956db77-b55mq"},{"name":"server-timing","value":"cache;desc=\"hit-front\", host;desc=\"cp3072\""},{"name":"set-cookie","value":"WMF-Uniq=M2xA1AaHn7ni_j55T1CNsgNeAAEBAFvd_dX3A9ZfxRKKnZ47TSo49ePDVo9L2E5s;Domain=.wikipedia.org;Path=/;HttpOnly;secure;SameSite=None;Expires=Wed, 12 May 2027 00:00:00 GMT"},{"name":"strict-transport-security","value":"max-age=106384710; includeSubDomains; preload"},{"name":"x-cache","value":"cp3072 miss, cp3072 hit/17254"},{"name":"x-cache-status","value":"hit-front"},{"name":"x-client-ip","value":"85.229.138.68"},{"name":"x-request-id","value":"f8351b02-8b83-4f78-9dd0-f7b44f060605"}],"_transferSize":38469,"fromDiskCache":false,"fromEarlyHints":false,"fromServiceWorker":false,"fromPrefetchCache":false},"connection":"115","serverIPAddress":"185.15.59.224","timings":{"blocked":0.134,"dns":-1,"connect":-1,"send":0.069,"wait":33.24,"receive":13.999,"ssl":-1,"_queued":0.981},"_requestTime":80707.479594,"_chunks":[{"ts":877.98,"bytes":37479},{"ts":878.574,"bytes":0}],"_isLCP":true},{"cache":{},"startedDateTime":"2026-05-12T12:16:34.854Z","_requestId":"35371.5","_initialPriority":"High","_priority":"High","pageref":"page_1","request":{"method":"GET","url":"https://www.wikipedia.org/portal/wikipedia.org/assets/js/index-34f340e24a.js","queryString":[],"headersSize":-1,"bodySize":0,"cookies":[],"headers":[{"name":"Referer","value":"https://www.wikipedia.org/"},{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36"},{"name":"sec-ch-ua","value":"\"Chromium\";v=\"148\", \"Google Chrome\";v=\"148\", \"Not/A)Brand\";v=\"99\""},{"name":"sec-ch-ua-mobile","value":"?0"},{"name":"sec-ch-ua-platform","value":"\"macOS\""}],"httpVersion":"h2"},"time":35.349999999999994,"_initiator_detail":"{\"columnNumber\":74,\"lineNumber\":941,\"type\":\"parser\",\"url\":\"https://www.wikipedia.org/\"}","_initiator_type":"parser","_resourceType":"script","_initiator":"https://www.wikipedia.org/","_initiator_line":942,"response":{"httpVersion":"h2","redirectURL":"","status":200,"statusText":"","content":{"mimeType":"text/javascript","charset":"","size":24131,"compression":14522},"headersSize":-1,"bodySize":9609,"cookies":[],"headers":[{"name":"accept-ranges","value":"bytes"},{"name":"access-control-allow-origin","value":"*"},{"name":"age","value":"55622"},{"name":"cache-control","value":"s-maxage=86400, max-age=86400"},{"name":"content-encoding","value":"gzip"},{"name":"content-length","value":"8607"},{"name":"content-type","value":"text/javascript"},{"name":"date","value":"Mon, 11 May 2026 20:49:32 GMT"},{"name":"etag","value":"W/\"5e43-65190a32c64c0\""},{"name":"expires","value":"Tue, 11 May 2027 20:49:32 GMT"},{"name":"last-modified","value":"Mon, 11 May 2026 20:31:55 GMT"},{"name":"nel","value":"{ \"report_to\": \"wm_nel\", \"max_age\": 604800, \"failure_fraction\": 0.05, \"success_fraction\": 0.0}"},{"name":"report-to","value":"{ \"group\": \"wm_nel\", \"max_age\": 604800, \"endpoints\": [{ \"url\": \"https://intake-logging.wikimedia.org/v1/events?stream=w3c.reportingapi.network_error&schema_uri=/w3c/reportingapi/network_error/1.0.0\" }] }"},{"name":"server","value":"mw-web.eqiad.main-57956db77-wf5nn"},{"name":"server-timing","value":"cache;desc=\"hit-front\", host;desc=\"cp3072\""},{"name":"set-cookie","value":"WMF-Uniq=M2xA1AaHn7ni_j55T1CNsgNeAAEBAFvdZSq7kJw1AD-wpAe6ORgTCcTW5QJJKzfe;Domain=.wikipedia.org;Path=/;HttpOnly;secure;SameSite=None;Expires=Wed, 12 May 2027 00:00:00 GMT"},{"name":"strict-transport-security","value":"max-age=106384710; includeSubDomains; preload"},{"name":"vary","value":"Accept-Encoding"},{"name":"x-cache","value":"cp3072 miss, cp3072 hit/42624"},{"name":"x-cache-status","value":"hit-front"},{"name":"x-client-ip","value":"85.229.138.68"},{"name":"x-request-id","value":"86255d3a-979e-4b9a-974d-337fab758e33"}],"_transferSize":9609,"fromDiskCache":false,"fromEarlyHints":false,"fromServiceWorker":false,"fromPrefetchCache":false},"connection":"115","serverIPAddress":"185.15.59.224","timings":{"blocked":0.073,"dns":-1,"connect":-1,"send":0.047,"wait":35.059,"receive":0.171,"ssl":-1,"_queued":0.345},"_requestTime":80707.480211,"_chunks":[{"ts":885.411,"bytes":24131},{"ts":885.431,"bytes":0}],"_renderBlocking":"blocking"},{"cache":{},"startedDateTime":"2026-05-12T12:16:34.855Z","_requestId":"35371.8","_initialPriority":"Medium","_priority":"Medium","pageref":"page_1","request":{"method":"GET","url":"https://www.wikipedia.org/portal/wikipedia.org/assets/js/gt-ie9-507b16b6be.js","queryString":[],"headersSize":-1,"bodySize":0,"cookies":[],"headers":[{"name":"Referer","value":"https://www.wikipedia.org/"},{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36"},{"name":"sec-ch-ua","value":"\"Chromium\";v=\"148\", \"Google Chrome\";v=\"148\", \"Not/A)Brand\";v=\"99\""},{"name":"sec-ch-ua-mobile","value":"?0"},{"name":"sec-ch-ua-platform","value":"\"macOS\""}],"httpVersion":"h2"},"time":46.947,"_initiator_detail":"{\"columnNumber\":66,\"lineNumber\":942,\"type\":\"parser\",\"url\":\"https://www.wikipedia.org/\"}","_initiator_type":"parser","_resourceType":"script","_initiator":"https://www.wikipedia.org/","_initiator_line":943,"response":{"httpVersion":"h2","redirectURL":"","status":200,"statusText":"","content":{"mimeType":"text/javascript","charset":"","size":580},"headersSize":-1,"bodySize":1555,"cookies":[],"headers":[{"name":"accept-ranges","value":"bytes"},{"name":"access-control-allow-origin","value":"*"},{"name":"age","value":"55622"},{"name":"cache-control","value":"s-maxage=86400, max-age=86400"},{"name":"content-length","value":"580"},{"name":"content-type","value":"text/javascript"},{"name":"date","value":"Mon, 11 May 2026 20:49:32 GMT"},{"name":"etag","value":"\"244-64df1c7836c80\""},{"name":"expires","value":"Tue, 11 May 2027 20:49:32 GMT"},{"name":"last-modified","value":"Thu, 26 Mar 2026 18:44:50 GMT"},{"name":"nel","value":"{ \"report_to\": \"wm_nel\", \"max_age\": 604800, \"failure_fraction\": 0.05, \"success_fraction\": 0.0}"},{"name":"report-to","value":"{ \"group\": \"wm_nel\", \"max_age\": 604800, \"endpoints\": [{ \"url\": \"https://intake-logging.wikimedia.org/v1/events?stream=w3c.reportingapi.network_error&schema_uri=/w3c/reportingapi/network_error/1.0.0\" }] }"},{"name":"server","value":"mw-web.eqiad.main-57956db77-pj5f6"},{"name":"server-timing","value":"cache;desc=\"hit-front\", host;desc=\"cp3072\""},{"name":"set-cookie","value":"WMF-Uniq=M2xA1AaHn7ni_j55T1CNsgNeAAEBAFvd9iovpL1sbfYVkNTxrOIJw3i4Ue6Avu5D;Domain=.wikipedia.org;Path=/;HttpOnly;secure;SameSite=None;Expires=Wed, 12 May 2027 00:00:00 GMT"},{"name":"strict-transport-security","value":"max-age=106384710; includeSubDomains; preload"},{"name":"x-cache","value":"cp3072 miss, cp3072 hit/38252"},{"name":"x-cache-status","value":"hit-front"},{"name":"x-client-ip","value":"85.229.138.68"},{"name":"x-request-id","value":"723e2d69-ec3b-4150-9d50-3f1d48781b81"}],"_transferSize":1555,"fromDiskCache":false,"fromEarlyHints":false,"fromServiceWorker":false,"fromPrefetchCache":false},"connection":"115","serverIPAddress":"185.15.59.224","timings":{"blocked":0.061,"dns":-1,"connect":-1,"send":0.037,"wait":46.694,"receive":0.155,"ssl":-1,"_queued":0.113},"_requestTime":80707.48036,"_chunks":[{"ts":892.102,"bytes":580},{"ts":892.11,"bytes":0}],"_renderBlocking":"in_body_parser_blocking"},{"cache":{},"startedDateTime":"2026-05-12T12:16:34.859Z","_requestId":"35371.9","_initialPriority":"Low","_priority":"High","pageref":"page_1","request":{"method":"GET","url":"https://www.wikipedia.org/portal/wikipedia.org/assets/img/sprite-e49fbf32.svg","queryString":[],"headersSize":-1,"bodySize":0,"cookies":[],"headers":[{"name":"Referer","value":"https://www.wikipedia.org/"},{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36"},{"name":"sec-ch-ua","value":"\"Chromium\";v=\"148\", \"Google Chrome\";v=\"148\", \"Not/A)Brand\";v=\"99\""},{"name":"sec-ch-ua-mobile","value":"?0"},{"name":"sec-ch-ua-platform","value":"\"macOS\""}],"httpVersion":"h2"},"time":54.892,"_initiator_detail":"{\"columnNumber\":74,\"lineNumber\":941,\"type\":\"parser\",\"url\":\"https://www.wikipedia.org/\"}","_initiator_type":"parser","_resourceType":"image","_initiator":"https://www.wikipedia.org/","_initiator_line":942,"response":{"httpVersion":"h2","redirectURL":"","status":200,"statusText":"","content":{"mimeType":"image/svg+xml","charset":"","size":51190,"compression":31902},"headersSize":-1,"bodySize":19288,"cookies":[],"headers":[{"name":"accept-ranges","value":"bytes"},{"name":"access-control-allow-origin","value":"*"},{"name":"age","value":"55622"},{"name":"cache-control","value":"s-maxage=86400, max-age=86400"},{"name":"content-encoding","value":"gzip"},{"name":"content-length","value":"18278"},{"name":"content-type","value":"image/svg+xml"},{"name":"date","value":"Mon, 11 May 2026 20:49:32 GMT"},{"name":"etag","value":"W/\"c7f6-64df1c7836c80\""},{"name":"expires","value":"Tue, 11 May 2027 20:49:32 GMT"},{"name":"last-modified","value":"Thu, 26 Mar 2026 18:44:50 GMT"},{"name":"nel","value":"{ \"report_to\": \"wm_nel\", \"max_age\": 604800, \"failure_fraction\": 0.05, \"success_fraction\": 0.0}"},{"name":"report-to","value":"{ \"group\": \"wm_nel\", \"max_age\": 604800, \"endpoints\": [{ \"url\": \"https://intake-logging.wikimedia.org/v1/events?stream=w3c.reportingapi.network_error&schema_uri=/w3c/reportingapi/network_error/1.0.0\" }] }"},{"name":"server","value":"mw-web.eqiad.main-57956db77-rm42j"},{"name":"server-timing","value":"cache;desc=\"hit-front\", host;desc=\"cp3072\""},{"name":"set-cookie","value":"WMF-Uniq=M2xA1AaHn7ni_j55T1CNsgNeAAEBAFvdYd6S7lO6IF3QrXT7mTM17NKdiKzEn2aB;Domain=.wikipedia.org;Path=/;HttpOnly;secure;SameSite=None;Expires=Wed, 12 May 2027 00:00:00 GMT"},{"name":"strict-transport-security","value":"max-age=106384710; includeSubDomains; preload"},{"name":"vary","value":"Accept-Encoding"},{"name":"x-cache","value":"cp3072 miss, cp3072 hit/39622"},{"name":"x-cache-status","value":"hit-front"},{"name":"x-client-ip","value":"85.229.138.68"},{"name":"x-request-id","value":"7b46ce70-32e9-4b92-bb10-1d465dc3e972"}],"_transferSize":19288,"fromDiskCache":false,"fromEarlyHints":false,"fromServiceWorker":false,"fromPrefetchCache":false},"connection":"115","serverIPAddress":"185.15.59.224","timings":{"blocked":0.267,"dns":-1,"connect":-1,"send":0.053,"wait":53.026,"receive":1.546,"ssl":-1,"_queued":0.12},"_requestTime":80707.484295,"_chunks":[{"ts":878.701,"bytes":51190},{"ts":885.228,"bytes":0}]},{"cache":{},"startedDateTime":"2026-05-12T12:16:34.997Z","_requestId":"35371.11","_initialPriority":"High","_priority":"High","pageref":"page_1","request":{"method":"GET","url":"https://www.wikipedia.org/static/favicon/wikipedia.ico","queryString":[],"headersSize":-1,"bodySize":0,"cookies":[{"name":"WMF-Last-Access","value":"12-May-2026","path":"/","domain":"www.wikipedia.org","expires":"1970-01-21T14:50:07.623Z","httpOnly":true,"secure":true},{"name":"WMF-Last-Access-Global","value":"12-May-2026","path":"/","domain":".wikipedia.org","expires":"1970-01-21T14:50:07.623Z","httpOnly":true,"secure":true},{"name":"GeoIP","value":"SE:AB:H__gersten:59.31:17.98:v4","path":"/","domain":".wikipedia.org","expires":"1969-12-31T23:59:59.999Z","httpOnly":false,"secure":true},{"name":"NetworkProbeLimit","value":"0.001","path":"/","domain":"www.wikipedia.org","expires":"1970-01-21T14:03:11.794Z","httpOnly":false,"secure":true},{"name":"WMF-Uniq","value":"M2xA1AaHn7ni_j55T1CNsgNeAAEBAFvdYd6S7lO6IF3QrXT7mTM17NKdiKzEn2aB","path":"/","domain":".wikipedia.org","expires":"1970-01-21T22:48:55.622Z","httpOnly":true,"secure":true}],"headers":[{"name":"Referer","value":"https://www.wikipedia.org/"},{"name":"User-Agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36"},{"name":"sec-ch-ua","value":"\"Chromium\";v=\"148\", \"Google Chrome\";v=\"148\", \"Not/A)Brand\";v=\"99\""},{"name":"sec-ch-ua-mobile","value":"?0"},{"name":"sec-ch-ua-platform","value":"\"macOS\""},{"name":":authority","value":"www.wikipedia.org"},{"name":":method","value":"GET"},{"name":":path","value":"/static/favicon/wikipedia.ico"},{"name":":scheme","value":"https"},{"name":"accept","value":"image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"},{"name":"accept-encoding","value":"gzip, deflate, br, zstd"},{"name":"accept-language","value":"en-US,en;q=0.9"},{"name":"cookie","value":"WMF-Last-Access=12-May-2026; WMF-Last-Access-Global=12-May-2026; GeoIP=SE:AB:H__gersten:59.31:17.98:v4; NetworkProbeLimit=0.001; WMF-Uniq=M2xA1AaHn7ni_j55T1CNsgNeAAEBAFvdYd6S7lO6IF3QrXT7mTM17NKdiKzEn2aB"},{"name":"priority","value":"u=1, i"},{"name":"referer","value":"https://www.wikipedia.org/"},{"name":"sec-ch-ua","value":"\"Chromium\";v=\"148\", \"Google Chrome\";v=\"148\", \"Not/A)Brand\";v=\"99\""},{"name":"sec-ch-ua-mobile","value":"?0"},{"name":"sec-ch-ua-platform","value":"\"macOS\""},{"name":"sec-fetch-dest","value":"image"},{"name":"sec-fetch-mode","value":"no-cors"},{"name":"sec-fetch-site","value":"same-origin"},{"name":"user-agent","value":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36"}],"httpVersion":"h2"},"time":27.677,"_initiator_detail":"{\"type\":\"other\"}","_initiator_type":"other","_resourceType":"other","response":{"httpVersion":"h2","redirectURL":"","status":200,"statusText":"","content":{"mimeType":"image/vnd.microsoft.icon","charset":"","size":2734,"compression":913},"headersSize":-1,"bodySize":1821,"cookies":[],"headers":[{"name":"accept-ranges","value":"bytes"},{"name":"access-control-allow-origin","value":"*"},{"name":"age","value":"44240"},{"name":"cache-control","value":"max-age=31536000"},{"name":"content-encoding","value":"gzip"},{"name":"content-length","value":"1035"},{"name":"content-type","value":"image/vnd.microsoft.icon"},{"name":"date","value":"Mon, 11 May 2026 23:59:14 GMT"},{"name":"etag","value":"W/\"aae-64df1c7742a40\""},{"name":"expires","value":"Tue, 11 May 2027 23:59:14 GMT"},{"name":"last-modified","value":"Thu, 26 Mar 2026 18:44:49 GMT"},{"name":"nel","value":"{ \"report_to\": \"wm_nel\", \"max_age\": 604800, \"failure_fraction\": 0.05, \"success_fraction\": 0.0}"},{"name":"report-to","value":"{ \"group\": \"wm_nel\", \"max_age\": 604800, \"endpoints\": [{ \"url\": \"https://intake-logging.wikimedia.org/v1/events?stream=w3c.reportingapi.network_error&schema_uri=/w3c/reportingapi/network_error/1.0.0\" }] }"},{"name":"server","value":"ATS/9.2.13"},{"name":"server-timing","value":"cache;desc=\"hit-front\", host;desc=\"cp3072\""},{"name":"strict-transport-security","value":"max-age=106384710; includeSubDomains; preload"},{"name":"x-cache","value":"cp3072 miss, cp3072 hit/1240720"},{"name":"x-cache-status","value":"hit-front"},{"name":"x-client-ip","value":"85.229.138.68"},{"name":"x-request-id","value":"b7d2655a-65eb-4111-a189-f671f59a27f4"}],"_transferSize":1821,"fromDiskCache":false,"fromEarlyHints":false,"fromServiceWorker":false,"fromPrefetchCache":false},"connection":"115","serverIPAddress":"185.15.59.224","timings":{"blocked":0.113,"dns":-1,"connect":-1,"send":0.061,"wait":27.363,"receive":0.14,"ssl":-1,"_queued":0.194},"_requestTime":80707.622425,"_chunks":[{"ts":933.154,"bytes":2734},{"ts":933.612,"bytes":0}]}],"browser":{"name":"Chrome","version":"148.0.7778.97"}}} \ No newline at end of file diff --git a/test/renderBlockingTest.js b/test/renderBlockingTest.js new file mode 100644 index 0000000..2ad7f16 --- /dev/null +++ b/test/renderBlockingTest.js @@ -0,0 +1,33 @@ +'use strict'; + +const assert = require('chai').assert, + har = require('./helpers/har'); + +describe('renderBlocking.recalculateStyle', function() { + it('should surface page-level style recalculation work for browsertime HARs', function() { + return har.pagesFromTestHar('sitespeed/browsertime-recalculate-style.har') + .then(pages => { + const rb = pages[0].renderBlocking; + assert.isObject(rb, 'renderBlocking should exist'); + assert.isObject(rb.recalculateStyle, 'recalculateStyle should be attached'); + assert.isObject(rb.recalculateStyle.beforeFCP); + assert.isObject(rb.recalculateStyle.beforeLCP); + assert.isNumber(rb.recalculateStyle.beforeFCP.elements); + assert.isNumber(rb.recalculateStyle.beforeFCP.durationInMillis); + assert.isNumber(rb.recalculateStyle.beforeLCP.elements); + assert.isNumber(rb.recalculateStyle.beforeLCP.durationInMillis); + }); + }); + + it('should leave renderBlocking alone for HARs without _renderBlocking', function() { + // The Aftonbladet HAR is a plain (non-browsertime, non-WPT) HAR + // with no _renderBlocking field on the page — recalculateStyle + // should not get fabricated for it. + return har.pagesFromTestHar('aftonbladet.se-redirecting-to-www.har') + .then(pages => { + if (pages[0].renderBlocking) { + assert.isUndefined(pages[0].renderBlocking.recalculateStyle); + } + }); + }); +}); From d9eb584d724d0d8d1da39ed943a40075f392f7e1 Mon Sep 17 00:00:00 2001 From: Peter Hedenskog Date: Tue, 12 May 2026 14:35:04 +0200 Subject: [PATCH 2/2] fix --- test/headersTest.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/headersTest.js b/test/headersTest.js index c3ff76b..446b15e 100644 --- a/test/headersTest.js +++ b/test/headersTest.js @@ -54,8 +54,12 @@ describe('headers', function() { }); it('should handle invalid date header', () => { + // last-modified is kept comfortably in the future so the + // `Date.now()` fallback (used when `date` is unparseable) + // still yields a negative diff — exercising the fallback + // path is the point of this test. const requestHeaders = { - 'last-modified': ['Wed, 26 Aug 2025 12:37:50 GMT'], + 'last-modified': ['Wed, 26 Aug 2099 12:37:50 GMT'], 'date': ['Wedding'] }; const timeSinceLastModified = headers.getTimeSinceLastModified(requestHeaders);