changeset 9614:4166cbca577f

8149537: JavaFX WebView performance regression when inserting html via javascript Reviewed-by: mbilla, kcr
author arajkumar
date Wed, 09 Mar 2016 18:58:20 -0800
parents b16479e74519
children 53252f651d0d
files modules/web/src/main/native/Source/WebCore/TargetJava.pri modules/web/src/main/native/Source/WebCore/css/MediaQueryMatcher.cpp modules/web/src/main/native/Source/WebCore/css/SVGCSSStyleSelector.cpp modules/web/src/main/native/Source/WebCore/css/StyleMedia.cpp modules/web/src/main/native/Source/WebCore/css/StyleResolver.cpp modules/web/src/main/native/Source/WebCore/css/StyleResolver.h modules/web/src/main/native/Source/WebCore/dom/Element.cpp modules/web/src/main/native/Source/WebCore/dom/Element.h modules/web/src/main/native/Source/WebCore/dom/NodeRenderStyle.h modules/web/src/main/native/Source/WebCore/dom/NodeRenderingTraversal.cpp modules/web/src/main/native/Source/WebCore/dom/NodeRenderingTraversal.h modules/web/src/main/native/Source/WebCore/dom/PseudoElement.cpp modules/web/src/main/native/Source/WebCore/dom/PseudoElement.h modules/web/src/main/native/Source/WebCore/html/HTMLOptGroupElement.cpp modules/web/src/main/native/Source/WebCore/html/HTMLOptGroupElement.h modules/web/src/main/native/Source/WebCore/html/HTMLOptionElement.cpp modules/web/src/main/native/Source/WebCore/html/HTMLOptionElement.h modules/web/src/main/native/Source/WebCore/html/HTMLTitleElement.cpp modules/web/src/main/native/Source/WebCore/html/shadow/TextControlInnerElements.cpp modules/web/src/main/native/Source/WebCore/html/shadow/TextControlInnerElements.h modules/web/src/main/native/Source/WebCore/rendering/RenderNamedFlowFragment.cpp modules/web/src/main/native/Source/WebCore/rendering/RenderNamedFlowFragment.h modules/web/src/main/native/Source/WebCore/style/StyleResolveTree.cpp modules/web/src/main/native/Source/WebCore/svg/SVGElement.cpp modules/web/src/main/native/Source/WebCore/svg/SVGElement.h
diffstat 25 files changed, 427 insertions(+), 377 deletions(-) [+]
line wrap: on
line diff
--- a/modules/web/src/main/native/Source/WebCore/TargetJava.pri	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/TargetJava.pri	Wed Mar 09 18:58:20 2016 -0800
@@ -224,14 +224,14 @@
     }
 
     linux-*|solaris-g++* {
-        QMAKE_LFLAGS += -Xlinker -version-script=$$PWD/mapfile-vers
+        QMAKE_LFLAGS += -Xlinker -version-script=$$PWD/mapfile-vers -Xlinker --no-undefined
 
-        # just for build debug: force verboce output from linker 
+        # just for build debug: force verboce output from linker
         QMAKE_LFLAGS +=  -Wl,--verbose
 
         # statically link with icu libraries in order to avoid version conflict
         QMAKE_LFLAGS += `pkg-config --libs-only-L icu-uc`
-        LIBS += -Wl,-Bstatic -licui18n -licuuc -licudata -Wl,-Bdynamic
+        LIBS += -Wl,-Bstatic -licui18n -licuuc -licudata -Wl,-Bdynamic -ldl
     }
     solaris-cc {
         QMAKE_LFLAGS += -M$$PWD/mapfile-vers
--- a/modules/web/src/main/native/Source/WebCore/css/MediaQueryMatcher.cpp	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/css/MediaQueryMatcher.cpp	Wed Mar 09 18:58:20 2016 -0800
@@ -28,6 +28,7 @@
 #include "MediaQueryEvaluator.h"
 #include "MediaQueryList.h"
 #include "MediaQueryListListener.h"
+#include "NodeRenderStyle.h"
 #include "StyleResolver.h"
 
 namespace WebCore {
@@ -84,7 +85,7 @@
     if (!documentElement)
         return nullptr;
 
-    RefPtr<RenderStyle> rootStyle = m_document->ensureStyleResolver().styleForElement(documentElement, 0 /*defaultParent*/, DisallowStyleSharing, MatchOnlyUserAgentRules);
+    RefPtr<RenderStyle> rootStyle = m_document->ensureStyleResolver().styleForElement(documentElement, m_document->renderStyle(), DisallowStyleSharing, MatchOnlyUserAgentRules);
 
     return std::make_unique<MediaQueryEvaluator>(mediaType(), m_document->frame(), rootStyle.get());
 }
--- a/modules/web/src/main/native/Source/WebCore/css/SVGCSSStyleSelector.cpp	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/css/SVGCSSStyleSelector.cpp	Wed Mar 09 18:58:20 2016 -0800
@@ -110,8 +110,8 @@
     const State& state = m_state;
     SVGRenderStyle& svgStyle = state.style()->accessSVGStyle();
 
-    bool isInherit = state.parentNode() && value->isInheritedValue();
-    bool isInitial = value->isInitialValue() || (!state.parentNode() && value->isInheritedValue());
+    bool isInherit = state.parentStyle() && value->isInheritedValue();
+    bool isInitial = value->isInitialValue() || (!state.parentStyle() && value->isInheritedValue());
 
     // What follows is a list that maps the CSS properties into their
     // corresponding front-end RenderStyle values. Shorthands(e.g. border,
--- a/modules/web/src/main/native/Source/WebCore/css/StyleMedia.cpp	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/css/StyleMedia.cpp	Wed Mar 09 18:58:20 2016 -0800
@@ -31,6 +31,7 @@
 #include "FrameView.h"
 #include "MediaList.h"
 #include "MediaQueryEvaluator.h"
+#include "NodeRenderStyle.h"
 #include "StyleResolver.h"
 
 namespace WebCore {
@@ -60,7 +61,7 @@
     if (!documentElement)
         return false;
 
-    RefPtr<RenderStyle> rootStyle = document->ensureStyleResolver().styleForElement(documentElement, 0 /*defaultParent*/, DisallowStyleSharing, MatchOnlyUserAgentRules);
+    RefPtr<RenderStyle> rootStyle = document->ensureStyleResolver().styleForElement(documentElement, document->renderStyle(), DisallowStyleSharing, MatchOnlyUserAgentRules);
 
     RefPtr<MediaQuerySet> media = MediaQuerySet::create();
     if (!media->parse(query))
--- a/modules/web/src/main/native/Source/WebCore/css/StyleResolver.cpp	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/css/StyleResolver.cpp	Wed Mar 09 18:58:20 2016 -0800
@@ -88,7 +88,6 @@
 #include "MediaList.h"
 #include "MediaQueryEvaluator.h"
 #include "NodeRenderStyle.h"
-#include "NodeRenderingTraversal.h"
 #include "Page.h"
 #include "PageRuleCollector.h"
 #include "Pair.h"
@@ -233,7 +232,6 @@
     m_element = nullptr;
     m_styledElement = nullptr;
     m_parentStyle = nullptr;
-    m_parentNode = nullptr;
     m_regionForStyling = nullptr;
     m_pendingImageProperties.clear();
 #if ENABLE(CSS_FILTERS)
@@ -280,7 +278,7 @@
         m_medium = std::make_unique<MediaQueryEvaluator>("all");
 
     if (root)
-        m_rootDefaultStyle = styleForElement(root, 0, DisallowStyleSharing, MatchOnlyUserAgentRules);
+        m_rootDefaultStyle = styleForElement(root, m_document.renderStyle(), DisallowStyleSharing, MatchOnlyUserAgentRules);
 
     if (m_rootDefaultStyle && view)
         m_medium = std::make_unique<MediaQueryEvaluator>(view->mediaType(), &view->frame(), m_rootDefaultStyle.get());
@@ -406,15 +404,10 @@
     m_regionForStyling = regionForStyling;
 
     if (e) {
-        m_parentNode = NodeRenderingTraversal::parent(e);
         bool resetStyleInheritance = hasShadowRootParent(*e) && toShadowRoot(e->parentNode())->resetStyleInheritance();
-        m_parentStyle = resetStyleInheritance ? 0 :
-            parentStyle ? parentStyle :
-            m_parentNode ? m_parentNode->renderStyle() : 0;
-    } else {
-        m_parentNode = 0;
+        m_parentStyle = resetStyleInheritance ? nullptr : parentStyle;
+    } else
         m_parentStyle = parentStyle;
-    }
 
     Node* docElement = e ? e->document().documentElement() : 0;
     RenderStyle* docStyle = document.renderStyle();
@@ -857,7 +850,7 @@
 
     // Start loading resources referenced by this style.
     loadPendingResources();
-
+    
     // Add all the animating properties to the keyframe.
     unsigned propertyCount = keyframe->properties().propertyCount();
     for (unsigned i = 0; i < propertyCount; ++i) {
@@ -894,7 +887,7 @@
     for (unsigned i = 0; i < keyframes.size(); ++i) {
         // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
         initElement(e);
-        m_state.initForStyleResolve(document(), e);
+        m_state.initForStyleResolve(document(), e, nullptr);
 
         const StyleKeyframe* keyframe = keyframes[i].get();
 
@@ -991,7 +984,7 @@
 
 PassRef<RenderStyle> StyleResolver::styleForPage(int pageIndex)
 {
-    m_state.initForStyleResolve(document(), document().documentElement()); // m_rootElementStyle will be set to the document style.
+    m_state.initForStyleResolve(m_document, m_document.documentElement(), m_document.renderStyle());
 
     m_state.setStyle(RenderStyle::create());
     m_state.style()->inheritFrom(m_state.rootElementStyle());
@@ -1110,7 +1103,7 @@
     return BLOCK;
 }
 
-// CSS requires text-decoration to be reset at each DOM element for tables,
+// CSS requires text-decoration to be reset at each DOM element for tables, 
 // inline blocks, inline tables, shadow DOM crossings, floating elements,
 // and absolute or relatively positioned elements.
 static bool doesNotInheritTextDecoration(const RenderStyle& style, Element* e)
@@ -1461,7 +1454,7 @@
     if (rulesToInclude & UAAndUserCSSRules) {
         // First we match rules from the user agent sheet.
         collector.matchUARules();
-
+        
         // Now we check user sheet rules.
         if (m_matchAuthorAndUserStyles)
             collector.matchUserRules(rulesToInclude & EmptyCSSRules);
@@ -1663,7 +1656,7 @@
     const MatchedPropertiesCacheItem* cacheItem = 0;
     if (cacheHash && (cacheItem = findFromMatchedPropertiesCache(cacheHash, matchResult))) {
         // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
-        // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the
+        // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the 
         // element context. This is fast and saves memory by reusing the style data structures.
         state.style()->copyNonInheritedFrom(cacheItem->renderStyle.get());
         if (state.parentStyle()->inheritedDataShared(cacheItem->parentRenderStyle.get()) && !isAtShadowBoundary(element)) {
@@ -1676,7 +1669,7 @@
             state.style()->setInsideLink(linkStatus);
             return;
         }
-        applyInheritedOnly = true;
+        applyInheritedOnly = true; 
     }
 
     // Directional properties (*-before/after) are aliases that depend on the TextDirection and WritingMode.
@@ -1740,9 +1733,9 @@
 
     // Start loading resources referenced by this style.
     loadPendingResources();
-
+    
     ASSERT(!state.fontDirty());
-
+    
     if (cacheItem || !cacheHash)
         return;
     if (!isCacheableInMatchedPropertiesCache(state.element(), state.style(), state.parentStyle()))
@@ -1753,7 +1746,7 @@
 void StyleResolver::applyPropertyToStyle(CSSPropertyID id, CSSValue* value, RenderStyle* style)
 {
     initElement(0);
-    m_state.initForStyleResolve(document(), 0, style);
+    m_state.initForStyleResolve(document(), nullptr, style);
     m_state.setStyle(*style);
     applyPropertyToCurrentStyle(id, value);
 }
@@ -2014,11 +2007,10 @@
         return applyProperty(newId, value);
     }
 
-    bool isInherit = state.parentNode() && value->isInheritedValue();
-    bool isInitial = value->isInitialValue() || (!state.parentNode() && value->isInheritedValue());
+    bool isInherit = state.parentStyle() && value->isInheritedValue();
+    bool isInitial = value->isInitialValue() || (!state.parentStyle() && value->isInheritedValue());
 
     ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
-    ASSERT(!isInherit || (state.parentNode() && state.parentStyle())); // isInherit -> (state.parentNode() && state.parentStyle())
 
     if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
         // Limit the properties that can be applied to only the ones honored by :visited.
@@ -2164,7 +2156,7 @@
                 state.style()->setContentAltText(emptyAtom);
             return;
         }
-
+        
     case CSSPropertyQuotes:
         if (isInherit) {
             state.style()->setQuotes(state.parentStyle()->quotes());
@@ -2568,7 +2560,7 @@
     // CSS Text Layout Module Level 3: Vertical writing support
     case CSSPropertyWebkitWritingMode: {
         HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode);
-
+        
         if (primitiveValue)
             setWritingMode(*primitiveValue);
 
@@ -3116,7 +3108,7 @@
 {
     if (!parentStyle)
         return;
-
+    
     if (style->effectiveZoom() == parentStyle->effectiveZoom())
         return;
 
@@ -3333,16 +3325,16 @@
     RenderStyle* style = state.style();
     RenderStyle* rootStyle = state.rootElementStyle();
     ASSERT(outOperations.isEmpty());
-
+    
     if (!inValue)
         return false;
-
+    
     if (inValue->isPrimitiveValue()) {
         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(inValue);
         if (primitiveValue->getValueID() == CSSValueNone)
             return true;
     }
-
+    
     if (!inValue->isValueList())
         return false;
 
--- a/modules/web/src/main/native/Source/WebCore/css/StyleResolver.h	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/css/StyleResolver.h	Wed Mar 09 18:58:20 2016 -0800
@@ -143,8 +143,8 @@
     void pushParentElement(Element*);
     void popParentElement(Element*);
 
-    PassRef<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, StyleSharingBehavior = AllowStyleSharing,
-        RuleMatchingBehavior = MatchAllRules, RenderRegion* regionForStyling = 0);
+    PassRef<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle, StyleSharingBehavior = AllowStyleSharing,
+        RuleMatchingBehavior = MatchAllRules, RenderRegion* regionForStyling = nullptr);
 
     void keyframeStylesForAnimation(Element*, const RenderStyle*, KeyframeList&);
 
@@ -158,7 +158,6 @@
     RenderStyle* rootElementStyle() const { return m_state.rootElementStyle(); }
     Element* element() { return m_state.element(); }
     Document& document() { return m_document; }
-    bool hasParentNode() const { return m_state.parentNode(); }
 
     // FIXME: It could be better to call m_ruleSets.appendAuthorStyleSheets() directly after we factor StyleRsolver further.
     // https://bugs.webkit.org/show_bug.cgi?id=108890
@@ -229,7 +228,7 @@
     bool usesSiblingRules() const { return !m_ruleSets.features().siblingRules.isEmpty(); }
     bool usesFirstLineRules() const { return m_ruleSets.features().usesFirstLineRules; }
     bool usesBeforeAfterRules() const { return m_ruleSets.features().usesBeforeAfterRules; }
-
+    
     void invalidateMatchedPropertiesCache();
 
 #if ENABLE(CSS_FILTERS)
@@ -263,7 +262,7 @@
     struct MatchedProperties {
         MatchedProperties();
         ~MatchedProperties();
-
+        
         RefPtr<StyleProperties> properties;
         union {
             struct {
@@ -333,7 +332,6 @@
         State()
         : m_element(0)
         , m_styledElement(0)
-        , m_parentNode(0)
         , m_parentStyle(0)
         , m_rootElementStyle(0)
         , m_regionForStyling(0)
@@ -348,7 +346,7 @@
 
     public:
         void initElement(Element*);
-        void initForStyleResolve(Document&, Element*, RenderStyle* parentStyle = 0, RenderRegion* regionForStyling = 0);
+        void initForStyleResolve(Document&, Element*, RenderStyle* parentStyle, RenderRegion* regionForStyling = nullptr);
         void clear();
 
         Document& document() const { return m_element->document(); }
@@ -358,7 +356,6 @@
         RenderStyle* style() const { return m_style.get(); }
         PassRef<RenderStyle> takeStyle() { return m_style.releaseNonNull(); }
 
-        const ContainerNode* parentNode() const { return m_parentNode; }
         void setParentStyle(PassRef<RenderStyle> parentStyle) { m_parentStyle = std::move(parentStyle); }
         RenderStyle* parentStyle() const { return m_parentStyle.get(); }
         RenderStyle* rootElementStyle() const { return m_rootElementStyle; }
@@ -405,13 +402,12 @@
         Element* m_element;
         RefPtr<RenderStyle> m_style;
         StyledElement* m_styledElement;
-        ContainerNode* m_parentNode;
         RefPtr<RenderStyle> m_parentStyle;
         RenderStyle* m_rootElementStyle;
 
         // Required to ASSERT in applyProperties.
         RenderRegion* m_regionForStyling;
-
+        
         EInsideLink m_elementLinkState;
 
         bool m_elementAffectedByClassRules;
@@ -590,7 +586,7 @@
             return;
         m_pushedStyleResolver->popParentElement(m_parent);
     }
-
+    
 private:
     Element* m_parent;
     StyleResolver* m_pushedStyleResolver;
--- a/modules/web/src/main/native/Source/WebCore/dom/Element.cpp	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/dom/Element.cpp	Wed Mar 09 18:58:20 2016 -0800
@@ -575,7 +575,7 @@
         renderer()->theme().stateChanged(renderer(), HoverState);
 }
 
-void Element::scrollIntoView(bool alignToTop)
+void Element::scrollIntoView(bool alignToTop) 
 {
     document().updateLayoutIgnorePendingStylesheets();
 
@@ -762,7 +762,7 @@
     bool inQuirksMode = document().inQuirksMode();
     if ((!inQuirksMode && document().documentElement() == this) || (inQuirksMode && isHTMLElement() && document().body() == this))
         return adjustForAbsoluteZoom(renderView.frameView().layoutWidth(), renderView);
-
+    
     if (RenderBox* renderer = renderBox())
 #if ENABLE(SUBPIXEL_LAYOUT)
         return adjustLayoutUnitForAbsoluteZoom(renderer->pixelSnappedClientWidth(), *renderer).round();
@@ -975,7 +975,7 @@
         return document().view()->contentsToRootView(renderer->absoluteBoundingBoxRect());
     return IntRect();
 }
-
+    
 IntRect Element::screenRect() const
 {
     if (RenderObject* renderer = this->renderer())
@@ -1434,16 +1434,6 @@
         document().renderView()->flowThreadController().unregisterNamedFlowContentElement(*this);
 }
 
-PassRef<RenderStyle> Element::styleForRenderer()
-{
-    if (hasCustomStyleResolveCallbacks()) {
-        if (RefPtr<RenderStyle> style = customStyleForRenderer())
-            return style.releaseNonNull();
-    }
-
-    return document().ensureStyleResolver().styleForElement(this);
-}
-
 ShadowRoot* Element::shadowRoot() const
 {
     return hasRareData() ? elementRareData()->shadowRoot() : 0;
@@ -1458,8 +1448,6 @@
 {
     if (element.isShadowRoot())
         return true;
-    if (element.isPseudoElement() || element.beforePseudoElement() || element.afterPseudoElement())
-        return true;
     return element.isInsertionPoint() || element.shadowRoot();
 }
 
@@ -1574,7 +1562,7 @@
     RenderStyle* style = parent->renderStyle();
     // :empty selector.
     checkForEmptyStyleChange(parent, style);
-
+    
     if (!style || (parent->needsStyleRecalc() && parent->childrenAffectedByPositionalRules()))
         return;
 
@@ -1589,7 +1577,7 @@
         // This is the insert/append case.
         if (newFirstElement != elementAfterChange && elementAfterChange->renderStyle() && elementAfterChange->renderStyle()->firstChildState())
             elementAfterChange->setNeedsStyleRecalc();
-
+            
         // We also have to handle node removal.
         if (checkType == SiblingElementRemoved && newFirstElement == elementAfterChange && newFirstElement && (!newFirstElement->renderStyle() || !newFirstElement->renderStyle()->firstChildState()))
             newFirstElement->setNeedsStyleRecalc();
@@ -1603,7 +1591,7 @@
 
         if (newLastElement != elementBeforeChange && elementBeforeChange->renderStyle() && elementBeforeChange->renderStyle()->lastChildState())
             elementBeforeChange->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 ((checkType == SiblingElementRemoved || checkType == FinishedParsingChildren) && newLastElement == elementBeforeChange && newLastElement
@@ -1906,7 +1894,7 @@
 
     // If the stylesheets have already been loaded we can reliably check isFocusable.
     // If not, we continue and set the focused node on the focus controller below so
-    // that it can be updated soon after attach.
+    // that it can be updated soon after attach. 
     if (document().haveStylesheetsLoaded()) {
         document().updateLayoutIgnorePendingStylesheets();
         if (!isFocusable())
@@ -1933,7 +1921,7 @@
         ensureElementRareData().setNeedsFocusAppearanceUpdateSoonAfterAttach(true);
         return;
     }
-
+        
     cancelFocusAppearanceUpdate();
 #if PLATFORM(IOS)
     // Focusing a form element triggers animation in UIKit to scroll to the right position.
@@ -1969,14 +1957,14 @@
         Frame* frame = document().frame();
         if (!frame)
             return;
-
+        
         // When focusing an editable element in an iframe, don't reset the selection if it already contains a selection.
         if (this == frame->selection().selection().rootEditableElement())
             return;
 
         // FIXME: We should restore the previous selection if there is one.
         VisibleSelection newSelection = VisibleSelection(firstPositionInOrBeforeNode(this), DOWNSTREAM);
-
+        
         if (frame->selection().shouldChangeSelection(newSelection)) {
             frame->selection().setSelection(newSelection);
             frame->selection().revealSelection();
@@ -2298,13 +2286,11 @@
 void Element::setBeforePseudoElement(PassRefPtr<PseudoElement> element)
 {
     ensureElementRareData().setBeforePseudoElement(element);
-    resetNeedsNodeRenderingTraversalSlowPath();
 }
 
 void Element::setAfterPseudoElement(PassRefPtr<PseudoElement> element)
 {
     ensureElementRareData().setAfterPseudoElement(element);
-    resetNeedsNodeRenderingTraversalSlowPath();
 }
 
 static void disconnectPseudoElement(PseudoElement* pseudoElement)
@@ -2323,7 +2309,6 @@
         return;
     disconnectPseudoElement(elementRareData()->beforePseudoElement());
     elementRareData()->setBeforePseudoElement(nullptr);
-    resetNeedsNodeRenderingTraversalSlowPath();
 }
 
 void Element::clearAfterPseudoElement()
@@ -2332,7 +2317,6 @@
         return;
     disconnectPseudoElement(elementRareData()->afterPseudoElement());
     elementRareData()->setAfterPseudoElement(nullptr);
-    resetNeedsNodeRenderingTraversalSlowPath();
 }
 
 // ElementTraversal API
@@ -2953,7 +2937,7 @@
     ASSERT(hasCustomStyleResolveCallbacks());
 }
 
-PassRefPtr<RenderStyle> Element::customStyleForRenderer()
+PassRefPtr<RenderStyle> Element::customStyleForRenderer(RenderStyle&)
 {
     ASSERT(hasCustomStyleResolveCallbacks());
     return 0;
--- a/modules/web/src/main/native/Source/WebCore/dom/Element.h	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/dom/Element.h	Wed Mar 09 18:58:20 2016 -0800
@@ -230,7 +230,7 @@
 
     PassRefPtr<ClientRectList> getClientRects();
     PassRefPtr<ClientRect> getBoundingClientRect();
-
+    
     // Returns the absolute bounding box translated into client coordinates.
     IntRect clientRect() const;
     // Returns the absolute bounding box translated into screen coordinates.
@@ -260,7 +260,7 @@
 #endif // ENABLE(CSS_SELECTOR_JIT)
     String tagName() const { return nodeName(); }
     bool hasTagName(const QualifiedName& tagName) const { return m_tagName.matches(tagName); }
-
+    
     // A fast function for checking the local name against another atomic string.
     bool hasLocalName(const AtomicString& other) const { return m_tagName.localName() == other; }
     bool hasLocalName(const QualifiedName& other) const { return m_tagName.localName() == other.localName(); }
@@ -408,7 +408,7 @@
 
     String innerText();
     String outerText();
-
+ 
     virtual String title() const;
 
     const AtomicString& pseudo() const;
@@ -503,7 +503,7 @@
         ALLOW_KEYBOARD_INPUT = 1 << 0,
         LEGACY_MOZILLA_REQUEST = 1 << 1,
     };
-
+    
     void webkitRequestFullScreen(unsigned short flags);
     bool containsFullScreenElement() const;
     void setContainsFullScreenElement(bool);
@@ -521,16 +521,14 @@
     void setUIActions(const AtomicString&);
     const AtomicString& UIActions() const;
 #endif
-
+    
     virtual bool isSpellCheckingEnabled() const;
 
-    PassRef<RenderStyle> styleForRenderer();
-
     RenderRegion* renderRegion() const;
 
 #if ENABLE(CSS_REGIONS)
     virtual bool shouldMoveToFlowThread(const RenderStyle&) const;
-
+    
     const AtomicString& webkitRegionOverset() const;
     Vector<RefPtr<Range>> webkitGetRegionFlowRanges() const;
 #endif
@@ -558,6 +556,7 @@
     virtual void didAttachRenderers();
     virtual void willDetachRenderers();
     virtual void didDetachRenderers();
+    virtual PassRefPtr<RenderStyle> customStyleForRenderer(RenderStyle& parentStyle);
 
     void setBeforePseudoElement(PassRefPtr<PseudoElement>);
     void setAfterPseudoElement(PassRefPtr<PseudoElement>);
@@ -579,9 +578,7 @@
     virtual void childrenChanged(const ChildChange&) override;
     virtual void removeAllEventListeners() override final;
 
-    virtual PassRefPtr<RenderStyle> customStyleForRenderer();
-
-    void clearTabIndexExplicitlyIfNeeded();
+    void clearTabIndexExplicitlyIfNeeded();    
     void setTabIndexExplicitly(short);
 
     PassRefPtr<HTMLCollection> ensureCachedHTMLCollection(CollectionType);
@@ -693,7 +690,7 @@
 {
     return isElementNode() && toElement(this)->hasTagName(name);
 }
-
+    
 inline bool Node::hasLocalName(const AtomicString& name) const
 {
     return isElementNode() && toElement(this)->hasLocalName(name);
--- a/modules/web/src/main/native/Source/WebCore/dom/NodeRenderStyle.h	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/dom/NodeRenderStyle.h	Wed Mar 09 18:58:20 2016 -0800
@@ -25,6 +25,7 @@
 #ifndef NodeRenderStyle_h
 #define NodeRenderStyle_h
 
+#include "RenderElement.h"
 #include "RenderObject.h"
 #include "RenderStyle.h"
 #include "Node.h"
--- a/modules/web/src/main/native/Source/WebCore/dom/NodeRenderingTraversal.cpp	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/dom/NodeRenderingTraversal.cpp	Wed Mar 09 18:58:20 2016 -0800
@@ -29,7 +29,6 @@
 #include "NodeRenderingTraversal.h"
 
 #include "InsertionPoint.h"
-#include "PseudoElement.h"
 #include "ShadowRoot.h"
 
 namespace WebCore {
@@ -55,7 +54,7 @@
 
     if (parent->isElementNode() && toElement(parent)->shadowRoot())
         return true;
-
+    
     return false;
 }
 
@@ -121,9 +120,6 @@
 
 static ContainerNode* traverseParent(const Node* node, ShadowRootCrossing shadowRootCrossing)
 {
-    if (node->isPseudoElement())
-        return toPseudoElement(node)->hostElement();
-
     if (shadowRootCrossing == DontCrossShadowRoot  && node->isShadowRoot())
         return 0;
 
@@ -222,47 +218,25 @@
     return traverseParent(node, CrossShadowRoot);
 }
 
+Node* firstChildSlow(const Node* node)
+{
+    ASSERT(!node->isShadowRoot());
+
+    return traverseFirstChild(node, DontCrossShadowRoot);
+}
+
 Node* nextSiblingSlow(const Node* node)
 {
     ASSERT(!node->isShadowRoot());
 
-    // FIXME: Why do these functions deal with before/after when other code here doesn't?
-    Node* nextSibling = 0;
-    if (node->isBeforePseudoElement()) {
-        nextSibling = traverseParent(node, CrossShadowRoot);
-        nextSibling = traverseFirstChild(nextSibling, CrossShadowRoot);
-    } else
-        nextSibling = traverseNextSibling(node);
-
-    if (nextSibling || node->isAfterPseudoElement())
-        return nextSibling;
-
-    Node* parent = traverseParent(node, CrossShadowRoot);
-    if (parent && parent->isElementNode())
-        return toElement(parent)->afterPseudoElement();
-
-    return 0;
+    return traverseNextSibling(node);
 }
 
 Node* previousSiblingSlow(const Node* node)
 {
     ASSERT(!node->isShadowRoot());
 
-    Node* previousSibling = 0;
-    if (node->isAfterPseudoElement()) {
-        ContainerNode* parent = traverseParent(node, CrossShadowRoot);
-        previousSibling = traverseLastChild(parent, CrossShadowRoot);
-    } else
-        previousSibling = traversePreviousSibling(node);
-
-    if (previousSibling || node->isBeforePseudoElement())
-        return previousSibling;
-
-    ContainerNode* parent = traverseParent(node, CrossShadowRoot);
-    if (parent && parent->isElementNode())
-        return toElement(parent)->beforePseudoElement();
-
-    return 0;
+    return traversePreviousSibling(node);
 }
 
 Node* nextInScope(const Node* node)
--- a/modules/web/src/main/native/Source/WebCore/dom/NodeRenderingTraversal.h	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/dom/NodeRenderingTraversal.h	Wed Mar 09 18:58:20 2016 -0800
@@ -35,6 +35,7 @@
 namespace NodeRenderingTraversal {
 
 ContainerNode* parent(const Node*);
+Node* firstChild(const Node*);
 Node* nextSibling(const Node*);
 Node* previousSibling(const Node*);
 
@@ -44,11 +45,13 @@
 Node* lastChildInScope(const Node*);
 
 ContainerNode* parentSlow(const Node*);
+Node* firstChildSlow(const Node*);
 Node* nextSiblingSlow(const Node*);
 Node* previousSiblingSlow(const Node*);
 
 inline ContainerNode* parent(const Node* node)
 {
+    ASSERT(!node->isPseudoElement());
     if (node->needsNodeRenderingTraversalSlowPath())
         return parentSlow(node);
 
@@ -56,8 +59,19 @@
     return node->parentNodeGuaranteedHostFree();
 }
 
+inline Node* firstChild(const Node* node)
+{
+    ASSERT(!node->isPseudoElement());
+    if (node->needsNodeRenderingTraversalSlowPath())
+        return firstChildSlow(node);
+
+    ASSERT(nextSiblingSlow(node) == node->nextSibling());
+    return node->firstChild();
+}
+
 inline Node* nextSibling(const Node* node)
 {
+    ASSERT(!node->isPseudoElement());
     if (node->needsNodeRenderingTraversalSlowPath())
         return nextSiblingSlow(node);
 
@@ -67,6 +81,7 @@
 
 inline Node* previousSibling(const Node* node)
 {
+    ASSERT(!node->isPseudoElement());
     if (node->needsNodeRenderingTraversalSlowPath())
         return previousSiblingSlow(node);
 
--- a/modules/web/src/main/native/Source/WebCore/dom/PseudoElement.cpp	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/dom/PseudoElement.cpp	Wed Mar 09 18:58:20 2016 -0800
@@ -70,9 +70,9 @@
     InspectorInstrumentation::pseudoElementDestroyed(document().page(), this);
 }
 
-PassRefPtr<RenderStyle> PseudoElement::customStyleForRenderer()
+PassRefPtr<RenderStyle> PseudoElement::customStyleForRenderer(RenderStyle& parentStyle)
 {
-    return m_hostElement->renderer()->getCachedPseudoStyle(m_pseudoId);
+    return m_hostElement->renderer()->getCachedPseudoStyle(m_pseudoId, &parentStyle);
 }
 
 void PseudoElement::didAttachRenderers()
--- a/modules/web/src/main/native/Source/WebCore/dom/PseudoElement.h	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/dom/PseudoElement.h	Wed Mar 09 18:58:20 2016 -0800
@@ -45,7 +45,7 @@
     Element* hostElement() const { return m_hostElement; }
     void clearHostElement() { m_hostElement = nullptr; }
 
-    virtual PassRefPtr<RenderStyle> customStyleForRenderer() override;
+    virtual PassRefPtr<RenderStyle> customStyleForRenderer(RenderStyle& parentStyle) override;
     virtual void didAttachRenderers() override;
     virtual bool rendererIsNeeded(const RenderStyle&) override;
 
--- a/modules/web/src/main/native/Source/WebCore/html/HTMLOptGroupElement.cpp	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/html/HTMLOptGroupElement.cpp	Wed Mar 09 18:58:20 2016 -0800
@@ -96,7 +96,7 @@
     // manually cache the value. This happens if our parent doesn't have a
     // renderer like <optgroup> or if it doesn't allow children like <select>.
     if (!m_style && parentNode()->renderStyle())
-        updateNonRenderStyle();
+        updateNonRenderStyle(*parentNode()->renderStyle());
 }
 
 void HTMLOptGroupElement::willDetachRenderers()
@@ -104,9 +104,9 @@
     m_style.clear();
 }
 
-void HTMLOptGroupElement::updateNonRenderStyle()
+void HTMLOptGroupElement::updateNonRenderStyle(RenderStyle& parentStyle)
 {
-    m_style = document().ensureStyleResolver().styleForElement(this);
+    m_style = document().ensureStyleResolver().styleForElement(this, &parentStyle);
 }
 
 RenderStyle* HTMLOptGroupElement::nonRendererStyle() const
@@ -114,35 +114,35 @@
     return m_style.get();
 }
 
-PassRefPtr<RenderStyle> HTMLOptGroupElement::customStyleForRenderer()
+PassRefPtr<RenderStyle> HTMLOptGroupElement::customStyleForRenderer(RenderStyle& parentStyle)
 {
     // styleForRenderer is called whenever a new style should be associated
     // with an Element so now is a good time to update our cached style.
-    updateNonRenderStyle();
+    updateNonRenderStyle(parentStyle);
     return m_style;
 }
 
 String HTMLOptGroupElement::groupLabelText() const
 {
     String itemText = document().displayStringModifiedByEncoding(getAttribute(labelAttr));
-
+    
     // In WinIE, leading and trailing whitespace is ignored in options and optgroups. We match this behavior.
     itemText = itemText.stripWhiteSpace();
     // We want to collapse our whitespace too.  This will match other browsers.
     itemText = itemText.simplifyWhiteSpace();
-
+        
     return itemText;
 }
-
+    
 HTMLSelectElement* HTMLOptGroupElement::ownerSelectElement() const
 {
     ContainerNode* select = parentNode();
     while (select && !select->hasTagName(selectTag))
         select = select->parentNode();
-
+    
     if (!select)
        return 0;
-
+    
     return toHTMLSelectElement(select);
 }
 
--- a/modules/web/src/main/native/Source/WebCore/html/HTMLOptGroupElement.h	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/html/HTMLOptGroupElement.h	Wed Mar 09 18:58:20 2016 -0800
@@ -27,7 +27,7 @@
 #include "HTMLElement.h"
 
 namespace WebCore {
-
+    
 class HTMLSelectElement;
 
 class HTMLOptGroupElement final : public HTMLElement {
@@ -36,7 +36,7 @@
 
     virtual bool isDisabledFormControl() const override;
     HTMLSelectElement* ownerSelectElement() const;
-
+    
     String groupLabelText() const;
 
 private:
@@ -54,9 +54,9 @@
     virtual void accessKeyAction(bool sendMouseEvents) override;
 
     // <optgroup> never has a renderer so we manually manage a cached style.
-    void updateNonRenderStyle();
+    void updateNonRenderStyle(RenderStyle& parentStyle);
     virtual RenderStyle* nonRendererStyle() const override;
-    virtual PassRefPtr<RenderStyle> customStyleForRenderer() override;
+    virtual PassRefPtr<RenderStyle> customStyleForRenderer(RenderStyle& parentStyle) override;
 
     void recalcSelectOptions();
 
--- a/modules/web/src/main/native/Source/WebCore/html/HTMLOptionElement.cpp	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/html/HTMLOptionElement.cpp	Wed Mar 09 18:58:20 2016 -0800
@@ -94,7 +94,7 @@
     // manually cache the value. This happens if our parent doesn't have a
     // renderer like <optgroup> or if it doesn't allow children like <select>.
     if (!m_style && parentNode()->renderStyle())
-        updateNonRenderStyle();
+        updateNonRenderStyle(*parentNode()->renderStyle());
 }
 
 void HTMLOptionElement::willDetachRenderers()
@@ -146,7 +146,7 @@
         removeChildren();
         appendChild(Text::create(document(), text), ec);
     }
-
+    
     if (selectIsMenuList && select->selectedIndex() != oldSelectedIndex)
         select->setSelectedIndex(oldSelectedIndex);
 }
@@ -291,7 +291,7 @@
 {
     const AtomicString& label = fastGetAttribute(labelAttr);
     if (!label.isNull())
-        return label;
+        return label; 
     return collectOptionInnerText().stripWhiteSpace(isHTMLSpace).simplifyWhiteSpace(isHTMLSpace);
 }
 
@@ -300,9 +300,9 @@
     setAttribute(labelAttr, label);
 }
 
-void HTMLOptionElement::updateNonRenderStyle()
+void HTMLOptionElement::updateNonRenderStyle(RenderStyle& parentStyle)
 {
-    m_style = document().ensureStyleResolver().styleForElement(this);
+    m_style = document().ensureStyleResolver().styleForElement(this, &parentStyle);
 }
 
 RenderStyle* HTMLOptionElement::nonRendererStyle() const
@@ -310,11 +310,11 @@
     return m_style.get();
 }
 
