diff --git a/core/audits/third-party-summary.js b/core/audits/third-party-summary.js index bb2fc70d3073..d0898f256a50 100644 --- a/core/audits/third-party-summary.js +++ b/core/audits/third-party-summary.js @@ -101,10 +101,13 @@ class ThirdPartySummary extends Audit { const taskDuration = task.selfTime * cpuMultiplier; // The amount of time spent on main thread is the sum of all durations. urlSummary.mainThreadTime += taskDuration; - // The amount of time spent *blocking* on main thread is the sum of all time longer than 50ms. - // Note that this is not totally equivalent to the TBT definition since it fails to account for FCP, - // but a majority of third-party work occurs after FCP and should yield largely similar numbers. - urlSummary.blockingTime += Math.max(taskDuration - 50, 0); + // Blocking time is the amount of time spent on the main thread *over* 50ms. + // This value is interpolated because not all tasks attributed to this URL are at the top level. + // + // Note that this is not totally equivalent to the TBT definition since it fails to account for + // the FCP&TTI bounds of TBT. + urlSummary.blockingTime += task.selfBlockingTime; + // TBT impact is similar to blocking time, but it accounts for the FCP&TTI bounds of TBT. urlSummary.tbtImpact += task.selfTbtImpact; byURL.set(attributableURL, urlSummary); } diff --git a/core/computed/metrics/lantern-first-contentful-paint.js b/core/computed/metrics/lantern-first-contentful-paint.js index f3b441c2183e..cfa300981218 100644 --- a/core/computed/metrics/lantern-first-contentful-paint.js +++ b/core/computed/metrics/lantern-first-contentful-paint.js @@ -16,8 +16,8 @@ class LanternFirstContentfulPaint extends Lantern.Metrics.FirstContentfulPaint { * @return {Promise} */ static async computeMetricWithGraphs(data, context, extras) { - return this.compute(await getComputationDataParams(data, context), extras) - .catch(lanternErrorAdapter); + const params = await getComputationDataParams(data, context); + return Promise.resolve(this.compute(params, extras)).catch(lanternErrorAdapter); } /** diff --git a/core/computed/metrics/lantern-interactive.js b/core/computed/metrics/lantern-interactive.js index 51abaa9edbc0..d0e4e346b8ff 100644 --- a/core/computed/metrics/lantern-interactive.js +++ b/core/computed/metrics/lantern-interactive.js @@ -17,8 +17,8 @@ class LanternInteractive extends Lantern.Metrics.Interactive { * @return {Promise} */ static async computeMetricWithGraphs(data, context, extras) { - return this.compute(await getComputationDataParams(data, context), extras) - .catch(lanternErrorAdapter); + const params = await getComputationDataParams(data, context); + return Promise.resolve(this.compute(params, extras)).catch(lanternErrorAdapter); } /** diff --git a/core/computed/metrics/lantern-largest-contentful-paint.js b/core/computed/metrics/lantern-largest-contentful-paint.js index 77c26c2e3b35..b52162c14526 100644 --- a/core/computed/metrics/lantern-largest-contentful-paint.js +++ b/core/computed/metrics/lantern-largest-contentful-paint.js @@ -17,8 +17,8 @@ class LanternLargestContentfulPaint extends Lantern.Metrics.LargestContentfulPai * @return {Promise} */ static async computeMetricWithGraphs(data, context, extras) { - return this.compute(await getComputationDataParams(data, context), extras) - .catch(lanternErrorAdapter); + const params = await getComputationDataParams(data, context); + return Promise.resolve(this.compute(params, extras)).catch(lanternErrorAdapter); } /** diff --git a/core/computed/metrics/lantern-max-potential-fid.js b/core/computed/metrics/lantern-max-potential-fid.js index 3d9580420406..bcbf308ba523 100644 --- a/core/computed/metrics/lantern-max-potential-fid.js +++ b/core/computed/metrics/lantern-max-potential-fid.js @@ -17,8 +17,8 @@ class LanternMaxPotentialFID extends Lantern.Metrics.MaxPotentialFID { * @return {Promise} */ static async computeMetricWithGraphs(data, context, extras) { - return this.compute(await getComputationDataParams(data, context), extras) - .catch(lanternErrorAdapter); + const params = await getComputationDataParams(data, context); + return Promise.resolve(this.compute(params, extras)).catch(lanternErrorAdapter); } /** diff --git a/core/computed/metrics/lantern-speed-index.js b/core/computed/metrics/lantern-speed-index.js index 9197fb93cd6c..53a621ad8ca8 100644 --- a/core/computed/metrics/lantern-speed-index.js +++ b/core/computed/metrics/lantern-speed-index.js @@ -18,8 +18,8 @@ class LanternSpeedIndex extends Lantern.Metrics.SpeedIndex { * @return {Promise} */ static async computeMetricWithGraphs(data, context, extras) { - return this.compute(await getComputationDataParams(data, context), extras) - .catch(lanternErrorAdapter); + const params = await getComputationDataParams(data, context); + return Promise.resolve(this.compute(params, extras)).catch(lanternErrorAdapter); } /** diff --git a/core/computed/tbt-impact-tasks.js b/core/computed/tbt-impact-tasks.js index 1a8097cff1f7..0d5a9ab636b7 100644 --- a/core/computed/tbt-impact-tasks.js +++ b/core/computed/tbt-impact-tasks.js @@ -64,8 +64,9 @@ class TBTImpactTasks { /** * @param {LH.Artifacts.TaskNode[]} tasks * @param {Map} taskToImpact + * @param {Map} taskToBlockingTime */ - static createImpactTasks(tasks, taskToImpact) { + static createImpactTasks(tasks, taskToImpact, taskToBlockingTime) { /** @type {LH.Artifacts.TBTImpactTask[]} */ const tbtImpactTasks = []; @@ -73,15 +74,25 @@ class TBTImpactTasks { const tbtImpact = taskToImpact.get(task) || 0; let selfTbtImpact = tbtImpact; + const blockingTime = taskToBlockingTime.get(task) || 0; + let selfBlockingTime = blockingTime; + for (const child of task.children) { const childTbtImpact = taskToImpact.get(child) || 0; selfTbtImpact -= childTbtImpact; + + const childBlockingTime = taskToBlockingTime.get(child) || 0; + selfBlockingTime -= childBlockingTime; } tbtImpactTasks.push({ ...task, - tbtImpact, - selfTbtImpact, + // Floating point numbers are not perfectly precise, so the subtraction operations above + // can sometimes output negative numbers close to 0 here. To prevent potentially confusing + // output we should bump those values to 0. + tbtImpact: Math.max(tbtImpact, 0), + selfTbtImpact: Math.max(selfTbtImpact, 0), + selfBlockingTime: Math.max(selfBlockingTime, 0), }); } @@ -98,6 +109,9 @@ class TBTImpactTasks { /** @type {Map} */ const taskToImpact = new Map(); + /** @type {Map} */ + const taskToBlockingTime = new Map(); + for (const task of tasks) { const event = { start: task.startTime, @@ -113,11 +127,13 @@ class TBTImpactTasks { }; const tbtImpact = calculateTbtImpactForEvent(event, startTimeMs, endTimeMs, topLevelEvent); + const blockingTime = calculateTbtImpactForEvent(event, -Infinity, Infinity, topLevelEvent); taskToImpact.set(task, tbtImpact); + taskToBlockingTime.set(task, blockingTime); } - return this.createImpactTasks(tasks, taskToImpact); + return this.createImpactTasks(tasks, taskToImpact, taskToBlockingTime); } /** @@ -131,6 +147,9 @@ class TBTImpactTasks { /** @type {Map} */ const taskToImpact = new Map(); + /** @type {Map} */ + const taskToBlockingTime = new Map(); + /** @type {Map} */ const topLevelTaskToEvent = new Map(); @@ -151,19 +170,21 @@ class TBTImpactTasks { }; const tbtImpact = calculateTbtImpactForEvent(event, startTimeMs, endTimeMs); + const blockingTime = calculateTbtImpactForEvent(event, -Infinity, Infinity); const task = traceEventToTask.get(node.event); if (!task) continue; topLevelTaskToEvent.set(task, event); taskToImpact.set(task, tbtImpact); + taskToBlockingTime.set(task, blockingTime); } // Interpolate the TBT impact of remaining tasks using the top level ancestor tasks. // We don't have any lantern estimates for tasks that are not top level, so we need to estimate // the lantern timing based on the task's observed timing relative to it's top level task's observed timing. for (const task of tasks) { - if (taskToImpact.has(task)) continue; + if (taskToImpact.has(task) || taskToBlockingTime.has(task)) continue; const topLevelTask = this.getTopLevelTask(task); @@ -183,11 +204,13 @@ class TBTImpactTasks { }; const tbtImpact = calculateTbtImpactForEvent(event, startTimeMs, endTimeMs, topLevelEvent); + const blockingTime = calculateTbtImpactForEvent(event, -Infinity, Infinity, topLevelEvent); taskToImpact.set(task, tbtImpact); + taskToBlockingTime.set(task, blockingTime); } - return this.createImpactTasks(tasks, taskToImpact); + return this.createImpactTasks(tasks, taskToImpact, taskToBlockingTime); } /** diff --git a/core/computed/trace-engine-result.js b/core/computed/trace-engine-result.js index b9f26e530e34..464ce46a53ac 100644 --- a/core/computed/trace-engine-result.js +++ b/core/computed/trace-engine-result.js @@ -19,7 +19,16 @@ class TraceEngineResult { * @return {Promise} */ static async runTraceEngine(traceEvents) { - const processor = TraceEngine.TraceProcessor.createWithAllHandlers(); + const traceHandlers = {...TraceEngine.TraceHandlers}; + + // @ts-expect-error Temporarily disable this handler + // It's not currently used anywhere in trace engine insights or Lighthouse. + // TODO: Re-enable this when its memory usage is improved in the trace engine + // https://github.com/GoogleChrome/lighthouse/issues/16111 + delete traceHandlers.Invalidations; + + const processor = new TraceEngine.TraceProcessor(traceHandlers); + // eslint-disable-next-line max-len await processor.parse(/** @type {import('@paulirish/trace_engine').Types.TraceEvents.TraceEventData[]} */ ( traceEvents diff --git a/core/scripts/roll-to-devtools.sh b/core/scripts/roll-to-devtools.sh index 5417522073ed..fe3acb8bf32b 100755 --- a/core/scripts/roll-to-devtools.sh +++ b/core/scripts/roll-to-devtools.sh @@ -80,6 +80,20 @@ lh_e2e_res_dir="third-party/devtools-tests/e2e/resources/lighthouse/" fe_e2e_res_dir="$dt_dir/test/e2e/resources/lighthouse" rsync -avh "$lh_e2e_res_dir" "$fe_e2e_res_dir" --exclude="OWNERS" --delete +PKG_VERSION=$(node -e "console.log(require('./package.json').version)") +REVISION=$(git rev-parse HEAD) +echo "Name: Lighthouse +Short Name: lighthouse +Version: $PKG_VERSION +Revision: $REVISION +URL: https://github.com/GoogleChrome/lighthouse +License: Apache License 2.0 +License File: LICENSE +Security Critical: no +Shipped: yes + +This directory contains Chromium's version of the lighthouse report assets, including renderer." > "$fe_lh_dir/README.chromium" + echo "" echo "Done. To run the e2e tests: " echo " DEVTOOLS_PATH=\"$dt_dir\" yarn test-devtools" diff --git a/core/test/audits/__snapshots__/third-party-summary-test.js.snap b/core/test/audits/__snapshots__/third-party-summary-test.js.snap index 88264c1716c6..3cb28ba2f1f6 100644 --- a/core/test/audits/__snapshots__/third-party-summary-test.js.snap +++ b/core/test/audits/__snapshots__/third-party-summary-test.js.snap @@ -3,13 +3,13 @@ exports[`Third party summary surface the discovered third parties 1`] = ` Array [ Object { - "blockingTime": 223.56, + "blockingTime": 225.30612021679366, "entity": "Wunderkind", "mainThreadTime": 879.9769999999949, "subItems": Object { "items": Array [ Object { - "blockingTime": 223.56, + "blockingTime": 225.30612021679366, "mainThreadTime": 287.06299999999925, "tbtImpact": 225.30612021679366, "transferSize": 16051, @@ -547,13 +547,13 @@ Array [ "transferSize": 450838, }, Object { - "blockingTime": 21.476, + "blockingTime": 64.66899999999367, "entity": "Google/Doubleclick Ads", "mainThreadTime": 347.9769999999987, "subItems": Object { "items": Array [ Object { - "blockingTime": 21.476, + "blockingTime": 64.66899999999367, "mainThreadTime": 339.7179999999987, "tbtImpact": 10.898000000000135, "transferSize": 145049, @@ -1118,6 +1118,25 @@ Array [ "tbtImpact": 10.898000000000135, "transferSize": 571412, }, + Object { + "blockingTime": 8.445999999999897, + "entity": "script.ac", + "mainThreadTime": 462.9409999999911, + "subItems": Object { + "items": Array [ + Object { + "blockingTime": 8.445999999999897, + "mainThreadTime": 462.9409999999911, + "tbtImpact": 8.445999999999897, + "transferSize": 50609, + "url": "https://cadmus.script.ac/d2uap9jskdzp2/script.js", + }, + ], + "type": "subitems", + }, + "tbtImpact": 8.445999999999897, + "transferSize": 50609, + }, Object { "blockingTime": 0, "entity": "gobankingrates.com", @@ -3343,25 +3362,6 @@ Array [ "tbtImpact": 0, "transferSize": 68466, }, - Object { - "blockingTime": 0, - "entity": "script.ac", - "mainThreadTime": 462.9409999999911, - "subItems": Object { - "items": Array [ - Object { - "blockingTime": 0, - "mainThreadTime": 462.9409999999911, - "tbtImpact": 8.445999999999897, - "transferSize": 50609, - "url": "https://cadmus.script.ac/d2uap9jskdzp2/script.js", - }, - ], - "type": "subitems", - }, - "tbtImpact": 8.445999999999897, - "transferSize": 50609, - }, Object { "blockingTime": 0, "entity": "myfinance.com", diff --git a/core/test/audits/third-party-facades-test.js b/core/test/audits/third-party-facades-test.js index cbf6f8c3334f..a503faf65ad5 100644 --- a/core/test/audits/third-party-facades-test.js +++ b/core/test/audits/third-party-facades-test.js @@ -468,7 +468,7 @@ Array [ expect(results.score).toBe(0); expect(results.metricSavings).toEqual({TBT: 145}); expect(results.displayValue).toBeDisplayString('1 facade alternative available'); - expect(results.details.items[0].blockingTime).toEqual(134.076); // TBT impact is not equal to the blocking time + expect(results.details.items[0].blockingTime).toBeCloseTo(145); expect(results.details.items[0].product) .toBeDisplayString('Intercom Widget (Customer Success)'); }); diff --git a/core/test/audits/third-party-summary-test.js b/core/test/audits/third-party-summary-test.js index cf88472fc139..f8fffb49fd49 100644 --- a/core/test/audits/third-party-summary-test.js +++ b/core/test/audits/third-party-summary-test.js @@ -26,10 +26,10 @@ describe('Third party summary', () => { settings.throttlingMethod = 'devtools'; const results = await ThirdPartySummary.audit(artifacts, {computedCache: new Map(), settings}); - expect(results.score).toBe(1); + expect(results.score).toBe(0); expect(results.metricSavings).toEqual({TBT: 245}); expect(results.displayValue).toBeDisplayString( - 'Third-party code blocked the main thread for 250 ms' + 'Third-party code blocked the main thread for 300 ms' ); expect(results.details.items).toMatchSnapshot(); }); @@ -49,9 +49,9 @@ describe('Third party summary', () => { expect(results.metricSavings).toEqual({TBT: 2570}); expect(results.details.items).toHaveLength(145); expect(Math.round(results.details.items[0].mainThreadTime)).toEqual(3520); - expect(Math.round(results.details.items[0].blockingTime)).toEqual(1103); + expect(Math.round(results.details.items[0].blockingTime)).toEqual(1182); expect(Math.round(results.details.items[1].mainThreadTime)).toEqual(1392); - expect(Math.round(results.details.items[1].blockingTime)).toEqual(659); + expect(Math.round(results.details.items[1].blockingTime)).toEqual(508); }); it('be not applicable when no third parties are present', async () => { diff --git a/core/test/computed/tbt-impact-tasks-test.js b/core/test/computed/tbt-impact-tasks-test.js index bfed8fff3ffc..3a2d9c8c79d1 100644 --- a/core/test/computed/tbt-impact-tasks-test.js +++ b/core/test/computed/tbt-impact-tasks-test.js @@ -12,8 +12,8 @@ import {createTestTrace, rootFrame} from '../create-test-trace.js'; import {networkRecordsToDevtoolsLog} from '../network-records-to-devtools-log.js'; import {MainThreadTasks} from '../../computed/main-thread-tasks.js'; -const trace = readJson('../fixtures/traces/lcp-m78.json', import.meta); -const devtoolsLog = readJson('../fixtures/traces/lcp-m78.devtools.log.json', import.meta); +const trace = readJson('../fixtures/artifacts/cnn/defaultPass.trace.json.gz', import.meta); +const devtoolsLog = readJson('../fixtures/artifacts/cnn/defaultPass.devtoolslog.json.gz', import.meta); describe('TBTImpactTasks', () => { const mainDocumentUrl = 'https://example.com'; @@ -115,23 +115,28 @@ describe('TBTImpactTasks', () => { expect(tbtImpactTasks).toMatchObject([ { tbtImpact: 3750, // 4000 (dur) - 200 (FCP cutoff) - 50 (blocking threshold) + selfBlockingTime: 2962.5, // 4000 (dur) - 50 (blocking threshold) - 493.75 - 493.75 selfTbtImpact: 2862.5, // 3750 - 393.75 - 493.75 }, { tbtImpact: 393.75, // 500 (dur) - 100 (FCP cutoff) - 6.25 (50 * 500 / 4000) + selfBlockingTime: 493.75, // 500 (dur) - 6.25 (50 * 500 / 4000) selfTbtImpact: 393.75, // No children }, { tbtImpact: 493.75, // 500 (dur) - 6.25 (50 * 500 / 4000) + selfBlockingTime: 493.75, // 500 (dur) - 6.25 (50 * 500 / 4000) selfTbtImpact: 493.75, // No children }, { tbtImpact: 950, // 3000 (dur) - 2000 (TTI cutoff) - 50 + selfBlockingTime: 2950, // 3000 (dur) - 50 (blocking threshold) selfTbtImpact: 950, // No children }, { // Included in test trace by default tbtImpact: 0, + selfBlockingTime: 0, selfTbtImpact: 0, }, ]); @@ -203,23 +208,28 @@ describe('TBTImpactTasks', () => { expect(tbtImpactTasks).toMatchObject([ { tbtImpact: 15_150, // 16_000 (dur) - 800 (FCP cutoff) - 50 (blocking threshold) - selfTbtImpact: 11562.5, // 15_150 - 1593.75 - 1993.75 + selfBlockingTime: 11_962.5, // 16_000 (dur) - 50 (blocking threshold) - 1993.75 - 1993.75 + selfTbtImpact: 11_562.5, // 15_150 - 1593.75 - 1993.75 }, { tbtImpact: 1593.75, // 2000 (dur) - 400 (FCP cutoff) - 6.25 (50 * 2000 / 16_000) + selfBlockingTime: 1993.75, // 2000 (dur) - 6.25 (50 * 2000 / 16_000) selfTbtImpact: 1593.75, // No children }, { tbtImpact: 1993.75, // 2000 (dur) - 6.25 (50 * 2000 / 16_000) + selfBlockingTime: 1993.75, // 2000 (dur) - 6.25 (50 * 2000 / 16_000) selfTbtImpact: 1993.75, // No children }, { tbtImpact: 3950, // 12_000 (dur) - 8000 (TTI cutoff) - 50 + selfBlockingTime: 11_950, // 12_000 (dur) - 50 selfTbtImpact: 3950, // No children }, { // Included in test trace by default tbtImpact: 0, + selfBlockingTime: 0, selfTbtImpact: 0, }, ]); @@ -241,7 +251,7 @@ describe('TBTImpactTasks', () => { expect(tasks.every(t => t.selfTbtImpact >= 0)).toBeTruthy(); const tasksImpactingTbt = tasks.filter(t => t.tbtImpact); - expect(tasksImpactingTbt.length).toMatchInlineSnapshot(`59`); + expect(tasksImpactingTbt.length).toMatchInlineSnapshot(`7374`); // Only tasks with no children should have a `selfTbtImpact` that equals `tbtImpact` if // `tbtImpact` is nonzero. @@ -250,7 +260,13 @@ describe('TBTImpactTasks', () => { expect(tasksWithNoChildren).toEqual(tasksWithAllSelfImpact); const totalSelfImpact = tasksImpactingTbt.reduce((sum, t) => sum += t.selfTbtImpact, 0); - expect(totalSelfImpact).toMatchInlineSnapshot(`1234`); + expect(totalSelfImpact).toMatchInlineSnapshot(`2819.9999999999577`); + + // Total self blocking time is just the total self impact without factoring in the TBT + // bounds, so it should always be greater than or equal to the total TBT self impact. + const totalSelfBlockingTime = tasksImpactingTbt + .reduce((sum, t) => sum += t.selfBlockingTime, 0); + expect(totalSelfImpact).toBeGreaterThanOrEqual(totalSelfBlockingTime); // The total self TBT impact of every task should equal the total TBT impact of just the top level tasks. const topLevelTasks = tasksImpactingTbt.filter(t => !t.parent); @@ -281,10 +297,11 @@ describe('TBTImpactTasks', () => { }; const tasks = await TBTImpactTasks.request(metricComputationData, context); + expect(tasks.every(t => t.selfTbtImpact >= 0)).toBeTruthy(); const tasksImpactingTbt = tasks.filter(t => t.tbtImpact); - expect(tasksImpactingTbt.length).toMatchInlineSnapshot(`5`); + expect(tasksImpactingTbt.length).toMatchInlineSnapshot(`1722`); // Only tasks with no children should have a `selfTbtImpact` that equals `tbtImpact` if // `tbtImpact` is nonzero. @@ -293,7 +310,13 @@ describe('TBTImpactTasks', () => { expect(tasksWithNoChildren).toEqual(tasksWithAllSelfImpact); const totalSelfImpact = tasksImpactingTbt.reduce((sum, t) => sum += t.selfTbtImpact, 0); - expect(totalSelfImpact).toMatchInlineSnapshot(`333.0050000000001`); + expect(totalSelfImpact).toMatchInlineSnapshot(`400.039`); + + // Total self blocking time is just the total self impact without factoring in the TBT + // bounds, so it should always be greater than or equal to the total TBT self impact. + const totalSelfBlockingTime = tasksImpactingTbt + .reduce((sum, t) => sum += t.selfBlockingTime, 0); + expect(totalSelfImpact).toBeGreaterThanOrEqual(totalSelfBlockingTime); // The total self TBT impact of every task should equal the total TBT impact of just the top level tasks. const topLevelTasks = tasksImpactingTbt.filter(t => !t.parent); diff --git a/core/test/fixtures/user-flows/reports/sample-flow-result.json b/core/test/fixtures/user-flows/reports/sample-flow-result.json index c6ff0b94bb24..f6252e5e984e 100644 --- a/core/test/fixtures/user-flows/reports/sample-flow-result.json +++ b/core/test/fixtures/user-flows/reports/sample-flow-result.json @@ -1509,7 +1509,7 @@ "description": "Third-party code can significantly impact load performance. Limit the number of redundant third-party providers and try to load third-party code after your page has primarily finished loading. [Learn how to minimize third-party impact](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/).", "score": 1, "scoreDisplayMode": "informative", - "displayValue": "Third-party code blocked the main thread for 30 ms", + "displayValue": "Third-party code blocked the main thread for 40 ms", "metricSavings": { "TBT": 50 }, @@ -1547,7 +1547,7 @@ "items": [ { "mainThreadTime": 163.40800000000056, - "blockingTime": 33.06, + "blockingTime": 39.99999999999996, "transferSize": 98875, "tbtImpact": 39.99999999999996, "entity": "Google Tag Manager", @@ -1557,7 +1557,7 @@ { "url": "https://www.googletagmanager.com/gtag/js?id=G-RTW9M3W5HC", "mainThreadTime": 163.40800000000056, - "blockingTime": 33.06, + "blockingTime": 39.99999999999996, "transferSize": 98875, "tbtImpact": 39.99999999999996 } @@ -1619,7 +1619,7 @@ ], "summary": { "wastedBytes": 116396, - "wastedMs": 33.06 + "wastedMs": 39.99999999999996 }, "isEntityGrouped": true }, @@ -7347,7 +7347,7 @@ "core/audits/third-party-summary.js | displayValue": [ { "values": { - "timeInMs": 33.06 + "timeInMs": 39.99999999999996 }, "path": "audits[third-party-summary].displayValue" } @@ -19199,7 +19199,7 @@ "description": "Third-party code can significantly impact load performance. Limit the number of redundant third-party providers and try to load third-party code after your page has primarily finished loading. [Learn how to minimize third-party impact](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/).", "score": 1, "scoreDisplayMode": "informative", - "displayValue": "Third-party code blocked the main thread for 30 ms", + "displayValue": "Third-party code blocked the main thread for 70 ms", "metricSavings": { "TBT": 50 }, @@ -19237,7 +19237,7 @@ "items": [ { "mainThreadTime": 217.02400000000034, - "blockingTime": 31.823999999999998, + "blockingTime": 65.0000000000002, "transferSize": 0, "tbtImpact": 65.0000000000002, "entity": "Google Tag Manager", @@ -19247,7 +19247,7 @@ { "url": "https://www.googletagmanager.com/gtag/js?id=G-RTW9M3W5HC", "mainThreadTime": 217.02400000000034, - "blockingTime": 31.823999999999998, + "blockingTime": 65.0000000000002, "transferSize": 0, "tbtImpact": 65.0000000000002 } @@ -19309,7 +19309,7 @@ ], "summary": { "wastedBytes": 17, - "wastedMs": 31.823999999999998 + "wastedMs": 65.0000000000002 }, "isEntityGrouped": true }, @@ -25241,7 +25241,7 @@ "core/audits/third-party-summary.js | displayValue": [ { "values": { - "timeInMs": 31.823999999999998 + "timeInMs": 65.0000000000002 }, "path": "audits[third-party-summary].displayValue" } diff --git a/package.json b/package.json index 3a5d10560888..eca0dcd389e4 100644 --- a/package.json +++ b/package.json @@ -167,7 +167,7 @@ "pako": "^2.0.3", "preact": "^10.7.2", "pretty-json-stringify": "^0.0.2", - "puppeteer": "^22.13.1", + "puppeteer": "^22.15.0", "resolve": "^1.22.1", "rollup": "^2.52.7", "rollup-plugin-polyfill-node": "^0.12.0", @@ -181,7 +181,7 @@ "webtreemap-cdt": "^3.2.1" }, "dependencies": { - "@paulirish/trace_engine": "0.0.28", + "@paulirish/trace_engine": "0.0.32", "@sentry/node": "^6.17.4", "axe-core": "^4.9.1", "chrome-launcher": "^1.1.2", @@ -200,11 +200,11 @@ "metaviewport-parser": "0.3.0", "open": "^8.4.0", "parse-cache-control": "1.0.1", - "puppeteer-core": "^22.13.1", + "puppeteer-core": "^22.15.0", "robots-parser": "^3.0.1", "semver": "^5.3.0", "speedline-core": "^1.4.3", - "third-party-web": "^0.24.3", + "third-party-web": "^0.24.5", "tldts-icann": "^6.1.16", "ws": "^7.0.0", "yargs": "^17.3.1", diff --git a/treemap/test/treemap-test-pptr.js b/treemap/test/treemap-test-pptr.js index e4e66718a3b8..3c5fd63d370a 100644 --- a/treemap/test/treemap-test-pptr.js +++ b/treemap/test/treemap-test-pptr.js @@ -31,7 +31,7 @@ describe('Lighthouse Treemap', () => { let browser; /** @type {import('puppeteer').Page} */ let page; - /** @type {Error[]} */ + /** @type {Array>} */ let pageErrors = []; let server; @@ -80,7 +80,13 @@ describe('Lighthouse Treemap', () => { async function ensureNoErrors() { await page.bringToFront(); await page.evaluate(() => new Promise(window.requestAnimationFrame)); - const errors = await claimErrors(); + const errors = (await claimErrors()).filter(error => { + // Filters out a cookie deprecation error that only occurs on ToT + // This error comes from gtag.js + // https://support.google.com/tagmanager/thread/288419928/error-failed-to-execute-getvalue-on-cookiedeprecationlabel?hl=en + return !error.match( + /Failed to execute 'getValue' on 'CookieDeprecationLabel': Illegal invocation/); + }); expect(errors).toHaveLength(0); } diff --git a/types/artifacts.d.ts b/types/artifacts.d.ts index 1dd3faddb62d..0abf2c060887 100644 --- a/types/artifacts.d.ts +++ b/types/artifacts.d.ts @@ -163,7 +163,7 @@ declare module Artifacts { type NetworkRequest = _NetworkRequest; type TaskNode = _TaskNode; - type TBTImpactTask = TaskNode & {tbtImpact: number, selfTbtImpact: number}; + type TBTImpactTask = TaskNode & {tbtImpact: number, selfTbtImpact: number, selfBlockingTime: number}; type MetaElement = Artifacts['MetaElements'][0]; interface URL { @@ -511,7 +511,7 @@ declare module Artifacts { interface TraceEngineResult { data: TraceEngine.Handlers.Types.TraceParseData; - insights: TraceEngine.Insights.Types.TraceInsightData; + insights: TraceEngine.Insights.Types.TraceInsightData; } interface TraceEngineRootCauses { diff --git a/yarn.lock b/yarn.lock index a8964ae4b3c7..6a4609c3213b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1080,10 +1080,10 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" -"@paulirish/trace_engine@0.0.28": - version "0.0.28" - resolved "https://registry.yarnpkg.com/@paulirish/trace_engine/-/trace_engine-0.0.28.tgz#9c7163c68fc697a3c39638248aa8f143eb188927" - integrity sha512-hxeqhny/jggy3y3yEUE/91UQmNREjoebaYlggWNTtX1ZFdIXJ4ea8MSMlO+dc1oWcnKHGQzdU3+Mhl01ZEuU0w== +"@paulirish/trace_engine@0.0.32": + version "0.0.32" + resolved "https://registry.yarnpkg.com/@paulirish/trace_engine/-/trace_engine-0.0.32.tgz#090fd603f9264aad6fce4461574693b1462f799f" + integrity sha512-KxWFdRNbv13U8bhYaQvH6gLG9CVEt2jKeosyOOYILVntWEVWhovbgDrbOiZ12pJO3vjZs0Zgbd3/Zgde98woEA== "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" @@ -1138,16 +1138,16 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= -"@puppeteer/browsers@2.2.4": - version "2.2.4" - resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.2.4.tgz#4307245d881aa5a79743050be66568bad0f6ffbb" - integrity sha512-BdG2qiI1dn89OTUUsx2GZSpUzW+DRffR1wlMJyKxVHYrhnKoELSDxDd+2XImUkuWPEKk76H5FcM/gPFrEK1Tfw== +"@puppeteer/browsers@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.3.0.tgz#791ea7d80450fea24eb19fb1d70c367ad4e08cae" + integrity sha512-ioXoq9gPxkss4MYhD+SFaU9p1IHFUX0ILAWFPyjGaBdjLsYAlZw6j1iLA0N/m12uVHLFDfSYNF7EQccjinIMDA== dependencies: debug "^4.3.5" extract-zip "^2.0.1" progress "^2.0.3" proxy-agent "^6.4.0" - semver "^7.6.2" + semver "^7.6.3" tar-fs "^3.0.6" unbzip2-stream "^1.4.3" yargs "^17.7.2" @@ -2358,10 +2358,10 @@ chrome-launcher@^1.1.2: is-wsl "^2.2.0" lighthouse-logger "^2.0.1" -chromium-bidi@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.6.1.tgz#533612dd166b7b36a8ba8b90685ad2fa0c98d064" - integrity sha512-kSxJRj0VgtUKz6nmzc2JPfyfJGzwzt65u7PqhPHtgGQUZLF5oG+ST6l6e5ONfStUMAlhSutFCjaGKllXZa16jA== +chromium-bidi@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.6.3.tgz#363fe1ca6b9c6122b9f1b2a47f9449ecf712f755" + integrity sha512-qXlsCmpCZJAnoTYI83Iu6EdYQpMYdVkCfq08KDh2pmlVqK5t5IA9mGs4/LwCwp4fqisSOMXZxP3HIh8w8aRn0A== dependencies: mitt "3.0.1" urlpattern-polyfill "10.0.0" @@ -2871,6 +2871,13 @@ debug@^4.3.5: dependencies: ms "2.1.2" +debug@^4.3.6: + version "4.3.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" + integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== + dependencies: + ms "2.1.2" + decamelize-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" @@ -2947,7 +2954,7 @@ 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.1299070, devtools-protocol@0.0.1312386: +devtools-protocol@0.0.1312386: version "0.0.1312386" resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz#5ab824d6f1669ec6c6eb0fba047e73601d969052" integrity sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA== @@ -6044,26 +6051,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@22.13.1, puppeteer-core@^22.13.1: - version "22.13.1" - resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-22.13.1.tgz#3ba03e5ebd98bbbd86e465864cf00314e07309de" - integrity sha512-NmhnASYp51QPRCAf9n0OPxuPMmzkKd8+2sB9Q+BjwwCG25gz6iuNc3LQDWa+cH2tyivmJppLhNNFt6Q3HmoOpw== +puppeteer-core@22.15.0, puppeteer-core@^22.15.0: + version "22.15.0" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-22.15.0.tgz#c76926cce5dbc177572797a9dacc325c313fa91a" + integrity sha512-cHArnywCiAAVXa3t4GGL2vttNxh7GqXtIYGym99egkNJ3oG//wL9LkvO4WE8W1TJe95t1F1ocu9X4xWaGsOKOA== dependencies: - "@puppeteer/browsers" "2.2.4" - chromium-bidi "0.6.1" - debug "^4.3.5" - devtools-protocol "0.0.1299070" + "@puppeteer/browsers" "2.3.0" + chromium-bidi "0.6.3" + debug "^4.3.6" + devtools-protocol "0.0.1312386" ws "^8.18.0" -puppeteer@^22.13.1: - version "22.13.1" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-22.13.1.tgz#f8e4217919b438f18adb754e9d8414fef58fb3de" - integrity sha512-PwXLDQK5u83Fm5A7TGMq+9BR7iHDJ8a3h21PSsh/E6VfhxiKYkU7+tvGZNSCap6k3pCNDd9oNteVBEctcBalmQ== +puppeteer@^22.15.0: + version "22.15.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-22.15.0.tgz#4f842087090f1d9017ce947512e7baff55a10e75" + integrity sha512-XjCY1SiSEi1T7iSYuxS82ft85kwDJUS7wj1Z0eGVXKdtr5g4xnVcbjwxhq5xBnpK/E7x1VZZoJDxpjAOasHT4Q== dependencies: - "@puppeteer/browsers" "2.2.4" + "@puppeteer/browsers" "2.3.0" cosmiconfig "^9.0.0" - devtools-protocol "0.0.1299070" - puppeteer-core "22.13.1" + devtools-protocol "0.0.1312386" + puppeteer-core "22.15.0" q@^1.5.1: version "1.5.1" @@ -6449,7 +6456,7 @@ semver@^7.2.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7: dependencies: lru-cache "^6.0.0" -semver@^7.6.2: +semver@^7.6.3: version "7.6.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== @@ -6956,10 +6963,10 @@ theredoc@^1.0.0: resolved "https://registry.yarnpkg.com/theredoc/-/theredoc-1.0.0.tgz#bcace376af6feb1873efbdd0f91ed026570ff062" integrity sha512-KU3SA3TjRRM932jpNfD3u4Ec3bSvedyo5ITPI7zgWYnKep7BwQQaxlhI9qbO+lKJoRnoAbEVfMcAHRuKVYikDA== -third-party-web@^0.24.3: - version "0.24.3" - resolved "https://registry.yarnpkg.com/third-party-web/-/third-party-web-0.24.3.tgz#d0281dc37a919f29b4b16110bd4bf64de552d529" - integrity sha512-imE6hXZyaCeGinGFCvpWsv0oelsEaufSG39qYBQhp3urGq4OLOtsuEddf3XgKxmAAczBD/I1Tnp8L3gJ3ksTuQ== +third-party-web@^0.24.5: + version "0.24.5" + resolved "https://registry.yarnpkg.com/third-party-web/-/third-party-web-0.24.5.tgz#7841c650bf0b589113709b0e2e8099ad3d6abfae" + integrity sha512-1rUOdMYpNTRajgk1F7CmHD26oA6rTKekBjHay854J6OkPXeNyPcR54rhWDaamlWyi9t2wAVPQESdedBhucmOLA== through2@^2.0.0: version "2.0.5"