Skip to content

Commit

Permalink
[0.71] Switch between V8 JSI and V8 Node-API (#12211)
Browse files Browse the repository at this point in the history
* Switch between V8 JSI and V8 Node-API

* Change files

* Format code
  • Loading branch information
vmoroz committed Oct 6, 2023
1 parent 707cdea commit 75b4202
Show file tree
Hide file tree
Showing 9 changed files with 192 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Switch between V8 JSI and V8 Node-API",
"packageName": "react-native-windows",
"email": "vmorozov@microsoft.com",
"dependentChangeType": "patch"
}
3 changes: 3 additions & 0 deletions vnext/Microsoft.ReactNative/ReactHost/React.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ struct ReactOptions {
winrt::Microsoft::ReactNative::IReactPropertyBag const &properties,
JSIEngine value) noexcept;

bool JsiEngineV8NodeApi() const noexcept;
static bool JsiEngineV8NodeApi(winrt::Microsoft::ReactNative::IReactPropertyBag const &properties) noexcept;

//! Enable live reload to load the source bundle from the React Native packager.
//! When the file is saved, the packager will trigger reloading.
void SetUseLiveReload(bool enable) noexcept;
Expand Down
16 changes: 16 additions & 0 deletions vnext/Microsoft.ReactNative/ReactHost/ReactHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "ReactHost.h"
#include <Future/FutureWait.h>
#include <ReactPropertyBag.h>
#include <winrt/Windows.Foundation.h>

