Alternative Instance Handle Approach without JSWeakRef

Reviewed By: fkgozali

Differential Revision: D8003736

fbshipit-source-id: 597378555cc3f9c0ae95e8927460a3c813ebfb45
This commit is contained in:
Sebastian Markbage 2018-05-18 20:19:03 -07:00 committed by Facebook Github Bot
parent f59e5a8d28
commit 6cc597e6e4
7 changed files with 73 additions and 32 deletions

View File

@ -74,7 +74,7 @@ public class FabricUIManager implements UIManager {
/** Creates a new {@link ReactShadowNode} */
@Nullable
public ReactShadowNode createNode(
int reactTag, String viewName, int rootTag, ReadableNativeMap props, int instanceHandle) {
int reactTag, String viewName, int rootTag, ReadableNativeMap props, long instanceHandle) {
if (DEBUG) {
Log.d(TAG, "createNode \n\ttag: " + reactTag +
"\n\tviewName: " + viewName +
@ -123,11 +123,12 @@ public class FabricUIManager implements UIManager {
* including its children set (note that the children nodes will not be cloned).
*/
@Nullable
public ReactShadowNode cloneNode(ReactShadowNode node) {
public ReactShadowNode cloneNode(ReactShadowNode node, long instanceHandle) {
if (DEBUG) {
Log.d(TAG, "cloneNode \n\tnode: " + node);
}
try {
// TODO: Pass new instanceHandle
ReactShadowNode clone = node.mutableCopy();
assertReactShadowNodeCopy(node, clone);
return clone;
@ -143,11 +144,12 @@ public class FabricUIManager implements UIManager {
* children set will be empty.
*/
@Nullable
public ReactShadowNode cloneNodeWithNewChildren(ReactShadowNode node) {
public ReactShadowNode cloneNodeWithNewChildren(ReactShadowNode node, long instanceHandle) {
if (DEBUG) {
Log.d(TAG, "cloneNodeWithNewChildren \n\tnode: " + node);
}
try {
// TODO: Pass new instanceHandle
ReactShadowNode clone = node.mutableCopyWithNewChildren();
assertReactShadowNodeCopy(node, clone);
return clone;
@ -164,11 +166,12 @@ public class FabricUIManager implements UIManager {
*/
@Nullable
public ReactShadowNode cloneNodeWithNewProps(
ReactShadowNode node, @Nullable ReadableNativeMap newProps) {
ReactShadowNode node, @Nullable ReadableNativeMap newProps, long instanceHandle) {
if (DEBUG) {
Log.d(TAG, "cloneNodeWithNewProps \n\tnode: " + node + "\n\tprops: " + newProps);
}
try {
// TODO: Pass new instanceHandle
ReactShadowNode clone =
node.mutableCopyWithNewProps(newProps == null ? null : new ReactStylesDiffMap(newProps));
assertReactShadowNodeCopy(node, clone);
@ -187,11 +190,12 @@ public class FabricUIManager implements UIManager {
*/
@Nullable
public ReactShadowNode cloneNodeWithNewChildrenAndProps(
ReactShadowNode node, ReadableNativeMap newProps) {
ReactShadowNode node, ReadableNativeMap newProps, long instanceHandle) {
if (DEBUG) {
Log.d(TAG, "cloneNodeWithNewChildrenAndProps \n\tnode: " + node + "\n\tnewProps: " + newProps);
}
try {
// TODO: Pass new instanceHandle
ReactShadowNode clone =
node.mutableCopyWithNewChildrenAndProps(
newProps == null ? null : new ReactStylesDiffMap(newProps));

View File

@ -27,6 +27,10 @@ public class FabricJSCBinding implements FabricBinding {
private static native HybridData initHybrid();
private native long createEventTarget(long jsContextNativePointer, long instanceHandlePointer);
private native void releaseEventTarget(long jsContextNativePointer, long eventTargetPointer);
private native void installFabric(long jsContextNativePointer, Object fabricModule);
public FabricJSCBinding() {

View File

@ -88,16 +88,16 @@ JSValueRef createNode(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb
static auto createNode =
jni::findClassStatic("com/facebook/react/fabric/FabricUIManager")
->getMethod<alias_ref<JShadowNode>(jint, jstring, jint, ReadableNativeMap::javaobject, jint)>("createNode");
->getMethod<alias_ref<JShadowNode>(jint, jstring, jint, ReadableNativeMap::javaobject, jlong)>("createNode");
int reactTag = (int)JSC_JSValueToNumber(ctx, arguments[0], NULL);
auto viewName = JSValueToJString(ctx, arguments[1]);
int rootTag = (int)JSC_JSValueToNumber(ctx, arguments[2], NULL);
auto props = JSC_JSValueIsNull(ctx, arguments[3]) ? local_ref<ReadableNativeMap::jhybridobject>(nullptr) :
JSValueToReadableMapViaJSON(ctx, arguments[3]);;
int instanceHandle = (int)JSC_JSValueToNumber(ctx, arguments[4], NULL);
auto instanceHandle = (void *)arguments[4];
auto node = createNode(manager, reactTag, viewName.get(), rootTag, props.get(), instanceHandle);
auto node = createNode(manager, reactTag, viewName.get(), rootTag, props.get(), (jlong)instanceHandle);
return JSC_JSObjectMake(ctx, classRef, makePlainGlobalRef(node.get()));
}
@ -109,10 +109,11 @@ JSValueRef cloneNode(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObj
static auto cloneNode =
jni::findClassStatic("com/facebook/react/fabric/FabricUIManager")
->getMethod<alias_ref<JShadowNode>(JShadowNode::javaobject)>("cloneNode");
->getMethod<alias_ref<JShadowNode>(JShadowNode::javaobject, jlong)>("cloneNode");
auto previousNode = JSValueToJShadowNode(ctx, arguments[0]);
auto newNode = cloneNode(manager, previousNode.get());
auto instanceHandle = (void *)arguments[1];
auto newNode = cloneNode(manager, previousNode.get(), (jlong)instanceHandle);
return JSC_JSObjectMake(ctx, classRef, makePlainGlobalRef(newNode.get()));
}
@ -124,10 +125,11 @@ JSValueRef cloneNodeWithNewChildren(JSContextRef ctx, JSObjectRef function, JSOb
static auto cloneNodeWithNewChildren =
jni::findClassStatic("com/facebook/react/fabric/FabricUIManager")
->getMethod<alias_ref<JShadowNode>(JShadowNode::javaobject)>("cloneNodeWithNewChildren");
->getMethod<alias_ref<JShadowNode>(JShadowNode::javaobject, jlong)>("cloneNodeWithNewChildren");
auto previousNode = JSValueToJShadowNode(ctx, arguments[0]);
auto newNode = cloneNodeWithNewChildren(manager, previousNode.get());
auto instanceHandle = (void *)arguments[1];
auto newNode = cloneNodeWithNewChildren(manager, previousNode.get(), (jlong)instanceHandle);
return JSC_JSObjectMake(ctx, classRef, makePlainGlobalRef(newNode.get()));
}
@ -139,11 +141,12 @@ JSValueRef cloneNodeWithNewProps(JSContextRef ctx, JSObjectRef function, JSObjec
static auto cloneNodeWithNewProps =
jni::findClassStatic("com/facebook/react/fabric/FabricUIManager")
->getMethod<alias_ref<JShadowNode>(JShadowNode::javaobject, ReadableNativeMap::javaobject)>("cloneNodeWithNewProps");
->getMethod<alias_ref<JShadowNode>(JShadowNode::javaobject, ReadableNativeMap::javaobject, jlong)>("cloneNodeWithNewProps");
auto previousNode = JSValueToJShadowNode(ctx, arguments[0]);
auto props = JSValueToReadableMapViaJSON(ctx, arguments[1]);
auto newNode = cloneNodeWithNewProps(manager, previousNode.get(), props.get());
auto instanceHandle = (void *)arguments[2];
auto newNode = cloneNodeWithNewProps(manager, previousNode.get(), props.get(), (jlong)instanceHandle);
return JSC_JSObjectMake(ctx, classRef, makePlainGlobalRef(newNode.get()));
}
@ -155,11 +158,12 @@ JSValueRef cloneNodeWithNewChildrenAndProps(JSContextRef ctx, JSObjectRef functi
static auto cloneNodeWithNewChildrenAndProps =
jni::findClassStatic("com/facebook/react/fabric/FabricUIManager")
->getMethod<alias_ref<JShadowNode>(JShadowNode::javaobject, ReadableNativeMap::javaobject)>("cloneNodeWithNewChildrenAndProps");
->getMethod<alias_ref<JShadowNode>(JShadowNode::javaobject, ReadableNativeMap::javaobject, jlong)>("cloneNodeWithNewChildrenAndProps");
auto previousNode = JSValueToJShadowNode(ctx, arguments[0]);
auto props = JSValueToReadableMapViaJSON(ctx, arguments[1]);
auto newNode = cloneNodeWithNewChildrenAndProps(manager, previousNode.get(), props.get());
auto instanceHandle = (void *)arguments[2];
auto newNode = cloneNodeWithNewChildrenAndProps(manager, previousNode.get(), props.get(), (jlong)instanceHandle);
return JSC_JSObjectMake(ctx, classRef, makePlainGlobalRef(newNode.get()));
}
@ -266,6 +270,27 @@ jni::local_ref<FabricJSCBinding::jhybriddata> FabricJSCBinding::initHybrid(
return makeCxxInstance();
}
jlong FabricJSCBinding::createEventTarget(
jlong jsContextNativePointer,
jlong instanceHandlePointer
) {
JSContextRef context = (JSContextRef)jsContextNativePointer;
JSValueRef value = (JSValueRef)instanceHandlePointer;
// Retain a strong reference to this object.
JSC_JSValueProtect(context, value);
return (jlong)((void *)value);
}
void FabricJSCBinding::releaseEventTarget(
jlong jsContextNativePointer,
jlong eventTargetPointer
) {
JSContextRef context = (JSContextRef)jsContextNativePointer;
JSValueRef value = (JSValueRef)((void *)eventTargetPointer);
// Release this object.
JSC_JSValueUnprotect(context, value);
}
void FabricJSCBinding::installFabric(jlong jsContextNativePointer,
jni::alias_ref<jobject> fabricModule) {
JSContextRef context = (JSContextRef)jsContextNativePointer;

View File

@ -26,6 +26,10 @@ private:
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jclass>);
jlong createEventTarget(jlong jsContextNativePointer, jlong instanceHandlePointer);
void releaseEventTarget(jlong jsContextNativePointer, jlong eventTargetPointer);
void installFabric(jlong jsContextNativePointer, jni::alias_ref<jobject> fabricModule);
};

View File

@ -97,7 +97,7 @@ public class FabricUIManagerTest {
ReactShadowNode child = createViewNode();
node.addChildAt(child, 0);
ReactShadowNode clonedNode = mFabricUIManager.cloneNode(node);
ReactShadowNode clonedNode = mFabricUIManager.cloneNode(node, 0);
assertThat(clonedNode).isNotSameAs(node);
assertThat(clonedNode.getOriginalReactShadowNode()).isSameAs(node);
@ -111,7 +111,7 @@ public class FabricUIManagerTest {
ReactShadowNode node = createViewNode();
node.setDefaultPadding(Spacing.LEFT, 10);
ReactShadowNode clonedNode = mFabricUIManager.cloneNode(node);
ReactShadowNode clonedNode = mFabricUIManager.cloneNode(node, 0);
node.setDefaultPadding(Spacing.LEFT, 20);
assertThat(clonedNode.getStylePadding(Spacing.LEFT).value).isEqualTo(10f, Offset.offset(0.01f));
@ -144,7 +144,7 @@ public class FabricUIManagerTest {
ReactShadowNode child = createViewNode();
node.addChildAt(child, 0);
ReactShadowNode clonedNode = mFabricUIManager.cloneNodeWithNewChildren(node);
ReactShadowNode clonedNode = mFabricUIManager.cloneNodeWithNewChildren(node, 0);
assertThat(clonedNode.getChildCount()).isZero();
assertSameFields(clonedNode, node);
@ -155,7 +155,7 @@ public class FabricUIManagerTest {
ReactShadowNode node = createViewNode();
ReadableNativeMap props = null; // TODO(ayc): Figure out how to create a Native map from tests.
ReactShadowNode clonedNode = mFabricUIManager.cloneNodeWithNewProps(node, props);
ReactShadowNode clonedNode = mFabricUIManager.cloneNodeWithNewProps(node, props, 0);
}
@Test
@ -163,7 +163,7 @@ public class FabricUIManagerTest {
ReactShadowNode node = createViewNode();
ReadableNativeMap props = null;
ReactShadowNode clonedNode = mFabricUIManager.cloneNodeWithNewChildrenAndProps(node, props);
ReactShadowNode clonedNode = mFabricUIManager.cloneNodeWithNewChildrenAndProps(node, props, 0);
assertThat(clonedNode.getChildCount()).isZero();
}
@ -260,10 +260,10 @@ public class FabricUIManagerTest {
mFabricUIManager.appendChildToSet(childSet, container);
mFabricUIManager.completeRoot(rootTag, childSet);
ReactShadowNode aaClone = mFabricUIManager.cloneNodeWithNewProps(aa, null);
ReactShadowNode aClone = mFabricUIManager.cloneNodeWithNewChildren(a);
ReactShadowNode aaClone = mFabricUIManager.cloneNodeWithNewProps(aa, null, 0);
ReactShadowNode aClone = mFabricUIManager.cloneNodeWithNewChildren(a, 0);
mFabricUIManager.appendChild(aClone, aaClone);
ReactShadowNode containerClone = mFabricUIManager.cloneNodeWithNewChildren(container);
ReactShadowNode containerClone = mFabricUIManager.cloneNodeWithNewChildren(container, 0);
mFabricUIManager.appendChild(containerClone, b);
mFabricUIManager.appendChild(containerClone, aClone);
List<ReactShadowNode> childSet2 = mFabricUIManager.createChildSet(rootTag);

View File

@ -115,10 +115,11 @@ SharedShadowNode FabricUIManager::createNode(int tag, std::string viewName, int
return shadowNode;
}
SharedShadowNode FabricUIManager::cloneNode(const SharedShadowNode &shadowNode) {
SharedShadowNode FabricUIManager::cloneNode(const SharedShadowNode &shadowNode, void *instanceHandle) {
isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNode(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode];
// TODO: Retain new instanceHandle
SharedShadowNode clonedShadowNode =
componentDescriptor->cloneShadowNode(shadowNode);
@ -126,11 +127,12 @@ SharedShadowNode FabricUIManager::cloneNode(const SharedShadowNode &shadowNode)
return clonedShadowNode;
}
SharedShadowNode FabricUIManager::cloneNodeWithNewChildren(const SharedShadowNode &shadowNode) {
SharedShadowNode FabricUIManager::cloneNodeWithNewChildren(const SharedShadowNode &shadowNode, void *instanceHandle) {
isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildren(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
// Assuming semantic: Cloning with same props but empty children.
const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode];
// TODO: Retain new instanceHandle
SharedShadowNode clonedShadowNode =
componentDescriptor->cloneShadowNode(
shadowNode,
@ -142,12 +144,13 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewChildren(const SharedShadowNod
return clonedShadowNode;
}
SharedShadowNode FabricUIManager::cloneNodeWithNewProps(const SharedShadowNode &shadowNode, folly::dynamic props) {
SharedShadowNode FabricUIManager::cloneNodeWithNewProps(const SharedShadowNode &shadowNode, folly::dynamic props, void *instanceHandle) {
isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNodeWithNewProps(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", props: " << props << ")";
// Assuming semantic: Cloning with same children and specified props.
const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode];
RawProps rawProps = rawPropsFromDynamic(props);
// TODO: Retain new instanceHandle
SharedShadowNode clonedShadowNode =
componentDescriptor->cloneShadowNode(
shadowNode,
@ -159,12 +162,13 @@ SharedShadowNode FabricUIManager::cloneNodeWithNewProps(const SharedShadowNode &
return clonedShadowNode;
}
SharedShadowNode FabricUIManager::cloneNodeWithNewChildrenAndProps(const SharedShadowNode &shadowNode, folly::dynamic props) {
SharedShadowNode FabricUIManager::cloneNodeWithNewChildrenAndProps(const SharedShadowNode &shadowNode, folly::dynamic props, void *instanceHandle) {
isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildrenAndProps(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", props: " << props << ")";
// Assuming semantic: Cloning with empty children and specified props.
const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode];
RawProps rawProps = rawPropsFromDynamic(props);
// TODO: Retain new instanceHandle
SharedShadowNode clonedShadowNode =
componentDescriptor->cloneShadowNode(
shadowNode,

View File

@ -36,10 +36,10 @@ public:
#pragma mark - JavaScript/React-facing Interface
SharedShadowNode createNode(Tag reactTag, std::string viewName, Tag rootTag, folly::dynamic props, void *instanceHandle);
SharedShadowNode cloneNode(const SharedShadowNode &node);
SharedShadowNode cloneNodeWithNewChildren(const SharedShadowNode &node);
SharedShadowNode cloneNodeWithNewProps(const SharedShadowNode &node, folly::dynamic props);
SharedShadowNode cloneNodeWithNewChildrenAndProps(const SharedShadowNode &node, folly::dynamic newProps);
SharedShadowNode cloneNode(const SharedShadowNode &node, void *instanceHandle);
SharedShadowNode cloneNodeWithNewChildren(const SharedShadowNode &node, void *instanceHandle);
SharedShadowNode cloneNodeWithNewProps(const SharedShadowNode &node, folly::dynamic props, void *instanceHandle);
SharedShadowNode cloneNodeWithNewChildrenAndProps(const SharedShadowNode &node, folly::dynamic newProps, void *instanceHandle);
void appendChild(const SharedShadowNode &parentNode, const SharedShadowNode &childNode);
SharedShadowNodeUnsharedList createChildSet(Tag rootTag);
void appendChildToSet(const SharedShadowNodeUnsharedList &childSet, const SharedShadowNode &childNode);