WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-88606-20121009182434.patch (text/plain), 39.69 KB, created by
Takashi Sakamoto
on 2012-10-09 02:25:33 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Takashi Sakamoto
Created:
2012-10-09 02:25:33 PDT
Size:
39.69 KB
patch
obsolete
>Subversion Revision: 130708 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 130a56c4aed9b41697280a668e41833c36ca7798..60083552b4842ad04cf3962c1d578e80abf91524 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,102 @@ >+2012-10-09 Takashi Sakamoto <tasak@google.com> >+ >+ [Shadow DOM] Needs @host rule for ShadowDOM styling >+ https://bugs.webkit.org/show_bug.cgi?id=88606 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Implemented @host-@rules according to the shadow dom spec: >+ http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#host-at-rule >+ The design doc is: >+ https://docs.google.com/document/d/1P2yorchF8lci2sccr-mVSRf2dtvjKeiuyQWzCB2bEA8/edit >+ >+ Test: fast/dom/shadow/athost-atrules.html >+ >+ * css/CSSGrammar.y: >+ Added rules for parsing @host @-rules. >+ * css/CSSParser.cpp: >+ (WebCore::CSSParser::detectAtToken): >+ Added a new token "@host". >+ (WebCore::CSSParser::createHostRule): >+ Added a new method to create an @host @-rule, which is invoked from >+ CSSGrammar.y. >+ (WebCore): >+ * css/CSSParser.h: >+ Added a declaration of the above new method: createHostRule. >+ * css/CSSPropertySourceData.h: >+ Added HOST_RULE to enum Type. >+ * css/RuleSet.cpp: >+ (WebCore::RuleData::RuleData): >+ Modified multiple bool arguments into one unsigned argument. Now it >+ uses combinations of values from enum AddRuleState. >+ (WebCore::RuleSet::addRule): >+ (WebCore::RuleSet::addRegionRule): >+ (WebCore::RuleSet::addRulesFromSheet): >+ (WebCore::RuleSet::addStyleRule): >+ Updated according to the RuleData's change. >+ Modified to Invoke increaseSpecificity if the given rule is @host >+ @-rule. >+ * css/RuleSet.h: >+ (RuleData): >+ (WebCore::RuleData::increaseSpecificity): >+ Added a new method to increase selector's specificity. This method is >+ used to make @host @-rules' specificity larger than normal author >+ rules' specificity. >+ (RuleSet): >+ * css/StyleResolver.cpp: >+ (WebCore::makeRuleSet): >+ Updated according to addRule's change. >+ (WebCore::StyleResolver::addHostRule): >+ Added a new method to register @host @-rules with shadow roots. >+ (WebCore): >+ (WebCore::StyleResolver::atHostRuleSetForScope): >+ Added a new method for finding rulesets from the given shadow root. >+ (WebCore::StyleResolver::matchesHostRules): >+ A new method to check whether any @host @-rules will be applied to >+ the given element or not. This is prepared for shared styles. >+ (WebCore::StyleResolver::matchHostRules): >+ A new method to find matched host rules when an element is given. >+ (WebCore::StyleResolver::matchAuthorRules): >+ Modified to invoke matchHostRules. >+ (WebCore::StyleResolver::locateSharedStyle): >+ Disable sibling style cache if the given element is a shadow host and >+ any @host @-rules are applied to the element. >+ * css/StyleResolver.h: >+ (StyleResolver): >+ * css/StyleRule.cpp: >+ (WebCore::StyleRuleBase::reportMemoryUsage): >+ (WebCore::StyleRuleBase::destroy): >+ (WebCore::StyleRuleBase::copy): >+ (WebCore::StyleRuleBase::createCSSOMWrapper): >+ (WebCore::StyleRuleHost::StyleRuleHost): >+ Implemented class StyleRuleHost. The class is almost the same as >+ StyleRuleBlock except type. >+ (WebCore): >+ * css/StyleRule.h: >+ (WebCore::StyleRuleBase::isHostRule): >+ (StyleRuleHost): >+ (WebCore::StyleRuleHost::create): >+ (WebCore::StyleRuleHost::copy): >+ (WebCore): >+ * css/StyleSheetContents.cpp: >+ (WebCore::childRulesHaveFailedOrCanceledSubresources): >+ * dom/ElementShadow.cpp: >+ (WebCore::ElementShadow::ElementShadow): >+ (WebCore::ElementShadow::addShadowRoot): >+ Since a new shadow root is added, disable @host @-rules cache. >+ * dom/ElementShadow.h: >+ (WebCore::ElementShadow::hasMatchedHostRule): >+ (WebCore::ElementShadow::hasMatchedHostRuleAvailable): >+ (WebCore::ElementShadow::clearHasMatchedHostRule): >+ (WebCore::ElementShadow::setHasMatchedHostRule): >+ Added four methods for @host @-rules cache. The cache has information >+ about whether any @host @-rules match the ElementShadow's host. >+ The return value of hasMatchedHostRule is available only if >+ hasMatchedHostRuleAvailable returns true. >+ (ElementShadow): >+ * dom/ShadowRoot.cpp: >+ (WebCore::ShadowRoot::childrenChanged): >+ > 2012-10-08 Alec Flett <alecflett@chromium.org> > > IndexedDB: remove autogenerated objectStore/index id code >diff --git a/Source/WebCore/css/CSSGrammar.y b/Source/WebCore/css/CSSGrammar.y >index 2b4274a9b32a35a296688f65b3b38af24ba3b40d..8faa134077e514a7b3078b39c90b9cdfa4cd8481 100644 >--- a/Source/WebCore/css/CSSGrammar.y >+++ b/Source/WebCore/css/CSSGrammar.y >@@ -132,6 +132,7 @@ static inline int cssyyerror(void*, const char*) > %token PAGE_SYM > %token MEDIA_SYM > %token FONT_FACE_SYM >+%token HOST_SYM > %token CHARSET_SYM > %token NAMESPACE_SYM > %token VARFUNCTION >@@ -219,6 +220,7 @@ static inline int cssyyerror(void*, const char*) > %type <rule> page > %type <rule> margin_box > %type <rule> font_face >+%type <rule> host > %type <rule> keyframes > %type <rule> invalid_rule > %type <rule> save_block >@@ -419,6 +421,7 @@ valid_rule: > | namespace > | import > | region >+ | host > ; > > rule: >@@ -841,6 +844,23 @@ font_face: > } > ; > >+before_host_rule: >+ /* empty */ { >+ parser->markRuleHeaderStart(CSSRuleSourceData::HOST_RULE); >+ } >+ ; >+ >+host: >+ before_host_rule HOST_SYM at_rule_header_end_maybe_space >+ '{' at_rule_body_start maybe_space block_rule_list save_block { >+ $$ = parser->createHostRule($7); >+ } >+ | before_host_rule HOST_SYM at_rule_header_end_maybe_space ';' { >+ $$ = 0; >+ parser->popRuleData(); >+ } >+ ; >+ > region_selector: > selector_list { > if ($1) { >diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp >index b9dfbead41720882b605c091ddd7def22fc1d374..56ed4bf9d1a2fe290f8a03f57b5f16e2020cac37 100644 >--- a/Source/WebCore/css/CSSParser.cpp >+++ b/Source/WebCore/css/CSSParser.cpp >@@ -9176,6 +9176,11 @@ inline void CSSParser::detectAtToken(int length, bool hasEscape) > m_token = FONT_FACE_SYM; > return; > >+ case 'h': >+ if (length == 5 && isEqualToCSSIdentifier(name + 2, "ost")) >+ m_token = HOST_SYM; >+ return; >+ > case 'i': > if (length == 7 && isEqualToCSSIdentifier(name + 2, "mport")) { > m_parsingMode = MediaQueryMode; >@@ -9965,6 +9970,22 @@ StyleRuleBase* CSSParser::createFontFaceRule() > return result; > } > >+StyleRuleBase* CSSParser::createHostRule(RuleList* rules) >+{ >+ m_allowImportRules = m_allowNamespaceDeclarations = false; >+ RefPtr<StyleRuleHost> rule; >+ if (rules) >+ rule = StyleRuleHost::create(*rules); >+ else { >+ RuleList emptyRules; >+ rule = StyleRuleHost::create(emptyRules); >+ } >+ StyleRuleHost* result = rule.get(); >+ m_parsedRules.append(rule.release()); >+ processAndAddNewRuleToSourceTreeIfNeeded(); >+ return result; >+} >+ > void CSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri) > { > if (!m_styleSheet || !m_allowNamespaceDeclarations) >diff --git a/Source/WebCore/css/CSSParser.h b/Source/WebCore/css/CSSParser.h >index 71d73995d019b9c80a4711d85068b16b32726581..4e5f060493b806bf99d49530c8feca751ec4540d 100644 >--- a/Source/WebCore/css/CSSParser.h >+++ b/Source/WebCore/css/CSSParser.h >@@ -282,6 +282,7 @@ public: > StyleRuleBase* createPageRule(PassOwnPtr<CSSParserSelector> pageSelector); > StyleRuleBase* createRegionRule(CSSSelectorVector* regionSelector, RuleList* rules); > StyleRuleBase* createMarginAtRule(CSSSelector::MarginBoxType); >+ StyleRuleBase* createHostRule(RuleList* rules); > void startDeclarationsForMarginBox(); > void endDeclarationsForMarginBox(); > >diff --git a/Source/WebCore/css/CSSPropertySourceData.h b/Source/WebCore/css/CSSPropertySourceData.h >index 469bdb630c1a5c5dba993fd1ad59ed07449a55be..079ec3362495c07979b475afde77602384c9996f 100644 >--- a/Source/WebCore/css/CSSPropertySourceData.h >+++ b/Source/WebCore/css/CSSPropertySourceData.h >@@ -94,7 +94,8 @@ struct CSSRuleSourceData : public RefCounted<CSSRuleSourceData> { > FONT_FACE_RULE, > PAGE_RULE, > KEYFRAMES_RULE, >- REGION_RULE >+ REGION_RULE, >+ HOST_RULE > }; > > static PassRefPtr<CSSRuleSourceData> create(Type type) >diff --git a/Source/WebCore/css/RuleSet.cpp b/Source/WebCore/css/RuleSet.cpp >index e2be5771e025f14cf9a85de7e51cd9c5a1309059..dabca8f05650abe5046782e4800d99aa09db784e 100644 >--- a/Source/WebCore/css/RuleSet.cpp >+++ b/Source/WebCore/css/RuleSet.cpp >@@ -107,18 +107,18 @@ static inline bool containsUncommonAttributeSelector(const CSSSelector* selector > return false; > } > >-RuleData::RuleData(StyleRule* rule, unsigned selectorIndex, unsigned position, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool inRegionRule) >+RuleData::RuleData(StyleRule* rule, unsigned selectorIndex, unsigned position, unsigned addRuleState) > : m_rule(rule) > , m_selectorIndex(selectorIndex) > , m_position(position) > , m_specificity(selector()->specificity()) >- , m_hasFastCheckableSelector(canUseFastCheckSelector && SelectorChecker::isFastCheckableSelector(selector())) >+ , m_hasFastCheckableSelector((addRuleState & RuleCanUseFastCheckSelector) && SelectorChecker::isFastCheckableSelector(selector())) > , m_hasMultipartSelector(!!selector()->tagHistory()) > , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector())) > , m_containsUncommonAttributeSelector(WebCore::containsUncommonAttributeSelector(selector())) > , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector())) >- , m_hasDocumentSecurityOrigin(hasDocumentSecurityOrigin) >- , m_isInRegionRule(inRegionRule) >+ , m_hasDocumentSecurityOrigin(addRuleState & RuleHasDocumentSecurityOrigin) >+ , m_isInRegionRule(addRuleState & RuleIsInRegionRule) > { > ASSERT(m_position == position); > ASSERT(m_selectorIndex == selectorIndex); >@@ -207,9 +207,14 @@ void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, const RuleDa > rules->append(ruleData); > } > >-void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool inRegionRule) >+void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, unsigned addRuleState) > { >- RuleData ruleData(rule, selectorIndex, m_ruleCount++, hasDocumentSecurityOrigin, canUseFastCheckSelector, inRegionRule); >+ RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleState); >+ static const unsigned athostRuleSpecificity = 0x100000; >+ >+ if (addRuleState & RuleIsHostRule) >+ ruleData.increaseSpecificity(athostRuleSpecificity); >+ > collectFeaturesFromRuleData(m_features, ruleData); > > CSSSelector* selector = ruleData.selector(); >@@ -264,10 +269,12 @@ void RuleSet::addRegionRule(StyleRuleRegion* regionRule, bool hasDocumentSecurit > > // Collect the region rules into a rule set > const Vector<RefPtr<StyleRuleBase> >& childRules = regionRule->childRules(); >+ unsigned addRuleState = hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : 0; >+ addRuleState |= RuleCanUseFastCheckSelector | RuleIsInRegionRule; > for (unsigned i = 0; i < childRules.size(); ++i) { > StyleRuleBase* regionStylingRule = childRules[i].get(); > if (regionStylingRule->isStyleRule()) >- regionRuleSet->addStyleRule(static_cast<StyleRule*>(regionStylingRule), hasDocumentSecurityOrigin, true, true); >+ regionRuleSet->addStyleRule(static_cast<StyleRule*>(regionStylingRule), addRuleState); > } > // Update the "global" rule count so that proper order is maintained > m_ruleCount = regionRuleSet->m_ruleCount; >@@ -286,6 +293,7 @@ void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvalu > addRulesFromSheet(importRule->styleSheet(), medium, resolver, scope); > } > bool hasDocumentSecurityOrigin = resolver && resolver->document()->securityOrigin()->canRequest(sheet->baseURL()); >+ unsigned addRuleState = (hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : 0) | (!scope ? RuleCanUseFastCheckSelector : 0); > > const Vector<RefPtr<StyleRuleBase> >& rules = sheet->childRules(); > for (unsigned i = 0; i < rules.size(); ++i) { >@@ -293,7 +301,7 @@ void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvalu > > ASSERT(!rule->isImportRule()); > if (rule->isStyleRule()) >- addStyleRule(static_cast<StyleRule*>(rule), hasDocumentSecurityOrigin, !scope); >+ addStyleRule(static_cast<StyleRule*>(rule), addRuleState); > else if (rule->isPageRule()) > addPageRule(static_cast<StyleRulePage*>(rule)); > else if (rule->isMediaRule()) { >@@ -305,7 +313,7 @@ void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvalu > for (unsigned j = 0; j < childRules.size(); ++j) { > StyleRuleBase* childRule = childRules[j].get(); > if (childRule->isStyleRule()) >- addStyleRule(static_cast<StyleRule*>(childRule), hasDocumentSecurityOrigin, !scope); >+ addStyleRule(static_cast<StyleRule*>(childRule), addRuleState); > else if (childRule->isPageRule()) > addPageRule(static_cast<StyleRulePage*>(childRule)); > else if (childRule->isFontFaceRule() && resolver) { >@@ -347,15 +355,17 @@ void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvalu > addRegionRule(static_cast<StyleRuleRegion*>(rule), hasDocumentSecurityOrigin); > } > #endif >+ else if (rule->isHostRule()) >+ resolver->addHostRule(static_cast<StyleRuleHost*>(rule), hasDocumentSecurityOrigin, scope); > } > if (m_autoShrinkToFitEnabled) > shrinkToFit(); > } > >-void RuleSet::addStyleRule(StyleRule* rule, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool isInRegionRule) >+void RuleSet::addStyleRule(StyleRule* rule, unsigned addRuleState) > { > for (size_t selectorIndex = 0; selectorIndex != notFound; selectorIndex = rule->selectorList().indexOfNextSelectorAfter(selectorIndex)) >- addRule(rule, selectorIndex, hasDocumentSecurityOrigin, canUseFastCheckSelector, isInRegionRule); >+ addRule(rule, selectorIndex, addRuleState); > } > > static inline void shrinkMapVectorsToFit(RuleSet::AtomRuleMap& map) >diff --git a/Source/WebCore/css/RuleSet.h b/Source/WebCore/css/RuleSet.h >index 6577238ba9236a9d681039195a0dd43a2e8082a0..a3dafc9b6d8185300c566085639c7d21f2bdf678 100644 >--- a/Source/WebCore/css/RuleSet.h >+++ b/Source/WebCore/css/RuleSet.h >@@ -31,6 +31,13 @@ > > namespace WebCore { > >+enum AddRuleState { >+ RuleHasDocumentSecurityOrigin = 1, >+ RuleCanUseFastCheckSelector = 1 << 1, >+ RuleIsInRegionRule = 1 << 2, >+ RuleIsHostRule = 1 << 3, >+}; >+ > class CSSSelector; > class ContainerNode; > class MediaQueryEvaluator; >@@ -40,7 +47,7 @@ class StyleSheetContents; > > class RuleData { > public: >- RuleData(StyleRule*, unsigned selectorIndex, unsigned position, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool inRegionRule); >+ RuleData(StyleRule*, unsigned selectorIndex, unsigned position, unsigned addRuleState); > > unsigned position() const { return m_position; } > StyleRule* rule() const { return m_rule; } >@@ -55,6 +62,7 @@ public: > unsigned linkMatchType() const { return m_linkMatchType; } > bool hasDocumentSecurityOrigin() const { return m_hasDocumentSecurityOrigin; } > bool isInRegionRule() const { return m_isInRegionRule; } >+ void increaseSpecificity(unsigned value) { m_specificity += value; } > > // Try to balance between memory usage (there can be lots of RuleData objects) and good filtering performance. > static const unsigned maximumIdentifierCount = 4; >@@ -98,8 +106,8 @@ public: > > void addRulesFromSheet(StyleSheetContents*, const MediaQueryEvaluator&, StyleResolver* = 0, const ContainerNode* = 0); > >- void addStyleRule(StyleRule*, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool isInRegionRule = false); >- void addRule(StyleRule*, unsigned selectorIndex, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool isInRegionRule = false); >+ void addStyleRule(StyleRule*, unsigned addRuleState); >+ void addRule(StyleRule*, unsigned selectorIndex, unsigned addRuleState); > void addPageRule(StyleRulePage*); > void addToRuleSet(AtomicStringImpl* key, AtomRuleMap&, const RuleData&); > void addRegionRule(StyleRuleRegion*, bool hasDocumentSecurityOrigin); >diff --git a/Source/WebCore/css/StyleResolver.cpp b/Source/WebCore/css/StyleResolver.cpp >index 36c8b6b5f7a633468f9a3f5f183064b22184cac4..763ffd290331aa23b7c6d934f30370621aa1e0fb 100644 >--- a/Source/WebCore/css/StyleResolver.cpp >+++ b/Source/WebCore/css/StyleResolver.cpp >@@ -61,6 +61,7 @@ > #include "CounterContent.h" > #include "CursorList.h" > #include "DocumentStyleSheetCollection.h" >+#include "ElementShadow.h" > #include "FontFeatureValue.h" > #include "FontValue.h" > #include "Frame.h" >@@ -382,7 +383,7 @@ static PassOwnPtr<RuleSet> makeRuleSet(const Vector<RuleFeature>& rules) > return nullptr; > OwnPtr<RuleSet> ruleSet = RuleSet::create(); > for (size_t i = 0; i < size; ++i) >- ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].hasDocumentSecurityOrigin, false); >+ ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : 0); > ruleSet->shrinkToFit(); > return ruleSet.release(); > } >@@ -479,6 +480,31 @@ void StyleResolver::appendAuthorStylesheets(unsigned firstNew, const Vector<RefP > document()->renderer()->style()->font().update(fontSelector()); > } > >+void StyleResolver::addHostRule(StyleRuleHost* hostRule, bool hasDocumentSecurityOrigin, const ContainerNode* scope) >+{ >+ if (!scope || !scope->isInShadowTree()) >+ return; >+ >+ ShadowRoot* shadowRoot = scope->shadowRoot(); >+ if (!shadowRoot || !shadowRoot->host()) >+ return; >+ shadowRoot->owner()->clearHasMatchedHostRule(); >+ >+ ScopedRuleSetMap::AddResult addResult = m_atHostRules.add(shadowRoot, nullptr); >+ if (addResult.isNewEntry) >+ addResult.iterator->value = RuleSet::create(); >+ >+ const Vector<RefPtr<StyleRuleBase> >& childRules = hostRule->childRules(); >+ unsigned addStateRule = hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : 0; >+ addStateRule |= RuleCanUseFastCheckSelector | RuleIsHostRule; >+ for (unsigned i = 0; i < childRules.size(); ++i) { >+ StyleRuleBase* hostStylingRule = childRules[i].get(); >+ if (hostStylingRule->isStyleRule()) >+ addResult.iterator->value->addStyleRule(static_cast<StyleRule*>(hostStylingRule), addStateRule); >+ } >+} >+ >+ > #if ENABLE(STYLE_SCOPED) > void StyleResolver::setupScopeStack(const ContainerNode* parent) > { >@@ -844,6 +870,64 @@ void StyleResolver::matchScopedAuthorRules(MatchResult& result, bool includeEmpt > #endif > } > >+inline RuleSet* StyleResolver::atHostRuleSetForScope(const ShadowRoot* shadowRoot) >+{ >+ ScopedRuleSetMap::const_iterator it = m_atHostRules.find(shadowRoot); >+ return it != m_atHostRules.end() ? it->value.get() : 0; >+} >+ >+ >+bool StyleResolver::matchesHostRules() >+{ >+ if (m_atHostRules.isEmpty()) >+ return false; >+ >+ ElementShadow* shadow = m_element->shadow(); >+ if (!shadow) >+ return false; >+ if (shadow->hasMatchedHostRuleAvailable()) >+ return shadow->hasMatchedHostRule(); >+ >+ for (ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) { >+ if (atHostRuleSetForScope(shadowRoot)) { >+ shadow->setHasMatchedHostRule(true); >+ return true; >+ } >+ if (!shadowRoot->hasShadowInsertionPoint()) >+ break; >+ } >+ shadow->setHasMatchedHostRule(false); >+ return false; >+} >+ >+void StyleResolver::matchHostRules(MatchResult& result, bool includeEmptyRules) >+{ >+ if (m_atHostRules.isEmpty()) >+ return; >+ >+ ElementShadow* shadow = m_element->shadow(); >+ if (!shadow) >+ return; >+ // If Already know whether there exist any matched host rules or not, see. >+ if (shadow->hasMatchedHostRuleAvailable() && !shadow->hasMatchedHostRule()) >+ return; >+ >+ Vector<RuleSet*, 16> matchedRules; >+ for (ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) { >+ if (RuleSet* ruleSet = atHostRuleSetForScope(shadowRoot)) >+ matchedRules.append(ruleSet); >+ if (!shadowRoot->hasShadowInsertionPoint()) >+ break; >+ } >+ if (matchedRules.isEmpty()) >+ return; >+ >+ MatchOptions options(includeEmptyRules); >+ options.scope = m_element; >+ for (unsigned i = matchedRules.size(); i > 0; --i) >+ collectMatchingRules(matchedRules.at(i-1), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options); >+} >+ > void StyleResolver::matchAuthorRules(MatchResult& result, bool includeEmptyRules) > { > m_matchedRules.clear(); >@@ -858,6 +942,7 @@ void StyleResolver::matchAuthorRules(MatchResult& result, bool includeEmptyRules > collectMatchingRulesForRegion(m_authorStyle.get(), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options); > > matchScopedAuthorRules(result, includeEmptyRules); >+ matchHostRules(result, includeEmptyRules); > > sortAndTransferMatchedRules(result); > } >@@ -1425,6 +1510,9 @@ RenderStyle* StyleResolver::locateSharedStyle() > // Can't share if attribute rules apply. > if (matchesRuleSet(m_uncommonAttributeRuleSet.get())) > return 0; >+ // Can't share if @host @-rules apply. >+ if (matchesHostRules()) >+ return 0; > // Tracking child index requires unique style for each node. This may get set by the sibling rule match above. > if (parentStylePreventsSharing(m_parentStyle)) > return 0; >diff --git a/Source/WebCore/css/StyleResolver.h b/Source/WebCore/css/StyleResolver.h >index afb7a48562ad78fd29c024a367b4e286ffeb3166..de8f4881ce21559005d10d6582ae9f7d5c4c021d 100644 >--- a/Source/WebCore/css/StyleResolver.h >+++ b/Source/WebCore/css/StyleResolver.h >@@ -72,6 +72,7 @@ class RenderRegion; > class RuleData; > class RuleSet; > class Settings; >+class ShadowRoot; > class StaticCSSRuleList; > class StyleBuilder; > class StyleImage; >@@ -79,6 +80,7 @@ class StyleKeyframe; > class StylePendingImage; > class StylePropertySet; > class StyleRule; >+class StyleRuleHost; > class StyleRuleKeyframes; > class StyleRulePage; > class StyleRuleRegion; >@@ -136,6 +138,7 @@ public: > void popParentElement(Element*); > void pushParentShadowRoot(const ShadowRoot*); > void popParentShadowRoot(const ShadowRoot*); >+ void addHostRule(StyleRuleHost*, bool, const ContainerNode*); > > PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, StyleSharingBehavior = AllowStyleSharing, > RuleMatchingBehavior = MatchAllRules, RenderRegion* regionForStyling = 0); >@@ -173,6 +176,7 @@ private: > void collectFeatures(); > RenderStyle* locateSharedStyle(); > bool matchesRuleSet(RuleSet*); >+ bool matchesHostRules(); > Node* locateCousinList(Element* parent, unsigned& visitedNodeCount) const; > StyledElement* findSiblingForStyleSharing(Node*, unsigned& count) const; > bool canShareStyleWithElement(StyledElement*) const; >@@ -333,6 +337,7 @@ private: > void matchAuthorRules(MatchResult&, bool includeEmptyRules); > void matchUserRules(MatchResult&, bool includeEmptyRules); > void matchScopedAuthorRules(MatchResult&, bool includeEmptyRules); >+ void matchHostRules(MatchResult&, bool includeEmptyRules); > void collectMatchingRules(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions&); > void collectMatchingRulesForRegion(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions&); > void collectMatchingRulesForList(const Vector<RuleData>*, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions&); >@@ -493,11 +498,13 @@ private: > HashMap<FilterOperation*, RefPtr<WebKitCSSSVGDocumentValue> > m_pendingSVGDocuments; > #endif > >+ typedef HashMap<const ContainerNode*, OwnPtr<RuleSet> > ScopedRuleSetMap; >+ >+ RuleSet* atHostRuleSetForScope(const ShadowRoot*); >+ > #if ENABLE(STYLE_SCOPED) > const ContainerNode* determineScope(const CSSStyleSheet*); > >- typedef HashMap<const ContainerNode*, OwnPtr<RuleSet> > ScopedRuleSetMap; >- > RuleSet* ruleSetForScope(const ContainerNode*) const; > > void setupScopeStack(const ContainerNode*); >@@ -520,6 +527,7 @@ private: > const ContainerNode* m_scopeStackParent; > int m_scopeStackParentBoundsIndex; > #endif >+ ScopedRuleSetMap m_atHostRules; > > CSSToStyleMap m_styleMap; > >diff --git a/Source/WebCore/css/StyleRule.cpp b/Source/WebCore/css/StyleRule.cpp >index 73b0af26ce42aa4594d9b761796b19d6a6bb665c..fd5c0c302d3da1339a09f654459e0cd413314e9f 100644 >--- a/Source/WebCore/css/StyleRule.cpp >+++ b/Source/WebCore/css/StyleRule.cpp >@@ -79,6 +79,9 @@ void StyleRuleBase::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const > case Keyframes: > static_cast<const StyleRuleKeyframes*>(this)->reportDescendantMemoryUsage(memoryObjectInfo); > return; >+ case Host: >+ static_cast<const StyleRuleBlock*>(this)->reportDescendantMemoryUsage(memoryObjectInfo); >+ return; > case Unknown: > case Charset: > case Keyframe: >@@ -117,6 +120,9 @@ void StyleRuleBase::destroy() > case Keyframes: > delete static_cast<StyleRuleKeyframes*>(this); > return; >+ case Host: >+ delete static_cast<StyleRuleHost*>(this); >+ return; > case Unknown: > case Charset: > case Keyframe: >@@ -150,6 +156,8 @@ PassRefPtr<StyleRuleBase> StyleRuleBase::copy() const > return 0; > case Keyframes: > return static_cast<const StyleRuleKeyframes*>(this)->copy(); >+ case Host: >+ return static_cast<const StyleRuleHost*>(this)->copy(); > case Unknown: > case Charset: > case Keyframe: >@@ -191,6 +199,7 @@ PassRefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet > case Keyframes: > rule = WebKitCSSKeyframesRule::create(static_cast<StyleRuleKeyframes*>(self), parentSheet); > break; >+ case Host: > case Unknown: > case Charset: > case Keyframe: >@@ -381,4 +390,14 @@ void StyleRuleRegion::reportDescendantMemoryUsage(MemoryObjectInfo* memoryObject > info.addMember(m_selectorList); > } > >+StyleRuleHost::StyleRuleHost(Vector<RefPtr<StyleRuleBase> >& adoptRules) >+ : StyleRuleBlock(Host, adoptRules) >+{ >+} >+ >+StyleRuleHost::StyleRuleHost(const StyleRuleHost& o) >+ : StyleRuleBlock(o) >+{ >+} >+ > } // namespace WebCore >diff --git a/Source/WebCore/css/StyleRule.h b/Source/WebCore/css/StyleRule.h >index e15f32e402aaf208d3cc0fccd358477b23035634..7ad313ecea8bbfb1f630a2c54d97b24417303903 100644 >--- a/Source/WebCore/css/StyleRule.h >+++ b/Source/WebCore/css/StyleRule.h >@@ -46,6 +46,7 @@ public: > Page, > Keyframes, > Keyframe, // Not used. These are internally non-rule StyleKeyframe objects. >+ Host, > Region = 16 > }; > Type type() const { return static_cast<Type>(m_type); } >@@ -58,6 +59,7 @@ public: > bool isStyleRule() const { return type() == Style; } > bool isRegionRule() const { return type() == Region; } > bool isImportRule() const { return type() == Import; } >+ bool isHostRule() const { return type() == Host; } > > PassRefPtr<StyleRuleBase> copy() const; > >@@ -223,6 +225,20 @@ private: > CSSSelectorList m_selectorList; > }; > >+class StyleRuleHost : public StyleRuleBlock { >+public: >+ static PassRefPtr<StyleRuleHost> create(Vector<RefPtr<StyleRuleBase> >& adoptRules) >+ { >+ return adoptRef(new StyleRuleHost(adoptRules)); >+ } >+ >+ PassRefPtr<StyleRuleHost> copy() const { return adoptRef(new StyleRuleHost(*this)); } >+ >+private: >+ StyleRuleHost(Vector<RefPtr<StyleRuleBase> >& adoptRules); >+ StyleRuleHost(const StyleRuleHost&); >+}; >+ > } // namespace WebCore > > #endif // StyleRule_h >diff --git a/Source/WebCore/css/StyleSheetContents.cpp b/Source/WebCore/css/StyleSheetContents.cpp >index e7ce81eaab48718624f4eb55238e5c1af35685b8..39e9a7b2cd6c2193bb04980fa88a82721e4a23de 100644 >--- a/Source/WebCore/css/StyleSheetContents.cpp >+++ b/Source/WebCore/css/StyleSheetContents.cpp >@@ -435,6 +435,10 @@ static bool childRulesHaveFailedOrCanceledSubresources(const Vector<RefPtr<Style > if (childRulesHaveFailedOrCanceledSubresources(static_cast<const StyleRuleRegion*>(rule)->childRules())) > return true; > break; >+ case StyleRuleBase::Host: >+ if (childRulesHaveFailedOrCanceledSubresources(static_cast<const StyleRuleHost*>(rule)->childRules())) >+ return true; >+ break; > case StyleRuleBase::Import: > ASSERT_NOT_REACHED(); > case StyleRuleBase::Page: >diff --git a/Source/WebCore/dom/ElementShadow.cpp b/Source/WebCore/dom/ElementShadow.cpp >index aeb5b5b475b219bc57dc85ef2e7b832aee8893fc..809bcc87822e514cd8d64c3db8d32ac758760e14 100644 >--- a/Source/WebCore/dom/ElementShadow.cpp >+++ b/Source/WebCore/dom/ElementShadow.cpp >@@ -39,6 +39,7 @@ > namespace WebCore { > > ElementShadow::ElementShadow() >+ : m_hasMatchedHostRuleAvailable(false) > { > } > >@@ -89,6 +90,10 @@ void ElementShadow::addShadowRoot(Element* shadowHost, PassRefPtr<ShadowRoot> sh > if (shadowHost->attached()) > shadowHost->lazyReattach(); > >+ // As a new shadow dom subtree might have @host @-rules, need to disable >+ // hasMatchedHostRules cache. >+ clearHasMatchedHostRule(); >+ > InspectorInstrumentation::didPushShadowRoot(shadowHost, shadowRoot.get()); > } > >diff --git a/Source/WebCore/dom/ElementShadow.h b/Source/WebCore/dom/ElementShadow.h >index ddb43806bde1539fc7adc2b9d8692ce723c833f6..51569b6a6ab566bf4a9ba4513b640d385d45f863 100644 >--- a/Source/WebCore/dom/ElementShadow.h >+++ b/Source/WebCore/dom/ElementShadow.h >@@ -71,11 +71,18 @@ public: > ContentDistributor& distributor(); > const ContentDistributor& distributor() const; > >+ bool hasMatchedHostRule() const { return m_hasMatchedHostRule; } >+ bool hasMatchedHostRuleAvailable() const { return m_hasMatchedHostRuleAvailable; } >+ void clearHasMatchedHostRule() { m_hasMatchedHostRuleAvailable = false; } >+ void setHasMatchedHostRule(bool hasRule) { m_hasMatchedHostRule = hasRule; m_hasMatchedHostRuleAvailable = true; } >+ > private: > void invalidateDistribution(Element* host); > > DoublyLinkedList<ShadowRoot> m_shadowRoots; > ContentDistributor m_distributor; >+ bool m_hasMatchedHostRule; >+ bool m_hasMatchedHostRuleAvailable; > }; > > inline ShadowRoot* ElementShadow::youngestShadowRoot() const >diff --git a/Source/WebCore/dom/ShadowRoot.cpp b/Source/WebCore/dom/ShadowRoot.cpp >index 5180a1c22d84894e370f5c162b6a3ac8ff6fd425..39604b91640704d1f9e8fc95717282bf878c1347 100644 >--- a/Source/WebCore/dom/ShadowRoot.cpp >+++ b/Source/WebCore/dom/ShadowRoot.cpp >@@ -224,6 +224,7 @@ void ShadowRoot::childrenChanged(bool changedByParser, Node* beforeChange, Node* > { > ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); > owner()->invalidateDistribution(); >+ owner()->clearHasMatchedHostRule(); > } > > } >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index d7fdc6b871179b884ff3de948463babfedd16db8..88f7785b987b417b4ae554816e931d79e1b997af 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,13 @@ >+2012-10-09 Takashi Sakamoto <tasak@google.com> >+ >+ [Shadow DOM] Needs @host rule for ShadowDOM styling >+ https://bugs.webkit.org/show_bug.cgi?id=88606 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * fast/dom/shadow/athost-atrules-expected.txt: Added. >+ * fast/dom/shadow/athost-atrules.html: Added. >+ > 2012-10-08 Alpha Lam <hclam@chromium.org> > > Not reviewed. Rebaselines for Chromium. >diff --git a/LayoutTests/fast/dom/shadow/athost-atrules-expected.txt b/LayoutTests/fast/dom/shadow/athost-atrules-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..a1f3b1c2551695678725bd665181313438649a14 >--- /dev/null >+++ b/LayoutTests/fast/dom/shadow/athost-atrules-expected.txt >@@ -0,0 +1,15 @@ >+host: rgb(255, 0, 0) >+host: rgb(255, 0, 0) >+hostA: rgb(255, 0, 0) >+hostB: rgb(0, 0, 255) >+host: rgb(0, 0, 255) >+host: rgb(128, 128, 128) >+host: rgb(0, 0, 255) >+host: rgb(0, 0, 255) >+host: rgb(128, 128, 128) >+host: rgb(255, 255, 0) >+host: rgb(255, 0, 0) >+nestedHost: rgb(0, 0, 255) >+host: rgb(255, 0, 0) >+host: rgb(255, 255, 0) >+Hello >diff --git a/LayoutTests/fast/dom/shadow/athost-atrules.html b/LayoutTests/fast/dom/shadow/athost-atrules.html >new file mode 100644 >index 0000000000000000000000000000000000000000..7d4b511ee02fa9d751e57e169b00a6d877d53a6d >--- /dev/null >+++ b/LayoutTests/fast/dom/shadow/athost-atrules.html >@@ -0,0 +1,190 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<style> >+#host { >+ color: gray; >+} >+</style> >+<script src="../../js/resources/js-test-pre.js"></script> >+<script src="resources/polyfill.js"></script> >+<script> >+function dumpComputedStyle(node) >+{ >+ debug(node.id + ": " + document.defaultView.getComputedStyle(node, null).getPropertyValue('color')); >+} >+ >+function preprocessForTest() >+{ >+ var parent = document.getElementById("parent"); >+ parent.innerHTML = '<div id="host"><span>Hello</span></div>'; >+} >+ >+function testSimpleContentCase() >+{ >+ preprocessForTest(); >+ var host = document.getElementById("host"); >+ var shadow = new WebKitShadowRoot(host); >+ shadow.innerHTML = "<style>@host { div { color: red; } }</style><content></content>"; >+ dumpComputedStyle(host); >+} >+ >+function testSimpleShadowCase() >+{ >+ preprocessForTest(); >+ var host = document.getElementById("host"); >+ var shadow = new WebKitShadowRoot(host); >+ shadow.innerHTML = "<style>@host { div { color: red; } }</style><shadow></shadow>"; >+ dumpComputedStyle(host); >+} >+ >+function testHostWithSelector() >+{ >+ var parent = document.getElementById("parent"); >+ parent.innerHTML = "<style scoped> .host { color: gray };</style>" >+ + "<div id='hostA' class='host'><span>Hello</span></div>" >+ + "<span id='hostB' class='host'><span>World</span></span>"; >+ >+ var hostA = document.getElementById("hostA"); >+ var shadowA = new WebKitShadowRoot(hostA); >+ var style = "<style>@host { div { color: red; } span { color: blue; } }</style>"; >+ shadowA.innerHTML = style + "<shadow></shadow>"; >+ >+ var hostB = document.getElementById("hostB"); >+ var shadowB = new WebKitShadowRoot(hostB); >+ shadowB.innerHTML = style + "<shadow></shadow>"; >+ >+ dumpComputedStyle(hostA); >+ dumpComputedStyle(hostB); >+} >+ >+function testPseudoHostWithScoped() >+{ >+ preprocessForTest(); >+ var host = document.getElementById("host"); >+ var shadow = new WebKitShadowRoot(host); >+ shadow.innerHTML = "<div><style scoped>@host { div { color: red; } }</style><shadow></shadow><div><style scoped>@host { div { color: blue; } }</style></div></div>"; >+ dumpComputedStyle(host); >+} >+ >+function testPseudoHostWithFallbackShadow() >+{ >+ preprocessForTest(); >+ var host = document.getElementById("host"); >+ var oldestShadow = new WebKitShadowRoot(host); >+ var youngestShadow = new WebKitShadowRoot(host); >+ oldestShadow.innerHTML = "<style>@host { div { color: red; } }</style><content></content>"; >+ youngestShadow.innerHTML = "<content><shadow></shadow></content>"; >+ dumpComputedStyle(host); >+} >+ >+function testTwoShadowRootsCase() >+{ >+ preprocessForTest(); >+ var host = document.getElementById("host"); >+ var oldestShadow = new WebKitShadowRoot(host); >+ var youngestShadow = new WebKitShadowRoot(host); >+ oldestShadow.innerHTML = "<style>@host { div { color: red; } }</style><content></content>"; >+ youngestShadow.innerHTML = "<style>@host { div { color: blue; } }</style><shadow></shadow>"; >+ dumpComputedStyle(host); >+} >+ >+function testTwoShadowRootsCreatingDifferentOrderCase() >+{ >+ preprocessForTest(); >+ var host = document.getElementById("host"); >+ var oldestShadow = new WebKitShadowRoot(host); >+ var youngestShadow = new WebKitShadowRoot(host); >+ youngestShadow.innerHTML = "<style>@host { div { color: blue; } }</style><shadow></shadow>"; >+ oldestShadow.innerHTML = "<style>@host { div { color: red; } }</style><content></content>"; >+ dumpComputedStyle(host); >+} >+ >+function testMultipleShadowRootsWithInertShadowContent() >+{ >+ preprocessForTest(); >+ var host = document.getElementById("host"); >+ var oldestShadow = new WebKitShadowRoot(host); >+ var olderShadow = new WebKitShadowRoot(host); >+ var youngerShadow = new WebKitShadowRoot(host); >+ var youngestShadow = new WebKitShadowRoot(host); >+ >+ youngestShadow.innerHTML = "<shadow></shadow>"; >+ youngerShadow.innerHTML = "<content></content>"; >+ olderShadow.innerHTML = "<style>@host { div { color: green; } }</style><shadow></shadow>"; >+ oldestShadow.innerHTML = "<style>@host { div { color: red; } }</style><content></content>"; >+ dumpComputedStyle(host); >+} >+ >+function testMultipleShadowRootsWithInertShadow() >+{ >+ preprocessForTest(); >+ var host = document.getElementById("host"); >+ var oldestShadow = new WebKitShadowRoot(host); >+ var olderShadow = new WebKitShadowRoot(host); >+ var youngerShadow = new WebKitShadowRoot(host); >+ var youngestShadow = new WebKitShadowRoot(host); >+ >+ youngestShadow.innerHTML = "<style>@host { div { color: yellow; } }</style><shadow></shadow>"; >+ youngerShadow.innerHTML = "<style>@host { div { color: blue; } }</style><div>inert</div>"; >+ olderShadow.innerHTML = "<style>@host { div { color: green; } }</style><shadow></shadow>"; >+ oldestShadow.innerHTML = "<style>@host { div { color: red; } }</style><content></content>"; >+ dumpComputedStyle(host); >+} >+ >+function testNestedCase() >+{ >+ preprocessForTest(); >+ var host = document.getElementById("host"); >+ var outerShadow = new WebKitShadowRoot(host); >+ outerShadow.innerHTML = '<style>@host { div { color: red; } }</style><div id="nestedHost">InnerShadow</div>'; >+ var nested = outerShadow.getElementById("nestedHost"); >+ var innerShadow = new WebKitShadowRoot(nested); >+ innerShadow.innerHTML = '<style>@host { div { color: blue; } }</style>Show <shadow></shadow> in outer.'; >+ dumpComputedStyle(host); >+ dumpComputedStyle(nested); >+} >+ >+function testHostVsScopedStyle() >+{ >+ preprocessForTest(); >+ var host = document.getElementById("host"); >+ host.innerHTML = "<style scoped>#host { color: yellow; }</style><span>Hello</span>"; >+ var shadow = new WebKitShadowRoot(host); >+ shadow.innerHTML = "<style>@host { #host { color: red; } }</style><content></content>"; >+ dumpComputedStyle(host); >+} >+ >+function testHostVsInlineStyle() >+{ >+ preprocessForTest(); >+ var host = document.getElementById("host"); >+ host.style.color = "yellow"; >+ host.innerHTML = "<span>Hello</span>"; >+ var shadow = new WebKitShadowRoot(host); >+ shadow.innerHTML = "<style>@host { div { color: red; } }</style><content></content>"; >+ dumpComputedStyle(host); >+} >+ >+function runTests() >+{ >+ testSimpleContentCase(); >+ testSimpleShadowCase(); >+ testHostWithSelector(); >+ testPseudoHostWithScoped(); >+ testPseudoHostWithFallbackShadow(); >+ testTwoShadowRootsCase(); >+ testTwoShadowRootsCreatingDifferentOrderCase(); >+ testMultipleShadowRootsWithInertShadowContent(); >+ testMultipleShadowRootsWithInertShadow(); >+ testNestedCase(); >+ testHostVsScopedStyle(); >+ testHostVsInlineStyle(); >+} >+</script> >+</head> >+<body onload="runTests()"> >+ <div id="parent"> >+ </div> >+</body> >+</html>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 88606
:
155250
|
155438
|
155477
|
155752
|
155754
|
155769
|
156902
|
159626
|
161866
|
164506
|
165044
|
166821
|
167716
|
167949
|
168155
|
168412
|
169112
|
169352
|
169594
|
170124
|
170292
|
170555
|
170831