public void runJSBundle() {
    Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "CatalystInstance_runJSBundle");

    try {
      final CountDownLatch initLatch = new CountDownLatch(1);
      mCatalystQueueConfiguration
          .getJSQueueThread()
          .runOnQueue(
              new Runnable() {
                @Override
                public void run() {
                  Assertions.assertCondition(!mJSBundleHasLoaded, "JS bundle was already loaded!");
                  mJSBundleHasLoaded = true;

                  incrementPendingJSCalls();

                  mJSBundleLoader.loadScript(mBridge);

                  initLatch.countDown();
                }
              });
      Assertions.assertCondition(
          initLatch.await(LOAD_JS_BUNDLE_TIMEOUT_MS, TimeUnit.MILLISECONDS),
          "Timed out loading JS!");
    } catch (InterruptedException e) {
      throw new RuntimeException(e);
    } finally {
      Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
    }
  }
  private ReactBridge initializeBridge(
      JavaScriptExecutor jsExecutor, JavaScriptModulesConfig jsModulesConfig) {
    mReactQueueConfiguration.getJSQueueThread().assertIsOnThread();
    Assertions.assertCondition(mBridge == null, "initializeBridge should be called once");

    Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "ReactBridgeCtor");
    ReactBridge bridge;
    try {
      bridge =
          new ReactBridge(
              jsExecutor,
              new NativeModulesReactCallback(),
              mReactQueueConfiguration.getNativeModulesQueueThread());
      mMainExecutorToken = bridge.getMainExecutorToken();
    } finally {
      Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
    }

    Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "setBatchedBridgeConfig");
    try {
      bridge.setGlobalVariable(
          "__fbBatchedBridgeConfig",
          buildModulesConfigJSONProperty(mJavaRegistry, jsModulesConfig));
      bridge.setGlobalVariable(
          "__RCTProfileIsProfiling",
          Systrace.isTracing(Systrace.TRACE_TAG_REACT_APPS) ? "true" : "false");
    } finally {
      Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
    }

    mJavaRegistry.notifyReactBridgeInitialized(bridge);
    return bridge;
  }
    @Override
    public void doFrame(long frameTimeNanos) {
      UiThreadUtil.assertOnUiThread();

      if (mShouldStop) {
        mIsPosted = false;
      } else {
        post();
      }

      Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "ScheduleDispatchFrameCallback");
      try {
        moveStagedEventsToDispatchQueue();

        if (mEventsToDispatchSize > 0 && !mHasDispatchScheduled) {
          mHasDispatchScheduled = true;
          Systrace.startAsyncFlow(
              Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
              "ScheduleDispatchFrameCallback",
              mHasDispatchScheduledCount);
          mReactContext.runOnJSQueueThread(mDispatchEventsRunnable);
        }
      } finally {
        Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
      }
    }
 @Override
 public void run() {
   Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "DispatchEventsRunnable");
   try {
     Systrace.endAsyncFlow(
         Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
         "ScheduleDispatchFrameCallback",
         mHasDispatchScheduledCount);
     mHasDispatchScheduled = false;
     mHasDispatchScheduledCount++;
     Assertions.assertNotNull(mRCTEventEmitter);
     synchronized (mEventsToDispatchLock) {
       // We avoid allocating an array and iterator, and "sorting" if we don't need to.
       // This occurs when the size of mEventsToDispatch is zero or one.
       if (mEventsToDispatchSize > 1) {
         Arrays.sort(mEventsToDispatch, 0, mEventsToDispatchSize, EVENT_COMPARATOR);
       }
       for (int eventIdx = 0; eventIdx < mEventsToDispatchSize; eventIdx++) {
         Event event = mEventsToDispatch[eventIdx];
         // Event can be null if it has been coalesced into another event.
         if (event == null) {
           continue;
         }
         Systrace.endAsyncFlow(
             Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, event.getEventName(), event.getUniqueID());
         event.dispatch(mRCTEventEmitter);
         event.dispose();
       }
       clearEventsToDispatch();
       mEventCookieToLastEventIdx.clear();
     }
   } finally {
     Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
   }
 }
  private void setupReactContext(ReactApplicationContext reactContext) {
    Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "setupReactContext");
    UiThreadUtil.assertOnUiThread();
    Assertions.assertCondition(mCurrentReactContext == null);
    mCurrentReactContext = Assertions.assertNotNull(reactContext);
    CatalystInstance catalystInstance =
        Assertions.assertNotNull(reactContext.getCatalystInstance());

    catalystInstance.initialize();
    mDevSupportManager.onNewReactContextCreated(reactContext);
    mMemoryPressureRouter.addMemoryPressureListener(catalystInstance);
    moveReactContextToCurrentLifecycleState();

    for (ReactRootView rootView : mAttachedRootViews) {
      attachMeasuredRootViewToInstance(rootView, catalystInstance);
    }

    ReactInstanceEventListener[] listeners =
        new ReactInstanceEventListener[mReactInstanceEventListeners.size()];
    listeners = mReactInstanceEventListeners.toArray(listeners);

    for (ReactInstanceEventListener listener : listeners) {
      listener.onReactContextInitialized(reactContext);
    }
    Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
  }
 private UIManagerModule createUIManager(ReactApplicationContext reactContext) {
   ReactMarker.logMarker(CREATE_UI_MANAGER_MODULE_START);
   Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "createUIManagerModule");
   try {
     List<ViewManager> viewManagersList =
         mReactInstanceManager.createAllViewManagers(reactContext);
     return new UIManagerModule(reactContext, viewManagersList, mUIImplementationProvider);
   } finally {
     Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
     ReactMarker.logMarker(CREATE_UI_MANAGER_MODULE_END);
   }
 }
 /** Uses configured {@link ReactPackage} instances to create all view managers */
 @Override
 public List<ViewManager> createAllViewManagers(
     ReactApplicationContext catalystApplicationContext) {
   Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "createAllViewManagers");
   try {
     List<ViewManager> allViewManagers = new ArrayList<>();
     for (ReactPackage reactPackage : mPackages) {
       allViewManagers.addAll(reactPackage.createViewManagers(catalystApplicationContext));
     }
     return allViewManagers;
   } finally {
     Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
   }
 }
  /**
   * Destroys this catalyst instance, waiting for any other threads in CatalystQueueConfiguration
   * (besides the UI thread) to finish running. Must be called from the UI thread so that we can
   * fully shut down other threads.
   */
  /* package */ void destroy() {
    UiThreadUtil.assertOnUiThread();

    if (mDestroyed) {
      return;
    }

    // TODO: tell all APIs to shut down
    mDestroyed = true;
    mJavaRegistry.notifyCatalystInstanceDestroy();
    mCatalystQueueConfiguration.destroy();
    boolean wasIdle = (mPendingJSCalls.getAndSet(0) == 0);
    if (!wasIdle && !mBridgeIdleListeners.isEmpty()) {
      for (NotThreadSafeBridgeIdleDebugListener listener : mBridgeIdleListeners) {
        listener.onTransitionToBridgeIdle();
      }
    }

    if (mTraceListener != null) {
      Systrace.unregisterListener(mTraceListener);
    }

    // We can access the Bridge from any thread now because we know either we are on the JS thread
    // or the JS thread has finished via CatalystQueueConfiguration#destroy()
    Assertions.assertNotNull(mBridge).dispose();
  }
  /**
   * Destroys this catalyst instance, waiting for any other threads in ReactQueueConfiguration
   * (besides the UI thread) to finish running. Must be called from the UI thread so that we can
   * fully shut down other threads.
   */
  @Override
  public void destroy() {
    UiThreadUtil.assertOnUiThread();

    synchronized (mTeardownLock) {
      if (mDestroyed) {
        return;
      }

      // TODO: tell all APIs to shut down
      mDestroyed = true;
      mJavaRegistry.notifyCatalystInstanceDestroy();

      Systrace.unregisterListener(mTraceListener);

      synchronouslyDisposeBridgeOnJSThread();
    }

    mReactQueueConfiguration.destroy();

    boolean wasIdle = (mPendingJSCalls.getAndSet(0) == 0);
    if (!wasIdle && !mBridgeIdleListeners.isEmpty()) {
      for (NotThreadSafeBridgeIdleDebugListener listener : mBridgeIdleListeners) {
        listener.onTransitionToBridgeIdle();
      }
    }
  }
