mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-28 23:50:05 +00:00
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.
162 lines
5.1 KiB
HTML
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>
|