Element::removeShadowRoot() and setShadowRoot() should be moved into ShadowTree.
https://bugs.webkit.org/show_bug.cgi?id=78313

Reviewed by Hajime Morita.

.:

* Source/autotools/symbols.filter:

Source/WebCore:

This patch is for refactoring ShadowTree related code.
  (1) Element::removeShadowRoot() and Element::setShadowRoot() are moved into ShadowTree.
  (2) ShadowTree is now put on its own heap.

No new tests, no change in behavior.

* WebCore.exp.in:
* dom/Element.cpp:
(WebCore::Element::~Element):
(WebCore::Element::shadowTree):
(WebCore::Element::ensureShadowTree):
  Ensure the existence of ShadowTree. This does not ensure ShadowRoot exists.
* dom/Element.h:
(Element):
* dom/ElementRareData.h:
  Makes ShadowTree on Heap.
(ElementRareData):
(WebCore::ElementRareData::~ElementRareData):
* dom/ShadowRoot.cpp:
(WebCore::ShadowRoot::create):
* dom/ShadowTree.cpp:
(WebCore::validateShadowRoot):
(WebCore):
(WebCore::ShadowTree::addShadowRoot):
(WebCore::ShadowTree::removeAllShadowRoots):
* dom/ShadowTree.h:
(ShadowTree):
* testing/Internals.cpp:
(WebCore::Internals::removeShadowRoot):

Source/WebKit2:

* win/WebKit2.def:
* win/WebKit2CFLite.def:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@109084 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 9fd4d2f..ee185cd 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,40 @@
+2012-02-27  Shinya Kawanaka  <shinyak@chromium.org>
+
+        Element::removeShadowRoot() and setShadowRoot() should be moved into ShadowTree.
+        https://bugs.webkit.org/show_bug.cgi?id=78313
+
+        Reviewed by Hajime Morita.
+
+        This patch is for refactoring ShadowTree related code.
+          (1) Element::removeShadowRoot() and Element::setShadowRoot() are moved into ShadowTree.
+          (2) ShadowTree is now put on its own heap.
+
+        No new tests, no change in behavior.
+
+        * WebCore.exp.in:
+        * dom/Element.cpp:
+        (WebCore::Element::~Element):
+        (WebCore::Element::shadowTree):
+        (WebCore::Element::ensureShadowTree):
+          Ensure the existence of ShadowTree. This does not ensure ShadowRoot exists.
+        * dom/Element.h:
+        (Element):
+        * dom/ElementRareData.h:
+          Makes ShadowTree on Heap.
+        (ElementRareData):
+        (WebCore::ElementRareData::~ElementRareData):
+        * dom/ShadowRoot.cpp:
+        (WebCore::ShadowRoot::create):
+        * dom/ShadowTree.cpp:
+        (WebCore::validateShadowRoot):
+        (WebCore):
+        (WebCore::ShadowTree::addShadowRoot):
+        (WebCore::ShadowTree::removeAllShadowRoots):
+        * dom/ShadowTree.h:
+        (ShadowTree):
+        * testing/Internals.cpp:
+        (WebCore::Internals::removeShadowRoot):
+
 2012-02-27  David Barton  <dbarton@mathscribe.com>
 
         Fix <msubsup> formatting, especially for a tall base, subscript, or superscript
diff --git a/Source/WebCore/WebCore.exp.in b/Source/WebCore/WebCore.exp.in
index 8b2d968..346a78e 100644
--- a/Source/WebCore/WebCore.exp.in
+++ b/Source/WebCore/WebCore.exp.in
@@ -143,6 +143,7 @@
 __ZN7WebCore10JSDocument6s_infoE
 __ZN7WebCore10MouseEvent6createERKN3WTF12AtomicStringENS1_10PassRefPtrINS_9DOMWindowEEERKNS_18PlatformMouseEventEiNS5_INS_4NodeEEE
 __ZN7WebCore10MouseEventC1ERKN3WTF12AtomicStringEbbNS1_10PassRefPtrINS_9DOMWindowEEEiiiiibbbbtNS5_INS_11EventTargetEEENS5_INS_9ClipboardEEEb
