Changeset 220447 in webkit
- Timestamp:
- Aug 9, 2017 12:36:45 AM (7 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r220444 r220447 1 2017-08-09 Antti Koivisto <antti@apple.com> 2 3 RenderQuote should not mutate render tree 4 https://bugs.webkit.org/show_bug.cgi?id=175328 5 6 Reviewed by Zalan Bujtas. 7 8 RenderQuote text renderers are currently created and deleted in a quirky fashion using a linked list. 9 This patch moves to a simpler model that guarantees the mutations are always done in controlled fashion 10 during render tree update. 11 12 * dom/Document.cpp: 13 (WebCore::Document::updateTextRenderer): 14 15 Move text renderer updating to Document so we can set the inRenderTreeUpdate bit for it too. 16 17 * dom/Document.h: 18 * dom/Text.cpp: 19 (WebCore::Text::updateRendererAfterContentChange): 20 * rendering/RenderDescendantIterator.h: 21 (WebCore::RenderDescendantIteratorAdapter<T>::at): 22 (WebCore::RenderDescendantConstIteratorAdapter<T>::at const): 23 24 Add at() function for starting iteration from a specified renderer. 25 26 * rendering/RenderQuote.cpp: 27 (WebCore::RenderQuote::insertedIntoTree): 28 (WebCore::RenderQuote::willBeRemovedFromTree): 29 30 Register and unregister quotes to RenderView. 31 Don't do any mutations. 32 33 (WebCore::RenderQuote::styleDidChange): 34 35 Invalidate the text renderer but don't mutate it. 36 37 (WebCore::RenderQuote::updateTextRenderer): 38 (WebCore::RenderQuote::computeText const): 39 (WebCore::RenderQuote::updateRenderers): 40 41 Compute depth of all render quotes and update the text renderer as needed. 42 43 (WebCore::RenderQuote::willBeDestroyed): Deleted. 44 (WebCore::RenderQuote::attachQuote): Deleted. 45 (WebCore::RenderQuote::detachQuote): Deleted. 46 (WebCore::RenderQuote::updateDepth): Deleted. 47 48 Get rid of the linked list. 49 50 * rendering/RenderQuote.h: 51 * rendering/RenderView.cpp: 52 (WebCore::RenderView::registerQuote): 53 (WebCore::RenderView::unregisterQuote): 54 55 Maintain a render tree order ListHashSet of RenderQuotes. 56 57 (WebCore::RenderView::updateSpecialRenderers): 58 59 Add a function for making additional render tree mutations at the end of a render tree update. 60 Currently this just invokes RenderQuote::updateRenderers. 61 62 * rendering/RenderView.h: 63 * style/RenderTreeUpdater.cpp: 64 (WebCore::RenderTreeUpdater::commit): 65 66 Call RenderView::updateSpecialRenderers after committing all other changes. 67 1 68 2017-08-09 Zan Dobersek <zdobersek@igalia.com> 2 69 -
trunk/Source/WebCore/dom/Document.cpp
r220427 r220447 1869 1869 } 1870 1870 1871 void Document::updateTextRenderer(Text& text) 1872 { 1873 ASSERT(!m_inRenderTreeUpdate); 1874 SetForScope<bool> inRenderTreeUpdate(m_inRenderTreeUpdate, true); 1875 1876 auto textUpdate = std::make_unique<Style::Update>(*this); 1877 textUpdate->addText(text); 1878 1879 RenderTreeUpdater renderTreeUpdater(*this); 1880 renderTreeUpdater.commit(WTFMove(textUpdate)); 1881 } 1882 1871 1883 bool Document::needsStyleRecalc() const 1872 1884 { -
trunk/Source/WebCore/dom/Document.h
r220376 r220447 1238 1238 bool inRenderTreeUpdate() const { return m_inRenderTreeUpdate; } 1239 1239 1240 void updateTextRenderer(Text&); 1241 1240 1242 // Return a Locale for the default locale if the argument is null or empty. 1241 1243 Locale& getCachedLocale(const AtomicString& locale = nullAtom()); -
trunk/Source/WebCore/dom/Text.cpp
r219856 r220447 27 27 #include "RenderSVGInlineText.h" 28 28 #include "RenderText.h" 29 #include "RenderTreeUpdater.h"30 29 #include "SVGElement.h" 31 30 #include "SVGNames.h" … … 219 218 return; 220 219 221 auto textUpdate = std::make_unique<Style::Update>(document()); 222 textUpdate->addText(*this); 223 224 RenderTreeUpdater renderTreeUpdater(document()); 225 renderTreeUpdater.commit(WTFMove(textUpdate)); 220 document().updateTextRenderer(*this); 226 221 227 222 if (auto* renderer = this->renderer()) -
trunk/Source/WebCore/rendering/RenderDescendantIterator.h
r200994 r220447 52 52 RenderDescendantIterator<T> begin(); 53 53 RenderDescendantIterator<T> end(); 54 RenderDescendantIterator<T> at(T&); 54 55 55 56 private: … … 63 64 RenderDescendantConstIterator<T> begin() const; 64 65 RenderDescendantConstIterator<T> end() const; 66 RenderDescendantConstIterator<T> at(const T&) const; 65 67 66 68 private: … … 131 133 } 132 134 135 template <typename T> 136 inline RenderDescendantIterator<T> RenderDescendantIteratorAdapter<T>::at(T& current) 137 { 138 return RenderDescendantIterator<T>(m_root, ¤t); 139 } 140 133 141 // RenderDescendantConstIteratorAdapter 134 142 … … 151 159 } 152 160 161 template <typename T> 162 inline RenderDescendantConstIterator<T> RenderDescendantConstIteratorAdapter<T>::at(const T& current) const 163 { 164 return RenderDescendantConstIterator<T>(m_root, ¤t); 165 } 166 153 167 // Standalone functions 154 168 -
trunk/Source/WebCore/rendering/RenderQuote.cpp
r217893 r220447 2 2 * Copyright (C) 2011 Nokia Inc. All rights reserved. 3 3 * Copyright (C) 2012 Google Inc. All rights reserved. 4 * Copyright (C) 2013 Apple Inc. All rights reserved.4 * Copyright (C) 2013, 2017 Apple Inc. All rights reserved. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 45 45 } 46 46 47 void RenderQuote::willBeDestroyed()48 {49 detachQuote();50 51 ASSERT(!m_isAttached);52 ASSERT(!m_next);53 ASSERT(!m_previous);54 55 RenderInline::willBeDestroyed();56 }57 58 47 void RenderQuote::insertedIntoTree() 59 48 { 60 49 RenderInline::insertedIntoTree(); 61 attachQuote();50 view().registerQuote(*this); 62 51 } 63 52 64 53 void RenderQuote::willBeRemovedFromTree() 65 54 { 55 view().unregisterQuote(*this); 66 56 RenderInline::willBeRemovedFromTree(); 67 detachQuote();68 57 } 69 58 … … 71 60 { 72 61 RenderInline::styleDidChange(diff, oldStyle); 73 updateText(); 62 if (diff >= StyleDifferenceLayout) { 63 m_needsTextUpdate = true; 64 view().setHasSpecialRendererNeedingUpdate(); 65 } 74 66 } 75 67 … … 356 348 } 357 349 358 void RenderQuote::updateText() 359 { 350 void RenderQuote::updateTextRenderer() 351 { 352 ASSERT_WITH_SECURITY_IMPLICATION(document().inRenderTreeUpdate()); 353 ASSERT_WITH_SECURITY_IMPLICATION(!view().renderTreeIsBeingMutatedInternally()); 354 360 355 String text = computeText(); 361 356 if (m_text == text) 362 357 return; 363 358 m_text = text; 364 // Start from the end of the child list because, if we've had a first-letter365 // renderer inserted then the remaining text will be at the end.366 359 if (auto* renderText = quoteTextRenderer(lastChild())) { 367 360 renderText->setContentString(m_text); … … 396 389 } 397 390 398 void RenderQuote::attachQuote() 399 { 400 if (view().renderTreeIsBeingMutatedInternally()) 401 return; 402 403 ASSERT(!m_isAttached); 404 ASSERT(!m_next); 405 ASSERT(!m_previous); 406 ASSERT(isRooted()); 407 408 // Optimize case where this is the first quote in a RenderView by not searching for predecessors in that case. 409 if (view().renderQuoteHead()) { 410 for (RenderObject* predecessor = previousInPreOrder(); predecessor; predecessor = predecessor->previousInPreOrder()) { 411 // Skip unattached predecessors to avoid having stale m_previous pointers 412 // if the previous node is never attached and is then destroyed. 413 if (!is<RenderQuote>(*predecessor) || !downcast<RenderQuote>(*predecessor).m_isAttached) 414 continue; 415 m_previous = downcast<RenderQuote>(predecessor); 416 m_next = m_previous->m_next; 417 m_previous->m_next = this; 418 if (m_next) 419 m_next->m_previous = this; 420 break; 391 void RenderQuote::updateRenderers(const RenderView& view) 392 { 393 int depth = -1; 394 for (auto* quote : view.quotes()) { 395 bool isOpen = quote->m_type == OPEN_QUOTE || quote->m_type == NO_OPEN_QUOTE; 396 if (!isOpen) 397 --depth; 398 else if (depth < 0) 399 depth = 0; 400 401 if (quote->m_depth != depth || quote->m_needsTextUpdate) { 402 quote->m_depth = depth; 403 quote->m_needsTextUpdate = false; 404 quote->updateTextRenderer(); 421 405 } 422 } 423 424 if (!m_previous) { 425 m_next = view().renderQuoteHead(); 426 view().setRenderQuoteHead(this); 427 if (m_next) 428 m_next->m_previous = this; 429 } 430 431 m_isAttached = true; 432 433 for (RenderQuote* quote = this; quote; quote = quote->m_next) 434 quote->updateDepth(); 435 436 ASSERT(!m_next || m_next->m_isAttached); 437 ASSERT(!m_next || m_next->m_previous == this); 438 ASSERT(!m_previous || m_previous->m_isAttached); 439 ASSERT(!m_previous || m_previous->m_next == this); 440 } 441 442 void RenderQuote::detachQuote() 443 { 444 if (view().renderTreeIsBeingMutatedInternally()) 445 return; 446 447 ASSERT(!m_next || m_next->m_isAttached); 448 ASSERT(!m_previous || m_previous->m_isAttached); 449 if (!m_isAttached) 450 return; 451 if (m_previous) 452 m_previous->m_next = m_next; 453 else 454 view().setRenderQuoteHead(m_next); 455 if (m_next) 456 m_next->m_previous = m_previous; 457 if (!renderTreeBeingDestroyed()) { 458 for (RenderQuote* quote = m_next; quote; quote = quote->m_next) 459 quote->updateDepth(); 460 } 461 m_isAttached = false; 462 m_next = 0; 463 m_previous = 0; 464 } 465 466 void RenderQuote::updateDepth() 467 { 468 ASSERT(m_isAttached); 469 int depth = 0; 470 if (m_previous) { 471 depth = m_previous->m_depth; 472 if (depth < 0) 473 depth = 0; 474 switch (m_previous->m_type) { 475 case OPEN_QUOTE: 476 case NO_OPEN_QUOTE: 477 depth++; 478 break; 479 case CLOSE_QUOTE: 480 case NO_CLOSE_QUOTE: 481 break; 482 } 483 } 484 switch (m_type) { 485 case OPEN_QUOTE: 486 case NO_OPEN_QUOTE: 487 break; 488 case CLOSE_QUOTE: 489 case NO_CLOSE_QUOTE: 490 depth--; 491 break; 492 } 493 if (m_depth == depth) 494 return; 495 m_depth = depth; 496 updateText(); 406 407 if (isOpen) 408 ++depth; 409 } 497 410 } 498 411 -
trunk/Source/WebCore/rendering/RenderQuote.h
r214173 r220447 32 32 virtual ~RenderQuote(); 33 33 34 void attachQuote();34 static void updateRenderers(const RenderView&); 35 35 36 36 private: 37 void willBeDestroyed() override;38 void detachQuote();39 40 37 const char* renderName() const override { return "RenderQuote"; } 41 38 bool isQuote() const override { return true; } … … 45 42 46 43 String computeText() const; 47 void updateText(); 48 void updateDepth(); 44 void updateTextRenderer(); 49 45 50 46 const QuoteType m_type; 51 47 int m_depth { -1 }; 52 RenderQuote* m_next { nullptr };53 RenderQuote* m_previous { nullptr };54 bool m_isAttached { false };55 48 String m_text; 49 50 bool m_needsTextUpdate { false }; 56 51 }; 57 52 -
trunk/Source/WebCore/rendering/RenderView.cpp
r220333 r220447 39 39 #include "NodeTraversal.h" 40 40 #include "Page.h" 41 #include "RenderDescendantIterator.h" 41 42 #include "RenderGeometryMap.h" 42 43 #include "RenderIterator.h" … … 48 49 #include "RenderMultiColumnSpannerPlaceholder.h" 49 50 #include "RenderNamedFlowThread.h" 51 #include "RenderQuote.h" 50 52 #include "RenderSelectionInfo.h" 51 53 #include "RenderWidget.h" … … 1523 1525 } 1524 1526 1527 void RenderView::registerQuote(RenderQuote& quote) 1528 { 1529 ASSERT(!m_quotes.contains("e)); 1530 1531 setHasSpecialRendererNeedingUpdate(); 1532 1533 if (m_quotes.isEmpty()) { 1534 m_quotes.add("e); 1535 return; 1536 } 1537 auto quoteRenderers = descendantsOfType<RenderQuote>(*this); 1538 auto it = quoteRenderers.at(quote); 1539 if (++it == quoteRenderers.end()) { 1540 m_quotes.add("e); 1541 return; 1542 } 1543 auto& nextQuote = *it; 1544 ASSERT(m_quotes.contains(&nextQuote)); 1545 m_quotes.insertBefore(&nextQuote, "e); 1546 } 1547 1548 void RenderView::unregisterQuote(RenderQuote& quote) 1549 { 1550 ASSERT(m_quotes.contains("e)); 1551 1552 setHasSpecialRendererNeedingUpdate(); 1553 1554 m_quotes.remove("e); 1555 } 1556 1557 void RenderView::updateSpecialRenderers() 1558 { 1559 ASSERT_WITH_SECURITY_IMPLICATION(document().inRenderTreeUpdate()); 1560 ASSERT_WITH_SECURITY_IMPLICATION(!renderTreeIsBeingMutatedInternally()); 1561 1562 if (!m_hasSpecialRendererNeedingUpdate) 1563 return; 1564 m_hasSpecialRendererNeedingUpdate = false; 1565 1566 RenderQuote::updateRenderers(*this); 1567 } 1568 1525 1569 #if ENABLE(CSS_SCROLL_SNAP) 1526 1570 void RenderView::registerBoxWithScrollSnapPositions(const RenderBox& box) -
trunk/Source/WebCore/rendering/RenderView.h
r219121 r220447 30 30 #include <memory> 31 31 #include <wtf/HashSet.h> 32 #include <wtf/ListHashSet.h> 32 33 33 34 #if ENABLE(SERVICE_CONTROLS) … … 196 197 IntSize viewportSizeForCSSViewportUnits() const; 197 198 198 void setRenderQuoteHead(RenderQuote* head) { m_renderQuoteHead = head; } 199 RenderQuote* renderQuoteHead() const { return m_renderQuoteHead; } 200 199 void registerQuote(RenderQuote&); 200 void unregisterQuote(RenderQuote&); 201 const ListHashSet<RenderQuote*>& quotes() const { return m_quotes; } 202 203 void setHasSpecialRendererNeedingUpdate() { m_hasSpecialRendererNeedingUpdate = true; } 204 void updateSpecialRenderers(); 205 201 206 // FIXME: see class RenderTreeInternalMutation below. 202 207 bool renderTreeIsBeingMutatedInternally() const { return !!m_renderTreeInternalMutationCounter; } … … 372 377 std::unique_ptr<FlowThreadController> m_flowThreadController; 373 378 374 RenderQuote* m_renderQuoteHead { nullptr }; 379 ListHashSet<RenderQuote*> m_quotes; 380 bool m_hasSpecialRendererNeedingUpdate { false }; 381 375 382 unsigned m_renderCounterCount { 0 }; 376 383 unsigned m_renderTreeInternalMutationCounter { 0 }; -
trunk/Source/WebCore/style/RenderTreeUpdater.cpp
r220202 r220447 125 125 updateRenderTree(*root); 126 126 127 m_document.renderView()->updateSpecialRenderers(); 128 127 129 m_styleUpdate = nullptr; 128 130 }
Note: See TracChangeset
for help on using the changeset viewer.