summaryrefslogtreecommitdiff
path: root/Libraries/LibWeb/TreeNode.h
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-10-22 23:38:14 +0200
committerAndreas Kling <kling@serenityos.org>2020-10-22 23:41:32 +0200
commitf79e28bd6532ad46ed8b173b118eaf9cb3da2ba8 (patch)
tree3af39b4fada806fdff4306a3c0ea74f62dcb4cbf /Libraries/LibWeb/TreeNode.h
parent018b4589620f2c6eea8b0c4c79496a5cb3191dc9 (diff)
downloadserenity-f79e28bd6532ad46ed8b173b118eaf9cb3da2ba8.zip
LibWeb: Break reference cycles so DOM::Document actually gets deleted
When a document reaches ref_count==0, we will now remove all of the descendant nodes from the document, and also break all the explicit links (such as the currently hovered element.) Basically, DOM nodes will keep the document alive even after the document reaches ref_count==0. This allows JS wrappers to stay alive and keep the document alive as well. This matches the behavior of at least some other browsers. This patch also adds a bunch of sanity checking assertions around DOM teardown, to help catch mistakes in the future. Fixes #3771.
Diffstat (limited to 'Libraries/LibWeb/TreeNode.h')
-rw-r--r--Libraries/LibWeb/TreeNode.h11
1 files changed, 9 insertions, 2 deletions
diff --git a/Libraries/LibWeb/TreeNode.h b/Libraries/LibWeb/TreeNode.h
index 5221e260f9..c4c5999811 100644
--- a/Libraries/LibWeb/TreeNode.h
+++ b/Libraries/LibWeb/TreeNode.h
@@ -39,18 +39,22 @@ class TreeNode : public Weakable<T> {
public:
void ref()
{
+ ASSERT(!m_in_removed_last_ref);
ASSERT(m_ref_count);
++m_ref_count;
}
void unref()
{
+ ASSERT(!m_in_removed_last_ref);
ASSERT(m_ref_count);
if (!--m_ref_count) {
- if constexpr (IsBaseOf<DOM::Node, T>::value)
+ if constexpr (IsBaseOf<DOM::Node, T>::value) {
+ m_in_removed_last_ref = true;
static_cast<T*>(this)->removed_last_ref();
- else
+ } else {
delete static_cast<T*>(this);
+ }
return;
}
}
@@ -280,6 +284,9 @@ public:
protected:
TreeNode() { }
+ bool m_deletion_has_begun { false };
+ bool m_in_removed_last_ref { false };
+
private:
int m_ref_count { 1 };
T* m_parent { nullptr };