void ShadowTree::recalcShadowTreeStyle(Node::StyleChange change) { ShadowRoot* youngest = youngestShadowRoot(); if (!youngest) return; if (needsReattachHostChildrenAndShadow()) reattachHostChildrenAndShadow(); else { StyleResolver* styleResolver = youngest->document()->styleResolver(); styleResolver->pushParentShadowRoot(youngest); for (Node* n = youngest->firstChild(); n; n = n->nextSibling()) { if (n->isElementNode()) static_cast<Element*>(n)->recalcStyle(change); else if (n->isTextNode()) toText(n)->recalcTextStyle(change); } styleResolver->popParentShadowRoot(youngest); } clearNeedsReattachHostChildrenAndShadow(); for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { root->clearNeedsStyleRecalc(); root->clearChildNeedsStyleRecalc(); } }
void ShadowTree::reattachHostChildrenAndShadow() { ASSERT(youngestShadowRoot()); Element* hostNode = youngestShadowRoot()->host(); hostNode->detachChildrenIfNeeded(); reattach(); hostNode->attachChildrenIfNeeded(); }
bool ElementShadow::childNeedsStyleRecalc() const { ASSERT(youngestShadowRoot()); for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) if (root->childNeedsStyleRecalc()) return true; return false; }
bool ShadowTree::needsStyleRecalc() { ASSERT(youngestShadowRoot()); for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) if (root->needsStyleRecalc()) return true; return false; }
void ElementShadow::attach() { ContentDistributor::ensureDistribution(youngestShadowRoot()); for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { if (!root->attached()) root->attach(); } }
void ShadowTree::hostChildrenChanged() { ASSERT(youngestShadowRoot()); if (!youngestShadowRoot()->hasInsertionPoint()) return; // This results in forced detaching/attaching of the shadow render tree. See ShadowRoot::recalcStyle(). setNeedsReattachHostChildrenAndShadow(); }
void ElementShadow::detach() { for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { if (root->attached()) root->detach(); } }
void ElementShadow::removeAllEventListeners() { for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { for (Node* node = root; node; node = NodeTraversal::next(node)) node->removeAllEventListeners(); } }
ShadowRoot& ElementShadow::addShadowRoot(Element& shadowHost, ShadowRootType type) { EventDispatchForbiddenScope assertNoEventDispatch; ScriptForbiddenScope forbidScript; if (type == ShadowRootType::V0 && m_shadowRoot) { DCHECK_EQ(m_shadowRoot->type(), ShadowRootType::V0); Deprecation::countDeprecation(shadowHost.document(), UseCounter::ElementCreateShadowRootMultiple); } if (m_shadowRoot) { // TODO(hayato): Is the order, from the youngest to the oldest, important? for (ShadowRoot* root = &youngestShadowRoot(); root; root = root->olderShadowRoot()) root->lazyReattachIfAttached(); } ShadowRoot* shadowRoot = ShadowRoot::create(shadowHost.document(), type); shadowRoot->setParentOrShadowHostNode(&shadowHost); shadowRoot->setParentTreeScope(shadowHost.treeScope()); appendShadowRoot(*shadowRoot); setNeedsDistributionRecalc(); shadowRoot->insertedInto(&shadowHost); shadowHost.setChildNeedsStyleRecalc(); shadowHost.setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Shadow)); InspectorInstrumentation::didPushShadowRoot(&shadowHost, shadowRoot); return *shadowRoot; }
void ElementShadow::distribute() { if (isV1()) youngestShadowRoot().distributeV1(); else distributeV0(); }
void ElementShadow::clearDistribution() { m_nodeToInsertionPoints.clear(); for (ShadowRoot* root = &youngestShadowRoot(); root; root = root->olderShadowRoot()) root->setShadowInsertionPointOfYoungerShadowRoot(nullptr); }
void ElementShadow::detach(const Node::AttachContext& context) { Node::AttachContext childrenContext(context); childrenContext.resolvedStyle = 0; for (ShadowRoot* root = &youngestShadowRoot(); root; root = root->olderShadowRoot()) root->detach(childrenContext); }
bool ElementShadow::resolveApplyAuthorStyles() const { for (const ShadowRoot* shadowRoot = youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) { if (shadowRoot->applyAuthorStyles()) return true; if (!shadowRoot->containsShadowElements()) break; } return false; }
bool ElementShadow::containsActiveStyles() const { for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { if (root->hasScopedHTMLStyleChild()) return true; if (!root->containsShadowElements()) return false; } return false; }
void ElementShadow::appendShadowRoot(ShadowRoot& shadowRoot) { if (!m_shadowRoot) { m_shadowRoot = &shadowRoot; return; } ShadowRoot& youngest = youngestShadowRoot(); DCHECK(shadowRoot.type() == ShadowRootType::V0); DCHECK(youngest.type() == ShadowRootType::V0); youngest.setYoungerShadowRoot(shadowRoot); shadowRoot.setOlderShadowRoot(youngest); }
void ShadowTree::attach() { // Children of m_selector is populated lazily in // ensureSelector(), and here we just ensure that it is in clean state. ASSERT(!selector().hasPopulated()); selector().willSelect(); for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { if (!root->attached()) root->attach(); } selector().didSelect(); }
void ElementShadow::distribute() { host()->setNeedsStyleRecalc(); Vector<HTMLShadowElement*, 32> shadowInsertionPoints; DistributionPool pool(*host()); for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { HTMLShadowElement* shadowInsertionPoint = 0; const Vector<RefPtr<InsertionPoint> >& insertionPoints = root->descendantInsertionPoints(); for (size_t i = 0; i < insertionPoints.size(); ++i) { InsertionPoint* point = insertionPoints[i].get(); if (!point->isActive()) continue; if (isHTMLShadowElement(point)) { if (!shadowInsertionPoint) shadowInsertionPoint = toHTMLShadowElement(point); } else { pool.distributeTo(point, this); if (ElementShadow* shadow = shadowWhereNodeCanBeDistributed(*point)) shadow->setNeedsDistributionRecalc(); } } if (shadowInsertionPoint) { shadowInsertionPoints.append(shadowInsertionPoint); if (shadowInsertionPoint->hasChildNodes()) pool.populateChildren(*shadowInsertionPoint); } else { pool.clear(); } } for (size_t i = shadowInsertionPoints.size(); i > 0; --i) { HTMLShadowElement* shadowInsertionPoint = shadowInsertionPoints[i - 1]; ShadowRoot* root = shadowInsertionPoint->containingShadowRoot(); ASSERT(root); if (root->isOldest()) { pool.distributeTo(shadowInsertionPoint, this); } else if (root->olderShadowRoot()->type() == root->type()) { // Only allow reprojecting older shadow roots between the same type to // disallow reprojecting UA elements into author shadows. DistributionPool olderShadowRootPool(*root->olderShadowRoot()); olderShadowRootPool.distributeTo(shadowInsertionPoint, this); root->olderShadowRoot()->setShadowInsertionPointOfYoungerShadowRoot(shadowInsertionPoint); } if (ElementShadow* shadow = shadowWhereNodeCanBeDistributed(*shadowInsertionPoint)) shadow->setNeedsDistributionRecalc(); } }
void ElementShadowV0::distribute() { HeapVector<Member<HTMLShadowElement>, 32> shadowInsertionPoints; DistributionPool pool(m_elementShadow->host()); for (ShadowRoot* root = &youngestShadowRoot(); root; root = root->olderShadowRoot()) { HTMLShadowElement* shadowInsertionPoint = 0; for (const auto& point : root->descendantInsertionPoints()) { if (!point->isActive()) continue; if (isHTMLShadowElement(*point)) { DCHECK(!shadowInsertionPoint); shadowInsertionPoint = toHTMLShadowElement(point); shadowInsertionPoints.append(shadowInsertionPoint); } else { pool.distributeTo(point, this); if (ElementShadow* shadow = shadowWhereNodeCanBeDistributedForV0(*point)) shadow->setNeedsDistributionRecalc(); } } } for (size_t i = shadowInsertionPoints.size(); i > 0; --i) { HTMLShadowElement* shadowInsertionPoint = shadowInsertionPoints[i - 1]; ShadowRoot* root = shadowInsertionPoint->containingShadowRoot(); DCHECK(root); if (root->isOldest()) { pool.distributeTo(shadowInsertionPoint, this); } else if (root->olderShadowRoot()->type() == root->type()) { // Only allow reprojecting older shadow roots between the same type to // disallow reprojecting UA elements into author shadows. DistributionPool olderShadowRootPool(*root->olderShadowRoot()); olderShadowRootPool.distributeTo(shadowInsertionPoint, this); root->olderShadowRoot()->setShadowInsertionPointOfYoungerShadowRoot( shadowInsertionPoint); } if (ElementShadow* shadow = shadowWhereNodeCanBeDistributedForV0(*shadowInsertionPoint)) shadow->setNeedsDistributionRecalc(); } InspectorInstrumentation::didPerformElementShadowDistribution( &m_elementShadow->host()); }
void ElementShadow::distributeV0() { host()->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Shadow)); WillBeHeapVector<RawPtrWillBeMember<HTMLShadowElement>, 32> shadowInsertionPoints; DistributionPool pool(*host()); for (ShadowRoot* root = &youngestShadowRoot(); root; root = root->olderShadowRoot()) { HTMLShadowElement* shadowInsertionPoint = 0; const WillBeHeapVector<RefPtrWillBeMember<InsertionPoint>>& insertionPoints = root->descendantInsertionPoints(); for (size_t i = 0; i < insertionPoints.size(); ++i) { InsertionPoint* point = insertionPoints[i].get(); if (!point->isActive()) continue; if (isHTMLShadowElement(*point)) { ASSERT(!shadowInsertionPoint); shadowInsertionPoint = toHTMLShadowElement(point); shadowInsertionPoints.append(shadowInsertionPoint); } else { pool.distributeTo(point, this); if (ElementShadow* shadow = shadowWhereNodeCanBeDistributed(*point)) shadow->setNeedsDistributionRecalc(); } } } for (size_t i = shadowInsertionPoints.size(); i > 0; --i) { HTMLShadowElement* shadowInsertionPoint = shadowInsertionPoints[i - 1]; ShadowRoot* root = shadowInsertionPoint->containingShadowRoot(); ASSERT(root); if (root->isOldest()) { pool.distributeTo(shadowInsertionPoint, this); } else if (root->olderShadowRoot()->type() == root->type()) { // Only allow reprojecting older shadow roots between the same type to // disallow reprojecting UA elements into author shadows. DistributionPool olderShadowRootPool(*root->olderShadowRoot()); olderShadowRootPool.distributeTo(shadowInsertionPoint, this); root->olderShadowRoot()->setShadowInsertionPointOfYoungerShadowRoot(shadowInsertionPoint); } if (ElementShadow* shadow = shadowWhereNodeCanBeDistributed(*shadowInsertionPoint)) shadow->setNeedsDistributionRecalc(); } InspectorInstrumentation::didPerformElementShadowDistribution(host()); }
bool ElementShadow::hasSameStyles(const ElementShadow* other) const { ShadowRoot* root = &youngestShadowRoot(); ShadowRoot* otherRoot = &other->youngestShadowRoot(); while (root || otherRoot) { if (!root || !otherRoot) return false; StyleSheetList& list = root->styleSheets(); StyleSheetList& otherList = otherRoot->styleSheets(); if (list.length() != otherList.length()) return false; for (size_t i = 0; i < list.length(); i++) { if (toCSSStyleSheet(list.item(i))->contents() != toCSSStyleSheet(otherList.item(i))->contents()) return false; } root = root->olderShadowRoot(); otherRoot = otherRoot->olderShadowRoot(); } return true; }
ShadowRoot& ElementShadow::addShadowRoot(Element& shadowHost, ShadowRoot::ShadowRootType type) { RefPtr<ShadowRoot> shadowRoot = ShadowRoot::create(shadowHost.document(), type); for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) root->lazyReattachIfAttached(); shadowRoot->setParentOrShadowHostNode(&shadowHost); shadowRoot->setParentTreeScope(shadowHost.treeScope()); m_shadowRoots.push(shadowRoot.get()); ChildNodeInsertionNotifier(shadowHost).notify(*shadowRoot); setNeedsDistributionRecalc(); // addShadowRoot() affects apply-author-styles. However, we know that the youngest shadow root has not had any children yet. // The youngest shadow root's apply-author-styles is default (false). So we can just set m_applyAuthorStyles false. m_applyAuthorStyles = false; shadowHost.didAddShadowRoot(*shadowRoot); InspectorInstrumentation::didPushShadowRoot(&shadowHost, shadowRoot.get()); ASSERT(m_shadowRoots.head()); ASSERT(shadowRoot.get() == m_shadowRoots.head()); return *m_shadowRoots.head(); }
void ElementShadow::recalcStyle(Node::StyleChange change) { for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) root->recalcStyle(change); }
Internals::ShadowRootIfShadowDOMEnabledOrNode* Internals::shadowRoot(Element* host, ExceptionCode& ec) { // FIXME: Internals::shadowRoot() in tests should be converted to youngestShadowRoot() or oldestShadowRoot(). // https://bugs.webkit.org/show_bug.cgi?id=78465 return youngestShadowRoot(host, ec); }
void ShadowTree::setParentTreeScope(TreeScope* scope) { for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) root->setParentTreeScope(scope); }
bool ShadowTree::needsReattachHostChildrenAndShadow() { return m_needsRecalculateContent || (youngestShadowRoot() && youngestShadowRoot()->hasInsertionPoint()); }
void ElementShadow::distributeV1() { if (!m_slotAssignment) m_slotAssignment = SlotAssignment::create(); m_slotAssignment->resolveAssignment(youngestShadowRoot()); }