Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(461)

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutObject.cpp

Issue 2770123003: Replace ASSERT with DCHECK in core/layout/ excluding subdirs (Closed)
Patch Set: Split some DCHECKs and add DCHECK_ops wherever possible Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2000 Dirk Mueller (mueller@kde.org) 4 * (C) 2000 Dirk Mueller (mueller@kde.org)
5 * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com) 5 * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011 Apple Inc. 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011 Apple Inc.
7 * All rights reserved. 7 * All rights reserved.
8 * Copyright (C) 2009 Google Inc. All rights reserved. 8 * Copyright (C) 2009 Google Inc. All rights reserved.
9 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. 9 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved.
10 * (http://www.torchmobile.com/) 10 * (http://www.torchmobile.com/)
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 LayoutPoint m_paintOffset; 129 LayoutPoint m_paintOffset;
130 std::unique_ptr<void*> m_rarePaintData; 130 std::unique_ptr<void*> m_rarePaintData;
131 }; 131 };
132 132
133 static_assert(sizeof(LayoutObject) == sizeof(SameSizeAsLayoutObject), 133 static_assert(sizeof(LayoutObject) == sizeof(SameSizeAsLayoutObject),
134 "LayoutObject should stay small"); 134 "LayoutObject should stay small");
135 135
136 bool LayoutObject::s_affectsParentBlock = false; 136 bool LayoutObject::s_affectsParentBlock = false;
137 137
138 void* LayoutObject::operator new(size_t sz) { 138 void* LayoutObject::operator new(size_t sz) {
139 ASSERT(isMainThread()); 139 DCHECK(isMainThread());
140 return PartitionAlloc(WTF::Partitions::layoutPartition(), sz, 140 return PartitionAlloc(WTF::Partitions::layoutPartition(), sz,
141 WTF_HEAP_PROFILER_TYPE_NAME(LayoutObject)); 141 WTF_HEAP_PROFILER_TYPE_NAME(LayoutObject));
142 } 142 }
143 143
144 void LayoutObject::operator delete(void* ptr) { 144 void LayoutObject::operator delete(void* ptr) {
145 ASSERT(isMainThread()); 145 DCHECK(isMainThread());
146 WTF::PartitionFree(ptr); 146 WTF::PartitionFree(ptr);
147 } 147 }
148 148
149 LayoutObject* LayoutObject::createObject(Element* element, 149 LayoutObject* LayoutObject::createObject(Element* element,
150 const ComputedStyle& style) { 150 const ComputedStyle& style) {
151 ASSERT(isAllowedToModifyLayoutTreeStructure(element->document())); 151 DCHECK(isAllowedToModifyLayoutTreeStructure(element->document()));
152 152
153 // Minimal support for content properties replacing an entire element. 153 // Minimal support for content properties replacing an entire element.
154 // Works only if we have exactly one piece of content and it's a URL. 154 // Works only if we have exactly one piece of content and it's a URL.
155 // Otherwise acts as if we didn't support this feature. 155 // Otherwise acts as if we didn't support this feature.
156 const ContentData* contentData = style.contentData(); 156 const ContentData* contentData = style.contentData();
157 if (contentData && !contentData->next() && contentData->isImage() && 157 if (contentData && !contentData->next() && contentData->isImage() &&
158 !element->isPseudoElement()) { 158 !element->isPseudoElement()) {
159 LayoutImage* image = new LayoutImage(element); 159 LayoutImage* image = new LayoutImage(element);
160 // LayoutImageResourceStyleImage requires a style being present on the image 160 // LayoutImageResourceStyleImage requires a style being present on the image
161 // but we don't want to trigger a style change now as the node is not fully 161 // but we don't want to trigger a style change now as the node is not fully
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 bool insideFlowThread) { 262 bool insideFlowThread) {
263 LayoutObject* next; 263 LayoutObject* next;
264 for (LayoutObject* object = this; object; object = next) { 264 for (LayoutObject* object = this; object; object = next) {
265 // If object is a fragmentation context it already updated the descendants 265 // If object is a fragmentation context it already updated the descendants
266 // flag accordingly. 266 // flag accordingly.
267 if (object->isLayoutFlowThread()) { 267 if (object->isLayoutFlowThread()) {
268 next = object->nextInPreOrderAfterChildren(this); 268 next = object->nextInPreOrderAfterChildren(this);
269 continue; 269 continue;
270 } 270 }
271 next = object->nextInPreOrder(this); 271 next = object->nextInPreOrder(this);
272 ASSERT(insideFlowThread != object->isInsideFlowThread()); 272 DCHECK_NE(insideFlowThread, object->isInsideFlowThread());
273 object->setIsInsideFlowThread(insideFlowThread); 273 object->setIsInsideFlowThread(insideFlowThread);
274 } 274 }
275 } 275 }
276 276
277 bool LayoutObject::requiresAnonymousTableWrappers( 277 bool LayoutObject::requiresAnonymousTableWrappers(
278 const LayoutObject* newChild) const { 278 const LayoutObject* newChild) const {
279 // Check should agree with: 279 // Check should agree with:
280 // CSS 2.1 Tables: 17.2.1 Anonymous table objects 280 // CSS 2.1 Tables: 17.2.1 Anonymous table objects
281 // http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes 281 // http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes
282 if (newChild->isLayoutTableCol()) { 282 if (newChild->isLayoutTableCol()) {
283 const LayoutTableCol* newTableColumn = toLayoutTableCol(newChild); 283 const LayoutTableCol* newTableColumn = toLayoutTableCol(newChild);
284 bool isColumnInColumnGroup = 284 bool isColumnInColumnGroup =
285 newTableColumn->isTableColumn() && isLayoutTableCol(); 285 newTableColumn->isTableColumn() && isLayoutTableCol();
286 return !isTable() && !isColumnInColumnGroup; 286 return !isTable() && !isColumnInColumnGroup;
287 } 287 }
288 if (newChild->isTableCaption()) 288 if (newChild->isTableCaption())
289 return !isTable(); 289 return !isTable();
290 if (newChild->isTableSection()) 290 if (newChild->isTableSection())
291 return !isTable(); 291 return !isTable();
292 if (newChild->isTableRow()) 292 if (newChild->isTableRow())
293 return !isTableSection(); 293 return !isTableSection();
294 if (newChild->isTableCell()) 294 if (newChild->isTableCell())
295 return !isTableRow(); 295 return !isTableRow();
296 return false; 296 return false;
297 } 297 }
298 298
299 DISABLE_CFI_PERF 299 DISABLE_CFI_PERF
300 void LayoutObject::addChild(LayoutObject* newChild, LayoutObject* beforeChild) { 300 void LayoutObject::addChild(LayoutObject* newChild, LayoutObject* beforeChild) {
301 ASSERT(isAllowedToModifyLayoutTreeStructure(document())); 301 DCHECK(isAllowedToModifyLayoutTreeStructure(document()));
302 302
303 LayoutObjectChildList* children = virtualChildren(); 303 LayoutObjectChildList* children = virtualChildren();
304 ASSERT(children); 304 DCHECK(children);
305 if (!children) 305 if (!children)
306 return; 306 return;
307 307
308 if (requiresAnonymousTableWrappers(newChild)) { 308 if (requiresAnonymousTableWrappers(newChild)) {
309 // Generate an anonymous table or reuse existing one from previous child 309 // Generate an anonymous table or reuse existing one from previous child
310 // Per: 17.2.1 Anonymous table objects 3. Generate missing parents 310 // Per: 17.2.1 Anonymous table objects 3. Generate missing parents
311 // http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes 311 // http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes
312 LayoutTable* table; 312 LayoutTable* table;
313 LayoutObject* afterChild = 313 LayoutObject* afterChild =
314 beforeChild ? beforeChild->previousSibling() : children->lastChild(); 314 beforeChild ? beforeChild->previousSibling() : children->lastChild();
(...skipping 26 matching lines...) Expand all
341 // To avoid the problem altogether, detect early if we're inside a hidden SVG 341 // To avoid the problem altogether, detect early if we're inside a hidden SVG
342 // subtree and stop creating layers at all for these cases - they're not used 342 // subtree and stop creating layers at all for these cases - they're not used
343 // anyways. 343 // anyways.
344 if (newChild->hasLayer() && !layerCreationAllowedForSubtree()) 344 if (newChild->hasLayer() && !layerCreationAllowedForSubtree())
345 toLayoutBoxModelObject(newChild) 345 toLayoutBoxModelObject(newChild)
346 ->layer() 346 ->layer()
347 ->removeOnlyThisLayerAfterStyleChange(); 347 ->removeOnlyThisLayerAfterStyleChange();
348 } 348 }
349 349
350 void LayoutObject::removeChild(LayoutObject* oldChild) { 350 void LayoutObject::removeChild(LayoutObject* oldChild) {
351 ASSERT(isAllowedToModifyLayoutTreeStructure(document())); 351 DCHECK(isAllowedToModifyLayoutTreeStructure(document()));
352 352
353 LayoutObjectChildList* children = virtualChildren(); 353 LayoutObjectChildList* children = virtualChildren();
354 ASSERT(children); 354 DCHECK(children);
355 if (!children) 355 if (!children)
356 return; 356 return;
357 357
358 children->removeChildNode(this, oldChild); 358 children->removeChildNode(this, oldChild);
359 } 359 }
360 360
361 void LayoutObject::setDangerousOneWayParent(LayoutObject* parent) { 361 void LayoutObject::setDangerousOneWayParent(LayoutObject* parent) {
362 ASSERT(!previousSibling()); 362 DCHECK(!previousSibling());
363 ASSERT(!nextSibling()); 363 DCHECK(!nextSibling());
364 ASSERT(!parent || !m_parent); 364 DCHECK(!parent || !m_parent);
365 setParent(parent); 365 setParent(parent);
366 } 366 }
367 367
368 void LayoutObject::registerSubtreeChangeListenerOnDescendants(bool value) { 368 void LayoutObject::registerSubtreeChangeListenerOnDescendants(bool value) {
369 // If we're set to the same value then we're done as that means it's 369 // If we're set to the same value then we're done as that means it's
370 // set down the tree that way already. 370 // set down the tree that way already.
371 if (m_bitfields.subtreeChangeListenerRegistered() == value) 371 if (m_bitfields.subtreeChangeListenerRegistered() == value)
372 return; 372 return;
373 373
374 m_bitfields.setSubtreeChangeListenerRegistered(value); 374 m_bitfields.setSubtreeChangeListenerRegistered(value);
(...skipping 20 matching lines...) Expand all
395 notifyAncestorsOfSubtreeChange(); 395 notifyAncestorsOfSubtreeChange();
396 396
397 // We can modify the layout tree during layout which means that we may 397 // We can modify the layout tree during layout which means that we may
398 // try to schedule this during performLayout. This should no longer 398 // try to schedule this during performLayout. This should no longer
399 // happen when crbug.com/370457 is fixed. 399 // happen when crbug.com/370457 is fixed.
400 DeprecatedScheduleStyleRecalcDuringLayout marker(document().lifecycle()); 400 DeprecatedScheduleStyleRecalcDuringLayout marker(document().lifecycle());
401 document().scheduleLayoutTreeUpdateIfNeeded(); 401 document().scheduleLayoutTreeUpdateIfNeeded();
402 } 402 }
403 403
404 void LayoutObject::handleSubtreeModifications() { 404 void LayoutObject::handleSubtreeModifications() {
405 ASSERT(wasNotifiedOfSubtreeChange()); 405 DCHECK(wasNotifiedOfSubtreeChange());
406 ASSERT(document().lifecycle().stateAllowsLayoutTreeNotifications()); 406 DCHECK(document().lifecycle().stateAllowsLayoutTreeNotifications());
407 407
408 if (consumesSubtreeChangeNotification()) 408 if (consumesSubtreeChangeNotification())
409 subtreeDidChange(); 409 subtreeDidChange();
410 410
411 m_bitfields.setNotifiedOfSubtreeChange(false); 411 m_bitfields.setNotifiedOfSubtreeChange(false);
412 412
413 for (LayoutObject* object = slowFirstChild(); object; 413 for (LayoutObject* object = slowFirstChild(); object;
414 object = object->nextSibling()) { 414 object = object->nextSibling()) {
415 if (!object->wasNotifiedOfSubtreeChange()) 415 if (!object->wasNotifiedOfSubtreeChange())
416 continue; 416 continue;
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 for (LayoutObject* curr = slowFirstChild(); curr; curr = curr->nextSibling()) 549 for (LayoutObject* curr = slowFirstChild(); curr; curr = curr->nextSibling())
550 curr->removeLayers(parentLayer); 550 curr->removeLayers(parentLayer);
551 } 551 }
552 552
553 void LayoutObject::moveLayers(PaintLayer* oldParent, PaintLayer* newParent) { 553 void LayoutObject::moveLayers(PaintLayer* oldParent, PaintLayer* newParent) {
554 if (!newParent) 554 if (!newParent)
555 return; 555 return;
556 556
557 if (hasLayer()) { 557 if (hasLayer()) {
558 PaintLayer* layer = toLayoutBoxModelObject(this)->layer(); 558 PaintLayer* layer = toLayoutBoxModelObject(this)->layer();
559 ASSERT(oldParent == layer->parent()); 559 DCHECK_EQ(oldParent, layer->parent());
560 if (oldParent) 560 if (oldParent)
561 oldParent->removeChild(layer); 561 oldParent->removeChild(layer);
562 newParent->addChild(layer); 562 newParent->addChild(layer);
563 return; 563 return;
564 } 564 }
565 565
566 for (LayoutObject* curr = slowFirstChild(); curr; curr = curr->nextSibling()) 566 for (LayoutObject* curr = slowFirstChild(); curr; curr = curr->nextSibling())
567 curr->moveLayers(oldParent, newParent); 567 curr->moveLayers(oldParent, newParent);
568 } 568 }
569 569
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 686
687 LayoutBox* ancestorBox = toLayoutBox(ancestor); 687 LayoutBox* ancestorBox = toLayoutBox(ancestor);
688 if (ancestorBox->canBeScrolledAndHasScrollableArea()) 688 if (ancestorBox->canBeScrolledAndHasScrollableArea())
689 return ancestorBox; 689 return ancestorBox;
690 } 690 }
691 691
692 return nullptr; 692 return nullptr;
693 } 693 }
694 694
695 LayoutFlowThread* LayoutObject::locateFlowThreadContainingBlock() const { 695 LayoutFlowThread* LayoutObject::locateFlowThreadContainingBlock() const {
696 ASSERT(isInsideFlowThread()); 696 DCHECK(isInsideFlowThread());
697 697
698 // See if we have the thread cached because we're in the middle of layout. 698 // See if we have the thread cached because we're in the middle of layout.
699 if (LayoutState* layoutState = view()->layoutState()) { 699 if (LayoutState* layoutState = view()->layoutState()) {
700 // TODO(mstensho): We should really just return whatever 700 // TODO(mstensho): We should really just return whatever
701 // layoutState->flowThread() returns here, also if the value is nullptr. 701 // layoutState->flowThread() returns here, also if the value is nullptr.
702 if (LayoutFlowThread* flowThread = layoutState->flowThread()) 702 if (LayoutFlowThread* flowThread = layoutState->flowThread())
703 return flowThread; 703 return flowThread;
704 } 704 }
705 705
706 // Not in the middle of layout so have to find the thread the slow way. 706 // Not in the middle of layout so have to find the thread the slow way.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
765 return false; 765 return false;
766 766
767 return true; 767 return true;
768 } 768 }
769 769
770 void LayoutObject::markContainerChainForLayout(bool scheduleRelayout, 770 void LayoutObject::markContainerChainForLayout(bool scheduleRelayout,
771 SubtreeLayoutScope* layouter) { 771 SubtreeLayoutScope* layouter) {
772 #if DCHECK_IS_ON() 772 #if DCHECK_IS_ON()
773 DCHECK(!isSetNeedsLayoutForbidden()); 773 DCHECK(!isSetNeedsLayoutForbidden());
774 #endif 774 #endif
775 ASSERT(!layouter || this != layouter->root()); 775 DCHECK(!layouter || this != layouter->root());
776 // When we're in layout, we're marking a descendant as needing layout with 776 // When we're in layout, we're marking a descendant as needing layout with
777 // the intention of visiting it during this layout. We shouldn't be 777 // the intention of visiting it during this layout. We shouldn't be
778 // scheduling it to be laid out later. Also, scheduleRelayout() must not be 778 // scheduling it to be laid out later. Also, scheduleRelayout() must not be
779 // called while iterating FrameView::m_layoutSubtreeRootList. 779 // called while iterating FrameView::m_layoutSubtreeRootList.
780 scheduleRelayout &= !frameView()->isInPerformLayout(); 780 scheduleRelayout &= !frameView()->isInPerformLayout();
781 781
782 LayoutObject* object = container(); 782 LayoutObject* object = container();
783 LayoutObject* last = this; 783 LayoutObject* last = this;
784 784
785 bool simplifiedNormalFlowLayout = needsSimplifiedNormalFlowLayout() && 785 bool simplifiedNormalFlowLayout = needsSimplifiedNormalFlowLayout() &&
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
826 break; 826 break;
827 object = container; 827 object = container;
828 } 828 }
829 829
830 if (scheduleRelayout) 830 if (scheduleRelayout)
831 last->scheduleRelayout(); 831 last->scheduleRelayout();
832 } 832 }
833 833
834 #if DCHECK_IS_ON() 834 #if DCHECK_IS_ON()
835 void LayoutObject::checkBlockPositionedObjectsNeedLayout() { 835 void LayoutObject::checkBlockPositionedObjectsNeedLayout() {
836 ASSERT(!needsLayout()); 836 DCHECK(!needsLayout());
837 837
838 if (isLayoutBlock()) 838 if (isLayoutBlock())
839 toLayoutBlock(this)->checkPositionedObjectsNeedLayout(); 839 toLayoutBlock(this)->checkPositionedObjectsNeedLayout();
840 } 840 }
841 #endif 841 #endif
842 842
843 void LayoutObject::setPreferredLogicalWidthsDirty(MarkingBehavior markParents) { 843 void LayoutObject::setPreferredLogicalWidthsDirty(MarkingBehavior markParents) {
844 m_bitfields.setPreferredLogicalWidthsDirty(true); 844 m_bitfields.setPreferredLogicalWidthsDirty(true);
845 if (markParents == MarkContainerChain && 845 if (markParents == MarkContainerChain &&
846 (isText() || !style()->hasOutOfFlowPosition())) 846 (isText() || !style()->hasOutOfFlowPosition()))
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 AncestorSkipInfo* skipInfo) const { 890 AncestorSkipInfo* skipInfo) const {
891 DCHECK(!isText()); 891 DCHECK(!isText());
892 892
893 LayoutObject* object = parent(); 893 LayoutObject* object = parent();
894 for (; object && !object->canContainFixedPositionObjects(); 894 for (; object && !object->canContainFixedPositionObjects();
895 object = object->parent()) { 895 object = object->parent()) {
896 if (skipInfo) 896 if (skipInfo)
897 skipInfo->update(*object); 897 skipInfo->update(*object);
898 } 898 }
899 899
900 ASSERT(!object || !object->isAnonymousBlock()); 900 DCHECK(!object || !object->isAnonymousBlock());
901 return toLayoutBlock(object); 901 return toLayoutBlock(object);
902 } 902 }
903 903
904 LayoutBlock* LayoutObject::containingBlockForAbsolutePosition( 904 LayoutBlock* LayoutObject::containingBlockForAbsolutePosition(
905 AncestorSkipInfo* skipInfo) const { 905 AncestorSkipInfo* skipInfo) const {
906 LayoutObject* object = containerForAbsolutePosition(skipInfo); 906 LayoutObject* object = containerForAbsolutePosition(skipInfo);
907 907
908 // For relpositioned inlines, we return the nearest non-anonymous enclosing 908 // For relpositioned inlines, we return the nearest non-anonymous enclosing
909 // block. We don't try to return the inline itself. This allows us to avoid 909 // block. We don't try to return the inline itself. This allows us to avoid
910 // having a positioned objects list in all LayoutInlines and lets us return a 910 // having a positioned objects list in all LayoutInlines and lets us return a
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
1185 1185
1186 LayoutRect LayoutObject::selectionRectInViewCoordinates() const { 1186 LayoutRect LayoutObject::selectionRectInViewCoordinates() const {
1187 LayoutRect selectionRect = localSelectionRect(); 1187 LayoutRect selectionRect = localSelectionRect();
1188 if (!selectionRect.isEmpty()) 1188 if (!selectionRect.isEmpty())
1189 mapToVisualRectInAncestorSpace(view(), selectionRect); 1189 mapToVisualRectInAncestorSpace(view(), selectionRect);
1190 return selectionRect; 1190 return selectionRect;
1191 } 1191 }
1192 1192
1193 PaintInvalidationReason LayoutObject::invalidatePaintIfNeeded( 1193 PaintInvalidationReason LayoutObject::invalidatePaintIfNeeded(
1194 const PaintInvalidationState& paintInvalidationState) { 1194 const PaintInvalidationState& paintInvalidationState) {
1195 DCHECK(&paintInvalidationState.currentObject() == this); 1195 DCHECK_EQ(&paintInvalidationState.currentObject(), this);
1196 1196
1197 if (styleRef().hasOutline()) { 1197 if (styleRef().hasOutline()) {
1198 PaintLayer& layer = paintInvalidationState.paintingLayer(); 1198 PaintLayer& layer = paintInvalidationState.paintingLayer();
1199 if (&layer.layoutObject() != this) 1199 if (&layer.layoutObject() != this)
1200 layer.setNeedsPaintPhaseDescendantOutlines(); 1200 layer.setNeedsPaintPhaseDescendantOutlines();
1201 } 1201 }
1202 1202
1203 LayoutView* v = view(); 1203 LayoutView* v = view();
1204 if (v->document().printing()) 1204 if (v->document().printing())
1205 return PaintInvalidationNone; // Don't invalidate paints if we're printing. 1205 return PaintInvalidationNone; // Don't invalidate paints if we're printing.
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
1557 bool requiresLayer = 1557 bool requiresLayer =
1558 toLayoutBoxModelObject(this)->layerTypeRequired() != NoPaintLayer; 1558 toLayoutBoxModelObject(this)->layerTypeRequired() != NoPaintLayer;
1559 if (hasLayer() != requiresLayer) 1559 if (hasLayer() != requiresLayer)
1560 diff.setNeedsFullLayout(); 1560 diff.setNeedsFullLayout();
1561 } 1561 }
1562 1562
1563 return diff; 1563 return diff;
1564 } 1564 }
1565 1565
1566 void LayoutObject::setPseudoStyle(PassRefPtr<ComputedStyle> pseudoStyle) { 1566 void LayoutObject::setPseudoStyle(PassRefPtr<ComputedStyle> pseudoStyle) {
1567 ASSERT(pseudoStyle->styleType() == PseudoIdBefore || 1567 DCHECK(pseudoStyle->styleType() == PseudoIdBefore ||
1568 pseudoStyle->styleType() == PseudoIdAfter || 1568 pseudoStyle->styleType() == PseudoIdAfter ||
1569 pseudoStyle->styleType() == PseudoIdFirstLetter); 1569 pseudoStyle->styleType() == PseudoIdFirstLetter);
1570 1570
1571 // FIXME: We should consider just making all pseudo items use an inherited 1571 // FIXME: We should consider just making all pseudo items use an inherited
1572 // style. 1572 // style.
1573 1573
1574 // Images are special and must inherit the pseudoStyle so the width and height 1574 // Images are special and must inherit the pseudoStyle so the width and height
1575 // of the pseudo element doesn't change the size of the image. In all other 1575 // of the pseudo element doesn't change the size of the image. In all other
1576 // cases we can just share the style. 1576 // cases we can just share the style.
1577 // 1577 //
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1636 1636
1637 void LayoutObject::setNeedsOverflowRecalcAfterStyleChange() { 1637 void LayoutObject::setNeedsOverflowRecalcAfterStyleChange() {
1638 bool neededRecalc = needsOverflowRecalcAfterStyleChange(); 1638 bool neededRecalc = needsOverflowRecalcAfterStyleChange();
1639 setSelfNeedsOverflowRecalcAfterStyleChange(); 1639 setSelfNeedsOverflowRecalcAfterStyleChange();
1640 if (!neededRecalc) 1640 if (!neededRecalc)
1641 markAncestorsForOverflowRecalcIfNeeded(); 1641 markAncestorsForOverflowRecalcIfNeeded();
1642 } 1642 }
1643 1643
1644 DISABLE_CFI_PERF 1644 DISABLE_CFI_PERF
1645 void LayoutObject::setStyle(PassRefPtr<ComputedStyle> style) { 1645 void LayoutObject::setStyle(PassRefPtr<ComputedStyle> style) {
1646 ASSERT(style); 1646 DCHECK(style);
1647 1647
1648 if (m_style == style) { 1648 if (m_style == style) {
1649 // We need to run through adjustStyleDifference() for iframes, plugins, and 1649 // We need to run through adjustStyleDifference() for iframes, plugins, and
1650 // canvas so style sharing is disabled for them. That should ensure that we 1650 // canvas so style sharing is disabled for them. That should ensure that we
1651 // never hit this code path. 1651 // never hit this code path.
1652 ASSERT(!isLayoutIFrame() && !isEmbeddedObject() && !isCanvas()); 1652 DCHECK(!isLayoutIFrame());
1653 DCHECK(!isEmbeddedObject());
1654 DCHECK(!isCanvas());
1653 return; 1655 return;
1654 } 1656 }
1655 1657
1656 StyleDifference diff; 1658 StyleDifference diff;
1657 if (m_style) 1659 if (m_style)
1658 diff = m_style->visualInvalidationDiff(*style); 1660 diff = m_style->visualInvalidationDiff(*style);
1659 1661
1660 diff = adjustStyleDifference(diff); 1662 diff = adjustStyleDifference(diff);
1661 1663
1662 styleWillChange(diff, *style); 1664 styleWillChange(diff, *style);
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
1843 if (!node()) 1845 if (!node())
1844 return; 1846 return;
1845 if (!node()->isElementNode()) 1847 if (!node()->isElementNode())
1846 return; 1848 return;
1847 if (ElementAnimations* animations = toElement(node())->elementAnimations()) 1849 if (ElementAnimations* animations = toElement(node())->elementAnimations())
1848 animations->clearBaseComputedStyle(); 1850 animations->clearBaseComputedStyle();
1849 } 1851 }
1850 1852
1851 static bool areNonIdenticalCursorListsEqual(const ComputedStyle* a, 1853 static bool areNonIdenticalCursorListsEqual(const ComputedStyle* a,
1852 const ComputedStyle* b) { 1854 const ComputedStyle* b) {
1853 ASSERT(a->cursors() != b->cursors()); 1855 DCHECK_NE(a->cursors(), b->cursors());
1854 return a->cursors() && b->cursors() && *a->cursors() == *b->cursors(); 1856 return a->cursors() && b->cursors() && *a->cursors() == *b->cursors();
1855 } 1857 }
1856 1858
1857 static inline bool areCursorsEqual(const ComputedStyle* a, 1859 static inline bool areCursorsEqual(const ComputedStyle* a,
1858 const ComputedStyle* b) { 1860 const ComputedStyle* b) {
1859 return a->cursor() == b->cursor() && (a->cursors() == b->cursors() || 1861 return a->cursor() == b->cursor() && (a->cursors() == b->cursors() ||
1860 areNonIdenticalCursorListsEqual(a, b)); 1862 areNonIdenticalCursorListsEqual(a, b));
1861 } 1863 }
1862 1864
1863 void LayoutObject::setScrollAnchorDisablingStyleChangedOnAncestor() { 1865 void LayoutObject::setScrollAnchorDisablingStyleChangedOnAncestor() {
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after
2292 transform.makeIdentity(); 2294 transform.makeIdentity();
2293 transform.translate(offsetInContainer.width().toFloat(), 2295 transform.translate(offsetInContainer.width().toFloat(),
2294 offsetInContainer.height().toFloat()); 2296 offsetInContainer.height().toFloat());
2295 PaintLayer* layer = hasLayer() ? toLayoutBoxModelObject(this)->layer() : 0; 2297 PaintLayer* layer = hasLayer() ? toLayoutBoxModelObject(this)->layer() : 0;
2296 if (layer && layer->transform()) 2298 if (layer && layer->transform())
2297 transform.multiply(layer->currentTransform()); 2299 transform.multiply(layer->currentTransform());
2298 2300
2299 if (containerObject && containerObject->hasLayer() && 2301 if (containerObject && containerObject->hasLayer() &&
2300 containerObject->style()->hasPerspective()) { 2302 containerObject->style()->hasPerspective()) {
2301 // Perpsective on the container affects us, so we have to factor it in here. 2303 // Perpsective on the container affects us, so we have to factor it in here.
2302 ASSERT(containerObject->hasLayer()); 2304 DCHECK(containerObject->hasLayer());
2303 FloatPoint perspectiveOrigin = 2305 FloatPoint perspectiveOrigin =
2304 toLayoutBoxModelObject(containerObject)->layer()->perspectiveOrigin(); 2306 toLayoutBoxModelObject(containerObject)->layer()->perspectiveOrigin();
2305 2307
2306 TransformationMatrix perspectiveMatrix; 2308 TransformationMatrix perspectiveMatrix;
2307 perspectiveMatrix.applyPerspective(containerObject->style()->perspective()); 2309 perspectiveMatrix.applyPerspective(containerObject->style()->perspective());
2308 2310
2309 transform.translateRight3d(-perspectiveOrigin.x(), -perspectiveOrigin.y(), 2311 transform.translateRight3d(-perspectiveOrigin.x(), -perspectiveOrigin.y(),
2310 0); 2312 0);
2311 transform = perspectiveMatrix * transform; 2313 transform = perspectiveMatrix * transform;
2312 transform.translateRight3d(perspectiveOrigin.x(), perspectiveOrigin.y(), 0); 2314 transform.translateRight3d(perspectiveOrigin.x(), perspectiveOrigin.y(), 0);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
2381 TransformationMatrix LayoutObject::localToAncestorTransform( 2383 TransformationMatrix LayoutObject::localToAncestorTransform(
2382 const LayoutBoxModelObject* ancestor, 2384 const LayoutBoxModelObject* ancestor,
2383 MapCoordinatesFlags mode) const { 2385 MapCoordinatesFlags mode) const {
2384 TransformState transformState(TransformState::ApplyTransformDirection); 2386 TransformState transformState(TransformState::ApplyTransformDirection);
2385 mapLocalToAncestor(ancestor, transformState, 2387 mapLocalToAncestor(ancestor, transformState,
2386 mode | ApplyContainerFlip | UseTransforms); 2388 mode | ApplyContainerFlip | UseTransforms);
2387 return transformState.accumulatedTransform(); 2389 return transformState.accumulatedTransform();
2388 } 2390 }
2389 2391
2390 LayoutSize LayoutObject::offsetFromContainer(const LayoutObject* o) const { 2392 LayoutSize LayoutObject::offsetFromContainer(const LayoutObject* o) const {
2391 ASSERT(o == container()); 2393 DCHECK_EQ(o, container());
2392 return o->hasOverflowClip() 2394 return o->hasOverflowClip()
2393 ? LayoutSize(-toLayoutBox(o)->scrolledContentOffset()) 2395 ? LayoutSize(-toLayoutBox(o)->scrolledContentOffset())
2394 : LayoutSize(); 2396 : LayoutSize();
2395 } 2397 }
2396 2398
2397 LayoutSize LayoutObject::offsetFromAncestorContainer( 2399 LayoutSize LayoutObject::offsetFromAncestorContainer(
2398 const LayoutObject* ancestorContainer) const { 2400 const LayoutObject* ancestorContainer) const {
2399 if (ancestorContainer == this) 2401 if (ancestorContainer == this)
2400 return LayoutSize(); 2402 return LayoutSize();
2401 2403
2402 LayoutSize offset; 2404 LayoutSize offset;
2403 LayoutPoint referencePoint; 2405 LayoutPoint referencePoint;
2404 const LayoutObject* currContainer = this; 2406 const LayoutObject* currContainer = this;
2405 do { 2407 do {
2406 const LayoutObject* nextContainer = currContainer->container(); 2408 const LayoutObject* nextContainer = currContainer->container();
2407 // This means we reached the top without finding container. 2409 // This means we reached the top without finding container.
2408 DCHECK(nextContainer); 2410 DCHECK(nextContainer);
2409 if (!nextContainer) 2411 if (!nextContainer)
2410 break; 2412 break;
2411 ASSERT(!currContainer->hasTransformRelatedProperty()); 2413 DCHECK(!currContainer->hasTransformRelatedProperty());
2412 LayoutSize currentOffset = 2414 LayoutSize currentOffset =
2413 currContainer->offsetFromContainer(nextContainer); 2415 currContainer->offsetFromContainer(nextContainer);
2414 offset += currentOffset; 2416 offset += currentOffset;
2415 referencePoint.move(currentOffset); 2417 referencePoint.move(currentOffset);
2416 currContainer = nextContainer; 2418 currContainer = nextContainer;
2417 } while (currContainer != ancestorContainer); 2419 } while (currContainer != ancestorContainer);
2418 2420
2419 return offset; 2421 return offset;
2420 } 2422 }
2421 2423
(...skipping 29 matching lines...) Expand all
2451 } 2453 }
2452 2454
2453 this->addLayerHitTestRects(layerRects, currentLayer, layerOffset, 2455 this->addLayerHitTestRects(layerRects, currentLayer, layerOffset,
2454 LayoutRect()); 2456 LayoutRect());
2455 } 2457 }
2456 2458
2457 void LayoutObject::addLayerHitTestRects(LayerHitTestRects& layerRects, 2459 void LayoutObject::addLayerHitTestRects(LayerHitTestRects& layerRects,
2458 const PaintLayer* currentLayer, 2460 const PaintLayer* currentLayer,
2459 const LayoutPoint& layerOffset, 2461 const LayoutPoint& layerOffset,
2460 const LayoutRect& containerRect) const { 2462 const LayoutRect& containerRect) const {
2461 ASSERT(currentLayer); 2463 DCHECK(currentLayer);
2462 ASSERT(currentLayer == this->enclosingLayer()); 2464 DCHECK_EQ(currentLayer, this->enclosingLayer());
2463 2465
2464 // Compute the rects for this layoutObject only and add them to the results. 2466 // Compute the rects for this layoutObject only and add them to the results.
2465 // Note that we could avoid passing the offset and instead adjust each result, 2467 // Note that we could avoid passing the offset and instead adjust each result,
2466 // but this seems slightly simpler. 2468 // but this seems slightly simpler.
2467 Vector<LayoutRect> ownRects; 2469 Vector<LayoutRect> ownRects;
2468 LayoutRect newContainerRect; 2470 LayoutRect newContainerRect;
2469 computeSelfHitTestRects(ownRects, layerOffset); 2471 computeSelfHitTestRects(ownRects, layerOffset);
2470 2472
2471 // When we get to have a lot of rects on a layer, the performance cost of 2473 // When we get to have a lot of rects on a layer, the performance cost of
2472 // tracking those rects outweighs the benefit of doing compositor thread hit 2474 // tracking those rects outweighs the benefit of doing compositor thread hit
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
2687 removeShapeImageClient(m_style->shapeOutside()); 2689 removeShapeImageClient(m_style->shapeOutside());
2688 removeCursorImageClient(m_style->cursors()); 2690 removeCursorImageClient(m_style->cursors());
2689 } 2691 }
2690 2692
2691 if (frameView()) 2693 if (frameView())
2692 setIsBackgroundAttachmentFixedObject(false); 2694 setIsBackgroundAttachmentFixedObject(false);
2693 } 2695 }
2694 2696
2695 DISABLE_CFI_PERF 2697 DISABLE_CFI_PERF
2696 void LayoutObject::insertedIntoTree() { 2698 void LayoutObject::insertedIntoTree() {
2697 // FIXME: We should ASSERT(isRooted()) here but generated content makes some 2699 // FIXME: We should DCHECK(isRooted()) here but generated content makes some
2698 // out-of-order insertion. 2700 // out-of-order insertion.
2699 2701
2700 // Keep our layer hierarchy updated. Optimize for the common case where we 2702 // Keep our layer hierarchy updated. Optimize for the common case where we
2701 // don't have any children and don't have a layer attached to ourselves. 2703 // don't have any children and don't have a layer attached to ourselves.
2702 PaintLayer* layer = nullptr; 2704 PaintLayer* layer = nullptr;
2703 if (slowFirstChild() || hasLayer()) { 2705 if (slowFirstChild() || hasLayer()) {
2704 layer = parent()->enclosingLayer(); 2706 layer = parent()->enclosingLayer();
2705 addLayers(layer); 2707 addLayers(layer);
2706 } 2708 }
2707 2709
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2754 if (anchor->refersTo(layoutObject)) { 2756 if (anchor->refersTo(layoutObject)) {
2755 found = true; 2757 found = true;
2756 if (behavior == Clear) 2758 if (behavior == Clear)
2757 anchor->notifyRemoved(layoutObject); 2759 anchor->notifyRemoved(layoutObject);
2758 } 2760 }
2759 } 2761 }
2760 return found; 2762 return found;
2761 } 2763 }
2762 2764
2763 void LayoutObject::willBeRemovedFromTree() { 2765 void LayoutObject::willBeRemovedFromTree() {
2764 // FIXME: We should ASSERT(isRooted()) but we have some out-of-order removals 2766 // FIXME: We should DCHECK(isRooted()) but we have some out-of-order removals
2765 // which would need to be fixed first. 2767 // which would need to be fixed first.
2766 2768
2767 // If we remove a visible child from an invisible parent, we don't know the 2769 // If we remove a visible child from an invisible parent, we don't know the
2768 // layer visibility any more. 2770 // layer visibility any more.
2769 PaintLayer* layer = nullptr; 2771 PaintLayer* layer = nullptr;
2770 if (parent()->style()->visibility() != EVisibility::kVisible && 2772 if (parent()->style()->visibility() != EVisibility::kVisible &&
2771 style()->visibility() == EVisibility::kVisible && !hasLayer()) { 2773 style()->visibility() == EVisibility::kVisible && !hasLayer()) {
2772 layer = parent()->enclosingLayer(); 2774 layer = parent()->enclosingLayer();
2773 if (layer) 2775 if (layer)
2774 layer->dirtyVisibleContentStatus(); 2776 layer->dirtyVisibleContentStatus();
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
3056 PseudoStyleRequest(PseudoIdFirstLineInherited), parentStyle); 3058 PseudoStyleRequest(PseudoIdFirstLineInherited), parentStyle);
3057 } 3059 }
3058 } 3060 }
3059 return nullptr; 3061 return nullptr;
3060 } 3062 }
3061 3063
3062 PassRefPtr<ComputedStyle> LayoutObject::uncachedFirstLineStyle() const { 3064 PassRefPtr<ComputedStyle> LayoutObject::uncachedFirstLineStyle() const {
3063 if (!document().styleEngine().usesFirstLineRules()) 3065 if (!document().styleEngine().usesFirstLineRules())
3064 return nullptr; 3066 return nullptr;
3065 3067
3066 ASSERT(!isText()); 3068 DCHECK(!isText());
3067 3069
3068 return firstLineStyleForCachedUncachedType(Uncached, this, m_style.get()); 3070 return firstLineStyleForCachedUncachedType(Uncached, this, m_style.get());
3069 } 3071 }
3070 3072
3071 ComputedStyle* LayoutObject::cachedFirstLineStyle() const { 3073 ComputedStyle* LayoutObject::cachedFirstLineStyle() const {
3072 ASSERT(document().styleEngine().usesFirstLineRules()); 3074 DCHECK(document().styleEngine().usesFirstLineRules());
3073 3075
3074 if (RefPtr<ComputedStyle> style = firstLineStyleForCachedUncachedType( 3076 if (RefPtr<ComputedStyle> style = firstLineStyleForCachedUncachedType(
3075 Cached, isText() ? parent() : this, m_style.get())) 3077 Cached, isText() ? parent() : this, m_style.get()))
3076 return style.get(); 3078 return style.get();
3077 3079
3078 return m_style.get(); 3080 return m_style.get();
3079 } 3081 }
3080 3082
3081 ComputedStyle* LayoutObject::getCachedPseudoStyle( 3083 ComputedStyle* LayoutObject::getCachedPseudoStyle(
3082 PseudoId pseudo, 3084 PseudoId pseudo,
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
3196 3198
3197 bool LayoutObject::isInert() const { 3199 bool LayoutObject::isInert() const {
3198 const LayoutObject* layoutObject = this; 3200 const LayoutObject* layoutObject = this;
3199 while (!layoutObject->node()) 3201 while (!layoutObject->node())
3200 layoutObject = layoutObject->parent(); 3202 layoutObject = layoutObject->parent();
3201 return layoutObject->node()->isInert(); 3203 return layoutObject->node()->isInert();
3202 } 3204 }
3203 3205
3204 void LayoutObject::imageChanged(ImageResourceContent* image, 3206 void LayoutObject::imageChanged(ImageResourceContent* image,
3205 const IntRect* rect) { 3207 const IntRect* rect) {
3206 ASSERT(m_node); 3208 DCHECK(m_node);
3207 3209
3208 // Image change notifications should not be received during paint because 3210 // Image change notifications should not be received during paint because
3209 // the resulting invalidations will be cleared following paint. This can also 3211 // the resulting invalidations will be cleared following paint. This can also
3210 // lead to modifying the tree out from under paint(), see: crbug.com/616700. 3212 // lead to modifying the tree out from under paint(), see: crbug.com/616700.
3211 DCHECK(document().lifecycle().state() != 3213 DCHECK_NE(document().lifecycle().state(),
3212 DocumentLifecycle::LifecycleState::InPaint); 3214 DocumentLifecycle::LifecycleState::InPaint);
3213 3215
3214 imageChanged(static_cast<WrappedImagePtr>(image), rect); 3216 imageChanged(static_cast<WrappedImagePtr>(image), rect);
3215 } 3217 }
3216 3218
3217 Element* LayoutObject::offsetParent(const Element* base) const { 3219 Element* LayoutObject::offsetParent(const Element* base) const {
3218 if (isDocumentElement() || isBody()) 3220 if (isDocumentElement() || isBody())
3219 return nullptr; 3221 return nullptr;
3220 3222
3221 if (isFixedPositioned()) 3223 if (isFixedPositioned())
3222 return nullptr; 3224 return nullptr;
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
3325 3327
3326 PositionWithAffinity LayoutObject::createPositionWithAffinity(int offset) { 3328 PositionWithAffinity LayoutObject::createPositionWithAffinity(int offset) {
3327 return createPositionWithAffinity(offset, TextAffinity::Downstream); 3329 return createPositionWithAffinity(offset, TextAffinity::Downstream);
3328 } 3330 }
3329 3331
3330 PositionWithAffinity LayoutObject::createPositionWithAffinity( 3332 PositionWithAffinity LayoutObject::createPositionWithAffinity(
3331 const Position& position) { 3333 const Position& position) {
3332 if (position.isNotNull()) 3334 if (position.isNotNull())
3333 return PositionWithAffinity(position); 3335 return PositionWithAffinity(position);
3334 3336
3335 ASSERT(!node()); 3337 DCHECK(!node());
3336 return createPositionWithAffinity(0); 3338 return createPositionWithAffinity(0);
3337 } 3339 }
3338 3340
3339 CursorDirective LayoutObject::getCursor(const LayoutPoint&, Cursor&) const { 3341 CursorDirective LayoutObject::getCursor(const LayoutPoint&, Cursor&) const {
3340 return SetCursorBasedOnStyle; 3342 return SetCursorBasedOnStyle;
3341 } 3343 }
3342 3344
3343 bool LayoutObject::canUpdateSelectionOnRootLineBoxes() const { 3345 bool LayoutObject::canUpdateSelectionOnRootLineBoxes() const {
3344 if (needsLayout()) 3346 if (needsLayout())
3345 return false; 3347 return false;
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
3535 void LayoutObject:: 3537 void LayoutObject::
3536 setShouldDoFullPaintInvalidationIncludingNonCompositingDescendants() { 3538 setShouldDoFullPaintInvalidationIncludingNonCompositingDescendants() {
3537 // Clear first because PaintInvalidationSubtree overrides other full paint 3539 // Clear first because PaintInvalidationSubtree overrides other full paint
3538 // invalidation reasons. 3540 // invalidation reasons.
3539 clearShouldDoFullPaintInvalidation(); 3541 clearShouldDoFullPaintInvalidation();
3540 setShouldDoFullPaintInvalidation(PaintInvalidationSubtree); 3542 setShouldDoFullPaintInvalidation(PaintInvalidationSubtree);
3541 } 3543 }
3542 3544
3543 void LayoutObject::setIsBackgroundAttachmentFixedObject( 3545 void LayoutObject::setIsBackgroundAttachmentFixedObject(
3544 bool isBackgroundAttachmentFixedObject) { 3546 bool isBackgroundAttachmentFixedObject) {
3545 ASSERT(frameView()); 3547 DCHECK(frameView());
3546 if (m_bitfields.isBackgroundAttachmentFixedObject() == 3548 if (m_bitfields.isBackgroundAttachmentFixedObject() ==
3547 isBackgroundAttachmentFixedObject) 3549 isBackgroundAttachmentFixedObject)
3548 return; 3550 return;
3549 m_bitfields.setIsBackgroundAttachmentFixedObject( 3551 m_bitfields.setIsBackgroundAttachmentFixedObject(
3550 isBackgroundAttachmentFixedObject); 3552 isBackgroundAttachmentFixedObject);
3551 if (isBackgroundAttachmentFixedObject) 3553 if (isBackgroundAttachmentFixedObject)
3552 frameView()->addBackgroundAttachmentFixedObject(this); 3554 frameView()->addBackgroundAttachmentFixedObject(this);
3553 else 3555 else
3554 frameView()->removeBackgroundAttachmentFixedObject(this); 3556 frameView()->removeBackgroundAttachmentFixedObject(this);
3555 } 3557 }
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
3674 const blink::LayoutObject* root = object1; 3676 const blink::LayoutObject* root = object1;
3675 while (root->parent()) 3677 while (root->parent())
3676 root = root->parent(); 3678 root = root->parent();
3677 root->showLayoutTreeAndMark(object1, "*", object2, "-", 0); 3679 root->showLayoutTreeAndMark(object1, "*", object2, "-", 0);
3678 } else { 3680 } else {
3679 WTFLogAlways("%s", "Cannot showLayoutTree. Root is (nil)"); 3681 WTFLogAlways("%s", "Cannot showLayoutTree. Root is (nil)");
3680 } 3682 }
3681 } 3683 }
3682 3684
3683 #endif 3685 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698