RCTBridgeModule.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  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. #import <Foundation/Foundation.h>
  8. #import <React/RCTDefines.h>
  9. @class RCTBridge;
  10. @protocol RCTBridgeMethod;
  11. /**
  12. * The type of a block that is capable of sending a response to a bridged
  13. * operation. Use this for returning callback methods to JS.
  14. */
  15. typedef void (^RCTResponseSenderBlock)(NSArray *response);
  16. /**
  17. * The type of a block that is capable of sending an error response to a
  18. * bridged operation. Use this for returning error information to JS.
  19. */
  20. typedef void (^RCTResponseErrorBlock)(NSError *error);
  21. /**
  22. * Block that bridge modules use to resolve the JS promise waiting for a result.
  23. * Nil results are supported and are converted to JS's undefined value.
  24. */
  25. typedef void (^RCTPromiseResolveBlock)(id result);
  26. /**
  27. * Block that bridge modules use to reject the JS promise waiting for a result.
  28. * The error may be nil but it is preferable to pass an NSError object for more
  29. * precise error messages.
  30. */
  31. typedef void (^RCTPromiseRejectBlock)(NSString *code, NSString *message, NSError *error);
  32. /**
  33. * This constant can be returned from +methodQueue to force module
  34. * methods to be called on the JavaScript thread. This can have serious
  35. * implications for performance, so only use this if you're sure it's what
  36. * you need.
  37. *
  38. * NOTE: RCTJSThread is not a real libdispatch queue
  39. */
  40. RCT_EXTERN dispatch_queue_t RCTJSThread;
  41. RCT_EXTERN_C_BEGIN
  42. typedef struct RCTMethodInfo {
  43. const char *const jsName;
  44. const char *const objcName;
  45. const BOOL isSync;
  46. } RCTMethodInfo;
  47. RCT_EXTERN_C_END
  48. /**
  49. * Provides the interface needed to register a bridge module.
  50. */
  51. @protocol RCTBridgeModule <NSObject>
  52. /**
  53. * Place this macro in your class implementation to automatically register
  54. * your module with the bridge when it loads. The optional js_name argument
  55. * will be used as the JS module name. If omitted, the JS module name will
  56. * match the Objective-C class name.
  57. */
  58. #define RCT_EXPORT_MODULE(js_name) \
  59. RCT_EXTERN void RCTRegisterModule(Class); \
  60. +(NSString *)moduleName \
  61. { \
  62. return @ #js_name; \
  63. } \
  64. +(void)load \
  65. { \
  66. RCTRegisterModule(self); \
  67. }
  68. /**
  69. * Same as RCT_EXPORT_MODULE, but uses __attribute__((constructor)) for module
  70. * registration. Useful for registering swift classes that forbids use of load
  71. * Used in RCT_EXTERN_REMAP_MODULE
  72. */
  73. #define RCT_EXPORT_MODULE_NO_LOAD(js_name, objc_name) \
  74. RCT_EXTERN void RCTRegisterModule(Class); \
  75. +(NSString *)moduleName \
  76. { \
  77. return @ #js_name; \
  78. } \
  79. __attribute__((constructor)) static void RCT_CONCAT(initialize_, objc_name)() \
  80. { \
  81. RCTRegisterModule([objc_name class]); \
  82. }
  83. /**
  84. * To improve startup performance users may want to generate their module lists
  85. * at build time and hook the delegate to merge with the runtime list. This
  86. * macro takes the place of the above for those cases by omitting the +load
  87. * generation.
  88. *
  89. */
  90. #define RCT_EXPORT_PRE_REGISTERED_MODULE(js_name) \
  91. +(NSString *)moduleName \
  92. { \
  93. return @ #js_name; \
  94. }
  95. // Implemented by RCT_EXPORT_MODULE
  96. + (NSString *)moduleName;
  97. @optional
  98. /**
  99. * A reference to the RCTBridge. Useful for modules that require access
  100. * to bridge features, such as sending events or making JS calls. This
  101. * will be set automatically by the bridge when it initializes the module.
  102. * To implement this in your module, just add `@synthesize bridge = _bridge;`
  103. * If using Swift, add `@objc var bridge: RCTBridge!` to your module.
  104. */
  105. @property (nonatomic, weak, readonly) RCTBridge *bridge;
  106. /**
  107. * The queue that will be used to call all exported methods. If omitted, this
  108. * will call on a default background queue, which is avoids blocking the main
  109. * thread.
  110. *
  111. * If the methods in your module need to interact with UIKit methods, they will
  112. * probably need to call those on the main thread, as most of UIKit is main-
  113. * thread-only. You can tell React Native to call your module methods on the
  114. * main thread by returning a reference to the main queue, like this:
  115. *
  116. * - (dispatch_queue_t)methodQueue
  117. * {
  118. * return dispatch_get_main_queue();
  119. * }
  120. *
  121. * If you don't want to specify the queue yourself, but you need to use it
  122. * inside your class (e.g. if you have internal methods that need to dispatch
  123. * onto that queue), you can just add `@synthesize methodQueue = _methodQueue;`
  124. * and the bridge will populate the methodQueue property for you automatically
  125. * when it initializes the module.
  126. */
  127. @property (nonatomic, strong, readonly) dispatch_queue_t methodQueue;
  128. /**
  129. * Wrap the parameter line of your method implementation with this macro to
  130. * expose it to JS. By default the exposed method will match the first part of
  131. * the Objective-C method selector name (up to the first colon). Use
  132. * RCT_REMAP_METHOD to specify the JS name of the method.
  133. *
  134. * For example, in ModuleName.m:
  135. *
  136. * - (void)doSomething:(NSString *)aString withA:(NSInteger)a andB:(NSInteger)b
  137. * { ... }
  138. *
  139. * becomes
  140. *
  141. * RCT_EXPORT_METHOD(doSomething:(NSString *)aString
  142. * withA:(NSInteger)a
  143. * andB:(NSInteger)b)
  144. * { ... }
  145. *
  146. * and is exposed to JavaScript as `NativeModules.ModuleName.doSomething`.
  147. *
  148. * ## Promises
  149. *
  150. * Bridge modules can also define methods that are exported to JavaScript as
  151. * methods that return a Promise, and are compatible with JS async functions.
  152. *
  153. * Declare the last two parameters of your native method to be a resolver block
  154. * and a rejecter block. The resolver block must precede the rejecter block.
  155. *
  156. * For example:
  157. *
  158. * RCT_EXPORT_METHOD(doSomethingAsync:(NSString *)aString
  159. * resolver:(RCTPromiseResolveBlock)resolve
  160. * rejecter:(RCTPromiseRejectBlock)reject
  161. * { ... }
  162. *
  163. * Calling `NativeModules.ModuleName.doSomethingAsync(aString)` from
  164. * JavaScript will return a promise that is resolved or rejected when your
  165. * native method implementation calls the respective block.
  166. *
  167. */
  168. #define RCT_EXPORT_METHOD(method) RCT_REMAP_METHOD(, method)
  169. /**
  170. * Same as RCT_EXPORT_METHOD but the method is called from JS
  171. * synchronously **on the JS thread**, possibly returning a result.
  172. *
  173. * WARNING: in the vast majority of cases, you should use RCT_EXPORT_METHOD which
  174. * allows your native module methods to be called asynchronously: calling
  175. * methods synchronously can have strong performance penalties and introduce
  176. * threading-related bugs to your native modules.
  177. *
  178. * The return type must be of object type (id) and should be serializable
  179. * to JSON. This means that the hook can only return nil or JSON values
  180. * (e.g. NSNumber, NSString, NSArray, NSDictionary).
  181. *
  182. * Calling these methods when running under the websocket executor
  183. * is currently not supported.
  184. */
  185. #define RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(method) RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(id, method)
  186. #define RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(returnType, method) \
  187. RCT_REMAP_BLOCKING_SYNCHRONOUS_METHOD(, returnType, method)
  188. /**
  189. * Similar to RCT_EXPORT_METHOD but lets you set the JS name of the exported
  190. * method. Example usage:
  191. *
  192. * RCT_REMAP_METHOD(executeQueryWithParameters,
  193. * executeQuery:(NSString *)query parameters:(NSDictionary *)parameters)
  194. * { ... }
  195. */
  196. #define RCT_REMAP_METHOD(js_name, method) \
  197. _RCT_EXTERN_REMAP_METHOD(js_name, method, NO) \
  198. -(void)method RCT_DYNAMIC;
  199. /**
  200. * Similar to RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD but lets you set
  201. * the JS name of the exported method. Example usage:
  202. *
  203. * RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(executeQueryWithParameters,
  204. * executeQuery:(NSString *)query parameters:(NSDictionary *)parameters)
  205. * { ... }
  206. */
  207. #define RCT_REMAP_BLOCKING_SYNCHRONOUS_METHOD(js_name, returnType, method) \
  208. _RCT_EXTERN_REMAP_METHOD(js_name, method, YES) \
  209. -(returnType)method RCT_DYNAMIC;
  210. /**
  211. * Use this macro in a private Objective-C implementation file to automatically
  212. * register an external module with the bridge when it loads. This allows you to
  213. * register Swift or private Objective-C classes with the bridge.
  214. *
  215. * For example if one wanted to export a Swift class to the bridge:
  216. *
  217. * MyModule.swift:
  218. *
  219. * @objc(MyModule) class MyModule: NSObject {
  220. *
  221. * @objc func doSomething(string: String! withFoo a: Int, bar b: Int) { ... }
  222. *
  223. * }
  224. *
  225. * MyModuleExport.m:
  226. *
  227. * #import <React/RCTBridgeModule.h>
  228. *
  229. * @interface RCT_EXTERN_MODULE(MyModule, NSObject)
  230. *
  231. * RCT_EXTERN_METHOD(doSomething:(NSString *)string withFoo:(NSInteger)a bar:(NSInteger)b)
  232. *
  233. * @end
  234. *
  235. * This will now expose MyModule and the method to JavaScript via
  236. * `NativeModules.MyModule.doSomething`
  237. */
  238. #define RCT_EXTERN_MODULE(objc_name, objc_supername) RCT_EXTERN_REMAP_MODULE(, objc_name, objc_supername)
  239. /**
  240. * Like RCT_EXTERN_MODULE, but allows setting a custom JavaScript name.
  241. */
  242. #define RCT_EXTERN_REMAP_MODULE(js_name, objc_name, objc_supername) \
  243. objc_name: \
  244. objc_supername @ \
  245. end @interface objc_name(RCTExternModule)<RCTBridgeModule> \
  246. @end \
  247. @implementation objc_name (RCTExternModule) \
  248. RCT_EXPORT_MODULE_NO_LOAD(js_name, objc_name)
  249. /**
  250. * Use this macro in accordance with RCT_EXTERN_MODULE to export methods
  251. * of an external module.
  252. */
  253. #define RCT_EXTERN_METHOD(method) _RCT_EXTERN_REMAP_METHOD(, method, NO)
  254. /**
  255. * Use this macro in accordance with RCT_EXTERN_MODULE to export methods
  256. * of an external module that should be invoked synchronously.
  257. */
  258. #define RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(method) _RCT_EXTERN_REMAP_METHOD(, method, YES)
  259. /**
  260. * Like RCT_EXTERN_REMAP_METHOD, but allows setting a custom JavaScript name
  261. * and also whether this method is synchronous.
  262. */
  263. #define _RCT_EXTERN_REMAP_METHOD(js_name, method, is_blocking_synchronous_method) \
  264. +(const RCTMethodInfo *)RCT_CONCAT(__rct_export__, RCT_CONCAT(js_name, RCT_CONCAT(__LINE__, __COUNTER__))) \
  265. { \
  266. static RCTMethodInfo config = {#js_name, #method, is_blocking_synchronous_method}; \
  267. return &config; \
  268. }
  269. /**
  270. * Most modules can be used from any thread. All of the modules exported non-sync method will be called on its
  271. * methodQueue, and the module will be constructed lazily when its first invoked. Some modules have main need to access
  272. * information that's main queue only (e.g. most UIKit classes). Since we don't want to dispatch synchronously to the
  273. * main thread to this safely, we construct these modules and export their constants ahead-of-time.
  274. *
  275. * Note that when set to false, the module constructor will be called from any thread.
  276. *
  277. * This requirement is currently inferred by checking if the module has a custom initializer or if there's exported
  278. * constants. In the future, we'll stop automatically inferring this and instead only rely on this method.
  279. */
  280. + (BOOL)requiresMainQueueSetup;
  281. /**
  282. * Injects methods into JS. Entries in this array are used in addition to any
  283. * methods defined using the macros above. This method is called only once,
  284. * before registration.
  285. */
  286. - (NSArray<id<RCTBridgeMethod>> *)methodsToExport;
  287. /**
  288. * Injects constants into JS. These constants are made accessible via NativeModules.ModuleName.X. It is only called once
  289. * for the lifetime of the bridge, so it is not suitable for returning dynamic values, but may be used for long-lived
  290. * values such as session keys, that are regenerated only as part of a reload of the entire React application.
  291. *
  292. * If you implement this method and do not implement `requiresMainQueueSetup`, you will trigger deprecated logic
  293. * that eagerly initializes your module on bridge startup. In the future, this behaviour will be changed to default
  294. * to initializing lazily, and even modules with constants will be initialized lazily.
  295. */
  296. - (NSDictionary *)constantsToExport;
  297. /**
  298. * Notifies the module that a batch of JS method invocations has just completed.
  299. */
  300. - (void)batchDidComplete;
  301. /**
  302. * Notifies the module that the active batch of JS method invocations has been
  303. * partially flushed.
  304. *
  305. * This occurs before -batchDidComplete, and more frequently.
  306. */
  307. - (void)partialBatchDidFlush;
  308. @end
  309. /**
  310. * A protocol that allows TurboModules to do lookup on other TurboModules.
  311. * Calling these methods may cause a module to be synchronously instantiated.
  312. */
  313. @protocol RCTTurboModuleLookupDelegate <NSObject>
  314. - (id)moduleForName:(const char *)moduleName;
  315. /**
  316. * Rationale:
  317. * When TurboModules lookup other modules by name, we first check the TurboModule
  318. * registry to see if a TurboModule exists with the respective name. In this case,
  319. * we don't want a RedBox to be raised if the TurboModule isn't found.
  320. *
  321. * This method is deprecated and will be deleted after the migration from
  322. * TurboModules to TurboModules is complete.
  323. */
  324. - (id)moduleForName:(const char *)moduleName warnOnLookupFailure:(BOOL)warnOnLookupFailure;
  325. - (BOOL)moduleIsInitialized:(const char *)moduleName;
  326. @end
  327. /**
  328. * Experimental.
  329. * A protocol to declare that a class supports TurboModule.
  330. * This may be removed in the future.
  331. * See RCTTurboModule.h for actual signature.
  332. */
  333. @protocol RCTTurboModule;