Example #10
0
    @Override
    public void onBatchComplete() {
      mCatalystQueueConfiguration.getNativeModulesQueueThread().assertIsOnThread();

      // The bridge may have been destroyed due to an exception during the batch. In that case
      // native modules could be in a bad state so we don't want to call anything on them. We
      // still want to trigger the debug listener since it allows instrumentation tests to end and
      // check their assertions without waiting for a timeout.
      if (!mDestroyed) {
        Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "onBatchComplete");
        try {
          mJavaRegistry.onBatchComplete();
        } finally {
          Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
        }
      }

      decrementPendingJSCalls();
    }
    @Override
    public void onExecutorUnregistered(ExecutorToken executorToken) {
      mReactQueueConfiguration.getNativeModulesQueueThread().assertIsOnThread();

      // Since onCatalystInstanceDestroy happens on the UI thread, we don't want to also execute
      // this callback on the native modules thread at the same time. Longer term,
      // onCatalystInstanceDestroy
      // should probably be executed on the native modules thread as well instead.
      synchronized (mTeardownLock) {
        if (!mDestroyed) {
          Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "onExecutorUnregistered");
          try {
            mJavaRegistry.onExecutorUnregistered(executorToken);
          } finally {
            Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
          }
        }
      }
    }
Example #12
0
 private void incrementPendingJSCalls() {
   int oldPendingCalls = mPendingJSCalls.getAndIncrement();
   boolean wasIdle = oldPendingCalls == 0;
   Systrace.traceCounter(
       Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, mJsPendingCallsTitleForTrace, oldPendingCalls + 1);
   if (wasIdle && !mBridgeIdleListeners.isEmpty()) {
     for (NotThreadSafeBridgeIdleDebugListener listener : mBridgeIdleListeners) {
       listener.onTransitionToBridgeBusy();
     }
   }
 }
  private void attachMeasuredRootViewToInstance(
      ReactRootView rootView, CatalystInstance catalystInstance) {
    Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "attachMeasuredRootViewToInstance");
    UiThreadUtil.assertOnUiThread();

    // Reset view content as it's going to be populated by the application content from JS
    rootView.removeAllViews();
    rootView.setId(View.NO_ID);

    UIManagerModule uiManagerModule = catalystInstance.getNativeModule(UIManagerModule.class);
    int rootTag = uiManagerModule.addMeasuredRootView(rootView);
    @Nullable Bundle launchOptions = rootView.getLaunchOptions();
    WritableMap initialProps = Arguments.makeNativeMap(launchOptions);
    String jsAppModuleName = rootView.getJSModuleName();

    WritableNativeMap appParams = new WritableNativeMap();
    appParams.putDouble("rootTag", rootTag);
    appParams.putMap("initialProps", initialProps);
    catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams);
    Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
  }
  @Override
  public List<NativeModule> createNativeModules(
      ReactApplicationContext catalystApplicationContext) {
    Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "createUIManagerModule");
    UIManagerModule uiManagerModule;
    try {
      List<ViewManager> viewManagersList =
          mReactInstanceManager.createAllViewManagers(catalystApplicationContext);
      uiManagerModule =
          new UIManagerModule(
              catalystApplicationContext,
              viewManagersList,
              mUIImplementationProvider.createUIImplementation(
                  catalystApplicationContext, viewManagersList));
    } finally {
      Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
    }

    List<NativeModule> nativeModulesList =
        new ArrayList<>(
            Arrays.<NativeModule>asList(
                new AnimationsDebugModule(
                    catalystApplicationContext,
                    mReactInstanceManager.getDevSupportManager().getDevSettings()),
                new AndroidInfoModule(),
                new DeviceEventManagerModule(catalystApplicationContext, mHardwareBackBtnHandler),
                new ExceptionsManagerModule(mReactInstanceManager.getDevSupportManager()),
                new Timing(
                    catalystApplicationContext, mReactInstanceManager.getDevSupportManager()),
                new SourceCodeModule(mReactInstanceManager.getSourceUrl()),
                uiManagerModule,
                new DebugComponentOwnershipModule(catalystApplicationContext)));

    if (ReactBuildConfig.DEBUG) {
      nativeModulesList.add(new JSCHeapCapture(catalystApplicationContext));
    }

    return nativeModulesList;
  }
