Skip to content

Commit 355ca28

Browse files
NickGerlemanfacebook-github-bot
authored andcommitted
Reland: Sanitize measure function results
Summary: D57285584 was reverted because we have service code with a faulty measure function, and adding logging to Yoga when invalid measurements were received was enough to spike error rate to elevated levels and block release. This is a reland of the below change, with a couple modifications: 1. We log warnings instead of errors, which from what I heard, shouldn't block release, but should still make signal 2. We only zero the dimension which was NaN, to preserve exact behavior ## Original We've started seeing assertion failures in Yoga where a `NaN` value makes its way to an `availableHeight` constraint when measuring Litho tree. Because it's only happening on Litho, I have some suspicion this might be originating from a Litho-specific measure function. This adds sanitization in Yoga to measure function results, where we will log an error, and set size to zero, if either dimension ends up being negative of `NaN`. This doesn't really help track down where the error was happening, but Yoga doesn't have great context to show this to begin with. If we see this is issue, next steps would be Litho internal intrumentation to find culprit. Changelog: [Internal] Reviewed By: sbuggay Differential Revision: D57473295 fbshipit-source-id: 979f1b9a51f5550a8d3ca534276ec191a3cb7b9e
1 parent af72108 commit 355ca28

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <iostream>
1111

1212
#include <yoga/debug/AssertFatal.h>
13+
#include <yoga/debug/Log.h>
1314
#include <yoga/node/Node.h>
1415
#include <yoga/numeric/Comparison.h>
1516

@@ -49,12 +50,31 @@ Node::Node(Node&& node) noexcept
4950
}
5051

5152
YGSize Node::measure(
52-
float width,
53+
float availableWidth,
5354
MeasureMode widthMode,
54-
float height,
55+
float availableHeight,
5556
MeasureMode heightMode) {
56-
return measureFunc_(
57-
this, width, unscopedEnum(widthMode), height, unscopedEnum(heightMode));
57+
const auto size = measureFunc_(
58+
this,
59+
availableWidth,
60+
unscopedEnum(widthMode),
61+
availableHeight,
62+
unscopedEnum(heightMode));
63+
64+
if (yoga::isUndefined(size.height) || size.height < 0 ||
65+
yoga::isUndefined(size.width) || size.width < 0) {
66+
yoga::log(
67+
this,
68+
LogLevel::Warn,
69+
"Measure function returned an invalid dimension to Yoga: [width=%f, height=%f]",
70+
size.width,
71+
size.height);
72+
return {
73+
.width = maxOrDefined(0.0f, size.width),
74+
.height = maxOrDefined(0.0f, size.height)};
75+
}
76+
77+
return size;
5878
}
5979

6080
float Node::baseline(float width, float height) const {

packages/react-native/ReactCommon/yoga/yoga/node/Node.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ class YG_EXPORT Node : public ::YGNode {
6666
}
6767

6868
YGSize measure(
69-
float width,
69+
float availableWidth,
7070
MeasureMode widthMode,
71-
float height,
71+
float availableHeight,
7272
MeasureMode heightMode);
7373

7474
bool hasBaselineFunc() const noexcept {

0 commit comments

Comments
 (0)