+__ZN7WebCore10ShadowTree20removeAllShadowRootsEv
 __ZN7WebCore10ScrollView17setUseFixedLayoutEb
 __ZN7WebCore10ScrollView18setFixedLayoutSizeERKNS_7IntSizeE
 __ZN7WebCore10ScrollView20setCanHaveScrollbarsEb
@@ -915,7 +916,6 @@
 __ZN7WebCore6toNodeEN3JSC7JSValueE
 __ZN7WebCore7Console21shouldPrintExceptionsEv
 __ZN7WebCore7Console24setShouldPrintExceptionsEb
-__ZN7WebCore7Element16removeShadowRootEv
 __ZN7WebCore7Element21boundsInRootViewSpaceEv
 __ZN7WebCore7Element9innerTextEv
 __ZN7WebCore7IntRect5scaleEf
diff --git a/Source/WebCore/dom/Element.cpp b/Source/WebCore/dom/Element.cpp
index 896eabb..5cf70b5 100644
--- a/Source/WebCore/dom/Element.cpp
+++ b/Source/WebCore/dom/Element.cpp
@@ -122,7 +122,8 @@
 
 Element::~Element()
 {
-    removeShadowRoot();
+    if (shadowTree())
+        rareData()->m_shadowTree.clear();
     if (m_attributeMap)
         m_attributeMap->detachFromElement();
 }
@@ -1161,47 +1162,16 @@
     if (!hasRareData())
         return 0;
 
-    return &rareData()->m_shadowTree;
+    return rareData()->m_shadowTree.get();
 }
 
-static bool validateShadowRoot(Document* document, ShadowRoot* shadowRoot, ExceptionCode& ec)
+ShadowTree* Element::ensureShadowTree()
 {
-    if (!shadowRoot)
-        return true;
+    if (ShadowTree* tree = ensureRareData()->m_shadowTree.get())
+        return tree;
 
-    if (shadowRoot->shadowHost()) {
-        ec = HIERARCHY_REQUEST_ERR;
-        return false;
-    }
-
-    if (shadowRoot->document() != document) {
-        ec = WRONG_DOCUMENT_ERR;
-        return false;
-    }
-
-    return true;
-}
-
-void Element::setShadowRoot(PassRefPtr<ShadowRoot> shadowRoot, ExceptionCode& ec)
-{
-    if (!validateShadowRoot(document(), shadowRoot.get(), ec))
-        return;
-
-    if (!hasRareData())
-        ensureRareData();
-
-    removeShadowRoot();
-
-    shadowRoot->setShadowHost(this);
-    shadowTree()->pushShadowRoot(shadowRoot.get());
-
-    if (inDocument())
-        shadowRoot->insertedIntoDocument();
-    if (attached()) {
-        shadowRoot->lazyAttach();
-        for (Node* child = firstChild(); child; child = child->nextSibling())
-            child->detach();
-    }
+    rareData()->m_shadowTree = adoptPtr(new ShadowTree());
+    return rareData()->m_shadowTree.get();
 }
 
 ShadowRoot* Element::ensureShadowRoot()
@@ -1212,32 +1182,6 @@
     return ShadowRoot::create(this, ShadowRoot::CreatingUserAgentShadowRoot).get();
 }
 
