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;
  }
  /**
   * 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();
      }
    }
  }
  @Override
  public void runJSBundle() {
    try {
      mJSBundleHasLoaded =
          mReactQueueConfiguration
              .getJSQueueThread()
              .callOnQueue(
                  new Callable<Boolean>() {
                    @Override
                    public Boolean call() throws Exception {
                      Assertions.assertCondition(
                          !mJSBundleHasLoaded, "JS bundle was already loaded!");

                      incrementPendingJSCalls();

                      Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "loadJSScript");
                      try {
                        mJSBundleLoader.loadScript(mBridge);

                        // This is registered after JS starts since it makes a JS call
                        Systrace.registerListener(mTraceListener);
                      } catch (JSExecutionException e) {
                        mNativeModuleCallExceptionHandler.handleException(e);
                      } finally {
                        Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
                      }

                      return true;
                    }
                  })
              .get();
    } catch (Exception t) {
      throw new RuntimeException(t);
    }
  }
 @Override
 public void handleMemoryPressure(final MemoryPressure level) {
   mReactQueueConfiguration
       .getJSQueueThread()
       .runOnQueue(
           new Runnable() {
             @Override
             public void run() {
               Assertions.assertNotNull(mBridge).handleMemoryPressure(level);
             }
           });
 }
  private CatalystInstanceImpl(
      final ReactQueueConfigurationSpec ReactQueueConfigurationSpec,
      final JavaScriptExecutor jsExecutor,
      final NativeModuleRegistry registry,
      final JavaScriptModulesConfig jsModulesConfig,
      final JSBundleLoader jsBundleLoader,
      NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) {
    FLog.d(ReactConstants.TAG, "Initializing React Bridge.");
    mReactQueueConfiguration =
        ReactQueueConfigurationImpl.create(
            ReactQueueConfigurationSpec, new NativeExceptionHandler());
    mBridgeIdleListeners = new CopyOnWriteArrayList<>();
    mJavaRegistry = registry;
    mJSModuleRegistry = new JavaScriptModuleRegistry(CatalystInstanceImpl.this, jsModulesConfig);
    mJSBundleLoader = jsBundleLoader;
    mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler;
    mTraceListener = new JSProfilerTraceListener();

    try {
      mBridge =
          mReactQueueConfiguration
              .getJSQueueThread()
              .callOnQueue(
                  new Callable<ReactBridge>() {
                    @Override
                    public ReactBridge call() throws Exception {
                      Systrace.beginSection(
                          Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "initializeBridge");
                      try {
                        return initializeBridge(jsExecutor, jsModulesConfig);
                      } finally {
                        Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
                      }
                    }
                  })
              .get();
    } catch (Exception t) {
      throw new RuntimeException("Failed to initialize bridge", t);
    }
  }
 private void synchronouslyDisposeBridgeOnJSThread() {
   final SimpleSettableFuture<Void> bridgeDisposeFuture = new SimpleSettableFuture<>();
   mReactQueueConfiguration
       .getJSQueueThread()
       .runOnQueue(
           new Runnable() {
             @Override
             public void run() {
               mBridge.destroy();
               mBridge.dispose();
               bridgeDisposeFuture.set(null);
             }
           });
   bridgeDisposeFuture.getOrThrow();
 }