Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / dom / shadow / ShadowRoot.cpp
index 95865b8..80be155 100644 (file)
 #include "config.h"
 #include "core/dom/shadow/ShadowRoot.h"
 
-#include "bindings/v8/ExceptionMessages.h"
 #include "bindings/v8/ExceptionState.h"
 #include "core/css/StyleSheetList.h"
 #include "core/css/resolver/StyleResolver.h"
 #include "core/dom/ElementTraversal.h"
 #include "core/dom/StyleEngine.h"
 #include "core/dom/Text.h"
-#include "core/dom/WhitespaceChildList.h"
 #include "core/dom/shadow/ElementShadow.h"
 #include "core/dom/shadow/InsertionPoint.h"
 #include "core/dom/shadow/ShadowRootRareData.h"
 #include "core/editing/markup.h"
+#include "core/html/shadow/HTMLShadowElement.h"
 #include "public/platform/Platform.h"
 
 namespace WebCore {
@@ -56,9 +55,9 @@ enum ShadowRootUsageOriginType {
     ShadowRootUsageOriginMax
 };
 
-ShadowRoot::ShadowRoot(Document* document, ShadowRootType type)
+ShadowRoot::ShadowRoot(Document& document, ShadowRootType type)
     : DocumentFragment(0, CreateShadowRoot)
-    , TreeScope(this, document)
+    , TreeScope(*this, document)
     , m_prev(0)
     , m_next(0)
     , m_numberOfStyles(0)
@@ -66,14 +65,13 @@ ShadowRoot::ShadowRoot(Document* document, ShadowRootType type)
     , m_resetStyleInheritance(false)
     , m_type(type)
     , m_registeredWithParentShadowRoot(false)
-    , m_childInsertionPointsIsValid(false)
+    , m_descendantInsertionPointsIsValid(false)
 {
-    ASSERT(document);
     ScriptWrappable::init(this);
 
     if (type == ShadowRoot::AuthorShadowRoot) {
-        ShadowRootUsageOriginType usageType = document->url().protocolIsInHTTPFamily() ? ShadowRootUsageOriginWeb : ShadowRootUsageOriginNotWeb;
-        WebKit::Platform::current()->histogramEnumeration("WebCore.ShadowRoot.constructor", usageType, ShadowRootUsageOriginMax);
+        ShadowRootUsageOriginType usageType = document.url().protocolIsInHTTPFamily() ? ShadowRootUsageOriginWeb : ShadowRootUsageOriginNotWeb;
+        blink::Platform::current()->histogramEnumeration("WebCore.ShadowRoot.constructor", usageType, ShadowRootUsageOriginMax);
     }
 }
 
@@ -85,7 +83,7 @@ ShadowRoot::~ShadowRoot()
     if (m_shadowRootRareData && m_shadowRootRareData->styleSheets())
         m_shadowRootRareData->styleSheets()->detachFromDocument();
 
-    documentInternal()->styleEngine()->didRemoveShadowRoot(this);
+    document().styleEngine()->didRemoveShadowRoot(this);
 
     // We cannot let ContainerNode destructor call willBeDeletedFromDocument()
     // for this ShadowRoot instance because TreeScope destructor
@@ -109,7 +107,7 @@ void ShadowRoot::dispose()
     removeDetachedChildren();
 }
 
-ShadowRoot* ShadowRoot::bindingsOlderShadowRoot() const
+ShadowRoot* ShadowRoot::olderShadowRootForBindings() const
 {
     ShadowRoot* older = olderShadowRoot();
     while (older && !older->shouldExposeToBindings())
@@ -127,9 +125,9 @@ bool ShadowRoot::isOldestAuthorShadowRoot() const
     return true;
 }
 
-PassRefPtr<Node> ShadowRoot::cloneNode(bool, ExceptionState& es)
+PassRefPtr<Node> ShadowRoot::cloneNode(bool, ExceptionState& exceptionState)
 {
-    es.throwDOMException(DataCloneError, ExceptionMessages::failedToExecute("cloneNode", "ShadowRoot", "ShadowRoot nodes are not clonable."));
+    exceptionState.throwDOMException(DataCloneError, "ShadowRoot nodes are not clonable.");
     return 0;
 }
 
@@ -138,29 +136,15 @@ String ShadowRoot::innerHTML() const
     return createMarkup(this, ChildrenOnly);
 }
 