-void Element::removeShadowRoot()
-{
-    if (!hasShadowRoot())
-        return;
-
-    while (RefPtr<ShadowRoot> oldRoot = shadowTree()->popShadowRoot()) {
-        document()->removeFocusedNodeOfSubtree(oldRoot.get());
-
-        if (oldRoot->attached())
-            oldRoot->detach();
-
-        oldRoot->setShadowHost(0);
-        document()->adoptIfNeeded(oldRoot.get());
-        if (oldRoot->inDocument())
-            oldRoot->removedFromDocument();
-        else
-            oldRoot->removedFromTree(true);
-        if (attached()) {
-            for (Node* child = firstChild(); child; child = child->nextSibling()) {
-                if (!child->attached())
-                    child->lazyAttach();
-            }
-        }
-    }
-}
-
 const AtomicString& Element::shadowPseudoId() const
 {
     return hasRareData() ? rareData()->m_shadowPseudoId : nullAtom;
diff --git a/Source/WebCore/dom/Element.h b/Source/WebCore/dom/Element.h
index 4a9f15b..c231cbe 100644
--- a/Source/WebCore/dom/Element.h
+++ b/Source/WebCore/dom/Element.h
@@ -255,12 +255,11 @@
 
     bool hasShadowRoot() const;
     ShadowTree* shadowTree() const;
+    ShadowTree* ensureShadowTree();
 
-    // FIXME: These API will be moved to ShadowTree.
-    // https://bugs.webkit.org/show_bug.cgi?id=78313
-    void setShadowRoot(PassRefPtr<ShadowRoot>, ExceptionCode&);
+    // FIXME: Remove Element::ensureShadowRoot
+    // https://bugs.webkit.org/show_bug.cgi?id=77608
     ShadowRoot* ensureShadowRoot();
-    void removeShadowRoot();
 
     virtual const AtomicString& shadowPseudoId() const;
     void setShadowPseudoId(const AtomicString&, ExceptionCode& = ASSERT_NO_EXCEPTION);
diff --git a/Source/WebCore/dom/ElementRareData.h b/Source/WebCore/dom/ElementRareData.h
index 45d89d5a..11c82579 100644
--- a/Source/WebCore/dom/ElementRareData.h
+++ b/Source/WebCore/dom/ElementRareData.h
@@ -64,11 +64,11 @@
 
     LayoutSize m_minimumSizeForResizing;
     RefPtr<RenderStyle> m_computedStyle;
-    ShadowTree m_shadowTree;
     AtomicString m_shadowPseudoId;
 
     OwnPtr<DatasetDOMStringMap> m_datasetDOMStringMap;
     OwnPtr<ClassList> m_classList;
+    OwnPtr<ShadowTree> m_shadowTree;
 
     bool m_styleAffectedByEmpty;
 
@@ -94,7 +94,7 @@
 
 inline ElementRareData::~ElementRareData()
 {
-    ASSERT(!m_shadowTree.hasShadowRoot());
+    ASSERT(!m_shadowTree);
 }
 
 inline void ElementRareData::resetComputedStyle()
diff --git a/Source/WebCore/dom/ShadowRoot.cpp b/Source/WebCore/dom/ShadowRoot.cpp
index c16c859..cb9d8c3 100644
--- a/Source/WebCore/dom/ShadowRoot.cpp
+++ b/Source/WebCore/dom/ShadowRoot.cpp
@@ -123,7 +123,7 @@
     RefPtr<ShadowRoot> shadowRoot = adoptRef(new ShadowRoot(element->document()));
 
     ec = 0;
-    element->setShadowRoot(shadowRoot, ec);
+    element->ensureShadowTree()->addShadowRoot(element, shadowRoot, ec);
     if (ec)
         return 0;
     ASSERT(element == shadowRoot->host());
diff --git a/Source/WebCore/dom/ShadowTree.cpp b/Source/WebCore/dom/ShadowTree.cpp
index f046c3f..3ef251b 100644
--- a/Source/WebCore/dom/ShadowTree.cpp
+++ b/Source/WebCore/dom/ShadowTree.cpp
@@ -44,29 +44,84 @@
 
 ShadowTree::~ShadowTree()
 {
-    ASSERT(!hasShadowRoot());
+    if (hasShadowRoot())
+        removeAllShadowRoots();
 }
 
-void ShadowTree::pushShadowRoot(ShadowRoot* shadowRoot)
+static bool validateShadowRoot(Document* document, ShadowRoot* shadowRoot, ExceptionCode& ec)
 {
+    if (!shadowRoot)
+        return true;
+
+    if (shadowRoot->shadowHost()) {
+        ec = HIERARCHY_REQUEST_ERR;
+        return false;
+    }
+
+    if (shadowRoot->document() != document) {
+        ec = WRONG_DOCUMENT_ERR;
+        return false;
+    }
+
+    return true;
+}
+
+void ShadowTree::addShadowRoot(Element* shadowHost, PassRefPtr<ShadowRoot> shadowRoot, ExceptionCode& ec)
+{
+    ASSERT(shadowHost);
+    ASSERT(shadowRoot);
 #if ENABLE(SHADOW_DOM)
-    if (!RuntimeEnabledFeatures::multipleShadowSubtreesEnabled())
-        ASSERT(!hasShadowRoot());
+    ASSERT(!hasShadowRoot() || RuntimeEnabledFeatures::multipleShadowSubtreesEnabled());
 #else
     ASSERT(!hasShadowRoot());
 #endif
 
-    m_shadowRoots.push(shadowRoot);
-    InspectorInstrumentation::didPushShadowRoot(host(), shadowRoot);
+    if (!validateShadowRoot(shadowHost->document(), shadowRoot.get(), ec))
+        return;
+
+    shadowRoot->setShadowHost(shadowHost);
+
+    if (shadowHost->inDocument())
+        shadowRoot->insertedIntoDocument();
+    if (shadowHost->attached()) {
+        shadowRoot->lazyAttach();
+        detach();
+        for (Node* child = shadowHost->firstChild(); child; child = child->nextSibling())
+            child->detach();
+    }
+
+    m_shadowRoots.push(shadowRoot.get());
+    InspectorInstrumentation::didPushShadowRoot(shadowHost, shadowRoot.get());
 }
 
-ShadowRoot* ShadowTree::popShadowRoot()
+void ShadowTree::removeAllShadowRoots()
 {
     if (!hasShadowRoot())
-        return 0;
+        return;
 
-    InspectorInstrumentation::willPopShadowRoot(host(), m_shadowRoots.head());
-    return m_shadowRoots.removeHead();
+    Element* shadowHost = host();
+
+    while (RefPtr<ShadowRoot> oldRoot = m_shadowRoots.removeHead()) {
+        InspectorInstrumentation::willPopShadowRoot(shadowHost, oldRoot.get());
+        shadowHost->document()->removeFocusedNodeOfSubtree(oldRoot.get());
+
+        if (oldRoot->attached())
+            oldRoot->detach();
+
+        oldRoot->setShadowHost(0);
+        shadowHost->document()->adoptIfNeeded(oldRoot.get());
+        if (oldRoot->inDocument())
+            oldRoot->removedFromDocument();
+        else
+            oldRoot->removedFromTree(true);
+    }
+
+    if (shadowHost->attached()) {
+        for (Node* child = shadowHost->firstChild(); child; child = child->nextSibling()) {
+            if (!child->attached())
+                child->lazyAttach();
+        }
+    }
 }
 
 void ShadowTree::insertedIntoDocument()
diff --git a/Source/WebCore/dom/ShadowTree.h b/Source/WebCore/dom/ShadowTree.h
index 6e37a7e..92e9b13 100644
--- a/Source/WebCore/dom/ShadowTree.h
+++ b/Source/WebCore/dom/ShadowTree.h
@@ -27,6 +27,7 @@
 #ifndef ShadowTree_h
 #define ShadowTree_h
 
+#include "ExceptionCode.h"
 #include "ShadowRoot.h"
 #include <wtf/DoublyLinkedList.h>
 #include <wtf/Noncopyable.h>
@@ -49,8 +50,8 @@
     ShadowRoot* youngestShadowRoot() const;
     ShadowRoot* oldestShadowRoot() const;
 
-    void pushShadowRoot(ShadowRoot*);
-    ShadowRoot* popShadowRoot();
+    void addShadowRoot(Element* shadowHost, PassRefPtr<ShadowRoot>, ExceptionCode&);
+    void removeAllShadowRoots();
 
     void insertedIntoDocument();
     void removedFromDocument();
diff --git a/Source/WebCore/testing/Internals.cpp b/Source/WebCore/testing/Internals.cpp
index 4e02903..b48f594 100644
--- a/Source/WebCore/testing/Internals.cpp
+++ b/Source/WebCore/testing/Internals.cpp
@@ -248,7 +248,8 @@
         return;
     }
 
