Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(336)

Side by Side Diff: third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp

Issue 1803933002: Use correct cascading order for Shadow DOM v1 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix enum Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/css/resolver/StyleResolver.h ('k') | third_party/WebKit/Source/core/dom/DocumentOrderedList.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698