namespace Mso::React {
Expand Down Expand Up @@ -35,6 +36,12 @@ winrt::Microsoft::ReactNative::IReactPropertyName JSIEngineProperty() noexcept {
return propName;
}

winrt::Microsoft::ReactNative::ReactPropertyId<bool> JSIEngineV8NodeApiProperty() noexcept {
static winrt::Microsoft::ReactNative::ReactPropertyId<bool> propId{
L"ReactNative.ReactOptions", L"JSIEngineV8NodeApi"};
return propId;
}

winrt::Microsoft::ReactNative::IReactPropertyName LiveReloadEnabledProperty() noexcept {
static winrt::Microsoft::ReactNative::IReactPropertyName propName =
winrt::Microsoft::ReactNative::ReactPropertyBagHelper::GetName(
Expand Down Expand Up @@ -137,6 +144,15 @@ void ReactOptions::SetJsiEngine(JSIEngine value) noexcept {
properties.Set(JSIEngineProperty(), winrt::box_value(static_cast<uint32_t>(value)));
}

/*static*/ bool ReactOptions::JsiEngineV8NodeApi(
winrt::Microsoft::ReactNative::IReactPropertyBag const &properties) noexcept {
return winrt::Microsoft::ReactNative::ReactPropertyBag(properties).Get(JSIEngineV8NodeApiProperty()).value_or(false);
}

bool ReactOptions::JsiEngineV8NodeApi() const noexcept {
return JsiEngineV8NodeApi(Properties);
}

/*static*/ void ReactOptions::SetUseFastRefresh(
winrt::Microsoft::ReactNative::IReactPropertyBag const &properties,
bool value) noexcept {
Expand Down
16 changes: 14 additions & 2 deletions vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@

#if defined(USE_V8)
#include <winrt/Windows.Storage.h>
#include "BaseScriptStoreImpl.h"
#include "JSI/V8RuntimeHolder.h"
#include "V8JSIRuntimeHolder.h"
#endif // USE_V8

#include "RedBox.h"
Expand Down Expand Up @@ -509,8 +511,18 @@ void ReactInstanceWin::Initialize() noexcept {
enableMultiThreadSupport = Microsoft::ReactNative::IsFabricEnabled(m_reactContext->Properties());
#endif // USE_FABRIC

devSettings->jsiRuntimeHolder = std::make_shared<Microsoft::ReactNative::V8RuntimeHolder>(
devSettings, m_jsMessageThread.Load(), std::move(preparedScriptStore), enableMultiThreadSupport);
if (m_options.JsiEngineV8NodeApi()) {
devSettings->jsiRuntimeHolder = std::make_shared<Microsoft::ReactNative::V8RuntimeHolder>(
devSettings, m_jsMessageThread.Load(), std::move(preparedScriptStore), enableMultiThreadSupport);
} else {
devSettings->jsiRuntimeHolder = std::make_shared<facebook::react::V8JSIRuntimeHolder>(
devSettings,
m_jsMessageThread.Load(),
std::move(scriptStore),
std::move(preparedScriptStore),
enableMultiThreadSupport);
}

break;
}
#endif // USE_V8
Expand Down
20 changes: 19 additions & 1 deletion vnext/Shared/OInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@

#if defined(USE_V8)
#include <JSI/V8RuntimeHolder.h>
#include "V8JSIRuntimeHolder.h"
#endif
#include <ReactCommon/CallInvoker.h>
#include <ReactCommon/TurboModuleBinding.h>
Expand Down Expand Up @@ -319,7 +320,24 @@ InstanceImpl::InstanceImpl(
m_devSettings, m_jsThread, std::move(preparedScriptStore));
break;
}
case JSIEngineOverride::V8:
case JSIEngineOverride::V8: {
#if defined(USE_V8)
std::shared_ptr<facebook::jsi::PreparedScriptStore> preparedScriptStore;

wchar_t tempPath[MAX_PATH];
if (GetTempPathW(MAX_PATH, tempPath)) {
preparedScriptStore =
std::make_shared<facebook::react::BasePreparedScriptStoreImpl>(winrt::to_string(tempPath));
}

m_devSettings->jsiRuntimeHolder = std::make_shared<facebook::react::V8JSIRuntimeHolder>(
m_devSettings, m_jsThread, nullptr, std::move(preparedScriptStore), /*multithreading*/ false);
break;
#else
assert(false); // V8 is not available in this build, fallthrough
[[fallthrough]];
#endif
}
case JSIEngineOverride::V8NodeApi: {
#if defined(USE_V8)
std::shared_ptr<facebook::jsi::PreparedScriptStore> preparedScriptStore;
Expand Down
4 changes: 4 additions & 0 deletions vnext/Shared/Shared.vcxitems
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@
<ClCompile Include="$(MSBuildThisFileDirectory)TurboModuleManager.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utils.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utils\WinRTConversions.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)V8JSIRuntimeHolder.cpp">
<ExcludedFromBuild Condition="'$(UseV8)' != 'true'">true</ExcludedFromBuild>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)..\include\Shared\cdebug.h" />
Expand Down Expand Up @@ -165,6 +168,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)Utils.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utils\CppWinrtLessExceptions.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utils\WinRTConversions.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)V8JSIRuntimeHolder.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)WebSocketJSExecutorFactory.h" />
<ClCompile Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\Modules\ReactRootViewTagGenerator.cpp" />
<ClCompile Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\Utils\ImageUtils.cpp" />
Expand Down
2 changes: 2 additions & 0 deletions vnext/Shared/Shared.vcxitems.filters
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@
<ClCompile Include="$(NodeApiJsiDir)src\ApiLoaders\HermesApi.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)JSI\V8RuntimeHolder.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)SafeLoadLibrary.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)V8JSIRuntimeHolder.cpp" />
</ItemGroup>
<ItemGroup>
<Filter Include="Source Files">
Expand Down Expand Up @@ -485,6 +486,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\Microsoft.ReactNative\JsiApi.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)JSI\V8RuntimeHolder.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)SafeLoadLibrary.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)V8JSIRuntimeHolder.h" />
</ItemGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)tracing\rnw.wprp">
Expand Down
71 changes: 71 additions & 0 deletions vnext/Shared/V8JSIRuntimeHolder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#include "pch.h"

#include <V8JsiRuntime.h>
#include "V8JSIRuntimeHolder.h"

#include <atomic>
#include <queue>

using namespace facebook;
using namespace facebook::react;

