Version
1.63.0 (WebKit 26.6 revision 2359); control: 1.62.1 (WebKit 26.5 revision 2336)
Steps to reproduce
The complete standalone reproduction below uses only a loopback HTTP server, one database/object store/key and a service worker that claims clients. The worker has no fetch handler, cache, IndexedDB access or background work. It contains no application code, account, credential or production request. The https://example.test/ destination is fulfilled locally.
Save the code as Playwright-WebKit-sentetik-ornek.mjs in an isolated directory, then run:
npm install @playwright/test@1.63.0
npx playwright install webkit
node Playwright-WebKit-sentetik-ornek.mjs
node Playwright-WebKit-sentetik-ornek.mjs --no-sw
The first run fails during the read after back navigation; the no-worker control passes. Repeat with Playwright 1.62.1 and its bundled WebKit as the passing earlier-version control.
// Standalone synthetic reproduction. No Nardora account, game code or production request.
// npm install @playwright/test@1.63.0 && npx playwright install webkit
// node Playwright-WebKit-sentetik-ornek.mjs
// Control: repeat with --no-sw, or @playwright/test 1.62.1 and its WebKit.
// PLAYWRIGHT_PACKAGE may point to an already installed @playwright/test directory.
import { createServer } from 'node:http';
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const packagePath = process.env.PLAYWRIGHT_PACKAGE || '@playwright/test';
const { webkit, expect } = require(packagePath);
const withWorker = !process.argv.includes('--no-sw');
const html = `<!doctype html><html><body>
<p id="status">loading</p><a href="https://example.test/">Other site</a>
<script type="module">
const ready = new Promise((resolve, reject) => {
const request = indexedDB.open('synthetic-roundtrip', 1);
request.onupgradeneeded = () => request.result.createObjectStore('items');
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
async function transaction(value) {
const db = await ready;
return new Promise((resolve, reject) => {
const tx = db.transaction('items', 'readwrite');
const request = tx.objectStore('items').get('name');
request.onsuccess = () => {
if (value) tx.objectStore('items').put(value, 'name');
};
tx.oncomplete = () => resolve(request.result);
tx.onerror = tx.onabort = () => reject(tx.error);
});
}
transaction().then(() => { document.querySelector('#status').textContent = 'ready'; });
window.save = () => transaction('Synthetic Player');
window.read = () => transaction();
${withWorker ? "addEventListener('load', () => navigator.serviceWorker.register('/worker.js'));" : ''}
</script></body></html>`;
const server = createServer((request, response) => {
if (request.url === '/worker.js') {
response.writeHead(200, { 'Content-Type': 'application/javascript' });
// No fetch handler, cache, IndexedDB, game code or background work in this worker.
response.end("self.addEventListener('activate', event => event.waitUntil(self.clients.claim()));");
} else {
response.writeHead(200, { 'Content-Type': 'text/html' });
response.end(html);
}
});
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
const browser = await webkit.launch();
const page = await browser.newPage();
const base = `http://127.0.0.1:${server.address().port}/`;
let phase = 'initial read';
try {
await page.route('https://example.test/', route => route.fulfill({
contentType: 'text/html', body: '<h1>Local synthetic destination</h1>'
}));
await page.goto(base);
await expect(page.locator('#status')).toHaveText('ready', { timeout: 7000 });
if (withWorker) {
await page.evaluate(() => navigator.serviceWorker.ready);
await page.waitForFunction(() => navigator.serviceWorker.controller, null, { timeout: 7000 });
}
await page.evaluate(() => window.save());
await page.locator('a').press('Enter');
await expect(page).toHaveURL('https://example.test/');
phase = 'read after back navigation';
await page.goBack();
await expect(page.locator('#status')).toHaveText('ready', { timeout: 7000 });
expect(await page.evaluate(() => window.read())).toBe('Synthetic Player');
console.log(JSON.stringify({ result: 'PASS', engine: browser.version(), withWorker, phase }));
} catch (error) {
console.log(JSON.stringify({ result: 'FAIL', engine: browser.version(), withWorker, phase,
message: error.message.split('\n').slice(0, 7).join(' ') }));
process.exitCode = 1;
} finally {
await browser.close();
await new Promise(resolve => server.close(resolve));
}
Expected behavior
After a cross-site round trip, the IndexedDB transaction completes and returns the previously saved synthetic value.
Actual behavior
After navigating back, database opening succeeds but the transaction does not complete within the unchanged seven-second expectation. The page remains at loading. Removing the service worker or using Playwright 1.62.1/WebKit 26.5 makes the same round trip pass.
Additional context
Additional isolated controls on 12 September 2026:
| Control |
Result |
| Another port on 127.0.0.1, no route interception |
PASS |
| Another port on 127.0.0.1, intercepted destination |
PASS |
| 127.0.0.1 to localhost, intercepted destination |
FAIL after back |
| HTTP example.test instead of HTTPS |
FAIL after back |
| Remove the destination route before back |
FAIL after back |
| Wait for serviceWorker.ready before opening the database |
FAIL after back |
| history.back() instead of page.goBack() |
FAIL after back |
| Explicitly close the database before leaving the page |
FAIL after back |
This narrows the trigger to a cross-site round trip with a controlling service worker; it is not evidence that route interception alone is the cause. A real external-destination control was inconclusive because navigation failed before the back step.
We have not identified a WebKit source commit or tested a physical Safari release. We have not disabled service workers, reset storage or weakened the application's atomic storage contract to make the candidate pass. Please advise whether this belongs to Playwright's WebKit integration or should be tracked in WebKit, and whether there is a supported fixed build to validate.
Environment
OS: Windows
Node.js: 24.18.0
@playwright/test: 1.63.0
Bundled WebKit: 26.6, revision 2359
Control: @playwright/test 1.62.1; WebKit 26.5, revision 2336
Physical Safari: not tested
Version
1.63.0 (WebKit 26.6 revision 2359); control: 1.62.1 (WebKit 26.5 revision 2336)
Steps to reproduce
The complete standalone reproduction below uses only a loopback HTTP server, one database/object store/key and a service worker that claims clients. The worker has no fetch handler, cache, IndexedDB access or background work. It contains no application code, account, credential or production request. The
https://example.test/destination is fulfilled locally.Save the code as
Playwright-WebKit-sentetik-ornek.mjsin an isolated directory, then run:The first run fails during the read after back navigation; the no-worker control passes. Repeat with Playwright 1.62.1 and its bundled WebKit as the passing earlier-version control.
Expected behavior
After a cross-site round trip, the IndexedDB transaction completes and returns the previously saved synthetic value.
Actual behavior
After navigating back, database opening succeeds but the transaction does not complete within the unchanged seven-second expectation. The page remains at
loading. Removing the service worker or using Playwright 1.62.1/WebKit 26.5 makes the same round trip pass.Additional context
Additional isolated controls on 12 September 2026:
This narrows the trigger to a cross-site round trip with a controlling service worker; it is not evidence that route interception alone is the cause. A real external-destination control was inconclusive because navigation failed before the back step.
We have not identified a WebKit source commit or tested a physical Safari release. We have not disabled service workers, reset storage or weakened the application's atomic storage contract to make the candidate pass. Please advise whether this belongs to Playwright's WebKit integration or should be tracked in WebKit, and whether there is a supported fixed build to validate.
Environment
OS: Windows Node.js: 24.18.0 @playwright/test: 1.63.0 Bundled WebKit: 26.6, revision 2359 Control: @playwright/test 1.62.1; WebKit 26.5, revision 2336 Physical Safari: not tested