Changeset 223500 in webkit
- Timestamp:
- Oct 17, 2017 2:21:05 AM (6 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r223476 r223500 1 2017-10-17 Antti Koivisto <antti@apple.com> 2 3 Resolve ::before and ::after pseudo elements during style resolution 4 https://bugs.webkit.org/show_bug.cgi?id=178339 5 6 Reviewed by Ryosuke Niwa. 7 8 They are currently resolved during render tree building which creates problems with display:contents and animations. 9 10 * dom/PseudoElement.cpp: 11 (WebCore::PseudoElement::PseudoElement): 12 13 Call InspectorInstrumentation from constructor. 14 15 * style/RenderTreeUpdater.cpp: 16 (WebCore::RenderTreeUpdater::Parent::Parent): 17 (WebCore::RenderTreeUpdater::updateRenderTree): 18 (WebCore::RenderTreeUpdater::pushParent): 19 20 Push the full update to the parent stack. 21 22 (WebCore::RenderTreeUpdater::popParent): 23 (WebCore::RenderTreeUpdater::updateBeforeDescendants): 24 (WebCore::RenderTreeUpdater::updateAfterDescendants): 25 (WebCore::RenderTreeUpdater::invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded): 26 * style/RenderTreeUpdater.h: 27 * style/RenderTreeUpdaterGeneratedContent.cpp: 28 (WebCore::RenderTreeUpdater::GeneratedContent::updatePseudoElement): 29 30 No need to resolve pseudo style, we have it already. 31 32 (WebCore::RenderTreeUpdater::GeneratedContent::needsPseudoElement): 33 (WebCore::RenderTreeUpdater::GeneratedContent::updateBeforePseudoElement): Deleted. 34 (WebCore::RenderTreeUpdater::GeneratedContent::updateAfterPseudoElement): Deleted. 35 * style/RenderTreeUpdaterGeneratedContent.h: 36 * style/StyleTreeResolver.cpp: 37 (WebCore::Style::TreeResolver::resolveElement): 38 (WebCore::Style::TreeResolver::resolvePseudoStyle): 39 40 Resolve pseudos. 41 42 (WebCore::Style::TreeResolver::createAnimatedElementUpdate): 43 44 Make a private member function. 45 46 (WebCore::Style::TreeResolver::resolveComposedTree): 47 * style/StyleTreeResolver.h: 48 * style/StyleUpdate.cpp: 49 (WebCore::Style::Update::elementUpdates const): 50 (WebCore::Style::Update::elementUpdates): 51 52 Bundle the style update for an element and the associated before/after pseudos. 53 54 (WebCore::Style::Update::elementStyle const): 55 (WebCore::Style::Update::elementStyle): 56 (WebCore::Style::Update::addElement): 57 (WebCore::Style::Update::elementUpdate const): Deleted. 58 (WebCore::Style::Update::elementUpdate): Deleted. 59 * style/StyleUpdate.h: 60 1 61 2017-10-17 Keith Miller <keith_miller@apple.com> 2 62 -
trunk/Source/WebCore/dom/PseudoElement.cpp
r220956 r223500 29 29 #include "PseudoElement.h" 30 30 31 #include "CSSAnimationController.h" 31 32 #include "ContentData.h" 32 33 #include "InspectorInstrumentation.h" … … 72 73 } 73 74 75 Ref<PseudoElement> PseudoElement::create(Element& host, PseudoId pseudoId) 76 { 77 auto pseudoElement = adoptRef(*new PseudoElement(host, pseudoId)); 78 79 InspectorInstrumentation::pseudoElementCreated(host.document().page(), pseudoElement.get()); 80 81 return pseudoElement; 82 } 83 74 84 void PseudoElement::clearHostElement() 75 85 { 76 86 InspectorInstrumentation::pseudoElementDestroyed(document().page(), *this); 87 88 if (auto* frame = document().frame()) 89 frame->animation().cancelAnimations(*this); 77 90 78 91 m_hostElement = nullptr; -
trunk/Source/WebCore/dom/PseudoElement.h
r222259 r223500 34 34 class PseudoElement final : public Element { 35 35 public: 36 static Ref<PseudoElement> create(Element& host, PseudoId pseudoId) 37 { 38 return adoptRef(*new PseudoElement(host, pseudoId)); 39 } 36 static Ref<PseudoElement> create(Element& host, PseudoId); 40 37 virtual ~PseudoElement(); 41 38 -
trunk/Source/WebCore/style/RenderTreeUpdater.cpp
r223131 r223500 75 75 } 76 76 77 RenderTreeUpdater::Parent::Parent(Element& element, Style::Change styleChange)77 RenderTreeUpdater::Parent::Parent(Element& element, const Style::ElementUpdates* updates) 78 78 : element(&element) 79 , styleChange(styleChange)79 , updates(updates) 80 80 , renderTreePosition(element.renderer() ? std::make_optional(RenderTreePosition(*element.renderer())) : std::nullopt) 81 81 { … … 176 176 auto& text = downcast<Text>(node); 177 177 auto* textUpdate = m_styleUpdate->textUpdate(text); 178 if ( parent().styleChange == Style::Detach|| textUpdate || m_invalidatedWhitespaceOnlyTextSiblings.contains(&text))178 if ((parent().updates && parent().updates->update.change == Style::Detach) || textUpdate || m_invalidatedWhitespaceOnlyTextSiblings.contains(&text)) 179 179 updateTextRenderer(text, textUpdate); 180 180 … … 185 185 auto& element = downcast<Element>(node); 186 186 187 auto* elementUpdate = m_styleUpdate->elementUpdate(element);187 auto* elementUpdates = m_styleUpdate->elementUpdates(element); 188 188 189 189 // We hop through display: contents elements in findRenderingRoot, so 190 190 // there may be other updates down the tree. 191 if (!elementUpdate && !element.hasDisplayContents()) {191 if (!elementUpdates && !element.hasDisplayContents()) { 192 192 it.traverseNextSkippingChildren(); 193 193 continue; 194 194 } 195 195 196 if (elementUpdate )197 updateElementRenderer(element, *elementUpdate);196 if (elementUpdates) 197 updateElementRenderer(element, elementUpdates->update); 198 198 199 199 bool mayHaveRenderedDescendants = element.renderer() || (element.hasDisplayContents() && shouldCreateRenderer(element, renderTreePosition().parent())); … … 203 203 } 204 204 205 pushParent(element, elementUpdate ? elementUpdate->change : Style::NoChange);205 pushParent(element, elementUpdates); 206 206 207 207 it.traverseNext(); … … 223 223 } 224 224 225 void RenderTreeUpdater::pushParent(Element& element, Style::Change changeType)226 { 227 m_parentStack.append(Parent(element, changeType));228 229 updateBeforeDescendants(element );225 void RenderTreeUpdater::pushParent(Element& element, const Style::ElementUpdates* updates) 226 { 227 m_parentStack.append(Parent(element, updates)); 228 229 updateBeforeDescendants(element, updates); 230 230 } 231 231 … … 234 234 auto& parent = m_parentStack.last(); 235 235 if (parent.element) 236 updateAfterDescendants(*parent.element, parent. styleChange);236 updateAfterDescendants(*parent.element, parent.updates); 237 237 238 238 m_parentStack.removeLast(); … … 247 247 } 248 248 249 void RenderTreeUpdater::updateBeforeDescendants(Element& element) 250 { 251 generatedContent().updateBeforePseudoElement(element); 252 } 253 254 void RenderTreeUpdater::updateAfterDescendants(Element& element, Style::Change styleChange) 255 { 256 generatedContent().updateAfterPseudoElement(element); 249 void RenderTreeUpdater::updateBeforeDescendants(Element& element, const Style::ElementUpdates* updates) 250 { 251 if (updates) 252 generatedContent().updatePseudoElement(element, updates->beforePseudoElementUpdate, BEFORE); 253 } 254 255 void RenderTreeUpdater::updateAfterDescendants(Element& element, const Style::ElementUpdates* updates) 256 { 257 if (updates) 258 generatedContent().updatePseudoElement(element, updates->afterPseudoElementUpdate, AFTER); 257 259 258 260 auto* renderer = element.renderer(); … … 268 270 MultiColumn::update(downcast<RenderBlockFlow>(*renderer)); 269 271 270 if (element.hasCustomStyleResolveCallbacks() && styleChange == Style::Detach)272 if (element.hasCustomStyleResolveCallbacks() && updates && updates->update.change == Style::Detach) 271 273 element.didAttachRenderers(); 272 274 } … … 471 473 for (Node* sibling = current.nextSibling(); sibling; sibling = sibling->nextSibling()) { 472 474 if (is<Element>(*sibling)) { 473 if (m_styleUpdate->elementUpdate (downcast<Element>(*sibling)))475 if (m_styleUpdate->elementUpdates(downcast<Element>(*sibling))) 474 476 return; 475 477 // Text renderers beyond rendered elements can't be affected. -
trunk/Source/WebCore/style/RenderTreeUpdater.h
r222129 r223500 63 63 void createRenderer(Element&, RenderStyle&&); 64 64 void invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(Node&); 65 void updateBeforeDescendants(Element& );66 void updateAfterDescendants(Element&, Style::Change);65 void updateBeforeDescendants(Element&, const Style::ElementUpdates*); 66 void updateAfterDescendants(Element&, const Style::ElementUpdates*); 67 67 68 68 struct Parent { 69 69 Element* element { nullptr }; 70 Style::Change styleChange { Style::NoChange};70 const Style::ElementUpdates* updates { nullptr }; 71 71 std::optional<RenderTreePosition> renderTreePosition; 72 72 73 73 Parent(ContainerNode& root); 74 Parent(Element&, Style::Change);74 Parent(Element&, const Style::ElementUpdates*); 75 75 }; 76 76 Parent& parent() { return m_parentStack.last(); } … … 79 79 GeneratedContent& generatedContent() { return *m_generatedContent; } 80 80 81 void pushParent(Element&, Style::Change);81 void pushParent(Element&, const Style::ElementUpdates*); 82 82 void popParent(); 83 83 void popParentsToDepth(unsigned depth); -
trunk/Source/WebCore/style/RenderTreeUpdaterGeneratedContent.cpp
r222679 r223500 43 43 : m_updater(updater) 44 44 { 45 }46 47 void RenderTreeUpdater::GeneratedContent::updateBeforePseudoElement(Element& element)48 {49 updatePseudoElement(element, BEFORE);50 }51 52 void RenderTreeUpdater::GeneratedContent::updateAfterPseudoElement(Element& element)53 {54 updatePseudoElement(element, AFTER);55 45 } 56 46 … … 103 93 } 104 94 105 void RenderTreeUpdater::GeneratedContent::updatePseudoElement(Element& current, PseudoId pseudoId)95 void RenderTreeUpdater::GeneratedContent::updatePseudoElement(Element& current, const std::optional<Style::ElementUpdate>& update, PseudoId pseudoId) 106 96 { 107 97 PseudoElement* pseudoElement = pseudoId == BEFORE ? current.beforePseudoElement() : current.afterPseudoElement(); … … 110 100 m_updater.renderTreePosition().invalidateNextSibling(*renderer); 111 101 112 if (!needsPseudoElement(current, pseudoId)) {102 if (!needsPseudoElement(current, update)) { 113 103 if (pseudoElement) { 114 104 if (pseudoId == BEFORE) … … 126 116 } 127 117 128 auto newStyle = RenderStyle::clonePtr(*current.renderer()->getCachedPseudoStyle(pseudoId, ¤t.renderer()->style())); 129 130 auto elementUpdate = Style::TreeResolver::createAnimatedElementUpdate(WTFMove(newStyle), *pseudoElement, Style::NoChange); 131 132 if (elementUpdate.change == Style::NoChange) 118 if (update->change == Style::NoChange) 133 119 return; 134 120 135 121 if (newPseudoElement) { 136 InspectorInstrumentation::pseudoElementCreated(m_updater.m_document.page(), *newPseudoElement);137 122 if (pseudoId == BEFORE) 138 123 current.setBeforePseudoElement(newPseudoElement.releaseNonNull()); … … 141 126 } 142 127 143 m_updater.updateElementRenderer(*pseudoElement, elementUpdate);128 m_updater.updateElementRenderer(*pseudoElement, *update); 144 129 145 130 auto* pseudoRenderer = pseudoElement->renderer(); … … 147 132 return; 148 133 149 if ( elementUpdate.change == Style::Detach)134 if (update->change == Style::Detach) 150 135 createContentRenderers(*pseudoRenderer); 151 136 else … … 160 145 } 161 146 162 bool RenderTreeUpdater::GeneratedContent::needsPseudoElement(Element& current, PseudoId pseudoId)147 bool RenderTreeUpdater::GeneratedContent::needsPseudoElement(Element& current, const std::optional<Style::ElementUpdate>& update) 163 148 { 149 ASSERT(!current.isPseudoElement()); 150 if (!update) 151 return false; 164 152 if (!current.renderer() || !current.renderer()->canHaveGeneratedChildren()) 165 153 return false; 166 if (current.isPseudoElement()) 167 return false; 168 if (!pseudoElementRendererIsNeeded(current.renderer()->getCachedPseudoStyle(pseudoId))) 154 if (!pseudoElementRendererIsNeeded(update->style.get())) 169 155 return false; 170 156 return true; -
trunk/Source/WebCore/style/RenderTreeUpdaterGeneratedContent.h
r220956 r223500 38 38 GeneratedContent(RenderTreeUpdater&); 39 39 40 void updateBeforePseudoElement(Element&); 41 void updateAfterPseudoElement(Element&); 40 void updatePseudoElement(Element&, const std::optional<Style::ElementUpdate>&, PseudoId); 42 41 void updateRemainingQuotes(); 43 42 44 43 private: 45 void updatePseudoElement(Element&, PseudoId);46 44 void updateQuotesUpTo(RenderQuote*); 47 45 48 static bool needsPseudoElement(Element&, PseudoId);46 static bool needsPseudoElement(Element&, const std::optional<Style::ElementUpdate>&); 49 47 50 48 RenderTreeUpdater& m_updater; -
trunk/Source/WebCore/style/StyleTreeResolver.cpp
r222806 r223500 175 175 } 176 176 177 ElementUpdate TreeResolver::resolveElement(Element& element)177 ElementUpdates TreeResolver::resolveElement(Element& element) 178 178 { 179 179 if (m_didSeePendingStylesheet && !element.renderer() && !m_document.isIgnoringPendingStylesheets()) { … … 219 219 } 220 220 221 return update; 221 auto beforeUpdate = resolvePseudoStyle(element, update, BEFORE); 222 auto afterUpdate = resolvePseudoStyle(element, update, AFTER); 223 224 return { WTFMove(update), WTFMove(beforeUpdate), WTFMove(afterUpdate) }; 225 } 226 227 ElementUpdate TreeResolver::resolvePseudoStyle(Element& element, const ElementUpdate& elementUpdate, PseudoId pseudoId) 228 { 229 if (!elementUpdate.style->hasPseudoStyle(pseudoId)) 230 return { }; 231 auto pseudoStyle = scope().styleResolver.pseudoStyleForElement(element, { pseudoId }, *elementUpdate.style); 232 233 PseudoElement* pseudoElement = pseudoId == BEFORE ? element.beforePseudoElement() : element.afterPseudoElement(); 234 if (!pseudoElement) { 235 auto newPseudoElement = PseudoElement::create(element, pseudoId); 236 pseudoElement = newPseudoElement.ptr(); 237 if (pseudoId == BEFORE) 238 element.setBeforePseudoElement(WTFMove(newPseudoElement)); 239 else 240 element.setAfterPseudoElement(WTFMove(newPseudoElement)); 241 } 242 243 return createAnimatedElementUpdate(WTFMove(pseudoStyle), *pseudoElement, elementUpdate.change); 222 244 } 223 245 … … 238 260 ElementUpdate TreeResolver::createAnimatedElementUpdate(std::unique_ptr<RenderStyle> newStyle, Element& element, Change parentChange) 239 261 { 240 auto& animationController = element.document().frame()->animation();262 auto& animationController = m_document.frame()->animation(); 241 263 242 264 auto* oldStyle = renderOrDisplayContentsStyle(element); … … 409 431 element.willRecalcStyle(parent.change); 410 432 411 auto elementUpdate = resolveElement(element);433 auto elementUpdates = resolveElement(element); 412 434 413 435 if (element.hasCustomStyleResolveCallbacks()) 414 element.didRecalcStyle(elementUpdate .change);415 416 style = elementUpdate .style.get();417 change = elementUpdate .change;436 element.didRecalcStyle(elementUpdates.update.change); 437 438 style = elementUpdates.update.style.get(); 439 change = elementUpdates.update.change; 418 440 419 441 if (affectedByPreviousSibling && change != Detach) 420 442 change = Force; 421 443 422 if (elementUpdate .style)423 m_update->addElement(element, parent.element, WTFMove(elementUpdate ));444 if (elementUpdates.update.style) 445 m_update->addElement(element, parent.element, WTFMove(elementUpdates)); 424 446 425 447 clearNeedsStyleResolution(element); -
trunk/Source/WebCore/style/StyleTreeResolver.h
r218793 r223500 52 52 std::unique_ptr<Update> resolve(); 53 53 54 static ElementUpdate createAnimatedElementUpdate(std::unique_ptr<RenderStyle>, Element&, Change parentChange);55 56 54 private: 57 55 std::unique_ptr<RenderStyle> styleForElement(Element&, const RenderStyle& inheritedStyle); 58 56 59 57 void resolveComposedTree(); 60 ElementUpdate resolveElement(Element&); 58 ElementUpdates resolveElement(Element&); 59 ElementUpdate createAnimatedElementUpdate(std::unique_ptr<RenderStyle>, Element&, Change parentChange); 60 ElementUpdate resolvePseudoStyle(Element&, const ElementUpdate&, PseudoId); 61 61 62 62 struct Scope : RefCounted<Scope> { -
trunk/Source/WebCore/style/StyleUpdate.cpp
r220523 r223500 42 42 } 43 43 44 const ElementUpdate * Update::elementUpdate(const Element& element) const44 const ElementUpdates* Update::elementUpdates(const Element& element) const 45 45 { 46 46 auto it = m_elements.find(&element); … … 50 50 } 51 51 52 ElementUpdate * Update::elementUpdate(const Element& element)52 ElementUpdates* Update::elementUpdates(const Element& element) 53 53 { 54 54 auto it = m_elements.find(&element); … … 68 68 const RenderStyle* Update::elementStyle(const Element& element) const 69 69 { 70 if (auto* update = elementUpdate(element))71 return update ->style.get();70 if (auto* updates = elementUpdates(element)) 71 return updates->update.style.get(); 72 72 auto* renderer = element.renderer(); 73 73 if (!renderer) … … 78 78 RenderStyle* Update::elementStyle(const Element& element) 79 79 { 80 if (auto* update = elementUpdate(element))81 return update ->style.get();80 if (auto* updates = elementUpdates(element)) 81 return updates->update.style.get(); 82 82 auto* renderer = element.renderer(); 83 83 if (!renderer) … … 86 86 } 87 87 88 void Update::addElement(Element& element, Element* parent, ElementUpdate && elementUpdate)88 void Update::addElement(Element& element, Element* parent, ElementUpdates&& elementUpdates) 89 89 { 90 90 ASSERT(!m_elements.contains(&element)); … … 92 92 93 93 addPossibleRoot(parent); 94 m_elements.add(&element, WTFMove(elementUpdate ));94 m_elements.add(&element, WTFMove(elementUpdates)); 95 95 } 96 96 -
trunk/Source/WebCore/style/StyleUpdate.h
r221213 r223500 58 58 }; 59 59 60 struct ElementUpdates { 61 #if !COMPILER_SUPPORTS(NSDMI_FOR_AGGREGATES) 62 ElementUpdates() = default; 63 ElementUpdates(ElementUpdate update, std::optional<ElementUpdate> beforePseudoElementUpdate, std::optional<ElementUpdate> afterPseudoElementUpdate) 64 : update { WTFMove(update) } 65 , beforePseudoElementUpdate { WTFMove(beforePseudoElementUpdate) } 66 , afterPseudoElementUpdate { WTFMove(afterPseudoElementUpdate) } 67 { 68 } 69 #endif 70 ElementUpdate update; 71 std::optional<ElementUpdate> beforePseudoElementUpdate; 72 std::optional<ElementUpdate> afterPseudoElementUpdate; 73 }; 74 60 75 struct TextUpdate { 61 76 #if !COMPILER_SUPPORTS(NSDMI_FOR_AGGREGATES) … … 79 94 const ListHashSet<ContainerNode*>& roots() const { return m_roots; } 80 95 81 const ElementUpdate * elementUpdate(const Element&) const;82 ElementUpdate * elementUpdate(const Element&);96 const ElementUpdates* elementUpdates(const Element&) const; 97 ElementUpdates* elementUpdates(const Element&); 83 98 84 99 const TextUpdate* textUpdate(const Text&) const; … … 91 106 unsigned size() const { return m_elements.size() + m_texts.size(); } 92 107 93 void addElement(Element&, Element* parent, ElementUpdate &&);108 void addElement(Element&, Element* parent, ElementUpdates&&); 94 109 void addText(Text&, Element* parent, TextUpdate&&); 95 110 void addText(Text&, TextUpdate&&); … … 100 115 Document& m_document; 101 116 ListHashSet<ContainerNode*> m_roots; 102 HashMap<const Element*, ElementUpdate > m_elements;117 HashMap<const Element*, ElementUpdates> m_elements; 103 118 HashMap<const Text*, TextUpdate> m_texts; 104 119 };
Note: See TracChangeset
for help on using the changeset viewer.