-PassRefPtr<RenderStyle> HTMLOptionElement::customStyleForRenderer()
+PassRefPtr<RenderStyle> HTMLOptionElement::customStyleForRenderer(RenderStyle& parentStyle)
 {
     // styleForRenderer is called whenever a new style should be associated
     // with an Element so now is a good time to update our cached style.
-    updateNonRenderStyle();
+    updateNonRenderStyle(parentStyle);
     return m_style;
 }
 
--- a/modules/web/src/main/native/Source/WebCore/html/HTMLOptionElement.h	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/html/HTMLOptionElement.h	Wed Mar 09 18:58:20 2016 -0800
@@ -82,9 +82,9 @@
     virtual void childrenChanged(const ChildChange&) override;
 
     // <option> never has a renderer so we manually manage a cached style.
-    void updateNonRenderStyle();
+    void updateNonRenderStyle(RenderStyle& parentStyle);
     virtual RenderStyle* nonRendererStyle() const override;
-    virtual PassRefPtr<RenderStyle> customStyleForRenderer() override;
+    virtual PassRefPtr<RenderStyle> customStyleForRenderer(RenderStyle& parentStyle) override;
 
     virtual void didRecalcStyle(Style::Change) override;
 
--- a/modules/web/src/main/native/Source/WebCore/html/HTMLTitleElement.cpp	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/html/HTMLTitleElement.cpp	Wed Mar 09 18:58:20 2016 -0800
@@ -25,8 +25,10 @@
 
 #include "Document.h"
 #include "HTMLNames.h"
