Remove Fabric android implementation

Summary: This diff removes the Fabric Android implementation in favor of Fabric C++, as part of another diff I'm going to move the fabricxx package into fabric package

Reviewed By: shergin

Differential Revision: D9841240

fbshipit-source-id: c7922b7bfb9885f33b1f52237ec7cf00c1df96fb
This commit is contained in:
David Vacca
2018-09-19 07:59:07 -07:00
committed by Facebook Github Bot
parent 5c23f20cee
commit 7e7040b7bd
37 changed files with 28 additions and 2947 deletions

View File

@@ -1,40 +0,0 @@
load("//tools/build_defs/oss:rn_defs.bzl", "IS_OSS_BUILD", "react_native_dep", "react_native_target", "react_native_tests_target", "rn_robolectric_test")
rn_robolectric_test(
name = "fabric",
srcs = glob(["**/*.java"]),
contacts = ["oncall+fbandroid_sheriff@xmail.facebook.com"],
resources = glob([
"**/*.txt",
"**/*.json",
]),
visibility = [
"PUBLIC",
],
deps = [
"xplat//yoga/java:java",
react_native_dep("third-party/java/assertj:assertj-core"),
react_native_dep("third-party/java/fest:fest"),
react_native_dep("third-party/java/fest:fest_android"),
react_native_dep("third-party/java/guava:guava"),
react_native_dep("third-party/java/jackson:jackson"),
react_native_dep("third-party/java/jsr-305:jsr-305"),
react_native_dep("third-party/java/jsr-330:jsr-330"),
react_native_dep("third-party/java/junit:junit"),
react_native_dep("third-party/java/mockito:mockito"),
react_native_dep("third-party/java/robolectric3/robolectric:robolectric"),
react_native_dep("libraries/fbcore/src/test/java/com/facebook/powermock:powermock"),
react_native_dep("libraries/soloader/java/com/facebook/soloader:soloader"),
react_native_dep("third-party/android/support/v4:lib-support-v4"),
react_native_target("java/com/facebook/react:react"),
react_native_target("java/com/facebook/react/bridge:bridge"),
react_native_target("java/com/facebook/react/common:common"),
react_native_target("java/com/facebook/react/fabric:fabric"),
react_native_target("java/com/facebook/react/modules/core:core"),
react_native_target("java/com/facebook/react/uimanager:uimanager"),
react_native_target("java/com/facebook/react/views/text:text"),
react_native_target("java/com/facebook/react/views/view:view"),
react_native_target("java/com/facebook/react/views/progressbar:progressbar"),
react_native_tests_target("java/com/facebook/react/bridge:testhelpers"),
],
) if not IS_OSS_BUILD else None

View File

