diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index 0eabd18204..e4285dff87 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -71,6 +71,10 @@ public class FabricUIManager implements UIManager { mFabricReconciler = new FabricReconciler(mUIViewOperationQueue); } + public void registerEventHandler(long eventHandlerPointer) { + // TODO: Release this event handler at some point. + } + /** Creates a new {@link ReactShadowNode} */ @Nullable public ReactShadowNode createNode( diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/FabricJSCBinding.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/FabricJSCBinding.java index bc2c8e9269..190a1aefcb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/FabricJSCBinding.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/FabricJSCBinding.java @@ -12,6 +12,7 @@ import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.JavaScriptContextHolder; import com.facebook.react.fabric.FabricBinding; import com.facebook.react.fabric.FabricUIManager; +import com.facebook.react.bridge.NativeMap; import com.facebook.soloader.SoLoader; @DoNotStrip @@ -31,6 +32,16 @@ public class FabricJSCBinding implements FabricBinding { private native void releaseEventTarget(long jsContextNativePointer, long eventTargetPointer); + private native void releaseEventHandler(long jsContextNativePointer, long eventHandlerPointer); + + private native void dispatchEventToTarget( + long jsContextNativePointer, + long eventHandlerPointer, + long eventTargetPointer, + String type, + NativeMap payload + ); + private native void installFabric(long jsContextNativePointer, Object fabricModule); public FabricJSCBinding() { diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.cpp index efc4db6196..9b18298562 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.cpp @@ -7,7 +7,6 @@ #include "FabricJSCBinding.h" #include -#include #include #include @@ -81,6 +80,15 @@ local_ref JSValueToReadableMapViaJSON(JSContex return ReadableNativeMap::newObjectCxxArgs(std::move(dynamicValue)); } +JSValueRef ReadableMapToJSValueViaJSON(JSContextRef ctx, NativeMap *map) { + folly::dynamic dynamicValue = map->consume(); + auto json = folly::toJson(dynamicValue); + JSStringRef jsonRef = JSC_JSStringCreateWithUTF8CString(ctx, json.c_str()); + auto value = JSC_JSValueMakeFromJSONString(ctx, jsonRef); + JSC_JSStringRelease(ctx, jsonRef); + return value; +} + JSValueRef createNode(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) { FabricJSCUIManager *managerWrapper = (FabricJSCUIManager *)JSC_JSObjectGetPrivate(useCustomJSC, function); alias_ref manager = managerWrapper->fabricUiManager; @@ -231,6 +239,21 @@ JSValueRef completeRoot(JSContextRef ctx, JSObjectRef function, JSObjectRef this return JSC_JSValueMakeUndefined(ctx); } +JSValueRef registerEventHandler(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) { + FabricJSCUIManager *managerWrapper = (FabricJSCUIManager *)JSC_JSObjectGetPrivate(useCustomJSC, function); + alias_ref manager = managerWrapper->fabricUiManager; + + static auto registerEventHandler = + jni::findClassStatic("com/facebook/react/fabric/FabricUIManager") + ->getMethod("registerEventHandler"); + + auto eventHandler = arguments[0]; + JSC_JSValueProtect(ctx, eventHandler); + registerEventHandler(manager, (jlong)eventHandler); + + return JSC_JSValueMakeUndefined(ctx); +} + void finalizeJNIObject(JSObjectRef object) { // Release whatever global ref object we're storing here. jobject globalRef = (jobject)JSC_JSObjectGetPrivate(useCustomJSC, object); @@ -291,6 +314,47 @@ void FabricJSCBinding::releaseEventTarget( JSC_JSValueUnprotect(context, value); } +void FabricJSCBinding::releaseEventHandler( + jlong jsContextNativePointer, + jlong eventHandlerPointer +) { + JSContextRef context = (JSContextRef)jsContextNativePointer; + JSValueRef value = (JSValueRef)((void *)eventHandlerPointer); + // Release this function. + JSC_JSValueUnprotect(context, value); +} + +void FabricJSCBinding::dispatchEventToTarget( + jlong jsContextNativePointer, + jlong eventHandlerPointer, + jlong eventTargetPointer, + std::string type, + NativeMap *payloadMap +) { + JSContextRef context = (JSContextRef)jsContextNativePointer; + JSObjectRef eventHandler = (JSObjectRef)((void *)eventHandlerPointer); + JSObjectRef eventTarget = (JSObjectRef)((void *)eventTargetPointer); + + JSObjectRef thisArg = (JSObjectRef)JSC_JSValueMakeUndefined(context); + JSStringRef typeStr = JSC_JSStringCreateWithUTF8CString(context, type.c_str()); + JSValueRef typeRef = JSC_JSValueMakeString(context, typeStr); + JSC_JSStringRelease(context, typeStr); + JSValueRef payloadRef = ReadableMapToJSValueViaJSON(context, payloadMap); + JSValueRef args[] = {eventTarget, typeRef, payloadRef}; + JSValueRef exn; + JSValueRef result = JSC_JSObjectCallAsFunction( + context, + eventHandler, + thisArg, + 3, + args, + &exn + ); + if (!result) { + // TODO: Handle error in exn + } +} + void FabricJSCBinding::installFabric(jlong jsContextNativePointer, jni::alias_ref fabricModule) { JSContextRef context = (JSContextRef)jsContextNativePointer; @@ -308,11 +372,14 @@ void FabricJSCBinding::installFabric(jlong jsContextNativePointer, addFabricMethod(context, fabricModule, classRef, module, "cloneNodeWithNewChildren", cloneNodeWithNewChildren); addFabricMethod(context, fabricModule, classRef, module, "cloneNodeWithNewProps", cloneNodeWithNewProps); addFabricMethod(context, fabricModule, classRef, module, "cloneNodeWithNewChildrenAndProps", cloneNodeWithNewChildrenAndProps); + addFabricMethod(context, fabricModule, classRef, module, "appendChild", appendChild); addFabricMethod(context, fabricModule, classRef, module, "createChildSet", createChildSet); addFabricMethod(context, fabricModule, classRef, module, "appendChildToSet", appendChildToSet); addFabricMethod(context, fabricModule, classRef, module, "completeRoot", completeRoot); + addFabricMethod(context, fabricModule, classRef, module, "registerEventHandler", registerEventHandler); + JSC_JSClassRelease(useCustomJSC, classRef); JSObjectRef globalObject = JSC_JSContextGetGlobalObject(context); @@ -325,6 +392,10 @@ void FabricJSCBinding::registerNatives() { registerHybrid({ makeNativeMethod("initHybrid", FabricJSCBinding::initHybrid), makeNativeMethod("installFabric", FabricJSCBinding::installFabric), + makeNativeMethod("createEventTarget", FabricJSCBinding::createEventTarget), + makeNativeMethod("releaseEventTarget", FabricJSCBinding::releaseEventTarget), + makeNativeMethod("releaseEventHandler", FabricJSCBinding::releaseEventHandler), + makeNativeMethod("dispatchEventToTarget", FabricJSCBinding::dispatchEventToTarget), }); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.h b/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.h index a6b9857b01..40b7cbd168 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.h +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jsc/jni/FabricJSCBinding.h @@ -9,6 +9,7 @@ #include #include +#include namespace facebook { namespace react { @@ -30,6 +31,16 @@ private: void releaseEventTarget(jlong jsContextNativePointer, jlong eventTargetPointer); + void releaseEventHandler(jlong jsContextNativePointer, jlong eventHandlerPointer); + + void dispatchEventToTarget( + jlong jsContextNativePointer, + jlong eventHandlerPointer, + jlong eventTargetPointer, + std::string type, + NativeMap *payload + ); + void installFabric(jlong jsContextNativePointer, jni::alias_ref fabricModule); };