Changeset 223604 in webkit
- Timestamp:
- Oct 18, 2017 6:41:04 AM (7 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r223594 r223604 1 2017-10-18 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 <rdar://problem/35025601> 6 7 Reviewed by Ryosuke Niwa. 8 9 Add a test verifying a crash noticed with earlier version of this patch. 10 11 * fast/css-generated-content/svg-use-crash-expected.html: Added. 12 * fast/css-generated-content/svg-use-crash.html: Added. 13 1 14 2017-10-18 Yusuke Suzuki <utatane.tea@gmail.com> 2 15 -
trunk/Source/WebCore/ChangeLog
r223602 r223604 1 2017-10-18 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-18 Ms2ger <Ms2ger@igalia.com> 2 62 -
trunk/Source/WebCore/dom/PseudoElement.cpp
r223579 r223604 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
r223579 r223604 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
r223579 r223604 76 76 } 77 77 78 RenderTreeUpdater::Parent::Parent(Element& element, Style::Change styleChange)78 RenderTreeUpdater::Parent::Parent(Element& element, const Style::ElementUpdates* updates) 79 79 : element(&element) 80 , styleChange(styleChange)80 , updates(updates) 81 81 , renderTreePosition(element.renderer() ? std::make_optional(RenderTreePosition(*element.renderer())) : std::nullopt) 82 82 { … … 177 177 auto& text = downcast<Text>(node); 178 178 auto* textUpdate = m_styleUpdate->textUpdate(text); 179 if ( parent().styleChange == Style::Detach|| textUpdate || m_invalidatedWhitespaceOnlyTextSiblings.contains(&text))179 if ((parent().updates && parent().updates->update.change == Style::Detach) || textUpdate || m_invalidatedWhitespaceOnlyTextSiblings.contains(&text)) 180 180 updateTextRenderer(text, textUpdate); 181 181 … … 186 186 auto& element = downcast<Element>(node); 187 187 188 auto* elementUpdate = m_styleUpdate->elementUpdate(element);188 auto* elementUpdates = m_styleUpdate->elementUpdates(element); 189 189 190 190 // We hop through display: contents elements in findRenderingRoot, so 191 191 // there may be other updates down the tree. 192 if (!elementUpdate && !element.hasDisplayContents()) {192 if (!elementUpdates && !element.hasDisplayContents()) { 193 193 it.traverseNextSkippingChildren(); 194 194 continue; 195 195 } 196 196 197 if (elementUpdate )198 updateElementRenderer(element, *elementUpdate);197 if (elementUpdates) 198 updateElementRenderer(element, elementUpdates->update); 199 199 200 200 bool mayHaveRenderedDescendants = element.renderer() || (element.hasDisplayContents() && shouldCreateRenderer(element, renderTreePosition().parent())); … … 204 204 } 205 205 206 pushParent(element, elementUpdate ? elementUpdate->change : Style::NoChange);206 pushParent(element, elementUpdates); 207 207 208 208 it.traverseNext(); … … 224 224 } 225 225 226 void RenderTreeUpdater::pushParent(Element& element, Style::Change changeType)227 { 228 m_parentStack.append(Parent(element, changeType));229 230 updateBeforeDescendants(element );226 void RenderTreeUpdater::pushParent(Element& element, const Style::ElementUpdates* updates) 227 { 228 m_parentStack.append(Parent(element, updates)); 229 230 updateBeforeDescendants(element, updates); 231 231 } 232 232 … … 235 235 auto& parent = m_parentStack.last(); 236 236 if (parent.element) 237 updateAfterDescendants(*parent.element, parent. styleChange);237 updateAfterDescendants(*parent.element, parent.updates); 238 238 239 239 m_parentStack.removeLast(); … … 248 248 } 249 249 250 void RenderTreeUpdater::updateBeforeDescendants(Element& element) 251 { 252 generatedContent().updateBeforePseudoElement(element); 253 } 254 255 void RenderTreeUpdater::updateAfterDescendants(Element& element, Style::Change styleChange) 256 { 257 generatedContent().updateAfterPseudoElement(element); 250 void RenderTreeUpdater::updateBeforeDescendants(Element& element, const Style::ElementUpdates* updates) 251 { 252 if (updates) 253 generatedContent().updatePseudoElement(element, updates->beforePseudoElementUpdate, BEFORE); 254 } 255 256 void RenderTreeUpdater::updateAfterDescendants(Element& element, const Style::ElementUpdates* updates) 257 { 258 if (updates) 259 generatedContent().updatePseudoElement(element, updates->afterPseudoElementUpdate, AFTER); 258 260 259 261 auto* renderer = element.renderer(); … … 269 271 MultiColumn::update(downcast<RenderBlockFlow>(*renderer)); 270 272 271 if (element.hasCustomStyleResolveCallbacks() && styleChange == Style::Detach)273 if (element.hasCustomStyleResolveCallbacks() && updates && updates->update.change == Style::Detach) 272 274 element.didAttachRenderers(); 273 275 } … … 494 496 for (Node* sibling = current.nextSibling(); sibling; sibling = sibling->nextSibling()) { 495 497 if (is<Element>(*sibling)) { 496 if (m_styleUpdate->elementUpdate (downcast<Element>(*sibling)))498 if (m_styleUpdate->elementUpdates(downcast<Element>(*sibling))) 497 499 return; 498 500 // Text renderers beyond rendered elements can't be affected. -
trunk/Source/WebCore/style/RenderTreeUpdater.h
r223579 r223604 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
r223579 r223604 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
r223579 r223604 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
r223579 r223604 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 232 auto pseudoStyle = scope().styleResolver.pseudoStyleForElement(element, { pseudoId }, *elementUpdate.style); 233 if (!pseudoStyle) 234 return { }; 235 236 PseudoElement* pseudoElement = pseudoId == BEFORE ? element.beforePseudoElement() : element.afterPseudoElement(); 237 if (!pseudoElement) { 238 auto newPseudoElement = PseudoElement::create(element, pseudoId); 239 pseudoElement = newPseudoElement.ptr(); 240 if (pseudoId == BEFORE) 241 element.setBeforePseudoElement(WTFMove(newPseudoElement)); 242 else 243 element.setAfterPseudoElement(WTFMove(newPseudoElement)); 244 } 245 246 return createAnimatedElementUpdate(WTFMove(pseudoStyle), *pseudoElement, elementUpdate.change); 222 247 } 223 248 … … 238 263 ElementUpdate TreeResolver::createAnimatedElementUpdate(std::unique_ptr<RenderStyle> newStyle, Element& element, Change parentChange) 239 264 { 240 auto& animationController = element.document().frame()->animation();265 auto& animationController = m_document.frame()->animation(); 241 266 242 267 auto* oldStyle = renderOrDisplayContentsStyle(element); … … 426 451 element.willRecalcStyle(parent.change); 427 452 428 auto elementUpdate = resolveElement(element);453 auto elementUpdates = resolveElement(element); 429 454 430 455 if (element.hasCustomStyleResolveCallbacks()) 431 element.didRecalcStyle(elementUpdate .change);432 433 style = elementUpdate .style.get();434 change = elementUpdate .change;456 element.didRecalcStyle(elementUpdates.update.change); 457 458 style = elementUpdates.update.style.get(); 459 change = elementUpdates.update.change; 435 460 436 461 if (affectedByPreviousSibling && change != Detach) 437 462 change = Force; 438 463 439 if (elementUpdate .style)440 m_update->addElement(element, parent.element, WTFMove(elementUpdate ));464 if (elementUpdates.update.style) 465 m_update->addElement(element, parent.element, WTFMove(elementUpdates)); 441 466 442 467 clearNeedsStyleResolution(element); -
trunk/Source/WebCore/style/StyleTreeResolver.h
r223579 r223604 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
r223579 r223604 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
r223579 r223604 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) … … 81 96 const ListHashSet<ContainerNode*>& roots() const { return m_roots; } 82 97 83 const ElementUpdate * elementUpdate(const Element&) const;84 ElementUpdate * elementUpdate(const Element&);98 const ElementUpdates* elementUpdates(const Element&) const; 99 ElementUpdates* elementUpdates(const Element&); 85 100 86 101 const TextUpdate* textUpdate(const Text&) const; … … 93 108 unsigned size() const { return m_elements.size() + m_texts.size(); } 94 109 95 void addElement(Element&, Element* parent, ElementUpdate &&);110 void addElement(Element&, Element* parent, ElementUpdates&&); 96 111 void addText(Text&, Element* parent, TextUpdate&&); 97 112 void addText(Text&, TextUpdate&&); … … 102 117 Document& m_document; 103 118 ListHashSet<ContainerNode*> m_roots; 104 HashMap<const Element*, ElementUpdate > m_elements;119 HashMap<const Element*, ElementUpdates> m_elements; 105 120 HashMap<const Text*, TextUpdate> m_texts; 106 121 };
Note: See TracChangeset
for help on using the changeset viewer.