Skip to content

Commit

Permalink
Create JSRuntime interface (facebook#41549)
Browse files Browse the repository at this point in the history
Summary:

Changelog: [Internal]

Introduces the `JSRuntime` interface as a straightforward wrapper around `jsi::Runtime`, and refactors `ReactInstance` to hold a `JSRuntime` instead of a `jsi::Runtime`. In an upcoming diff we'll add debugging-related methods to `JSRuntime` and specialise their implementations for Hermes.

NOTE: `JSRuntime` is somewhat analogous to `JSExecutor` in the Bridge architecture.

Reviewed By: huntie

Differential Revision: D51447934
  • Loading branch information
motiz88 authored and facebook-github-bot committed Nov 23, 2023
1 parent 6b89dc1 commit 8dabd82
Show file tree
Hide file tree
Showing 16 changed files with 70 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void JHermesInstance::registerNatives() {
});
}

std::unique_ptr<jsi::Runtime> JHermesInstance::createJSRuntime(
std::unique_ptr<JSRuntime> JHermesInstance::createJSRuntime(
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept {
return HermesInstance::createJSRuntime(
reactNativeConfig_, nullptr, msgQueueThread);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class JHermesInstance
JHermesInstance(std::shared_ptr<const ReactNativeConfig> reactNativeConfig)
: reactNativeConfig_(reactNativeConfig){};

std::unique_ptr<jsi::Runtime> createJSRuntime(
std::unique_ptr<JSRuntime> createJSRuntime(
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept;

~JHermesInstance() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class JSCInstance : public jni::HybridClass<JSCInstance, JJSRuntimeFactory> {
});
}

std::unique_ptr<jsi::Runtime> createJSRuntime(
std::unique_ptr<JSRuntime> createJSRuntime(
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept {
return jsc::makeJSCRuntime();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include "JSRuntimeFactory.h"

namespace facebook::react {
jsi::Runtime& JSIRuntimeHolder::getRuntime() noexcept {
return *runtime_;
}

JSIRuntimeHolder::JSIRuntimeHolder(std::unique_ptr<jsi::Runtime> runtime)
: runtime_(std::move(runtime)) {
assert(runtime_ != nullptr);
}
} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,38 @@

namespace facebook::react {

/**
* An interface that represents an instance of a JS VM
*/
class JSRuntime {
public:
virtual jsi::Runtime& getRuntime() noexcept = 0;

virtual ~JSRuntime() = default;
};

/**
* Interface for a class that creates instances of a JS VM
*/
class JSRuntimeFactory {
public:
virtual std::unique_ptr<jsi::Runtime> createJSRuntime(
virtual std::unique_ptr<JSRuntime> createJSRuntime(
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept = 0;

virtual ~JSRuntimeFactory() = default;
};

/**
* Utility class for creating a JSRuntime from a uniquely owned jsi::Runtime.
*/
class JSIRuntimeHolder : public JSRuntime {
public:
jsi::Runtime& getRuntime() noexcept override;

explicit JSIRuntimeHolder(std::unique_ptr<jsi::Runtime> runtime);

private:
std::unique_ptr<jsi::Runtime> runtime_;
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Pod::Spec.new do |s|
s.dependency "React-jsitracing"
s.dependency "React-utils"
s.dependency "React-jsi"
s.dependency "React-RuntimeCore"

if ENV["USE_HERMES"] == nil || ENV["USE_HERMES"] == "1"
s.dependency "hermes-engine"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
namespace facebook::react {

ReactInstance::ReactInstance(
std::unique_ptr<jsi::Runtime> runtime,
std::unique_ptr<JSRuntime> runtime,
std::shared_ptr<MessageQueueThread> jsMessageQueueThread,
std::shared_ptr<TimerManager> timerManager,
JsErrorHandler::JsErrorHandlingFunc jsErrorHandlingFunc,
Expand All @@ -36,7 +36,7 @@ ReactInstance::ReactInstance(
timerManager_(std::move(timerManager)),
jsErrorHandler_(jsErrorHandlingFunc),
hasFatalJsError_(std::make_shared<bool>(false)) {
auto runtimeExecutor = [weakRuntime = std::weak_ptr<jsi::Runtime>(runtime_),
auto runtimeExecutor = [weakRuntime = std::weak_ptr<JSRuntime>(runtime_),
weakTimerManager =
std::weak_ptr<TimerManager>(timerManager_),
weakJsMessageQueueThread =
Expand All @@ -63,20 +63,20 @@ ReactInstance::ReactInstance(
sharedJsMessageQueueThread->runOnQueue(
[weakRuntime, weakTimerManager, callback = std::move(callback)]() {
if (auto strongRuntime = weakRuntime.lock()) {
jsi::Runtime& jsiRuntime = strongRuntime->getRuntime();
SystraceSection s("ReactInstance::_runtimeExecutor[Callback]");
try {
callback(*strongRuntime);
callback(jsiRuntime);

// If we have first-class support for microtasks,
// they would've been called as part of the previous callback.
if (!CoreFeatures::enableMicrotasks) {
if (auto strongTimerManager = weakTimerManager.lock()) {
strongTimerManager->callReactNativeMicrotasks(
*strongRuntime);
strongTimerManager->callReactNativeMicrotasks(jsiRuntime);
}
}
} catch (jsi::JSError& originalError) {
handleJSError(*strongRuntime, originalError, true);
handleJSError(jsiRuntime, originalError, true);
}
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <jsireact/JSIExecutor.h>
#include <react/renderer/runtimescheduler/RuntimeScheduler.h>
#include <react/runtime/BufferedRuntimeExecutor.h>
#include <react/runtime/JSRuntimeFactory.h>
#include <react/runtime/TimerManager.h>

namespace facebook::react {
Expand All @@ -29,7 +30,7 @@ class ReactInstance final {
using BindingsInstallFunc = std::function<void(jsi::Runtime& runtime)>;

ReactInstance(
std::unique_ptr<jsi::Runtime> runtime,
std::unique_ptr<JSRuntime> runtime,
std::shared_ptr<MessageQueueThread> jsMessageQueueThread,
std::shared_ptr<TimerManager> timerManager,
JsErrorHandler::JsErrorHandlingFunc JsErrorHandlingFunc,
Expand Down Expand Up @@ -64,7 +65,7 @@ class ReactInstance final {
void handleMemoryPressureJs(int pressureLevel);

private:
std::shared_ptr<jsi::Runtime> runtime_;
std::shared_ptr<JSRuntime> runtime_;
std::shared_ptr<MessageQueueThread> jsMessageQueueThread_;
std::shared_ptr<BufferedRuntimeExecutor> bufferedRuntimeExecutor_;
std::shared_ptr<TimerManager> timerManager_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ target_link_libraries(bridgelesshermes
hermes_inspector_modern
jsi
hermes_executor_common
bridgeless
)

if(${CMAKE_BUILD_TYPE} MATCHES Debug)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class DecoratedRuntime : public jsi::RuntimeDecorator<jsi::Runtime> {

#endif

std::unique_ptr<jsi::Runtime> HermesInstance::createJSRuntime(
std::unique_ptr<JSRuntime> HermesInstance::createJSRuntime(
std::shared_ptr<const ReactNativeConfig> reactNativeConfig,
std::shared_ptr<::hermes::vm::CrashManager> cm,
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept {
Expand Down Expand Up @@ -144,10 +144,10 @@ std::unique_ptr<jsi::Runtime> HermesInstance::createJSRuntime(
std::unique_ptr<DecoratedRuntime> decoratedRuntime =
std::make_unique<DecoratedRuntime>(
std::move(hermesRuntime), msgQueueThread);
return decoratedRuntime;
return std::make_unique<JSIRuntimeHolder>(std::move(decoratedRuntime));
#endif

return hermesRuntime;
return std::make_unique<JSIRuntimeHolder>(std::move(hermesRuntime));
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
#include <hermes/hermes.h>
#include <jsi/jsi.h>
#include <react/config/ReactNativeConfig.h>
#include <react/runtime/JSRuntimeFactory.h>

namespace facebook::react {

class HermesInstance {
public:
static std::unique_ptr<jsi::Runtime> createJSRuntime(
static std::unique_ptr<JSRuntime> createJSRuntime(
std::shared_ptr<const ReactNativeConfig> reactNativeConfig,
std::shared_ptr<::hermes::vm::CrashManager> cm,
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class RCTHermesInstance : public JSRuntimeFactory {
std::shared_ptr<const ReactNativeConfig> reactNativeConfig,
CrashManagerProvider crashManagerProvider);

std::unique_ptr<jsi::Runtime> createJSRuntime(
std::unique_ptr<JSRuntime> createJSRuntime(
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept override;

~RCTHermesInstance(){};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
{
}

std::unique_ptr<jsi::Runtime> RCTHermesInstance::createJSRuntime(
std::unique_ptr<JSRuntime> RCTHermesInstance::createJSRuntime(
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept
{
return _hermesInstance->createJSRuntime(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class RCTJscInstance : public JSRuntimeFactory {
public:
RCTJscInstance();

std::unique_ptr<jsi::Runtime> createJSRuntime(
std::unique_ptr<JSRuntime> createJSRuntime(
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept override;

~RCTJscInstance(){};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@

RCTJscInstance::RCTJscInstance() {}

std::unique_ptr<jsi::Runtime> RCTJscInstance::createJSRuntime(
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept
std::unique_ptr<JSRuntime> RCTJscInstance::createJSRuntime(std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept
{
return jsc::makeJSCRuntime();
return std::make_unique<JSIRuntimeHolder>(jsc::makeJSCRuntime());
}

} // namespace react
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ class ReactInstanceTest : public ::testing::Test {
ReactInstanceTest() {}

void SetUp() override {
auto runtime = hermes::makeHermesRuntime();
runtime_ = runtime.get();
auto runtime =
std::make_unique<JSIRuntimeHolder>(hermes::makeHermesRuntime());
runtime_ = &runtime->getRuntime();
messageQueueThread_ = std::make_shared<MockMessageQueueThread>();
auto mockRegistry = std::make_unique<MockTimerRegistry>();
mockRegistry_ = mockRegistry.get();
Expand Down

0 comments on commit 8dabd82

Please sign in to comment.