@@ -1,205 +0,0 @@
// Copyright (c) Facebook, Inc. and its affiliates.
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
package com.facebook.react.fabric;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import com.facebook.react.bridge.CatalystInstance;
import com.facebook.react.bridge.JavaScriptContextHolder;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactTestHelper;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.uimanager.NativeViewHierarchyManager;
import com.facebook.react.uimanager.ReactShadowNode;
import com.facebook.react.uimanager.ReactShadowNodeImpl;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIViewOperationQueue;
import com.facebook.react.uimanager.ViewAtIndex;
import com.facebook.react.uimanager.ViewManager;
import com.facebook.react.uimanager.ViewManagerRegistry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
/** Tests {@link FabricReconciler} */
@RunWith(RobolectricTestRunner.class)
public class FabricReconcilerTest {
private FabricReconciler mFabricReconciler;
private FabricUIManager mFabricUIManager;
private MockUIViewOperationQueue mMockUIViewOperationQueue;
@Before
public void setUp() {
CatalystInstance catalystInstance = ReactTestHelper.createMockCatalystInstance();
ReactApplicationContext reactContext =
new ReactApplicationContext(RuntimeEnvironment.application);
reactContext.initializeWithInstance(catalystInstance);
List<ViewManager> viewManagers = new ArrayList<>();
ViewManagerRegistry viewManagerRegistry = new ViewManagerRegistry(viewManagers);
JavaScriptContextHolder jsContext = mock(JavaScriptContextHolder.class);
EventDispatcher eventDispatcher = mock(EventDispatcher.class);
mFabricUIManager = new FabricUIManager(reactContext, viewManagerRegistry, jsContext, eventDispatcher);
mMockUIViewOperationQueue = new MockUIViewOperationQueue(reactContext);
mFabricReconciler = new FabricReconciler(mMockUIViewOperationQueue);
}
@Test
public void testSimpleHierarchy() {
ReactShadowNode parent = createNode(0);
ReactShadowNode child1 = createNode(1);
ReactShadowNode child2 = createNode(2);
addChildren(parent, child1, child2);
ReactShadowNode parentCloned = createNode(0);
ReactShadowNode child3 = createNode(3);
addChildren(parentCloned, child3, child2);
mFabricReconciler.manageChildren(parent, parentCloned);
List<ManageChildrenOperation> expectedOperations = new ArrayList<>();
expectedOperations.add(
new ManageChildrenOperation(
0,
new int[] {0, 1},
new ViewAtIndex[] {new ViewAtIndex(3, 0), new ViewAtIndex(2, 1)},
new int[] {1}));
assertThat(mMockUIViewOperationQueue.getOperations()).isEqualTo(expectedOperations);
}
@Test
public void testVirtualNodes() {
ReactShadowNode parent = createNode(0);
ReactShadowNode child1 = createVirtualNode(1);
ReactShadowNode child2 = createVirtualNode(2);
ReactShadowNode child3 = createVirtualNode(3);
addChildren(parent, child1, child2, child3);
ReactShadowNode parentCloned = createNode(0);
ReactShadowNode child4 = createVirtualNode(4);
addChildren(parentCloned, child1, child4, child3);
mFabricReconciler.manageChildren(parent, parentCloned);
List<ManageChildrenOperation> expectedOperations = new ArrayList<>();
assertThat(mMockUIViewOperationQueue.getOperations()).isEqualTo(expectedOperations);
}
private void addChildren(ReactShadowNode parent, ReactShadowNode... children) {
for (ReactShadowNode child : children) {
mFabricUIManager.appendChild(parent, child);
}
}
private static ReactShadowNode createNode(int tag) {
return createNode(tag, false);
}
private static ReactShadowNode createVirtualNode(int tag) {
return createNode(tag, true);
}
private static ReactShadowNode createNode(int tag, boolean virtual) {
ReactShadowNode node;
if (virtual) {
node = new VirtualReactShadowNode();
} else {
node = new ReactShadowNodeImpl();
}
node.setReactTag(tag);
node.setViewClassName("View");
node.setThemedContext(mock(ThemedReactContext.class));
return node;
}
private static class VirtualReactShadowNode extends ReactShadowNodeImpl {
VirtualReactShadowNode() {}
VirtualReactShadowNode(VirtualReactShadowNode original) {
super(original);
}
@Override
public boolean isVirtual() {
return true;
}
@Override
public ReactShadowNodeImpl copy() {
return new VirtualReactShadowNode(this);
}
}
private static class ManageChildrenOperation {
private int mTag;
private int[] mIndicesToRemove;
private ViewAtIndex[] mViewsToAdd;
private int[] mTagsToRemove;
private ManageChildrenOperation(
int tag, int[] indicesToRemove, ViewAtIndex[] viewsToAdd, int[] tagsToRemove) {
mTag = tag;
mIndicesToRemove = indicesToRemove;
mViewsToAdd = viewsToAdd;
mTagsToRemove = tagsToRemove;
}
@Override
public boolean equals(Object obj) {
if (obj == null || obj.getClass() != getClass()) {
return false;
}
ManageChildrenOperation op = (ManageChildrenOperation) obj;
return mTag == op.mTag
&& Arrays.equals(mIndicesToRemove, op.mIndicesToRemove)
&& Arrays.equals(mViewsToAdd, op.mViewsToAdd)
&& Arrays.equals(mTagsToRemove, op.mTagsToRemove);
}
@Override
public int hashCode() {
return Arrays.deepHashCode(new Object[] {mTag, mIndicesToRemove, mViewsToAdd, mTagsToRemove});
}
@Override
public String toString() {
return "ManageChildrenOperation \n\tindicesToRemove: "
+ Arrays.toString(mIndicesToRemove)
+ "\n\tviewsToAdd: "
+ Arrays.toString(mViewsToAdd)
+ "\n\ttagsToRemove: "
+ Arrays.toString(mTagsToRemove);
}
}
private static class MockUIViewOperationQueue extends UIViewOperationQueue {
private List<ManageChildrenOperation> mOperations;
private MockUIViewOperationQueue(ReactApplicationContext context) {
super(context, mock(NativeViewHierarchyManager.class), 0);
mOperations = new ArrayList<>();
}
@Override
public void enqueueManageChildren(
int reactTag, int[] indicesToRemove, ViewAtIndex[] viewsToAdd, int[] tagsToDelete) {
mOperations.add(
new ManageChildrenOperation(reactTag, indicesToRemove, viewsToAdd, tagsToDelete));
}
public List<ManageChildrenOperation> getOperations() {
return Collections.unmodifiableList(mOperations);
}
}
}

