Skip to content

Strongly typed value serialization and deserialization using IJSValueReader, JSValue, and IJSValueWriter #3760

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
3 commits merged into from
Dec 11, 2019
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": "Strongly typed value serialization and deserialization using IJSValueReader, JSValue, and IJSValueWriter",
"packageName": "react-native-windows",
"email": "vmorozov@microsoft.com",
"commit": "d7599a1fbbb88300ccd2b3e280b74fda9f41f061",
"date": "2019-12-11T20:44:46.143Z"
}
15 changes: 10 additions & 5 deletions packages/microsoft-reactnative-sampleapps/index.windows.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ var getCallback = function(prefix) {
};
};

var getErrorCallback = function(prefix) {
return function(error) {
log(prefix + (error || {}).message);
Copy link
Contributor

@NickGerleman NickGerleman Dec 11, 2019

Choose a reason for hiding this comment

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

|| {} [](start = 24, length = 5)

What is the motivation for this change? #Resolved

Copy link
Member Author

@vmoroz vmoroz Dec 11, 2019

Choose a reason for hiding this comment

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

The error object has a member 'message' the ||{} technique is used to ensure that we do not crash should the error be null. #Resolved

};
};

class SampleApp extends Component {
componentDidMount() {
this._TimedEventCSSub = SampleModuleCSEmitter.addListener('TimedEventCS', getCallback('SampleModuleCS.TimedEventCS() => '));
Expand Down Expand Up @@ -77,10 +83,10 @@ class SampleApp extends Component {
NativeModules.SampleModuleCS.ExplicitCallbackMethodWithArgs(numberArg, getCallback('SampleModuleCS.ExplicitCallbackMethodWithArgs => '));

var promise1 = NativeModules.SampleModuleCS.ExplicitPromiseMethod();
promise1.then(getCallback('SampleModuleCS.ExplicitPromiseMethod then => ')).catch(getCallback('SampleModuleCS.ExplicitPromiseMethod catch => '));
promise1.then(getCallback('SampleModuleCS.ExplicitPromiseMethod then => ')).catch(getErrorCallback('SampleModuleCS.ExplicitPromiseMethod catch => '));

var promise2 = NativeModules.SampleModuleCS.ExplicitPromiseMethodWithArgs(numberArg);
promise2.then(getCallback('SampleModuleCS.ExplicitPromiseMethodWithArgs then => ')).catch(getCallback('SampleModuleCS.ExplicitPromiseMethodWithArgs catch => '));
promise2.then(getCallback('SampleModuleCS.ExplicitPromiseMethodWithArgs then => ')).catch(getErrorCallback('SampleModuleCS.ExplicitPromiseMethodWithArgs catch => '));

log('SampleModuleCS.SyncReturnMethod => ' + NativeModules.SampleModuleCS.SyncReturnMethod());

Expand Down Expand Up @@ -115,10 +121,10 @@ class SampleApp extends Component {
NativeModules.SampleModuleCPP.ExplicitCallbackMethodWithArgs(numberArg, getCallback('SampleModuleCPP.ExplicitCallbackMethodWithArgs => '));

var promise1 = NativeModules.SampleModuleCPP.ExplicitPromiseMethod();
promise1.then(getCallback('SampleModuleCPP.ExplicitPromiseMethod then => ')).catch(getCallback('SampleModuleCPP.ExplicitPromiseMethod catch => '));
promise1.then(getCallback('SampleModuleCPP.ExplicitPromiseMethod then => ')).catch(getErrorCallback('SampleModuleCPP.ExplicitPromiseMethod catch => '));

var promise2 = NativeModules.SampleModuleCPP.ExplicitPromiseMethodWithArgs(numberArg);
promise2.then(getCallback('SampleModuleCPP.ExplicitPromiseMethodWithArgs then => ')).catch(getCallback('SampleModuleCPP.ExplicitPromiseMethodWithArgs catch => '));
promise2.then(getCallback('SampleModuleCPP.ExplicitPromiseMethodWithArgs then => ')).catch(getErrorCallback('SampleModuleCPP.ExplicitPromiseMethodWithArgs catch => '));

log('SampleModuleCPP.SyncReturnMethod => ' + NativeModules.SampleModuleCPP.SyncReturnMethod());

Expand Down Expand Up @@ -191,7 +197,6 @@ class SampleApp extends Component {
<Text style={styles.boxText}>CircleCPP!</Text>
</View>
</CircleCPP>

<Text style={styles.instructions}>
Hello from Microsoft!
</Text>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

#include "DebugConsole.h"

using namespace Microsoft::ReactNative;
using namespace winrt::Microsoft::ReactNative::Bridge;

namespace winrt::SampleApp::implementation {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,14 @@
<ItemGroup>
<AppxManifest Include="Package.appxmanifest" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Filter Include="Assets">
<UniqueIdentifier>{e48dc53e-40b1-40cb-970a-f89935452892}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="PropertySheet.props" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Text Include="readme.txt" />
Expand Down
72 changes: 72 additions & 0 deletions packages/microsoft-reactnative-sampleapps/windows/SampleApps.sln

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ FrameworkElement CircleViewManagerCPP::CreateView() noexcept {

// IViewManagerWithChildren

void CircleViewManagerCPP::AddView(FrameworkElement const &parent, UIElement const &child, int64_t index) noexcept {
void CircleViewManagerCPP::AddView(FrameworkElement const &parent, UIElement const &child, int64_t /*index*/) noexcept {
Copy link
Contributor

@NickGerleman NickGerleman Dec 11, 2019

Choose a reason for hiding this comment

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

Did you add this change as part of this PR? If so, could we separate the unrelated changes out? If not I think your branch might be in a weird state. #Resolved

Copy link
Member Author

@vmoroz vmoroz Dec 11, 2019

Choose a reason for hiding this comment

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

I have eliminated a warning caused by the unused variable. My branch is in a good state. #Resolved

if (auto const &border = parent.try_as<Border>()) {
border.Child(child);
}
Expand All @@ -50,15 +50,15 @@ void CircleViewManagerCPP::RemoveAllChildren(FrameworkElement const &parent) noe
}
}

void CircleViewManagerCPP::RemoveChildAt(FrameworkElement const &parent, int64_t index) noexcept {
void CircleViewManagerCPP::RemoveChildAt(FrameworkElement const &parent, int64_t /*index*/) noexcept {
if (auto const &border = parent.try_as<Border>()) {
border.Child(nullptr);
}
}

void CircleViewManagerCPP::ReplaceChild(
FrameworkElement const &parent,
UIElement const &oldChild,
UIElement const & /*oldChild*/,
UIElement const &newChild) noexcept {
if (auto const &border = parent.try_as<Border>()) {
border.Child(newChild);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ struct HeightToCornerRadiusConverter

winrt::Windows::Foundation::IInspectable Convert(
winrt::Windows::Foundation::IInspectable const &value,
winrt::Windows::UI::Xaml::Interop::TypeName const &targetType,
winrt::Windows::Foundation::IInspectable const &parameter,
winrt::hstring const &language) noexcept {
winrt::Windows::UI::Xaml::Interop::TypeName const & /*targetType*/,
winrt::Windows::Foundation::IInspectable const & /*parameter*/,
winrt::hstring const & /*language*/) noexcept {
double d = winrt::unbox_value<double>(value);

if (isnan(d)) {
Expand All @@ -54,9 +54,9 @@ struct HeightToCornerRadiusConverter

winrt::Windows::Foundation::IInspectable ConvertBack(
winrt::Windows::Foundation::IInspectable const &value,
winrt::Windows::UI::Xaml::Interop::TypeName const &targetType,
winrt::Windows::Foundation::IInspectable const &parameter,
winrt::hstring const &language) noexcept {
winrt::Windows::UI::Xaml::Interop::TypeName const & /*targetType*/,
winrt::Windows::Foundation::IInspectable const & /*parameter*/,
winrt::hstring const & /*language*/) noexcept {
return value;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include "SampleModuleCPP.h"

using namespace winrt::Microsoft::ReactNative::Bridge;
using namespace Microsoft::ReactNative;

namespace winrt::SampleLibraryCPP::implementation {

Expand All @@ -21,8 +20,9 @@ void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuil
packageBuilder.AddViewManager(L"CustomUserControlViewManagerCPP", [](IReactContext const &reactContext) {
return winrt::make<CustomUserControlViewManagerCPP>(reactContext);
});
packageBuilder.AddViewManager(
L"CircleViewManagerCPP", [](IReactContext const &reactContext) { return winrt::make<CircleViewManagerCPP>(); });
packageBuilder.AddViewManager(L"CircleViewManagerCPP", [](IReactContext const & /*reactContext*/) {
return winrt::make<CircleViewManagerCPP>();
});
}

} // namespace winrt::SampleLibraryCPP::implementation
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.props')" />
<Import Project="$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="Globals">
<CppWinRTOptimized>true</CppWinRTOptimized>
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
Expand Down Expand Up @@ -158,13 +158,13 @@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.190730.2\build\native\Microsoft.Windows.CppWinRT.targets'))" />
</Target>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ struct SampleModuleCPP {
const std::string StringConstant = "Hello World";

REACT_CONSTANT_PROVIDER(ConstantsViaConstantsProvider)
void ConstantsViaConstantsProvider(const winrt::Microsoft::ReactNative::Bridge::IJSValueWriter &writer) noexcept {
::Microsoft::ReactNative::WriteProperty(writer, "NumberConstantViaProvider", M_PI);
::Microsoft::ReactNative::WriteProperty(writer, "StringConstantViaProvider", "Hello World");
void ConstantsViaConstantsProvider(ReactConstantProvider &constants) noexcept {
constants.Add(L"NumberConstantViaProvider", M_PI);
constants.Add(L"StringConstantViaProvider", "Hello World");
}

#pragma endregion
Expand Down Expand Up @@ -77,27 +77,24 @@ struct SampleModuleCPP {
}

REACT_METHOD(ExplicitPromiseMethod);
void ExplicitPromiseMethod(
std::function<void(double)> &&resolve,
std::function<void(std::string)> &&reject) noexcept {
void ExplicitPromiseMethod(winrt::Microsoft::ReactNative::Bridge::ReactPromise<double> &&result) noexcept {
DebugWriteLine(Name, "ExplicitPromiseMethod");
try {
resolve(M_PI);
result.Resolve(M_PI);
} catch (const std::exception &ex) {
reject(ex.what());
result.Reject(ex.what());
}
}

REACT_METHOD(ExplicitPromiseMethodWithArgs);
void ExplicitPromiseMethodWithArgs(
double arg,
std::function<void(double)> &&resolve,
std::function<void(std::string)> &&reject) noexcept {
winrt::Microsoft::ReactNative::Bridge::ReactPromise<double> &&result) noexcept {
DebugWriteLine(Name, "ExplicitPromiseMethodWithArgs", arg);
try {
resolve(M_PI);
result.Resolve(M_PI);
} catch (const std::exception &ex) {
reject(ex.what());
result.Reject(ex.what());
}
}

Expand All @@ -121,7 +118,7 @@ struct SampleModuleCPP {

#pragma region Events

REACT_EVENT(TimedEvent, "TimedEventCPP");
REACT_EVENT(TimedEvent, L"TimedEventCPP");
std::function<void(int)> TimedEvent;

#pragma endregion
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Microsoft.ReactNative.Managed;
using System;
using System.Collections.Generic;
using System.Diagnostics;

using Windows.System.Threading;

using Microsoft.ReactNative.Bridge;
using Microsoft.ReactNative.Managed;

namespace SampleLibraryCS
{
// Sample ReactModule
Expand Down Expand Up @@ -83,32 +79,32 @@ public void ExplicitCallbackMethodWithArgs(double arg, ReactCallback<double> cal
}

[ReactMethod]
public void ExplicitPromiseMethod(ReactCallback<double> resolve, ReactCallback<string> reject)
public void ExplicitPromiseMethod(IReactPromise<double> result)
{
Debug.WriteLine($"{Name}.{nameof(ExplicitPromiseMethod)}()");

try
{
resolve(Math.PI);
result.Resolve(Math.PI);
}
catch (Exception ex)
{
reject(ex.Message);
result.Reject(new ReactError { Message = ex.Message });
}
}

[ReactMethod]
public void ExplicitPromiseMethodWithArgs(double arg, ReactCallback<double> resolve, ReactCallback<string> reject)
public void ExplicitPromiseMethodWithArgs(double arg, IReactPromise<double> result)
{
Debug.WriteLine($"{Name}.{nameof(ExplicitPromiseMethodWithArgs)}({arg})");

try
{
resolve(Math.PI);
result.Resolve(Math.PI);
}
catch (Exception ex)
{
reject(ex.Message);
result.Reject(new ReactError { Message = ex.Message });
}
}

Expand Down
8 changes: 4 additions & 4 deletions vnext/Desktop.Test.DLL/React.Windows.Desktop.Test.DLL.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,15 @@
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\boost.1.68.0.0\build\boost.targets" Condition="Exists('..\packages\boost.1.68.0.0\build\boost.targets')" />
<Import Project="..\packages\ReactWindows.OpenSSL.StdCall.Static.1.0.2-p.2\build\native\ReactWindows.OpenSSL.StdCall.Static.targets" Condition="Exists('..\packages\ReactWindows.OpenSSL.StdCall.Static.1.0.2-p.2\build\native\ReactWindows.OpenSSL.StdCall.Static.targets')" />
<Import Project="$(SolutionDir)packages\boost.1.68.0.0\build\boost.targets" Condition="Exists('$(SolutionDir)packages\boost.1.68.0.0\build\boost.targets')" />
<Import Project="$(SolutionDir)packages\ReactWindows.OpenSSL.StdCall.Static.1.0.2-p.2\build\native\ReactWindows.OpenSSL.StdCall.Static.targets" Condition="Exists('$(SolutionDir)packages\ReactWindows.OpenSSL.StdCall.Static.1.0.2-p.2\build\native\ReactWindows.OpenSSL.StdCall.Static.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\boost.1.68.0.0\build\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost.1.68.0.0\build\boost.targets'))" />
<Error Condition="!Exists('..\packages\ReactWindows.OpenSSL.StdCall.Static.1.0.2-p.2\build\native\ReactWindows.OpenSSL.StdCall.Static.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\ReactWindows.OpenSSL.StdCall.Static.1.0.2-p.2\build\native\ReactWindows.OpenSSL.StdCall.Static.targets'))" />
<Error Condition="!Exists('$(SolutionDir)packages\boost.1.68.0.0\build\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)packages\boost.1.68.0.0\build\boost.targets'))" />
<Error Condition="!Exists('$(SolutionDir)packages\ReactWindows.OpenSSL.StdCall.Static.1.0.2-p.2\build\native\ReactWindows.OpenSSL.StdCall.Static.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)packages\ReactWindows.OpenSSL.StdCall.Static.1.0.2-p.2\build\native\ReactWindows.OpenSSL.StdCall.Static.targets'))" />
</Target>
<Target Name="GetTargetFileName" Returns="$(OutDir)$(TargetName).dll" />
</Project>
Loading