-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix case where absolute nodes would sometimes not be cloned (#1675)
Summary: X-link: facebook/react-native#45240 Pull Request resolved: #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
- Loading branch information
1 parent
b9e335e
commit a1e9abb
Showing
4 changed files
with
160 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
#include <gtest/gtest.h> | ||
#include <yoga/Yoga.h> | ||
|
||
static void recursivelyAssertProperNodeOwnership(YGNodeRef node) { | ||
for (size_t i = 0; i < YGNodeGetChildCount(node); ++i) { | ||
const auto child = YGNodeGetChild(node, i); | ||
ASSERT_EQ(node, YGNodeGetOwner(child)); | ||
recursivelyAssertProperNodeOwnership(child); | ||
} | ||
} | ||
|
||
TEST(YogaTest, absolute_node_cloned_with_static_parent) { | ||
YGNodeRef root = YGNodeNew(); | ||
YGNodeStyleSetWidth(root, 100); | ||
YGNodeStyleSetHeight(root, 100); | ||
|
||
YGNodeRef root_child0 = YGNodeNew(); | ||
YGNodeStyleSetPositionType(root_child0, YGPositionTypeStatic); | ||
YGNodeStyleSetWidth(root_child0, 10); | ||
YGNodeStyleSetHeight(root_child0, 10); | ||
YGNodeInsertChild(root, root_child0, 0); | ||
|
||
YGNodeRef root_child0_child0 = YGNodeNew(); | ||
YGNodeStyleSetPositionType(root_child0_child0, YGPositionTypeAbsolute); | ||
YGNodeStyleSetWidthPercent(root_child0_child0, 1); | ||
YGNodeStyleSetHeight(root_child0_child0, 1); | ||
YGNodeInsertChild(root_child0, root_child0_child0, 0); | ||
|
||
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); | ||
|
||
YGNodeRef clonedRoot = YGNodeClone(root); | ||
YGNodeStyleSetWidth(clonedRoot, 110); | ||
YGNodeCalculateLayout(clonedRoot, YGUndefined, YGUndefined, YGDirectionLTR); | ||
|
||
recursivelyAssertProperNodeOwnership(clonedRoot); | ||
|
||
YGNodeFreeRecursive(root); | ||
YGNodeFreeRecursive(clonedRoot); | ||
} | ||
|
||
TEST(YogaTest, absolute_node_cloned_with_static_ancestors) { | ||
YGNodeRef root = YGNodeNew(); | ||
YGNodeStyleSetWidth(root, 100); | ||
YGNodeStyleSetHeight(root, 100); | ||
|
||
YGNodeRef root_child0 = YGNodeNew(); | ||
YGNodeStyleSetPositionType(root_child0, YGPositionTypeStatic); | ||
YGNodeStyleSetWidth(root_child0, 50); | ||
YGNodeStyleSetHeight(root_child0, 50); | ||
YGNodeInsertChild(root, root_child0, 0); | ||
|
||
YGNodeRef root_child0_child0 = YGNodeNew(); | ||
YGNodeStyleSetPositionType(root_child0_child0, YGPositionTypeStatic); | ||
YGNodeStyleSetWidth(root_child0_child0, 40); | ||
YGNodeStyleSetHeight(root_child0_child0, 40); | ||
YGNodeInsertChild(root_child0, root_child0_child0, 0); | ||
|
||
YGNodeRef root_child0_child0_child0 = YGNodeNew(); | ||
YGNodeStyleSetPositionType(root_child0_child0_child0, YGPositionTypeStatic); | ||
YGNodeStyleSetWidth(root_child0_child0_child0, 30); | ||
YGNodeStyleSetHeight(root_child0_child0_child0, 30); | ||
YGNodeInsertChild(root_child0_child0, root_child0_child0_child0, 0); | ||
|
||
YGNodeRef root_child0_child0_child0_child0 = YGNodeNew(); | ||
YGNodeStyleSetPositionType( | ||
root_child0_child0_child0_child0, YGPositionTypeAbsolute); | ||
YGNodeStyleSetWidthPercent(root_child0_child0_child0_child0, 1); | ||
YGNodeStyleSetHeight(root_child0_child0_child0_child0, 1); | ||
YGNodeInsertChild( | ||
root_child0_child0_child0, root_child0_child0_child0_child0, 0); | ||
|
||
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); | ||
|
||
YGNodeRef clonedRoot = YGNodeClone(root); | ||
YGNodeStyleSetWidth(clonedRoot, 110); | ||
YGNodeCalculateLayout(clonedRoot, YGUndefined, YGUndefined, YGDirectionLTR); | ||
|
||
recursivelyAssertProperNodeOwnership(clonedRoot); | ||
|
||
YGNodeFreeRecursive(root); | ||
YGNodeFreeRecursive(clonedRoot); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters