Skip to content

Commit 9f7cedb

Browse files
priteshrnandgaonkarfacebook-github-bot
authored andcommittedFeb 2, 2018
Remove the use of legacy flag and log the diff if its used
Reviewed By: emilsjolander Differential Revision: D6856812 fbshipit-source-id: e4724d80702cc75c1894e348e137b24e663573d2
1 parent 752427b commit 9f7cedb

File tree

5 files changed

+227
-7
lines changed

5 files changed

+227
-7
lines changed
 

‎ReactCommon/yoga/yoga/YGNode.cpp

+61
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,13 @@ void YGNode::markDirtyAndPropogate() {
572572
}
573573
}
574574

575+
void YGNode::markDirtyAndPropogateDownwards() {
576+
isDirty_ = true;
577+
for_each(children_.begin(), children_.end(), [](YGNodeRef childNode) {
578+
childNode->markDirtyAndPropogateDownwards();
579+
});
580+
}
581+
575582
float YGNode::resolveFlexGrow() {
576583
// Root nodes flexGrow should always be 0
577584
if (parent_ == nullptr) {
@@ -666,3 +673,57 @@ float YGNode::getLeadingPaddingAndBorder(
666673
const float widthSize) {
667674
return getLeadingPadding(axis, widthSize) + getLeadingBorder(axis);
668675
}
676+
677+
bool YGNode::didUseLegacyFlag() {
678+
bool didUseLegacyFlag = layout_.didUseLegacyFlag;
679+
if (didUseLegacyFlag) {
680+
return true;
681+
}
682+
for (const auto& child : children_) {
683+
if (child->layout_.didUseLegacyFlag) {
684+
didUseLegacyFlag = true;
685+
break;
686+
}
687+
}
688+
return didUseLegacyFlag;
689+
}
690+
691+
void YGNode::setAndPropogateUseLegacyFlag(bool useLegacyFlag) {
692+
config_->useLegacyStretchBehaviour = useLegacyFlag;
693+
for_each(children_.begin(), children_.end(), [=](YGNodeRef childNode) {
694+
childNode->getConfig()->useLegacyStretchBehaviour = useLegacyFlag;
695+
});
696+
}
697+
698+
void YGNode::setLayoutDoesLegacyFlagAffectsLayout(
699+
bool doesLegacyFlagAffectsLayout) {
700+
layout_.doesLegacyStretchFlagAffectsLayout = doesLegacyFlagAffectsLayout;
701+
}
702+
703+
void YGNode::setLayoutDidUseLegacyFlag(bool didUseLegacyFlag) {
704+
layout_.didUseLegacyFlag = didUseLegacyFlag;
705+
}
706+
707+
bool YGNode::isLayoutTreeEqualToNode(const YGNode& node) const {
708+
if (children_.size() != node.children_.size()) {
709+
return false;
710+
}
711+
if (layout_ != node.layout_) {
712+
return false;
713+
}
714+
if (children_.size() == 0) {
715+
return true;
716+
}
717+
718+
bool isLayoutTreeEqual = true;
719+
YGNodeRef otherNodeChildren = nullptr;
720+
for (std::vector<YGNodeRef>::size_type i = 0; i < children_.size(); ++i) {
721+
otherNodeChildren = node.children_[i];
722+
isLayoutTreeEqual =
723+
children_[i]->isLayoutTreeEqualToNode(*otherNodeChildren);
724+
if (!isLayoutTreeEqual) {
725+
return false;
726+
}
727+
}
728+
return isLayoutTreeEqual;
729+
}

‎ReactCommon/yoga/yoga/YGNode.h

+6
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ struct YGNode {
129129
const float mainSize,
130130
const float crossSize,
131131
const float parentWidth);
132+
void setAndPropogateUseLegacyFlag(bool useLegacyFlag);
133+
void setLayoutDoesLegacyFlagAffectsLayout(bool doesLegacyFlagAffectsLayout);
134+
void setLayoutDidUseLegacyFlag(bool didUseLegacyFlag);
135+
void markDirtyAndPropogateDownwards();
132136

133137
// Other methods
134138
YGValue marginLeadingValue(const YGFlexDirection axis) const;
@@ -150,4 +154,6 @@ struct YGNode {
150154
float resolveFlexGrow();
151155
float resolveFlexShrink();
152156
bool isNodeFlexible();
157+
bool didUseLegacyFlag();
158+
bool isLayoutTreeEqualToNode(const YGNode& node) const;
153159
};

‎ReactCommon/yoga/yoga/Yoga-internal.h

+72-4
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,43 @@ bool YGValueArrayEqual(
4444
return areEqual;
4545
}
4646

47-
typedef struct YGCachedMeasurement {
47+
struct YGCachedMeasurement {
4848
float availableWidth;
4949
float availableHeight;
5050
YGMeasureMode widthMeasureMode;
5151
YGMeasureMode heightMeasureMode;
5252

5353
float computedWidth;
5454
float computedHeight;
55-
} YGCachedMeasurement;
55+
56+
bool operator==(YGCachedMeasurement measurement) const {
57+
bool isEqual = widthMeasureMode == measurement.widthMeasureMode &&
58+
heightMeasureMode == measurement.heightMeasureMode;
59+
60+
if (!std::isnan(availableWidth) ||
61+
!std::isnan(measurement.availableWidth)) {
62+
isEqual = isEqual && availableWidth == measurement.availableWidth;
63+
}
64+
if (!std::isnan(availableHeight) ||
65+
!std::isnan(measurement.availableHeight)) {
66+
isEqual = isEqual && availableHeight == measurement.availableHeight;
67+
}
68+
if (!std::isnan(computedWidth) || !std::isnan(measurement.computedWidth)) {
69+
isEqual = isEqual && computedWidth == measurement.computedWidth;
70+
}
71+
if (!std::isnan(
72+
computedHeight || !std::isnan(measurement.computedHeight))) {
73+
isEqual = isEqual && computedHeight == measurement.computedHeight;
74+
}
75+
76+
return availableWidth == measurement.availableWidth &&
77+
availableHeight == measurement.availableHeight &&
78+
widthMeasureMode == measurement.widthMeasureMode &&
79+
heightMeasureMode == measurement.heightMeasureMode &&
80+
computedWidth == measurement.computedWidth &&
81+
computedHeight == measurement.computedHeight;
82+
}
83+
};
5684

5785
// This value was chosen based on empiracle data. Even the most complicated
5886
// layouts should not require more than 16 entries to fit within the cache.
@@ -80,6 +108,44 @@ struct YGLayout {
80108
std::array<float, 2> measuredDimensions;
81109

82110
YGCachedMeasurement cachedLayout;
111+
bool didUseLegacyFlag;
112+
bool doesLegacyStretchFlagAffectsLayout;
113+
114+
bool operator==(YGLayout layout) const {
115+
bool isEqual = position == layout.position &&
116+
dimensions == layout.dimensions && margin == layout.margin &&
117+
border == layout.border && padding == layout.padding &&
118+
direction == layout.direction && hadOverflow == layout.hadOverflow &&
119+
lastParentDirection == layout.lastParentDirection &&
120+
nextCachedMeasurementsIndex == layout.nextCachedMeasurementsIndex &&
121+
cachedLayout == layout.cachedLayout;
122+
123+
for (uint32_t i = 0; i < YG_MAX_CACHED_RESULT_COUNT && isEqual; ++i) {
124+
isEqual =
125+
isEqual && cachedMeasurements[i] == layout.cachedMeasurements[i];
126+
}
127+
128+
if (!YGFloatIsUndefined(computedFlexBasis) ||
129+
!YGFloatIsUndefined(layout.computedFlexBasis)) {
130+
isEqual = isEqual && (computedFlexBasis == layout.computedFlexBasis);
131+
}
132+
if (!YGFloatIsUndefined(measuredDimensions[0]) ||
133+
!YGFloatIsUndefined(layout.measuredDimensions[0])) {
134+
isEqual =
135+
isEqual && (measuredDimensions[0] == layout.measuredDimensions[0]);
136+
}
137+
if (!YGFloatIsUndefined(measuredDimensions[1]) ||
138+
!YGFloatIsUndefined(layout.measuredDimensions[1])) {
139+
isEqual =
140+
isEqual && (measuredDimensions[1] == layout.measuredDimensions[1]);
141+
}
142+
143+
return isEqual;
144+
}
145+
146+
bool operator!=(YGLayout layout) const {
147+
return !(*this == layout);
148+
}
83149
};
84150

85151
struct YGStyle {
@@ -150,15 +216,15 @@ struct YGStyle {
150216
}
151217
};
152218

153-
typedef struct YGConfig {
219+
struct YGConfig {
154220
bool experimentalFeatures[YGExperimentalFeatureCount + 1];
155221
bool useWebDefaults;
156222
bool useLegacyStretchBehaviour;
157223
float pointScaleFactor;
158224
YGLogger logger;
159225
YGNodeClonedFunc cloneNodeCallback;
160226
void* context;
161-
} YGConfig;
227+
};
162228

163229
#define YG_UNDEFINED_VALUES \
164230
{ .value = YGUndefined, .unit = YGUnitUndefined }
@@ -272,6 +338,8 @@ static const YGLayout gYGNodeLayoutDefaults = {
272338
.computedWidth = -1,
273339
.computedHeight = -1,
274340
},
341+
.didUseLegacyFlag = false,
342+
.doesLegacyStretchFlagAffectsLayout = false,
275343
};
276344

277345
extern bool YGFloatsEqual(const float a, const float b);

‎ReactCommon/yoga/yoga/Yoga.cpp

+87-3
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ bool YGNodeIsDirty(YGNodeRef node) {
211211
return node->isDirty();
212212
}
213213

214+
bool YGNodeLayoutGetDidUseLegacyFlag(const YGNodeRef node) {
215+
return node->didUseLegacyFlag();
216+
}
217+
214218
int32_t gNodeInstanceCount = 0;
215219
int32_t gConfigInstanceCount = 0;
216220

@@ -243,6 +247,29 @@ YGNodeRef YGNodeClone(YGNodeRef oldNode) {
243247
return node;
244248
}
245249

250+
static YGNodeRef YGNodeDeepClone(YGNodeRef oldNode) {
251+
YGNodeRef node = YGNodeClone(oldNode);
252+
YGVector vec = YGVector();
253+
vec.reserve(oldNode->getChildren().size());
254+
YGNodeRef childNode = nullptr;
255+
for (auto& item : oldNode->getChildren()) {
256+
childNode = YGNodeDeepClone(item);
257+
childNode->setParent(node);
258+
vec.push_back(childNode);
259+
}
260+
node->setChildren(vec);
261+
262+
if (oldNode->getNextChild() != nullptr) {
263+
node->setNextChild(YGNodeDeepClone(oldNode->getNextChild()));
264+
}
265+
266+
if (node->getConfig() != nullptr) {
267+
node->setConfig(new YGConfig(*node->getConfig()));
268+
}
269+
270+
return node;
271+
}
272+
246273
void YGNodeFree(const YGNodeRef node) {
247274
if (node->getParent()) {
248275
node->getParent()->removeChild(node);
@@ -1975,10 +2002,15 @@ static void YGNodelayoutImpl(const YGNodeRef node,
19752002
} else {
19762003
if (!node->getConfig()->useLegacyStretchBehaviour &&
19772004
(totalFlexGrowFactors == 0 || node->resolveFlexGrow() == 0)) {
1978-
// If we don't have any children to flex or we can't flex the node itself,
1979-
// space we've used is all space we need. Root node also should be shrunk to minimum
2005+
// If we don't have any children to flex or we can't flex the node
2006+
// itself, space we've used is all space we need. Root node also
2007+
// should be shrunk to minimum
19802008
availableInnerMainDim = sizeConsumedOnCurrentLine;
19812009
}
2010+
2011+
if (node->getConfig()->useLegacyStretchBehaviour) {
2012+
node->setLayoutDidUseLegacyFlag(true);
2013+
}
19822014
sizeBasedOnContent = !node->getConfig()->useLegacyStretchBehaviour;
19832015
}
19842016
}
@@ -3330,7 +3362,6 @@ void YGNodeCalculateLayout(const YGNodeRef node,
33303362
// input
33313363
// parameters don't change.
33323364
gCurrentGenerationCount++;
3333-
33343365
node->resolveDimension();
33353366
float width = YGUndefined;
33363367
YGMeasureMode widthMeasureMode = YGMeasureModeUndefined;
@@ -3396,6 +3427,59 @@ void YGNodeCalculateLayout(const YGNodeRef node,
33963427
YGPrintOptionsStyle));
33973428
}
33983429
}
3430+
3431+
bool didUseLegacyFlag = node->didUseLegacyFlag();
3432+
3433+
// We want to get rid off `useLegacyStretchBehaviour` from YGConfig. But we
3434+
// aren't sure whether client's of yoga have gotten rid off this flag or not.
3435+
// So logging this in YGLayout would help to find out the call sites depending
3436+
// on this flag. This check would be removed once we are sure no one is
3437+
// dependent on this flag anymore.
3438+
if (didUseLegacyFlag) {
3439+
const YGNodeRef originalNode = YGNodeDeepClone(node);
3440+
originalNode->resolveDimension();
3441+
// Recursively mark nodes as dirty
3442+
originalNode->markDirtyAndPropogateDownwards();
3443+
gCurrentGenerationCount++;
3444+
// Rerun the layout, and calculate the diff
3445+
originalNode->setAndPropogateUseLegacyFlag(false);
3446+
if (YGLayoutNodeInternal(
3447+
originalNode,
3448+
width,
3449+
height,
3450+
parentDirection,
3451+
widthMeasureMode,
3452+
heightMeasureMode,
3453+
parentWidth,
3454+
parentHeight,
3455+
true,
3456+
"initial",
3457+
originalNode->getConfig())) {
3458+
originalNode->setPosition(
3459+
originalNode->getLayout().direction,
3460+
parentWidth,
3461+
parentHeight,
3462+
parentWidth);
3463+
YGRoundToPixelGrid(
3464+
originalNode,
3465+
originalNode->getConfig()->pointScaleFactor,
3466+
0.0f,
3467+
0.0f);
3468+
3469+
// Set whether the two layouts are different or not.
3470+
node->setLayoutDoesLegacyFlagAffectsLayout(
3471+
!originalNode->isLayoutTreeEqualToNode(*node));
3472+
3473+
if (gPrintTree) {
3474+
YGNodePrint(
3475+
originalNode,
3476+
(YGPrintOptions)(
3477+
YGPrintOptionsLayout | YGPrintOptionsChildren |
3478+
YGPrintOptionsStyle));
3479+
}
3480+
}
3481+
YGNodeFreeRecursive(originalNode);
3482+
}
33993483
}
34003484

34013485
void YGConfigSetLogger(const YGConfigRef config, YGLogger logger) {

‎ReactCommon/yoga/yoga/Yoga.h

+1
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ void YGNodeSetHasNewLayout(YGNodeRef node, bool hasNewLayout);
175175
YGNodeType YGNodeGetNodeType(YGNodeRef node);
176176
void YGNodeSetNodeType(YGNodeRef node, YGNodeType nodeType);
177177
bool YGNodeIsDirty(YGNodeRef node);
178+
bool YGNodeLayoutGetDidUseLegacyFlag(const YGNodeRef node);
178179

179180
YG_NODE_STYLE_PROPERTY(YGDirection, Direction, direction);
180181
YG_NODE_STYLE_PROPERTY(YGFlexDirection, FlexDirection, flexDirection);

0 commit comments

Comments
 (0)
Please sign in to comment.