Make CachedSVGDocumentReference independent of FilterOperation
[WebKit-https.git] / Source / WebCore / css / StyleResolver.cpp
index b8cde5d..22ad201 100644 (file)
 #include "TransformationMatrix.h"
 #include "TranslateTransformOperation.h"
 #include "UserAgentStyleSheets.h"
+#include "ViewportStyleResolver.h"
 #include "WebCoreMemoryInstrumentation.h"
 #include "WebKitCSSKeyframeRule.h"
 #include "WebKitCSSKeyframesRule.h"
 
 #if ENABLE(CSS_SHADERS)
 #include "CustomFilterArrayParameter.h"
+#include "CustomFilterConstants.h"
 #include "CustomFilterNumberParameter.h"
 #include "CustomFilterOperation.h"
 #include "CustomFilterParameter.h"
 
 using namespace std;
 
+namespace WTF {
+
+template<> struct SequenceMemoryInstrumentationTraits<const WebCore::RuleData*> {
+    template <typename I> static void reportMemoryUsage(I, I, MemoryClassInfo&) { }
+};
+
+}
+
 namespace WebCore {
 
 using namespace HTMLNames;
@@ -193,13 +203,6 @@ if (isInitial) { \
     return; \
 }
 
-#define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
-HANDLE_INHERIT(prop, Prop) \
-if (isInitial) { \
-    m_style->set##Prop(RenderStyle::initial##Value());\
-    return;\
-}
-
 static RuleSet* defaultStyle;
 static RuleSet* defaultQuirksStyle;
 static RuleSet* defaultPrintStyle;
@@ -273,8 +276,10 @@ StyleResolver::StyleResolver(Document* document, bool matchAuthorAndUserStyles)
     , m_matchAuthorAndUserStyles(matchAuthorAndUserStyles)
     , m_sameOriginOnly(false)
     , m_distributedToInsertionPoint(false)
-    , m_hasUnknownPseudoElements(false)
     , m_fontSelector(CSSFontSelector::create(document))
+#if ENABLE(CSS_DEVICE_ADAPTATION)
+    , m_viewportStyleResolver(ViewportStyleResolver::create(document))
+#endif
     , m_applyPropertyToRegularStyle(true)
     , m_applyPropertyToVisitedLinkStyle(false)
     , m_styleBuilder(StyleBuilder::sharedStyleBuilder())
@@ -292,17 +297,8 @@ StyleResolver::StyleResolver(Document* document, bool matchAuthorAndUserStyles)
             loadFullDefaultStyle();
     }
 
-    // construct document root element default style. this is needed
-    // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
-    // This is here instead of constructor, because when constructor is run,
-    // document doesn't have documentElement
-    // NOTE: this assumes that element that gets passed to styleForElement -call
-    // is always from the document that owns the style selector
     FrameView* view = document->view();
-    if (view)
-        m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType()));
-    else
-        m_medium = adoptPtr(new MediaQueryEvaluator("all"));
+    m_medium = adoptPtr(new MediaQueryEvaluator(view ? view->mediaType() : "all"));
 
     if (root)
         m_rootDefaultStyle = styleForElement(root, 0, DisallowStyleSharing, MatchOnlyUserAgentRules);
@@ -312,16 +308,6 @@ StyleResolver::StyleResolver(Document* document, bool matchAuthorAndUserStyles)
 
     resetAuthorStyle();
 
-    DocumentStyleSheetCollection* styleSheetCollection = document->styleSheetCollection();
-    // FIXME: This sucks! The user sheet is reparsed every time!
-    OwnPtr<RuleSet> tempUserStyle = RuleSet::create();
-    if (CSSStyleSheet* pageUserSheet = styleSheetCollection->pageUserSheet())
-        tempUserStyle->addRulesFromSheet(pageUserSheet->contents(), *m_medium, this);
-    addAuthorRulesAndCollectUserRulesFromSheets(styleSheetCollection->pageGroupUserSheets(), *tempUserStyle);
-    addAuthorRulesAndCollectUserRulesFromSheets(styleSheetCollection->documentUserSheets(), *tempUserStyle);
-    if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRules.size() > 0)
-        m_userStyle = tempUserStyle.release();
-
 #if ENABLE(SVG_FONTS)
     if (document->svgExtensions()) {
         const HashSet<SVGFontFaceElement*>& svgFontFaceElements = document->svgExtensions()->svgFontFaceElements();
@@ -331,38 +317,20 @@ StyleResolver::StyleResolver(Document* document, bool matchAuthorAndUserStyles)
     }
 #endif
 
-    addStylesheetsFromSeamlessParents();
+    DocumentStyleSheetCollection* styleSheetCollection = document->styleSheetCollection();
+    collectRulesFromUserStyleSheets(styleSheetCollection->activeUserStyleSheets());
     appendAuthorStyleSheets(0, styleSheetCollection->activeAuthorStyleSheets());
 }
 