Example #15
0
  private void decrementPendingJSCalls() {
    int newPendingCalls = mPendingJSCalls.decrementAndGet();
    Assertions.assertCondition(newPendingCalls >= 0);
    boolean isNowIdle = newPendingCalls == 0;
    Systrace.traceCounter(
        Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, mJsPendingCallsTitleForTrace, newPendingCalls);

    if (isNowIdle && !mBridgeIdleListeners.isEmpty()) {
      for (NotThreadSafeBridgeIdleDebugListener listener : mBridgeIdleListeners) {
        listener.onTransitionToBridgeIdle();
      }
    }
  }
 /** Sends the given Event to JS, coalescing eligible events if JS is backed up. */
 public void dispatchEvent(Event event) {
   Assertions.assertCondition(event.isInitialized(), "Dispatched event hasn't been initialized");
   synchronized (mEventsStagingLock) {
     mEventStaging.add(event);
     Systrace.startAsyncFlow(
         Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, event.getEventName(), event.getUniqueID());
   }
   if (mRCTEventEmitter != null) {
     // If the host activity is paused, the frame callback may not be currently
     // posted. Ensure that it is so that this event gets delivered promptly.
     mCurrentFrameCallback.maybePostFromNonUI();
   } else {
     // No JS application has started yet, or resumed. This can happen when a ReactRootView is
     // added to view hierarchy, but ReactContext creation has not completed yet. In this case, any
     // touch event dispatch will hit this codepath, and we simply queue them so that they
     // are dispatched once ReactContext creation completes and JS app is running.
   }
 }
  /** Invoked at the end of the transaction to commit any updates to the node hierarchy. */
  public void dispatchViewUpdates(EventDispatcher eventDispatcher, int batchId) {
    for (int i = 0; i < mShadowNodeRegistry.getRootNodeCount(); i++) {
      int tag = mShadowNodeRegistry.getRootTag(i);
      ReactShadowNode cssRoot = mShadowNodeRegistry.getNode(tag);
      notifyOnBeforeLayoutRecursive(cssRoot);

      SystraceMessage.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "cssRoot.calculateLayout")
          .arg("rootTag", tag)
          .flush();
      try {
        cssRoot.calculateLayout(mLayoutContext);
      } finally {
        Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
      }
      applyUpdatesRecursive(cssRoot, 0f, 0f, eventDispatcher);
    }

    mNativeViewHierarchyOptimizer.onBatchComplete();
    mOperationsQueue.dispatchViewUpdates(batchId);
  }
