Skip to content

Commit 5687182

Browse files
NickGerlemanfacebook-github-bot
authored andcommitted
Remove legacy absolute positioning path (#1725)
Summary: X-link: facebook/react-native#46984 Pull Request resolved: #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 43be588 commit 5687182

File tree

8 files changed

+213
-356
lines changed

8 files changed

+213
-356
lines changed

enums.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,10 @@
6161
# Allows main-axis flex basis to be stretched without flexGrow being
6262
# set (previously referred to as "UseLegacyStretchBehaviour")
6363
("StretchFlexBasis", 1 << 0),
64-
# Positioning of absolute nodes will have various bugs related to
65-
# justification, alignment, and insets
66-
("AbsolutePositioningIncorrect", 1 << 1),
64+
# Absolute position in a given axis will be relative to the padding
65+
# edge of the parent container instead of the content edge when a
66+
# specific inset (top/bottom/left/right) is not set.
67+
("AbsolutePositionWithoutInsetsExcludesPadding", 1 << 1),
6768
# Absolute nodes will resolve percentages against the inner size of
6869
# their containing node, not the padding box
6970
("AbsolutePercentAgainstInnerSize", 1 << 2),

java/com/facebook/yoga/YogaErrata.java

+2-2
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;

javascript/src/generated/YGEnums.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export enum Edge {
5555
export enum Errata {
5656
None = 0,
5757
StretchFlexBasis = 1,
58-
AbsolutePositioningIncorrect = 2,
58+
AbsolutePositionWithoutInsetsExcludesPadding = 2,
5959
AbsolutePercentAgainstInnerSize = 4,
6060
All = 2147483647,
6161
Classic = 2147483646,
@@ -162,7 +162,7 @@ const constants = {
162162
EDGE_ALL: Edge.All,
163163
ERRATA_NONE: Errata.None,
164164
ERRATA_STRETCH_FLEX_BASIS: Errata.StretchFlexBasis,
165-
ERRATA_ABSOLUTE_POSITIONING_INCORRECT: Errata.AbsolutePositioningIncorrect,
165+
ERRATA_ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING: Errata.AbsolutePositionWithoutInsetsExcludesPadding,
166166
ERRATA_ABSOLUTE_PERCENT_AGAINST_INNER_SIZE: Errata.AbsolutePercentAgainstInnerSize,
167167
ERRATA_ALL: Errata.All,
168168
ERRATA_CLASSIC: Errata.Classic,

yoga/YGEnums.cpp

+2-2
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:

yoga/YGEnums.h

+1-1
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)

yoga/algorithm/AbsoluteLayout.cpp

+38-112
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)