mirror of
https://github.com/status-im/react-native.git
synced 2025-01-15 20:15:11 +00:00
Binding for js events
Reviewed By: fkgozali Differential Revision: D8181616 fbshipit-source-id: 5937c83f22ac09e3041fcb0f8d4e9e3026b2b397
This commit is contained in:
parent
23fbd312aa
commit
0f10e03dd8
@ -261,7 +261,7 @@ public class ReactAppTestActivity extends FragmentActivity
|
|||||||
List<ViewManager> viewManagers =
|
List<ViewManager> viewManagers =
|
||||||
mReactInstanceManager.getOrCreateViewManagers(reactApplicationContext);
|
mReactInstanceManager.getOrCreateViewManagers(reactApplicationContext);
|
||||||
FabricUIManager fabricUIManager =
|
FabricUIManager fabricUIManager =
|
||||||
new FabricUIManager(reactApplicationContext, new ViewManagerRegistry(viewManagers));
|
new FabricUIManager(reactApplicationContext, new ViewManagerRegistry(viewManagers), jsContext);
|
||||||
new FabricJSCBinding().installFabric(jsContext, fabricUIManager);
|
new FabricJSCBinding().installFabric(jsContext, fabricUIManager);
|
||||||
return fabricUIManager;
|
return fabricUIManager;
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,24 @@
|
|||||||
package com.facebook.react.fabric;
|
package com.facebook.react.fabric;
|
||||||
|
|
||||||
import com.facebook.react.bridge.JavaScriptContextHolder;
|
import com.facebook.react.bridge.JavaScriptContextHolder;
|
||||||
|
import com.facebook.react.bridge.NativeMap;
|
||||||
|
|
||||||
public interface FabricBinding {
|
public interface FabricBinding {
|
||||||
|
|
||||||
void installFabric(JavaScriptContextHolder jsContext, FabricUIManager fabricModule);
|
void installFabric(JavaScriptContextHolder jsContext, FabricUIManager fabricModule);
|
||||||
|
|
||||||
|
long createEventTarget(long jsContextNativePointer, long instanceHandlePointer);
|
||||||
|
|
||||||
|
void releaseEventTarget(long jsContextNativePointer, long eventTargetPointer);
|
||||||
|
|
||||||
|
void releaseEventHandler(long jsContextNativePointer, long eventHandlerPointer);
|
||||||
|
|
||||||
|
void dispatchEventToTarget(
|
||||||
|
long jsContextNativePointer,
|
||||||
|
long eventHandlerPointer,
|
||||||
|
long eventTargetPointer,
|
||||||
|
String type,
|
||||||
|
NativeMap payload
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,15 +14,15 @@ import static android.view.View.MeasureSpec.UNSPECIFIED;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import com.facebook.infer.annotation.Assertions;
|
import com.facebook.infer.annotation.Assertions;
|
||||||
import com.facebook.react.bridge.GuardedRunnable;
|
|
||||||
import com.facebook.react.bridge.JavaScriptContextHolder;
|
import com.facebook.react.bridge.JavaScriptContextHolder;
|
||||||
import com.facebook.react.bridge.ReactApplicationContext;
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
import com.facebook.react.bridge.ReadableArray;
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
import com.facebook.react.bridge.ReadableMap;
|
import com.facebook.react.bridge.ReadableMap;
|
||||||
import com.facebook.react.bridge.ReadableNativeMap;
|
import com.facebook.react.bridge.ReadableNativeMap;
|
||||||
import com.facebook.react.bridge.UIManager;
|
import com.facebook.react.bridge.UIManager;
|
||||||
import com.facebook.react.common.ReactConstants;
|
|
||||||
import com.facebook.react.bridge.WritableMap;
|
import com.facebook.react.bridge.WritableMap;
|
||||||
|
import com.facebook.react.bridge.WritableNativeMap;
|
||||||
|
import com.facebook.react.common.ReactConstants;
|
||||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||||
import com.facebook.react.modules.i18nmanager.I18nUtil;
|
import com.facebook.react.modules.i18nmanager.I18nUtil;
|
||||||
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||||
@ -39,10 +39,8 @@ import com.facebook.react.uimanager.common.MeasureSpecProvider;
|
|||||||
import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout;
|
import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout;
|
||||||
import com.facebook.yoga.YogaDirection;
|
import com.facebook.yoga.YogaDirection;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,14 +58,16 @@ public class FabricUIManager implements UIManager, JSHandler {
|
|||||||
private final ViewManagerRegistry mViewManagerRegistry;
|
private final ViewManagerRegistry mViewManagerRegistry;
|
||||||
private final UIViewOperationQueue mUIViewOperationQueue;
|
private final UIViewOperationQueue mUIViewOperationQueue;
|
||||||
private final NativeViewHierarchyManager mNativeViewHierarchyManager;
|
private final NativeViewHierarchyManager mNativeViewHierarchyManager;
|
||||||
|
private final JavaScriptContextHolder mJSContext;
|
||||||
private volatile int mCurrentBatch = 0;
|
private volatile int mCurrentBatch = 0;
|
||||||
private final FabricReconciler mFabricReconciler;
|
private final FabricReconciler mFabricReconciler;
|
||||||
// TODO: Initialize new Binding (waiting for C++ implemenation to be landed)
|
|
||||||
private FabricBinding mBinding;
|
private FabricBinding mBinding;
|
||||||
private JavaScriptContextHolder mContext;
|
private long mEventHandlerPointer;
|
||||||
|
|
||||||
public FabricUIManager(
|
public FabricUIManager(
|
||||||
ReactApplicationContext reactContext, ViewManagerRegistry viewManagerRegistry) {
|
ReactApplicationContext reactContext,
|
||||||
|
ViewManagerRegistry viewManagerRegistry,
|
||||||
|
JavaScriptContextHolder jsContext) {
|
||||||
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext);
|
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext);
|
||||||
mReactApplicationContext = reactContext;
|
mReactApplicationContext = reactContext;
|
||||||
mViewManagerRegistry = viewManagerRegistry;
|
mViewManagerRegistry = viewManagerRegistry;
|
||||||
@ -76,10 +76,11 @@ public class FabricUIManager implements UIManager, JSHandler {
|
|||||||
new UIViewOperationQueue(
|
new UIViewOperationQueue(
|
||||||
reactContext, mNativeViewHierarchyManager, 0);
|
reactContext, mNativeViewHierarchyManager, 0);
|
||||||
mFabricReconciler = new FabricReconciler(mUIViewOperationQueue);
|
mFabricReconciler = new FabricReconciler(mUIViewOperationQueue);
|
||||||
|
mJSContext = jsContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerEventHandler(long eventHandlerPointer) {
|
public void setBinding(FabricBinding binding) {
|
||||||
// TODO: Release this event handler at some point.
|
mBinding = binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates a new {@link ReactShadowNode} */
|
/** Creates a new {@link ReactShadowNode} */
|
||||||
@ -480,20 +481,39 @@ public class FabricUIManager implements UIManager, JSHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Nullable
|
||||||
public void invoke(int instanceHandle, String name, WritableMap params) {
|
public long createEventTarget(int reactTag) {
|
||||||
Log.e(TAG, "Invoking '" + name + "' on instanceHandle: '" + instanceHandle + "' from FabricUIManager.");
|
|
||||||
// -> call to C++
|
|
||||||
}
|
|
||||||
|
|
||||||
public long createEventTarget(int reactTag) throws IllegalStateException {
|
|
||||||
long instanceHandle = mNativeViewHierarchyManager.getInstanceHandle(reactTag);
|
long instanceHandle = mNativeViewHierarchyManager.getInstanceHandle(reactTag);
|
||||||
if (instanceHandle == 0) {
|
long context = mJSContext.get();
|
||||||
throw new IllegalStateException("View with reactTag " + reactTag + " does not exist.");
|
long eventTarget = mBinding.createEventTarget(context, instanceHandle);
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.e(
|
||||||
|
TAG,
|
||||||
|
"Created EventTarget: " + eventTarget + " for tag: " + reactTag + " with instanceHandle: " + instanceHandle);
|
||||||
}
|
}
|
||||||
|
return eventTarget;
|
||||||
// TODO: uncomment after diff including Binding is landed
|
|
||||||
// return mBinding.createEventTarget(mContext.get(), instanceHandle);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void registerEventHandler(long eventHandlerPointer) {
|
||||||
|
mEventHandlerPointer = eventHandlerPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void releaseEventTarget(long eventTargetPointer) {
|
||||||
|
mBinding.releaseEventTarget(mJSContext.get(), eventTargetPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void releaseEventHandler(long eventHandlerPointer) {
|
||||||
|
mBinding.releaseEventHandler(mJSContext.get(), eventHandlerPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(long eventTarget, String name, WritableMap params) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.e(
|
||||||
|
TAG,
|
||||||
|
"Dispatching event for target: " + eventTarget);
|
||||||
|
}
|
||||||
|
mBinding.dispatchEventToTarget(mJSContext.get(), mEventHandlerPointer, eventTarget, name, (WritableNativeMap) params);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,6 @@ import com.facebook.react.bridge.WritableMap;
|
|||||||
|
|
||||||
public interface JSHandler {
|
public interface JSHandler {
|
||||||
|
|
||||||
void invoke(int instanceHandle, String name, WritableMap params);
|
void invoke(long instanceHandle, String name, WritableMap params);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -49,9 +49,8 @@ public class FabricEventEmitter implements RCTEventEmitter, Closeable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void receiveEvent(int targetTag, String eventName, @Nullable WritableMap params) {
|
public void receiveEvent(int targetTag, String eventName, @Nullable WritableMap params) {
|
||||||
//TODO get instanceHandle associated with targetTag.
|
long eventTarget = mFabricUIManager.createEventTarget(targetTag);
|
||||||
int instanceHandle = targetTag;
|
mScheduler.scheduleWork(new FabricUIManagerWork(eventTarget, eventName, params));
|
||||||
mScheduler.scheduleWork(new FabricUIManagerWork(instanceHandle, eventName, params) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -60,19 +59,26 @@ public class FabricEventEmitter implements RCTEventEmitter, Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class FabricUIManagerWork implements Work {
|
private class FabricUIManagerWork implements Work {
|
||||||
private final int mInstanceHandle;
|
private final long mEventTarget;
|
||||||
private final String mEventName;
|
private final String mEventName;
|
||||||
private final WritableMap mParams;
|
private final WritableMap mParams;
|
||||||
|
|
||||||
public FabricUIManagerWork(int instanceHandle, String eventName, @Nullable WritableMap params) {
|
public FabricUIManagerWork(long eventTarget, String eventName, @Nullable WritableMap params) {
|
||||||
mInstanceHandle = instanceHandle;
|
mEventTarget = eventTarget;
|
||||||
mEventName = eventName;
|
mEventName = eventName;
|
||||||
mParams = params;
|
mParams = params;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mFabricUIManager.invoke(mInstanceHandle, mEventName, mParams);
|
try {
|
||||||
|
mFabricUIManager.invoke(mEventTarget, mEventName, mParams);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.e(TAG, "Error sending event " + mEventName, t);
|
||||||
|
//TODO: manage exception properly
|
||||||
|
} finally{
|
||||||
|
mFabricUIManager.releaseEventTarget(mEventTarget);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,13 +28,17 @@ public class FabricJSCBinding implements FabricBinding {
|
|||||||
|
|
||||||
private static native HybridData initHybrid();
|
private static native HybridData initHybrid();
|
||||||
|
|
||||||
private native long createEventTarget(long jsContextNativePointer, long instanceHandlePointer);
|
@Override
|
||||||
|
public native long createEventTarget(long jsContextNativePointer, long instanceHandlePointer);
|
||||||
|
|
||||||
private native void releaseEventTarget(long jsContextNativePointer, long eventTargetPointer);
|
@Override
|
||||||
|
public native void releaseEventTarget(long jsContextNativePointer, long eventTargetPointer);
|
||||||
|
|
||||||
private native void releaseEventHandler(long jsContextNativePointer, long eventHandlerPointer);
|
@Override
|
||||||
|
public native void releaseEventHandler(long jsContextNativePointer, long eventHandlerPointer);
|
||||||
|
|
||||||
private native void dispatchEventToTarget(
|
@Override
|
||||||
|
public native void dispatchEventToTarget(
|
||||||
long jsContextNativePointer,
|
long jsContextNativePointer,
|
||||||
long eventHandlerPointer,
|
long eventHandlerPointer,
|
||||||
long eventTargetPointer,
|
long eventTargetPointer,
|
||||||
@ -50,6 +54,7 @@ public class FabricJSCBinding implements FabricBinding {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void installFabric(JavaScriptContextHolder jsContext, FabricUIManager fabricModule) {
|
public void installFabric(JavaScriptContextHolder jsContext, FabricUIManager fabricModule) {
|
||||||
|
fabricModule.setBinding(this);
|
||||||
installFabric(jsContext.get(), fabricModule);
|
installFabric(jsContext.get(), fabricModule);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,17 +222,15 @@ public class NativeViewHierarchyManager {
|
|||||||
@Nullable
|
@Nullable
|
||||||
@TargetApi(Build.VERSION_CODES.DONUT)
|
@TargetApi(Build.VERSION_CODES.DONUT)
|
||||||
public long getInstanceHandle(int reactTag) {
|
public long getInstanceHandle(int reactTag) {
|
||||||
UiThreadUtil.assertOnUiThread();
|
|
||||||
|
|
||||||
View view = mTagsToViews.get(reactTag);
|
View view = mTagsToViews.get(reactTag);
|
||||||
if (view == null) {
|
if (view == null) {
|
||||||
throw new IllegalArgumentException("Unable to find view for tag: " + reactTag);
|
throw new IllegalArgumentException("Unable to find view for tag: " + reactTag);
|
||||||
}
|
}
|
||||||
Long tag = (Long) view.getTag(R.id.view_tag_instance_handle);
|
Long instanceHandle = (Long) view.getTag(R.id.view_tag_instance_handle);
|
||||||
if (tag == null) {
|
if (instanceHandle == null) {
|
||||||
throw new IllegalArgumentException("Unable to find instanceHandle for tag: " + reactTag);
|
throw new IllegalArgumentException("Unable to find instanceHandle for tag: " + reactTag);
|
||||||
}
|
}
|
||||||
return tag;
|
return instanceHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateLayout(View viewToUpdate, int x, int y, int width, int height) {
|
private void updateLayout(View viewToUpdate, int x, int y, int width, int height) {
|
||||||
|
@ -115,7 +115,7 @@ public class EventDispatcher implements LifecycleEventListener,
|
|||||||
for (EventDispatcherListener listener : mListeners) {
|
for (EventDispatcherListener listener : mListeners) {
|
||||||
listener.onEventDispatch(event);
|
listener.onEventDispatch(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (mEventsStagingLock) {
|
synchronized (mEventsStagingLock) {
|
||||||
mEventStaging.add(event);
|
mEventStaging.add(event);
|
||||||
Systrace.startAsyncFlow(
|
Systrace.startAsyncFlow(
|
||||||
|
@ -5,6 +5,7 @@ import static org.fest.assertions.api.Assertions.assertThat;
|
|||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
import com.facebook.react.bridge.CatalystInstance;
|
import com.facebook.react.bridge.CatalystInstance;
|
||||||
|
import com.facebook.react.bridge.JavaScriptContextHolder;
|
||||||
import com.facebook.react.bridge.ReactApplicationContext;
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
import com.facebook.react.bridge.ReactTestHelper;
|
import com.facebook.react.bridge.ReactTestHelper;
|
||||||
import com.facebook.react.uimanager.NativeViewHierarchyManager;
|
import com.facebook.react.uimanager.NativeViewHierarchyManager;
|
||||||
@ -41,7 +42,8 @@ public class FabricReconcilerTest {
|
|||||||
reactContext.initializeWithInstance(catalystInstance);
|
reactContext.initializeWithInstance(catalystInstance);
|
||||||
List<ViewManager> viewManagers = new ArrayList<>();
|
List<ViewManager> viewManagers = new ArrayList<>();
|
||||||
ViewManagerRegistry viewManagerRegistry = new ViewManagerRegistry(viewManagers);
|
ViewManagerRegistry viewManagerRegistry = new ViewManagerRegistry(viewManagers);
|
||||||
mFabricUIManager = new FabricUIManager(reactContext, viewManagerRegistry);
|
JavaScriptContextHolder jsContext = mock(JavaScriptContextHolder.class);
|
||||||
|
mFabricUIManager = new FabricUIManager(reactContext, viewManagerRegistry, jsContext);
|
||||||
mMockUIViewOperationQueue = new MockUIViewOperationQueue(reactContext);
|
mMockUIViewOperationQueue = new MockUIViewOperationQueue(reactContext);
|
||||||
mFabricReconciler = new FabricReconciler(mMockUIViewOperationQueue);
|
mFabricReconciler = new FabricReconciler(mMockUIViewOperationQueue);
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,10 @@ package com.facebook.react.fabric;
|
|||||||
|
|
||||||
import static org.fest.assertions.api.Assertions.assertThat;
|
import static org.fest.assertions.api.Assertions.assertThat;
|
||||||
import static com.facebook.react.bridge.InstanceHandleHelper.randomInstanceHandle;
|
import static com.facebook.react.bridge.InstanceHandleHelper.randomInstanceHandle;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
import com.facebook.react.ReactRootView;
|
import com.facebook.react.ReactRootView;
|
||||||
|
import com.facebook.react.bridge.JavaScriptContextHolder;
|
||||||
import com.facebook.react.bridge.ReactApplicationContext;
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
import com.facebook.react.bridge.ReactTestHelper;
|
import com.facebook.react.bridge.ReactTestHelper;
|
||||||
import com.facebook.react.bridge.ReadableNativeMap;
|
import com.facebook.react.bridge.ReadableNativeMap;
|
||||||
@ -49,8 +51,8 @@ public class FabricUIManagerTest {
|
|||||||
Arrays.<ViewManager>asList(
|
Arrays.<ViewManager>asList(
|
||||||
new ReactViewManager(), new ReactTextViewManager(), new ReactRawTextManager());
|
new ReactViewManager(), new ReactTextViewManager(), new ReactRawTextManager());
|
||||||
ViewManagerRegistry viewManagerRegistry = new ViewManagerRegistry(viewManagers);
|
ViewManagerRegistry viewManagerRegistry = new ViewManagerRegistry(viewManagers);
|
||||||
|
JavaScriptContextHolder jsContext = mock(JavaScriptContextHolder.class);
|
||||||
mFabricUIManager = new FabricUIManager(reactContext, viewManagerRegistry);
|
mFabricUIManager = new FabricUIManager(reactContext, viewManagerRegistry, jsContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user