Version
1.62.1
Steps to reproduce
Serve an XML document that references an XSL stylesheet, then navigate to it with waitUntil: 'domcontentloaded'.
import http from 'node:http';
import { chromium, firefox } from 'playwright';
const xsl = `<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/"><html><body><h1>transformed</h1></body></html></xsl:template>
</xsl:stylesheet>`;
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/style.xsl"?>
<root><item>hello</item></root>`;
const server = http.createServer((req, res) => {
const [type, body] = req.url.startsWith('/style.xsl') ? ['text/xsl', xsl] : ['application/xml', xml];
res.writeHead(200, { 'content-type': type });
res.end(body);
});
await new Promise((resolve) => server.listen(0, resolve));
const url = `http://127.0.0.1:${server.address().port}/doc.xml`;
for (const [name, browserType] of Object.entries({ firefox, chromium })) {
const browser = await browserType.launch();
const page = await browser.newPage();
console.log(`\n${name} ${browser.version()}`);
for (const waitUntil of ['domcontentloaded', 'load']) {
const started = Date.now();
try {
await page.goto(url, { waitUntil, timeout: 5000 });
console.log(` goto '${waitUntil}' -> resolved in ${Date.now() - started}ms`);
} catch (error) {
console.log(` goto '${waitUntil}' -> ${error.message.split('\n')[0]}`);
}
}
console.log(` document.readyState: ${await page.evaluate(() => document.readyState)}`);
try {
await page.waitForLoadState('domcontentloaded', { timeout: 5000 });
console.log(' waitForLoadState(domcontentloaded) on the loaded page -> resolved');
} catch (error) {
console.log(` waitForLoadState(domcontentloaded) on the loaded page -> ${error.message.split('\n')[0]}`);
}
await browser.close();
}
server.close();
Expected behavior
goto with waitUntil: 'domcontentloaded' resolves, as it does in Chromium and as waitUntil: 'load' does in Firefox. load cannot fire before DOMContentLoaded, so once the document is loaded, waiting for the earlier event should never block.
Actual behavior
In Firefox the event is never reported for the transform output, so both goto and waitForLoadState hit their timeout while the document is fully loaded (readyState: 'complete', transformed DOM in place). Retrying and using a fresh browser context change nothing. Chromium is fine.
Any XSL-styled XML page reproduces it, not just the local server above, e.g. https://yoast.com/sitemap_index.xml.
Additional context
No response
Environment
System:
OS: macOS 26.2
CPU: (14) arm64 Apple M4 Pro
Memory: 237.63 MB / 24.00 GB
Binaries:
Node: 24.15.0 - /Users/.../.nvm/versions/node/v24.15.0/bin/node
npm: 11.12.1 - /Users/.../.nvm/versions/node/v24.15.0/bin/npm
pnpm: 11.15.1 - /opt/homebrew/bin/pnpm
IDEs:
Cursor: 3.15.6 - /usr/local/bin/cursor
Claude Code: 2.1.169 - /Users/.../.local/bin/claude
Languages:
Bash: 3.2.57 - /bin/bash
npmPackages:
@playwright/browser-chromium: 1.62.1 => 1.62.1
@playwright/browser-firefox: 1.62.1 => 1.62.1
playwright: 1.62.1 => 1.62.1
Version
1.62.1
Steps to reproduce
Serve an XML document that references an XSL stylesheet, then navigate to it with
waitUntil: 'domcontentloaded'.Expected behavior
goto with waitUntil: 'domcontentloaded' resolves, as it does in Chromium and as waitUntil: 'load' does in Firefox. load cannot fire before DOMContentLoaded, so once the document is loaded, waiting for the earlier event should never block.
Actual behavior
In Firefox the event is never reported for the transform output, so both goto and waitForLoadState hit their timeout while the document is fully loaded (readyState: 'complete', transformed DOM in place). Retrying and using a fresh browser context change nothing. Chromium is fine.
Any XSL-styled XML page reproduces it, not just the local server above, e.g.
https://yoast.com/sitemap_index.xml.Additional context
No response
Environment
System: OS: macOS 26.2 CPU: (14) arm64 Apple M4 Pro Memory: 237.63 MB / 24.00 GB Binaries: Node: 24.15.0 - /Users/.../.nvm/versions/node/v24.15.0/bin/node npm: 11.12.1 - /Users/.../.nvm/versions/node/v24.15.0/bin/npm pnpm: 11.15.1 - /opt/homebrew/bin/pnpm IDEs: Cursor: 3.15.6 - /usr/local/bin/cursor Claude Code: 2.1.169 - /Users/.../.local/bin/claude Languages: Bash: 3.2.57 - /bin/bash npmPackages: @playwright/browser-chromium: 1.62.1 => 1.62.1 @playwright/browser-firefox: 1.62.1 => 1.62.1 playwright: 1.62.1 => 1.62.1