@Override public final List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); for (ModuleSpec holder : getNativeModules(reactContext)) { NativeModule nativeModule; SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createNativeModule") .arg("module", holder.getType()) .flush(); try { ReactMarker.logMarker( ReactMarkerConstants.CREATE_MODULE_START, holder.getType().getSimpleName()); nativeModule = holder.getProvider().get(); ReactMarker.logMarker(ReactMarkerConstants.CREATE_MODULE_END); } finally { Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); } modules.add(nativeModule); } return modules; }
private void processPackage( ReactPackage reactPackage, NativeModuleRegistryBuilder nativeModuleRegistryBuilder, JavaScriptModuleRegistry.Builder jsModulesBuilder) { SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "processPackage") .arg("className", reactPackage.getClass().getSimpleName()) .flush(); if (reactPackage instanceof ReactPackageLogger) { ((ReactPackageLogger) reactPackage).startProcessPackage(); } nativeModuleRegistryBuilder.processPackage(reactPackage); for (Class<? extends JavaScriptModule> jsModuleClass : reactPackage.createJSModules()) { jsModulesBuilder.add(jsModuleClass); } if (reactPackage instanceof ReactPackageLogger) { ((ReactPackageLogger) reactPackage).endProcessPackage(); } Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); }
private NativeModule create() { SoftAssertions.assertCondition(mModule == null, "Creating an already created module."); ReactMarker.logMarker(CREATE_MODULE_START, mName); SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createModule") .arg("name", mName) .flush(); NativeModule module = assertNotNull(mProvider).get(); mProvider = null; if (mInitializeNeeded) { doInitialize(module); mInitializeNeeded = false; } Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); ReactMarker.logMarker(CREATE_MODULE_END); return module; }
private void processArguments() { if (mArgumentsProcessed) { return; } SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "processArguments") .arg("method", mModuleWrapper.getName() + "." + mMethod.getName()) .flush(); mArgumentsProcessed = true; mArgumentExtractors = buildArgumentExtractors(mParameterTypes); mSignature = buildSignature(mMethod, mParameterTypes, (mType.equals(BaseJavaModule.METHOD_TYPE_SYNC))); // Since native methods are invoked from a message queue executed on a single thread, it is // safe to allocate only one arguments object per method that can be reused across calls mArguments = new Object[mParameterTypes.length]; mJSArgumentsNeeded = calculateJSArgumentsNeeded(); com.facebook.systrace.Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); }
@DoNotStrip public NativeArray getConstants() { BaseJavaModule baseJavaModule = getModule(); ReactMarker.logMarker(GET_CONSTANTS_START, getName()); SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "Map constants") .arg("moduleName", getName()) .flush(); Map<String, Object> map = baseJavaModule.getConstants(); Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "WritableNativeMap constants") .arg("moduleName", getName()) .flush(); ReactMarker.logMarker(CONVERT_CONSTANTS_START, getName()); WritableNativeMap writableNativeMap; try { writableNativeMap = Arguments.makeNativeMap(map); } finally { Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); } WritableNativeArray array = new WritableNativeArray(); array.pushMap(writableNativeMap); ReactMarker.logMarker(CONVERT_CONSTANTS_END); ReactMarker.logMarker(GET_CONSTANTS_END); return array; }
private NativeModule create() { boolean isEagerModule = mInfo instanceof LegacyModuleInfo; String name = isEagerModule ? ((LegacyModuleInfo) mInfo).mType.getSimpleName() : mInfo.name(); if (!isEagerModule) { ReactMarker.logMarker(CREATE_MODULE_START); } SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createModule") .arg("name", name) .flush(); NativeModule module = assertNotNull(mProvider).get(); if (mInitializeNeeded) { doInitialize(module); mInitializeNeeded = false; } Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); if (!isEagerModule) { ReactMarker.logMarker(CREATE_MODULE_END); } return module; }
@DoNotStrip public NativeArray getConstants() { SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "Map constants") .arg("moduleName", getName()) .flush(); Map<String, Object> map = getModule().getConstants(); Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "WritableNativeMap constants") .arg("moduleName", getName()) .flush(); WritableNativeMap writableNativeMap; try { writableNativeMap = Arguments.makeNativeMap(map); } finally { Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); } WritableNativeArray array = new WritableNativeArray(); array.pushMap(writableNativeMap); return array; }
public void createView( ThemedReactContext themedContext, int tag, String className, @Nullable ReactStylesDiffMap initialProps) { UiThreadUtil.assertOnUiThread(); SystraceMessage.beginSection( Systrace.TRACE_TAG_REACT_VIEW, "NativeViewHierarchyManager_createView") .arg("tag", tag) .arg("className", className) .flush(); try { ViewManager viewManager = mViewManagers.get(className); View view = viewManager.createView(themedContext, mJSResponderHandler); mTagsToViews.put(tag, view); mTagsToViewManagers.put(tag, viewManager); // Use android View id field to store React tag. This is possible since we don't inflate // React views from layout xmls. Thus it is easier to just reuse that field instead of // creating another (potentially much more expensive) mapping from view to React tag view.setId(tag); if (initialProps != null) { viewManager.updateProperties(view, initialProps); } } finally { Systrace.endSection(Systrace.TRACE_TAG_REACT_VIEW); } }
protected void calculateRootLayout(ReactShadowNode cssRoot) { SystraceMessage.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "cssRoot.calculateLayout") .arg("rootTag", cssRoot.getReactTag()) .flush(); double startTime = (double) System.nanoTime(); try { cssRoot.calculateLayout(); } finally { Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); mLayoutTimer = mLayoutTimer + ((double)System.nanoTime() - startTime) / 1000000.0; mLayoutCount = mLayoutCount + 1; } }
/** * To implement the transactional requirement mentioned in the class javadoc, we only commit * UI changes to the actual view hierarchy once a batch of JS->Java calls have been completed. * We know this is safe because all JS->Java calls that are triggered by a Java->JS call (e.g. * the delivery of a touch event or execution of 'renderApplication') end up in a single * JS->Java transaction. * * A better way to do this would be to have JS explicitly signal to this module when a UI * transaction is done. Right now, though, this is how iOS does it, and we should probably * update the JS and native code and make this change at the same time. * * TODO(5279396): Make JS UI library explicitly notify the native UI module of the end of a UI * transaction using a standard native call */ @Override public void onBatchComplete() { int batchId = mBatchId; mBatchId++; SystraceMessage.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "onBatchCompleteUI") .arg("BatchId", batchId) .flush(); try { mUIImplementation.dispatchViewUpdates(batchId); } finally { Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); } }
private void doInitialize(NativeModule module) { SystraceMessage.Builder section = SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "initialize"); if (module instanceof CxxModuleWrapper) { section.arg("className", module.getClass().getSimpleName()); } else { section.arg("name", mName); } section.flush(); ReactMarker.logMarker(ReactMarkerConstants.INITIALIZE_MODULE_START, mName); module.initialize(); ReactMarker.logMarker(ReactMarkerConstants.INITIALIZE_MODULE_END); Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); }
@DoNotStrip public @Nullable NativeArray getConstants() { if (!mModuleHolder.getHasConstants()) { return null; } BaseJavaModule baseJavaModule = getModule(); ReactMarker.logMarker(GET_CONSTANTS_START, getName()); SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "Map constants") .arg("moduleName", getName()) .flush(); Map<String, Object> map = baseJavaModule.getConstants(); Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "WritableNativeMap constants") .arg("moduleName", getName()) .flush(); ReactMarker.logMarker(CONVERT_CONSTANTS_START, getName()); WritableNativeMap writableNativeMap; try { writableNativeMap = Arguments.makeNativeMap(map); } finally { Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); } WritableNativeArray array = new WritableNativeArray(); array.pushMap(writableNativeMap); ReactMarker.logMarker(CONVERT_CONSTANTS_END); ReactMarker.logMarker(GET_CONSTANTS_END); return array; }
void dispatchViewUpdates(final int batchId) { // Store the current operation queues to dispatch and create new empty ones to continue // receiving new operations final ArrayList<UIOperation> operations = mOperations.isEmpty() ? null : mOperations; if (operations != null) { mOperations = new ArrayList<>(); } if (mViewHierarchyUpdateDebugListener != null) { mViewHierarchyUpdateDebugListener.onViewHierarchyUpdateEnqueued(); } synchronized (mDispatchRunnablesLock) { mDispatchUIRunnables.add( new Runnable() { @Override public void run() { SystraceMessage.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "DispatchUI") .arg("BatchId", batchId) .flush(); try { if (operations != null) { for (int i = 0; i < operations.size(); i++) { operations.get(i).execute(); } } // Clear layout animation, as animation only apply to current UI operations batch. mNativeViewHierarchyManager.clearLayoutAnimation(); if (mViewHierarchyUpdateDebugListener != null) { mViewHierarchyUpdateDebugListener.onViewHierarchyUpdateFinished(); } } finally { Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); } } }); } }
protected void calculateRootLayout(ReactShadowNode cssRoot) { SystraceMessage.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "cssRoot.calculateLayout") .arg("rootTag", cssRoot.getReactTag()) .flush(); try { cssRoot.calculateLayout(mLayoutContext); } finally { Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); } }
/** * To implement the transactional requirement mentioned in the class javadoc, we only commit * UI changes to the actual view hierarchy once a batch of JS->Java calls have been completed. * We know this is safe because all JS->Java calls that are triggered by a Java->JS call (e.g. * the delivery of a touch event or execution of 'renderApplication') end up in a single * JS->Java transaction. * * A better way to do this would be to have JS explicitly signal to this module when a UI * transaction is done. Right now, though, this is how iOS does it, and we should probably * update the JS and native code and make this change at the same time. * * TODO(5279396): Make JS UI library explicitly notify the native UI module of the end of a UI * transaction using a standard native call */ @Override public void onBatchComplete() { int batchId = mBatchId; mBatchId++; SystraceMessage.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "onBatchCompleteUI") .arg("BatchId", batchId) .flush(); try { mUIImplementation.dispatchViewUpdates(mEventDispatcher, batchId); } finally { Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); } }
@Override public final List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); for (ModuleSpec holder : getNativeModules(reactContext)) { SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createNativeModule") .arg("module", holder.getType()) .flush(); try { modules.add(holder.getProvider().get()); } finally { Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); } } return modules; }
protected void calculateRootLayout(ReactShadowNode cssRoot) { SystraceMessage.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "cssRoot.calculateLayout") .arg("rootTag", cssRoot.getReactTag()) .flush(); double startTime = (double) System.nanoTime(); try { cssRoot.calculateLayout(mLayoutContext); } finally { Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); mLayoutTimer = mLayoutTimer + ((double)System.nanoTime() - startTime)/ 1000000000.0; mLayoutCount = mLayoutCount + 1; } }
private void processPackage( ReactPackage reactPackage, ReactApplicationContext reactContext, List<ModuleSpec> moduleSpecs, Map<Class, ReactModuleInfo> reactModuleInfoMap, JavaScriptModuleRegistry.Builder jsModulesBuilder) { SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "processPackage") .arg("className", reactPackage.getClass().getSimpleName()) .flush(); if (mLazyNativeModulesEnabled && reactPackage instanceof LazyReactPackage) { LazyReactPackage lazyReactPackage = (LazyReactPackage) reactPackage; ReactModuleInfoProvider instance = lazyReactPackage.getReactModuleInfoProvider(); Map<Class, ReactModuleInfo> map = instance.getReactModuleInfos(); if (!map.isEmpty()) { reactModuleInfoMap.putAll(map); } moduleSpecs.addAll(lazyReactPackage.getNativeModules(reactContext)); } else { FLog.d( ReactConstants.TAG, reactPackage.getClass().getSimpleName() + " is not a LazyReactPackage, falling back to old version."); for (NativeModule nativeModule : reactPackage.createNativeModules(reactContext)) { moduleSpecs.add( new ModuleSpec(nativeModule.getClass(), new EagerModuleProvider(nativeModule))); } } for (Class<? extends JavaScriptModule> jsModuleClass : reactPackage.createJSModules()) { jsModulesBuilder.add(jsModuleClass); } Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); }
private void doInitialize(NativeModule module) { SystraceMessage.Builder section = SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "initialize"); if (module instanceof CxxModuleWrapper) { section.arg("className", module.getClass().getSimpleName()); } else { section.arg("name", mInfo.name()); } section.flush(); callInitializeOnUiThread(module); Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); }
void dispatchViewUpdates(final int batchId) { // Store the current operation queues to dispatch and create new empty ones to continue // receiving new operations final ArrayList<UIOperation> operations = mOperations.isEmpty() ? null : mOperations; if (operations != null) { mOperations = new ArrayList<>(); } final UIOperation[] nonBatchedOperations; synchronized (mNonBatchedOperationsLock) { if (!mNonBatchedOperations.isEmpty()) { nonBatchedOperations = mNonBatchedOperations.toArray(new UIOperation[mNonBatchedOperations.size()]); mNonBatchedOperations.clear(); } else { nonBatchedOperations = null; } } if (mViewHierarchyUpdateDebugListener != null) { mViewHierarchyUpdateDebugListener.onViewHierarchyUpdateEnqueued(); } synchronized (mDispatchRunnablesLock) { mDispatchUIRunnables.add( new Runnable() { @Override public void run() { SystraceMessage.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "DispatchUI") .arg("BatchId", batchId) .flush(); try { // All nonBatchedOperations should be executed before regular operations as // regular operations may depend on them if (nonBatchedOperations != null) { for (UIOperation op : nonBatchedOperations) { op.execute(); } } if (operations != null) { for (int i = 0; i < operations.size(); i++) { operations.get(i).execute(); } } // Clear layout animation, as animation only apply to current UI operations batch. mNativeViewHierarchyManager.clearLayoutAnimation(); if (mViewHierarchyUpdateDebugListener != null) { mViewHierarchyUpdateDebugListener.onViewHierarchyUpdateFinished(); } } catch (Exception e) { mIsInIllegalUIState = true; throw e; } finally { Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE); } } }); } // In the case where the frame callback isn't enqueued, the UI isn't being displayed or is being // destroyed. In this case it's no longer important to align to frames, but it is imporant to make // sure any late-arriving UI commands are executed. if (!mIsDispatchUIFrameCallbackEnqueued) { UiThreadUtil.runOnUiThread( new GuardedRunnable(mReactApplicationContext) { @Override public void runGuarded() { flushPendingBatches(); } }); } }
/** * Generates map of constants that is then exposed by {@link UIManagerModule}. The constants map * contains the following predefined fields for 'customBubblingEventTypes' and * 'customDirectEventTypes'. Provided list of {@param viewManagers} is then used to populate * content of those predefined fields using * {@link ViewManager#getExportedCustomBubblingEventTypeConstants} and * {@link ViewManager#getExportedCustomDirectEventTypeConstants} respectively. Each view manager * is in addition allowed to expose viewmanager-specific constants that are placed under the key * that corresponds to the view manager's name (see {@link ViewManager#getName}). Constants are * merged into the map of {@link UIManagerModule} base constants that is stored in * {@link UIManagerModuleConstants}. * TODO(6845124): Create a test for this */ /* package */ static Map<String, Object> createConstants( List<ViewManager> viewManagers, boolean lazyViewManagersEnabled) { Map<String, Object> constants = UIManagerModuleConstants.getConstants(); Map bubblingEventTypesConstants = UIManagerModuleConstants.getBubblingEventTypeConstants(); Map directEventTypesConstants = UIManagerModuleConstants.getDirectEventTypeConstants(); for (ViewManager viewManager : viewManagers) { SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "constants for ViewManager") .arg("ViewManager", viewManager.getName()) .flush(); try { Map viewManagerBubblingEvents = viewManager.getExportedCustomBubblingEventTypeConstants(); if (viewManagerBubblingEvents != null) { recursiveMerge(bubblingEventTypesConstants, viewManagerBubblingEvents); } Map viewManagerDirectEvents = viewManager.getExportedCustomDirectEventTypeConstants(); if (viewManagerDirectEvents != null) { recursiveMerge(directEventTypesConstants, viewManagerDirectEvents); } Map viewManagerConstants = MapBuilder.newHashMap(); Map customViewConstants = viewManager.getExportedViewConstants(); if (customViewConstants != null) { viewManagerConstants.put("Constants", customViewConstants); } Map viewManagerCommands = viewManager.getCommandsMap(); if (viewManagerCommands != null) { viewManagerConstants.put("Commands", viewManagerCommands); } Map<String, String> viewManagerNativeProps = viewManager.getNativeProps(); if (!viewManagerNativeProps.isEmpty()) { viewManagerConstants.put("NativeProps", viewManagerNativeProps); } if (!viewManagerConstants.isEmpty()) { constants.put(viewManager.getName(), viewManagerConstants); } } finally { Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); } } constants.put(CUSTOM_BUBBLING_EVENT_TYPES_KEY, bubblingEventTypesConstants); constants.put(CUSTOM_DIRECT_EVENT_TYPES_KEY, directEventTypesConstants); constants.put("AndroidLazyViewManagersEnabled", lazyViewManagersEnabled); return constants; }
public void updateLayout( int parentTag, int tag, int x, int y, int width, int height) { UiThreadUtil.assertOnUiThread(); SystraceMessage.beginSection( Systrace.TRACE_TAG_REACT_VIEW, "NativeViewHierarchyManager_updateLayout") .arg("parentTag", parentTag) .arg("tag", tag) .flush(); try { View viewToUpdate = resolveView(tag); // Even though we have exact dimensions, we still call measure because some platform views (e.g. // Switch) assume that method will always be called before onLayout and onDraw. They use it to // calculate and cache information used in the draw pass. For most views, onMeasure can be // stubbed out to only call setMeasuredDimensions. For ViewGroups, onLayout should be stubbed // out to not recursively call layout on its children: React Native already handles doing that. // // Also, note measure and layout need to be called *after* all View properties have been updated // because of caching and calculation that may occur in onMeasure and onLayout. Layout // operations should also follow the native view hierarchy and go top to bottom for consistency // with standard layout passes (some views may depend on this). viewToUpdate.measure( View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)); // Check if the parent of the view has to layout the view, or the child has to lay itself out. if (!mRootTags.get(parentTag)) { ViewManager parentViewManager = mTagsToViewManagers.get(parentTag); ViewGroupManager parentViewGroupManager; if (parentViewManager instanceof ViewGroupManager) { parentViewGroupManager = (ViewGroupManager) parentViewManager; } else { throw new IllegalViewOperationException( "Trying to use view with tag " + tag + " as a parent, but its Manager doesn't extends ViewGroupManager"); } if (parentViewGroupManager != null && !parentViewGroupManager.needsCustomLayoutForChildren()) { updateLayout(viewToUpdate, x, y, width, height); } } else { updateLayout(viewToUpdate, x, y, width, height); } } finally { Systrace.endSection(Systrace.TRACE_TAG_REACT_VIEW); } }
@Override public void invoke(JSInstance jsInstance, ExecutorToken executorToken, ReadableNativeArray parameters) { String traceName = mModuleWrapper.getName() + "." + mMethod.getName(); SystraceMessage.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "callJavaModuleMethod") .arg("method", traceName) .flush(); try { if (!mArgumentsProcessed) { processArguments(); } if (mArguments == null || mArgumentExtractors == null) { throw new Error("processArguments failed"); } if (mJSArgumentsNeeded != parameters.size()) { throw new NativeArgumentsParseException( traceName + " got " + parameters.size() + " arguments, expected " + mJSArgumentsNeeded); } // Modules that support web workers are expected to take an ExecutorToken as the first // parameter to all their @ReactMethod-annotated methods. We compensate for that here. int i = 0, jsArgumentsConsumed = 0; int executorTokenOffset = 0; if (mModuleWrapper.supportsWebWorkers()) { mArguments[0] = executorToken; executorTokenOffset = 1; } try { for (; i < mArgumentExtractors.length; i++) { mArguments[i + executorTokenOffset] = mArgumentExtractors[i].extractArgument( jsInstance, executorToken, parameters, jsArgumentsConsumed); jsArgumentsConsumed += mArgumentExtractors[i].getJSArgumentsNeeded(); } } catch (UnexpectedNativeTypeException e) { throw new NativeArgumentsParseException( e.getMessage() + " (constructing arguments for " + traceName + " at argument index " + getAffectedRange(jsArgumentsConsumed, mArgumentExtractors[i].getJSArgumentsNeeded()) + ")", e); } try { mMethod.invoke(mModuleWrapper.getModule(), mArguments); } catch (IllegalArgumentException ie) { throw new RuntimeException("Could not invoke " + traceName, ie); } catch (IllegalAccessException iae) { throw new RuntimeException("Could not invoke " + traceName, iae); } catch (InvocationTargetException ite) { // Exceptions thrown from native module calls end up wrapped in InvocationTargetException // which just make traces harder to read and bump out useful information if (ite.getCause() instanceof RuntimeException) { throw (RuntimeException) ite.getCause(); } throw new RuntimeException("Could not invoke " + traceName, ite); } } finally { com.facebook.systrace.Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); } }