Skip to content

Commit

Permalink
Implement "tickleJS" for Hermes (facebook#39289)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: facebook#39289

"tickleJS" is a function in RN Hermes Debugger, we need to implement it for Bridgeless for feature correctness and keep parity with Bridge.

Changelog:
[General][Changed] -  Implement "tickleJS" for Hermes

Differential Revision: D48952581

fbshipit-source-id: ce83dfd81c8b1258f462c7325998db7586073f31
  • Loading branch information
Lulu Wu authored and facebook-github-bot committed Sep 5, 2023
1 parent d468d9d commit ea7d908
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,9 @@ std::unique_ptr<jsi::Runtime> JHermesInstance::createJSRuntime() noexcept {
return HermesInstance::createJSRuntime();
}

std::unique_ptr<jsi::Runtime> JHermesInstance::createJSRuntime(
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept {
return HermesInstance::createJSRuntime(msgQueueThread);
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <memory>
#include <string>

#include <cxxreact/MessageQueueThread.h>
#include <fbjni/fbjni.h>
#include <jni.h>
#include <jsi/jsi.h>
Expand All @@ -30,6 +31,8 @@ class JHermesInstance
static void registerNatives();

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

~JHermesInstance() {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ JReactInstance::JReactInstance(
jBindingsInstaller_ = jni::make_global(jBindingsInstaller);

instance_ = std::make_unique<ReactInstance>(
jsEngineInstance->cthis()->createJSRuntime(),
jsEngineInstance->cthis()->createJSRuntime(sharedJSMessageQueueThread),
sharedJSMessageQueueThread,
timerManager,
std::move(jsErrorHandlingFunc));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#pragma once

#include <ReactCommon/RuntimeExecutor.h>
#include <cxxreact/MessageQueueThread.h>
#include <jsi/jsi.h>

namespace facebook::react {
Expand All @@ -19,6 +20,9 @@ class JSEngineInstance {
public:
virtual std::unique_ptr<jsi::Runtime> createJSRuntime() noexcept = 0;

virtual std::unique_ptr<jsi::Runtime> createJSRuntime(
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept = 0;

virtual ~JSEngineInstance() = default;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,44 @@ namespace facebook::react {
// lead to a runtime crash.
class HermesInstanceRuntimeAdapter : public inspector_modern::RuntimeAdapter {
public:
HermesInstanceRuntimeAdapter(std::shared_ptr<HermesRuntime> hermesRuntime)
: hermesRuntime_(hermesRuntime) {}
HermesInstanceRuntimeAdapter(
std::shared_ptr<HermesRuntime> hermesRuntime,
std::shared_ptr<MessageQueueThread> msgQueueThread)
: hermesRuntime_(hermesRuntime), messageQueueThread_(msgQueueThread) {
assert(hermesRuntime_ != nullptr);
}
virtual ~HermesInstanceRuntimeAdapter() = default;

HermesRuntime& getRuntime() override {
return *hermesRuntime_;
}

void tickleJs() override {
std::weak_ptr<HermesRuntime> weakRuntime(hermesRuntime_);
messageQueueThread_->runOnQueue([weakRuntime]() {
auto runtime = weakRuntime.lock();
if (!runtime) {
return;
}
jsi::Function func =
runtime->global().getPropertyAsFunction(*runtime, "__tickleJs");
func.call(*runtime);
});
}

private:
std::shared_ptr<HermesRuntime> hermesRuntime_;
std::shared_ptr<MessageQueueThread> messageQueueThread_;
};

class DecoratedRuntime : public jsi::RuntimeDecorator<jsi::Runtime> {
public:
DecoratedRuntime(std::unique_ptr<HermesRuntime> runtime)
DecoratedRuntime(
std::unique_ptr<HermesRuntime> runtime,
std::shared_ptr<MessageQueueThread> msgQueueThread)
: RuntimeDecorator<jsi::Runtime>(*runtime), runtime_(std::move(runtime)) {
auto adapter = std::make_unique<HermesInstanceRuntimeAdapter>(runtime_);
auto adapter = std::make_unique<HermesInstanceRuntimeAdapter>(
runtime_, msgQueueThread);

debugToken_ = inspector_modern::chrome::enableDebugging(
std::move(adapter), "Hermes Bridgeless React Native");
Expand All @@ -71,12 +92,18 @@ class DecoratedRuntime : public jsi::RuntimeDecorator<jsi::Runtime> {
#endif

std::unique_ptr<jsi::Runtime> HermesInstance::createJSRuntime() noexcept {
return createJSRuntime(nullptr, nullptr);
return createJSRuntime(nullptr, nullptr, nullptr);
}

std::unique_ptr<jsi::Runtime> HermesInstance::createJSRuntime(
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept {
return createJSRuntime(nullptr, nullptr, msgQueueThread);
}

std::unique_ptr<jsi::Runtime> HermesInstance::createJSRuntime(
std::shared_ptr<const ReactNativeConfig> reactNativeConfig,
std::shared_ptr<::hermes::vm::CrashManager> cm) noexcept {
std::shared_ptr<::hermes::vm::CrashManager> cm,
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept {
int64_t vmExperimentFlags = reactNativeConfig
? reactNativeConfig->getInt64("ios_hermes:vm_experiment_flags")
: 0;
Expand Down Expand Up @@ -113,7 +140,8 @@ std::unique_ptr<jsi::Runtime> HermesInstance::createJSRuntime(

#ifdef HERMES_ENABLE_DEBUGGER
std::unique_ptr<DecoratedRuntime> decoratedRuntime =
std::make_unique<DecoratedRuntime>(std::move(hermesRuntime));
std::make_unique<DecoratedRuntime>(
std::move(hermesRuntime), msgQueueThread);
return decoratedRuntime;
#endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#pragma once

#include <cxxreact/MessageQueueThread.h>
#include <hermes/hermes.h>
#include <jsi/jsi.h>
#include <react/config/ReactNativeConfig.h>
Expand All @@ -18,9 +19,13 @@ class HermesInstance {
// This is only needed for Android. Consider removing.
static std::unique_ptr<jsi::Runtime> createJSRuntime() noexcept;

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

static std::unique_ptr<jsi::Runtime> createJSRuntime(
std::shared_ptr<const ReactNativeConfig> reactNativeConfig,
std::shared_ptr<::hermes::vm::CrashManager> cm) noexcept;
std::shared_ptr<::hermes::vm::CrashManager> cm,
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept;
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#import <UIKit/UIKit.h>

#include <cxxreact/MessageQueueThread.h>
#import <hermes/Public/CrashManager.h>
#import <jsi/jsi.h>
#import <react/runtime/JSEngineInstance.h>
Expand All @@ -26,6 +27,8 @@ class RCTHermesInstance : public JSEngineInstance {
CrashManagerProvider crashManagerProvider);

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

~RCTHermesInstance(){};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,15 @@
std::unique_ptr<jsi::Runtime> RCTHermesInstance::createJSRuntime() noexcept
{
return _hermesInstance->createJSRuntime(
_reactNativeConfig, _crashManagerProvider ? _crashManagerProvider() : nullptr);
_reactNativeConfig, _crashManagerProvider ? _crashManagerProvider() : nullptr, nullptr);
}

std::unique_ptr<jsi::Runtime> RCTHermesInstance::createJSRuntime(
std::shared_ptr<MessageQueueThread> msgQueueThread) noexcept
{
return _hermesInstance->createJSRuntime(
_reactNativeConfig, _crashManagerProvider ? _crashManagerProvider() : nullptr, msgQueueThread);
}

} // namespace react
} // namespace facebook
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,10 @@ - (void)_start

// Create the React Instance
_reactInstance = std::make_unique<ReactInstance>(
_jsEngineInstance->createJSRuntime(), _jsThreadManager.jsMessageThread, timerManager, jsErrorHandlingFunc);
_jsEngineInstance->createJSRuntime(_jsThreadManager.jsMessageThread),
_jsThreadManager.jsMessageThread,
timerManager,
jsErrorHandlingFunc);
_valid = true;

RuntimeExecutor bufferedRuntimeExecutor = _reactInstance->getBufferedRuntimeExecutor();
Expand Down

0 comments on commit ea7d908

Please sign in to comment.