Remove JsToNativeBridge's nativeQueue
Reviewed By: mhorowitz Differential Revision: D4589737 fbshipit-source-id: 3b2730417d99c4f98cfaad386bc50328f2551592
This commit is contained in:
parent
fbf6d1aaeb
commit
d7b37c4050
|
@ -101,70 +101,25 @@ namespace {
|
|||
// is not the JS thread. C++ modules don't use RCTNativeModule, so this little
|
||||
// adapter does the work.
|
||||
|
||||
class QueueNativeModule : public NativeModule {
|
||||
class DispatchMessageQueueThread : public MessageQueueThread {
|
||||
public:
|
||||
QueueNativeModule(RCTCxxBridge *bridge,
|
||||
std::unique_ptr<NativeModule> module)
|
||||
: bridge_(bridge)
|
||||
, module_(std::move(module))
|
||||
// Create new queue (store queueName, as it isn't retained by dispatch_queue)
|
||||
, queueName_("com.facebook.react." + module_->getName() + "Queue")
|
||||
, queue_(dispatch_queue_create(queueName_.c_str(), DISPATCH_QUEUE_SERIAL)) {}
|
||||
DispatchMessageQueueThread(RCTModuleData *moduleData)
|
||||
: moduleData_(moduleData) {}
|
||||
|
||||
std::string getName() override {
|
||||
return module_->getName();
|
||||
}
|
||||
|
||||
std::vector<MethodDescriptor> getMethods() override {
|
||||
return module_->getMethods();
|
||||
}
|
||||
|
||||
folly::dynamic getConstants() override {
|
||||
return module_->getConstants();
|
||||
}
|
||||
|
||||
bool supportsWebWorkers() override {
|
||||
return module_->supportsWebWorkers();
|
||||
}
|
||||
|
||||
void invoke(ExecutorToken token, unsigned int reactMethodId,
|
||||
folly::dynamic &¶ms) override {
|
||||
__weak RCTCxxBridge *bridge = bridge_;
|
||||
auto module = module_;
|
||||
auto cparams = std::make_shared<folly::dynamic>(std::move(params));
|
||||
dispatch_async(queue_, ^{
|
||||
if (!bridge || !bridge.valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
module->invoke(token, reactMethodId, std::move(*cparams));
|
||||
void runOnQueue(std::function<void()>&& func) override {
|
||||
dispatch_async(moduleData_.methodQueue, [func=std::move(func)] {
|
||||
func();
|
||||
});
|
||||
}
|
||||
|
||||
MethodCallResult callSerializableNativeHook(
|
||||
ExecutorToken token, unsigned int reactMethodId,
|
||||
folly::dynamic &&args) override {
|
||||
return module_->callSerializableNativeHook(token, reactMethodId, std::move(args));
|
||||
void runOnQueueSync(std::function<void()>&& func) override {
|
||||
LOG(FATAL) << "Unsupported operation";
|
||||
}
|
||||
void quitSynchronous() override {
|
||||
LOG(FATAL) << "Unsupported operation";
|
||||
}
|
||||
|
||||
private:
|
||||
RCTCxxBridge *bridge_;
|
||||
std::shared_ptr<NativeModule> module_;
|
||||
std::string queueName_;
|
||||
dispatch_queue_t queue_;
|
||||
};
|
||||
|
||||
|
||||
// This is a temporary hack. The cxx bridge assumes a single native
|
||||
// queue handles all native method calls, but that's false on ios. So
|
||||
// this is a no-thread passthrough, and queues are handled in
|
||||
// RCTNativeModule. A similar refactoring should be done on the Java
|
||||
// bridge.
|
||||
class InlineMessageQueueThread : public MessageQueueThread {
|
||||
public:
|
||||
void runOnQueue(std::function<void()>&& func) override { func(); }
|
||||
void runOnQueueSync(std::function<void()>&& func) override { func(); }
|
||||
void quitSynchronous() override {}
|
||||
RCTModuleData *moduleData_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -551,12 +506,13 @@ struct RCTInstanceCallback : public InstanceCallback {
|
|||
if (![moduleData hasInstance]) {
|
||||
continue;
|
||||
}
|
||||
modules.emplace_back(
|
||||
new QueueNativeModule(self, std::make_unique<CxxNativeModule>(
|
||||
_reactInstance, [moduleData.name UTF8String],
|
||||
[moduleData] { return [(RCTCxxModule *)(moduleData.instance) move]; })));
|
||||
modules.emplace_back(std::make_unique<CxxNativeModule>(
|
||||
_reactInstance,
|
||||
[moduleData.name UTF8String],
|
||||
[moduleData] { return [(RCTCxxModule *)(moduleData.instance) move]; },
|
||||
std::make_shared<DispatchMessageQueueThread>(moduleData)));
|
||||
} else {
|
||||
modules.emplace_back(new RCTNativeModule(self, moduleData));
|
||||
modules.emplace_back(std::make_unique<RCTNativeModule>(self, moduleData));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -586,7 +542,6 @@ struct RCTInstanceCallback : public InstanceCallback {
|
|||
std::unique_ptr<RCTInstanceCallback>(new RCTInstanceCallback(self)),
|
||||
executorFactory,
|
||||
_jsMessageThread,
|
||||
std::unique_ptr<MessageQueueThread>(new InlineMessageQueueThread),
|
||||
std::move([self _createModuleRegistry]));
|
||||
|
||||
#if RCT_PROFILE
|
||||
|
|
|
@ -41,13 +41,17 @@ class Exception : public jni::JavaClass<Exception> {
|
|||
|
||||
class JInstanceCallback : public InstanceCallback {
|
||||
public:
|
||||
explicit JInstanceCallback(alias_ref<ReactCallback::javaobject> jobj)
|
||||
: jobj_(make_global(jobj)) {}
|
||||
explicit JInstanceCallback(
|
||||
alias_ref<ReactCallback::javaobject> jobj,
|
||||
std::shared_ptr<JMessageQueueThread> messageQueueThread)
|
||||
: jobj_(make_global(jobj)), messageQueueThread_(std::move(messageQueueThread)) {}
|
||||
|
||||
void onBatchComplete() override {
|
||||
static auto method =
|
||||
ReactCallback::javaClassStatic()->getMethod<void()>("onBatchComplete");
|
||||
method(jobj_);
|
||||
messageQueueThread_->runOnQueue([this] {
|
||||
static auto method =
|
||||
ReactCallback::javaClassStatic()->getMethod<void()>("onBatchComplete");
|
||||
method(jobj_);
|
||||
});
|
||||
}
|
||||
|
||||
void incrementPendingJSCalls() override {
|
||||
|
@ -61,6 +65,7 @@ class JInstanceCallback : public InstanceCallback {
|
|||
}
|
||||
|
||||
void decrementPendingJSCalls() override {
|
||||
jni::ThreadScope guard;
|
||||
static auto method =
|
||||
ReactCallback::javaClassStatic()->getMethod<void()>("decrementPendingJSCalls");
|
||||
method(jobj_);
|
||||
|
@ -81,12 +86,11 @@ class JInstanceCallback : public InstanceCallback {
|
|||
return jobj->cthis()->getExecutorToken(jobj);
|
||||
}
|
||||
|
||||
void onExecutorStopped(ExecutorToken) override {
|
||||
// TODO(cjhopman): implement this.
|
||||
}
|
||||
void onExecutorStopped(ExecutorToken) override {}
|
||||
|
||||
private:
|
||||
global_ref<ReactCallback::javaobject> jobj_;
|
||||
std::shared_ptr<JMessageQueueThread> messageQueueThread_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -97,7 +101,12 @@ jni::local_ref<CatalystInstanceImpl::jhybriddata> CatalystInstanceImpl::initHybr
|
|||
}
|
||||
|
||||
CatalystInstanceImpl::CatalystInstanceImpl()
|
||||
: instance_(folly::make_unique<Instance>()) {}
|
||||
: instance_(folly::make_unique<Instance>()) {}
|
||||
|
||||
CatalystInstanceImpl::~CatalystInstanceImpl() {
|
||||
// TODO: 16669252: this prevents onCatalystInstanceDestroy from being called
|
||||
moduleMessageQueue_->quitSynchronous();
|
||||
}
|
||||
|
||||
void CatalystInstanceImpl::registerNatives() {
|
||||
registerHybrid({
|
||||
|
@ -127,11 +136,12 @@ void CatalystInstanceImpl::initializeBridge(
|
|||
// This executor is actually a factory holder.
|
||||
JavaScriptExecutorHolder* jseh,
|
||||
jni::alias_ref<JavaMessageQueueThread::javaobject> jsQueue,
|
||||
jni::alias_ref<JavaMessageQueueThread::javaobject> moduleQueue,
|
||||
jni::alias_ref<JavaMessageQueueThread::javaobject> nativeModulesQueue,
|
||||
jni::alias_ref<jni::JCollection<JavaModuleWrapper::javaobject>::javaobject> javaModules,
|
||||
jni::alias_ref<jni::JCollection<ModuleHolder::javaobject>::javaobject> cxxModules) {
|
||||
// TODO mhorowitz: how to assert here?
|
||||
// Assertions.assertCondition(mBridge == null, "initializeBridge should be called once");
|
||||
moduleMessageQueue_ = std::make_shared<JMessageQueueThread>(nativeModulesQueue);
|
||||
|
||||
// This used to be:
|
||||
//
|
||||
|
@ -149,12 +159,12 @@ void CatalystInstanceImpl::initializeBridge(
|
|||
// don't need jsModuleDescriptions any more, all the way up and down the
|
||||
// stack.
|
||||
|
||||
instance_->initializeBridge(folly::make_unique<JInstanceCallback>(callback),
|
||||
jseh->getExecutorFactory(),
|
||||
folly::make_unique<JMessageQueueThread>(jsQueue),
|
||||
folly::make_unique<JMessageQueueThread>(moduleQueue),
|
||||
buildModuleRegistry(std::weak_ptr<Instance>(instance_),
|
||||
javaModules, cxxModules));
|
||||
instance_->initializeBridge(
|
||||
folly::make_unique<JInstanceCallback>(callback, moduleMessageQueue_),
|
||||
jseh->getExecutorFactory(),
|
||||
folly::make_unique<JMessageQueueThread>(jsQueue),
|
||||
buildModuleRegistry(
|
||||
std::weak_ptr<Instance>(instance_), javaModules, cxxModules, moduleMessageQueue_));
|
||||
}
|
||||
|
||||
void CatalystInstanceImpl::jniSetSourceURL(const std::string& sourceURL) {
|
||||
|
|
|
@ -28,6 +28,7 @@ class CatalystInstanceImpl : public jni::HybridClass<CatalystInstanceImpl> {
|
|||
static constexpr auto kJavaDescriptor = "Lcom/facebook/react/cxxbridge/CatalystInstanceImpl;";
|
||||
|
||||
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jclass>);
|
||||
~CatalystInstanceImpl() override;
|
||||
|
||||
static void registerNatives();
|
||||
|
||||
|
@ -74,6 +75,7 @@ class CatalystInstanceImpl : public jni::HybridClass<CatalystInstanceImpl> {
|
|||
// This should be the only long-lived strong reference, but every C++ class
|
||||
// will have a weak reference.
|
||||
std::shared_ptr<Instance> instance_;
|
||||
std::shared_ptr<JMessageQueueThread> moduleMessageQueue_;
|
||||
};
|
||||
|
||||
}}
|
||||
|
|
|
@ -87,30 +87,36 @@ bool JavaNativeModule::supportsWebWorkers() {
|
|||
}
|
||||
|
||||
void JavaNativeModule::invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
static auto invokeMethod =
|
||||
wrapper_->getClass()->getMethod<void(JExecutorToken::javaobject, jint, ReadableNativeArray::javaobject)>("invoke");
|
||||
invokeMethod(wrapper_, JExecutorToken::extractJavaPartFromToken(token).get(), static_cast<jint>(reactMethodId),
|
||||
ReadableNativeArray::newObjectCxxArgs(std::move(params)).get());
|
||||
messageQueueThread_->runOnQueue([this, token, reactMethodId, params=std::move(params)] {
|
||||
static auto invokeMethod = wrapper_->getClass()->
|
||||
getMethod<void(JExecutorToken::javaobject, jint, ReadableNativeArray::javaobject)>("invoke");
|
||||
invokeMethod(wrapper_,
|
||||
JExecutorToken::extractJavaPartFromToken(token).get(),
|
||||
static_cast<jint>(reactMethodId),
|
||||
ReadableNativeArray::newObjectCxxArgs(std::move(params)).get());
|
||||
});
|
||||
}
|
||||
|
||||
MethodCallResult JavaNativeModule::callSerializableNativeHook(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
// TODO: evaluate whether calling through invoke is potentially faster
|
||||
if (reactMethodId >= syncMethods_.size()) {
|
||||
throw std::invalid_argument(
|
||||
folly::to<std::string>("methodId ", reactMethodId, " out of range [0..", syncMethods_.size(), "]"));
|
||||
}
|
||||
// TODO: evaluate whether calling through invoke is potentially faster
|
||||
if (reactMethodId >= syncMethods_.size()) {
|
||||
throw std::invalid_argument(
|
||||
folly::to<std::string>("methodId ", reactMethodId, " out of range [0..", syncMethods_.size(), "]"));
|
||||
}
|
||||
|
||||
auto& method = syncMethods_[reactMethodId];
|
||||
CHECK(method.hasValue() && method->isSyncHook()) << "Trying to invoke a asynchronous method as synchronous hook";
|
||||
return method->invoke(instance_, wrapper_->getModule(), token, params);
|
||||
auto& method = syncMethods_[reactMethodId];
|
||||
CHECK(method.hasValue() && method->isSyncHook()) << "Trying to invoke a asynchronous method as synchronous hook";
|
||||
return method->invoke(instance_, wrapper_->getModule(), token, params);
|
||||
}
|
||||
|
||||
NewJavaNativeModule::NewJavaNativeModule(
|
||||
std::weak_ptr<Instance> instance,
|
||||
jni::alias_ref<JavaModuleWrapper::javaobject> wrapper)
|
||||
: instance_(std::move(instance)),
|
||||
wrapper_(make_global(wrapper)),
|
||||
module_(make_global(wrapper->getModule())) {
|
||||
jni::alias_ref<JavaModuleWrapper::javaobject> wrapper,
|
||||
std::shared_ptr<MessageQueueThread> messageQueueThread)
|
||||
: instance_(std::move(instance))
|
||||
, wrapper_(make_global(wrapper))
|
||||
, module_(make_global(wrapper->getModule()))
|
||||
, messageQueueThread_(std::move(messageQueueThread)) {
|
||||
auto descs = wrapper_->getMethodDescriptors();
|
||||
std::string moduleName = getName();
|
||||
methods_.reserve(descs->size());
|
||||
|
@ -161,7 +167,9 @@ void NewJavaNativeModule::invoke(ExecutorToken token, unsigned int reactMethodId
|
|||
folly::to<std::string>("methodId ", reactMethodId, " out of range [0..", methods_.size(), "]"));
|
||||
}
|
||||
CHECK(!methods_[reactMethodId].isSyncHook()) << "Trying to invoke a synchronous hook asynchronously";
|
||||
invokeInner(token, reactMethodId, std::move(params));
|
||||
messageQueueThread_->runOnQueue([this, token, reactMethodId, params=std::move(params)] () mutable {
|
||||
invokeInner(token, reactMethodId, std::move(params));
|
||||
});
|
||||
}
|
||||
|
||||
MethodCallResult NewJavaNativeModule::callSerializableNativeHook(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace facebook {
|
|||
namespace react {
|
||||
|
||||
class Instance;
|
||||
class MessageQueueThread;
|
||||
|
||||
struct JMethodDescriptor : public jni::JavaClass<JMethodDescriptor> {
|
||||
static constexpr auto kJavaDescriptor =
|
||||
|
@ -44,8 +45,11 @@ class JavaNativeModule : public NativeModule {
|
|||
public:
|
||||
JavaNativeModule(
|
||||
std::weak_ptr<Instance> instance,
|
||||
jni::alias_ref<JavaModuleWrapper::javaobject> wrapper)
|
||||
: instance_(std::move(instance)), wrapper_(make_global(wrapper)) {}
|
||||
jni::alias_ref<JavaModuleWrapper::javaobject> wrapper,
|
||||
std::shared_ptr<MessageQueueThread> messageQueueThread)
|
||||
: instance_(std::move(instance))
|
||||
, wrapper_(make_global(wrapper))
|
||||
, messageQueueThread_(std::move(messageQueueThread)) {}
|
||||
|
||||
std::string getName() override;
|
||||
folly::dynamic getConstants() override;
|
||||
|
@ -57,6 +61,7 @@ class JavaNativeModule : public NativeModule {
|
|||
private:
|
||||
std::weak_ptr<Instance> instance_;
|
||||
jni::global_ref<JavaModuleWrapper::javaobject> wrapper_;
|
||||
std::shared_ptr<MessageQueueThread> messageQueueThread_;
|
||||
std::vector<folly::Optional<MethodInvoker>> syncMethods_;
|
||||
};
|
||||
|
||||
|
@ -65,7 +70,8 @@ class NewJavaNativeModule : public NativeModule {
|
|||
public:
|
||||
NewJavaNativeModule(
|
||||
std::weak_ptr<Instance> instance,
|
||||
jni::alias_ref<JavaModuleWrapper::javaobject> wrapper);
|
||||
jni::alias_ref<JavaModuleWrapper::javaobject> wrapper,
|
||||
std::shared_ptr<MessageQueueThread> messageQueueThread);
|
||||
|
||||
std::string getName() override;
|
||||
std::vector<MethodDescriptor> getMethods() override;
|
||||
|
@ -78,6 +84,7 @@ class NewJavaNativeModule : public NativeModule {
|
|||
std::weak_ptr<Instance> instance_;
|
||||
jni::global_ref<JavaModuleWrapper::javaobject> wrapper_;
|
||||
jni::global_ref<JBaseJavaModule::javaobject> module_;
|
||||
std::shared_ptr<MessageQueueThread> messageQueueThread_;
|
||||
std::vector<MethodInvoker> methods_;
|
||||
std::vector<MethodDescriptor> methodDescriptors_;
|
||||
|
||||
|
|
|
@ -32,14 +32,16 @@ xplat::module::CxxModule::Provider ModuleHolder::getProvider() const {
|
|||
std::unique_ptr<ModuleRegistry> buildModuleRegistry(
|
||||
std::weak_ptr<Instance> winstance,
|
||||
jni::alias_ref<jni::JCollection<JavaModuleWrapper::javaobject>::javaobject> javaModules,
|
||||
jni::alias_ref<jni::JCollection<ModuleHolder::javaobject>::javaobject> cxxModules) {
|
||||
jni::alias_ref<jni::JCollection<ModuleHolder::javaobject>::javaobject> cxxModules,
|
||||
std::shared_ptr<MessageQueueThread> moduleMessageQueue) {
|
||||
std::vector<std::unique_ptr<NativeModule>> modules;
|
||||
for (const auto& jm : *javaModules) {
|
||||
modules.emplace_back(folly::make_unique<JavaNativeModule>(winstance, jm));
|
||||
modules.emplace_back(folly::make_unique<JavaNativeModule>(
|
||||
winstance, jm, moduleMessageQueue));
|
||||
}
|
||||
for (const auto& cm : *cxxModules) {
|
||||
modules.emplace_back(
|
||||
folly::make_unique<CxxNativeModule>(winstance, cm->getName(), cm->getProvider()));
|
||||
modules.emplace_back(folly::make_unique<CxxNativeModule>(
|
||||
winstance, cm->getName(), cm->getProvider(), moduleMessageQueue));
|
||||
}
|
||||
if (modules.empty()) {
|
||||
return nullptr;
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class MessageQueueThread;
|
||||
|
||||
class ModuleHolder : public jni::JavaClass<ModuleHolder> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor =
|
||||
|
@ -24,7 +26,8 @@ class ModuleHolder : public jni::JavaClass<ModuleHolder> {
|
|||
std::unique_ptr<ModuleRegistry> buildModuleRegistry(
|
||||
std::weak_ptr<Instance> winstance,
|
||||
jni::alias_ref<jni::JCollection<JavaModuleWrapper::javaobject>::javaobject> javaModules,
|
||||
jni::alias_ref<jni::JCollection<ModuleHolder::javaobject>::javaobject> cxxModules);
|
||||
jni::alias_ref<jni::JCollection<ModuleHolder::javaobject>::javaobject> cxxModules,
|
||||
std::shared_ptr<MessageQueueThread> moduleMessageQueue);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,13 +46,6 @@ CxxModule::Callback convertCallback(
|
|||
|
||||
}
|
||||
|
||||
CxxNativeModule::CxxNativeModule(std::weak_ptr<Instance> instance,
|
||||
std::string name,
|
||||
CxxModule::Provider provider)
|
||||
: instance_(instance)
|
||||
, name_(std::move(name))
|
||||
, provider_(provider) {}
|
||||
|
||||
std::string CxxNativeModule::getName() {
|
||||
return name_;
|
||||
}
|
||||
|
@ -85,8 +78,8 @@ bool CxxNativeModule::supportsWebWorkers() {
|
|||
|
||||
void CxxNativeModule::invoke(ExecutorToken token, unsigned int reactMethodId, folly::dynamic&& params) {
|
||||
if (reactMethodId >= methods_.size()) {
|
||||
throw std::invalid_argument(
|
||||
folly::to<std::string>("methodId ", reactMethodId, " out of range [0..", methods_.size(), "]"));
|
||||
throw std::invalid_argument(folly::to<std::string>("methodId ", reactMethodId,
|
||||
" out of range [0..", methods_.size(), "]"));
|
||||
}
|
||||
if (!params.isArray()) {
|
||||
throw std::invalid_argument(
|
||||
|
@ -99,25 +92,20 @@ void CxxNativeModule::invoke(ExecutorToken token, unsigned int reactMethodId, fo
|
|||
const auto& method = methods_[reactMethodId];
|
||||
|
||||
if (!method.func) {
|
||||
throw std::runtime_error(
|
||||
folly::to<std::string>("Method ", method.name,
|
||||
" is synchronous but invoked asynchronously"));
|
||||
throw std::runtime_error(folly::to<std::string>("Method ", method.name,
|
||||
" is synchronous but invoked asynchronously"));
|
||||
}
|
||||
|
||||
if (params.size() < method.callbacks) {
|
||||
throw std::invalid_argument(
|
||||
folly::to<std::string>("Expected ", method.callbacks, " callbacks, but only ",
|
||||
params.size(), " parameters provided"));
|
||||
throw std::invalid_argument(folly::to<std::string>("Expected ", method.callbacks,
|
||||
" callbacks, but only ", params.size(), " parameters provided"));
|
||||
}
|
||||
|
||||
if (method.callbacks == 1) {
|
||||
first = convertCallback(
|
||||
makeCallback(instance_, token, params[params.size() - 1]));
|
||||
first = convertCallback(makeCallback(instance_, token, params[params.size() - 1]));
|
||||
} else if (method.callbacks == 2) {
|
||||
first = convertCallback(
|
||||
makeCallback(instance_, token, params[params.size() - 2]));
|
||||
second = convertCallback(
|
||||
makeCallback(instance_, token, params[params.size() - 1]));
|
||||
first = convertCallback(makeCallback(instance_, token, params[params.size() - 2]));
|
||||
second = convertCallback(makeCallback(instance_, token, params[params.size() - 1]));
|
||||
}
|
||||
|
||||
params.resize(params.size() - method.callbacks);
|
||||
|
@ -141,16 +129,18 @@ void CxxNativeModule::invoke(ExecutorToken token, unsigned int reactMethodId, fo
|
|||
// stack. I'm told that will be possible in the future. TODO
|
||||
// mhorowitz #7128529: convert C++ exceptions to Java
|
||||
|
||||
try {
|
||||
method.func(std::move(params), first, second);
|
||||
} catch (const facebook::xplat::JsArgumentException& ex) {
|
||||
// This ends up passed to the onNativeException callback.
|
||||
throw;
|
||||
} catch (...) {
|
||||
// This means some C++ code is buggy. As above, we fail hard so the C++
|
||||
// developer can debug and fix it.
|
||||
std::terminate();
|
||||
}
|
||||
messageQueueThread_->runOnQueue([method, params=std::move(params), first, second] () {
|
||||
try {
|
||||
method.func(std::move(params), first, second);
|
||||
} catch (const facebook::xplat::JsArgumentException& ex) {
|
||||
// This ends up passed to the onNativeException callback.
|
||||
throw;
|
||||
} catch (...) {
|
||||
// This means some C++ code is buggy. As above, we fail hard so the C++
|
||||
// developer can debug and fix it.
|
||||
std::terminate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
MethodCallResult CxxNativeModule::callSerializableNativeHook(
|
||||
|
|
|
@ -15,8 +15,14 @@ std::function<void(folly::dynamic)> makeCallback(
|
|||
|
||||
class CxxNativeModule : public NativeModule {
|
||||
public:
|
||||
CxxNativeModule(std::weak_ptr<Instance> instance, std::string name,
|
||||
xplat::module::CxxModule::Provider provider);
|
||||
CxxNativeModule(std::weak_ptr<Instance> instance,
|
||||
std::string name,
|
||||
xplat::module::CxxModule::Provider provider,
|
||||
std::shared_ptr<MessageQueueThread> messageQueueThread)
|
||||
: instance_(instance)
|
||||
, name_(std::move(name))
|
||||
, provider_(provider)
|
||||
, messageQueueThread_(messageQueueThread) {}
|
||||
|
||||
std::string getName() override;
|
||||
std::vector<MethodDescriptor> getMethods() override;
|
||||
|
@ -32,6 +38,7 @@ private:
|
|||
std::weak_ptr<Instance> instance_;
|
||||
std::string name_;
|
||||
xplat::module::CxxModule::Provider provider_;
|
||||
std::shared_ptr<MessageQueueThread> messageQueueThread_;
|
||||
std::unique_ptr<xplat::module::CxxModule> module_;
|
||||
std::vector<xplat::module::CxxModule::Method> methods_;
|
||||
};
|
||||
|
|
|
@ -33,24 +33,14 @@ void Instance::initializeBridge(
|
|||
std::unique_ptr<InstanceCallback> callback,
|
||||
std::shared_ptr<JSExecutorFactory> jsef,
|
||||
std::shared_ptr<MessageQueueThread> jsQueue,
|
||||
std::unique_ptr<MessageQueueThread> nativeQueue,
|
||||
std::shared_ptr<ModuleRegistry> moduleRegistry) {
|
||||
callback_ = std::move(callback);
|
||||
|
||||
if (!nativeQueue) {
|
||||
// TODO pass down a thread/queue from java, instead of creating our own.
|
||||
|
||||
auto queue = folly::make_unique<CxxMessageQueue>();
|
||||
std::thread t(queue->getUnregisteredRunLoop());
|
||||
t.detach();
|
||||
nativeQueue = std::move(queue);
|
||||
}
|
||||
|
||||
jsQueue->runOnQueueSync(
|
||||
[this, &jsef, moduleRegistry, jsQueue,
|
||||
nativeQueue=folly::makeMoveWrapper(std::move(nativeQueue))] () mutable {
|
||||
[this, &jsef, moduleRegistry, jsQueue] () mutable {
|
||||
nativeToJsBridge_ = folly::make_unique<NativeToJsBridge>(
|
||||
jsef.get(), moduleRegistry, jsQueue, nativeQueue.move(), callback_);
|
||||
jsef.get(), moduleRegistry, jsQueue, callback_);
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_syncMutex);
|
||||
m_syncReady = true;
|
||||
|
|
|
@ -31,7 +31,6 @@ class Instance {
|
|||
std::unique_ptr<InstanceCallback> callback,
|
||||
std::shared_ptr<JSExecutorFactory> jsef,
|
||||
std::shared_ptr<MessageQueueThread> jsQueue,
|
||||
std::unique_ptr<MessageQueueThread> nativeQueue,
|
||||
std::shared_ptr<ModuleRegistry> moduleRegistry);
|
||||
|
||||
void setSourceURL(std::string sourceURL);
|
||||
|
|
|
@ -24,11 +24,9 @@ class JsToNativeBridge : public react::ExecutorDelegate {
|
|||
public:
|
||||
JsToNativeBridge(NativeToJsBridge* nativeToJs,
|
||||
std::shared_ptr<ModuleRegistry> registry,
|
||||
std::unique_ptr<MessageQueueThread> nativeQueue,
|
||||
std::shared_ptr<InstanceCallback> callback)
|
||||
: m_nativeToJs(nativeToJs)
|
||||
, m_registry(registry)
|
||||
, m_nativeQueue(std::move(nativeQueue))
|
||||
, m_callback(callback) {}
|
||||
|
||||
void registerExecutor(std::unique_ptr<JSExecutor> executor,
|
||||
|
@ -51,24 +49,25 @@ public:
|
|||
CHECK(m_registry || calls.empty()) <<
|
||||
"native module calls cannot be completed with no native modules";
|
||||
ExecutorToken token = m_nativeToJs->getTokenForExecutor(executor);
|
||||
m_nativeQueue->runOnQueue([this, token, calls=std::move(calls), isEndOfBatch] () mutable {
|
||||
m_batchHadNativeModuleCalls = m_batchHadNativeModuleCalls || !calls.empty();
|
||||
m_batchHadNativeModuleCalls = m_batchHadNativeModuleCalls || !calls.empty();
|
||||
|
||||
// An exception anywhere in here stops processing of the batch. This
|
||||
// was the behavior of the Android bridge, and since exception handling
|
||||
// terminates the whole bridge, there's not much point in continuing.
|
||||
for (auto& call : react::parseMethodCalls(std::move(calls))) {
|
||||
m_registry->callNativeMethod(
|
||||
token, call.moduleId, call.methodId, std::move(call.arguments), call.callId);
|
||||
// An exception anywhere in here stops processing of the batch. This
|
||||
// was the behavior of the Android bridge, and since exception handling
|
||||
// terminates the whole bridge, there's not much point in continuing.
|
||||
for (auto& call : parseMethodCalls(std::move(calls))) {
|
||||
m_registry->callNativeMethod(
|
||||
token, call.moduleId, call.methodId, std::move(call.arguments), call.callId);
|
||||
}
|
||||
if (isEndOfBatch) {
|
||||
// onBatchComplete will be called on the native (module) queue, but
|
||||
// decrementPendingJSCalls will be called sync. Be aware that the bridge may still
|
||||
// be processing native calls when the birdge idle signaler fires.
|
||||
if (m_batchHadNativeModuleCalls) {
|
||||
m_callback->onBatchComplete();
|
||||
m_batchHadNativeModuleCalls = false;
|
||||
}
|
||||
if (isEndOfBatch) {
|
||||
if (m_batchHadNativeModuleCalls) {
|
||||
m_callback->onBatchComplete();
|
||||
m_batchHadNativeModuleCalls = false;
|
||||
}
|
||||
m_callback->decrementPendingJSCalls();
|
||||
}
|
||||
});
|
||||
m_callback->decrementPendingJSCalls();
|
||||
}
|
||||
}
|
||||
|
||||
MethodCallResult callSerializableNativeHook(
|
||||
|
@ -78,10 +77,6 @@ public:
|
|||
return m_registry->callSerializableNativeHook(token, moduleId, methodId, std::move(args));
|
||||
}
|
||||
|
||||
void quitQueueSynchronous() {
|
||||
m_nativeQueue->quitSynchronous();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// These methods are always invoked from an Executor. The NativeToJsBridge
|
||||
|
@ -91,7 +86,6 @@ private:
|
|||
// valid object during a call to a delegate method from an exectuto.
|
||||
NativeToJsBridge* m_nativeToJs;
|
||||
std::shared_ptr<ModuleRegistry> m_registry;
|
||||
std::unique_ptr<MessageQueueThread> m_nativeQueue;
|
||||
std::shared_ptr<InstanceCallback> m_callback;
|
||||
bool m_batchHadNativeModuleCalls = false;
|
||||
};
|
||||
|
@ -100,12 +94,10 @@ NativeToJsBridge::NativeToJsBridge(
|
|||
JSExecutorFactory* jsExecutorFactory,
|
||||
std::shared_ptr<ModuleRegistry> registry,
|
||||
std::shared_ptr<MessageQueueThread> jsQueue,
|
||||
std::unique_ptr<MessageQueueThread> nativeQueue,
|
||||
std::shared_ptr<InstanceCallback> callback)
|
||||
: m_destroyed(std::make_shared<bool>(false))
|
||||
, m_mainExecutorToken(callback->createExecutorToken())
|
||||
, m_delegate(std::make_shared<JsToNativeBridge>(
|
||||
this, registry, std::move(nativeQueue), callback)) {
|
||||
, m_delegate(std::make_shared<JsToNativeBridge>(this, registry, callback)) {
|
||||
std::unique_ptr<JSExecutor> mainExecutor =
|
||||
jsExecutorFactory->createJSExecutor(m_delegate, jsQueue);
|
||||
// cached to avoid locked map lookup in the common case
|
||||
|
@ -129,7 +121,6 @@ void NativeToJsBridge::loadApplication(
|
|||
startupScript=folly::makeMoveWrapper(std::move(startupScript)),
|
||||
startupScriptSourceURL=std::move(startupScriptSourceURL)]
|
||||
(JSExecutor* executor) mutable {
|
||||
|
||||
auto unbundle = unbundleWrap.move();
|
||||
if (unbundle) {
|
||||
executor->setJSModulesUnbundle(std::move(unbundle));
|
||||
|
@ -322,7 +313,6 @@ ExecutorToken NativeToJsBridge::getTokenForExecutor(JSExecutor& executor) {
|
|||
}
|
||||
|
||||
void NativeToJsBridge::destroy() {
|
||||
m_delegate->quitQueueSynchronous();
|
||||
auto* executorMessageQueueThread = getMessageQueueThread(m_mainExecutorToken);
|
||||
// All calls made through runOnExecutorQueue have an early exit if
|
||||
// m_destroyed is true. Setting this before the runOnQueueSync will cause
|
||||
|
@ -331,7 +321,7 @@ void NativeToJsBridge::destroy() {
|
|||
executorMessageQueueThread->runOnQueueSync([this, executorMessageQueueThread] {
|
||||
m_mainExecutor->destroy();
|
||||
executorMessageQueueThread->quitSynchronous();
|
||||
unregisterExecutor(*m_mainExecutor);
|
||||
m_delegate->unregisterExecutor(*m_mainExecutor);
|
||||
m_mainExecutor = nullptr;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -61,7 +61,6 @@ public:
|
|||
JSExecutorFactory* jsExecutorFactory,
|
||||
std::shared_ptr<ModuleRegistry> registry,
|
||||
std::shared_ptr<MessageQueueThread> jsQueue,
|
||||
std::unique_ptr<MessageQueueThread> nativeQueue,
|
||||
std::shared_ptr<InstanceCallback> callback);
|
||||
virtual ~NativeToJsBridge();
|
||||
|
||||
|
|
Loading…
Reference in New Issue