From 6a536b3a11902491d9f882776999a7897bba8c2f Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Thu, 24 Apr 2025 19:34:34 +0200 Subject: [PATCH] [speedometer][v3.0-custom] Add params.leakyIframes to main-custom DevTools can't handle sources from detached iframes. To simplify local development we add an an option that just hides the iframes away but never detaches them from the DOM. Drive-by-fix: - Properly use markEnd Change-Id: I037f7dfa7b3eb6c16f1aea0d12ea74703c95e562 --- index.html | 1 + resources/benchmark-runner.mjs | 18 +++++++++++------- resources/developer-mode.mjs | 20 +++++++++++++++++++- resources/main.css | 4 ++++ resources/params.mjs | 7 +++++++ 5 files changed, 42 insertions(+), 8 deletions(-) diff --git a/index.html b/index.html index 0425773..2604e02 100644 --- a/index.html +++ b/index.html @@ -41,6 +41,7 @@
3.0
+
diff --git a/resources/benchmark-runner.mjs b/resources/benchmark-runner.mjs index 2d3fb7f..62c054c 100644 --- a/resources/benchmark-runner.mjs +++ b/resources/benchmark-runner.mjs @@ -360,10 +360,14 @@ export class BenchmarkRunner { _removeFrame() { if (this._frame) { - // Downstream only. The React-Window workload sets a global childWindow object. - if (this._frame.contentWindow.globalThis.childWindow) - this._frame.contentWindow.globalThis.childWindow.close(); - this._frame.parentNode.removeChild(this._frame); + if (params.leakyIframes) { + document.getElementById("leakedIframes").append(this._frame); + } else { + // Downstream only. The React-Window workload sets a global childWindow object. + if (this._frame.contentWindow.globalThis.childWindow) + this._frame.contentWindow.globalThis.childWindow.close(); + this._frame.parentNode.removeChild(this._frame); + } this._frame = null; } } @@ -432,7 +436,7 @@ export class BenchmarkRunner { // Remove frame to clear the view for displaying the results. this._removeFrame(); await this._finalize(); - this.markStart(finalizeLabel, finalizeStartLabel, finalizeEndLabel); + this.markEnd(finalizeLabel, finalizeStartLabel, finalizeEndLabel); } async _runSuite(suite) { @@ -462,7 +466,7 @@ export class BenchmarkRunner { this.markStart(suiteLabel, suiteStartLabel); for (const test of suite.tests) await this._runTestAndRecordResults(suite, test); - this.markStart(suiteLabel, suiteStartLabel, suiteEndLabel); + this.markEnd(suiteLabel, suiteStartLabel, suiteEndLabel); } _prepareMetrics(suite) { @@ -512,7 +516,7 @@ export class BenchmarkRunner { // Infinite loop for the specified ms. while (performance.now() - startTime < params.warmupBeforeSync) continue; - this.markStart("warmup", "warmup-start", "warmup-end"); + this.markEnd("warmup", "warmup-start", "warmup-end"); } this.markStart(syncLabel, syncStartLabel); const syncStartTime = performance.now(); diff --git a/resources/developer-mode.mjs b/resources/developer-mode.mjs index 60d5a1f..3179da8 100644 --- a/resources/developer-mode.mjs +++ b/resources/developer-mode.mjs @@ -25,6 +25,7 @@ export function createDeveloperModeContainer() { settings.append(createUIForMeasurePrepare()); settings.append(createUIForDomainPerIteration()); settings.append(createUIForForceGC()); + settings.append(createUIForLeakyIframes()); content.append(settings); @@ -59,6 +60,23 @@ function createUIForMeasurementMethod() { return label; } +function createUIForLeakyIframes() { + let check = document.createElement("input"); + check.type = "checkbox"; + check.id = "leaky-iframes-checkbox"; + check.checked = !!params.leakyIframes; + + check.onchange = () => { + params.leakyIframes = check.checked; + updateURL(); + }; + + let label = document.createElement("label"); + label.append(check, " ", span("Leak IFrames")); + + return label; +} + function createUIForWarmupSuite() { let check = document.createElement("input"); check.type = "checkbox"; @@ -326,7 +344,7 @@ function updateURL() { else url.searchParams.delete("measurementMethod"); - const boolParamKeys = ["iterationCount", "useWarmupSuite", "warmupBeforeSync", "waitBeforeSync", "domainPerIteration", "suiteForceGC"]; + const boolParamKeys = ["iterationCount", "useWarmupSuite", "warmupBeforeSync", "waitBeforeSync", "domainPerIteration", "suiteForceGC", "leakyIframes"]; for (const paramKey of boolParamKeys) { if (params[paramKey] !== defaultParams[paramKey]) url.searchParams.set(paramKey, params[paramKey]); diff --git a/resources/main.css b/resources/main.css index 82915bd..ffd5de2 100644 --- a/resources/main.css +++ b/resources/main.css @@ -324,6 +324,10 @@ section > p { height: var(--viewport-height); } +#leakedIframes { + display: none; +} + section#home p { margin: 0 auto; width: 70%; diff --git a/resources/params.mjs b/resources/params.mjs index 037d8e6..abc6bef 100644 --- a/resources/params.mjs +++ b/resources/params.mjs @@ -33,6 +33,8 @@ export class Params { suiteForceGC = false; currentIteration = 0; embedded = false; + // Leak iframes to DevTools can display sources. + leakyIframes = false; constructor(searchParams = undefined, freeze = true) { @@ -151,6 +153,11 @@ export class Params { searchParams.delete("shuffleSeed"); } + if (searchParams.has("leakyIframes")) { + this.leakyIframes = true; + searchParams.delete("leakyIframes"); + } + const unused = Array.from(searchParams.keys()); if (unused.length > 0) console.error("Got unused search params", unused);