Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1809
X-link: https://github.com/facebook/react-native/pull/51181
We want to know if an artifact created during measurement can fully be reused after final layout, but the final layout is allowed to be slightly larger due to pixel grid rounding (while still allowing reuse). It's hard to tell after the fact, whether it is larger because of this rounding (though the measure is used), or if it may be a pixel larger for valid reasons.
We can expose the unsnapped dimensions of a node to give us this information, and to correlate measurement artifacts.
This is most of the time the same as the layout's measured dimension, though I don't think it's safe to use this, since anything else measuring the node after could clobber this (I think `YGNodeLayoutGetOverflow` may also be prone to this as a bug).
Changelog: [Internal]
Reviewed By: rshest
Differential Revision: D74292949
fbshipit-source-id: 05011c66a9a9480544313eb1dfe2c46bf7742bac
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1776
# Changelog:
[Internal] -
I was looking into some profiling results and noticed that Yoga has some quirky custom logic when it comes to rounding to the pixel grid, especially for the values that are halfway through.
There are already unit tests in place, but those cases weren't covered, so I am adding these extra corner cases here, to make sure they are covered in case that the actual rounding function may get modified (which it might make sense to, as it's currently can be more expensive than it could have been in some scenarios).
Reviewed By: christophpurrer
Differential Revision: D67712673
fbshipit-source-id: da1b7339a8939ced8d91f15441bc7d1f8af768c8
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1768
Depending on the flex direction text will either be capped to the measured size or to the longest word, so I added that functionality
Reviewed By: mlord93
Differential Revision: D67106199
fbshipit-source-id: 0b4691768809004043a847f3fc5f7b94e92f1575
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1759
We just have block based tests right now. Intrinsic sizing is commonly used with text so lets add a few there.
Reviewed By: NickGerleman
Differential Revision: D66662940
fbshipit-source-id: f8b91419c89d22d79a91d3bd8c7da70429c827fb
Summary:
X-link: https://github.com/facebook/react-native/pull/47895
Pull Request resolved: https://github.com/facebook/yoga/pull/1750
These APIs were only added so that we could do TDD as we work on intrinsic sizing functionality. As of right now they do nothing. We are aiming on publishing a new version of Yoga soon so for the time being we are going to back these out so as not to confuse anyone with this new functionality. Ideally we get to a point where we have some temporary experimental header to stage these in but this is a bit time sensitive so just backing out for now
Changelog: [Internal]
Reviewed By: NickGerleman
Differential Revision: D66332307
fbshipit-source-id: 1d596964e0c893091c541988506e8b80fa6d1957
Summary:
X-link: https://github.com/facebook/react-native/pull/47732
This pull request addresses the issue where combining align-content and align-items properties resulted in incorrect layout behavior in Yoga version 3.1.0, as reported in [Issue https://github.com/facebook/yoga/issues/1739](https://github.com/facebook/yoga/issues/1739).
# Changes Made:
Alignment Logic Update: Modified the alignment calculations to ensure that the combination of align-content and align-items properties produces the expected layout, consistent with CSS Flexbox standards and previous Yoga versions.
Test Cases Added: Introduced new test cases to cover scenarios involving various combinations of align-content and align-items properties to prevent future regressions.
# Testing:
All existing tests pass successfully.
New test cases confirm that the layout behaves as expected when align-content and align-items are used together.
# Impact:
This fix ensures that layouts using both align-content and align-items properties render correctly, aligning with the behavior observed in Yoga version 1.19.0 and standard web browsers.
Pull Request resolved: https://github.com/facebook/yoga/pull/1742
Reviewed By: joevilches
Differential Revision: D65953882
Pulled By: zeyap
fbshipit-source-id: 7e12a21b1d442b35c3f3536cad32dc4b82130d15
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1746
Chrome made some changes for how overflowed row-reverse containers are laid out which was causing some issues on CI. I updated them here and skipped the new failing tests which we would want to followup on.
For LTR, the differences are seen below
|Before|After|
|--|
|{F1962694149} | {F1962694151}|
The extra space is now extending past the flex start edge vs flex end. RTL is the opposite. NickGerleman had deviated from the spec back in the day to match Chrome and it seems they made the adjustment recently. T208209388 is tracking the followup to align with the spec again. Basically, there is a notion of fallback alignment when certain justification/alignment values cannot actually apply. Right now we are falling back to flex start in all cases but we should fallback to start sometimes.
Changelog: [Internal]
Reviewed By: NickGerleman
Differential Revision: D66138361
fbshipit-source-id: c46d2e9b0cd297069b9cc544e3bded995e4867a6
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1723
Adds gentest support for intrinsic sizing keywords and creates an initial batch of somewhat interesting tests for these keywords on `width`, `height`, `min-width`, `min-height`, `max-width`, `max-height`, and `flex-basis`
Reviewed By: NickGerleman
Differential Revision: D64145117
fbshipit-source-id: 1e3e7214fab062ab6f260cfe7bdfaf3c0aca3bf7
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1721
X-link: https://github.com/facebook/react-native/pull/46938
The private internals of how we store styles needed to change a bit to support 3 new keyword values. Right now the only other keyword that can be stored is `auto`. As a result there isn't much fancy logic to support storing this and its just stored as a specific type inside of `StyleValueHandle`. There are only 3 bits for types (8 values), so it is not sustainable to just stuff every keyword in there. So the change writes the keyword as a value with a new `keyword` `Type`.
I chose not to put `auto` in there even though it is a keyword since it is a hot path, I did not want to regress perf when I did not need to.
I also make a new `StyleSizeValue` class to store size values - so values for `width`, `height`, etc. This way these new keywords are kept specific to sizes and we will not be able to create, for example, a margin: `max-content`.
Changelog: [Internal]
Reviewed By: NickGerleman
Differential Revision: D63927512
fbshipit-source-id: 7285469d37ac4b05226183b56275c77f0c06996c
Summary:
Adds unit tests that directly cover the order in which `LayoutableChildren` iterator goes over the descendant nodes. The covered cases are as follows (nodes with `display: contents` are marked green):
### Single `display: contents` node
```mermaid
flowchart TD
R((R)) --> A((A))
R --> B((B))
R --> C((C))
B --> D((D))
B --> E((E))
style B fill:https://github.com/facebook/yoga/issues/090
```
Correct order: `A, D, E, C`
### Multiple `display: contents` nodes
```mermaid
flowchart TD
R((R)) --> A((A))
R --> B((B))
R --> C((C))
A --> D((D))
A --> E((E))
B --> F((F))
B --> G((G))
C --> H((H))
C --> I((I))
style A fill:https://github.com/facebook/yoga/issues/090
style B fill:https://github.com/facebook/yoga/issues/090
style C fill:https://github.com/facebook/yoga/issues/090
```
Correct order: `D, E, F, G, H, I`
### Nested `display: contents` nodes
```mermaid
flowchart TD
R((R)) --> A((A))
R --> B((B))
R --> C((C))
B --> D((D))
B --> E((E))
E --> F((F))
E --> G((G))
style B fill:https://github.com/facebook/yoga/issues/090
style E fill:https://github.com/facebook/yoga/issues/090
```
Correct order: `A, D, F, G, C`
### Leaf `display: contents` node
```mermaid
flowchart TD
R((R)) --> A((A))
R --> B((B))
R --> C((C))
style B fill:https://github.com/facebook/yoga/issues/090
```
Correct order: `A, C`
### Root `display: contents` node
```mermaid
flowchart TD
R((R)) --> A((A))
R --> B((B))
R --> C((C))
style R fill:https://github.com/facebook/yoga/issues/090
```
Correct order: `A, B, C` - `LayoutableChildren` goes over the children with `display: contents` property, setting it on the root node should have no effect.
Changelog: [Internal]
Pull Request resolved: https://github.com/facebook/yoga/pull/1731
Reviewed By: joevilches
Differential Revision: D64981779
Pulled By: NickGerleman
fbshipit-source-id: ee39759c663a40f96ad313f1b775d53ab68fb442
Summary:
X-link: https://github.com/facebook/react-native/pull/47035
This PR adds support for `display: contents` style by effectively skipping nodes with `display: contents` set during layout.
This required changes in the logic related to children traversal - before this PR a node would be always laid out in the context of its direct parent. After this PR that assumption is no longer true - `display: contents` allows nodes to be skipped, i.e.:
```html
<div id="node1">
<div id="node2" style="display: contents;">
<div id="node3" />
</div>
</div>
```
`node3` will be laid out as if it were a child of `node1`.
Because of this, iterating over direct children of a node is no longer correct to achieve the correct layout. This PR introduces `LayoutableChildren::Iterator` which can traverse the subtree of a given node in a way that nodes with `display: contents` are replaced with their concrete children.
A tree like this:
```mermaid
flowchart TD
A((A))
B((B))
C((C))
D((D))
E((E))
F((F))
G((G))
H((H))
I((I))
J((J))
A --> B
A --> C
B --> D
B --> E
C --> F
D --> G
F --> H
G --> I
H --> J
style B fill:https://github.com/facebook/yoga/issues/050
style C fill:https://github.com/facebook/yoga/issues/050
style D fill:https://github.com/facebook/yoga/issues/050
style H fill:https://github.com/facebook/yoga/issues/050
style I fill:https://github.com/facebook/yoga/issues/050
```
would be laid out as if the green nodes (ones with `display: contents`) did not exist. It also changes the logic where children were accessed by index to use the iterator instead as random access would be non-trivial to implement and it's not really necessary - the iteration was always sequential and indices were only used as boundaries.
There's one place where knowledge of layoutable children is required to calculate the gap. An optimization for this is for a node to keep a counter of how many `display: contents` nodes are its children. If there are none, a short path of just returning the size of the children vector can be taken, otherwise it needs to iterate over layoutable children and count them, since the structure may be complex.
One more major change this PR introduces is `cleanupContentsNodesRecursively`. Since nodes with `display: contents` would be entirely skipped during the layout pass, they would keep previous metrics, would be kept as dirty, and, in the case of nested `contents` nodes, would not be cloned, breaking `doesOwn` relation. All of this is handled in the new method which clones `contents` nodes recursively, sets empty layout, and marks them as clean and having a new layout so that it can be used on the React Native side.
Relies on https://github.com/facebook/yoga/pull/1725
Changelog: [Internal]
Pull Request resolved: https://github.com/facebook/yoga/pull/1726
Test Plan: Added tests for `display: contents` based on existing tests for `display: none` and ensured that all the tests were passing.
Reviewed By: joevilches
Differential Revision: D64404340
Pulled By: NickGerleman
fbshipit-source-id: f6f6e9a6fad82873f18c8a0ead58aad897df5d09
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1719
Right now there is no way to test fixtures with `auto` widths, heights, or flex basis - even though we expose those functions. I updated gentest to generate those functions. Notably, position and margin (the other auto-able props) already account for this.
I also created `YGAutoTest.html` to test this. Not really testing the capabilities of `auto` here, just if we can create a test about it.
Reviewed By: NickGerleman
Differential Revision: D64125522
fbshipit-source-id: 291ec82003cf53f99c21943142a63e2ef30402a5
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1715
X-link: https://github.com/facebook/react-native/pull/46799
Content box impl had a bug where we resolved padding % against the same reference length as the dimensions. Padding should always be against containing block's width. This is also true for width, but not for height, which should be against containing block's height.
This just pipes the width into our box sizing functions.
Changelog: [Internal]
Reviewed By: NickGerleman
Differential Revision: D63787577
fbshipit-source-id: e512338770f25b66506cabab5a7cde8f04397ea0
Summary:
X-link: https://github.com/facebook/react-native/pull/46800
Pull Request resolved: https://github.com/facebook/yoga/pull/1716
Had a mini heart attack thinking I set the default to content box. Wrote this to double check and it passed. Might as well check it in
Technically the default to BoxSizing.h is ContentBox, but in the style we override that. Regardless I switched that around so border box was the default.
Changelog: [Internal]
Reviewed By: NickGerleman
Differential Revision: D63802722
fbshipit-source-id: 49ed29657c964bc12a2bf70988061ab4599267ec
Summary:
X-link: https://github.com/facebook/react-native/pull/46741
Pull Request resolved: https://github.com/facebook/yoga/pull/1711
box sizing is really just a reinterpretation of what length properties (like `width`, `height`, `max-width`, etc) mean. So to implement this I just add the border and padding if we are in content box when we ask for any of these properties. All the math that gets done by the algorithm is still in border box land, and the layout we return is to be interpreted as the border box (this is actually the expected behavior per https://drafts.csswg.org/css-sizing/#box-sizing). This makes this implementation pretty simple actually.
Changelog: [Internal]
Reviewed By: NickGerleman
Differential Revision: D63416833
fbshipit-source-id: fd76132cf51e8a5092129802c3a12ab24023018b
Summary:
X-link: https://github.com/facebook/react-native/pull/46428
Pull Request resolved: https://github.com/facebook/yoga/pull/1696
We do not validate the aspect ratio to ensure it is non zero and non inf in a lot of places. Per the spec, these values should act like auto. There is no auto keyword, but it is the default so I just set the style to a default FloatOptional in this case
Changelog: [Internal]
Reviewed By: NickGerleman
Differential Revision: D62473161
fbshipit-source-id: 6857de819538a7a87ce0a652e99f5a49992921ae
Summary:
X-link: https://github.com/facebook/react-native/pull/46216
Regarding [issue](https://github.com/facebook/react-native/issues/45817) with incorrect layout when `left` is set to `auto`. This PR introduces handling `auto` whenever inline or flex position is checked to be defined and it fixes above issue.
Changelog:
[General][Fixed] - Fix handling 'auto' checks in absolute layout
## Tests:
I have run the provided unit tests and everything passes.
Pull Request resolved: https://github.com/facebook/yoga/pull/1689
Reviewed By: cipolleschi
Differential Revision: D61737876
Pulled By: NickGerleman
fbshipit-source-id: 531199a91c5e122b930b49725ea567cbb1d592ce
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1677
We have Clang Tidy warnings enabled internally, that will flag `const YG*Ref` as misleading, as a const pointer to non-const, instead of non-const pointer to const.
Let's remove all the misleading const in existing tests, and generated tests.
Reviewed By: joevilches
Differential Revision: D59335968
fbshipit-source-id: c66af878904ba7900f8ffcd99162968d90f8e5c7
Summary:
X-link: https://github.com/facebook/react-native/pull/45240
Pull Request resolved: https://github.com/facebook/yoga/pull/1675
There was a bug where some crash would happen if a tree was cloned that had static/absolute parent/child pair inside it. This was because we were no longer calling `cloneChildrenIfNeeded` on the static parent, but would still layout the absolute child. So that child's owner would be stale and have new layout. In React Native this would lead to a failed assert which causes the crash.
The fix here is to clone the children of static nodes during `layoutAbsoluteDescendants` so that we guarantee the node is either cloned if it is going to have new layout.
Changelog: [Internal]
Reviewed By: NickGerleman
Differential Revision: D59175629
fbshipit-source-id: 4d110a08ba5368704327d5ab69a8695b28e746f4
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1671
This diff adds support for intrinsic sizing in generated tests. This is done by importing a testing font called "Ahem" which, as used, has an exact width and height of 10px for each character. Support has been added for C++, Java, and Javascript generated tests.
Reviewed By: NickGerleman
Differential Revision: D58307002
fbshipit-source-id: e1dcc1e03310d35a32e0c70f71994880d8f7de55
Summary:
X-link: https://github.com/facebook/react-native/pull/44792
Pull Request resolved: https://github.com/facebook/yoga/pull/1663
Fixing https://github.com/facebook/yoga/issues/1658. We had a problem where if a child had a different flex direction than its parent, and it also set a position as a percent, it would look at the wrong axis to evaluate the percent. What was happening was we were passing in the container's mainAxis size and crossAxis size to use to evaluate the position size if it was a percent. However, we matched these sizes with the main/cross axis of the child - which is wrong if the flex direction is different.
I changed it so that the function just takes in ownerWidth and ownerHeight then calls isRow to determine which one to use for the main/cross axis position. This reduces the ambiguity quite a bit imo.
Changelog: [Internal]
Reviewed By: NickGerleman
Differential Revision: D58172416
fbshipit-source-id: eafd8069e03493fc56c41a76879d1ad9b7e9236d
Summary:
X-link: https://github.com/facebook/react-native/pull/44791
Pull Request resolved: https://github.com/facebook/yoga/pull/1662
This should fix https://github.com/facebook/yoga/issues/1657. Rather insidious bug but we had code like
```
// The total padding/border for a given axis does not depend on the direction
// so hardcoding LTR here to avoid piping direction to this function
return node->style().computeInlineStartPaddingAndBorder(
axis, Direction::LTR, widthSize) +
node->style().computeInlineEndPaddingAndBorder(
axis, Direction::LTR, widthSize);
```
That comment is NOT true if someone sets both the physical edge and relative edge. So like paddingLeft and paddingEnd for RTL. This diff simply pipes the direction to that spot to use instead of hardcoding LTR. Every file changed is just to pipe `direction`.
Changelog: [Internal]
Reviewed By: NickGerleman
Differential Revision: D58169843
fbshipit-source-id: 5b4854dddc019285076bd06955557edf73ef7ec5
Summary:
X-link: https://github.com/facebook/react-native/pull/44010
Pull Request resolved: https://github.com/facebook/yoga/pull/1641
Yoga has quirk where newly constructed nodes are clean, which isn't really correct. Normally never shows in in real code because setting a style or children will dirty. Fabric doesn't use the public APIs that do this dirtying, so it ends up getting creative instead.
We should fix so that newly constructed nodes are dirty. Copy-constructed Nodes (also only a Fabric thing, will retain original dirty flag.
Changelog: [Internal]
Reviewed By: sammy-SC
Differential Revision: D55855328
fbshipit-source-id: be49efaf8ac29351f8e5ec509bd9912546944332
Summary:
X-link: https://github.com/facebook/react-native/pull/43752
Gentest tests started failing because Chrome changed behavior of overflowed align-content container. Spec says should fallback to "safe center", which is really just "start", instead of previous "center" behavior. This changes behavior accordingly.
There is one bit where I think we are doing the wrong thing wrt alignment of flex start vs start (which we don't support yet), but couldn't repro a failing chrome test.
Changelog: [Internal]
Reviewed By: joevilches
Differential Revision: D55617689
fbshipit-source-id: 08f23d198c75f2c2f51ccaa8795289e6e4a92cb8
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1593
X-link: https://github.com/facebook/react-native/pull/43417
There was a bug where we did not position absolute nodes correctly if the static node had a different main/cross axis from the containing node. This fixes that. The change is somewhat complicated unfortunately but I tried to add sufficient comments to explain what is happening
Reviewed By: NickGerleman
Differential Revision: D54703955
fbshipit-source-id: 096c643f61d4f9bb3ee6278d675ebd69b57350d7
Summary:
X-link: https://github.com/facebook/litho/pull/976
Pull Request resolved: https://github.com/facebook/yoga/pull/1586
X-link: https://github.com/facebook/react-native/pull/43299
Add the React Clang Tidy config to Yoga, run the auto fixes, and make some manual mechanical tweaks.
Notably, the automatic changes to the infra for generating a Yoga tree from JSON capture make it 70% faster.
Before:
{F1463947076}
After:
{F1463946802}
This also cleans up all the no-op shallow const parameters in headers.
{F1463943386}
Not all checks are available in all environments, but that is okay, as Clang Tidy will gracefully skip them.
Changelog: [Internal]
Reviewed By: sammy-SC
Differential Revision: D54461054
fbshipit-source-id: dbd2d9ce51afd3174d1f2c6d439fa7d08baff46f
Summary:
X-link: https://github.com/facebook/react-native/pull/42688
Pull Request resolved: https://github.com/facebook/yoga/pull/1567
We are planning on overhauling NodeToString to output JSON instead of HTML for the purposes of better benchmarking and capturing trees in JSON format to benchmark later. This gives us a bit of a headache as we have to revise several build files to ensure this new library works, ensure that it is only included in certain debug builds, and deal with the benchmark <-> internal cross boundary that arises as the benchmark code (which is a separate binary) tries to interact with it.
On top of it all this is really not used at all.
The plan is to rip out this functionality and just put it in a separate binary that one can include if they really want to debug. That means that it cannot exist in the public API, so I am removing it here.
Private internals come next
Changelog: [Internal]
Reviewed By: NickGerleman
Differential Revision: D53137544
fbshipit-source-id: 7571d243b914cd9bf09ac2418d9a1b86d1bee64a
Summary:
X-link: https://github.com/facebook/react-native/pull/42411
Pull Request resolved: https://github.com/facebook/yoga/pull/1562
I added a small regression D52605596, where negative border would not be correctly floored. This fixes that, and starts adding tests specifically targeting the computed style API, now decoupled from the yoga node.
Reviewed By: joevilches
Differential Revision: D52930827
fbshipit-source-id: e165dade705a8de54c92d65f3664c9081137788c
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1561
Back when I introduced the inline functions that would get the edge according to the writing direction I swapped some instances of `setLayoutPosition` which wrote to the flexStart edge erroneously. We should basically never read from some inline style and write to the flex edge. This changes them all to use the flex values.
Reviewed By: NickGerleman
Differential Revision: D52921401
fbshipit-source-id: 92b74d652018596134c91827806272ed7418ef6c
Summary:
X-link: https://github.com/facebook/react-native/pull/42131
Pull Request resolved: https://github.com/facebook/yoga/pull/1534
Now that the storage method is a hidden implementation detail, this changes the underlying data structure used to store styles, from `CompactValue` (a customized 32-bit float with tag bits), to `StyleValuePool`.
This new structure operates on 16-bit handles, and a shared small buffer. The vast majority of real-world values can be stored directly in the handle, but we allow arbitrary 32 bit (and soon 64-bit) values to be stored, where the handle then becomes an index into the styles buffer.
This results in a real-world memory usage win, while also letting us store the 64-bit values we are wanting to use for math function support (compared to doubling the storage requirements).
This does seem to make style reads slower, which due to their heavy frequency, does have a performance impact observable by synthetics. In an example laying out a tree of 10,000 nodes, we originally read from `StyleValuePool` 2.4 million times.
This originally resulted in a ~10% regression, but when combined with the changes in the last diff, most style reads become simple bitwise operations on the handle, and we are actually 14% faster than before.
| | Before | After | Δ |
| `sizeof(yoga::Style)` | 208B | 144B | -64B/-31% |
| `sizeof(yoga::Node)` | 640B | 576B | -64B/-10% |
| `sizeof(YogaLayoutableShadowNode) ` | 920B | 856B | -64B/-7% |
| `sizeof(YogaLayoutableShadowNode) + sizeof(YogaStylableProps)` | 1296B | 1168B | -128B/-10% |
| `sizeof(ViewShadowNode)` | 920B | 856B | -64B/-7% |
| `sizeof(ViewShadowNode) + sizeof(ViewShadowNodeProps)` | 2000B | 1872B | -128B/-6% |
| "Huge nested layout" microbenchmark (M1 Ultra) | 11.5ms | 9.9ms | -1.6ms/-14% |
| Quest Store C++ heap usage (avg over 10 runs) | 86.2MB | 84.9MB | -1.3MB/-1.5% |
Reviewed By: joevilches
Differential Revision: D52223122
fbshipit-source-id: 990f4b7e991e8e22d198ce20f7da66d9c6ba637b
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1560
I added these when I was trying to debug the Facepile break removing the row-reverse errata caused. Yoga is doing the right thing, and the tests pass. We didn't have this specific coverage before, so add it.
Reviewed By: joevilches
Differential Revision: D52909633
fbshipit-source-id: d1e8f55bb534d76bd7dfdc46a1e1cc6f0a3ca211
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1549
X-link: https://github.com/facebook/react-native/pull/42253
This experimental feature is always false, and with the next diff I will be deleting the branch that actually calls into this. Separating this diff out to simplify the review process.
Reviewed By: NickGerleman
Differential Revision: D52705765
fbshipit-source-id: 705f4aa297eae730af9b44753eb01c9dec385dcf
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1547
X-link: https://github.com/facebook/react-native/pull/42251
Yoga has an odd behavior, where `start`/`end` edges under row-reverse are relative to flex-direction, instead of writing direction.
While Yoga doesn't actually document what this behavior is supposed to be, it goes against CK documentation, historic RN documentation, and the behavior valid on the web. It is also applied inconsistently (e.g. sometimes only on container, sometimes on child). It really is a bug, instead of an intended behavior.
We changed the default behavior for Yoga, but left the existing one behind an errata (so existing fbsource users got old behavior). We have previously seen this behavior show up in product code, including CK when running on FlexLayout.
`row-reverse` is surprisingly uncommon though:
1. Litho has <40 usages
2. RN has ~40 usages in `RKJSModules`,~30 in `arvr/js`, ~6 in `xplat/archon`
3. CK has ~80 usages
4. NT has ~40 usages
There are few enough, mostly simple components, that we can inspect through each of them, looking for signs they will hit the issue (at the potential chance of missing some).
CK accounts for 10/14 usages that I could tell would trigger the issue, since it only exposes start/end edge, and not left/right. It might make sense to make it preserve behavior instead, to reduce risk a bit.
FlexLayout is now separately powering Bloks, which wasn't surveyed, so I didn't touch CK behavior under Bloks.
There could also be other usages in other frameworks/bespoke usages, and this has implications for OSS users. But based on our own usage, of many, many components, this seems rare.
Changelog:
[General][Breaking] - Make `start/end` in styles always refer to writing direction
Reviewed By: pentiumao, joevilches
Differential Revision: D52698130
fbshipit-source-id: 2a9ac47e177469f30dc988d916b6c0ad95d53461
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1530
Yoga has a shortcut where if a min dimension and max dimension are the same, the value acts as a definite length.
I was curious how browsers handled this.
CSS 2.1 said:
> If the containing block's width depends on this element's width, then the resulting layout is undefined
This is superceded in the CSS box sizing spec. https://www.w3.org/TR/css-sizing-3/#sizing-values
> If, in a particular axis, the containing block’s size depends on the box’s size, see the relevant layout module for special rules on how to resolve percentages. Negative values are invalid.
And later:
https://www.w3.org/TR/css-sizing-3/#cyclic-percentage-contribution
> Sometimes the size of a percentage-sized box’s containing block depends on the intrinsic size contribution of the box itself, creating a cyclic dependency. When calculating the intrinsic size contribution of such a box (including any calculations for a content-based automatic minimum size), a percentage value that resolves against a size in the same axis as the intrinsic size contribution (a cyclic percentage size) is resolved specially:
> If the box is non-replaced, then the entire value of any max size property or preferred size property (width/max-width/height/max-height) specified as an expression containing a percentage (such as 10% or calc(10px + 0%)) that is cyclic is treated for the purpose of calculating the box’s intrinsic size contributions only as that property’s initial value. For example, given a box with width: calc(20px + 50%), its max-content contribution is calculated as if its width were auto. (The percentage is honored as usual, however, during the actual sizing of the box itself; see below.)
> Otherwise, the percentage is resolved against the containing block’s size. (The containing block’s size is not re-resolved based on the resulting size of the box; the contents might thus overflow or underflow the containing block).
So, for the purpose of sizing the parent, the child sized using a percentage does not contribute, but we should be sizing children based on that size.
Yoga does not really work like this right now, but gets the answer right answer for half of these tests.
Reviewed By: yungsters
Differential Revision: D52251601
fbshipit-source-id: 4978b90723130283b00e87bbf49795a4d209174c
Summary:
X-link: https://github.com/facebook/react-native/pull/41776
Pull Request resolved: https://github.com/facebook/yoga/pull/1492
# Summary
In preparation to replace `CompactValue`, this fully encapsulates it as an implementation detail of `yoga::Style`.
The internal API now always operates on `Style::Length`, converted to `YGValue` at the public API boundary.
In the next step, we can plug in a new representation within `Style`, which should enable 64 bit values, and lower memory usage.
# Test Plan
1. Existing tests (inc for style, invalidation, CompactValue) pass
2. Check that constexpr `yoga::isinf()` produces same assembly under Clang as `std::isinf()`
3. Fabric Android builds
4. Yoga benchmark does style reads
# Performance
Checking whether a style is defined, then reading after, is a hot path, and we are doubling any space style lengths take in the stack (but not long-term on the node). After a naive move, on one system, the Yoga benchmark creating, laying out, and destroying a tree, ran about 8-10% slower in the "Huge nested flex" example. We are converting in many more cases instead of doing undefined check, but operating on accessed style values no longer needs to do the conversion multiple times.
I changed the `CompactValue` conversion to YGValue/StyleLength path to check for undefined as the common case (since we always convert, instead of calling `isUndefined` directly on CompactValue. That seemed to get the difference down to ~5-6% when I was playing with it then. We can optimistically make some of this up with ValuePool giving better locality, and fix this more holistically if we reduce edge and value resolution.
On another machine where I tested this, the new revision went the opposite direction, and was about 5% faster, so this isn't really a cut and dry regression, but we see different characteristics than before.
# Changelog
[Internal]
Reviewed By: rozele
Differential Revision: D51775346
fbshipit-source-id: c618af41b4882b4a227c917fcad07375806faf78
Summary:
X-link: https://github.com/facebook/react-native/pull/41964
Pull Request resolved: https://github.com/facebook/yoga/pull/1524
D52087013 (#1513) fixed some issues, including where measuring under max-content or fit-content, align-content stretch would consume the entire available cross-dimensions, instead of only sizing to definite dimension, like the spec dicates.
I missed a case, where flexbox considers a container as having a definite cross-size if it is being stretched, even if it doesn't have a definite length.
https://www.w3.org/TR/css-flexbox-1/#definite-sizes
> 3. Once the cross size of a flex line has been determined, items in auto-sized flex containers are also considered definite for the purpose of layout;
> 1. If a single-line flex container has a definite cross size, the outer cross size of any stretched flex items is the flex container’s inner cross size (clamped to the flex item’s min and max cross size) and is considered definite.
We handle `align-items: stretch` of a flex container after cross-size determination by laying out the child under stretch-fit (previously YGMeasureModeExactly) constraint. This checks that case, and sizing the line container to specified cross-dim if we are told to stretch to it.
We could probably afford to merge this a bit with later with what is currently step 9, where we end up redoing some of this same math.
Reviewed By: yungsters
Differential Revision: D52234980
fbshipit-source-id: 475773a352fd01f63a4b21e93a55519726dc0da7