Merge from Chromium at DEPS revision r213371

This commit was generated by merge_to_master.py.

Change-Id: I03fae1c1dae6e5de12e56e0a6c3780252291bfae
diff --git a/Source/core/dom/CheckedRadioButtons.cpp b/Source/core/dom/CheckedRadioButtons.cpp
index a628b43..d8d7a46 100644
--- a/Source/core/dom/CheckedRadioButtons.cpp
+++ b/Source/core/dom/CheckedRadioButtons.cpp
@@ -260,7 +260,7 @@
     if (it->value->isEmpty()) {
         // FIXME: We may skip deallocating the empty RadioButtonGroup for
         // performance improvement. If we do so, we need to change the key type
-        // of m_nameToGroupMap from AtomicStringImpl* to RefPtr<AtomicStringImpl>.
+        // of m_nameToGroupMap from StringImpl* to AtomicString.
         m_nameToGroupMap->remove(it);
         if (m_nameToGroupMap->isEmpty())
             m_nameToGroupMap.clear();
diff --git a/Source/core/dom/CheckedRadioButtons.h b/Source/core/dom/CheckedRadioButtons.h
index 32bb5fe..6a1585b 100644
--- a/Source/core/dom/CheckedRadioButtons.h
+++ b/Source/core/dom/CheckedRadioButtons.h
@@ -24,6 +24,7 @@
 #include "wtf/Forward.h"
 #include "wtf/HashMap.h"
 #include "wtf/OwnPtr.h"
+#include "wtf/text/StringHash.h"
 
 namespace WebCore {
 
@@ -44,7 +45,7 @@
     bool isInRequiredGroup(HTMLInputElement*) const;
 
 private:
-    typedef HashMap<AtomicStringImpl*, OwnPtr<RadioButtonGroup> > NameToGroupMap;
+    typedef HashMap<StringImpl*, OwnPtr<RadioButtonGroup> > NameToGroupMap;
     OwnPtr<NameToGroupMap> m_nameToGroupMap;
 };
 
diff --git a/Source/core/dom/CustomElement.cpp b/Source/core/dom/CustomElement.cpp
new file mode 100644
index 0000000..de0b688
--- /dev/null
+++ b/Source/core/dom/CustomElement.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "core/dom/CustomElement.h"
+
+#include "core/dom/CustomElementCallbackScheduler.h"
+#include "core/dom/CustomElementRegistrationContext.h"
+#include "core/dom/Element.h"
+
+namespace WebCore {
+
+void CustomElement::define(Element* element, PassRefPtr<CustomElementDefinition> passDefinition)
+{
+    RefPtr<CustomElementDefinition> definition(passDefinition);
+    element->setCustomElementState(Element::Defined);
+    definitions().add(element, definition);
+    CustomElementCallbackScheduler::scheduleCreatedCallback(definition->callbacks(), element);
+}
+
+void CustomElement::attributeDidChange(Element* element, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue)
+{
+    ASSERT(element->customElementState() == Element::Upgraded);
+    CustomElementCallbackScheduler::scheduleAttributeChangedCallback(definitions().get(element)->callbacks(), element, name, oldValue, newValue);
+}
+
+void CustomElement::didEnterDocument(Element* element)
+{
+    ASSERT(element->customElementState() == Element::Upgraded);
+    CustomElementCallbackScheduler::scheduleEnteredDocumentCallback(definitions().get(element)->callbacks(), element);
+}
+
+void CustomElement::didLeaveDocument(Element* element)
+{
+    ASSERT(element->customElementState() == Element::Upgraded);
+    CustomElementCallbackScheduler::scheduleLeftDocumentCallback(definitions().get(element)->callbacks(), element);
+}
+
+void CustomElement::wasDestroyed(Element* element)
+{
+    definitions().remove(element);
+
+    // FIXME: Elements should only depend on their document's
+    // registration context at creation; maintain a mapping to
+    // registration context for upgrade candidates.
+    if (element->document() && element->document()->registrationContext())
+        element->document()->registrationContext()->customElementWasDestroyed(element);
+}
+
+void CustomElement::DefinitionMap::add(Element* element, PassRefPtr<CustomElementDefinition> definition)
+{
+    ASSERT(definition.get());
+    DefinitionMap::ElementDefinitionHashMap::AddResult result = m_definitions.add(element, definition);
+    ASSERT(result.isNewEntry);
+}
+
+void CustomElement::DefinitionMap::remove(Element* element)
+{
+    m_definitions.remove(element);
+}
+
+CustomElementDefinition* CustomElement::DefinitionMap::get(Element* element)
+{
+    DefinitionMap::ElementDefinitionHashMap::const_iterator it = m_definitions.find(element);
+    ASSERT(it != m_definitions.end());
+    return it->value.get();
+}
+
+CustomElement::DefinitionMap& CustomElement::definitions()
+{
+    DEFINE_STATIC_LOCAL(DefinitionMap, definitionMap, ());
+    return definitionMap;
+}
+
+} // namespace WebCore
diff --git a/Source/core/dom/CustomElement.h b/Source/core/dom/CustomElement.h
new file mode 100644
index 0000000..21bc28c
--- /dev/null
+++ b/Source/core/dom/CustomElement.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of Google Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CustomElement_h
+#define CustomElement_h
+
+#include "core/dom/CustomElementDefinition.h"
+#include "wtf/HashMap.h"
+#include "wtf/Noncopyable.h"
+#include "wtf/PassRefPtr.h"
+#include "wtf/RefPtr.h"
+#include "wtf/text/AtomicString.h"
+
+namespace WebCore {
+
+class Element;
+
+class CustomElement {
+public:
+    static void define(Element*, PassRefPtr<CustomElementDefinition>);
+    static void attributeDidChange(Element*, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue);
+    static void didEnterDocument(Element*);
+    static void didLeaveDocument(Element*);
+    static void wasDestroyed(Element*);
+
+private:
+    CustomElement();
+
+    class DefinitionMap {
+        WTF_MAKE_NONCOPYABLE(DefinitionMap);
+    public:
+        DefinitionMap() { }
+        ~DefinitionMap() { }
+
+        void add(Element*, PassRefPtr<CustomElementDefinition>);
+        void remove(Element*);
+        CustomElementDefinition* get(Element*);
+
+    private:
+        typedef HashMap<Element*, RefPtr<CustomElementDefinition> > ElementDefinitionHashMap;
+        ElementDefinitionHashMap m_definitions;
+    };
+
+    static DefinitionMap& definitions();
+};
+
+}
+
+#endif // CustomElement_h
diff --git a/Source/core/dom/CustomElementRegistrationContext.cpp b/Source/core/dom/CustomElementRegistrationContext.cpp
index 4ed6abf..c3a0cad 100644
--- a/Source/core/dom/CustomElementRegistrationContext.cpp
+++ b/Source/core/dom/CustomElementRegistrationContext.cpp
@@ -34,7 +34,7 @@
 #include "HTMLNames.h"
 #include "MathMLNames.h"
 #include "SVGNames.h"
-#include "core/dom/CustomElementCallbackScheduler.h"
+#include "core/dom/CustomElement.h"
 #include "core/dom/CustomElementDefinition.h"
 #include "core/dom/CustomElementRegistry.h"
 #include "core/dom/CustomElementUpgradeCandidateMap.h"
@@ -56,10 +56,6 @@
 
     virtual PassRefPtr<Element> createCustomTagElement(Document*, const QualifiedName&) OVERRIDE;
     virtual void didGiveTypeExtension(Element*) OVERRIDE { }
-
-    virtual void customElementAttributeDidChange(Element*, const AtomicString&, const AtomicString&, const AtomicString&) OVERRIDE { }
-    virtual void customElementDidEnterDocument(Element*) OVERRIDE { }
-    virtual void customElementDidLeaveDocument(Element*) OVERRIDE { }
 };
 
 PassRefPtr<Element> NullRegistrationContext::createCustomTagElement(Document* document, const QualifiedName& tagName)
@@ -96,18 +92,13 @@
     virtual PassRefPtr<Element> createCustomTagElement(Document*, const QualifiedName&) OVERRIDE;
     virtual void didGiveTypeExtension(Element*) OVERRIDE;
 
-    virtual void customElementAttributeDidChange(Element*, const AtomicString&, const AtomicString&, const AtomicString&) OVERRIDE;
-    virtual void customElementDidEnterDocument(Element*) OVERRIDE;
-    virtual void customElementDidLeaveDocument(Element*) OVERRIDE;
-    virtual void customElementIsBeingDestroyed(Element*) OVERRIDE;
+    virtual void customElementWasDestroyed(Element*) OVERRIDE;
 
 private:
     void resolve(Element*);
     void didResolveElement(CustomElementDefinition*, Element*);
     void didCreateUnresolvedElement(const CustomElementDescriptor&, Element*);
 
-    CustomElementDefinition* definitionFor(Element*) const;
-
     CustomElementRegistry m_registry;
 
     // Element creation
@@ -166,8 +157,7 @@
 
 void ActiveRegistrationContext::didResolveElement(CustomElementDefinition* definition, Element* element)
 {
-    element->setCustomElementState(Element::Defined);
-    CustomElementCallbackScheduler::scheduleCreatedCallback(definition->callbacks(), element);
+    CustomElement::define(element, definition);
 }
 
 void ActiveRegistrationContext::didCreateUnresolvedElement(const CustomElementDescriptor& descriptor, Element* element)
@@ -176,39 +166,10 @@
     m_candidates.add(descriptor, element);
 }
 
-CustomElementDefinition* ActiveRegistrationContext::definitionFor(Element* element) const
-{
-    ASSERT(element->customElementState() == Element::Defined || element->customElementState() == Element::Upgraded);
-    ASSERT(element->document()->registrationContext() == this);
-    const CustomElementDescriptor& descriptor = describe(element);
-    return m_registry.find(descriptor);
-}
-
-void ActiveRegistrationContext::customElementAttributeDidChange(Element* element, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue)
-{
-    ASSERT(element->customElementState() == Element::Upgraded);
-    CustomElementDefinition* definition = definitionFor(element);
-    CustomElementCallbackScheduler::scheduleAttributeChangedCallback(definition->callbacks(), element, name, oldValue, newValue);
-}
-
-void ActiveRegistrationContext::customElementDidEnterDocument(Element* element)
-{
-    ASSERT(element->customElementState() == Element::Upgraded);
-    CustomElementDefinition* definition = definitionFor(element);
-    CustomElementCallbackScheduler::scheduleEnteredDocumentCallback(definition->callbacks(), element);
-}
-
-void ActiveRegistrationContext::customElementDidLeaveDocument(Element* element)
-{
-    ASSERT(element->customElementState() == Element::Upgraded);
-    CustomElementDefinition* definition = definitionFor(element);
-    CustomElementCallbackScheduler::scheduleLeftDocumentCallback(definition->callbacks(), element);
-}
-
-void ActiveRegistrationContext::customElementIsBeingDestroyed(Element* element)
+void ActiveRegistrationContext::customElementWasDestroyed(Element* element)
 {
     m_candidates.remove(element);
-    CustomElementRegistrationContext::customElementIsBeingDestroyed(element);
+    CustomElementRegistrationContext::customElementWasDestroyed(element);
 }
 
 PassRefPtr<CustomElementRegistrationContext> CustomElementRegistrationContext::create()
@@ -276,7 +237,7 @@
     element->document()->registrationContext()->didGiveTypeExtension(element);
 }
 
