Changeset 249497 in webkit
- Timestamp:
- Sep 4, 2019 1:42:08 PM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r249494 r249497 1 2019-09-04 Zalan Bujtas <zalan@apple.com> 2 3 [LFC] Assert on FormattingContext escaping 4 https://bugs.webkit.org/show_bug.cgi?id=201464 5 <rdar://problem/55029574> 6 7 Reviewed by Antti Koivisto. 8 9 This patch asserts on accidental formatting context escaping. This is only a correctness issue at the moment, 10 since we don't support multithreaded subtree layout yet. 11 Normally we should not need to access display boxes in different formatting contexts during layout, but there are a few, justified cases when it is required. 12 13 * layout/FormattingContext.cpp: 14 (WebCore::Layout::FormattingContext::displayBoxForLayoutBox const): 15 * layout/FormattingContext.h: 16 (WebCore::Layout::FormattingContext::displayBoxForLayoutBox const): Deleted. 17 * layout/FormattingContextGeometry.cpp: 18 (WebCore::Layout::FormattingContext::Geometry::contentHeightForFormattingContextRoot const): 19 (WebCore::Layout::FormattingContext::Geometry::staticVerticalPositionForOutOfFlowPositioned const): 20 (WebCore::Layout::FormattingContext::Geometry::staticHorizontalPositionForOutOfFlowPositioned const): 21 * layout/FormattingContextQuirks.cpp: 22 (WebCore::Layout::FormattingContext::Quirks::heightValueOfNearestContainingBlockWithFixedHeight): 23 * layout/floats/FloatingContext.cpp: 24 (WebCore::Layout::FloatingContext::absoluteDisplayBoxCoordinates const): 25 (WebCore::Layout::FloatingContext::mapToFloatingStateRoot const): 26 (WebCore::Layout::FloatingContext::mapTopToFloatingStateRoot const): 27 (WebCore::Layout::FloatingContext::mapPointFromFormattingContextRootToFloatingStateRoot const): 28 * page/FrameViewLayoutContext.cpp: 29 (WebCore::layoutUsingFormattingContext): 30 1 31 2019-09-04 Zalan Bujtas <zalan@apple.com> 2 32 -
trunk/Source/WebCore/layout/FormattingContext.cpp
r249494 r249497 184 184 } 185 185 186 Display::Box& FormattingContext::displayBoxForLayoutBox(const Box& layoutBox, Optional<EscapeType> escapeType) const 187 { 188 UNUSED_PARAM(escapeType); 189 190 #ifndef NDEBUG 191 auto isOkToAccessDisplayBox = [&] { 192 // 1. Highly common case of accessing the formatting root's display box itself. This is formatting context escaping in the strict sense, since 193 // the formatting context root box lives in the parent formatting context. 194 // This happens e.g. when a block level box box needs to stretch horizontally and checks its containing block for horizontal space (this should probably be limited to reading horizontal constraint values). 195 if (&layoutBox == &root()) 196 return true; 197 198 // 2. Special case when accessing the ICB's display box 199 if (layoutBox.isInitialContainingBlock()) { 200 // There has to be a valid reason to access the ICB. 201 if (!escapeType) 202 return false; 203 return *escapeType == EscapeType::AccessParentFormattingContext || *escapeType == EscapeType::AccessAncestorFormattingContext; 204 } 205 206 // 3. Most common case of accessing box/containing block display box within the same formatting context tree. 207 if (&layoutBox.formattingContextRoot() == &root()) 208 return true; 209 210 if (!escapeType) 211 return false; 212 213 // 4. Accessing child formatting context subtree is relatively rare. It happens when e.g a shrink to fit (out-of-flow block level) box checks the content width. 214 // Checking the content width means to get display boxes from the established formatting context (we try to access display boxes in a child formatting context) 215 if (*escapeType == EscapeType::AccessChildFormattingContext && &layoutBox.formattingContextRoot().formattingContextRoot() == &root()) 216 return true; 217 218 // 5. Float box top/left values are mapped relative to the FloatState's root. Inline formatting contexts(A) inherit floats from parent 219 // block formatting contexts(B). Floats in these inline formatting contexts(A) need to be mapped to the parent, block formatting context(B). 220 if (*escapeType == EscapeType::AccessParentFormattingContext && &layoutBox.formattingContextRoot() == &root().formattingContextRoot()) 221 return true; 222 223 // 6. Finding the first containing block with fixed height quirk. See Quirks::heightValueOfNearestContainingBlockWithFixedHeight 224 if (*escapeType == EscapeType::AccessAncestorFormattingContext) { 225 auto& targetFormattingRoot = layoutBox.formattingContextRoot(); 226 auto* ancestorFormattingContextRoot = &root().formattingContextRoot(); 227 while (true) { 228 if (&targetFormattingRoot == ancestorFormattingContextRoot) 229 return true; 230 if (ancestorFormattingContextRoot->isInitialContainingBlock()) 231 return false; 232 ancestorFormattingContextRoot = &ancestorFormattingContextRoot->formattingContextRoot(); 233 } 234 235 } 236 return false; 237 }; 238 #endif 239 ASSERT(isOkToAccessDisplayBox()); 240 return layoutState().displayBoxForLayoutBox(layoutBox); 241 } 242 186 243 #ifndef NDEBUG 187 244 void FormattingContext::validateGeometryConstraintsAfterLayout() const -
trunk/Source/WebCore/layout/FormattingContext.h
r249494 r249497 70 70 bool isTableFormattingContext() const { return root().establishesTableFormattingContext(); } 71 71 72 Display::Box& displayBoxForLayoutBox(const Box& layoutBox) const { return layoutState().displayBoxForLayoutBox(layoutBox); } 72 enum class EscapeType { 73 AccessChildFormattingContext, 74 AccessParentFormattingContext, 75 AccessAncestorFormattingContext 76 }; 77 Display::Box& displayBoxForLayoutBox(const Box&, Optional<EscapeType> = WTF::nullopt) const; 73 78 bool hasDisplayBox(const Box& layoutBox) const { return layoutState().hasDisplayBox(layoutBox); } 74 79 -
trunk/Source/WebCore/layout/FormattingContextGeometry.cpp
r249357 r249497 121 121 } else if (formattingRootContainer.establishesBlockFormattingContext() || layoutBox.isDocumentBox()) { 122 122 if (formattingRootContainer.hasInFlowChild()) { 123 auto& firstDisplayBox = formattingContext.displayBoxForLayoutBox(*formattingRootContainer.firstInFlowChild() );124 auto& lastDisplayBox = formattingContext.displayBoxForLayoutBox(*formattingRootContainer.lastInFlowChild() );123 auto& firstDisplayBox = formattingContext.displayBoxForLayoutBox(*formattingRootContainer.firstInFlowChild(), EscapeType::AccessChildFormattingContext); 124 auto& lastDisplayBox = formattingContext.displayBoxForLayoutBox(*formattingRootContainer.lastInFlowChild(), EscapeType::AccessChildFormattingContext); 125 125 top = firstDisplayBox.rectWithMargin().top(); 126 126 bottom = lastDisplayBox.rectWithMargin().bottom(); … … 206 206 if (auto* previousInFlowSibling = layoutBox.previousInFlowSibling()) { 207 207 // Add sibling offset 208 auto& previousInFlowDisplayBox = formattingContext.displayBoxForLayoutBox(*previousInFlowSibling );208 auto& previousInFlowDisplayBox = formattingContext.displayBoxForLayoutBox(*previousInFlowSibling, FormattingContext::EscapeType::AccessChildFormattingContext); 209 209 top += previousInFlowDisplayBox.bottom() + previousInFlowDisplayBox.nonCollapsedMarginAfter(); 210 210 } else { 211 211 ASSERT(layoutBox.parent()); 212 top = formattingContext.displayBoxForLayoutBox(*layoutBox.parent() ).contentBoxTop();212 top = formattingContext.displayBoxForLayoutBox(*layoutBox.parent(), FormattingContext::EscapeType::AccessChildFormattingContext).contentBoxTop(); 213 213 } 214 214 … … 217 217 // Start with the parent since we pretend that this box is normal flow. 218 218 for (auto* container = layoutBox.parent(); container != &containingBlock; container = container->containingBlock()) { 219 auto& displayBox = formattingContext.displayBoxForLayoutBox(*container );219 auto& displayBox = formattingContext.displayBoxForLayoutBox(*container, FormattingContext::EscapeType::AccessChildFormattingContext); 220 220 // Display::Box::top is the border box top position in its containing block's coordinate system. 221 221 top += displayBox.top(); … … 235 235 auto& formattingContext = this->formattingContext(); 236 236 ASSERT(layoutBox.parent()); 237 auto left = formattingContext.displayBoxForLayoutBox(*layoutBox.parent() ).contentBoxLeft();237 auto left = formattingContext.displayBoxForLayoutBox(*layoutBox.parent(), FormattingContext::EscapeType::AccessChildFormattingContext).contentBoxLeft(); 238 238 239 239 // Resolve left all the way up to the containing block. … … 241 241 // Start with the parent since we pretend that this box is normal flow. 242 242 for (auto* container = layoutBox.parent(); container != &containingBlock; container = container->containingBlock()) { 243 auto& displayBox = formattingContext.displayBoxForLayoutBox(*container );243 auto& displayBox = formattingContext.displayBoxForLayoutBox(*container, FormattingContext::EscapeType::AccessChildFormattingContext); 244 244 // Display::Box::left is the border box left position in its containing block's coordinate system. 245 245 left += displayBox.left(); … … 247 247 } 248 248 // Move the static position relative to the padding box. This is very specific to abolutely positioned boxes. 249 auto paddingBoxLeft = formattingContext.displayBoxForLayoutBox(containingBlock ).paddingBoxLeft();249 auto paddingBoxLeft = formattingContext.displayBoxForLayoutBox(containingBlock, FormattingContext::EscapeType::AccessChildFormattingContext).paddingBoxLeft(); 250 250 return left - paddingBoxLeft; 251 251 } -
trunk/Source/WebCore/layout/FormattingContextQuirks.cpp
r249357 r249497 51 51 // -and it's totally insane because now we freely travel across formatting context boundaries and computed margins are nonexistent. 52 52 if (containingBlock->isBodyBox() || containingBlock->isDocumentBox()) { 53 auto& displayBox = formattingContext.displayBoxForLayoutBox(*containingBlock );53 auto& displayBox = formattingContext.displayBoxForLayoutBox(*containingBlock, FormattingContext::EscapeType::AccessAncestorFormattingContext); 54 54 55 auto usedValues = UsedHorizontalValues { formattingContext.displayBoxForLayoutBox(*containingBlock->containingBlock() ).contentBoxWidth() };55 auto usedValues = UsedHorizontalValues { formattingContext.displayBoxForLayoutBox(*containingBlock->containingBlock(), FormattingContext::EscapeType::AccessAncestorFormattingContext).contentBoxWidth() }; 56 56 auto verticalMargin = formattingContext.geometry().computedVerticalMargin(*containingBlock, usedValues); 57 57 auto verticalPadding = displayBox.paddingTop().valueOr(0) + displayBox.paddingBottom().valueOr(0); … … 63 63 } 64 64 // Initial containing block has to have a height. 65 return formattingContext.displayBoxForLayoutBox(layoutBox.initialContainingBlock() ).contentBox().height() - bodyAndDocumentVerticalMarginPaddingAndBorder;65 return formattingContext.displayBoxForLayoutBox(layoutBox.initialContainingBlock(), FormattingContext::EscapeType::AccessAncestorFormattingContext).contentBox().height() - bodyAndDocumentVerticalMarginPaddingAndBorder; 66 66 } 67 67 -
trunk/Source/WebCore/layout/floats/FloatingContext.cpp
r249494 r249497 426 426 427 427 if (&containingBlock == &floatingState().root()) { 428 auto containingBlockDisplayBox = formattingContext().displayBoxForLayoutBox(containingBlock );428 auto containingBlockDisplayBox = formattingContext().displayBoxForLayoutBox(containingBlock, FormattingContext::EscapeType::AccessParentFormattingContext); 429 429 return { displayBox, { }, { containingBlockDisplayBox.contentBoxLeft(), containingBlockDisplayBox.contentBoxRight() } }; 430 430 } … … 437 437 { 438 438 auto& floatingStateRoot = floatingState().root(); 439 auto& displayBox = formattingContext().displayBoxForLayoutBox(floatBox );439 auto& displayBox = formattingContext().displayBoxForLayoutBox(floatBox, FormattingContext::EscapeType::AccessParentFormattingContext); 440 440 auto topLeft = displayBox.topLeft(); 441 441 for (auto* containingBlock = floatBox.containingBlock(); containingBlock && containingBlock != &floatingStateRoot; containingBlock = containingBlock->containingBlock()) 442 topLeft.moveBy(formattingContext().displayBoxForLayoutBox(*containingBlock ).topLeft());442 topLeft.moveBy(formattingContext().displayBoxForLayoutBox(*containingBlock, FormattingContext::EscapeType::AccessParentFormattingContext).topLeft()); 443 443 444 444 auto mappedDisplayBox = Display::Box(displayBox); … … 450 450 { 451 451 auto& floatingStateRoot = floatingState().root(); 452 auto top = formattingContext().displayBoxForLayoutBox(floatBox ).top();452 auto top = formattingContext().displayBoxForLayoutBox(floatBox, FormattingContext::EscapeType::AccessParentFormattingContext).top(); 453 453 for (auto* container = floatBox.containingBlock(); container && container != &floatingStateRoot; container = container->containingBlock()) 454 top += formattingContext().displayBoxForLayoutBox(*container ).top();454 top += formattingContext().displayBoxForLayoutBox(*container, FormattingContext::EscapeType::AccessParentFormattingContext).top(); 455 455 return top; 456 456 } … … 464 464 auto mappedPosition = position; 465 465 for (auto* container = &from; container && container != &to; container = container->containingBlock()) 466 mappedPosition.moveBy(formattingContext().displayBoxForLayoutBox(*container ).topLeft());466 mappedPosition.moveBy(formattingContext().displayBoxForLayoutBox(*container, FormattingContext::EscapeType::AccessParentFormattingContext).topLeft()); 467 467 return mappedPosition; 468 468 }
Note: See TracChangeset
for help on using the changeset viewer.