|
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 114-119
TreeResolver::TreeResolver(Document& doc
Source/WebCore/style/StyleTreeResolver.cpp_sec4
|
| 114 |
ensurePlaceholderStyle(document); |
101 |
ensurePlaceholderStyle(document); |
| 115 |
} |
102 |
} |
| 116 |
|
103 |
|
|
|
104 |
TreeResolver::~TreeResolver() |
| 105 |
{ |
| 106 |
} |
| 107 |
|
| 117 |
TreeResolver::Scope::Scope(Document& document) |
108 |
TreeResolver::Scope::Scope(Document& document) |
| 118 |
: styleResolver(document.ensureStyleResolver()) |
109 |
: styleResolver(document.ensureStyleResolver()) |
| 119 |
, sharingResolver(document, styleResolver.ruleSets(), selectorFilter) |
110 |
, sharingResolver(document, styleResolver.ruleSets(), selectorFilter) |
|
Lines 131-146
TreeResolver::Scope::Scope(ShadowRoot& s
Source/WebCore/style/StyleTreeResolver.cpp_sec5
|
| 131 |
TreeResolver::Parent::Parent(Document& document, Change change) |
122 |
TreeResolver::Parent::Parent(Document& document, Change change) |
| 132 |
: element(nullptr) |
123 |
: element(nullptr) |
| 133 |
, style(*document.renderStyle()) |
124 |
, style(*document.renderStyle()) |
| 134 |
, renderTreePosition(*document.renderView()) |
|
|
| 135 |
, change(change) |
125 |
, change(change) |
| 136 |
{ |
126 |
{ |
| 137 |
} |
127 |
} |
| 138 |
|
128 |
|
| 139 |
TreeResolver::Parent::Parent(Element& element, RenderStyle& style, RenderTreePosition renderTreePosition, Change change) |
129 |
TreeResolver::Parent::Parent(Element& element, ElementUpdate& update) |
| 140 |
: element(&element) |
130 |
: element(&element) |
| 141 |
, style(style) |
131 |
, style(*update.style) |
| 142 |
, renderTreePosition(renderTreePosition) |
132 |
, change(update.change) |
| 143 |
, change(change) |
|
|
| 144 |
{ |
133 |
{ |
| 145 |
} |
134 |
} |
| 146 |
|
135 |
|
|
Lines 160-176
void TreeResolver::popScope()
Source/WebCore/style/StyleTreeResolver.cpp_sec6
|
| 160 |
return m_scopeStack.removeLast(); |
149 |
return m_scopeStack.removeLast(); |
| 161 |
} |
150 |
} |
| 162 |
|
151 |
|
| 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) |
152 |
Ref<RenderStyle> TreeResolver::styleForElement(Element& element, RenderStyle& inheritedStyle) |
| 175 |
{ |
153 |
{ |
| 176 |
if (!m_document.haveStylesheetsLoaded() && !element.renderer()) { |
154 |
if (!m_document.haveStylesheetsLoaded() && !element.renderer()) { |
|
Lines 178-264
Ref<RenderStyle> TreeResolver::styleForE
Source/WebCore/style/StyleTreeResolver.cpp_sec7
|
| 178 |
return *placeholderStyle; |
156 |
return *placeholderStyle; |
| 179 |
} |
157 |
} |
| 180 |
|
158 |
|
|
|
159 |
scope().styleResolver.setOverrideDocumentElementStyle(m_documentElementStyle.get()); |
| 160 |
|
| 181 |
if (element.hasCustomStyleResolveCallbacks()) { |
161 |
if (element.hasCustomStyleResolveCallbacks()) { |
| 182 |
RenderStyle* shadowHostStyle = scope().shadowRoot ? scope().shadowRoot->host()->renderStyle() : nullptr; |
162 |
RenderStyle* shadowHostStyle = scope().shadowRoot ? m_update->elementStyle(*scope().shadowRoot->host()) : nullptr; |
| 183 |
if (auto customStyle = element.resolveCustomStyle(inheritedStyle, shadowHostStyle)) { |
163 |
if (auto customStyle = element.resolveCustomStyle(inheritedStyle, shadowHostStyle)) { |
| 184 |
Style::commitRelationsToDocument(WTFMove(customStyle->relations)); |
164 |
if (customStyle->relations) |
|
|
165 |
commitRelations(WTFMove(customStyle->relations), *m_update); |
| 166 |
|
| 185 |
return WTFMove(customStyle->renderStyle); |
167 |
return WTFMove(customStyle->renderStyle); |
| 186 |
} |
168 |
} |
| 187 |
} |
169 |
} |
| 188 |
|
170 |
|
| 189 |
if (auto style = scope().sharingResolver.resolve(element)) |
171 |
if (auto style = scope().sharingResolver.resolve(element, *m_update)) |
| 190 |
return *style; |
172 |
return *style; |
| 191 |
|
173 |
|
| 192 |
auto elementStyle = scope().styleResolver.styleForElement(element, &inheritedStyle, MatchAllRules, nullptr, &scope().selectorFilter); |
174 |
auto elementStyle = scope().styleResolver.styleForElement(element, &inheritedStyle, MatchAllRules, nullptr, &scope().selectorFilter); |
| 193 |
|
175 |
|
| 194 |
Style::commitRelationsToDocument(WTFMove(elementStyle.relations)); |
176 |
if (elementStyle.relations) |
| 195 |
return WTFMove(elementStyle.renderStyle); |
177 |
commitRelations(WTFMove(elementStyle.relations), *m_update); |
| 196 |
} |
|
|
| 197 |
|
| 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 |
|
178 |
|
| 238 |
// Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style |
179 |
return WTFMove(elementStyle.renderStyle); |
| 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 |
} |
180 |
} |
| 263 |
|
181 |
|
| 264 |
static void invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(Node& current) |
182 |
static void invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(Node& current) |
|
Lines 348-354
static void createTextRendererIfNeeded(T
Source/WebCore/style/StyleTreeResolver.cpp_sec8
|
| 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_sec9
|
| 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_sec10
|
| 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_sec11
|
| 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-715
static void detachRenderTree(Element& cu
Source/WebCore/style/StyleTreeResolver.cpp_sec12
|
| 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 |
auto newStyle = styleForElement(element, parent().style); |
| 643 |
|
391 |
|
| 644 |
const PseudoStyleCache* pseudoStyleCache = currentStyle.cachedPseudoStyles(); |
392 |
auto* renderer = element.renderer(); |
| 645 |
if (!pseudoStyleCache) |
|
|
| 646 |
return false; |
| 647 |
|
393 |
|
| 648 |
for (auto& cache : *pseudoStyleCache) { |
394 |
bool affectsRenderedSubtree = renderer || newStyle->display() != NONE || newStyle->hasFlowInto(); |
| 649 |
RefPtr<RenderStyle> newPseudoStyle; |
395 |
if (!affectsRenderedSubtree) |
| 650 |
PseudoId pseudoId = cache->styleType(); |
396 |
return { }; |
| 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 |
|
397 |
|
| 673 |
Change TreeResolver::resolveElement(Element& current) |
398 |
ElementUpdate update; |
| 674 |
{ |
|
|
| 675 |
Change localChange = Detach; |
| 676 |
RefPtr<RenderStyle> newStyle; |
| 677 |
RefPtr<RenderStyle> currentStyle = current.renderStyle(); |
| 678 |
|
399 |
|
| 679 |
if (currentStyle && current.styleChangeType() != ReconstructRenderTree) { |
400 |
bool needsNewRenderer = !renderer || element.styleChangeType() == ReconstructRenderTree || parent().change == Detach; |
| 680 |
Ref<RenderStyle> style(styleForElement(current, parent().style)); |
401 |
if (!needsNewRenderer && m_document.frame()->animation().updateAnimations(*renderer, newStyle, newStyle)) |
| 681 |
newStyle = style.ptr(); |
402 |
update.isSynthetic = true; |
| 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 |
|
403 |
|
| 694 |
return Detach; |
404 |
update.change = needsNewRenderer ? Detach : determineChange(renderer->style(), newStyle); |
| 695 |
} |
405 |
update.style = WTFMove(newStyle); |
| 696 |
|
406 |
|
| 697 |
if (RenderElement* renderer = current.renderer()) { |
407 |
if (element.styleChangeType() == SyntheticStyleChange) |
| 698 |
if (localChange != NoChange || pseudoStyleCacheIsInvalid(renderer, newStyle.get()) || (parent().change == Force && renderer->requiresForcedStyleRecalcPropagation()) || current.styleChangeType() == SyntheticStyleChange) |
408 |
update.isSynthetic = true; |
| 699 |
renderer->setAnimatableStyle(*newStyle, current.styleChangeType() == SyntheticStyleChange ? StyleDifferenceRecompositeLayer : StyleDifferenceEqual); |
409 |
|
| 700 |
} |
410 |
if (&element == m_document.documentElement()) { |
|
|
411 |
m_documentElementStyle = update.style; |
| 701 |
|
412 |
|
| 702 |
// If "rem" units are used anywhere in the document, and if the document element's font size changes, then force font updating |
413 |
// If "rem" units are used anywhere in the document, and if the document element's font size changes, then force font updating |
| 703 |
// 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). |
414 |
// 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). |
| 704 |
if (m_document.authorStyleSheets().usesRemUnits() && m_document.documentElement() == ¤t && localChange != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize()) { |
415 |
if (m_document.authorStyleSheets().usesRemUnits() && update.change != NoChange && renderer && renderer->style().fontSize() != update.style->fontSize()) { |
| 705 |
// Cached RenderStyles may depend on the re units. |
416 |
// Cached RenderStyles may depend on the rem units. |
| 706 |
scope().styleResolver.invalidateMatchedPropertiesCache(); |
417 |
scope().styleResolver.invalidateMatchedPropertiesCache(); |
| 707 |
return Force; |
418 |
update.change = Force; |
|
|
419 |
} |
| 708 |
} |
420 |
} |
| 709 |
if (parent().change == Force || current.styleChangeType() >= FullStyleChange) |
|
|
| 710 |
return Force; |
| 711 |
|
421 |
|
| 712 |
return localChange; |
422 |
// This is needed for resolving color:-webkit-text for subsequent elements. |
|
|
423 |
// FIXME: We shouldn't mutate document when resolving style. |
| 424 |
if (&element == m_document.body()) |
| 425 |
m_document.setTextColor(update.style->visitedDependentColor(CSSPropertyColor)); |
| 426 |
|
| 427 |
if (update.change != Detach && (parent().change == Force || element.styleChangeType() >= FullStyleChange)) |
| 428 |
update.change = Force; |
| 429 |
|
| 430 |
return update; |
| 713 |
} |
431 |
} |
| 714 |
|
432 |
|
| 715 |
void resolveTextNode(Text& text, RenderTreePosition& renderTreePosition) |
433 |
void resolveTextNode(Text& text, RenderTreePosition& renderTreePosition) |
|
Lines 731-760
void resolveTextNode(Text& text, RenderT
Source/WebCore/style/StyleTreeResolver.cpp_sec13
|
| 731 |
invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(text); |
449 |
invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(text); |
| 732 |
} |
450 |
} |
| 733 |
|
451 |
|
| 734 |
void TreeResolver::resolveBeforeOrAfterPseudoElement(Element& current, Change change, PseudoId pseudoId, RenderTreePosition& renderTreePosition) |
|
|
| 735 |
{ |
| 736 |
if (!current.renderer()) |
| 737 |
return; |
| 738 |
PseudoElement* existingPseudoElement = beforeOrAfterPseudoElement(current, pseudoId); |
| 739 |
if (!existingPseudoElement) { |
| 740 |
createRenderTreeForBeforeOrAfterPseudoElement(current, pseudoId, renderTreePosition); |
| 741 |
return; |
| 742 |
} |
| 743 |
|
| 744 |
if (existingPseudoElement->renderer()) |
| 745 |
renderTreePosition.invalidateNextSibling(*existingPseudoElement->renderer()); |
| 746 |
|
| 747 |
if (change == NoChange && !existingPseudoElement->needsStyleRecalc()) |
| 748 |
return; |
| 749 |
|
| 750 |
if (needsPseudoElement(current, pseudoId)) { |
| 751 |
auto change = resolveElement(*existingPseudoElement); |
| 752 |
existingPseudoElement->didRecalcStyle(change); |
| 753 |
existingPseudoElement->clearNeedsStyleRecalc(); |
| 754 |
} else |
| 755 |
clearBeforeOrAfterPseudoElement(current, pseudoId); |
| 756 |
} |
| 757 |
|
| 758 |
#if PLATFORM(IOS) |
452 |
#if PLATFORM(IOS) |
| 759 |
static EVisibility elementImplicitVisibility(const Element* element) |
453 |
static EVisibility elementImplicitVisibility(const Element* element) |
| 760 |
{ |
454 |
{ |
|
Lines 809-819
private:
Source/WebCore/style/StyleTreeResolver.cpp_sec14
|
| 809 |
}; |
503 |
}; |
| 810 |
#endif // PLATFORM(IOS) |
504 |
#endif // PLATFORM(IOS) |
| 811 |
|
505 |
|
| 812 |
void TreeResolver::pushParent(Element& element, RenderStyle& style, RenderTreePosition renderTreePosition, Change change) |
506 |
void TreeResolver::pushParent(Element& element, ElementUpdate& update) |
| 813 |
{ |
507 |
{ |
| 814 |
scope().selectorFilter.pushParent(&element); |
508 |
scope().selectorFilter.pushParent(&element); |
| 815 |
|
509 |
|
| 816 |
Parent parent(element, style, renderTreePosition, change); |
510 |
Parent parent(element, update); |
| 817 |
|
511 |
|
| 818 |
if (auto* shadowRoot = element.shadowRoot()) { |
512 |
if (auto* shadowRoot = element.shadowRoot()) { |
| 819 |
pushScope(*shadowRoot); |
513 |
pushScope(*shadowRoot); |
|
Lines 827-842
void TreeResolver::pushParent(Element& e
Source/WebCore/style/StyleTreeResolver.cpp_sec15
|
| 827 |
#endif |
521 |
#endif |
| 828 |
|
522 |
|
| 829 |
m_parentStack.append(WTFMove(parent)); |
523 |
m_parentStack.append(WTFMove(parent)); |
| 830 |
|
|
|
| 831 |
resolveBeforeOrAfterPseudoElement(element, change, BEFORE, renderTreePosition); |
| 832 |
} |
524 |
} |
| 833 |
|
525 |
|
| 834 |
void TreeResolver::popParent() |
526 |
void TreeResolver::popParent() |
| 835 |
{ |
527 |
{ |
| 836 |
auto& parentElement = *parent().element; |
528 |
auto& parentElement = *parent().element; |
| 837 |
|
529 |
|
| 838 |
resolveBeforeOrAfterPseudoElement(parentElement, parent().change, AFTER, parent().renderTreePosition); |
|
|
| 839 |
|
| 840 |
parentElement.clearNeedsStyleRecalc(); |
530 |
parentElement.clearNeedsStyleRecalc(); |
| 841 |
parentElement.clearChildNeedsStyleRecalc(); |
531 |
parentElement.clearChildNeedsStyleRecalc(); |
| 842 |
|
532 |
|
|
Lines 857-862
void TreeResolver::popParentsToDepth(uns
Source/WebCore/style/StyleTreeResolver.cpp_sec16
|
| 857 |
popParent(); |
547 |
popParent(); |
| 858 |
} |
548 |
} |
| 859 |
|
549 |
|
|
|
550 |
static bool shouldResolvePseudoElement(PseudoElement* pseudoElement) |
| 551 |
{ |
| 552 |
if (!pseudoElement) |
| 553 |
return false; |
| 554 |
bool needsStyleRecalc = pseudoElement->needsStyleRecalc(); |
| 555 |
pseudoElement->clearNeedsStyleRecalc(); |
| 556 |
return needsStyleRecalc; |
| 557 |
} |
| 558 |
|
| 860 |
void TreeResolver::resolveComposedTree() |
559 |
void TreeResolver::resolveComposedTree() |
| 861 |
{ |
560 |
{ |
| 862 |
ASSERT(m_parentStack.size() == 1); |
561 |
ASSERT(m_parentStack.size() == 1); |
|
Lines 878-889
void TreeResolver::resolveComposedTree()
Source/WebCore/style/StyleTreeResolver.cpp_sec17
|
| 878 |
ASSERT(node.containingShadowRoot() == scope().shadowRoot); |
577 |
ASSERT(node.containingShadowRoot() == scope().shadowRoot); |
| 879 |
ASSERT(node.parentElement() == parent.element || is<ShadowRoot>(node.parentNode()) || node.parentElement()->shadowRoot()); |
578 |
ASSERT(node.parentElement() == parent.element || is<ShadowRoot>(node.parentNode()) || node.parentElement()->shadowRoot()); |
| 880 |
|
579 |
|
| 881 |
if (auto* existingRenderer = node.renderer()) |
|
|
| 882 |
parent.renderTreePosition.invalidateNextSibling(*existingRenderer); |
| 883 |
|
| 884 |
if (is<Text>(node)) { |
580 |
if (is<Text>(node)) { |
| 885 |
if (node.needsStyleRecalc()) |
581 |
auto& text = downcast<Text>(node); |
| 886 |
resolveTextNode(downcast<Text>(node), parent.renderTreePosition); |
582 |
if (text.styleChangeType() == ReconstructRenderTree && parent.change != Detach) |
|
|
583 |
m_update->addText(text, parent.element); |
| 584 |
|
| 585 |
text.clearNeedsStyleRecalc(); |
| 887 |
it.traverseNextSkippingChildren(); |
586 |
it.traverseNextSkippingChildren(); |
| 888 |
continue; |
587 |
continue; |
| 889 |
} |
588 |
} |
|
Lines 895-903
void TreeResolver::resolveComposedTree()
Source/WebCore/style/StyleTreeResolver.cpp_sec18
|
| 895 |
if (element.needsStyleRecalc() || parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle) |
594 |
if (element.needsStyleRecalc() || parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle) |
| 896 |
parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle = element.affectsNextSiblingElementStyle(); |
595 |
parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle = element.affectsNextSiblingElementStyle(); |
| 897 |
|
596 |
|
| 898 |
Change change = NoChange; |
597 |
bool shouldResolveForPseudoElement = shouldResolvePseudoElement(element.beforePseudoElement()) || shouldResolvePseudoElement(element.afterPseudoElement()); |
| 899 |
|
598 |
|
| 900 |
bool shouldResolve = parent.change >= Inherit || element.needsStyleRecalc() || affectedByPreviousSibling; |
599 |
ElementUpdate update; |
|
|
600 |
update.style = element.renderStyle(); |
| 601 |
|
| 602 |
bool shouldResolve = parent.change >= Inherit || element.needsStyleRecalc() || shouldResolveForPseudoElement || affectedByPreviousSibling; |
| 901 |
if (shouldResolve) { |
603 |
if (shouldResolve) { |
| 902 |
#if PLATFORM(IOS) |
604 |
#if PLATFORM(IOS) |
| 903 |
CheckForVisibilityChangeOnRecalcStyle checkForVisibilityChange(&element, element.renderStyle()); |
605 |
CheckForVisibilityChangeOnRecalcStyle checkForVisibilityChange(&element, element.renderStyle()); |
|
Lines 910-954
void TreeResolver::resolveComposedTree()
Source/WebCore/style/StyleTreeResolver.cpp_sec19
|
| 910 |
continue; |
612 |
continue; |
| 911 |
} |
613 |
} |
| 912 |
} |
614 |
} |
| 913 |
change = resolveElement(element); |
|
|
| 914 |
|
615 |
|
| 915 |
element.clearNeedsStyleRecalc(); |
616 |
update = resolveElement(element); |
| 916 |
|
617 |
|
| 917 |
if (element.hasCustomStyleResolveCallbacks()) |
618 |
if (element.hasCustomStyleResolveCallbacks()) |
| 918 |
element.didRecalcStyle(change); |
619 |
element.didRecalcStyle(update.change); |
| 919 |
|
620 |
|
| 920 |
if (change == Detach) { |
621 |
if (affectedByPreviousSibling && update.change != Detach) |
| 921 |
it.traverseNextSkippingChildren(); |
622 |
update.change = Force; |
| 922 |
continue; |
623 |
|
| 923 |
} |
624 |
if (update.style) |
|
|
625 |
m_update->addElement(element, parent.element, update); |
| 924 |
|
626 |
|
| 925 |
if (affectedByPreviousSibling) |
627 |
element.clearNeedsStyleRecalc(); |
| 926 |
change = Force; |
|
|
| 927 |
} |
628 |
} |
| 928 |
|
629 |
|
|
|
630 |
|
| 929 |
#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) |
631 |
#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT) |
| 930 |
if (is<HTMLSlotElement>(element)) { |
632 |
if (is<HTMLSlotElement>(element)) { |
| 931 |
// FIXME: We should compute style for the slot and use it as parent style. |
633 |
// FIXME: We should compute style for the slot and use it as parent style. |
| 932 |
// FIXME: This should be display:contents check. |
634 |
// Duplicate the style from the parent context. |
| 933 |
// Duplicate the style and render tree position from the current context. |
635 |
ElementUpdate slotUpdate; |
| 934 |
pushParent(element, parent.style.get(), parent.renderTreePosition, change); |
636 |
slotUpdate.style = parent.style.ptr(); |
|
|
637 |
slotUpdate.change = update.change; |
| 638 |
if (!shouldResolve) |
| 639 |
m_update->addElement(element, parent.element, update); |
| 640 |
pushParent(element, slotUpdate); |
| 935 |
it.traverseNext(); |
641 |
it.traverseNext(); |
| 936 |
continue; |
642 |
continue; |
| 937 |
} |
643 |
} |
| 938 |
#endif |
644 |
#endif |
| 939 |
auto* renderer = element.renderer(); |
645 |
if (!update.style) { |
| 940 |
if (!renderer) { |
|
|
| 941 |
resetStyleForNonRenderedDescendants(element); |
646 |
resetStyleForNonRenderedDescendants(element); |
| 942 |
element.clearChildNeedsStyleRecalc(); |
647 |
element.clearChildNeedsStyleRecalc(); |
| 943 |
} |
648 |
} |
| 944 |
|
649 |
|
| 945 |
bool shouldIterateChildren = renderer && (element.childNeedsStyleRecalc() || change != NoChange); |
650 |
bool shouldIterateChildren = update.style && (element.childNeedsStyleRecalc() || update.change != NoChange); |
| 946 |
if (!shouldIterateChildren) { |
651 |
if (!shouldIterateChildren) { |
| 947 |
it.traverseNextSkippingChildren(); |
652 |
it.traverseNextSkippingChildren(); |
| 948 |
continue; |
653 |
continue; |
| 949 |
} |
654 |
} |
| 950 |
|
655 |
|
| 951 |
pushParent(element, renderer->style(), RenderTreePosition(*renderer), change); |
656 |
pushParent(element, update); |
| 952 |
|
657 |
|
| 953 |
it.traverseNext(); |
658 |
it.traverseNext(); |
| 954 |
} |
659 |
} |
|
Lines 956-979
void TreeResolver::resolveComposedTree()
Source/WebCore/style/StyleTreeResolver.cpp_sec20
|
| 956 |
popParentsToDepth(1); |
661 |
popParentsToDepth(1); |
| 957 |
} |
662 |
} |
| 958 |
|
663 |
|
| 959 |
void TreeResolver::resolve(Change change) |
664 |
std::unique_ptr<const Update> TreeResolver::resolve(Change change) |
| 960 |
{ |
665 |
{ |
| 961 |
auto& renderView = *m_document.renderView(); |
666 |
auto& renderView = *m_document.renderView(); |
| 962 |
|
667 |
|
| 963 |
Element* documentElement = m_document.documentElement(); |
668 |
Element* documentElement = m_document.documentElement(); |
| 964 |
if (!documentElement) |
669 |
if (!documentElement) |
| 965 |
return; |
670 |
return nullptr; |
| 966 |
if (change != Force && !documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc()) |
671 |
if (change != Force && !documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc()) |
| 967 |
return; |
672 |
return nullptr; |
| 968 |
|
673 |
|
|
|
674 |
m_update = std::make_unique<Update>(m_document); |
| 969 |
m_scopeStack.append(adoptRef(*new Scope(m_document))); |
675 |
m_scopeStack.append(adoptRef(*new Scope(m_document))); |
|
|
676 |
m_parentStack.append(Parent(m_document, change)); |
| 970 |
|
677 |
|
| 971 |
// Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc. |
678 |
// Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc. |
| 972 |
renderView.setUsesFirstLineRules(renderView.usesFirstLineRules() || scope().styleResolver.usesFirstLineRules()); |
679 |
renderView.setUsesFirstLineRules(renderView.usesFirstLineRules() || scope().styleResolver.usesFirstLineRules()); |
| 973 |
renderView.setUsesFirstLetterRules(renderView.usesFirstLetterRules() || scope().styleResolver.usesFirstLetterRules()); |
680 |
renderView.setUsesFirstLetterRules(renderView.usesFirstLetterRules() || scope().styleResolver.usesFirstLetterRules()); |
| 974 |
|
681 |
|
| 975 |
m_parentStack.append(Parent(m_document, change)); |
|
|
| 976 |
|
| 977 |
resolveComposedTree(); |
682 |
resolveComposedTree(); |
| 978 |
|
683 |
|
| 979 |
renderView.setUsesFirstLineRules(scope().styleResolver.usesFirstLineRules()); |
684 |
renderView.setUsesFirstLineRules(scope().styleResolver.usesFirstLineRules()); |
|
Lines 981-991
void TreeResolver::resolve(Change change
Source/WebCore/style/StyleTreeResolver.cpp_sec21
|
| 981 |
|
686 |
|
| 982 |
m_parentStack.clear(); |
687 |
m_parentStack.clear(); |
| 983 |
m_scopeStack.clear(); |
688 |
m_scopeStack.clear(); |
| 984 |
} |
|
|
| 985 |
|
689 |
|
| 986 |
void detachRenderTree(Element& element) |
690 |
if (m_update->roots().isEmpty()) |
| 987 |
{ |
691 |
return { }; |
| 988 |
detachRenderTree(element, NormalDetach); |
692 |
|
|
|
693 |
return WTFMove(m_update); |
| 989 |
} |
694 |
} |
| 990 |
|
695 |
|
| 991 |
static Vector<std::function<void ()>>& postResolutionCallbackQueue() |
696 |
static Vector<std::function<void ()>>& postResolutionCallbackQueue() |