-void ShadowRoot::setInnerHTML(const String& markup, ExceptionState& es)
+void ShadowRoot::setInnerHTML(const String& markup, ExceptionState& exceptionState)
 {
     if (isOrphan()) {
-        es.throwDOMException(InvalidAccessError, ExceptionMessages::failedToExecute("setInnerHTML", "ShadowRoot", "The ShadowRoot does not have a host."));
+        exceptionState.throwDOMException(InvalidAccessError, "The ShadowRoot does not have a host.");
         return;
     }
 
-    if (RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup, host(), AllowScriptingContent, "innerHTML", es))
-        replaceChildrenWithFragment(this, fragment.release(), es);
-}
-
-bool ShadowRoot::childTypeAllowed(NodeType type) const
-{
-    switch (type) {
-    case ELEMENT_NODE:
-    case PROCESSING_INSTRUCTION_NODE:
-    case COMMENT_NODE:
-    case TEXT_NODE:
-    case CDATA_SECTION_NODE:
-        return true;
-    default:
-        return false;
-    }
+    if (RefPtr<DocumentFragment> fragment = createFragmentForInnerOuterHTML(markup, host(), AllowScriptingContent, "innerHTML", exceptionState))
+        replaceChildrenWithFragment(this, fragment.release(), exceptionState);
 }
 
 void ShadowRoot::recalcStyle(StyleRecalcChange change)
@@ -168,43 +152,49 @@ void ShadowRoot::recalcStyle(StyleRecalcChange change)
     // ShadowRoot doesn't support custom callbacks.
     ASSERT(!hasCustomStyleCallbacks());
 
-    StyleResolver* styleResolver = document().styleResolver();
-    styleResolver->pushParentShadowRoot(*this);
+    // If we're propagating an Inherit change and this ShadowRoot resets
+    // inheritance we don't need to look at the children.
+    if (change <= Inherit && resetStyleInheritance() && !needsStyleRecalc() && !childNeedsStyleRecalc())
+        return;
+
+    StyleResolver& styleResolver = document().ensureStyleResolver();
+    styleResolver.pushParentShadowRoot(*this);
 
-    // When we're set to lazyAttach we'll have a SubtreeStyleChange and we'll need
-    // to promote the change to a Force for all our descendants so they get a
-    // recalc and will attach.
     if (styleChangeType() >= SubtreeStyleChange)
         change = Force;
 
+    // There's no style to update so just calling recalcStyle means we're updated.
+    clearNeedsStyleRecalc();
+
     // FIXME: This doesn't handle :hover + div properly like Element::recalcStyle does.
-    WhitespaceChildList whitespaceChildList(change);
+    Text* lastTextNode = 0;
     for (Node* child = lastChild(); child; child = child->previousSibling()) {
         if (child->isTextNode()) {
-            Text* textChild = toText(child);
-            if (textChild->containsOnlyWhitespace())
-                whitespaceChildList.append(textChild);
-            else
-                textChild->recalcTextStyle(change);
-        } else if (child->isElementNode() && shouldRecalcStyle(change, child)) {
-            toElement(child)->recalcStyle(change);
+            toText(child)->recalcTextStyle(change, lastTextNode);
+            lastTextNode = toText(child);
+        } else if (child->isElementNode()) {
+            if (child->shouldCallRecalcStyle(change))
+                toElement(child)->recalcStyle(change, lastTextNode);
+            if (child->renderer())
+                lastTextNode = 0;
         }
     }
 
-    whitespaceChildList.recalcStyle();
+    styleResolver.popParentShadowRoot(*this);
 
-    styleResolver->popParentShadowRoot(*this);
-    clearNeedsStyleRecalc();
     clearChildNeedsStyleRecalc();
-    setAttached();
 }
 
-bool ShadowRoot::isActive() const
+bool ShadowRoot::isActiveForStyling() const
 {
-    for (ShadowRoot* shadowRoot = youngerShadowRoot(); shadowRoot; shadowRoot = shadowRoot->youngerShadowRoot())
-        if (!shadowRoot->containsShadowElements())
-            return false;
-    return true;
+    if (!youngerShadowRoot())
+        return true;
+
+    if (InsertionPoint* point = shadowInsertionPointOfYoungerShadowRoot()) {
+        if (point->containingShadowRoot())
+            return true;
+    }
+    return false;
 }
 
 void ShadowRoot::setApplyAuthorStyles(bool value)
@@ -212,17 +202,17 @@ void ShadowRoot::setApplyAuthorStyles(bool value)
     if (isOrphan())
         return;
 
-    if (m_applyAuthorStyles == value)
+    if (applyAuthorStyles() == value)
         return;
 
     m_applyAuthorStyles = value;
