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": "none",
"comment": "Added new unit test projects to ReactWindows-Universal solution.",
"packageName": "react-native-windows",
"email": "vmorozov@microsoft.com",
"commit": "dac50d48f1dc58362e90084646d20bbffa003429",
"date": "2019-12-14T03:51:32.037Z"
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{6c60e295-c8ca-4dc5-b8be-09888f58b249}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>Microsoft_ReactNative_Cxx_UnitTests</RootNamespace>
<RootNamespace>Microsoft.ReactNative</RootNamespace>
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.18362.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
<WindowsTargetPlatformMinVersion>10.0.15063.0</WindowsTargetPlatformMinVersion>
Copy link

Choose a reason for hiding this comment

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

15063 [](start = 42, length = 5)

why is there a decrease in versions?

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 is a minimal supported version of WIndows. We must support 15063.0 in order to have C++/WinRT projects load .Net assemblies. In this test project it was not needed, but I want to make sure that tests are compiled with the same settings as other projects.

<CppWinRTNamespaceMergeDepth>2</CppWinRTNamespaceMergeDepth>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(ReactNativeWindowsDir)PropertySheets\React.Cpp.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
Expand Down Expand Up @@ -67,22 +69,21 @@
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
<PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level4</WarningLevel>
<AdditionalOptions>%(AdditionalOptions) /permissive- /bigobj</AdditionalOptions>
<AdditionalOptions>/await %(AdditionalOptions) /permissive- /bigobj</AdditionalOptions>
</ClCompile>
<Midl>
<AdditionalIncludeDirectories>$(ReactNativeWindowsDir)Microsoft.ReactNative;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</Midl>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
</Link>
<Midl>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\git\vmoroz\react-native-windows\vnext\Microsoft.ReactNative;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</Midl>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
<ClCompile>
Expand Down Expand Up @@ -131,13 +132,13 @@
</Text>
</ItemGroup>
<ItemGroup>
<Midl Include="..\Microsoft.ReactNative\IBoxedValue.idl" />
<Midl Include="..\Microsoft.ReactNative\IJSValueReader.idl" />
<Midl Include="..\Microsoft.ReactNative\IJSValueWriter.idl" />
<Midl Include="..\Microsoft.ReactNative\IReactContext.idl" />
<Midl Include="..\Microsoft.ReactNative\IReactModuleBuilder.idl" />
<Midl Include="..\Microsoft.ReactNative\IReactPackageBuilder.idl" />
<Midl Include="..\Microsoft.ReactNative\IViewManager.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IBoxedValue.idl" />
<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\IReactModuleBuilder.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IReactPackageBuilder.idl" />
<Midl Include="$(ReactNativeWindowsDir)Microsoft.ReactNative\IViewManager.idl" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
Expand Down
2 changes: 1 addition & 1 deletion vnext/Microsoft.ReactNative.Cxx.UnitTests/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"

