void InsertionPoint::removedFrom(ContainerNode* insertionPoint) { ShadowRoot* root = containingShadowRoot(); if (!root) root = insertionPoint->containingShadowRoot(); if (root) { if (ElementShadow* rootOwner = root->owner()) rootOwner->setNeedsDistributionRecalc(); } // host can be null when removedFrom() is called from ElementShadow destructor. ElementShadow* rootOwner = root ? root->owner() : 0; // Since this insertion point is no longer visible from the shadow subtree, it need to clean itself up. clearDistribution(); if (m_registeredWithShadowRoot && insertionPoint->treeScope().rootNode() == root) { ASSERT(root); m_registeredWithShadowRoot = false; root->didRemoveInsertionPoint(this); if (rootOwner) { if (canAffectSelector()) rootOwner->willAffectSelector(); } } HTMLElement::removedFrom(insertionPoint); }
Node* ComposedTreeWalker::traverseChild(const Node* node, TraversalDirection direction) const { ASSERT(node); ElementShadow* shadow = shadowFor(node); return shadow ? traverseLightChildren(shadow->youngestShadowRoot(), direction) : traverseLightChildren(node, direction); }
void ScopedStyleResolver::matchHostRules(ElementRuleCollector& collector, bool includeEmptyRules) { if (m_atHostRules.isEmpty() || !m_scopingNode->isElementNode()) return; ElementShadow* shadow = toElement(m_scopingNode)->shadow(); if (!shadow) return; collector.clearMatchedRules(); collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1; // FIXME(99827): https://bugs.webkit.org/show_bug.cgi?id=99827 // add a new flag to ElementShadow and cache whether any @host @-rules are // applied to the element or not. So we can quickly exit this method // by using the flag. ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); for (; shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) if (!ScopeContentDistribution::hasShadowElement(shadowRoot)) break; // All shadow roots have <shadow>. if (!shadowRoot) shadowRoot = shadow->oldestShadowRoot(); StyleResolver::RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange(); collector.setBehaviorAtBoundary(static_cast<SelectorChecker::BehaviorAtBoundary>(SelectorChecker::DoesNotCrossBoundary | SelectorChecker::ScopeContainsLastMatchedElement)); for (; shadowRoot; shadowRoot = shadowRoot->youngerShadowRoot()) { if (RuleSet* ruleSet = atHostRuleSetFor(shadowRoot)) collector.collectMatchingRules(MatchRequest(ruleSet, includeEmptyRules, m_scopingNode), ruleRange); } collector.sortAndTransferMatchedRules(); }
void ElementShadowV0::willAffectSelector() { for (ElementShadow* shadow = m_elementShadow; shadow; shadow = shadow->containingShadow()) { if (shadow->isV1() || shadow->v0().needsSelectFeatureSet()) break; shadow->v0().setNeedsSelectFeatureSet(); } m_elementShadow->setNeedsDistributionRecalc(); }
void ElementShadow::willAffectSelector() { for (ElementShadow* shadow = this; shadow; shadow = shadow->containingShadow()) { if (shadow->needsSelectFeatureSet()) break; shadow->setNeedsSelectFeatureSet(); } setNeedsDistributionRecalc(); }
Node* FlatTreeTraversal::traverseChild(const Node& node, TraversalDirection direction) { ElementShadow* shadow = shadowFor(node); if (shadow) { ShadowRoot& shadowRoot = shadow->youngestShadowRoot(); return resolveDistributionStartingAt(direction == TraversalDirectionForward ? shadowRoot.firstChild() : shadowRoot.lastChild(), direction); } return resolveDistributionStartingAt(direction == TraversalDirectionForward ? node.firstChild() : node.lastChild(), direction); }
Node* ComposedShadowTreeWalker::traverseChild(const Node* node, TraversalDirection direction) const { ASSERT(node); if (canCrossUpperBoundary()) { ElementShadow* shadow = shadowFor(node); return shadow ? traverseLightChildren(shadow->youngestShadowRoot(), direction) : traverseLightChildren(node, direction); } if (isShadowHost(node)) return 0; return traverseLightChildren(node, direction); }
Node* ComposedShadowTreeWalker::traverseSiblingOrBackToInsertionPoint(const Node* node, TraversalDirection direction) { ASSERT(node); ElementShadow* shadow = shadowOfParent(node); if (!shadow) return traverseSiblingInCurrentTree(node, direction); InsertionPoint* insertionPoint = shadow->insertionPointFor(node); if (!insertionPoint) return traverseSiblingInCurrentTree(node, direction); if (Node* next = (direction == TraversalDirectionForward ? insertionPoint->nextTo(node) : insertionPoint->previousTo(node))) return traverseNode(next, direction); return traverseSiblingOrBackToInsertionPoint(insertionPoint, direction); }
// FIXME: Move the following helper functions, authorShadowRootOf, firstWithinTraversingShadowTree, // nextTraversingShadowTree to the best place, e.g. NodeTraversal. static ShadowRoot* authorShadowRootOf(const ContainerNode& node) { if (!node.isElementNode() || !isShadowHost(&node)) return 0; ElementShadow* shadow = toElement(node).shadow(); ASSERT(shadow); for (ShadowRoot* shadowRoot = shadow->oldestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->youngerShadowRoot()) { if (shadowRoot->type() == ShadowRoot::AuthorShadowRoot) return shadowRoot; } return 0; }
// FIXME: Move the following helper functions, authorShadowRootOf, firstWithinTraversingShadowTree, // nextTraversingShadowTree to the best place, e.g. NodeTraversal. static ShadowRoot* authorShadowRootOf(const ContainerNode& node) { if (!node.isElementNode() || !isShadowHost(&node)) return nullptr; ElementShadow* shadow = toElement(node).shadow(); ASSERT(shadow); for (ShadowRoot* shadowRoot = shadow->oldestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->youngerShadowRoot()) { if (shadowRoot->type() == ShadowRootType::OpenByDefault || shadowRoot->type() == ShadowRootType::Open) return shadowRoot; } return nullptr; }
void ContentDistributor::ensureDistribution(ShadowRoot* shadowRoot) { ASSERT(shadowRoot); Vector<ElementShadow*, 8> elementShadows; for (Element* current = shadowRoot->host(); current; current = current->shadowHost()) { ElementShadow* elementShadow = current->shadow(); if (!elementShadow->distributor().needsDistribution()) break; elementShadows.append(elementShadow); } for (size_t i = elementShadows.size(); i > 0; --i) elementShadows[i - 1]->distributor().distribute(elementShadows[i - 1]->host()); }
void ScopedStyleTree::collectScopedResolversForHostedShadowTrees(const Element* element, Vector<ScopedStyleResolver*, 8>& resolvers) { ElementShadow* shadow = element->shadow(); if (!shadow) return; // Adding scoped resolver for active shadow roots for shadow host styling. for (ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) { if (shadowRoot->hasScopedHTMLStyleChild()) { if (ScopedStyleResolver* resolver = scopedStyleResolverFor(*shadowRoot)) resolvers.append(resolver); } if (!shadowRoot->containsShadowElements()) break; } }
void InputType::destroyShadowSubtree() { ElementShadow* shadow = element()->shadow(); if (!shadow) return; ShadowRoot* root = shadow->oldestShadowRoot(); root->removeAllChildren(); // It's ok to clear contents of all other ShadowRoots because they must have // been created by TextFieldDecorationElement, and we don't allow adding // AuthorShadowRoot to HTMLInputElement. while ((root = root->youngerShadowRoot())) { root->removeAllChildren(); root->appendChild(HTMLShadowElement::create(shadowTag, element()->document())); } }
void StyleScopeResolver::matchHostRules(const Element* element, Vector<RuleSet*>& matchedRules) { if (m_atHostRules.isEmpty()) return; ElementShadow* shadow = element->shadow(); if (!shadow) return; // FIXME(99827): https://bugs.webkit.org/show_bug.cgi?id=99827 // add a new flag to ElementShadow and cache whether any @host @-rules are // applied to the element or not. So we can quickly exit this method // by using the flag. if (ShadowRoot* shadowRoot = shadow->shadowRoot()) { if (RuleSet* ruleSet = atHostRuleSetFor(shadowRoot)) matchedRules.append(ruleSet); } }
void collectDestinationInsertionPoints(const Node& node, WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8>& results) { const Node* current = &node; ElementShadow* lastElementShadow = 0; while (true) { ElementShadow* shadow = shadowWhereNodeCanBeDistributed(*current); if (!shadow || shadow == lastElementShadow) return; lastElementShadow = shadow; const DestinationInsertionPoints* insertionPoints = shadow->destinationInsertionPointsFor(&node); if (!insertionPoints) return; for (size_t i = 0; i < insertionPoints->size(); ++i) results.append(insertionPoints->at(i).get()); ASSERT(current != insertionPoints->last().get()); current = insertionPoints->last().get(); } }
void InsertionPoint::detach() { ShadowRoot* root = shadowRoot(); if (root && isActive()) { ElementShadow* shadow = root->owner(); if (doesSelectFromHostChildren()) clearDistribution(shadow); else if (ShadowRoot* assignedShadowRoot = assignedFrom()) clearAssignment(assignedShadowRoot); // When shadow element is detached, shadow tree should be recreated to re-calculate selector for // other insertion points. shadow->setNeedsRedistributing(); } ASSERT(m_distribution.isEmpty()); HTMLElement::detach(); }
bool StyleScopeResolver::styleSharingCandidateMatchesHostRules(const Element* element) { if (m_atHostRules.isEmpty()) return false; ElementShadow* shadow = element->shadow(); if (!shadow) return false; // FIXME(99827): https://bugs.webkit.org/show_bug.cgi?id=99827 // add a new flag to ElementShadow and cache whether any@host @-rules are // applied to the element or not. So we can avoid always traversing // shadow roots. if (ShadowRoot* shadowRoot = shadow->shadowRoot()) { if (atHostRuleSetFor(shadowRoot)) return true; } return false; }
const InsertionPoint* resolveReprojection(const Node* projectedNode) { ASSERT(projectedNode); const InsertionPoint* insertionPoint = 0; const Node* current = projectedNode; ElementShadow* lastElementShadow = 0; while (true) { ElementShadow* shadow = shadowWhereNodeCanBeDistributed(*current); if (!shadow || shadow == lastElementShadow) break; lastElementShadow = shadow; const InsertionPoint* insertedTo = shadow->finalDestinationInsertionPointFor(projectedNode); if (!insertedTo) break; ASSERT(current != insertedTo); current = insertedTo; insertionPoint = insertedTo; } return insertionPoint; }
void InsertionPoint::removedFrom(ContainerNode* insertionPoint) { ShadowRoot* root = containingShadowRoot(); if (!root) root = insertionPoint->containingShadowRoot(); // host can be null when removedFrom() is called from ElementShadow destructor. ElementShadow* rootOwner = root ? root->owner() : 0; if (rootOwner) rootOwner->invalidateDistribution(); // Since this insertion point is no longer visible from the shadow subtree, it need to clean itself up. clearDistribution(); if (m_registeredWithShadowRoot && insertionPoint->treeScope()->rootNode() == root) { ASSERT(root); m_registeredWithShadowRoot = false; root->ensureScopeDistribution()->unregisterInsertionPoint(this); } HTMLElement::removedFrom(insertionPoint); }
void ChildFrameDisconnector::collectFrameOwners(ElementShadow& shadow) { for (ShadowRoot* root = &shadow.youngestShadowRoot(); root; root = root->olderShadowRoot()) collectFrameOwners(*root); }