Skip to content

[BUG] WebKit: Cache Storage entry silently lost across page.reload() (container survives, entry does not) #41618

Description

Context

We recently added a mobile-ios project (devices['iPhone 17'], WebKit engine) to our Playwright config and found that a bare Cache Storage write does not survive page.reload() under WebKit, while the same code works fine on chromium and a Chromium-based mobile emulation project.

This looks adjacent to the WebKit navigation/document-loading regression documented in #37766 (a Sept 2025 WebKit binary roll that caused crashes in WebCore::Navigation::initializeForNewWindow / DocumentLoader::commitLoad, fixed upstream in Playwright 1.57 per https://bugs.webkit.org/show_bug.cgi?id=300402). We are on Playwright 1.61.0, well past that fix, so we do not see a crash — but we do see silent data loss in the same code path. I searched issues for "CacheStorage reload", "cache.put webkit reload", "caches.open webkit", "webkit cache storage reload", and "webkit cache lost" and found no existing report matching this exact symptom, so filing fresh with #37766 linked as related prior art.

Repro

import { test } from '@playwright/test';

test('cache does not survive reload on webkit', async ({ page }) => {
  // Optional: rules out any app-registered service worker as the cause.
  await page.route('**/sw.js*', (route) => route.abort());

  await page.goto('/');
  await page.evaluate(async () => {
    const cache = await caches.open('repro-cache-v1');
    await cache.put('/meta', new Response(JSON.stringify({ hello: 'world' })));
  });

  await page.reload();

  const afterReload = await page.evaluate(async () => {
    const cache = await caches.open('repro-cache-v1');
    const resp = await cache.match('/meta');
    return resp ? await resp.text() : null;
  });
  console.log('afterReload:', afterReload); // null on WebKit; the actual JSON on chromium

  const keys = await page.evaluate(() => caches.keys());
  console.log('keys:', keys); // still lists 'repro-cache-v1' on WebKit even though the entry inside is gone
});

Run against a devices['iPhone 17'] (or any WebKit) project vs a Chromium project, pointed at any static origin (no app code needed — reproduces against a plain static file server, a Vite dev server, and a production vite build && vite preview origin equally).

Observed

  • WebKit: afterReload is null. keys() still returns ['repro-cache-v1'] — the cache container persists, but the entry written just before reload is gone.
  • Chromium (desktop and mobile-emulated): afterReload returns the original JSON payload as expected. keys() also returns ['repro-cache-v1'].

Expected

A Cache Storage entry written via cache.put() before page.reload() should still be readable via cache.match() after the reload, matching Chromium's behavior and real Safari's behavior (Cache Storage is spec'd to be persistent, not tied to the page lifecycle).

Environment

  • Playwright: 1.61.0
  • Node: v24.14.0
  • OS: macOS (Darwin, arm64)
  • Browser: WebKit (bundled webkit-2311)
  • Confirmed reproduces against: Vite dev server, a production static build served via vite preview, ruling out any dev-only service-worker shim as the cause.

Additional notes

  • Not a crash — Playwright and the page remain fully responsive after the reload; only the cache entry is missing.
  • Reproduces with any app-registered service worker explicitly blocked via page.route(), ruling out interference from an app's own SW.
  • We suspect this may be a residual/adjacent effect of the same WebKit navigation-internals rework referenced in [Bug]: WebKit crashes after page reload in 1.56 #37766, but have not root-caused it further on our end.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions