Diff
Modified: trunk/Source/WebCore/ChangeLog (164194 => 164195)
--- trunk/Source/WebCore/ChangeLog 2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/ChangeLog 2014-02-16 22:18:13 UTC (rev 164195)
@@ -1,3 +1,73 @@
+2014-02-15 Antti Koivisto <an...@apple.com>
+
+ Move document life time management from TreeScope to Document
+ https://bugs.webkit.org/show_bug.cgi?id=128877
+
+ Reviewed by Andreas Kling.
+
+ Document life time is managed in confusing manner by TreeScopes which are also inherited to ShadowRoots.
+
+ This patches moves the life time management to Document. Nodes in shadow trees selfOnlyRef the Document instead
+ of the ShadowRoot. ShadowRoot is treated like any other node and selfOnlyRefs the Document as well (which it
+ also did earlier, indirectly).
+
+ TreeScope is devirtualized.
+
+ * css/ElementRuleCollector.cpp:
+ (WebCore::ElementRuleCollector::collectMatchingRules):
+
+ Author stylesheets never match in UA shadow trees.
+
+ * dom/ContainerNode.cpp:
+ (WebCore::ContainerNode::~ContainerNode):
+ * dom/Document.cpp:
+ (WebCore::Document::Document):
+ (WebCore::Document::~Document):
+ (WebCore::Document::removedLastRef):
+ * dom/Document.h:
+ (WebCore::Document::selfOnlyRef):
+ (WebCore::Document::selfOnlyDeref):
+
+ To avoid branches Document self-refs itself like all other Nodes. This is why deletion will now happen on ref count of 1.
+
+ (WebCore::Node::isDocumentNode):
+ (WebCore::Node::Node):
+ * dom/DocumentOrderedMap.cpp:
+ (WebCore::DocumentOrderedMap::add):
+ * dom/Element.cpp:
+ (WebCore::Element::insertedInto):
+ (WebCore::Element::removedFrom):
+ * dom/Node.cpp:
+ (WebCore::Node::~Node):
+ (WebCore::Node::removedLastRef):
+ * dom/Node.h:
+ (WebCore::Node::document):
+ (WebCore::Node::inDocument):
+ * dom/ShadowRoot.cpp:
+ (WebCore::ShadowRoot::ShadowRoot):
+ (WebCore::ShadowRoot::~ShadowRoot):
+ * dom/ShadowRoot.h:
+ * dom/TreeScope.cpp:
+ (WebCore::TreeScope::TreeScope):
+ (WebCore::TreeScope::~TreeScope):
+ (WebCore::TreeScope::setParentTreeScope):
+ * dom/TreeScope.h:
+ (WebCore::TreeScope::documentScope):
+
+ Document can no longer ever be null.
+
+ (WebCore::TreeScope::rootNode):
+ (WebCore::TreeScope::setDocumentScope):
+ * dom/TreeScopeAdopter.cpp:
+ (WebCore::TreeScopeAdopter::moveTreeToNewScope):
+ (WebCore::TreeScopeAdopter::moveShadowTreeToNewDocument):
+
+ Manage Document selfOnlyRefs for nodes in shadow trees too.
+
+ (WebCore::TreeScopeAdopter::updateTreeScope):
+ (WebCore::TreeScopeAdopter::moveNodeToNewDocument):
+ * dom/TreeScopeAdopter.h:
+
2014-02-16 Ryosuke Niwa <rn...@webkit.org>
setSelectionRange shouldn't directly instantiate VisibleSelection
Modified: trunk/Source/WebCore/css/ElementRuleCollector.cpp (164194 => 164195)
--- trunk/Source/WebCore/css/ElementRuleCollector.cpp 2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/css/ElementRuleCollector.cpp 2014-02-16 22:18:13 UTC (rev 164195)
@@ -154,11 +154,8 @@
if (m_element.isWebVTTElement())
collectMatchingRulesForList(matchRequest.ruleSet->cuePseudoRules(), matchRequest, ruleRange);
#endif
- // Check whether other types of rules are applicable in the current tree scope. Criteria for this:
- // a) it's a UA rule
- // b) the tree scope allows author rules
- if (!MatchingUARulesScope::isMatchingUARules()
- && !m_element.treeScope().applyAuthorStyles())
+ // Only match UA rules in shadow tree.
+ if (!MatchingUARulesScope::isMatchingUARules() && m_element.treeScope().rootNode()->isShadowRoot())
return;
// We need to collect the rules for id, class, tag, and everything else into a buffer and
Modified: trunk/Source/WebCore/dom/ContainerNode.cpp (164194 => 164195)
--- trunk/Source/WebCore/dom/ContainerNode.cpp 2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/ContainerNode.cpp 2014-02-16 22:18:13 UTC (rev 164195)
@@ -150,8 +150,7 @@
ContainerNode::~ContainerNode()
{
- if (Document* document = documentInternal())
- willBeDeletedFrom(document);
+ willBeDeletedFrom(&document());
removeDetachedChildren();
}
Modified: trunk/Source/WebCore/dom/Document.cpp (164194 => 164195)
--- trunk/Source/WebCore/dom/Document.cpp 2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/Document.cpp 2014-02-16 22:18:13 UTC (rev 164195)
@@ -393,8 +393,9 @@
#endif
Document::Document(Frame* frame, const URL& url, unsigned documentClasses, unsigned constructionFlags)
- : ContainerNode(nullptr, CreateDocument)
- , TreeScope(this)
+ : ContainerNode(this, CreateDocument)
+ , TreeScope(*this)
+ , m_selfOnlyRefCount(1)
#if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS)
, m_handlingTouchEvent(false)
, m_touchEventRegionsDirty(false)
@@ -633,43 +634,59 @@
for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_nodeListAndCollectionCounts); ++i)
ASSERT(!m_nodeListAndCollectionCounts[i]);
- clearDocumentScope();
-
InspectorCounters::decrementCounter(InspectorCounters::DocumentCounter);
}
-void Document::dropChildren()
+void Document::removedLastRef()
{
ASSERT(!m_deletionHasBegun);
+ ASSERT(m_selfOnlyRefCount);
+ if (m_selfOnlyRefCount > 1) {
+ // If removing a child removes the last self-only ref, we don't want the scope to be destroyed
+ // until after removeDetachedChildren returns, so we protect ourselves with an extra self-only ref.
+ selfOnlyRef();
- // We must make sure not to be retaining any of our children through
- // these extra pointers or we will create a reference cycle.
- m_focusedElement = nullptr;
- m_hoveredElement = nullptr;
- m_activeElement = nullptr;
- m_titleElement = nullptr;
- m_documentElement = nullptr;
- m_userActionElements.documentDidRemoveLastRef();
+ // We must make sure not to be retaining any of our children through
+ // these extra pointers or we will create a reference cycle.
+ m_focusedElement = nullptr;
+ m_hoveredElement = nullptr;
+ m_activeElement = nullptr;
+ m_titleElement = nullptr;
+ m_documentElement = nullptr;
+ m_userActionElements.documentDidRemoveLastRef();
#if ENABLE(FULLSCREEN_API)
- m_fullScreenElement = nullptr;
- m_fullScreenElementStack.clear();
+ m_fullScreenElement = nullptr;
+ m_fullScreenElementStack.clear();
#endif
- detachParser();
+ detachParser();
- // removeDetachedChildren() doesn't always unregister IDs,
- // so tear down scope information up front to avoid having
- // stale references in the map.
+ // removeDetachedChildren() doesn't always unregister IDs,
+ // so tear down scope information up front to avoid having
+ // stale references in the map.
- destroyTreeScopeData();
- removeDetachedChildren();
- m_formController.clear();
+ destroyTreeScopeData();
+ removeDetachedChildren();
+ m_formController.clear();
+
+ m_markers->detach();
+
+ m_cssCanvasElements.clear();
+
+ commonTeardown();
- m_markers->detach();
-
- m_cssCanvasElements.clear();
-
- commonTeardown();
+#ifndef NDEBUG
+ // We need to do this right now since selfOnlyDeref() can delete this.
+ m_inRemovedLastRefFunction = false;
+#endif
+ selfOnlyDeref();
+ } else {
+#ifndef NDEBUG
+ m_inRemovedLastRefFunction = false;
+ m_deletionHasBegun = true;
+#endif
+ delete this;
+ }
}
void Document::commonTeardown()
Modified: trunk/Source/WebCore/dom/Document.h (164194 => 164195)
--- trunk/Source/WebCore/dom/Document.h 2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/Document.h 2014-02-16 22:18:13 UTC (rev 164195)
@@ -263,6 +263,31 @@
virtual ~Document();
+ // Nodes belonging to this document hold self-only references -
+ // these are enough to keep the document from being destroyed, but
+ // not enough to keep it from removing its children. This allows a
+ // node that outlives its scope to still have a valid document
+ // pointer without introducing reference cycles.
+ void selfOnlyRef()
+ {
+ ASSERT(!m_deletionHasBegun);
+ ++m_selfOnlyRefCount;
+ }
+
+ void selfOnlyDeref()
+ {
+ ASSERT(!m_deletionHasBegun || m_selfOnlyRefCount == 1);
+ --m_selfOnlyRefCount;
+ if (m_selfOnlyRefCount == 1 && !refCount()) {
+#if !ASSERT_DISABLED
+ m_deletionHasBegun = true;
+#endif
+ delete this;
+ }
+ }
+
+ void removedLastRef();
+
MediaQueryMatcher& mediaQueryMatcher();
using ContainerNode::ref;
@@ -1254,8 +1279,6 @@
void createRenderTree();
void detachParser();
- virtual void dropChildren() override;
-
typedef void (*ArgumentsCallback)(const String& keyString, const String& valueString, Document*, void* data);
void processArguments(const String& features, void* data, ArgumentsCallback);
@@ -1320,6 +1343,9 @@
void didAssociateFormControlsTimerFired(Timer<Document>&);
void styleResolverThrowawayTimerFired(DeferrableOneShotTimer<Document>&);
+
+ unsigned m_selfOnlyRefCount;
+
DeferrableOneShotTimer<Document> m_styleResolverThrowawayTimer;
OwnPtr<StyleResolver> m_styleResolver;
@@ -1679,17 +1705,17 @@
inline bool Node::isDocumentNode() const
{
- return this == documentInternal();
+ return this == &document();
}
inline Node::Node(Document* document, ConstructionType type)
: m_nodeFlags(type)
, m_parentNode(0)
- , m_treeScope(document ? document : &TreeScope::noDocumentInstance())
+ , m_treeScope(document)
, m_previous(0)
, m_next(0)
{
- m_treeScope->selfOnlyRef();
+ document->selfOnlyRef();
#if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS)
trackForDebugging();
Modified: trunk/Source/WebCore/dom/DocumentOrderedMap.cpp (164194 => 164195)
--- trunk/Source/WebCore/dom/DocumentOrderedMap.cpp 2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/DocumentOrderedMap.cpp 2014-02-16 22:18:13 UTC (rev 164195)
@@ -89,9 +89,10 @@
void DocumentOrderedMap::add(const AtomicStringImpl& key, Element& element, const TreeScope& treeScope)
{
+ UNUSED_PARAM(treeScope);
ASSERT_WITH_SECURITY_IMPLICATION(element.isInTreeScope());
ASSERT_WITH_SECURITY_IMPLICATION(treeScope.rootNode()->containsIncludingShadowDOM(&element));
- if (!element.isInTreeScope() || &element.document() != treeScope.documentScope())
+ if (!element.isInTreeScope())
return;
Map::AddResult addResult = m_map.add(&key, MapEntry(&element));
if (addResult.isNewEntry)
Modified: trunk/Source/WebCore/dom/Element.cpp (164194 => 164195)
--- trunk/Source/WebCore/dom/Element.cpp 2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/Element.cpp 2014-02-16 22:18:13 UTC (rev 164195)
@@ -1353,9 +1353,9 @@
elementRareData()->clearClassListValueForQuirksMode();
TreeScope* newScope = &insertionPoint.treeScope();
- HTMLDocument* newDocument = !wasInDocument && inDocument() && newScope->documentScope()->isHTMLDocument() ? toHTMLDocument(newScope->documentScope()) : 0;
+ HTMLDocument* newDocument = !wasInDocument && inDocument() && newScope->documentScope().isHTMLDocument() ? toHTMLDocument(&newScope->documentScope()) : nullptr;
if (newScope != &treeScope())
- newScope = 0;
+ newScope = nullptr;
const AtomicString& idValue = getIdAttribute();
if (!idValue.isNull()) {
@@ -1396,9 +1396,9 @@
if (insertionPoint.isInTreeScope()) {
TreeScope* oldScope = &insertionPoint.treeScope();
- HTMLDocument* oldDocument = inDocument() && oldScope->documentScope()->isHTMLDocument() ? toHTMLDocument(oldScope->documentScope()) : 0;
+ HTMLDocument* oldDocument = inDocument() && oldScope->documentScope().isHTMLDocument() ? toHTMLDocument(&oldScope->documentScope()) : nullptr;
if (oldScope != &treeScope())
- oldScope = 0;
+ oldScope = nullptr;
const AtomicString& idValue = getIdAttribute();
if (!idValue.isNull()) {
Modified: trunk/Source/WebCore/dom/Node.cpp (164194 => 164195)
--- trunk/Source/WebCore/dom/Node.cpp 2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/Node.cpp 2014-02-16 22:18:13 UTC (rev 164195)
@@ -305,12 +305,10 @@
if (hasRareData())
clearRareData();
- if (!isContainerNode()) {
- if (Document* document = documentInternal())
- willBeDeletedFrom(document);
- }
+ if (!isContainerNode())
+ willBeDeletedFrom(&document());
- m_treeScope->selfOnlyDeref();
+ document().selfOnlyDeref();
InspectorCounters::decrementCounter(InspectorCounters::NodeCounter);
}
@@ -2190,31 +2188,6 @@
return hasEventListeners(eventNames().mousewheelEvent);
}
-// This is here so it can be inlined into Node::removedLastRef.
-// FIXME: Really? Seems like this could be inlined into Node::removedLastRef if it was in TreeScope.h.
-// FIXME: It also not seem important to inline this. Is this really hot?
-inline void TreeScope::removedLastRefToScope()
-{
- ASSERT(!deletionHasBegun());
- if (m_selfOnlyRefCount) {
- // If removing a child removes the last self-only ref, we don't want the scope to be destroyed
- // until after removeDetachedChildren returns, so we protect ourselves with an extra self-only ref.
- selfOnlyRef();
- dropChildren();
-#ifndef NDEBUG
- // We need to do this right now since selfOnlyDeref() can delete this.
- rootNode()->m_inRemovedLastRefFunction = false;
-#endif
- selfOnlyDeref();
- } else {
-#ifndef NDEBUG
- rootNode()->m_inRemovedLastRefFunction = false;
- beginDeletion();
-#endif
- delete this;
- }
-}
-
// It's important not to inline removedLastRef, because we don't want to inline the code to
// delete a Node at each deref call site.
void Node::removedLastRef()
@@ -2222,8 +2195,8 @@
// An explicit check for Document here is better than a virtual function since it is
// faster for non-Document nodes, and because the call to removedLastRef that is inlined
// at all deref call sites is smaller if it's a non-virtual function.
- if (isTreeScope()) {
- treeScope().removedLastRefToScope();
+ if (isDocumentNode()) {
+ toDocument(*this).removedLastRef();
return;
}
Modified: trunk/Source/WebCore/dom/Node.h (164194 => 164195)
--- trunk/Source/WebCore/dom/Node.h 2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/Node.h 2014-02-16 22:18:13 UTC (rev 164195)
@@ -382,8 +382,7 @@
Document& document() const
{
ASSERT(this);
- ASSERT(documentInternal());
- return *documentInternal();
+ return treeScope().documentScope();
}
TreeScope& treeScope() const
@@ -396,7 +395,6 @@
// node tree, false otherwise.
bool inDocument() const
{
- ASSERT(documentInternal() || !getFlag(InDocumentFlag));
return getFlag(InDocumentFlag);
}
bool isInShadowTree() const { return getFlag(IsInShadowTreeFlag); }
@@ -644,7 +642,6 @@
void setNeedsNodeRenderingTraversalSlowPath(bool flag) { setFlag(flag, NeedsNodeRenderingTraversalSlowPathFlag); }
- Document* documentInternal() const { return treeScope().documentScope(); }
void setTreeScope(TreeScope& scope) { m_treeScope = &scope; }
void setStyleChange(StyleChangeType changeType) { m_nodeFlags = (m_nodeFlags & ~StyleChangeMask) | changeType; }
Modified: trunk/Source/WebCore/dom/ShadowRoot.cpp (164194 => 164195)
--- trunk/Source/WebCore/dom/ShadowRoot.cpp 2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/ShadowRoot.cpp 2014-02-16 22:18:13 UTC (rev 164195)
@@ -52,9 +52,8 @@
};
ShadowRoot::ShadowRoot(Document& document, ShadowRootType type)
- : DocumentFragment(0, CreateShadowRoot)
- , TreeScope(this, &document)
- , m_applyAuthorStyles(false)
+ : DocumentFragment(&document, CreateShadowRoot)
+ , TreeScope(*this, document)
, m_resetStyleInheritance(false)
, m_type(type)
, m_hostElement(0)
@@ -67,24 +66,14 @@
// for this ShadowRoot instance because TreeScope destructor
// clears Node::m_treeScope thus ContainerNode is no longer able
// to access it Document reference after that.
- willBeDeletedFrom(documentInternal());
+ willBeDeletedFrom(&document());
// We must remove all of our children first before the TreeScope destructor
// runs so we don't go through TreeScopeAdopter for each child with a
// destructed tree scope in each descendant.
removeDetachedChildren();
-
- // We must call clearRareData() here since a ShadowRoot class inherits TreeScope
- // as well as Node. See a comment on TreeScope.h for the reason.
- if (hasRareData())
- clearRareData();
}
-void ShadowRoot::dropChildren()
-{
- removeDetachedChildren();
-}
-
PassRefPtr<Node> ShadowRoot::cloneNode(bool, ExceptionCode& ec)
{
ec = DATA_CLONE_ERR;
@@ -122,17 +111,6 @@
}
}
-void ShadowRoot::setApplyAuthorStyles(bool value)
-{
- if (isOrphan())
- return;
-
- if (m_applyAuthorStyles != value) {
- m_applyAuthorStyles = value;
- hostElement()->setNeedsStyleRecalc();
- }
-}
-
void ShadowRoot::setResetStyleInheritance(bool value)
{
if (isOrphan())
Modified: trunk/Source/WebCore/dom/ShadowRoot.h (164194 => 164195)
--- trunk/Source/WebCore/dom/ShadowRoot.h 2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/ShadowRoot.h 2014-02-16 22:18:13 UTC (rev 164195)
@@ -50,8 +50,6 @@
virtual ~ShadowRoot();
- virtual bool applyAuthorStyles() const override { return m_applyAuthorStyles; }
- void setApplyAuthorStyles(bool);
bool resetStyleInheritance() const { return m_resetStyleInheritance; }
void setResetStyleInheritance(bool);
@@ -75,7 +73,6 @@
private:
ShadowRoot(Document&, ShadowRootType);
- virtual void dropChildren() override;
virtual bool childTypeAllowed(NodeType) const override;
virtual void childrenChanged(const ChildChange&) override;
@@ -85,7 +82,6 @@
// FIXME: This shouldn't happen. https://bugs.webkit.org/show_bug.cgi?id=88834
bool isOrphan() const { return !hostElement(); }
- unsigned m_applyAuthorStyles : 1;
unsigned m_resetStyleInheritance : 1;
unsigned m_type : 1;
Modified: trunk/Source/WebCore/dom/TreeScope.cpp (164194 => 164195)
--- trunk/Source/WebCore/dom/TreeScope.cpp 2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/TreeScope.cpp 2014-02-16 22:18:13 UTC (rev 164195)
@@ -49,60 +49,37 @@
namespace WebCore {
struct SameSizeAsTreeScope {
- virtual ~SameSizeAsTreeScope();
void* pointers[9];
- int ints[1];
};
COMPILE_ASSERT(sizeof(TreeScope) == sizeof(SameSizeAsTreeScope), treescope_should_stay_small);
using namespace HTMLNames;
-TreeScope::TreeScope(ContainerNode* rootNode, Document* document)
- : m_rootNode(rootNode)
- , m_documentScope(document)
- , m_parentTreeScope(document)
- , m_selfOnlyRefCount(0)
+TreeScope::TreeScope(ShadowRoot& shadowRoot, Document& document)
+ : m_rootNode(shadowRoot)
+ , m_documentScope(&document)
+ , m_parentTreeScope(&document)
, m_idTargetObserverRegistry(std::make_unique<IdTargetObserverRegistry>())
{
- ASSERT(rootNode);
- ASSERT(document);
- ASSERT(rootNode != document);
- m_parentTreeScope->selfOnlyRef();
- m_rootNode->setTreeScope(*this);
+ shadowRoot.setTreeScope(*this);
}
-TreeScope::TreeScope(Document* document)
+TreeScope::TreeScope(Document& document)
: m_rootNode(document)
- , m_documentScope(document)
+ , m_documentScope(&document)
, m_parentTreeScope(nullptr)
- , m_selfOnlyRefCount(0)
, m_idTargetObserverRegistry(std::make_unique<IdTargetObserverRegistry>())
{
- ASSERT(document);
- m_rootNode->setTreeScope(*this);
+ document.setTreeScope(*this);
}
-TreeScope::TreeScope()
- : m_rootNode(nullptr)
- , m_documentScope(nullptr)
- , m_parentTreeScope(nullptr)
- , m_selfOnlyRefCount(0)
-{
-}
-
TreeScope::~TreeScope()
{
- ASSERT(!m_selfOnlyRefCount);
- m_rootNode->setTreeScope(noDocumentInstance());
-
if (m_selection) {
m_selection->clearTreeScope();
m_selection = nullptr;
}
-
- if (m_parentTreeScope)
- m_parentTreeScope->selfOnlyDeref();
}
void TreeScope::destroyTreeScopeData()
@@ -112,12 +89,6 @@
m_labelsByForAttribute = nullptr;
}
-void TreeScope::clearDocumentScope()
-{
- ASSERT(rootNode()->isDocumentNode());
- m_documentScope = nullptr;
-}
-
void TreeScope::setParentTreeScope(TreeScope* newParentScope)
{
// A document node cannot be re-parented.
@@ -125,11 +96,8 @@
// Every scope other than document needs a parent scope.
ASSERT(newParentScope);
- newParentScope->selfOnlyRef();
- if (m_parentTreeScope)
- m_parentTreeScope->selfOnlyDeref();
m_parentTreeScope = newParentScope;
- setDocumentScope(newParentScope->documentScope());
+ setDocumentScope(&newParentScope->documentScope());
}
Element* TreeScope::getElementById(const AtomicString& elementId) const
@@ -345,11 +313,6 @@
return nullptr;
}
-bool TreeScope::applyAuthorStyles() const
-{
- return true;
-}
-
void TreeScope::adoptIfNeeded(Node* node)
{
ASSERT(this);
@@ -426,24 +389,4 @@
return treeScopesA[indexA] == treeScopesB[indexB] ? treeScopesA[indexA] : nullptr;
}
-#ifndef NDEBUG
-bool TreeScope::deletionHasBegun()
-{
- return rootNode() && rootNode()->m_deletionHasBegun;
-}
-
-void TreeScope::beginDeletion()
-{
- ASSERT(this != &noDocumentInstance());
- rootNode()->m_deletionHasBegun = true;
-}
-#endif
-
-int TreeScope::refCount() const
-{
- if (Node* root = rootNode())
- return root->refCount();
- return 0;
-}
-
} // namespace WebCore
Modified: trunk/Source/WebCore/dom/TreeScope.h (164194 => 164195)
--- trunk/Source/WebCore/dom/TreeScope.h 2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/TreeScope.h 2014-02-16 22:18:13 UTC (rev 164195)
@@ -43,10 +43,8 @@
class LayoutPoint;
class IdTargetObserverRegistry;
class Node;
+class ShadowRoot;
-// A class which inherits both Node and TreeScope must call clearRareData() in its destructor
-// so that the Node destructor no longer does problematic NodeList cache manipulation in
-// the destructor.
class TreeScope {
friend class Document;
friend class TreeScopeAdopter;
@@ -69,7 +67,7 @@
void addElementByName(const AtomicStringImpl&, Element&);
void removeElementByName(const AtomicStringImpl&, Element&);
- Document* documentScope() const { return m_documentScope; }
+ Document& documentScope() const { return *m_documentScope; }
Node* ancestorInThisScope(Node*) const;
@@ -94,76 +92,29 @@
// quirks mode for historical compatibility reasons.
Element* findAnchor(const String& name);
- virtual bool applyAuthorStyles() const;
-
// Used by the basic DOM mutation methods (e.g., appendChild()).
void adoptIfNeeded(Node*);
- ContainerNode* rootNode() const { return m_rootNode; }
+ ContainerNode* rootNode() const { return &m_rootNode; }
IdTargetObserverRegistry& idTargetObserverRegistry() const { return *m_idTargetObserverRegistry.get(); }
- static TreeScope& noDocumentInstance()
- {
- DEFINE_STATIC_LOCAL(TreeScope, instance, ());
- return instance;
- }
-
- // Nodes belonging to this scope hold self-only references -
- // these are enough to keep the scope from being destroyed, but
- // not enough to keep it from removing its children. This allows a
- // node that outlives its scope to still have a valid document
- // pointer without introducing reference cycles.
- void selfOnlyRef()
- {
- ASSERT(!deletionHasBegun());
- ++m_selfOnlyRefCount;
- }
-
- void selfOnlyDeref()
- {
- ASSERT(!deletionHasBegun());
- --m_selfOnlyRefCount;
- if (!m_selfOnlyRefCount && !refCount() && this != &noDocumentInstance()) {
- beginDeletion();
- delete this;
- }
- }
-
- void removedLastRefToScope();
-
protected:
- TreeScope(ContainerNode*, Document*);
- explicit TreeScope(Document*);
- virtual ~TreeScope();
+ TreeScope(ShadowRoot&, Document&);
+ explicit TreeScope(Document&);
+ ~TreeScope();
void destroyTreeScopeData();
- void clearDocumentScope();
void setDocumentScope(Document* document)
{
ASSERT(document);
- ASSERT(this != &noDocumentInstance());
m_documentScope = document;
}
private:
- TreeScope();
-
- virtual void dropChildren() { }
-
- int refCount() const;
-#ifndef NDEBUG
- bool deletionHasBegun();
- void beginDeletion();
-#else
- bool deletionHasBegun() { return false; }
- void beginDeletion() { }
-#endif
-
- ContainerNode* m_rootNode;
+ ContainerNode& m_rootNode;
Document* m_documentScope;
TreeScope* m_parentTreeScope;
- unsigned m_selfOnlyRefCount;
std::unique_ptr<DocumentOrderedMap> m_elementsById;
std::unique_ptr<DocumentOrderedMap> m_elementsByName;
Modified: trunk/Source/WebCore/dom/TreeScopeAdopter.cpp (164194 => 164195)
--- trunk/Source/WebCore/dom/TreeScopeAdopter.cpp 2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/TreeScopeAdopter.cpp 2014-02-16 22:18:13 UTC (rev 164195)
@@ -32,27 +32,28 @@
namespace WebCore {
+// FIXME: Do we ever change tree scopes except between documents?
void TreeScopeAdopter::moveTreeToNewScope(Node* root) const
{
ASSERT(needsScopeChange());
- m_oldScope.selfOnlyRef();
-
// If an element is moved from a document and then eventually back again the collection cache for
// that element may contain stale data as changes made to it will have updated the DOMTreeVersion
// of the document it was moved to. By increasing the DOMTreeVersion of the donating document here
// we ensure that the collection cache will be invalidated as needed when the element is moved back.
- Document* oldDocument = m_oldScope.documentScope();
- Document* newDocument = m_newScope.documentScope();
- bool willMoveToNewDocument = oldDocument != newDocument;
- if (oldDocument && willMoveToNewDocument)
- oldDocument->incDOMTreeVersion();
+ Document& oldDocument = m_oldScope.documentScope();
+ Document& newDocument = m_newScope.documentScope();
+ bool willMoveToNewDocument = &oldDocument != &newDocument;
+ if (willMoveToNewDocument) {
+ oldDocument.selfOnlyRef();
+ oldDocument.incDOMTreeVersion();
+ }
for (Node* node = root; node; node = NodeTraversal::next(node, root)) {
updateTreeScope(node);
if (willMoveToNewDocument)
- moveNodeToNewDocument(node, oldDocument, newDocument);
+ moveNodeToNewDocument(node, &oldDocument, &newDocument);
else if (node->hasRareData()) {
NodeRareData* rareData = node->rareData();
if (rareData->nodeLists())
@@ -71,19 +72,20 @@
if (ShadowRoot* shadow = node->shadowRoot()) {
shadow->setParentTreeScope(&m_newScope);
if (willMoveToNewDocument)
- moveTreeToNewDocument(shadow, oldDocument, newDocument);
+ moveShadowTreeToNewDocument(shadow, &oldDocument, &newDocument);
}
}
- m_oldScope.selfOnlyDeref();
+ if (willMoveToNewDocument)
+ oldDocument.selfOnlyDeref();
}
-void TreeScopeAdopter::moveTreeToNewDocument(Node* root, Document* oldDocument, Document* newDocument) const
+void TreeScopeAdopter::moveShadowTreeToNewDocument(ShadowRoot* shadowRoot, Document* oldDocument, Document* newDocument) const
{
- for (Node* node = root; node; node = NodeTraversal::next(node, root)) {
+ for (Node* node = shadowRoot; node; node = NodeTraversal::next(node, shadowRoot)) {
moveNodeToNewDocument(node, oldDocument, newDocument);
if (ShadowRoot* shadow = node->shadowRoot())
- moveTreeToNewDocument(shadow, oldDocument, newDocument);
+ moveShadowTreeToNewDocument(shadow, oldDocument, newDocument);
}
}
@@ -103,8 +105,6 @@
{
ASSERT(!node->isTreeScope());
ASSERT(&node->treeScope() == &m_oldScope);
- m_newScope.selfOnlyRef();
- m_oldScope.selfOnlyDeref();
node->setTreeScope(m_newScope);
}
@@ -112,6 +112,9 @@
{
ASSERT(!node->inDocument() || oldDocument != newDocument);
+ newDocument->selfOnlyRef();
+ oldDocument->selfOnlyDeref();
+
if (node->hasRareData()) {
NodeRareData* rareData = node->rareData();
if (rareData->nodeLists())
Modified: trunk/Source/WebCore/dom/TreeScopeAdopter.h (164194 => 164195)
--- trunk/Source/WebCore/dom/TreeScopeAdopter.h 2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/TreeScopeAdopter.h 2014-02-16 22:18:13 UTC (rev 164195)
@@ -47,7 +47,7 @@
private:
void updateTreeScope(Node*) const;
void moveTreeToNewScope(Node*) const;
- void moveTreeToNewDocument(Node*, Document* oldDocument, Document* newDocument) const;
+ void moveShadowTreeToNewDocument(ShadowRoot*, Document* oldDocument, Document* newDocument) const;
void moveNodeToNewDocument(Node*, Document* oldDocument, Document* newDocument) const;
Node* m_toAdopt;