123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- /*
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
- #pragma once
- #include <condition_variable>
- #include <list>
- #include <memory>
- #include <mutex>
- #include <cxxreact/NativeToJsBridge.h>
- #ifndef RN_EXPORT
- #define RN_EXPORT __attribute__((visibility("default")))
- #endif
- namespace folly {
- struct dynamic;
- }
- namespace facebook {
- namespace react {
- class JSBigString;
- class JSExecutorFactory;
- class MessageQueueThread;
- class ModuleRegistry;
- class RAMBundleRegistry;
- struct InstanceCallback {
- virtual ~InstanceCallback() {}
- virtual void onBatchComplete() {}
- virtual void incrementPendingJSCalls() {}
- virtual void decrementPendingJSCalls() {}
- };
- class RN_EXPORT Instance {
- public:
- ~Instance();
- void initializeBridge(
- std::unique_ptr<InstanceCallback> callback,
- std::shared_ptr<JSExecutorFactory> jsef,
- std::shared_ptr<MessageQueueThread> jsQueue,
- std::shared_ptr<ModuleRegistry> moduleRegistry);
- void initializeRuntime();
- void setSourceURL(std::string sourceURL);
- void loadScriptFromString(
- std::unique_ptr<const JSBigString> string,
- std::string sourceURL,
- bool loadSynchronously);
- static bool isIndexedRAMBundle(const char *sourcePath);
- static bool isIndexedRAMBundle(std::unique_ptr<const JSBigString> *string);
- void loadRAMBundleFromString(
- std::unique_ptr<const JSBigString> script,
- const std::string &sourceURL);
- void loadRAMBundleFromFile(
- const std::string &sourcePath,
- const std::string &sourceURL,
- bool loadSynchronously);
- void loadRAMBundle(
- std::unique_ptr<RAMBundleRegistry> bundleRegistry,
- std::unique_ptr<const JSBigString> startupScript,
- std::string startupScriptSourceURL,
- bool loadSynchronously);
- bool supportsProfiling();
- void setGlobalVariable(
- std::string propName,
- std::unique_ptr<const JSBigString> jsonValue);
- void *getJavaScriptContext();
- bool isInspectable();
- bool isBatchActive();
- void callJSFunction(
- std::string &&module,
- std::string &&method,
- folly::dynamic &¶ms);
- void callJSCallback(uint64_t callbackId, folly::dynamic &¶ms);
- // This method is experimental, and may be modified or removed.
- void registerBundle(uint32_t bundleId, const std::string &bundlePath);
- const ModuleRegistry &getModuleRegistry() const;
- ModuleRegistry &getModuleRegistry();
- void handleMemoryPressure(int pressureLevel);
- /**
- * JS CallInvoker is used by TurboModules to schedule work on the JS thread.
- *
- * Why is the bridge creating JS CallInvoker?
- *
- * - After every Native -> JS call in the TurboModule system, the bridge
- * needs to flush all queued NativeModule method calls. The bridge must
- * also dispatch onBatchComplete if the queue of NativeModule method calls
- * was not empty.
- */
- std::shared_ptr<CallInvoker> getJSCallInvoker();
- /**
- * Native CallInvoker is used by TurboModules to schedule work on the
- * NativeModule thread(s).
- *
- * Why is the bridge decorating native CallInvoker?
- *
- * - The bridge must be informed of all TurboModule async method calls. Why?
- * When all queued NativeModule method calls are flushed by a call from
- * Native -> JS, if that queue was non-zero in size, JsToNativeBridge
- * dispatches onBatchComplete. When we turn our NativeModules to
- * TurboModuels, there will be less and less pending NativeModule method
- * calls, so onBatchComplete will not fire as often. Therefore, the bridge
- * needs to know how many TurboModule async method calls have been completed
- * since the last time the bridge was flushed. If this number is non-zero,
- * we fire onBatchComplete.
- *
- * Why can't we just create and return a new native CallInvoker?
- *
- * - On Android, we have one NativeModule thread. That thread is created and
- * managed outisde of NativeToJsBridge. On iOS, we have one MethodQueue per
- * module. Those MethodQueues are also created and managed outside of
- * NativeToJsBridge. Therefore, we need to pass in a CallInvoker that
- * schedules work on the respective thread.
- */
- std::shared_ptr<CallInvoker> getDecoratedNativeCallInvoker(
- std::shared_ptr<CallInvoker> nativeInvoker);
- private:
- void callNativeModules(folly::dynamic &&calls, bool isEndOfBatch);
- void loadBundle(
- std::unique_ptr<RAMBundleRegistry> bundleRegistry,
- std::unique_ptr<const JSBigString> startupScript,
- std::string startupScriptSourceURL);
- void loadBundleSync(
- std::unique_ptr<RAMBundleRegistry> bundleRegistry,
- std::unique_ptr<const JSBigString> startupScript,
- std::string startupScriptSourceURL);
- std::shared_ptr<InstanceCallback> callback_;
- std::shared_ptr<NativeToJsBridge> nativeToJsBridge_;
- std::shared_ptr<ModuleRegistry> moduleRegistry_;
- std::mutex m_syncMutex;
- std::condition_variable m_syncCV;
- bool m_syncReady = false;
- class JSCallInvoker : public CallInvoker {
- private:
- std::weak_ptr<NativeToJsBridge> m_nativeToJsBridge;
- std::mutex m_mutex;
- bool m_shouldBuffer = true;
- std::list<std::function<void()>> m_workBuffer;
- void scheduleAsync(std::function<void()> &&work);
- public:
- void setNativeToJsBridgeAndFlushCalls(
- std::weak_ptr<NativeToJsBridge> nativeToJsBridge);
- void invokeAsync(std::function<void()> &&work) override;
- void invokeSync(std::function<void()> &&work) override;
- };
- std::shared_ptr<JSCallInvoker> jsCallInvoker_ =
- std::make_shared<JSCallInvoker>();
- };
- } // namespace react
- } // namespace facebook
|