-void CustomElementRegistrationContext::customElementIsBeingDestroyed(Element* element)
+void CustomElementRegistrationContext::customElementWasDestroyed(Element* element)
 {
     ASSERT(element->isCustomElement());
     typeExtensionMap()->remove(element);
diff --git a/Source/core/dom/CustomElementRegistrationContext.h b/Source/core/dom/CustomElementRegistrationContext.h
index e909255..c0c89da 100644
--- a/Source/core/dom/CustomElementRegistrationContext.h
+++ b/Source/core/dom/CustomElementRegistrationContext.h
@@ -54,8 +54,11 @@
     virtual ~CustomElementRegistrationContext() { }
 
     // Model
+    // FIXME: Move this to CustomElementRegistry
     static bool isValidTypeName(const AtomicString& type);
+    // FIXME: Move this to CustomElement
     static bool isCustomTagName(const AtomicString& localName);
+    // FIXME: Privatize this when CustomElementWrapper uses the definition map.
     static CustomElementDescriptor describe(Element*);
 
     // Definitions
@@ -67,10 +70,7 @@
     static void setTypeExtension(Element*, const AtomicString& type);
 
     // Instance lifecycle
-    virtual void customElementAttributeDidChange(Element*, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue) = 0;
-    virtual void customElementDidEnterDocument(Element*) = 0;
-    virtual void customElementDidLeaveDocument(Element*) = 0;
-    virtual void customElementIsBeingDestroyed(Element*);
+    virtual void customElementWasDestroyed(Element*);
 
 protected:
     CustomElementRegistrationContext() { }
diff --git a/Source/core/dom/DecodedDataDocumentParser.cpp b/Source/core/dom/DecodedDataDocumentParser.cpp
index 2f76a28..610d44e 100644
--- a/Source/core/dom/DecodedDataDocumentParser.cpp
+++ b/Source/core/dom/DecodedDataDocumentParser.cpp
@@ -27,10 +27,58 @@
 #include "core/dom/DecodedDataDocumentParser.h"
 
 #include "core/dom/Document.h"
+#include "core/dom/Element.h"
 #include "core/loader/TextResourceDecoder.h"
+#include "wtf/text/TextEncodingRegistry.h"
 
 namespace WebCore {
 
+namespace {
+
+class TitleEncodingFixer {
+public:
+    explicit TitleEncodingFixer(Document* document)
+        : m_document(document)
+        , m_firstEncoding(document->decoder()->encoding())
+    {
+    }
+
+    // It's possible for the encoding of the document to change while we're decoding
+    // data. That can only occur while we're processing the <head> portion of the
+    // document. There isn't much user-visible content in the <head>, but there is
+    // the <title> element. This function detects that situation and re-decodes the
+    // document's title so that the user doesn't see an incorrectly decoded title
+    // in the title bar.
+    inline void fixTitleEncodingIfNeeded()
+    {
+        if (m_firstEncoding == m_document->decoder()->encoding())
+            return; // In the common case, the encoding doesn't change and there isn't any work to do.
+        fixTitleEncoding();
+    }
+
+private:
+    void fixTitleEncoding();
+
+    Document* m_document;
+    WTF::TextEncoding m_firstEncoding;
+};
+
+void TitleEncodingFixer::fixTitleEncoding()
+{
+    RefPtr<Element> titleElement = m_document->titleElement();
+    if (!titleElement
+        || titleElement->firstElementChild()
+        || m_firstEncoding != Latin1Encoding()
+        || !titleElement->textContent().containsOnlyLatin1())
+        return; // Either we don't have a title yet or something bizzare as happened and we give up.
+    CString originalBytes = titleElement->textContent().latin1();
+    OwnPtr<TextCodec> codec = newTextCodec(m_document->decoder()->encoding());
+    String correctlyDecodedTitle = codec->decode(originalBytes.data(), originalBytes.length(), true);
+    titleElement->setTextContent(correctlyDecodedTitle, IGNORE_EXCEPTION);
+}
+
+}
+
 DecodedDataDocumentParser::DecodedDataDocumentParser(Document* document)
     : DocumentParser(document)
 {
@@ -41,7 +89,12 @@
     if (!length)
         return 0;
 
+    TitleEncodingFixer encodingFixer(document());
+
     String decoded = document()->decoder()->decode(data, length);
+
+    encodingFixer.fixTitleEncodingIfNeeded();
+
     if (decoded.isEmpty())
         return 0;
 
diff --git a/Source/core/dom/Document.cpp b/Source/core/dom/Document.cpp
index d4b4fc7..42aaace 100644
--- a/Source/core/dom/Document.cpp
+++ b/Source/core/dom/Document.cpp
@@ -398,7 +398,6 @@
     , m_inStyleRecalc(false)
     , m_closeAfterStyleRecalc(false)
     , m_gotoAnchorNeededAfterStylesheetsLoad(false)
-    , m_pendingStyleRecalcShouldForce(false)
     , m_containsValidityStyleRules(false)
     , m_updateFocusAppearanceRestoresSelection(false)
     , m_ignoreDestructiveWriteCount(0)
@@ -1133,7 +1132,7 @@
     m_contentLanguage = language;
 
     // Document's style depends on the content language.
-    scheduleForcedStyleRecalc();
+    setNeedsStyleRecalc();
 }
 
 void Document::setXMLVersion(const String& version, ExceptionCode& ec)
@@ -1317,7 +1316,7 @@
     else if (!m_titleElement) {
         if (HTMLElement* headElement = head()) {
             m_titleElement = createElement(titleTag, false);
-            headElement->appendChild(m_titleElement, ASSERT_NO_EXCEPTION);
+            headElement->appendChild(m_titleElement, ASSERT_NO_EXCEPTION, AttachLazily);
         }
     }
 
@@ -1529,12 +1528,6 @@
     return TreeWalker::create(root, whatToShow, filter);
 }
 
-void Document::scheduleForcedStyleRecalc()
-{
-    m_pendingStyleRecalcShouldForce = true;
-    scheduleStyleRecalc();
-}
-
 void Document::scheduleStyleRecalc()
 {
     if (shouldDisplaySeamlesslyWithParent()) {
@@ -1547,7 +1540,7 @@
     if (m_styleRecalcTimer.isActive())
         return;
 
-    ASSERT(childNeedsStyleRecalc() || m_pendingStyleRecalcShouldForce);
+    ASSERT(needsStyleRecalc() || childNeedsStyleRecalc());
 
     m_styleRecalcTimer.startOneShot(0);
 
@@ -1556,10 +1549,8 @@
 
 void Document::unscheduleStyleRecalc()
 {
-    ASSERT(!childNeedsStyleRecalc());
-
+    ASSERT(!attached() || (!needsStyleRecalc() && !childNeedsStyleRecalc()));
     m_styleRecalcTimer.stop();
-    m_pendingStyleRecalcShouldForce = false;
 }
 
 bool Document::hasPendingStyleRecalc() const
@@ -1569,7 +1560,7 @@
 
 bool Document::hasPendingForcedStyleRecalc() const
 {
-    return m_styleRecalcTimer.isActive() && m_pendingStyleRecalcShouldForce;
+    return hasPendingStyleRecalc() && styleChangeType() == SubtreeStyleChange;
 }
 
 void Document::styleRecalcTimerFired(Timer<Document>*)
@@ -1577,11 +1568,6 @@
     updateStyleIfNeeded();
 }
 
-bool Document::childNeedsAndNotInStyleRecalc()
-{
-    return childNeedsStyleRecalc() && !m_inStyleRecalc;
-}
-
 void Document::recalcStyle(StyleChange change)
 {
     // we should not enter style recalc while painting
@@ -1625,7 +1611,7 @@
         if (!renderer() || !renderArena())
             goto bailOut;
 
-        if (m_pendingStyleRecalcShouldForce)
+        if (styleChangeType() == SubtreeStyleChange)
             change = Force;
 
         // Recalculating the root style (on the document) is not needed in the common case.
@@ -1655,6 +1641,11 @@
         clearChildNeedsStyleRecalc();
         unscheduleStyleRecalc();
 
+        // FIXME: SVG <use> element can schedule a recalc in the middle of an already running one.
+        // See DocumentStyleSheetCollection::updateActiveStyleSheets.
+        if (m_styleSheetCollection->needsUpdateActiveStylesheetsOnStyleRecalc())
+            setNeedsStyleRecalc();
+
         m_inStyleRecalc = false;
 
         // Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc.
@@ -1690,7 +1681,7 @@
     ASSERT(isMainThread());
     ASSERT(!view() || (!view()->isInLayout() && !view()->isPainting()));
 
-    if (!m_pendingStyleRecalcShouldForce && !childNeedsStyleRecalc())
+    if (!needsStyleRecalc() && !childNeedsStyleRecalc())
         return;
 
     AnimationUpdateBlock animationUpdateBlock(m_frame ? m_frame->animation() : 0);
@@ -2012,7 +2003,7 @@
     // FIXME: How is possible to not have a renderer here?
     if (renderer())
         renderer()->style()->setRTLOrdering(VisualOrder);
-    scheduleForcedStyleRecalc();
+    setNeedsStyleRecalc();
 }
 
 PassRefPtr<DocumentParser> Document::createParser()
@@ -2044,6 +2035,7 @@
         setURL(ownerDocument->url());
         m_cookieURL = ownerDocument->cookieURL();
         setSecurityOrigin(ownerDocument->securityOrigin());
+        InspectorInstrumentation::childDocumentOpened(this);
     }
 
     if (m_frame) {
@@ -2637,7 +2629,16 @@
         parseDNSPrefetchControlHeader(content);
     else if (equalIgnoringCase(equiv, "x-frame-options"))
         processHttpEquivXFrameOptions(content);
-    else if (equalIgnoringCase(equiv, "content-security-policy"))
+    else if (equalIgnoringCase(equiv, "content-security-policy")
+        || equalIgnoringCase(equiv, "content-security-policy-report-only")
+        || equalIgnoringCase(equiv, "x-webkit-csp")
+        || equalIgnoringCase(equiv, "x-webkit-csp-report-only"))
+        processHttpEquivContentSecurityPolicy(equiv, content);
+}
+
+void Document::processHttpEquivContentSecurityPolicy(const String& equiv, const String& content)
+{
+    if (equalIgnoringCase(equiv, "content-security-policy"))
         contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::Enforce);
     else if (equalIgnoringCase(equiv, "content-security-policy-report-only"))
         contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::Report);
@@ -2645,6 +2646,8 @@
         contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::PrefixedEnforce);
     else if (equalIgnoringCase(equiv, "x-webkit-csp-report-only"))
         contentSecurityPolicy()->didReceiveHeader(content, ContentSecurityPolicy::PrefixedReport);
+    else
+        ASSERT_NOT_REACHED();
 }
 
 void Document::processHttpEquivDefaultStyle(const String& content)
@@ -2995,7 +2998,7 @@
     bool needsRecalc = m_styleSheetCollection->updateActiveStyleSheets(updateMode);
 
     if (updateType >= DeferRecalcStyle) {
-        scheduleForcedStyleRecalc();
+        setNeedsStyleRecalc();
         return;
     }
 
@@ -3924,7 +3927,7 @@
 {
     m_designMode = value;
     for (Frame* frame = m_frame; frame && frame->document(); frame = frame->tree()->traverseNext(m_frame))
-        frame->document()->scheduleForcedStyleRecalc();
+        frame->document()->setNeedsStyleRecalc();
 }
 
 Document::InheritedBool Document::getDesignMode() const
@@ -4077,6 +4080,11 @@
     if (!m_documentTiming.domContentLoadedEventEnd)
         m_documentTiming.domContentLoadedEventEnd = monotonicallyIncreasingTime();
 
