| OLD | NEW | 
|     1 /* |     1 /* | 
|     2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |     2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 
|     3  *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) |     3  *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) | 
|     4  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) |     4  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) | 
|     5  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc.
       All rights reserved. |     5  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc.
       All rights reserved. | 
|     6  * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> |     6  * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> | 
|     7  * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> |     7  * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> | 
|     8  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
      orchmobile.com/) |     8  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
      orchmobile.com/) | 
|     9  * Copyright (c) 2011, Code Aurora Forum. All rights reserved. |     9  * Copyright (c) 2011, Code Aurora Forum. All rights reserved. | 
|    10  * Copyright (C) Research In Motion Limited 2011. All rights reserved. |    10  * Copyright (C) Research In Motion Limited 2011. All rights reserved. | 
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   382  |   382  | 
|   383 void StyleResolver::clearStyleSharingList() |   383 void StyleResolver::clearStyleSharingList() | 
|   384 { |   384 { | 
|   385     m_styleSharingLists.resize(0); |   385     m_styleSharingLists.resize(0); | 
|   386 } |   386 } | 
|   387  |   387  | 
|   388 static inline ScopedStyleResolver* scopedResolverFor(const Element& element) |   388 static inline ScopedStyleResolver* scopedResolverFor(const Element& element) | 
|   389 { |   389 { | 
|   390     // Ideally, returning element->treeScope().scopedStyleResolver() should be |   390     // Ideally, returning element->treeScope().scopedStyleResolver() should be | 
|   391     // enough, but ::cue and custom pseudo elements like ::-webkit-meter-bar pie
      rce |   391     // enough, but ::cue and custom pseudo elements like ::-webkit-meter-bar pie
      rce | 
|   392     // through a shadow dom boundary, yet they are not part of m_treeBoundaryCro
      ssingRules. |   392     // through a shadow dom boundary, yet they are not part of m_treeBoundaryCro
      ssingScopes. | 
|   393     // The assumption here is that these rules only pierce through one boundary 
      and |   393     // The assumption here is that these rules only pierce through one boundary 
      and | 
|   394     // that the scope of these elements do not have a style resolver due to the 
      fact |   394     // that the scope of these elements do not have a style resolver due to the 
      fact | 
|   395     // that VTT scopes and UA shadow trees don't have <style> elements. This is |   395     // that VTT scopes and UA shadow trees don't have <style> elements. This is | 
|   396     // backed up by the ASSERTs below. |   396     // backed up by the ASSERTs below. | 
|   397     // |   397     // | 
|   398     // FIXME: Make ::cue and custom pseudo elements part of boundary crossing ru
      les |   398     // FIXME: Make ::cue and custom pseudo elements part of boundary crossing ru
      les | 
|   399     // when moving those rules to ScopedStyleResolver as part of issue 401359. |   399     // when moving those rules to ScopedStyleResolver as part of issue 401359. | 
|   400  |   400  | 
|   401     TreeScope* treeScope = &element.treeScope(); |   401     TreeScope* treeScope = &element.treeScope(); | 
|   402     if (ScopedStyleResolver* resolver = treeScope->scopedStyleResolver()) { |   402     if (ScopedStyleResolver* resolver = treeScope->scopedStyleResolver()) { | 
|   403         ASSERT(element.shadowPseudoId().isEmpty()); |   403         ASSERT(element.shadowPseudoId().isEmpty()); | 
|   404         ASSERT(!element.isVTTElement()); |   404         ASSERT(!element.isVTTElement()); | 
|   405         return resolver; |   405         return resolver; | 
|   406     } |   406     } | 
|   407  |   407  | 
|   408     treeScope = treeScope->parentTreeScope(); |   408     treeScope = treeScope->parentTreeScope(); | 
|   409     if (!treeScope) |   409     if (!treeScope) | 
|   410         return nullptr; |   410         return nullptr; | 
|   411     if (element.shadowPseudoId().isEmpty() && !element.isVTTElement()) |   411     if (element.shadowPseudoId().isEmpty() && !element.isVTTElement()) | 
|   412         return nullptr; |   412         return nullptr; | 
|   413     return treeScope->scopedStyleResolver(); |   413     return treeScope->scopedStyleResolver(); | 
|   414 } |   414 } | 
|   415  |   415  | 
 |   416 static void matchHostRules(const Element& element, ElementRuleCollector& collect
      or) | 
 |   417 { | 
 |   418     ElementShadow* shadow = element.shadow(); | 
 |   419     if (!shadow) | 
 |   420         return; | 
 |   421  | 
 |   422     for (ShadowRoot* shadowRoot = shadow->oldestShadowRoot(); shadowRoot; shadow
      Root = shadowRoot->youngerShadowRoot()) { | 
 |   423         if (!shadowRoot->numberOfStyles()) | 
 |   424             continue; | 
 |   425         if (ScopedStyleResolver* resolver = shadowRoot->scopedStyleResolver()) { | 
 |   426             collector.clearMatchedRules(); | 
 |   427             resolver->collectMatchingShadowHostRules(collector); | 
 |   428             collector.sortAndTransferMatchedRules(); | 
 |   429             collector.finishAddingAuthorRulesForTreeScope(); | 
 |   430         } | 
 |   431     } | 
 |   432 } | 
 |   433  | 
 |   434 static void matchElementScopeRules(const Element& element, ScopedStyleResolver* 
      elementScopeResolver, ElementRuleCollector& collector) | 
 |   435 { | 
 |   436     if (elementScopeResolver) { | 
 |   437         collector.clearMatchedRules(); | 
 |   438         elementScopeResolver->collectMatchingAuthorRules(collector); | 
 |   439         elementScopeResolver->collectMatchingTreeBoundaryCrossingRules(collector
      ); | 
 |   440         collector.sortAndTransferMatchedRules(); | 
 |   441     } | 
 |   442  | 
 |   443     if (element.isStyledElement() && element.inlineStyle() && !collector.isColle
      ctingForPseudoElement()) { | 
 |   444         // Inline style is immutable as long as there is no CSSOM wrapper. | 
 |   445         bool isInlineStyleCacheable = !element.inlineStyle()->isMutable(); | 
 |   446         collector.addElementStyleProperties(element.inlineStyle(), isInlineStyle
      Cacheable); | 
 |   447     } | 
 |   448  | 
 |   449     collector.finishAddingAuthorRulesForTreeScope(); | 
 |   450 } | 
 |   451  | 
 |   452 static bool shouldCheckScope(const Element& element, const Node& scopingNode, bo
      ol isInnerTreeScope) | 
 |   453 { | 
 |   454     if (isInnerTreeScope && element.treeScope() != scopingNode.treeScope()) { | 
 |   455         // Check if |element| may be affected by a ::content rule in |scopingNod
      e|'s style. | 
 |   456         // If |element| is a descendant of a shadow host which is ancestral to |
      scopingNode|, | 
 |   457         // the |element| should be included for rule collection. | 
 |   458         // Skip otherwise. | 
 |   459         const TreeScope* scope = &scopingNode.treeScope(); | 
 |   460         while (scope && scope->parentTreeScope() != &element.treeScope()) | 
 |   461             scope = scope->parentTreeScope(); | 
 |   462         Element* shadowHost = scope ? scope->rootNode().shadowHost() : nullptr; | 
 |   463         return shadowHost && element.isDescendantOf(shadowHost); | 
 |   464     } | 
 |   465  | 
 |   466     // When |element| can be distributed to |scopingNode| via <shadow>, ::conten
      t rule can match, | 
 |   467     // thus the case should be included. | 
 |   468     if (!isInnerTreeScope && scopingNode.parentOrShadowHostNode() == element.tre
      eScope().rootNode().parentOrShadowHostNode()) | 
 |   469         return true; | 
 |   470  | 
 |   471     // Obviously cases when ancestor scope has /deep/ or ::shadow rule should be
       included. | 
 |   472     // Skip otherwise. | 
 |   473     return scopingNode.treeScope().scopedStyleResolver()->hasDeepOrShadowSelecto
      r(); | 
 |   474 } | 
 |   475  | 
 |   476 void StyleResolver::matchScopedRules(const Element& element, ElementRuleCollecto
      r& collector) | 
 |   477 { | 
 |   478     // Match rules from treeScopes in the reverse tree-of-trees order, since the | 
 |   479     // cascading order for normal rules is such that when comparing rules from | 
 |   480     // different shadow trees, the rule from the tree which comes first in the | 
 |   481     // tree-of-trees order wins. From other treeScopes than the element's own | 
 |   482     // scope, only tree-boundary-crossing rules may match. | 
 |   483  | 
 |   484     ScopedStyleResolver* elementScopeResolver = scopedResolverFor(element); | 
 |   485     bool matchElementScopeDone = !elementScopeResolver && !element.inlineStyle()
      ; | 
 |   486  | 
 |   487     // TODO(kochi): This loops through m_treeBoundaryCrossingScopes because to h
      andle | 
 |   488     // Shadow DOM V0 documents as well. In pure V1 document only have to go thro
      ugh | 
 |   489     // the chain of scopes for assigned slots. Add fast path for pure V1 documen
      t. | 
 |   490     for (auto it = m_treeBoundaryCrossingScopes.rbegin(); it != m_treeBoundaryCr
      ossingScopes.rend(); ++it) { | 
 |   491         const TreeScope& scope = (*it)->treeScope(); | 
 |   492         ScopedStyleResolver* resolver = scope.scopedStyleResolver(); | 
 |   493         ASSERT(resolver); | 
 |   494  | 
 |   495         bool isInnerTreeScope = element.treeScope().isInclusiveAncestorOf(scope)
      ; | 
 |   496         if (!shouldCheckScope(element, **it, isInnerTreeScope)) | 
 |   497             continue; | 
 |   498  | 
 |   499         if (!matchElementScopeDone && scope.isInclusiveAncestorOf(element.treeSc
      ope())) { | 
 |   500  | 
 |   501             matchElementScopeDone = true; | 
 |   502  | 
 |   503             // At this point, the iterator has either encountered the scope for 
      the element | 
 |   504             // itself (if that scope has boundary-crossing rules), or the iterat
      or has moved | 
 |   505             // to a scope which appears before the element's scope in the tree-o
      f-trees order. | 
 |   506             // Try to match all rules from the element's scope. | 
 |   507  | 
 |   508             matchElementScopeRules(element, elementScopeResolver, collector); | 
 |   509             if (resolver == elementScopeResolver) { | 
 |   510                 // Boundary-crossing rules already collected in matchElementScop
      eRules. | 
 |   511                 continue; | 
 |   512             } | 
 |   513         } | 
 |   514  | 
 |   515         collector.clearMatchedRules(); | 
 |   516         resolver->collectMatchingTreeBoundaryCrossingRules(collector); | 
 |   517         collector.sortAndTransferMatchedRules(); | 
 |   518         collector.finishAddingAuthorRulesForTreeScope(); | 
 |   519     } | 
 |   520  | 
 |   521     if (!matchElementScopeDone) | 
 |   522         matchElementScopeRules(element, elementScopeResolver, collector); | 
 |   523 } | 
 |   524  | 
|   416 void StyleResolver::matchAuthorRules(const Element& element, ElementRuleCollecto
      r& collector) |   525 void StyleResolver::matchAuthorRules(const Element& element, ElementRuleCollecto
      r& collector) | 
|   417 { |   526 { | 
 |   527     if (element.document().styleEngine().shadowCascadeOrder() != ShadowCascadeOr
      der::ShadowCascadeV1) { | 
 |   528         matchAuthorRulesV0(element, collector); | 
 |   529         return; | 
 |   530     } | 
 |   531  | 
 |   532     ASSERT(RuntimeEnabledFeatures::shadowDOMV1Enabled()); | 
 |   533     matchHostRules(element, collector); | 
 |   534     matchScopedRules(element, collector); | 
 |   535 } | 
 |   536  | 
 |   537 void StyleResolver::matchAuthorRulesV0(const Element& element, ElementRuleCollec
      tor& collector) | 
 |   538 { | 
|   418     collector.clearMatchedRules(); |   539     collector.clearMatchedRules(); | 
|   419  |   540  | 
|   420     CascadeOrder cascadeOrder = 0; |   541     CascadeOrder cascadeOrder = 0; | 
|   421     WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8> resolversInShad
      owTree; |   542     WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8> resolversInShad
      owTree; | 
|   422     collectScopedResolversForHostedShadowTrees(element, resolversInShadowTree); |   543     collectScopedResolversForHostedShadowTrees(element, resolversInShadowTree); | 
|   423  |   544  | 
|   424     // Apply :host and :host-context rules from inner scopes. |   545     // Apply :host and :host-context rules from inner scopes. | 
|   425     for (int j = resolversInShadowTree.size() - 1; j >= 0; --j) |   546     for (int j = resolversInShadowTree.size() - 1; j >= 0; --j) | 
|   426         resolversInShadowTree.at(j)->collectMatchingShadowHostRules(collector, +
      +cascadeOrder); |   547         resolversInShadowTree.at(j)->collectMatchingShadowHostRules(collector, +
      +cascadeOrder); | 
|   427  |   548  | 
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   480             if (isAuto) { |   601             if (isAuto) { | 
|   481                 state.setHasDirAutoAttribute(true); |   602                 state.setHasDirAutoAttribute(true); | 
|   482                 collector.addElementStyleProperties(textDirection == LTR ? leftT
      oRightDeclaration() : rightToLeftDeclaration()); |   603                 collector.addElementStyleProperties(textDirection == LTR ? leftT
      oRightDeclaration() : rightToLeftDeclaration()); | 
|   483             } |   604             } | 
|   484         } |   605         } | 
|   485     } |   606     } | 
|   486  |   607  | 
|   487     matchAuthorRules(*state.element(), collector); |   608     matchAuthorRules(*state.element(), collector); | 
|   488  |   609  | 
|   489     if (state.element()->isStyledElement()) { |   610     if (state.element()->isStyledElement()) { | 
|   490         if (state.element()->inlineStyle()) { |   611         // For Shadow DOM V1, inline style is already collected in matchScopedRu
      les(). | 
 |   612         if (state.element()->document().styleEngine().shadowCascadeOrder() != Sh
      adowCascadeOrder::ShadowCascadeV1 && state.element()->inlineStyle()) { | 
|   491             // Inline style is immutable as long as there is no CSSOM wrapper. |   613             // Inline style is immutable as long as there is no CSSOM wrapper. | 
|   492             bool isInlineStyleCacheable = !state.element()->inlineStyle()->isMut
      able(); |   614             bool isInlineStyleCacheable = !state.element()->inlineStyle()->isMut
      able(); | 
|   493             collector.addElementStyleProperties(state.element()->inlineStyle(), 
      isInlineStyleCacheable); |   615             collector.addElementStyleProperties(state.element()->inlineStyle(), 
      isInlineStyleCacheable); | 
|   494         } |   616         } | 
|   495  |   617  | 
|   496         // Now check SMIL animation override style. |   618         // Now check SMIL animation override style. | 
|   497         if (includeSMILProperties && state.element()->isSVGElement()) |   619         if (includeSMILProperties && state.element()->isSVGElement()) | 
|   498             collector.addElementStyleProperties(toSVGElement(state.element())->a
      nimatedSMILStyleProperties(), false /* isCacheable */); |   620             collector.addElementStyleProperties(toSVGElement(state.element())->a
      nimatedSMILStyleProperties(), false /* isCacheable */); | 