-void StyleResolver::addStylesheetsFromSeamlessParents()
-{
-    // Build a list of stylesheet lists from our ancestors, and walk that
-    // list in reverse order so that the root-most sheets are appended first.
-    Document* childDocument = document();
-    Vector<const Vector<RefPtr<CSSStyleSheet> >* > ancestorSheets;
-    while (HTMLIFrameElement* parentIFrame = childDocument->seamlessParentIFrame()) {
-        Document* parentDocument = parentIFrame->document();
-        ancestorSheets.append(&parentDocument->styleSheetCollection()->activeAuthorStyleSheets());
-        childDocument = parentDocument;
-    }
-    for (int i = ancestorSheets.size() - 1; i >= 0; i--)
-        appendAuthorStyleSheets(0, *ancestorSheets[i]);
-}
-
-void StyleResolver::addAuthorRulesAndCollectUserRulesFromSheets(const Vector<RefPtr<CSSStyleSheet> >* userSheets, RuleSet& userStyle)
+void StyleResolver::collectRulesFromUserStyleSheets(const Vector<RefPtr<CSSStyleSheet> >& userSheets)
 {
-    if (!userSheets)
-        return;
-
-    unsigned length = userSheets->size();
-    for (unsigned i = 0; i < length; i++) {
-        StyleSheetContents* sheet = userSheets->at(i)->contents();
-        if (sheet->isUserStyleSheet())
-            userStyle.addRulesFromSheet(sheet, *m_medium, this);
-        else
-            m_authorStyle->addRulesFromSheet(sheet, *m_medium, this);
+    OwnPtr<RuleSet> userStyleRuleSet = RuleSet::create();
+    for (unsigned i = 0; i < userSheets.size(); ++i) {
+        ASSERT(userSheets[i]->contents()->isUserStyleSheet());
+        userStyleRuleSet->addRulesFromSheet(userSheets[i]->contents(), *m_medium, this);
     }
+    if (userStyleRuleSet->m_ruleCount > 0 || userStyleRuleSet->m_pageRules.size() > 0)
+        m_userStyle = userStyleRuleSet.release();
 }
 
 static PassOwnPtr<RuleSet> makeRuleSet(const Vector<RuleFeature>& rules)
@@ -427,6 +395,10 @@ void StyleResolver::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefP
     
     if (document()->renderer() && document()->renderer()->style())
         document()->renderer()->style()->font().update(fontSelector());
+
+#if ENABLE(CSS_DEVICE_ADAPTATION)
+    viewportStyleResolver()->resolve();
+#endif
 }
 
 void StyleResolver::pushParentElement(Element* parent)
@@ -481,13 +453,17 @@ void StyleResolver::addKeyframeStyle(PassRefPtr<StyleRuleKeyframes> rule)
 StyleResolver::~StyleResolver()
 {
     m_fontSelector->clearDocument();
+
+#if ENABLE(CSS_DEVICE_ADAPTATION)
+    m_viewportStyleResolver->clearDocument();
+#endif
 }
 
 void StyleResolver::sweepMatchedPropertiesCache(Timer<StyleResolver>*)
 {
     // Look for cache entries containing a style declaration with a single ref and remove them.
-    // This may happen when an element attribute mutation causes it to generate a new attributeStyle(),
-    // potentially leaving this cache with the last ref on the old one.
+    // This may happen when an element attribute mutation causes it to generate a new inlineStyle()
+    // or presentationAttributeStyle(), potentially leaving this cache with the last ref on the old one.
     Vector<unsigned, 16> toRemove;
     MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.begin();
     MatchedPropertiesCache::iterator end = m_matchedPropertiesCache.end();
@@ -637,11 +613,56 @@ inline void StyleResolver::addElementStyleProperties(MatchResult& result, const
         result.isCacheable = false;
 }
 
+class MatchingUARulesScope {
+public:
+    MatchingUARulesScope();
+    ~MatchingUARulesScope();
+
+    static bool isMatchingUARules();
+
+private:
+    static bool m_matchingUARules;
+};
+
+MatchingUARulesScope::MatchingUARulesScope()
+{
+    ASSERT(!m_matchingUARules);
+    m_matchingUARules = true;
+}
+
+MatchingUARulesScope::~MatchingUARulesScope()
+{
+    m_matchingUARules = false;
+}
+
+inline bool MatchingUARulesScope::isMatchingUARules()
+{
+    return m_matchingUARules;
+}
+
+bool MatchingUARulesScope::m_matchingUARules = false;
+
 void StyleResolver::collectMatchingRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options)
 {
     ASSERT(rules);
     ASSERT(m_element);
 
+    const AtomicString& pseudoId = m_element->shadowPseudoId();
+    if (!pseudoId.isEmpty()) {
+        ASSERT(m_styledElement);
+        collectMatchingRulesForList(rules->shadowPseudoElementRules(pseudoId.impl()), firstRuleIndex, lastRuleIndex, options);
+    }
+
+    // Check whether other types of rules are applicable in the current tree scope. Criteria for this:
+    // a) it's a UA rule
+    // b) the tree scope allows author rules
+    // c) the rules comes from a scoped style sheet within the same tree scope
+    TreeScope* treeScope = m_element->treeScope();
+    if (!MatchingUARulesScope::isMatchingUARules()
+        && !treeScope->applyAuthorStyles()
+        && (!options.scope || options.scope->treeScope() != treeScope))
+        return;
+
     // We need to collect the rules for id, class, tag, and everything else into a buffer and
     // then sort the buffer.
     if (m_element->hasID())
@@ -650,11 +671,7 @@ void StyleResolver::collectMatchingRules(RuleSet* rules, int& firstRuleIndex, in
         for (size_t i = 0; i < m_styledElement->classNames().size(); ++i)
             collectMatchingRulesForList(rules->classRules(m_styledElement->classNames()[i].impl()), firstRuleIndex, lastRuleIndex, options);
     }
-    const AtomicString& pseudoId = m_element->shadowPseudoId();
-    if (!pseudoId.isEmpty()) {
-        ASSERT(m_styledElement);
-        collectMatchingRulesForList(rules->shadowPseudoElementRules(pseudoId.impl()), firstRuleIndex, lastRuleIndex, options);
-    }
+
     if (m_element->isLink())
         collectMatchingRulesForList(rules->linkPseudoClassRules(), firstRuleIndex, lastRuleIndex, options);
     if (m_checker.matchesFocusPseudoClass(m_element))
@@ -818,42 +835,11 @@ void StyleResolver::matchUARules(MatchResult& result, RuleSet* rules)
     sortAndTransferMatchedRules(result);
 }
 
