<!DOCTYPE html>
<title>Tests that typing should not retain detached subtree</title>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../../resources/gc.js"></script>
<div id="root"></div>
<script>
const n = 100;
function createSubtree() {
let last = document.createElement('div');
last.spellcheck = false;
last.contentEditable = true;
last.id = 'target';
for (let i = 0; i < n; ++i) {
let div = document.createElement('div');
div.appendChild(last);
last = div;
}
root.appendChild(last);
}
function raf() {
return new Promise(resolve => requestAnimationFrame(resolve));
}
promise_setup(async () => {
assert_own_property(window, 'internals', 'This test requires internals')
})
promise_test(async () => {
await asyncGC();
let nodesBefore = internals.numberOfLiveNodes();
createSubtree();
document.getElementById('target').focus();
document.execCommand('insertText', false, 'foo');
assert_true(internals.hasLastEditCommand(document));
root.firstChild.remove();
await raf();
await raf();
await asyncGC();
let nodesAfter = internals.numberOfLiveNodes();
assert_equals(nodesAfter, nodesBefore);
assert_false(internals.hasLastEditCommand(document));
}, 'Typing should not retain detached subtree');
promise_test(async () => {
createSubtree();
document.getElementById('target').focus();
document.execCommand('insertText', false, 'foo');
document.getElementById('target').blur();
assert_true(internals.hasLastEditCommand(document));
await raf();
await raf();
await asyncGC();
assert_true(internals.hasLastEditCommand(document));
}, 'Last edit command should be retained if node is still connected');
</script>
</body>