+#include "NodeRenderStyle.h"
 #include "RenderStyle.h"
 #include "StyleInheritedData.h"
+#include "StyleResolver.h"
 #include "Text.h"
 #include "TextNodeTraversal.h"
 #include <wtf/Ref.h>
@@ -85,7 +87,7 @@
     if (RenderStyle* computedStyle = this->computedStyle())
         direction = computedStyle->direction();
     else {
-        Ref<RenderStyle> style(styleForRenderer());
+        Ref<RenderStyle> style(document().ensureStyleResolver().styleForElement(this, parentElement() ? parentElement()->renderStyle() : nullptr));
         direction = style.get().direction();
     }
     return StringWithDirection(text(), direction);
@@ -96,7 +98,7 @@
     Ref<HTMLTitleElement> protectFromMutationEvents(*this);
 
     int numChildren = childNodeCount();
-
+    
     if (numChildren == 1 && firstChild()->isTextNode())
         toText(firstChild())->setData(value, IGNORE_EXCEPTION);
     else {
--- a/modules/web/src/main/native/Source/WebCore/html/shadow/TextControlInnerElements.cpp	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/html/shadow/TextControlInnerElements.cpp	Wed Mar 09 18:58:20 2016 -0800
@@ -57,7 +57,7 @@
 {
     return adoptRef(new TextControlInnerContainer(document));
 }
-
+    
 RenderPtr<RenderElement> TextControlInnerContainer::createElementRenderer(PassRef<RenderStyle> style)
 {
     return createRenderer<RenderTextControlInnerContainer>(*this, std::move(style));
@@ -74,7 +74,7 @@
     return adoptRef(new TextControlInnerElement(document));
 }
 
-PassRefPtr<RenderStyle> TextControlInnerElement::customStyleForRenderer()
+PassRefPtr<RenderStyle> TextControlInnerElement::customStyleForRenderer(RenderStyle&)
 {
     RenderTextControlSingleLine* parentRenderer = toRenderTextControlSingleLine(shadowHost()->renderer());
     return parentRenderer->createInnerBlockStyle(&parentRenderer->style());
@@ -122,7 +122,7 @@
     return toRenderTextControlInnerBlock(HTMLDivElement::renderer());
 }
 
-PassRefPtr<RenderStyle> TextControlInnerTextElement::customStyleForRenderer()
+PassRefPtr<RenderStyle> TextControlInnerTextElement::customStyleForRenderer(RenderStyle&)
 {
     RenderTextControl* parentRenderer = toRenderTextControl(shadowHost()->renderer());
     return parentRenderer->createInnerTextStyle(&parentRenderer->style());
--- a/modules/web/src/main/native/Source/WebCore/html/shadow/TextControlInnerElements.h	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/html/shadow/TextControlInnerElements.h	Wed Mar 09 18:58:20 2016 -0800
@@ -21,9 +21,9 @@
  * 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.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
-
+ 
 #ifndef TextControlInnerElements_h
 #define TextControlInnerElements_h
 
@@ -50,7 +50,7 @@
 
 protected:
     TextControlInnerElement(Document&);
-    virtual PassRefPtr<RenderStyle> customStyleForRenderer() override;
+    virtual PassRefPtr<RenderStyle> customStyleForRenderer(RenderStyle& parentStyle) override;
 
 private:
     virtual bool isMouseFocusable() const override { return false; }
@@ -67,7 +67,7 @@
 private:
     TextControlInnerTextElement(Document&);
     virtual RenderPtr<RenderElement> createElementRenderer(PassRef<RenderStyle>) override;
-    virtual PassRefPtr<RenderStyle> customStyleForRenderer() override;
+    virtual PassRefPtr<RenderStyle> customStyleForRenderer(RenderStyle& parentStyle) override;
     virtual bool isMouseFocusable() const override { return false; }
     virtual bool isTextControlInnerTextElement() const override { return true; }
 };
--- a/modules/web/src/main/native/Source/WebCore/rendering/RenderNamedFlowFragment.cpp	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/rendering/RenderNamedFlowFragment.cpp	Wed Mar 09 18:58:20 2016 -0800
@@ -34,6 +34,7 @@
 #include "PaintInfo.h"
 #include "RenderBoxRegionInfo.h"
 #include "RenderFlowThread.h"
+#include "RenderIterator.h"
 #include "RenderNamedFlowThread.h"
 #include "RenderView.h"
 #include "StyleResolver.h"
@@ -195,7 +196,7 @@
     // If they do not continue into another region in that direction, they should be
     // painted all the way to the region's border box.
     // Regions with overflow:hidden will apply clip at the border box, not the content box.
-
+    
     LayoutRect clippingRect = flowThreadPortionRect();
     RenderBlockFlow& container = fragmentContainer();
     if (container.style().hasPadding()) {
@@ -208,14 +209,14 @@
                 clippingRect.expand(container.paddingBefore(), 0);
             }
         }