|   499     } |   621     } | 
|   500  |   622  | 
|   501     collector.finishAddingAuthorRulesForTreeScope(); |   623     collector.finishAddingAuthorRulesForTreeScope(); | 
|   502 } |   624 } | 
|   503  |   625  | 
|   504 static bool shouldCheckScope(const Element& element, const Node& scopingNode, bo
      ol isInnerTreeScope) |  | 
|   505 { |  | 
|   506     if (isInnerTreeScope && element.treeScope() != scopingNode.treeScope()) { |  | 
|   507         // Check if |element| may be affected by a ::content rule in |scopingNod
      e|'s style. |  | 
|   508         // If |element| is a descendant of a shadow host which is ancestral to |
      scopingNode|, |  | 
|   509         // the |element| should be included for rule collection. |  | 
|   510         // Skip otherwise. |  | 
|   511         const TreeScope* scope = &scopingNode.treeScope(); |  | 
|   512         while (scope && scope->parentTreeScope() != &element.treeScope()) |  | 
|   513             scope = scope->parentTreeScope(); |  | 
|   514         Element* shadowHost = scope ? scope->rootNode().shadowHost() : nullptr; |  | 
|   515         return shadowHost && element.isDescendantOf(shadowHost); |  | 
|   516     } |  | 
|   517  |  | 
|   518     // When |element| can be distributed to |scopingNode| via <shadow>, ::conten
      t rule can match, |  | 
|   519     // thus the case should be included. |  | 
|   520     if (!isInnerTreeScope && scopingNode.parentOrShadowHostNode() == element.tre
      eScope().rootNode().parentOrShadowHostNode()) |  | 
|   521         return true; |  | 
|   522  |  | 
|   523     // Obviously cases when ancestor scope has /deep/ or ::shadow rule should be
       included. |  | 
|   524     // Skip otherwise. |  | 
|   525     return scopingNode.treeScope().scopedStyleResolver()->hasDeepOrShadowSelecto
      r(); |  | 
|   526 } |  | 
|   527  |  | 
|   528 void StyleResolver::collectTreeBoundaryCrossingRules(const Element& element, Ele
      mentRuleCollector& collector) |   626 void StyleResolver::collectTreeBoundaryCrossingRules(const Element& element, Ele
      mentRuleCollector& collector) | 
