Clone children only during layout, allow mixing shared + owned children
Summary: @public Limit child cloning to layout calculation. This also allows for mixing shared and owned children. Rationale: We do allow for shared children if the caller manages themselves. The single known use case is React Native. So far, we have cloned children eagerly whenever child lists are mutated, or layout is run. This was to allow for a quick check of the owner of any first child, assuming that either *all* or *no* child of a node are shared. For Yoga/Java, we want to get rid of global weak JNI refs, and these are also used to invoke clone callbacks. We can achieve that goal by switching to an alternative approach, passing additional data to the layout pass. This additional data has to be passed to any configured cloning callback. Therefore, it is desirable to **only call cloning functions during the layout pass.** The obvious solution seems to be to not uphold the invariant of the first child determining shared/owned state of all siblings, and allow for a mix of shared and own children. Reviewed By: shergin Differential Revision: D14136223 fbshipit-source-id: 34490cfeeb2170c99d6ed1b9bdcbcedb316813af
This commit is contained in:
committed by
Facebook Github Bot
parent
367a93de88
commit
b1c749075d
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
#include <gtest/gtest.h>
|
||||
#include <yoga/Yoga.h>
|
||||
#include <yoga/YGNode.h>
|
||||
|
||||
TEST(YogaTest, cloning_shared_root) {
|
||||
const YGConfigRef config = YGConfigNew();
|
||||
@@ -104,7 +105,7 @@ TEST(YogaTest, cloning_shared_root) {
|
||||
YGConfigFree(config);
|
||||
}
|
||||
|
||||
TEST(YogaTest, mutating_children_of_a_clone_clones) {
|
||||
TEST(YogaTest, mutating_children_of_a_clone_clones_only_after_layout) {
|
||||
const YGConfigRef config = YGConfigNew();
|
||||
|
||||
const YGNodeRef root = YGNodeNewWithConfig(config);
|
||||
@@ -129,7 +130,7 @@ TEST(YogaTest, mutating_children_of_a_clone_clones) {
|
||||
ASSERT_EQ(1, YGNodeGetChildCount(root2));
|
||||
ASSERT_EQ(2, YGNodeGetChildCount(root3));
|
||||
ASSERT_EQ(root3_child1, YGNodeGetChild(root3, 1));
|
||||
ASSERT_NE(YGNodeGetChild(root2, 0), YGNodeGetChild(root3, 0));
|
||||
ASSERT_EQ(YGNodeGetChild(root2, 0), YGNodeGetChild(root3, 0));
|
||||
|
||||
const YGNodeRef root4 = YGNodeClone(root3);
|
||||
ASSERT_EQ(root3_child1, YGNodeGetChild(root4, 1));
|
||||
@@ -137,7 +138,12 @@ TEST(YogaTest, mutating_children_of_a_clone_clones) {
|
||||
YGNodeRemoveChild(root4, root3_child1);
|
||||
ASSERT_EQ(2, YGNodeGetChildCount(root3));
|
||||
ASSERT_EQ(1, YGNodeGetChildCount(root4));
|
||||
ASSERT_EQ(YGNodeGetChild(root3, 0), YGNodeGetChild(root4, 0));
|
||||
|
||||
YGNodeCalculateLayout(root4, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||
ASSERT_NE(YGNodeGetChild(root3, 0), YGNodeGetChild(root4, 0));
|
||||
YGNodeCalculateLayout(root3, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||
ASSERT_NE(YGNodeGetChild(root2, 0), YGNodeGetChild(root3, 0));
|
||||
|
||||
YGNodeFreeRecursive(root4);
|
||||
YGNodeFreeRecursive(root3);
|
||||
@@ -245,3 +251,34 @@ TEST(YogaTest, cloning_and_freeing) {
|
||||
|
||||
ASSERT_EQ(initialInstanceCount, YGNodeGetInstanceCount());
|
||||
}
|
||||
|
||||
TEST(YogaTest, mixed_shared_and_owned_children) {
|
||||
// Don't try this at home!
|
||||
|
||||
YGNodeRef root0 = YGNodeNew();
|
||||
YGNodeRef root1 = YGNodeNew();
|
||||
|
||||
YGNodeRef root0_child0 = YGNodeNew();
|
||||
YGNodeRef root0_child0_0 = YGNodeNew();
|
||||
YGNodeInsertChild(root0, root0_child0, 0);
|
||||
YGNodeInsertChild(root0_child0, root0_child0_0, 0);
|
||||
|
||||
YGNodeRef root1_child0 = YGNodeNew();
|
||||
YGNodeRef root1_child2 = YGNodeNew();
|
||||
YGNodeInsertChild(root1, root1_child0, 0);
|
||||
YGNodeInsertChild(root1, root1_child2, 1);
|
||||
|
||||
auto children = root1->getChildren();
|
||||
children.insert(children.begin() + 1, root0_child0);
|
||||
root1->setChildren(children);
|
||||
auto secondChild = YGNodeGetChild(root1, 1);
|
||||
ASSERT_EQ(secondChild, YGNodeGetChild(root0, 0));
|
||||
ASSERT_EQ(YGNodeGetChild(secondChild, 0), YGNodeGetChild(root0_child0, 0));
|
||||
|
||||
YGNodeCalculateLayout(root1, YGUndefined, YGUndefined, YGDirectionLTR);
|
||||
secondChild = YGNodeGetChild(root1, 1);
|
||||
ASSERT_NE(secondChild, YGNodeGetChild(root0, 0));
|
||||
ASSERT_EQ(YGNodeGetOwner(secondChild), root1);
|
||||
ASSERT_NE(YGNodeGetChild(secondChild, 0), YGNodeGetChild(root0_child0, 0));
|
||||
ASSERT_EQ(YGNodeGetOwner(YGNodeGetChild(secondChild, 0)), secondChild);
|
||||
}
|
||||
|
Reference in New Issue
Block a user