Skip to content

Commit

Permalink
Address PR feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
vmoroz committed Jan 2, 2021
1 parent b707a8c commit 2cccbe1
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 149 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,14 @@
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IReactNonAbiValue.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IReactNotificationService.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IReactPackageBuilder.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IReactPackageProvider.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IReactPropertyBag.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IViewManager.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IViewManagerCore.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\JsiApi.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\ReactInstanceSettings.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\ReactNativeHost.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\RedBoxHandler.idl" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,23 @@ void ReactContextMock::EmitJSEvent(
m_builderMock->EmitJSEvent(eventEmitterName, eventName, paramsArgWriter);
}

Microsoft::ReactNative::IReactPropertyNamespace ReactPropertyBagHelper::GlobalNamespace() {
VerifyElseCrashSz(false, "Not implemented");
}

Microsoft::ReactNative::IReactPropertyNamespace ReactPropertyBagHelper::GetNamespace(
param::hstring const & /*namespaceName*/) {
VerifyElseCrashSz(false, "Not implemented");
}

Microsoft::ReactNative::IReactPropertyName ReactPropertyBagHelper::GetName(
Microsoft::ReactNative::IReactPropertyNamespace const & /*ns*/,
param::hstring const & /*localName*/) {
VerifyElseCrashSz(false, "Not implemented");
}

Microsoft::ReactNative::IReactPropertyBag ReactPropertyBagHelper::CreatePropertyBag() {
VerifyElseCrashSz(false, "Not implemented");
}

} // namespace winrt::Microsoft::ReactNative
58 changes: 58 additions & 0 deletions vnext/Microsoft.ReactNative.Cxx/JSI/JsiApiContext.cpp
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
48 changes: 2 additions & 46 deletions vnext/Microsoft.ReactNative.Cxx/JSI/JsiApiContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,62 +8,18 @@
#include "../ReactContext.h"
#include "JsiAbiApi.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.
inline 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;
}
facebook::jsi::Runtime &GetOrCreateContextRuntime(ReactContext const &context) noexcept;

// Call provided lambda with the facebook::jsi::Runtime& parameter.
// For example: ExecuteJsi(context, [](facebook::jsi::Runtime& runtime){...})
// The code is executed synchronously if it is already in JSDispatcher, or asynchronously otherwise.
template <class TCodeWithRuntime>
inline void ExecuteJsi(ReactContext const &context, TCodeWithRuntime const &code) {
void ExecuteJsi(ReactContext const &context, TCodeWithRuntime const &code) {
ReactDispatcher jsDispatcher = context.JSDispatcher();
if (jsDispatcher.HasThreadAccess()) {
// Execute immediately if we are in JS thread.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,14 @@
<ClCompile Include="$(JSI_SourcePath)\jsi\jsi.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)JSI\JsiAbiApi.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)JSI\JsiApiContext.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)JSValue.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)JSValueTreeReader.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)JSValueTreeWriter.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)ModuleRegistration.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)ReactPromise.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)JSI\JsiAbiApi.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)TurboModuleProvider.cpp" />
<ClCompile Include="$(TurboModule_SourcePath)\ReactCommon\LongLivedObject.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,21 @@
<ClCompile Include="$(MSBuildThisFileDirectory)JSI\JsiAbiApi.cpp">
<Filter>JSI</Filter>
</ClCompile>
<ClCompile Include="$(ReactNativeDir)\ReactCommon\react\nativemodule\core\ReactCommon\TurboModule.cpp">
<ClCompile Include="$(MSBuildThisFileDirectory)ReactCommon\TurboModuleUtils.cpp">
<Filter>TurboModule</Filter>
</ClCompile>
<ClCompile Include="$(ReactNativeDir)\ReactCommon\react\nativemodule\core\ReactCommon\LongLivedObject.cpp">
<ClCompile Include="$(MSBuildThisFileDirectory)TurboModuleProvider.cpp">
<Filter>TurboModule</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)ReactCommon\TurboModuleUtils.cpp">
<ClCompile Include="$(TurboModule_SourcePath)\ReactCommon\TurboModule.cpp">
<Filter>TurboModule</Filter>
</ClCompile>
<ClCompile Include="$(TurboModule_SourcePath)\ReactCommon\LongLivedObject.cpp">
<Filter>TurboModule</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)JSI\JsiApiContext.cpp">
<Filter>JSI</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)Crash.h" />
Expand Down Expand Up @@ -121,15 +127,6 @@
<ClInclude Include="$(JSI_SourcePath)\jsi\instrumentation.h">
<Filter>JSI</Filter>
</ClInclude>
<ClInclude Include="$(ReactNativeDir)\ReactCommon\react\nativemodule\core\ReactCommon\TurboModule.h">
<Filter>TurboModule</Filter>
</ClInclude>
<ClInclude Include="$(ReactNativeDir)\ReactCommon\callinvoker\ReactCommon\CallInvoker.h">
<Filter>TurboModule</Filter>
</ClInclude>
<ClInclude Include="$(ReactNativeDir)\ReactCommon\react\nativemodule\core\ReactCommon\LongLivedObject.h">
<Filter>TurboModule</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)TurboModuleProvider.h">
<Filter>TurboModule</Filter>
</ClInclude>
Expand All @@ -139,6 +136,13 @@
<ClInclude Include="$(MSBuildThisFileDirectory)JSI\JsiApiContext.h">
<Filter>JSI</Filter>
</ClInclude>
<ClInclude Include="$(CallInvoker_SourcePath)\ReactCommon\CallInvoker.h" />
<ClInclude Include="$(TurboModule_SourcePath)\ReactCommon\TurboModule.h">
<Filter>TurboModule</Filter>
</ClInclude>
<ClInclude Include="$(TurboModule_SourcePath)\ReactCommon\LongLivedObject.h">
<Filter>TurboModule</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="JSI">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include <cassert>
#include <string>

// RNW changes: commended out the unused include that creates unnecessary dependency on folly
// RNW changes: commented out the unused include that creates unnecessary dependency on Folly.
//#include <folly/Optional.h>
#include <jsi/jsi.h>

Expand Down
1 change: 1 addition & 0 deletions vnext/Microsoft.ReactNative.Cxx/ReactPropertyBag.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
//

#include <winrt/Microsoft.ReactNative.h>
#include <winrt/Windows.Foundation.h>
#include <optional>
#include "ReactHandleHelper.h"
#include "ReactNonAbiValue.h"
Expand Down
61 changes: 61 additions & 0 deletions vnext/Microsoft.ReactNative.Cxx/TurboModuleProvider.cpp
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
Loading

0 comments on commit 2cccbe1

Please sign in to comment.