Skip to content

Commit 52f0f0c

Browse files
joevilchesfacebook-github-bot
authored andcommitted
[skip ci] Support transforms forming containing blocks (facebook#42191)
Summary: X-link: facebook/yoga#1539 React native supports transforms and if a node has a transform it will [form a containing block for absolute descendants regardless of position type](https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block). So we need to pass that information into Yoga to ensure this happens. The verbiage for the field "alwaysFormsContainingBlock" is very specific. In a vacuum a node cannot simply "form a containing block". It only forms a containing block in reference to a different node. This can be illustrated in a scenario where we have a static node that is a flex container which has 1 absolute child and 1 relative child. This static node will form a containing block for the relative child but not the absolute one. We could just pass the information on rather something has a transform or not but Yoga is not supposed to know about transforms in general. As a result we have a notion of "always" forming a containing block. Since Yoga is a flexbox spec, non-absolute nodes' containing blocks will ways be their parent. If we add something like a transform to a node then that will also apply to absolute nodes - hence we can say the node will **always** form a CB, no matter who is the descendant. Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D52521160
1 parent 3adb629 commit 52f0f0c

File tree

6 files changed

+35
-2
lines changed

6 files changed

+35
-2
lines changed

packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,11 @@ void YogaLayoutableShadowNode::updateYogaProps() {
383383
}
384384

385385
yogaNode_.setStyle(styleResult);
386+
if (getTraits().check(ShadowNodeTraits::ViewKind)) {
387+
auto& viewProps = static_cast<const ViewProps&>(*props_);
388+
YGNodeSetAlwaysFormsContainingBlock(
389+
&yogaNode_, viewProps.transform != Transform::Identity());
390+
}
386391
}
387392

388393
/*static*/ yoga::Style YogaLayoutableShadowNode::applyAliasedProps(

packages/react-native/ReactCommon/yoga/yoga/YGNode.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,12 @@ void YGNodeSetPrintFunc(YGNodeRef node, YGPrintFunc printFunc) {
328328
resolveRef(node)->setPrintFunc(printFunc);
329329
}
330330

331+
void YGNodeSetAlwaysFormsContainingBlock(
332+
YGNodeRef node,
333+
bool alwaysFormsContainingBlock) {
334+
resolveRef(node)->setAlwaysFormsContainingBlock(alwaysFormsContainingBlock);
335+
}
336+
331337
#ifdef DEBUG
332338
void YGNodePrint(const YGNodeConstRef node, const YGPrintOptions options) {
333339
yoga::print(resolveRef(node), scopedEnum(options));

packages/react-native/ReactCommon/yoga/yoga/YGNode.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,17 @@ typedef void (*YGPrintFunc)(YGNodeConstRef node);
270270
*/
271271
YG_EXPORT void YGNodeSetPrintFunc(YGNodeRef node, YGPrintFunc printFunc);
272272

273+
/**
274+
* Make it so that this node will always form a containing block for any
275+
* descendant nodes. This is useful for when a node has a property outside of
276+
* of Yoga that will form a containing block. For example, transforms or some of
277+
* the others listed in
278+
* https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block
279+
*/
280+
YG_EXPORT void YGNodeSetAlwaysFormsContainingBlock(
281+
YGNodeRef node,
282+
bool alwaysFormsContainingBlock);
283+
273284
/**
274285
* Print a node to log output.
275286
*/

packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,9 @@ void layoutAbsoluteDescendants(
528528
if (needsTrailingPosition(crossAxis)) {
529529
setChildTrailingPosition(currentNode, child, crossAxis);
530530
}
531-
} else if (child->getStyle().positionType() == PositionType::Static) {
531+
} else if (
532+
child->getStyle().positionType() == PositionType::Static &&
533+
!child->alwaysFormsContainingBlock()) {
532534
const Direction childDirection =
533535
child->resolveDirection(currentNodeDirection);
534536
const float childMainOffsetFromContainingBlock =

packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2034,7 +2034,7 @@ static void calculateLayoutImpl(
20342034
// Let the containing block layout its absolute descendants. By definition
20352035
// the containing block will not be static unless we are at the root.
20362036
if (node->getStyle().positionType() != PositionType::Static ||
2037-
depth == 1) {
2037+
node->alwaysFormsContainingBlock() || depth == 1) {
20382038
layoutAbsoluteDescendants(
20392039
node,
20402040
node,

packages/react-native/ReactCommon/yoga/yoga/node/Node.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ class YG_EXPORT Node : public ::YGNode {
4848
return context_;
4949
}
5050

51+
bool alwaysFormsContainingBlock() const {
52+
return alwaysFormsContainingBlock_;
53+
}
54+
5155
void print();
5256

5357
bool getHasNewLayout() const {
@@ -242,6 +246,10 @@ class YG_EXPORT Node : public ::YGNode {
242246
context_ = context;
243247
}
244248

249+
void setAlwaysFormsContainingBlock(bool alwaysFormsContainingBlock) {
250+
alwaysFormsContainingBlock_ = alwaysFormsContainingBlock;
251+
}
252+
245253
void setPrintFunc(YGPrintFunc printFunc) {
246254
printFunc_ = printFunc;
247255
}
@@ -369,6 +377,7 @@ class YG_EXPORT Node : public ::YGNode {
369377
bool hasNewLayout_ : 1 = true;
370378
bool isReferenceBaseline_ : 1 = false;
371379
bool isDirty_ : 1 = false;
380+
bool alwaysFormsContainingBlock_ : 1 = false;
372381
NodeType nodeType_ : bitCount<NodeType>() = NodeType::Default;
373382
void* context_ = nullptr;
374383
YGMeasureFunc measureFunc_ = {nullptr};

0 commit comments

Comments
 (0)