From e7a6d39fafc69cb83a20bda589ea413f4825cb5a Mon Sep 17 00:00:00 2001 From: Derek Perkins Date: Fri, 26 May 2023 13:42:38 -0600 Subject: [PATCH 01/14] misc(proto): add package name (#15116) --- proto/lighthouse-result.proto | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proto/lighthouse-result.proto b/proto/lighthouse-result.proto index 8257620c4bb5..5720e4116c0c 100644 --- a/proto/lighthouse-result.proto +++ b/proto/lighthouse-result.proto @@ -1,5 +1,7 @@ syntax = "proto3"; +package googlechrome.lighthouse; + // This comment required for Lightrider import compatibility # header import "google/protobuf/struct.proto"; From 06f17aee52a91f1671291f89de1fcba8ab2c735c Mon Sep 17 00:00:00 2001 From: Ben Schwarz Date: Wed, 31 May 2023 05:33:22 +1000 Subject: [PATCH 02/14] core(network-requests): add entity classification (#15105) --- core/audits/network-requests.js | 6 + core/test/audits/network-requests-test.js | 24 ++ .../reports/sample-flow-result.json | 252 +++++++++++------- core/test/results/sample_v2.json | 90 ++++--- 4 files changed, 245 insertions(+), 127 deletions(-) diff --git a/core/audits/network-requests.js b/core/audits/network-requests.js index f7e99bf5135b..4e4ebe30fd73 100644 --- a/core/audits/network-requests.js +++ b/core/audits/network-requests.js @@ -8,6 +8,7 @@ import {Audit} from './audit.js'; import UrlUtils from '../lib/url-utils.js'; import {NetworkRecords} from '../computed/network-records.js'; import {MainResource} from '../computed/main-resource.js'; +import {EntityClassification} from '../computed/entity-classification.js'; class NetworkRequests extends Audit { /** @@ -31,6 +32,8 @@ class NetworkRequests extends Audit { static async audit(artifacts, context) { const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS]; const records = await NetworkRecords.request(devtoolsLog, context); + const classifiedEntities = await EntityClassification.request( + {URL: artifacts.URL, devtoolsLog}, context); const earliestRendererStartTime = records.reduce( (min, record) => Math.min(min, record.rendererStartTime), Infinity @@ -61,6 +64,8 @@ class NetworkRequests extends Audit { ((record.frameId === mainFrameId) || undefined) : undefined; + const entity = classifiedEntities.entityByUrl.get(record.url); + return { url: UrlUtils.elideDataURI(record.url), sessionTargetType: record.sessionTargetType, @@ -77,6 +82,7 @@ class NetworkRequests extends Audit { priority: record.priority, isLinkPreload, experimentalFromMainFrame, + entity: entity?.name, lrEndTimeDeltaMs: endTimeDeltaMs, // Only exists on Lightrider runs lrTCPMs: TCPMs, // Only exists on Lightrider runs lrRequestMs: requestMs, // Only exists on Lightrider runs diff --git a/core/test/audits/network-requests-test.js b/core/test/audits/network-requests-test.js index a05dfdf02a65..e57ff9af08fd 100644 --- a/core/test/audits/network-requests-test.js +++ b/core/test/audits/network-requests-test.js @@ -168,4 +168,28 @@ describe('Network requests audit', () => { isLinkPreload: true, }]); }); + + it('should include if network request was first or third party', async () => { + const records = [ + {url: 'https://example.com/'}, + {url: 'https://www.googletagmanager.com/gtm.js'}, + ]; + + const artifacts = { + devtoolsLogs: { + [NetworkRequests.DEFAULT_PASS]: networkRecordsToDevtoolsLog(records), + }, + URL: {mainDocumentUrl: 'https://example.com/'}, + GatherContext, + }; + const output = await NetworkRequests.audit(artifacts, {computedCache: new Map()}); + + expect(output.details.items).toMatchObject([{ + url: 'https://example.com/', + entity: 'example.com', + }, { + url: 'https://www.googletagmanager.com/gtm.js', + entity: 'Google Tag Manager', + }]); + }); }); diff --git a/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json b/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json index 9d0b627138bb..f2f4d32f8183 100644 --- a/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json +++ b/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json @@ -756,7 +756,8 @@ "mimeType": "text/html", "resourceType": "Document", "priority": "VeryHigh", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/fonts/danielbd.woff2", @@ -773,7 +774,8 @@ "resourceType": "Font", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://events.mikescerealshack.co/js/index.js", @@ -789,7 +791,8 @@ "mimeType": "application/javascript", "resourceType": "Script", "priority": "Low", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/css/08dcb440d7d83b488817.css", @@ -806,7 +809,8 @@ "resourceType": "Stylesheet", "priority": "VeryHigh", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/main-1f8481d632114a408557.js", @@ -823,7 +827,8 @@ "resourceType": "Script", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/webpack-657a8433bac0aabd564e.js", @@ -840,7 +845,8 @@ "resourceType": "Script", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/framework.9d524150d48315f49e80.js", @@ -857,7 +863,8 @@ "resourceType": "Script", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/commons.49455e4fa8cc3f51203f.js", @@ -874,7 +881,8 @@ "resourceType": "Script", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/pages/_app-ef508c97234d1af96c47.js", @@ -891,7 +899,8 @@ "resourceType": "Script", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/1aeab0175d4c4d823d7a78205bceb5dd9cd36d32.a629f28ec97ae6e480bf.js", @@ -908,7 +917,8 @@ "resourceType": "Script", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/pages/index-37980adf97404e76e41a.js", @@ -925,7 +935,8 @@ "resourceType": "Script", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/logo-text.svg", @@ -941,7 +952,8 @@ "mimeType": "image/svg+xml", "resourceType": "Image", "priority": "Low", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/t5QnfQSErVZVsTAuFcBWI/_buildManifest.js", @@ -957,7 +969,8 @@ "mimeType": "application/javascript", "resourceType": "Script", "priority": "Low", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/t5QnfQSErVZVsTAuFcBWI/_ssgManifest.js", @@ -973,7 +986,8 @@ "mimeType": "application/javascript", "resourceType": "Script", "priority": "Low", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;700&display=swap", @@ -989,7 +1003,8 @@ "mimeType": "text/css", "resourceType": "Stylesheet", "priority": "VeryLow", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "Google Fonts" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/1aeab0175d4c4d823d7a78205bceb5dd9cd36d32.a629f28ec97ae6e480bf.js", @@ -1005,7 +1020,8 @@ "mimeType": "application/javascript", "resourceType": "Other", "priority": "VeryLow", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/9ea7d3ba8dd80c65c50028121847762825088b49.dc477066508a83415fce.js", @@ -1021,7 +1037,8 @@ "mimeType": "application/javascript", "resourceType": "Other", "priority": "VeryLow", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/pages/scenes/%5Bseason%5D/%5Bepisode%5D/%5Bscene%5D-526fe33be891a56314a3.js", @@ -1037,7 +1054,8 @@ "mimeType": "application/javascript", "resourceType": "Other", "priority": "VeryLow", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://fonts.gstatic.com/s/poppins/v20/pxiEyp8kv8JHgFVrJJfecnFHGPc.woff2", @@ -1053,7 +1071,8 @@ "mimeType": "font/woff2", "resourceType": "Font", "priority": "VeryHigh", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "Google Fonts" }, { "url": "https://fonts.gstatic.com/s/poppins/v20/pxiByp8kv8JHgFVrLCz7Z1xlFd2JQEk.woff2", @@ -1069,7 +1088,8 @@ "mimeType": "font/woff2", "resourceType": "Font", "priority": "VeryHigh", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "Google Fonts" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/9ea7d3ba8dd80c65c50028121847762825088b49.dc477066508a83415fce.js", @@ -1085,7 +1105,8 @@ "mimeType": "application/javascript", "resourceType": "Script", "priority": "Low", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/pages/scenes/%5Bseason%5D/%5Bepisode%5D/%5Bscene%5D-526fe33be891a56314a3.js", @@ -1101,7 +1122,8 @@ "mimeType": "application/javascript", "resourceType": "Script", "priority": "Low", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/favicon.png", @@ -1117,7 +1139,8 @@ "mimeType": "image/png", "resourceType": "Other", "priority": "High", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" } ], "debugData": { @@ -5624,79 +5647,79 @@ }, { "startTime": 127, - "name": "lh:audit:network-rtt", + "name": "lh:computed:EntityClassification", "duration": 1, "entryType": "measure" }, { "startTime": 128, - "name": "lh:audit:network-server-latency", + "name": "lh:audit:network-rtt", "duration": 1, "entryType": "measure" }, { "startTime": 129, - "name": "lh:audit:main-thread-tasks", + "name": "lh:audit:network-server-latency", "duration": 1, "entryType": "measure" }, { "startTime": 130, - "name": "lh:audit:metrics", + "name": "lh:audit:main-thread-tasks", "duration": 1, "entryType": "measure" }, { "startTime": 131, - "name": "lh:computed:TimingSummary", + "name": "lh:audit:metrics", "duration": 1, "entryType": "measure" }, { "startTime": 132, - "name": "lh:computed:FirstContentfulPaintAllFrames", + "name": "lh:computed:TimingSummary", "duration": 1, "entryType": "measure" }, { "startTime": 133, - "name": "lh:computed:LargestContentfulPaintAllFrames", + "name": "lh:computed:FirstContentfulPaintAllFrames", "duration": 1, "entryType": "measure" }, { "startTime": 134, - "name": "lh:computed:LCPBreakdown", + "name": "lh:computed:LargestContentfulPaintAllFrames", "duration": 1, "entryType": "measure" }, { "startTime": 135, - "name": "lh:computed:TimeToFirstByte", + "name": "lh:computed:LCPBreakdown", "duration": 1, "entryType": "measure" }, { "startTime": 136, - "name": "lh:computed:LCPImageRecord", + "name": "lh:computed:TimeToFirstByte", "duration": 1, "entryType": "measure" }, { "startTime": 137, - "name": "lh:audit:performance-budget", + "name": "lh:computed:LCPImageRecord", "duration": 1, "entryType": "measure" }, { "startTime": 138, - "name": "lh:computed:ResourceSummary", + "name": "lh:audit:performance-budget", "duration": 1, "entryType": "measure" }, { "startTime": 139, - "name": "lh:computed:EntityClassification", + "name": "lh:computed:ResourceSummary", "duration": 1, "entryType": "measure" }, @@ -8511,7 +8534,8 @@ "statusCode": 200, "mimeType": "application/javascript", "resourceType": "Script", - "priority": "Low" + "priority": "Low", + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/logo-text.svg", @@ -8526,7 +8550,8 @@ "statusCode": 200, "mimeType": "image/svg+xml", "resourceType": "Image", - "priority": "High" + "priority": "High", + "entity": "mikescerealshack.co" }, { "url": "https://mnl4bjjsnz-dsn.algolia.net/1/indexes/dev_OFFICE_SCENES/query", @@ -8541,7 +8566,8 @@ "statusCode": 200, "mimeType": "text/plain", "resourceType": "Preflight", - "priority": "High" + "priority": "High", + "entity": "Algolia" }, { "url": "https://mnl4bjjsnz-dsn.algolia.net/1/indexes/dev_OFFICE_SCENES/query", @@ -8556,7 +8582,8 @@ "statusCode": 200, "mimeType": "application/json", "resourceType": "Fetch", - "priority": "High" + "priority": "High", + "entity": "Algolia" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/pages/index-37980adf97404e76e41a.js", @@ -8571,7 +8598,8 @@ "statusCode": 200, "mimeType": "application/javascript", "resourceType": "Other", - "priority": "VeryLow" + "priority": "VeryLow", + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/pages/terms-0236318e86139dd7d7f2.js", @@ -8586,7 +8614,8 @@ "statusCode": 200, "mimeType": "application/javascript", "resourceType": "Other", - "priority": "VeryLow" + "priority": "VeryLow", + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/pages/privacy-864d3895f3c3722acef2.js", @@ -8601,7 +8630,8 @@ "statusCode": 200, "mimeType": "application/javascript", "resourceType": "Other", - "priority": "VeryLow" + "priority": "VeryLow", + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/pages/privacy-864d3895f3c3722acef2.js", @@ -8616,7 +8646,8 @@ "statusCode": 200, "mimeType": "application/javascript", "resourceType": "Script", - "priority": "Low" + "priority": "Low", + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/pages/terms-0236318e86139dd7d7f2.js", @@ -8631,7 +8662,8 @@ "statusCode": 200, "mimeType": "application/javascript", "resourceType": "Script", - "priority": "Low" + "priority": "Low", + "entity": "mikescerealshack.co" }, { "url": "https://cdn.mikescerealshack.co/frames/s8/e13/128w/81d89db1bf3d43b5b21f813d2f2a9777.jpg", @@ -8646,7 +8678,8 @@ "statusCode": 200, "mimeType": "image/jpeg", "resourceType": "Image", - "priority": "Low" + "priority": "Low", + "entity": "mikescerealshack.co" }, { "url": "https://cdn.mikescerealshack.co/frames/s3/e3/128w/9b3031eb3988ba363fe946929a79e016.jpg", @@ -8661,7 +8694,8 @@ "statusCode": 200, "mimeType": "image/jpeg", "resourceType": "Image", - "priority": "Low" + "priority": "Low", + "entity": "mikescerealshack.co" }, { "url": "https://cdn.mikescerealshack.co/frames/s3/e3/128w/793a408ca63a660b5d7aa1a41ac126ca.jpg", @@ -8676,7 +8710,8 @@ "statusCode": 200, "mimeType": "image/jpeg", "resourceType": "Image", - "priority": "Low" + "priority": "Low", + "entity": "mikescerealshack.co" }, { "url": "https://cdn.mikescerealshack.co/frames/s7/e11/128w/5d1df07b1741f4c3e66ed20ef00265f5.jpg", @@ -8691,7 +8726,8 @@ "statusCode": 200, "mimeType": "image/jpeg", "resourceType": "Image", - "priority": "Low" + "priority": "Low", + "entity": "mikescerealshack.co" }, { "url": "https://cdn.mikescerealshack.co/frames/s8/e13/128w/b997cdb40263ff124e2a245c5e86a9a3.jpg", @@ -8706,7 +8742,8 @@ "statusCode": 200, "mimeType": "image/jpeg", "resourceType": "Image", - "priority": "Low" + "priority": "Low", + "entity": "mikescerealshack.co" }, { "url": "https://cdn.mikescerealshack.co/frames/s8/e3/128w/08b3049589ca7ae688b0f771f9730caf.jpg", @@ -8721,7 +8758,8 @@ "statusCode": 200, "mimeType": "image/jpeg", "resourceType": "Image", - "priority": "Low" + "priority": "Low", + "entity": "mikescerealshack.co" }, { "url": "https://cdn.mikescerealshack.co/frames/s8/e13/128w/f5c5012a2afa2ac6b190dcd68306dbac.jpg", @@ -8736,7 +8774,8 @@ "statusCode": 200, "mimeType": "image/jpeg", "resourceType": "Image", - "priority": "Low" + "priority": "Low", + "entity": "mikescerealshack.co" }, { "url": "https://cdn.mikescerealshack.co/frames/s9/e9/128w/5fbc916d0fffb01af1225d4ec2ab001d.jpg", @@ -8751,7 +8790,8 @@ "statusCode": 200, "mimeType": "image/jpeg", "resourceType": "Image", - "priority": "Low" + "priority": "Low", + "entity": "mikescerealshack.co" }, { "url": "https://cdn.mikescerealshack.co/frames/s9/e9/128w/558dc2f7d9c947e5445fb3f1838cb62c.jpg", @@ -8766,7 +8806,8 @@ "statusCode": 200, "mimeType": "image/jpeg", "resourceType": "Image", - "priority": "Low" + "priority": "Low", + "entity": "mikescerealshack.co" } ], "debugData": { @@ -10948,43 +10989,43 @@ }, { "startTime": 62, - "name": "lh:audit:network-rtt", + "name": "lh:computed:EntityClassification", "duration": 1, "entryType": "measure" }, { "startTime": 63, - "name": "lh:computed:NetworkAnalysis", + "name": "lh:audit:network-rtt", "duration": 1, "entryType": "measure" }, { "startTime": 64, - "name": "lh:audit:network-server-latency", + "name": "lh:computed:NetworkAnalysis", "duration": 1, "entryType": "measure" }, { "startTime": 65, - "name": "lh:audit:main-thread-tasks", + "name": "lh:audit:network-server-latency", "duration": 1, "entryType": "measure" }, { "startTime": 66, - "name": "lh:audit:resource-summary", + "name": "lh:audit:main-thread-tasks", "duration": 1, "entryType": "measure" }, { "startTime": 67, - "name": "lh:computed:ResourceSummary", + "name": "lh:audit:resource-summary", "duration": 1, "entryType": "measure" }, { "startTime": 68, - "name": "lh:computed:EntityClassification", + "name": "lh:computed:ResourceSummary", "duration": 1, "entryType": "measure" }, @@ -17446,7 +17487,8 @@ "mimeType": "text/html", "resourceType": "Document", "priority": "VeryHigh", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/fonts/danielbd.woff2", @@ -17463,7 +17505,8 @@ "resourceType": "Font", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://events.mikescerealshack.co/js/index.js", @@ -17479,7 +17522,8 @@ "mimeType": "application/javascript", "resourceType": "Script", "priority": "Low", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/css/08dcb440d7d83b488817.css", @@ -17496,7 +17540,8 @@ "resourceType": "Stylesheet", "priority": "VeryHigh", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/main-1f8481d632114a408557.js", @@ -17513,7 +17558,8 @@ "resourceType": "Script", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/webpack-657a8433bac0aabd564e.js", @@ -17530,7 +17576,8 @@ "resourceType": "Script", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/framework.9d524150d48315f49e80.js", @@ -17547,7 +17594,8 @@ "resourceType": "Script", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/commons.49455e4fa8cc3f51203f.js", @@ -17564,7 +17612,8 @@ "resourceType": "Script", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/pages/_app-ef508c97234d1af96c47.js", @@ -17581,7 +17630,8 @@ "resourceType": "Script", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/1aeab0175d4c4d823d7a78205bceb5dd9cd36d32.a629f28ec97ae6e480bf.js", @@ -17598,7 +17648,8 @@ "resourceType": "Script", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/pages/corrections-7a620a51252fe2c2f77b.js", @@ -17615,7 +17666,8 @@ "resourceType": "Script", "priority": "High", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/logo-text.svg", @@ -17631,7 +17683,8 @@ "mimeType": "image/svg+xml", "resourceType": "Image", "priority": "Low", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/oscar-actually.jpg", @@ -17647,7 +17700,8 @@ "mimeType": "image/jpeg", "resourceType": "Image", "priority": "High", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/t5QnfQSErVZVsTAuFcBWI/_buildManifest.js", @@ -17663,7 +17717,8 @@ "mimeType": "application/javascript", "resourceType": "Script", "priority": "Low", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/t5QnfQSErVZVsTAuFcBWI/_ssgManifest.js", @@ -17679,7 +17734,8 @@ "mimeType": "application/javascript", "resourceType": "Script", "priority": "Low", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;700&display=swap", @@ -17695,7 +17751,8 @@ "mimeType": "text/css", "resourceType": "Stylesheet", "priority": "VeryLow", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "Google Fonts" }, { "url": "https://fonts.gstatic.com/s/poppins/v20/pxiByp8kv8JHgFVrLCz7Z1xlFd2JQEk.woff2", @@ -17711,7 +17768,8 @@ "mimeType": "font/woff2", "resourceType": "Font", "priority": "VeryHigh", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "Google Fonts" }, { "url": "https://fonts.gstatic.com/s/poppins/v20/pxiEyp8kv8JHgFVrJJfecnFHGPc.woff2", @@ -17727,7 +17785,8 @@ "mimeType": "font/woff2", "resourceType": "Font", "priority": "VeryHigh", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "Google Fonts" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/1aeab0175d4c4d823d7a78205bceb5dd9cd36d32.a629f28ec97ae6e480bf.js", @@ -17743,7 +17802,8 @@ "mimeType": "application/javascript", "resourceType": "Other", "priority": "VeryLow", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/pages/index-37980adf97404e76e41a.js", @@ -17759,7 +17819,8 @@ "mimeType": "application/javascript", "resourceType": "Other", "priority": "VeryLow", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" }, { "url": "https://www.mikescerealshack.co/_next/static/chunks/pages/index-37980adf97404e76e41a.js", @@ -17775,7 +17836,8 @@ "mimeType": "application/javascript", "resourceType": "Script", "priority": "Low", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "mikescerealshack.co" } ], "debugData": { @@ -22306,79 +22368,79 @@ }, { "startTime": 125, - "name": "lh:audit:network-rtt", + "name": "lh:computed:EntityClassification", "duration": 1, "entryType": "measure" }, { "startTime": 126, - "name": "lh:audit:network-server-latency", + "name": "lh:audit:network-rtt", "duration": 1, "entryType": "measure" }, { "startTime": 127, - "name": "lh:audit:main-thread-tasks", + "name": "lh:audit:network-server-latency", "duration": 1, "entryType": "measure" }, { "startTime": 128, - "name": "lh:audit:metrics", + "name": "lh:audit:main-thread-tasks", "duration": 1, "entryType": "measure" }, { "startTime": 129, - "name": "lh:computed:TimingSummary", + "name": "lh:audit:metrics", "duration": 1, "entryType": "measure" }, { "startTime": 130, - "name": "lh:computed:FirstContentfulPaintAllFrames", + "name": "lh:computed:TimingSummary", "duration": 1, "entryType": "measure" }, { "startTime": 131, - "name": "lh:computed:LargestContentfulPaintAllFrames", + "name": "lh:computed:FirstContentfulPaintAllFrames", "duration": 1, "entryType": "measure" }, { "startTime": 132, - "name": "lh:computed:LCPBreakdown", + "name": "lh:computed:LargestContentfulPaintAllFrames", "duration": 1, "entryType": "measure" }, { "startTime": 133, - "name": "lh:computed:TimeToFirstByte", + "name": "lh:computed:LCPBreakdown", "duration": 1, "entryType": "measure" }, { "startTime": 134, - "name": "lh:computed:LCPImageRecord", + "name": "lh:computed:TimeToFirstByte", "duration": 1, "entryType": "measure" }, { "startTime": 135, - "name": "lh:audit:performance-budget", + "name": "lh:computed:LCPImageRecord", "duration": 1, "entryType": "measure" }, { "startTime": 136, - "name": "lh:computed:ResourceSummary", + "name": "lh:audit:performance-budget", "duration": 1, "entryType": "measure" }, { "startTime": 137, - "name": "lh:computed:EntityClassification", + "name": "lh:computed:ResourceSummary", "duration": 1, "entryType": "measure" }, diff --git a/core/test/results/sample_v2.json b/core/test/results/sample_v2.json index 73efc6dccfd6..fba8b5b92136 100644 --- a/core/test/results/sample_v2.json +++ b/core/test/results/sample_v2.json @@ -1277,7 +1277,8 @@ "mimeType": "text/html", "resourceType": "Document", "priority": "VeryHigh", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/dbw_tester.css?delay=100", @@ -1293,7 +1294,8 @@ "mimeType": "text/css", "resourceType": "Stylesheet", "priority": "VeryHigh", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/unknown404.css?delay=200", @@ -1309,7 +1311,8 @@ "mimeType": "text/css", "resourceType": "Stylesheet", "priority": "VeryHigh", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/dbw_tester.css?delay=2200", @@ -1325,7 +1328,8 @@ "mimeType": "text/css", "resourceType": "Stylesheet", "priority": "VeryHigh", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/dbw_disabled.css?delay=200&isdisabled", @@ -1341,7 +1345,8 @@ "mimeType": "text/css", "resourceType": "Stylesheet", "priority": "VeryHigh", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/dbw_tester.css?delay=3000&capped", @@ -1357,7 +1362,8 @@ "mimeType": "text/css", "resourceType": "Stylesheet", "priority": "VeryHigh", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/dbw_tester.css?delay=2000&async=true", @@ -1374,7 +1380,8 @@ "resourceType": "Stylesheet", "priority": "VeryHigh", "isLinkPreload": true, - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/dbw_tester.css?delay=3000&async=true", @@ -1390,7 +1397,8 @@ "mimeType": "text/css", "resourceType": "Stylesheet", "priority": "VeryHigh", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/dbw_tester.js", @@ -1406,7 +1414,8 @@ "mimeType": "application/javascript", "resourceType": "Script", "priority": "High", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/empty_module.js?delay=500", @@ -1422,7 +1431,8 @@ "mimeType": "application/javascript", "resourceType": "Script", "priority": "High", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/empty.css", @@ -1438,7 +1448,8 @@ "mimeType": "text/css", "resourceType": "Stylesheet", "priority": "VeryLow", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/fcp-delayer.js?delay=5000", @@ -1454,7 +1465,8 @@ "mimeType": "application/javascript", "resourceType": "Script", "priority": "High", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/lighthouse-480x318.jpg?iar1", @@ -1470,7 +1482,8 @@ "mimeType": "image/jpeg", "resourceType": "Image", "priority": "Low", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/lighthouse-480x318.jpg?isr1", @@ -1486,7 +1499,8 @@ "mimeType": "image/jpeg", "resourceType": "Image", "priority": "High", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/lighthouse-480x318.jpg?isr2", @@ -1502,7 +1516,8 @@ "mimeType": "image/jpeg", "resourceType": "Image", "priority": "High", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/lighthouse-480x318.jpg?isr3", @@ -1518,7 +1533,8 @@ "mimeType": "image/jpeg", "resourceType": "Image", "priority": "High", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/lighthouse-480x318.jpg", @@ -1534,7 +1550,8 @@ "mimeType": "image/jpeg", "resourceType": "Image", "priority": "High", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/lighthouse-rotating.gif", @@ -1550,7 +1567,8 @@ "mimeType": "image/gif", "resourceType": "Image", "priority": "Low", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/third_party/aggressive-promise-polyfill.js", @@ -1566,7 +1584,8 @@ "mimeType": "application/javascript", "resourceType": "Script", "priority": "Medium", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js", @@ -1582,7 +1601,8 @@ "mimeType": "text/javascript", "resourceType": "Script", "priority": "Medium", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "Google CDN" }, { "url": "http://localhost:10200/dobetterweb/lighthouse-480x318.jpg?iar2", @@ -1598,7 +1618,8 @@ "mimeType": "image/jpeg", "resourceType": "Image", "priority": "High", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/dbw_tester.css?scriptActivated&delay=200", @@ -1614,7 +1635,8 @@ "mimeType": "text/css", "resourceType": "Stylesheet", "priority": "VeryHigh", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/dbw_tester.html", @@ -1630,7 +1652,8 @@ "mimeType": "text/html", "resourceType": "XHR", "priority": "VeryHigh", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "blob:http://localhost:10200/3f2bc9df-684b-4541-837c-1590152ef65d", @@ -1678,7 +1701,8 @@ "mimeType": "image/vnd.microsoft.icon", "resourceType": "Other", "priority": "High", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/lighthouse-1024x680.jpg?lcp&redirect=lighthouse-1024x680.jpg%3Fredirected-lcp", @@ -1693,7 +1717,8 @@ "statusCode": 302, "mimeType": "", "priority": "High", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" }, { "url": "http://localhost:10200/dobetterweb/lighthouse-1024x680.jpg?redirected-lcp", @@ -1709,7 +1734,8 @@ "mimeType": "image/jpeg", "resourceType": "Image", "priority": "High", - "experimentalFromMainFrame": true + "experimentalFromMainFrame": true, + "entity": "localhost" } ], "debugData": { @@ -7873,6 +7899,12 @@ "duration": 100, "entryType": "measure" }, + { + "startTime": 0, + "name": "lh:computed:EntityClassification", + "duration": 100, + "entryType": "measure" + }, { "startTime": 0, "name": "lh:audit:network-rtt", @@ -7945,12 +7977,6 @@ "duration": 100, "entryType": "measure" }, - { - "startTime": 0, - "name": "lh:computed:EntityClassification", - "duration": 100, - "entryType": "measure" - }, { "startTime": 0, "name": "lh:audit:timing-budget", From 47eb8b9b3dea6b15edf5919f51accdb1dea547ac Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Wed, 31 May 2023 10:11:30 -0700 Subject: [PATCH 03/14] tests(smoke): add expectations for network-rtt, network-server-latency (#15113) --- .../smokehouse/test-definitions/dobetterweb.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cli/test/smokehouse/test-definitions/dobetterweb.js b/cli/test/smokehouse/test-definitions/dobetterweb.js index 29b6b3af1dde..4ea441f676ee 100644 --- a/cli/test/smokehouse/test-definitions/dobetterweb.js +++ b/cli/test/smokehouse/test-definitions/dobetterweb.js @@ -574,6 +574,20 @@ const expectations = { }, }, }, + 'network-rtt': { + details: { + items: [ + {origin: 'http://localhost:10200', rtt: '>0'}, + ], + }, + }, + 'network-server-latency': { + details: { + items: [ + {origin: 'http://localhost:10200', serverResponseTime: '>0'}, + ], + }, + }, 'metrics': { // Flaky in DevTools _excludeRunner: 'devtools', From 186e1804ae7757b6a975c9a8b8af1a5e9b67f81e Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Wed, 31 May 2023 10:36:48 -0700 Subject: [PATCH 04/14] core: expose error stack on errored audits (#14491) --- core/audits/audit.js | 7 +++-- core/gather/driver/execution-context.js | 18 ++++++++--- core/legacy/config/config.js | 2 +- core/lib/asset-saver.js | 19 ++++++++++++ core/lib/lh-error.js | 26 +++++++++------- core/runner.js | 6 ++-- core/scripts/cleanup-LHR-for-diff.js | 5 +++ core/scripts/update-flow-fixtures.js | 1 + .../gather/driver/execution-context-test.js | 31 +++++++++++++++++++ core/test/lib/asset-saver-test.js | 31 ++++++++++++++++++- core/test/runner-test.js | 31 +++++++++++++++++++ package.json | 2 +- tsconfig-base.json | 2 +- types/audit.d.ts | 2 ++ types/lhr/audit-result.d.ts | 2 ++ yarn.lock | 12 +++---- 16 files changed, 167 insertions(+), 30 deletions(-) diff --git a/core/audits/audit.js b/core/audits/audit.js index f44f617692af..481d3b5d2e94 100644 --- a/core/audits/audit.js +++ b/core/audits/audit.js @@ -348,12 +348,14 @@ class Audit { /** * @param {typeof Audit} audit * @param {string | LH.IcuMessage} errorMessage + * @param {string=} errorStack * @return {LH.RawIcu} */ - static generateErrorAuditResult(audit, errorMessage) { + static generateErrorAuditResult(audit, errorMessage, errorStack) { return Audit.generateAuditResult(audit, { score: null, errorMessage, + errorStack, }); } @@ -371,7 +373,7 @@ class Audit { let scoreDisplayMode = audit.meta.scoreDisplayMode || Audit.SCORING_MODES.BINARY; // But override if product contents require it. - if (product.errorMessage) { + if (product.errorMessage !== undefined) { // Error result. scoreDisplayMode = Audit.SCORING_MODES.ERROR; } else if (product.notApplicable) { @@ -407,6 +409,7 @@ class Audit { displayValue: product.displayValue, explanation: product.explanation, errorMessage: product.errorMessage, + errorStack: product.errorStack, warnings: product.warnings, details: product.details, diff --git a/core/gather/driver/execution-context.js b/core/gather/driver/execution-context.js index 0f08f665b375..f5238e517d9a 100644 --- a/core/gather/driver/execution-context.js +++ b/core/gather/driver/execution-context.js @@ -125,14 +125,22 @@ class ExecutionContext { this._session.setNextProtocolTimeout(timeout); const response = await this._session.sendCommand('Runtime.evaluate', evaluationParams); - if (response.exceptionDetails) { + + const ex = response.exceptionDetails; + if (ex) { // An error occurred before we could even create a Promise, should be *very* rare. // Also occurs when the expression is not valid JavaScript. - const errorMessage = response.exceptionDetails.exception ? - response.exceptionDetails.exception.description : - response.exceptionDetails.text; - return Promise.reject(new Error(`Evaluation exception: ${errorMessage}`)); + const elidedExpression = expression.replace(/\s+/g, ' ').substring(0, 100); + const messageLines = [ + 'Runtime.evaluate exception', + `Expression: ${elidedExpression}\n---- (elided)`, + !ex.stackTrace ? `Parse error at: ${ex.lineNumber + 1}:${ex.columnNumber + 1}` : null, + ex.exception?.description || ex.text, + ].filter(Boolean); + const evaluationError = new Error(messageLines.join('\n')); + return Promise.reject(evaluationError); } + // Protocol should always return a 'result' object, but it is sometimes undefined. See #6026. if (response.result === undefined) { return Promise.reject( diff --git a/core/legacy/config/config.js b/core/legacy/config/config.js index af55d7c33d96..d5de3e613006 100644 --- a/core/legacy/config/config.js +++ b/core/legacy/config/config.js @@ -205,7 +205,7 @@ class LegacyResolvedConfig { } /** - * @deprecated `Config.fromJson` should be used instead. + * @deprecated `LegacyResolvedConfig.fromJson` should be used instead. * @constructor * @param {LH.Config} config * @param {{settings: LH.Config.Settings, passes: ?LH.Config.Pass[], audits: ?LH.Config.AuditDefn[]}} opts diff --git a/core/lib/asset-saver.js b/core/lib/asset-saver.js index 76a6736c2e91..87ac80dd4c49 100644 --- a/core/lib/asset-saver.js +++ b/core/lib/asset-saver.js @@ -7,6 +7,7 @@ import fs from 'fs'; import path from 'path'; import stream from 'stream'; +import url from 'url'; import log from 'lighthouse-logger'; @@ -16,6 +17,7 @@ import {MetricTraceEvents} from './traces/metric-trace-events.js'; import {NetworkAnalysis} from '../computed/network-analysis.js'; import {LoadSimulator} from '../computed/load-simulator.js'; import {LighthouseError} from '../lib/lh-error.js'; +import {LH_ROOT} from '../../root.js'; const optionsFilename = 'options.json'; const artifactsFilename = 'artifacts.json'; @@ -425,6 +427,22 @@ function normalizeTimingEntries(timings) { } } +/** + * @param {LH.Result} lhr + */ +function elideAuditErrorStacks(lhr) { + const baseCallFrameUrl = url.pathToFileURL(LH_ROOT); + for (const auditResult of Object.values(lhr.audits)) { + if (auditResult.errorStack) { + auditResult.errorStack = auditResult.errorStack + // Make paths relative to the repo root. + .replaceAll(baseCallFrameUrl.pathname, '') + // Remove line/col info. + .replaceAll(/:\d+:\d+/g, ''); + } + } +} + export { saveArtifacts, saveFlowArtifacts, @@ -438,4 +456,5 @@ export { saveLanternNetworkData, stringifyReplacer, normalizeTimingEntries, + elideAuditErrorStacks, }; diff --git a/core/lib/lh-error.js b/core/lib/lh-error.js index fff6226d9bbf..adcb949fb82d 100644 --- a/core/lib/lh-error.js +++ b/core/lib/lh-error.js @@ -107,17 +107,18 @@ const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings); const LHERROR_SENTINEL = '__LighthouseErrorSentinel'; const ERROR_SENTINEL = '__ErrorSentinel'; /** - * @typedef {{sentinel: '__LighthouseErrorSentinel', code: string, stack?: string, [p: string]: string|undefined}} SerializedLighthouseError - * @typedef {{sentinel: '__ErrorSentinel', message: string, code?: string, stack?: string}} SerializedBaseError + * @typedef {{sentinel: '__LighthouseErrorSentinel', code: string, stack?: string, cause?: unknown, properties?: {[p: string]: string|undefined}}} SerializedLighthouseError + * @typedef {{sentinel: '__ErrorSentinel', message: string, code?: string, stack?: string, cause?: unknown}} SerializedBaseError */ class LighthouseError extends Error { /** * @param {LighthouseErrorDefinition} errorDefinition * @param {Record=} properties + * @param {ErrorOptions=} options */ - constructor(errorDefinition, properties) { - super(errorDefinition.code); + constructor(errorDefinition, properties, options) { + super(errorDefinition.code, options); this.name = 'LighthouseError'; this.code = errorDefinition.code; // Add additional properties to be ICU replacements in the error string. @@ -163,19 +164,20 @@ class LighthouseError extends Error { if (err instanceof LighthouseError) { // Remove class props so that remaining values were what was passed in as `properties`. // eslint-disable-next-line no-unused-vars - const {name, code, message, friendlyMessage, lhrRuntimeError, stack, ...properties} = err; + const {name, code, message, friendlyMessage, lhrRuntimeError, stack, cause, ...properties} = err; return { sentinel: LHERROR_SENTINEL, code, stack, - ...properties, + cause, + properties: /** @type {{ [p: string]: string | undefined }} */ (properties), }; } // Unexpected errors won't be LighthouseErrors, but we want them serialized as well. if (err instanceof Error) { - const {message, stack} = err; + const {message, stack, cause} = err; // @ts-expect-error - code can be helpful for e.g. node errors, so preserve it if it's present. const code = err.code; return { @@ -183,6 +185,7 @@ class LighthouseError extends Error { message, code, stack, + cause, }; } @@ -203,17 +206,18 @@ class LighthouseError extends Error { if (possibleError.sentinel === LHERROR_SENTINEL) { // Include sentinel in destructuring so it doesn't end up in `properties`. // eslint-disable-next-line no-unused-vars - const {sentinel, code, stack, ...properties} = /** @type {SerializedLighthouseError} */ (possibleError); + const {code, stack, cause, properties} = /** @type {SerializedLighthouseError} */ (possibleError); const errorDefinition = LighthouseError.errors[/** @type {keyof typeof ERRORS} */ (code)]; - const lhError = new LighthouseError(errorDefinition, properties); + const lhError = new LighthouseError(errorDefinition, properties, {cause}); lhError.stack = stack; return lhError; } if (possibleError.sentinel === ERROR_SENTINEL) { - const {message, code, stack} = /** @type {SerializedBaseError} */ (possibleError); - const error = new Error(message); + const {message, code, stack, cause} = /** @type {SerializedBaseError} */ (possibleError); + const opts = cause ? {cause} : undefined; + const error = new Error(message, opts); Object.assign(error, {code, stack}); return error; } diff --git a/core/runner.js b/core/runner.js index 15a34835d145..64991d03a2c2 100644 --- a/core/runner.js +++ b/core/runner.js @@ -429,7 +429,7 @@ class Runner { // Create a friendlier display error and mark it as expected to avoid duplicates in Sentry const error = new LighthouseError(LighthouseError.errors.ERRORED_REQUIRED_ARTIFACT, - {artifactName, errorMessage: artifactError.message}); + {artifactName, errorMessage: artifactError.message}, {cause: artifactError}); // @ts-expect-error Non-standard property added to Error error.expected = true; throw error; @@ -468,7 +468,9 @@ class Runner { Sentry.captureException(err, {tags: {audit: audit.meta.id}, level: 'error'}); // Errors become error audit result. const errorMessage = err.friendlyMessage ? err.friendlyMessage : err.message; - auditResult = Audit.generateErrorAuditResult(audit, errorMessage); + // Prefer the stack trace closest to the error. + const stack = err.cause?.stack ?? err.stack; + auditResult = Audit.generateErrorAuditResult(audit, errorMessage, stack); } log.timeEnd(status); diff --git a/core/scripts/cleanup-LHR-for-diff.js b/core/scripts/cleanup-LHR-for-diff.js index 6dd0d8fc3024..d1d9f2d55688 100755 --- a/core/scripts/cleanup-LHR-for-diff.js +++ b/core/scripts/cleanup-LHR-for-diff.js @@ -10,6 +10,8 @@ import {readFileSync, writeFileSync} from 'fs'; +import {elideAuditErrorStacks} from '../lib/asset-saver.js'; + const filename = process.argv[2]; const extraFlag = process.argv[3]; if (!filename) throw new Error('No filename provided.'); @@ -45,6 +47,9 @@ function cleanAndFormatLHR(lhrString) { auditResult.description = '**Excluded from diff**'; } } + + elideAuditErrorStacks(lhr); + // Ensure we have a final newline to conform to .editorconfig return `${JSON.stringify(lhr, null, 2)}\n`; } diff --git a/core/scripts/update-flow-fixtures.js b/core/scripts/update-flow-fixtures.js index c968bad7d666..44d01a72eca3 100644 --- a/core/scripts/update-flow-fixtures.js +++ b/core/scripts/update-flow-fixtures.js @@ -152,6 +152,7 @@ async function generateFlowResult() { // Normalize some data so it doesn't change on every update. for (const {lhr} of flowResult.steps) { assetSaver.normalizeTimingEntries(lhr.timing.entries); + assetSaver.elideAuditErrorStacks(lhr); lhr.timing.total = lhr.timing.entries.length; } diff --git a/core/test/gather/driver/execution-context-test.js b/core/test/gather/driver/execution-context-test.js index b00b2fcacd4c..c8e2d5bdc904 100644 --- a/core/test/gather/driver/execution-context-test.js +++ b/core/test/gather/driver/execution-context-test.js @@ -187,6 +187,37 @@ describe('.evaluateAsync', () => { const value = await executionContext.evaluateAsync('"magic"', {useIsolation: true}); expect(value).toEqual('mocked value'); }); + + it('handles runtime evaluation exception', async () => { + /** @type {LH.Crdp.Runtime.ExceptionDetails} */ + const exceptionDetails = { + exceptionId: 1, + text: 'Uncaught', + lineNumber: 7, + columnNumber: 8, + stackTrace: {description: '', callFrames: []}, + exception: { + type: 'object', + subtype: 'error', + className: 'ReferenceError', + description: 'ReferenceError: Prosmise is not defined\n' + + ' at wrapInNativePromise (_lighthouse-eval.js:8:9)\n' + + ' at _lighthouse-eval.js:83:8', + }, + }; + sessionMock.sendCommand = createMockSendCommandFn() + .mockResponse('Page.enable') + .mockResponse('Runtime.enable') + .mockResponse('Page.getResourceTree', {frameTree: {frame: {id: '1337'}}}) + .mockResponse('Page.getFrameTree', {frameTree: {frame: {id: '1337'}}}) + .mockResponse('Page.createIsolatedWorld', {executionContextId: 9001}) + .mockResponse('Runtime.evaluate', {exceptionDetails}); + + const promise = executionContext.evaluateAsync('new Prosmise', {useIsolation: true}); + await expect(promise).rejects.toThrow(/Expression: new Prosmise/); + await expect(promise).rejects.toThrow(/elided/); + await expect(promise).rejects.toThrow(/at wrapInNativePromise/); + }); }); describe('.evaluate', () => { diff --git a/core/test/lib/asset-saver-test.js b/core/test/lib/asset-saver-test.js index d567592209a7..96cdda27d34a 100644 --- a/core/test/lib/asset-saver-test.js +++ b/core/test/lib/asset-saver-test.js @@ -370,7 +370,9 @@ describe('asset-saver helper', () => { // Use an LighthouseError that has an ICU replacement. const protocolMethod = 'Page.getFastness'; const lhError = new LighthouseError( - LighthouseError.errors.PROTOCOL_TIMEOUT, {protocolMethod}); + LighthouseError.errors.PROTOCOL_TIMEOUT, + {protocolMethod}, + {cause: new Error('the cause')}); const artifacts = { traces: {}, @@ -385,6 +387,8 @@ describe('asset-saver helper', () => { expect(roundTripArtifacts.ScriptElements).toBeInstanceOf(LighthouseError); expect(roundTripArtifacts.ScriptElements.code).toEqual('PROTOCOL_TIMEOUT'); expect(roundTripArtifacts.ScriptElements.protocolMethod).toEqual(protocolMethod); + expect(roundTripArtifacts.ScriptElements.cause).toBeInstanceOf(Error); + expect(roundTripArtifacts.ScriptElements.cause.message).toEqual('the cause'); expect(roundTripArtifacts.ScriptElements.stack).toMatch( /^LighthouseError: PROTOCOL_TIMEOUT.*test[\\/]lib[\\/]asset-saver-test\.js/s); expect(roundTripArtifacts.ScriptElements.friendlyMessage) @@ -439,4 +443,29 @@ describe('asset-saver helper', () => { }); }); }); + + describe('elideAuditErrorStacks', () => { + it('elides correctly', async () => { + const lhr = JSON.parse(JSON.stringify(dbwResults)); + lhr.audits['bf-cache'].errorStack = `Error: LighthouseError: ERRORED_REQUIRED_ARTIFACT + at Runner._runAudit (${LH_ROOT}/core/runner.js:431:25) + at Runner._runAudits (${LH_ROOT}/core/runner.js:370:40) + at process.processTicksAndRejections (node:internal/process/task_queues:95:5) + at async Runner.audit (${LH_ROOT}/core/runner.js:62:32) + at async runLighthouse (${LH_ROOT}/cli/run.js:250:8) + at async ${LH_ROOT}/cli/index.js:10:1 + at :1:1`; + assetSaver.elideAuditErrorStacks(lhr); + + // eslint-disable-next-line max-len + expect(lhr.audits['bf-cache'].errorStack).toEqual(`Error: LighthouseError: ERRORED_REQUIRED_ARTIFACT + at Runner._runAudit (/core/runner.js) + at Runner._runAudits (/core/runner.js) + at process.processTicksAndRejections (node:internal/process/task_queues) + at async Runner.audit (/core/runner.js) + at async runLighthouse (/cli/run.js) + at async /cli/index.js + at `); + }); + }); }); diff --git a/core/test/runner-test.js b/core/test/runner-test.js index 1a443cf66fab..55c160673bf3 100644 --- a/core/test/runner-test.js +++ b/core/test/runner-test.js @@ -604,6 +604,37 @@ describe('Runner', () => { assert.strictEqual(auditResult.score, null); assert.strictEqual(auditResult.scoreDisplayMode, 'error'); assert.ok(auditResult.errorMessage.includes(errorMessage)); + assert.ok(auditResult.errorStack.match(/at [a-zA-Z]*.audit/)); + }); + }); + + it('produces an error audit result that prefers cause stack', async () => { + const errorMessage = 'Audit yourself'; + const resolvedConfig = await LegacyResolvedConfig.fromJson({ + settings: { + auditMode: moduleDir + '/fixtures/artifacts/empty-artifacts/', + }, + audits: [ + class ThrowyAudit extends Audit { + static get meta() { + return testAuditMeta; + } + static audit() { + this.aFn(); + } + static aFn() { + throw new Error(errorMessage); + } + }, + ], + }); + + return runGatherAndAudit({}, {resolvedConfig}).then(results => { + const auditResult = results.lhr.audits['throwy-audit']; + assert.strictEqual(auditResult.score, null); + assert.strictEqual(auditResult.scoreDisplayMode, 'error'); + assert.ok(auditResult.errorMessage.includes(errorMessage)); + assert.ok(auditResult.errorStack.match(/at [a-zA-Z]*.aFn/)); }); }); }); diff --git a/package.json b/package.json index 0f52d1ca975a..6f408bef5d70 100644 --- a/package.json +++ b/package.json @@ -179,7 +179,7 @@ "rollup-plugin-terser": "^7.0.2", "tabulator-tables": "^4.9.3", "terser": "^5.3.8", - "testdouble": "^3.16.8", + "testdouble": "^3.17.2", "typed-query-selector": "^2.6.1", "typescript": "^5.0.4", "wait-for-expect": "^3.0.2", diff --git a/tsconfig-base.json b/tsconfig-base.json index e61e358647a3..9e90928e1355 100644 --- a/tsconfig-base.json +++ b/tsconfig-base.json @@ -11,7 +11,7 @@ "outDir": ".tmp/tsbuildinfo/", "rootDir": ".", - "target": "es2020", + "target": "es2022", "module": "es2022", "moduleResolution": "node", "esModuleInterop": true, diff --git a/types/audit.d.ts b/types/audit.d.ts index ae28dafe7b03..9a83f6337722 100644 --- a/types/audit.d.ts +++ b/types/audit.d.ts @@ -75,6 +75,8 @@ declare module Audit { explanation?: string | IcuMessage; /** Error message from any exception thrown while running this audit. */ errorMessage?: string | IcuMessage; + /** Error stack from any exception thrown while running this audit. */ + errorStack?: string; warnings?: Array; /** Overrides scoreDisplayMode with notApplicable if set to true */ notApplicable?: boolean; diff --git a/types/lhr/audit-result.d.ts b/types/lhr/audit-result.d.ts index a9d95fc0cda4..7abe29ec137a 100644 --- a/types/lhr/audit-result.d.ts +++ b/types/lhr/audit-result.d.ts @@ -39,6 +39,8 @@ export interface Result { explanation?: string; /** Error message from any exception thrown while running this audit. */ errorMessage?: string; + /** Error stack from any exception thrown while running this audit. */ + errorStack?: string; warnings?: string[]; /** The scored value of the audit, provided in the range `0-1`, or null if `scoreDisplayMode` indicates not scored. */ score: number|null; diff --git a/yarn.lock b/yarn.lock index 610edb8d60da..f9cd2e901879 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6142,7 +6142,7 @@ query-string@^4.1.0: object-assign "^4.1.0" strict-uri-encode "^1.0.0" -quibble@^0.6.14: +quibble@^0.6.17: version "0.6.17" resolved "https://registry.yarnpkg.com/quibble/-/quibble-0.6.17.tgz#1c47d40c4ee670fc1a5a4277ee792ca6eec8f4ca" integrity sha512-uybGnGrx1hAhBCmzmVny+ycKaS5F71+q+iWVzbf8x/HyeEMDGeiQFVjWl1zhi4rwfTHa05+/NIExC4L5YRNPjQ== @@ -7006,13 +7006,13 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -testdouble@^3.16.8: - version "3.16.8" - resolved "https://registry.yarnpkg.com/testdouble/-/testdouble-3.16.8.tgz#9c761031f3693d973c726e31a60ee73cd2871c96" - integrity sha512-jOKYRJ9mfgDxwuUOj84sl9DWiP1+KpHcgnhjlSHC8h1ZxJT3KD1FAAFVqnqmmyrzc/+0DRbI/U5xo1/K3PLi8w== +testdouble@^3.17.2: + version "3.17.2" + resolved "https://registry.yarnpkg.com/testdouble/-/testdouble-3.17.2.tgz#a7d624c2040453580b4a636b3f017bf183a8f487" + integrity sha512-oRrk1DJISNoFr3aaczIqrrhkOUQ26BsXN3SopYT/U0GTvk9hlKPCEbd9R2uxkcufKZgEfo9D1JAB4CJrjHE9cw== dependencies: lodash "^4.17.21" - quibble "^0.6.14" + quibble "^0.6.17" stringify-object-es5 "^2.5.0" theredoc "^1.0.0" From 4c64c15e8a1405fe885cdca66a81186d57d9110c Mon Sep 17 00:00:00 2001 From: Ben Schwarz Date: Fri, 9 Jun 2023 05:49:21 +1000 Subject: [PATCH 05/14] docs(readme): add unit test tips (#15108) --- readme.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/readme.md b/readme.md index a2a345477813..1788ea000d94 100644 --- a/readme.md +++ b/readme.md @@ -297,6 +297,12 @@ for more info. # lint and test all files yarn test +# run all unit tests +yarn unit + +# run a given unit test (e.g. core/test/audits/byte-efficiency/uses-long-cache-ttl-test.js) +yarn mocha uses-long-cache-ttl + # watch for file changes and run tests # Requires http://entrproject.org : brew install entr yarn watch From 642494ab3f7cd2fd75beae14f91593126979a351 Mon Sep 17 00:00:00 2001 From: Adam Raine <6752989+adamraine@users.noreply.github.com> Date: Thu, 8 Jun 2023 19:46:39 -0700 Subject: [PATCH 06/14] core(inspector-issues): add `stylesheetLoadingIssue` (#15144) --- core/gather/gatherers/inspector-issues.js | 1 + core/lib/tracehouse/trace-processor.js | 2 +- core/test/gather/gatherers/inspector-issues-test.js | 4 ++++ package.json | 6 +++--- .../inspector-issueAdded-types-test.js | 1 + types/artifacts.d.ts | 1 + yarn.lock | 8 ++++---- 7 files changed, 15 insertions(+), 8 deletions(-) diff --git a/core/gather/gatherers/inspector-issues.js b/core/gather/gatherers/inspector-issues.js index c0f1bd8e0f32..d98f58b4fd95 100644 --- a/core/gather/gatherers/inspector-issues.js +++ b/core/gather/gatherers/inspector-issues.js @@ -75,6 +75,7 @@ class InspectorIssues extends FRGatherer { quirksModeIssue: [], cookieIssue: [], sharedArrayBufferIssue: [], + stylesheetLoadingIssue: [], }; const keys = /** @type {Array} */(Object.keys(artifact)); for (const key of keys) { diff --git a/core/lib/tracehouse/trace-processor.js b/core/lib/tracehouse/trace-processor.js index a397cdbfc2b4..fc64f813ff2b 100644 --- a/core/lib/tracehouse/trace-processor.js +++ b/core/lib/tracehouse/trace-processor.js @@ -705,7 +705,7 @@ class TraceProcessor { return Boolean( evt.name === 'FrameCommittedInBrowser' && evt.args.data?.frame && - evt.args.data.url + evt.args.data.url !== undefined ); }).forEach(evt => { framesById.set(evt.args.data.frame, { diff --git a/core/test/gather/gatherers/inspector-issues-test.js b/core/test/gather/gatherers/inspector-issues-test.js index 68061624d9d6..d19d170401a9 100644 --- a/core/test/gather/gatherers/inspector-issues-test.js +++ b/core/test/gather/gatherers/inspector-issues-test.js @@ -246,6 +246,7 @@ describe('_getArtifact', () => { quirksModeIssue: [], sharedArrayBufferIssue: [], federatedAuthRequestIssue: [], + stylesheetLoadingIssue: [], }); }); @@ -303,6 +304,7 @@ describe('_getArtifact', () => { quirksModeIssue: [], sharedArrayBufferIssue: [], federatedAuthRequestIssue: [], + stylesheetLoadingIssue: [], }); }); }); @@ -367,6 +369,7 @@ describe('FR compat (inspector-issues)', () => { quirksModeIssue: [], sharedArrayBufferIssue: [], federatedAuthRequestIssue: [], + stylesheetLoadingIssue: [], }); }); @@ -403,6 +406,7 @@ describe('FR compat (inspector-issues)', () => { quirksModeIssue: [], sharedArrayBufferIssue: [], federatedAuthRequestIssue: [], + stylesheetLoadingIssue: [], }); }); }); diff --git a/package.json b/package.json index 6f408bef5d70..e8e05a14641a 100644 --- a/package.json +++ b/package.json @@ -191,7 +191,7 @@ "chrome-launcher": "^0.15.2", "configstore": "^5.0.1", "csp_evaluator": "1.1.1", - "devtools-protocol": "0.0.1130274", + "devtools-protocol": "0.0.1154250", "enquirer": "^2.3.6", "http-link-header": "^1.1.1", "intl-messageformat": "^4.4.0", @@ -215,8 +215,8 @@ "yargs-parser": "^21.0.0" }, "resolutions": { - "puppeteer/**/devtools-protocol": "0.0.1130274", - "puppeteer-core/**/devtools-protocol": "0.0.1130274" + "puppeteer/**/devtools-protocol": "0.0.1154250", + "puppeteer-core/**/devtools-protocol": "0.0.1154250" }, "repository": "GoogleChrome/lighthouse", "keywords": [ diff --git a/third-party/chromium-synchronization/inspector-issueAdded-types-test.js b/third-party/chromium-synchronization/inspector-issueAdded-types-test.js index 291d5adb10e9..33dd1fc919b5 100644 --- a/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +++ b/third-party/chromium-synchronization/inspector-issueAdded-types-test.js @@ -48,6 +48,7 @@ Array [ "navigatorUserAgentIssueDetails", "quirksModeIssueDetails", "sharedArrayBufferIssueDetails", + "stylesheetLoadingIssueDetails", ] `); }); diff --git a/types/artifacts.d.ts b/types/artifacts.d.ts index c293c9b48f52..3a9b8a395820 100644 --- a/types/artifacts.d.ts +++ b/types/artifacts.d.ts @@ -618,6 +618,7 @@ declare module Artifacts { quirksModeIssue: Crdp.Audits.QuirksModeIssueDetails[]; cookieIssue: Crdp.Audits.CookieIssueDetails[]; sharedArrayBufferIssue: Crdp.Audits.SharedArrayBufferIssueDetails[]; + stylesheetLoadingIssue: Crdp.Audits.StylesheetLoadingIssueDetails[]; } // Computed artifact types below. diff --git a/yarn.lock b/yarn.lock index f9cd2e901879..c1394c2a7245 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3002,10 +3002,10 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -devtools-protocol@0.0.1120988, devtools-protocol@0.0.1130274: - version "0.0.1130274" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1130274.tgz#1cd0c472a84fc9a09becaaed35a247a6eab9310c" - integrity sha512-kIozBWajgsi1g0W8yzALI4ZdCp6KG1yWaq8NN1ehQM3zX6JRegLSzfexz7XT5eFjmq1RkpMYgeKmfi3GsHrCLw== +devtools-protocol@0.0.1120988, devtools-protocol@0.0.1154250: + version "0.0.1154250" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1154250.tgz#cb3a06e2c8bb07f977c1dc08a781e14a9dd1b3e8" + integrity sha512-ETduFBWzd+g4WL8iVpMTmeMDI0NfkjURd3rhO2mTKkL6wM54xNeIXBlIrsG3LPfxltQU7YRICvO++LHIflPXSQ== diff-sequences@^28.0.2: version "28.0.2" From bf8e6f22da5e81976e45749790883e4e6c4d50db Mon Sep 17 00:00:00 2001 From: Adam Raine <6752989+adamraine@users.noreply.github.com> Date: Fri, 9 Jun 2023 09:57:02 -0700 Subject: [PATCH 07/14] deps: upgrade `puppeteer` and `puppeteer-core` (#15143) --- package.json | 4 +- yarn.lock | 259 +++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 214 insertions(+), 49 deletions(-) diff --git a/package.json b/package.json index e8e05a14641a..c3008712a367 100644 --- a/package.json +++ b/package.json @@ -169,7 +169,7 @@ "pako": "^2.0.3", "preact": "^10.7.2", "pretty-json-stringify": "^0.0.2", - "puppeteer": "^20.1.0", + "puppeteer": "^20.5.0", "resolve": "^1.20.0", "rollup": "^2.52.7", "rollup-plugin-node-resolve": "^5.2.0", @@ -205,7 +205,7 @@ "open": "^8.4.0", "parse-cache-control": "1.0.1", "ps-list": "^8.0.0", - "puppeteer-core": "^20.1.0", + "puppeteer-core": "^20.5.0", "robots-parser": "^3.0.0", "semver": "^5.3.0", "speedline-core": "^1.4.3", diff --git a/yarn.lock b/yarn.lock index c1394c2a7245..67df7b7cf7bc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1123,16 +1123,15 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= -"@puppeteer/browsers@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-1.0.0.tgz#89de56a718c922857b1d802aac473ebbe1f54d99" - integrity sha512-YKecOIlwH0UsiM9zkKy31DYg11iD8NhOoQ7SQ4oCpwDSd1Ud31WYRoAldbVlVBj9b4hLJIXxn7XSnkH1ta1tpA== +"@puppeteer/browsers@1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-1.4.1.tgz#9c8ba163c3ef77ae3fc9708ad1f5787263f7290e" + integrity sha512-H43VosMzywHCcYcgv0GXXopvwnV21Ud9g2aXbPlQUJj1Xcz9V0wBwHeFz6saFhx/3VKisZfI1GEKEOhQCau7Vw== dependencies: debug "4.3.4" extract-zip "2.0.1" - https-proxy-agent "5.0.1" progress "2.0.3" - proxy-from-env "1.1.0" + proxy-agent "6.2.1" tar-fs "2.1.1" unbzip2-stream "1.4.3" yargs "17.7.1" @@ -1794,6 +1793,11 @@ acorn-walk@^6.0.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.1.1.tgz#d363b66f5fac5f018ff9c3a1e7b6f8e310cc3913" integrity sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw== +acorn-walk@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + acorn@^6.0.1, acorn@^6.0.2: version "6.4.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" @@ -1809,6 +1813,11 @@ acorn@^8.6.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895" integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw== +acorn@^8.7.0: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + add-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" @@ -1821,6 +1830,13 @@ agent-base@6: dependencies: debug "4" +agent-base@^7.0.1, agent-base@^7.0.2, agent-base@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.0.tgz#536802b76bc0b34aa50195eb2442276d613e3434" + integrity sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg== + dependencies: + debug "^4.3.4" + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -2021,6 +2037,13 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= +ast-types@^0.13.2: + version "0.13.4" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782" + integrity sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w== + dependencies: + tslib "^2.0.1" + async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" @@ -2115,6 +2138,11 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" +basic-ftp@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/basic-ftp/-/basic-ftp-5.0.3.tgz#b14c0fe8111ce001ec913686434fe0c2fb461228" + integrity sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g== + bcrypt-pbkdf@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz#3ca76b85241c7170bf7d9703e7b9aa74630040d4" @@ -2419,10 +2447,10 @@ chrome-launcher@^0.15.2: is-wsl "^2.2.0" lighthouse-logger "^1.0.0" -chromium-bidi@0.4.7: - version "0.4.7" - resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.4.7.tgz#4c022c2b0fb1d1c9b571fadf373042160e71d236" - integrity sha512-6+mJuFXwTMU6I3vYLs6IL8A1DyQTPjCfIL971X0aMPVGRbGnNfl6i6Cl0NMbxi2bRYLGESt9T2ZIMRM5PAEcIQ== +chromium-bidi@0.4.11: + version "0.4.11" + resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.4.11.tgz#d3eafb0a99f417406a734b889dacd777be5e227c" + integrity sha512-p03ajLhlQ5gebw3cmbDBFmBc2wnJM5dnXS8Phu6mblGn/KQd76yOVL5VwE0VAisa7oazNfKGTaXlIZ8Q5Bb9OA== dependencies: mitt "3.0.0" @@ -2825,12 +2853,12 @@ cross-env@^7.0.2: dependencies: cross-spawn "^7.0.1" -cross-fetch@3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" - integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== +cross-fetch@3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.6.tgz#bae05aa31a4da760969756318feeee6e70f15d6c" + integrity sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g== dependencies: - node-fetch "2.6.7" + node-fetch "^2.6.11" cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2: version "7.0.3" @@ -2890,6 +2918,11 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-uri-to-buffer@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-5.0.1.tgz#db89a9e279c2ffe74f50637a59a32fb23b3e4d7c" + integrity sha512-a9l6T1qqDogvvnw0nKlfZzqsyikEBZBClF39V3TFoKhDtGBqHu2HkuomJc02j5zft8zrUaXEuoicLeW54RkzPg== + data-urls@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe" @@ -2997,6 +3030,16 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +degenerator@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-4.0.2.tgz#55b7fb41239ee0ea7644fa3f2aba84e0adfaa40c" + integrity sha512-HKwIFvZROUMfH3qI3gBpD61BYh7q3c3GXD5UGZzoVNJwVSYgZKvYl1fRMXc9ozoTxl/VZxKJ5v/bA+19tywFiw== + dependencies: + ast-types "^0.13.2" + escodegen "^1.8.1" + esprima "^4.0.0" + vm2 "^3.9.17" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -3310,7 +3353,7 @@ escape-string-regexp@^2.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== -escodegen@^1.11.0: +escodegen@^1.11.0, escodegen@^1.8.1: version "1.14.3" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== @@ -3833,6 +3876,15 @@ fs-extra@^7.0.0: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -3907,6 +3959,16 @@ get-tsconfig@^3.0.1: resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-3.0.1.tgz#02cadb5abc5f0d53033c8b2f3005b84134ba22e9" integrity sha512-+m30eQjbcf3xMNdnacXH5IDAKUMbI7Mhbf3e1BHif1FzBlUhBzBlmOVc7kL4+kB035l8OCyBdI3dNXZ3of9HqA== +get-uri@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-6.0.1.tgz#cff2ba8d456c3513a04b70c45de4dbcca5b1527c" + integrity sha512-7ZqONUVqaabogsYNWlYj0t3YZaL6dhuEueZXGF+/YVmf6dHmaFg8/6psJKqhx9QykIDKzpGcy2cn4oV4YC7V/Q== + dependencies: + basic-ftp "^5.0.2" + data-uri-to-buffer "^5.0.1" + debug "^4.3.4" + fs-extra "^8.1.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -4079,6 +4141,11 @@ graceful-fs@^4.1.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== +graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" @@ -4233,6 +4300,14 @@ http-parser-js@>=0.5.1: resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== +http-proxy-agent@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz#e9096c5afd071a3fce56e6252bb321583c124673" + integrity sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -4242,14 +4317,6 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -https-proxy-agent@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" - integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== - dependencies: - agent-base "6" - debug "4" - https-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" @@ -4258,6 +4325,14 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +https-proxy-agent@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.0.tgz#75cb70d04811685667183b31ab158d006750418a" + integrity sha512-0euwPCRyAPSgGdzD1IVN9nJYHtBhJwb6XPfbpQcYbPCwrBidX6GzxmchnaF4sfF/jPb74Ojx5g4yTg3sixlyPw== + dependencies: + agent-base "^7.0.2" + debug "4" + humanize-url@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/humanize-url/-/humanize-url-1.0.1.tgz#f4ab99e0d288174ca4e1e50407c55fbae464efff" @@ -4378,6 +4453,16 @@ intl-messageformat@^4.1.2, intl-messageformat@^4.4.0: dependencies: intl-messageformat-parser "^1.8.1" +ip@^1.1.5: + version "1.1.8" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48" + integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg== + +ip@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" + integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== + is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" @@ -5252,6 +5337,11 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lru-cache@^7.14.1: + version "7.18.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" + integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== + lru_map@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" @@ -5530,18 +5620,30 @@ nested-error-stacks@^2.0.0, nested-error-stacks@^2.1.0: resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61" integrity sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug== +netmask@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7" + integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg== + node-fetch@2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== -node-fetch@2.6.7, node-fetch@^2.6.1: +node-fetch@^2.6.1: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" +node-fetch@^2.6.11: + version "2.6.11" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25" + integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w== + dependencies: + whatwg-url "^5.0.0" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -5808,6 +5910,28 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +pac-proxy-agent@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-6.0.3.tgz#61042187093b67aa7dd05b41e4ec7c241a27c428" + integrity sha512-5Hr1KgPDoc21Vn3rsXBirwwDnF/iac1jN/zkpsOYruyT+ZgsUhUOgVwq3v9+ukjZd/yGm/0nzO1fDfl7rkGoHQ== + dependencies: + agent-base "^7.0.2" + debug "^4.3.4" + get-uri "^6.0.1" + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.0" + pac-resolver "^6.0.1" + socks-proxy-agent "^8.0.1" + +pac-resolver@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-6.0.1.tgz#319c182d3db4e6782e79519cb4dd1dda46579292" + integrity sha512-dg497MhVT7jZegPRuOScQ/z0aV/5WR0gTdRu1md+Irs9J9o+ls5jIuxjo1WfaTG+eQQkxyn5HMGvWK+w7EIBkQ== + dependencies: + degenerator "^4.0.1" + ip "^1.1.5" + netmask "^2.0.2" + pako@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/pako/-/pako-2.0.3.tgz#cdf475e31b678565251406de9e759196a0ea7a43" @@ -6067,7 +6191,21 @@ protobufjs@^6.10.0: "@types/node" ">=13.7.0" long "^4.0.0" -proxy-from-env@1.1.0: +proxy-agent@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.2.1.tgz#062df6609a4012fd1c108974865599b61e77abde" + integrity sha512-OIbBKlRAT+ycCm6wAYIzMwPejzRtjy8F3QiDX0eKOA3e4pe3U9F/IvzcHP42bmgQxVv97juG+J8/gx+JIeCX/Q== + dependencies: + agent-base "^7.0.2" + debug "^4.3.4" + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.0" + lru-cache "^7.14.1" + pac-proxy-agent "^6.0.3" + proxy-from-env "^1.1.0" + socks-proxy-agent "^8.0.1" + +proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== @@ -6095,34 +6233,26 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -puppeteer-core@20.1.0, puppeteer-core@^20.1.0: - version "20.1.0" - resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-20.1.0.tgz#c74e21ad642b0adb273da83b4bf444fdecc6500f" - integrity sha512-/xTvabzAN4mnnuYkJCuWNnnEhOb3JrBTa3sY6qVi1wybuIEk5ODRg8Z5PPiKUGiKC9iG7GWOJ5CjF3iuMuxZSA== +puppeteer-core@20.5.0, puppeteer-core@^20.5.0: + version "20.5.0" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-20.5.0.tgz#4b9ccd6c4ca35fe02373bf2147dc75b42ebd22c4" + integrity sha512-9ddHXUQ7jpliGei87zYTuEZYQvFj6Lzk5R8w4vT4gMmNArkEqC5CX72TnVIJiTUbiTpOXJkvMQaXIHYopjdUtQ== dependencies: - "@puppeteer/browsers" "1.0.0" - chromium-bidi "0.4.7" - cross-fetch "3.1.5" + "@puppeteer/browsers" "1.4.1" + chromium-bidi "0.4.11" + cross-fetch "3.1.6" debug "4.3.4" devtools-protocol "0.0.1120988" - extract-zip "2.0.1" - https-proxy-agent "5.0.1" - proxy-from-env "1.1.0" - tar-fs "2.1.1" - unbzip2-stream "1.4.3" ws "8.13.0" -puppeteer@^20.1.0: - version "20.1.0" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-20.1.0.tgz#30331e2729b235b3306a39cab3ad5b0cf2b90e7d" - integrity sha512-kZp1eYScK1IpHxkgnDaFSGKKCzt27iZfsxO6Xlv/cklzYrhobxTK9/PxzCacPCrYnxNQwKwHzHLPOCuSyjw1jg== +puppeteer@^20.5.0: + version "20.5.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-20.5.0.tgz#453f42edb2cb085bb237914c2bcda7938b7ab1c2" + integrity sha512-3j0JShJGDT5z8rfDKf+wZQq3IHxw7JaDAdP7py5H5zOIgmqNG0e8R19y4tFzJ8i2WC4H/0bC51rIrTXyDop1FA== dependencies: - "@puppeteer/browsers" "1.0.0" + "@puppeteer/browsers" "1.4.1" cosmiconfig "8.1.3" - https-proxy-agent "5.0.1" - progress "2.0.3" - proxy-from-env "1.1.0" - puppeteer-core "20.1.0" + puppeteer-core "20.5.0" q@^1.5.1: version "1.5.1" @@ -6618,6 +6748,11 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -6648,6 +6783,23 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +socks-proxy-agent@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.1.tgz#ffc5859a66dac89b0c4dab90253b96705f3e7120" + integrity sha512-59EjPbbgg8U3x62hhKOFVAmySQUcfRQ4C7Q/D5sEHnZTQRrQlNKINks44DMR1gwXp0p4LaVIeccX2KHTTcHVqQ== + dependencies: + agent-base "^7.0.1" + debug "^4.3.4" + socks "^2.7.1" + +socks@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55" + integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== + dependencies: + ip "^2.0.0" + smart-buffer "^4.2.0" + sort-keys@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" @@ -7172,6 +7324,11 @@ tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tslib@^2.0.1: + version "2.5.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" + integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== + tslib@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" @@ -7365,6 +7522,14 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +vm2@^3.9.17: + version "3.9.19" + resolved "https://registry.yarnpkg.com/vm2/-/vm2-3.9.19.tgz#be1e1d7a106122c6c492b4d51c2e8b93d3ed6a4a" + integrity sha512-J637XF0DHDMV57R6JyVsTak7nIL8gy5KH4r1HiwWLf/4GBbb5MKL5y7LpmF4A8E2nR6XmzpmMFQ7V7ppPTmUQg== + dependencies: + acorn "^8.7.0" + acorn-walk "^8.2.0" + w3c-hr-time@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" From ea4a3e8a8657e986235027354d9e301fd9ca6252 Mon Sep 17 00:00:00 2001 From: Adam Raine <6752989+adamraine@users.noreply.github.com> Date: Fri, 9 Jun 2023 13:35:53 -0700 Subject: [PATCH 08/14] core(inspector-issues): add `federatedAuthUserInfoRequestIssue` (#15149) --- core/gather/gatherers/inspector-issues.js | 1 + core/test/gather/gatherers/inspector-issues-test.js | 4 ++++ package.json | 6 +++--- .../inspector-issueAdded-types-test.js | 1 + types/artifacts.d.ts | 1 + yarn.lock | 8 ++++---- 6 files changed, 14 insertions(+), 7 deletions(-) diff --git a/core/gather/gatherers/inspector-issues.js b/core/gather/gatherers/inspector-issues.js index d98f58b4fd95..c60cfa062eb1 100644 --- a/core/gather/gatherers/inspector-issues.js +++ b/core/gather/gatherers/inspector-issues.js @@ -76,6 +76,7 @@ class InspectorIssues extends FRGatherer { cookieIssue: [], sharedArrayBufferIssue: [], stylesheetLoadingIssue: [], + federatedAuthUserInfoRequestIssue: [], }; const keys = /** @type {Array} */(Object.keys(artifact)); for (const key of keys) { diff --git a/core/test/gather/gatherers/inspector-issues-test.js b/core/test/gather/gatherers/inspector-issues-test.js index d19d170401a9..4f18572c76c8 100644 --- a/core/test/gather/gatherers/inspector-issues-test.js +++ b/core/test/gather/gatherers/inspector-issues-test.js @@ -247,6 +247,7 @@ describe('_getArtifact', () => { sharedArrayBufferIssue: [], federatedAuthRequestIssue: [], stylesheetLoadingIssue: [], + federatedAuthUserInfoRequestIssue: [], }); }); @@ -305,6 +306,7 @@ describe('_getArtifact', () => { sharedArrayBufferIssue: [], federatedAuthRequestIssue: [], stylesheetLoadingIssue: [], + federatedAuthUserInfoRequestIssue: [], }); }); }); @@ -370,6 +372,7 @@ describe('FR compat (inspector-issues)', () => { sharedArrayBufferIssue: [], federatedAuthRequestIssue: [], stylesheetLoadingIssue: [], + federatedAuthUserInfoRequestIssue: [], }); }); @@ -407,6 +410,7 @@ describe('FR compat (inspector-issues)', () => { sharedArrayBufferIssue: [], federatedAuthRequestIssue: [], stylesheetLoadingIssue: [], + federatedAuthUserInfoRequestIssue: [], }); }); }); diff --git a/package.json b/package.json index c3008712a367..826191260af9 100644 --- a/package.json +++ b/package.json @@ -191,7 +191,7 @@ "chrome-launcher": "^0.15.2", "configstore": "^5.0.1", "csp_evaluator": "1.1.1", - "devtools-protocol": "0.0.1154250", + "devtools-protocol": "0.0.1155343", "enquirer": "^2.3.6", "http-link-header": "^1.1.1", "intl-messageformat": "^4.4.0", @@ -215,8 +215,8 @@ "yargs-parser": "^21.0.0" }, "resolutions": { - "puppeteer/**/devtools-protocol": "0.0.1154250", - "puppeteer-core/**/devtools-protocol": "0.0.1154250" + "puppeteer/**/devtools-protocol": "0.0.1155343", + "puppeteer-core/**/devtools-protocol": "0.0.1155343" }, "repository": "GoogleChrome/lighthouse", "keywords": [ diff --git a/third-party/chromium-synchronization/inspector-issueAdded-types-test.js b/third-party/chromium-synchronization/inspector-issueAdded-types-test.js index 33dd1fc919b5..c4b617a49434 100644 --- a/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +++ b/third-party/chromium-synchronization/inspector-issueAdded-types-test.js @@ -41,6 +41,7 @@ Array [ "corsIssueDetails", "deprecationIssueDetails", "federatedAuthRequestIssueDetails", + "federatedAuthUserInfoRequestIssueDetails", "genericIssueDetails", "heavyAdIssueDetails", "lowTextContrastIssueDetails", diff --git a/types/artifacts.d.ts b/types/artifacts.d.ts index 3a9b8a395820..ae56d2c5585e 100644 --- a/types/artifacts.d.ts +++ b/types/artifacts.d.ts @@ -619,6 +619,7 @@ declare module Artifacts { cookieIssue: Crdp.Audits.CookieIssueDetails[]; sharedArrayBufferIssue: Crdp.Audits.SharedArrayBufferIssueDetails[]; stylesheetLoadingIssue: Crdp.Audits.StylesheetLoadingIssueDetails[]; + federatedAuthUserInfoRequestIssue: Crdp.Audits.FederatedAuthUserInfoRequestIssueDetails[]; } // Computed artifact types below. diff --git a/yarn.lock b/yarn.lock index 67df7b7cf7bc..b778f71940f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3045,10 +3045,10 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -devtools-protocol@0.0.1120988, devtools-protocol@0.0.1154250: - version "0.0.1154250" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1154250.tgz#cb3a06e2c8bb07f977c1dc08a781e14a9dd1b3e8" - integrity sha512-ETduFBWzd+g4WL8iVpMTmeMDI0NfkjURd3rhO2mTKkL6wM54xNeIXBlIrsG3LPfxltQU7YRICvO++LHIflPXSQ== +devtools-protocol@0.0.1120988, devtools-protocol@0.0.1155343: + version "0.0.1155343" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1155343.tgz#9e4ce46e9b05a1be6d6b629fbfaa1a38b1c18a3b" + integrity sha512-oD9vGBV2wTc7fAzAM6KC0chSgs234V8+qDEeK+mcbRj2UvcuA7lgBztGi/opj/iahcXD3BSj8Ymvib628yy9FA== diff-sequences@^28.0.2: version "28.0.2" From 333a6674613dd739382be0525f6a399cc0a2dc65 Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Fri, 9 Jun 2023 15:42:22 -0700 Subject: [PATCH 09/14] deps(es-main): update to 1.2.0 (#15121) --- package.json | 2 +- types/internal/es-main.d.ts | 18 ------------------ yarn.lock | 8 ++++---- 3 files changed, 5 insertions(+), 23 deletions(-) delete mode 100644 types/internal/es-main.d.ts diff --git a/package.json b/package.json index 826191260af9..58d306038894 100644 --- a/package.json +++ b/package.json @@ -143,7 +143,7 @@ "cpy": "^8.1.2", "cross-env": "^7.0.2", "csv-validator": "^0.0.3", - "es-main": "^1.0.2", + "es-main": "^1.2.0", "eslint": "^8.4.1", "eslint-config-google": "^0.14.0", "eslint-formatter-codeframe": "^7.32.1", diff --git a/types/internal/es-main.d.ts b/types/internal/es-main.d.ts deleted file mode 100644 index 08e56fa064a7..000000000000 --- a/types/internal/es-main.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @license Copyright 2021 The Lighthouse Authors. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - */ - -/** - * @fileoverview Types for the `es-main` npm module. - */ - -/** - * Test if an ES module is run directly with Node.js. - * @param importMeta `import.meta` - */ -declare function esMain(importMeta: ImportMeta): boolean; -declare module 'es-main' { - export = esMain; -} diff --git a/yarn.lock b/yarn.lock index b778f71940f5..709ff9a02d61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3188,10 +3188,10 @@ es-abstract@^1.19.0, es-abstract@^1.19.1: string.prototype.trimstart "^1.0.4" unbox-primitive "^1.0.1" -es-main@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/es-main/-/es-main-1.0.2.tgz#c9030d78796f609f865b66f4125a78d77fec3de3" - integrity sha512-LLgW8Cby/FiyQygrI23q2EswulHiDKoyjWlDRgTGXjQ3iRim2R26VfoehpxI5oKRXSNams3L/80KtggoUdxdDQ== +es-main@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/es-main/-/es-main-1.2.0.tgz#b85954f1d9d9f542fcb08685ec19515f969bad16" + integrity sha512-A4tCSY43O/mH4rHjG1n0mI4DhK2BmKDr8Lk8PXK/GBB6zxGFGmIW4bbkbTQ2Gi9iNamMZ9vbGrwjZOIeiM7vMw== es-module-lexer@^0.10.5: version "0.10.5" From 1bae93393f7b4cfd3700703f882183f03dc3afda Mon Sep 17 00:00:00 2001 From: Adam Raine <6752989+adamraine@users.noreply.github.com> Date: Mon, 12 Jun 2023 12:42:47 -0700 Subject: [PATCH 10/14] core(largest-contentful-paint-element): display LCP value (#15061) --- .../test-definitions/dobetterweb.js | 2 +- .../test-definitions/perf-trace-elements.js | 2 +- .../largest-contentful-paint-element.js | 80 ++++++++++++------- .../largest-contentful-paint-element-test.js | 11 ++- .../reports/sample-flow-result.json | 46 +++++------ core/test/results/sample_v2.json | 30 +++---- 6 files changed, 93 insertions(+), 78 deletions(-) diff --git a/cli/test/smokehouse/test-definitions/dobetterweb.js b/cli/test/smokehouse/test-definitions/dobetterweb.js index 4ea441f676ee..1d10dc576ea2 100644 --- a/cli/test/smokehouse/test-definitions/dobetterweb.js +++ b/cli/test/smokehouse/test-definitions/dobetterweb.js @@ -599,7 +599,7 @@ const expectations = { }, 'largest-contentful-paint-element': { score: null, - displayValue: '1 element found', + displayValue: /\d+\xa0ms/, details: { items: [ { diff --git a/cli/test/smokehouse/test-definitions/perf-trace-elements.js b/cli/test/smokehouse/test-definitions/perf-trace-elements.js index 79b8cb3fd0d7..4491dd576f97 100644 --- a/cli/test/smokehouse/test-definitions/perf-trace-elements.js +++ b/cli/test/smokehouse/test-definitions/perf-trace-elements.js @@ -144,7 +144,7 @@ const expectations = { audits: { 'largest-contentful-paint-element': { score: null, - displayValue: '1 element found', + displayValue: /\d+\xa0ms/, details: { items: { 0: { diff --git a/core/audits/largest-contentful-paint-element.js b/core/audits/largest-contentful-paint-element.js index 0931a744f2f8..b92bccfd9096 100644 --- a/core/audits/largest-contentful-paint-element.js +++ b/core/audits/largest-contentful-paint-element.js @@ -50,19 +50,44 @@ class LargestContentfulPaintElement extends Audit { } /** - * @param {LH.Artifacts} artifacts + * @param {LH.Artifacts.MetricComputationDataInput} metricComputationData * @param {LH.Audit.Context} context - * @return {Promise} + * @return {Promise} */ - static async makePhaseTable(artifacts, context) { - const trace = artifacts.traces[Audit.DEFAULT_PASS]; - const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS]; - const gatherContext = artifacts.GatherContext; - const metricComputationData = {trace, devtoolsLog, gatherContext, - settings: context.settings, URL: artifacts.URL}; + static async getOptionalLCPMetric(metricComputationData, context) { + try { + const {timing: metricLcp} = + await LargestContentfulPaint.request(metricComputationData, context); + return metricLcp; + } catch {} + } + + /** + * @param {LH.Artifacts} artifacts + * @return {LH.Audit.Details.Table|undefined} + */ + static makeElementTable(artifacts) { + const lcpElement = artifacts.TraceElements + .find(element => element.traceEventType === 'largest-contentful-paint'); + if (!lcpElement) return; + + /** @type {LH.Audit.Details.Table['headings']} */ + const headings = [ + {key: 'node', valueType: 'node', label: str_(i18n.UIStrings.columnElement)}, + ]; - const {timing: metricLcp} = - await LargestContentfulPaint.request(metricComputationData, context); + const lcpElementDetails = [{node: Audit.makeNodeItem(lcpElement.node)}]; + + return Audit.makeTableDetails(headings, lcpElementDetails); + } + + /** + * @param {number} metricLcp + * @param {LH.Artifacts.MetricComputationDataInput} metricComputationData + * @param {LH.Audit.Context} context + * @return {Promise} + */ + static async makePhaseTable(metricLcp, metricComputationData, context) { const {ttfb, loadStart, loadEnd} = await LCPBreakdown.request(metricComputationData, context); let loadDelay = 0; @@ -102,36 +127,29 @@ class LargestContentfulPaintElement extends Audit { * @return {Promise} */ static async audit(artifacts, context) { - const lcpElement = artifacts.TraceElements - .find(element => element.traceEventType === 'largest-contentful-paint'); - const lcpElementDetails = []; - if (lcpElement) { - lcpElementDetails.push({ - node: Audit.makeNodeItem(lcpElement.node), - }); - } - - /** @type {LH.Audit.Details.Table['headings']} */ - const headings = [ - {key: 'node', valueType: 'node', label: str_(i18n.UIStrings.columnElement)}, - ]; + const trace = artifacts.traces[Audit.DEFAULT_PASS]; + const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS]; + const gatherContext = artifacts.GatherContext; + const metricComputationData = {trace, devtoolsLog, gatherContext, + settings: context.settings, URL: artifacts.URL}; - const elementTable = Audit.makeTableDetails(headings, lcpElementDetails); + const elementTable = this.makeElementTable(artifacts); + if (!elementTable) return {score: null, notApplicable: true}; const items = [elementTable]; - if (elementTable.items.length) { - const phaseTable = await this.makePhaseTable(artifacts, context); - if (phaseTable) items.push(phaseTable); + let displayValue; + + const metricLcp = await this.getOptionalLCPMetric(metricComputationData, context); + if (metricLcp) { + displayValue = str_(i18n.UIStrings.ms, {timeInMs: metricLcp}); + const phaseTable = await this.makePhaseTable(metricLcp, metricComputationData, context); + items.push(phaseTable); } const details = Audit.makeListDetails(items); - const displayValue = str_(i18n.UIStrings.displayValueElementsFound, - {nodeCount: lcpElementDetails.length}); - return { score: 1, - notApplicable: lcpElementDetails.length === 0, displayValue, details, }; diff --git a/core/test/audits/largest-contentful-paint-element-test.js b/core/test/audits/largest-contentful-paint-element-test.js index ae27f38bc27c..5ecdcb3f0734 100644 --- a/core/test/audits/largest-contentful-paint-element-test.js +++ b/core/test/audits/largest-contentful-paint-element-test.js @@ -101,8 +101,8 @@ describe('Performance: largest-contentful-paint-element audit', () => { const auditResult = await LargestContentfulPaintElementAudit.audit(artifacts, context); expect(auditResult.score).toEqual(1); - expect(auditResult.notApplicable).toEqual(false); - expect(auditResult.displayValue).toBeDisplayString('1 element found'); + expect(auditResult.notApplicable).toBeUndefined(); + expect(auditResult.displayValue).toBeDisplayString('5,800\xa0ms'); expect(auditResult.details.items).toHaveLength(2); expect(auditResult.details.items[0].items).toHaveLength(1); expect(auditResult.details.items[0].items[0].node.path).toEqual('1,HTML,3,BODY,5,DIV,0,HEADER'); @@ -145,10 +145,9 @@ describe('Performance: largest-contentful-paint-element audit', () => { const context = {settings: artifacts.settings, computedCache: new Map()}; const auditResult = await LargestContentfulPaintElementAudit.audit(artifacts, context); - expect(auditResult.score).toEqual(1); + expect(auditResult.score).toEqual(null); expect(auditResult.notApplicable).toEqual(true); - expect(auditResult.displayValue).toBeDisplayString('0 elements found'); - expect(auditResult.details.items).toHaveLength(1); - expect(auditResult.details.items[0].items).toHaveLength(0); + expect(auditResult.displayValue).toBeUndefined(); + expect(auditResult.details).toBeUndefined(); }); }); diff --git a/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json b/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json index f2f4d32f8183..fd6bdbbc87fb 100644 --- a/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json +++ b/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json @@ -1541,7 +1541,7 @@ "description": "This is the largest contentful element painted within the viewport. [Learn more about the Largest Contentful Paint element](https://developer.chrome.com/docs/lighthouse/performance/lighthouse-largest-contentful-paint/)", "score": null, "scoreDisplayMode": "informative", - "displayValue": "1 element found", + "displayValue": "1,350 ms", "details": { "type": "list", "items": [ @@ -6700,6 +6700,12 @@ "timeInMs": 22.397999999999982 }, "path": "audits[network-server-latency].displayValue" + }, + { + "values": { + "timeInMs": 1352.107 + }, + "path": "audits[largest-contentful-paint-element].displayValue" } ], "core/lib/i18n/i18n.js | maxPotentialFIDMetric": [ @@ -7016,20 +7022,6 @@ "core/audits/largest-contentful-paint-element.js | description": [ "audits[largest-contentful-paint-element].description" ], - "core/lib/i18n/i18n.js | displayValueElementsFound": [ - { - "values": { - "nodeCount": 1 - }, - "path": "audits[largest-contentful-paint-element].displayValue" - }, - { - "values": { - "nodeCount": 5 - }, - "path": "audits[layout-shift-elements].displayValue" - } - ], "core/lib/i18n/i18n.js | columnElement": [ "audits[largest-contentful-paint-element].details.items[0].headings[0].label", "audits[lcp-lazy-loaded].details.headings[0].label", @@ -7069,6 +7061,14 @@ "core/audits/layout-shift-elements.js | description": [ "audits[layout-shift-elements].description" ], + "core/lib/i18n/i18n.js | displayValueElementsFound": [ + { + "values": { + "nodeCount": 5 + }, + "path": "audits[layout-shift-elements].displayValue" + } + ], "core/audits/layout-shift-elements.js | columnContribution": [ "audits[layout-shift-elements].details.headings[1].label" ], @@ -18213,7 +18213,7 @@ "description": "This is the largest contentful element painted within the viewport. [Learn more about the Largest Contentful Paint element](https://developer.chrome.com/docs/lighthouse/performance/lighthouse-largest-contentful-paint/)", "score": null, "scoreDisplayMode": "informative", - "displayValue": "1 element found", + "displayValue": "1,800 ms", "details": { "type": "list", "items": [ @@ -23415,6 +23415,12 @@ "timeInMs": 3.5377 }, "path": "audits[network-server-latency].displayValue" + }, + { + "values": { + "timeInMs": 1803.0092 + }, + "path": "audits[largest-contentful-paint-element].displayValue" } ], "core/lib/i18n/i18n.js | maxPotentialFIDMetric": [ @@ -23733,14 +23739,6 @@ "core/audits/largest-contentful-paint-element.js | description": [ "audits[largest-contentful-paint-element].description" ], - "core/lib/i18n/i18n.js | displayValueElementsFound": [ - { - "values": { - "nodeCount": 1 - }, - "path": "audits[largest-contentful-paint-element].displayValue" - } - ], "core/lib/i18n/i18n.js | columnElement": [ "audits[largest-contentful-paint-element].details.items[0].headings[0].label", "audits[lcp-lazy-loaded].details.headings[0].label", diff --git a/core/test/results/sample_v2.json b/core/test/results/sample_v2.json index fba8b5b92136..4096658d059c 100644 --- a/core/test/results/sample_v2.json +++ b/core/test/results/sample_v2.json @@ -2309,7 +2309,7 @@ "description": "This is the largest contentful element painted within the viewport. [Learn more about the Largest Contentful Paint element](https://developer.chrome.com/docs/lighthouse/performance/lighthouse-largest-contentful-paint/)", "score": null, "scoreDisplayMode": "informative", - "displayValue": "1 element found", + "displayValue": "13,320 ms", "details": { "type": "list", "items": [ @@ -9009,6 +9009,12 @@ "timeInMs": 582.2760000000001 }, "path": "audits[network-server-latency].displayValue" + }, + { + "values": { + "timeInMs": 13319.961 + }, + "path": "audits[largest-contentful-paint-element].displayValue" } ], "core/lib/i18n/i18n.js | maxPotentialFIDMetric": [ @@ -9429,20 +9435,6 @@ "core/audits/largest-contentful-paint-element.js | description": [ "audits[largest-contentful-paint-element].description" ], - "core/lib/i18n/i18n.js | displayValueElementsFound": [ - { - "values": { - "nodeCount": 1 - }, - "path": "audits[largest-contentful-paint-element].displayValue" - }, - { - "values": { - "nodeCount": 5 - }, - "path": "audits[layout-shift-elements].displayValue" - } - ], "core/lib/i18n/i18n.js | columnElement": [ "audits[largest-contentful-paint-element].details.items[0].headings[0].label", "audits[layout-shift-elements].details.headings[0].label", @@ -9482,6 +9474,14 @@ "core/audits/layout-shift-elements.js | description": [ "audits[layout-shift-elements].description" ], + "core/lib/i18n/i18n.js | displayValueElementsFound": [ + { + "values": { + "nodeCount": 5 + }, + "path": "audits[layout-shift-elements].displayValue" + } + ], "core/audits/layout-shift-elements.js | columnContribution": [ "audits[layout-shift-elements].details.headings[1].label" ], From c741df0cca8fee85aec67a82d1b2233a74e75535 Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Mon, 12 Jun 2023 12:56:50 -0700 Subject: [PATCH 11/14] core(time-to-first-byte): use receiveHeadersStart (#15126) --- core/computed/metrics/time-to-first-byte.js | 14 ++++++++------ core/lib/network-request.js | 16 ++++++++++++++++ .../computed/metrics/time-to-first-byte-test.js | 2 +- core/test/lib/network-request-test.js | 13 ++++++++++++- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/core/computed/metrics/time-to-first-byte.js b/core/computed/metrics/time-to-first-byte.js index 74ac7ff5b172..40de6b061cae 100644 --- a/core/computed/metrics/time-to-first-byte.js +++ b/core/computed/metrics/time-to-first-byte.js @@ -41,15 +41,17 @@ class TimeToFirstByte extends NavigationMetric { * @return {Promise} */ static async computeObservedMetric(data, context) { - const {processedNavigation} = data; - const timeOriginTs = processedNavigation.timestamps.timeOrigin; const mainResource = await MainResource.request(data, context); + if (!mainResource.timing) { + throw new Error('missing timing for main resource'); + } - // Technically TTFB is the start of the response headers not the end. - // That signal isn't available to us so we use header end time as a best guess. - const timestamp = mainResource.responseHeadersEndTime * 1000; + const {processedNavigation} = data; + const timeOriginTs = processedNavigation.timestamps.timeOrigin; + const timestampMs = + mainResource.timing.requestTime * 1000 + mainResource.timing.receiveHeadersStart; + const timestamp = timestampMs * 1000; const timing = (timestamp - timeOriginTs) / 1000; - return {timing, timestamp}; } } diff --git a/core/lib/network-request.js b/core/lib/network-request.js index 990b64e12c30..f7fa5345c0a5 100644 --- a/core/lib/network-request.js +++ b/core/lib/network-request.js @@ -274,6 +274,7 @@ class NetworkRequest { } this._updateResponseHeadersEndTimeIfNecessary(); + this._backfillReceiveHeaderStartTiming(); this._updateTransferSizeForLightrider(); this._updateTimingsForLightrider(); } @@ -293,6 +294,7 @@ class NetworkRequest { this.localizedFailDescription = data.errorText; this._updateResponseHeadersEndTimeIfNecessary(); + this._backfillReceiveHeaderStartTiming(); this._updateTransferSizeForLightrider(); this._updateTimingsForLightrider(); } @@ -315,6 +317,7 @@ class NetworkRequest { this.networkEndTime = data.timestamp * 1000; this._updateResponseHeadersEndTimeIfNecessary(); + this._backfillReceiveHeaderStartTiming(); } /** @@ -449,6 +452,19 @@ class NetworkRequest { } } + /** + * TODO(compat): remove M116. + * `timing.receiveHeadersStart` was added recently, and will be in M116. Until then, + * set it to receiveHeadersEnd, which is close enough, to allow consumers of NetworkRequest + * to use the new field without accounting for this backcompat. + */ + _backfillReceiveHeaderStartTiming() { + // Do nothing if a value is already present! + if (!this.timing || this.timing.receiveHeadersStart !== undefined) return; + + this.timing.receiveHeadersStart = this.timing.receiveHeadersEnd; + } + /** * LR gets additional, accurate timing information from its underlying fetch infrastructure. This * is passed in via X-Headers similar to 'X-TotalFetchedSize'. diff --git a/core/test/computed/metrics/time-to-first-byte-test.js b/core/test/computed/metrics/time-to-first-byte-test.js index d257d6562c50..e2f111200910 100644 --- a/core/test/computed/metrics/time-to-first-byte-test.js +++ b/core/test/computed/metrics/time-to-first-byte-test.js @@ -53,7 +53,7 @@ function mockNetworkRecords() { networkRequestTime: 300, responseHeadersEndTime: 400, networkEndTime: 500, - timing: {sendEnd: 0, receiveHeadersEnd: 100}, + timing: {sendEnd: 0, receiveHeadersStart: 100}, transferSize: 16_000, url: mainDocumentUrl, frameId: 'ROOT_FRAME', diff --git a/core/test/lib/network-request-test.js b/core/test/lib/network-request-test.js index c22888443ec9..cf963de66851 100644 --- a/core/test/lib/network-request-test.js +++ b/core/test/lib/network-request-test.js @@ -13,6 +13,17 @@ describe('NetworkRequest', () => { global.isLightrider = undefined; }); + it('backcompat for receiveHeadersStart', function() { + const req = { + timing: {receiveHeadersEnd: 123}, + }; + const devtoolsLog = networkRecordsToDevtoolsLog([req]); + const record = NetworkRecorder.recordsFromLogs(devtoolsLog)[0]; + + expect(record.timing.receiveHeadersStart).toEqual(123); + expect(record.timing.receiveHeadersEnd).toEqual(123); + }); + describe('update transfer size for Lightrider', () => { function getRequest() { return { @@ -108,7 +119,7 @@ describe('NetworkRequest', () => { }); }); - describe('update fetch stats for Lightrider', () => { + describe('update timings for Lightrider', () => { function getRequest() { return { rendererStartTime: 0, From 0464a56eb6a2a097269c321b1fb53dd8c08e364c Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Mon, 12 Jun 2023 13:00:14 -0700 Subject: [PATCH 12/14] core(cumulative-layout-shift): remove totalCumulativeLayoutShift (#15122) --- .../__snapshots__/report-assert-test.js.snap | 10 ++++------ .../test-definitions/perf-frame-metrics.js | 1 - core/audits/metrics.js | 2 -- .../metrics/cumulative-layout-shift.js | 16 +--------------- core/computed/metrics/timing-summary.js | 3 --- .../audits/__snapshots__/metrics-test.js.snap | 10 ---------- core/test/audits/metrics-test.js | 17 +---------------- .../metrics/cumulative-layout-shift-test.js | 1 - .../metrics/cumulative-layout-shift-test.js | 18 ------------------ .../computed/metrics/timing-summary-test.js | 2 -- .../reports/sample-flow-result.json | 13 +++---------- core/test/results/sample_v2.json | 5 +---- types/artifacts.d.ts | 2 -- 13 files changed, 10 insertions(+), 90 deletions(-) diff --git a/cli/test/smokehouse/__snapshots__/report-assert-test.js.snap b/cli/test/smokehouse/__snapshots__/report-assert-test.js.snap index f6cbcce93b08..1dc0c6c3d68a 100644 --- a/cli/test/smokehouse/__snapshots__/report-assert-test.js.snap +++ b/cli/test/smokehouse/__snapshots__/report-assert-test.js.snap @@ -3,7 +3,7 @@ exports[`getAssertionReport works (multiple failing) 1`] = ` "X difference at cumulative-layout-shift audit.details.items.length expected: [] - found: [{\\"cumulativeLayoutShiftMainFrame\\":0.13570762803819444,\\"totalCumulativeLayoutShift\\":0.13570762803819444}] + found: [{\\"cumulativeLayoutShiftMainFrame\\":0.13570762803819444}] X difference at cumulative-layout-shift audit.details.blah @@ -24,8 +24,7 @@ exports[`getAssertionReport works (multiple failing) 1`] = ` \\"type\\": \\"debugdata\\", \\"items\\": [ { - \\"cumulativeLayoutShiftMainFrame\\": 0.13570762803819444, - \\"totalCumulativeLayoutShift\\": 0.13570762803819444 + \\"cumulativeLayoutShiftMainFrame\\": 0.13570762803819444 } ] } @@ -35,7 +34,7 @@ exports[`getAssertionReport works (multiple failing) 1`] = ` exports[`getAssertionReport works (trivial failing) 1`] = ` "X difference at cumulative-layout-shift audit.details.items.length expected: [] - found: [{\\"cumulativeLayoutShiftMainFrame\\":0.13570762803819444,\\"totalCumulativeLayoutShift\\":0.13570762803819444}] + found: [{\\"cumulativeLayoutShiftMainFrame\\":0.13570762803819444}] found result: { @@ -51,8 +50,7 @@ exports[`getAssertionReport works (trivial failing) 1`] = ` \\"type\\": \\"debugdata\\", \\"items\\": [ { - \\"cumulativeLayoutShiftMainFrame\\": 0.13570762803819444, - \\"totalCumulativeLayoutShift\\": 0.13570762803819444 + \\"cumulativeLayoutShiftMainFrame\\": 0.13570762803819444 } ] } diff --git a/cli/test/smokehouse/test-definitions/perf-frame-metrics.js b/cli/test/smokehouse/test-definitions/perf-frame-metrics.js index 1031528cf33e..b82be5a9d119 100644 --- a/cli/test/smokehouse/test-definitions/perf-frame-metrics.js +++ b/cli/test/smokehouse/test-definitions/perf-frame-metrics.js @@ -78,7 +78,6 @@ const expectations = { largestContentfulPaintAllFrames: '<5000', cumulativeLayoutShift: '0.133 +/- 0.001', cumulativeLayoutShiftMainFrame: '0.001 +/- 0.0005', - totalCumulativeLayoutShift: '0.001 +/- 0.0005', }, { lcpInvalidated: false, diff --git a/core/audits/metrics.js b/core/audits/metrics.js index b69f04ecb19d..d8c61020fa0a 100644 --- a/core/audits/metrics.js +++ b/core/audits/metrics.js @@ -11,10 +11,8 @@ import {TimingSummary} from '../computed/metrics/timing-summary.js'; const DECIMAL_METRIC_KEYS = new Set([ 'cumulativeLayoutShift', 'cumulativeLayoutShiftMainFrame', - 'totalCumulativeLayoutShift', 'observedCumulativeLayoutShift', 'observedCumulativeLayoutShiftMainFrame', - 'observedTotalCumulativeLayoutShift', ]); class Metrics extends Audit { diff --git a/core/computed/metrics/cumulative-layout-shift.js b/core/computed/metrics/cumulative-layout-shift.js index 122417a39e61..9f95547d2507 100644 --- a/core/computed/metrics/cumulative-layout-shift.js +++ b/core/computed/metrics/cumulative-layout-shift.js @@ -101,19 +101,10 @@ class CumulativeLayoutShift { return maxScore; } - /** - * Sum all layout shift events from the entire trace. - * @param {Array} layoutShiftEvents - * @return {number} - */ - static calculateTotalCumulativeLayoutShift(layoutShiftEvents) { - return layoutShiftEvents.reduce((sum, e) => sum += e.weightedScore, 0); - } - /** * @param {LH.Trace} trace * @param {LH.Artifacts.ComputedContext} context - * @return {Promise<{cumulativeLayoutShift: number, cumulativeLayoutShiftMainFrame: number, totalCumulativeLayoutShift: number}>} + * @return {Promise<{cumulativeLayoutShift: number, cumulativeLayoutShiftMainFrame: number}>} */ static async compute_(trace, context) { const processedTrace = await ProcessedTrace.request(trace, context); @@ -122,14 +113,9 @@ class CumulativeLayoutShift { CumulativeLayoutShift.getLayoutShiftEvents(processedTrace); const mainFrameShiftEvents = allFrameShiftEvents.filter(e => e.isMainFrame); - // The original Cumulative Layout Shift metric, the sum of all main-frame shift events. - const totalCumulativeLayoutShift = - CumulativeLayoutShift.calculateTotalCumulativeLayoutShift(mainFrameShiftEvents); - return { cumulativeLayoutShift: CumulativeLayoutShift.calculate(allFrameShiftEvents), cumulativeLayoutShiftMainFrame: CumulativeLayoutShift.calculate(mainFrameShiftEvents), - totalCumulativeLayoutShift, }; } } diff --git a/core/computed/metrics/timing-summary.js b/core/computed/metrics/timing-summary.js index bbbfebcd694c..6e7a856e88c2 100644 --- a/core/computed/metrics/timing-summary.js +++ b/core/computed/metrics/timing-summary.js @@ -65,7 +65,6 @@ class TimingSummary { const { cumulativeLayoutShift, cumulativeLayoutShiftMainFrame, - totalCumulativeLayoutShift, } = cumulativeLayoutShiftValues || {}; /** @type {LH.Artifacts.TimingSummary} */ @@ -89,7 +88,6 @@ class TimingSummary { maxPotentialFID: maxPotentialFID?.timing, cumulativeLayoutShift, cumulativeLayoutShiftMainFrame, - totalCumulativeLayoutShift, lcpLoadStart: lcpBreakdown?.loadStart, lcpLoadEnd: lcpBreakdown?.loadEnd, @@ -123,7 +121,6 @@ class TimingSummary { observedDomContentLoadedTs: processedNavigation?.timestamps.domContentLoaded, observedCumulativeLayoutShift: cumulativeLayoutShift, observedCumulativeLayoutShiftMainFrame: cumulativeLayoutShiftMainFrame, - observedTotalCumulativeLayoutShift: totalCumulativeLayoutShift, // Include some visual metrics from speedline observedFirstVisualChange: speedline.first, diff --git a/core/test/audits/__snapshots__/metrics-test.js.snap b/core/test/audits/__snapshots__/metrics-test.js.snap index 2783540127c9..f6b9bf215404 100644 --- a/core/test/audits/__snapshots__/metrics-test.js.snap +++ b/core/test/audits/__snapshots__/metrics-test.js.snap @@ -47,7 +47,6 @@ Object { "observedSpeedIndexTs": 760623438456, "observedTimeOrigin": 0, "observedTimeOriginTs": 760620643599, - "observedTotalCumulativeLayoutShift": 0, "observedTraceEnd": 4778, "observedTraceEndTs": 760625421283, "speedIndex": 6313, @@ -55,7 +54,6 @@ Object { "timeToFirstByte": 2394, "timeToFirstByteTs": undefined, "totalBlockingTime": 162, - "totalCumulativeLayoutShift": 0, } `; @@ -106,7 +104,6 @@ Object { "observedSpeedIndexTs": 23467605703, "observedTimeOrigin": 0, "observedTimeOriginTs": 23466023130, - "observedTotalCumulativeLayoutShift": undefined, "observedTraceEnd": 6006, "observedTraceEndTs": 23472029453, "speedIndex": 1583, @@ -114,7 +111,6 @@ Object { "timeToFirstByte": 565, "timeToFirstByteTs": 23466588051, "totalBlockingTime": 0, - "totalCumulativeLayoutShift": undefined, } `; @@ -165,7 +161,6 @@ Object { "observedSpeedIndexTs": 713038416494, "observedTimeOrigin": 0, "observedTimeOriginTs": 713037023064, - "observedTotalCumulativeLayoutShift": 0, "observedTraceEnd": 7416, "observedTraceEndTs": 713044439102, "speedIndex": 3683, @@ -173,7 +168,6 @@ Object { "timeToFirstByte": 611, "timeToFirstByteTs": undefined, "totalBlockingTime": 1205, - "totalCumulativeLayoutShift": 0, } `; @@ -224,7 +218,6 @@ Object { "observedSpeedIndexTs": 225414776724, "observedTimeOrigin": 0, "observedTimeOriginTs": 225414172015, - "observedTotalCumulativeLayoutShift": 0, "observedTraceEnd": 12540, "observedTraceEndTs": 225426711887, "speedIndex": 605, @@ -232,7 +225,6 @@ Object { "timeToFirstByte": 261, "timeToFirstByteTs": 225414432704, "totalBlockingTime": 48, - "totalCumulativeLayoutShift": 0, } `; @@ -283,7 +275,6 @@ Object { "observedSpeedIndexTs": 225414776724, "observedTimeOrigin": 0, "observedTimeOriginTs": 225414172015, - "observedTotalCumulativeLayoutShift": 0, "observedTraceEnd": 12540, "observedTraceEndTs": 225426711887, "speedIndex": 1676, @@ -291,6 +282,5 @@ Object { "timeToFirstByte": 760, "timeToFirstByteTs": undefined, "totalBlockingTime": 777, - "totalCumulativeLayoutShift": 0, } `; diff --git a/core/test/audits/metrics-test.js b/core/test/audits/metrics-test.js index e44d42ae7342..23a6615a0ffe 100644 --- a/core/test/audits/metrics-test.js +++ b/core/test/audits/metrics-test.js @@ -150,15 +150,11 @@ describe('Performance: metrics', () => { const {details} = await MetricsAudit.audit(artifacts, context); expect(details.items[0]).toMatchObject({ cumulativeLayoutShift: undefined, - cumulativeLayoutShiftMainFrame: undefined, - totalCumulativeLayoutShift: undefined, observedCumulativeLayoutShift: undefined, - observedCumulativeLayoutShiftMainFrame: undefined, - observedTotalCumulativeLayoutShift: undefined, }); }); - it('evaluates new CLS correctly across all frames', async () => { + it('evaluates CLS correctly across all frames', async () => { const URL = getURLArtifactFromDevtoolsLog(clsAllFramesDevtoolsLog); const artifacts = { URL, @@ -177,15 +173,9 @@ describe('Performance: metrics', () => { }; const {details} = await MetricsAudit.audit(artifacts, context); - // Only a single main-frame shift event, so mfCls and oldCls are equal. expect(details.items[0]).toMatchObject({ cumulativeLayoutShift: expect.toBeApproximately(0.026463, 6), - cumulativeLayoutShiftMainFrame: expect.toBeApproximately(0.001166, 6), - totalCumulativeLayoutShift: expect.toBeApproximately(0.001166, 6), - observedCumulativeLayoutShift: expect.toBeApproximately(0.026463, 6), - observedCumulativeLayoutShiftMainFrame: expect.toBeApproximately(0.001166, 6), - observedTotalCumulativeLayoutShift: expect.toBeApproximately(0.001166, 6), }); }); @@ -232,12 +222,7 @@ describe('Performance: metrics', () => { const {details} = await MetricsAudit.audit(artifacts, context); expect(details.items[0]).toMatchObject({ cumulativeLayoutShift: expect.toBeApproximately(2.268816, 6), - cumulativeLayoutShiftMainFrame: expect.toBeApproximately(2.268816, 6), - totalCumulativeLayoutShift: expect.toBeApproximately(4.809794, 6), - observedCumulativeLayoutShift: expect.toBeApproximately(2.268816, 6), - observedCumulativeLayoutShiftMainFrame: expect.toBeApproximately(2.268816, 6), - observedTotalCumulativeLayoutShift: expect.toBeApproximately(4.809794, 6), }); }); }); diff --git a/core/test/audits/metrics/cumulative-layout-shift-test.js b/core/test/audits/metrics/cumulative-layout-shift-test.js index 92f32ba65868..a60bd3938468 100644 --- a/core/test/audits/metrics/cumulative-layout-shift-test.js +++ b/core/test/audits/metrics/cumulative-layout-shift-test.js @@ -32,7 +32,6 @@ describe('Cumulative Layout Shift', () => { type: 'debugdata', items: [{ cumulativeLayoutShiftMainFrame: expect.toBeApproximately(2.268816, 6), - totalCumulativeLayoutShift: expect.toBeApproximately(4.809794, 6), }], }, }); diff --git a/core/test/computed/metrics/cumulative-layout-shift-test.js b/core/test/computed/metrics/cumulative-layout-shift-test.js index 230d18cdf337..8f880154199a 100644 --- a/core/test/computed/metrics/cumulative-layout-shift-test.js +++ b/core/test/computed/metrics/cumulative-layout-shift-test.js @@ -26,7 +26,6 @@ describe('Metrics: CLS', () => { expect(result).toEqual({ cumulativeLayoutShift: expect.toBeApproximately(2.268816, 6), cumulativeLayoutShiftMainFrame: expect.toBeApproximately(2.268816, 6), - totalCumulativeLayoutShift: expect.toBeApproximately(4.809794, 6), }); }); @@ -40,7 +39,6 @@ describe('Metrics: CLS', () => { expect(result).toEqual({ cumulativeLayoutShift: 0.026463014612806653, cumulativeLayoutShiftMainFrame: 0.0011656245471340055, - totalCumulativeLayoutShift: 0.0011656245471340055, }); }); @@ -49,7 +47,6 @@ describe('Metrics: CLS', () => { expect(result).toEqual({ cumulativeLayoutShift: 0, cumulativeLayoutShiftMainFrame: 0, - totalCumulativeLayoutShift: 0, }); }); }); @@ -123,7 +120,6 @@ describe('Metrics: CLS', () => { expect(result).toEqual({ cumulativeLayoutShift: 4, cumulativeLayoutShiftMainFrame: 4, - totalCumulativeLayoutShift: 4, }); }); @@ -140,7 +136,6 @@ describe('Metrics: CLS', () => { expect(result).toEqual({ cumulativeLayoutShift: 3, cumulativeLayoutShiftMainFrame: 3, - totalCumulativeLayoutShift: 3, }); }); @@ -158,7 +153,6 @@ describe('Metrics: CLS', () => { expect(result).toEqual({ cumulativeLayoutShift: 0.75, cumulativeLayoutShiftMainFrame: 0.75, - totalCumulativeLayoutShift: 3.75, // 30 * 0.125 }); }); @@ -183,7 +177,6 @@ describe('Metrics: CLS', () => { expect(result).toEqual({ cumulativeLayoutShift: 1.0625, cumulativeLayoutShiftMainFrame: 1.0625, - totalCumulativeLayoutShift: 1.375, }); }); @@ -201,7 +194,6 @@ describe('Metrics: CLS', () => { expect(result).toEqual({ cumulativeLayoutShift: 3.75, // 30 * 0.125 cumulativeLayoutShiftMainFrame: 3.75, - totalCumulativeLayoutShift: 3.75, }); }); @@ -225,7 +217,6 @@ describe('Metrics: CLS', () => { expect(result).toEqual({ cumulativeLayoutShift: 3, cumulativeLayoutShiftMainFrame: 3, - totalCumulativeLayoutShift: 3, }); }); }); @@ -246,7 +237,6 @@ describe('Metrics: CLS', () => { expect(result).toEqual({ cumulativeLayoutShift: 0.75, // Same value as single-frame uniformly distributed. cumulativeLayoutShiftMainFrame: 0.125, // All 1s gaps, so only one event per cluster. - totalCumulativeLayoutShift: 1.875, // 0.125 * 15 }); }); @@ -275,7 +265,6 @@ describe('Metrics: CLS', () => { expect(result).toMatchObject({ cumulativeLayoutShift: 4, cumulativeLayoutShiftMainFrame: 2, - totalCumulativeLayoutShift: 2, }); }); @@ -330,7 +319,6 @@ describe('Metrics: CLS', () => { expect(result).toMatchObject({ cumulativeLayoutShift: 5, cumulativeLayoutShiftMainFrame: 3, - totalCumulativeLayoutShift: 3, }); }); @@ -346,7 +334,6 @@ describe('Metrics: CLS', () => { expect(result).toMatchObject({ cumulativeLayoutShift: 4, cumulativeLayoutShiftMainFrame: 2, - totalCumulativeLayoutShift: 2, }); }); @@ -375,7 +362,6 @@ describe('Metrics: CLS', () => { expect(result).toMatchObject({ cumulativeLayoutShift: 3, cumulativeLayoutShiftMainFrame: 1, - totalCumulativeLayoutShift: 1, }); }); }); @@ -395,7 +381,6 @@ describe('Metrics: CLS', () => { expect(result).toMatchObject({ cumulativeLayoutShift: 6, cumulativeLayoutShiftMainFrame: 6, - totalCumulativeLayoutShift: 6, }); }); @@ -414,7 +399,6 @@ describe('Metrics: CLS', () => { expect(result).toMatchObject({ cumulativeLayoutShift: 6, cumulativeLayoutShiftMainFrame: 1, - totalCumulativeLayoutShift: 4, }); }); @@ -428,7 +412,6 @@ describe('Metrics: CLS', () => { expect(result).toMatchObject({ cumulativeLayoutShift: 2, cumulativeLayoutShiftMainFrame: 2, - totalCumulativeLayoutShift: 2, }); }); @@ -442,7 +425,6 @@ describe('Metrics: CLS', () => { expect(result).toMatchObject({ cumulativeLayoutShift: 2, cumulativeLayoutShiftMainFrame: 1, - totalCumulativeLayoutShift: 1, }); }); }); diff --git a/core/test/computed/metrics/timing-summary-test.js b/core/test/computed/metrics/timing-summary-test.js index 8ceb358ed6e2..49336fc6d910 100644 --- a/core/test/computed/metrics/timing-summary-test.js +++ b/core/test/computed/metrics/timing-summary-test.js @@ -66,7 +66,6 @@ describe('Timing summary', () => { "observedSpeedIndexTs": 10328522489.12, "observedTimeOrigin": 0, "observedTimeOriginTs": 10327187909, - "observedTotalCumulativeLayoutShift": 0.0011656245471340055, "observedTraceEnd": 14214.313, "observedTraceEndTs": 10341402222, "speedIndex": 1335, @@ -74,7 +73,6 @@ describe('Timing summary', () => { "timeToFirstByte": 570.329, "timeToFirstByteTs": 10327758238, "totalBlockingTime": 2.7429999999994834, - "totalCumulativeLayoutShift": 0.0011656245471340055, } `); // Includes performance metrics diff --git a/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json b/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json index fd6bdbbc87fb..af6ffcb5e3fa 100644 --- a/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json +++ b/core/test/fixtures/fraggle-rock/reports/sample-flow-result.json @@ -186,8 +186,7 @@ "type": "debugdata", "items": [ { - "cumulativeLayoutShiftMainFrame": 0.002631263732910156, - "totalCumulativeLayoutShift": 0.002631263732910156 + "cumulativeLayoutShiftMainFrame": 0.002631263732910156 } ] } @@ -1318,7 +1317,6 @@ "maxPotentialFID": 193, "cumulativeLayoutShift": 0.002631263732910156, "cumulativeLayoutShiftMainFrame": 0.002631263732910156, - "totalCumulativeLayoutShift": 0.002631263732910156, "lcpLoadStart": 985, "lcpLoadEnd": 1062, "timeToFirstByte": 615, @@ -1346,7 +1344,6 @@ "observedDomContentLoadedTs": 183713237485, "observedCumulativeLayoutShift": 0.002631263732910156, "observedCumulativeLayoutShiftMainFrame": 0.002631263732910156, - "observedTotalCumulativeLayoutShift": 0.002631263732910156, "observedFirstVisualChange": 341, "observedFirstVisualChangeTs": 183713323617, "observedLastVisualChange": 575, @@ -8071,8 +8068,7 @@ "type": "debugdata", "items": [ { - "cumulativeLayoutShiftMainFrame": 0.13125, - "totalCumulativeLayoutShift": 0.13125 + "cumulativeLayoutShiftMainFrame": 0.13125 } ] } @@ -16911,8 +16907,7 @@ "type": "debugdata", "items": [ { - "cumulativeLayoutShiftMainFrame": 0, - "totalCumulativeLayoutShift": 0 + "cumulativeLayoutShiftMainFrame": 0 } ] } @@ -18007,7 +18002,6 @@ "maxPotentialFID": 76, "cumulativeLayoutShift": 0, "cumulativeLayoutShiftMainFrame": 0, - "totalCumulativeLayoutShift": 0, "lcpLoadStart": 603, "lcpLoadEnd": 837, "timeToFirstByte": 603, @@ -18035,7 +18029,6 @@ "observedDomContentLoadedTs": 183729805229, "observedCumulativeLayoutShift": 0, "observedCumulativeLayoutShiftMainFrame": 0, - "observedTotalCumulativeLayoutShift": 0, "observedFirstVisualChange": 89, "observedFirstVisualChangeTs": 183729849318, "observedLastVisualChange": 505, diff --git a/core/test/results/sample_v2.json b/core/test/results/sample_v2.json index 4096658d059c..5c77b04d1d2a 100644 --- a/core/test/results/sample_v2.json +++ b/core/test/results/sample_v2.json @@ -200,8 +200,7 @@ "type": "debugdata", "items": [ { - "cumulativeLayoutShiftMainFrame": 0.13570762803819444, - "totalCumulativeLayoutShift": 0.13570762803819444 + "cumulativeLayoutShiftMainFrame": 0.13570762803819444 } ] } @@ -1942,7 +1941,6 @@ "maxPotentialFID": 1175, "cumulativeLayoutShift": 0.13570762803819444, "cumulativeLayoutShiftMainFrame": 0.13570762803819444, - "totalCumulativeLayoutShift": 0.13570762803819444, "lcpLoadStart": 10849, "lcpLoadEnd": 12900, "timeToFirstByte": 572, @@ -1971,7 +1969,6 @@ "observedDomContentLoadedTs": 8704886496, "observedCumulativeLayoutShift": 0.13570762803819444, "observedCumulativeLayoutShiftMainFrame": 0.13570762803819444, - "observedTotalCumulativeLayoutShift": 0.13570762803819444, "observedFirstVisualChange": 8058, "observedFirstVisualChangeTs": 8704758822, "observedLastVisualChange": 8893, diff --git a/types/artifacts.d.ts b/types/artifacts.d.ts index ae56d2c5585e..75605685bddb 100644 --- a/types/artifacts.d.ts +++ b/types/artifacts.d.ts @@ -802,7 +802,6 @@ declare module Artifacts { maxPotentialFID: number | undefined; cumulativeLayoutShift: number | undefined; cumulativeLayoutShiftMainFrame: number | undefined; - totalCumulativeLayoutShift: number | undefined; totalBlockingTime: number | undefined; observedTimeOrigin: number; observedTimeOriginTs: number; @@ -810,7 +809,6 @@ declare module Artifacts { observedNavigationStartTs: number | undefined; observedCumulativeLayoutShift: number | undefined; observedCumulativeLayoutShiftMainFrame: number | undefined; - observedTotalCumulativeLayoutShift: number | undefined; observedFirstPaint: number | undefined; observedFirstPaintTs: number | undefined; observedFirstContentfulPaint: number | undefined; From fe61d6a8b18a7f8558eccc35fd0ed96baa6e7f39 Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Mon, 12 Jun 2023 13:49:48 -0700 Subject: [PATCH 13/14] core(server-response-time): use receiveHeadersStart instead of end (#15155) --- core/audits/server-response-time.js | 2 +- core/test/audits/server-response-time-test.js | 29 ++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/core/audits/server-response-time.js b/core/audits/server-response-time.js index 41070d7fb755..cabf8e4b45ec 100644 --- a/core/audits/server-response-time.js +++ b/core/audits/server-response-time.js @@ -46,7 +46,7 @@ class ServerResponseTime extends Audit { */ static calculateResponseTime(record) { const timing = record.timing; - return timing ? timing.receiveHeadersEnd - timing.sendEnd : 0; + return timing ? timing.receiveHeadersStart - timing.sendEnd : 0; } /** diff --git a/core/test/audits/server-response-time-test.js b/core/test/audits/server-response-time-test.js index da57cc502a8e..e8aa072af9e4 100644 --- a/core/test/audits/server-response-time-test.js +++ b/core/test/audits/server-response-time-test.js @@ -11,7 +11,7 @@ describe('Performance: server-response-time audit', () => { const mainResource = { url: 'https://example.com/', requestId: '0', - timing: {receiveHeadersEnd: 830, sendEnd: 200}, + timing: {receiveHeadersStart: 830, sendEnd: 200}, }; const devtoolsLog = networkRecordsToDevtoolsLog([mainResource]); @@ -37,6 +37,33 @@ describe('Performance: server-response-time audit', () => { }); it('succeeds when response time of root document is lower than 600ms', async () => { + const mainResource = { + url: 'https://example.com/', + requestId: '0', + timing: {receiveHeadersStart: 400, sendEnd: 200}, + }; + const devtoolsLog = networkRecordsToDevtoolsLog([mainResource]); + + const artifacts = { + devtoolsLogs: {[ServerResponseTime.DEFAULT_PASS]: devtoolsLog}, + URL: {mainDocumentUrl: 'https://example.com/'}, + GatherContext: {gatherMode: 'navigation'}, + }; + + const result = await ServerResponseTime.audit(artifacts, {computedCache: new Map()}); + expect(result).toMatchObject({ + numericValue: 200, + score: 1, + metricSavings: { + FCP: 100, + LCP: 100, + }, + }); + }); + + // TODO(compat): remove M116. See _backfillReceiveHeaderStartTiming. + // eslint-disable-next-line max-len + it('succeeds when response time of root document is lower than 600ms (receiveHeadersEnd fallback)', async () => { const mainResource = { url: 'https://example.com/', requestId: '0', From 18a8c2824466eb9137468924fcb54db98e376ead Mon Sep 17 00:00:00 2001 From: Connor Clark Date: Mon, 12 Jun 2023 15:13:09 -0700 Subject: [PATCH 14/14] core(network-analyzer): include 0 start times in rtt estimate (#15100) --- .../dependency-graph/simulator/network-analyzer.js | 13 +++++++------ .../fixtures/lantern-baseline-computed-values.json | 4 ++-- .../simulator/network-analyzer-test.js | 14 +++++++++++--- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/core/lib/dependency-graph/simulator/network-analyzer.js b/core/lib/dependency-graph/simulator/network-analyzer.js index d0c2f273f5d9..a1634187776d 100644 --- a/core/lib/dependency-graph/simulator/network-analyzer.js +++ b/core/lib/dependency-graph/simulator/network-analyzer.js @@ -139,14 +139,15 @@ class NetworkAnalyzer { return NetworkAnalyzer._estimateValueByOrigin(records, ({timing, connectionReused, record}) => { if (connectionReused) return; - if (timing.connectEnd > 0 && timing.connectStart > 0 && record.protocol.startsWith('h3')) { + const {connectStart, sslStart, sslEnd, connectEnd} = timing; + if (connectEnd >= 0 && connectStart >= 0 && record.protocol.startsWith('h3')) { // These values are equal to sslStart and sslEnd for h3. - return timing.connectEnd - timing.connectStart; - } else if (timing.sslStart > 0 && timing.sslEnd > 0) { + return connectEnd - connectStart; + } else if (sslStart >= 0 && sslEnd >= 0 && sslStart !== connectStart) { // SSL can also be more than 1 RT but assume False Start was used. - return [timing.connectEnd - timing.sslStart, timing.sslStart - timing.connectStart]; - } else if (timing.connectStart > 0 && timing.connectEnd > 0) { - return timing.connectEnd - timing.connectStart; + return [connectEnd - sslStart, sslStart - connectStart]; + } else if (connectStart >= 0 && connectEnd >= 0) { + return connectEnd - connectStart; } }); } diff --git a/core/test/fixtures/lantern-baseline-computed-values.json b/core/test/fixtures/lantern-baseline-computed-values.json index 447a9cf23794..e89cbc2a2f15 100644 --- a/core/test/fixtures/lantern-baseline-computed-values.json +++ b/core/test/fixtures/lantern-baseline-computed-values.json @@ -4,7 +4,7 @@ {"url": "http://www.zol.com.cn/", "roughEstimateOfFCP": 3296, "optimisticFCP": 3296, "pessimisticFCP": 3296, "roughEstimateOfFMP": 3296, "optimisticFMP": 3296, "pessimisticFMP": 3296, "roughEstimateOfTTI": 15560, "optimisticTTI": 14661, "pessimisticTTI": 16459, "roughEstimateOfSI": 12324, "optimisticSI": 4861, "pessimisticSI": 8876, "roughEstimateOfLCP": 4201, "optimisticLCP": 4123, "pessimisticLCP": 4279, "roughEstimateOfTTFB": 648}, {"url": "https://birdsarentreal.com", "roughEstimateOfFCP": 2950, "optimisticFCP": 2950, "pessimisticFCP": 2950, "roughEstimateOfFMP": 3434, "optimisticFMP": 3111, "pessimisticFMP": 3756, "roughEstimateOfTTI": 13409, "optimisticTTI": 12063, "pessimisticTTI": 14755, "roughEstimateOfSI": 5108, "optimisticSI": 1323, "pessimisticSI": 5393, "roughEstimateOfLCP": 7721, "optimisticLCP": 6959, "pessimisticLCP": 8483, "roughEstimateOfTTFB": 701}, {"url": "https://depositfiles.com/", "roughEstimateOfFCP": 5098, "optimisticFCP": 5098, "pessimisticFCP": 5098, "roughEstimateOfFMP": 5486, "optimisticFMP": 5098, "pessimisticFMP": 5874, "roughEstimateOfTTI": 5982, "optimisticTTI": 5854, "pessimisticTTI": 6109, "roughEstimateOfSI": 7568, "optimisticSI": 2787, "pessimisticSI": 6025, "roughEstimateOfLCP": 6034, "optimisticLCP": 6034, "pessimisticLCP": 6034, "roughEstimateOfTTFB": 907}, - {"url": "https://en-maktoob.yahoo.com/?p=xa", "roughEstimateOfFCP": 1350, "optimisticFCP": 1350, "pessimisticFCP": 1350, "roughEstimateOfFMP": 1366, "optimisticFMP": 1350, "pessimisticFMP": 1383, "roughEstimateOfTTI": 5816, "optimisticTTI": 5163, "pessimisticTTI": 6470, "roughEstimateOfSI": 3643, "optimisticSI": 1039, "pessimisticSI": 3751, "roughEstimateOfLCP": 6844, "optimisticLCP": 6703, "pessimisticLCP": 6984, "roughEstimateOfTTFB": 618}, + {"url": "https://en-maktoob.yahoo.com/?p=xa", "roughEstimateOfFCP": 1350, "optimisticFCP": 1350, "pessimisticFCP": 1350, "roughEstimateOfFMP": 1366, "optimisticFMP": 1350, "pessimisticFMP": 1383, "roughEstimateOfTTI": 5820, "optimisticTTI": 5166, "pessimisticTTI": 6474, "roughEstimateOfSI": 3644, "optimisticSI": 1039, "pessimisticSI": 3753, "roughEstimateOfLCP": 6848, "optimisticLCP": 6707, "pessimisticLCP": 6990, "roughEstimateOfTTFB": 618}, {"url": "https://en.softonic.com", "roughEstimateOfFCP": 2187, "optimisticFCP": 2187, "pessimisticFCP": 2187, "roughEstimateOfFMP": 2580, "optimisticFMP": 2187, "pessimisticFMP": 2973, "roughEstimateOfTTI": 31124, "optimisticTTI": 26796, "pessimisticTTI": 35453, "roughEstimateOfSI": 12951, "optimisticSI": 3067, "pessimisticSI": 13703, "roughEstimateOfLCP": 3907, "optimisticLCP": 3498, "pessimisticLCP": 4316, "roughEstimateOfTTFB": 899}, {"url": "https://gm.58.com/glsanfrancisco-sl/", "roughEstimateOfFCP": 3019, "optimisticFCP": 3019, "pessimisticFCP": 3019, "roughEstimateOfFMP": 3019, "optimisticFMP": 3019, "pessimisticFMP": 3019, "roughEstimateOfTTI": 4785, "optimisticTTI": 4436, "pessimisticTTI": 5134, "roughEstimateOfSI": 4605, "optimisticSI": 1762, "pessimisticSI": 3674, "roughEstimateOfLCP": 5337, "optimisticLCP": 5045, "pessimisticLCP": 5630, "roughEstimateOfTTFB": 787}, {"url": "https://m.facebook.com/", "roughEstimateOfFCP": 2438, "optimisticFCP": 2407, "pessimisticFCP": 2468, "roughEstimateOfFMP": 2438, "optimisticFMP": 2407, "pessimisticFMP": 2468, "roughEstimateOfTTI": 4822, "optimisticTTI": 4217, "pessimisticTTI": 5427, "roughEstimateOfSI": 2685, "optimisticSI": 479, "pessimisticSI": 3484, "roughEstimateOfLCP": 3422, "optimisticLCP": 3391, "pessimisticLCP": 3452, "roughEstimateOfTTFB": 626}, @@ -28,7 +28,7 @@ {"url": "https://www.att.com/", "roughEstimateOfFCP": 5590, "optimisticFCP": 5139, "pessimisticFCP": 6042, "roughEstimateOfFMP": 5750, "optimisticFMP": 5139, "pessimisticFMP": 6361, "roughEstimateOfTTI": 30035, "optimisticTTI": 27711, "pessimisticTTI": 32359, "roughEstimateOfSI": 9131, "optimisticSI": 1858, "pessimisticSI": 10430, "roughEstimateOfLCP": 13751, "optimisticLCP": 13671, "pessimisticLCP": 13831, "roughEstimateOfTTFB": 651}, {"url": "https://www.bing.com/", "roughEstimateOfFCP": 962, "optimisticFCP": 962, "pessimisticFCP": 962, "roughEstimateOfFMP": 1339, "optimisticFMP": 962, "pessimisticFMP": 1717, "roughEstimateOfTTI": 2491, "optimisticTTI": 2241, "pessimisticTTI": 2741, "roughEstimateOfSI": 1565, "optimisticSI": 467, "pessimisticSI": 1788, "roughEstimateOfLCP": 1548, "optimisticLCP": 1262, "pessimisticLCP": 1834, "roughEstimateOfTTFB": 608}, {"url": "https://www.blogger.com/about/", "roughEstimateOfFCP": 1528, "optimisticFCP": 1528, "pessimisticFCP": 1528, "roughEstimateOfFMP": 2103, "optimisticFMP": 1953, "pessimisticFMP": 2253, "roughEstimateOfTTI": 2245, "optimisticTTI": 2216, "pessimisticTTI": 2274, "roughEstimateOfSI": 6825, "optimisticSI": 4188, "pessimisticSI": 1865, "roughEstimateOfLCP": 2377, "optimisticLCP": 2274, "pessimisticLCP": 2480, "roughEstimateOfTTFB": 603}, - {"url": "https://www.cnet.com/", "roughEstimateOfFCP": 2575, "optimisticFCP": 2215, "pessimisticFCP": 2934, "roughEstimateOfFMP": 2811, "optimisticFMP": 2536, "pessimisticFMP": 3085, "roughEstimateOfTTI": 43130, "optimisticTTI": 39828, "pessimisticTTI": 46433, "roughEstimateOfSI": 15812, "optimisticSI": 1339, "pessimisticSI": 21828, "roughEstimateOfLCP": 4259, "optimisticLCP": 4179, "pessimisticLCP": 4339, "roughEstimateOfTTFB": 608}, + {"url": "https://www.cnet.com/", "roughEstimateOfFCP": 2575, "optimisticFCP": 2215, "pessimisticFCP": 2934, "roughEstimateOfFMP": 2811, "optimisticFMP": 2536, "pessimisticFMP": 3085, "roughEstimateOfTTI": 43130, "optimisticTTI": 39828, "pessimisticTTI": 46433, "roughEstimateOfSI": 15812, "optimisticSI": 1339, "pessimisticSI": 21827, "roughEstimateOfLCP": 4259, "optimisticLCP": 4179, "pessimisticLCP": 4339, "roughEstimateOfTTFB": 608}, {"url": "https://www.codewars.com", "roughEstimateOfFCP": 2239, "optimisticFCP": 2239, "pessimisticFCP": 2239, "roughEstimateOfFMP": 3431, "optimisticFMP": 2407, "pessimisticFMP": 4455, "roughEstimateOfTTI": 8773, "optimisticTTI": 7002, "pessimisticTTI": 10543, "roughEstimateOfSI": 3990, "optimisticSI": 834, "pessimisticSI": 4728, "roughEstimateOfLCP": 9584, "optimisticLCP": 9261, "pessimisticLCP": 9907, "roughEstimateOfTTFB": 609}, {"url": "https://www.dawn.com/", "roughEstimateOfFCP": 2573, "optimisticFCP": 2250, "pessimisticFCP": 2897, "roughEstimateOfFMP": 2816, "optimisticFMP": 2573, "pessimisticFMP": 3059, "roughEstimateOfTTI": 25689, "optimisticTTI": 23528, "pessimisticTTI": 27850, "roughEstimateOfSI": 10403, "optimisticSI": 1332, "pessimisticSI": 13519, "roughEstimateOfLCP": 3868, "optimisticLCP": 3221, "pessimisticLCP": 4516, "roughEstimateOfTTFB": 652}, {"url": "https://www.deviantart.com/", "roughEstimateOfFCP": 2920, "optimisticFCP": 2920, "pessimisticFCP": 2920, "roughEstimateOfFMP": 2920, "optimisticFMP": 2920, "pessimisticFMP": 2920, "roughEstimateOfTTI": 13172, "optimisticTTI": 11356, "pessimisticTTI": 14989, "roughEstimateOfSI": 3085, "optimisticSI": 996, "pessimisticSI": 2986, "roughEstimateOfLCP": 12002, "optimisticLCP": 10543, "pessimisticLCP": 13462, "roughEstimateOfTTFB": 1009}, diff --git a/core/test/lib/dependency-graph/simulator/network-analyzer-test.js b/core/test/lib/dependency-graph/simulator/network-analyzer-test.js index 2a74cca89387..de85462ad8e7 100644 --- a/core/test/lib/dependency-graph/simulator/network-analyzer-test.js +++ b/core/test/lib/dependency-graph/simulator/network-analyzer-test.js @@ -136,7 +136,15 @@ describe('DependencyGraph/Simulator/NetworkAnalyzer', () => { describe('#estimateRTTByOrigin', () => { it('should infer from tcp timing when available', () => { - const timing = {connectStart: 1, connectEnd: 100}; + const timing = {connectStart: 0, connectEnd: 99}; + const record = createRecord({networkRequestTime: 0, networkEndTime: 1, timing}); + const result = NetworkAnalyzer.estimateRTTByOrigin([record]); + const expected = {min: 99, max: 99, avg: 99, median: 99}; + assert.deepStrictEqual(result.get('https://example.com'), expected); + }); + + it('should infer only one estimate if tcp and ssl start times are equal', () => { + const timing = {connectStart: 0, connectEnd: 99, sslStart: 0, sslEnd: 99}; const record = createRecord({networkRequestTime: 0, networkEndTime: 1, timing}); const result = NetworkAnalyzer.estimateRTTByOrigin([record]); const expected = {min: 99, max: 99, avg: 99, median: 99}; @@ -144,7 +152,7 @@ describe('DependencyGraph/Simulator/NetworkAnalyzer', () => { }); it('should infer from tcp and ssl timing when available', () => { - const timing = {connectStart: 1, connectEnd: 100, sslStart: 50, sslEnd: 100}; + const timing = {connectStart: 0, connectEnd: 99, sslStart: 50, sslEnd: 99}; const record = createRecord({networkRequestTime: 0, networkEndTime: 1, timing}); const result = NetworkAnalyzer.estimateRTTByOrigin([record]); const expected = {min: 49, max: 50, avg: 49.5, median: 49.5}; @@ -152,7 +160,7 @@ describe('DependencyGraph/Simulator/NetworkAnalyzer', () => { }); it('should infer from connection timing when available for h3 (one estimate)', () => { - const timing = {connectStart: 1, connectEnd: 100, sslStart: 1, sslEnd: 100}; + const timing = {connectStart: 0, connectEnd: 99, sslStart: 1, sslEnd: 99}; const record = createRecord({networkRequestTime: 0, networkEndTime: 1, timing, protocol: 'h3'}); const result = NetworkAnalyzer.estimateRTTByOrigin([record]);