Skip to content

Commit 0a2dec1

Browse files
NickGerlemanfacebook-github-bot
authored andcommitted
Remove legacy absolute positioning path (#46984)
Summary: Pull Request resolved: #46984 X-link: facebook/yoga#1725 The legacy (wrong) absolute positioning path positions in two places, including work that is definitely always overwritten in the new absolute layout path. This came up before for position: static, but we didn't clean this up at the time. This code is also now leading display: contents impl being more annoying. This diff tries to converge to the more spec correct implementation of positioning here, that also only happens in one place. Previous path would potentially also incorrectly justify when `justify-content` was non-default, but not handled in the previous few cases? We don't have access to the flexLine at this point later, and apart from the existing tests now passing I reused the new correct logic for justification (spec says we should position child as if its the only child in the container https://www.w3.org/TR/css-flexbox-1/#abspos-items). I added a new, more scoped errata `AbsolutePositionWithoutInsetsExcludesPadding` to preserve some of the legacy behavior that showed as very breaking. I also did not try removing `AbsolutePercentAgainstInnerSize` which I suspect would be more breaking than this change. Changelog: [General][Breaking] - More spec compliant absolute positioning Reviewed By: joevilches Differential Revision: D64244949 fbshipit-source-id: ca97570e0de82e8f0424a0912adfd0b05254559e
1 parent 2ffd31b commit 0a2dec1

File tree

6 files changed

+207
-351
lines changed

6 files changed

+207
-351
lines changed

packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaErrata.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
public enum YogaErrata {
1313
NONE(0),
1414
STRETCH_FLEX_BASIS(1),
15-
ABSOLUTE_POSITIONING_INCORRECT(2),
15+
ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING(2),
1616
ABSOLUTE_PERCENT_AGAINST_INNER_SIZE(4),
1717
ALL(2147483647),
1818
CLASSIC(2147483646);
@@ -31,7 +31,7 @@ public static YogaErrata fromInt(int value) {
3131
switch (value) {
3232
case 0: return NONE;
3333
case 1: return STRETCH_FLEX_BASIS;
34-
case 2: return ABSOLUTE_POSITIONING_INCORRECT;
34+
case 2: return ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING;
3535
case 4: return ABSOLUTE_PERCENT_AGAINST_INNER_SIZE;
3636
case 2147483647: return ALL;
3737
case 2147483646: return CLASSIC;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ const char* YGErrataToString(const YGErrata value) {
105105
return "none";
106106
case YGErrataStretchFlexBasis:
107107
return "stretch-flex-basis";
108-
case YGErrataAbsolutePositioningIncorrect:
109-
return "absolute-positioning-incorrect";
108+
case YGErrataAbsolutePositionWithoutInsetsExcludesPadding:
109+
return "absolute-position-without-insets-excludes-padding";
110110
case YGErrataAbsolutePercentAgainstInnerSize:
111111
return "absolute-percent-against-inner-size";
112112
case YGErrataAll:

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ YG_ENUM_DECL(
6161
YGErrata,
6262
YGErrataNone = 0,
6363
YGErrataStretchFlexBasis = 1,
64-
YGErrataAbsolutePositioningIncorrect = 2,
64+
YGErrataAbsolutePositionWithoutInsetsExcludesPadding = 2,
6565
YGErrataAbsolutePercentAgainstInnerSize = 4,
6666
YGErrataAll = 2147483647,
6767
YGErrataClassic = 2147483646)

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

Lines changed: 38 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@ static inline void setFlexStartLayoutPosition(
1919
const Direction direction,
2020
const FlexDirection axis,
2121
const float containingBlockWidth) {
22-
child->setLayoutPosition(
23-
child->style().computeFlexStartMargin(
24-
axis, direction, containingBlockWidth) +
25-
parent->getLayout().border(flexStartEdge(axis)) +
26-
parent->getLayout().padding(flexStartEdge(axis)),
27-
flexStartEdge(axis));
22+
float position = child->style().computeFlexStartMargin(
23+
axis, direction, containingBlockWidth) +
24+
parent->getLayout().border(flexStartEdge(axis));
25+
26+
if (!child->hasErrata(Errata::AbsolutePositionWithoutInsetsExcludesPadding)) {
27+
position += parent->getLayout().padding(flexStartEdge(axis));
28+
}
29+
30+
child->setLayoutPosition(position, flexStartEdge(axis));
2831
}
2932

3033
static inline void setFlexEndLayoutPosition(
@@ -33,15 +36,16 @@ static inline void setFlexEndLayoutPosition(
3336
const Direction direction,
3437
const FlexDirection axis,
3538
const float containingBlockWidth) {
39+
float flexEndPosition = parent->getLayout().border(flexEndEdge(axis)) +
40+
child->style().computeFlexEndMargin(
41+
axis, direction, containingBlockWidth);
42+
43+
if (!child->hasErrata(Errata::AbsolutePositionWithoutInsetsExcludesPadding)) {
44+
flexEndPosition += parent->getLayout().padding(flexEndEdge(axis));
45+
}
46+
3647
child->setLayoutPosition(
37-
getPositionOfOppositeEdge(
38-
parent->getLayout().border(flexEndEdge(axis)) +
39-
parent->getLayout().padding(flexEndEdge(axis)) +
40-
child->style().computeFlexEndMargin(
41-
axis, direction, containingBlockWidth),
42-
axis,
43-
parent,
44-
child),
48+
getPositionOfOppositeEdge(flexEndPosition, axis, parent, child),
4549
flexStartEdge(axis));
4650
}
4751

@@ -51,22 +55,30 @@ static inline void setCenterLayoutPosition(
5155
const Direction direction,
5256
const FlexDirection axis,
5357
const float containingBlockWidth) {
54-
const float parentContentBoxSize =
58+
float parentContentBoxSize =
5559
parent->getLayout().measuredDimension(dimension(axis)) -
5660
parent->getLayout().border(flexStartEdge(axis)) -
57-
parent->getLayout().border(flexEndEdge(axis)) -
58-
parent->getLayout().padding(flexStartEdge(axis)) -
59-
parent->getLayout().padding(flexEndEdge(axis));
61+
parent->getLayout().border(flexEndEdge(axis));
62+
63+
if (!child->hasErrata(Errata::AbsolutePositionWithoutInsetsExcludesPadding)) {
64+
parentContentBoxSize -= parent->getLayout().padding(flexStartEdge(axis));
65+
parentContentBoxSize -= parent->getLayout().padding(flexEndEdge(axis));
66+
}
67+
6068
const float childOuterSize =
6169
child->getLayout().measuredDimension(dimension(axis)) +
6270
child->style().computeMarginForAxis(axis, containingBlockWidth);
63-
child->setLayoutPosition(
64-
(parentContentBoxSize - childOuterSize) / 2.0f +
65-
parent->getLayout().border(flexStartEdge(axis)) +
66-
parent->getLayout().padding(flexStartEdge(axis)) +
67-
child->style().computeFlexStartMargin(
68-
axis, direction, containingBlockWidth),
69-
flexStartEdge(axis));
71+
72+
float position = (parentContentBoxSize - childOuterSize) / 2.0f +
73+
parent->getLayout().border(flexStartEdge(axis)) +
74+
child->style().computeFlexStartMargin(
75+
axis, direction, containingBlockWidth);
76+
77+
if (!child->hasErrata(Errata::AbsolutePositionWithoutInsetsExcludesPadding)) {
78+
position += parent->getLayout().padding(flexStartEdge(axis));
79+
}
80+
81+
child->setLayoutPosition(position, flexStartEdge(axis));
7082
}
7183

7284
static void justifyAbsoluteChild(
@@ -133,62 +145,6 @@ static void alignAbsoluteChild(
133145
}
134146
}
135147

136-
// To ensure no breaking changes, we preserve the legacy way of positioning
137-
// absolute children and determine if we should use it using an errata.
138-
static void positionAbsoluteChildLegacy(
139-
const yoga::Node* const containingNode,
140-
const yoga::Node* const parent,
141-
yoga::Node* child,
142-
const Direction direction,
143-
const FlexDirection axis,
144-
const bool isMainAxis,
145-
const float containingBlockWidth,
146-
const float containingBlockHeight) {
147-
const bool isAxisRow = isRow(axis);
148-
const bool shouldCenter = isMainAxis
149-
? parent->style().justifyContent() == Justify::Center
150-
: resolveChildAlignment(parent, child) == Align::Center;
151-
const bool shouldFlexEnd = isMainAxis
152-
? parent->style().justifyContent() == Justify::FlexEnd
153-
: ((resolveChildAlignment(parent, child) == Align::FlexEnd) ^
154-
(parent->style().flexWrap() == Wrap::WrapReverse));
155-
156-
if (child->style().isFlexEndPositionDefined(axis, direction) &&
157-
(!child->style().isFlexStartPositionDefined(axis, direction) ||
158-
child->style().isFlexStartPositionAuto(axis, direction))) {
159-
child->setLayoutPosition(
160-
containingNode->getLayout().measuredDimension(dimension(axis)) -
161-
child->getLayout().measuredDimension(dimension(axis)) -
162-
containingNode->style().computeFlexEndBorder(axis, direction) -
163-
child->style().computeFlexEndMargin(
164-
axis,
165-
direction,
166-
isAxisRow ? containingBlockWidth : containingBlockHeight) -
167-
child->style().computeFlexEndPosition(
168-
axis,
169-
direction,
170-
isAxisRow ? containingBlockWidth : containingBlockHeight),
171-
flexStartEdge(axis));
172-
} else if (
173-
(!child->style().isFlexStartPositionDefined(axis, direction) ||
174-
child->style().isFlexStartPositionAuto(axis, direction)) &&
175-
shouldCenter) {
176-
child->setLayoutPosition(
177-
(parent->getLayout().measuredDimension(dimension(axis)) -
178-
child->getLayout().measuredDimension(dimension(axis))) /
179-
2.0f,
180-
flexStartEdge(axis));
181-
} else if (
182-
(!child->style().isFlexStartPositionDefined(axis, direction) ||
183-
child->style().isFlexStartPositionAuto(axis, direction)) &&
184-
shouldFlexEnd) {
185-
child->setLayoutPosition(
186-
(parent->getLayout().measuredDimension(dimension(axis)) -
187-
child->getLayout().measuredDimension(dimension(axis))),
188-
flexStartEdge(axis));
189-
}
190-
}
191-
192148
/*
193149
* Absolutely positioned nodes do not participate in flex layout and thus their
194150
* positions can be determined independently from the rest of their siblings.
@@ -205,7 +161,7 @@ static void positionAbsoluteChildLegacy(
205161
* This function does that positioning for the given axis. The spec has more
206162
* information on this topic: https://www.w3.org/TR/css-flexbox-1/#abspos-items
207163
*/
208-
static void positionAbsoluteChildImpl(
164+
static void positionAbsoluteChild(
209165
const yoga::Node* const containingNode,
210166
const yoga::Node* const parent,
211167
yoga::Node* child,
@@ -267,36 +223,6 @@ static void positionAbsoluteChildImpl(
267223
}
268224
}
269225

270-
static void positionAbsoluteChild(
271-
const yoga::Node* const containingNode,
272-
const yoga::Node* const parent,
273-
yoga::Node* child,
274-
const Direction direction,
275-
const FlexDirection axis,
276-
const bool isMainAxis,
277-
const float containingBlockWidth,
278-
const float containingBlockHeight) {
279-
child->hasErrata(Errata::AbsolutePositioningIncorrect)
280-
? positionAbsoluteChildLegacy(
281-
containingNode,
282-
parent,
283-
child,
284-
direction,
285-
axis,
286-
isMainAxis,
287-
containingBlockWidth,
288-
containingBlockHeight)
289-
: positionAbsoluteChildImpl(
290-
containingNode,
291-
parent,
292-
child,
293-
direction,
294-
axis,
295-
isMainAxis,
296-
containingBlockWidth,
297-
containingBlockHeight);
298-
}
299-
300226
void layoutAbsoluteChild(
301227
const yoga::Node* const containingNode,
302228
const yoga::Node* const node,

0 commit comments

Comments
 (0)