|
Lines 4-10
Source/WebCore/style/StyleTreeResolver.cpp_sec1
|
| 4 |
* (C) 2001 Peter Kelly (pmk@post.com) |
4 |
* (C) 2001 Peter Kelly (pmk@post.com) |
| 5 |
* (C) 2001 Dirk Mueller (mueller@kde.org) |
5 |
* (C) 2001 Dirk Mueller (mueller@kde.org) |
| 6 |
* (C) 2007 David Smith (catfish.man@gmail.com) |
6 |
* (C) 2007 David Smith (catfish.man@gmail.com) |
| 7 |
* Copyright (C) 2004-2010, 2012-2014 Apple Inc. All rights reserved. |
7 |
* Copyright (C) 2004-2010, 2012-2016 Apple Inc. All rights reserved. |
| 8 |
* (C) 2007 Eric Seidel (eric@webkit.org) |
8 |
* (C) 2007 Eric Seidel (eric@webkit.org) |
| 9 |
* |
9 |
* |
| 10 |
* This library is free software; you can redistribute it and/or |
10 |
* This library is free software; you can redistribute it and/or |
|
Lines 26-52
Source/WebCore/style/StyleTreeResolver.cpp_sec2
|
| 26 |
#include "config.h" |
26 |
#include "config.h" |
| 27 |
#include "StyleTreeResolver.h" |
27 |
#include "StyleTreeResolver.h" |
| 28 |
|
28 |
|
| 29 |
#include "AXObjectCache.h" |
|
|
| 30 |
#include "AnimationController.h" |
| 31 |
#include "AuthorStyleSheets.h" |
29 |
#include "AuthorStyleSheets.h" |
| 32 |
#include "CSSFontSelector.h" |
30 |
#include "CSSFontSelector.h" |
| 33 |
#include "ComposedTreeAncestorIterator.h" |
31 |
#include "ComposedTreeAncestorIterator.h" |
| 34 |
#include "ComposedTreeIterator.h" |
32 |
#include "ComposedTreeIterator.h" |
| 35 |
#include "ElementIterator.h" |
33 |
#include "ElementIterator.h" |
| 36 |
#include "ElementRareData.h" |
34 |
#include "HTMLBodyElement.h" |
| 37 |
#include "FlowThreadController.h" |
|
|
| 38 |
#include "HTMLSlotElement.h" |
35 |
#include "HTMLSlotElement.h" |
| 39 |
#include "InspectorInstrumentation.h" |
|
|
| 40 |
#include "LoaderStrategy.h" |
36 |
#include "LoaderStrategy.h" |
| 41 |
#include "MainFrame.h" |
37 |
#include "MainFrame.h" |
| 42 |
#include "NodeRenderStyle.h" |
38 |
#include "NodeRenderStyle.h" |
| 43 |
#include "NodeTraversal.h" |
|
|
| 44 |
#include "PlatformStrategies.h" |
39 |
#include "PlatformStrategies.h" |
| 45 |
#include "RenderFullScreen.h" |
|
|
| 46 |
#include "RenderNamedFlowThread.h" |
| 47 |
#include "RenderText.h" |
| 48 |
#include "RenderTreePosition.h" |
| 49 |
#include "RenderWidget.h" |
| 50 |
#include "Settings.h" |
40 |
#include "Settings.h" |
| 51 |
#include "ShadowRoot.h" |
41 |
#include "ShadowRoot.h" |
| 52 |
#include "StyleResolver.h" |
42 |
#include "StyleResolver.h" |
|
Lines 60-69
namespace WebCore {
Source/WebCore/style/StyleTreeResolver.cpp_sec3
|
| 60 |
|
50 |
|
| 61 |
namespace Style { |
51 |
namespace Style { |
| 62 |
|
52 |
|
| 63 |
enum DetachType { NormalDetach, ReattachDetach }; |
|
|
| 64 |
|
| 65 |
static void attachTextRenderer(Text&, RenderTreePosition&); |
53 |
static void attachTextRenderer(Text&, RenderTreePosition&); |
| 66 |
static void detachRenderTree(Element&, DetachType); |
|
|
| 67 |
static void resolveTextNode(Text&, RenderTreePosition&); |
54 |
static void resolveTextNode(Text&, RenderTreePosition&); |
| 68 |
|
55 |
|
| 69 |
class SelectorFilterPusher { |
56 |
class SelectorFilterPusher { |
|
Lines 131-146
TreeResolver::Scope::Scope(ShadowRoot& s
Source/WebCore/style/StyleTreeResolver.cpp_sec4
|
| 131 |
TreeResolver::Parent::Parent(Document& document, Change change) |
118 |
TreeResolver::Parent::Parent(Document& document, Change change) |
| 132 |
: element(nullptr) |
119 |
: element(nullptr) |
| 133 |
, style(*document.renderStyle()) |
120 |
, style(*document.renderStyle()) |
| 134 |
, renderTreePosition(*document.renderView()) |
|
|
| 135 |
, change(change) |
121 |
, change(change) |
| 136 |
{ |
122 |
{ |
| 137 |
} |
123 |
} |
| 138 |
|
124 |
|
| 139 |
TreeResolver::Parent::Parent(Element& element, RenderStyle& style, RenderTreePosition renderTreePosition, Change change) |
125 |
TreeResolver::Parent::Parent(Element& element, ElementUpdate& change) |
| 140 |
: element(&element) |
126 |
: element(&element) |
| 141 |
, style(style) |
127 |
, style(*change.style) |
| 142 |
, renderTreePosition(renderTreePosition) |
128 |
, change(change.type) |
| 143 |
, change(change) |
|
|
| 144 |
{ |
129 |
{ |
| 145 |
} |
130 |
} |
| 146 |
|
131 |
|
|
Lines 160-266
void TreeResolver::popScope()
Source/WebCore/style/StyleTreeResolver.cpp_sec5
|
| 160 |
return m_scopeStack.removeLast(); |
145 |
return m_scopeStack.removeLast(); |
| 161 |
} |
146 |
} |
| 162 |
|
147 |
|
| 163 |
static bool shouldCreateRenderer(const Element& element, const RenderElement& parentRenderer) |
|
|
| 164 |
{ |
| 165 |
if (!element.document().shouldCreateRenderers()) |
| 166 |
return false; |
| 167 |
if (!parentRenderer.canHaveChildren() && !(element.isPseudoElement() && parentRenderer.canHaveGeneratedChildren())) |
| 168 |
return false; |
| 169 |
if (parentRenderer.element() && !parentRenderer.element()->childShouldCreateRenderer(element)) |
| 170 |
return false; |
| 171 |
return true; |
| 172 |
} |
| 173 |
|
| 174 |
Ref<RenderStyle> TreeResolver::styleForElement(Element& element, RenderStyle& inheritedStyle) |
148 |
Ref<RenderStyle> TreeResolver::styleForElement(Element& element, RenderStyle& inheritedStyle) |
| 175 |
{ |
149 |
{ |
|
|
150 |
auto addRelations = [this] (std::unique_ptr<Relations> relations) |
| 151 |
{ |
| 152 |
if (!relations) |
| 153 |
return; |
| 154 |
commitNthChildRelationsToDocument(*relations); |
| 155 |
m_update->addRelations(WTFMove(relations)); |
| 156 |
}; |
| 157 |
|
| 176 |
if (!m_document.haveStylesheetsLoaded() && !element.renderer()) { |
158 |
if (!m_document.haveStylesheetsLoaded() && !element.renderer()) { |
| 177 |
m_document.setHasNodesWithPlaceholderStyle(); |
159 |
m_document.setHasNodesWithPlaceholderStyle(); |
| 178 |
return *placeholderStyle; |
160 |
return *placeholderStyle; |
| 179 |
} |
161 |
} |
| 180 |
|
162 |
|
|
|
163 |
scope().styleResolver.setOverrideRootElementStyle(m_documentElementStyle.get()); |
| 164 |
|
| 181 |
if (element.hasCustomStyleResolveCallbacks()) { |
165 |
if (element.hasCustomStyleResolveCallbacks()) { |
| 182 |
RenderStyle* shadowHostStyle = scope().shadowRoot ? scope().shadowRoot->host()->renderStyle() : nullptr; |
166 |
RenderStyle* shadowHostStyle = scope().shadowRoot ? m_update->elementStyle(*scope().shadowRoot->host()) : nullptr; |
| 183 |
if (auto customStyle = element.resolveCustomStyle(inheritedStyle, shadowHostStyle)) { |
167 |
if (auto customStyle = element.resolveCustomStyle(inheritedStyle, shadowHostStyle)) { |
| 184 |
Style::commitRelationsToDocument(WTFMove(customStyle->relations)); |
168 |
addRelations(WTFMove(customStyle->relations)); |
| 185 |
return WTFMove(customStyle->renderStyle); |
169 |
return WTFMove(customStyle->renderStyle); |
| 186 |
} |
170 |
} |
| 187 |
} |
171 |
} |
| 188 |
|
172 |
|
| 189 |
if (auto* sharingElement = scope().sharingResolver.resolve(element)) |
173 |
// if (auto* sharedStyle = scope().sharingResolver.resolve(element, *m_update)) |
| 190 |
return *sharingElement->renderStyle(); |
174 |
// return *sharedStyle; |
| 191 |
|
175 |
|
| 192 |
auto elementStyle = scope().styleResolver.styleForElement(element, &inheritedStyle, MatchAllRules, nullptr, &scope().selectorFilter); |
176 |
auto elementStyle = scope().styleResolver.styleForElement(element, &inheritedStyle, MatchAllRules, nullptr, &scope().selectorFilter); |
| 193 |
|
177 |
|
| 194 |
Style::commitRelationsToDocument(WTFMove(elementStyle.relations)); |
178 |
addRelations(WTFMove(elementStyle.relations)); |
| 195 |
return WTFMove(elementStyle.renderStyle); |
179 |
return WTFMove(elementStyle.renderStyle); |
| 196 |
} |
180 |
} |
| 197 |
|
181 |
|
| 198 |
#if ENABLE(CSS_REGIONS) |
|
|
| 199 |
static RenderNamedFlowThread* moveToFlowThreadIfNeeded(Element& element, const RenderStyle& style) |
| 200 |
{ |
| 201 |
if (!element.shouldMoveToFlowThread(style)) |
| 202 |
return 0; |
| 203 |
|
| 204 |
FlowThreadController& flowThreadController = element.document().renderView()->flowThreadController(); |
| 205 |
RenderNamedFlowThread& parentFlowRenderer = flowThreadController.ensureRenderFlowThreadWithName(style.flowThread()); |
| 206 |
flowThreadController.registerNamedFlowContentElement(element, parentFlowRenderer); |
| 207 |
return &parentFlowRenderer; |
| 208 |
} |
| 209 |
#endif |
| 210 |
|
| 211 |
void TreeResolver::createRenderer(Element& element, RenderTreePosition& renderTreePosition, RefPtr<RenderStyle>&& resolvedStyle) |
| 212 |
{ |
| 213 |
ASSERT(shouldCreateRenderer(element, renderTreePosition.parent())); |
| 214 |
ASSERT(resolvedStyle); |
| 215 |
|
| 216 |
RenderNamedFlowThread* parentFlowRenderer = 0; |
| 217 |
#if ENABLE(CSS_REGIONS) |
| 218 |
parentFlowRenderer = moveToFlowThreadIfNeeded(element, *resolvedStyle); |
| 219 |
#endif |
| 220 |
|
| 221 |
if (!element.rendererIsNeeded(*resolvedStyle)) |
| 222 |
return; |
| 223 |
|
| 224 |
renderTreePosition.computeNextSibling(element); |
| 225 |
|
| 226 |
RenderTreePosition insertionPosition = parentFlowRenderer |
| 227 |
? RenderTreePosition(*parentFlowRenderer, parentFlowRenderer->nextRendererForElement(element)) |
| 228 |
: renderTreePosition; |
| 229 |
|
| 230 |
RenderElement* newRenderer = element.createElementRenderer(resolvedStyle.releaseNonNull(), insertionPosition).leakPtr(); |
| 231 |
if (!newRenderer) |
| 232 |
return; |
| 233 |
if (!insertionPosition.canInsert(*newRenderer)) { |
| 234 |
newRenderer->destroy(); |
| 235 |
return; |
| 236 |
} |
| 237 |
|
| 238 |
// Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style |
| 239 |
// for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail. |
| 240 |
newRenderer->setFlowThreadState(insertionPosition.parent().flowThreadState()); |
| 241 |
|
| 242 |
// Code below updateAnimations() can depend on Element::renderer() already being set. |
| 243 |
element.setRenderer(newRenderer); |
| 244 |
|
| 245 |
// FIXME: There's probably a better way to factor this. |
| 246 |
// This just does what setAnimatedStyle() does, except with setStyleInternal() instead of setStyle(). |
| 247 |
Ref<RenderStyle> animatedStyle = newRenderer->style(); |
| 248 |
newRenderer->animation().updateAnimations(*newRenderer, animatedStyle, animatedStyle); |
| 249 |
newRenderer->setStyleInternal(WTFMove(animatedStyle)); |
| 250 |
|
| 251 |
newRenderer->initializeStyle(); |
| 252 |
|
| 253 |
#if ENABLE(FULLSCREEN_API) |
| 254 |
if (m_document.webkitIsFullScreen() && m_document.webkitCurrentFullScreenElement() == &element) { |
| 255 |
newRenderer = RenderFullScreen::wrapRenderer(newRenderer, &insertionPosition.parent(), m_document); |
| 256 |
if (!newRenderer) |
| 257 |
return; |
| 258 |
} |
| 259 |
#endif |
| 260 |
// Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer. |
| 261 |
insertionPosition.insert(*newRenderer); |
| 262 |
} |
| 263 |
|
| 264 |
static void invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(Node& current) |
182 |
static void invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(Node& current) |
| 265 |
{ |
183 |
{ |
| 266 |
// FIXME: This needs to traverse in composed tree order. |
184 |
// FIXME: This needs to traverse in composed tree order. |
|
Lines 348-354
static void createTextRendererIfNeeded(T
Source/WebCore/style/StyleTreeResolver.cpp_sec6
|
| 348 |
newRenderer->setFlowThreadState(renderTreePosition.parent().flowThreadState()); |
266 |
newRenderer->setFlowThreadState(renderTreePosition.parent().flowThreadState()); |
| 349 |
|
267 |
|
| 350 |
textNode.setRenderer(newRenderer.get()); |
268 |
textNode.setRenderer(newRenderer.get()); |
| 351 |
// Parent takes care of the animations, no need to call setAnimatableStyle. |
|
|
| 352 |
renderTreePosition.insert(*newRenderer.leakPtr()); |
269 |
renderTreePosition.insert(*newRenderer.leakPtr()); |
| 353 |
} |
270 |
} |
| 354 |
|
271 |
|
|
Lines 381-455
void updateTextRendererAfterContentChang
Source/WebCore/style/StyleTreeResolver.cpp_sec7
|
| 381 |
textNode.renderer()->setTextWithOffset(textNode.data(), offsetOfReplacedData, lengthOfReplacedData); |
298 |
textNode.renderer()->setTextWithOffset(textNode.data(), offsetOfReplacedData, lengthOfReplacedData); |
| 382 |
} |
299 |
} |
| 383 |
|
300 |
|
| 384 |
void TreeResolver::createRenderTreeForChildren(ContainerNode& current, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition) |
|
|
| 385 |
{ |
| 386 |
for (Node* child = current.firstChild(); child; child = child->nextSibling()) { |
| 387 |
ASSERT((!child->renderer() || child->isNamedFlowContentNode()) || current.shadowRoot()); |
| 388 |
if (child->renderer()) { |
| 389 |
renderTreePosition.invalidateNextSibling(*child->renderer()); |
| 390 |
continue; |
| 391 |
} |
| 392 |
if (is<Text>(*child)) { |
| 393 |
attachTextRenderer(downcast<Text>(*child), renderTreePosition); |
| 394 |
continue; |
| 395 |
} |
| 396 |
if (is<Element>(*child)) |
| 397 |
createRenderTreeRecursively(downcast<Element>(*child), inheritedStyle, renderTreePosition, nullptr); |
| 398 |
} |
| 399 |
} |
| 400 |
|
| 401 |
void TreeResolver::createRenderTreeForShadowRoot(ShadowRoot& shadowRoot) |
| 402 |
{ |
| 403 |
ASSERT(shadowRoot.host()); |
| 404 |
ASSERT(shadowRoot.host()->renderer()); |
| 405 |
|
| 406 |
pushScope(shadowRoot); |
| 407 |
|
| 408 |
auto& renderer = *shadowRoot.host()->renderer(); |
| 409 |
RenderTreePosition renderTreePosition(renderer); |
| 410 |
createRenderTreeForChildren(shadowRoot, renderer.style(), renderTreePosition); |
| 411 |
|
| 412 |
popScope(); |
| 413 |
|
| 414 |
shadowRoot.clearNeedsStyleRecalc(); |
| 415 |
shadowRoot.clearChildNeedsStyleRecalc(); |
| 416 |
} |
| 417 |
|
| 418 |
static PseudoElement* beforeOrAfterPseudoElement(Element& current, PseudoId pseudoId) |
| 419 |
{ |
| 420 |
ASSERT(pseudoId == BEFORE || pseudoId == AFTER); |
| 421 |
if (pseudoId == BEFORE) |
| 422 |
return current.beforePseudoElement(); |
| 423 |
return current.afterPseudoElement(); |
| 424 |
} |
| 425 |
|
| 426 |
static void setBeforeOrAfterPseudoElement(Element& current, Ref<PseudoElement>&& pseudoElement, PseudoId pseudoId) |
| 427 |
{ |
| 428 |
ASSERT(pseudoId == BEFORE || pseudoId == AFTER); |
| 429 |
if (pseudoId == BEFORE) { |
| 430 |
current.setBeforePseudoElement(WTFMove(pseudoElement)); |
| 431 |
return; |
| 432 |
} |
| 433 |
current.setAfterPseudoElement(WTFMove(pseudoElement)); |
| 434 |
} |
| 435 |
|
| 436 |
static void clearBeforeOrAfterPseudoElement(Element& current, PseudoId pseudoId) |
| 437 |
{ |
| 438 |
ASSERT(pseudoId == BEFORE || pseudoId == AFTER); |
| 439 |
if (pseudoId == BEFORE) { |
| 440 |
current.clearBeforePseudoElement(); |
| 441 |
return; |
| 442 |
} |
| 443 |
current.clearAfterPseudoElement(); |
| 444 |
} |
| 445 |
|
| 446 |
static void resetStyleForNonRenderedDescendants(Element& current) |
301 |
static void resetStyleForNonRenderedDescendants(Element& current) |
| 447 |
{ |
302 |
{ |
| 448 |
// FIXME: This is not correct with shadow trees. This should be done with ComposedTreeIterator. |
303 |
// FIXME: This is not correct with shadow trees. This should be done with ComposedTreeIterator. |
| 449 |
ASSERT(!current.renderer()); |
|
|
| 450 |
bool elementNeedingStyleRecalcAffectsNextSiblingElementStyle = false; |
304 |
bool elementNeedingStyleRecalcAffectsNextSiblingElementStyle = false; |
| 451 |
for (auto& child : childrenOfType<Element>(current)) { |
305 |
for (auto& child : childrenOfType<Element>(current)) { |
| 452 |
ASSERT(!child.renderer()); |
|
|
| 453 |
bool affectedByPreviousSibling = child.styleIsAffectedByPreviousSibling() && elementNeedingStyleRecalcAffectsNextSiblingElementStyle; |
306 |
bool affectedByPreviousSibling = child.styleIsAffectedByPreviousSibling() && elementNeedingStyleRecalcAffectsNextSiblingElementStyle; |
| 454 |
if (child.needsStyleRecalc() || elementNeedingStyleRecalcAffectsNextSiblingElementStyle) |
307 |
if (child.needsStyleRecalc() || elementNeedingStyleRecalcAffectsNextSiblingElementStyle) |
| 455 |
elementNeedingStyleRecalcAffectsNextSiblingElementStyle = child.affectsNextSiblingElementStyle(); |
308 |
elementNeedingStyleRecalcAffectsNextSiblingElementStyle = child.affectsNextSiblingElementStyle(); |
|
Lines 466-576
static void resetStyleForNonRenderedDesc
Source/WebCore/style/StyleTreeResolver.cpp_sec8
|
| 466 |
} |
319 |
} |
| 467 |
} |
320 |
} |
| 468 |
|
321 |
|
| 469 |
static bool needsPseudoElement(Element& current, PseudoId pseudoId) |
|
|
| 470 |
{ |
| 471 |
if (!current.renderer() || !current.renderer()->canHaveGeneratedChildren()) |
| 472 |
return false; |
| 473 |
if (current.isPseudoElement()) |
| 474 |
return false; |
| 475 |
if (!pseudoElementRendererIsNeeded(current.renderer()->getCachedPseudoStyle(pseudoId))) |
| 476 |
return false; |
| 477 |
return true; |
| 478 |
} |
| 479 |
|
| 480 |
void TreeResolver::createRenderTreeForBeforeOrAfterPseudoElement(Element& current, PseudoId pseudoId, RenderTreePosition& renderTreePosition) |
| 481 |
{ |
| 482 |
if (!needsPseudoElement(current, pseudoId)) |
| 483 |
return; |
| 484 |
Ref<PseudoElement> pseudoElement = PseudoElement::create(current, pseudoId); |
| 485 |
InspectorInstrumentation::pseudoElementCreated(m_document.page(), pseudoElement.get()); |
| 486 |
setBeforeOrAfterPseudoElement(current, pseudoElement.copyRef(), pseudoId); |
| 487 |
createRenderTreeRecursively(pseudoElement.get(), *current.renderStyle(), renderTreePosition, nullptr); |
| 488 |
} |
| 489 |
|
| 490 |
#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) |
| 491 |
void TreeResolver::createRenderTreeForSlotAssignees(HTMLSlotElement& slot, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition) |
| 492 |
{ |
| 493 |
ASSERT(shouldCreateRenderer(slot, renderTreePosition.parent())); |
| 494 |
|
| 495 |
if (auto* assignedNodes = slot.assignedNodes()) { |
| 496 |
pushEnclosingScope(); |
| 497 |
for (auto* child : *assignedNodes) { |
| 498 |
if (is<Text>(*child)) |
| 499 |
attachTextRenderer(downcast<Text>(*child), renderTreePosition); |
| 500 |
else if (is<Element>(*child)) |
| 501 |
createRenderTreeRecursively(downcast<Element>(*child), inheritedStyle, renderTreePosition, nullptr); |
| 502 |
} |
| 503 |
popScope(); |
| 504 |
} else { |
| 505 |
SelectorFilterPusher selectorFilterPusher(scope().selectorFilter, slot); |
| 506 |
createRenderTreeForChildren(slot, inheritedStyle, renderTreePosition); |
| 507 |
} |
| 508 |
|
| 509 |
slot.clearNeedsStyleRecalc(); |
| 510 |
slot.clearChildNeedsStyleRecalc(); |
| 511 |
} |
| 512 |
#endif |
| 513 |
|
| 514 |
void TreeResolver::createRenderTreeRecursively(Element& current, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition, RefPtr<RenderStyle>&& resolvedStyle) |
| 515 |
{ |
| 516 |
ASSERT(!current.renderer()); |
| 517 |
|
| 518 |
PostResolutionCallbackDisabler callbackDisabler(m_document); |
| 519 |
WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; |
| 520 |
|
| 521 |
bool shouldCallCreateRenderer = shouldCreateRenderer(current, renderTreePosition.parent()); |
| 522 |
|
| 523 |
RefPtr<RenderStyle> style = resolvedStyle; |
| 524 |
if (!style) |
| 525 |
style = styleForElement(current, inheritedStyle); |
| 526 |
|
| 527 |
#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) |
| 528 |
if (is<HTMLSlotElement>(current)) { |
| 529 |
if (shouldCallCreateRenderer && current.rendererIsNeeded(*style)) |
| 530 |
createRenderTreeForSlotAssignees(downcast<HTMLSlotElement>(current), inheritedStyle, renderTreePosition); |
| 531 |
return; |
| 532 |
} |
| 533 |
#endif |
| 534 |
|
| 535 |
if (current.hasCustomStyleResolveCallbacks()) |
| 536 |
current.willAttachRenderers(); |
| 537 |
|
| 538 |
if (shouldCallCreateRenderer) |
| 539 |
createRenderer(current, renderTreePosition, style.releaseNonNull()); |
| 540 |
|
| 541 |
if (auto* renderer = current.renderer()) { |
| 542 |
SelectorFilterPusher selectorFilterPusher(scope().selectorFilter, current, SelectorFilterPusher::NoPush); |
| 543 |
|
| 544 |
RenderTreePosition childRenderTreePosition(*renderer); |
| 545 |
createRenderTreeForBeforeOrAfterPseudoElement(current, BEFORE, childRenderTreePosition); |
| 546 |
|
| 547 |
auto* shadowRoot = current.shadowRoot(); |
| 548 |
if (shadowRoot) { |
| 549 |
selectorFilterPusher.push(); |
| 550 |
createRenderTreeForShadowRoot(*shadowRoot); |
| 551 |
} else if (current.firstChild()) |
| 552 |
selectorFilterPusher.push(); |
| 553 |
|
| 554 |
bool skipChildren = shadowRoot; |
| 555 |
if (!skipChildren) |
| 556 |
createRenderTreeForChildren(current, renderer->style(), childRenderTreePosition); |
| 557 |
|
| 558 |
if (AXObjectCache* cache = m_document.axObjectCache()) |
| 559 |
cache->updateCacheAfterNodeIsAttached(¤t); |
| 560 |
|
| 561 |
createRenderTreeForBeforeOrAfterPseudoElement(current, AFTER, childRenderTreePosition); |
| 562 |
|
| 563 |
current.updateFocusAppearanceAfterAttachIfNeeded(); |
| 564 |
} else |
| 565 |
resetStyleForNonRenderedDescendants(current); |
| 566 |
|
| 567 |
current.clearNeedsStyleRecalc(); |
| 568 |
current.clearChildNeedsStyleRecalc(); |
| 569 |
|
| 570 |
if (current.hasCustomStyleResolveCallbacks()) |
| 571 |
current.didAttachRenderers(); |
| 572 |
} |
| 573 |
|
| 574 |
static void detachChildren(ContainerNode& current, DetachType detachType) |
322 |
static void detachChildren(ContainerNode& current, DetachType detachType) |
| 575 |
{ |
323 |
{ |
| 576 |
for (Node* child = current.firstChild(); child; child = child->nextSibling()) { |
324 |
for (Node* child = current.firstChild(); child; child = child->nextSibling()) { |
|
Lines 606-612
static void detachSlotAssignees(HTMLSlot
Source/WebCore/style/StyleTreeResolver.cpp_sec9
|
| 606 |
} |
354 |
} |
| 607 |
#endif |
355 |
#endif |
| 608 |
|
356 |
|
| 609 |
static void detachRenderTree(Element& current, DetachType detachType) |
357 |
void detachRenderTree(Element& current, DetachType detachType) |
| 610 |
{ |
358 |
{ |
| 611 |
WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; |
359 |
WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; |
| 612 |
|
360 |
|
|
Lines 637-720
static void detachRenderTree(Element& cu
Source/WebCore/style/StyleTreeResolver.cpp_sec10
|
| 637 |
current.didDetachRenderers(); |
385 |
current.didDetachRenderers(); |
| 638 |
} |
386 |
} |
| 639 |
|
387 |
|
| 640 |
static bool pseudoStyleCacheIsInvalid(RenderElement* renderer, RenderStyle* newStyle) |
388 |
ElementUpdate TreeResolver::resolveElement(Element& element) |
| 641 |
{ |
389 |
{ |
| 642 |
const RenderStyle& currentStyle = renderer->style(); |
390 |
ElementUpdate update; |
| 643 |
|
391 |
|
| 644 |
const PseudoStyleCache* pseudoStyleCache = currentStyle.cachedPseudoStyles(); |
392 |
update.wasExplicitlyInvalidated = element.styleChangeType() != NoStyleChange; |
| 645 |
if (!pseudoStyleCache) |
393 |
update.needsRecompositeLayers = element.styleChangeType() == SyntheticStyleChange; |
| 646 |
return false; |
|
|
| 647 |
|
394 |
|
| 648 |
for (auto& cache : *pseudoStyleCache) { |
395 |
auto newStyle = styleForElement(element, parent().style); |
| 649 |
RefPtr<RenderStyle> newPseudoStyle; |
|
|
| 650 |
PseudoId pseudoId = cache->styleType(); |
| 651 |
if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) |
| 652 |
newPseudoStyle = renderer->uncachedFirstLineStyle(newStyle); |
| 653 |
else |
| 654 |
newPseudoStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId), newStyle, newStyle); |
| 655 |
if (!newPseudoStyle) |
| 656 |
return true; |
| 657 |
if (*newPseudoStyle != *cache) { |
| 658 |
if (pseudoId < FIRST_INTERNAL_PSEUDOID) |
| 659 |
newStyle->setHasPseudoStyle(pseudoId); |
| 660 |
newStyle->addCachedPseudoStyle(newPseudoStyle); |
| 661 |
if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) { |
| 662 |
// FIXME: We should do an actual diff to determine whether a repaint vs. layout |
| 663 |
// is needed, but for now just assume a layout will be required. The diff code |
| 664 |
// in RenderObject::setStyle would need to be factored out so that it could be reused. |
| 665 |
renderer->setNeedsLayoutAndPrefWidthsRecalc(); |
| 666 |
} |
| 667 |
return true; |
| 668 |
} |
| 669 |
} |
| 670 |
return false; |
| 671 |
} |
| 672 |
|
396 |
|
| 673 |
Change TreeResolver::resolveElement(Element& current) |
397 |
auto* renderer = element.renderer(); |
| 674 |
{ |
398 |
bool needsNewRenderer = !renderer || element.styleChangeType() == ReconstructRenderTree || parent().change == Detach; |
| 675 |
Change localChange = Detach; |
|
|
| 676 |
RefPtr<RenderStyle> newStyle; |
| 677 |
RefPtr<RenderStyle> currentStyle = current.renderStyle(); |
| 678 |
|
399 |
|
| 679 |
if (currentStyle && current.styleChangeType() != ReconstructRenderTree) { |
400 |
if (!needsNewRenderer && m_document.frame()->animation().updateAnimations(*renderer, newStyle, newStyle)) |
| 680 |
Ref<RenderStyle> style(styleForElement(current, parent().style)); |
401 |
update.needsRecompositeLayers = true; |
| 681 |
newStyle = style.ptr(); |
|
|
| 682 |
localChange = determineChange(*currentStyle, style); |
| 683 |
} |
| 684 |
if (localChange == Detach) { |
| 685 |
if (current.renderer() || current.isNamedFlowContentNode()) |
| 686 |
detachRenderTree(current, ReattachDetach); |
| 687 |
#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) |
| 688 |
else if (is<HTMLSlotElement>(current)) |
| 689 |
detachRenderTree(current, ReattachDetach); |
| 690 |
#endif |
| 691 |
createRenderTreeRecursively(current, parent().style, parent().renderTreePosition, newStyle.release()); |
| 692 |
invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(current); |
| 693 |
|
402 |
|
| 694 |
return Detach; |
403 |
update.type = needsNewRenderer ? Detach : determineChange(renderer->style(), newStyle); |
| 695 |
} |
404 |
update.style = WTFMove(newStyle); |
|
|
405 |
// |
| 406 |
// if (update.type == NoChange && !update.wasExplicitlyInvalidated) |
| 407 |
// update.style = &renderer->style(); |
| 408 |
// else |
| 409 |
// update.style = WTFMove(newStyle); |
| 410 |
// |
| 411 |
if (&element == m_document.documentElement()) { |
| 412 |
m_documentElementStyle = update.style; |
| 696 |
|
413 |
|
| 697 |
if (RenderElement* renderer = current.renderer()) { |
414 |
// If "rem" units are used anywhere in the document, and if the document element's font size changes, then force font updating |
| 698 |
if (localChange != NoChange || pseudoStyleCacheIsInvalid(renderer, newStyle.get()) || (parent().change == Force && renderer->requiresForcedStyleRecalcPropagation()) || current.styleChangeType() == SyntheticStyleChange) |
415 |
// all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway). |
| 699 |
renderer->setAnimatableStyle(*newStyle, current.styleChangeType() == SyntheticStyleChange ? StyleDifferenceRecompositeLayer : StyleDifferenceEqual); |
416 |
if (m_document.authorStyleSheets().usesRemUnits() && update.type != NoChange && renderer && update.style && renderer->style().fontSize() != update.style->fontSize()) { |
| 700 |
else if (current.needsStyleRecalc()) { |
417 |
// Cached RenderStyles may depend on the rem units. |
| 701 |
// Although no change occurred, we use the new style so that the cousin style sharing code won't get |
418 |
scope().styleResolver.invalidateMatchedPropertiesCache(); |
| 702 |
// fooled into believing this style is the same. |
419 |
update.type = Force; |
| 703 |
renderer->setStyleInternal(*newStyle); |
|
|
| 704 |
} |
420 |
} |
| 705 |
} |
421 |
} |
| 706 |
|
422 |
|
| 707 |
// If "rem" units are used anywhere in the document, and if the document element's font size changes, then force font updating |
423 |
// This is needed for resolving color:-webkit-text for subsequent elements. |
| 708 |
// all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway). |
424 |
// FIXME: We shouldn't mutate document when resolving style. |
| 709 |
if (m_document.authorStyleSheets().usesRemUnits() && m_document.documentElement() == ¤t && localChange != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize()) { |
425 |
if (&element == m_document.body()) |
| 710 |
// Cached RenderStyles may depend on the re units. |
426 |
m_document.setTextColor(update.style->visitedDependentColor(CSSPropertyColor)); |
| 711 |
scope().styleResolver.invalidateMatchedPropertiesCache(); |
|
|
| 712 |
return Force; |
| 713 |
} |
| 714 |
if (parent().change == Force || current.styleChangeType() >= FullStyleChange) |
| 715 |
return Force; |
| 716 |
|
427 |
|
| 717 |
return localChange; |
428 |
if (update.type != Detach && (parent().change == Force || element.styleChangeType() >= FullStyleChange)) |
|
|
429 |
update.type = Force; |
| 430 |
|
| 431 |
return update; |
| 718 |
} |
432 |
} |
| 719 |
|
433 |
|
| 720 |
void resolveTextNode(Text& text, RenderTreePosition& renderTreePosition) |
434 |
void resolveTextNode(Text& text, RenderTreePosition& renderTreePosition) |
|
Lines 736-765
void resolveTextNode(Text& text, RenderT
Source/WebCore/style/StyleTreeResolver.cpp_sec11
|
| 736 |
invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(text); |
450 |
invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(text); |
| 737 |
} |
451 |
} |
| 738 |
|
452 |
|
| 739 |
void TreeResolver::resolveBeforeOrAfterPseudoElement(Element& current, Change change, PseudoId pseudoId, RenderTreePosition& renderTreePosition) |
|
|
| 740 |
{ |
| 741 |
if (!current.renderer()) |
| 742 |
return; |
| 743 |
PseudoElement* existingPseudoElement = beforeOrAfterPseudoElement(current, pseudoId); |
| 744 |
if (!existingPseudoElement) { |
| 745 |
createRenderTreeForBeforeOrAfterPseudoElement(current, pseudoId, renderTreePosition); |
| 746 |
return; |
| 747 |
} |
| 748 |
|
| 749 |
if (existingPseudoElement->renderer()) |
| 750 |
renderTreePosition.invalidateNextSibling(*existingPseudoElement->renderer()); |
| 751 |
|
| 752 |
if (change == NoChange && !existingPseudoElement->needsStyleRecalc()) |
| 753 |
return; |
| 754 |
|
| 755 |
if (needsPseudoElement(current, pseudoId)) { |
| 756 |
auto change = resolveElement(*existingPseudoElement); |
| 757 |
existingPseudoElement->didRecalcStyle(change); |
| 758 |
existingPseudoElement->clearNeedsStyleRecalc(); |
| 759 |
} else |
| 760 |
clearBeforeOrAfterPseudoElement(current, pseudoId); |
| 761 |
} |
| 762 |
|
| 763 |
#if PLATFORM(IOS) |
453 |
#if PLATFORM(IOS) |
| 764 |
static EVisibility elementImplicitVisibility(const Element* element) |
454 |
static EVisibility elementImplicitVisibility(const Element* element) |
| 765 |
{ |
455 |
{ |
|
Lines 814-824
private:
Source/WebCore/style/StyleTreeResolver.cpp_sec12
|
| 814 |
}; |
504 |
}; |
| 815 |
#endif // PLATFORM(IOS) |
505 |
#endif // PLATFORM(IOS) |
| 816 |
|
506 |
|
| 817 |
void TreeResolver::pushParent(Element& element, RenderStyle& style, RenderTreePosition renderTreePosition, Change change) |
507 |
void TreeResolver::pushParent(Element& element, ElementUpdate& update) |
| 818 |
{ |
508 |
{ |
| 819 |
scope().selectorFilter.pushParent(&element); |
509 |
scope().selectorFilter.pushParent(&element); |
| 820 |
|
510 |
|
| 821 |
Parent parent(element, style, renderTreePosition, change); |
511 |
Parent parent(element, update); |
| 822 |
|
512 |
|
| 823 |
if (auto* shadowRoot = element.shadowRoot()) { |
513 |
if (auto* shadowRoot = element.shadowRoot()) { |
| 824 |
pushScope(*shadowRoot); |
514 |
pushScope(*shadowRoot); |
|
Lines 832-847
void TreeResolver::pushParent(Element& e
Source/WebCore/style/StyleTreeResolver.cpp_sec13
|
| 832 |
#endif |
522 |
#endif |
| 833 |
|
523 |
|
| 834 |
m_parentStack.append(WTFMove(parent)); |
524 |
m_parentStack.append(WTFMove(parent)); |
| 835 |
|
|
|
| 836 |
resolveBeforeOrAfterPseudoElement(element, change, BEFORE, renderTreePosition); |
| 837 |
} |
525 |
} |
| 838 |
|
526 |
|
| 839 |
void TreeResolver::popParent() |
527 |
void TreeResolver::popParent() |
| 840 |
{ |
528 |
{ |
| 841 |
auto& parentElement = *parent().element; |
529 |
auto& parentElement = *parent().element; |
| 842 |
|
530 |
|
| 843 |
resolveBeforeOrAfterPseudoElement(parentElement, parent().change, AFTER, parent().renderTreePosition); |
|
|
| 844 |
|
| 845 |
parentElement.clearNeedsStyleRecalc(); |
531 |
parentElement.clearNeedsStyleRecalc(); |
| 846 |
parentElement.clearChildNeedsStyleRecalc(); |
532 |
parentElement.clearChildNeedsStyleRecalc(); |
| 847 |
|
533 |
|
|
Lines 862-869
void TreeResolver::popParentsToDepth(uns
Source/WebCore/style/StyleTreeResolver.cpp_sec14
|
| 862 |
popParent(); |
548 |
popParent(); |
| 863 |
} |
549 |
} |
| 864 |
|
550 |
|
|
|
551 |
|
| 552 |
void TreeResolver::addUpdate(Text& text) |
| 553 |
{ |
| 554 |
m_update->add(text, parent().element); |
| 555 |
} |
| 556 |
|
| 557 |
void TreeResolver::addUpdate(Element& element, ElementUpdate& update) |
| 558 |
{ |
| 559 |
m_update->add(element, parent().element, update); |
| 560 |
} |
| 561 |
|
| 562 |
static bool shouldResolvePseudoElement(PseudoElement* pseudoElement) |
| 563 |
{ |
| 564 |
if (!pseudoElement) |
| 565 |
return false; |
| 566 |
bool needsStyleRecalc = pseudoElement->needsStyleRecalc(); |
| 567 |
pseudoElement->clearNeedsStyleRecalc(); |
| 568 |
return needsStyleRecalc; |
| 569 |
} |
| 570 |
|
| 865 |
void TreeResolver::resolveComposedTree() |
571 |
void TreeResolver::resolveComposedTree() |
| 866 |
{ |
572 |
{ |
|
|
573 |
fprintf(stderr, "resolveComposedTree\n"); |
| 574 |
// fprintf(stderr, "%s\n", composedTreeAsText(m_document, ComposedTreeAsTextMode::WithPointers).utf8().data()); |
| 575 |
|
| 867 |
ASSERT(m_parentStack.size() == 1); |
576 |
ASSERT(m_parentStack.size() == 1); |
| 868 |
ASSERT(m_scopeStack.size() == 1); |
577 |
ASSERT(m_scopeStack.size() == 1); |
| 869 |
|
578 |
|
|
Lines 883-894
void TreeResolver::resolveComposedTree()
Source/WebCore/style/StyleTreeResolver.cpp_sec15
|
| 883 |
ASSERT(node.containingShadowRoot() == scope().shadowRoot); |
592 |
ASSERT(node.containingShadowRoot() == scope().shadowRoot); |
| 884 |
ASSERT(node.parentElement() == parent.element || is<ShadowRoot>(node.parentNode()) || node.parentElement()->shadowRoot()); |
593 |
ASSERT(node.parentElement() == parent.element || is<ShadowRoot>(node.parentNode()) || node.parentElement()->shadowRoot()); |
| 885 |
|
594 |
|
| 886 |
if (auto* existingRenderer = node.renderer()) |
|
|
| 887 |
parent.renderTreePosition.invalidateNextSibling(*existingRenderer); |
| 888 |
|
| 889 |
if (is<Text>(node)) { |
595 |
if (is<Text>(node)) { |
| 890 |
if (node.needsStyleRecalc()) |
596 |
auto& text = downcast<Text>(node); |
| 891 |
resolveTextNode(downcast<Text>(node), parent.renderTreePosition); |
597 |
if (text.styleChangeType() == ReconstructRenderTree && parent.change != Detach) |
|
|
598 |
addUpdate(text); |
| 599 |
|
| 600 |
text.clearNeedsStyleRecalc(); |
| 892 |
it.traverseNextSkippingChildren(); |
601 |
it.traverseNextSkippingChildren(); |
| 893 |
continue; |
602 |
continue; |
| 894 |
} |
603 |
} |
|
Lines 900-908
void TreeResolver::resolveComposedTree()
Source/WebCore/style/StyleTreeResolver.cpp_sec16
|
| 900 |
if (element.needsStyleRecalc() || parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle) |
609 |
if (element.needsStyleRecalc() || parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle) |
| 901 |
parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle = element.affectsNextSiblingElementStyle(); |
610 |
parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle = element.affectsNextSiblingElementStyle(); |
| 902 |
|
611 |
|
| 903 |
Change change = NoChange; |
612 |
bool shouldResolveForPseudoElement = shouldResolvePseudoElement(element.beforePseudoElement()) || shouldResolvePseudoElement(element.afterPseudoElement()); |
| 904 |
|
613 |
|
| 905 |
bool shouldResolve = parent.change >= Inherit || element.needsStyleRecalc() || affectedByPreviousSibling; |
614 |
ElementUpdate update; |
|
|
615 |
update.style = element.renderStyle(); |
| 616 |
|
| 617 |
bool shouldResolve = parent.change >= Inherit || element.needsStyleRecalc() || shouldResolveForPseudoElement || affectedByPreviousSibling; |
| 906 |
if (shouldResolve) { |
618 |
if (shouldResolve) { |
| 907 |
#if PLATFORM(IOS) |
619 |
#if PLATFORM(IOS) |
| 908 |
CheckForVisibilityChangeOnRecalcStyle checkForVisibilityChange(&element, element.renderStyle()); |
620 |
CheckForVisibilityChangeOnRecalcStyle checkForVisibilityChange(&element, element.renderStyle()); |
|
Lines 915-959
void TreeResolver::resolveComposedTree()
Source/WebCore/style/StyleTreeResolver.cpp_sec17
|
| 915 |
continue; |
627 |
continue; |
| 916 |
} |
628 |
} |
| 917 |
} |
629 |
} |
| 918 |
change = resolveElement(element); |
630 |
update = resolveElement(element); |
| 919 |
|
|
|
| 920 |
element.clearNeedsStyleRecalc(); |
| 921 |
|
631 |
|
| 922 |
if (element.hasCustomStyleResolveCallbacks()) |
632 |
if (element.hasCustomStyleResolveCallbacks()) |
| 923 |
element.didRecalcStyle(change); |
633 |
element.didRecalcStyle(update.type); |
| 924 |
|
634 |
|
| 925 |
if (change == Detach) { |
635 |
if (affectedByPreviousSibling && update.type != Detach) |
| 926 |
it.traverseNextSkippingChildren(); |
636 |
update.type = Force; |
| 927 |
continue; |
|
|
| 928 |
} |
| 929 |
|
637 |
|
| 930 |
if (affectedByPreviousSibling) |
638 |
addUpdate(element, update); |
| 931 |
change = Force; |
639 |
|
|
|
640 |
element.clearNeedsStyleRecalc(); |
| 932 |
} |
641 |
} |
| 933 |
|
642 |
|
|
|
643 |
|
| 934 |
#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) |
644 |
#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) |
| 935 |
if (is<HTMLSlotElement>(element)) { |
645 |
if (is<HTMLSlotElement>(element)) { |
| 936 |
// FIXME: We should compute style for the slot and use it as parent style. |
646 |
// FIXME: We should compute style for the slot and use it as parent style. |
| 937 |
// FIXME: This should be display:contents check. |
647 |
// Duplicate the style from the parent context. |
| 938 |
// Duplicate the style and render tree position from the current context. |
648 |
ElementUpdate slotUpdate; |
| 939 |
pushParent(element, parent.style.get(), parent.renderTreePosition, change); |
649 |
slotUpdate.style = parent.style.ptr(); |
|
|
650 |
slotUpdate.type = update.type; |
| 651 |
if (!shouldResolve) |
| 652 |
addUpdate(element, slotUpdate); |
| 653 |
pushParent(element, slotUpdate); |
| 940 |
it.traverseNext(); |
654 |
it.traverseNext(); |
| 941 |
continue; |
655 |
continue; |
| 942 |
} |
656 |
} |
| 943 |
#endif |
657 |
#endif |
| 944 |
auto* renderer = element.renderer(); |
658 |
if (!update.style) { |
| 945 |
if (!renderer) { |
|
|
| 946 |
resetStyleForNonRenderedDescendants(element); |
659 |
resetStyleForNonRenderedDescendants(element); |
| 947 |
element.clearChildNeedsStyleRecalc(); |
660 |
element.clearChildNeedsStyleRecalc(); |
| 948 |
} |
661 |
} |
| 949 |
|
662 |
|
| 950 |
bool shouldIterateChildren = renderer && (element.childNeedsStyleRecalc() || change != NoChange); |
663 |
bool shouldIterateChildren = update.style && (element.childNeedsStyleRecalc() || update.type != NoChange); |
| 951 |
if (!shouldIterateChildren) { |
664 |
if (!shouldIterateChildren) { |
| 952 |
it.traverseNextSkippingChildren(); |
665 |
it.traverseNextSkippingChildren(); |
| 953 |
continue; |
666 |
continue; |
| 954 |
} |
667 |
} |
| 955 |
|
668 |
|
| 956 |
pushParent(element, renderer->style(), RenderTreePosition(*renderer), change); |
669 |
pushParent(element, update); |
| 957 |
|
670 |
|
| 958 |
it.traverseNext(); |
671 |
it.traverseNext(); |
| 959 |
} |
672 |
} |
|
Lines 961-984
void TreeResolver::resolveComposedTree()
Source/WebCore/style/StyleTreeResolver.cpp_sec18
|
| 961 |
popParentsToDepth(1); |
674 |
popParentsToDepth(1); |
| 962 |
} |
675 |
} |
| 963 |
|
676 |
|
| 964 |
void TreeResolver::resolve(Change change) |
677 |
std::unique_ptr<const Update> TreeResolver::resolve(Change change) |
| 965 |
{ |
678 |
{ |
| 966 |
auto& renderView = *m_document.renderView(); |
679 |
auto& renderView = *m_document.renderView(); |
| 967 |
|
680 |
|
| 968 |
Element* documentElement = m_document.documentElement(); |
681 |
Element* documentElement = m_document.documentElement(); |
| 969 |
if (!documentElement) |
682 |
if (!documentElement) |
| 970 |
return; |
683 |
return nullptr; |
| 971 |
if (change != Force && !documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc()) |
684 |
if (change != Force && !documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc()) |
| 972 |
return; |
685 |
return nullptr; |
| 973 |
|
686 |
|
|
|
687 |
m_update = std::make_unique<Update>(m_document); |
| 974 |
m_scopeStack.append(adoptRef(*new Scope(m_document))); |
688 |
m_scopeStack.append(adoptRef(*new Scope(m_document))); |
|
|
689 |
m_parentStack.append(Parent(m_document, change)); |
| 975 |
|
690 |
|
| 976 |
// Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc. |
691 |
// Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc. |
| 977 |
renderView.setUsesFirstLineRules(renderView.usesFirstLineRules() || scope().styleResolver.usesFirstLineRules()); |
692 |
renderView.setUsesFirstLineRules(renderView.usesFirstLineRules() || scope().styleResolver.usesFirstLineRules()); |
| 978 |
renderView.setUsesFirstLetterRules(renderView.usesFirstLetterRules() || scope().styleResolver.usesFirstLetterRules()); |
693 |
renderView.setUsesFirstLetterRules(renderView.usesFirstLetterRules() || scope().styleResolver.usesFirstLetterRules()); |
| 979 |
|
694 |
|
| 980 |
m_parentStack.append(Parent(m_document, change)); |
|
|
| 981 |
|
| 982 |
resolveComposedTree(); |
695 |
resolveComposedTree(); |
| 983 |
|
696 |
|
| 984 |
renderView.setUsesFirstLineRules(scope().styleResolver.usesFirstLineRules()); |
697 |
renderView.setUsesFirstLineRules(scope().styleResolver.usesFirstLineRules()); |
|
Lines 986-996
void TreeResolver::resolve(Change change
Source/WebCore/style/StyleTreeResolver.cpp_sec19
|
| 986 |
|
699 |
|
| 987 |
m_parentStack.clear(); |
700 |
m_parentStack.clear(); |
| 988 |
m_scopeStack.clear(); |
701 |
m_scopeStack.clear(); |
| 989 |
} |
|
|
| 990 |
|
702 |
|
| 991 |
void detachRenderTree(Element& element) |
703 |
if (m_update->roots().isEmpty()) |
| 992 |
{ |
704 |
m_update = { }; |
| 993 |
detachRenderTree(element, NormalDetach); |
705 |
|
|
|
706 |
return WTFMove(m_update); |
| 994 |
} |
707 |
} |
| 995 |
|
708 |
|
| 996 |
static Vector<std::function<void ()>>& postResolutionCallbackQueue() |
709 |
static Vector<std::function<void ()>>& postResolutionCallbackQueue() |