+    // The loader's finishedParsing() method may invoke script that causes this object to
+    // be dereferenced (when this document is in an iframe and the onload causes the iframe's src to change).
+    // Keep it alive until we are done.
+    RefPtr<Document> protect(this);
+
     if (RefPtr<Frame> f = frame()) {
         // FrameLoader::finishedParsing() might end up calling Document::implicitClose() if all
         // resource loads are complete. HTMLObjectElements can start loading their resources from
diff --git a/Source/core/dom/Document.h b/Source/core/dom/Document.h
index cfd2f8f..3c47aa6 100644
--- a/Source/core/dom/Document.h
+++ b/Source/core/dom/Document.h
@@ -482,7 +482,6 @@
     PassRefPtr<Text> createEditingTextNode(const String&);
 
     void recalcStyle(StyleChange = NoChange);
-    bool childNeedsAndNotInStyleRecalc();
     void updateStyleIfNeeded();
     void updateStyleForNodeIfNeeded(Node*);
     void updateLayout();
@@ -654,8 +653,7 @@
     // Updates for :target (CSS3 selector).
     void setCSSTarget(Element*);
     Element* cssTarget() const { return m_cssTarget; }
-    
-    void scheduleForcedStyleRecalc();
+
     void scheduleStyleRecalc();
     void unscheduleStyleRecalc();
     bool hasPendingStyleRecalc() const;
@@ -754,6 +752,7 @@
     String title() const { return m_title.string(); }
     void setTitle(const String&);
 
+    Element* titleElement() const { return m_titleElement.get(); }
     void setTitleElement(const StringWithDirection&, Element* titleElement);
     void removeTitle(Element* titleElement);
 
@@ -1112,6 +1111,7 @@
     void processHttpEquivRefresh(const String& content);
     void processHttpEquivSetCookie(const String& content);
     void processHttpEquivXFrameOptions(const String& content);
+    void processHttpEquivContentSecurityPolicy(const String& equiv, const String& content);
 
     Timer<Document> m_styleResolverThrowawayTimer;
     double m_lastStyleResolverAccessTime;
@@ -1198,9 +1198,8 @@
     bool m_visuallyOrdered;
     ReadyState m_readyState;
     bool m_bParsing;
-    
+
     Timer<Document> m_styleRecalcTimer;
-    bool m_pendingStyleRecalcShouldForce;
     bool m_inStyleRecalc;
     bool m_closeAfterStyleRecalc;
 
diff --git a/Source/core/dom/DocumentOrderedMap.cpp b/Source/core/dom/DocumentOrderedMap.cpp
index 9f62cdb..76f236a 100644
--- a/Source/core/dom/DocumentOrderedMap.cpp
+++ b/Source/core/dom/DocumentOrderedMap.cpp
@@ -42,22 +42,22 @@
 
 using namespace HTMLNames;
 
-inline bool keyMatchesId(AtomicStringImpl* key, Element* element)
+inline bool keyMatchesId(StringImpl* key, Element* element)
 {
     return element->getIdAttribute().impl() == key;
 }
 
-inline bool keyMatchesMapName(AtomicStringImpl* key, Element* element)
+inline bool keyMatchesMapName(StringImpl* key, Element* element)
 {
     return element->hasTagName(mapTag) && toHTMLMapElement(element)->getName().impl() == key;
 }
 
-inline bool keyMatchesLowercasedMapName(AtomicStringImpl* key, Element* element)
+inline bool keyMatchesLowercasedMapName(StringImpl* key, Element* element)
 {
     return element->hasTagName(mapTag) && toHTMLMapElement(element)->getName().lower().impl() == key;
 }
 
-inline bool keyMatchesLabelForAttribute(AtomicStringImpl* key, Element* element)
+inline bool keyMatchesLabelForAttribute(StringImpl* key, Element* element)
 {
     return isHTMLLabelElement(element) && element->getAttribute(forAttr).impl() == key;
 }
@@ -68,7 +68,7 @@
     m_duplicateCounts.clear();
 }
 
-void DocumentOrderedMap::add(AtomicStringImpl* key, Element* element)
+void DocumentOrderedMap::add(StringImpl* key, Element* element)
 {
     ASSERT(key);
     ASSERT(element);
@@ -98,7 +98,7 @@
     m_duplicateCounts.add(key);
 }
 
-void DocumentOrderedMap::remove(AtomicStringImpl* key, Element* element)
+void DocumentOrderedMap::remove(StringImpl* key, Element* element)
 {
     ASSERT(key);
     ASSERT(element);
@@ -111,8 +111,8 @@
         m_duplicateCounts.remove(key);
 }
 
-template<bool keyMatches(AtomicStringImpl*, Element*)>
-inline Element* DocumentOrderedMap::get(AtomicStringImpl* key, const TreeScope* scope) const
+template<bool keyMatches(StringImpl*, Element*)>
+inline Element* DocumentOrderedMap::get(StringImpl* key, const TreeScope* scope) const
 {
     ASSERT(key);
     ASSERT(scope);
@@ -138,22 +138,22 @@
     return 0;
 }
 
-Element* DocumentOrderedMap::getElementById(AtomicStringImpl* key, const TreeScope* scope) const
+Element* DocumentOrderedMap::getElementById(StringImpl* key, const TreeScope* scope) const
 {
     return get<keyMatchesId>(key, scope);
 }
 
-Element* DocumentOrderedMap::getElementByMapName(AtomicStringImpl* key, const TreeScope* scope) const
+Element* DocumentOrderedMap::getElementByMapName(StringImpl* key, const TreeScope* scope) const
 {
     return get<keyMatchesMapName>(key, scope);
 }
 
-Element* DocumentOrderedMap::getElementByLowercasedMapName(AtomicStringImpl* key, const TreeScope* scope) const
+Element* DocumentOrderedMap::getElementByLowercasedMapName(StringImpl* key, const TreeScope* scope) const
 {
     return get<keyMatchesLowercasedMapName>(key, scope);
 }
 
-Element* DocumentOrderedMap::getElementByLabelForAttribute(AtomicStringImpl* key, const TreeScope* scope) const
+Element* DocumentOrderedMap::getElementByLabelForAttribute(StringImpl* key, const TreeScope* scope) const
 {
     return get<keyMatchesLabelForAttribute>(key, scope);
 }
diff --git a/Source/core/dom/DocumentOrderedMap.h b/Source/core/dom/DocumentOrderedMap.h
index 9fe076a..b6fc8e0 100644
--- a/Source/core/dom/DocumentOrderedMap.h
+++ b/Source/core/dom/DocumentOrderedMap.h
@@ -33,7 +33,7 @@
 
 #include "wtf/HashCountedSet.h"
 #include "wtf/HashMap.h"
-#include "wtf/text/AtomicStringImpl.h"
+#include "wtf/text/StringImpl.h"
 
 namespace WebCore {
 
@@ -42,38 +42,38 @@
 
 class DocumentOrderedMap {
 public:
-    void add(AtomicStringImpl*, Element*);
-    void remove(AtomicStringImpl*, Element*);
+    void add(StringImpl*, Element*);
+    void remove(StringImpl*, Element*);
     void clear();
 
-    bool contains(AtomicStringImpl*) const;
-    bool containsMultiple(AtomicStringImpl*) const;
+    bool contains(StringImpl*) const;
+    bool containsMultiple(StringImpl*) const;
     // concrete instantiations of the get<>() method template
-    Element* getElementById(AtomicStringImpl*, const TreeScope*) const;
-    Element* getElementByMapName(AtomicStringImpl*, const TreeScope*) const;
-    Element* getElementByLowercasedMapName(AtomicStringImpl*, const TreeScope*) const;
-    Element* getElementByLabelForAttribute(AtomicStringImpl*, const TreeScope*) const;
+    Element* getElementById(StringImpl*, const TreeScope*) const;
+    Element* getElementByMapName(StringImpl*, const TreeScope*) const;
+    Element* getElementByLowercasedMapName(StringImpl*, const TreeScope*) const;
+    Element* getElementByLabelForAttribute(StringImpl*, const TreeScope*) const;
 
     void checkConsistency() const;
 
 private:
-    template<bool keyMatches(AtomicStringImpl*, Element*)> Element* get(AtomicStringImpl*, const TreeScope*) const;
+    template<bool keyMatches(StringImpl*, Element*)> Element* get(StringImpl*, const TreeScope*) const;
 
-    typedef HashMap<AtomicStringImpl*, Element*> Map;
+    typedef HashMap<StringImpl*, Element*> Map;
 
     // We maintain the invariant that m_duplicateCounts is the count of all elements with a given key
     // excluding the one referenced in m_map, if any. This means it one less than the total count
     // when the first node with a given key is cached, otherwise the same as the total count.
     mutable Map m_map;
-    mutable HashCountedSet<AtomicStringImpl*> m_duplicateCounts;
+    mutable HashCountedSet<StringImpl*> m_duplicateCounts;
 };
 
-inline bool DocumentOrderedMap::contains(AtomicStringImpl* id) const
+inline bool DocumentOrderedMap::contains(StringImpl* id) const
 {
     return m_map.contains(id) || m_duplicateCounts.contains(id);
 }
 
-inline bool DocumentOrderedMap::containsMultiple(AtomicStringImpl* id) const
+inline bool DocumentOrderedMap::containsMultiple(StringImpl* id) const
 {
     return m_duplicateCounts.contains(id);
 }
diff --git a/Source/core/dom/DocumentStyleSheetCollection.cpp b/Source/core/dom/DocumentStyleSheetCollection.cpp
index e2088d8..d45931c 100644
--- a/Source/core/dom/DocumentStyleSheetCollection.cpp
+++ b/Source/core/dom/DocumentStyleSheetCollection.cpp
@@ -254,7 +254,6 @@
         // https://bugs.webkit.org/show_bug.cgi?id=54344
         // FIXME: This should be fixed in SVG and the call site replaced by ASSERT(!m_inStyleRecalc).
         m_needsUpdateActiveStylesheetsOnStyleRecalc = true;
-        m_document->scheduleForcedStyleRecalc();
         return false;
 
     }
diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp
index 7affb64..dc64b8d 100644
--- a/Source/core/dom/Element.cpp
+++ b/Source/core/dom/Element.cpp
@@ -33,6 +33,7 @@
 #include "SVGNames.h"
 #include "XMLNames.h"
 #include "core/accessibility/AXObjectCache.h"
+#include "core/animation/DocumentTimeline.h"
 #include "core/css/CSSParser.h"
 #include "core/css/CSSStyleSheet.h"
 #include "core/css/CSSValuePool.h"
@@ -43,6 +44,7 @@
 #include "core/dom/Attribute.h"
 #include "core/dom/ClientRect.h"
 #include "core/dom/ClientRectList.h"
+#include "core/dom/CustomElement.h"
 #include "core/dom/CustomElementRegistrationContext.h"
 #include "core/dom/DatasetDOMStringMap.h"
 #include "core/dom/Document.h"
@@ -208,8 +210,8 @@
         data->clearShadow();
     }
 
-    if (isCustomElement() && document() && document()->registrationContext())
-        document()->registrationContext()->customElementIsBeingDestroyed(this);
+    if (isCustomElement())
+        CustomElement::wasDestroyed(this);
 
     if (hasSyntheticAttrChildNodes())
         detachAllAttrNodesFromElement();
@@ -373,34 +375,31 @@
     return rareData->attributeMap();
 }
 
-void Element::addActiveAnimation(Animation* animation)
+ActiveAnimations* Element::activeAnimations() const
 {
-    ElementRareData* rareData = ensureElementRareData();
-    if (!rareData->activeAnimations())
-        rareData->setActiveAnimations(adoptPtr(new Vector<Animation*>));
-    rareData->activeAnimations()->append(animation);
+    if (hasActiveAnimations())
+        return elementRareData()->activeAnimations();
+    return 0;
 }
 
