Skip to content

feat(storage): capture OPFS in storage state - #42248

Open
Yury Semikhatsky (yury-s) wants to merge 5 commits into
microsoft:mainfrom
yury-s:fix-41400
Open

feat(storage): capture OPFS in storage state#42248
Yury Semikhatsky (yury-s) wants to merge 5 commits into
microsoft:mainfrom
yury-s:fix-41400

Conversation

@yury-s

Copy link
Copy Markdown
Member

Summary

  • add opt-in OPFS capture and restoration to storage state
  • preserve binary files, nested directories, and empty directories across browser and request contexts
  • handle Firefox worker-based writes and persistent WebKit contexts

Fixes #41400

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Add opt-in OPFS serialization and restoration for browser and request context storage state, including cross-browser handling and round-trip coverage.\n\nFixes: microsoft#41400
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@yury-s
Yury Semikhatsky (yury-s) marked this pull request as ready for review August 14, 2026 17:24
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

The firefox utility world is a sandbox with an extended principal, so the
page is denied access to objects allocated there and writing a Uint8Array
built in that world fails with 'Permission denied to access property "data"'.
Decode base64 through the page's own fetch instead, so that the blob passed
to write() belongs to the page. This works in all browsers and removes the
firefox-specific worker.
@github-actions

Copy link
Copy Markdown
Contributor

Test results for "tests 1"

1 failed
❌ [playwright-test] › ui-mode-test-network-tab.spec.ts:107 › should filter network requests by url @windows-latest-node22

20 flaky ⚠️ [chromium-library] › library/global-fetch.spec.ts:293 › should return security details from response `@frozen-time-library-chromium-linux`
⚠️ [chromium-library] › library/har.spec.ts:639 › should have security details `@frozen-time-library-chromium-linux`
⚠️ [chromium-library] › library/video.spec.ts:736 › screencast › should work with video+trace `@frozen-time-library-chromium-linux`
⚠️ [chromium-library] › library/browsercontext-page-event.spec.ts:160 › should work with Shift-clicking `@chromium-ubuntu-22.04-arm-node20`
⚠️ [chromium-library] › library/global-fetch.spec.ts:293 › should return security details from response `@chromium-ubuntu-22.04-arm-node20`
⚠️ [chromium-library] › library/har.spec.ts:639 › should have security details `@chromium-ubuntu-22.04-arm-node20`
⚠️ [chromium-library] › library/global-fetch.spec.ts:293 › should return security details from response `@realtime-time-library-chromium-linux`
⚠️ [chromium-library] › library/har.spec.ts:639 › should have security details `@realtime-time-library-chromium-linux`
⚠️ [chromium-library] › library/beforeunload.spec.ts:130 › should support dismissing the dialog multiple times `@chromium-ubuntu-22.04-node24`
⚠️ [chromium-library] › library/global-fetch.spec.ts:293 › should return security details from response `@chromium-ubuntu-22.04-node24`
⚠️ [chromium-library] › library/har.spec.ts:639 › should have security details `@chromium-ubuntu-22.04-node24`
⚠️ [chromium-library] › library/global-fetch.spec.ts:293 › should return security details from response `@chromium-ubuntu-22.04-node20`
⚠️ [chromium-library] › library/har.spec.ts:639 › should have security details `@chromium-ubuntu-22.04-node20`
⚠️ [chromium-library] › library/global-fetch.spec.ts:293 › should return security details from response `@chromium-ubuntu-22.04-node22`
⚠️ [chromium-library] › library/har.spec.ts:639 › should have security details `@chromium-ubuntu-22.04-node22`
⚠️ [firefox-library] › library/global-fetch.spec.ts:293 › should return security details from response `@firefox-ubuntu-22.04-node20`
⚠️ [firefox-library] › library/har.spec.ts:639 › should have security details `@firefox-ubuntu-22.04-node20`
⚠️ [firefox-page] › page/page-event-request.spec.ts:181 › should return response body when Cross-Origin-Opener-Policy is set `@firefox-ubuntu-22.04-node20`
⚠️ [webkit-library] › library/global-fetch.spec.ts:293 › should return security details from response `@webkit-ubuntu-22.04-node20`
⚠️ [webkit-library] › library/har.spec.ts:639 › should have security details `@webkit-ubuntu-22.04-node20`

51116 passed, 1228 skipped


Merge workflow run.

@github-actions

Copy link
Copy Markdown
Contributor

Test results for "MCP"

3 failed
❌ [chrome] › mcp/cli-core.spec.ts:248 › click in iframe @mcp-macos-latest-chrome
❌ [chrome] › mcp/cli-devtools.spec.ts:189 › request with out-of-range index @mcp-macos-latest-chrome
❌ [firefox] › mcp/cli-json.spec.ts:220 › request and per-part commands return JSON result @mcp-windows-latest-firefox

