Skip to content

Commit

Permalink
Unset mComponentScope in the root ComponentContext.
Browse files Browse the repository at this point in the history
Summary:
When a `ComponentTree` is initialized with a `ComponentContext` from another Component (from another tree) the global key of the root component is generated in context of a component which is outside the tree. This is generally `null`.

In such a case when a state update is dispatched, and the framework tries to generate the global key for the root component. The root component (which has a non null parent in this case) will ask its parent to generate a global key.

Now the **falsy** parent components child counters haven’t been reset so it will check that this is a new instance of the same component and deduplicate the global key (i.e. append !n). This changes the global keys for all descendants components.

In some cases it can trigger a new state update and the cycle repeat over and over again.

Reviewed By: davidaurelio

Differential Revision: D15363542

fbshipit-source-id: bea8923e7087dbdedb430b3c1af5a47e688e4193
  • Loading branch information
adityasharat authored and facebook-github-bot committed May 18, 2019
1 parent c3bcacf commit 05f11a7
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ static ComponentContext withComponentTree(ComponentContext context, ComponentTre
ComponentContext componentContext =
new ComponentContext(context, new StateHandler(), null, null, null);
componentContext.mComponentTree = componentTree;
componentContext.mComponentScope = null;
componentContext.mLayoutStateFuture = null;

return componentContext;
Expand Down
29 changes: 29 additions & 0 deletions litho-it/src/test/java/com/facebook/litho/ComponentTreeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,16 @@ public void testCreate() {
Assert.assertFalse(componentTreeHasSizeSpec(componentTree));
}

@Test
public void testCreate_ContextIsNotScoped() {
ComponentContext scopedContext =
ComponentContext.withComponentScope(mContext, Row.create(mContext).build());
ComponentTree componentTree = ComponentTree.create(scopedContext, mComponent).build();

ComponentContext c = Whitebox.getInternalState(componentTree, "mContext");
Assert.assertNull(c.getComponentScope());
}

@Test
public void testSetSizeSpec() {
ComponentTree componentTree =
Expand Down Expand Up @@ -202,6 +212,25 @@ public void testSetSizeSpecAsync() {
postSizeSpecChecks(componentTree, "mBackgroundLayoutState");
}

@Test
public void testLayoutState_ContextIsNotScoped() {
ComponentContext scopedContext =
ComponentContext.withComponentScope(mContext, Row.create(mContext).build());
Component root = Column.create(scopedContext).build();

ComponentTree componentTree = ComponentTree.create(scopedContext, root).build();

componentTree.setSizeSpecAsync(mWidthSpec, mHeightSpec);

mLayoutThreadShadowLooper.runOneTask();

LayoutState layoutState = getInternalState(componentTree, "mBackgroundLayoutState");
ComponentContext c = getInternalState(componentTree, "mContext");
assertThat(c).isNotEqualTo(scopedContext);
Assert.assertNull(c.getComponentScope());
assertThat(layoutState.getRootComponent().getScopedContext()).isNotEqualTo(scopedContext);
}

@Test
public void testSetSizeSpecAsyncThenSyncBeforeRunningTask() {
ComponentTree componentTree =
Expand Down

0 comments on commit 05f11a7

Please sign in to comment.