|   529 { |   627 { | 
|   530     if (m_treeBoundaryCrossingScopes.isEmpty()) |   628     if (m_treeBoundaryCrossingScopes.isEmpty()) | 
|   531         return; |   629         return; | 
|   532  |   630  | 
|   533     // When comparing rules declared in outer treescopes, outer's rules win. |   631     // When comparing rules declared in outer treescopes, outer's rules win. | 
|   534     CascadeOrder outerCascadeOrder = m_treeBoundaryCrossingScopes.size() * 2; |   632     CascadeOrder outerCascadeOrder = m_treeBoundaryCrossingScopes.size() * 2; | 
|   535     // When comparing rules declared in inner treescopes, inner's rules win. |   633     // When comparing rules declared in inner treescopes, inner's rules win. | 
|   536     CascadeOrder innerCascadeOrder = m_treeBoundaryCrossingScopes.size(); |   634     CascadeOrder innerCascadeOrder = m_treeBoundaryCrossingScopes.size(); | 
|   537  |   635  | 
| (...skipping 1076 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1614     visitor->trace(m_uncommonAttributeRuleSet); |  1712     visitor->trace(m_uncommonAttributeRuleSet); | 
|  1615     visitor->trace(m_watchedSelectorsRules); |  1713     visitor->trace(m_watchedSelectorsRules); | 
|  1616     visitor->trace(m_treeBoundaryCrossingScopes); |  1714     visitor->trace(m_treeBoundaryCrossingScopes); | 
|  1617     visitor->trace(m_styleSharingLists); |  1715     visitor->trace(m_styleSharingLists); | 
|  1618     visitor->trace(m_pendingStyleSheets); |  1716     visitor->trace(m_pendingStyleSheets); | 
|  1619     visitor->trace(m_document); |  1717     visitor->trace(m_document); | 
|  1620 #endif |  1718 #endif | 
|  1621 } |  1719 } | 
|  1622  |  1720  | 
|  1623 } // namespace blink |  1721 } // namespace blink | 
| OLD | NEW |