-
+        
         if (isLastRegionInRange) {
             if (flowThread()->isHorizontalWritingMode())
                 clippingRect.expand(0, container.paddingAfter());
             else
                 clippingRect.expand(container.paddingAfter(), 0);
         }
-
+        
         if (flowThread()->isHorizontalWritingMode()) {
             clippingRect.move(-container.paddingStart(), 0);
             clippingRect.expand(container.paddingStart() + container.paddingEnd(), 0);
@@ -224,7 +225,7 @@
             clippingRect.expand(0, container.paddingStart() + container.paddingEnd());
         }
     }
-
+    
     return clippingRect;
 }
 
@@ -278,24 +279,21 @@
     toRenderNamedFlowThread(m_flowThread)->checkRegionsWithStyling();
 }
 
-PassRefPtr<RenderStyle> RenderNamedFlowFragment::computeStyleInRegion(const RenderObject* object)
+PassRefPtr<RenderStyle> RenderNamedFlowFragment::computeStyleInRegion(RenderElement& renderer, RenderStyle& parentStyle)
 {
-    ASSERT(object);
-    ASSERT(!object->isAnonymous());
-    ASSERT(object->node() && object->node()->isElementNode());
+    ASSERT(!renderer.isAnonymous());
 
     // FIXME: Region styling fails for pseudo-elements because the renderers don't have a node.
-    Element* element = toElement(object->node());
-    RefPtr<RenderStyle> renderObjectRegionStyle = object->view().document().ensureStyleResolver().styleForElement(element, 0, DisallowStyleSharing, MatchAllRules, this);
+    RefPtr<RenderStyle> renderObjectRegionStyle = renderer.view().document().ensureStyleResolver().styleForElement(renderer.element(), &parentStyle, DisallowStyleSharing, MatchAllRules, this);
 
     return renderObjectRegionStyle.release();
 }
 
