Files
browser/src/browser/tests/document/write.html
Karl Seguin 3d6af216dc document.write, document.close, document.open
Add support for both modes - parsing and post-parsing. In post-parsing mode,
document.write implicitly calls document open, and document.open wipes the
document. This mode is probably rarely, if ever, used.

However, while parsing, document.write does not call document.open and does not
remove all existing nodes. It just writes the html into the document where the
parser is. That isn't something we can properly do..but we can hack it. We
create a new DocumentFragment, parse the html into the document fragment, then
transfer the children into the document where we currently are.

Our hack probably doesn't work for some advance usage of document.write (e.g
nested calls), but it should work for more common cases, e.g. injecting a script
tag.
2025-12-19 21:29:28 +08:00

162 lines
5.1 KiB
HTML

<!DOCTYPE html>
<head>
<title>document.write Tests</title>
<script src="../testing.js"></script>
</head>
<body>
<!-- Phase 1 Tests: Basic HTML (no scripts) -->
<script id=basic_write_and_verify>
document.write('<h1 id="written">Hello</h1>');
// Add a simple assertion so the test framework doesn't complain
testing.expectEqual(true, true);
</script>
<script id=verify_basic>
const written = document.getElementById('written');
testing.expectEqual('Hello', written.textContent);
testing.expectEqual('H1', written.tagName);
</script>
<script id=multiple_writes>
document.write('<div id="a">A</div>');
document.write('<div id="b">B</div>');
testing.expectEqual(true, true);
</script>
<script id=verify_multiple>
const a = document.getElementById('a');
const b = document.getElementById('b');
testing.expectEqual('A', a.textContent);
testing.expectEqual('B', b.textContent);
// Verify they're siblings in the correct order
testing.expectEqual(b, a.nextElementSibling);
</script>
<script id=write_with_attributes>
document.write('<div id="styled" class="foo bar" data-value="123">Content</div>');
testing.expectEqual(true, true);
</script>
<script id=verify_attributes>
const el = document.getElementById('styled');
testing.expectEqual('foo bar', el.className);
testing.expectEqual('123', el.getAttribute('data-value'));
testing.expectEqual('Content', el.textContent);
</script>
<script id=write_multiple_elements>
document.write('<p id="p1">First</p><p id="p2">Second</p>');
testing.expectEqual(true, true);
</script>
<script id=verify_multiple_elements>
const p1 = document.getElementById('p1');
const p2 = document.getElementById('p2');
testing.expectEqual('First', p1.textContent);
testing.expectEqual('Second', p2.textContent);
testing.expectEqual(p2, p1.nextElementSibling);
</script>
<script id=write_nested_elements>
document.write('<div id="outer"><span id="inner">Nested</span></div>');
testing.expectEqual(true, true);
</script>
<script id=verify_nested>
const outer = document.getElementById('outer');
const inner = document.getElementById('inner');
testing.expectEqual(outer, inner.parentElement);
testing.expectEqual('Nested', inner.textContent);
</script>
<!-- Phase 2 Tests: Script execution -->
<script id=write_script>
document.write('<script id="written_script">window.executed = true; testing.expectEqual(true, true);<\/script>');
testing.expectEqual(true, true);
</script>
<script id=verify_script_executed>
testing.expectEqual(true, window.executed);
testing.expectEqual(document.getElementById('written_script').tagName, 'SCRIPT');
</script>
<script id=written_script_can_write>
document.write('<script id="nested_writer">document.write("<div id=\\"nested\\">OK</div>"); testing.expectEqual(true, true);<\/script>');
testing.expectEqual(true, true);
</script>
<script id=verify_nested_write>
const nested = document.getElementById('nested');
testing.expectEqual('OK', nested.textContent);
</script>
<div id="before_script">Before</div>
<script id=written_script_sees_dom>
document.write('<script id="dom_accessor">document.getElementById("before_script").setAttribute("data-modified", "yes"); testing.expectEqual(true, true);<\/script>');
testing.expectEqual(true, true);
</script>
<script id=verify_dom_modification>
const beforeScript = document.getElementById('before_script');
testing.expectEqual('yes', beforeScript.getAttribute('data-modified'));
</script>
<!-- Phase 3 Tests: document.open/close would go here -->
<!-- Note: Testing document.open/close requires async/setTimeout which doesn't -->
<!-- work well with the test isolation. The implementation is tested manually. -->
<script id=final_assertion>
// Just verify the methods exist
testing.expectEqual('function', typeof document.open);
testing.expectEqual('function', typeof document.close);
testing.expectEqual('function', typeof document.write);
</script>
<!-- Phase 3 Tests: document.open/close (post-parsing with setTimeout) -->
<div id="will_be_removed">This will be removed by document.open()</div>
<script id=test_open_close_async>
// Mark that we saw the element before
const sawBefore = document.getElementById('will_be_removed') !== null;
testing.expectEqual(true, sawBefore);
// Use setTimeout to ensure we're after parsing completes
setTimeout(() => {
document.open();
}, 5);
testing.eventually(() => {
// The element should be gone now
const afterOpen = document.getElementById('will_be_removed');
testing.expectEqual(null, afterOpen);
// Write new content
document.write('<html><body>');
document.write('<h1 id="new_content">Replaced</h1>');
document.write('</body></html>');
// Close the document
document.close();
// Verify new content exists
const newContent = document.getElementById('new_content');
testing.expectEqual('Replaced', newContent.textContent);
})
</script>
<script>
// doing this after test_open_close_async used to crash, so we keep it
// to make sure it doesn't
setTimeout(() => {
document.open();
document.close();
}, 20);
</script>
</body>