Instance.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #pragma once
  8. #include <condition_variable>
  9. #include <list>
  10. #include <memory>
  11. #include <mutex>
  12. #include <cxxreact/NativeToJsBridge.h>
  13. #ifndef RN_EXPORT
  14. #define RN_EXPORT __attribute__((visibility("default")))
  15. #endif
  16. namespace folly {
  17. struct dynamic;
  18. }
  19. namespace facebook {
  20. namespace react {
  21. class JSBigString;
  22. class JSExecutorFactory;
  23. class MessageQueueThread;
  24. class ModuleRegistry;
  25. class RAMBundleRegistry;
  26. struct InstanceCallback {
  27. virtual ~InstanceCallback() {}
  28. virtual void onBatchComplete() {}
  29. virtual void incrementPendingJSCalls() {}
  30. virtual void decrementPendingJSCalls() {}
  31. };
  32. class RN_EXPORT Instance {
  33. public:
  34. ~Instance();
  35. void initializeBridge(
  36. std::unique_ptr<InstanceCallback> callback,
  37. std::shared_ptr<JSExecutorFactory> jsef,
  38. std::shared_ptr<MessageQueueThread> jsQueue,
  39. std::shared_ptr<ModuleRegistry> moduleRegistry);
  40. void initializeRuntime();
  41. void setSourceURL(std::string sourceURL);
  42. void loadScriptFromString(
  43. std::unique_ptr<const JSBigString> string,
  44. std::string sourceURL,
  45. bool loadSynchronously);
  46. static bool isIndexedRAMBundle(const char *sourcePath);
  47. static bool isIndexedRAMBundle(std::unique_ptr<const JSBigString> *string);
  48. void loadRAMBundleFromString(
  49. std::unique_ptr<const JSBigString> script,
  50. const std::string &sourceURL);
  51. void loadRAMBundleFromFile(
  52. const std::string &sourcePath,
  53. const std::string &sourceURL,
  54. bool loadSynchronously);
  55. void loadRAMBundle(
  56. std::unique_ptr<RAMBundleRegistry> bundleRegistry,
  57. std::unique_ptr<const JSBigString> startupScript,
  58. std::string startupScriptSourceURL,
  59. bool loadSynchronously);
  60. bool supportsProfiling();
  61. void setGlobalVariable(
  62. std::string propName,
  63. std::unique_ptr<const JSBigString> jsonValue);
  64. void *getJavaScriptContext();
  65. bool isInspectable();
  66. bool isBatchActive();
  67. void callJSFunction(
  68. std::string &&module,
  69. std::string &&method,
  70. folly::dynamic &&params);
  71. void callJSCallback(uint64_t callbackId, folly::dynamic &&params);
  72. // This method is experimental, and may be modified or removed.
  73. void registerBundle(uint32_t bundleId, const std::string &bundlePath);
  74. const ModuleRegistry &getModuleRegistry() const;
  75. ModuleRegistry &getModuleRegistry();
  76. void handleMemoryPressure(int pressureLevel);
  77. /**
  78. * JS CallInvoker is used by TurboModules to schedule work on the JS thread.
  79. *
  80. * Why is the bridge creating JS CallInvoker?
  81. *
  82. * - After every Native -> JS call in the TurboModule system, the bridge
  83. * needs to flush all queued NativeModule method calls. The bridge must
  84. * also dispatch onBatchComplete if the queue of NativeModule method calls
  85. * was not empty.
  86. */
  87. std::shared_ptr<CallInvoker> getJSCallInvoker();
  88. /**
  89. * Native CallInvoker is used by TurboModules to schedule work on the
  90. * NativeModule thread(s).
  91. *
  92. * Why is the bridge decorating native CallInvoker?
  93. *
  94. * - The bridge must be informed of all TurboModule async method calls. Why?
  95. * When all queued NativeModule method calls are flushed by a call from
  96. * Native -> JS, if that queue was non-zero in size, JsToNativeBridge
  97. * dispatches onBatchComplete. When we turn our NativeModules to
  98. * TurboModuels, there will be less and less pending NativeModule method
  99. * calls, so onBatchComplete will not fire as often. Therefore, the bridge
  100. * needs to know how many TurboModule async method calls have been completed
  101. * since the last time the bridge was flushed. If this number is non-zero,
  102. * we fire onBatchComplete.
  103. *
  104. * Why can't we just create and return a new native CallInvoker?
  105. *
  106. * - On Android, we have one NativeModule thread. That thread is created and
  107. * managed outisde of NativeToJsBridge. On iOS, we have one MethodQueue per
  108. * module. Those MethodQueues are also created and managed outside of
  109. * NativeToJsBridge. Therefore, we need to pass in a CallInvoker that
  110. * schedules work on the respective thread.
  111. */
  112. std::shared_ptr<CallInvoker> getDecoratedNativeCallInvoker(
  113. std::shared_ptr<CallInvoker> nativeInvoker);
  114. private:
  115. void callNativeModules(folly::dynamic &&calls, bool isEndOfBatch);
  116. void loadBundle(
  117. std::unique_ptr<RAMBundleRegistry> bundleRegistry,
  118. std::unique_ptr<const JSBigString> startupScript,
  119. std::string startupScriptSourceURL);
  120. void loadBundleSync(
  121. std::unique_ptr<RAMBundleRegistry> bundleRegistry,
  122. std::unique_ptr<const JSBigString> startupScript,
  123. std::string startupScriptSourceURL);
  124. std::shared_ptr<InstanceCallback> callback_;
  125. std::shared_ptr<NativeToJsBridge> nativeToJsBridge_;
  126. std::shared_ptr<ModuleRegistry> moduleRegistry_;
  127. std::mutex m_syncMutex;
  128. std::condition_variable m_syncCV;
  129. bool m_syncReady = false;
  130. class JSCallInvoker : public CallInvoker {
  131. private:
  132. std::weak_ptr<NativeToJsBridge> m_nativeToJsBridge;
  133. std::mutex m_mutex;
  134. bool m_shouldBuffer = true;
  135. std::list<std::function<void()>> m_workBuffer;
  136. void scheduleAsync(std::function<void()> &&work);
  137. public:
  138. void setNativeToJsBridgeAndFlushCalls(
  139. std::weak_ptr<NativeToJsBridge> nativeToJsBridge);
  140. void invokeAsync(std::function<void()> &&work) override;
  141. void invokeSync(std::function<void()> &&work) override;
  142. };
  143. std::shared_ptr<JSCallInvoker> jsCallInvoker_ =
  144. std::make_shared<JSCallInvoker>();
  145. };
  146. } // namespace react
  147. } // namespace facebook