Skip to content

Commit

Permalink
Remove legacy absolute positioning path (#1725)
Browse files Browse the repository at this point in the history
Summary:
X-link: facebook/react-native#46984


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 did not try removing `AbsolutePercentAgainstInnerSize` which I suspect would be pretty breaking.

Changelog: 
[General][Breaking] - More spec compliant absolute positioning

Reviewed By: joevilches

Differential Revision: D64244949
  • Loading branch information
NickGerleman authored and facebook-github-bot committed Oct 17, 2024
1 parent 43be588 commit 6cd7d33
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 336 deletions.
5 changes: 1 addition & 4 deletions enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,9 @@
# Allows main-axis flex basis to be stretched without flexGrow being
# set (previously referred to as "UseLegacyStretchBehaviour")
("StretchFlexBasis", 1 << 0),
# Positioning of absolute nodes will have various bugs related to
# justification, alignment, and insets
("AbsolutePositioningIncorrect", 1 << 1),
# Absolute nodes will resolve percentages against the inner size of
# their containing node, not the padding box
("AbsolutePercentAgainstInnerSize", 1 << 2),
("AbsolutePercentAgainstInnerSize", 1 << 1),
# Enable all incorrect behavior (preserve compatibility)
("All", 0x7FFFFFFF),
# Enable all errata except for "StretchFlexBasis" (Defaults behavior
Expand Down
6 changes: 2 additions & 4 deletions java/com/facebook/yoga/YogaErrata.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
public enum YogaErrata {
NONE(0),
STRETCH_FLEX_BASIS(1),
ABSOLUTE_POSITIONING_INCORRECT(2),
ABSOLUTE_PERCENT_AGAINST_INNER_SIZE(4),
ABSOLUTE_PERCENT_AGAINST_INNER_SIZE(2),
ALL(2147483647),
CLASSIC(2147483646);

Expand All @@ -31,8 +30,7 @@ public static YogaErrata fromInt(int value) {
switch (value) {
case 0: return NONE;
case 1: return STRETCH_FLEX_BASIS;
case 2: return ABSOLUTE_POSITIONING_INCORRECT;
case 4: return ABSOLUTE_PERCENT_AGAINST_INNER_SIZE;
case 2: return ABSOLUTE_PERCENT_AGAINST_INNER_SIZE;
case 2147483647: return ALL;
case 2147483646: return CLASSIC;
default: throw new IllegalArgumentException("Unknown enum value: " + value);
Expand Down
4 changes: 1 addition & 3 deletions javascript/src/generated/YGEnums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ export enum Edge {
export enum Errata {
None = 0,
StretchFlexBasis = 1,
AbsolutePositioningIncorrect = 2,
AbsolutePercentAgainstInnerSize = 4,
AbsolutePercentAgainstInnerSize = 2,
All = 2147483647,
Classic = 2147483646,
}
Expand Down Expand Up @@ -162,7 +161,6 @@ const constants = {
EDGE_ALL: Edge.All,
ERRATA_NONE: Errata.None,
ERRATA_STRETCH_FLEX_BASIS: Errata.StretchFlexBasis,
ERRATA_ABSOLUTE_POSITIONING_INCORRECT: Errata.AbsolutePositioningIncorrect,
ERRATA_ABSOLUTE_PERCENT_AGAINST_INNER_SIZE: Errata.AbsolutePercentAgainstInnerSize,
ERRATA_ALL: Errata.All,
ERRATA_CLASSIC: Errata.Classic,
Expand Down
2 changes: 0 additions & 2 deletions yoga/YGEnums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ const char* YGErrataToString(const YGErrata value) {
return "none";
case YGErrataStretchFlexBasis:
return "stretch-flex-basis";
case YGErrataAbsolutePositioningIncorrect:
return "absolute-positioning-incorrect";
case YGErrataAbsolutePercentAgainstInnerSize:
return "absolute-percent-against-inner-size";
case YGErrataAll:
Expand Down
3 changes: 1 addition & 2 deletions yoga/YGEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ YG_ENUM_DECL(
YGErrata,
YGErrataNone = 0,
YGErrataStretchFlexBasis = 1,
YGErrataAbsolutePositioningIncorrect = 2,
YGErrataAbsolutePercentAgainstInnerSize = 4,
YGErrataAbsolutePercentAgainstInnerSize = 2,
YGErrataAll = 2147483647,
YGErrataClassic = 2147483646)
YG_DEFINE_ENUM_FLAG_OPERATORS(YGErrata)
Expand Down
88 changes: 1 addition & 87 deletions yoga/algorithm/AbsoluteLayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,62 +133,6 @@ static void alignAbsoluteChild(
}
}

// To ensure no breaking changes, we preserve the legacy way of positioning
// absolute children and determine if we should use it using an errata.
static void positionAbsoluteChildLegacy(
const yoga::Node* const containingNode,
const yoga::Node* const parent,
yoga::Node* child,
const Direction direction,
const FlexDirection axis,
const bool isMainAxis,
const float containingBlockWidth,
const float containingBlockHeight) {
const bool isAxisRow = isRow(axis);
const bool shouldCenter = isMainAxis
? parent->style().justifyContent() == Justify::Center
: resolveChildAlignment(parent, child) == Align::Center;
const bool shouldFlexEnd = isMainAxis
? parent->style().justifyContent() == Justify::FlexEnd
: ((resolveChildAlignment(parent, child) == Align::FlexEnd) ^
(parent->style().flexWrap() == Wrap::WrapReverse));

if (child->style().isFlexEndPositionDefined(axis, direction) &&
(!child->style().isFlexStartPositionDefined(axis, direction) ||
child->style().isFlexStartPositionAuto(axis, direction))) {
child->setLayoutPosition(
containingNode->getLayout().measuredDimension(dimension(axis)) -
child->getLayout().measuredDimension(dimension(axis)) -
containingNode->style().computeFlexEndBorder(axis, direction) -
child->style().computeFlexEndMargin(
axis,
direction,
isAxisRow ? containingBlockWidth : containingBlockHeight) -
child->style().computeFlexEndPosition(
axis,
direction,
isAxisRow ? containingBlockWidth : containingBlockHeight),
flexStartEdge(axis));
} else if (
(!child->style().isFlexStartPositionDefined(axis, direction) ||
child->style().isFlexStartPositionAuto(axis, direction)) &&
shouldCenter) {
child->setLayoutPosition(
(parent->getLayout().measuredDimension(dimension(axis)) -
child->getLayout().measuredDimension(dimension(axis))) /
2.0f,
flexStartEdge(axis));
} else if (
(!child->style().isFlexStartPositionDefined(axis, direction) ||
child->style().isFlexStartPositionAuto(axis, direction)) &&
shouldFlexEnd) {
child->setLayoutPosition(
(parent->getLayout().measuredDimension(dimension(axis)) -
child->getLayout().measuredDimension(dimension(axis))),
flexStartEdge(axis));
}
}

/*
* Absolutely positioned nodes do not participate in flex layout and thus their
* positions can be determined independently from the rest of their siblings.
Expand All @@ -205,7 +149,7 @@ static void positionAbsoluteChildLegacy(
* This function does that positioning for the given axis. The spec has more
* information on this topic: https://www.w3.org/TR/css-flexbox-1/#abspos-items
*/
static void positionAbsoluteChildImpl(
static void positionAbsoluteChild(
const yoga::Node* const containingNode,
const yoga::Node* const parent,
yoga::Node* child,
Expand Down Expand Up @@ -267,36 +211,6 @@ static void positionAbsoluteChildImpl(
}
}

static void positionAbsoluteChild(
const yoga::Node* const containingNode,
const yoga::Node* const parent,
yoga::Node* child,
const Direction direction,
const FlexDirection axis,
const bool isMainAxis,
const float containingBlockWidth,
const float containingBlockHeight) {
child->hasErrata(Errata::AbsolutePositioningIncorrect)
? positionAbsoluteChildLegacy(
containingNode,
parent,
child,
direction,
axis,
isMainAxis,
containingBlockWidth,
containingBlockHeight)
: positionAbsoluteChildImpl(
containingNode,
parent,
child,
direction,
axis,
isMainAxis,
containingBlockWidth,
containingBlockHeight);
}

void layoutAbsoluteChild(
const yoga::Node* const containingNode,
const yoga::Node* const node,
Expand Down
Loading

0 comments on commit 6cd7d33

Please sign in to comment.