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": "Fixed ReactContext copy/move semantic",
"packageName": "react-native-windows",
"email": "[email protected]",
"dependentChangeType": "patch",
"date": "2020-05-11T18:06:42.425Z"
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ReactContextTest.cpp" />
<ClCompile Include="ReactModuleBuilderMock.cpp" />
<ClCompile Include="TurboModuleTest.cpp" />
</ItemGroup>
Expand Down
113 changes: 113 additions & 0 deletions vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactContextTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#include "pch.h"
#include <ReactContext.h>
#include "ReactModuleBuilderMock.h"

using namespace winrt::Microsoft::ReactNative;

struct ReactContextStub : implements<ReactContextStub, IReactContext> {
IReactPropertyBag Properties() noexcept {
VerifyElseCrashSz(false, "Not implemented");
}

void DispatchEvent(
xaml::FrameworkElement const & /*view*/,
hstring const & /*eventName*/,
JSValueArgWriter const & /*eventDataArgWriter*/) noexcept {
VerifyElseCrashSz(false, "Not implemented");
}

void CallJSFunction(
hstring const & /*moduleName*/,
hstring const & /*functionName*/,
JSValueArgWriter const & /*paramsArgWriter*/) noexcept {
VerifyElseCrashSz(false, "Not implemented");
}

void EmitJSEvent(
hstring const & /*eventEmitterName*/,
hstring const & /*eventName*/,
JSValueArgWriter const & /*paramsArgWriter*/) noexcept {
VerifyElseCrashSz(false, "Not implemented");
}
};

namespace ReactNativeTests {

TEST_CLASS (ReactContextTest) {
TEST_METHOD(Test_ctor_Default) {
ReactContext context;
TestCheck(!context);
}

TEST_METHOD(Test_ctor_IReactContext) {
auto reactContextMock = winrt::make<ReactContextStub>();
ReactContext context{reactContextMock};
TestCheck(context);
}

TEST_METHOD(Test_ctor_copy) {
auto reactContextMock = winrt::make<ReactContextStub>();
ReactContext context1{reactContextMock};
ReactContext context2{context1};
TestCheck(context1);
TestCheck(context2);
TestCheckEqual(context1, context2);
}

TEST_METHOD(Test_ctor_move) {
auto reactContextMock = winrt::make<ReactContextStub>();
ReactContext context1{reactContextMock};
ReactContext context2{std::move(context1)};
TestCheck(!context1);
TestCheck(context2);
}

TEST_METHOD(Test_assign_nullptr) {
ReactContext context;
context = nullptr;
TestCheck(!context);
}

TEST_METHOD(Test_assign_copy) {
auto reactContextMock = winrt::make<ReactContextStub>();
ReactContext context1{reactContextMock};
ReactContext context2;
context2 = context1;
TestCheck(context1);
TestCheck(context2);
TestCheckEqual(context1, context2);
}

TEST_METHOD(Test_assign_move) {
auto reactContextMock = winrt::make<ReactContextStub>();
ReactContext context1{reactContextMock};
ReactContext context2;
context2 = std::move(context1);
TestCheck(!context1);
TestCheck(context2);
}

TEST_METHOD(Test_compare) {
auto reactContextMock1 = winrt::make<ReactContextStub>();
auto reactContextMock2 = winrt::make<ReactContextStub>();
ReactContext context11{reactContextMock1};
ReactContext context12{context11};
ReactContext context2{reactContextMock2};
ReactContext context3;
TestCheck(context11 == context12);
TestCheck(context12 == context11);
TestCheck(context11 != context2);
TestCheck(context11 != context3);
TestCheck(context2 != context11);
TestCheck(context3 != context11);
TestCheck(context3 == nullptr);
TestCheck(nullptr == context3);
TestCheck(context11 != nullptr);
TestCheck(nullptr != context11);
}
};

} // namespace ReactNativeTests
3 changes: 2 additions & 1 deletion vnext/Microsoft.ReactNative.Cxx/JSValueWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
#ifndef MICROSOFT_REACTNATIVE_JSVALUEWRITER
#define MICROSOFT_REACTNATIVE_JSVALUEWRITER

