-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
197 additions
and
149 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
#include "pch.h" | ||
#include "JsiApiContext.h" | ||
|
||
// Use __ImageBase to get current DLL handle. | ||
// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx | ||
extern "C" IMAGE_DOS_HEADER __ImageBase; | ||
|
||
namespace winrt::Microsoft::ReactNative { | ||
|
||
// Get JSI Runtime from the current JS dispatcher thread. | ||
// If it is not found, then create it and store it in the context.Properties(). | ||
// Make sure that the JSI runtime holder is removed when the instance is unloaded. | ||
facebook::jsi::Runtime &GetOrCreateContextRuntime(ReactContext const &context) noexcept { | ||
ReactDispatcher jsDispatcher = context.JSDispatcher(); | ||
VerifyElseCrashSz(jsDispatcher.HasThreadAccess(), "Must be in JS thread"); | ||
|
||
// The JSI runtime is not available if we do Web debugging when JS is running in web browser. | ||
JsiRuntime abiJsiRuntime = context.Handle().JSRuntime().as<JsiRuntime>(); | ||
VerifyElseCrashSz(abiJsiRuntime, "JSI runtime is not available"); | ||
|
||
// See if the JSI runtime was previously created. | ||
JsiAbiRuntime *runtime = JsiAbiRuntime::GetFromJsiRuntime(abiJsiRuntime); | ||
if (!runtime) { | ||
// Create the runtime | ||
std::unique_ptr<JsiAbiRuntime> runtimeHolder = std::make_unique<JsiAbiRuntime>(abiJsiRuntime); | ||
runtime = runtimeHolder.get(); | ||
|
||
// We want to keep the JSI runtime while current instance is alive. | ||
// The JSI runtime object must be local to our DLL. | ||
// We create a property name based on the current DLL handle. | ||
HMODULE currentDllHanlde = reinterpret_cast<HMODULE>(&__ImageBase); | ||
std::wstring jsiRuntimeLocalName = L"jsiRuntime_" + std::to_wstring(reinterpret_cast<uintptr_t>(currentDllHanlde)); | ||
using ValueType = ReactNonAbiValue<std::unique_ptr<JsiAbiRuntime>>; | ||
ReactPropertyId<ValueType> jsiRuntimeProperty{L"ReactNative.InstanceData", jsiRuntimeLocalName.c_str()}; | ||
ValueType runtimeValue{std::in_place, std::move(runtimeHolder)}; | ||
context.Properties().Set(jsiRuntimeProperty, runtimeValue); | ||
|
||
// We remove the JSI runtime from properties when React instance is destroyed. | ||
auto destroyInstanceNotificationId{ | ||
ReactNotificationId<InstanceDestroyedEventArgs>{L"ReactNative.InstanceSettings", L"InstanceDestroyed"}}; | ||
context.Notifications().Subscribe( | ||
destroyInstanceNotificationId, | ||
jsDispatcher, | ||
[context, jsiRuntimeProperty]( | ||
winrt::Windows::Foundation::IInspectable const & /*sender*/, | ||
ReactNotificationArgs<InstanceDestroyedEventArgs> const &args) noexcept { | ||
context.Properties().Remove(jsiRuntimeProperty); | ||
args.Subscription().Unsubscribe(); // Unsubscribe after we handle the notification. | ||
}); | ||
} | ||
|
||
return *runtime; | ||
} | ||
|
||
} // namespace winrt::Microsoft::ReactNative |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
#include "pch.h" | ||
#include "TurboModuleProvider.h" | ||
|
||
namespace winrt::Microsoft::ReactNative { | ||
|
||
// CallInvoker implementation based on JSDispatcher. | ||
struct AbiCallInvoker final : facebook::react::CallInvoker { | ||
AbiCallInvoker(IReactDispatcher const &jsDispatcher) : m_jsDispatcher(jsDispatcher) {} | ||
|
||
void invokeAsync(std::function<void()> &&func) override { | ||
m_jsDispatcher.Post([func = std::move(func)]() { func(); }); | ||
} | ||
|
||
void invokeSync(std::function<void()> &&func) override { | ||
if (m_jsDispatcher.HasThreadAccess()) { | ||
func(); | ||
} else { | ||
std::mutex mutex; | ||
std::condition_variable cv; | ||
bool completed{false}; | ||
std::exception_ptr ex; | ||
|
||
auto lock = std::unique_lock{mutex}; | ||
|
||
m_jsDispatcher.Post([&func, &mutex, &cv, &completed, &ex]() { | ||
// Since this method is synchronous, we catch all func exceptions and rethrow them in this thread. | ||
try { | ||
func(); | ||
} catch (...) { | ||
ex = std::current_exception(); | ||
} | ||
|
||
auto lock = std::unique_lock{mutex}; | ||
completed = true; | ||
cv.notify_all(); | ||
}); | ||
|
||
cv.wait(lock, [&] { return completed; }); | ||
|
||
if (ex) { | ||
std::rethrow_exception(ex); | ||
} | ||
} | ||
|
||
// Since func is passed as an r-value, we want to clean it up in this method as we would move the value. | ||
func = nullptr; | ||
} | ||
|
||
private: | ||
IReactDispatcher m_jsDispatcher{nullptr}; | ||
}; | ||
|
||
// Creates CallInvoker based on JSDispatcher. | ||
std::shared_ptr<facebook::react::CallInvoker> MakeAbiCallInvoker(IReactDispatcher const &jsDispatcher) noexcept { | ||
return std::make_shared<AbiCallInvoker>(jsDispatcher); | ||
} | ||
|
||
} // namespace winrt::Microsoft::ReactNative |
Oops, something went wrong.