Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"type": "prerelease",
"comment": "ReactNotificationService to allow communications between native modules",
"packageName": "react-native-windows",
"email": "[email protected]",
"dependentChangeType": "patch",
"date": "2020-05-19T20:43:32.803Z"
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,18 @@ struct SampleModuleCppImpl {
DEBUG_OUTPUT("C++ Properties.Prop1:", *reactContext.Properties().Get(myProp1));
DEBUG_OUTPUT("C++ Properties.Prop2:", winrt::to_string(*reactContext.Properties().Get(myProp2)));

const ReactNotificationId<int> cppTimerNotification{L"SampleModuleCppImpl", L"TimerNotification"};
const ReactNotificationId<int> csTimerNotification{L"SampleModuleCS", L"TimerNotification"};

reactContext.Notifications().Subscribe(csTimerNotification, [
](winrt::Windows::Foundation::IInspectable const &, ReactNotificationArgs<int> const &args) noexcept {
DEBUG_OUTPUT("C++ module, C# timer:", *args.Data());
});

m_timer = winrt::Windows::System::Threading::ThreadPoolTimer::CreatePeriodicTimer(
[this](const winrt::Windows::System::Threading::ThreadPoolTimer) noexcept {
[ this, cppTimerNotification, notifications = reactContext.Notifications() ](
const winrt::Windows::System::Threading::ThreadPoolTimer) noexcept {
notifications.SendNotification(cppTimerNotification, m_timerCount);
TimedEvent(++m_timerCount);
if (m_timer && m_timerCount == 5) {
m_timer.Cancel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,15 @@ public void Initialize(ReactContext reactContext)
Debug.WriteLine($"C# Properties.Prop1: {reactContext.Handle.Properties.Get(ReactPropertyBagHelper.GetName(null, "Prop1"))}");
Debug.WriteLine($"C# Properties.Prop2: {reactContext.Handle.Properties.Get(ReactPropertyBagHelper.GetName(null, "Prop2"))}");

var cppTimerNotification = ReactPropertyBagHelper.GetName(ReactPropertyBagHelper.GetNamespace("SampleModuleCppImpl"), "TimerNotification");
var csTimerNotification = ReactPropertyBagHelper.GetName(ReactPropertyBagHelper.GetNamespace("SampleModuleCS"), "TimerNotification");

reactContext.Handle.Notifications.Subscribe(cppTimerNotification, null,
(object sender, IReactNotificationArgs args) => Debug.WriteLine($"C# module, C++ timer:: {args.Data}"));

_timer = ThreadPoolTimer.CreatePeriodicTimer(new TimerElapsedHandler((timer) =>
{
reactContext.Handle.Notifications.SendNotification(csTimerNotification, null, _timerCount);
TimedEvent?.Invoke(++_timerCount);
if (_timerCount == 5)
{
Expand Down
3 changes: 3 additions & 0 deletions vnext/Desktop/React.Windows.Desktop.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@
<Midl Include="..\Microsoft.ReactNative\IReactContext.idl" />
<Midl Include="..\Microsoft.ReactNative\IJSValueReader.idl" />
<Midl Include="..\Microsoft.ReactNative\IViewManager.idl" />
<Midl Include="..\Microsoft.ReactNative\IReactDispatcher.idl" />
<Midl Include="..\Microsoft.ReactNative\IReactNotificationService.idl" />
<Midl Include="..\Microsoft.ReactNative\IReactPropertyBag.idl" />
<Midl Include="..\Microsoft.ReactNative\RedBoxHandler.idl" />
<Midl Include="..\Microsoft.ReactNative\ReactInstance.idl" />
Expand All @@ -147,6 +149,7 @@
<DependentUpon>..\Microsoft.ReactNative\ReactNativeHost.idl</DependentUpon>
<ObjectFileName>$(IntDir)\ABI\</ObjectFileName>
</ClCompile>
<ClCompile Include="..\Microsoft.ReactNative\IReactNotificationService.cpp" />
<ClCompile Include="..\Microsoft.ReactNative\IReactPropertyBag.cpp" />
<ClCompile Include="..\Microsoft.ReactNative\ReactHost\ReactHost.cpp" />
<ClCompile Include="..\Microsoft.ReactNative\ReactHost\MsoUtils.cpp" />
Expand Down
40 changes: 23 additions & 17 deletions vnext/Desktop/React.Windows.Desktop.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -30,49 +30,55 @@
</Filter>
</ItemGroup>
<ItemGroup>
<Midl Include="ABI\MemoryTracker.idl">
<Midl Include="..\Microsoft.ReactNative\IJSValueReader.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="ABI\MessageQueue.idl">
<Midl Include="..\Microsoft.ReactNative\IJSValueWriter.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="ABI\NativeLogging.idl">
<Midl Include="..\Microsoft.ReactNative\IReactContext.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="ABI\NativeTracing.idl">
<Midl Include="..\Microsoft.ReactNative\IReactDispatcher.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="..\Microsoft.ReactNative\ReactNativeHost.idl">
<Midl Include="..\Microsoft.ReactNative\IReactModuleBuilder.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="..\Microsoft.ReactNative\IReactNotificationService.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="..\Microsoft.ReactNative\IReactPackageBuilder.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="..\Microsoft.ReactNative\IReactPackageProvider.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="..\Microsoft.ReactNative\ReactInstanceSettings.idl">
<Midl Include="..\Microsoft.ReactNative\IReactPropertyBag.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="..\Microsoft.ReactNative\IReactPackageBuilder.idl">
<Midl Include="..\Microsoft.ReactNative\IViewManager.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="..\Microsoft.ReactNative\IReactModuleBuilder.idl">
<Midl Include="..\Microsoft.ReactNative\ReactInstanceSettings.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="..\Microsoft.ReactNative\IJSValueWriter.idl">
<Midl Include="..\Microsoft.ReactNative\ReactNativeHost.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="..\Microsoft.ReactNative\IReactContext.idl">
<Midl Include="..\Microsoft.ReactNative\RedBoxHandler.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="..\Microsoft.ReactNative\IJSValueReader.idl">
<Midl Include="ABI\MemoryTracker.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="..\Microsoft.ReactNative\IViewManager.idl">
<Midl Include="ABI\MessageQueue.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="..\Microsoft.ReactNative\IReactPropertyBag.idl">
<Midl Include="ABI\NativeLogging.idl">
<Filter>ABI</Filter>
</Midl>
<Midl Include="..\Microsoft.ReactNative\RedBoxHandler.idl">
<Midl Include="ABI\NativeTracing.idl">
<Filter>ABI</Filter>
</Midl>
</ItemGroup>
Expand Down Expand Up @@ -116,9 +122,6 @@
<ClCompile Include="module.g.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="WebSocketResourceFactory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Modules\NetworkingModule.cpp">
<Filter>Source Files\Modules</Filter>
</ClCompile>
Expand All @@ -129,6 +132,9 @@
<Filter>Source Files\Modules</Filter>
</ClCompile>
<ClCompile Include="pch.cpp" />
<ClCompile Include="WebSocketResourceFactory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ABI\MemoryTracker.h">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,14 @@
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IJSValueReader.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IJSValueWriter.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IReactContext.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IReactDispatcher.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IReactModuleBuilder.idl" />
<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\IReactPropertyBag.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IViewManager.idl" />
<Midl Include="..\Microsoft.ReactNative\IReactNonAbiValue.idl" />
<Midl Include="..\Microsoft.ReactNative\IReactPropertyBag.idl" />
<Midl Include="..\Microsoft.ReactNative\NoExceptionAttribute.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\NoExceptionAttribute.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 @@ -12,6 +12,10 @@ struct ReactContextStub : implements<ReactContextStub, IReactContext> {
VerifyElseCrashSz(false, "Not implemented");
}

IReactNotificationService Notifications() noexcept {
VerifyElseCrashSz(false, "Not implemented");
}

void DispatchEvent(
xaml::FrameworkElement const & /*view*/,
hstring const & /*eventName*/,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ struct ReactContextMock : implements<ReactContextMock, IReactContext> {
VerifyElseCrashSz(false, "Not implemented");
}

IReactNotificationService Notifications() noexcept {
VerifyElseCrashSz(false, "Not implemented");
}

void DispatchEvent(
xaml::FrameworkElement const & /*view*/,
hstring const & /*eventName*/,
Expand Down
2 changes: 1 addition & 1 deletion vnext/Microsoft.ReactNative.Cxx.UnitTests/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@

#undef GetCurrentTime

#include <winrt/Microsoft.ReactNative.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Foundation.h>
#include "winrt/Microsoft.ReactNative.h"

#include "gtest/gtest.h"
#include "motifCpp/gTestAdapter.h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)CppWinRTIncludes.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Crash.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ReactHandleHelper.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)JSValue.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)JSValueReader.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)JSValueTreeReader.h" />
Expand All @@ -28,7 +29,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)ModuleRegistration.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)NamespaceRedirect.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)NativeModules.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ReactDispatcher.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ReactNonAbiValue.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ReactNotificationService.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ReactPropertyBag.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ReactContext.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ReactError.h" />
Expand Down
7 changes: 6 additions & 1 deletion vnext/Microsoft.ReactNative.Cxx/ReactContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <CppWinRTIncludes.h>
#include <string_view>
#include "JSValueWriter.h"
#include "ReactNotificationService.h"
#include "ReactPropertyBag.h"

namespace winrt::Microsoft::ReactNative {
Expand All @@ -25,13 +26,17 @@ struct ReactContext {
}

explicit operator bool() const noexcept {
return static_cast<bool>(m_handle);
return m_handle ? true : false;
}

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

ReactNotificationService Notifications() const noexcept {
return ReactNotificationService{m_handle.Notifications()};
}

// Call methodName JS function of module with moduleName.
// args are either function arguments or a single lambda with 'IJSValueWriter const&' argument.
template <class... TArgs>
Expand Down
49 changes: 49 additions & 0 deletions vnext/Microsoft.ReactNative.Cxx/ReactDispatcher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#pragma once
#ifndef MICROSOFT_REACTNATIVE_REACTDISPATCHER
#define MICROSOFT_REACTNATIVE_REACTDISPATCHER

#include <winrt/Microsoft.ReactNative.h>
#include "ReactHandleHelper.h"

namespace winrt::Microsoft::ReactNative {

// Represents a dispatcher queue to invoke work item asynchronously.
// It wraps up the IReactDispatcher and adds convenience methods for
// working with C++ types.
struct ReactDispatcher {
ReactDispatcher(std::nullptr_t = nullptr) noexcept {}

explicit ReactDispatcher(IReactDispatcher const &handle) noexcept : m_handle{handle} {}
Copy link

@NikoAri NikoAri May 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

& [](start = 49, length = 2)

(nit) Since we are doing assignment anyways, wouldn't && be better here? #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the C++/WinRT thing. It always gives us const &.


In reply to: 427624661 [](ancestors = 427624661)


IReactDispatcher const &Handle() const noexcept {
return m_handle;
}

explicit operator bool() const noexcept {
return m_handle ? true : false;
}

void Post(ReactDispatcherCallback const &callback) const noexcept {
if (m_handle) {
Copy link

@NikoAri NikoAri May 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m_handle [](start = 8, length = 8)

(nit) can you add comment of why we would ever want this to be null? #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class supports move semantic. It can be null if its content is moved out, or nullptr is given at construction.


In reply to: 427625320 [](ancestors = 427625320)

m_handle.Post(callback);
}
}

bool HasThreadAccess() const noexcept {
return m_handle ? m_handle.HasThreadAccess() : false;
}

static ReactDispatcher CreateSerialDispatcher() noexcept {
return ReactDispatcher{ReactDispatcherHelper::CreateSerialDispatcher()};
}

private:
IReactDispatcher m_handle;
};

} // namespace winrt::Microsoft::ReactNative

#endif // MICROSOFT_REACTNATIVE_REACTDISPATCHER
67 changes: 67 additions & 0 deletions vnext/Microsoft.ReactNative.Cxx/ReactHandleHelper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#pragma once
#ifndef MICROSOFT_REACTNATIVE_REACTHANDLEHELPER
#define MICROSOFT_REACTNATIVE_REACTHANDLEHELPER

//
// Helper methods for types that have Handle() method that return
// an IInspectable-inherited value.
//

#include <winrt/Microsoft.ReactNative.h>
#include <type_traits>

namespace winrt::Microsoft::ReactNative {

namespace Internal {
template <class T>
auto TestHandle(int) -> decltype(std::declval<T>().Handle());
template <class>
auto TestHandle(int *) -> void;
} // namespace Internal

template <class T>
inline constexpr bool HasHandleV =
std::is_base_of_v<Windows::Foundation::IInspectable, std::decay_t<decltype(Internal::TestHandle<T>(0))>>;

// True if two types with Handle() have the same handle.
template <class T, std::enable_if_t<HasHandleV<T>, int> = 0>
inline bool operator==(T const &left, T const &right) noexcept {
return left.Handle() == right.Handle();
}

// True if two types with Handle() have different handles.
template <class T, std::enable_if_t<HasHandleV<T>, int> = 0>
inline bool operator!=(T const &left, T const &right) noexcept {
return !(left.Handle() == right.Handle());
}

// True if handle of left is null.
template <class T, std::enable_if_t<HasHandleV<T>, int> = 0>
inline bool operator==(T const &left, std::nullptr_t) noexcept {
return !static_cast<bool>(left.Handle());
}

// True if handle of left is not null.
template <class T, std::enable_if_t<HasHandleV<T>, int> = 0>
inline bool operator!=(T const &left, std::nullptr_t) noexcept {
return static_cast<bool>(left.Handle());
}

// True if handle of right is null.
template <class T, std::enable_if_t<HasHandleV<T>, int> = 0>
inline bool operator==(std::nullptr_t, T const &right) noexcept {
return !static_cast<bool>(right.Handle());
}

// True if handle of left is not null.
template <class T, std::enable_if_t<HasHandleV<T>, int> = 0>
inline bool operator!=(std::nullptr_t, T const &right) noexcept {
return static_cast<bool>(right.Handle());
}

} // namespace winrt::Microsoft::ReactNative

#endif // MICROSOFT_REACTNATIVE_REACTHANDLEHELPER
Loading