int main(int argc, char *argv[]) {
int __cdecl main(int argc, char *argv[]) {
winrt::init_apartment();
return Catch::Session().run(argc, argv);
}
3 changes: 3 additions & 0 deletions vnext/Microsoft.ReactNative.Cxx/JSValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ namespace winrt::Microsoft::ReactNative::Bridge {
/*static*/ const JSValueArray JSValue::EmptyArray;
/*static*/ const std::string JSValue::EmptyString;

#pragma warning(push)
#pragma warning(disable : 26495) // False positive for union member not initialized
JSValue::JSValue(JSValue &&other) noexcept : m_type{other.m_type} {
switch (m_type) {
case JSValueType::Object:
Expand All @@ -40,6 +42,7 @@ JSValue::JSValue(JSValue &&other) noexcept : m_type{other.m_type} {
other.m_type = JSValueType::Null;
other.m_int64 = 0;
}
#pragma warning(pop)

JSValue &JSValue::operator=(JSValue &&other) noexcept {
if (this != &other) {
Expand Down
3 changes: 3 additions & 0 deletions vnext/Microsoft.ReactNative.Cxx/JSValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ inline auto JSValueArrayView::end() const noexcept {
// JSValue inline implementation
//===========================================================================

#pragma warning(push)
#pragma warning(disable : 26495) // False positive for union member not initialized
inline JSValue::JSValue() noexcept : m_type{JSValueType::Null}, m_int64{0} {}
inline JSValue::JSValue(std::nullptr_t) noexcept : m_type{JSValueType::Null}, m_int64{0} {}
inline JSValue::JSValue(JSValueObject &&value) noexcept : m_type{JSValueType::Object}, m_object{std::move(value)} {}
Expand All @@ -179,6 +181,7 @@ inline JSValue::JSValue(TBool value) noexcept : m_type{JSValueType::Boolean}, m_
template <class TInt, std::enable_if_t<std::is_integral_v<TInt> && !std::is_same_v<TInt, bool>, int>>
inline JSValue::JSValue(TInt value) noexcept : m_type{JSValueType::Int64}, m_int64{static_cast<int64_t>(value)} {}
inline JSValue::JSValue(double value) noexcept : m_type{JSValueType::Double}, m_double{value} {}
#pragma warning(pop)

inline JSValueType JSValue::Type() const noexcept {
return m_type;
Expand Down
29 changes: 24 additions & 5 deletions vnext/Microsoft.ReactNative.Cxx/JSValueReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ T ReadValue(IJSValueReader const &reader) noexcept;
template <class T>
T ReadValue(const JSValue &jsValue) noexcept;

template <class T>
void SkipValue(IJSValueReader const &reader) noexcept;
template <class T>
void SkipValue(const JSValue &jsValue) noexcept;

template <class T, class TJSValueReader, std::enable_if_t<std::is_same_v<TJSValueReader, IJSValueReader>, int> = 1>
void ReadValue(TJSValueReader const &reader, /*out*/ T &value) noexcept;

Expand All @@ -60,11 +65,11 @@ template <class T, std::enable_if_t<std::is_enum_v<T>, int> = 1>
void ReadValue(IJSValueReader const &reader, /*out*/ T &value) noexcept;
template <class T>
void ReadValue(IJSValueReader const &reader, /*out*/ std::optional<T> &value) noexcept;
template <class T, class TCompare = std::less<>, class TAlloc = std::allocator<pair<const std::string, T>>>
template <class T, class TCompare = std::less<>, class TAlloc = std::allocator<std::pair<const std::string, T>>>
void ReadValue(IJSValueReader const &reader, /*out*/ std::map<std::string, T, TCompare, TAlloc> &value) noexcept;
template <class T, class TCompare = std::less<>, class TAlloc = std::allocator<pair<const std::string, T>>>
template <class T, class TCompare = std::less<>, class TAlloc = std::allocator<std::pair<const std::string, T>>>
void ReadValue(IJSValueReader const &reader, /*out*/ std::map<std::wstring, T, TCompare, TAlloc> &value) noexcept;
template <class T, class TAlloc = allocator<T>>
template <class T, class TAlloc = std::allocator<T>>
void ReadValue(IJSValueReader const &reader, /*out*/ std::vector<T, TAlloc> &value) noexcept;
template <class... Ts>
void ReadValue(IJSValueReader const &reader, /*out*/ std::tuple<Ts...> &value) noexcept;
Expand Down Expand Up @@ -100,6 +105,20 @@ inline T ReadValue(const JSValue &jsValue) noexcept {
return result;
}

// Call ReadValue for IJSValueReader and ignore result.
template <class T>
inline void SkipValue(IJSValueReader const &reader) noexcept {
T result;
ReadValue(reader, /*out*/ result);
}

// Call ReadValue for JSValue and ignore result.
template <class T>
inline void SkipValue(const JSValue &jsValue) noexcept {
T result;
ReadValue(jsValue, /*out*/ result);
}

// Try to call ReadValue for JSValue unless it is already called us with TypeWrapper parameter.
template <class T, class TJSValueReader, std::enable_if_t<std::is_same_v<TJSValueReader, IJSValueReader>, int>>
inline void ReadValue(TJSValueReader const &reader, /*out*/ T &value) noexcept {
Expand Down Expand Up @@ -385,7 +404,7 @@ inline void ReadValue(IJSValueReader const &reader, /*out*/ T &value) noexcept {
if (it != fieldMap.end()) {
it->second.ReadField(reader, &value);
} else {
ReadValue<JSValue>(reader); // Skip this property
SkipValue<JSValue>(reader); // Skip this property
}
}
}
Expand All @@ -394,7 +413,7 @@ inline void ReadValue(IJSValueReader const &reader, /*out*/ T &value) noexcept {
// It helps to read arguments from an array if there are more items than expected.
inline bool SkipArrayToEnd(IJSValueReader const &reader) noexcept {
while (reader.GetNextArrayItem()) {
ReadValue<JSValue>(reader); // Read and ignore the value
SkipValue<JSValue>(reader); // Read and ignore the value
}

return true;
Expand Down
6 changes: 3 additions & 3 deletions vnext/Microsoft.ReactNative.Cxx/JSValueWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ template <class T, std::enable_if_t<std::is_enum_v<T>, int> = 1>
void WriteValue(IJSValueWriter const &writer, T const &value) noexcept;
template <class T>
void WriteValue(IJSValueWriter const &writer, std::optional<T> const &value) noexcept;
template <class T, class TCompare = std::less<>, class TAlloc = std::allocator<pair<const std::string, T>>>
template <class T, class TCompare = std::less<>, class TAlloc = std::allocator<std::pair<const std::string, T>>>
void WriteValue(IJSValueWriter const &writer, std::map<std::string, T, TCompare, TAlloc> const &value) noexcept;
template <class T, class TCompare = std::less<>, class TAlloc = std::allocator<pair<const std::string, T>>>
template <class T, class TCompare = std::less<>, class TAlloc = std::allocator<std::pair<const std::string, T>>>
void WriteValue(IJSValueWriter const &writer, std::map<std::wstring, T, TCompare, TAlloc> const &value) noexcept;
template <class T, class TAlloc = allocator<T>>
template <class T, class TAlloc = std::allocator<T>>
void WriteValue(IJSValueWriter const &writer, std::vector<T, TAlloc> const &value) noexcept;
template <class... Ts>
void WriteValue(IJSValueWriter const &writer, std::tuple<Ts...> const &value) noexcept;
Expand Down
9 changes: 6 additions & 3 deletions vnext/Microsoft.ReactNative.Cxx/NativeModules.h
Original file line number Diff line number Diff line change
Expand Up @@ -719,14 +719,17 @@ struct BoxedValue : implements<BoxedValue<T>, IBoxedValue> {
return reinterpret_cast<int64_t>(&m_value);
}

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

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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public static void WriteValue(this IJSValueWriter writer, RobotModel value)
// Reading discriminating union requires using JSValue.
public static void ReadValue(this JSValue jsValue, out OneOf2<T2Extra, R2D2Extra> value)
{
value = default;
value = default(OneOf2<T2Extra, R2D2Extra>);
if (jsValue.TryGetObjectProperty("Kind", out JSValue kind))
{
RobotModel modelType = kind.ReadValue<RobotModel>();
Expand Down
6 changes: 3 additions & 3 deletions vnext/Microsoft.ReactNative.SharedManaged/JSValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,12 @@ public bool TryGetObjectProperty(string propertyName, out JSValue value)
return false;
}

public static bool operator ==(in JSValue lhs, in JSValue rhs)
public static bool operator ==(JSValue lhs, JSValue rhs)
{
return lhs.ValueEquals(rhs);
}

public static bool operator !=(in JSValue lhs, in JSValue rhs)
public static bool operator !=(JSValue lhs, JSValue rhs)
{
return !lhs.ValueEquals(rhs);
}
Expand All @@ -112,7 +112,7 @@ public bool Equals(JSValue other)
return ValueEquals(other);
}

private bool ValueEquals(in JSValue other)
private bool ValueEquals(JSValue other)
{
if (Type == other.Type)
{
Expand Down
4 changes: 2 additions & 2 deletions vnext/Microsoft.ReactNative.SharedManaged/JSValueGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -413,10 +413,10 @@ public static Expression SetProperty(this Expression instance, PropertyInfo prop
return Assign(Property(propertyInfo.GetSetMethod().IsStatic ? null : instance, propertyInfo), value);
}

public static TDelegate CompileLambda<TDelegate>(params object[] expressions) where TDelegate : Delegate
public static TDelegate CompileLambda<TDelegate>(params object[] expressions) /*TODO: add in C# v7.3: where TDelegate : Delegate*/
{
var typeWrapper = new TypeWrapper(typeof(TDelegate));
return (TDelegate)typeWrapper.CompileLambda(expressions);
return (TDelegate)(object)typeWrapper.CompileLambda(expressions);
}

public static VariableWrapper[] MethodArgs(
Expand Down
Loading