Skip to content

Commit

Permalink
Do not create RuntimeExecutor on non-JSI executors (facebook#38125)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: facebook#38125

On Android, when using the remote debugging feature (using legacy websockets), it's not safe to assume we can get a `jsi::Runtime` from `JSExecutor`.

Changelog: [General][Fixed] Android does't crash when using remote debugger

Reviewed By: NickGerleman

Differential Revision: D47124234

fbshipit-source-id: 0542da1aca5d411964e3a0833f4c48428ed90c91
  • Loading branch information
javache authored and Luna Wei committed Jun 30, 2023
1 parent 73293f2 commit ea93ab5
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -418,8 +418,11 @@ CatalystInstanceImpl::getNativeCallInvokerHolder() {
jni::alias_ref<JRuntimeExecutor::javaobject>
CatalystInstanceImpl::getRuntimeExecutor() {
if (!runtimeExecutor_) {
runtimeExecutor_ = jni::make_global(
JRuntimeExecutor::newObjectCxxArgs(instance_->getRuntimeExecutor()));
auto executor = instance_->getRuntimeExecutor();
if (executor) {
runtimeExecutor_ =
jni::make_global(JRuntimeExecutor::newObjectCxxArgs(executor));
}
}
return runtimeExecutor_;
}
Expand All @@ -428,15 +431,16 @@ jni::alias_ref<JRuntimeScheduler::javaobject>
CatalystInstanceImpl::getRuntimeScheduler() {
if (!runtimeScheduler_) {
auto runtimeExecutor = instance_->getRuntimeExecutor();
auto runtimeScheduler = std::make_shared<RuntimeScheduler>(runtimeExecutor);

runtimeScheduler_ =
jni::make_global(JRuntimeScheduler::newObjectCxxArgs(runtimeScheduler));

runtimeExecutor([runtimeScheduler](jsi::Runtime &runtime) {
RuntimeSchedulerBinding::createAndInstallIfNeeded(
runtime, runtimeScheduler);
});
if (runtimeExecutor) {
auto runtimeScheduler =
std::make_shared<RuntimeScheduler>(runtimeExecutor);
runtimeScheduler_ = jni::make_global(
JRuntimeScheduler::newObjectCxxArgs(runtimeScheduler));
runtimeExecutor([scheduler =
std::move(runtimeScheduler)](jsi::Runtime &runtime) {
RuntimeSchedulerBinding::createAndInstallIfNeeded(runtime, scheduler);
});
}
}

return runtimeScheduler_;
Expand Down
3 changes: 2 additions & 1 deletion packages/react-native/ReactCommon/cxxreact/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ target_link_libraries(reactnative
jsinspector
logger
reactperflogger
runtimeexecutor)
runtimeexecutor
react_debug)
44 changes: 25 additions & 19 deletions packages/react-native/ReactCommon/cxxreact/Instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <cxxreact/JSIndexedRAMBundle.h>
#include <folly/MoveWrapper.h>
#include <folly/json.h>
#include <react/debug/react_native_assert.h>

#include <glog/logging.h>

Expand Down Expand Up @@ -212,26 +213,31 @@ std::shared_ptr<CallInvoker> Instance::getJSCallInvoker() {
}

RuntimeExecutor Instance::getRuntimeExecutor() {
std::weak_ptr<NativeToJsBridge> weakNativeToJsBridge = nativeToJsBridge_;
// HACK: RuntimeExecutor is not compatible with non-JSIExecutor, we return
// a null callback, which the caller should handle.
if (!getJavaScriptContext()) {
return nullptr;
}

auto runtimeExecutor =
[weakNativeToJsBridge](
std::function<void(jsi::Runtime & runtime)> &&callback) {
if (auto strongNativeToJsBridge = weakNativeToJsBridge.lock()) {
strongNativeToJsBridge->runOnExecutorQueue(
[callback = std::move(callback)](JSExecutor *executor) {
jsi::Runtime *runtime =
(jsi::Runtime *)executor->getJavaScriptContext();
try {
callback(*runtime);
executor->flush();
} catch (jsi::JSError &originalError) {
handleJSError(*runtime, originalError, true);
}
});
}
};
return runtimeExecutor;
std::weak_ptr<NativeToJsBridge> weakNativeToJsBridge = nativeToJsBridge_;
return [weakNativeToJsBridge](
std::function<void(jsi::Runtime & runtime)> &&callback) {
if (auto strongNativeToJsBridge = weakNativeToJsBridge.lock()) {
strongNativeToJsBridge->runOnExecutorQueue(
[callback = std::move(callback)](JSExecutor *executor) {
// Assumes the underlying executor is a JSIExecutor
jsi::Runtime *runtime =
(jsi::Runtime *)executor->getJavaScriptContext();
try {
react_native_assert(runtime != nullptr);
callback(*runtime);
executor->flush();
} catch (jsi::JSError &originalError) {
handleJSError(*runtime, originalError, true);
}
});
}
};
}

std::shared_ptr<CallInvoker> Instance::getDecoratedNativeCallInvoker(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Pod::Spec.new do |s|
s.source_files = "*.{cpp,h}"
s.exclude_files = "SampleCxxModule.*"
s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags
s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-runtimeexecutor/React_runtimeexecutor.framework/Headers\"",
s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-runtimeexecutor/React_runtimeexecutor.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-debug/React_debug.framework/Headers\"",
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17" }
s.header_dir = "cxxreact"

Expand All @@ -47,6 +47,7 @@ Pod::Spec.new do |s|
s.dependency "React-perflogger", version
s.dependency "React-jsi", version
s.dependency "React-logger", version
s.dependency "React-debug", version

if ENV['USE_HERMES'] == nil || ENV['USE_HERMES'] == "1"
s.dependency 'hermes-engine'
Expand Down

0 comments on commit ea93ab5

Please sign in to comment.