1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 02:17:34 +00:00

LibWeb: Update live DOM ranges on Text and CharacterData mutations

Taking care of the FIXMEs I added in earlier patches. :^)
This commit is contained in:
Andreas Kling 2022-03-21 20:05:25 +01:00
parent c74b1b6d65
commit 1254758b00
4 changed files with 60 additions and 11 deletions

View file

@ -1,11 +1,12 @@
/* /*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <LibWeb/DOM/CharacterData.h> #include <LibWeb/DOM/CharacterData.h>
#include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Range.h>
namespace Web::DOM { namespace Web::DOM {
@ -66,17 +67,33 @@ ExceptionOr<void> CharacterData::replace_data(size_t offset, size_t count, Strin
// 7. Starting from delete offset code units, remove count code units from nodes data. // 7. Starting from delete offset code units, remove count code units from nodes data.
StringBuilder builder; StringBuilder builder;
builder.append(this->data().substring_view(0, offset)); builder.append(this->data().substring_view(0, offset));
builder.append(data.characters(), count); builder.append(data);
builder.append(this->data().substring_view(offset + count)); builder.append(this->data().substring_view(offset + count));
set_data(builder.to_string()); 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 datas 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 datas 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 datas 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 datas 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 nodes parent is non-null, then run the children changed steps for nodes parent. // 12. If nodes parent is non-null, then run the children changed steps for nodes parent.
if (parent()) if (parent())

View file

@ -18,6 +18,12 @@
namespace Web::DOM { namespace Web::DOM {
HashTable<Range*>& Range::live_ranges()
{
static HashTable<Range*> ranges;
return ranges;
}
NonnullRefPtr<Range> Range::create(HTML::Window& window) NonnullRefPtr<Range> Range::create(HTML::Window& window)
{ {
return Range::create(window.associated_document()); 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) Range::Range(Node& start_container, u32 start_offset, Node& end_container, u32 end_offset)
: AbstractRange(start_container, start_offset, end_container, 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 // https://dom.spec.whatwg.org/#concept-range-root

View file

@ -15,7 +15,7 @@ class Range final : public AbstractRange {
public: public:
using WrapperType = Bindings::RangeWrapper; using WrapperType = Bindings::RangeWrapper;
virtual ~Range() override = default; virtual ~Range() override;
static NonnullRefPtr<Range> create(Document&); static NonnullRefPtr<Range> create(Document&);
static NonnullRefPtr<Range> create(HTML::Window&); static NonnullRefPtr<Range> create(HTML::Window&);
@ -67,6 +67,8 @@ public:
String to_string() const; String to_string() const;
static HashTable<Range*>& live_ranges();
private: private:
explicit Range(Document&); explicit Range(Document&);

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <LibWeb/DOM/Range.h>
#include <LibWeb/DOM/Text.h> #include <LibWeb/DOM/Text.h>
#include <LibWeb/HTML/HTMLInputElement.h> #include <LibWeb/HTML/HTMLInputElement.h>
#include <LibWeb/HTML/Window.h> #include <LibWeb/HTML/Window.h>
@ -58,13 +59,30 @@ ExceptionOr<NonnullRefPtr<Text>> Text::split_text(size_t offset)
// 1. Insert new node into parent before nodes next sibling. // 1. Insert new node into parent before nodes next sibling.
parent->insert_before(new_node, 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. // 8. Replace data with node node, offset offset, count count, and data the empty string.