-void RenderNamedFlowFragment::computeChildrenStyleInRegion(const RenderElement* object)
+void RenderNamedFlowFragment::computeChildrenStyleInRegion(RenderElement& renderer)
 {
-    for (RenderObject* child = object->firstChild(); child; child = child->nextSibling()) {
+    for (auto& child : childrenOfType<RenderObject>(renderer)) {
 
-        auto it = m_renderObjectRegionStyle.find(child);
+        auto it = m_renderObjectRegionStyle.find(&child);
 
         RefPtr<RenderStyle> childStyleInRegion;
         bool objectRegionStyleCached = false;
@@ -303,17 +301,17 @@
             childStyleInRegion = it->value.style;
             objectRegionStyleCached = true;
         } else {
-            if (child->isAnonymous() || child->isInFlowRenderFlowThread())
-                childStyleInRegion = RenderStyle::createAnonymousStyleWithDisplay(&object->style(), child->style().display());
-            else if (child->isText())
-                childStyleInRegion = RenderStyle::clone(&object->style());
+            if (child.isAnonymous() || child.isInFlowRenderFlowThread())
+                childStyleInRegion = RenderStyle::createAnonymousStyleWithDisplay(&renderer.style(), child.style().display());
+            else if (child.isText())
+                childStyleInRegion = RenderStyle::clone(&renderer.style());
             else
-                childStyleInRegion = computeStyleInRegion(child);
+                childStyleInRegion = computeStyleInRegion(toRenderElement(child), renderer.style());
         }
 
-        setObjectStyleInRegion(child, childStyleInRegion, objectRegionStyleCached);
+        setObjectStyleInRegion(&child, childStyleInRegion, objectRegionStyleCached);
 
-        if (child->isRenderElement())
+        if (child.isRenderElement())
             computeChildrenStyleInRegion(toRenderElement(child));
     }
 }
@@ -381,11 +379,11 @@
             ASSERT(it->value.cached);
             objectRegionStyleCached = true;
         } else
-            objectStyleInRegion = computeStyleInRegion(object);
+            objectStyleInRegion = computeStyleInRegion(*object, style());
 
         setObjectStyleInRegion(object, objectStyleInRegion, objectRegionStyleCached);
 
-        computeChildrenStyleInRegion(object);
+        computeChildrenStyleInRegion(*object);
     }
 }
 
@@ -433,7 +431,7 @@
         if (boxInfo && boxInfo->overflow())
             return boxInfo->overflow()->visualOverflowRect();
     }
-
+    
     return RenderRegion::visualOverflowRect();
 }
 
@@ -460,7 +458,7 @@
 {
     if (m_flowThread && hasAutoLogicalHeight())
         decrementAutoLogicalHeightCount();
-
+    
     RenderRegion::detachRegion();
 }
 
--- a/modules/web/src/main/native/Source/WebCore/rendering/RenderNamedFlowFragment.h	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/rendering/RenderNamedFlowFragment.h	Wed Mar 09 18:58:20 2016 -0800
@@ -59,7 +59,7 @@
 
     virtual LayoutUnit pageLogicalHeight() const;
     LayoutUnit maxPageLogicalHeight() const;
-
+    
     LayoutRect flowThreadPortionRectForClipping(bool isFirstRegionInRange, bool isLastRegionInRange) const;
 
     RenderBlockFlow& fragmentContainer() const;
@@ -79,7 +79,7 @@
 
     void setRegionObjectsRegionStyle();
     void restoreRegionObjectsOriginalStyle();
-
+    
     virtual LayoutRect visualOverflowRect() const override;
 
     RenderNamedFlowThread* namedFlowThread() const;
@@ -114,8 +114,8 @@
 private:
     virtual const char* renderName() const override { return "RenderNamedFlowFragment"; }
 
-    PassRefPtr<RenderStyle> computeStyleInRegion(const RenderObject*);
-    void computeChildrenStyleInRegion(const RenderElement*);
+    PassRefPtr<RenderStyle> computeStyleInRegion(RenderElement&, RenderStyle& parentStyle);
+    void computeChildrenStyleInRegion(RenderElement&);
     void setObjectStyleInRegion(RenderObject*, PassRefPtr<RenderStyle>, bool objectRegionStyleCached);
 
     void updateRegionHasAutoLogicalHeightFlag();
--- a/modules/web/src/main/native/Source/WebCore/style/StyleResolveTree.cpp	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/style/StyleResolveTree.cpp	Wed Mar 09 18:58:20 2016 -0800
@@ -4,7 +4,7 @@
  *           (C) 2001 Peter Kelly (pmk@post.com)
  *           (C) 2001 Dirk Mueller (mueller@kde.org)
  *           (C) 2007 David Smith (catfish.man@gmail.com)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2010, 2012-2014 Apple Inc. All rights reserved.
  *           (C) 2007 Eric Seidel (eric@webkit.org)
  *
  * This library is free software; you can redistribute it and/or
@@ -60,10 +60,34 @@
 
 enum DetachType { NormalDetach, ReattachDetach };
 
-static void attachRenderTree(Element&, PassRefPtr<RenderStyle>);
-static void attachTextRenderer(Text&);
+class RenderTreePosition {
+public:
+    RenderTreePosition(RenderElement* parent);
+    RenderTreePosition(RenderElement* parent, RenderObject* nextSibling);
+
+    RenderElement* parent() { return m_parent; }
+
+    void insert(RenderObject&);
+    bool canInsert(RenderElement&) const;
+    bool canInsert(RenderText&) const;
+
+    void computeNextSibling(const Node&, ContainerNode& renderingParentNode);
+    void invalidateNextSibling(const RenderObject&);
+
+private:
+    RenderElement* m_parent;
+    RenderObject* m_nextSibling;
+    bool m_hasValidNextSibling;
+#if !ASSERT_DISABLED
+    unsigned m_assertionLimitCounter;
+#endif
+};
+
+static void attachRenderTree(Element&, ContainerNode& renderingParentNode, RenderTreePosition&, PassRefPtr<RenderStyle>);
+static void attachTextRenderer(Text&, ContainerNode& renderingParentNode, RenderTreePosition&);
 static void detachRenderTree(Element&, DetachType);
-static void resolveTree(Element&, Change);
+static void resolveTextNode(Text&, ContainerNode& renderingParentNode, RenderTreePosition&);
+static void resolveTree(Element&, ContainerNode& renderingParentNode, RenderTreePosition&, Change);
 
 Change determineChange(const RenderStyle* s1, const RenderStyle* s2)
 {
@@ -126,43 +150,120 @@
     return false;
 }
 
