Changeset 224279 in webkit
- Timestamp:
- Nov 1, 2017 9:28:17 AM (6 years ago)
- Location:
- trunk
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r224273 r224279 1 2017-11-01 Commit Queue <commit-queue@webkit.org> 2 3 Unreviewed, rolling out r224273 and r224278. 4 https://bugs.webkit.org/show_bug.cgi?id=179120 5 6 Some crashes under guard malloc (Requested by anttik on 7 #webkit). 8 9 Reverted changesets: 10 11 "Remove empty continuations in 12 RenderObject::removeFromParentAndDestroyCleaningUpAnonymousWrappers" 13 https://bugs.webkit.org/show_bug.cgi?id=179014 14 https://trac.webkit.org/changeset/224273 15 16 "Fix ContinuationChainNode::insertAfter assertion." 17 https://bugs.webkit.org/show_bug.cgi?id=179115 18 https://trac.webkit.org/changeset/224278 19 1 20 2017-11-01 Antti Koivisto <antti@apple.com> 2 21 -
trunk/LayoutTests/fast/ruby/float-overhang-from-ruby-text-expected.txt
r224273 r224279 18 18 RenderRuby (inline) {RUBY} at (0,0) size 100x50 19 19 RenderRubyRun (anonymous) at (0,0) size 100x50 20 RenderText {#text} at (0,0) size 100x50 21 text run at (0,0) width 100: "aa" 20 RenderRubyBase (anonymous) at (0,0) size 100x50 21 RenderText {#text} at (0,0) size 100x50 22 text run at (0,0) width 100: "aa" 22 23 RenderText {#text} at (0,0) size 0x0 -
trunk/LayoutTests/platform/mac/fast/ruby/rubyDOM-remove-rt1-expected.txt
r224273 r224279 25 25 text run at (30,0) width 47: "HTML" 26 26 RenderRubyRun (anonymous) at (259,10) size 9x18 27 RenderText {#text} at (0,0) size 8x18 28 text run at (0,0) width 8: "5" 27 RenderRubyBase (anonymous) at (0,0) size 8x18 28 RenderText {#text} at (0,0) size 8x18 29 text run at (0,0) width 8: "5" 29 30 RenderText {#text} at (267,10) size 38x18 30 31 text run at (267,10) width 38: " spec." -
trunk/Source/WebCore/ChangeLog
r224278 r224279 1 2017-11-01 Commit Queue <commit-queue@webkit.org> 2 3 Unreviewed, rolling out r224273 and r224278. 4 https://bugs.webkit.org/show_bug.cgi?id=179120 5 6 Some crashes under guard malloc (Requested by anttik on 7 #webkit). 8 9 Reverted changesets: 10 11 "Remove empty continuations in 12 RenderObject::removeFromParentAndDestroyCleaningUpAnonymousWrappers" 13 https://bugs.webkit.org/show_bug.cgi?id=179014 14 https://trac.webkit.org/changeset/224273 15 16 "Fix ContinuationChainNode::insertAfter assertion." 17 https://bugs.webkit.org/show_bug.cgi?id=179115 18 https://trac.webkit.org/changeset/224278 19 1 20 2017-11-01 Emilio Cobos Álvarez <emilio@crisal.io> 2 21 -
trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp
r224273 r224279 164 164 static inline RenderObject* firstChildInContinuation(RenderInline& renderer) 165 165 { 166 auto *continuation = renderer.continuation();166 auto continuation = renderer.continuation(); 167 167 168 168 while (continuation) { -
trunk/Source/WebCore/rendering/RenderBlock.cpp
r224273 r224279 436 436 437 437 auto& newStyle = style(); 438 if (!isAnonymousBlock() && !isContinuation()) {438 if (!isAnonymousBlock()) { 439 439 // Ensure that all of our continuation blocks pick up the new style. 440 for (RenderBlock* currCont = blockElementContinuation(); currCont; currCont = currCont->blockElementContinuation()) 440 for (RenderBlock* currCont = blockElementContinuation(); currCont; currCont = currCont->blockElementContinuation()) { 441 RenderBoxModelObject* nextCont = currCont->continuation(); 442 currCont->setContinuation(0); 441 443 currCont->setStyle(RenderStyle::clone(newStyle)); 444 currCont->setContinuation(nextCont); 445 } 442 446 } 443 447 … … 815 819 } 816 820 817 void RenderBlock::dropAnonymousBoxChild(RenderBlock& child)818 { 819 setNeedsLayoutAndPrefWidthsRecalc();820 setChildrenInline(child.childrenInline());821 void RenderBlock::dropAnonymousBoxChild(RenderBlock& parent, RenderBlock& child) 822 { 823 parent.setNeedsLayoutAndPrefWidthsRecalc(); 824 parent.setChildrenInline(child.childrenInline()); 821 825 RenderObject* nextSibling = child.nextSibling(); 822 826 823 auto toBeDeleted = takeChildInternal(child, child.hasLayer() ? NotifyChildren : DontNotifyChildren);824 child.moveAllChildrenTo( this, nextSibling, child.hasLayer());827 auto toBeDeleted = parent.takeChildInternal(child, child.hasLayer() ? NotifyChildren : DontNotifyChildren); 828 child.moveAllChildrenTo(&parent, nextSibling, child.hasLayer()); 825 829 // Delete the now-empty block's lines and nuke it. 826 830 child.deleteLines(); … … 890 894 // The removal has knocked us down to containing only a single anonymous 891 895 // box. We can pull the content right back up into our box. 892 dropAnonymousBoxChild( downcast<RenderBlock>(*child));896 dropAnonymousBoxChild(*this, downcast<RenderBlock>(*child)); 893 897 } else if (((prev && prev->isAnonymousBlock()) || (next && next->isAnonymousBlock())) && canDropAnonymousBlockChild()) { 894 898 // It's possible that the removal has knocked us down to a single anonymous … … 906 910 } 907 911 if (dropAnonymousBlock) 908 dropAnonymousBoxChild( anonBlock);912 dropAnonymousBoxChild(*this, anonBlock); 909 913 } 910 914 } … … 914 918 if (childrenInline()) 915 919 deleteLines(); 920 921 // If we are an empty anonymous block in the continuation chain, 922 // we need to remove ourself and fix the continuation chain. 923 if (!beingDestroyed() && isAnonymousBlockContinuation() && !oldChild.isListMarker()) { 924 auto containingBlockIgnoringAnonymous = containingBlock(); 925 while (containingBlockIgnoringAnonymous && containingBlockIgnoringAnonymous->isAnonymousBlock()) 926 containingBlockIgnoringAnonymous = containingBlockIgnoringAnonymous->containingBlock(); 927 for (RenderObject* current = this; current; current = current->previousInPreOrder(containingBlockIgnoringAnonymous)) { 928 if (!is<RenderBoxModelObject>(current) || downcast<RenderBoxModelObject>(*current).continuation() != this) 929 continue; 930 // Found our previous continuation. We just need to point it to 931 // |this|'s next continuation. 932 auto* nextContinuation = continuation(); 933 if (is<RenderInline>(*current)) 934 downcast<RenderInline>(*current).setContinuation(nextContinuation); 935 else if (is<RenderBlock>(*current)) 936 downcast<RenderBlock>(*current).setContinuation(nextContinuation); 937 else 938 ASSERT_NOT_REACHED(); 939 break; 940 } 941 setContinuation(nullptr); 942 // FIXME: This is dangerous. 943 removeFromParentAndDestroy(); 944 } 916 945 } 917 946 return takenChild; -
trunk/Source/WebCore/rendering/RenderBlock.h
r224273 r224279 193 193 RenderBlock* blockElementContinuation() const; 194 194 195 using RenderBoxModelObject::continuation; 196 using RenderBoxModelObject::setContinuation; 197 195 198 static RenderPtr<RenderBlock> createAnonymousWithParentRendererAndDisplay(const RenderBox& parent, EDisplay = BLOCK); 196 199 RenderPtr<RenderBlock> createAnonymousBlock(EDisplay = BLOCK) const; 197 void dropAnonymousBoxChild(RenderBlock& child);200 static void dropAnonymousBoxChild(RenderBlock& parent, RenderBlock& child); 198 201 199 202 RenderPtr<RenderBox> createAnonymousBoxWithSameTypeAs(const RenderBox&) const override; -
trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp
r224278 r224279 78 78 // <b><i><p>Hello</p></i></b>. In this example the <i> will have a block as 79 79 // its continuation but the <b> will just have an inline as its continuation. 80 81 struct RenderBoxModelObject::ContinuationChainNode { 82 WeakPtr<RenderBoxModelObject> renderer; 83 ContinuationChainNode* previous { nullptr }; 84 ContinuationChainNode* next { nullptr }; 85 86 ContinuationChainNode(RenderBoxModelObject&); 87 ~ContinuationChainNode(); 88 89 void insertAfter(ContinuationChainNode&); 90 91 WTF_MAKE_FAST_ALLOCATED; 92 }; 93 94 RenderBoxModelObject::ContinuationChainNode::ContinuationChainNode(RenderBoxModelObject& renderer) 95 : renderer(makeWeakPtr(renderer)) 96 { 97 } 98 99 RenderBoxModelObject::ContinuationChainNode::~ContinuationChainNode() 100 { 101 if (next) { 102 ASSERT(previous); 103 ASSERT(next->previous == this); 104 next->previous = previous; 105 } 106 if (previous) { 107 ASSERT(previous->next == this); 108 previous->next = next; 109 } 110 } 111 112 void RenderBoxModelObject::ContinuationChainNode::insertAfter(ContinuationChainNode& after) 113 { 114 ASSERT(!previous); 115 ASSERT(!next); 116 if ((next = after.next)) { 117 ASSERT(next->previous == &after); 118 next->previous = this; 119 } 120 previous = &after; 121 after.next = this; 122 } 123 124 typedef HashMap<const RenderBoxModelObject*, std::unique_ptr<RenderBoxModelObject::ContinuationChainNode>> ContinuationChainNodeMap; 125 static ContinuationChainNodeMap& continuationChainNodeMap() 126 { 127 static NeverDestroyed<ContinuationChainNodeMap> map; 80 typedef HashMap<const RenderBoxModelObject*, WeakPtr<RenderBoxModelObject>> ContinuationMap; 81 static ContinuationMap& continuationMap() 82 { 83 static NeverDestroyed<ContinuationMap> map; 128 84 return map; 129 85 } … … 232 188 void RenderBoxModelObject::willBeDestroyed() 233 189 { 234 if (continuation() && !isContinuation()) { 235 removeAndDestroyAllContinuations(); 236 ASSERT(!continuation()); 237 } 238 if (hasContinuationChainNode()) 239 removeFromContinuationChain(); 190 if (hasContinuation()) { 191 continuation()->removeFromParentAndDestroy(); 192 setContinuation(nullptr); 193 } 240 194 241 195 // If this is a first-letter object with a remaining text fragment then the … … 2494 2448 RenderBoxModelObject* RenderBoxModelObject::continuation() const 2495 2449 { 2496 if (!hasContinuation ChainNode())2450 if (!hasContinuation()) 2497 2451 return nullptr; 2498 2499 auto& continuationChainNode = *continuationChainNodeMap().get(this); 2500 if (!continuationChainNode.next) 2501 return nullptr; 2502 return continuationChainNode.next->renderer.get(); 2503 } 2504 2505 void RenderBoxModelObject::insertIntoContinuationChainAfter(RenderBoxModelObject& afterRenderer) 2506 { 2507 ASSERT(isContinuation()); 2508 ASSERT(!continuationChainNodeMap().contains(this)); 2509 2510 auto& after = afterRenderer.ensureContinuationChainNode(); 2511 ensureContinuationChainNode().insertAfter(after); 2512 } 2513 2514 void RenderBoxModelObject::removeFromContinuationChain() 2515 { 2516 ASSERT(hasContinuationChainNode()); 2517 ASSERT(continuationChainNodeMap().contains(this)); 2518 setHasContinuationChainNode(false); 2519 continuationChainNodeMap().remove(this); 2520 } 2521 2522 auto RenderBoxModelObject::ensureContinuationChainNode() -> ContinuationChainNode& 2523 { 2524 setHasContinuationChainNode(true); 2525 return *continuationChainNodeMap().ensure(this, [&] { 2526 return std::make_unique<ContinuationChainNode>(*this); 2527 }).iterator->value; 2528 } 2529 2530 void RenderBoxModelObject::removeAndDestroyAllContinuations() 2531 { 2532 ASSERT(!isContinuation()); 2533 ASSERT(hasContinuationChainNode()); 2534 ASSERT(continuationChainNodeMap().contains(this)); 2535 auto& continuationChainNode = *continuationChainNodeMap().get(this); 2536 while (continuationChainNode.next) 2537 continuationChainNode.next->renderer->removeFromParentAndDestroy(); 2538 removeFromContinuationChain(); 2452 return continuationMap().get(this).get(); 2453 } 2454 2455 void RenderBoxModelObject::setContinuation(RenderBoxModelObject* continuation) 2456 { 2457 ASSERT(!continuation || continuation->isContinuation()); 2458 if (continuation) 2459 continuationMap().set(this, makeWeakPtr(continuation)); 2460 else if (hasContinuation()) 2461 continuationMap().remove(this); 2462 setHasContinuation(!!continuation); 2539 2463 } 2540 2464 -
trunk/Source/WebCore/rendering/RenderBoxModelObject.h
r224273 r224279 236 236 237 237 RenderBoxModelObject* continuation() const; 238 239 void insertIntoContinuationChainAfter(RenderBoxModelObject&);240 void removeFromContinuationChain();241 238 242 239 virtual LayoutRect paintRectToClipOutFromBorder(const LayoutRect&) { return LayoutRect(); }; … … 260 257 InterpolationQuality chooseInterpolationQuality(GraphicsContext&, Image&, const void*, const LayoutSize&); 261 258 259 void setContinuation(RenderBoxModelObject*); 260 262 261 LayoutRect localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset); 263 262 … … 303 302 RenderBlock* containingBlockForAutoHeightDetection(Length logicalHeight) const; 304 303 305 struct ContinuationChainNode;306 307 304 private: 308 ContinuationChainNode& ensureContinuationChainNode();309 void removeAndDestroyAllContinuations();310 311 305 LayoutUnit computedCSSPadding(const Length&) const; 312 306 -
trunk/Source/WebCore/rendering/RenderElement.cpp
r224273 r224279 102 102 , m_hasPausedImageAnimations(false) 103 103 , m_hasCounterNodeMap(false) 104 , m_hasContinuation ChainNode(false)104 , m_hasContinuation(false) 105 105 , m_isContinuation(false) 106 106 , m_hasValidCachedFirstLineStyle(false) … … 962 962 void RenderElement::removeAnonymousWrappersForInlinesIfNecessary() 963 963 { 964 // FIXME: Move to RenderBlock. 965 if (!is<RenderBlock>(*this)) 966 return; 967 RenderBlock& thisBlock = downcast<RenderBlock>(*this); 968 if (!thisBlock.canDropAnonymousBlockChild()) 964 RenderBlock& parentBlock = downcast<RenderBlock>(*parent()); 965 if (!parentBlock.canDropAnonymousBlockChild()) 969 966 return; 970 967 … … 974 971 // FIXME: We should also handle split inlines here - we exclude them at the moment by returning 975 972 // if we find a continuation. 976 RenderObject* current = firstChild();977 while (current && ((current->isAnonymousBlock() && !downcast<RenderBlock>(*current).is Continuation()) || current->style().isFloating() || current->style().hasOutOfFlowPosition()))973 RenderObject* current = parent()->firstChild(); 974 while (current && ((current->isAnonymousBlock() && !downcast<RenderBlock>(*current).isAnonymousBlockContinuation()) || current->style().isFloating() || current->style().hasOutOfFlowPosition())) 978 975 current = current->nextSibling(); 979 976 … … 982 979 983 980 RenderObject* next; 984 for (current = firstChild(); current; current = next) {981 for (current = parent()->firstChild(); current; current = next) { 985 982 next = current->nextSibling(); 986 983 if (current->isAnonymousBlock()) 987 thisBlock.dropAnonymousBoxChild(downcast<RenderBlock>(*current));984 parentBlock.dropAnonymousBoxChild(parentBlock, downcast<RenderBlock>(*current)); 988 985 } 989 986 } … … 1014 1011 1015 1012 if (s_noLongerAffectsParentBlock) 1016 parent()->removeAnonymousWrappersForInlinesIfNecessary();1013 removeAnonymousWrappersForInlinesIfNecessary(); 1017 1014 1018 1015 SVGRenderSupport::styleChanged(*this, oldStyle); … … 2156 2153 downcast<RenderElement>(child).updateOutlineAutoAncestor(hasOutlineAuto); 2157 2154 } 2158 if (is<RenderBoxModelObject>(*this)) { 2159 if (auto* continuation = downcast<RenderBoxModelObject>(*this).continuation()) 2160 continuation->updateOutlineAutoAncestor(hasOutlineAuto); 2161 } 2155 if (hasContinuation()) 2156 downcast<RenderBoxModelObject>(*this).continuation()->updateOutlineAutoAncestor(hasOutlineAuto); 2162 2157 } 2163 2158 -
trunk/Source/WebCore/rendering/RenderElement.h
r224273 r224279 222 222 virtual void updateAnonymousChildStyle(const RenderObject&, RenderStyle&) const { }; 223 223 224 void removeAnonymousWrappersForInlinesIfNecessary(); 225 226 bool hasContinuationChainNode() const { return m_hasContinuationChainNode; } 224 bool hasContinuation() const { return m_hasContinuation; } 227 225 bool isContinuation() const { return m_isContinuation; } 228 226 void setIsContinuation() { m_isContinuation = true; } … … 267 265 bool renderInlineAlwaysCreatesLineBoxes() const { return m_renderInlineAlwaysCreatesLineBoxes; } 268 266 269 void setHasContinuation ChainNode(bool b) { m_hasContinuationChainNode= b; }267 void setHasContinuation(bool b) { m_hasContinuation = b; } 270 268 271 269 void setRenderBlockHasMarginBeforeQuirk(bool b) { m_renderBlockHasMarginBeforeQuirk = b; } … … 306 304 // normal flow object. 307 305 void handleDynamicFloatPositionChange(); 306 void removeAnonymousWrappersForInlinesIfNecessary(); 308 307 309 308 bool shouldRepaintForStyleDifference(StyleDifference) const; … … 338 337 unsigned m_hasPausedImageAnimations : 1; 339 338 unsigned m_hasCounterNodeMap : 1; 340 unsigned m_hasContinuation ChainNode: 1;339 unsigned m_hasContinuation : 1; 341 340 unsigned m_isContinuation : 1; 342 341 mutable unsigned m_hasValidCachedFirstLineStyle : 1; -
trunk/Source/WebCore/rendering/RenderInline.cpp
r224273 r224279 190 190 auto& newStyle = style(); 191 191 RenderInline* continuation = inlineElementContinuation(); 192 if (continuation && !isContinuation()) { 193 for (RenderInline* currCont = continuation; currCont; currCont = currCont->inlineElementContinuation()) 192 if (continuation) { 193 for (RenderInline* currCont = continuation; currCont; currCont = currCont->inlineElementContinuation()) { 194 RenderBoxModelObject* nextCont = currCont->continuation(); 195 currCont->setContinuation(nullptr); 194 196 currCont->setStyle(RenderStyle::clone(newStyle)); 197 currCont->setContinuation(nextCont); 198 } 195 199 // If an inline's in-flow positioning has changed and it is part of an active continuation as a descendant of an anonymous containing block, 196 200 // then any descendant blocks will need to change their in-flow positioning accordingly. … … 341 345 newBox->setIsContinuation(); 342 346 RenderBoxModelObject* oldContinuation = continuation(); 343 if (oldContinuation) 344 oldContinuation->removeFromContinuationChain(); 345 newBox->insertIntoContinuationChainAfter(*this); 347 setContinuation(newBox.get()); 346 348 347 349 splitFlow(beforeChild, WTFMove(newBox), WTFMove(newChild), oldContinuation); … … 416 418 rendererToMove = nextSibling; 417 419 } 420 cloneInline->setContinuation(oldCont); 418 421 // Hook |clone| up as the continuation of the middle block. 419 cloneInline->insertIntoContinuationChainAfter(*middleBlock); 420 if (oldCont) 421 oldCont->insertIntoContinuationChainAfter(*cloneInline); 422 middleBlock->setContinuation(cloneInline.get()); 422 423 423 424 // We have been reparented and are now under the fromBlock. We need … … 443 444 444 445 // Hook the clone up as a continuation of |curr|. 445 cloneInline->insertIntoContinuationChainAfter(*current); 446 RenderInline& currentInline = downcast<RenderInline>(*current); 447 oldCont = currentInline.continuation(); 448 currentInline.setContinuation(cloneInline.get()); 449 cloneInline->setContinuation(oldCont); 446 450 447 451 // Now we need to take all of the children starting from the first child 448 452 // *after* currentChild and append them all to the clone. 449 for (auto* sibling = currentChild->nextSibling(); sibling;) {450 auto* next = sibling->nextSibling();451 auto childToMove = current ->takeChildInternal(*sibling, NotifyChildren);453 for (auto* current = currentChild->nextSibling(); current;) { 454 auto* next = current->nextSibling(); 455 auto childToMove = currentInline.takeChildInternal(*current, NotifyChildren); 452 456 cloneInline->addChildIgnoringContinuation(WTFMove(childToMove)); 453 sibling->setNeedsLayoutAndPrefWidthsRecalc();454 sibling= next;457 current->setNeedsLayoutAndPrefWidthsRecalc(); 458 current = next; 455 459 } 456 460 } … … 573 577 while (parent && parent->parent() && parent->parent()->isAnonymous()) { 574 578 // The ancestor candidate needs to be inside the continuation. 575 if (parent-> isContinuation())579 if (parent->hasContinuation()) 576 580 break; 577 581 parent = parent->parent(); … … 1376 1380 newBox->setIsContinuation(); 1377 1381 RenderBoxModelObject* oldContinuation = continuation(); 1378 if (oldContinuation) 1379 oldContinuation->removeFromContinuationChain(); 1380 newBox->insertIntoContinuationChainAfter(*this); 1382 setContinuation(newBox.get()); 1381 1383 RenderObject* beforeChild = child.nextSibling(); 1382 1384 auto removedChild = takeChildInternal(child, NotifyChildren); -
trunk/Source/WebCore/rendering/RenderInline.h
r224273 r224279 87 87 void addFocusRingRects(Vector<LayoutRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) final; 88 88 void paintOutline(PaintInfo&, const LayoutPoint&); 89 90 using RenderBoxModelObject::continuation; 91 using RenderBoxModelObject::setContinuation; 89 92 90 93 bool alwaysCreateLineBoxes() const { return renderInlineAlwaysCreatesLineBoxes(); } -
trunk/Source/WebCore/rendering/RenderObject.cpp
r224273 r224279 825 825 ASSERT(rendererHasOutlineAutoAncestor 826 826 || renderer->outlineStyleForRepaint().outlineStyleIsAuto() 827 || (is<Render BoxModelObject>(*renderer) && downcast<RenderBoxModelObject>(*renderer).isContinuation()));827 || (is<RenderElement>(*renderer) && downcast<RenderElement>(*renderer).hasContinuation())); 828 828 if (renderer == &repaintContainer && rendererHasOutlineAutoAncestor) 829 829 repaintRectNeedsConverting = true; … … 1176 1176 if (is<RenderBoxModelObject>(*this)) { 1177 1177 auto& renderer = downcast<RenderBoxModelObject>(*this); 1178 if (renderer. continuation())1178 if (renderer.hasContinuation()) 1179 1179 stream << " continuation->(" << renderer.continuation() << ")"; 1180 1180 } … … 1467 1467 if (destroyRootParent->isRenderFragmentedFlow()) 1468 1468 break; 1469 // FIXME: Destroy continuations here too. 1470 if (destroyRootParent->isContinuation()) 1471 break; 1469 1472 bool destroyingOnlyChild = destroyRootParent->firstChild() == destroyRoot && destroyRootParent->lastChild() == destroyRoot; 1470 1473 if (!destroyingOnlyChild) … … 1488 1491 downcast<RenderTableRow>(destroyRoot).collapseAndDestroyAnonymousSiblingRows(); 1489 1492 1490 auto& destroyRootParent = *destroyRoot.parent(); 1491 destroyRootParent.removeAndDestroyChild(destroyRoot); 1492 destroyRootParent.removeAnonymousWrappersForInlinesIfNecessary(); 1493 destroyRoot.removeFromParentAndDestroy(); 1493 1494 // WARNING: |this| is deleted here. 1494 1495 }
Note: See TracChangeset
for help on using the changeset viewer.