-class MatchingUARulesScope {
-public:
-    MatchingUARulesScope();
-    ~MatchingUARulesScope();
-
-    static bool isMatchingUARules();
-
-private:
-    static bool m_matchingUARules;
-};
-
-MatchingUARulesScope::MatchingUARulesScope()
-{
-    ASSERT(!m_matchingUARules);
-    m_matchingUARules = true;
-}
-
-MatchingUARulesScope::~MatchingUARulesScope()
-{
-    m_matchingUARules = false;
-}
-
-inline bool MatchingUARulesScope::isMatchingUARules()
-{
-    return m_matchingUARules;
-}
-
-bool MatchingUARulesScope::m_matchingUARules = false;
-
 void StyleResolver::collectMatchingRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options)
 {
     if (!rules)
         return;
 
-    TreeScope* treeScope = m_element->treeScope();
-
     // In some cases we may end up looking up style for random elements in the middle of a recursive tree resolve.
     // Ancestor identifier filter won't be up-to-date in that case and we can't use the fast path.
     bool canUseFastReject = m_checker.parentStackIsConsistent(m_parentNode);
@@ -867,19 +853,6 @@ void StyleResolver::collectMatchingRulesForList(const Vector<RuleData>* rules, i
         StyleRule* rule = ruleData.rule();
         InspectorInstrumentationCookie cookie = InspectorInstrumentation::willMatchRule(document(), rule);
         if (checkSelector(ruleData, options.scope)) {
-            // Check whether the rule is applicable in the current tree scope. Criteria for this:
-            // a) it's a UA rule
-            // b) the tree scope allows author rules
-            // c) the rules comes from a scoped style sheet within the same tree scope
-            // d) the rule contains shadow-ID pseudo elements
-            if (!MatchingUARulesScope::isMatchingUARules()
-                && !treeScope->applyAuthorStyles()
-                && (!options.scope || options.scope->treeScope() != treeScope)
-                && !m_hasUnknownPseudoElements) {
-
-                InspectorInstrumentation::didMatchRule(cookie, false);
-                continue;
-            }
             // If the rule has no properties to apply, then ignore it in the non-debug mode.
             const StylePropertySet* properties = rule->properties();
             if (!properties || (properties->isEmpty() && !options.includeEmptyRules)) {
@@ -938,12 +911,12 @@ void StyleResolver::matchAllRules(MatchResult& result, bool includeSMILPropertie
         
     // Now check author rules, beginning first with presentational attributes mapped from HTML.
     if (m_styledElement) {
-        addElementStyleProperties(result, m_styledElement->attributeStyle());
+        addElementStyleProperties(result, m_styledElement->presentationAttributeStyle());
 
         // Now we check additional mapped declarations.
         // Tables and table cells share an additional mapped rule that must be applied
         // after all attributes, since their mapped style depends on the values of multiple attributes.
-        addElementStyleProperties(result, m_styledElement->additionalAttributeStyle());
+        addElementStyleProperties(result, m_styledElement->additionalPresentationAttributeStyle());
 
         if (m_styledElement->isHTMLElement()) {
             bool isAuto;
@@ -993,21 +966,10 @@ inline bool shouldResetStyleInheritance(NodeRenderingContext& context)
     if (context.resetStyleInheritance())
         return true;
 
-    InsertionPoint* insertionPoint = context.insertionPoint();
-    if (!insertionPoint)
-        return false;
-
-    ASSERT(parentElementForDistribution(context.node()));
-    ElementShadow* shadow = parentElementForDistribution(context.node())->shadow();
-    ASSERT(shadow);
+    if (InsertionPoint* insertionPoint = context.insertionPoint())
+        return insertionPoint->resetStyleInheritance();
 
-    for ( ; insertionPoint; ) {
-        InsertionPoint* youngerInsertionPoint = shadow->insertionPointFor(insertionPoint);
-        if (!youngerInsertionPoint)
-            break;
-        insertionPoint = youngerInsertionPoint;
-    }
-    return insertionPoint->resetStyleInheritance();
+    return false;
 }
 
 inline void StyleResolver::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID)
@@ -1112,8 +1074,12 @@ bool StyleResolver::canShareStyleWithControl(StyledElement* element) const
     if (!thisInputElement || !otherInputElement)
         return false;
 
-    if (thisInputElement->fastGetAttribute(typeAttr) != otherInputElement->fastGetAttribute(typeAttr))
-        return false;
+    if (thisInputElement->attributeData() != otherInputElement->attributeData()) {
+        if (thisInputElement->fastGetAttribute(typeAttr) != otherInputElement->fastGetAttribute(typeAttr))
+            return false;
+        if (thisInputElement->fastGetAttribute(readonlyAttr) != otherInputElement->fastGetAttribute(readonlyAttr))
+            return false;
+    }
 
     if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled())
         return false;
@@ -1158,10 +1124,10 @@ static inline bool attributeStylesEqual(const StylePropertySet* a, const StylePr
         return false;
     unsigned propertyCount = a->propertyCount();
     for (unsigned i = 0; i < propertyCount; ++i) {
-        const CSSProperty& aProperty = a->propertyAt(i);
+        StylePropertySet::PropertyReference aProperty = a->propertyAt(i);
         unsigned j;
         for (j = 0; j < propertyCount; ++j) {
-            const CSSProperty& bProperty = b->propertyAt(j);
+            StylePropertySet::PropertyReference bProperty = b->propertyAt(j);
             if (aProperty.id() != bProperty.id())
                 continue;
             // We could get a few more hits by comparing cssText() here, but that gets expensive quickly.
@@ -1181,6 +1147,39 @@ static inline bool elementHasDirectionAuto(Element* element)
     return element->isHTMLElement() && toHTMLElement(element)->hasDirectionAuto();
 }
 
+static inline bool haveIdenticalStyleAffectingAttributes(StyledElement* a, StyledElement* b)
+{
+    if (a->attributeData() == b->attributeData())
+        return true;
+    if (a->fastGetAttribute(XMLNames::langAttr) != b->fastGetAttribute(XMLNames::langAttr))
+        return false;
+    if (a->fastGetAttribute(langAttr) != b->fastGetAttribute(langAttr))
+        return false;
+    if (a->hasClass()) {
+#if ENABLE(SVG)
+        // SVG elements require a (slow!) getAttribute comparision because "class" is an animatable attribute for SVG.
+        if (a->isSVGElement()) {
+            if (a->getAttribute(classAttr) != b->getAttribute(classAttr))
+                return false;
+        } else
+#endif
+        if (a->attributeData()->classNames() != b->attributeData()->classNames())
+            return false;
+    }
+
+    if (a->presentationAttributeStyle() && !attributeStylesEqual(a->presentationAttributeStyle(), b->presentationAttributeStyle()))
+        return false;
+
+#if ENABLE(PROGRESS_ELEMENT)
+    if (a->hasTagName(progressTag)) {
+        if (static_cast<HTMLProgressElement*>(a)->isDeterminate() != static_cast<HTMLProgressElement*>(b)->isDeterminate())
+            return false;
+    }
+#endif
+
+    return true;
+}
+
 bool StyleResolver::canShareStyleWithElement(StyledElement* element) const
 {
     RenderStyle* style = element->renderStyle();
@@ -1201,11 +1200,11 @@ bool StyleResolver::canShareStyleWithElement(StyledElement* element) const
     if (element->isSVGElement() && static_cast<SVGElement*>(element)->animatedSMILStyleProperties())
         return false;
 #endif
-    if (!!element->attributeStyle() != !!m_styledElement->attributeStyle())
+    if (!!element->presentationAttributeStyle() != !!m_styledElement->presentationAttributeStyle())
         return false;
-    const StylePropertySet* additionalAttributeStyleA = element->additionalAttributeStyle();
-    const StylePropertySet* additionalAttributeStyleB = m_styledElement->additionalAttributeStyle();
-    if (!additionalAttributeStyleA != !additionalAttributeStyleB)
+    const StylePropertySet* additionalPresentationAttributeStyleA = element->additionalPresentationAttributeStyle();
+    const StylePropertySet* additionalPresentationAttributeStyleB = m_styledElement->additionalPresentationAttributeStyle();
+    if (!additionalPresentationAttributeStyleA != !additionalPresentationAttributeStyleB)
         return false;
     if (element->isLink() != m_element->isLink())
         return false;
@@ -1221,33 +1220,15 @@ bool StyleResolver::canShareStyleWithElement(StyledElement* element) const
         return false;
     if (element == element->document()->cssTarget())
         return false;
-    if (m_element == m_element->document()->cssTarget())
-        return false;
-    if (element->fastGetAttribute(XMLNames::langAttr) != m_element->fastGetAttribute(XMLNames::langAttr))
-        return false;
-    if (element->fastGetAttribute(langAttr) != m_element->fastGetAttribute(langAttr))
-        return false;
-    if (element->fastGetAttribute(readonlyAttr) != m_element->fastGetAttribute(readonlyAttr))
-        return false;
-    if (element->fastGetAttribute(cellpaddingAttr) != m_element->fastGetAttribute(cellpaddingAttr))
+
+    if (!haveIdenticalStyleAffectingAttributes(element, m_styledElement))
         return false;
+
     if (element->hasID() && m_features.idsInRules.contains(element->idForStyleResolution().impl()))
         return false;
     if (element->hasScopedHTMLStyleChild())
         return false;
 
-#if ENABLE(PROGRESS_ELEMENT)
-    if (element->hasTagName(progressTag)) {
-        if (!m_element->hasTagName(progressTag))
-            return false;
-
-        HTMLProgressElement* thisProgressElement = static_cast<HTMLProgressElement*>(element);
-        HTMLProgressElement* otherProgressElement = static_cast<HTMLProgressElement*>(m_element);
-        if (thisProgressElement->isDeterminate() != otherProgressElement->isDeterminate())
-            return false;
-    }
-#endif
-
     // FIXME: We should share style for option and optgroup whenever possible.
     // Before doing so, we need to resolve issues in HTMLSelectElement::recalcListItems
     // and RenderMenuList::setText. See also https://bugs.webkit.org/show_bug.cgi?id=88405
@@ -1277,25 +1258,10 @@ bool StyleResolver::canShareStyleWithElement(StyledElement* element) const
         return false;
 #endif
 
-    if (elementHasDirectionAuto(element) || elementHasDirectionAuto(m_element))
-        return false;
-
-    if (element->hasClass()) {
-#if ENABLE(SVG)
-        // SVG elements require a (slow!) getAttribute comparision because "class" is an animatable attribute for SVG.
-        if (element->isSVGElement()) {
-            if (element->getAttribute(classAttr) != m_element->getAttribute(classAttr))
-                return false;
-        } else
-#endif
-        if (element->fastGetAttribute(classAttr) != m_element->fastGetAttribute(classAttr))
-            return false;
-    }
-
-    if (element->attributeStyle() && !attributeStylesEqual(element->attributeStyle(), m_styledElement->attributeStyle()))
+    if (elementHasDirectionAuto(element))
         return false;
 
-    if (additionalAttributeStyleA && !attributeStylesEqual(additionalAttributeStyleA, additionalAttributeStyleB))
+    if (additionalPresentationAttributeStyleA && !attributeStylesEqual(additionalPresentationAttributeStyleA, additionalPresentationAttributeStyleB))
         return false;
 
     if (element->isLink() && m_elementLinkState != style->insideLink())
@@ -1343,6 +1309,10 @@ RenderStyle* StyleResolver::locateSharedStyle()
         return 0;
     if (m_styledElement->hasScopedHTMLStyleChild())
         return 0;
+    if (m_element == m_element->document()->cssTarget())
+        return 0;
+    if (elementHasDirectionAuto(m_element))
+        return 0;
 
     // Check previous siblings and their cousins.
     unsigned count = 0;
@@ -1576,9 +1546,10 @@ PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS
     // contenteditable attribute (implemented by -webkit-user-modify) should
     // be propagated from shadow host to distributed node.
     if (m_distributedToInsertionPoint) {
-        ASSERT(element->parentElement());
-        if (RenderStyle* styleOfShadowHost = element->parentElement()->renderStyle())
-            m_style->setUserModify(styleOfShadowHost->userModify());
+        if (Element* parent = element->parentElement()) {
+            if (RenderStyle* styleOfShadowHost = parent->renderStyle())
+                m_style->setUserModify(styleOfShadowHost->userModify());
+        }
     }
 
     if (element->isLink()) {
@@ -1999,6 +1970,9 @@ void StyleResolver::adjustRenderStyle(RenderStyle* style, RenderStyle* parentSty
         // Touch overflow scrolling creates a stacking context.
         || ((style->overflowX() != OHIDDEN || style->overflowY() != OHIDDEN) && style->useTouchOverflowScrolling())
 #endif
+#if ENABLE(DIALOG_ELEMENT)
+        || (e && e->isInTopLayer())
+#endif
         ))
         style->setZIndex(0);
 
@@ -2196,7 +2170,6 @@ PassRefPtr<CSSRuleList> StyleResolver::pseudoStyleRulesForElement(Element* e, Ps
 inline bool StyleResolver::checkSelector(const RuleData& ruleData, const ContainerNode* scope)
 {
     m_dynamicPseudo = NOPSEUDO;
-    m_hasUnknownPseudoElements = false;
 
     if (ruleData.hasFastCheckableSelector()) {
         // We know this selector does not include any pseudo elements.
@@ -2220,7 +2193,7 @@ inline bool StyleResolver::checkSelector(const RuleData& ruleData, const Contain
     context.elementParentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
     context.scope = scope;
     context.pseudoStyle = m_pseudoStyle;
-    SelectorChecker::SelectorMatch match = m_checker.checkSelector(context, m_dynamicPseudo, m_hasUnknownPseudoElements);
+    SelectorChecker::SelectorMatch match = m_checker.checkSelector(context, m_dynamicPseudo);
     if (match != SelectorChecker::SelectorMatches)
         return false;
     if (m_pseudoStyle != NOPSEUDO && m_pseudoStyle != m_dynamicPseudo)
@@ -2233,7 +2206,6 @@ bool StyleResolver::checkRegionSelector(CSSSelector* regionSelector, Element* re
     if (!regionSelector || !regionElement)
         return false;
 
-    m_hasUnknownPseudoElements = false;
     m_pseudoStyle = NOPSEUDO;
 
     for (CSSSelector* s = regionSelector; s; s = CSSSelectorList::next(s))
@@ -2264,7 +2236,7 @@ void StyleResolver::applyProperties(const StylePropertySet* properties, StyleRul
 
     unsigned propertyCount = properties->propertyCount();
     for (unsigned i = 0; i < propertyCount; ++i) {
-        const CSSProperty& current = properties->propertyAt(i);
+        StylePropertySet::PropertyReference current = properties->propertyAt(i);
         if (isImportant != current.isImportant())
             continue;
         if (inheritedOnly && !current.isInherited()) {
@@ -2423,6 +2395,8 @@ static bool isCacheableInMatchedPropertiesCache(const Element* element, const Re
         return false;
     if (style->zoom() != RenderStyle::initialZoom())
         return false;
+    if (style->writingMode() != RenderStyle::initialWritingMode())
+        return false;
     // The cache assumes static knowledge about which properties are inherited.
     if (parentStyle->hasExplicitlyInheritedProperties())
         return false;
@@ -2609,27 +2583,16 @@ static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wra
     collectCSSOMWrappers(wrapperMap, styleSheetWrapper.get());
 }
 
-static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wrapperMap, DocumentStyleSheetCollection* styleSheetCollection)
+static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wrapperMap, const Vector<RefPtr<CSSStyleSheet> >& sheets)
 {
-    const Vector<RefPtr<CSSStyleSheet> >& styleSheets = styleSheetCollection->activeAuthorStyleSheets();
-    for (unsigned i = 0; i < styleSheets.size(); ++i)
-        collectCSSOMWrappers(wrapperMap, styleSheets[i].get());
+    for (unsigned i = 0; i < sheets.size(); ++i)
+        collectCSSOMWrappers(wrapperMap, sheets[i].get());
+}
 
-    collectCSSOMWrappers(wrapperMap, styleSheetCollection->pageUserSheet());
-    {
-        const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets = styleSheetCollection->pageGroupUserSheets();
-        if (pageGroupUserSheets) {
-            for (size_t i = 0, size = pageGroupUserSheets->size(); i < size; ++i)
-                collectCSSOMWrappers(wrapperMap, pageGroupUserSheets->at(i).get());
-        }
-    }
-    {
-        const Vector<RefPtr<CSSStyleSheet> >* documentUserSheets = styleSheetCollection->documentUserSheets();
-        if (documentUserSheets) {
-            for (size_t i = 0, size = documentUserSheets->size(); i < size; ++i)
-                collectCSSOMWrappers(wrapperMap, documentUserSheets->at(i).get());
-        }
-    }
+static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wrapperMap, DocumentStyleSheetCollection* styleSheetCollection)
+{
+    collectCSSOMWrappers(wrapperMap, styleSheetCollection->activeAuthorStyleSheets());
+    collectCSSOMWrappers(wrapperMap, styleSheetCollection->activeUserStyleSheets());
 }
 
 CSSStyleRule* StyleResolver::ensureFullCSSOMWrapperForInspector(StyleRule* rule)
@@ -2768,7 +2731,7 @@ static bool createGridTrackList(CSSValue* value, Vector<Length>& lengths, StyleR
 }
 
 
-static bool createGridPosition(CSSValue* value, Length& position)
+static bool createGridPosition(CSSValue* value, GridPosition& position)
 {
     // For now, we only accept: <integer> | 'auto'
     if (!value->isPrimitiveValue())
@@ -2779,7 +2742,7 @@ static bool createGridPosition(CSSValue* value, Length& position)
         return true;
 
     ASSERT(primitiveValue->isNumber());
-    position.setValue(primitiveValue->getIntValue());
+    position.setIntegerPosition(primitiveValue->getIntValue());
     return true;
 }
 
@@ -2817,7 +2780,7 @@ void StyleResolver::resolveVariables(CSSPropertyID id, CSSValue* value, Vector<s
         return; // expression failed to parse.
 
     for (unsigned i = 0; i < resultSet->propertyCount(); i++) {
-        const CSSProperty& property = resultSet->propertyAt(i);
+        StylePropertySet::PropertyReference property = resultSet->propertyAt(i);
         if (property.id() != CSSPropertyVariable && hasVariableReference(property.value()))
             resolveVariables(property.id(), property.value(), knownExpressions);
         else
@@ -2840,13 +2803,14 @@ void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
     bool isInitial = value->isInitialValue() || (!m_parentNode && value->isInheritedValue());
 
     ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
+    ASSERT(!isInherit || (m_parentNode && m_parentStyle)); // isInherit -> (m_parentNode && m_parentStyle)
 
     if (!applyPropertyToRegularStyle() && (!applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
         // Limit the properties that can be applied to only the ones honored by :visited.
         return;
     }
 
-    if (isInherit && m_parentStyle && !m_parentStyle->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id))
+    if (isInherit && !m_parentStyle->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id))
         m_parentStyle->setHasExplicitlyInheritedProperties();
 
 #if ENABLE(CSS_VARIABLES)
@@ -2976,8 +2940,7 @@ void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
         }
     case CSSPropertyQuotes:
         if (isInherit) {
-            if (m_parentStyle)
-                m_style->setQuotes(m_parentStyle->quotes());
+            m_style->setQuotes(m_parentStyle->quotes());
             return;
         }
         if (isInitial) {
@@ -3624,14 +3587,14 @@ void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
     }
 
     case CSSPropertyWebkitGridColumn: {
-        Length column;
+        GridPosition column;
         if (!createGridPosition(value, column))
             return;
         m_style->setGridItemColumn(column);
         return;
     }
     case CSSPropertyWebkitGridRow: {
-        Length row;
+        GridPosition row;
         if (!createGridPosition(value, row))
             return;
         m_style->setGridItemRow(row);
@@ -3875,6 +3838,7 @@ void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
 #if ENABLE(CSS3_TEXT)
     case CSSPropertyWebkitTextDecorationLine:
     case CSSPropertyWebkitTextDecorationStyle:
+    case CSSPropertyWebkitTextAlignLast:
 #endif // CSS3_TEXT
     case CSSPropertyWebkitTextEmphasisColor:
     case CSSPropertyWebkitTextEmphasisPosition:
@@ -3899,8 +3863,8 @@ void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
 #if ENABLE(CSS_EXCLUSIONS)
     case CSSPropertyWebkitWrap:
     case CSSPropertyWebkitWrapFlow:
-    case CSSPropertyWebkitWrapMargin:
-    case CSSPropertyWebkitWrapPadding:
+    case CSSPropertyWebkitShapeMargin:
+    case CSSPropertyWebkitShapePadding:
     case CSSPropertyWebkitWrapThrough:
     case CSSPropertyWebkitShapeInside:
     case CSSPropertyWebkitShapeOutside:
@@ -3913,6 +3877,12 @@ void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
     case CSSPropertyWordWrap:
     case CSSPropertyZIndex:
     case CSSPropertyZoom:
+#if ENABLE(CSS_DEVICE_ADAPTATION)
+    case CSSPropertyMaxZoom:
+    case CSSPropertyMinZoom:
+    case CSSPropertyOrientation:
+    case CSSPropertyUserZoom:
+#endif
         ASSERT_NOT_REACHED();
         return;
 #if ENABLE(SVG)
@@ -4272,18 +4242,6 @@ Color StyleResolver::colorFromPrimitiveValue(CSSPrimitiveValue* value, bool forV
     }
 }
 
-bool StyleResolver::hasSelectorForAttribute(const AtomicString &attrname) const
-{
-    return m_features.attrsInRules.contains(attrname.impl());
-}
-
-bool StyleResolver::hasSelectorForId(const AtomicString& idValue) const
-{
-    if (idValue.isEmpty())
-        return false;
-    return m_features.idsInRules.contains(idValue.impl());
-}
-
 void StyleResolver::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result)
 {
     m_viewportDependentMediaQueryResults.append(adoptPtr(new MediaQueryResult(*expr, result)));
@@ -4616,7 +4574,7 @@ void StyleResolver::loadPendingSVGDocuments()
         return;
 
     CachedResourceLoader* cachedResourceLoader = m_element->document()->cachedResourceLoader();
-    Vector<RefPtr<FilterOperation> >& filterOperations = m_style->filter().operations();
+    Vector<RefPtr<FilterOperation> >& filterOperations = m_style->mutableFilter().operations();
     for (unsigned i = 0; i < filterOperations.size(); ++i) {
         RefPtr<FilterOperation> filterOperation = filterOperations.at(i);
         if (filterOperation->getOperationType() == FilterOperation::REFERENCE) {
@@ -4630,7 +4588,7 @@ void StyleResolver::loadPendingSVGDocuments()
                 continue;
 
             // Stash the CachedSVGDocument on the reference filter.
-            referenceFilter->setData(adoptPtr(new CachedSVGDocumentReference(cachedDocument)));
+            referenceFilter->setCachedSVGDocumentReference(adoptPtr(new CachedSVGDocumentReference(cachedDocument)));
         }
     }
     m_pendingSVGDocuments.clear();
@@ -4660,7 +4618,7 @@ void StyleResolver::loadPendingShaders()
 
     CachedResourceLoader* cachedResourceLoader = m_element->document()->cachedResourceLoader();
 
-    Vector<RefPtr<FilterOperation> >& filterOperations = m_style->filter().operations();
+    Vector<RefPtr<FilterOperation> >& filterOperations = m_style->mutableFilter().operations();
     for (unsigned i = 0; i < filterOperations.size(); ++i) {
         RefPtr<FilterOperation> filterOperation = filterOperations.at(i);
         if (filterOperation->getOperationType() == FilterOperation::CUSTOM) {
@@ -4809,16 +4767,18 @@ PassRefPtr<CustomFilterOperation> StyleResolver::createCustomFilterOperation(Web
     ASSERT(shadersValue->isValueList());
     CSSValueList* shadersList = static_cast<CSSValueList*>(shadersValue);
 
-    ASSERT(shadersList->length());
-    RefPtr<StyleShader> vertexShader = styleShader(shadersList->itemWithoutBoundsCheck(0));
+    unsigned shadersListLength = shadersList->length();
+    ASSERT(shadersListLength);
 
+    RefPtr<StyleShader> vertexShader = styleShader(shadersList->itemWithoutBoundsCheck(0));
     RefPtr<StyleShader> fragmentShader;
-    CustomFilterProgramType programType = PROGRAM_TYPE_NO_ELEMENT_TEXTURE;
+    CustomFilterProgramType programType = PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE;
     CustomFilterProgramMixSettings mixSettings;
-    if (shadersList->length() > 1) {
+
+    if (shadersListLength > 1) {
         CSSValue* fragmentShaderOrMixFunction = shadersList->itemWithoutBoundsCheck(1);
+
         if (fragmentShaderOrMixFunction->isWebKitCSSMixFunctionValue()) {
-            programType = PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE;
             WebKitCSSMixFunctionValue* mixFunction = static_cast<WebKitCSSMixFunctionValue*>(fragmentShaderOrMixFunction);
             CSSValueListIterator iterator(mixFunction);
 
@@ -4837,14 +4797,16 @@ PassRefPtr<CustomFilterOperation> StyleResolver::createCustomFilterOperation(Web
                     ASSERT_NOT_REACHED();
                 iterator.advance();
             }
-        } else
+        } else {
+            programType = PROGRAM_TYPE_NO_ELEMENT_TEXTURE;
             fragmentShader = styleShader(fragmentShaderOrMixFunction);
+        }
     }
     
     unsigned meshRows = 1;
     unsigned meshColumns = 1;
-    CustomFilterOperation::MeshBoxType meshBoxType = CustomFilterOperation::FILTER_BOX;
-    CustomFilterOperation::MeshType meshType = CustomFilterOperation::ATTACHED;
+    CustomFilterMeshBoxType meshBoxType = MeshBoxTypeFilter;
+    CustomFilterMeshType meshType = MeshTypeAttached;
     
     CSSValue* parametersValue = 0;
     
@@ -4888,7 +4850,7 @@ PassRefPtr<CustomFilterOperation> StyleResolver::createCustomFilterOperation(Web
         if (iterator.hasMore() && iterator.isPrimitiveValue()) {
             CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(iterator.value());
             if (primitiveValue->getIdent() == CSSValueDetached) {
-                meshType = CustomFilterOperation::DETACHED;
+                meshType = MeshTypeDetached;
                 iterator.advance();
             }
         }
@@ -4908,7 +4870,7 @@ PassRefPtr<CustomFilterOperation> StyleResolver::createCustomFilterOperation(Web
     if (parametersValue && !parseCustomFilterParameterList(parametersValue, parameterList))
         return 0;
     
-    RefPtr<StyleCustomFilterProgram> program = StyleCustomFilterProgram::create(vertexShader.release(), fragmentShader.release(), programType, mixSettings);
+    RefPtr<StyleCustomFilterProgram> program = StyleCustomFilterProgram::create(vertexShader.release(), fragmentShader.release(), programType, mixSettings, meshType);
     return CustomFilterOperation::create(program.release(), parameterList, meshRows, meshColumns, meshBoxType, meshType);
 }
 #endif
@@ -4940,6 +4902,11 @@ bool StyleResolver::createFilterOperations(CSSValue* inValue, RenderStyle* style
         FilterOperation::OperationType operationType = filterOperationForType(filterValue->operationType());
 
 #if ENABLE(CSS_SHADERS)
+        if (operationType == FilterOperation::VALIDATED_CUSTOM) {
+            // ValidatedCustomFilterOperation is not supposed to end up in the RenderStyle.
+            ASSERT_NOT_REACHED();
+            continue;
+        }
         if (operationType == FilterOperation::CUSTOM) {
             RefPtr<CustomFilterOperation> operation = createCustomFilterOperation(filterValue);
             if (!operation)
@@ -4965,8 +4932,8 @@ bool StyleResolver::createFilterOperations(CSSValue* inValue, RenderStyle* style
             if (SVGURIReference::isExternalURIReference(svgDocumentValue->url(), m_element->document())) {
                 if (!svgDocumentValue->loadRequested())
                     m_pendingSVGDocuments.set(operation.get(), svgDocumentValue);
-                else
-                    operation->setData(adoptPtr(new CachedSVGDocumentReference(svgDocumentValue->cachedSVGDocument())));
+                else if (svgDocumentValue->cachedSVGDocument())
+                    operation->setCachedSVGDocumentReference(adoptPtr(new CachedSVGDocumentReference(svgDocumentValue->cachedSVGDocument())));
             }
             operations.operations().append(operation);
 #endif
@@ -5072,7 +5039,7 @@ PassRefPtr<StyleImage> StyleResolver::loadPendingImage(StylePendingImage* pendin
 
     if (pendingImage->cssImageValue()) {
         CSSImageValue* imageValue = pendingImage->cssImageValue();
-        return imageValue->cachedImage(cachedResourceLoader);
+        return imageValue->cachedImage(cachedResourceLoader, m_element);
     }
 
     if (pendingImage->cssImageGeneratorValue()) {