From 1254758b00b046cac8e50128cc897dc4ddec1332 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 21 Mar 2022 20:05:25 +0100 Subject: [PATCH] LibWeb: Update live DOM ranges on Text and CharacterData mutations Taking care of the FIXMEs I added in earlier patches. :^) --- .../Libraries/LibWeb/DOM/CharacterData.cpp | 29 +++++++++++++++---- Userland/Libraries/LibWeb/DOM/Range.cpp | 12 ++++++++ Userland/Libraries/LibWeb/DOM/Range.h | 4 ++- Userland/Libraries/LibWeb/DOM/Text.cpp | 26 ++++++++++++++--- 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/Userland/Libraries/LibWeb/DOM/CharacterData.cpp b/Userland/Libraries/LibWeb/DOM/CharacterData.cpp index a01b36e029..dec8901baf 100644 --- a/Userland/Libraries/LibWeb/DOM/CharacterData.cpp +++ b/Userland/Libraries/LibWeb/DOM/CharacterData.cpp @@ -1,11 +1,12 @@ /* - * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2018-2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #include #include +#include namespace Web::DOM { @@ -66,17 +67,33 @@ ExceptionOr CharacterData::replace_data(size_t offset, size_t count, Strin // 7. Starting from delete offset code units, remove count code units from node’s data. StringBuilder builder; builder.append(this->data().substring_view(0, offset)); - builder.append(data.characters(), count); + builder.append(data); builder.append(this->data().substring_view(offset + count)); set_data(builder.to_string()); - // FIXME: 8. For each live range whose start node is node and start offset is greater than offset but less than or equal to offset plus count, set its start offset to offset. + // 8. For each live range whose start node is node and start offset is greater than offset but less than or equal to offset plus count, set its start offset to offset. + for (auto& range : Range::live_ranges()) { + if (range->start_container() == this && range->start_offset() > offset && range->start_offset() <= (offset + count)) + range->set_start(*range->start_container(), offset); + } - // FIXME: 9. For each live range whose end node is node and end offset is greater than offset but less than or equal to offset plus count, set its end offset to offset. + // 9. For each live range whose end node is node and end offset is greater than offset but less than or equal to offset plus count, set its end offset to offset. + for (auto& range : Range::live_ranges()) { + if (range->end_container() == this && range->end_offset() > offset && range->end_offset() <= (offset + count)) + range->set_end(*range->end_container(), range->end_offset()); + } - // FIXME: 10. For each live range whose start node is node and start offset is greater than offset plus count, increase its start offset by data’s length and decrease it by count. + // 10. For each live range whose start node is node and start offset is greater than offset plus count, increase its start offset by data’s length and decrease it by count. + for (auto& range : Range::live_ranges()) { + if (range->start_container() == this && range->start_offset() > (offset + count)) + range->set_start(*range->start_container(), range->start_offset() + data.length() - count); + } - // FIXME: 11. For each live range whose end node is node and end offset is greater than offset plus count, increase its end offset by data’s length and decrease it by count. + // 11. For each live range whose end node is node and end offset is greater than offset plus count, increase its end offset by data’s length and decrease it by count. + for (auto& range : Range::live_ranges()) { + if (range->end_container() == this && range->end_offset() > (offset + count)) + range->set_end(*range->end_container(), range->end_offset() + data.length() - count); + } // 12. If node’s parent is non-null, then run the children changed steps for node’s parent. if (parent()) diff --git a/Userland/Libraries/LibWeb/DOM/Range.cpp b/Userland/Libraries/LibWeb/DOM/Range.cpp index 1da56a9995..6ed57abe02 100644 --- a/Userland/Libraries/LibWeb/DOM/Range.cpp +++ b/Userland/Libraries/LibWeb/DOM/Range.cpp @@ -18,6 +18,12 @@ namespace Web::DOM { +HashTable& Range::live_ranges() +{ + static HashTable ranges; + return ranges; +} + NonnullRefPtr Range::create(HTML::Window& window) { return Range::create(window.associated_document()); @@ -46,6 +52,12 @@ Range::Range(Document& document) Range::Range(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset) : AbstractRange(start_container, start_offset, end_container, end_offset) { + live_ranges().set(this); +} + +Range::~Range() +{ + live_ranges().remove(this); } // https://dom.spec.whatwg.org/#concept-range-root diff --git a/Userland/Libraries/LibWeb/DOM/Range.h b/Userland/Libraries/LibWeb/DOM/Range.h index 50d9ef5d1b..427254d3d8 100644 --- a/Userland/Libraries/LibWeb/DOM/Range.h +++ b/Userland/Libraries/LibWeb/DOM/Range.h @@ -15,7 +15,7 @@ class Range final : public AbstractRange { public: using WrapperType = Bindings::RangeWrapper; - virtual ~Range() override = default; + virtual ~Range() override; static NonnullRefPtr create(Document&); static NonnullRefPtr create(HTML::Window&); @@ -67,6 +67,8 @@ public: String to_string() const; + static HashTable& live_ranges(); + private: explicit Range(Document&); diff --git a/Userland/Libraries/LibWeb/DOM/Text.cpp b/Userland/Libraries/LibWeb/DOM/Text.cpp index ca96370727..6e45de9fbd 100644 --- a/Userland/Libraries/LibWeb/DOM/Text.cpp +++ b/Userland/Libraries/LibWeb/DOM/Text.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -58,13 +59,30 @@ ExceptionOr> Text::split_text(size_t offset) // 1. Insert new node into parent before node’s next sibling. parent->insert_before(new_node, next_sibling()); - // FIXME: 2. For each live range whose start node is node and start offset is greater than offset, set its start node to new node and decrease its start offset by offset. + // 2. For each live range whose start node is node and start offset is greater than offset, set its start node to new node and decrease its start offset by offset. + for (auto& range : Range::live_ranges()) { + if (range->start_container() == this && range->start_offset() > offset) + range->set_start(new_node, range->start_offset() - offset); + } - // FIXME: 3. For each live range whose end node is node and end offset is greater than offset, set its end node to new node and decrease its end offset by offset. + // 3. For each live range whose end node is node and end offset is greater than offset, set its end node to new node and decrease its end offset by offset. + for (auto& range : Range::live_ranges()) { + if (range->end_container() == this && range->end_offset() > offset) + range->set_end(new_node, range->end_offset() - offset); + } - // FIXME: 4. For each live range whose start node is parent and start offset is equal to the index of node plus 1, increase its start offset by 1. + // 4. For each live range whose start node is parent and start offset is equal to the index of node plus 1, increase its start offset by 1. + for (auto& range : Range::live_ranges()) { + if (range->start_container() == this && range->start_offset() == index() + 1) + range->set_start(*range->start_container(), range->start_offset() + 1); + } - // FIXME: 5. For each live range whose end node is parent and end offset is equal to the index of node plus 1, increase its end offset by 1. + // 5. For each live range whose end node is parent and end offset is equal to the index of node plus 1, increase its end offset by 1. + for (auto& range : Range::live_ranges()) { + if (range->end_container() == parent && range->end_offset() == index() + 1) { + range->set_end(*range->end_container(), range->end_offset() + 1); + } + } } // 8. Replace data with node node, offset offset, count count, and data the empty string.