-    if (!isActive())
+    if (!isActiveForStyling())
         return;
 
     ASSERT(host());
     ASSERT(host()->shadow());
     if (host()->shadow()->didAffectApplyAuthorStyles())
-        host()->setNeedsStyleRecalc();
+        host()->setNeedsStyleRecalc(SubtreeStyleChange);
 
     // Since styles in shadow trees can select shadow hosts, set shadow host's needs-recalc flag true.
     // FIXME: host->setNeedsStyleRecalc() should take care of all elements in its shadow tree.
@@ -230,7 +220,7 @@ void ShadowRoot::setApplyAuthorStyles(bool value)
     // no recalc style is invoked for any elements in its shadow tree.
     // This problem occurs when using getComputedStyle() API.
     // So currently host and shadow root's needsStyleRecalc flags are set to be true.
-    setNeedsStyleRecalc();
+    setNeedsStyleRecalc(SubtreeStyleChange);
 }
 
 void ShadowRoot::setResetStyleInheritance(bool value)
@@ -238,22 +228,22 @@ void ShadowRoot::setResetStyleInheritance(bool value)
     if (isOrphan())
         return;
 
-    if (value == m_resetStyleInheritance)
+    if (value == resetStyleInheritance())
         return;
 
     m_resetStyleInheritance = value;
-    if (!isActive())
+    if (!isActiveForStyling())
         return;
 
-    setNeedsStyleRecalc();
+    setNeedsStyleRecalc(SubtreeStyleChange);
 }
 
 void ShadowRoot::attach(const AttachContext& context)
 {
-    StyleResolver* styleResolver = document().styleResolver();
-    styleResolver->pushParentShadowRoot(*this);
+    StyleResolver& styleResolver = document().ensureStyleResolver();
+    styleResolver.pushParentShadowRoot(*this);
     DocumentFragment::attach(context);
-    styleResolver->popParentShadowRoot(*this);
+    styleResolver.popParentShadowRoot(*this);
 }
 
 Node::InsertionNotificationRequest ShadowRoot::insertedInto(ContainerNode* insertionPoint)
@@ -357,13 +347,13 @@ void ShadowRoot::setShadowInsertionPointOfYoungerShadowRoot(PassRefPtr<HTMLShado
 void ShadowRoot::didAddInsertionPoint(InsertionPoint* insertionPoint)
 {
     ensureShadowRootRareData()->didAddInsertionPoint(insertionPoint);
-    invalidateChildInsertionPoints();
+    invalidateDescendantInsertionPoints();
 }
 
 void ShadowRoot::didRemoveInsertionPoint(InsertionPoint* insertionPoint)
 {
     m_shadowRootRareData->didRemoveInsertionPoint(insertionPoint);
-    invalidateChildInsertionPoints();
+    invalidateDescendantInsertionPoints();
 }
 
 void ShadowRoot::addChildShadowRoot()
@@ -384,9 +374,9 @@ unsigned ShadowRoot::childShadowRootCount() const
     return m_shadowRootRareData ? m_shadowRootRareData->childShadowRootCount() : 0;
 }
 
-void ShadowRoot::invalidateChildInsertionPoints()
+void ShadowRoot::invalidateDescendantInsertionPoints()
 {
-    m_childInsertionPointsIsValid = false;
+    m_descendantInsertionPointsIsValid = false;
     m_shadowRootRareData->clearDescendantInsertionPoints();
 }
 
@@ -394,16 +384,16 @@ const Vector<RefPtr<InsertionPoint> >& ShadowRoot::descendantInsertionPoints()
 {
     DEFINE_STATIC_LOCAL(const Vector<RefPtr<InsertionPoint> >, emptyList, ());
 
-    if (m_shadowRootRareData && m_childInsertionPointsIsValid)
+    if (m_shadowRootRareData && m_descendantInsertionPointsIsValid)
         return m_shadowRootRareData->descendantInsertionPoints();
 
-    m_childInsertionPointsIsValid = true;
+    m_descendantInsertionPointsIsValid = true;
 
     if (!containsInsertionPoints())
         return emptyList;
 
     Vector<RefPtr<InsertionPoint> > insertionPoints;
-    for (Element* element = ElementTraversal::firstWithin(this); element; element = ElementTraversal::next(element, this)) {
+    for (Element* element = ElementTraversal::firstWithin(*this); element; element = ElementTraversal::next(*element, this)) {
         if (element->isInsertionPoint())
             insertionPoints.append(toInsertionPoint(element));
     }