From cb6c7677319f22074ae2ec09989022ddf0f8ea87 Mon Sep 17 00:00:00 2001 From: Harvey Zhao Date: Sun, 13 Sep 2026 02:55:57 +0800 Subject: [PATCH] test(iframe): [PKG-IFRAME-05] verify native cached history and interrupted navigation --- .github/workflows/nodejs.yml | 3 + package.json | 1 + .../artplayer-tool-iframe/ARCHITECTURE.md | 26 +- playwright.iframe-history.config.js | 23 + .../baselines/iframe-history-validation.json | 7302 +++++++++++++++++ .../2026-09-13-PKG-IFRAME-05-history.md | 122 + refactor/docs-browser-testing.md | 8 +- refactor/iframe-document-protocol.md | 14 +- refactor/plan.md | 2 +- refactor/progress.md | 17 +- refactor/risks.json | 10 +- refactor/tasks.json | 4 +- test/history/child.html | 20 + test/history/fixtures.js | 43 + test/history/iframe-history.spec.js | 88 + test/history/iframe-interruption.spec.js | 69 + test/history/observe.js | 16 + test/history/parent.html | 26 + test/history/server.mjs | 127 + 19 files changed, 7908 insertions(+), 13 deletions(-) create mode 100644 playwright.iframe-history.config.js create mode 100644 refactor/baselines/iframe-history-validation.json create mode 100644 refactor/changes/2026-09-13-PKG-IFRAME-05-history.md create mode 100644 test/history/child.html create mode 100644 test/history/fixtures.js create mode 100644 test/history/iframe-history.spec.js create mode 100644 test/history/iframe-interruption.spec.js create mode 100644 test/history/observe.js create mode 100644 test/history/parent.html create mode 100644 test/history/server.mjs diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 53129aeb8..8ff9a8ce0 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -87,6 +87,8 @@ jobs: node --input-type=module -e 'import fs from "node:fs"; const { output } = JSON.parse(fs.readFileSync("refactor/.cache/packages/latest.json")); fs.appendFileSync(process.env.GITHUB_ENV, `ARTPLAYER_BROWSER_ARTIFACTS=${output}/browser-artifacts.json\n`);' - name: Run all three engines run: yarn test:browser + - name: Verify iframe cached history and interrupted navigation + run: yarn test:iframe-history - name: Compare installed performance and verify resource cleanup run: yarn test:performance - name: Upload browser evidence @@ -96,6 +98,7 @@ jobs: name: browser-${{ github.run_id }}-${{ github.run_attempt }} path: | refactor/.cache/browser/ + refactor/.cache/iframe-history/ refactor/.cache/performance/ refactor/.cache/packages/latest.json refactor/.cache/packages/run-*/*.json diff --git a/package.json b/package.json index 75fff5d75..2e9ea2a1c 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "test:coverage": "node --test test/coverage.test.js && node scripts/coverage.mjs", "test": "yarn test:node && yarn test:baseline", "test:browser": "playwright test", + "test:iframe-history": "playwright test --config playwright.iframe-history.config.js", "test:performance": "playwright test --config playwright.performance.config.js", "test:browser:install": "playwright install chromium firefox webkit", "test:browser:report": "playwright show-report refactor/.cache/browser/html", diff --git a/packages/artplayer-tool-iframe/ARCHITECTURE.md b/packages/artplayer-tool-iframe/ARCHITECTURE.md index ce2bfcff5..4ece5841f 100644 --- a/packages/artplayer-tool-iframe/ARCHITECTURE.md +++ b/packages/artplayer-tool-iframe/ARCHITECTURE.md @@ -181,6 +181,26 @@ its initial commit handles cancellation during cleanup. This is an editor convention, not automatic DOM-removal behavior or a new player API. Standalone integrations remain responsible for calling destroy themselves. -Physical devices, actual BFCache restoration, interrupted navigation and final -distribution remain separate gates. Passing desktop player/editor tests does not -complete those gates or establish the old helper/package-name migration. +`yarn test:iframe-history` runs the separate cacheable HTTP fixture and full +Chromium channel, removing Playwright's BFCache-disabling default argument. It +checks actual whole-page restoration through native persisted events, parent/child +witnesses, media and the real commit protocol. Firefox/WebKit reload controls are +reported separately and never counted as cached restoration. Do not replace this +configuration with the default headless shell or simulated lifecycle events. + +An entire cached page also freezes the parent. If the private leave message did +not reach it, the original request can remain pending and settle after restoration. +If leave was delivered, that request remains rejected; a late result cannot change +its outcome. Resume retains the same document ID and emits no duplicate public +inject. The test checks actual delivered phases against settlement. + +The same command tests native stop, HTTP 204 and a truncated document response. +After a failed navigation, new work still waits for actual injection into the +target document; it is not sent to the unrelated old document. Navigate the frame +to a valid source or destroy the tool to finish/cancel that work. There is no +implicit timeout or automatic fallback to an old source. + +Physical devices, native Firefox/WebKit cached restoration and final distribution +remain separate gates. Desktop evidence does not establish the old helper or +package-name migration. See ADR-026 and the task 05 history checkpoint for the +exact fixture, automation limitations and source/main/legacy evidence. diff --git a/playwright.iframe-history.config.js b/playwright.iframe-history.config.js new file mode 100644 index 000000000..4a31dbe57 --- /dev/null +++ b/playwright.iframe-history.config.js @@ -0,0 +1,23 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +const port = Number(process.env.ARTPLAYER_IFRAME_HISTORY_PORT || 8085) + +export default defineConfig({ + testDir: './test/history', + timeout: 20000, + expect: { timeout: 7000 }, + fullyParallel: true, + forbidOnly: Boolean(process.env.CI), + retries: 0, + workers: process.env.CI ? 2 : 3, + outputDir: 'refactor/.cache/iframe-history/results', + reporter: [['list'], ['json', { outputFile: 'refactor/.cache/iframe-history/report.json' }]], + use: { baseURL: `http://127.0.0.1:${port}`, trace: 'retain-on-failure', screenshot: 'only-on-failure' }, + projects: [ + { name: 'chromium', use: { ...devices['Desktop Chrome'], channel: 'chromium', launchOptions: { ignoreDefaultArgs: ['--disable-back-forward-cache'] } } }, + { name: 'firefox', use: { ...devices['Desktop Firefox'] } }, + { name: 'webkit', use: { ...devices['Desktop Safari'] } }, + ], + webServer: { command: 'node test/history/server.mjs', url: `http://127.0.0.1:${port}/manifest.json`, reuseExistingServer: false, timeout: 60000, env: { ARTPLAYER_IFRAME_HISTORY_PORT: String(port) } }, +}) diff --git a/refactor/baselines/iframe-history-validation.json b/refactor/baselines/iframe-history-validation.json new file mode 100644 index 000000000..9ef0c7db3 --- /dev/null +++ b/refactor/baselines/iframe-history-validation.json @@ -0,0 +1,7302 @@ +{ + "task": "PKG-IFRAME-05", + "status": "doing", + "checkpoint": "native-cached-history-and-interrupted-navigation", + "sourceCommit": "b35183c7af10a7309c9409b50fe8d5fda9db9ffb", + "scope": "Three runs of 90 desktop cases: each has 12 actual Chromium BFCache restorations, 24 Firefox/WebKit reload controls, 54 interruption/recovery/cleanup cases. Reload controls do not satisfy cached-restoration acceptance. Physical devices and final distribution remain outstanding.", + "sourceSha256LF": { + "package.json": "c4236c4bc18cb41e7acec3741f1e87260b4d089f4eda6d9705ea543aefb7393c", + ".github/workflows/nodejs.yml": "3bb6e55488cde2374821d606016a89f9186ad353c8e338b4d69ba15ad724d7ec", + "playwright.iframe-history.config.js": "02ad4b13f328e74eddb70bf77bd4979792d591d8eeee8dd59375d5fe69de14b7", + "test/history/child.html": "c0348ca9debf298ae93a1733102b6967ba80999962461474654aeb02aeea83ed", + "test/history/fixtures.js": "a94a5714664b03a41097cf898ac13920a4f051ba9bb4b91d45d6abfe6b1e2197", + "test/history/iframe-history.spec.js": "3db52a5d544e11faa69d3edcbd3d0de904fc1d195fc398e145755422ca89d9d1", + "test/history/iframe-interruption.spec.js": "8aca2c9fc16699e30fc1816ee7d45dbed5d49125c47a78a68311fe03c4daf419", + "test/history/observe.js": "e24a06ba4b3a07e968b33c27f2c92a586e058f5c415dbcd4e6a8a49d90079513", + "test/history/parent.html": "c85cb5ccf13b92e8206e81fdf0b620e0aed99891a0ee8469eefa58ab7c0868fc", + "test/history/server.mjs": "3cbccfda75efb71fdc5855148ba22239ce9fdb99a9c70718b4c8ddca569cae22" + }, + "unchangedRuntimeSha256LF": { + "packages/artplayer-tool-iframe/src/index.ts": "64fd8f39b3d23e886ddecda38ae2b1e17b5b93c156825b1de23915c71f33991e", + "packages/artplayer-tool-iframe/src/requests.ts": "74bc15f2102eb45fa00d3b801b629aa1a280ea20af491949ad644e765cb3dbe9", + "packages/artplayer-tool-iframe/src/connection.ts": "a0b2f5a34f1c479f874d824429d1429804f2fabea53015a8e76b9548e8eb208d", + "packages/artplayer-tool-iframe/src/protocol.ts": "c1046b798d79b2765648a7b5e7caa0d8554d2b12f074e960c297429575fa841f", + "packages/artplayer-tool-iframe/src/navigation.ts": "f17f00448e6b337772bd2feb4183cf670e2560d8ab2c1bef63b494ce815c9a7d", + "packages/artplayer-tool-iframe/src/child-session.ts": "0078dd6c209c9f7608c165277b80be40696d90433848b9025e25fc15ec4bf3d5" + }, + "unchangedArtifacts": { + "packages/artplayer-tool-iframe/dist/artplayer-tool-iframe.js": "7408fceccb000e1b304abe30ac9bc364da7860c3896ad5aaa6af427804c237e6", + "packages/artplayer-tool-iframe/dist/artplayer-tool-iframe.legacy.js": "4e8bd39cdc37e98bff9cd19b5e0c9453ebe5231264242fc1c573aa96edb5ea8a", + "packages/artplayer-tool-iframe/dist/artplayer-tool-iframe.mjs": "ac4c5efa670c0429fc95bdab7902df60f5b5540f0dad9c7e65c2bd660796dc83" + }, + "reports": [ + { + "kind": "source", + "file": "refactor/.cache/iframe05-history-source.json", + "sha256": "d30186a8587b0b8dd20849f7bb6f2d8e09537c8c20fcb5f108ea54647d3b4910", + "resultsDirectory": "refactor/.cache/iframe05-history-source-results", + "stats": { + "startTime": "2026-09-12T18:42:00.677Z", + "duration": 73648.323, + "expected": 90, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "counts": { + "chromium:actual-bfcache": 12, + "firefox:reload-control": 12, + "webkit:reload-control": 12, + "chromium:recovered-and-cleaned": 18, + "firefox:recovered-and-cleaned": 18, + "webkit:recovered-and-cleaned": 18 + }, + "browsers": { + "chromium": "153.0.8010.12", + "firefox": "155.0", + "webkit": "26.6" + }, + "stops": { + "chromium": "CDP Page.stopLoading", + "firefox": "top window.stop()", + "webkit": "top window.stop()" + }, + "manifest": { + "tool": { + "name": "candidate-source", + "sha256": "3748a8b38801d858cb018ffb9d690146bd2d3ce6bca086212401e7baa4cbf2cf" + }, + "cores": { + "candidate": "e8945bc9d3ff0a6e247772a662f874df13875f7dbeb949968943b9589f6e2946", + "4.5.9": "09a9f09e3a64a02ca7c27af710d7254f886f0bfb09fd54bf3a728ce863e5a497", + "5.4.0": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f" + }, + "files": { + "parent.html": "c85cb5ccf13b92e8206e81fdf0b620e0aed99891a0ee8469eefa58ab7c0868fc", + "child.html": "c0348ca9debf298ae93a1733102b6967ba80999962461474654aeb02aeea83ed", + "observe.js": "e24a06ba4b3a07e968b33c27f2c92a586e058f5c415dbcd4e6a8a49d90079513", + "tool.js": "3748a8b38801d858cb018ffb9d690146bd2d3ce6bca086212401e7baa4cbf2cf", + "pattern.mp4": "0ad1d7ad286aec6e0fa9e27fc1e487e7277df2e603e30040fb942365763d0233" + } + }, + "rows": [ + { + "title": "Iframe cached history 4.5.9/same/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 911, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/same/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 1115, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.235833, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 1014, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 806, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.244802, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 648, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 806, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.234165, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 610, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 796, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.22199, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 628, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 758, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.204353, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 617, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 771, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.238984, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/same/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 2231, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/same/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 2375, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 2264, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 953, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 810, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 976, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 862, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 1011, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 859, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 945, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 865, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 1024, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/same/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2664, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/same/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2672, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5610, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5546, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2171, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2271, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5516, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5907, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2281, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2519, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5781, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5943, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 676, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 710, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 633, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 670, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 699, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 774, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 640, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 770, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 726, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 768, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 720, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 1083, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 762, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 750, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 756, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 774, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 997, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 677, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 834, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 791, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 985, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 780, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 774, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1129, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 859, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 996, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1023, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 983, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 964, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1235, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 816, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 817, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1753, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1555, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 830, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1656, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 4087, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3244, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3160, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 8286, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 7381, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 5350, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 4992, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3560, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3118, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 6372, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 6140, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 6949, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3942, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3133, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3915, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 7356, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 6441, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 6428, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + } + ] + }, + { + "kind": "main", + "file": "refactor/.cache/iframe05-history-main.json", + "sha256": "a0addf4aac2d4b4eb5a4f38d7a87a5d246011124d15cfffc412d997a2c3d977d", + "resultsDirectory": "refactor/.cache/iframe05-history-main-results", + "stats": { + "startTime": "2026-09-12T18:44:02.461Z", + "duration": 73381.238, + "expected": 90, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "counts": { + "chromium:actual-bfcache": 12, + "firefox:reload-control": 12, + "webkit:reload-control": 12, + "chromium:recovered-and-cleaned": 18, + "firefox:recovered-and-cleaned": 18, + "webkit:recovered-and-cleaned": 18 + }, + "browsers": { + "chromium": "153.0.8010.12", + "firefox": "155.0", + "webkit": "26.6" + }, + "stops": { + "chromium": "CDP Page.stopLoading", + "firefox": "top window.stop()", + "webkit": "top window.stop()" + }, + "manifest": { + "tool": { + "name": "candidate-artifact", + "sha256": "7408fceccb000e1b304abe30ac9bc364da7860c3896ad5aaa6af427804c237e6" + }, + "cores": { + "candidate": "4b29968839ba816db09910a908d1d6b8ec6cf1edaad418c96e1f407545a19bf9", + "4.5.9": "09a9f09e3a64a02ca7c27af710d7254f886f0bfb09fd54bf3a728ce863e5a497", + "5.4.0": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f" + }, + "files": { + "parent.html": "c85cb5ccf13b92e8206e81fdf0b620e0aed99891a0ee8469eefa58ab7c0868fc", + "child.html": "c0348ca9debf298ae93a1733102b6967ba80999962461474654aeb02aeea83ed", + "observe.js": "e24a06ba4b3a07e968b33c27f2c92a586e058f5c415dbcd4e6a8a49d90079513", + "tool.js": "7408fceccb000e1b304abe30ac9bc364da7860c3896ad5aaa6af427804c237e6", + "pattern.mp4": "0ad1d7ad286aec6e0fa9e27fc1e487e7277df2e603e30040fb942365763d0233" + } + }, + "rows": [ + { + "title": "Iframe cached history 4.5.9/same/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 1032, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/same/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 1055, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.23394, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 1072, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 849, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.231603, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 701, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 823, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.221838, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 714, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 890, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.239047, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 709, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 798, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.238842, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 687, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 884, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.201828, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/same/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 2252, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/same/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 2417, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 2184, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 946, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 807, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 966, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 860, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 974, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 798, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 1039, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 889, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 1020, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/same/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2378, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/same/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2353, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5616, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5563, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2311, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2571, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5422, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5025, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2283, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2505, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5783, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5950, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 886, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 811, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 773, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 680, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 782, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 739, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 733, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 720, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 927, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 633, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 885, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 701, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 642, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 714, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 708, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 960, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 873, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 717, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1039, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 960, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 945, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 989, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 990, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 969, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 839, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 866, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1193, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 972, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1215, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1011, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 734, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 770, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1703, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 819, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1633, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1609, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 4328, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3164, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 4041, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 8390, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 5221, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 5413, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 4308, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3553, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3140, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 8070, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 6099, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 6283, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 4999, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3928, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 2898, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 9137, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 6591, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 6173, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + } + ] + }, + { + "kind": "legacy", + "file": "refactor/.cache/iframe05-history-legacy.json", + "sha256": "d1e6935fe477b07ede7520a0051fa8cca81970a21047de84772592e65fa70eb3", + "resultsDirectory": "refactor/.cache/iframe05-history-legacy-results", + "stats": { + "startTime": "2026-09-12T18:46:02.238Z", + "duration": 71009.257, + "expected": 90, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "counts": { + "chromium:actual-bfcache": 12, + "firefox:reload-control": 12, + "webkit:reload-control": 12, + "chromium:recovered-and-cleaned": 18, + "firefox:recovered-and-cleaned": 18, + "webkit:recovered-and-cleaned": 18 + }, + "browsers": { + "chromium": "153.0.8010.12", + "firefox": "155.0", + "webkit": "26.6" + }, + "stops": { + "chromium": "CDP Page.stopLoading", + "firefox": "top window.stop()", + "webkit": "top window.stop()" + }, + "manifest": { + "tool": { + "name": "candidate-artifact", + "sha256": "4e8bd39cdc37e98bff9cd19b5e0c9453ebe5231264242fc1c573aa96edb5ea8a" + }, + "cores": { + "candidate": "2dc2eb7cb26012ef1d780680d622aba61a79b7ac3b37bb1ca7a6047834513dd9", + "4.5.9": "09a9f09e3a64a02ca7c27af710d7254f886f0bfb09fd54bf3a728ce863e5a497", + "5.4.0": "f1db1fa3406aa6d41baa7c554749429a8e79f99d56a794bde23345eb9c07573f" + }, + "files": { + "parent.html": "c85cb5ccf13b92e8206e81fdf0b620e0aed99891a0ee8469eefa58ab7c0868fc", + "child.html": "c0348ca9debf298ae93a1733102b6967ba80999962461474654aeb02aeea83ed", + "observe.js": "e24a06ba4b3a07e968b33c27f2c92a586e058f5c415dbcd4e6a8a49d90079513", + "tool.js": "4e8bd39cdc37e98bff9cd19b5e0c9453ebe5231264242fc1c573aa96edb5ea8a", + "pattern.mp4": "0ad1d7ad286aec6e0fa9e27fc1e487e7277df2e603e30040fb942365763d0233" + } + }, + "rows": [ + { + "title": "Iframe cached history 4.5.9/same/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 888, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/same/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 1048, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.12895, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 1054, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 790, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.230033, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 664, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 801, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.23722, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 599, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 773, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.251951, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 628, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 754, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.213357, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/paused", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 644, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/playing", + "project": "chromium", + "outcome": "actual-bfcache", + "durationMs": 782, + "measurement": { + "parentRestored": true, + "childRestored": true, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + }, + { + "type": "pagehide", + "persisted": true + }, + { + "type": "pageshow", + "persisted": true + } + ], + "rate": 1.25, + "time": 1.252248, + "held": "function", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/same/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 2197, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/same/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 2342, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 2148, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 978, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 765, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 955, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 904, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 1062, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 874, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 979, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/paused", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 882, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/playing", + "project": "firefox", + "outcome": "reload-control", + "durationMs": 1086, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/same/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2313, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/same/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2418, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 4713, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 4.5.9/cross/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5131, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2105, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/same/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2395, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5439, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history 5.4.0/cross/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 4946, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 320 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2237, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/same/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 2653, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/paused", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5668, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe cached history candidate/cross/playing", + "project": "webkit", + "outcome": "reload-control", + "durationMs": 5038, + "measurement": { + "parentRestored": false, + "childRestored": false, + "parentLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "childLifecycle": [ + { + "type": "pageshow", + "persisted": false + } + ], + "rate": 1, + "time": 0, + "held": "undefined", + "playback": { + "playing": true, + "width": 640 + }, + "final": { + "pending": 0, + "errors": [] + } + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 667, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 683, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 847, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 867, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 874, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 701, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 691, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 721, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 701, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 690, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 927, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 748, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 654, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 818, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 757, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/stop", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 986, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/204", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 726, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/reset", + "project": "chromium", + "outcome": "recovered-and-cleaned", + "durationMs": 782, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 782, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 789, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 991, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 798, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 807, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1331, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 792, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1163, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 979, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 781, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 798, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1388, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 968, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 966, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1667, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/stop", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1704, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/204", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 936, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/reset", + "project": "firefox", + "outcome": "recovered-and-cleaned", + "durationMs": 1446, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3817, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3253, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/same/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3104, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 7479, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 6299, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 4.5.9/cross/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 6309, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 4286, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3385, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/same/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3099, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 8507, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 5596, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation 5.4.0/cross/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 6465, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 5953, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 3280, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/same/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 2962, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/stop", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 8392, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/204", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 6345, + "measurement": { + "old": { + "status": "resolved", + "value": 9 + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + }, + { + "title": "Iframe interrupted navigation candidate/cross/reset", + "project": "webkit", + "outcome": "recovered-and-cleaned", + "durationMs": 6255, + "measurement": { + "old": { + "status": "rejected", + "error": "The iframe document has changed" + }, + "queued": { + "status": "resolved", + "value": "2" + }, + "pending": 0, + "documentChanged": true + } + } + ] + } + ], + "workflow": { + "actionlint": { + "file": "refactor/.cache/iframe05-history-actionlint.log", + "sha256": "ad7ed44e79c7e5d554c2e008819df3a5da44834e9cfdb4aecaef9224a39c87dd", + "version": "1.7.12", + "exitCode": 0 + }, + "hostedRun": "not run; no push performed", + "command": "yarn test:iframe-history" + }, + "environment": { + "ordinaryBrowserConfigChanged": false, + "channel": "chromium", + "removedDefaultArgs": [ + "--disable-back-forward-cache" + ], + "serverPort": 8085, + "cachePolicy": "public, max-age=60 on fixture pages/scripts/media; no request routing", + "fixtureMessages": "A test-only parent signal finishes an already-held child resolver and returns its document witness. Chromium stopping uses Page.stopLoading to stop a pending cross-process navigation; Firefox/WebKit use top window.stop()." + }, + "probes": [ + { + "file": "refactor/.cache/iframe05-history-probe.log", + "sha256": "31c84d3c5ead798ae31837c06a4a6241a8b658148d89d759c4d65b915f749d19" + }, + { + "file": "refactor/.cache/iframe05-history-probe2.log", + "sha256": "514f5b9c167390111c121480a2033d2806c15e9930d6ab32283f1a157e038c71" + }, + { + "file": "refactor/.cache/iframe05-history-probe3.log", + "sha256": "747dfad84712221102df8b8a7e1254b245c1130b6fb15af09121e37c3597904d" + }, + { + "file": "refactor/.cache/iframe05-history-probe4.log", + "sha256": "87ef2d50716b7baac6f0f4a13b238fb9e4409c98f4c70eae9c2ab4ee1491464d" + }, + { + "file": "refactor/.cache/iframe05-history-probe5.log", + "sha256": "8cee0077c5af47827b26a1fba38af08c136646f86c4bba1fa0c21de125ac06aa" + }, + { + "file": "refactor/.cache/iframe05-full-chromium-install.log", + "sha256": "1e463647d6d69d59d11b522121a833ae4367a54aadec1d473677d0d8363559f6" + }, + { + "file": "refactor/.cache/iframe05-full-chromium-proxy-install.log", + "sha256": "ce0fa911e83701d2b74815ec012a9094aaf16ed347242a93ba365417d7022bfc" + }, + { + "file": "refactor/.cache/iframe05-interruption-probe.json", + "sha256": "9af9a356ee100483746a78e8e2ff06e7e1c15e5ecbc97783ab51df277e81cb20" + }, + { + "file": "refactor/.cache/iframe05-interruption-probe2.json", + "sha256": "50fb90398630a97fe6ac00fafb88ace86b0ea4a826cbd7a51a92841b19985929" + }, + { + "file": "refactor/.cache/iframe05-interruption-probe3.json", + "sha256": "a9fccd1528fa5ab47336b21653a14672a0348ea6797f7967d51ee583ec1e62a5" + }, + { + "file": "refactor/.cache/iframe05-interruption-probe4.json", + "sha256": "c732d3b3705b129cb2c1b321066d6e111fbed16a2b965ec226d0643441dc8e83" + } + ], + "remaining": [ + "Physical devices", + "Native Firefox/WebKit BFCache restoration (current runs only prove reload controls)", + "Final 8082/distribution acceptance and old helper/package-name migration under task 06" + ], + "verification": { + "ci": { + "file": "refactor/.cache/iframe05-history-ci.log", + "sha256": "cf715235e10c0f5a0fdf93fe5dd2b2aacfb54d62d097925270345f2b80855b17", + "exitCode": 0, + "tests": 1544, + "unit": 1365, + "engineering": 14, + "baseline": 165, + "productionTypeScriptFiles": 330 + }, + "imports": { + "file": "refactor/.cache/iframe05-history-imports.log", + "sha256": "1e21efd8046e8f1e0cc20a7a6671a46e236ba1e34509b5447671b2b90abab924", + "exitCode": 0, + "tests": 3 + }, + "lint": "Browser/history/config lint passes. Full CI retains only the pre-existing generated core editor unused namespace-disable warning.", + "coverage": "No production runtime or coverage policy changed; this checkpoint does not claim a new coverage run. The preceding checkpoint coverage evidence remains in iframe-integration-validation.json." + } +} diff --git a/refactor/changes/2026-09-13-PKG-IFRAME-05-history.md b/refactor/changes/2026-09-13-PKG-IFRAME-05-history.md new file mode 100644 index 000000000..45b4b6e19 --- /dev/null +++ b/refactor/changes/2026-09-13-PKG-IFRAME-05-history.md @@ -0,0 +1,122 @@ +# PKG-IFRAME-05 native cached history and interrupted navigation checkpoint + +Started from b35183c7af10a7309c9409b50fe8d5fda9db9ffb with a clean worktree. +The preceding checkpoint verifies actual player and Monaco integration. This +checkpoint addresses genuine BFCache restoration and external navigation +interruption without changing public APIs or production runtime bytes. + +## Reproducible browser environment + +The installed Playwright 1.63.0 source explicitly adds +`--disable-back-forward-cache` to Chromium. Its default headless shell also +reloaded this fixture after that argument was removed. The separate +`playwright.iframe-history.config.js` therefore uses the full `chromium` channel +and removes only that BFCache-disabling argument. Ordinary browser tests retain +their original configuration and report directory. + +Initial download of full Chromium 153.0.8010.12 timed out. A supplementary probe +with the already installed full 151.0.7922.34 demonstrated actual restoration, +but is not substituted for the pinned-version results. After confirming a local +proxy listener, a process-scoped HTTPS_PROXY allowed the normal Playwright +installer to download full 153.0.8010.12. No machine proxy or repository proxy +configuration was changed. No package dependency version was changed. + +`yarn test:iframe-history` uses a separate local fixture server on port 8085 and +records to `refactor/.cache/iframe-history`. The browser receives real HTTP pages, +core/tool scripts and media with cacheable headers. There is no request routing, +synthetic pageshow event, reconstructed document, or mocked media in this matrix. +The parent and child each retain an independent random document witness and +native page lifecycle events. All candidate script and fixture hashes are in +the environment attachment. Artifact overrides never silently fall back to source. + +The GitHub browser job now runs this command and uploads its evidence directory. +Local Windows evidence is not evidence that the hosted macOS job has executed. + +## History assertions + +The history matrix has 36 cases: cores 4.5.9, frozen 5.4.0 and candidate; same +and cross origin; paused and playing; Chromium, Firefox and WebKit. Full Chromium +must show actual `pageshow.persisted`, unchanged parent/child witnesses and +unchanged private document IDs. Player position/rate and the pending resolver +survive in the same document, communication resumes, playback works and resources +can be destroyed. Private resume packets must not become public callbacks or +duplicate the original inject callback. + +Whole-page caching freezes the parent too. A child's best-effort pagehide message +may not reach that frozen parent. The test correlates the request state with the +actual delivered private phases: with no delivered leave, the old request stays +pending and can resolve after restoration; with a delivered leave it must already +be rejected and a late resolver cannot change the result. This is distinct from +the existing child-only navigation tests, where an active parent processes leave. + +Firefox and WebKit currently recreate both documents. These cases explicitly +record `reload-control`, verify changed witnesses and successful fresh playback, +and do not count toward actual BFCache acceptance. Native Firefox/WebKit cached +restoration and physical devices remain unverified. + +## Interrupted navigation assertions + +Another 54 cases cover the same three cores and two origins on all three engines: + +- Stop a genuinely pending HTTP navigation. Chromium uses native CDP + `Page.stopLoading`; Firefox and WebKit use top-window `window.stop()`. +- Return HTTP 204, retaining the old document. +- Start an HTTP 200 document response, declare more bytes than are sent, then + destroy the connection after writing the partial HTML. + +An active old document can still settle a request it already received. A committed +replacement cancels old owned work. Queued new requests cannot execute in the old +document and remain waiting until a subsequent valid iframe source injects. The +test then starts another stalled navigation, destroys the tool and removes the +frame, checking immediate rejection and release of the test server's barrier. + +This preserves the existing absence of implicit request timeouts. A failed target +does not automatically authorize commands to run in a different old document. +The application can navigate to another valid source or destroy the tool. These +tests establish those recovery paths, not automatic recovery from every network +failure or an undocumented timeout policy. + +## Failed probes retained + +`iframe05-history-probe*.json/log` retain shell/full browser comparisons, the +missing full-browser executable, and actual supplementary/pinned-version probes. +The full installer logs retain direct timeout and process-proxy success. + +Chromium's automation frame inventory omitted the restored cross-origin child in +the probe even while native parent/child witnesses and SDK communication survived. +The permanent tests inspect the restored child through the actual public commit +protocol rather than relying on an automation-side Frame object. + +The first stop probe stalled while evaluating the old cross-origin child during +its pending navigation. Sending a stop signal to that child, and then calling +top-window stop, also failed to terminate the pending cross-process navigation in +Chromium. The final test uses the browser's Page.stopLoading command there. These +failures are preserved in `iframe05-interruption-probe*.json` and complete results +directories. No SDK behavior was changed to work around the driver/browser stop +boundary; the exact stop mechanism is recorded per engine. + +Final source/main/legacy results, input hashes, CI and workflow verification are +recorded in `baselines/iframe-history-validation.json`. Task 05 remains doing and +its risk records stay open for remaining device/cache-engine/release acceptance. +No push, tag, npm publication or major-version release is performed. + +## Final verification and rollback + +- Source/main/legacy each pass 90 cases without skips, retries or flaky results: + 270 total, including 36 actual Chromium cache restorations, 72 explicit reload + controls and 162 interruption/recovery cases. +- Full CI passes 1544 tests (1365 unit, 14 engineering, 165 baseline) and strict + checking of 330 production TypeScript files; import/SSR checks pass 3 tests. +- actionlint 1.7.12 validates the updated workflow. All new browser/config files + pass lint. The generated core editor's existing unused directive warning is + unchanged. No new coverage run is claimed for unchanged production source. +- The runtime source and all three iframe distribution files match the preceding + checkpoint byte-for-byte. No package rebuild is necessary for these test/docs + and CI-only changes. Hosted CI, physical devices and other cache engines are + not promoted to passed from local evidence. + +Rollback removes the independent history test/config/server/script and CI step +together, and restores the linked documentation/evidence. It does not require a +runtime rollback or change the old public API. + +Checkpoint subject: `test(iframe): [PKG-IFRAME-05] verify native cached history and interrupted navigation`. diff --git a/refactor/docs-browser-testing.md b/refactor/docs-browser-testing.md index fd5a2703f..49303dc5c 100644 --- a/refactor/docs-browser-testing.md +++ b/refactor/docs-browser-testing.md @@ -1,6 +1,6 @@ # 复用 docs HTML 与在线编辑器进行真实测试 -2026-09-10 已核对下列页面及脚本源码,尚未实际运行页面。优先复用现有 HTML 和示例作为浏览器验收入口,保留旧 URL/参数和编辑器功能;另补可靠断言、状态隔离和报告,不把演示能打开当作兼容性通过。 +2026-09-10 首次清点时仅核对源码。后续实际运行以各任务证据为准:IFRAME-05 已验证真实iframe页面、Monaco Run和桌面历史导航,见[播放器/编辑器记录](changes/2026-09-13-PKG-IFRAME-05-integration.md)及[缓存/中断记录](changes/2026-09-13-PKG-IFRAME-05-history.md)。保留旧 URL/参数和编辑器功能,补可靠断言、状态隔离和报告,不把演示能打开当作兼容性通过。 ## 入口与实际加载方式 @@ -38,6 +38,12 @@ ENG-05 已提供 `yarn test:browser`、8084 隔离服务和 `ARTPLAYER_BROWSER_A ## 任务归属与验收 +IFRAME-05 的 `yarn test:iframe-history` 使用8085的独立缓存页面及完整Chromium通道, +移除Playwright默认禁用BFCache的参数。原8084配置保持不变。只有父子文档标识连续且 +原生pageshow.persisted为true才记为缓存恢复;Firefox/WebKit的reload-control单独计数。 +该命令还验证真实停止加载、HTTP 204、截断文档响应和后续导航/销毁,GitHub浏览器任务 +运行并上传对应报告。它不替代8082实际分发、完整站点、物理设备或其他缓存引擎的验收。 + | 任务 | 负责交付 | | --- | --- | | BASE-04 | 记录上述页面、核心/插件加载路径、存储状态及核心/chapter 的真实行为基线 | diff --git a/refactor/iframe-document-protocol.md b/refactor/iframe-document-protocol.md index bcb61dc5a..1f9159043 100644 --- a/refactor/iframe-document-protocol.md +++ b/refactor/iframe-document-protocol.md @@ -47,6 +47,15 @@ WindowProxy在导航中保持身份。旧协议只用Date.now的请求ID,无 `The instance has been destroyed`。调用方需要处理commit/postMessage的拒绝。 未确认离开前,原文档已完成的响应仍可结算原请求;这属于活文档的正常完成,不是假定所有导航意图都是换页。 +整页进入BFCache时父页也会冻结,子页的best-effort leave不一定送达。实际完整Chromium +恢复证明父子文档及标记可以保持不变:未收到leave的原请求可以在恢复后继续完成;已收到 +leave的原请求保持拒绝。resume不伪造公开inject,也不会让已结算的请求复活。测试同时 +核对实际私有消息阶段和Promise结果,而不只检查history.back或Navigation Timing类型。 + +停止加载、HTTP 204及截断响应不会授权把新请求发送给旧目标。旧文档仍活跃时可完成 +原请求,新队列继续等实际inject;设置后续有效iframe.src或destroy分别恢复或取消队列。 +没有新增隐式超时、自动旧源回退或覆盖window.stop。真实停止方法和网络响应见history测试记录。 + 公开promises记录保留resove/reject和对象身份。普通响应仍尊重用户替换的公开回调; 内部取消独立持有原Promise拒绝入口,不能因用户删除/替换记录而泄漏原Promise。 @@ -56,8 +65,9 @@ WindowProxy在导航中保持身份。旧协议只用Date.now的请求ID,无 不能通过未升级的一侧可靠证明。完整文档保护需双方使用新实现,旧正常协议继续兼容。 - MutationObserver不可用时,只能在公开方法/轮询时检查可观察的源变化;语法legacy目标不等于补齐DOM能力。 - 未标记的自定义原生消息仍按旧协议接受;其文档级归属由应用管理。SDK提供的消息在协商后携带标记。 -- 历史返回用例记录实际pageshow.persisted。普通重新加载不能计作原生BFCache验证;完整播放器、 - 原生BFCache/设备、外部中断导航与文档站实际组合仍在IFRAME-05及发布复盘核验,未由本轮自动豁免。 +- 历史返回必须核对实际pageshow.persisted与文档标识。IFRAME-05新增完整Chromium真实缓存恢复、 + 实际播放器及编辑器、停止/204/截断响应验收。Firefox/WebKit的重新加载对照不能计作缓存恢复; + 原生设备、其余缓存引擎及最终分发仍待验收,不由桌面通过结果自动豁免。 - 本协议不验证父页origin许可,也不把可执行commit变成代码沙箱;嵌入父页和选定子内容仍需可信。 验证入口为test/iframe-navigation.test.js和test/browser/iframe-navigation.spec.js,记录见 diff --git a/refactor/plan.md b/refactor/plan.md index c5e4ff3ac..0afcdb028 100644 --- a/refactor/plan.md +++ b/refactor/plan.md @@ -534,5 +534,5 @@ - PKG-IFRAME-02: [记录](changes/2026-09-12-PKG-IFRAME-02-behavior.md) [记录](baselines/iframe-behavior-validation.json) - PKG-IFRAME-03: [记录](changes/2026-09-12-PKG-IFRAME-03-requests-checkpoint.md) [记录](baselines/iframe-requests-checkpoint.json) [记录](changes/2026-09-12-PKG-IFRAME-03-boundaries-checkpoint.md) [记录](baselines/iframe-boundaries-checkpoint.json) [记录](iframe-message-boundary.md) [记录](changes/2026-09-13-PKG-IFRAME-03-navigation.md) [记录](baselines/iframe-navigation-validation.json) [记录](iframe-document-protocol.md) - PKG-IFRAME-04: [记录](changes/2026-09-13-PKG-IFRAME-04-types.md) [记录](baselines/iframe-types-validation.json) -- PKG-IFRAME-05: [记录](changes/2026-09-13-PKG-IFRAME-05-integration.md) [记录](baselines/iframe-integration-validation.json) +- PKG-IFRAME-05: [记录](changes/2026-09-13-PKG-IFRAME-05-integration.md) [记录](baselines/iframe-integration-validation.json) [记录](changes/2026-09-13-PKG-IFRAME-05-history.md) [记录](baselines/iframe-history-validation.json) - PKG-FACTORY-01: [记录](baselines/factory-assignment-gaps.json) [记录](baselines/factory-compatibility-proposals.json) [记录](factory-compatibility-decision.md) [记录](changes/2026-09-12-PKG-FACTORY-01-decision.md) diff --git a/refactor/progress.md b/refactor/progress.md index 36eaae052..513778036 100644 --- a/refactor/progress.md +++ b/refactor/progress.md @@ -1,5 +1,18 @@ # 进度与证据 +## PKG-IFRAME-05 原生缓存与中断导航检查点(doing) + +新增独立 `yarn test:iframe-history`:完整Chromium通道与可缓存HTTP页面,避免默认 +Playwright禁用BFCache产生的错误验收。源码/main/legacy各90项通过,共270项;其中 +36项实际Chromium缓存恢复、72项Firefox/WebKit重新加载对照、162项停止/204/截断响应 +后的恢复和销毁。核对父子文档标识、原生persisted、媒体状态、请求结算和后续通信。 +GitHub浏览器任务已增加运行及报告上传,actionlint通过;未推送或声称远端CI已执行。 +全仓CI1544、330生产TS检查和3导入测试通过;不把未重新运行的覆盖率标成本轮新结果。 +原生产源码/产物及公开接口未变;整页冻结可能保留未收到leave的原请求,已明确记录。 +见[变更](changes/2026-09-13-PKG-IFRAME-05-history.md)与 +[验证](baselines/iframe-history-validation.json)。物理设备、Firefox/WebKit实际缓存恢复、 +最终分发仍待验收。222项:109 done、10 doing、103 todo。 + ## PKG-IFRAME-05 播放器与真实编辑器检查点(doing) 冻结原支持核心4.5.9的176个npm文件,与已冻结5.4.0、候选核心组成真实媒体矩阵。 @@ -9,8 +22,8 @@ Monaco页面Run流程。覆盖播放、seek/rate、网页全屏、切源、播 源码和运行产物字节未变,旧公开API保持;失败探针、trace及后续通过报告均留存。 全仓CI1544、330生产TS检查、3导入测试通过,配置覆盖率门槛0违例(224运行文件)。 见[变更](changes/2026-09-13-PKG-IFRAME-05-integration.md)和 -[验证](baselines/iframe-integration-validation.json)。实际BFCache、物理设备、外部 -中断导航及最终分发仍待验收,不因此关闭任务或风险。222项:109 done、10 doing、103 todo。 +[验证](baselines/iframe-integration-validation.json)。后续缓存/中断证据见上方;物理设备与 +最终分发仍待验收,不因此关闭任务或风险。222项:109 done、10 doing、103 todo。 ## PKG-IFRAME-04 完成:公开类型、模块入口和编辑器 diff --git a/refactor/risks.json b/refactor/risks.json index b9a4ca75e..14c9d78d8 100644 --- a/refactor/risks.json +++ b/refactor/risks.json @@ -3776,7 +3776,7 @@ ], "status": "open", "confirmation": "reproduced", - "compatibleResolution": "Owned requests and ADR-026 document cancellation are implemented. IFRAME-05 now verifies actual desktop players and Monaco Run on source/main/legacy, including pending-request and multiple-player cleanup. Keep open for actual BFCache/device and interrupted-navigation acceptance; unchanged legacy peers retain documented document-identity limits.", + "compatibleResolution": "Owned requests and ADR-026 document cancellation are implemented. Task 05 verifies actual desktop players/Monaco and source/main/legacy cached history plus stop/204/truncated-response recovery. Full Chromium proves native BFCache; Firefox/WebKit only prove reload controls. Keep open for physical devices, remaining cache engines and final release acceptance; legacy peers retain documented document-identity limits.", "closureCriteria": "Old behavior and candidate fixes have deterministic race/resource tests plus actual iframe integration.", "evidence": [ "refactor/baselines/iframe-contract.md", @@ -3792,7 +3792,9 @@ "refactor/baselines/iframe-navigation-validation.json", "refactor/iframe-document-protocol.md", "refactor/changes/2026-09-13-PKG-IFRAME-05-integration.md", - "refactor/baselines/iframe-integration-validation.json" + "refactor/baselines/iframe-integration-validation.json", + "refactor/changes/2026-09-13-PKG-IFRAME-05-history.md", + "refactor/baselines/iframe-history-validation.json" ] }, { @@ -3819,7 +3821,9 @@ "refactor/baselines/iframe-navigation-validation.json", "refactor/iframe-document-protocol.md", "refactor/changes/2026-09-13-PKG-IFRAME-05-integration.md", - "refactor/baselines/iframe-integration-validation.json" + "refactor/baselines/iframe-integration-validation.json", + "refactor/changes/2026-09-13-PKG-IFRAME-05-history.md", + "refactor/baselines/iframe-history-validation.json" ] }, { diff --git a/refactor/tasks.json b/refactor/tasks.json index feb6ca591..5612857b9 100644 --- a/refactor/tasks.json +++ b/refactor/tasks.json @@ -3710,7 +3710,9 @@ "acceptance": "最终核心与原支持范围核心分别通过;设备/SDK 缺证据不能标完成", "evidence": [ "changes/2026-09-13-PKG-IFRAME-05-integration.md", - "baselines/iframe-integration-validation.json" + "baselines/iframe-integration-validation.json", + "changes/2026-09-13-PKG-IFRAME-05-history.md", + "baselines/iframe-history-validation.json" ] }, { diff --git a/test/history/child.html b/test/history/child.html new file mode 100644 index 000000000..1db779dfa --- /dev/null +++ b/test/history/child.html @@ -0,0 +1,20 @@ + +Iframe media history child + + + + +
+ diff --git a/test/history/fixtures.js b/test/history/fixtures.js new file mode 100644 index 000000000..934c9caad --- /dev/null +++ b/test/history/fixtures.js @@ -0,0 +1,43 @@ +import { test as base, expect } from '@playwright/test' +import { hash } from '../../refactor/scripts/releases.mjs' + +export const test = base.extend({ + diagnostics: [async ({ page, browser, request, browserName }, use, testInfo) => { + const errors = [] + const misses = [] + let stopLoading = () => page.evaluate(() => window.stop()) + const failedRequests = [] + page.on('requestfailed', request => failedRequests.push({ url: request.url(), failure: request.failure() })) + page.on('pageerror', error => errors.push(error.message)) + if (browserName === 'chromium') { + const session = await page.context().newCDPSession(page) + await session.send('Page.enable') + stopLoading = () => session.send('Page.stopLoading') + session.on('Page.backForwardCacheNotUsed', event => misses.push(event)) + } + await use({ misses, stopLoading }) + const manifest = await (await request.get('/manifest.json')).json() + await testInfo.attach('history-environment', { contentType: 'application/json', body: JSON.stringify({ browser: browser.version(), stopMethod: browserName === 'chromium' ? 'CDP Page.stopLoading' : 'top window.stop()', manifest, errors, misses, failedRequests }) }) + expect(errors).toEqual([]) + }, { auto: true }], +}) + +export async function initialize(page, core, relation, testInfo) { + const id = hash(`${testInfo.title}/${testInfo.project.name}/${testInfo.workerIndex}`).slice(0, 16) + await page.goto(`/parent.html?core=${core}&relation=${relation}&case=${id}&epoch=1`) + await expect.poll(() => page.evaluate(() => window.tool.injected)).toBe(true) + await expect.poll(() => page.evaluate(() => window.tool.commit(() => { + return window.art.video.readyState >= 2 + }))).toBe(true) + await page.evaluate(() => { + window.track('old', window.tool.commit((resolve) => { + window.finishHeld = () => resolve(9) + })) + }) + await expect.poll(() => page.evaluate(() => window.tool.commit(() => { + return typeof window.finishHeld + }))).toBe('function') + return id +} + +export { expect } diff --git a/test/history/iframe-history.spec.js b/test/history/iframe-history.spec.js new file mode 100644 index 000000000..aa1201993 --- /dev/null +++ b/test/history/iframe-history.spec.js @@ -0,0 +1,88 @@ +import { expect, initialize, test } from './fixtures.js' + +for (const core of ['4.5.9', '5.4.0', 'candidate']) { + for (const relation of ['same', 'cross']) { + for (const mode of ['paused', 'playing']) { + test(`Iframe cached history ${core}/${relation}/${mode}`, async ({ page, browserName }, testInfo) => { + await initialize(page, core, relation, testInfo) + await page.evaluate(() => window.tool.commit((resolve) => { + const art = window.art + art.currentTime = 1 + art.playbackRate = 1.25 + if (art.video.seeking) + art.video.addEventListener('seeked', () => resolve(true), { once: true }) + else resolve(true) + })) + if (mode === 'playing') { + await page.evaluate(() => window.tool.commit((resolve) => { + window.art.play().then(() => resolve(true)) + })) + await expect.poll(() => page.evaluate(() => window.tool.commit(() => { + return window.art.currentTime + }))).toBeGreaterThan(1.05) + } + const before = await page.evaluate(async () => ({ + parent: window.documentWitness, + child: await window.tool.commit(() => { + return { witness: window.documentWitness, version: window.Artplayer.version, currentTime: window.art.currentTime, rate: window.art.playbackRate } + }), + document: window.timeline.find(packet => packet.type === 'inject').__artplayerIframe.document, + })) + await page.goto('/away.html') + await page.goBack({ waitUntil: 'commit' }) + await expect.poll(() => page.evaluate(() => window.lifecycle?.some(event => event.type === 'pageshow'))).toBe(true) + const parent = await page.evaluate(() => ({ witness: window.documentWitness, lifecycle: window.lifecycle })) + const restored = parent.lifecycle.some(event => event.type === 'pageshow' && event.persisted) + if (browserName === 'chromium') + expect(restored, 'The full Chromium channel must actually restore BFCache').toBe(true) + await expect.poll(() => page.evaluate(() => window.tool.injected)).toBe(true) + const child = await page.evaluate(() => window.tool.commit(() => { + return { witness: window.documentWitness, lifecycle: window.lifecycle, version: window.Artplayer.version, currentTime: window.art.currentTime, rate: window.art.playbackRate, held: typeof window.finishHeld, errors: window.fixtureErrors } + })) + expect(child.errors).toEqual([]) + if (restored) { + expect(parent.witness).toBe(before.parent) + expect(child.witness).toBe(before.child.witness) + expect(child.lifecycle.some(event => event.type === 'pageshow' && event.persisted)).toBe(true) + expect(child.rate).toBe(1.25) + expect(child.currentTime).toBeGreaterThanOrEqual(1) + expect(child.held).toBe('function') + await expect.poll(() => page.evaluate(() => window.timeline.some(packet => packet.__artplayerIframe?.phase === 'resume'))).toBe(true) + const continuity = await page.evaluate(() => ({ old: window.states.old, phases: window.timeline.filter(packet => packet.__artplayerIframe).map(packet => packet.__artplayerIframe.phase), ids: window.timeline.filter(packet => packet.__artplayerIframe).map(packet => packet.__artplayerIframe.document), injects: window.callbacks.filter(packet => packet.type === 'inject').length, privateCallbacks: window.callbacks.filter(packet => packet.type === 'artplayer-tool-iframe:session').length })) + expect(continuity.ids.every(id => id === before.document)).toBe(true) + expect(continuity.injects).toBe(1) + expect(continuity.privateCallbacks).toBe(0) + expect(continuity.old.status).toBe(continuity.phases.includes('leave') ? 'rejected' : 'pending') + await page.evaluate(() => window.tool.commit(() => { + window.finishHeld() + })) + await expect.poll(() => page.evaluate(() => window.states.old.status)).not.toBe('pending') + if (continuity.old.status === 'pending') + expect(await page.evaluate(() => window.states.old)).toEqual({ status: 'resolved', value: 9 }) + else + expect(continuity.old).toEqual({ status: 'rejected', error: 'The iframe document has changed' }) + } + else { + expect(parent.witness).not.toBe(before.parent) + expect(child.witness).not.toBe(before.child.witness) + expect(child.lifecycle.some(event => event.persisted)).toBe(false) + } + const playback = await page.evaluate(() => window.tool.commit((resolve) => { + window.art.play().then(() => { + const result = { playing: !window.art.video.paused, width: window.art.video.videoWidth } + resolve(result) + }) + })) + expect(playback.playing).toBe(true) + expect(playback.width).toBeGreaterThan(0) + await page.evaluate(() => window.tool.commit(() => { + window.art.destroy() + })) + const final = await page.evaluate(() => ({ pending: Object.keys(window.tool.promises).length, errors: window.fixtureErrors })) + expect(final).toEqual({ pending: 0, errors: [] }) + await testInfo.attach('iframe-history', { contentType: 'application/json', body: JSON.stringify({ outcome: restored ? 'actual-bfcache' : 'reload-control', core, relation, mode, before, parent, child, playback, final, scope: 'Real top-level history with embedded player. Reload controls do not satisfy BFCache acceptance. No simulated pageshow events or document recreation is counted as cached restoration.' }) }) + await page.evaluate(() => window.tool.destroy()) + }) + } + } +} diff --git a/test/history/iframe-interruption.spec.js b/test/history/iframe-interruption.spec.js new file mode 100644 index 000000000..ab13f6873 --- /dev/null +++ b/test/history/iframe-interruption.spec.js @@ -0,0 +1,69 @@ +import { expect, initialize, test } from './fixtures.js' + +for (const core of ['4.5.9', '5.4.0', 'candidate']) { + for (const relation of ['same', 'cross']) { + for (const mode of ['stop', '204', 'reset']) { + test(`Iframe interrupted navigation ${core}/${relation}/${mode}`, async ({ page, request, diagnostics }, testInfo) => { + const id = await initialize(page, core, relation, testInfo) + const original = await page.evaluate(() => ({ source: window.targetFrame.src, document: window.timeline.find(packet => packet.type === 'inject').__artplayerIframe.document })) + const witness = await page.evaluate(() => window.tool.commit(() => { + return window.documentWitness + })) + const stall = new URL(`/stall?case=${id}`, original.source).href + await page.evaluate((stall) => { + window.targetFrame.src = stall + window.track('queued', window.tool.commit(() => { + window.executions = (window.executions || 0) + 1 + return new URL(location.href).searchParams.get('epoch') + })) + }, stall) + await expect.poll(async () => (await (await request.get(`/status?case=${id}`)).json()).pending).toBe(true) + expect(await page.evaluate(() => window.tool.injected)).toBe(false) + expect(await page.evaluate(() => window.states.queued.status)).toBe('pending') + if (mode === 'stop') + await diagnostics.stopLoading() + else + expect((await request.get(`/release?case=${id}&mode=${mode}`)).ok()).toBe(true) + await expect.poll(async () => (await (await request.get(`/status?case=${id}`)).json()).pending).toBe(false) + if (mode === 'reset') { + await expect.poll(() => page.evaluate(() => window.states.old.status)).toBe('rejected') + expect(await page.evaluate(() => window.states.old.error)).toBe('The iframe document has changed') + } + else { + await page.evaluate(() => window.targetFrame.contentWindow.postMessage({ type: 'history-fixture-finish' }, '*')) + await expect.poll(() => page.evaluate(() => window.timeline.some(packet => packet.type === 'history-fixture-old-document'))).toBe(true) + expect(await page.evaluate(() => window.timeline.find(packet => packet.type === 'history-fixture-old-document').data)).toEqual({ witness, executions: 0 }) + await expect.poll(() => page.evaluate(() => window.states.old.status)).toBe('resolved') + expect(await page.evaluate(() => window.states.old.value)).toBe(9) + } + expect(await page.evaluate(() => window.states.queued.status)).toBe('pending') + const finalUrl = new URL(original.source) + finalUrl.searchParams.set('epoch', '2') + await page.evaluate(url => window.targetFrame.src = url, finalUrl.href) + await expect.poll(() => page.evaluate(() => window.states.queued.status)).toBe('resolved') + expect(await page.evaluate(() => window.states.queued.value)).toBe('2') + await expect.poll(() => page.evaluate(() => window.tool.commit(() => { + return window.art.video.readyState >= 2 + }))).toBe(true) + const recovered = await page.evaluate(() => ({ states: window.states, pending: Object.keys(window.tool.promises).length, document: window.timeline.filter(packet => packet.type === 'inject').at(-1).__artplayerIframe.document })) + expect(recovered.document).not.toBe(original.document) + expect(recovered.pending).toBe(0) + await page.evaluate((stall) => { + window.targetFrame.src = stall + window.track('cleanup', window.tool.commit(() => { + return 'must not execute' + })) + }, stall) + await expect.poll(async () => (await (await request.get(`/status?case=${id}`)).json()).pending).toBe(true) + await page.evaluate(() => { + window.tool.destroy() + window.targetFrame.remove() + }) + await expect.poll(() => page.evaluate(() => window.states.cleanup.status)).toBe('rejected') + expect(await page.evaluate(() => window.states.cleanup.error)).toBe('The instance has been destroyed') + await expect.poll(async () => (await (await request.get(`/status?case=${id}`)).json()).pending).toBe(false) + await testInfo.attach('iframe-interruption', { contentType: 'application/json', body: JSON.stringify({ outcome: 'recovered-and-cleaned', core, relation, mode, original, recovered, scope: 'Native browser stop (Chromium Page.stopLoading; other engines top window.stop), HTTP 204 without document replacement, or truncated committed HTTP response. New requests wait for actual injection; applications resume through a later valid navigation or destroy. No implicit timeout or automatic failed-navigation recovery is claimed.' }) }) + }) + } + } +} diff --git a/test/history/observe.js b/test/history/observe.js new file mode 100644 index 000000000..d90f4b4e2 --- /dev/null +++ b/test/history/observe.js @@ -0,0 +1,16 @@ +window.documentWitness = Math.random().toString(36) +window.lifecycle = [] +window.fixtureErrors = [] +for (const name of ['pageshow', 'pagehide']) { + addEventListener(name, event => window.lifecycle.push({ type: event.type, persisted: event.persisted })) +} +addEventListener('error', event => window.fixtureErrors.push(event.message)) +addEventListener('unhandledrejection', event => window.fixtureErrors.push(String(event.reason))) +addEventListener('message', (event) => { + if (window === window.parent || event.source !== window.parent) + return + if (event.data?.type === 'history-fixture-finish') { + window.parent.postMessage({ type: 'history-fixture-old-document', data: { witness: window.documentWitness, executions: window.executions || 0 } }, '*') + window.finishHeld() + } +}) diff --git a/test/history/parent.html b/test/history/parent.html new file mode 100644 index 000000000..8b7f3bd8b --- /dev/null +++ b/test/history/parent.html @@ -0,0 +1,26 @@ + +Iframe document history + + + + diff --git a/test/history/server.mjs b/test/history/server.mjs new file mode 100644 index 000000000..f4668d23e --- /dev/null +++ b/test/history/server.mjs @@ -0,0 +1,127 @@ +/* eslint-disable antfu/no-top-level-await -- Assemble immutable test resources before listening. */ +import assert from 'node:assert/strict' +import { Buffer } from 'node:buffer' +import fs from 'node:fs' +import http from 'node:http' +import path from 'node:path' +import process from 'node:process' +import { ensureArchive, hash, readMember } from '../../refactor/scripts/releases.mjs' +import { iframeCandidate } from '../helpers/iframe.js' +import { compilePackage } from '../helpers/load.js' + +const port = Number(process.env.ARTPLAYER_IFRAME_HISTORY_PORT || 8085) +assert(Number.isInteger(port) && port > 0 && port < 65536) +const tool = await iframeCandidate() +const mapFile = process.env.ARTPLAYER_BROWSER_ARTIFACTS +let coreBytes +if (mapFile) { + const map = JSON.parse(fs.readFileSync(mapFile)) + assert(typeof map.artplayer === 'string', 'Missing explicit core artifact') + coreBytes = fs.readFileSync(path.resolve(path.dirname(mapFile), map.artplayer)) +} +else { + coreBytes = Buffer.from(await compilePackage('artplayer', 'umd')) +} +const cores = new Map([['candidate', coreBytes]]) +const releases = JSON.parse(fs.readFileSync('refactor/baselines/releases.json')).releases +const oldCore = JSON.parse(fs.readFileSync('refactor/baselines/iframe-core.json')).release +for (const release of [oldCore, releases.find(release => release.name === 'artplayer')]) { + const member = `package/${release.manifest.main.replace(/^\.\//, '')}` + const bytes = readMember(await ensureArchive(release), member) + assert.equal(hash(bytes), release.files[member]) + cores.set(release.version, bytes) +} +const files = new Map(['parent.html', 'child.html', 'observe.js'].map(name => [name, fs.readFileSync(new URL(name, import.meta.url))])) +files.set('tool.js', Buffer.from(tool.code)) +files.set('pattern.mp4', fs.readFileSync('test/browser/media/pattern.mp4')) +const manifest = { tool: { name: tool.name, sha256: hash(tool.code) }, cores: Object.fromEntries([...cores].map(([name, bytes]) => [name, hash(bytes)])), files: Object.fromEntries([...files].map(([name, bytes]) => [name, hash(bytes)])) } +const stalled = new Map() +function send(req, res, bytes, type) { + res.setHeader('Content-Type', type) + res.setHeader('Cache-Control', 'public, max-age=60') + if (req.headers.range) { + const range = /^bytes=(\d+)-(\d*)$/.exec(req.headers.range) + const start = Number(range?.[1]) + const end = range?.[2] ? Math.min(Number(range[2]), bytes.length - 1) : bytes.length - 1 + if (!range || start > end || start >= bytes.length) { + res.writeHead(416).end() + return + } + res.statusCode = 206 + res.setHeader('Content-Range', `bytes ${start}-${end}/${bytes.length}`) + bytes = bytes.subarray(start, end + 1) + } + res.setHeader('Content-Length', bytes.length) + res.setHeader('Accept-Ranges', 'bytes') + res.end(bytes) +} +const server = http.createServer((req, res) => { + try { + assert.equal(req.method, 'GET') + const url = new URL(req.url, `http://127.0.0.1:${port}`) + if (url.pathname === '/manifest.json') { + res.setHeader('Content-Type', 'application/json') + res.end(JSON.stringify(manifest)) + return + } + if (url.pathname === '/away.html') { + send(req, res, Buffer.from('Away

Away from player

'), 'text/html') + return + } + if (url.pathname === '/favicon.ico') { + res.writeHead(204).end() + return + } + if (['/stall', '/release', '/status'].includes(url.pathname)) { + const id = url.searchParams.get('case') + assert(id && /^[a-f0-9]{16}$/.test(id)) + if (url.pathname === '/stall') { + assert(!stalled.has(id) && stalled.size < 100, 'Duplicate or excessive test barrier') + stalled.set(id, res) + res.on('close', () => { + if (stalled.get(id) === res) + stalled.delete(id) + }) + return + } + if (url.pathname === '/release') { + const pending = stalled.get(id) + assert(pending, 'No stalled request') + if (url.searchParams.get('mode') === 'reset') { + pending.writeHead(200, { 'Content-Type': 'text/html', 'Content-Length': 1000 }) + pending.write('Interrupted response', () => pending.destroy()) + } + else { + pending.writeHead(204).end() + } + } + res.setHeader('Content-Type', 'application/json') + res.setHeader('Cache-Control', 'no-store') + res.end(JSON.stringify({ pending: stalled.has(id) })) + return + } + if (url.pathname === '/core.js') { + const bytes = cores.get(url.searchParams.get('core')) + assert(bytes, 'Unknown core') + send(req, res, bytes, 'text/javascript') + return + } + const name = url.pathname.slice(1) + let bytes = files.get(name) + assert(bytes, 'Unknown fixture resource') + if (name === 'child.html') { + const core = url.searchParams.get('core') + assert(cores.has(core), 'Unknown child core') + bytes = Buffer.from(bytes.toString().replace('__CORE__', core)) + } + send(req, res, bytes, name.endsWith('.js') ? 'text/javascript' : name.endsWith('.mp4') ? 'video/mp4' : 'text/html') + } + catch (error) { res.writeHead(400, { 'Content-Type': 'text/plain' }).end(error.message) } +}) +server.listen(port, '127.0.0.1', () => process.stdout.write(`Iframe history server: ${port}\n`)) +for (const signal of ['SIGINT', 'SIGTERM']) { + process.on(signal, () => { + server.closeAllConnections() + server.close() + }) +}