-    host->removeShadowRoot();
+    if (host->hasShadowRoot())
+        host->shadowTree()->removeAllShadowRoots();
 }
 
 void Internals::setMultipleShadowSubtreesEnabled(bool enabled)
diff --git a/Source/WebKit2/ChangeLog b/Source/WebKit2/ChangeLog
index 429ea85..a28592e 100644
--- a/Source/WebKit2/ChangeLog
+++ b/Source/WebKit2/ChangeLog
@@ -1,3 +1,13 @@
+2012-02-27  Shinya Kawanaka  <shinyak@chromium.org>
+
+        Element::removeShadowRoot() and setShadowRoot() should be moved into ShadowTree.
+        https://bugs.webkit.org/show_bug.cgi?id=78313
+
+        Reviewed by Hajime Morita.
+
+        * win/WebKit2.def:
+        * win/WebKit2CFLite.def:
+
 2012-02-27  Brady Eidson  <beidson@apple.com>
 
         <rdar://problem/10924993> and https://bugs.webkit.org/show_bug.cgi?id=79725
diff --git a/Source/WebKit2/win/WebKit2.def b/Source/WebKit2/win/WebKit2.def
index a2a6d3d..ab99653 100644
--- a/Source/WebKit2/win/WebKit2.def
+++ b/Source/WebKit2/win/WebKit2.def
@@ -176,7 +176,7 @@
         ?page@Document@WebCore@@QBEPAVPage@2@XZ
         ?paintControlTints@FrameView@WebCore@@AAEXXZ
         ?rangeFromLocationAndLength@TextIterator@WebCore@@SA?AV?$PassRefPtr@VRange@WebCore@@@WTF@@PAVElement@2@HH_N@Z