#include <winrt/Microsoft.ReactNative.h>
#include "JSValue.h"
#include "StructInfo.h"
#include "winrt/Microsoft.ReactNative.h"

namespace winrt::Microsoft::ReactNative {

Expand Down
28 changes: 27 additions & 1 deletion vnext/Microsoft.ReactNative.Cxx/ReactContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ namespace winrt::Microsoft::ReactNative {
// It wraps up the IReactContext and adds convenience methods for
// working with C++ types.
struct ReactContext {
ReactContext(std::nullptr_t = nullptr) noexcept {}

ReactContext(IReactContext const &handle) noexcept : m_handle{handle} {}

IReactContext const &Handle() const noexcept {
Expand Down Expand Up @@ -66,8 +68,32 @@ struct ReactContext {
m_handle.DispatchEvent(view, eventName, paramsArgWriter);
}

friend bool operator==(ReactContext const &left, ReactContext const &right) noexcept {
return left.m_handle == right.m_handle;
}

friend bool operator!=(ReactContext const &left, ReactContext const &right) noexcept {
return left.m_handle != right.m_handle;
}

friend bool operator==(ReactContext const &left, std::nullptr_t) noexcept {
return !static_cast<bool>(left.m_handle);
}

friend bool operator!=(ReactContext const &left, std::nullptr_t) noexcept {
return static_cast<bool>(left.m_handle);
}

friend bool operator==(std::nullptr_t, ReactContext const &right) noexcept {
return !static_cast<bool>(right.m_handle);
}

friend bool operator!=(std::nullptr_t, ReactContext const &right) noexcept {
return static_cast<bool>(right.m_handle);
}

private:
const IReactContext m_handle;
IReactContext m_handle;
};

} // namespace winrt::Microsoft::ReactNative
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "pch.h"

#include <NativeModules.h>

using namespace React;

namespace ReactNativeIntegrationTests {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,6 @@ TEST_CLASS (ReactPropertyBagTests) {
}

TEST_METHOD(PropertyBag_Property_string) {
// We only support enums defined in IDL.
ReactPropertyId<hstring> fooName{L"Foo"};
ReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()};

Expand All @@ -504,6 +503,25 @@ TEST_CLASS (ReactPropertyBagTests) {
pb.Remove(fooName);
TestCheck(!pb.Get(fooName));
}

TEST_METHOD(PropertyBag_Property_delegate) {
ReactPropertyId<ReactCreatePropertyValue> fooName{L"Foo"};
ReactPropertyBag pb{ReactPropertyBagHelper::CreatePropertyBag()};

TestCheck(!pb.Get(fooName));
ReactCreatePropertyValue createValue1 = []() { return winrt::box_value(5); };
TestCheckEqual(createValue1, *pb.GetOrCreate(fooName, [&createValue1]() { return createValue1; }));
TestCheckEqual(createValue1, *pb.Get(fooName));
TestCheckEqual(5, winrt::unbox_value<int>((*pb.Get(fooName))()));

ReactCreatePropertyValue createValue2 = []() { return winrt::box_value(10); };
pb.Set(fooName, createValue2);
TestCheckEqual(createValue2, *pb.Get(fooName));
TestCheckEqual(10, winrt::unbox_value<int>((*pb.Get(fooName))()));
TestCheck(createValue1 != *pb.Get(fooName));
pb.Remove(fooName);
TestCheck(!pb.Get(fooName));
}
};

} // namespace ReactNativeIntegrationTests
1 change: 0 additions & 1 deletion vnext/Microsoft.ReactNative.IntegrationTests/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#define NOMINMAX

#include <future>
#include "NativeModules.h"
#include "functional/functor.h"
#include "motifCpp/testCheck.h"

Expand Down