View File

@@ -1,336 +0,0 @@
// Copyright (c) Facebook, Inc. and its affiliates.
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
package com.facebook.react.fabric;
import static org.fest.assertions.api.Assertions.assertThat;
import static com.facebook.react.bridge.InstanceHandleHelper.randomInstanceHandle;
import static org.mockito.Mockito.mock;
import com.facebook.react.ReactRootView;
import com.facebook.react.bridge.JavaScriptContextHolder;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactTestHelper;
import com.facebook.react.bridge.ReadableNativeMap;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.uimanager.ReactShadowNode;
import com.facebook.react.uimanager.ReactShadowNodeImpl;
import com.facebook.react.uimanager.Spacing;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewManager;
import com.facebook.react.uimanager.ViewManagerRegistry;
import com.facebook.react.views.progressbar.ProgressBarShadowNode;
import com.facebook.react.views.text.ReactRawTextManager;
import com.facebook.react.views.text.ReactRawTextShadowNode;
import com.facebook.react.views.text.ReactTextViewManager;
import com.facebook.react.views.view.ReactViewManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.fest.assertions.data.Offset;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
/** Tests {@link FabricUIManager} */
@RunWith(RobolectricTestRunner.class)
public class FabricUIManagerTest {
private FabricUIManager mFabricUIManager;
private ThemedReactContext mThemedReactContext;
private int mNextReactTag;
@Before
public void setUp() throws Exception {
mNextReactTag = 2;
ReactApplicationContext reactContext = new ReactApplicationContext(RuntimeEnvironment.application);
reactContext.initializeWithInstance(ReactTestHelper.createMockCatalystInstance());
mThemedReactContext = new ThemedReactContext(reactContext, reactContext);
List<ViewManager> viewManagers =
Arrays.<ViewManager>asList(
new ReactViewManager(), new ReactTextViewManager(), new ReactRawTextManager());
ViewManagerRegistry viewManagerRegistry = new ViewManagerRegistry(viewManagers);
JavaScriptContextHolder jsContext = mock(JavaScriptContextHolder.class);
EventDispatcher eventDispatcher = mock(EventDispatcher.class);
mFabricUIManager = new FabricUIManager(reactContext, viewManagerRegistry, jsContext, eventDispatcher);
}
@Test
public void testCreateNode() {
ReactRootView rootView =
new ReactRootView(RuntimeEnvironment.application.getApplicationContext());
int rootTag = mFabricUIManager.addRootView(rootView);
int reactTag = mNextReactTag++;
String viewClass = ReactViewManager.REACT_CLASS;
ReactShadowNode node =
mFabricUIManager.createNode(reactTag, viewClass, rootTag, null, randomInstanceHandle());
assertThat(reactTag).isEqualTo(node.getReactTag());
assertThat(viewClass).isEqualTo(node.getViewClass());
assertThat(rootTag).isEqualTo(rootTag);
}
@Test
public void testCreateMultpleRootViews() {
createAndRenderRootView();
createAndRenderRootView();
}
private int createAndRenderRootView() {
ReactRootView rootView =
new ReactRootView(RuntimeEnvironment.application.getApplicationContext());
int rootTag = mFabricUIManager.addRootView(rootView);
int reactTag = mNextReactTag++;
String viewClass = ReactViewManager.REACT_CLASS;
ReactShadowNode node =
mFabricUIManager.createNode(reactTag, viewClass, rootTag, null, randomInstanceHandle());
List<ReactShadowNode> childSet = mFabricUIManager.createChildSet(rootTag);
mFabricUIManager.appendChildToSet(childSet, node);
mFabricUIManager.completeRoot(rootTag, childSet);
return rootTag;
}
@Test
public void testCloneNode() {
ReactShadowNode node = createViewNode();
ReactShadowNode child = createViewNode();
node.addChildAt(child, 0);
ReactShadowNode clonedNode = mFabricUIManager.cloneNode(node);
assertThat(clonedNode).isNotSameAs(node);
assertThat(clonedNode.getOriginalReactShadowNode()).isSameAs(node);
assertSameFields(clonedNode, node);
assertSameChildren(clonedNode, node);
assertThat(clonedNode.getChildAt(0)).isEqualTo(child);
}
@Test
public void testDefaultSpacingCloning() {
ReactShadowNode node = createViewNode();
node.setDefaultPadding(Spacing.LEFT, 10);
ReactShadowNode clonedNode = mFabricUIManager.cloneNode(node);
node.setDefaultPadding(Spacing.LEFT, 20);
assertThat(clonedNode.getStylePadding(Spacing.LEFT).value).isEqualTo(10f, Offset.offset(0.01f));
assertThat(node.getStylePadding(Spacing.LEFT).value).isEqualTo(20f, Offset.offset(0.01f));
}
@Test
public void testCloneVirtualNode() {
ReactRawTextShadowNode node = new ReactRawTextShadowNode();
node.setText("test");
assertThat(node.isVirtual()).isTrue();
ReactRawTextShadowNode clonedNode = (ReactRawTextShadowNode) node.mutableCopy(randomInstanceHandle());
assertThat(clonedNode.getText()).isEqualTo("test");
assertThat(clonedNode).isNotEqualTo(node);
}
@Test
public void testLayoutProgressBarAfterClonning() {
ProgressBarShadowNode node = new ProgressBarShadowNode();
node.setThemedContext(mThemedReactContext);
ProgressBarShadowNode clone = (ProgressBarShadowNode) node.mutableCopy(randomInstanceHandle());
clone.calculateLayout();
}
@Test
public void testCloneNodeWithNewChildren() {
ReactShadowNode node = createViewNode();
ReactShadowNode child = createViewNode();
node.addChildAt(child, 0);
ReactShadowNode clonedNode = mFabricUIManager.cloneNodeWithNewChildren(node);
assertThat(clonedNode.getChildCount()).isZero();
assertSameFields(clonedNode, node);
}
@Test
public void testCloneNodeWithNewProps() {
ReactShadowNode node = createViewNode();
ReadableNativeMap props = null; // TODO(ayc): Figure out how to create a Native map from tests.
ReactShadowNode clonedNode = mFabricUIManager.cloneNodeWithNewProps(node, props);
}
@Test
public void testCloneNodeWithNewChildrenAndProps() {
ReactShadowNode node = createViewNode();
ReadableNativeMap props = null;
ReactShadowNode clonedNode = mFabricUIManager.cloneNodeWithNewChildrenAndProps(node, props);
assertThat(clonedNode.getChildCount()).isZero();
}
@Test
public void testAppendChild() {
ReactShadowNode node = createViewNode();
ReactShadowNode child = createViewNode();
mFabricUIManager.appendChild(node, child);
assertThat(node.getChildCount()).isEqualTo(1);
assertThat(node.getChildAt(0)).isEqualTo(child);
}
@Test
public void testCreateChildSet() {
List<ReactShadowNode> childSet = mFabricUIManager.createChildSet(0);
assertThat(childSet).isEmpty();
}
@Test
public void testAppendChildToSet() {
ReactShadowNode node = createViewNode();
List<ReactShadowNode> childSet = mFabricUIManager.createChildSet(0);
mFabricUIManager.appendChildToSet(childSet, node);
assertThat(childSet).hasSize(1);
assertThat(childSet).contains(node);
}
@Test(expected = AssertionError.class)
public void testCompleteRootBeforeAddRoot() {
mFabricUIManager.completeRoot(0, new ArrayList<ReactShadowNode>());
}
@Test
public void testCompleteRoot() {
ReactRootView rootView =
new ReactRootView(RuntimeEnvironment.application.getApplicationContext());
int rootTag = mFabricUIManager.addRootView(rootView);
List<ReactShadowNode> children = mFabricUIManager.createChildSet(rootTag);
mFabricUIManager.completeRoot(rootTag, children);
}
@Test
public void testSealReactShadowNode() {
ReactRootView rootView =
new ReactRootView(RuntimeEnvironment.application.getApplicationContext());
int rootTag = mFabricUIManager.addRootView(rootView);
String viewClass = ReactViewManager.REACT_CLASS;
ReactShadowNode container = mFabricUIManager.createNode(6, viewClass, rootTag, null, randomInstanceHandle());
List<ReactShadowNode> childSet = mFabricUIManager.createChildSet(rootTag);
mFabricUIManager.appendChildToSet(childSet, container);
assertThat(container.isSealed()).isFalse();
mFabricUIManager.completeRoot(rootTag, childSet);
assertThat(container.isSealed()).isTrue();
}
/**
* Tests that cloned text nodes will not share measure functions
*/
@Test
public void testTextMutableClone() {
ReactRootView rootView =
new ReactRootView(RuntimeEnvironment.application.getApplicationContext());
int rootTag = mFabricUIManager.addRootView(rootView);
ReactShadowNode text =
mFabricUIManager.createNode(0, ReactTextViewManager.REACT_CLASS, rootTag, null, randomInstanceHandle());
assertThat(text.isMeasureDefined()).isTrue();
ReactShadowNode textCopy = text.mutableCopy(randomInstanceHandle());
assertThat(textCopy.isMeasureDefined()).isTrue();
textCopy.setStyleWidth(200);
text.onBeforeLayout();
text.calculateLayout();
textCopy.onBeforeLayout();
textCopy.calculateLayout();
assertThat(text.getLayoutWidth()).isNotEqualTo(textCopy.getLayoutWidth());
}
/**
* Verifies that the reconciliation phase will always set the originalNode field of every node in
* the tree to null once completeRoot has finished to prevent memory leaks.
*/
@Test
public void testRemoveOriginalNodeReferences() {
ReactRootView rootView =
new ReactRootView(RuntimeEnvironment.application.getApplicationContext());
int rootTag = mFabricUIManager.addRootView(rootView);
String viewClass = ReactViewManager.REACT_CLASS;
ReactShadowNode aa = mFabricUIManager.createNode(2, viewClass, rootTag, null, randomInstanceHandle());
ReactShadowNode a = mFabricUIManager.createNode(3, viewClass, rootTag, null, randomInstanceHandle());
mFabricUIManager.appendChild(a, aa);
ReactShadowNode bb = mFabricUIManager.createNode(4, viewClass, rootTag, null, randomInstanceHandle());
ReactShadowNode b = mFabricUIManager.createNode(5, viewClass, rootTag, null, randomInstanceHandle());
mFabricUIManager.appendChild(b, bb);
ReactShadowNode container = mFabricUIManager.createNode(6, viewClass, rootTag, null, randomInstanceHandle());
mFabricUIManager.appendChild(container, a);
mFabricUIManager.appendChild(container, b);
List<ReactShadowNode> childSet = mFabricUIManager.createChildSet(rootTag);
mFabricUIManager.appendChildToSet(childSet, container);
mFabricUIManager.completeRoot(rootTag, childSet);
ReactShadowNode aaClone = mFabricUIManager.cloneNodeWithNewProps(aa, null);
ReactShadowNode aClone = mFabricUIManager.cloneNodeWithNewChildren(a);
mFabricUIManager.appendChild(aClone, aaClone);
ReactShadowNode containerClone = mFabricUIManager.cloneNodeWithNewChildren(container);
mFabricUIManager.appendChild(containerClone, b);
mFabricUIManager.appendChild(containerClone, aClone);
List<ReactShadowNode> childSet2 = mFabricUIManager.createChildSet(rootTag);
mFabricUIManager.appendChildToSet(childSet2, containerClone);
mFabricUIManager.completeRoot(rootTag, childSet2);
ReactShadowNode[] nodes =
new ReactShadowNode[] {aa, a, bb, b, container, aaClone, aClone, containerClone};
for (ReactShadowNode node : nodes) {
assertThat(node.getOriginalReactShadowNode()).isNull();
}
}
private void assertSameChildren(ReactShadowNode node1, ReactShadowNode node2) {
assertThat(node1.getChildCount()).isEqualTo(node2.getChildCount());
for (int i = 0; i < node1.getChildCount(); i++) {
assertThat(node1.getChildAt(i)).isEqualTo(node2.getChildAt(i));
}
}
private void assertSameFields(ReactShadowNode node1, ReactShadowNode node2) {
assertThat(node1.getReactTag()).isEqualTo(node2.getReactTag());
assertThat(node1.getViewClass()).isEqualTo(node2.getViewClass());
assertThat(node2.getParent()).isNull();
assertThat(node1.getThemedContext()).isEqualTo(node2.getThemedContext());
assertThat(node1.isVirtual()).isEqualTo(node2.isVirtual());
assertThat(node1.getLayoutDirection()).isEqualTo(node2.getLayoutDirection());
assertThat(node1.getLayoutHeight()).isEqualTo(node2.getLayoutHeight());
assertThat(node1.getLayoutWidth()).isEqualTo(node2.getLayoutWidth());
assertThat(node1.getLayoutX()).isEqualTo(node2.getLayoutX());
assertThat(node1.getLayoutY()).isEqualTo(node2.getLayoutY());
for (int spacingType = Spacing.LEFT; spacingType <= Spacing.ALL; spacingType++) {
assertThat(node1.getStylePadding(spacingType)).isEqualTo(node2.getStylePadding(spacingType));
}
assertThat(node1.getStyleWidth()).isEqualTo(node2.getStyleWidth());
assertThat(node1.getStyleHeight()).isEqualTo(node2.getStyleHeight());
}
private ReactShadowNode createViewNode() {
ReactShadowNode node = new ReactShadowNodeImpl();
node.setViewClassName(ReactViewManager.REACT_CLASS);
node.setThemedContext(mThemedReactContext);
return node;
}
}

View File

@@ -1,23 +0,0 @@
// Copyright (c) Facebook, Inc. and its affiliates.
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
package com.facebook.react.fabric;
import com.facebook.react.uimanager.ReactShadowNodeImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/** Tests {@link ReactShadowNode} */
@RunWith(RobolectricTestRunner.class)
public class ReactShadowNodeTest {
@Test(expected = AssertionError.class)
public void testClonedInstance() {
TestReactShadowNode node = new TestReactShadowNode();
node.mutableCopy(node.getInstanceHandle());
}
private static class TestReactShadowNode extends ReactShadowNodeImpl {}
}