void RenderTreeUpdater::updateRenderTree(ContainerNode& root) { ASSERT(root.renderer()); ASSERT(m_parentStack.isEmpty()); m_parentStack.append(Parent(root)); auto descendants = composedTreeDescendants(root); auto it = descendants.begin(); auto end = descendants.end(); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=156172 it.dropAssertions(); while (it != end) { popParentsToDepth(it.depth()); auto& node = *it; if (auto* renderer = node.renderer()) renderTreePosition().invalidateNextSibling(*renderer); if (is<Text>(node)) { auto& text = downcast<Text>(node); if (parent().styleChange == Style::Detach || m_styleUpdate->textUpdate(text) || m_invalidatedWhitespaceOnlyTextSiblings.contains(&text)) updateTextRenderer(text); it.traverseNextSkippingChildren(); continue; } auto& element = downcast<Element>(node); auto* elementUpdate = m_styleUpdate->elementUpdate(element); if (!elementUpdate) { it.traverseNextSkippingChildren(); continue; } updateElementRenderer(element, *elementUpdate); bool mayHaveRenderedDescendants = element.renderer() || (element.hasDisplayContents() && shouldCreateRenderer(element, renderTreePosition().parent())); if (!mayHaveRenderedDescendants) { it.traverseNextSkippingChildren(); continue; } pushParent(element, elementUpdate ? elementUpdate->change : Style::NoChange); it.traverseNext(); } popParentsToDepth(0); m_invalidatedWhitespaceOnlyTextSiblings.clear(); }
void TreeResolver::resolveComposedTree() { ASSERT(m_parentStack.size() == 1); ASSERT(m_scopeStack.size() == 1); auto descendants = composedTreeDescendants(m_document); auto it = descendants.begin(); auto end = descendants.end(); // FIXME: SVG <use> element may cause tree mutations during style recalc. it.dropAssertions(); while (it != end) { popParentsToDepth(it.depth()); auto& node = *it; auto& parent = this->parent(); ASSERT(node.containingShadowRoot() == scope().shadowRoot); ASSERT(node.parentElement() == parent.element || is<ShadowRoot>(node.parentNode()) || node.parentElement()->shadowRoot()); if (is<Text>(node)) { auto& text = downcast<Text>(node); if (text.styleChangeType() == ReconstructRenderTree && parent.change != Detach) m_update->addText(text, parent.element); text.clearNeedsStyleRecalc(); it.traverseNextSkippingChildren(); continue; } auto& element = downcast<Element>(node); if (it.depth() > Settings::defaultMaximumRenderTreeDepth) { resetStyleForNonRenderedDescendants(element); element.clearChildNeedsStyleRecalc(); it.traverseNextSkippingChildren(); continue; } // FIXME: We should deal with this during style invalidation. bool affectedByPreviousSibling = element.styleIsAffectedByPreviousSibling() && parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle; if (element.needsStyleRecalc() || parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle) parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle = element.affectsNextSiblingElementStyle(); bool shouldResolveForPseudoElement = shouldResolvePseudoElement(element.beforePseudoElement()) || shouldResolvePseudoElement(element.afterPseudoElement()); const RenderStyle* style; Change change; bool shouldResolve = parent.change >= Inherit || element.needsStyleRecalc() || shouldResolveForPseudoElement || affectedByPreviousSibling || element.hasDisplayContents(); if (shouldResolve) { #if PLATFORM(IOS) CheckForVisibilityChangeOnRecalcStyle checkForVisibilityChange(&element, element.renderStyle()); #endif element.resetComputedStyle(); if (element.hasCustomStyleResolveCallbacks()) { if (!element.willRecalcStyle(parent.change)) { it.traverseNextSkippingChildren(); continue; } } auto elementUpdate = resolveElement(element); if (element.hasCustomStyleResolveCallbacks()) element.didRecalcStyle(elementUpdate.change); style = elementUpdate.style.get(); change = elementUpdate.change; if (affectedByPreviousSibling && change != Detach) change = Force; if (elementUpdate.style) m_update->addElement(element, parent.element, WTFMove(elementUpdate)); element.clearNeedsStyleRecalc(); } else { style = element.renderStyle(); change = NoChange; } if (!style) { resetStyleForNonRenderedDescendants(element); element.clearChildNeedsStyleRecalc(); } bool shouldIterateChildren = style && (element.childNeedsStyleRecalc() || change != NoChange); if (!shouldIterateChildren) { it.traverseNextSkippingChildren(); continue; } pushParent(element, *style, change); it.traverseNext(); } popParentsToDepth(1); }