Skip to content

Commit 1e65f84

Browse files
javachefacebook-github-bot
authored andcommitted
Do not create RuntimeExecutor on non-JSI executors
Summary: 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 Differential Revision: D47124234 fbshipit-source-id: c49c7ace4ca5f8b47bce20c42872c97f46572a43
1 parent 0bd6b28 commit 1e65f84

File tree

3 files changed

+42
-31
lines changed

3 files changed

+42
-31
lines changed

packages/react-native/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -398,8 +398,11 @@ CatalystInstanceImpl::getNativeMethodCallInvokerHolder() {
398398
jni::alias_ref<JRuntimeExecutor::javaobject>
399399
CatalystInstanceImpl::getRuntimeExecutor() {
400400
if (!runtimeExecutor_) {
401-
runtimeExecutor_ = jni::make_global(
402-
JRuntimeExecutor::newObjectCxxArgs(instance_->getRuntimeExecutor()));
401+
auto executor = instance_->getRuntimeExecutor();
402+
if (executor) {
403+
runtimeExecutor_ =
404+
jni::make_global(JRuntimeExecutor::newObjectCxxArgs(executor));
405+
}
403406
}
404407
return runtimeExecutor_;
405408
}
@@ -408,15 +411,16 @@ jni::alias_ref<JRuntimeScheduler::javaobject>
408411
CatalystInstanceImpl::getRuntimeScheduler() {
409412
if (!runtimeScheduler_) {
410413
auto runtimeExecutor = instance_->getRuntimeExecutor();
411-
auto runtimeScheduler = std::make_shared<RuntimeScheduler>(runtimeExecutor);
412-
413-
runtimeScheduler_ =
414-
jni::make_global(JRuntimeScheduler::newObjectCxxArgs(runtimeScheduler));
415-
416-
runtimeExecutor([runtimeScheduler](jsi::Runtime &runtime) {
417-
RuntimeSchedulerBinding::createAndInstallIfNeeded(
418-
runtime, runtimeScheduler);
419-
});
414+
if (runtimeExecutor) {
415+
auto runtimeScheduler =
416+
std::make_shared<RuntimeScheduler>(runtimeExecutor);
417+
runtimeScheduler_ = jni::make_global(
418+
JRuntimeScheduler::newObjectCxxArgs(runtimeScheduler));
419+
runtimeExecutor([scheduler =
420+
std::move(runtimeScheduler)](jsi::Runtime &runtime) {
421+
RuntimeSchedulerBinding::createAndInstallIfNeeded(runtime, scheduler);
422+
});
423+
}
420424
}
421425

422426
return runtimeScheduler_;

packages/react-native/ReactCommon/cxxreact/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@ target_link_libraries(reactnative
2727
jsinspector
2828
logger
2929
reactperflogger
30-
runtimeexecutor)
30+
runtimeexecutor
31+
react_debug)

packages/react-native/ReactCommon/cxxreact/Instance.cpp

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <cxxreact/JSIndexedRAMBundle.h>
2222
#include <folly/MoveWrapper.h>
2323
#include <folly/json.h>
24+
#include <react/debug/react_native_assert.h>
2425

2526
#include <glog/logging.h>
2627

@@ -211,26 +212,31 @@ std::shared_ptr<CallInvoker> Instance::getJSCallInvoker() {
211212
}
212213

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

216-
auto runtimeExecutor =
217-
[weakNativeToJsBridge](
218-
std::function<void(jsi::Runtime & runtime)> &&callback) {
219-
if (auto strongNativeToJsBridge = weakNativeToJsBridge.lock()) {
220-
strongNativeToJsBridge->runOnExecutorQueue(
221-
[callback = std::move(callback)](JSExecutor *executor) {
222-
jsi::Runtime *runtime =
223-
(jsi::Runtime *)executor->getJavaScriptContext();
224-
try {
225-
callback(*runtime);
226-
executor->flush();
227-
} catch (jsi::JSError &originalError) {
228-
handleJSError(*runtime, originalError, true);
229-
}
230-
});
231-
}
232-
};
233-
return runtimeExecutor;
221+
std::weak_ptr<NativeToJsBridge> weakNativeToJsBridge = nativeToJsBridge_;
222+
return [weakNativeToJsBridge](
223+
std::function<void(jsi::Runtime & runtime)> &&callback) {
224+
if (auto strongNativeToJsBridge = weakNativeToJsBridge.lock()) {
225+
strongNativeToJsBridge->runOnExecutorQueue(
226+
[callback = std::move(callback)](JSExecutor *executor) {
227+
// Assumes the underlying executor is a JSIExecutor
228+
jsi::Runtime *runtime =
229+
(jsi::Runtime *)executor->getJavaScriptContext();
230+
try {
231+
react_native_assert(runtime != nullptr);
232+
callback(*runtime);
233+
executor->flush();
234+
} catch (jsi::JSError &originalError) {
235+
handleJSError(*runtime, originalError, true);
236+
}
237+
});
238+
}
239+
};
234240
}
235241

236242
std::shared_ptr<NativeMethodCallInvoker>

0 commit comments

Comments
 (0)