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/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
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1513
X-link: https://github.com/facebook/react-native/pull/41916
Fixes https://github.com/facebook/yoga/issues/1300
Fixes https://github.com/facebook/yoga/issues/1008
This fixes a smattering of issues related to both sizing and aligment of multi-line-containers:
1. We were previously incorrectly bounding the size of each flex line to the min/max of the entire container.
2. Per-line leads were sometimes incorrectly contributing to alignment within the line
3. The cross dim size used for multi-line alignment is not correct, or correctly clamped. If the available size comes from a max constraint, that was incorrectly used instead of a definite size, or size of content. Leads were entirely skipped for min constraint.
Need to test how breaking this is, to see if it might need to go behind an errata.
See related PRs:
1. https://github.com/facebook/yoga/pull/1491
2. https://github.com/facebook/yoga/pull/1493
3. https://github.com/facebook/yoga/pull/1013
Changelog:
[General][Fixed] - Fix Yoga sizing and alignment issues with multi-line containers
Reviewed By: joevilches
Differential Revision: D52087013
fbshipit-source-id: 8d95ad17e58c1fec1cceab9756413d0b3bd4cd8f
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1522
I have the types but not the core
Reviewed By: NickGerleman
Differential Revision: D52216588
fbshipit-source-id: ec348537655213f6d8a3b35402fec03998744c78
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1505
This will ensure that all tests are not modified by hand and that gentest was run if needed (i.e. someone edited those files and forgot to update the tests). Not sure if this works right now, need to export to github and see what happens :)
Reviewed By: NickGerleman
Differential Revision: D52002920
fbshipit-source-id: 1ee033eda04eeba5d01885488bfe8078e7b2f386
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1504
I aim to consume this via a github action or workflow. Separating out the CI configuration from the actual script. We could and should maybe change this script to take in arguments for the test dirs so it is more configurable, but getting the barebones down right now.
Reviewed By: NickGerleman
Differential Revision: D51999865
fbshipit-source-id: 5792c6eec5692943518fecefc6226d784c6f0ad8
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1503
This diff makes it so that our driver will sign all of the generated files to help ensure that they are not edited by hand. Next I will add CI to actually verify the signature
Reviewed By: NickGerleman
Differential Revision: D51966201
fbshipit-source-id: f7e3f4fde1c98832212a448b2dcc8e21be0560c4
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1501
Now that we have `gentest-driver.ts` we can delete the ruby gentest. I also regened all of the tests that have a comment with the wrong file name for where it was generated.
Reviewed By: yungsters, NickGerleman
Differential Revision: D51956567
fbshipit-source-id: d389492e54711cf161dff9e649396cc40f1e5073
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1499
This uses the minimist library to parse the command line easily for flags and options. I added over the same ones in the ruby script (-f and -s).
Reviewed By: yungsters, NickGerleman
Differential Revision: D51877810
fbshipit-source-id: 643606cad25609ed2567bb63470818b81ebef531
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1498
The only instance of ruby in this repository is `gentest.rb` used to generate test cases from html fixtures. This is quite annoying as ruby is not the most popular compared to something like Node and it does not integrate into the rest of our stack. I changed this to use Node.js instead. Instead of `watir` we now use `selenium-webdriver`. `watir` is backed by Selenium so I do not expect anything to change.
Next commits will add command line options, clean up gentest.rb and its references, and change the README
allow-large-files
Reviewed By: yungsters, NickGerleman
Differential Revision: D51874433
fbshipit-source-id: ef8588d48aa7f8b720b57df08738bbd01e9e74a3
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1488
These were disabled when they were written because they were broken. The recent changes made them pass now so lets enable them. I also added another test that is already passing
Reviewed By: NickGerleman
Differential Revision: D51404875
fbshipit-source-id: ed10004968b871c1d033640d75138f00afc15968
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1490
X-link: https://github.com/facebook/react-native/pull/41692
In the previous diffs I fixed problems with justifying absolute nodes. The same issues plague aligning so I fixed them in the same way. Added tests that were failing before but now passing
Reviewed By: NickGerleman
Differential Revision: D51404489
fbshipit-source-id: 604495d651eb67cfdcca40df9d8d3a125c5741a8
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1487
X-link: https://github.com/facebook/react-native/pull/41691
The code here was just wrong. I changed it to be the same logic as the Justify:FlexStart case, but with the flex end sides. Then I get the position for the opposite edge since we need to write to flex start side.
Reviewed By: NickGerleman
Differential Revision: D51383792
fbshipit-source-id: 372835a44edff361dbd84dd92ff9f2ec844b9f9c
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1489
X-link: https://github.com/facebook/react-native/pull/41690
Centering involves centering the margin box in the content box of the parent, and then getting the distance from the flex start edge of the parent to the child
Reviewed By: NickGerleman
Differential Revision: D51383625
fbshipit-source-id: 6bbbace95689ef39c35303bea4b99505952df457
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1485
X-link: https://github.com/facebook/react-native/pull/41686
The size of the containing block is the size of the padding box of the containing node for absolute nodes. We were looking at `containingNode->getLayout().measuredDimension(Dimension::Width)` which is the border box. So we need to subtract the border from this.
Added a test that was failing before this change as well
Reviewed By: NickGerleman
Differential Revision: D51330526
fbshipit-source-id: adc448dfb71b54f1bbed0d9d61c5553bda4b106c
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1482
X-link: https://github.com/facebook/react-native/pull/41685
This is the final step (that I know of) to get the core features of static working. Here we turn on all of the tests and pass down the correct owner size for the call to `calculateLayoutInternal` that is in `layoutAbsoluteChild`
Reviewed By: NickGerleman
Differential Revision: D51293606
fbshipit-source-id: 972259e7ebecb19b55aef2ef866bd7cb57aaf0ca
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1496
Gentest code has a problem where we try to apply a border in our test when the web browser is not actually adding one. This happens when we do something like `border-top: 10px`. This will actually set the style of the border to `initial` which is just `none`, so nothing renders. This is causing at least 1 test to pass when it actually fails.
I changed it so we ignore setting this value if the style is one of these values. I then re-ran the gentest code and excluded the now failing test (which gets fixed in my static stack).
Reviewed By: NickGerleman
Differential Revision: D51831754
fbshipit-source-id: a325e4a42b2d7cd6f19efc6cd5a2445574467fb7
Summary:
X-link: https://github.com/facebook/react-native/pull/41480
Pull Request resolved: https://github.com/facebook/yoga/pull/1469
The previous version of static didn't do anything inside of Yoga. Now that we're making it do something, this changes the default back to relative so that users with no errata set don't see their deafult styles changing.
Reviewed By: joevilches
Differential Revision: D51182955
fbshipit-source-id: c0ea357694e1367fb6786f1907dfff784b19a4bc
Summary:
X-link: https://github.com/facebook/react-native/pull/41293
Pull Request resolved: https://github.com/facebook/yoga/pull/1446
NickGerleman pointed out that my recent changes to fix the slew of row-reverse problems in Yoga actually ended up regressing some parts. Specifically, absolute children of row-reverse containers would have their insets set to the wrong side. So if you set left: 10 it would apply it to the right.
Turns out, in `layoutAbsoluteChild` there were cases where we were applying inlineStart/End values to the flexStart/End edge, which can never be right. So I changed the values to also be flexStart/End as the fix here.
Reviewed By: NickGerleman
Differential Revision: D50945475
fbshipit-source-id: 290de06dcc04e8e644a3a32c127af12fdabb2f75
Summary:
`child.offsetLeft/Top` calculates the offset from child to its nearest positioned ancestor, not its direct parent. These are often the same and have not mattered in the past since we have not supported position static. Since are are in the process of supporting that, we would like our tests to be usable so this adjusts the gentest methodology to only speak the same language as Yoga - that is left/top are always relative to direct parents.
It works by using `getBoundingClientRect().left/top` instead. Then we pass that down to children and subtract it from the childs `getBoundingClientRect()` to get the position relative to the parent. Note we have to round the final result as `child.offsetLeft/Top` is rounded.
Reviewed By: NickGerleman
Differential Revision: D51053629
fbshipit-source-id: 8809588d12953565228ae50fdf38197213c46182
Summary:
Fixes https://github.com/facebook/yoga/issues/1417
This dramatically simplifies the matrix of Node vs web, ASM vs WASM, sync vs async compilation, or CommonJS vs ES Modules. We have one variant, using wasm, with ESModule top-level await to do async compilation. Web/node share the same binary, and we base64 encode the WASM into a wrapper JS file for compatibility with Node and bundlers.
This has some downsides, like requiring an environment with top level await, but also has upsides, like a consistent, sync looking API compatible with older Yoga, and mitigating TypeScript issues with package exports and typings resolution.
As part of this work I also removed `ts-node` from the toolchain (at the cost of a couple of config files needing to be vanilla JS).
Pull Request resolved: https://github.com/facebook/yoga/pull/1433
Test Plan:
1. `yarn test`
2. `yarn lint`
3. `yarn tsc`
4. `yarn benchmark`
5. `yarn build` website-next
6. `yarn lint` website-next
7. Locally test website-next
8. Examine package artifact created by GitHub
9. All Automation passes
Reviewed By: yungsters
Differential Revision: D50453324
Pulled By: NickGerleman
fbshipit-source-id: fe1192acc69e57fa69a1ff056dd7b5844d2198d5
Summary:
I was playing around with absolute children and padding and noticed an issue so adding tests to track.
Made a github issue: https://github.com/facebook/yoga/issues/1436
Reviewed By: yungsters
Differential Revision: D50670457
fbshipit-source-id: 4672d1e8b831a0a42509d95e91178944fc0f5c06
Summary:
Doing some test-driven-development to support this feature, so I will start by adding a ton of tests to ensure the nuance of position: static is captured in Yoga. Specifically I have a slew of tests to capture:
* Insets have no effect on static elements
* Insets are relative to the nearest non-static ancestor
* Percentage values for insets, padding, and margin of absolute children respect the correct dimension of the nearest non-static ancestor
* Also added similar ones for static and relative children which should just respect their ancestor (static only because it is a flexbox by default)
* This rule does NOT apply to border
* The containing block for absolute children is the padding box of their nearest non-static ancestor
* The containing block for static children is the content box of their parent (because all elements are flex containers in yoga, at least right now)
Reviewed By: NickGerleman
Differential Revision: D50475939
fbshipit-source-id: 7988ffc9bea3317875128dd1908d787b9b714a45
Summary:
I am about to embark on supporting `position: static` in Yoga. The enum exists already (and is the default position type, lol) but does not actually do anything and just behaves like `position: relative`.
My approach here is to write a bunch of tests to test for the various behaviors of static positions and then develop on Yoga afterwards to get those tests passing. To do this, we need to make a few changes to the gentest files as there is not support for adding `position: static` at the moment:
* Make it so that the gentest code can physically write `YGPositionTypeStatic` if it encounters `position: static` in the style
* Make it so that gentest.js knows that Yoga's default is actually static. This way the code generated in the tests will actually label nodes for non default values
* Explicitly label the position type even when it is not declared in the style prop (with the exception of the default)
* Regenerate all the tests
Additionally I added the first, basic test: making sure insets do nothing on a statically positioned element.
Reviewed By: NickGerleman
Differential Revision: D50437855
fbshipit-source-id: 0e8bbf1c224d477ea4592b7563d0b70d2ffa79c8
Summary: Now that the tests are passing let's not skip it anymore. Also adding errata tests to make sure most prod builds are still protected.
Reviewed By: NickGerleman
Differential Revision: D50390993
fbshipit-source-id: cb91a7a377e919eaca24fb25e3d73d3c92eb8931
Summary:
These tests were a bit weird for testing something with position. The gentest setup makes it so that the fixtures are wrapped in a absolutely positioned container with height and width bot 0. However, the generated yoga tests do NOT do this and instead have the root node as the fixture itself with no wrapping container.
This causes a problem when testing left/right/top/bottom position insets. Because left/right/top/bottom will position the element relative to its containing block when position is absolute, we will get different values on yoga and chrome even if the implementation is correct: https://developer.mozilla.org/en-US/docs/Web/CSS/right#description
To fix this, we just wrap the fixture in a set size div that is also absolutely positioned.
The file was also formatted.
Reviewed By: NickGerleman
Differential Revision: D50389229
fbshipit-source-id: ecd23939b973225cfb0611dc87f30c262952c5fc
Summary:
X-link: https://github.com/facebook/react-native/pull/41019
### Changes made
- Regenerated tests (as some aspect ratio tests seem to be out of date compared to the fixtures)
- Added SpaceEvenly variant to the "Align" enums (via enums.py)
- Implemented `align-content: space-evenly` alignment in CalculateLayout.cpp
- Added generated tests `align-content: space-evenly`
- Updated NumericBitfield test to account for the fact that the Align enum now requires more bits (this bit could do with being reviewed as I am not 100% certain that it's valid to just update the test like this).
### Changes not made
- Any attempt to improve the spec-compliance of content alignment in general (e.g. I think https://github.com/facebook/yoga/pull/1013 probably still needs to happen)
Pull Request resolved: https://github.com/facebook/yoga/pull/1422
Reviewed By: yungsters
Differential Revision: D50305438
Pulled By: NickGerleman
fbshipit-source-id: ef9f6f14220a0db066bc30db8dd690a4a82a0b00
Summary: this is fixed now so we can turn it on
Reviewed By: NickGerleman
Differential Revision: D50348206
fbshipit-source-id: 61c2a72164c6f0ee91b1b5b576d3f129e8cfbe40
Summary: Wires up the option to use overflow: scroll in JS, Java, and CPP gentest fixtures.
Reviewed By: NickGerleman
Differential Revision: D50225803
fbshipit-source-id: f71c000b7143ad9e0e34d99e2d5ba2c6186266d1
Summary: after looking into the issue described in https://github.com/facebook/yoga/issues/1208 it seems to apply to position too, so adding tests to confirm
Reviewed By: NickGerleman
Differential Revision: D50154056
fbshipit-source-id: 64dd04ce3ad765526a547fe60b699b664f251c06
Summary: after looking into the issue described in https://github.com/facebook/yoga/issues/1208 it seems to apply to border too, so adding tests to confirm
Reviewed By: NickGerleman
Differential Revision: D50153472
fbshipit-source-id: a50f3e040153086b6a573924b513919dbb94f3c0
Summary: after looking into the issue described in https://github.com/facebook/yoga/issues/1208 it seems to apply to padding too, so adding tests to confirm
Reviewed By: NickGerleman
Differential Revision: D50153085
fbshipit-source-id: bad0ef50389a71a45ec3a58d87c1dea0c2b26024
Summary:
This diff adds the ability to add 2 flags to gentest.rb that can help with debugging that I found myself wanting to use:
* The ability to suspend the script. Meaning the chrome browser will pause after running each fixture so the user can inspect elements to see if their html is as expected. Normally, the browser just redirects to the next fixture
* The ability to run a specific fixture instead of all fixtures. I found myself wanting to do this as I was changing one in the previous diff. If the user input is incorrect it just ignores it.
Hopefully this will help make debugging this script a bit easier for noobs like me :P
Reviewed By: NickGerleman
Differential Revision: D49775228
fbshipit-source-id: 29933029119ee5afc0195213df70d4d2cf881a9e
Summary:
Yoga has a known bug where marginStart and marginEnd will swap with row-reverse flex direction. This is not the intended behavior. On Paper this is also an issue with marginLeft and marginRight (at least we think Paper is the culprit, not exactly clear yet).
margin-start (and end) is not actually valid css. The gentest.rb script will just turn this into margin-left, but the cpp generated will properly test marginStart. This seems a bit weird to be since marginStart != marginLeft AFAIK. Things like RTL and LTR modes might make this test not exactly right. But given how many other tests depend on this quirk I think it is fine to add as is - the end result is the same after all. If not, a followup would be to add support for mapping margin-inline-start (valid css) to marginStart.
Anyway, this diff is to add test coverage for this scenario. Next stop is to actually try to fix this problem, which may be a bit harder :P
See https://github.com/facebook/yoga/issues/1208 for more info.
Reviewed By: NickGerleman
Differential Revision: D49744271
fbshipit-source-id: 75b8dd0cc5c53b2f338476fb70b60006aaa89054
Summary:
If the first element of a line is not contributing (e.g. position absolute), an additional gap will be added to the line, because the first gap element of the line is never identified (wrong start index).
Fix: raise the index of the first line element until we find an element that is contributing to the line.
Pull Request resolved: https://github.com/facebook/yoga/pull/1408
Reviewed By: yungsters
Differential Revision: D49722065
Pulled By: NickGerleman
fbshipit-source-id: 1068cb0b11ae4b04ec8d063e70540cce06181d5a
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1380
X-link: https://github.com/facebook/react-native/pull/39433
Back when rolling out flex gap, we encountered a bug where gap was added to the end of the main axis when a size was not specified.
During flex line justification/sizing, we calculate the amount of space that should be in between children. We erroneously add this, even after the last child element.
For `justify-content`, this space between children is derived from free space along the axis. The only time we have free space is if we had a dimension/dimension constraint already set on the parent. In this case, the extra space added to the end of the flex line is usually never noticed, because we bound `maxLineMainDim` to container dimension constraints at the end of layout, and the error doesn't effect how any children are positioned or sized.
There was at least one screenshot test where this issue showed up though, and I was able to add a slightly different repro where we may have free space without a definite dimension by enforcing a min dimension and not stretching.
{F1091401183}
The new reference is correct, and looking back at diffs, is what this seemed to originally look like when added three years ago. Seems like there may have been a potential regression, but I didn't spot anything suspicious when I looked around the code history.
`betweenMainDim` may still be set for `gap` even if we don't have a sized parent, which makes the extra space propagated to `maxLineMainDim` effect parent size.
Because we were in a code freeze, I opted to have us go with a solution just effecting flex gap, instead of the right one, in case there were any side effects. This cleans up the code to use the right calculation everywhere, and fixes a separate bug, where `endOfLineIndex` and `startOfLineIndex` may not be the last/first in the line if they are out of the layout flow (absolutely positioned, or display: none_
See the original conversation on https://github.com/facebook/yoga/pull/1188
Reviewed By: javache
Differential Revision: D49260049
fbshipit-source-id: 218552c5ff938668b9f257df7a1493e13ded4d0d
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1317
X-link: https://github.com/facebook/react-native/pull/37374
This is edge-casey enough, and I actually broke this in D42282358 without us noticing (I changed height to width of the bottom usage, instead, copy/pasting the value of the top one).
Reviewed By: yungsters
Differential Revision: D45766764
fbshipit-source-id: b600b79b8436534fe48ef2acbfde8ba64068e593
Summary: I was not able to run `ruby gentest.rb` from Yoga. Updating watir seems to fix the issue.
Reviewed By: shwanton, NickGerleman
Differential Revision: D46687292
fbshipit-source-id: 9922996144aa23fc7fa2f0dcb372367121689598
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1302
These C# bindings were contributed as part of ff8f17ac99. They have occasionally been refreshed, but has never really had validation it built continuously, or dedicated maintenance.
There has been a surge of work with https://github.com/facebook/yoga/pull/1207 to try to modernize the build for these, but checking with jkoritzinsky I'm not sure either of us have the time to commit to supporting these at the same level as other bindings.
Some well-known projects like Unity had already abandoned this set of bindings for their own. 016297e35c (diff-c85198aaac9095a5446ed00b0fba8025072d235b2b69dea8aad85abc64a83e1e)
So, as part of the work for an official OSS release, and really trying to define what is deprecated, and what we will try to support, I am removing the in-tree C# bindings from Yoga.
In the past, gaps in Yoga bindings we haven't supported have led to new bindings with dedicated maintainers e.g. [FlexLayout](https://github.com/layoutBox/FlexLayout), [yoga-rs](https://github.com/bschwind/yoga-rs), [yoga-wasm-web](https://github.com/shuding/yoga-wasm-web). My hope is that by removing the C# bindings that we are not supporting, we free up the opportunity for a new version to become the defacto.
Reviewed By: javache
Differential Revision: D46425886
fbshipit-source-id: df964c4d55adf93c4d1e82c104e74ca5ad181612
Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1287
Outputs tests as TypeScript, along with using/testing the new form of enums imported directly from the package.
We need to change how we are telling Jest which variant to run, so that tests can import enums from "yoga-layout" and have it resolve to the entrypoint which has a binary which has already been built.
Reviewed By: yungsters
Differential Revision: D45723545
fbshipit-source-id: 887d929344a78cadec159a07c643b74b76b87c6c