LibWeb: Invalidate viewport's text blocks cache on layout update

156c1083e9 introduced a text blocks cache
for better performance when searching through text on a page, but when
we partially recreate the layout tree, this cache does not get
invalidated. We now rebuild the entire text blocks cache after a layout
update.
This commit is contained in:
Jelle Raaijmakers 2025-05-14 15:36:52 +02:00 committed by Tim Ledbetter
commit c3a5e8e266
Notes: github-actions[bot] 2025-05-15 10:45:40 +00:00
4 changed files with 38 additions and 0 deletions

View file

@ -1304,6 +1304,10 @@ void Document::update_layout(UpdateLayoutReason reason)
if (m_created_for_appropriate_template_contents)
return;
// Clear text blocks cache so we rebuild them on the next find action.
if (m_layout_root)
m_layout_root->invalidate_text_blocks_cache();
invalidate_display_list();
auto* document_element = this->document_element();

View file

@ -28,6 +28,7 @@ public:
Vector<TextPosition> positions;
};
Vector<TextBlock> const& text_blocks();
void invalidate_text_blocks_cache() { m_text_blocks.clear(); }
const DOM::Document& dom_node() const { return static_cast<const DOM::Document&>(*Node::dom_node()); }

View file

@ -0,0 +1,3 @@
Selection: [object Text] 0 - [object Text] 6
Selection: [object Text] 0 - [object Text] 3
Expected exception: IndexSizeError: Selection.getRangeAt() on empty Selection or with invalid argument

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<script src="../include.js"></script>
<div>foobar</div>
<script>
test(() => {
function showSelection() {
let range = getSelection().getRangeAt(0);
println(`Selection: ${range.startContainer} ${range.startOffset} - ${range.endContainer} ${range.endOffset}`);
}
// Select 'foobar'.
window.find('foobar');
showSelection();
// Remove 'bar'.
document.querySelector('div').childNodes[0].deleteData(3, 3);
showSelection();
// Try to find 'bar'.
getSelection().empty();
window.find('bar');
// This should now fail.
try {
showSelection();
} catch (e) {
println(`Expected exception: ${e}`);
}
});
</script>