Example #18
0
  private CatalystInstance(
      final CatalystQueueConfigurationSpec catalystQueueConfigurationSpec,
      final JavaScriptExecutor jsExecutor,
      final NativeModuleRegistry registry,
      final JavaScriptModulesConfig jsModulesConfig,
      final JSBundleLoader jsBundleLoader,
      NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) {
    mCatalystQueueConfiguration =
        CatalystQueueConfiguration.create(
            catalystQueueConfigurationSpec, new NativeExceptionHandler());
    mBridgeIdleListeners = new CopyOnWriteArrayList<>();
    mJavaRegistry = registry;
    mJSModuleRegistry = new JavaScriptModuleRegistry(CatalystInstance.this, jsModulesConfig);
    mJSBundleLoader = jsBundleLoader;
    mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler;
    mTraceListener = new JSProfilerTraceListener();
    Systrace.registerListener(mTraceListener);

    final CountDownLatch initLatch = new CountDownLatch(1);
    mCatalystQueueConfiguration
        .getJSQueueThread()
        .runOnQueue(
            new Runnable() {
              @Override
              public void run() {
                initializeBridge(jsExecutor, jsModulesConfig);
                initLatch.countDown();
              }
            });

    try {
      Assertions.assertCondition(
          initLatch.await(BRIDGE_SETUP_TIMEOUT_MS, TimeUnit.MILLISECONDS),
          "Timed out waiting for bridge to initialize!");
    } catch (InterruptedException e) {
      throw new RuntimeException(e);
    }
  }
  /** @return instance of {@link ReactContext} configured a {@link CatalystInstance} set */
  private ReactApplicationContext createReactContext(
      JavaScriptExecutor jsExecutor, JSBundleLoader jsBundleLoader) {
    FLog.i(ReactConstants.TAG, "Creating react context.");
    ReactMarker.logMarker(CREATE_REACT_CONTEXT_START);
    mSourceUrl = jsBundleLoader.getSourceUrl();
    NativeModuleRegistry.Builder nativeRegistryBuilder = new NativeModuleRegistry.Builder();
    JavaScriptModulesConfig.Builder jsModulesBuilder = new JavaScriptModulesConfig.Builder();

    ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);
    if (mUseDeveloperSupport) {
      reactContext.setNativeModuleCallExceptionHandler(mDevSupportManager);
    }

    ReactMarker.logMarker(PROCESS_PACKAGES_START);
    Systrace.beginSection(
        Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "createAndProcessCoreModulesPackage");
    try {
      CoreModulesPackage coreModulesPackage =
          new CoreModulesPackage(this, mBackBtnHandler, mUIImplementationProvider);
      processPackage(coreModulesPackage, reactContext, nativeRegistryBuilder, jsModulesBuilder);
    } finally {
      Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
    }

    // TODO(6818138): Solve use-case of native/js modules overriding
    for (ReactPackage reactPackage : mPackages) {
      Systrace.beginSection(
          Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "createAndProcessCustomReactPackage");
      try {
        processPackage(reactPackage, reactContext, nativeRegistryBuilder, jsModulesBuilder);
      } finally {
        Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
      }
    }
    ReactMarker.logMarker(PROCESS_PACKAGES_END);

    ReactMarker.logMarker(BUILD_NATIVE_MODULE_REGISTRY_START);
    Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "buildNativeModuleRegistry");
    NativeModuleRegistry nativeModuleRegistry;
    try {
      nativeModuleRegistry = nativeRegistryBuilder.build();
    } finally {
      Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
      ReactMarker.logMarker(BUILD_NATIVE_MODULE_REGISTRY_END);
    }

    ReactMarker.logMarker(BUILD_JS_MODULE_CONFIG_START);
    Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "buildJSModuleConfig");
    JavaScriptModulesConfig javaScriptModulesConfig;
    try {
      javaScriptModulesConfig = jsModulesBuilder.build();
    } finally {
      Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
      ReactMarker.logMarker(BUILD_JS_MODULE_CONFIG_END);
    }

    NativeModuleCallExceptionHandler exceptionHandler =
        mNativeModuleCallExceptionHandler != null
            ? mNativeModuleCallExceptionHandler
            : mDevSupportManager;
    CatalystInstanceImpl.Builder catalystInstanceBuilder =
        new CatalystInstanceImpl.Builder()
            .setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
            .setJSExecutor(jsExecutor)
            .setRegistry(nativeModuleRegistry)
            .setJSModulesConfig(javaScriptModulesConfig)
            .setJSBundleLoader(jsBundleLoader)
            .setNativeModuleCallExceptionHandler(exceptionHandler);

    ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_START);
    Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "createCatalystInstance");
    CatalystInstance catalystInstance;
    try {
      catalystInstance = catalystInstanceBuilder.build();
    } finally {
      Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
      ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_END);
    }

    if (mBridgeIdleDebugListener != null) {
      catalystInstance.addBridgeIdleDebugListener(mBridgeIdleDebugListener);
    }

    reactContext.initializeWithInstance(catalystInstance);

    ReactMarker.logMarker(RUN_JS_BUNDLE_START);
    Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "runJSBundle");
    try {
      catalystInstance.runJSBundle();
    } finally {
      Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
      ReactMarker.logMarker(RUN_JS_BUNDLE_END);
    }

    ReactMarker.logMarker(CREATE_REACT_CONTEXT_END);
    return reactContext;
  }