-static RenderObject* nextSiblingRenderer(const Element& element, const ContainerNode* renderingParentNode)
+static RenderObject* nextSiblingRenderer(const Node& node, const ContainerNode& renderingParentNode)
 {
+    if (!renderingParentNode.isElementNode())
+        return nullptr;
+    const Element& renderingParentElement = toElement(renderingParentNode);
     // Avoid an O(N^2) problem with this function by not checking for
     // nextRenderer() when the parent element hasn't attached yet.
     // FIXME: Why would we get here anyway if parent is not attached?
-    if (renderingParentNode && !renderingParentNode->renderer())
+    if (!renderingParentElement.renderer())
         return nullptr;
-    for (Node* sibling = NodeRenderingTraversal::nextSibling(&element); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
+    if (node.isAfterPseudoElement())
+        return nullptr;
+    Node* sibling = node.isBeforePseudoElement() ? NodeRenderingTraversal::firstChild(&renderingParentNode) : NodeRenderingTraversal::nextSibling(&node);
+    for (; sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
         RenderObject* renderer = sibling->renderer();
         if (renderer && !isRendererReparented(renderer))
             return renderer;
     }
+    if (PseudoElement* after = renderingParentElement.afterPseudoElement())
+        return after->renderer();
     return nullptr;
 }
 
-static bool shouldCreateRenderer(const Element& element, const ContainerNode* renderingParent)
+RenderTreePosition::RenderTreePosition(RenderElement* parent)
+    : m_parent(parent)
+    , m_nextSibling(nullptr)
+    , m_hasValidNextSibling(false)
+#if !ASSERT_DISABLED
+    , m_assertionLimitCounter(0)
+#endif
+{
+}
+
+RenderTreePosition::RenderTreePosition(RenderElement* parent, RenderObject* nextSibling)
+    : m_parent(parent)
+    , m_nextSibling(nextSibling)
+    , m_hasValidNextSibling(true)
+#if !ASSERT_DISABLED
+    , m_assertionLimitCounter(0)
+#endif
+{
+}
+
+bool RenderTreePosition::canInsert(RenderElement& renderer) const
+{
+    ASSERT(m_parent);
+    ASSERT(!renderer.parent());
+    return m_parent->isChildAllowed(renderer, renderer.style());
+}
+
+bool RenderTreePosition::canInsert(RenderText& renderer) const
+{
+    ASSERT(m_parent);
+    ASSERT(!renderer.parent());
+    return m_parent->isChildAllowed(renderer, m_parent->style());
+}
+
+void RenderTreePosition::insert(RenderObject& renderer)
+{
+    ASSERT(m_parent);
+    ASSERT(m_hasValidNextSibling);
+    m_parent->addChild(&renderer, m_nextSibling);
+}
+
+void RenderTreePosition::computeNextSibling(const Node& node, ContainerNode& renderingParentNode)
+{
+    ASSERT(!node.renderer());
+    if (m_hasValidNextSibling) {
+        // Stop validating at some point so the assert doesn't make us O(N^2) on debug builds.
+        ASSERT(++m_assertionLimitCounter > 20 || nextSiblingRenderer(node, renderingParentNode) == m_nextSibling);
+        return;
+    }
+    m_nextSibling = nextSiblingRenderer(node, renderingParentNode);
+    m_hasValidNextSibling = true;
+}
+
+void RenderTreePosition::invalidateNextSibling(const RenderObject& siblingRenderer)
+{
+    if (!m_hasValidNextSibling)
+        return;
+    if (m_nextSibling == &siblingRenderer)
+        m_hasValidNextSibling = false;
+}
+
+static bool shouldCreateRenderer(const Element& element, const ContainerNode& renderingParent)
 {
     if (!element.document().shouldCreateRenderers())
         return false;
-    if (!renderingParent)
-        return false;
-    RenderObject* parentRenderer = renderingParent->renderer();
+    RenderObject* parentRenderer = renderingParent.renderer();
     if (!parentRenderer)
         return false;
     if (!parentRenderer->canHaveChildren() && !(element.isPseudoElement() && parentRenderer->canHaveGeneratedChildren()))
         return false;
-    if (!renderingParent->childShouldCreateRenderer(element))
+    if (!renderingParent.childShouldCreateRenderer(element))
         return false;
     return true;
 }
 
+static PassRef<RenderStyle> styleForElement(Element& element, ContainerNode& renderingParentNode)
+{
+    RenderStyle* parentStyle = renderingParentNode.renderStyle();
+    if (element.hasCustomStyleResolveCallbacks() && parentStyle) {
+        if (RefPtr<RenderStyle> style = element.customStyleForRenderer(*parentStyle))
+            return style.releaseNonNull();
+    }
+    return element.document().ensureStyleResolver().styleForElement(&element, parentStyle);
+}
+
 // Check the specific case of elements that are children of regions but are flowed into a flow thread themselves.
-static bool elementInsideRegionNeedsRenderer(Element& element, const ContainerNode* renderingParentNode, RefPtr<RenderStyle>& style)
+static bool elementInsideRegionNeedsRenderer(Element& element, ContainerNode& renderingParentNode, RefPtr<RenderStyle>& style)
 {
 #if ENABLE(CSS_REGIONS)
     // The parent of a region should always be an element.
-    const RenderElement* parentRenderer = renderingParentNode ? renderingParentNode->renderer() : 0;
+    const RenderElement* parentRenderer = renderingParentNode.renderer();
 
     bool parentIsRegion = parentRenderer && !parentRenderer->canHaveChildren() && parentRenderer->isRenderNamedFlowFragmentContainer();
     bool parentIsNonRenderedInsideRegion = !parentRenderer && element.parentElement() && element.parentElement()->isInsideRegion();
@@ -170,7 +271,7 @@
         return false;
 
     if (!style)
-        style = element.styleForRenderer();
+        style = styleForElement(element, renderingParentNode);
 
     // Children of this element will only be allowed to be flowed into other flow-threads if display is NOT none.
     if (element.rendererIsNeeded(*style))
@@ -198,12 +299,10 @@
 }
 #endif
 
-static void createRendererIfNeeded(Element& element, PassRefPtr<RenderStyle> resolvedStyle)
+static void createRendererIfNeeded(Element& element, ContainerNode& renderingParentNode, RenderTreePosition& renderTreePosition, PassRefPtr<RenderStyle> resolvedStyle)
 {
     ASSERT(!element.renderer());
 
-    ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&element);
-
     RefPtr<RenderStyle> style = resolvedStyle;
 
     element.setIsInsideRegion(false);
@@ -212,7 +311,7 @@
         return;
 
     if (!style)
-        style = element.styleForRenderer();
+        style = styleForElement(element, renderingParentNode);
 
     RenderNamedFlowThread* parentFlowRenderer = 0;
 #if ENABLE(CSS_REGIONS)
@@ -222,28 +321,23 @@
     if (!element.rendererIsNeeded(*style))
         return;
 
-    RenderElement* parentRenderer;
-    RenderObject* nextRenderer;
-    if (parentFlowRenderer) {
-        parentRenderer = parentFlowRenderer;
-        nextRenderer = parentFlowRenderer->nextRendererForElement(element);
-    } else {
-        // FIXME: Make this path Element only, handle the root special case separately.
-        parentRenderer = renderingParentNode->renderer();
-        nextRenderer = nextSiblingRenderer(element, renderingParentNode);
-    }
+    renderTreePosition.computeNextSibling(element, renderingParentNode);
+
+    RenderTreePosition insertionPosition = parentFlowRenderer
+        ? RenderTreePosition(parentFlowRenderer, parentFlowRenderer->nextRendererForElement(element))
+        : renderTreePosition;
 
     RenderElement* newRenderer = element.createElementRenderer(style.releaseNonNull()).leakPtr();
     if (!newRenderer)
         return;
-    if (!parentRenderer->isChildAllowed(*newRenderer, newRenderer->style())) {
+    if (!insertionPosition.canInsert(*newRenderer)) {
         newRenderer->destroy();
         return;
     }
 
     // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
     // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
-    newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
+    newRenderer->setFlowThreadState(insertionPosition.parent()->flowThreadState());
 
     // Code below updateAnimations() can depend on Element::renderer() already being set.
     element.setRenderer(newRenderer);
@@ -257,13 +351,13 @@
 #if ENABLE(FULLSCREEN_API)
     Document& document = element.document();
     if (document.webkitIsFullScreen() && document.webkitCurrentFullScreenElement() == &element) {
-        newRenderer = RenderFullScreen::wrapRenderer(newRenderer, parentRenderer, document);
+        newRenderer = RenderFullScreen::wrapRenderer(newRenderer, insertionPosition.parent(), document);
         if (!newRenderer)
             return;
     }
 #endif
     // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
-    parentRenderer->addChild(newRenderer, nextRenderer);
+    insertionPosition.insert(*newRenderer);
 }
 
 static RenderObject* previousSiblingRenderer(const Text& textNode)
@@ -275,30 +369,19 @@
         if (renderer && !isRendererReparented(renderer))
             return renderer;
     }
-    return 0;
+    if (PseudoElement* before = textNode.parentElement()->beforePseudoElement())
+        return before->renderer();
+    return nullptr;
 }
 