-        ?removeShadowRoot@Element@WebCore@@QAEXXZ
+        ?removeAllShadowRoots@ShadowTree@WebCore@@QAEXXZ
         ?scriptExecutionContext@JSDOMGlobalObject@WebCore@@QBEPAVScriptExecutionContext@2@XZ
         ?scrollElementToRect@FrameView@WebCore@@QAEXPAVElement@2@ABVIntRect@2@@Z
         ?setDOMException@WebCore@@YAXPAVExecState@JSC@@H@Z
diff --git a/Source/WebKit2/win/WebKit2CFLite.def b/Source/WebKit2/win/WebKit2CFLite.def
index ffb0c75..b9392d8 100644
--- a/Source/WebKit2/win/WebKit2CFLite.def
+++ b/Source/WebKit2/win/WebKit2CFLite.def
@@ -169,7 +169,7 @@
         ?page@Document@WebCore@@QBEPAVPage@2@XZ
         ?paintControlTints@FrameView@WebCore@@AAEXXZ
         ?rangeFromLocationAndLength@TextIterator@WebCore@@SA?AV?$PassRefPtr@VRange@WebCore@@@WTF@@PAVElement@2@HH_N@Z
-        ?removeShadowRoot@Element@WebCore@@QAEXXZ
+        ?removeAllShadowRoots@ShadowTree@WebCore@@QAEXXZ
         ?scriptExecutionContext@JSDOMGlobalObject@WebCore@@QBEPAVScriptExecutionContext@2@XZ
         ?scrollElementToRect@FrameView@WebCore@@QAEXPAVElement@2@ABVIntRect@2@@Z
         ?setDOMException@WebCore@@YAXPAVExecState@JSC@@H@Z
diff --git a/Source/autotools/symbols.filter b/Source/autotools/symbols.filter
index 24ac8d0..86348ad 100644
--- a/Source/autotools/symbols.filter
+++ b/Source/autotools/symbols.filter
@@ -42,6 +42,7 @@
 _ZN7WebCore10ClientRectC1Ev;
 _ZN7WebCore10ClientRectC1ERKNS_7IntRectE;
 _ZN7WebCore10ShadowRoot6createEPNS_7ElementERi;
+_ZN7WebCore10ShadowTree20removeAllShadowRootsEv;
 _ZN7WebCore11EventTarget17toGeneratedStreamEv;
 _ZN7WebCore11EventTarget8toStreamEv;
 _ZN7WebCore12TextIterator26rangeFromLocationAndLengthEPNS_7ElementEiib;
@@ -66,7 +67,6 @@
 _ZN7WebCore6JSNode20visitChildrenVirtualERN3JSC11SlotVisitorE;
 _ZN7WebCore6JSNode6s_infoE;
 _ZN7WebCore6toNodeEN3JSC7JSValueE;
-_ZN7WebCore7Element16removeShadowRootEv;
 _ZN7WebCore7toRangeEN3JSC7JSValueE;
 _ZN7WebCore9JSElement10putVirtualEPN3JSC9ExecStateERKNS1_10IdentifierENS1_7JSValueERNS1_15PutPropertySlotE;
 _ZN7WebCore9JSElement6s_infoE;