RCTObjcExecutor.mm 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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 "RCTObjcExecutor.h"
  8. #import <React/RCTCxxUtils.h>
  9. #import <React/RCTFollyConvert.h>
  10. #import <React/RCTJavaScriptExecutor.h>
  11. #import <React/RCTLog.h>
  12. #import <React/RCTProfile.h>
  13. #import <React/RCTUtils.h>
  14. #import <cxxreact/JSBigString.h>
  15. #import <cxxreact/JSExecutor.h>
  16. #import <cxxreact/MessageQueueThread.h>
  17. #import <cxxreact/ModuleRegistry.h>
  18. #import <cxxreact/RAMBundleRegistry.h>
  19. #import <folly/json.h>
  20. namespace facebook {
  21. namespace react {
  22. namespace {
  23. class JSEException : public std::runtime_error {
  24. public:
  25. JSEException(NSError *error) : runtime_error([[error description] UTF8String]) {}
  26. };
  27. class RCTObjcExecutor : public JSExecutor {
  28. public:
  29. RCTObjcExecutor(
  30. id<RCTJavaScriptExecutor> jse,
  31. RCTJavaScriptCompleteBlock errorBlock,
  32. std::shared_ptr<MessageQueueThread> jsThread,
  33. std::shared_ptr<ExecutorDelegate> delegate)
  34. : m_jse(jse), m_errorBlock(errorBlock), m_delegate(std::move(delegate)), m_jsThread(std::move(jsThread))
  35. {
  36. m_jsCallback = ^(id json, NSError *error) {
  37. if (error) {
  38. // Do not use "m_errorBlock" here as the bridge might be in the middle
  39. // of invalidation as a result of error handling and "this" can be
  40. // already deallocated.
  41. errorBlock(error);
  42. return;
  43. }
  44. m_jsThread->runOnQueue(
  45. [this, json] { m_delegate->callNativeModules(*this, convertIdToFollyDynamic(json), true); });
  46. };
  47. // Synchronously initialize the executor
  48. [jse setUp];
  49. folly::dynamic nativeModuleConfig = folly::dynamic::array;
  50. auto moduleRegistry = m_delegate->getModuleRegistry();
  51. for (const auto &name : moduleRegistry->moduleNames()) {
  52. auto config = moduleRegistry->getConfig(name);
  53. nativeModuleConfig.push_back(config ? config->config : nullptr);
  54. }
  55. folly::dynamic config = folly::dynamic::object("remoteModuleConfig", std::move(nativeModuleConfig));
  56. setGlobalVariable("__fbBatchedBridgeConfig", std::make_unique<JSBigStdString>(folly::toJson(config)));
  57. }
  58. void initializeRuntime() override
  59. {
  60. // We do nothing here since initialization is done in the constructor
  61. }
  62. void loadBundle(std::unique_ptr<const JSBigString> script, std::string sourceURL) override
  63. {
  64. RCTProfileBeginFlowEvent();
  65. [m_jse executeApplicationScript:[NSData dataWithBytes:script->c_str() length:script->size()]
  66. sourceURL:[[NSURL alloc] initWithString:@(sourceURL.c_str())]
  67. onComplete:^(NSError *error) {
  68. RCTProfileEndFlowEvent();
  69. if (error) {
  70. m_errorBlock(error);
  71. return;
  72. }
  73. [m_jse flushedQueue:m_jsCallback];
  74. }];
  75. }
  76. void setBundleRegistry(std::unique_ptr<RAMBundleRegistry>) override
  77. {
  78. RCTAssert(NO, @"RAM bundles are not supported in RCTObjcExecutor");
  79. }
  80. void registerBundle(uint32_t __unused bundleId, const std::string __unused &bundlePath) override
  81. {
  82. RCTAssert(NO, @"RAM bundles are not supported in RCTObjcExecutor");
  83. }
  84. void callFunction(const std::string &module, const std::string &method, const folly::dynamic &arguments) override
  85. {
  86. [m_jse callFunctionOnModule:@(module.c_str())
  87. method:@(method.c_str())
  88. arguments:convertFollyDynamicToId(arguments)
  89. callback:m_jsCallback];
  90. }
  91. void invokeCallback(double callbackId, const folly::dynamic &arguments) override
  92. {
  93. [m_jse invokeCallbackID:@(callbackId) arguments:convertFollyDynamicToId(arguments) callback:m_jsCallback];
  94. }
  95. virtual void setGlobalVariable(std::string propName, std::unique_ptr<const JSBigString> jsonValue) override
  96. {
  97. [m_jse injectJSONText:@(jsonValue->c_str()) asGlobalObjectNamed:@(propName.c_str()) callback:m_errorBlock];
  98. }
  99. virtual std::string getDescription() override
  100. {
  101. return [NSStringFromClass([m_jse class]) UTF8String];
  102. }
  103. private:
  104. id<RCTJavaScriptExecutor> m_jse;
  105. RCTJavaScriptCompleteBlock m_errorBlock;
  106. std::shared_ptr<ExecutorDelegate> m_delegate;
  107. std::shared_ptr<MessageQueueThread> m_jsThread;
  108. RCTJavaScriptCallback m_jsCallback;
  109. };
  110. }
  111. RCTObjcExecutorFactory::RCTObjcExecutorFactory(id<RCTJavaScriptExecutor> jse, RCTJavaScriptCompleteBlock errorBlock)
  112. : m_jse(jse), m_errorBlock(errorBlock)
  113. {
  114. }
  115. std::unique_ptr<JSExecutor> RCTObjcExecutorFactory::createJSExecutor(
  116. std::shared_ptr<ExecutorDelegate> delegate,
  117. std::shared_ptr<MessageQueueThread> jsQueue)
  118. {
  119. return std::unique_ptr<JSExecutor>(new RCTObjcExecutor(m_jse, m_errorBlock, jsQueue, delegate));
  120. }
  121. }
  122. }