-static RenderObject* nextSiblingRenderer(const Text& textNode)
-{
-    if (textNode.renderer())
-        return textNode.renderer()->nextSibling();
-    for (Node* sibling = NodeRenderingTraversal::nextSibling(&textNode); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
-        RenderObject* renderer = sibling->renderer();
-        if (renderer && !isRendererReparented(renderer))
-            return renderer;
-    }
-    return 0;
-}
-
-static void reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(Node& current)
+static void invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(Node& current)
 {
     if (isInsertionPoint(current))
         return;
     // This function finds sibling text renderers where the results of textRendererIsNeeded may have changed as a result of
     // the current node gaining or losing the renderer. This can only affect white space text nodes.
-    for (Node* sibling = NodeRenderingTraversal::nextSibling(&current); sibling; sibling = NodeRenderingTraversal::nextSibling(sibling)) {
-        // Siblings haven't been attached yet. They will be handled normally when they are.
-        if (sibling->styleChangeType() == ReconstructRenderTree)
+    for (Node* sibling = current.nextSibling(); sibling; sibling = sibling->nextSibling()) {
+        if (sibling->needsStyleRecalc())
             return;
         if (sibling->isElementNode()) {
             // Text renderers beyond rendered elements can't be affected.
@@ -308,39 +391,41 @@
         }
         if (!sibling->isTextNode())
             continue;
-        Text& textSibling = *toText(sibling);
-        if (!textSibling.length() || !textSibling.containsOnlyWhitespace())
-            return;
-        Text& whitespaceTextSibling = textSibling;
-        bool hadRenderer = whitespaceTextSibling.renderer();
-        detachTextRenderer(whitespaceTextSibling);
-        attachTextRenderer(whitespaceTextSibling);
-        // No changes, futher renderers can't be affected.
-        if (hadRenderer == !!whitespaceTextSibling.renderer())
-            return;
+        Text& textSibling = toText(*sibling);
+        if (!textSibling.containsOnlyWhitespace())
+            continue;
+        textSibling.setNeedsStyleRecalc();
     }
 }
 
-static bool textRendererIsNeeded(const Text& textNode, const RenderObject& parentRenderer, const RenderStyle& style)
+static bool textRendererIsNeeded(const Text& textNode, ContainerNode& renderingParentNode)
 {
+    if (!renderingParentNode.renderer())
+        return false;
+    RenderElement& parentRenderer = *renderingParentNode.renderer();
+    if (!parentRenderer.canHaveChildren())
+        return false;
+    if (!renderingParentNode.childShouldCreateRenderer(textNode))
+        return false;
+
     if (textNode.isEditingText())
         return true;
     if (!textNode.length())
         return false;
-    if (style.display() == NONE)
+    if (parentRenderer.style().display() == NONE)
         return false;
     if (!textNode.containsOnlyWhitespace())
         return true;
     // This text node has nothing but white space. We may still need a renderer in some cases.
     if (parentRenderer.isTable() || parentRenderer.isTableRow() || parentRenderer.isTableSection() || parentRenderer.isRenderTableCol() || parentRenderer.isFrameSet())
         return false;
-    if (style.preserveNewline()) // pre/pre-wrap/pre-line always make renderers.
+    if (parentRenderer.style().preserveNewline()) // pre/pre-wrap/pre-line always make renderers.
         return true;
 
     RenderObject* previousRenderer = previousSiblingRenderer(textNode);
     if (previousRenderer && previousRenderer->isBR()) // <span><br/> <br/></span>
         return false;
-
+        
     if (parentRenderer.isRenderInline()) {
         // <span><div/> <div/></span>
         if (previousRenderer && !previousRenderer->isInline())
@@ -348,11 +433,11 @@
     } else {
         if (parentRenderer.isRenderBlock() && !parentRenderer.childrenInline() && (!previousRenderer || !previousRenderer->isInline()))
             return false;
-
-        RenderObject* first = toRenderElement(parentRenderer).firstChild();
+        
+        RenderObject* first = parentRenderer.firstChild();
         while (first && first->isFloatingOrOutOfFlowPositioned())
             first = first->nextSibling();
-        RenderObject* nextRenderer = nextSiblingRenderer(textNode);
+        RenderObject* nextRenderer = nextSiblingRenderer(textNode, *textNode.parentNode());
         if (!first || nextRenderer == first) {
             // Whitespace at the start of a block just goes away. Don't even make a render object for this text.
             return false;
@@ -361,43 +446,33 @@
     return true;
 }
 
-static void createTextRendererIfNeeded(Text& textNode)
+static void createTextRendererIfNeeded(Text& textNode, ContainerNode& renderingParentNode, RenderTreePosition& renderTreePosition)
 {
     ASSERT(!textNode.renderer());
 
-    ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&textNode);
-    if (!renderingParentNode)
-        return;
-    RenderElement* parentRenderer = renderingParentNode->renderer();
-    if (!parentRenderer || !parentRenderer->canHaveChildren())
-        return;
-    if (!renderingParentNode->childShouldCreateRenderer(textNode))
+    if (!textRendererIsNeeded(textNode, renderingParentNode))
         return;
 
-    const auto& style = parentRenderer->style();
-
-    if (!textRendererIsNeeded(textNode, *parentRenderer, style))
-        return;
-
-    auto newRenderer = textNode.createTextRenderer(style);
+    auto newRenderer = textNode.createTextRenderer(*renderingParentNode.renderStyle());
     ASSERT(newRenderer);
 
-    if (!parentRenderer->isChildAllowed(*newRenderer, style))
+    renderTreePosition.computeNextSibling(textNode, renderingParentNode);
+
+    if (!renderTreePosition.canInsert(*newRenderer))
         return;
 
     // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
     // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
-    newRenderer->setFlowThreadState(parentRenderer->flowThreadState());
+    newRenderer->setFlowThreadState(renderTreePosition.parent()->flowThreadState());
 
-    RenderObject* nextRenderer = nextSiblingRenderer(textNode);
     textNode.setRenderer(newRenderer.get());
     // Parent takes care of the animations, no need to call setAnimatableStyle.
-    parentRenderer->addChild(newRenderer.leakPtr(), nextRenderer);
+    renderTreePosition.insert(*newRenderer.leakPtr());
 }
 
-void attachTextRenderer(Text& textNode)
+void attachTextRenderer(Text& textNode, ContainerNode& renderingParentNode, RenderTreePosition& renderTreePosition)
 {
-    createTextRendererIfNeeded(textNode);
+    createTextRendererIfNeeded(textNode, renderingParentNode, renderTreePosition);
 
     textNode.clearNeedsStyleRecalc();
 }
@@ -411,62 +486,68 @@
 
 void updateTextRendererAfterContentChange(Text& textNode, unsigned offsetOfReplacedData, unsigned lengthOfReplacedData)
 {
-    RenderText* textRenderer = textNode.renderer();
-    if (!textRenderer) {
-        attachTextRenderer(textNode);
-        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(textNode);
+    ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&textNode);
+    if (!renderingParentNode)
         return;
-    }
-    RenderObject* parentRenderer = NodeRenderingTraversal::parent(&textNode)->renderer();
-    if (!textRendererIsNeeded(textNode, *parentRenderer, textRenderer->style())) {
-        detachTextRenderer(textNode);
-        attachTextRenderer(textNode);
-        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(textNode);
-        return;
-    }
-    textRenderer->setTextWithOffset(textNode.dataImpl(), offsetOfReplacedData, lengthOfReplacedData);
+
+    bool hadRenderer = textNode.renderer();
+
+    RenderTreePosition renderTreePosition(renderingParentNode->renderer());
+    resolveTextNode(textNode, *renderingParentNode, renderTreePosition);
+
+    if (hadRenderer && textNode.renderer())
+        textNode.renderer()->setTextWithOffset(textNode.dataImpl(), offsetOfReplacedData, lengthOfReplacedData);
 }
 
-static void attachDistributedChildren(InsertionPoint& insertionPoint)
+static void attachChildren(ContainerNode& current, ContainerNode& renderingParentNode, RenderTreePosition& renderTreePosition)
+{
+    for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
+        ASSERT((!child->renderer() || child->inNamedFlow()) || current.shadowRoot());
+        if (child->renderer()) {
+            renderTreePosition.invalidateNextSibling(*child->renderer());
+            continue;
+        }
+        if (child->isTextNode()) {
+            attachTextRenderer(*toText(child), renderingParentNode, renderTreePosition);
+            continue;
+        }
+        if (child->isElementNode())
+            attachRenderTree(*toElement(child), renderingParentNode, renderTreePosition, nullptr);
+    }
+}
+
+static void attachDistributedChildren(InsertionPoint& insertionPoint, ContainerNode& renderingParentNode, RenderTreePosition& renderTreePosition)
 {
     if (ShadowRoot* shadowRoot = insertionPoint.containingShadowRoot())
         ContentDistributor::ensureDistribution(shadowRoot);
+
     for (Node* current = insertionPoint.firstDistributed(); current; current = insertionPoint.nextDistributedTo(current)) {
+        if (current->renderer())
+            renderTreePosition.invalidateNextSibling(*current->renderer());
         if (current->isTextNode()) {
             if (current->renderer())
                 continue;
-            attachTextRenderer(*toText(current));
+            attachTextRenderer(*toText(current), renderingParentNode, renderTreePosition);
             continue;
         }
         if (current->isElementNode()) {
-            if (current->renderer())
-                detachRenderTree(*toElement(current));
-            attachRenderTree(*toElement(current), nullptr);
+            Element& currentElement = toElement(*current);
+            if (currentElement.renderer())
+                detachRenderTree(currentElement);
+            attachRenderTree(currentElement, renderingParentNode, renderTreePosition, nullptr);
         }
     }
-}
-
-static void attachChildren(ContainerNode& current)
-{
-    if (isInsertionPoint(current))
-        attachDistributedChildren(toInsertionPoint(current));
-
-    for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
-        ASSERT((!child->renderer() || child->inNamedFlow()) || current.shadowRoot() || isInsertionPoint(current));
-        if (child->renderer())
-            continue;
-        if (child->isTextNode()) {
-            attachTextRenderer(*toText(child));
-            continue;
-        }
-        if (child->isElementNode())
-            attachRenderTree(*toElement(child), nullptr);
-    }
+    // Use actual children as fallback content.
+    if (!insertionPoint.hasDistribution())
+        attachChildren(insertionPoint, renderingParentNode, renderTreePosition);
 }
 
 static void attachShadowRoot(ShadowRoot& shadowRoot)
 {
-    attachChildren(shadowRoot);
+    ASSERT(shadowRoot.hostElement());
+
+    RenderTreePosition renderTreePosition(shadowRoot.hostElement()->renderer());
+    attachChildren(shadowRoot, *shadowRoot.hostElement(), renderTreePosition);
 
     shadowRoot.clearNeedsStyleRecalc();
     shadowRoot.clearChildNeedsStyleRecalc();
@@ -500,7 +581,7 @@
     current.clearAfterPseudoElement();
 }
 
-static bool needsPseudeElement(Element& current, PseudoId pseudoId)
+static bool needsPseudoElement(Element& current, PseudoId pseudoId)
 {
     if (!current.document().styleSheetCollection().usesBeforeAfterRules())
         return false;
@@ -513,16 +594,16 @@
     return true;
 }
 
-static void attachBeforeOrAfterPseudoElementIfNeeded(Element& current, PseudoId pseudoId)
+static void attachBeforeOrAfterPseudoElementIfNeeded(Element& current, PseudoId pseudoId, RenderTreePosition& renderTreePosition)
 {
-    if (!needsPseudeElement(current, pseudoId))
+    if (!needsPseudoElement(current, pseudoId))
         return;
     RefPtr<PseudoElement> pseudoElement = PseudoElement::create(current, pseudoId);
     setBeforeOrAfterPseudoElement(current, pseudoElement, pseudoId);
-    attachRenderTree(*pseudoElement, nullptr);
+    attachRenderTree(*pseudoElement, current, renderTreePosition, nullptr);
 }
 
-static void attachRenderTree(Element& current, PassRefPtr<RenderStyle> resolvedStyle)
+static void attachRenderTree(Element& current, ContainerNode& renderingParentNode, RenderTreePosition& renderTreePosition, PassRefPtr<RenderStyle> resolvedStyle)
 {
     PostAttachCallbackDisabler callbackDisabler(current.document());
     WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
@@ -530,23 +611,26 @@
     if (current.hasCustomStyleResolveCallbacks())
         current.willAttachRenderers();
 
-    createRendererIfNeeded(current, resolvedStyle);
+    createRendererIfNeeded(current, renderingParentNode, renderTreePosition, resolvedStyle);
 
     if (current.parentElement() && current.parentElement()->isInCanvasSubtree())
         current.setIsInCanvasSubtree(true);
 
-    attachBeforeOrAfterPseudoElementIfNeeded(current, BEFORE);
-
     StyleResolverParentPusher parentPusher(&current);
 
-    // When a shadow root exists, it does the work of attaching the children.
+    RenderTreePosition childRenderTreePosition(current.renderer());
+    attachBeforeOrAfterPseudoElementIfNeeded(current, BEFORE, childRenderTreePosition);
+
     if (ShadowRoot* shadowRoot = current.shadowRoot()) {
         parentPusher.push();
         attachShadowRoot(*shadowRoot);
     } else if (current.firstChild())
         parentPusher.push();
 
-    attachChildren(current);
+    if (isInsertionPoint(current))
+        attachDistributedChildren(toInsertionPoint(current), renderingParentNode, renderTreePosition);
+    else
+        attachChildren(current, current, childRenderTreePosition);
 
     current.clearNeedsStyleRecalc();
     current.clearChildNeedsStyleRecalc();
@@ -554,10 +638,10 @@
     if (AXObjectCache* cache = current.document().axObjectCache())
         cache->updateCacheAfterNodeIsAttached(&current);
 
-    attachBeforeOrAfterPseudoElementIfNeeded(current, AFTER);
+    attachBeforeOrAfterPseudoElementIfNeeded(current, AFTER, childRenderTreePosition);
 
     current.updateFocusAppearanceAfterAttachIfNeeded();
-
+    
     if (current.hasCustomStyleResolveCallbacks())
         current.didAttachRenderers();
 }
@@ -656,7 +740,7 @@
     return false;
 }
 
-static Change resolveLocal(Element& current, Change inheritedChange)
+static Change resolveLocal(Element& current, ContainerNode& renderingParentNode, RenderTreePosition& renderTreePosition, Change inheritedChange)
 {
     Change localChange = Detach;
     RefPtr<RenderStyle> newStyle;
@@ -664,14 +748,14 @@
 
     Document& document = current.document();
     if (currentStyle && current.styleChangeType() != ReconstructRenderTree) {
-        newStyle = current.styleForRenderer();
+        newStyle = styleForElement(current, renderingParentNode);
         localChange = determineChange(currentStyle.get(), newStyle.get());
     }
     if (localChange == Detach) {
         if (current.renderer() || current.inNamedFlow())
             detachRenderTree(current, ReattachDetach);
-        attachRenderTree(current, newStyle.release());
-        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(current);
+        attachRenderTree(current, renderingParentNode, renderTreePosition, newStyle.release());
+        invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(current);
 
         return Detach;
     }
@@ -702,49 +786,57 @@
     return localChange;
 }
 