namespace facebook {
namespace react {

class TaskRunnerAdapter : public v8runtime::JSITaskRunner {
public:
TaskRunnerAdapter(std::shared_ptr<facebook::react::MessageQueueThread> jsQueue) : jsQueue_(std::move(jsQueue)) {}

void postTask(std::unique_ptr<v8runtime::JSITask> task) override {
std::shared_ptr<v8runtime::JSITask> shared_task(task.release());
jsQueue_->runOnQueue([shared_task2 = std::move(shared_task)]() { shared_task2->run(); });
}

private:
TaskRunnerAdapter(const TaskRunnerAdapter &) = delete;
TaskRunnerAdapter &operator=(const TaskRunnerAdapter &) = delete;

std::shared_ptr<facebook::react::MessageQueueThread> jsQueue_;
};

facebook::react::JSIEngineOverride V8JSIRuntimeHolder::getRuntimeType() noexcept {
return facebook::react::JSIEngineOverride::V8;
}

std::shared_ptr<facebook::jsi::Runtime> V8JSIRuntimeHolder::getRuntime() noexcept {
std::call_once(once_flag_, [this]() { initRuntime(); });

if (!runtime_)
std::terminate();

// V8JsiRuntime is not thread safe as of now.
if (own_thread_id_ != std::this_thread::get_id())
std::terminate();

return runtime_;
}

void V8JSIRuntimeHolder::initRuntime() noexcept {
v8runtime::V8RuntimeArgs args{};

if (debuggerPort_ > 0)
args.inspectorPort = debuggerPort_;

args.flags.enableInspector = useDirectDebugger_;
args.flags.waitForDebugger = debuggerBreakOnNextLine_;
args.debuggerRuntimeName = debuggerRuntimeName_;

args.foreground_task_runner = std::make_shared<TaskRunnerAdapter>(jsQueue_);
args.preparedScriptStore = std::move(preparedScriptStore_);
args.flags.enableMultiThread = enableMultiThreadingSupport_;

runtime_ = v8runtime::makeV8Runtime(std::move(args));

own_thread_id_ = std::this_thread::get_id();
}

} // namespace react
} // namespace facebook
56 changes: 56 additions & 0 deletions vnext/Shared/V8JSIRuntimeHolder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#pragma once

#include <DevSettings.h>

#include <JSI/RuntimeHolder.h>
#include <JSI/ScriptStore.h>

#include <Logging.h>

namespace facebook {
namespace react {

class V8JSIRuntimeHolder : public Microsoft::JSI::RuntimeHolderLazyInit {
public:
std::shared_ptr<facebook::jsi::Runtime> getRuntime() noexcept override;
facebook::react::JSIEngineOverride getRuntimeType() noexcept override;

V8JSIRuntimeHolder(
std::shared_ptr<facebook::react::DevSettings> devSettings,
std::shared_ptr<facebook::react::MessageQueueThread> jsQueue,
std::unique_ptr<facebook::jsi::ScriptStore> &&scriptStore,
std::shared_ptr<facebook::jsi::PreparedScriptStore> &&preparedScriptStore,
bool enableMultiThreadingSupport) noexcept
: useDirectDebugger_(devSettings->useDirectDebugger),
debuggerBreakOnNextLine_(devSettings->debuggerBreakOnNextLine),
debuggerPort_(devSettings->debuggerPort),
debuggerRuntimeName_(devSettings->debuggerRuntimeName),
jsQueue_(std::move(jsQueue)),
scriptStore_(std::move(scriptStore)),
preparedScriptStore_(std::move(preparedScriptStore)),
enableMultiThreadingSupport_(enableMultiThreadingSupport) {}

private:
void initRuntime() noexcept;

std::shared_ptr<facebook::jsi::Runtime> runtime_;
std::shared_ptr<facebook::react::MessageQueueThread> jsQueue_;

std::unique_ptr<facebook::jsi::ScriptStore> scriptStore_;
std::shared_ptr<facebook::jsi::PreparedScriptStore> preparedScriptStore_;

std::once_flag once_flag_;
std::thread::id own_thread_id_;

uint16_t debuggerPort_;
bool useDirectDebugger_;
bool debuggerBreakOnNextLine_;
std::string debuggerRuntimeName_;
bool enableMultiThreadingSupport_;
};

} // namespace react
} // namespace facebook

0 comments on commit 75b4202

Please sign in to comment.