-void Element::removeActiveAnimation(Animation* animation)
+ActiveAnimations* Element::ensureActiveAnimations()
 {
-    ElementRareData* rareData = elementRareData();
-    ASSERT(rareData);
-    size_t position = rareData->activeAnimations()->find(animation);
-    ASSERT(position != notFound);
-    rareData->activeAnimations()->remove(position);
+    ElementRareData* rareData = ensureElementRareData();
+    if (!elementRareData()->activeAnimations())
+        rareData->setActiveAnimations(adoptPtr(new ActiveAnimations()));
+    return rareData->activeAnimations();
 }
 
 bool Element::hasActiveAnimations() const
 {
-    return hasRareData() && elementRareData()->activeAnimations()
-        && elementRareData()->activeAnimations()->size();
-}
+    if (!RuntimeEnabledFeatures::webAnimationsEnabled())
+        return false;
 
-Vector<Animation*>* Element::activeAnimations() const
-{
-    if (!elementRareData())
-        return 0;
-    return elementRareData()->activeAnimations();
+    if (!hasRareData())
+        return false;
+
+    ActiveAnimations* activeAnimations = elementRareData()->activeAnimations();
+    return activeAnimations && !activeAnimations->isEmpty();
 }
 
 Node::NodeType Element::nodeType() const
@@ -1200,37 +1199,6 @@
     return RenderObject::createObject(this, style);
 }
 
-#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-bool Element::isDateTimeEditElement() const
-{
-    return false;
-}
-
-bool Element::isDateTimeFieldElement() const
-{
-    return false;
-}
-
-bool Element::isPickerIndicatorElement() const
-{
-    return false;
-}
-#endif
-
-bool Element::isClearButtonElement() const
-{
-    return false;
-}
-
-bool Element::wasChangedSinceLastFormControlChangeEvent() const
-{
-    return false;
-}
-
-void Element::setChangedSinceLastFormControlChangeEvent(bool)
-{
-}
-
 bool Element::isInert() const
 {
     const Element* dialog = document()->activeModalDialog();
@@ -1265,7 +1233,7 @@
         return InsertionDone;
 
     if (isUpgradedCustomElement())
-        document()->registrationContext()->customElementDidEnterDocument(this);
+        CustomElement::didEnterDocument(this);
 
     const AtomicString& idValue = getIdAttribute();
     if (!idValue.isNull())
@@ -1326,14 +1294,14 @@
         if (hasPendingResources())
             document()->accessSVGExtensions()->removeElementFromPendingResources(this);
 
-        if (isUpgradedCustomElement() && document()->registrationContext())
-            document()->registrationContext()->customElementDidLeaveDocument(this);
+        if (isUpgradedCustomElement())
+            CustomElement::didLeaveDocument(this);
     }
 }
 
 void Element::createRendererIfNeeded(const AttachContext& context)
 {
-    NodeRenderingContext(this, context).createRendererForElementIfNeeded();
+    NodeRenderingContext(this, context.resolvedStyle).createRendererForElementIfNeeded();
 }
 
 void Element::attach(const AttachContext& context)
@@ -1464,12 +1432,12 @@
         willRecalcStyle(change);
 
     // Ref currentStyle in case it would otherwise be deleted when setting the new style in the renderer.
-    RefPtr<RenderStyle> currentStyle(renderStyle());
-    bool hasParentStyle = parentNodeForRenderingAndStyle() ? static_cast<bool>(parentNodeForRenderingAndStyle()->renderStyle()) : false;
+    RefPtr<RenderStyle> currentStyle = renderStyle();
+    bool hasParentStyle = static_cast<bool>(parentRenderStyle());
     bool hasDirectAdjacentRules = childrenAffectedByDirectAdjacentRules();
     bool hasIndirectAdjacentRules = childrenAffectedByForwardPositionalRules();
 
-    if ((change > NoChange || needsStyleRecalc())) {
+    if (change > NoChange || needsStyleRecalc()) {
         if (hasRareData())
             elementRareData()->resetComputedStyle();
     }
@@ -1528,11 +1496,12 @@
     }
     StyleResolverParentPusher parentPusher(this);
 
-    // FIXME: This does not care about sibling combinators. Will be necessary in XBL2 world.
     if (ElementShadow* shadow = this->shadow()) {
-        if (shouldRecalcStyle(change, shadow)) {
-            parentPusher.push();
-            shadow->recalcStyle(change);
+        for (ShadowRoot* root = shadow->youngestShadowRoot(); root; root = root->olderShadowRoot()) {
+            if (shouldRecalcStyle(change, root)) {
+                parentPusher.push();
+                root->recalcStyle(change);
+            }
         }
     }
 
@@ -1673,7 +1642,7 @@
     return false;
 }
 
-static void checkForEmptyStyleChange(Element* element, RenderStyle* style)
+static void inline checkForEmptyStyleChange(Element* element, RenderStyle* style)
 {
     if (!style && !element->styleAffectedByEmpty())
         return;
@@ -1685,80 +1654,74 @@
 static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool finishedParsingCallback,
                                         Node* beforeChange, Node* afterChange, int childCountDelta)
 {
+    if (!e->attached() || e->document()->hasPendingForcedStyleRecalc() || e->styleChangeType() == SubtreeStyleChange)
+        return;
+
     // :empty selector.
     checkForEmptyStyleChange(e, style);
 
     if (!style || (e->needsStyleRecalc() && e->childrenAffectedByPositionalRules()))
         return;
 
-    // :first-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
-    // In the DOM case, we only need to do something if |afterChange| is not 0.
-    // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
-    if (e->childrenAffectedByFirstChildRules() && afterChange) {
-        // Find our new first child.
-        Node* newFirstChild = 0;
-        for (newFirstChild = e->firstChild(); newFirstChild && !newFirstChild->isElementNode(); newFirstChild = newFirstChild->nextSibling()) {};
-
-        // Find the first element node following |afterChange|
-        Node* firstElementAfterInsertion = 0;
-        for (firstElementAfterInsertion = afterChange;
-             firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
-             firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
-
-        // This is the insert/append case.
-        if (newFirstChild != firstElementAfterInsertion && firstElementAfterInsertion && firstElementAfterInsertion->attached() &&
-            firstElementAfterInsertion->renderStyle() && firstElementAfterInsertion->renderStyle()->firstChildState())
-            firstElementAfterInsertion->setNeedsStyleRecalc();
-
-        // We also have to handle node removal.
-        if (childCountDelta < 0 && newFirstChild == firstElementAfterInsertion && newFirstChild && (!newFirstChild->renderStyle() || !newFirstChild->renderStyle()->firstChildState()))
-            newFirstChild->setNeedsStyleRecalc();
-    }
-
-    // :last-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
-    // In the DOM case, we only need to do something if |afterChange| is not 0.
-    if (e->childrenAffectedByLastChildRules() && beforeChange) {
-        // Find our new last child.
-        Node* newLastChild = 0;
-        for (newLastChild = e->lastChild(); newLastChild && !newLastChild->isElementNode(); newLastChild = newLastChild->previousSibling()) {};
-
-        // Find the last element node going backwards from |beforeChange|
-        Node* lastElementBeforeInsertion = 0;
-        for (lastElementBeforeInsertion = beforeChange;
-             lastElementBeforeInsertion && !lastElementBeforeInsertion->isElementNode();
-             lastElementBeforeInsertion = lastElementBeforeInsertion->previousSibling()) {};
-
-        if (newLastChild != lastElementBeforeInsertion && lastElementBeforeInsertion && lastElementBeforeInsertion->attached() &&
-            lastElementBeforeInsertion->renderStyle() && lastElementBeforeInsertion->renderStyle()->lastChildState())
-            lastElementBeforeInsertion->setNeedsStyleRecalc();
-
-        // We also have to handle node removal.  The parser callback case is similar to node removal as well in that we need to change the last child
-        // to match now.
-        if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && (!newLastChild->renderStyle() || !newLastChild->renderStyle()->lastChildState()))
-            newLastChild->setNeedsStyleRecalc();
-    }
-
-    // The + selector.  We need to invalidate the first element following the insertion point.  It is the only possible element
-    // that could be affected by this DOM change.
-    if (e->childrenAffectedByDirectAdjacentRules() && afterChange) {
-        Node* firstElementAfterInsertion = 0;
-        for (firstElementAfterInsertion = afterChange;
-             firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
-             firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
-        if (firstElementAfterInsertion && firstElementAfterInsertion->attached())
-            firstElementAfterInsertion->setNeedsStyleRecalc();
-    }
-
     // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type.
     // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
     // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
     // backward case.
     // |afterChange| is 0 in the parser callback case, so we won't do any work for the forward case if we don't have to.
     // For performance reasons we just mark the parent node as changed, since we don't want to make childrenChanged O(n^2) by crawling all our kids
-    // here.  recalcStyle will then force a walk of the children when it sees that this has happened.
-    if ((e->childrenAffectedByForwardPositionalRules() && afterChange)
-        || (e->childrenAffectedByBackwardPositionalRules() && beforeChange))
+    // here. recalcStyle will then force a walk of the children when it sees that this has happened.
+    if ((e->childrenAffectedByForwardPositionalRules() && afterChange) || (e->childrenAffectedByBackwardPositionalRules() && beforeChange)) {
         e->setNeedsStyleRecalc();
+        return;
+    }
+
+    // :first-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
+    // In the DOM case, we only need to do something if |afterChange| is not 0.
+    // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
+    if (e->childrenAffectedByFirstChildRules() && afterChange) {
+        // Find our new first child.
+        Node* newFirstChild = e->firstElementChild();
+        RenderStyle* newFirstChildStyle = newFirstChild ? newFirstChild->renderStyle() : 0;
+
+        // Find the first element node following |afterChange|
+        Node* firstElementAfterInsertion = afterChange->isElementNode() ? afterChange : afterChange->nextElementSibling();
+        RenderStyle* firstElementAfterInsertionStyle = firstElementAfterInsertion ? firstElementAfterInsertion->renderStyle() : 0;
+
+        // This is the insert/append case.
+        if (newFirstChild != firstElementAfterInsertion && firstElementAfterInsertionStyle && firstElementAfterInsertionStyle->firstChildState())
+            firstElementAfterInsertion->setNeedsStyleRecalc();
+
+        // We also have to handle node removal.
+        if (childCountDelta < 0 && newFirstChild == firstElementAfterInsertion && newFirstChild && (!newFirstChildStyle || !newFirstChildStyle->firstChildState()))
+            newFirstChild->setNeedsStyleRecalc();
+    }
+
+    // :last-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
+    // In the DOM case, we only need to do something if |afterChange| is not 0.
+    if (e->childrenAffectedByLastChildRules() && beforeChange) {
+        // Find our new last child.
+        Node* newLastChild = e->lastElementChild();
+        RenderStyle* newLastChildStyle = newLastChild ? newLastChild->renderStyle() : 0;
+
+        // Find the last element node going backwards from |beforeChange|
+        Node* lastElementBeforeInsertion = beforeChange->isElementNode() ? beforeChange : beforeChange->previousElementSibling();
+        RenderStyle* lastElementBeforeInsertionStyle = lastElementBeforeInsertion ? lastElementBeforeInsertion->renderStyle() : 0;
+
+        if (newLastChild != lastElementBeforeInsertion && lastElementBeforeInsertionStyle && lastElementBeforeInsertionStyle->lastChildState())
+            lastElementBeforeInsertion->setNeedsStyleRecalc();
+
+        // We also have to handle node removal.  The parser callback case is similar to node removal as well in that we need to change the last child
+        // to match now.
+        if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && (!newLastChildStyle || !newLastChildStyle->lastChildState()))
+            newLastChild->setNeedsStyleRecalc();
+    }
+
+    // The + selector.  We need to invalidate the first element following the insertion point.  It is the only possible element
+    // that could be affected by this DOM change.
+    if (e->childrenAffectedByDirectAdjacentRules() && afterChange) {
+        if (Node* firstElementAfterInsertion = afterChange->nextElementSibling())
+            firstElementAfterInsertion->setNeedsStyleRecalc();
+    }
 }
 
 void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