-static void updateTextStyle(Text& text)
+void resolveTextNode(Text& text, ContainerNode& renderingParentNode, RenderTreePosition& renderTreePosition)
 {
-    RenderText* renderer = text.renderer();
+    text.clearNeedsStyleRecalc();
 
-    if (!text.needsStyleRecalc())
+    bool hasRenderer = text.renderer();
+    bool needsRenderer = textRendererIsNeeded(text, renderingParentNode);
+    if (hasRenderer) {
+        if (needsRenderer)
+            return;
+        detachTextRenderer(text);
+        invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(text);
         return;
-    if (renderer)
-        renderer->setText(text.dataImpl());
-    else {
-        attachTextRenderer(text);
-        reattachTextRenderersForWhitespaceOnlySiblingsAfterAttachIfNeeded(text);
     }
-    text.clearNeedsStyleRecalc();
+    if (!needsRenderer)
+        return;
+    attachTextRenderer(text, renderingParentNode, renderTreePosition);
+    invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(text);
 }
 
-static void resolveShadowTree(ShadowRoot* shadowRoot, Style::Change change)
+static void resolveShadowTree(ShadowRoot& shadowRoot, Element& host, Style::Change change)
 {
-    if (!shadowRoot)
-        return;
-
-    for (Node* child = shadowRoot->firstChild(); child; child = child->nextSibling()) {
-        if (child->isTextNode()) {
-            updateTextStyle(*toText(child));
+    ASSERT(shadowRoot.hostElement() == &host);
+    RenderTreePosition renderTreePosition(host.renderer());
+    for (Node* child = shadowRoot.firstChild(); child; child = child->nextSibling()) {
+        if (child->renderer())
+            renderTreePosition.invalidateNextSibling(*child->renderer());
+        if (child->isTextNode() && child->needsStyleRecalc()) {
+            resolveTextNode(*toText(child), host, renderTreePosition);
             continue;
         }
         if (child->isElementNode())
-            resolveTree(*toElement(child), change);
+            resolveTree(*toElement(child), host, renderTreePosition, change);
     }
 
-    shadowRoot->clearNeedsStyleRecalc();
-    shadowRoot->clearChildNeedsStyleRecalc();
+    shadowRoot.clearNeedsStyleRecalc();
+    shadowRoot.clearChildNeedsStyleRecalc();
 }
 
-static void updateBeforeOrAfterPseudoElement(Element& current, Change change, PseudoId pseudoId)
+static void updateBeforeOrAfterPseudoElement(Element& current, Change change, PseudoId pseudoId, RenderTreePosition& renderTreePosition)
 {
     if (PseudoElement* existingPseudoElement = beforeOrAfterPseudoElement(current, pseudoId)) {
-        if (needsPseudeElement(current, pseudoId))
-            resolveTree(*existingPseudoElement, current.needsStyleRecalc() ? Force : change);
+        if (existingPseudoElement->renderer())
+            renderTreePosition.invalidateNextSibling(*existingPseudoElement->renderer());
+
+        if (needsPseudoElement(current, pseudoId))
+            resolveTree(*existingPseudoElement, current, renderTreePosition, current.needsStyleRecalc() ? Force : change);
         else
             clearBeforeOrAfterPseudoElement(current, pseudoId);
         return;
     }
-    attachBeforeOrAfterPseudoElementIfNeeded(current, pseudoId);
+    attachBeforeOrAfterPseudoElementIfNeeded(current, pseudoId, renderTreePosition);
 }
 
 #if PLATFORM(IOS)
@@ -799,7 +891,7 @@
 };
 #endif // PLATFORM(IOS)
 
-void resolveTree(Element& current, Change change)
+void resolveTree(Element& current, ContainerNode& renderingParentNode, RenderTreePosition& renderTreePosition, Change change)
 {
     ASSERT(change != Detach);
 
@@ -808,8 +900,7 @@
             return;
     }
 
-    ContainerNode* renderingParentNode = NodeRenderingTraversal::parent(&current);
-    bool hasParentStyle = renderingParentNode && renderingParentNode->renderStyle();
+    bool hasParentStyle = renderingParentNode.renderStyle();
     bool hasDirectAdjacentRules = current.childrenAffectedByDirectAdjacentRules();
     bool hasIndirectAdjacentRules = current.childrenAffectedByForwardPositionalRules();
 
@@ -821,7 +912,7 @@
         current.resetComputedStyle();
 
     if (hasParentStyle && (change >= Inherit || current.needsStyleRecalc()))
-        change = resolveLocal(current, change);
+        change = resolveLocal(current, renderingParentNode, renderTreePosition, change);
 
     if (change != Detach) {
         StyleResolverParentPusher parentPusher(&current);
@@ -829,11 +920,12 @@
         if (ShadowRoot* shadowRoot = current.shadowRoot()) {
             if (change >= Inherit || shadowRoot->childNeedsStyleRecalc() || shadowRoot->needsStyleRecalc()) {
                 parentPusher.push();
-                resolveShadowTree(shadowRoot, change);
+                resolveShadowTree(*shadowRoot, current, change);
             }
         }
 
-        updateBeforeOrAfterPseudoElement(current, change, BEFORE);
+        RenderTreePosition childRenderTreePosition(current.renderer());
+        updateBeforeOrAfterPseudoElement(current, change, BEFORE, childRenderTreePosition);
 
         // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
         // For now we will just worry about the common case, since it's a lot trickier to get the second case right
@@ -841,8 +933,10 @@
         bool forceCheckOfNextElementSibling = false;
         bool forceCheckOfAnyElementSibling = false;
         for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
-            if (child->isTextNode()) {
-                updateTextStyle(*toText(child));
+            if (child->renderer())
+                childRenderTreePosition.invalidateNextSibling(*child->renderer());
+            if (child->isTextNode() && child->needsStyleRecalc()) {
+                resolveTextNode(*toText(child), current, childRenderTreePosition);
                 continue;
             }
             if (!child->isElementNode())
@@ -853,18 +947,18 @@
                 childElement->setNeedsStyleRecalc();
             if (change >= Inherit || childElement->childNeedsStyleRecalc() || childElement->needsStyleRecalc()) {
                 parentPusher.push();
-                resolveTree(*childElement, change);
+                resolveTree(*childElement, current, childRenderTreePosition, change);
             }
             forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
             forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged && hasIndirectAdjacentRules);
         }
 
-        updateBeforeOrAfterPseudoElement(current, change, AFTER);
+        updateBeforeOrAfterPseudoElement(current, change, AFTER, childRenderTreePosition);
     }
 
     current.clearNeedsStyleRecalc();
     current.clearChildNeedsStyleRecalc();
-
+    
     if (current.hasCustomStyleResolveCallbacks())
         current.didRecalcStyle(change);
 }
@@ -894,7 +988,8 @@
         return;
     if (change < Inherit && !documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc())
         return;
-    resolveTree(*documentElement, change);
+    RenderTreePosition renderTreePosition(document.renderView());
+    resolveTree(*documentElement, document, renderTreePosition, change);
 }
 
 void detachRenderTree(Element& element)
--- a/modules/web/src/main/native/Source/WebCore/svg/SVGElement.cpp	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/svg/SVGElement.cpp	Wed Mar 09 18:58:20 2016 -0800
@@ -375,7 +375,7 @@
     // global inclusion of Document.h in SVG code.
     return document().accessSVGExtensions();
 }
-
+ 
 void SVGElement::mapInstanceToElement(SVGElementInstance* instance)
 {
     ASSERT(instance);
@@ -385,7 +385,7 @@
 
     instances.add(instance);
 }
-
+ 
 void SVGElement::removeInstanceMapping(SVGElementInstance* instance)
 {
     ASSERT(instance);
@@ -426,7 +426,7 @@
     rareData.setCursorElement(cursorElement);
 }
 
-void SVGElement::cursorElementRemoved()
+void SVGElement::cursorElementRemoved() 
 {
     ASSERT(m_svgRareData);
     m_svgRareData->setCursorElement(0);
@@ -547,14 +547,14 @@
 bool SVGElement::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> prpListener, bool useCapture)
 {
     RefPtr<EventListener> listener = prpListener;
-
+    
     // Add event listener to regular DOM element
     if (!Node::addEventListener(eventType, listener, useCapture))
         return false;
 
     // Add event listener to all shadow tree DOM element instances
     HashSet<SVGElementInstance*> instances;
-    collectInstancesForSVGElement(this, instances);
+    collectInstancesForSVGElement(this, instances);    
     const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
     for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
         ASSERT((*it)->shadowTreeElement());
@@ -768,18 +768,12 @@
     contextElement->synchronizeSystemLanguage();
 }
 
-PassRefPtr<RenderStyle> SVGElement::customStyleForRenderer()
+PassRefPtr<RenderStyle> SVGElement::customStyleForRenderer(RenderStyle& parentStyle)
 {
     if (!correspondingElement())
-        return document().ensureStyleResolver().styleForElement(this);
+        return document().ensureStyleResolver().styleForElement(this, &parentStyle);
 
-    RenderStyle* style = 0;
-    if (Element* parent = parentOrShadowHostElement()) {
-        if (auto renderer = parent->renderer())
-            style = &renderer->style();
-    }
-
-    return document().ensureStyleResolver().styleForElement(correspondingElement(), style, DisallowStyleSharing);
+    return document().ensureStyleResolver().styleForElement(correspondingElement(), &parentStyle, DisallowStyleSharing);
 }
 
 MutableStyleProperties* SVGElement::animatedSMILStyleProperties() const
@@ -1165,7 +1159,7 @@
 {
     return isMouseFocusable();
 }
-
+    
 void SVGElement::accessKeyAction(bool sendMouseEvents)
 {
     dispatchSimulatedClick(0, sendMouseEvents ? SendMouseUpDownEvents : SendNoEvents);
--- a/modules/web/src/main/native/Source/WebCore/svg/SVGElement.h	Wed Mar 09 18:42:09 2016 -0800
+++ b/modules/web/src/main/native/Source/WebCore/svg/SVGElement.h	Wed Mar 09 18:58:20 2016 -0800
@@ -111,8 +111,8 @@
 
     void synchronizeAnimatedSVGAttribute(const QualifiedName&) const;
     static void synchronizeAllAnimatedSVGAttribute(SVGElement*);
-
-    virtual PassRefPtr<RenderStyle> customStyleForRenderer() override;
+ 
+    virtual PassRefPtr<RenderStyle> customStyleForRenderer(RenderStyle& parentStyle) override;
 
     static void synchronizeRequiredFeatures(SVGElement* contextElement);
     static void synchronizeRequiredExtensions(SVGElement* contextElement);