first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
# 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.
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE on)
include(${REACT_COMMON_DIR}/cmake-utils/internal/react-native-platform-selector.cmake)
include(${REACT_COMMON_DIR}/cmake-utils/react-native-flags.cmake)
file(GLOB_RECURSE bridgeless_hermes_SRC CONFIGURE_DEPENDS *.cpp)
add_library(
bridgelesshermes
OBJECT
${bridgeless_hermes_SRC}
)
target_include_directories(bridgelesshermes PUBLIC .)
react_native_android_selector(reactnative reactnative "")
target_link_libraries(bridgelesshermes
hermes-engine::hermesvm
hermes_executor_common
hermes_inspector_modern
jsi
jsitooling
jsinspector
${reactnative}
)
target_compile_reactnative_options(bridgelesshermes PRIVATE)
if(${CMAKE_BUILD_TYPE} MATCHES Debug OR REACT_NATIVE_DEBUG_OPTIMIZED)
target_compile_options(
bridgelesshermes
PRIVATE
-DHERMES_ENABLE_DEBUGGER=1
)
if (HERMES_V1_ENABLED)
target_compile_options(bridgelesshermes PRIVATE -DHERMES_V1_ENABLED=1)
endif()
endif()

View File

@@ -0,0 +1,179 @@
/*
* 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 "HermesInstance.h"
#include <hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h>
#include <jsi/jsilib.h>
#include <jsinspector-modern/InspectorFlags.h>
#include <react/featureflags/ReactNativeFeatureFlags.h>
#ifdef HERMES_ENABLE_DEBUGGER
#include <hermes/inspector-modern/chrome/Registration.h>
#ifndef HERMES_V1_ENABLED
#include <hermes/inspector/RuntimeAdapter.h>
#endif
#include <jsi/decorator.h>
#endif
using namespace facebook::hermes;
using namespace facebook::jsi;
namespace facebook::react {
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
// Wrapper that strongly retains the HermesRuntime for on device debugging.
//
// HermesInstanceRuntimeAdapter needs to strongly retain the HermesRuntime. Why:
// - facebook::hermes::inspector_modern::chrome::Connection::Impl owns the
// Adapter
// - facebook::hermes::inspector_modern::chrome::Connection::Impl also owns
// jsi:: objects
// - jsi:: objects need to be deleted before the Runtime.
//
// If Adapter doesn't share ownership over jsi::Runtime, the runtime can be
// deleted before Connection::Impl cleans up all its jsi:: Objects. This will
// lead to a runtime crash.
class HermesInstanceRuntimeAdapter : public inspector_modern::RuntimeAdapter {
public:
HermesInstanceRuntimeAdapter(
std::shared_ptr<HermesRuntime> hermesRuntime,
std::shared_ptr<MessageQueueThread> msgQueueThread)
: hermesRuntime_(std::move(hermesRuntime)),
messageQueueThread_(std::move(msgQueueThread)) {}
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,
std::shared_ptr<MessageQueueThread> msgQueueThread)
: RuntimeDecorator<jsi::Runtime>(*runtime), runtime_(std::move(runtime)) {
auto adapter = std::make_unique<HermesInstanceRuntimeAdapter>(
runtime_, msgQueueThread);
debugToken_ = inspector_modern::chrome::enableDebugging(
std::move(adapter), "Hermes Bridgeless React Native");
}
~DecoratedRuntime() {
inspector_modern::chrome::disableDebugging(debugToken_);
}
private:
std::shared_ptr<HermesRuntime> runtime_;
inspector_modern::chrome::DebugSessionToken debugToken_;
};
#endif // defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
class HermesJSRuntime : public JSRuntime {
public:
HermesJSRuntime(std::unique_ptr<HermesRuntime> runtime)
: runtime_(std::move(runtime)) {}
jsi::Runtime& getRuntime() noexcept override {
return *runtime_;
}
jsinspector_modern::RuntimeTargetDelegate& getRuntimeTargetDelegate()
override {
if (!targetDelegate_) {
targetDelegate_.emplace(runtime_);
}
return *targetDelegate_;
}
void unstable_initializeOnJsThread() override {
runtime_->registerForProfiling();
}
private:
std::shared_ptr<HermesRuntime> runtime_;
std::optional<jsinspector_modern::HermesRuntimeTargetDelegate>
targetDelegate_;
};
std::unique_ptr<JSRuntime> HermesInstance::createJSRuntime(
std::shared_ptr<::hermes::vm::CrashManager> crashManager,
std::shared_ptr<MessageQueueThread> msgQueueThread,
bool allocInOldGenBeforeTTI) noexcept {
assert(msgQueueThread != nullptr);
auto gcConfig = ::hermes::vm::GCConfig::Builder()
// Default to 3GB
.withMaxHeapSize(3072 << 20)
.withName("RNBridgeless");
if (allocInOldGenBeforeTTI) {
// For the next two arguments: avoid GC before TTI
// by initializing the runtime to allocate directly
// in the old generation, but revert to normal
// operation when we reach the (first) TTI point.
gcConfig.withAllocInYoung(false).withRevertToYGAtTTI(true);
}
::hermes::vm::RuntimeConfig::Builder runtimeConfigBuilder =
::hermes::vm::RuntimeConfig::Builder()
.withGCConfig(gcConfig.build())
.withEnableSampleProfiling(true)
.withMicrotaskQueue(
ReactNativeFeatureFlags::enableBridgelessArchitecture());
if (crashManager) {
runtimeConfigBuilder.withCrashMgr(crashManager);
}
std::unique_ptr<HermesRuntime> hermesRuntime =
hermes::makeHermesRuntime(runtimeConfigBuilder.build());
auto errorPrototype = hermesRuntime->global()
.getPropertyAsObject(*hermesRuntime, "Error")
.getPropertyAsObject(*hermesRuntime, "prototype");
errorPrototype.setProperty(*hermesRuntime, "jsEngine", "hermes");
#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)
auto& inspectorFlags = jsinspector_modern::InspectorFlags::getInstance();
if (!inspectorFlags.getFuseboxEnabled()) {
std::unique_ptr<DecoratedRuntime> decoratedRuntime =
std::make_unique<DecoratedRuntime>(
std::move(hermesRuntime), msgQueueThread);
return std::make_unique<JSIRuntimeHolder>(std::move(decoratedRuntime));
}
#else
(void)msgQueueThread;
#endif
return std::make_unique<HermesJSRuntime>(std::move(hermesRuntime));
}
} // namespace facebook::react

View File

@@ -0,0 +1,25 @@
/*
* 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.
*/
#pragma once
#include <cxxreact/MessageQueueThread.h>
#include <hermes/hermes.h>
#include <jsi/jsi.h>
#include <react/runtime/JSRuntimeFactory.h>
namespace facebook::react {
class HermesInstance {
public:
static std::unique_ptr<JSRuntime> createJSRuntime(
std::shared_ptr<::hermes::vm::CrashManager> crashManager,
std::shared_ptr<MessageQueueThread> msgQueueThread,
bool allocInOldGenBeforeTTI) noexcept;
};
} // namespace facebook::react