@@ -1769,7 +1732,7 @@
     else
         checkForSiblingStyleChanges(this, renderStyle(), false, beforeChange, afterChange, childCountDelta);
 
-    if (ElementShadow * shadow = this->shadow())
+    if (ElementShadow* shadow = this->shadow())
         shadow->invalidateDistribution();
 }
 
@@ -2157,11 +2120,6 @@
     return content.toString();
 }
 
-String Element::title() const
-{
-    return String();
-}
-
 const AtomicString& Element::pseudo() const
 {
     return getAttribute(pseudoAttr);
@@ -2475,16 +2433,6 @@
     return 0;
 }
 
-bool Element::matchesReadOnlyPseudoClass() const
-{
-    return false;
-}
-
-bool Element::matchesReadWritePseudoClass() const
-{
-    return false;
-}
-
 bool Element::webkitMatchesSelector(const String& selector, ExceptionCode& ec)
 {
     if (selector.isEmpty()) {
@@ -2498,11 +2446,6 @@
     return selectorQuery->matches(this);
 }
 
-bool Element::shouldAppearIndeterminate() const
-{
-    return false;
-}
-
 DOMTokenList* Element::classList()
 {
     ElementRareData* data = ensureElementRareData();
@@ -2822,7 +2765,7 @@
            setNeedsStyleRecalc();
 
         if (isUpgradedCustomElement())
-            document()->registrationContext()->customElementAttributeDidChange(this, name.localName(), oldValue, newValue);
+            CustomElement::attributeDidChange(this, name.localName(), oldValue, newValue);
     }
 
     if (OwnPtr<MutationObserverInterestGroup> recipients = MutationObserverInterestGroup::createForAttributesMutation(this, name))
@@ -3096,9 +3039,9 @@
 
 struct PresentationAttributeCacheKey {
     PresentationAttributeCacheKey() : tagName(0) { }
-    AtomicStringImpl* tagName;
+    StringImpl* tagName;
     // Only the values need refcounting.
-    Vector<pair<AtomicStringImpl*, AtomicString>, 3> attributesAndValues;
+    Vector<pair<StringImpl*, AtomicString>, 3> attributesAndValues;
 };
 
 struct PresentationAttributeCacheEntry {
@@ -3318,7 +3261,7 @@
         inlineStyle->addSubresourceStyleURLs(urls, document()->elementSheet()->contents());
 }
 
-static inline bool attributeNameSort(const pair<AtomicStringImpl*, AtomicString>& p1, const pair<AtomicStringImpl*, AtomicString>& p2)
+static inline bool attributeNameSort(const pair<StringImpl*, AtomicString>& p1, const pair<StringImpl*, AtomicString>& p2)
 {
     // Sort based on the attribute name pointers. It doesn't matter what the order is as long as it is always the same.
     return p1.first < p2.first;
diff --git a/Source/core/dom/Element.h b/Source/core/dom/Element.h
index 35f6e17..989019c 100644
--- a/Source/core/dom/Element.h
+++ b/Source/core/dom/Element.h
@@ -37,7 +37,7 @@
 
 namespace WebCore {
 
-class Animation;
+class ActiveAnimations;
 class Attr;
 class Attribute;
 class ClientRect;
@@ -513,7 +513,7 @@
  
     String textFromChildren();
 
-    virtual String title() const;
+    virtual String title() const { return String(); }
 
     const AtomicString& pseudo() const;
     void setPseudo(const AtomicString&);
@@ -531,10 +531,10 @@
     PseudoElement* pseudoElement(PseudoId) const;
     RenderObject* pseudoElementRenderer(PseudoId) const;
 
-    virtual bool matchesReadOnlyPseudoClass() const;
-    virtual bool matchesReadWritePseudoClass() const;
+    virtual bool matchesReadOnlyPseudoClass() const { return false; }
+    virtual bool matchesReadWritePseudoClass() const { return false; }
     bool webkitMatchesSelector(const String& selectors, ExceptionCode&);
-    virtual bool shouldAppearIndeterminate() const;
+    virtual bool shouldAppearIndeterminate() const { return false; }
 
     DOMTokenList* classList();
 
@@ -547,9 +547,9 @@
     virtual bool isInputFieldSpeechButtonElement() const { return false; }
 #endif
 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
-    virtual bool isDateTimeEditElement() const;
-    virtual bool isDateTimeFieldElement() const;
-    virtual bool isPickerIndicatorElement() const;
+    virtual bool isDateTimeEditElement() const { return false; }
+    virtual bool isDateTimeFieldElement() const { return false; }
+    virtual bool isPickerIndicatorElement() const { return false; }
 #endif
 
     virtual bool isFormControlElement() const { return false; }
@@ -564,14 +564,15 @@
     virtual bool isOutOfRange() const { return false; }
     virtual bool isFrameElementBase() const { return false; }
     virtual bool isPasswordGeneratorButtonElement() const { return false; }
-    virtual bool isClearButtonElement() const;
+    virtual bool isClearButtonElement() const { return false; }
 
     virtual bool canContainRangeEndPoint() const { return true; }
 
     virtual const AtomicString& formControlType() const { return nullAtom; }
 
-    virtual bool wasChangedSinceLastFormControlChangeEvent() const;
-    virtual void setChangedSinceLastFormControlChangeEvent(bool);
+    // FIXME: Only HTMLInputElement uses these, they don't need to be virtual.
+    virtual bool wasChangedSinceLastFormControlChangeEvent() const { return false; }
+    virtual void setChangedSinceLastFormControlChangeEvent(bool) { }
     virtual void dispatchFormControlChangeEvent() { }
 
     // Used for disabled form elements; if true, prevents mouse events from being dispatched
@@ -622,10 +623,9 @@
     IntSize savedLayerScrollOffset() const;
     void setSavedLayerScrollOffset(const IntSize&);
 
-    void addActiveAnimation(Animation*);
-    void removeActiveAnimation(Animation*);
+    ActiveAnimations* activeAnimations() const;
+    ActiveAnimations* ensureActiveAnimations();
     bool hasActiveAnimations() const;
-    Vector<Animation*>* activeAnimations() const;
 
     InputMethodContext* getInputContext();
 
diff --git a/Source/core/dom/ElementRareData.h b/Source/core/dom/ElementRareData.h
index 4b86859..117e93a 100644
--- a/Source/core/dom/ElementRareData.h
+++ b/Source/core/dom/ElementRareData.h
@@ -22,6 +22,7 @@
 #ifndef ElementRareData_h
 #define ElementRareData_h
 
+#include "core/animation/ActiveAnimations.h"
 #include "core/dom/DatasetDOMStringMap.h"
 #include "core/dom/NamedNodeMap.h"
 #include "core/dom/NodeRareData.h"
@@ -34,7 +35,6 @@
 
 namespace WebCore {
 
-class Animation;
 class HTMLElement;
 
 class ElementRareData : public NodeRareData {
@@ -128,10 +128,10 @@
     IntSize savedLayerScrollOffset() const { return m_savedLayerScrollOffset; }
     void setSavedLayerScrollOffset(IntSize size) { m_savedLayerScrollOffset = size; }
 
-    Vector<Animation*>* activeAnimations() { return m_activeAnimations.get(); }
-    void setActiveAnimations(PassOwnPtr<Vector<Animation*> > animations)
+    ActiveAnimations* activeAnimations() { return m_activeAnimations.get(); }
+    void setActiveAnimations(PassOwnPtr<ActiveAnimations> activeAnimations)
     {
-        m_activeAnimations = animations;
+        m_activeAnimations = activeAnimations;
     }
 
     bool hasPendingResources() const { return m_hasPendingResources; }
@@ -178,8 +178,7 @@
     OwnPtr<ElementShadow> m_shadow;
     OwnPtr<NamedNodeMap> m_attributeMap;
     OwnPtr<InputMethodContext> m_inputMethodContext;
-
-    OwnPtr<Vector<Animation*> > m_activeAnimations;
+    OwnPtr<ActiveAnimations> m_activeAnimations;
 
     RefPtr<PseudoElement> m_generatedBefore;
     RefPtr<PseudoElement> m_generatedAfter;
diff --git a/Source/core/dom/EventPathWalker.cpp b/Source/core/dom/EventPathWalker.cpp
index a3b9760..4c28e19 100644
--- a/Source/core/dom/EventPathWalker.cpp
+++ b/Source/core/dom/EventPathWalker.cpp
@@ -62,14 +62,14 @@
     }
     if (!m_node->isShadowRoot()) {
         m_node = m_node->parentNode();
-        if (!(m_node && m_node->isShadowRoot() && ScopeContentDistribution::assignedTo(toShadowRoot(m_node))))
+        if (!(m_node && m_node->isShadowRoot() && toShadowRoot(m_node)->insertionPoint()))
             m_distributedNode = m_node;
         m_isVisitingInsertionPointInReprojection = false;
         return;
     }
 
     const ShadowRoot* shadowRoot = toShadowRoot(m_node);
-    if (InsertionPoint* insertionPoint = ScopeContentDistribution::assignedTo(shadowRoot)) {
+    if (InsertionPoint* insertionPoint = shadowRoot->insertionPoint()) {
         m_node = insertionPoint;
         m_isVisitingInsertionPointInReprojection = true;
         return;
diff --git a/Source/core/dom/FullscreenController.cpp b/Source/core/dom/FullscreenController.cpp
index ed63fee..c365872 100644
--- a/Source/core/dom/FullscreenController.cpp
+++ b/Source/core/dom/FullscreenController.cpp
@@ -431,7 +431,7 @@
         m_fullScreenRenderer->unwrapRenderer();
 
     m_fullScreenElement = 0;
-    document()->scheduleForcedStyleRecalc();
+    document()->setNeedsStyleRecalc();
 
     // When webkitCancelFullScreen is called, we call webkitExitFullScreen on the topDocument(). That
     // means that the events will be queued there. So if we have no events here, start the timer on
diff --git a/Source/core/dom/IdTargetObserverRegistry.h b/Source/core/dom/IdTargetObserverRegistry.h
index fb04ff5..4af563a 100644
--- a/Source/core/dom/IdTargetObserverRegistry.h
+++ b/Source/core/dom/IdTargetObserverRegistry.h
@@ -30,7 +30,7 @@
 #include "wtf/HashMap.h"
 #include "wtf/HashSet.h"
 #include "wtf/PassOwnPtr.h"
-#include "wtf/text/AtomicString.h"
+#include "wtf/text/StringHash.h"
 
 namespace WebCore {
 
@@ -50,7 +50,7 @@
     void notifyObserversInternal(const AtomicString& id);
 
     typedef HashSet<IdTargetObserver*> ObserverSet;
-    typedef HashMap<AtomicStringImpl*, OwnPtr<ObserverSet> > IdToObserverSetMap;
+    typedef HashMap<StringImpl*, OwnPtr<ObserverSet> > IdToObserverSetMap;
     IdToObserverSetMap m_registry;
     ObserverSet* m_notifyingObserversInSet;
 };
diff --git a/Source/core/dom/MessagePort.cpp b/Source/core/dom/MessagePort.cpp
index 07b4eb1..be7ab66 100644
--- a/Source/core/dom/MessagePort.cpp
+++ b/Source/core/dom/MessagePort.cpp
@@ -68,7 +68,7 @@
         for (unsigned int i = 0; i < ports->size(); ++i) {
             MessagePort* dataPort = (*ports)[i].get();
             if (dataPort == this || m_entangledChannel->isConnectedTo(dataPort)) {
-                es.throwDOMException(InvalidStateError);
+                es.throwDOMException(DataCloneError);
                 return;
             }
         }
diff --git a/Source/core/dom/Node.cpp b/Source/core/dom/Node.cpp
index 8f63f06..4cdd942 100644
--- a/Source/core/dom/Node.cpp
+++ b/Source/core/dom/Node.cpp
@@ -55,7 +55,7 @@
 #include "core/dom/MutationEvent.h"
 #include "core/dom/NameNodeList.h"
 #include "core/dom/NodeRareData.h"
-#include "core/dom/NodeRenderingContext.h"
+#include "core/dom/NodeRenderingTraversal.h"
 #include "core/dom/NodeTraversal.h"
 #include "core/dom/ProcessingInstruction.h"
 #include "core/dom/SelectorQuery.h"
@@ -650,10 +650,14 @@
 
     for (const Node* node = this; node; node = node->parentNode()) {
         if ((node->isHTMLElement() || node->isDocumentNode()) && node->renderer()) {
+#if ENABLE(USERSELECT_ALL)
             // Elements with user-select: all style are considered atomic
             // therefore non editable.
             if (node->renderer()->style()->userSelect() == SELECT_ALL && treatment == UserSelectAllIsAlwaysNonEditable)
                 return false;
+#else
+            UNUSED_PARAM(treatment);
+#endif
             switch (node->renderer()->style()->userModify()) {
             case READ_ONLY:
                 return false;
@@ -770,7 +774,7 @@
     for (ContainerNode* p = parentOrShadowHostNode(); p && !p->childNeedsStyleRecalc(); p = p->parentOrShadowHostNode())
         p->setChildNeedsStyleRecalc();
 
-    if (document()->childNeedsStyleRecalc())
+    if (document()->needsStyleRecalc() || document()->childNeedsStyleRecalc())
         document()->scheduleStyleRecalc();
 }
 
@@ -1140,11 +1144,6 @@
     return 0;
 }
 
-ContainerNode* Node::parentNodeForRenderingAndStyle()
-{
-    return NodeRenderingContext(this).parentNodeForRenderingAndStyle();
-}
-
 RenderStyle* Node::virtualComputedStyle(PseudoId pseudoElementSpecifier)
 {
     return parentOrShadowHostNode() ? parentOrShadowHostNode()->computedStyle(pseudoElementSpecifier) : 0;
@@ -1656,7 +1655,7 @@
             ChildListMutationScope mutation(this);
             container->removeChildren();
             if (!text.isEmpty())
-                container->appendChild(document()->createTextNode(text), ec);
+                container->appendChild(document()->createTextNode(text), ec, AttachLazily);
             return;
         }
         case DOCUMENT_NODE:
diff --git a/Source/core/dom/Node.h b/Source/core/dom/Node.h
index f71a14a..45db9bc 100644
--- a/Source/core/dom/Node.h
+++ b/Source/core/dom/Node.h
@@ -570,10 +570,10 @@
 
     void reattach(const AttachContext& = AttachContext());
     void lazyReattachIfAttached();
-    ContainerNode* parentNodeForRenderingAndStyle();
 
     // Wrapper for nodes that don't have a renderer, but still cache the style (like HTMLOptionElement).
     RenderStyle* renderStyle() const;
+    RenderStyle* parentRenderStyle() const;
 
     RenderStyle* computedStyle(PseudoId pseudoElementSpecifier = NOPSEUDO) { return virtualComputedStyle(pseudoElementSpecifier); }
 
@@ -931,9 +931,7 @@
     lazyAttach(shouldSetAttached);
 }
 
-// Need a template since ElementShadow is not a Node, but has the style recalc methods.
-template<class T>
-inline bool shouldRecalcStyle(Node::StyleChange change, const T* node)
+inline bool shouldRecalcStyle(Node::StyleChange change, const Node* node)
 {
     return change >= Node::Inherit || node->childNeedsStyleRecalc() || node->needsStyleRecalc();
 }
diff --git a/Source/core/dom/NodeRenderStyle.h b/Source/core/dom/NodeRenderStyle.h
index 2ab78c3..a9487ab 100644
--- a/Source/core/dom/NodeRenderStyle.h
+++ b/Source/core/dom/NodeRenderStyle.h
@@ -26,6 +26,7 @@
 #define NodeRenderStyle_h
 
 #include "core/dom/Node.h"
+#include "core/dom/NodeRenderingTraversal.h"
 #include "core/rendering/RenderObject.h"
 #include "core/rendering/style/RenderStyle.h"
 
@@ -40,5 +41,11 @@
     return nonRendererStyle();
 }
 
+inline RenderStyle* Node::parentRenderStyle() const
+{
+    ContainerNode* parent = NodeRenderingTraversal::parent(this);
+    return parent ? parent->renderStyle() : 0;
+}
+
 }
 #endif
diff --git a/Source/core/dom/NodeRenderingContext.cpp b/Source/core/dom/NodeRenderingContext.cpp
index f403465..2677c13 100644
--- a/Source/core/dom/NodeRenderingContext.cpp
+++ b/Source/core/dom/NodeRenderingContext.cpp
@@ -27,13 +27,12 @@
 #include "core/dom/NodeRenderingContext.h"
 
 #include "RuntimeEnabledFeatures.h"
-#include "SVGNames.h"
 #include "core/css/resolver/StyleResolver.h"
 #include "core/dom/ContainerNode.h"
 #include "core/dom/FullscreenController.h"
 #include "core/dom/Node.h"
 #include "core/dom/Text.h"
-#include "core/html/shadow/HTMLShadowElement.h"
+#include "core/dom/shadow/InsertionPoint.h"
 #include "core/rendering/FlowThreadController.h"
 #include "core/rendering/RenderFullScreen.h"
 #include "core/rendering/RenderNamedFlowThread.h"
@@ -43,33 +42,15 @@
 
 namespace WebCore {
 
-NodeRenderingContext::NodeRenderingContext(Node* node)
-    : m_node(node)
-    , m_parentFlowRenderer(0)
-{
-    m_renderingParent = NodeRenderingTraversal::parent(node, &m_parentDetails);
-}
-
 NodeRenderingContext::NodeRenderingContext(Node* node, RenderStyle* style)
     : m_node(node)
     , m_renderingParent(0)
     , m_style(style)
     , m_parentFlowRenderer(0)
 {
-}
-
-NodeRenderingContext::NodeRenderingContext(Node* node, const Node::AttachContext& context)
-: m_node(node)
-, m_style(context.resolvedStyle)
-, m_parentFlowRenderer(0)
-{
     m_renderingParent = NodeRenderingTraversal::parent(node, &m_parentDetails);
 }
 
-NodeRenderingContext::~NodeRenderingContext()
-{
-}
-
 static bool isRendererReparented(const RenderObject* renderer)
 {
     if (!renderer->node()->isElementNode())
@@ -175,7 +156,6 @@
 {
     if (!m_renderingParent)
         return false;
-
     RenderObject* parentRenderer = this->parentRenderer();
     if (!parentRenderer)
         return false;
@@ -224,16 +204,6 @@
     flowThreadController->registerNamedFlowContentNode(m_node, m_parentFlowRenderer);
 }
 
-bool NodeRenderingContext::isOnEncapsulationBoundary() const
-{
-    return isOnUpperEncapsulationBoundary() || isLowerEncapsulationBoundary(m_parentDetails.insertionPoint()) || isLowerEncapsulationBoundary(m_node->parentNode());
-}
-
-bool NodeRenderingContext::isOnUpperEncapsulationBoundary() const
-{
-    return m_node->parentNode() && m_node->parentNode()->isShadowRoot();
-}
-
 void NodeRenderingContext::createRendererForElementIfNeeded()
 {
     ASSERT(!m_node->renderer());
@@ -254,14 +224,12 @@
     if (!element->rendererIsNeeded(*this))
         return;
 
-    RenderObject* parentRenderer = this->parentRenderer();
-    RenderObject* nextRenderer = this->nextRenderer();
-
-    Document* document = element->document();
     RenderObject* newRenderer = element->createRenderer(m_style.get());
     if (!newRenderer)
         return;
 
+    RenderObject* parentRenderer = this->parentRenderer();
+
     if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) {
         newRenderer->destroy();
         return;
@@ -271,11 +239,12 @@
     // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
     newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
 
+    RenderObject* nextRenderer = this->nextRenderer();
     element->setRenderer(newRenderer);
     newRenderer->setAnimatableStyle(m_style.release()); // setAnimatableStyle() can depend on renderer() already being set.
 
     if (FullscreenController::isActiveFullScreenElement(element)) {
-        newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer, document);
+        newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer, element->document());
         if (!newRenderer)
             return;
     }
@@ -294,19 +263,16 @@
         return;
 
     RenderObject* parentRenderer = this->parentRenderer();
-    ASSERT(parentRenderer);
-    Document* document = textNode->document();
 
     if (resetStyleInheritance())
-        m_style = document->styleResolver()->defaultStyleForElement();
+        m_style = textNode->document()->styleResolver()->defaultStyleForElement();
     else
         m_style = parentRenderer->style();
 
     if (!textNode->textRendererIsNeeded(*this))
         return;
+
     RenderText* newRenderer = textNode->createTextRenderer(m_style.get());
-    if (!newRenderer)
-        return;
     if (!parentRenderer->isChildAllowed(newRenderer, m_style.get())) {
         newRenderer->destroy();
         return;
diff --git a/Source/core/dom/NodeRenderingContext.h b/Source/core/dom/NodeRenderingContext.h
index 3bacbf4..9e448a8 100644
--- a/Source/core/dom/NodeRenderingContext.h
+++ b/Source/core/dom/NodeRenderingContext.h
@@ -44,10 +44,7 @@
 
 class NodeRenderingContext {
 public:
-    explicit NodeRenderingContext(Node*);
-    NodeRenderingContext(Node*, RenderStyle*);
-    NodeRenderingContext(Node*, const Node::AttachContext&);
-    ~NodeRenderingContext();
+    NodeRenderingContext(Node*, RenderStyle* = 0);
 
     void createRendererForTextIfNeeded();
     void createRendererForElementIfNeeded();
@@ -62,9 +59,6 @@
 
     const RenderStyle* style() const;
 
-    bool isOnUpperEncapsulationBoundary() const;
-    bool isOnEncapsulationBoundary() const;
-
 private:
     bool shouldCreateRenderer() const;
     void moveToFlowThreadIfNeeded();
diff --git a/Source/core/dom/Position.cpp b/Source/core/dom/Position.cpp
index b1d7f07..c917fb5 100644
--- a/Source/core/dom/Position.cpp
+++ b/Source/core/dom/Position.cpp
@@ -852,6 +852,7 @@
     return node->parentNode();
 }
 
+#if ENABLE(USERSELECT_ALL)
 bool Position::nodeIsUserSelectAll(const Node* node)
 {
     return node && node->renderer() && node->renderer()->style()->userSelect() == SELECT_ALL;
@@ -878,6 +879,7 @@
     }
     return candidateRoot;
 }
+#endif
 
 bool Position::isCandidate() const
 {
diff --git a/Source/core/dom/Position.h b/Source/core/dom/Position.h
index 5d4fd32..c3ad406 100644
--- a/Source/core/dom/Position.h
+++ b/Source/core/dom/Position.h
@@ -189,8 +189,10 @@
 
     static bool hasRenderedNonAnonymousDescendantsWithHeight(RenderObject*);
     static bool nodeIsUserSelectNone(Node*);
+#if ENABLE(USERSELECT_ALL)
     static bool nodeIsUserSelectAll(const Node*);
     static Node* rootUserSelectAllForNode(Node*);
+#endif
     static ContainerNode* findParent(const Node*);
     
     void debugPosition(const char* msg = "") const;
diff --git a/Source/core/dom/Text.cpp b/Source/core/dom/Text.cpp
index 9886613..826f282 100644
--- a/Source/core/dom/Text.cpp
+++ b/Source/core/dom/Text.cpp
@@ -207,13 +207,11 @@
     if (context.style()->display() == NONE)
         return false;
 
-    bool onlyWS = containsOnlyWhitespace();
-    if (!onlyWS)
+    if (!containsOnlyWhitespace())
         return true;
 
     RenderObject* parent = context.parentRenderer();
-    if (parent->isTable() || parent->isTableRow() || parent->isTableSection() || parent->isRenderTableCol() || parent->isFrameSet()
-        || parent->isFlexibleBox() || parent->isRenderGrid())
+    if (!parent->canHaveWhitespaceChildren())
         return false;
     
     if (context.style()->preserveNewline()) // pre/pre-wrap/pre-line always make renderers.
@@ -230,17 +228,19 @@
     } else {
         if (parent->isRenderBlock() && !parent->childrenInline() && (!prev || !prev->isInline()))
             return false;
-        
+
+        // Avoiding creation of a Renderer for the text node is a non-essential memory optimization.
+        // So to avoid blowing up on very wide DOMs, we limit the number of siblings to visit.
+        unsigned maxSiblingsToVisit = 50;
+
         RenderObject* first = parent->firstChild();
-        while (first && first->isFloatingOrOutOfFlowPositioned())
+        while (first && first->isFloatingOrOutOfFlowPositioned() && maxSiblingsToVisit--)
             first = first->nextSibling();
-        RenderObject* next = context.nextRenderer();
-        if (!first || next == first)
+        if (!first || context.nextRenderer() == first)
             // Whitespace at the start of a block just goes away.  Don't even
             // make a render object for this text.
             return false;
     }
-    
     return true;
 }
 
@@ -298,10 +298,7 @@
 bool Text::needsWhitespaceRenderer()
 {
     ASSERT(!renderer());
-    ContainerNode* parent = parentNodeForRenderingAndStyle();
-    if (!parent)
-        return false;
-    if (RenderStyle* style = parent->renderStyle())
+    if (RenderStyle* style = parentRenderStyle())
         return style->preserveNewline();
     return false;
 }
diff --git a/Source/core/dom/TextLinkColors.cpp b/Source/core/dom/TextLinkColors.cpp
index f6e1fd8..59589a5 100644
--- a/Source/core/dom/TextLinkColors.cpp
+++ b/Source/core/dom/TextLinkColors.cpp
@@ -44,17 +44,17 @@
 
 void TextLinkColors::resetLinkColor()
 {
-    m_linkColor = Color(0, 0, 238);
+    m_linkColor = StyleColor(0, 0, 238);
 }
 
 void TextLinkColors::resetVisitedLinkColor()
 {
-    m_visitedLinkColor = Color(85, 26, 139);
+    m_visitedLinkColor = StyleColor(85, 26, 139);
 }
 
 void TextLinkColors::resetActiveLinkColor()
 {
-    m_activeLinkColor.setNamedColor("red");
+    m_activeLinkColor = StyleColor(255, 0, 0);
 }
 
 static Color colorForCSSValue(CSSValueID cssValueId)
@@ -94,10 +94,10 @@
     return RenderTheme::defaultTheme()->systemColor(cssValueId);
 }
 
-Color TextLinkColors::colorFromPrimitiveValue(const CSSPrimitiveValue* value, Color currentColor, bool forVisitedLink) const
+StyleColor TextLinkColors::colorFromPrimitiveValue(const CSSPrimitiveValue* value, bool forVisitedLink) const
 {
     if (value->isRGBColor())
-        return Color(value->getRGBA32Value());
+        return StyleColor(value->getRGBA32Value());
 
     CSSValueID valueID = value->getValueID();
     switch (valueID) {
@@ -112,7 +112,7 @@
     case CSSValueWebkitFocusRingColor:
         return RenderTheme::focusRingColor();
     case CSSValueCurrentcolor:
-        return currentColor;
+        return StyleColor::currentColor();
     default:
         return colorForCSSValue(valueID);
     }
diff --git a/Source/core/dom/TextLinkColors.h b/Source/core/dom/TextLinkColors.h
index 6d2728c..fb223e8 100644
--- a/Source/core/dom/TextLinkColors.h
+++ b/Source/core/dom/TextLinkColors.h
@@ -28,7 +28,7 @@
 #ifndef TextLinkColors_h
 #define TextLinkColors_h
 
-#include "core/platform/graphics/Color.h"
+#include "core/css/StyleColor.h"
 #include "wtf/Noncopyable.h"
 
 namespace WebCore {
@@ -41,25 +41,25 @@
 public:
     TextLinkColors();
 
-    void setTextColor(const Color& color) { m_textColor = color; }
-    Color textColor() const { return m_textColor; }
+    void setTextColor(const StyleColor& color) { m_textColor = color; }
+    StyleColor textColor() const { return m_textColor; }
 
-    const Color& linkColor() const { return m_linkColor; }
-    const Color& visitedLinkColor() const { return m_visitedLinkColor; }
-    const Color& activeLinkColor() const { return m_activeLinkColor; }
+    const StyleColor& linkColor() const { return m_linkColor; }
+    const StyleColor& visitedLinkColor() const { return m_visitedLinkColor; }
+    const StyleColor& activeLinkColor() const { return m_activeLinkColor; }
     void setLinkColor(const Color& color) { m_linkColor = color; }
     void setVisitedLinkColor(const Color& color) { m_visitedLinkColor = color; }
     void setActiveLinkColor(const Color& color) { m_activeLinkColor = color; }
     void resetLinkColor();
     void resetVisitedLinkColor();
     void resetActiveLinkColor();
-    Color colorFromPrimitiveValue(const CSSPrimitiveValue*, Color currentColor, bool forVisitedLink = false) const;
+    StyleColor colorFromPrimitiveValue(const CSSPrimitiveValue*, bool forVisitedLink = false) const;
 private:
 
-    Color m_textColor;
-    Color m_linkColor;
-    Color m_visitedLinkColor;
-    Color m_activeLinkColor;
+    StyleColor m_textColor;
+    StyleColor m_linkColor;
+    StyleColor m_visitedLinkColor;
+    StyleColor m_activeLinkColor;
 };
 
 }
diff --git a/Source/core/dom/TouchEvent.idl b/Source/core/dom/TouchEvent.idl
index b054441..c3b7a81 100644
--- a/Source/core/dom/TouchEvent.idl
+++ b/Source/core/dom/TouchEvent.idl
@@ -22,9 +22,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-[
-    AllowJSCreationOnlyIfFeatureEnabled
-] interface TouchEvent : UIEvent {
+interface TouchEvent : UIEvent {
     readonly attribute TouchList touches;
     readonly attribute TouchList targetTouches;
     readonly attribute TouchList changedTouches;
diff --git a/Source/core/dom/TreeScope.cpp b/Source/core/dom/TreeScope.cpp
index a5f47dd..6afde25 100644
--- a/Source/core/dom/TreeScope.cpp
+++ b/Source/core/dom/TreeScope.cpp
@@ -178,7 +178,7 @@
 
 void TreeScope::addImageMap(HTMLMapElement* imageMap)
 {
-    AtomicStringImpl* name = imageMap->getName().impl();
+    StringImpl* name = imageMap->getName().impl();
     if (!name)
         return;
     if (!m_imageMapsByName)
@@ -190,7 +190,7 @@
 {
     if (!m_imageMapsByName)
         return;
-    AtomicStringImpl* name = imageMap->getName().impl();
+    StringImpl* name = imageMap->getName().impl();
     if (!name)
         return;
     m_imageMapsByName->remove(name, imageMap);
diff --git a/Source/core/dom/TreeScope.h b/Source/core/dom/TreeScope.h
index 6f4b3ee..54144ab 100644
--- a/Source/core/dom/TreeScope.h
+++ b/Source/core/dom/TreeScope.h
@@ -56,7 +56,7 @@
 
     Element* adjustedFocusedElement();
     Element* getElementById(const AtomicString&) const;
-    bool hasElementWithId(AtomicStringImpl* id) const;
+    bool hasElementWithId(StringImpl* id) const;
     bool containsMultipleElementsWithId(const AtomicString& id) const;
     void addElementById(const AtomicString& elementId, Element*);
     void removeElementById(const AtomicString& elementId, Element*);
@@ -174,7 +174,7 @@
     mutable RefPtr<DOMSelection> m_selection;
 };
 
-inline bool TreeScope::hasElementWithId(AtomicStringImpl* id) const
+inline bool TreeScope::hasElementWithId(StringImpl* id) const
 {
     ASSERT(id);
     return m_elementsById && m_elementsById->contains(id);
diff --git a/Source/core/dom/shadow/ComposedShadowTreeWalker.cpp b/Source/core/dom/shadow/ComposedShadowTreeWalker.cpp
index e647b33..84b2fd2 100644
--- a/Source/core/dom/shadow/ComposedShadowTreeWalker.cpp
+++ b/Source/core/dom/shadow/ComposedShadowTreeWalker.cpp
@@ -50,7 +50,7 @@
         return false;
 
     if (ShadowRoot* shadowRoot = parent->isShadowRoot() ? toShadowRoot(parent) : 0)
-        return ScopeContentDistribution::assignedTo(shadowRoot);
+        return shadowRoot->insertionPoint();
 
     if (parent->isElementNode() && toElement(parent)->shadow())
         return true;
@@ -185,7 +185,7 @@
     if (node->parentNode() && node->parentNode()->isShadowRoot()) {
         ShadowRoot* parentShadowRoot = toShadowRoot(node->parentNode());
         if (!parentShadowRoot->isYoungest()) {
-            InsertionPoint* assignedInsertionPoint = ScopeContentDistribution::assignedTo(parentShadowRoot);
+            InsertionPoint* assignedInsertionPoint = parentShadowRoot->insertionPoint();
             ASSERT(assignedInsertionPoint);
             return traverseSiblingInCurrentTree(assignedInsertionPoint, direction);
         }
@@ -254,7 +254,7 @@
 Node* ComposedShadowTreeWalker::traverseParentBackToYoungerShadowRootOrHost(const ShadowRoot* shadowRoot, ParentTraversalDetails* details) const
 {
     ASSERT(shadowRoot);
-    ASSERT(!ScopeContentDistribution::assignedTo(shadowRoot));
+    ASSERT(!shadowRoot->insertionPoint());
 
     if (shadowRoot->isYoungest()) {
         if (canCrossUpperBoundary()) {
diff --git a/Source/core/dom/shadow/ContentDistributor.cpp b/Source/core/dom/shadow/ContentDistributor.cpp
index 5b3a68b..e7ae775 100644
--- a/Source/core/dom/shadow/ContentDistributor.cpp
+++ b/Source/core/dom/shadow/ContentDistributor.cpp
@@ -99,7 +99,7 @@
     m_insertionPointListIsValid = true;
     ASSERT(m_insertionPointList.isEmpty());
 
-    if (!hasInsertionPoint(shadowRoot))
+    if (!shadowRoot->containsInsertionPoints())
         return m_insertionPointList;
 
     for (Element* element = ElementTraversal::firstWithin(shadowRoot); element; element = ElementTraversal::next(element, shadowRoot)) {
@@ -140,43 +140,6 @@
     invalidateInsertionPointList();
 }
 
-bool ScopeContentDistribution::hasShadowElement(const ShadowRoot* holder)
-{
-    if (!holder->scopeDistribution())
-        return false;
-
-    return holder->scopeDistribution()->hasShadowElementChildren();
-}
-
-bool ScopeContentDistribution::hasContentElement(const ShadowRoot* holder)
-{
-    if (!holder->scopeDistribution())
-        return false;
-
-    return holder->scopeDistribution()->hasContentElementChildren();
-}
-
-unsigned ScopeContentDistribution::countElementShadow(const ShadowRoot* holder)
-{
-    if (!holder->scopeDistribution())
-        return 0;
-
-    return holder->scopeDistribution()->numberOfElementShadowChildren();
-}
-
-bool ScopeContentDistribution::hasInsertionPoint(const ShadowRoot* holder)
-{
-    return hasShadowElement(holder) || hasContentElement(holder);
-}
-
-InsertionPoint* ScopeContentDistribution::assignedTo(const ShadowRoot* holder)
-{
-    if (!holder->scopeDistribution())
-        return 0;
-
-    return holder->scopeDistribution()->insertionPointAssignedTo();
-}
-
 ContentDistributor::ContentDistributor()
     : m_needsSelectFeatureSet(false)
     , m_validity(Undetermined)
@@ -395,14 +358,14 @@
 
 void ContentDistributor::collectSelectFeatureSetFrom(ShadowRoot* root)
 {
-    if (ScopeContentDistribution::hasElementShadow(root)) {
+    if (root->containsShadowRoots()) {
         for (Element* element = ElementTraversal::firstWithin(root); element; element = ElementTraversal::next(element)) {
             if (ElementShadow* elementShadow = element->shadow())
                 m_selectFeatures.add(elementShadow->distributor().ensureSelectFeatureSet(elementShadow));
         }
     }
 
-    if (ScopeContentDistribution::hasContentElement(root)) {
+    if (root->containsContentElements()) {
         for (Element* element = ElementTraversal::firstWithin(root); element; element = ElementTraversal::next(element)) {
             if (!isHTMLContentElement(element))
                 continue;
diff --git a/Source/core/dom/shadow/ContentDistributor.h b/Source/core/dom/shadow/ContentDistributor.h
index 442dc41..ba8707f 100644
--- a/Source/core/dom/shadow/ContentDistributor.h
+++ b/Source/core/dom/shadow/ContentDistributor.h
@@ -92,13 +92,6 @@
 
     bool isUsedForRendering() const;
 
-    static bool hasShadowElement(const ShadowRoot*);
-    static bool hasContentElement(const ShadowRoot*);
-    static bool hasInsertionPoint(const ShadowRoot*);
-    static bool hasElementShadow(const ShadowRoot* holder) { return countElementShadow(holder); }
-    static unsigned countElementShadow(const ShadowRoot*);
-    static InsertionPoint* assignedTo(const ShadowRoot*);
-
 private:
     InsertionPoint* m_insertionPointAssignedTo;
     unsigned m_numberOfShadowElementChildren;
diff --git a/Source/core/dom/shadow/ElementShadow.cpp b/Source/core/dom/shadow/ElementShadow.cpp
index b767737..e1983e5 100644
--- a/Source/core/dom/shadow/ElementShadow.cpp
+++ b/Source/core/dom/shadow/ElementShadow.cpp
@@ -96,32 +96,6 @@
     }
 }
 
-bool ElementShadow::childNeedsStyleRecalc() const
-{
-    ASSERT(youngestShadowRoot());
-    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot())
-        if (root->childNeedsStyleRecalc())
-            return true;
-
-    return false;
-}
-
-bool ElementShadow::needsStyleRecalc() const
-{
-    ASSERT(youngestShadowRoot());
-    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot())
-        if (root->needsStyleRecalc())
-            return true;
-
-    return false;
-}
-
-void ElementShadow::recalcStyle(Node::StyleChange change)
-{
-    for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot())
-        root->recalcStyle(change);
-}
-
 void ElementShadow::removeAllEventListeners()
 {
     for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) {
diff --git a/Source/core/dom/shadow/ElementShadow.h b/Source/core/dom/shadow/ElementShadow.h
index a1f645d..084d7c1 100644
--- a/Source/core/dom/shadow/ElementShadow.h
+++ b/Source/core/dom/shadow/ElementShadow.h
@@ -59,9 +59,6 @@
     void attach(const Node::AttachContext&);
     void detach(const Node::AttachContext&);
 
-    bool childNeedsStyleRecalc() const;
-    bool needsStyleRecalc() const;
-    void recalcStyle(Node::StyleChange);
     void removeAllEventListeners();
 
     void invalidateDistribution() { m_distributor.invalidateDistribution(host()); }
diff --git a/Source/core/dom/shadow/InsertionPoint.cpp b/Source/core/dom/shadow/InsertionPoint.cpp
index e0ef0b2..0fe52d9 100644
--- a/Source/core/dom/shadow/InsertionPoint.cpp
+++ b/Source/core/dom/shadow/InsertionPoint.cpp
@@ -90,11 +90,6 @@
     return isActive() && !hasDistribution();
 }
 
-bool InsertionPoint::isShadowBoundary() const
-{
-    return treeScope()->rootNode()->isShadowRoot() && isActive();
-}
-
 bool InsertionPoint::isActive() const
 {
     if (!containingShadowRoot())
@@ -124,7 +119,7 @@
 
 bool InsertionPoint::rendererIsNeeded(const NodeRenderingContext& context)
 {
-    return !isShadowBoundary() && HTMLElement::rendererIsNeeded(context);
+    return !isActive() && HTMLElement::rendererIsNeeded(context);
 }
 
 void InsertionPoint::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
@@ -201,7 +196,7 @@
 
 bool InsertionPoint::contains(const Node* node) const
 {
-    return m_distribution.contains(const_cast<Node*>(node)) || (node->isShadowRoot() && ScopeContentDistribution::assignedTo(toShadowRoot(node)) == this);
+    return m_distribution.contains(const_cast<Node*>(node)) || (node->isShadowRoot() && toShadowRoot(node)->insertionPoint() == this);
 }
 
 const CSSSelectorList& InsertionPoint::emptySelectorList()
@@ -228,7 +223,7 @@
         }
 
         if (Node* parent = parentNodeForDistribution(current)) {
-            if (InsertionPoint* insertedTo = parent->isShadowRoot() ? ScopeContentDistribution::assignedTo(toShadowRoot(parent)) : 0) {
+            if (InsertionPoint* insertedTo = parent->isShadowRoot() ? toShadowRoot(parent)->insertionPoint() : 0) {
                 current = insertedTo;
                 insertionPoint = insertedTo;
                 continue;
@@ -255,7 +250,7 @@
             }
         }
         if (Node* parent = parentNodeForDistribution(current)) {
-            if (InsertionPoint* insertedTo = parent->isShadowRoot() ? ScopeContentDistribution::assignedTo(toShadowRoot(parent)) : 0) {
+            if (InsertionPoint* insertedTo = parent->isShadowRoot() ? toShadowRoot(parent)->insertionPoint() : 0) {
                 current = insertedTo;
                 results.append(insertedTo);
                 continue;
diff --git a/Source/core/dom/shadow/InsertionPoint.h b/Source/core/dom/shadow/InsertionPoint.h
index 44cd1f9..0f1d486 100644
--- a/Source/core/dom/shadow/InsertionPoint.h
+++ b/Source/core/dom/shadow/InsertionPoint.h
@@ -57,7 +57,6 @@
     bool hasDistribution() const { return !m_distribution.isEmpty(); }
     void setDistribution(ContentDistribution& distribution) { m_distribution.swap(distribution); }
     void clearDistribution() { m_distribution.clear(); }
-    bool isShadowBoundary() const;
     bool isActive() const;
 
     PassRefPtr<NodeList> getDistributedNodes() const;
@@ -118,13 +117,6 @@
     return node->isInsertionPoint() && toInsertionPoint(node)->isActive();
 }
 
-inline bool isLowerEncapsulationBoundary(Node* node)
-{
-    if (!node || !node->isInsertionPoint())
-        return false;
-    return toInsertionPoint(node)->isShadowBoundary();
-}
-
 inline Node* parentNodeForDistribution(const Node* node)
 {
     ASSERT(node);
diff --git a/Source/core/dom/shadow/SelectRuleFeatureSet.h b/Source/core/dom/shadow/SelectRuleFeatureSet.h
index 7292b12..429d277 100644
--- a/Source/core/dom/shadow/SelectRuleFeatureSet.h
+++ b/Source/core/dom/shadow/SelectRuleFeatureSet.h
@@ -68,19 +68,19 @@
 inline bool SelectRuleFeatureSet::hasSelectorForId(const AtomicString& idValue) const
 {
     ASSERT(!idValue.isEmpty());
-    return m_cssRuleFeatureSet.idsInRules.contains(idValue.impl());
+    return m_cssRuleFeatureSet.idsInRules.contains(idValue);
 }
 
 inline bool SelectRuleFeatureSet::hasSelectorForClass(const AtomicString& classValue) const
 {
     ASSERT(!classValue.isEmpty());
-    return m_cssRuleFeatureSet.classesInRules.contains(classValue.impl());
+    return m_cssRuleFeatureSet.classesInRules.contains(classValue);
 }
 
 inline bool SelectRuleFeatureSet::hasSelectorForAttribute(const AtomicString& attributeName) const
 {
     ASSERT(!attributeName.isEmpty());
-    return m_cssRuleFeatureSet.attrsInRules.contains(attributeName.impl());
+    return m_cssRuleFeatureSet.attrsInRules.contains(attributeName);
 }
 
 }
diff --git a/Source/core/dom/shadow/ShadowRoot.cpp b/Source/core/dom/shadow/ShadowRoot.cpp
index 2fc2f26..a897eb9 100644
--- a/Source/core/dom/shadow/ShadowRoot.cpp
+++ b/Source/core/dom/shadow/ShadowRoot.cpp
@@ -192,7 +192,7 @@
 bool ShadowRoot::isActive() const
 {
     for (ShadowRoot* shadowRoot = youngerShadowRoot(); shadowRoot; shadowRoot = shadowRoot->youngerShadowRoot())
-        if (!ScopeContentDistribution::hasShadowElement(shadowRoot))
+        if (!shadowRoot->containsShadowElements())
             return false;
     return true;
 }
@@ -302,4 +302,24 @@
     return m_scopeDistribution.get();
 }
 
+bool ShadowRoot::containsShadowElements() const
+{
+    return m_scopeDistribution ? m_scopeDistribution->hasShadowElementChildren() : 0;
+}
+
+bool ShadowRoot::containsContentElements() const
+{
+    return m_scopeDistribution ? m_scopeDistribution->hasContentElementChildren() : 0;
+}
+
+bool ShadowRoot::containsShadowRoots() const
+{
+    return m_scopeDistribution ? m_scopeDistribution->numberOfElementShadowChildren() : 0;
+}
+
+InsertionPoint* ShadowRoot::insertionPoint() const
+{
+    return m_scopeDistribution ? m_scopeDistribution->insertionPointAssignedTo() : 0;
+}
+
 }
diff --git a/Source/core/dom/shadow/ShadowRoot.h b/Source/core/dom/shadow/ShadowRoot.h
index 4e9c5e5..3759557 100644
--- a/Source/core/dom/shadow/ShadowRoot.h
+++ b/Source/core/dom/shadow/ShadowRoot.h
@@ -38,6 +38,7 @@
 namespace WebCore {
 
 class ElementShadow;
+class InsertionPoint;
 class ScopeContentDistribution;
 
 class ShadowRoot FINAL : public DocumentFragment, public TreeScope, public DoublyLinkedListNode<ShadowRoot> {
@@ -93,6 +94,12 @@
     const ScopeContentDistribution* scopeDistribution() const { return m_scopeDistribution.get(); }
     ScopeContentDistribution* ensureScopeDistribution();
 
+    bool containsShadowElements() const;
+    bool containsContentElements() const;
+    bool containsInsertionPoints() const { return containsShadowElements() || containsContentElements(); }
+    bool containsShadowRoots() const;
+    InsertionPoint* insertionPoint() const;
+
     ShadowRootType type() const { return static_cast<ShadowRootType>(m_type); }
 
     PassRefPtr<Node> cloneNode(bool, ExceptionCode&);