Skip to content

Commit

Permalink
Implemented PropertyBag for ReactContext and ReactInstanceSettings (#…
Browse files Browse the repository at this point in the history
…4817)

* Implemented PropertyBag for ReactContext and ReactInstanceSettings

* Change files

* yarn format

* Delete the old PropertyBag files.

* Make PropertyBag's ToObject and FromObject methods private.

* Renamed some classes and methods.

* Fixed sample project compilation

* VS updates the sln file

* VS automatically updated solutions
  • Loading branch information
vmoroz authored and NickGerleman committed May 14, 2020
1 parent 283b06c commit e73a55e
Show file tree
Hide file tree
Showing 40 changed files with 1,322 additions and 1,021 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"type": "prerelease",
"comment": "Implemented PropertyBag for ReactContext and ReactInstanceSettings",
"packageName": "react-native-windows",
"email": "vmorozov@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-05-07T03:33:40.086Z"
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "App.h"
#include "ReactPackageProvider.h"
#include "ReactPropertyBag.h"
#include "winrt/SampleLibraryCS.h"
#include "winrt/SampleLibraryCpp.h"

Expand Down Expand Up @@ -34,6 +35,9 @@ App::App() noexcept {
InstanceSettings().EnableDeveloperMenu(false);
#endif

ReactPropertyBag::Set(InstanceSettings().Properties(), ReactPropertyId<int>{L"Prop1"}, 42);
ReactPropertyBag::Set(InstanceSettings().Properties(), ReactPropertyId<hstring>{L"Prop2"}, L"Hello World!");

PackageProviders().Append(make<ReactPackageProvider>()); // Includes all modules in this project
PackageProviders().Append(winrt::SampleLibraryCpp::ReactPackageProvider());
PackageProviders().Append(winrt::SampleLibraryCS::ReactPackageProvider());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ public App()
InstanceSettings.EnableDeveloperMenu = false;
#endif

InstanceSettings.Properties.Set(ReactPropertyBagHelper.GetName(null, "Prop1"), 43);
InstanceSettings.Properties.Set(ReactPropertyBagHelper.GetName(null, "Prop2"), "Hello RNW!");

PackageProviders.Add(new Microsoft.ReactNative.Managed.ReactPackageProvider()); // Includes any modules in this project
PackageProviders.Add(new SampleLibraryCS.ReactPackageProvider());
PackageProviders.Add(new SampleLibraryCpp.ReactPackageProvider());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
..\..\..\vnext\Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{09f4e6c1-2d12-4059-aa96-0b190861fd6a}*SharedItemsImports = 4
..\..\..\vnext\JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9
..\..\..\vnext\ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603144}*SharedItemsImports = 4
..\..\..\vnext\Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9
..\..\..\vnext\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{47eec7f3-40d3-49ba-82c1-eaf103b54215}*SharedItemsImports = 4
..\..\..\vnext\Microsoft.ReactNative.SharedManaged\Microsoft.ReactNative.SharedManaged.projitems*{67a1076f-7790-4203-86ea-4402ccb5e782}*SharedItemsImports = 13
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ struct SampleModuleCppImpl {
#pragma region Initialization

REACT_INIT(Initialize)
void Initialize(ReactContext const & /*reactContext*/) noexcept {
void Initialize(ReactContext const &reactContext) noexcept {
const ReactPropertyId<int> myProp1{L"Prop1"};
const ReactPropertyId<winrt::hstring> myProp2{L"Prop2"};
DEBUG_OUTPUT("globalProps.Prop1:", *reactContext.Properties().Get(myProp1));
DEBUG_OUTPUT("instanceProps.Prop2:", winrt::to_string(*reactContext.Properties().Get(myProp2)));

m_timer = winrt::Windows::System::Threading::ThreadPoolTimer::CreatePeriodicTimer(
[this](const winrt::Windows::System::Threading::ThreadPoolTimer) noexcept {
TimedEvent(++m_timerCount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ internal sealed class SampleModuleCS
#region Initializer

[ReactInitializer]
public void Initialize(ReactContext _)
public void Initialize(ReactContext reactContext)
{
Debug.WriteLine($"C# globalProps.Prop1: {reactContext.Handle.Properties.Get(ReactPropertyBagHelper.GetName(null, "Prop1"))}");
Debug.WriteLine($"C# instanceProps.Prop2: {reactContext.Handle.Properties.Get(ReactPropertyBagHelper.GetName(null, "Prop2"))}");

_timer = ThreadPoolTimer.CreatePeriodicTimer(new TimerElapsedHandler((timer) =>
{
TimedEvent?.Invoke(++_timerCount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IReactModuleBuilder.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IReactPackageBuilder.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IViewManager.idl" />
<Midl Include="..\Microsoft.ReactNative\IReactPropertyBag.idl" />
<Midl Include="..\Microsoft.ReactNative\NoExceptionAttribute.idl" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ TEST_CLASS (NativeModuleTest) {
auto provider = React::MakeModuleProvider<SimpleNativeModule>();
m_moduleObject = m_builderMock.CreateModule(provider, m_moduleBuilder);
auto reactModule = m_moduleObject.as<React::IBoxedValue>();
m_module = &React::BoxedValue<SimpleNativeModule>::GetImpl(reactModule);
m_module = &React::BoxedValue<SimpleNativeModule>::GetValueUnsafe(reactModule);
}

TEST_METHOD(TestMethodCall_Add) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ TEST_CLASS (NoAttributeNativeModuleTest) {
auto provider = React::MakeModuleProvider<SimpleNativeModule2>();
m_moduleObject = m_builderMock.CreateModule(provider, m_moduleBuilder);
auto reactModule = m_moduleObject.as<React::IBoxedValue>();
m_module = &React::BoxedValue<SimpleNativeModule2>::GetImpl(reactModule);
m_module = &React::BoxedValue<SimpleNativeModule2>::GetValueUnsafe(reactModule);
}

TEST_METHOD(TestMethodCall_Add) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ struct ReactModuleBuilderMock {
struct ReactContextMock : implements<ReactContextMock, IReactContext> {
ReactContextMock(ReactModuleBuilderMock *builderMock) noexcept;

IReactPropertyBag Properties() noexcept {
VerifyElseCrashSz(false, "Not implemented");
}

void DispatchEvent(
FrameworkElement const & /*view*/,
hstring const & /*eventName*/,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1118,7 +1118,7 @@ TEST_CLASS (TurboModuleTest) {
auto provider = winrt::Microsoft::ReactNative::MakeTurboModuleProvider<MyTurboModule, MyTurboModuleSpec>();
m_moduleObject = m_builderMock.CreateModule(provider, m_moduleBuilder);
auto reactModule = m_moduleObject.as<winrt::Microsoft::ReactNative::IBoxedValue>();
m_module = &winrt::Microsoft::ReactNative::BoxedValue<MyTurboModule>::GetImpl(reactModule);
m_module = &winrt::Microsoft::ReactNative::BoxedValue<MyTurboModule>::GetValueUnsafe(reactModule);
}

TEST_METHOD(TestMethodCall_Add) {
Expand Down
2 changes: 2 additions & 0 deletions vnext/Microsoft.ReactNative.Cxx.UnitTests/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#include <unknwn.h>

#undef GetCurrentTime

#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Foundation.h>
#include "winrt/Microsoft.ReactNative.h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)JSValueXaml.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ModuleRegistration.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)NativeModules.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ReactPropertyBag.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ReactContext.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ReactError.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ReactPromise.h" />
Expand Down
16 changes: 7 additions & 9 deletions vnext/Microsoft.ReactNative.Cxx/NativeModules.h
Original file line number Diff line number Diff line change
Expand Up @@ -1107,28 +1107,26 @@ struct TurboModuleSpec {

template <class T>
struct BoxedValue : implements<BoxedValue<T>, IBoxedValue> {
BoxedValue() noexcept {}
template <class... TArgs>
BoxedValue(TArgs &&... args) noexcept : m_value(std::forward<TArgs>(args)...) {}

int64_t GetPtr() noexcept {
return reinterpret_cast<int64_t>(&m_value);
}

static T &GetImpl(IBoxedValue &module) noexcept;
static T &GetValueUnsafe(IBoxedValue const &boxedValue) noexcept {
return *reinterpret_cast<T *>(boxedValue.GetPtr());
}

private:
T m_value{};
};

template <class T>
inline T &BoxedValue<T>::GetImpl(IBoxedValue &module) noexcept {
return *reinterpret_cast<T *>(module.GetPtr());
}

template <class TModule>
inline ReactModuleProvider MakeModuleProvider() noexcept {
return [](IReactModuleBuilder const &moduleBuilder) noexcept {
auto moduleObject = make<BoxedValue<TModule>>();
auto module = &BoxedValue<TModule>::GetImpl(moduleObject);
auto module = &BoxedValue<TModule>::GetValueUnsafe(moduleObject);
ReactModuleBuilder builder{module, moduleBuilder};
GetReactModuleInfo(module, builder);
builder.CompleteRegistration();
Expand All @@ -1141,7 +1139,7 @@ inline ReactModuleProvider MakeTurboModuleProvider() noexcept {
TModuleSpec::template ValidateModule<TModule>();
return [](IReactModuleBuilder const &moduleBuilder) noexcept {
auto moduleObject = make<BoxedValue<TModule>>();
auto module = &BoxedValue<TModule>::GetImpl(moduleObject);
auto module = &BoxedValue<TModule>::GetValueUnsafe(moduleObject);
ReactModuleBuilder builder{module, moduleBuilder};
GetReactModuleInfo(module, builder);
builder.CompleteRegistration();
Expand Down
97 changes: 31 additions & 66 deletions vnext/Microsoft.ReactNative.Cxx/ReactContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,106 +7,71 @@

#include <string_view>
#include "JSValueWriter.h"
#include "winrt/Microsoft.ReactNative.h"
#include "ReactPropertyBag.h"

namespace winrt::Microsoft::ReactNative {

// Represents a context of execution for the Native Module.
// It wraps up the IReactContext and adds convenience methods for
// working with C++ types.
struct ReactContext {
ReactContext(IReactContext const &context) noexcept;
ReactContext(IReactContext const &handle) noexcept : m_handle{handle} {}

IReactContext const &ContextAbi() const noexcept;
IReactContext const &Handle() const noexcept {
return m_handle;
}

explicit operator bool() noexcept;
explicit operator bool() const noexcept {
return static_cast<bool>(m_handle);
}

ReactPropertyBag Properties() const noexcept {
return ReactPropertyBag{m_handle.Properties()};
}

template <class... TArgs>
void CallJSFunction(std::wstring_view moduleName, std::wstring_view methodName, TArgs &&... args) noexcept;
void CallJSFunction(std::wstring_view moduleName, std::wstring_view methodName, TArgs &&... args) const noexcept {
m_handle.CallJSFunction(moduleName, methodName, MakeJSValueArgWriter(std::forward<TArgs>(args)...));
}

void CallJSFunction(
std::wstring_view moduleName,
std::wstring_view methodName,
JSValueArgWriter const &paramsArgWriter) noexcept;
JSValueArgWriter const &paramsArgWriter) const noexcept {
m_handle.CallJSFunction(moduleName, methodName, paramsArgWriter);
}

template <class... TArgs>
void EmitJSEvent(std::wstring_view eventEmitterName, std::wstring_view eventName, TArgs &&... args) noexcept;
void EmitJSEvent(std::wstring_view eventEmitterName, std::wstring_view eventName, TArgs &&... args) const noexcept {
m_handle.EmitJSEvent(eventEmitterName, eventName, MakeJSValueArgWriter(std::forward<TArgs>(args)...));
}

void EmitJSEvent(
std::wstring_view eventEmitterName,
std::wstring_view eventName,
JSValueArgWriter const &paramsArgWriter) noexcept;
JSValueArgWriter const &paramsArgWriter) const noexcept {
m_handle.EmitJSEvent(eventEmitterName, eventName, paramsArgWriter);
}

template <class... TArgs>
void DispatchEvent(
winrt::Windows::UI::Xaml::FrameworkElement const &view,
std::wstring_view eventName,
TArgs &&... args) noexcept;
TArgs &&... args) const noexcept {
m_handle.DispatchEvent(view, eventName, MakeJSValueArgWriter(std::forward<TArgs>(args)...));
}

void DispatchEvent(
winrt::Windows::UI::Xaml::FrameworkElement const &view,
std::wstring_view eventName,
JSValueArgWriter const &paramsArgWriter) noexcept;
JSValueArgWriter const &paramsArgWriter) const noexcept {
m_handle.DispatchEvent(view, eventName, paramsArgWriter);
}

private:
const IReactContext m_context;
const IReactContext m_handle;
};

//==============================================================================
// ReactContext inline implementation
//==============================================================================

inline ReactContext::ReactContext(IReactContext const &context) noexcept : m_context{context} {}

inline IReactContext const &ReactContext::ContextAbi() const noexcept {
return m_context;
}

inline ReactContext::operator bool() noexcept {
return m_context != nullptr;
}

template <class... TArgs>
inline void
ReactContext::CallJSFunction(std::wstring_view moduleName, std::wstring_view methodName, TArgs &&... args) noexcept {
m_context.CallJSFunction(moduleName, methodName, MakeJSValueArgWriter(std::forward<TArgs>(args)...));
}

inline void ReactContext::CallJSFunction(
std::wstring_view moduleName,
std::wstring_view methodName,
JSValueArgWriter const &paramsArgWriter) noexcept {
m_context.CallJSFunction(moduleName, methodName, paramsArgWriter);
}

template <class... TArgs>
inline void
ReactContext::EmitJSEvent(std::wstring_view eventEmitterName, std::wstring_view eventName, TArgs &&... args) noexcept {
m_context.EmitJSEvent(eventEmitterName, eventName, MakeJSValueArgWriter(std::forward<TArgs>(args)...));
}

inline void ReactContext::EmitJSEvent(
std::wstring_view eventEmitterName,
std::wstring_view eventName,
JSValueArgWriter const &paramsArgWriter) noexcept {
m_context.EmitJSEvent(eventEmitterName, eventName, paramsArgWriter);
}

template <class... TArgs>
inline void ReactContext::DispatchEvent(
winrt::Windows::UI::Xaml::FrameworkElement const &view,
std::wstring_view eventName,
TArgs &&... args) noexcept {
m_context.DispatchEvent(view, eventName, MakeJSValueArgWriter(std::forward<TArgs>(args)...));
}

inline void ReactContext::DispatchEvent(
winrt::Windows::UI::Xaml::FrameworkElement const &view,
std::wstring_view eventName,
JSValueArgWriter const &paramsArgWriter) noexcept {
m_context.DispatchEvent(view, eventName, paramsArgWriter);
}

} // namespace winrt::Microsoft::ReactNative

#endif // MICROSOFT_REACTNATIVE_REACTCONTEXT

0 comments on commit e73a55e

Please sign in to comment.