diff --git a/change/react-native-windows-2020-04-21-06-23-19-MS_CppTurboModules.json b/change/react-native-windows-2020-04-21-06-23-19-MS_CppTurboModules.json
new file mode 100644
index 00000000000..80fe2a4b0ef
--- /dev/null
+++ b/change/react-native-windows-2020-04-21-06-23-19-MS_CppTurboModules.json
@@ -0,0 +1,8 @@
+{
+ "type": "prerelease",
+ "comment": "Implemented C++ TurboModule compile time spec validation",
+ "packageName": "react-native-windows",
+ "email": "vmorozov@microsoft.com",
+ "dependentChangeType": "patch",
+ "date": "2020-04-21T13:23:19.348Z"
+}
\ No newline at end of file
diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj b/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj
index 7959860f16f..352c770761e 100644
--- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj
+++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/Microsoft.ReactNative.Cxx.UnitTests.vcxproj
@@ -112,6 +112,7 @@
+
@@ -126,6 +127,7 @@
Create
+
@@ -157,4 +159,4 @@
-
+
\ No newline at end of file
diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp
index 8edd3933795..84eb534ceda 100644
--- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp
+++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp
@@ -5,24 +5,15 @@
#include "ReactModuleBuilderMock.h"
#include
-#include "NativeModules.h"
+#include "Point.h"
#include "future/futureWait.h"
-namespace winrt::Microsoft::ReactNative {
-
-REACT_STRUCT(Point)
-struct Point {
- REACT_FIELD(X)
- int X;
-
- REACT_FIELD(Y)
- int Y;
-};
+namespace ReactNativeTests {
REACT_MODULE(SimpleNativeModule)
struct SimpleNativeModule {
REACT_INIT(Initialize)
- void Initialize(IReactContext const &context) noexcept {
+ void Initialize(React::IReactContext const &context) noexcept {
IsInitialized = true;
TestCheck(context != nullptr);
@@ -322,46 +313,46 @@ struct SimpleNativeModule {
}
REACT_METHOD(DividePromise)
- void DividePromise(int x, int y, ReactPromise const &result) noexcept {
+ void DividePromise(int x, int y, React::ReactPromise const &result) noexcept {
if (y != 0) {
result.Resolve(x / y);
} else {
- ReactError error{};
+ React::ReactError error{};
error.Message = "Division by 0";
result.Reject(std::move(error));
}
}
REACT_METHOD(NegatePromise)
- void NegatePromise(int x, ReactPromise const &result) noexcept {
+ void NegatePromise(int x, React::ReactPromise const &result) noexcept {
if (x >= 0) {
result.Resolve(-x);
} else {
- ReactError error{};
+ React::ReactError error{};
error.Message = "Already negative";
result.Reject(std::move(error));
}
}
REACT_METHOD(NegateAsyncPromise)
- fire_and_forget NegateAsyncPromise(int x, ReactPromise result) noexcept {
+ fire_and_forget NegateAsyncPromise(int x, React::ReactPromise result) noexcept {
co_await winrt::resume_background();
if (x >= 0) {
result.Resolve(-x);
} else {
- ReactError error{};
+ React::ReactError error{};
error.Message = "Already negative";
result.Reject(std::move(error));
}
}
REACT_METHOD(NegateDispatchQueuePromise)
- void NegateDispatchQueuePromise(int x, ReactPromise const &result) noexcept {
+ void NegateDispatchQueuePromise(int x, React::ReactPromise const &result) noexcept {
Mso::DispatchQueue::ConcurrentQueue().Post([ x, result ]() noexcept {
if (x >= 0) {
result.Resolve(-x);
} else {
- ReactError error{};
+ React::ReactError error{};
error.Message = "Already negative";
result.Reject(std::move(error));
}
@@ -369,12 +360,12 @@ struct SimpleNativeModule {
}
REACT_METHOD(NegateFuturePromise)
- void NegateFuturePromise(int x, ReactPromise const &result) noexcept {
+ void NegateFuturePromise(int x, React::ReactPromise const &result) noexcept {
Mso::PostFuture([ x, result ]() noexcept {
if (x >= 0) {
result.Resolve(-x);
} else {
- ReactError error{};
+ React::ReactError error{};
error.Message = "Already negative";
result.Reject(std::move(error));
}
@@ -383,7 +374,7 @@ struct SimpleNativeModule {
// Each macro has second optional parameter: JS name.
REACT_METHOD(VoidPromise, L"voidPromise")
- void VoidPromise(int x, ReactPromise const &result) noexcept {
+ void VoidPromise(int x, React::ReactPromise const &result) noexcept {
if (x % 2 == 0) {
result.Resolve();
} else {
@@ -392,58 +383,58 @@ struct SimpleNativeModule {
}
REACT_METHOD(ResolveSayHelloPromise)
- void ResolveSayHelloPromise(ReactPromise const &result) noexcept {
+ void ResolveSayHelloPromise(React::ReactPromise const &result) noexcept {
result.Resolve("Hello_4");
}
REACT_METHOD(RejectSayHelloPromise)
- void RejectSayHelloPromise(ReactPromise const &result) noexcept {
- ReactError error{};
+ void RejectSayHelloPromise(React::ReactPromise const &result) noexcept {
+ React::ReactError error{};
error.Message = "Promise rejected";
result.Reject(std::move(error));
}
REACT_METHOD(StaticDividePromise)
- static void StaticDividePromise(int x, int y, ReactPromise const &result) noexcept {
+ static void StaticDividePromise(int x, int y, React::ReactPromise const &result) noexcept {
if (y != 0) {
result.Resolve(x / y);
} else {
- ReactError error{};
+ React::ReactError error{};
error.Message = "Division by 0";
result.Reject(std::move(error));
}
}
REACT_METHOD(StaticNegatePromise)
- static void StaticNegatePromise(int x, ReactPromise const &result) noexcept {
+ static void StaticNegatePromise(int x, React::ReactPromise const &result) noexcept {
if (x >= 0) {
result.Resolve(-x);
} else {
- ReactError error{};
+ React::ReactError error{};
error.Message = "Already negative";
result.Reject(std::move(error));
}
}
REACT_METHOD(StaticNegateAsyncPromise)
- static fire_and_forget StaticNegateAsyncPromise(int x, ReactPromise result) noexcept {
+ static fire_and_forget StaticNegateAsyncPromise(int x, React::ReactPromise result) noexcept {
co_await winrt::resume_background();
if (x >= 0) {
result.Resolve(-x);
} else {
- ReactError error{};
+ React::ReactError error{};
error.Message = "Already negative";
result.Reject(std::move(error));
}
}
REACT_METHOD(StaticNegateDispatchQueuePromise)
- static void StaticNegateDispatchQueuePromise(int x, ReactPromise const &result) noexcept {
+ static void StaticNegateDispatchQueuePromise(int x, React::ReactPromise const &result) noexcept {
Mso::DispatchQueue::ConcurrentQueue().Post([ x, result ]() noexcept {
if (x >= 0) {
result.Resolve(-x);
} else {
- ReactError error{};
+ React::ReactError error{};
error.Message = "Already negative";
result.Reject(std::move(error));
}
@@ -451,12 +442,12 @@ struct SimpleNativeModule {
}
REACT_METHOD(StaticNegateFuturePromise)
- static void StaticNegateFuturePromise(int x, ReactPromise const &result) noexcept {
+ static void StaticNegateFuturePromise(int x, React::ReactPromise const &result) noexcept {
Mso::PostFuture([ x, result ]() noexcept {
if (x >= 0) {
result.Resolve(-x);
} else {
- ReactError error{};
+ React::ReactError error{};
error.Message = "Already negative";
result.Reject(std::move(error));
}
@@ -465,7 +456,7 @@ struct SimpleNativeModule {
// Each macro has second optional parameter: JS name.
REACT_METHOD(StaticVoidPromise, L"staticVoidPromise")
- void StaticVoidPromise(int x, ReactPromise const &result) noexcept {
+ void StaticVoidPromise(int x, React::ReactPromise const &result) noexcept {
if (x % 2 == 0) {
result.Resolve();
} else {
@@ -474,13 +465,13 @@ struct SimpleNativeModule {
}
REACT_METHOD(StaticResolveSayHelloPromise)
- static void StaticResolveSayHelloPromise(ReactPromise const &result) noexcept {
+ static void StaticResolveSayHelloPromise(React::ReactPromise const &result) noexcept {
result.Resolve("Hello_4");
}
REACT_METHOD(StaticRejectSayHelloPromise)
- static void StaticRejectSayHelloPromise(ReactPromise const &result) noexcept {
- ReactError error{};
+ static void StaticRejectSayHelloPromise(React::ReactPromise const &result) noexcept {
+ React::ReactError error{};
error.Message = "Promise rejected";
result.Reject(std::move(error));
}
@@ -528,13 +519,13 @@ struct SimpleNativeModule {
static constexpr Point Constant4{/*X =*/3, /*Y =*/4};
REACT_CONSTANT_PROVIDER(Constant5)
- void Constant5(ReactConstantProvider &provider) noexcept {
+ void Constant5(React::ReactConstantProvider &provider) noexcept {
provider.Add(L"const51", Point{/*X =*/12, /*Y =*/14});
provider.Add(L"const52", "MyConstant52");
}
REACT_CONSTANT_PROVIDER(Constant6)
- static void Constant6(ReactConstantProvider &provider) noexcept {
+ static void Constant6(React::ReactConstantProvider &provider) noexcept {
provider.Add(L"const61", Point{/*X =*/15, /*Y =*/17});
provider.Add(L"const62", "MyConstant62");
}
@@ -560,9 +551,9 @@ struct SimpleNativeModule {
REACT_EVENT(OnStringEvent, L"onStringEvent", L"MyEventEmitter")
std::function OnStringEvent;
- // Use JSValue which is an immutable JSON-like data representation.
+ // Use React::JSValue which is an immutable JSON-like data representation.
REACT_EVENT(OnJSValueEvent)
- std::function OnJSValueEvent;
+ std::function OnJSValueEvent;
// Allows to call JS functions.
REACT_FUNCTION(JSIntFunction)
@@ -585,9 +576,9 @@ struct SimpleNativeModule {
REACT_FUNCTION(JSStringFunction, L"stringFunc", L"MyModule")
std::function JSStringFunction;
- // Use JSValue which is an immutable JSON-like data representation.
+ // Use React::JSValue which is an immutable JSON-like data representation.
REACT_FUNCTION(JSValueFunction)
- std::function JSValueFunction;
+ std::function JSValueFunction;
public: // Used to report some test messages
bool IsInitialized{false};
@@ -598,17 +589,17 @@ struct SimpleNativeModule {
/*static*/ std::string SimpleNativeModule::StaticMessage;
TEST_CLASS (NativeModuleTest) {
- ReactModuleBuilderMock m_builderMock{};
- IReactModuleBuilder m_moduleBuilder;
+ React::ReactModuleBuilderMock m_builderMock{};
+ React::IReactModuleBuilder m_moduleBuilder;
Windows::Foundation::IInspectable m_moduleObject{nullptr};
SimpleNativeModule *m_module;
NativeModuleTest() {
- m_moduleBuilder = make(m_builderMock);
- auto provider = MakeModuleProvider();
+ m_moduleBuilder = winrt::make(m_builderMock);
+ auto provider = React::MakeModuleProvider();
m_moduleObject = m_builderMock.CreateModule(provider, m_moduleBuilder);
- auto reactModule = m_moduleObject.as();
- m_module = &BoxedValue::GetImpl(reactModule);
+ auto reactModule = m_moduleObject.as();
+ m_module = &React::BoxedValue::GetImpl(reactModule);
}
TEST_METHOD(TestMethodCall_Add) {
@@ -644,7 +635,6 @@ TEST_CLASS (NativeModuleTest) {
m_builderMock.Call1(L"StaticSayHello", std::function([
](const std::string &result) noexcept { TestCheck(result == "Hello"); }));
TestCheck(m_builderMock.IsResolveCallbackCalled());
- TestCheck(m_builderMock.IsResolveCallbackCalled());
}
TEST_METHOD(TestMethodCall_SayHello0) {
@@ -1005,8 +995,8 @@ TEST_CLASS (NativeModuleTest) {
m_builderMock.Call2(
L"DividePromise",
std::function([](int result) noexcept { TestCheck(result == 3); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Division by 0"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Division by 0"); }),
6,
2);
TestCheck(m_builderMock.IsResolveCallbackCalled());
@@ -1016,8 +1006,8 @@ TEST_CLASS (NativeModuleTest) {
m_builderMock.Call2(
L"DividePromise",
std::function([](int result) noexcept { TestCheck(result == 3); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Division by 0"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Division by 0"); }),
6,
0);
TestCheck(m_builderMock.IsRejectCallbackCalled());
@@ -1027,8 +1017,8 @@ TEST_CLASS (NativeModuleTest) {
m_builderMock.Call2(
L"NegatePromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
5);
TestCheck(m_builderMock.IsResolveCallbackCalled());
}
@@ -1037,8 +1027,8 @@ TEST_CLASS (NativeModuleTest) {
m_builderMock.Call2(
L"NegatePromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
-5);
TestCheck(m_builderMock.IsRejectCallbackCalled());
}
@@ -1047,8 +1037,8 @@ TEST_CLASS (NativeModuleTest) {
Mso::FutureWait(m_builderMock.Call2(
L"NegateAsyncPromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
5));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}
@@ -1057,8 +1047,8 @@ TEST_CLASS (NativeModuleTest) {
Mso::FutureWait(m_builderMock.Call2(
L"NegateAsyncPromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
-5));
TestCheck(m_builderMock.IsRejectCallbackCalled());
}
@@ -1067,8 +1057,8 @@ TEST_CLASS (NativeModuleTest) {
Mso::FutureWait(m_builderMock.Call2(
L"NegateDispatchQueuePromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
5));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}
@@ -1077,8 +1067,8 @@ TEST_CLASS (NativeModuleTest) {
Mso::FutureWait(m_builderMock.Call2(
L"NegateDispatchQueuePromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
-5));
TestCheck(m_builderMock.IsRejectCallbackCalled());
}
@@ -1087,8 +1077,8 @@ TEST_CLASS (NativeModuleTest) {
Mso::FutureWait(m_builderMock.Call2(
L"NegateFuturePromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
5));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}
@@ -1097,8 +1087,8 @@ TEST_CLASS (NativeModuleTest) {
Mso::FutureWait(m_builderMock.Call2(
L"NegateFuturePromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
-5));
TestCheck(m_builderMock.IsRejectCallbackCalled());
}
@@ -1107,8 +1097,8 @@ TEST_CLASS (NativeModuleTest) {
m_builderMock.Call2(
L"voidPromise",
std::function([]() noexcept {}),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Odd unexpected"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Odd unexpected"); }),
2);
TestCheck(m_builderMock.IsResolveCallbackCalled());
}
@@ -1117,8 +1107,8 @@ TEST_CLASS (NativeModuleTest) {
m_builderMock.Call2(
L"voidPromise",
std::function([]() noexcept {}),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Odd unexpected"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Odd unexpected"); }),
3);
TestCheck(m_builderMock.IsRejectCallbackCalled());
}
@@ -1128,8 +1118,8 @@ TEST_CLASS (NativeModuleTest) {
L"ResolveSayHelloPromise",
std::function(
[](const std::string &result) noexcept { TestCheck(result == "Hello_4"); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Promise rejected"); }));
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Promise rejected"); }));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}
@@ -1138,8 +1128,8 @@ TEST_CLASS (NativeModuleTest) {
L"RejectSayHelloPromise",
std::function(
[](const std::string &result) noexcept { TestCheck(result == "Hello_4"); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Promise rejected"); }));
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Promise rejected"); }));
TestCheck(m_builderMock.IsRejectCallbackCalled());
}
@@ -1147,8 +1137,8 @@ TEST_CLASS (NativeModuleTest) {
m_builderMock.Call2(
L"StaticDividePromise",
std::function([](int result) noexcept { TestCheck(result == 3); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Division by 0"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Division by 0"); }),
6,
2);
TestCheck(m_builderMock.IsResolveCallbackCalled());
@@ -1158,8 +1148,8 @@ TEST_CLASS (NativeModuleTest) {
m_builderMock.Call2(
L"StaticDividePromise",
std::function([](int result) noexcept { TestCheck(result == 3); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Division by 0"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Division by 0"); }),
6,
0);
TestCheck(m_builderMock.IsRejectCallbackCalled());
@@ -1169,8 +1159,8 @@ TEST_CLASS (NativeModuleTest) {
m_builderMock.Call2(
L"StaticNegatePromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
5);
TestCheck(m_builderMock.IsResolveCallbackCalled());
}
@@ -1179,8 +1169,8 @@ TEST_CLASS (NativeModuleTest) {
Mso::FutureWait(m_builderMock.Call2(
L"StaticNegateAsyncPromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
-5));
TestCheck(m_builderMock.IsRejectCallbackCalled());
}
@@ -1189,8 +1179,8 @@ TEST_CLASS (NativeModuleTest) {
Mso::FutureWait(m_builderMock.Call2(
L"StaticNegateAsyncPromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
5));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}
@@ -1199,8 +1189,8 @@ TEST_CLASS (NativeModuleTest) {
m_builderMock.Call2(
L"StaticNegatePromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
-5);
TestCheck(m_builderMock.IsRejectCallbackCalled());
}
@@ -1209,8 +1199,8 @@ TEST_CLASS (NativeModuleTest) {
Mso::FutureWait(m_builderMock.Call2(
L"StaticNegateDispatchQueuePromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
5));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}
@@ -1219,8 +1209,8 @@ TEST_CLASS (NativeModuleTest) {
Mso::FutureWait(m_builderMock.Call2(
L"StaticNegateDispatchQueuePromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
-5));
TestCheck(m_builderMock.IsRejectCallbackCalled());
}
@@ -1229,8 +1219,8 @@ TEST_CLASS (NativeModuleTest) {
Mso::FutureWait(m_builderMock.Call2(
L"StaticNegateFuturePromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
5));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}
@@ -1239,8 +1229,8 @@ TEST_CLASS (NativeModuleTest) {
Mso::FutureWait(m_builderMock.Call2(
L"StaticNegateFuturePromise",
std::function([](int result) noexcept { TestCheck(result == -5); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Already negative"); }),
-5));
TestCheck(m_builderMock.IsRejectCallbackCalled());
}
@@ -1249,8 +1239,8 @@ TEST_CLASS (NativeModuleTest) {
m_builderMock.Call2(
L"staticVoidPromise",
std::function([]() noexcept {}),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Odd unexpected"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Odd unexpected"); }),
2);
TestCheck(m_builderMock.IsResolveCallbackCalled());
}
@@ -1259,8 +1249,8 @@ TEST_CLASS (NativeModuleTest) {
m_builderMock.Call2(
L"staticVoidPromise",
std::function([]() noexcept {}),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Odd unexpected"); }),
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Odd unexpected"); }),
3);
TestCheck(m_builderMock.IsRejectCallbackCalled());
}
@@ -1270,8 +1260,8 @@ TEST_CLASS (NativeModuleTest) {
L"StaticResolveSayHelloPromise",
std::function(
[](const std::string &result) noexcept { TestCheck(result == "Hello_4"); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Promise rejected"); }));
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Promise rejected"); }));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}
@@ -1280,8 +1270,8 @@ TEST_CLASS (NativeModuleTest) {
L"StaticRejectSayHelloPromise",
std::function(
[](const std::string &result) noexcept { TestCheck(result == "Hello_4"); }),
- std::function(
- [](JSValue const &error) noexcept { TestCheck(error["message"] == "Promise rejected"); }));
+ std::function(
+ [](React::JSValue const &error) noexcept { TestCheck(error["message"] == "Promise rejected"); }));
TestCheck(m_builderMock.IsRejectCallbackCalled());
}
@@ -1340,7 +1330,7 @@ TEST_CLASS (NativeModuleTest) {
TEST_METHOD(TestEvent_IntEventField) {
bool eventRaised = false;
m_builderMock.ExpectEvent(
- L"RCTDeviceEventEmitter", L"OnIntEvent", [&eventRaised](JSValueArray const &args) noexcept {
+ L"RCTDeviceEventEmitter", L"OnIntEvent", [&eventRaised](React::JSValueArray const &args) noexcept {
TestCheck(args[0] == 42);
eventRaised = true;
});
@@ -1352,7 +1342,7 @@ TEST_CLASS (NativeModuleTest) {
TEST_METHOD(TestEvent_OnNoArgEventField) {
bool eventRaised = false;
m_builderMock.ExpectEvent(
- L"RCTDeviceEventEmitter", L"OnNoArgEvent", [&eventRaised](JSValueArray const &args) noexcept {
+ L"RCTDeviceEventEmitter", L"OnNoArgEvent", [&eventRaised](React::JSValueArray const &args) noexcept {
TestCheckEqual(0, args.size());
eventRaised = true;
});
@@ -1364,7 +1354,7 @@ TEST_CLASS (NativeModuleTest) {
TEST_METHOD(TestEvent_TwoArgsEventField) {
bool eventRaised = false;
m_builderMock.ExpectEvent(
- L"RCTDeviceEventEmitter", L"OnTwoArgsEvent", [&eventRaised](JSValueArray const &args) noexcept {
+ L"RCTDeviceEventEmitter", L"OnTwoArgsEvent", [&eventRaised](React::JSValueArray const &args) noexcept {
TestCheckEqual(4, args[0]["X"]);
TestCheckEqual(2, args[0]["Y"]);
TestCheckEqual(12, args[1]["X"]);
@@ -1379,7 +1369,7 @@ TEST_CLASS (NativeModuleTest) {
TEST_METHOD(TestEvent_JSNameEventField) {
bool eventRaised = false;
m_builderMock.ExpectEvent(
- L"RCTDeviceEventEmitter", L"onPointEvent", [&eventRaised](JSValueArray const &args) noexcept {
+ L"RCTDeviceEventEmitter", L"onPointEvent", [&eventRaised](React::JSValueArray const &args) noexcept {
TestCheck(args[0]["X"] == 4);
TestCheck(args[0]["Y"] == 2);
eventRaised = true;
@@ -1391,10 +1381,11 @@ TEST_CLASS (NativeModuleTest) {
TEST_METHOD(TestEvent_JSEventEmitterEventField) {
bool eventRaised = false;
- m_builderMock.ExpectEvent(L"MyEventEmitter", L"onStringEvent", [&eventRaised](JSValueArray const &args) noexcept {
- TestCheckEqual("Hello World!", args[0]);
- eventRaised = true;
- });
+ m_builderMock.ExpectEvent(
+ L"MyEventEmitter", L"onStringEvent", [&eventRaised](React::JSValueArray const &args) noexcept {
+ TestCheckEqual("Hello World!", args[0]);
+ eventRaised = true;
+ });
m_module->OnStringEvent("Hello World!");
TestCheck(eventRaised == true);
@@ -1403,20 +1394,20 @@ TEST_CLASS (NativeModuleTest) {
TEST_METHOD(TestEvent_JSValueObjectEventField) {
bool eventRaised = false;
m_builderMock.ExpectEvent(
- L"RCTDeviceEventEmitter", L"OnJSValueEvent", ([&eventRaised](JSValueArray const &args) noexcept {
+ L"RCTDeviceEventEmitter", L"OnJSValueEvent", ([&eventRaised](React::JSValueArray const &args) noexcept {
TestCheck(args[0]["X"] == 4);
TestCheck(args[0]["Y"] == 2);
eventRaised = true;
}));
- m_module->OnJSValueEvent(JSValueObject{{"X", 4}, {"Y", 2}});
+ m_module->OnJSValueEvent(React::JSValueObject{{"X", 4}, {"Y", 2}});
TestCheck(eventRaised == true);
}
TEST_METHOD(TestEvent_JSValueArrayEventField) {
bool eventRaised = false;
m_builderMock.ExpectEvent(
- L"RCTDeviceEventEmitter", L"OnJSValueEvent", ([&eventRaised](JSValueArray const &args) noexcept {
+ L"RCTDeviceEventEmitter", L"OnJSValueEvent", ([&eventRaised](React::JSValueArray const &args) noexcept {
TestCheck(args[0][0] == "X");
TestCheck(args[0][1] == 4);
TestCheck(args[0][2] == true);
@@ -1424,26 +1415,26 @@ TEST_CLASS (NativeModuleTest) {
eventRaised = true;
}));
- m_module->OnJSValueEvent(JSValueArray{"X", 4, true, JSValueObject{{"Id", 42}}});
+ m_module->OnJSValueEvent(React::JSValueArray{"X", 4, true, React::JSValueObject{{"Id", 42}}});
TestCheck(eventRaised == true);
}
TEST_METHOD(TestEvent_JSValueArray1EventField) {
bool eventRaised = false;
m_builderMock.ExpectEvent(
- L"RCTDeviceEventEmitter", L"OnJSValueEvent", ([&eventRaised](JSValueArray const &args) noexcept {
+ L"RCTDeviceEventEmitter", L"OnJSValueEvent", ([&eventRaised](React::JSValueArray const &args) noexcept {
TestCheck(args[0][0] == 4);
eventRaised = true;
}));
- m_module->OnJSValueEvent(JSValueArray{4});
+ m_module->OnJSValueEvent(React::JSValueArray{4});
TestCheck(eventRaised == true);
}
TEST_METHOD(TestFunction_JSIntFunctionField) {
bool functionCalled = false;
m_builderMock.ExpectFunction(
- L"SimpleNativeModule", L"JSIntFunction", [&functionCalled](JSValueArray const &args) noexcept {
+ L"SimpleNativeModule", L"JSIntFunction", [&functionCalled](React::JSValueArray const &args) noexcept {
TestCheck(args[0] == 42);
functionCalled = true;
});
@@ -1455,7 +1446,7 @@ TEST_CLASS (NativeModuleTest) {
TEST_METHOD(TestFunction_JSNameFunctionField) {
bool functionCalled = false;
m_builderMock.ExpectFunction(
- L"SimpleNativeModule", L"pointFunc", [&functionCalled](JSValueArray const &args) noexcept {
+ L"SimpleNativeModule", L"pointFunc", [&functionCalled](React::JSValueArray const &args) noexcept {
TestCheck(args[0]["X"] == 4);
TestCheck(args[0]["Y"] == 2);
functionCalled = true;
@@ -1468,7 +1459,7 @@ TEST_CLASS (NativeModuleTest) {
TEST_METHOD(TestFunction_TwoArgFunctionField) {
bool functionCalled = false;
m_builderMock.ExpectFunction(
- L"SimpleNativeModule", L"lineFunc", [&functionCalled](JSValueArray const &args) noexcept {
+ L"SimpleNativeModule", L"lineFunc", [&functionCalled](React::JSValueArray const &args) noexcept {
TestCheck(args[0]["X"] == 4);
TestCheck(args[0]["Y"] == 2);
TestCheck(args[1]["X"] == 12);
@@ -1483,7 +1474,7 @@ TEST_CLASS (NativeModuleTest) {
TEST_METHOD(TestFunction_NoArgFunctionField) {
bool functionCalled = false;
m_builderMock.ExpectFunction(
- L"SimpleNativeModule", L"JSNoArgFunction", [&functionCalled](JSValueArray const &args) noexcept {
+ L"SimpleNativeModule", L"JSNoArgFunction", [&functionCalled](React::JSValueArray const &args) noexcept {
TestCheckEqual(0, args.size());
functionCalled = true;
});
@@ -1494,10 +1485,11 @@ TEST_CLASS (NativeModuleTest) {
TEST_METHOD(TestFunction_JSModuleNameFunctionField) {
bool functionCalled = false;
- m_builderMock.ExpectFunction(L"MyModule", L"stringFunc", [&functionCalled](JSValueArray const &args) noexcept {
- TestCheck(args[0] == "Hello World!");
- functionCalled = true;
- });
+ m_builderMock.ExpectFunction(
+ L"MyModule", L"stringFunc", [&functionCalled](React::JSValueArray const &args) noexcept {
+ TestCheck(args[0] == "Hello World!");
+ functionCalled = true;
+ });
m_module->JSStringFunction("Hello World!");
TestCheck(functionCalled == true);
@@ -1506,20 +1498,20 @@ TEST_CLASS (NativeModuleTest) {
TEST_METHOD(TestFunction_JSValueObjectFunctionField) {
bool functionCalled = false;
m_builderMock.ExpectFunction(
- L"SimpleNativeModule", L"JSValueFunction", ([&functionCalled](JSValueArray const &args) noexcept {
+ L"SimpleNativeModule", L"JSValueFunction", ([&functionCalled](React::JSValueArray const &args) noexcept {
TestCheck(args[0]["X"] == 4);
TestCheck(args[0]["Y"] == 2);
functionCalled = true;
}));
- m_module->JSValueFunction(JSValueObject{{"X", 4}, {"Y", 2}});
+ m_module->JSValueFunction(React::JSValueObject{{"X", 4}, {"Y", 2}});
TestCheck(functionCalled == true);
}
TEST_METHOD(TestFunction_JSValueArrayFunctionField) {
bool functionCalled = false;
m_builderMock.ExpectFunction(
- L"SimpleNativeModule", L"JSValueFunction", ([&functionCalled](JSValueArray const &args) noexcept {
+ L"SimpleNativeModule", L"JSValueFunction", ([&functionCalled](React::JSValueArray const &args) noexcept {
TestCheck(args[0][0] == "X");
TestCheck(args[0][1] == 4);
TestCheck(args[0][2] == true);
@@ -1527,7 +1519,7 @@ TEST_CLASS (NativeModuleTest) {
functionCalled = true;
}));
- m_module->JSValueFunction(JSValueArray{"X", 4, true, JSValueObject{{"Id", 42}}});
+ m_module->JSValueFunction(React::JSValueArray{"X", 4, true, React::JSValueObject{{"Id", 42}}});
TestCheck(functionCalled == true);
}
@@ -1536,4 +1528,4 @@ TEST_CLASS (NativeModuleTest) {
}
};
-} // namespace winrt::Microsoft::ReactNative
+} // namespace ReactNativeTests
diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp
index 149e39eec87..35c2af283aa 100644
--- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp
+++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/NoAttributeNativeModuleTest.cpp
@@ -507,7 +507,7 @@ struct SimpleNativeModule2 {
/*static*/ std::string SimpleNativeModule2::StaticMessage;
-void RegisterModule(ReactModuleBuilder &moduleBuilder) noexcept {
+void GetReactModuleInfo(SimpleNativeModule2 *, ReactModuleBuilder &moduleBuilder) noexcept {
moduleBuilder.RegisterModuleName(L"SimpleNativeModule2");
moduleBuilder.RegisterInitMethod(&SimpleNativeModule2::Initialize);
moduleBuilder.RegisterMethod(&SimpleNativeModule2::Add, L"Add");
@@ -577,8 +577,8 @@ void RegisterModule(ReactModuleBuilder &moduleBuilder) noex
moduleBuilder.RegisterConstantField(&SimpleNativeModule2::Constant2, L"const2");
moduleBuilder.RegisterConstantField(&SimpleNativeModule2::Constant3, L"const3");
moduleBuilder.RegisterConstantField(&SimpleNativeModule2::Constant4, L"Constant4");
- moduleBuilder.RegisterConstantMethod(&SimpleNativeModule2::Constant5, L"Constant5");
- moduleBuilder.RegisterConstantMethod(&SimpleNativeModule2::Constant6, L"Constant6");
+ moduleBuilder.RegisterConstantMethod(&SimpleNativeModule2::Constant5);
+ moduleBuilder.RegisterConstantMethod(&SimpleNativeModule2::Constant6);
moduleBuilder.RegisterEventField(&SimpleNativeModule2::OnIntEvent, L"OnIntEvent");
moduleBuilder.RegisterEventField(&SimpleNativeModule2::OnNoArgEvent, L"OnNoArgEvent");
moduleBuilder.RegisterEventField(&SimpleNativeModule2::OnTwoArgsEvent, L"OnTwoArgsEvent");
diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/Point.h b/vnext/Microsoft.ReactNative.Cxx.UnitTests/Point.h
new file mode 100644
index 00000000000..d711b247c33
--- /dev/null
+++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/Point.h
@@ -0,0 +1,15 @@
+#pragma once
+#include "NativeModules.h"
+
+namespace ReactNativeTests {
+
+REACT_STRUCT(Point)
+struct Point {
+ REACT_FIELD(X)
+ int X;
+
+ REACT_FIELD(Y)
+ int Y;
+};
+
+} // namespace ReactNativeTests
diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h b/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h
index ded81090484..88ec6935f02 100644
--- a/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h
+++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/ReactModuleBuilderMock.h
@@ -112,8 +112,8 @@ struct ReactModuleBuilderMock {
std::vector m_constantProviders;
std::map> m_methods;
std::map m_syncMethods;
- bool m_isResolveCallbackCalled;
- bool m_isRejectCallbackCalled;
+ bool m_isResolveCallbackCalled{false};
+ bool m_isRejectCallbackCalled{false};
Mso::Functor m_jsFunctionHandler;
Mso::Functor m_jsEventHandler;
};
diff --git a/vnext/Microsoft.ReactNative.Cxx.UnitTests/TurboModuleTest.cpp b/vnext/Microsoft.ReactNative.Cxx.UnitTests/TurboModuleTest.cpp
new file mode 100644
index 00000000000..7564168c4dd
--- /dev/null
+++ b/vnext/Microsoft.ReactNative.Cxx.UnitTests/TurboModuleTest.cpp
@@ -0,0 +1,2050 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#include "pch.h"
+#include "ReactModuleBuilderMock.h"
+
+#include
+#include "Point.h"
+#include "future/futureWait.h"
+
+namespace ReactNativeTests {
+REACT_MODULE(MyTurboModule)
+struct MyTurboModule {
+ REACT_INIT(Initialize)
+ void Initialize(React::IReactContext const &context) noexcept {
+ IsInitialized = true;
+ TestCheck(context != nullptr);
+
+ // Event and Function fields are initialized before REACT_INIT method call.
+ TestCheck(this->OnIntEvent != nullptr);
+ TestCheck(this->JSIntFunction != nullptr);
+ }
+
+ REACT_METHOD(Add)
+ int Add(int x, int y) noexcept {
+ return x + y;
+ }
+
+ REACT_METHOD(Negate)
+ int Negate(int x) noexcept {
+ return -x;
+ }
+
+ REACT_METHOD(SayHello)
+ std::string SayHello() noexcept {
+ return "Hello";
+ }
+
+ REACT_METHOD(StaticAdd)
+ static int StaticAdd(int x, int y) noexcept {
+ return x + y;
+ }
+
+ REACT_METHOD(StaticNegate)
+ static int StaticNegate(int x) noexcept {
+ return -x;
+ }
+
+ REACT_METHOD(StaticSayHello)
+ static std::string StaticSayHello() noexcept {
+ return "Hello";
+ }
+
+ REACT_METHOD(SayHello0)
+ void SayHello0() noexcept {
+ Message = "Hello_0";
+ }
+
+ REACT_METHOD(PrintPoint)
+ void PrintPoint(Point pt) noexcept {
+ std::stringstream ss;
+ ss << "Point: (" << pt.X << ", " << pt.Y << ")";
+ Message = ss.str();
+ }
+
+ REACT_METHOD(PrintLine)
+ void PrintLine(Point start, Point end) noexcept {
+ std::stringstream ss;
+ ss << "Line: (" << start.X << ", " << start.Y << ")-(" << end.X << ", " << end.Y << ")";
+ Message = ss.str();
+ }
+
+ REACT_METHOD(StaticSayHello0)
+ static void StaticSayHello0() noexcept {
+ StaticMessage = "Hello_0";
+ }
+
+ REACT_METHOD(StaticPrintPoint)
+ static void StaticPrintPoint(Point pt) noexcept {
+ std::stringstream ss;
+ ss << "Static Point: (" << pt.X << ", " << pt.Y << ")";
+ StaticMessage = ss.str();
+ }
+
+ REACT_METHOD(StaticPrintLine)
+ static void StaticPrintLine(Point start, Point end) noexcept {
+ std::stringstream ss;
+ ss << "Static Line: (" << start.X << ", " << start.Y << ")-(" << end.X << ", " << end.Y << ")";
+ StaticMessage = ss.str();
+ }
+
+ REACT_METHOD(AddCallback)
+ void AddCallback(int x, int y, std::function const &resolve) noexcept {
+ resolve(x + y);
+ }
+
+ REACT_METHOD(NegateCallback)
+ void NegateCallback(int x, std::function const &resolve) noexcept {
+ resolve(-x);
+ }
+
+ REACT_METHOD(NegateAsyncCallback)
+ fire_and_forget NegateAsyncCallback(int x, std::function resolve) noexcept {
+ co_await winrt::resume_background();
+ resolve(-x);
+ }
+
+ REACT_METHOD(NegateDispatchQueueCallback)
+ void NegateDispatchQueueCallback(int x, std::function const &resolve) noexcept {
+ Mso::DispatchQueue::ConcurrentQueue().Post([ x, resolve ]() noexcept { resolve(-x); });
+ }
+
+ REACT_METHOD(NegateFutureCallback)
+ void NegateFutureCallback(int x, std::function const &resolve) noexcept {
+ Mso::PostFuture([ x, resolve ]() noexcept { resolve(-x); });
+ }
+
+ REACT_METHOD(SayHelloCallback)
+ void SayHelloCallback(std::function const &resolve) noexcept {
+ resolve("Hello_2");
+ }
+
+ REACT_METHOD(StaticAddCallback)
+ static void StaticAddCallback(int x, int y, std::function const &resolve) noexcept {
+ resolve(x + y);
+ }
+
+ REACT_METHOD(StaticNegateCallback)
+ static void StaticNegateCallback(int x, std::function const &resolve) noexcept {
+ resolve(-x);
+ }
+
+ REACT_METHOD(StaticNegateAsyncCallback)
+ static fire_and_forget StaticNegateAsyncCallback(int x, std::function resolve) noexcept {
+ co_await winrt::resume_background();
+ resolve(-x);
+ }
+
+ REACT_METHOD(StaticNegateDispatchQueueCallback)
+ static void StaticNegateDispatchQueueCallback(int x, std::function const &resolve) noexcept {
+ Mso::DispatchQueue::ConcurrentQueue().Post([ x, resolve ]() noexcept { resolve(-x); });
+ }
+
+ REACT_METHOD(StaticNegateFutureCallback)
+ static void StaticNegateFutureCallback(int x, std::function const &resolve) noexcept {
+ Mso::PostFuture([ x, resolve ]() noexcept { resolve(-x); });
+ }
+
+ REACT_METHOD(StaticSayHelloCallback)
+ static void StaticSayHelloCallback(std::function const &resolve) noexcept {
+ resolve("Static Hello_2");
+ }
+
+ REACT_METHOD(DivideCallbacks)
+ void DivideCallbacks(
+ int x,
+ int y,
+ std::function const &resolve,
+ std::function const &reject) noexcept {
+ if (y != 0) {
+ resolve(x / y);
+ } else {
+ reject("Division by 0");
+ }
+ }
+
+ REACT_METHOD(NegateCallbacks)
+ void NegateCallbacks(
+ int x,
+ std::function const &resolve,
+ std::function const &reject) noexcept {
+ if (x >= 0) {
+ resolve(-x);
+ } else {
+ reject("Already negative");
+ }
+ }
+
+ REACT_METHOD(NegateAsyncCallbacks)
+ fire_and_forget NegateAsyncCallbacks(
+ int x,
+ std::function resolve,
+ std::function reject) noexcept {
+ co_await winrt::resume_background();
+ if (x >= 0) {
+ resolve(-x);
+ } else {
+ reject("Already negative");
+ }
+ }
+
+ REACT_METHOD(NegateDispatchQueueCallbacks)
+ void NegateDispatchQueueCallbacks(
+ int x,
+ std::function const &resolve,
+ std::function const &reject) noexcept {
+ Mso::DispatchQueue::ConcurrentQueue().Post([ x, resolve, reject ]() noexcept {
+ if (x >= 0) {
+ resolve(-x);
+ } else {
+ reject("Already negative");
+ }
+ });
+ }
+
+ REACT_METHOD(NegateFutureCallbacks)
+ void NegateFutureCallbacks(
+ int x,
+ std::function const &resolve,
+ std::function const &reject) noexcept {
+ Mso::PostFuture([ x, resolve, reject ]() noexcept {
+ if (x >= 0) {
+ resolve(-x);
+ } else {
+ reject("Already negative");
+ }
+ });
+ }
+
+ REACT_METHOD(ResolveSayHelloCallbacks)
+ void ResolveSayHelloCallbacks(
+ std::function const &resolve,
+ std::function const & /*reject*/) noexcept {
+ resolve("Hello_3");
+ }
+
+ REACT_METHOD(RejectSayHelloCallbacks)
+ void RejectSayHelloCallbacks(
+ std::function const & /*resolve*/,
+ std::function const &reject) noexcept {
+ reject("Goodbye");
+ }
+
+ REACT_METHOD(StaticDivideCallbacks)
+ static void StaticDivideCallbacks(
+ int x,
+ int y,
+ std::function const &resolve,
+ std::function const &reject) noexcept {
+ if (y != 0) {
+ resolve(x / y);
+ } else {
+ reject("Division by 0");
+ }
+ }
+
+ REACT_METHOD(StaticNegateCallbacks)
+ static void StaticNegateCallbacks(
+ int x,
+ std::function const &resolve,
+ std::function const &reject) noexcept {
+ if (x >= 0) {
+ resolve(-x);
+ } else {
+ reject("Already negative");
+ }
+ }
+
+ REACT_METHOD(StaticNegateAsyncCallbacks)
+ static fire_and_forget StaticNegateAsyncCallbacks(
+ int x,
+ std::function resolve,
+ std::function reject) noexcept {
+ co_await winrt::resume_background();
+ if (x >= 0) {
+ resolve(-x);
+ } else {
+ reject("Already negative");
+ }
+ }
+
+ REACT_METHOD(StaticNegateDispatchQueueCallbacks)
+ static void StaticNegateDispatchQueueCallbacks(
+ int x,
+ std::function const &resolve,
+ std::function const &reject) noexcept {
+ Mso::DispatchQueue::ConcurrentQueue().Post([ x, resolve, reject ]() noexcept {
+ if (x >= 0) {
+ resolve(-x);
+ } else {
+ reject("Already negative");
+ }
+ });
+ }
+
+ REACT_METHOD(StaticNegateFutureCallbacks)
+ static void StaticNegateFutureCallbacks(
+ int x,
+ std::function const &resolve,
+ std::function const &reject) noexcept {
+ Mso::PostFuture([ x, resolve, reject ]() noexcept {
+ if (x >= 0) {
+ resolve(-x);
+ } else {
+ reject("Already negative");
+ }
+ });
+ }
+
+ REACT_METHOD(StaticResolveSayHelloCallbacks)
+ static void StaticResolveSayHelloCallbacks(
+ std::function const &resolve,
+ std::function const & /*reject*/) noexcept {
+ resolve("Hello_3");
+ }
+
+ REACT_METHOD(StaticRejectSayHelloCallbacks)
+ static void StaticRejectSayHelloCallbacks(
+ std::function const & /*resolve*/,
+ std::function const &reject) noexcept {
+ reject("Goodbye");
+ }
+
+ REACT_METHOD(DividePromise)
+ void DividePromise(int x, int y, React::ReactPromise const &result) noexcept {
+ if (y != 0) {
+ result.Resolve(x / y);
+ } else {
+ React::ReactError error{};
+ error.Message = "Division by 0";
+ result.Reject(std::move(error));
+ }
+ }
+
+ REACT_METHOD(NegatePromise)
+ void NegatePromise(int x, React::ReactPromise const &result) noexcept {
+ if (x >= 0) {
+ result.Resolve(-x);
+ } else {
+ React::ReactError error{};
+ error.Message = "Already negative";
+ result.Reject(std::move(error));
+ }
+ }
+
+ REACT_METHOD(NegateAsyncPromise)
+ fire_and_forget NegateAsyncPromise(int x, React::ReactPromise result) noexcept {
+ co_await winrt::resume_background();
+ if (x >= 0) {
+ result.Resolve(-x);
+ } else {
+ React::ReactError error{};
+ error.Message = "Already negative";
+ result.Reject(std::move(error));
+ }
+ }
+
+ REACT_METHOD(NegateDispatchQueuePromise)
+ void NegateDispatchQueuePromise(int x, React::ReactPromise const &result) noexcept {
+ Mso::DispatchQueue::ConcurrentQueue().Post([ x, result ]() noexcept {
+ if (x >= 0) {
+ result.Resolve(-x);
+ } else {
+ React::ReactError error{};
+ error.Message = "Already negative";
+ result.Reject(std::move(error));
+ }
+ });
+ }
+
+ REACT_METHOD(NegateFuturePromise)
+ void NegateFuturePromise(int x, React::ReactPromise const &result) noexcept {
+ Mso::PostFuture([ x, result ]() noexcept {
+ if (x >= 0) {
+ result.Resolve(-x);
+ } else {
+ React::ReactError error{};
+ error.Message = "Already negative";
+ result.Reject(std::move(error));
+ }
+ });
+ }
+
+ // Each macro has second optional parameter: JS name.
+ REACT_METHOD(VoidPromise, L"voidPromise")
+ void VoidPromise(int x, React::ReactPromise const &result) noexcept {
+ if (x % 2 == 0) {
+ result.Resolve();
+ } else {
+ result.Reject("Odd unexpected");
+ }
+ }
+
+ REACT_METHOD(ResolveSayHelloPromise)
+ void ResolveSayHelloPromise(React::ReactPromise const &result) noexcept {
+ result.Resolve("Hello_4");
+ }
+
+ REACT_METHOD(RejectSayHelloPromise)
+ void RejectSayHelloPromise(React::ReactPromise const &result) noexcept {
+ React::ReactError error{};
+ error.Message = "Promise rejected";
+ result.Reject(std::move(error));
+ }
+
+ REACT_METHOD(StaticDividePromise)
+ static void StaticDividePromise(int x, int y, React::ReactPromise const &result) noexcept {
+ if (y != 0) {
+ result.Resolve(x / y);
+ } else {
+ React::ReactError error{};
+ error.Message = "Division by 0";
+ result.Reject(std::move(error));
+ }
+ }
+
+ REACT_METHOD(StaticNegatePromise)
+ static void StaticNegatePromise(int x, React::ReactPromise const &result) noexcept {
+ if (x >= 0) {
+ result.Resolve(-x);
+ } else {
+ React::ReactError error{};
+ error.Message = "Already negative";
+ result.Reject(std::move(error));
+ }
+ }
+
+ REACT_METHOD(StaticNegateAsyncPromise)
+ static fire_and_forget StaticNegateAsyncPromise(int x, React::ReactPromise result) noexcept {
+ co_await winrt::resume_background();
+ if (x >= 0) {
+ result.Resolve(-x);
+ } else {
+ React::ReactError error{};
+ error.Message = "Already negative";
+ result.Reject(std::move(error));
+ }
+ }
+
+ REACT_METHOD(StaticNegateDispatchQueuePromise)
+ static void StaticNegateDispatchQueuePromise(int x, React::ReactPromise const &result) noexcept {
+ Mso::DispatchQueue::ConcurrentQueue().Post([ x, result ]() noexcept {
+ if (x >= 0) {
+ result.Resolve(-x);
+ } else {
+ React::ReactError error{};
+ error.Message = "Already negative";
+ result.Reject(std::move(error));
+ }
+ });
+ }
+
+ REACT_METHOD(StaticNegateFuturePromise)
+ static void StaticNegateFuturePromise(int x, React::ReactPromise const &result) noexcept {
+ Mso::PostFuture([ x, result ]() noexcept {
+ if (x >= 0) {
+ result.Resolve(-x);
+ } else {
+ React::ReactError error{};
+ error.Message = "Already negative";
+ result.Reject(std::move(error));
+ }
+ });
+ }
+
+ // Each macro has second optional parameter: JS name.
+ REACT_METHOD(StaticVoidPromise, L"staticVoidPromise")
+ void StaticVoidPromise(int x, React::ReactPromise const &result) noexcept {
+ if (x % 2 == 0) {
+ result.Resolve();
+ } else {
+ result.Reject("Odd unexpected");
+ }
+ }
+
+ REACT_METHOD(StaticResolveSayHelloPromise)
+ static void StaticResolveSayHelloPromise(React::ReactPromise const &result) noexcept {
+ result.Resolve("Hello_4");
+ }
+
+ REACT_METHOD(StaticRejectSayHelloPromise)
+ static void StaticRejectSayHelloPromise(React::ReactPromise const &result) noexcept {
+ React::ReactError error{};
+ error.Message = "Promise rejected";
+ result.Reject(std::move(error));
+ }
+
+ REACT_SYNC_METHOD(AddSync)
+ int AddSync(int x, int y) noexcept {
+ return x + y;
+ }
+
+ REACT_SYNC_METHOD(NegateSync)
+ int NegateSync(int x) noexcept {
+ return -x;
+ }
+
+ REACT_SYNC_METHOD(SayHelloSync)
+ std::string SayHelloSync() noexcept {
+ return "Hello";
+ }
+
+ REACT_SYNC_METHOD(StaticAddSync)
+ static int StaticAddSync(int x, int y) noexcept {
+ return x + y;
+ }
+
+ REACT_SYNC_METHOD(StaticNegateSync)
+ static int StaticNegateSync(int x) noexcept {
+ return -x;
+ }
+
+ REACT_SYNC_METHOD(StaticSayHelloSync)
+ static std::string StaticSayHelloSync() noexcept {
+ return "Hello";
+ }
+
+ REACT_CONSTANT(Constant1)
+ const std::string Constant1{"MyConstant1"};
+
+ REACT_CONSTANT(Constant2, L"const2")
+ const std::string Constant2{"MyConstant2"};
+
+ REACT_CONSTANT(Constant3, L"const3")
+ static constexpr Point Constant3{/*X =*/2, /*Y =*/3};
+
+ REACT_CONSTANT(Constant4)
+ static constexpr Point Constant4{/*X =*/3, /*Y =*/4};
+
+ REACT_CONSTANT_PROVIDER(Constant5)
+ void Constant5(React::ReactConstantProvider &provider) noexcept {
+ provider.Add(L"const51", Point{/*X =*/12, /*Y =*/14});
+ provider.Add(L"const52", "MyConstant52");
+ }
+
+ REACT_CONSTANT_PROVIDER(Constant6)
+ static void Constant6(React::ReactConstantProvider &provider) noexcept {
+ provider.Add(L"const61", Point{/*X =*/15, /*Y =*/17});
+ provider.Add(L"const62", "MyConstant62");
+ }
+
+ // Allows to emit native module events
+ REACT_EVENT(OnIntEvent)
+ std::function OnIntEvent;
+
+ // An event without arguments
+ REACT_EVENT(OnNoArgEvent)
+ std::function OnNoArgEvent;
+
+ // An event with two arguments
+ REACT_EVENT(OnTwoArgsEvent)
+ std::function OnTwoArgsEvent;
+
+ // Specify event name different from the field name.
+ REACT_EVENT(OnPointEvent, L"onPointEvent")
+ std::function OnPointEvent;
+
+ // By default we use the event emitter name from REACT_MODULE which is by default 'RCTDeviceEventEmitter'.
+ // Here we specify event emitter name local for this event.
+ REACT_EVENT(OnStringEvent, L"onStringEvent", L"MyEventEmitter")
+ std::function OnStringEvent;
+
+ // Use React::JSValue which is an immutable JSON-like data representation.
+ REACT_EVENT(OnJSValueEvent)
+ std::function OnJSValueEvent;
+
+ // Allows to call JS functions.
+ REACT_FUNCTION(JSIntFunction)
+ std::function JSIntFunction;
+
+ // Specify JS function name different from the field name.
+ REACT_FUNCTION(JSPointFunction, L"pointFunc")
+ std::function JSPointFunction;
+
+ // Use two arguments. Specify JS function name different from the field name.
+ REACT_FUNCTION(JSLineFunction, L"lineFunc")
+ std::function JSLineFunction;
+
+ // Use no arguments.
+ REACT_FUNCTION(JSNoArgFunction)
+ std::function JSNoArgFunction;
+
+ // By default we use the module name from REACT_MODULE which is by default the struct name.
+ // Here we specify module name local for this function.
+ REACT_FUNCTION(JSStringFunction, L"stringFunc", L"MyModule")
+ std::function JSStringFunction;
+
+ // Use React::JSValue which is an immutable JSON-like data representation.
+ REACT_FUNCTION(JSValueFunction)
+ std::function JSValueFunction;
+
+ public: // Used to report some test messages
+ bool IsInitialized{false};
+ std::string Message;
+ static std::string StaticMessage;
+};
+
+/*static*/ std::string MyTurboModule::StaticMessage;
+
+// The TurboModule spec is going to be generated from the Flow spec file.
+// It verifies that:
+// - module methods names are unique;
+// - method names are matching to the module spec method names;
+// - method signatures match the spec method signatures.
+struct MyTurboModuleSpec : winrt::Microsoft::ReactNative::TurboModuleSpec {
+ static constexpr auto methods = std::tuple{
+ Method) noexcept>{0, L"Add"},
+ Method) noexcept>{1, L"Negate"},
+ Method) noexcept>{2, L"SayHello"},
+ Method) noexcept>{3, L"StaticAdd"},
+ Method) noexcept>{4, L"StaticNegate"},
+ Method) noexcept>{5, L"StaticSayHello"},
+ Method{6, L"SayHello0"},
+ Method{7, L"PrintPoint"},
+ Method{8, L"PrintLine"},
+ Method{9, L"StaticSayHello0"},
+ Method{10, L"StaticPrintPoint"},
+ Method{11, L"StaticPrintLine"},
+ Method) noexcept>{12, L"AddCallback"},
+ Method) noexcept>{13, L"NegateCallback"},
+ Method) noexcept>{14, L"NegateAsyncCallback"},
+ Method) noexcept>{15, L"NegateDispatchQueueCallback"},
+ Method) noexcept>{16, L"NegateFutureCallback"},
+ Method) noexcept>{17, L"SayHelloCallback"},
+ Method) noexcept>{18, L"StaticAddCallback"},
+ Method) noexcept>{19, L"StaticNegateCallback"},
+ Method) noexcept>{20, L"StaticNegateAsyncCallback"},
+ Method) noexcept>{21, L"StaticNegateDispatchQueueCallback"},
+ Method) noexcept>{22, L"StaticNegateFutureCallback"},
+ Method) noexcept>{23, L"StaticSayHelloCallback"},
+ Method, Callback) noexcept>{24, L"DivideCallbacks"},
+ Method, Callback) noexcept>{25, L"NegateCallbacks"},
+ Method, Callback) noexcept>{26, L"NegateAsyncCallbacks"},
+ Method, Callback) noexcept>{27, L"NegateDispatchQueueCallbacks"},
+ Method, Callback) noexcept>{28, L"NegateFutureCallbacks"},
+ Method, Callback) noexcept>{29, L"ResolveSayHelloCallbacks"},
+ Method, Callback) noexcept>{30, L"RejectSayHelloCallbacks"},
+ Method, Callback) noexcept>{31, L"StaticDivideCallbacks"},
+ Method, Callback) noexcept>{32, L"StaticNegateCallbacks"},
+ Method, Callback) noexcept>{33, L"StaticNegateAsyncCallbacks"},
+ Method