8098 passed, 1311 skipped


Merge workflow run.

@github-actions

Copy link
Copy Markdown
Contributor

Hi, I'm the Playwright bot and I took a first look at the CI failures.

🟡 One Windows-only failure I can't pin either way

The latest run has a single real failure — ui-mode-test-network-tab.spec.ts:107 › should filter network requests by url on windows-latest-node22, a timeout. The earlier storage-state regressions are gone from this run, so the OPFS work looks fixed. This one test is green 1028/1028 in the results DB and has only ever failed on this PR's SHA — so I can't call it a proven flake, but a UI-mode network-tab timeout doesn't obviously touch the storage/OPFS diff either. Leans infra noise; a re-run should settle it.

Details

Overall: no storage-state failures remain in the latest run — the group that broke earlier revisions is fixed. What's left is one uncertain Windows timeout plus retry-rescued flakes → yellow.

Uncertain

  • [playwright-test] › ui-mode-test-network-tab.spec.ts:107 › should filter network requests by url @windows-latest-node22timedOut, one OS, one test. Across the results DB it's 1028/1028 passing, and the only recorded failure is this PR's own SHA (93c852b2), so the hard rule blocks calling it a known flake. But it's a UI-mode network-tab render/filter test that this storage-state + OPFS PR (injected/storageScript.ts, server/client browserContext.ts, fetch.ts, storage-state protocol structs) doesn't plausibly reach. A timeout on Windows in UI mode is a common infra signature. Re-run it — if it goes green, it's noise. windows-latest-node22 history for this test:

    🟩🟩🟩🟩🟥

Pre-existing flake / infra

  • The 20 "flaky" entries in the report were all rescued by retry within the run — library/global-fetch.spec.ts:293 › should return security details from response, library/har.spec.ts:639 › should have security details, video.spec.ts, beforeunload.spec.ts, and friends, all on Chromium Linux bots. None are real failures, and none sit on the storage-state path this PR touches.

Triaged by the Playwright bot - agent run

@github-actions

Copy link
Copy Markdown
Contributor

Hi, I'm the Playwright bot — I took a first pass at the CI failures here.

🟡 No failure points at this PR, but three timeouts I can't fully clear

The four red tests are all timedOut, none touch the OPFS/storage-state path this PR changes, and they cluster on two specific bots (mcp-macos-latest-chrome, windows-latest-node22) — the signature of slow/overloaded runners, not a code bug. One is a confirmed pre-existing flake; the other three I can't strictly prove either way, so I'm landing on yellow.

Details

Overall: the diff is scoped to OPFS capture in storage state (fetch.ts, browserContext.ts, networkDispatchers.ts, protocol, docs). It doesn't touch MCP CLI or the trace/UI-mode network tab. Every failure is a timeout, and the same tests time out on the same bots across this PR's last few runs (31830009958, 31830010211) as in the latest report — a bot/OS pattern, not a per-feature one.

Pre-existing flake / infra

  • [firefox] › mcp/cli-json.spec.ts:220 › request and per-part commands return JSON result (mcp-windows-latest-firefox) — pre-existing flake. In the test-results DB it failed 4 of 723 runs across 2 unrelated PRs, passing the rest. The PR doesn't touch the MCP JSON path.

Uncertain (most likely infra, unproven)

  • [chrome] › mcp/cli-core.spec.ts:248 › click in iframe (mcp-macos-latest-chrome)

  • [chrome] › mcp/cli-devtools.spec.ts:189 › request with out-of-range index (mcp-macos-latest-chrome)

  • [playwright-test] › ui-mode-test-network-tab.spec.ts:107 › should filter network requests by url (windows-latest-node22)

    All three have 0 failures across 700–1000+ prior runs in the DB, so I can't cite the same test failing off this PR to call it a flake outright. But they can't be reached by the diff — OPFS storage-state capture has nothing to do with clicking an iframe, an out-of-range MCP request index, or filtering the UI-mode network tab — and all three timedOut on the same two bots in earlier runs of this same PR (31830009958, 31830010211). That reads as slow-runner/infra noise. To be sure, a rerun on those bots should clear them; if the identical (test, bot) timeouts persist across reruns, worth a second look at macOS-chrome / Windows agent load.

Triaged by the Playwright bot - agent run

- `localStorage` <[Array]<[Object]>>
- `name` <[string]>
- `value` <[string]>
- `opfs` ?<[Array]<[Object]>> Entries in the origin private file system.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

types here were a regret, we stopped doing them since idb

});

it('should round-trip OPFS in a persistent WebKit context', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/41400' } }, async ({ browserName, launchPersistent, server }) => {
it.skip(browserName !== 'webkit');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a weird feature, why supporting something that does not work on major browsers?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Capture OPFS in storageState

3 participants