Port REACT_MODULE() from react-native-windows to react-native-macos (1/4) (#595)
* ... * ... * ... * ... * ... * Built JSValue.h * Add include path * ... * Built JSValueTree(Reader|Writer) * ... * Built JSValue(Reader|Writer) * ... * Built ModuleRegistration * ... * ... * ... * ... * ... * ... * ... * ... * ... * ... * Update ReactContext.h * Update ReactPropertyBag.h * Update ReactNonAbiValue.h * ... * Built ReactPromise * ... * Create Windows.Foundation.h * ... * Update NativeModules.h * ... * Update NativeModules.h * Build dummy react module * Fix build break
This commit is contained in:
Родитель
44211a6304
Коммит
1a5abe4bec
|
@ -10,6 +10,7 @@
|
|||
#import <React/RCTUtils.h>
|
||||
#import <ReactCommon/RCTTurboModuleManager.h>
|
||||
#import <ReactCommon/TurboModuleUtils.h>
|
||||
#import <NativeModules.h>
|
||||
|
||||
static NSImage* TakeScreenshot()
|
||||
{
|
||||
|
@ -114,6 +115,32 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
REACT_STRUCT(ScreenshotArguments)
|
||||
struct ScreenshotArguments
|
||||
{
|
||||
};
|
||||
|
||||
REACT_MODULE(ScreenshotManagerCxx, L"ScreenshotManager")
|
||||
struct ScreenshotManagerCxx
|
||||
{
|
||||
REACT_INIT(Initialize)
|
||||
void Initialize(const winrt::Microsoft::ReactNative::ReactContext&) noexcept
|
||||
{
|
||||
// to be implemented
|
||||
}
|
||||
|
||||
REACT_METHOD(TakeScreenshot, L"takeScreenshot")
|
||||
void TakeScreenshot(
|
||||
std::string,
|
||||
ScreenshotArguments&&,
|
||||
winrt::Microsoft::ReactNative::ReactPromise<std::string> result
|
||||
) noexcept
|
||||
{
|
||||
// to be implemented
|
||||
result.Reject(L"Not implemented!");
|
||||
}
|
||||
};
|
||||
|
||||
@implementation ScreenshotManagerTurboModuleManagerDelegate
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
|
|
|
@ -395,7 +395,7 @@ DEPENDENCIES:
|
|||
- Yoga (from `../ReactCommon/yoga`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://cdn.cocoapods.org/:
|
||||
trunk:
|
||||
- CocoaAsyncSocket
|
||||
- CocoaLibEvent
|
||||
- Flipper
|
||||
|
@ -473,38 +473,49 @@ EXTERNAL SOURCES:
|
|||
:path: "../ReactCommon/yoga"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
boost-for-react-native: a110407d9db2642fd2e1bcd7c5a51c81f2521dc9
|
||||
boost-for-react-native: dabda8622e76020607c2ae1e65cc0cda8b61479d
|
||||
CocoaAsyncSocket: eafaa68a7e0ec99ead0a7b35015e0bf25d2c8987
|
||||
CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f
|
||||
DoubleConversion: a1bc12a74baa397a2609e0f10e19b8062d864053
|
||||
FBLazyVector: 5b6d8c9cfd8538e30e1e2269526196ffe96d37ef
|
||||
FBReactNativeSpec: c48b4d3b293cd0b82c582d2405acd6a1b07d3451
|
||||
Folly: feff29ba9d0b7c2e4f793a94942831d6cc5bbad7
|
||||
glog: b3f6d74f3e2d33396addc0ee724d2b2b79fc3e00
|
||||
RCTRequired: 622690f1bcbe26868f52961e719d860f3004b6b6
|
||||
RCTTypeSafety: 3ea632ebbb03638caff9e84f6f6abb7e936a3e5b
|
||||
React: 8d5eec1276f11a81b19d8abb6443dcc39a110300
|
||||
React-ART: c013918bd3d8c62b8ad582031fd9a760c6df53d8
|
||||
React-Core: bd781c39a56a76af11a6f9657c5aaff3bbff46ff
|
||||
React-CoreModules: de492a564074fb323f5a7577cc8fad169f6b35a1
|
||||
React-cxxreact: 9797c881683a4d7cb3755a533942745f0244fc0b
|
||||
React-jsi: 30ffe0e2af47cf815eb7ee61084ea891cbf48cbb
|
||||
React-jsiexecutor: f1080a4b5aa627a393f8b9e2b545f98e32b1e8ed
|
||||
React-jsinspector: 5e2444bdfaf148c9f14b9ed68dd607cd12a3c201
|
||||
React-RCTActionSheet: 96944bdeca027606bdb9c798b61d82ee34c12105
|
||||
React-RCTAnimation: 14a267ca1675e8aa46038e54cedaa568089ca72f
|
||||
React-RCTBlob: 8df5ae4defda691fa058b42b1d2bc253ceb8bcd5
|
||||
React-RCTImage: 51693ef8b6539c75a39046569894c46936f9e46f
|
||||
React-RCTLinking: 3925342df1e9de2c4b8674cca39de0e7a42d0ccf
|
||||
React-RCTNetwork: de7a645b95657b88fd891e0b59298b7bf1a50ad9
|
||||
React-RCTPushNotification: 61aff4a48cd87145c170a173426c1bec96b288d3
|
||||
React-RCTSettings: 5c4b741b59a4547f8f002a3c17bc9b817298c8e0
|
||||
React-RCTTest: 5afe9d3c7ab66dfd2ca5145f9189c0a85f2fb34b
|
||||
React-RCTText: 09b6d9d7363064d23380f50fc01af3ab75131cf7
|
||||
React-RCTVibration: 8135beb48e3065fbcbe6417b9a6bbbc884c02a78
|
||||
ReactCommon: a377fdc9faecc5c9408bcd07ce997703c0ce22ff
|
||||
Yoga: 7d784f976888661a2cea9333ab06125b1133e435
|
||||
DoubleConversion: 681b789128e5512811c81706e9b361209f40d21e
|
||||
FBLazyVector: 74ccce103368f2500ecb881984a4672fb2e390a4
|
||||
FBReactNativeSpec: ea51ad751995d8f42e682c6d38122a9bc9066130
|
||||
Flipper: 10b225e352595f521be0e5badddd90e241336e89
|
||||
Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41
|
||||
Flipper-Folly: c12092ea368353b58e992843a990a3225d4533c3
|
||||
Flipper-Glog: 1dfd6abf1e922806c52ceb8701a3599a79a200a6
|
||||
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
|
||||
Flipper-RSocket: 64e7431a55835eb953b0bf984ef3b90ae9fdddd7
|
||||
FlipperKit: 88b7f0d0cf907ddc2137b85eeb7f3d4d8d9395c8
|
||||
glog: d86cb3634e15ec6d8cd9a1c7c1b9d6fa295beb37
|
||||
hermes: e6c81c75290bb87d1d62d594c269fba09b84e216
|
||||
libevent: ee9265726a1fc599dea382964fa304378affaa5f
|
||||
OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355
|
||||
RCT-Folly: 71ece0166f9c96c1ec9279eeb0317baf533c020f
|
||||
RCTRequired: c721a56b4efd7a0581a04cee5049f69df497f893
|
||||
RCTTypeSafety: 35f563c6cb2730109cd08ed968fdebe17bc6f4e5
|
||||
React: 3c14ebe07758f4c0ee42adf96fb8653e2de345de
|
||||
React-ART: ef5636898187cfc1e05035eeeface3ee71a13880
|
||||
React-Core: 02fcc8650660b7657bef74e3b5ce29a03ec4d035
|
||||
React-CoreModules: d5346b790e84f25c9c15d697b67a3d42a6ed92e3
|
||||
React-cxxreact: 371d5fb5ac097a6fefb56e4c7b3e14a6d5e2127c
|
||||
React-jsi: 11e865c33e2607b962aee0bb8edcc13897f3a420
|
||||
React-jsiexecutor: 099015ce3845eba990f678ee829e011edbec3678
|
||||
React-jsinspector: 3aa1aad3ffe8f911df2951f26b55bc8d3908b250
|
||||
React-RCTActionSheet: 10340a23d7a2744bfb3940bbe0f9e7074a80353c
|
||||
React-RCTAnimation: 095c1674ad4452d44a56965e39c52751595e1f8f
|
||||
React-RCTBlob: dfaa578bea585da33fbf2cfad5c93fb577df56e5
|
||||
React-RCTImage: 71697890f79c520fe7b9043e7def03917bd3db50
|
||||
React-RCTLinking: f18761b366132b22c01c1e1e12bdededa9e84dfe
|
||||
React-RCTNetwork: 7598459c59afd073d612fafcda35d26387744318
|
||||
React-RCTPushNotification: f31cc802ffa824353595a028c2c708c21392ec02
|
||||
React-RCTSettings: 46ab8699cda8682a67b388b704647da0374503c9
|
||||
React-RCTTest: e1888c36f5589f52e3e567b49387f12da1d5e1fe
|
||||
React-RCTText: 5f44e6f6e7f0ac4844d452c07786e2e2c8388508
|
||||
React-RCTVibration: f357bd81edc86eeb460c97b93e27dc5aa28ecd1f
|
||||
ReactCommon: 5435fb8c36c46ad634c914b65f51f281198bcbb6
|
||||
Yoga: 07d9ce7f0929862ae9ff4cad7aebe62c609296bc
|
||||
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
|
||||
|
||||
PODFILE CHECKSUM: 8a50297c26ad9d948d1614b33e20d755094cb377
|
||||
|
||||
COCOAPODS: 1.9.1
|
||||
COCOAPODS: 1.9.3
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef VerifyElseCrash
|
||||
#define VerifyElseCrash(condition) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
assert(false && #condition); \
|
||||
std::terminate(); \
|
||||
} \
|
||||
} while (false)
|
||||
#endif
|
||||
|
||||
#ifndef VerifyElseCrashSz
|
||||
#define VerifyElseCrashSz(condition, message) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
assert(false && (message)); \
|
||||
std::terminate(); \
|
||||
} \
|
||||
} while (false)
|
||||
#endif
|
|
@ -0,0 +1,857 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pch.h"
|
||||
#include "JSValue.h"
|
||||
#include <cctype>
|
||||
#include <iomanip>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string_view>
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
//===========================================================================
|
||||
// JSValue type conversion helpers.
|
||||
//===========================================================================
|
||||
|
||||
namespace {
|
||||
|
||||
struct JSConverter {
|
||||
static constexpr char const *NullString = "null";
|
||||
static constexpr char const *ObjectString = "[object Object]";
|
||||
static constexpr char const *WhiteSpace = " \n\r\t\f\v";
|
||||
static const std::set<std::string> StringToBoolean;
|
||||
|
||||
static std::string LowerString(std::string const &value) noexcept {
|
||||
std::string result{value};
|
||||
std::transform(
|
||||
result.begin(), result.end(), result.begin(), [](char ch) { return static_cast<char>(std::tolower(ch)); });
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string_view TrimString(std::string_view value) noexcept {
|
||||
size_t start = value.find_first_not_of(WhiteSpace);
|
||||
if (start == std::string::npos) {
|
||||
return "";
|
||||
}
|
||||
|
||||
size_t end = value.find_last_not_of(WhiteSpace);
|
||||
return {value.data() + start, end - start + 1};
|
||||
}
|
||||
|
||||
static char const *ToCString(bool value) noexcept {
|
||||
return value ? "true" : "false";
|
||||
}
|
||||
|
||||
static char const *NaNToCString(double value) noexcept {
|
||||
if (std::isnan(value)) {
|
||||
return "NaN";
|
||||
} else if (value == std::numeric_limits<double>::infinity()) {
|
||||
return "Infinity";
|
||||
} else if (value == -std::numeric_limits<double>::infinity()) {
|
||||
return "-Infinity";
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static std::string ToJSString(double value) noexcept {
|
||||
if (std::isfinite(value)) {
|
||||
std::stringstream ss;
|
||||
ss << value;
|
||||
return ss.str();
|
||||
} else {
|
||||
return NaNToCString(value);
|
||||
}
|
||||
}
|
||||
|
||||
static std::ostream &WriteJSString(std::ostream &stream, double value) noexcept {
|
||||
if (std::isfinite(value)) {
|
||||
return stream << value;
|
||||
} else {
|
||||
return stream << NaNToCString(value);
|
||||
}
|
||||
}
|
||||
|
||||
static bool ToBoolean(std::string const &value) noexcept {
|
||||
auto key = LowerString(value);
|
||||
auto it = StringToBoolean.find(key);
|
||||
return it != StringToBoolean.end();
|
||||
}
|
||||
|
||||
static double ToJSNumber(std::string_view value) noexcept {
|
||||
auto trimmed = TrimString(value);
|
||||
if (trimmed.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *end;
|
||||
double result = strtod(trimmed.data(), &end);
|
||||
return (end == trimmed.data() + trimmed.size()) ? result : std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
|
||||
static int64_t ToInt64(double value) noexcept {
|
||||
return (std::numeric_limits<int64_t>::min() <= value && value <= std::numeric_limits<int64_t>::max())
|
||||
? static_cast<int64_t>(value)
|
||||
: 0;
|
||||
}
|
||||
};
|
||||
|
||||
/*static*/ const std::set<std::string> JSConverter::StringToBoolean{"true", "1", "yes", "y", "on"};
|
||||
|
||||
struct JSValueLogWriter {
|
||||
static constexpr char const *IndentString = " ";
|
||||
|
||||
JSValueLogWriter(std::ostream &stream) noexcept : m_stream{stream} {}
|
||||
|
||||
static std::string ToString(JSValue const &value) noexcept {
|
||||
std::stringstream stream;
|
||||
JSValueLogWriter writer{stream};
|
||||
writer.WriteValue(value);
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
JSValueLogWriter &WriteIndent() noexcept {
|
||||
for (size_t i = 0; i < m_indent; ++i) {
|
||||
m_stream << IndentString;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSValueLogWriter &WriteLine() noexcept {
|
||||
m_stream << '\n';
|
||||
return WriteIndent();
|
||||
}
|
||||
|
||||
JSValueLogWriter &Write(std::string_view value) noexcept {
|
||||
m_stream << value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSValueLogWriter &WriteQuotedString(std::string_view value) noexcept {
|
||||
auto writeChar = [](std::ostream & stream, char ch) noexcept->std::ostream & {
|
||||
switch (ch) {
|
||||
case '"':
|
||||
return stream << "\\\"";
|
||||
case '\\':
|
||||
return stream << "\\\\";
|
||||
case '\b':
|
||||
return stream << "\\b";
|
||||
case '\f':
|
||||
return stream << "\\f";
|
||||
case '\n':
|
||||
return stream << "\\n";
|
||||
case '\r':
|
||||
return stream << "\\r";
|
||||
case '\t':
|
||||
return stream << "\\t";
|
||||
default:
|
||||
if ('\x00' <= ch && ch <= '\x1f') { // Non-printable ASCII characters.
|
||||
return stream << "\\u" << std::hex << std::setw(4) << std::setfill('0') << (int)ch;
|
||||
} else {
|
||||
return stream << ch;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
m_stream << '"';
|
||||
for (auto ch : value) {
|
||||
writeChar(m_stream, ch);
|
||||
}
|
||||
|
||||
m_stream << '"';
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSValueLogWriter &WriteSeparator(bool &start) noexcept {
|
||||
if (start) {
|
||||
start = false;
|
||||
} else {
|
||||
m_stream << ",";
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSValueLogWriter &WriteObject(JSValueObject const &value) noexcept {
|
||||
if (value.empty()) {
|
||||
return Write("{}");
|
||||
}
|
||||
|
||||
Write("{");
|
||||
++m_indent;
|
||||
bool start = true;
|
||||
for (auto const &prop : value) {
|
||||
WriteSeparator(start).WriteLine();
|
||||
Write(prop.first).Write(": ").WriteValue(prop.second);
|
||||
}
|
||||
|
||||
--m_indent;
|
||||
return WriteLine().Write("}");
|
||||
}
|
||||
|
||||
JSValueLogWriter &WriteArray(JSValueArray const &value) noexcept {
|
||||
if (value.empty()) {
|
||||
return Write("[]");
|
||||
}
|
||||
|
||||
Write("[");
|
||||
++m_indent;
|
||||
bool start = true;
|
||||
for (auto const &item : value) {
|
||||
WriteSeparator(start).WriteLine();
|
||||
WriteValue(item);
|
||||
}
|
||||
|
||||
--m_indent;
|
||||
return WriteLine().Write("]");
|
||||
}
|
||||
|
||||
JSValueLogWriter &WriteValue(JSValue const &value) noexcept {
|
||||
if (value.IsNull()) {
|
||||
return Write(JSConverter::NullString);
|
||||
} else if (auto objectPtr = value.TryGetObject()) {
|
||||
return WriteObject(*objectPtr);
|
||||
} else if (auto arrayPtr = value.TryGetArray()) {
|
||||
return WriteArray(*arrayPtr);
|
||||
} else if (auto stringPtr = value.TryGetString()) {
|
||||
return WriteQuotedString(*stringPtr);
|
||||
} else if (auto boolPtr = value.TryGetBoolean()) {
|
||||
return Write(JSConverter::ToCString(*boolPtr));
|
||||
} else if (auto int64Ptr = value.TryGetInt64()) {
|
||||
return (m_stream << *int64Ptr, *this);
|
||||
} else if (auto doublePtr = value.TryGetDouble()) {
|
||||
return (JSConverter::WriteJSString(m_stream, *doublePtr), *this);
|
||||
} else {
|
||||
VerifyElseCrashSz(false, "Unexpected JSValue type");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
size_t m_indent{0};
|
||||
std::ostream &m_stream;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
//===========================================================================
|
||||
// JSValueObject implementation
|
||||
//===========================================================================
|
||||
|
||||
JSValueObject::JSValueObject(std::initializer_list<JSValueObjectKeyValue> initObject) noexcept {
|
||||
for (auto const &item : initObject) {
|
||||
this->try_emplace(std::string(item.Key), std::move(*const_cast<JSValue *>(&item.Value)));
|
||||
}
|
||||
}
|
||||
|
||||
JSValueObject::JSValueObject(std::map<std::string, JSValue, std::less<>> &&other) noexcept : map{std::move(other)} {}
|
||||
|
||||
JSValueObject JSValueObject::Copy() const noexcept {
|
||||
JSValueObject object;
|
||||
for (auto const &property : *this) {
|
||||
object.try_emplace(property.first, property.second.Copy());
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
JSValue &JSValueObject::operator[](std::string_view propertyName) noexcept {
|
||||
// When we search for a node we do no want to convert string_view to a string.
|
||||
auto it = lower_bound(propertyName);
|
||||
if (it != end() && !key_comp()(propertyName, it->first)) {
|
||||
return it->second;
|
||||
} else {
|
||||
return emplace_hint(it, propertyName, nullptr)->second;
|
||||
}
|
||||
}
|
||||
|
||||
JSValue const &JSValueObject::operator[](std::string_view propertyName) const noexcept {
|
||||
auto it = find(propertyName);
|
||||
if (it != end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return JSValue::Null;
|
||||
}
|
||||
|
||||
bool JSValueObject::Equals(JSValueObject const &other) const noexcept {
|
||||
if (size() != other.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// std::map keeps key-values in an ordered sequence.
|
||||
// Make sure that pairs are matching at the same position.
|
||||
auto otherIt = other.begin();
|
||||
for (auto const &property : *this) {
|
||||
auto it = otherIt++;
|
||||
if (property.first != it->first || !property.second.Equals(it->second)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSValueObject::JSEquals(JSValueObject const &other) const noexcept {
|
||||
if (size() != other.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// std::map keeps key-values in an ordered sequence.
|
||||
// Make sure that pairs are matching at the same position.
|
||||
auto otherIt = other.begin();
|
||||
for (auto const &property : *this) {
|
||||
auto it = otherIt++;
|
||||
if (property.first != it->first || !property.second.JSEquals(it->second)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*static*/ JSValueObject JSValueObject::ReadFrom(IJSValueReader const &reader) noexcept {
|
||||
JSValueObject object;
|
||||
if (reader.ValueType() == JSValueType::Object) {
|
||||
hstring propertyName;
|
||||
while (reader.GetNextObjectProperty(/*ref*/ propertyName)) {
|
||||
object.try_emplace(to_string(propertyName), JSValue::ReadFrom(reader));
|
||||
}
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
void JSValueObject::WriteTo(IJSValueWriter const &writer) const noexcept {
|
||||
writer.WriteObjectBegin();
|
||||
for (auto const &property : *this) {
|
||||
writer.WritePropertyName(to_hstring(property.first));
|
||||
property.second.WriteTo(writer);
|
||||
}
|
||||
|
||||
writer.WriteObjectEnd();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// JSValueArray implementation
|
||||
//===========================================================================
|
||||
|
||||
JSValueArray::JSValueArray(size_type size) noexcept {
|
||||
reserve(size);
|
||||
for (size_type i = 0; i < size; ++i) {
|
||||
emplace_back(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
JSValueArray::JSValueArray(size_type size, JSValue const &defaultValue) noexcept {
|
||||
reserve(size);
|
||||
for (size_type i = 0; i < size; ++i) {
|
||||
push_back(defaultValue.Copy());
|
||||
}
|
||||
}
|
||||
|
||||
JSValueArray::JSValueArray(std::initializer_list<JSValueArrayItem> initArray) noexcept {
|
||||
for (auto const &item : initArray) {
|
||||
this->push_back(std::move(*const_cast<JSValue *>(&item.Item)));
|
||||
}
|
||||
}
|
||||
|
||||
JSValueArray::JSValueArray(std::vector<JSValue> &&other) noexcept : vector{std::move(other)} {}
|
||||
|
||||
JSValueArray JSValueArray::Copy() const noexcept {
|
||||
JSValueArray array;
|
||||
array.reserve(size());
|
||||
for (auto const &item : *this) {
|
||||
array.push_back(item.Copy());
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
bool JSValueArray::Equals(JSValueArray const &other) const noexcept {
|
||||
if (size() != other.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto otherIt = other.begin();
|
||||
for (auto const &item : *this) {
|
||||
if (!item.Equals(*otherIt++)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JSValueArray::JSEquals(JSValueArray const &other) const noexcept {
|
||||
if (size() != other.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto otherIt = other.begin();
|
||||
for (auto const &item : *this) {
|
||||
if (!item.JSEquals(*otherIt++)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*static*/ JSValueArray JSValueArray::ReadFrom(IJSValueReader const &reader) noexcept {
|
||||
JSValueArray array;
|
||||
if (reader.ValueType() == JSValueType::Array) {
|
||||
while (reader.GetNextArrayItem()) {
|
||||
array.push_back(JSValue::ReadFrom(reader));
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
void JSValueArray::WriteTo(IJSValueWriter const &writer) const noexcept {
|
||||
writer.WriteArrayBegin();
|
||||
for (const JSValue &item : *this) {
|
||||
item.WriteTo(writer);
|
||||
}
|
||||
|
||||
writer.WriteArrayEnd();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// JSValue implementation
|
||||
//===========================================================================
|
||||
|
||||
/*static*/ JSValue const JSValue::Null;
|
||||
/*static*/ JSValue const JSValue::EmptyObject{JSValueObject{}};
|
||||
/*static*/ JSValue const JSValue::EmptyArray{JSValueArray{}};
|
||||
/*static*/ JSValue const JSValue::EmptyString{std::string{}};
|
||||
|
||||
#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:
|
||||
new (&m_object) JSValueObject(std::move(other.m_object));
|
||||
break;
|
||||
case JSValueType::Array:
|
||||
new (&m_array) JSValueArray(std::move(other.m_array));
|
||||
break;
|
||||
case JSValueType::String:
|
||||
new (&m_string) std::string(std::move(other.m_string));
|
||||
break;
|
||||
case JSValueType::Boolean:
|
||||
m_bool = other.m_bool;
|
||||
break;
|
||||
case JSValueType::Int64:
|
||||
m_int64 = other.m_int64;
|
||||
break;
|
||||
case JSValueType::Double:
|
||||
m_double = other.m_double;
|
||||
break;
|
||||
}
|
||||
|
||||
other.m_type = JSValueType::Null;
|
||||
other.m_int64 = 0;
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
||||
JSValue::~JSValue() noexcept {
|
||||
switch (m_type) {
|
||||
case JSValueType::Object:
|
||||
m_object.~JSValueObject();
|
||||
break;
|
||||
case JSValueType::Array:
|
||||
m_array.~JSValueArray();
|
||||
break;
|
||||
case JSValueType::String:
|
||||
m_string.~basic_string();
|
||||
break;
|
||||
case JSValueType::Boolean:
|
||||
case JSValueType::Int64:
|
||||
case JSValueType::Double:
|
||||
case JSValueType::Null:
|
||||
break;
|
||||
}
|
||||
|
||||
m_type = JSValueType::Null;
|
||||
m_int64 = 0;
|
||||
}
|
||||
|
||||
JSValue &JSValue::operator=(JSValue &&other) noexcept {
|
||||
if (this != &other) {
|
||||
this->~JSValue();
|
||||
new (this) JSValue(std::move(other));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSValue JSValue::Copy() const noexcept {
|
||||
switch (m_type) {
|
||||
case JSValueType::Object:
|
||||
return JSValue{m_object.Copy()};
|
||||
case JSValueType::Array:
|
||||
return JSValue{m_array.Copy()};
|
||||
case JSValueType::String:
|
||||
return JSValue{std::string(m_string)};
|
||||
case JSValueType::Boolean:
|
||||
return JSValue{m_bool};
|
||||
case JSValueType::Int64:
|
||||
return JSValue{m_int64};
|
||||
case JSValueType::Double:
|
||||
return JSValue{m_double};
|
||||
default:
|
||||
return JSValue{};
|
||||
}
|
||||
}
|
||||
|
||||
JSValueObject JSValue::MoveObject() noexcept {
|
||||
JSValueObject result;
|
||||
if (m_type == JSValueType::Object) {
|
||||
result = std::move(m_object);
|
||||
m_type = JSValueType::Null;
|
||||
m_int64 = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
JSValueArray JSValue::MoveArray() noexcept {
|
||||
JSValueArray result;
|
||||
if (m_type == JSValueType::Array) {
|
||||
result = std::move(m_array);
|
||||
m_type = JSValueType::Null;
|
||||
m_int64 = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string JSValue::AsString() const noexcept {
|
||||
switch (m_type) {
|
||||
case JSValueType::Null:
|
||||
return JSConverter::NullString;
|
||||
case JSValueType::String:
|
||||
return m_string;
|
||||
case JSValueType::Boolean:
|
||||
return JSConverter::ToCString(m_bool);
|
||||
case JSValueType::Int64:
|
||||
return std::to_string(m_int64);
|
||||
case JSValueType::Double:
|
||||
return JSConverter::ToJSString(m_double);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
bool JSValue::AsBoolean() const noexcept {
|
||||
switch (m_type) {
|
||||
case JSValueType::Object:
|
||||
return !m_object.empty();
|
||||
case JSValueType::Array:
|
||||
return !m_array.empty();
|
||||
case JSValueType::String:
|
||||
return JSConverter::ToBoolean(m_string);
|
||||
case JSValueType::Boolean:
|
||||
return m_bool;
|
||||
case JSValueType::Int64:
|
||||
return m_int64 != 0;
|
||||
case JSValueType::Double:
|
||||
return !std::isnan(m_double) && m_double != 0;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t JSValue::AsInt64() const noexcept {
|
||||
switch (m_type) {
|
||||
case JSValueType::String:
|
||||
return JSConverter::ToInt64(JSConverter::ToJSNumber(m_string));
|
||||
case JSValueType::Boolean:
|
||||
return m_bool ? 1 : 0;
|
||||
case JSValueType::Int64:
|
||||
return m_int64;
|
||||
case JSValueType::Double:
|
||||
return JSConverter::ToInt64(m_double);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
double JSValue::AsDouble() const noexcept {
|
||||
switch (m_type) {
|
||||
case JSValueType::String:
|
||||
return JSConverter::ToJSNumber(m_string);
|
||||
case JSValueType::Boolean:
|
||||
return m_bool ? 1 : 0;
|
||||
case JSValueType::Int64:
|
||||
return static_cast<double>(m_int64);
|
||||
case JSValueType::Double:
|
||||
return m_double;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string JSValue::AsJSString() const noexcept {
|
||||
struct JSStringWriter {
|
||||
static std::ostream &Write(std::ostream &os, JSValue const &node) noexcept {
|
||||
switch (node.m_type) {
|
||||
case JSValueType::Null:
|
||||
return os << JSConverter::NullString;
|
||||
case JSValueType::Object:
|
||||
return os << JSConverter::ObjectString;
|
||||
case JSValueType::Array: {
|
||||
bool start = true;
|
||||
for (auto const &item : node.m_array) {
|
||||
if (start) {
|
||||
start = false;
|
||||
} else {
|
||||
os << ",";
|
||||
}
|
||||
|
||||
JSStringWriter::Write(os, item);
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
case JSValueType::String:
|
||||
return os << node.m_string;
|
||||
case JSValueType::Boolean:
|
||||
return os << JSConverter::ToCString(node.m_bool);
|
||||
case JSValueType::Int64:
|
||||
return os << node.m_int64;
|
||||
case JSValueType::Double:
|
||||
return JSConverter::WriteJSString(os, node.m_double);
|
||||
default:
|
||||
return os;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
switch (m_type) {
|
||||
case JSValueType::Null:
|
||||
return JSConverter::NullString;
|
||||
case JSValueType::Object:
|
||||
return JSConverter::ObjectString;
|
||||
case JSValueType::Array: {
|
||||
std::stringstream stream;
|
||||
JSStringWriter::Write(stream, *this);
|
||||
return stream.str();
|
||||
}
|
||||
case JSValueType::String:
|
||||
return m_string;
|
||||
case JSValueType::Boolean:
|
||||
return JSConverter::ToCString(m_bool);
|
||||
case JSValueType::Int64:
|
||||
return std::to_string(m_int64);
|
||||
case JSValueType::Double:
|
||||
return JSConverter::ToJSString(m_double);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
bool JSValue::AsJSBoolean() const noexcept {
|
||||
switch (m_type) {
|
||||
case JSValueType::Object:
|
||||
case JSValueType::Array:
|
||||
return true;
|
||||
case JSValueType::String:
|
||||
return !m_string.empty();
|
||||
case JSValueType::Boolean:
|
||||
return m_bool;
|
||||
case JSValueType::Int64:
|
||||
return m_int64 != 0;
|
||||
case JSValueType::Double:
|
||||
return !std::isnan(m_double) && m_double != 0;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
double JSValue::AsJSNumber() const noexcept {
|
||||
switch (m_type) {
|
||||
case JSValueType::Object:
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
case JSValueType::Array:
|
||||
switch (m_array.size()) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return JSConverter::ToJSNumber(m_array[0].AsJSString());
|
||||
default:
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
case JSValueType::String:
|
||||
return JSConverter::ToJSNumber(m_string);
|
||||
case JSValueType::Boolean:
|
||||
return m_bool ? 1 : 0;
|
||||
case JSValueType::Int64:
|
||||
return static_cast<double>(m_int64);
|
||||
case JSValueType::Double:
|
||||
return m_double;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string JSValue::ToString() const noexcept {
|
||||
switch (m_type) {
|
||||
case JSValueType::Null:
|
||||
return JSConverter::NullString;
|
||||
case JSValueType::Object:
|
||||
case JSValueType::Array:
|
||||
case JSValueType::String:
|
||||
return JSValueLogWriter::ToString(*this);
|
||||
case JSValueType::Boolean:
|
||||
return JSConverter::ToJSString(m_bool);
|
||||
case JSValueType::Int64:
|
||||
return std::to_string(m_int64);
|
||||
case JSValueType::Double:
|
||||
return JSConverter::ToJSString(m_double);
|
||||
default:
|
||||
VerifyElseCrashSz(false, "Unexpected JSValue type");
|
||||
}
|
||||
}
|
||||
|
||||
size_t JSValue::PropertyCount() const noexcept {
|
||||
return (m_type == JSValueType::Object) ? m_object.size() : 0;
|
||||
}
|
||||
|
||||
JSValue const *JSValue::TryGetObjectProperty(std::string_view propertyName) const noexcept {
|
||||
if (m_type == JSValueType::Object) {
|
||||
auto it = m_object.find(propertyName);
|
||||
if (it != m_object.end()) {
|
||||
return &it->second;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSValue const &JSValue::GetObjectProperty(std::string_view propertyName) const noexcept {
|
||||
auto result = TryGetObjectProperty(propertyName);
|
||||
return result ? *result : Null;
|
||||
}
|
||||
|
||||
size_t JSValue::ItemCount() const noexcept {
|
||||
return (m_type == JSValueType::Array) ? m_array.size() : 0;
|
||||
}
|
||||
|
||||
JSValue const *JSValue::TryGetArrayItem(JSValueArray::size_type index) const noexcept {
|
||||
return (m_type == JSValueType::Array && index < m_array.size()) ? &m_array[index] : nullptr;
|
||||
}
|
||||
|
||||
JSValue const &JSValue::GetArrayItem(JSValueArray::size_type index) const noexcept {
|
||||
auto result = TryGetArrayItem(index);
|
||||
return result ? *result : Null;
|
||||
}
|
||||
|
||||
bool JSValue::Equals(JSValue const &other) const noexcept {
|
||||
if (m_type != other.m_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (m_type) {
|
||||
case JSValueType::Null:
|
||||
return true;
|
||||
case JSValueType::Object:
|
||||
return m_object.Equals(other.m_object);
|
||||
case JSValueType::Array:
|
||||
return m_array.Equals(other.m_array);
|
||||
case JSValueType::String:
|
||||
return m_string == other.m_string;
|
||||
case JSValueType::Boolean:
|
||||
return m_bool == other.m_bool;
|
||||
case JSValueType::Int64:
|
||||
return m_int64 == other.m_int64;
|
||||
case JSValueType::Double:
|
||||
return m_double == other.m_double;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool JSValue::JSEquals(JSValue const &other) const noexcept {
|
||||
if (m_type == other.m_type) {
|
||||
switch (m_type) {
|
||||
case JSValueType::Object:
|
||||
return m_object.JSEquals(other.m_object);
|
||||
case JSValueType::Array:
|
||||
return m_array.JSEquals(other.m_array);
|
||||
default:
|
||||
return Equals(other);
|
||||
}
|
||||
} else if (m_type == JSValueType::Null || other.m_type == JSValueType::Null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If one of the types Boolean, Int64, or Double, then compare as Numbers,
|
||||
// otherwise compare as strings.
|
||||
JSValueType const greatestType = m_type > other.m_type ? m_type : other.m_type;
|
||||
if (greatestType >= JSValueType::Boolean) {
|
||||
return AsJSNumber() == other.AsJSNumber();
|
||||
} else {
|
||||
return AsJSString() == other.AsJSString();
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ JSValue JSValue::ReadFrom(IJSValueReader const &reader) noexcept {
|
||||
switch (reader.ValueType()) {
|
||||
case JSValueType::Null:
|
||||
return JSValue();
|
||||
case JSValueType::Object:
|
||||
return JSValue(JSValueObject::ReadFrom(reader));
|
||||
case JSValueType::Array:
|
||||
return JSValue(JSValueArray::ReadFrom(reader));
|
||||
case JSValueType::String:
|
||||
return JSValue(to_string(reader.GetString()));
|
||||
case JSValueType::Boolean:
|
||||
return JSValue(reader.GetBoolean());
|
||||
case JSValueType::Int64:
|
||||
return JSValue(reader.GetInt64());
|
||||
case JSValueType::Double:
|
||||
return JSValue(reader.GetDouble());
|
||||
default:
|
||||
VerifyElseCrashSz(false, "Unexpected JSValue type");
|
||||
}
|
||||
}
|
||||
|
||||
void JSValue::WriteTo(IJSValueWriter const &writer) const noexcept {
|
||||
switch (m_type) {
|
||||
case JSValueType::Null:
|
||||
return writer.WriteNull();
|
||||
case JSValueType::Object:
|
||||
return m_object.WriteTo(writer);
|
||||
case JSValueType::Array:
|
||||
return m_array.WriteTo(writer);
|
||||
case JSValueType::String:
|
||||
return writer.WriteString(to_hstring(m_string));
|
||||
case JSValueType::Boolean:
|
||||
return writer.WriteBoolean(m_bool);
|
||||
case JSValueType::Int64:
|
||||
return writer.WriteInt64(m_int64);
|
||||
case JSValueType::Double:
|
||||
return writer.WriteDouble(m_double);
|
||||
default:
|
||||
VerifyElseCrashSz(false, "Unexpected JSValue type");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
|
@ -0,0 +1,929 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#ifndef MICROSOFT_REACTNATIVE_JSVALUE
|
||||
#define MICROSOFT_REACTNATIVE_JSVALUE
|
||||
|
||||
#include "Crash.h"
|
||||
#include "winrt/Microsoft.ReactNative.h"
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
//==============================================================================
|
||||
// Forward declarations.
|
||||
//==============================================================================
|
||||
|
||||
struct JSValue;
|
||||
struct JSValueObjectKeyValue;
|
||||
struct JSValueArrayItem;
|
||||
IJSValueReader MakeJSValueTreeReader(JSValue const &root) noexcept;
|
||||
IJSValueReader MakeJSValueTreeReader(JSValue &&root) noexcept;
|
||||
IJSValueWriter MakeJSValueTreeWriter() noexcept;
|
||||
JSValue TakeJSValue(IJSValueWriter const &writer) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
// JSValueObject declaration.
|
||||
//==============================================================================
|
||||
|
||||
//! JSValueObject is based on std::map and has a custom constructor with std::intializer_list.
|
||||
//! It is possible to write: JSValueObject{{"X", 4}, {"Y", 5}} and assign it to JSValue.
|
||||
//! It uses the std::less<> comparison algorithm that allows an efficient
|
||||
//! key lookup using std::string_view that does not allocate memory for the std::string key.
|
||||
struct JSValueObject : std::map<std::string, JSValue, std::less<>> {
|
||||
//! Default constructor.
|
||||
JSValueObject() = default;
|
||||
|
||||
//! Construct JSValueObject from the move iterator.
|
||||
template <class TMoveInputIterator>
|
||||
JSValueObject(TMoveInputIterator first, TMoveInputIterator last) noexcept;
|
||||
|
||||
//! Move-construct JSValueObject from the initializer list.
|
||||
JSValueObject(std::initializer_list<JSValueObjectKeyValue> initObject) noexcept;
|
||||
|
||||
//! Move-construct JSValueObject from the string-JSValue map.
|
||||
JSValueObject(std::map<std::string, JSValue, std::less<>> &&other) noexcept;
|
||||
|
||||
//! Delete copy constructor to avoid unexpected copies. Use the Copy method instead.
|
||||
JSValueObject(JSValueObject const &) = delete;
|
||||
|
||||
// Default move constructor.
|
||||
JSValueObject(JSValueObject &&) = default;
|
||||
|
||||
//! Delete copy assignment to avoid unexpected copies. Use the Copy method instead.
|
||||
JSValueObject &operator=(JSValueObject const &) = delete;
|
||||
|
||||
// Default move assignment.
|
||||
JSValueObject &operator=(JSValueObject &&) = default;
|
||||
|
||||
//! Do a deep copy of JSValueObject.
|
||||
JSValueObject Copy() const noexcept;
|
||||
|
||||
//! Get a reference to object property value if the property is found,
|
||||
//! or a reference to a new property created with JSValue::Null value otherwise.
|
||||
JSValue &operator[](std::string_view propertyName) noexcept;
|
||||
|
||||
//! Get a reference to object property value if the property is found,
|
||||
//! or a reference to JSValue::Null otherwise.
|
||||
JSValue const &operator[](std::string_view propertyName) const noexcept;
|
||||
|
||||
//! Return true if this JSValueObject is strictly equal to other JSValueObject.
|
||||
//! Both objects must have the same set of equal properties.
|
||||
//! Property values must be equal.
|
||||
bool Equals(JSValueObject const &other) const noexcept;
|
||||
|
||||
//! Return true if this JSValueObject is strictly equal to other JSValueObject
|
||||
//! after their property values are converted to the same type.
|
||||
//! See JSValue::JSEquals for details about the conversion.
|
||||
bool JSEquals(JSValueObject const &other) const noexcept;
|
||||
|
||||
//! Create JSValueObject from IJSValueReader.
|
||||
static JSValueObject ReadFrom(IJSValueReader const &reader) noexcept;
|
||||
|
||||
//! Write this JSValueObject to IJSValueWriter.
|
||||
void WriteTo(IJSValueWriter const &writer) const noexcept;
|
||||
|
||||
#pragma region Deprecated methods
|
||||
|
||||
[[deprecated("Use JSEquals")]] bool EqualsAfterConversion(JSValueObject const &other) const noexcept;
|
||||
|
||||
#pragma endregion
|
||||
};
|
||||
|
||||
//! True if left.Equals(right)
|
||||
bool operator==(JSValueObject const &left, JSValueObject const &right) noexcept;
|
||||
|
||||
//! True if !left.Equals(right)
|
||||
bool operator!=(JSValueObject const &left, JSValueObject const &right) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
// JSValueArray declaration.
|
||||
//==============================================================================
|
||||
|
||||
//! JSValueArray is based on std::vector<JSValue> and has a custom constructor with std::intializer_list.
|
||||
//! It is possible to write: JSValueArray{"X", 42, nullptr, true} and assign it to JSValue.
|
||||
struct JSValueArray : std::vector<JSValue> {
|
||||
//! Default constructor.
|
||||
JSValueArray() = default;
|
||||
|
||||
//! Constructs JSValueArray with 'size' count of JSValue::Null elements.
|
||||
explicit JSValueArray(size_type size) noexcept;
|
||||
|
||||
//! Constructs JSValueArray with 'size' count elements.
|
||||
//! Each element is a copy of defaultValue.
|
||||
JSValueArray(size_type size, JSValue const &defaultValue) noexcept;
|
||||
|
||||
//! Construct JSValueArray from the move iterator.
|
||||
template <class TMoveInputIterator, std::enable_if_t<!std::is_integral_v<TMoveInputIterator>, int> = 1>
|
||||
JSValueArray(TMoveInputIterator first, TMoveInputIterator last) noexcept;
|
||||
|
||||
//! Move-construct JSValueArray from the initializer list.
|
||||
JSValueArray(std::initializer_list<JSValueArrayItem> initObject) noexcept;
|
||||
|
||||
//! Move-construct JSValueArray from the JSValue vector.
|
||||
JSValueArray(std::vector<JSValue> &&other) noexcept;
|
||||
|
||||
//! Delete copy constructor to avoid unexpected copies. Use the Copy method instead.
|
||||
JSValueArray(JSValueArray const &) = delete;
|
||||
|
||||
// Default move constructor.
|
||||
JSValueArray(JSValueArray &&) = default;
|
||||
|
||||
//! Delete copy assignment to avoid unexpected copies. Use the Copy method instead.
|
||||
JSValueArray &operator=(JSValueArray const &) = delete;
|
||||
|
||||
// Default move assignment.
|
||||
JSValueArray &operator=(JSValueArray &&) = default;
|
||||
|
||||
//! Do a deep copy of JSValueArray.
|
||||
JSValueArray Copy() const noexcept;
|
||||
|
||||
//! Return true if this JSValueArray is strictly equal to other JSValueArray.
|
||||
//! Both arrays must have the same set of items. Items must have the same type and value.
|
||||
bool Equals(JSValueArray const &other) const noexcept;
|
||||
|
||||
//! Return true if this JSValueArray is strictly equal to other JSValueArray
|
||||
//! after their items are converted to the same type.
|
||||
//! See JSValue::JSEquals for details about the conversion.
|
||||
bool JSEquals(JSValueArray const &other) const noexcept;
|
||||
|
||||
//! Create JSValueArray from IJSValueReader.
|
||||
static JSValueArray ReadFrom(IJSValueReader const &reader) noexcept;
|
||||
|
||||
//! Write this JSValueArray to IJSValueWriter.
|
||||
void WriteTo(IJSValueWriter const &writer) const noexcept;
|
||||
|
||||
#pragma region Deprecated methods
|
||||
|
||||
[[deprecated("Use JSEquals")]] bool EqualsAfterConversion(JSValueArray const &other) const noexcept;
|
||||
|
||||
#pragma endregion
|
||||
};
|
||||
|
||||
//! True if left.Equals(right)
|
||||
bool operator==(JSValueArray const &left, JSValueArray const &right) noexcept;
|
||||
|
||||
//! True if !left.Equals(right)
|
||||
bool operator!=(JSValueArray const &left, JSValueArray const &right) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
// JSValue declaration.
|
||||
//==============================================================================
|
||||
|
||||
//! JSValue represents an immutable JavaScript value that can be passed as a parameter.
|
||||
//! It is created to simplify working with IJSValueReader in some complex cases.
|
||||
//! It takes more resources than direct use of IJSValueReader, but provides more flexibility.
|
||||
//! The JSValue is an immutable and is safe to be used from multiple threads.
|
||||
//! It is move-only to avoid unnecessary or unexpected copying of values.
|
||||
//! For copy operations the explicit Copy() method must be used.
|
||||
//! Note that the move operations are not thread safe.
|
||||
struct JSValue {
|
||||
//! JSValue with JSValueType::Null.
|
||||
static JSValue const Null;
|
||||
|
||||
//! JSValue with empty object.
|
||||
static JSValue const EmptyObject;
|
||||
|
||||
//! JSValue with empty array.
|
||||
static JSValue const EmptyArray;
|
||||
|
||||
//! JSValue with empty string.
|
||||
static JSValue const EmptyString;
|
||||
|
||||
//! Create a Null JSValue.
|
||||
JSValue() noexcept;
|
||||
|
||||
//! Create a Null JSValue.
|
||||
JSValue(std::nullptr_t) noexcept;
|
||||
|
||||
//! Create an Object JSValue.
|
||||
JSValue(JSValueObject &&value) noexcept;
|
||||
|
||||
//! Create an Array JSValue.
|
||||
JSValue(JSValueArray &&value) noexcept;
|
||||
|
||||
//! Create a String JSValue.
|
||||
JSValue(std::string &&value) noexcept;
|
||||
|
||||
//! Create a String JSValue from any type that can be converted to std::string_view.
|
||||
template <class TStringView, std::enable_if_t<std::is_convertible_v<TStringView, std::string_view>, int> = 1>
|
||||
JSValue(TStringView value) noexcept;
|
||||
|
||||
//! Create a Boolean JSValue.
|
||||
template <class TBool, std::enable_if_t<std::is_same_v<TBool, bool>, int> = 1>
|
||||
JSValue(TBool value) noexcept;
|
||||
|
||||
//! Create an Int64 JSValue from any integral type except bool.
|
||||
template <class TInt, std::enable_if_t<std::is_integral_v<TInt> && !std::is_same_v<TInt, bool>, int> = 1>
|
||||
JSValue(TInt value) noexcept;
|
||||
|
||||
//! Create a Double JSValue.
|
||||
JSValue(double value) noexcept;
|
||||
|
||||
//! Delete the copy constructor to avoid unexpected copies. Use the Copy method instead.
|
||||
JSValue(const JSValue &other) = delete;
|
||||
|
||||
//! Move constructor. The 'other' JSValue becomes JSValue::Null.
|
||||
JSValue(JSValue &&other) noexcept;
|
||||
|
||||
//! Destroys JSValue.
|
||||
~JSValue() noexcept;
|
||||
|
||||
//! Delete the copy assignment to avoid unexpected copies. Use the Copy method instead.
|
||||
JSValue &operator=(JSValue const &other) = delete;
|
||||
|
||||
//! Move assignment. The 'other' JSValue becomes JSValue::Null.
|
||||
JSValue &operator=(JSValue &&other) noexcept;
|
||||
|
||||
//! Do a deep copy of JSValue.
|
||||
JSValue Copy() const noexcept;
|
||||
|
||||
//! Move out Object and set this to JSValue::Null. It returns JSValue::EmptyObject
|
||||
//! and keeps this JSValue unchanged if current type is not an object.
|
||||
JSValueObject MoveObject() noexcept;
|
||||
|
||||
//! Move out Array and set this to JSValue::Null. It returns JSValue::EmptyArray
|
||||
//! and keeps this JSValue unchanged if current type is not an array.
|
||||
JSValueArray MoveArray() noexcept;
|
||||
|
||||
//! Get JSValue type.
|
||||
JSValueType Type() const noexcept;
|
||||
|
||||
//! Return true if JSValue type is Null.
|
||||
bool IsNull() const noexcept;
|
||||
|
||||
//! Return pointer to JSValueObject if JSValue type is Object, or nullptr otherwise.
|
||||
JSValueObject const *TryGetObject() const noexcept;
|
||||
|
||||
//! Return pointer to JSValueArray if JSValue type is Array, or nullptr otherwise.
|
||||
JSValueArray const *TryGetArray() const noexcept;
|
||||
|
||||
//! Return pointer to string if JSValue type is String, or nullptr otherwise.
|
||||
std::string const *TryGetString() const noexcept;
|
||||
|
||||
//! Return pointer to bool value if JSValue type is Boolean, or nullptr otherwise.
|
||||
bool const *TryGetBoolean() const noexcept;
|
||||
|
||||
//! Return pointer to int64_t value if JSValue type is Int64, or nullptr otherwise.
|
||||
int64_t const *TryGetInt64() const noexcept;
|
||||
|
||||
//! Return pointer to double value if JSValue type is Double, or nullptr otherwise.
|
||||
double const *TryGetDouble() const noexcept;
|
||||
|
||||
//! Return Object representation of JSValue. It is JSValue::EmptyObject if type is not Object.
|
||||
JSValueObject const &AsObject() const noexcept;
|
||||
|
||||
//! Return Array representation of JSValue. It is JSValue::EmptyArray if type is not Object.
|
||||
JSValueArray const &AsArray() const noexcept;
|
||||
|
||||
//! Return a string representation of JSValue.
|
||||
//! Null is "null".
|
||||
//! Object and Array are empty strings "".
|
||||
//! Boolean is "true" or "false".
|
||||
//! Int64 is converted to string using integer representation.
|
||||
//! Double uses AsJSString() conversion which uses "NaN", "Infinity", and "-Infinity" for special values.
|
||||
std::string AsString() const noexcept;
|
||||
|
||||
//! Return a Boolean representation of JSValue.
|
||||
//! Object and Array are true if they are not empty.
|
||||
//! String is true if it case-insensitively matches "true", "1", "yes", "y", or "on" strings.
|
||||
//! Int64 or Double are false if they are zero or NAN.
|
||||
bool AsBoolean() const noexcept;
|
||||
|
||||
//! Return an int8_t representation of JSValue. It is the same as (int8_t)AsInt64().
|
||||
int8_t AsInt8() const noexcept;
|
||||
|
||||
//! Return an int16_t representation of JSValue. It is the same as (int16_t)AsInt64().
|
||||
int16_t AsInt16() const noexcept;
|
||||
|
||||
//! Return an int32_t representation of JSValue. It is the same as (int32_t)AsInt64().
|
||||
int32_t AsInt32() const noexcept;
|
||||
|
||||
//! Return an int64_t representation of JSValue.
|
||||
//! String is converted to double first before converting to Int64.
|
||||
//! Boolean is converted to 0 or 1.
|
||||
int64_t AsInt64() const noexcept;
|
||||
|
||||
//! Return an uint8_t representation of JSValue. It is the same as (uint8_t)AsInt64().
|
||||
uint8_t AsUInt8() const noexcept;
|
||||
|
||||
//! Return an uint16_t representation of JSValue. It is the same as (uint16_t)AsInt64().
|
||||
uint16_t AsUInt16() const noexcept;
|
||||
|
||||
//! Return an uint32_t representation of JSValue. It is the same as (uint32_t)AsInt64().
|
||||
uint32_t AsUInt32() const noexcept;
|
||||
|
||||
//! Return an uint64_t representation of JSValue. It is the same as (uint64_t)AsInt64().
|
||||
uint64_t AsUInt64() const noexcept;
|
||||
|
||||
//! Return a float representation of JSValue. It is the same as (float)AsDouble().
|
||||
float AsSingle() const noexcept;
|
||||
|
||||
//! Return a double representation of JSValue.
|
||||
//! Boolean is converted to 0.0 or 1.0.
|
||||
//! Null, Object, and Array are 0.
|
||||
double AsDouble() const noexcept;
|
||||
|
||||
//! Cast JSValue to std::string using AsString() call.
|
||||
explicit operator std::string() const noexcept;
|
||||
|
||||
//! Cast JSValue to bool using AsBoolean() call.
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
//! Cast JSValue to int8_t using AsInt8() call.
|
||||
explicit operator int8_t() const noexcept;
|
||||
|
||||
//! Cast JSValue to int16_t using AsInt16() call.
|
||||
explicit operator int16_t() const noexcept;
|
||||
|
||||
//! Cast JSValue to int32_t using AsInt32() call.
|
||||
explicit operator int32_t() const noexcept;
|
||||
|
||||
//! Cast JSValue to int64_t using AsInt64() call.
|
||||
explicit operator int64_t() const noexcept;
|
||||
|
||||
//! Cast JSValue to uint8_t using AsUInt8() call.
|
||||
explicit operator uint8_t() const noexcept;
|
||||
|
||||
//! Cast JSValue to uint16_t using AsUInt16() call.
|
||||
explicit operator uint16_t() const noexcept;
|
||||
|
||||
//! Cast JSValue to uint32_t using AsUInt32() call.
|
||||
explicit operator uint32_t() const noexcept;
|
||||
|
||||
//! Cast JSValue to uint64_t using AsUInt64() call.
|
||||
explicit operator uint64_t() const noexcept;
|
||||
|
||||
//! Cast JSValue to float using (float)AsDouble() call.
|
||||
explicit operator float() const noexcept;
|
||||
|
||||
//! Cast JSValue to double using AsDouble() call.
|
||||
explicit operator double() const noexcept;
|
||||
|
||||
//! Return a string representation of JSValue. It is equivalent to JavaScript String(value) result.
|
||||
std::string AsJSString() const noexcept;
|
||||
|
||||
//! Return a bool representation of JSValue. It is equivalent to JavaScript Boolean(value) result.
|
||||
bool AsJSBoolean() const noexcept;
|
||||
|
||||
//! Return a Double representation of JSValue. It is equivalent to JavaScript Number(value) result.
|
||||
double AsJSNumber() const noexcept;
|
||||
|
||||
//! Convert JSValue to a readable string that can be used for logging.
|
||||
std::string ToString() const noexcept;
|
||||
|
||||
//! Return value T that is created from JSValue using the ReadValue function override.
|
||||
//! Default T is constructed by using default constructor.
|
||||
template <
|
||||
class T,
|
||||
std::enable_if_t<std::is_default_constructible_v<T> && !std::is_constructible_v<T, std::nullptr_t>, int> = 0>
|
||||
T To() const noexcept;
|
||||
|
||||
//! Return value T that is created from JSValue using the ReadValue function override.
|
||||
//! Default T is constructed by using constructor that receives nullptr as a parameter.
|
||||
template <class T, std::enable_if_t<std::is_constructible_v<T, std::nullptr_t>, int> = 0>
|
||||
T To() const noexcept;
|
||||
|
||||
//! Return value T that is created from JSValue using the ReadValue function override.
|
||||
//! Default T is constructed from the provided 'default' value.
|
||||
template <class T>
|
||||
T To(T &&defaultValue) const noexcept;
|
||||
|
||||
//! Create JSValue from a type that has WriteValue method defined to write to IJSValueWriter.
|
||||
template <class T>
|
||||
static JSValue From(T const &value) noexcept;
|
||||
|
||||
//! Return property count if JSValue is Object, or 0 otherwise.
|
||||
size_t PropertyCount() const noexcept;
|
||||
|
||||
//! Get a pointer to object property value if JSValue type is Object and the property is found,
|
||||
//! or nullptr otherwise.
|
||||
JSValue const *TryGetObjectProperty(std::string_view propertyName) const noexcept;
|
||||
|
||||
//! Get a reference to object property value if JSValue type is Object and the property is found,
|
||||
//! or a reference to JSValue::Null otherwise.
|
||||
JSValue const &GetObjectProperty(std::string_view propertyName) const noexcept;
|
||||
|
||||
//! Get a reference to object property value if JSValue type is Object and the property is found,
|
||||
//! or a reference to JSValue::Null otherwise.
|
||||
JSValue const &operator[](std::string_view propertyName) const noexcept;
|
||||
|
||||
//! Return item count if JSValue is Array, or 0 otherwise.
|
||||
size_t ItemCount() const noexcept;
|
||||
|
||||
//! Get a pointer to array item if JSValue type is Array and the index is in bounds,
|
||||
//! or nullptr otherwise.
|
||||
JSValue const *TryGetArrayItem(JSValueArray::size_type index) const noexcept;
|
||||
|
||||
//! Get a reference to array item if JSValue type is Array and the index is in bounds,
|
||||
//! or a reference to JSValue::Null otherwise.
|
||||
JSValue const &GetArrayItem(JSValueArray::size_type index) const noexcept;
|
||||
|
||||
//! Get a reference to array item if JSValue type is Array and the index is in bounds,
|
||||
//! or a reference to JSValue::Null otherwise.
|
||||
JSValue const &operator[](JSValueArray::size_type index) const noexcept;
|
||||
|
||||
//! Return true if this JSValue is strictly equal to JSValue.
|
||||
//! Compared values must have the same type and value.
|
||||
//!
|
||||
//! The behavior is similar to JavaScript === operator except for Object and Array where
|
||||
//! this functions does a deep structured comparison instead of pointer equality.
|
||||
bool Equals(JSValue const &other) const noexcept;
|
||||
|
||||
//! Return true if this JSValue is strictly equal to JSValue after they are converted to the same type.
|
||||
//!
|
||||
//! Null is not converted to any other type before comparison.
|
||||
//! Object and Array types are converted first to a String type using AsString() before comparing
|
||||
//! with other types, and then we apply the same rules as for the String type.
|
||||
//! String is converted to Double before comparing with Boolean, Int64, or Double.
|
||||
//! Boolean is converted to 1.0 and +0.0 when comparing with String, Int64, or Double.
|
||||
//! Int64 is converted to Double before comparing with other types.
|
||||
//!
|
||||
//! The behavior is similar to JavaScript == operator except for Object and Array for which
|
||||
//! this functions does a deep structured comparison using JSEquals instead
|
||||
//! of pointer equality.
|
||||
bool JSEquals(JSValue const &other) const noexcept;
|
||||
|
||||
//! Create JSValue from IJSValueReader.
|
||||
static JSValue ReadFrom(IJSValueReader const &reader) noexcept;
|
||||
|
||||
//! Create JSValueObject from IJSValueReader.
|
||||
static JSValueObject ReadObjectFrom(IJSValueReader const &reader) noexcept;
|
||||
|
||||
//! Create JSValueArray from IJSValueReader.
|
||||
static JSValueArray ReadArrayFrom(IJSValueReader const &reader) noexcept;
|
||||
|
||||
//! Write this JSValue to IJSValueWriter.
|
||||
void WriteTo(IJSValueWriter const &writer) const noexcept;
|
||||
|
||||
#pragma region Deprecated methods
|
||||
|
||||
// The methods below are deprecated in favor of other methods with clearer semantic
|
||||
[[deprecated("Use TryGetObject or AsObject")]] JSValueObject const &Object() const noexcept;
|
||||
[[deprecated("Use TryGetArray or As Array")]] JSValueArray const &Array() const noexcept;
|
||||
[[deprecated("Use TryGetString, AsString, or AsJSString")]] std::string const &String() const noexcept;
|
||||
[[deprecated("Use TryGetBoolean, AsBoolean, or AsJSBoolean")]] bool Boolean() const noexcept;
|
||||
[[deprecated("Use TryGetInt64, AsInt64, or AsJSNumber")]] int64_t Int64() const noexcept;
|
||||
[[deprecated("Use TryGetDouble, AsDouble, or AsJSNumber")]] double Double() const noexcept;
|
||||
|
||||
// We have renamed or moved the methods below.
|
||||
template <class T>
|
||||
[[deprecated("Use JSValue::To")]] T As() const noexcept;
|
||||
template <class T>
|
||||
[[deprecated("Use JSValue::To")]] T As(T &&defaultValue) const noexcept;
|
||||
[[deprecated("Use MoveObject")]] JSValueObject TakeObject() noexcept;
|
||||
[[deprecated("Use MoveArray")]] JSValueArray TakeArray() noexcept;
|
||||
[[deprecated("Use JSValueObject::Copy")]] static JSValueObject CopyObject(JSValueObject const &other) noexcept;
|
||||
[[deprecated("Use JSValueArray::Copy")]] static JSValueArray CopyArray(JSValueArray const &other) noexcept;
|
||||
[[deprecated("Use JSValueObject::WriteTo")]] static void WriteObjectTo(
|
||||
IJSValueWriter const &writer,
|
||||
JSValueObject const &value) noexcept;
|
||||
[[deprecated("Use JSValueArray::WriteTo")]] static void WriteArrayTo(
|
||||
IJSValueWriter const &writer,
|
||||
JSValueArray const &value) noexcept;
|
||||
[[deprecated("Use JSEquals")]] bool EqualsAfterConversion(JSValue const &other) const noexcept;
|
||||
[[deprecated("Use AsSingle")]] float AsFloat() const noexcept;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
private: // Instance fields
|
||||
JSValueType m_type;
|
||||
union {
|
||||
JSValueObject m_object;
|
||||
JSValueArray m_array;
|
||||
std::string m_string;
|
||||
bool m_bool;
|
||||
int64_t m_int64;
|
||||
double m_double;
|
||||
};
|
||||
};
|
||||
|
||||
//! True if left.Equals(right)
|
||||
bool operator==(JSValue const &left, JSValue const &right) noexcept;
|
||||
|
||||
//! True if !left.Equals(right)
|
||||
bool operator!=(JSValue const &left, JSValue const &right) noexcept;
|
||||
|
||||
//===========================================================================
|
||||
// Helper classes for JSValueObject and JSValueArray initialization lists.
|
||||
//===========================================================================
|
||||
|
||||
//! Helps initialize key-value pairs for JSValueObject.
|
||||
//! It creates its own instance of JSValue which then can be moved to JSValueObject.
|
||||
struct JSValueObjectKeyValue {
|
||||
template <class TKey, class TValue>
|
||||
JSValueObjectKeyValue(TKey &&key, TValue &&value) noexcept
|
||||
: Key(std::forward<TKey>(key)), Value(std::forward<TValue>(value)) {}
|
||||
|
||||
std::string_view Key;
|
||||
JSValue Value;
|
||||
};
|
||||
|
||||
//! Helps initialize items for JSValueArray.
|
||||
//! It creates its own instance of JSValue which then can be moved to JSValueArray.
|
||||
struct JSValueArrayItem {
|
||||
template <class TItem>
|
||||
JSValueArrayItem(TItem &&item) noexcept : Item(std::forward<TItem>(item)) {}
|
||||
|
||||
JSValue Item;
|
||||
};
|
||||
|
||||
//===========================================================================
|
||||
// Inline JSValueObject implementation.
|
||||
//===========================================================================
|
||||
template <class TMoveInputIterator>
|
||||
JSValueObject::JSValueObject(TMoveInputIterator first, TMoveInputIterator last) noexcept {
|
||||
auto it = first;
|
||||
while (it != last) {
|
||||
auto pair = *it++;
|
||||
try_emplace(std::move(pair.first), std::move(pair.second));
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
inline bool JSValueObject::EqualsAfterConversion(JSValueObject const &other) const noexcept {
|
||||
return JSEquals(other);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Inline JSValueObject standalone function implementations.
|
||||
//===========================================================================
|
||||
|
||||
inline bool operator==(JSValueObject const &left, JSValueObject const &right) noexcept {
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
inline bool operator!=(JSValueObject const &left, JSValueObject const &right) noexcept {
|
||||
return !left.Equals(right);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Inline JSValueArray implementation.
|
||||
//===========================================================================
|
||||
|
||||
template <class TMoveInputIterator, std::enable_if_t<!std::is_integral_v<TMoveInputIterator>, int>>
|
||||
JSValueArray::JSValueArray(TMoveInputIterator first, TMoveInputIterator last) noexcept {
|
||||
auto it = first;
|
||||
while (it != last) {
|
||||
push_back(*it++);
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
inline bool JSValueArray::EqualsAfterConversion(JSValueArray const &other) const noexcept {
|
||||
return JSEquals(other);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Inline JSValueArray standalone function implementations.
|
||||
//===========================================================================
|
||||
|
||||
inline bool operator==(JSValueArray const &left, JSValueArray const &right) noexcept {
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
inline bool operator!=(JSValueArray const &left, JSValueArray const &right) noexcept {
|
||||
return !left.Equals(right);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Inline JSValue 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)) {}
|
||||
inline JSValue::JSValue(JSValueArray &&value) noexcept : m_type{JSValueType::Array}, m_array(std::move(value)) {}
|
||||
inline JSValue::JSValue(std::string &&value) noexcept : m_type{JSValueType::String}, m_string{std::move(value)} {}
|
||||
template <class TStringView, std::enable_if_t<std::is_convertible_v<TStringView, std::string_view>, int>>
|
||||
inline JSValue::JSValue(TStringView value) noexcept : m_type{JSValueType::String}, m_string{value} {}
|
||||
template <class TBool, std::enable_if_t<std::is_same_v<TBool, bool>, int>>
|
||||
inline JSValue::JSValue(TBool value) noexcept : m_type{JSValueType::Boolean}, m_bool{value} {}
|
||||
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;
|
||||
}
|
||||
|
||||
inline bool JSValue::IsNull() const noexcept {
|
||||
return m_type == JSValueType::Null;
|
||||
}
|
||||
|
||||
inline JSValueObject const *JSValue::TryGetObject() const noexcept {
|
||||
return (m_type == JSValueType::Object) ? &m_object : nullptr;
|
||||
}
|
||||
|
||||
inline JSValueArray const *JSValue::TryGetArray() const noexcept {
|
||||
return (m_type == JSValueType::Array) ? &m_array : nullptr;
|
||||
}
|
||||
|
||||
inline std::string const *JSValue::TryGetString() const noexcept {
|
||||
return (m_type == JSValueType::String) ? &m_string : nullptr;
|
||||
}
|
||||
|
||||
inline bool const *JSValue::TryGetBoolean() const noexcept {
|
||||
return (m_type == JSValueType::Boolean) ? &m_bool : nullptr;
|
||||
}
|
||||
|
||||
inline int64_t const *JSValue::TryGetInt64() const noexcept {
|
||||
return (m_type == JSValueType::Int64) ? &m_int64 : nullptr;
|
||||
}
|
||||
|
||||
inline double const *JSValue::TryGetDouble() const noexcept {
|
||||
return (m_type == JSValueType::Double) ? &m_double : nullptr;
|
||||
}
|
||||
|
||||
inline JSValueObject const &JSValue::AsObject() const noexcept {
|
||||
return (m_type == JSValueType::Object) ? m_object : EmptyObject.m_object;
|
||||
}
|
||||
|
||||
inline JSValueArray const &JSValue::AsArray() const noexcept {
|
||||
return (m_type == JSValueType::Array) ? m_array : EmptyArray.m_array;
|
||||
}
|
||||
|
||||
inline int8_t JSValue::AsInt8() const noexcept {
|
||||
return (int8_t)AsInt64();
|
||||
}
|
||||
|
||||
inline int16_t JSValue::AsInt16() const noexcept {
|
||||
return (int16_t)AsInt64();
|
||||
}
|
||||
|
||||
inline int32_t JSValue::AsInt32() const noexcept {
|
||||
return (int32_t)AsInt64();
|
||||
}
|
||||
|
||||
inline uint8_t JSValue::AsUInt8() const noexcept {
|
||||
return (uint8_t)AsInt64();
|
||||
}
|
||||
|
||||
inline uint16_t JSValue::AsUInt16() const noexcept {
|
||||
return (uint16_t)AsInt64();
|
||||
}
|
||||
|
||||
inline uint32_t JSValue::AsUInt32() const noexcept {
|
||||
return (uint32_t)AsInt64();
|
||||
}
|
||||
|
||||
inline uint64_t JSValue::AsUInt64() const noexcept {
|
||||
return (uint64_t)AsInt64();
|
||||
}
|
||||
|
||||
inline float JSValue::AsSingle() const noexcept {
|
||||
return (float)AsDouble();
|
||||
}
|
||||
|
||||
inline JSValue::operator std::string() const noexcept {
|
||||
return AsString();
|
||||
}
|
||||
|
||||
inline JSValue::operator bool() const noexcept {
|
||||
return AsBoolean();
|
||||
}
|
||||
|
||||
inline JSValue::operator int8_t() const noexcept {
|
||||
return AsInt8();
|
||||
}
|
||||
|
||||
inline JSValue::operator int16_t() const noexcept {
|
||||
return AsInt16();
|
||||
}
|
||||
|
||||
inline JSValue::operator int32_t() const noexcept {
|
||||
return AsInt32();
|
||||
}
|
||||
|
||||
inline JSValue::operator int64_t() const noexcept {
|
||||
return AsInt64();
|
||||
}
|
||||
|
||||
inline JSValue::operator uint8_t() const noexcept {
|
||||
return AsUInt8();
|
||||
}
|
||||
|
||||
inline JSValue::operator uint16_t() const noexcept {
|
||||
return AsUInt16();
|
||||
}
|
||||
|
||||
inline JSValue::operator uint32_t() const noexcept {
|
||||
return AsUInt32();
|
||||
}
|
||||
|
||||
inline JSValue::operator uint64_t() const noexcept {
|
||||
return AsUInt64();
|
||||
}
|
||||
|
||||
inline JSValue::operator float() const noexcept {
|
||||
return AsSingle();
|
||||
}
|
||||
|
||||
inline JSValue::operator double() const noexcept {
|
||||
return AsDouble();
|
||||
}
|
||||
|
||||
inline JSValue const &JSValue::operator[](std::string_view propertyName) const noexcept {
|
||||
return GetObjectProperty(propertyName);
|
||||
}
|
||||
|
||||
inline JSValue const &JSValue::operator[](JSValueArray::size_type index) const noexcept {
|
||||
return GetArrayItem(index);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::string JSValue::To() const noexcept {
|
||||
return AsString();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JSValue::To() const noexcept {
|
||||
return AsBoolean();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int8_t JSValue::To() const noexcept {
|
||||
return AsInt8();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int16_t JSValue::To() const noexcept {
|
||||
return AsInt16();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int32_t JSValue::To() const noexcept {
|
||||
return AsInt32();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int64_t JSValue::To() const noexcept {
|
||||
return AsInt64();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint8_t JSValue::To() const noexcept {
|
||||
return AsUInt8();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint16_t JSValue::To() const noexcept {
|
||||
return AsUInt16();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint32_t JSValue::To() const noexcept {
|
||||
return AsUInt32();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline uint64_t JSValue::To() const noexcept {
|
||||
return AsUInt64();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline float JSValue::To() const noexcept {
|
||||
return AsSingle();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline double JSValue::To() const noexcept {
|
||||
return AsDouble();
|
||||
}
|
||||
|
||||
template <
|
||||
class T,
|
||||
std::enable_if_t<std::is_default_constructible_v<T> && !std::is_constructible_v<T, std::nullptr_t>, int>>
|
||||
inline T JSValue::To() const noexcept {
|
||||
T result;
|
||||
ReadValue(MakeJSValueTreeReader(*this), /*out*/ result);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, std::enable_if_t<std::is_constructible_v<T, std::nullptr_t>, int>>
|
||||
inline T JSValue::To() const noexcept {
|
||||
T result{nullptr};
|
||||
ReadValue(MakeJSValueTreeReader(*this), /*out*/ result);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T JSValue::To(T &&defaultValue) const noexcept {
|
||||
T result{std::move(defaultValue)};
|
||||
ReadValue(MakeJSValueTreeReader(*this), /*out*/ result);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
JSValue JSValue::From(T const &value) noexcept {
|
||||
auto writer = MakeJSValueTreeWriter();
|
||||
WriteValue(writer, value);
|
||||
return TakeJSValue(writer);
|
||||
}
|
||||
|
||||
inline /*static*/ JSValueObject JSValue::ReadObjectFrom(IJSValueReader const &reader) noexcept {
|
||||
return JSValueObject::ReadFrom(reader);
|
||||
}
|
||||
|
||||
inline /*static*/ JSValueArray JSValue::ReadArrayFrom(IJSValueReader const &reader) noexcept {
|
||||
return JSValueArray::ReadFrom(reader);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// JSValue deprecated methods.
|
||||
//===========================================================================
|
||||
|
||||
inline const JSValueObject &JSValue::Object() const noexcept {
|
||||
return AsObject();
|
||||
}
|
||||
|
||||
inline const JSValueArray &JSValue::Array() const noexcept {
|
||||
return AsArray();
|
||||
}
|
||||
|
||||
inline const std::string &JSValue::String() const noexcept {
|
||||
return (m_type == JSValueType::String) ? m_string : EmptyString.m_string;
|
||||
}
|
||||
|
||||
inline bool JSValue::Boolean() const noexcept {
|
||||
return (m_type == JSValueType::Boolean) ? m_bool : false;
|
||||
}
|
||||
|
||||
inline int64_t JSValue::Int64() const noexcept {
|
||||
return (m_type == JSValueType::Int64) ? m_int64 : 0;
|
||||
}
|
||||
|
||||
inline double JSValue::Double() const noexcept {
|
||||
return (m_type == JSValueType::Double) ? m_double : 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T JSValue::As() const noexcept {
|
||||
return To<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T JSValue::As(T &&defaultValue) const noexcept {
|
||||
return To<T>(std::move(defaultValue));
|
||||
}
|
||||
|
||||
inline JSValueObject JSValue::TakeObject() noexcept {
|
||||
return MoveObject();
|
||||
}
|
||||
|
||||
inline JSValueArray JSValue::TakeArray() noexcept {
|
||||
return MoveArray();
|
||||
}
|
||||
|
||||
inline /*static*/ JSValueObject JSValue::CopyObject(JSValueObject const &other) noexcept {
|
||||
return other.Copy();
|
||||
}
|
||||
|
||||
inline /*static*/ JSValueArray JSValue::CopyArray(JSValueArray const &other) noexcept {
|
||||
return other.Copy();
|
||||
}
|
||||
|
||||
inline /*static*/ void JSValue::WriteObjectTo(IJSValueWriter const &writer, JSValueObject const &value) noexcept {
|
||||
value.WriteTo(writer);
|
||||
}
|
||||
|
||||
inline /*static*/ void JSValue::WriteArrayTo(IJSValueWriter const &writer, JSValueArray const &value) noexcept {
|
||||
value.WriteTo(writer);
|
||||
}
|
||||
|
||||
inline bool JSValue::EqualsAfterConversion(JSValue const &other) const noexcept {
|
||||
return JSEquals(other);
|
||||
}
|
||||
|
||||
inline float JSValue::AsFloat() const noexcept {
|
||||
return (float)AsDouble();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Inline JSValue standalone function implementations.
|
||||
//===========================================================================
|
||||
|
||||
inline bool operator==(JSValue const &left, JSValue const &right) noexcept {
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
inline bool operator!=(JSValue const &left, JSValue const &right) noexcept {
|
||||
return !left.Equals(right);
|
||||
}
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
||||
|
||||
#endif // MICROSOFT_REACTNATIVE_JSVALUE
|
|
@ -0,0 +1,426 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#ifndef MICROSOFT_REACTNATIVE_JSVALUEREADER
|
||||
#define MICROSOFT_REACTNATIVE_JSVALUEREADER
|
||||
|
||||
#include "JSValue.h"
|
||||
#include "JSValueTreeReader.h"
|
||||
#include "StructInfo.h"
|
||||
|
||||
#include "winrt/Microsoft.ReactNative.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
// A value can be read from IJSValueReader in one of three ways:
|
||||
// 1. Using a ReadValue standalone function with IJSValueReader& as a first argument.
|
||||
// 2. Using a ReadValue standalone function with const JSValue& as a first argument.
|
||||
// 3. We can auto-generate the read method for the type in some cases.
|
||||
|
||||
// A special type to prevent circular call between
|
||||
// ReadValue(IJSValueReader&, T&) and ReadValue(JSValue&, T&)
|
||||
template <class T>
|
||||
struct TypeWrapper {
|
||||
T Value;
|
||||
operator T &() noexcept {
|
||||
return Value;
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
// IJSValueReader extensions
|
||||
//==============================================================================
|
||||
|
||||
// Forward declarations
|
||||
template <class T>
|
||||
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;
|
||||
|
||||
template <class T, class TJSValue, std::enable_if_t<std::is_same_v<TJSValue, JSValue>, int> = 1>
|
||||
void ReadValue(TJSValue const &jsValue, /*out*/ T &value) noexcept;
|
||||
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ std::string &value) noexcept;
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ std::wstring &value) noexcept;
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ bool &value) noexcept;
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ int8_t &value) noexcept;
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ int16_t &value) noexcept;
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ int32_t &value) noexcept;
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ int64_t &value) noexcept;
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ uint8_t &value) noexcept;
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ uint16_t &value) noexcept;
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ uint32_t &value) noexcept;
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ uint64_t &value) noexcept;
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ float &value) noexcept;
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ double &value) noexcept;
|
||||
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<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<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 = 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;
|
||||
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ JSValue &value) noexcept;
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ JSValueObject &value) noexcept;
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ JSValueArray &value) noexcept;
|
||||
|
||||
template <class T, std::enable_if_t<!std::is_void_v<decltype(GetStructInfo(static_cast<T *>(nullptr)))>, int> = 1>
|
||||
void ReadValue(IJSValueReader const &reader, /*out*/ T &value) noexcept;
|
||||
|
||||
bool SkipArrayToEnd(IJSValueReader const &reader) noexcept;
|
||||
template <class... TArgs>
|
||||
void ReadArgs(IJSValueReader const &reader, /*out*/ TArgs &... args) noexcept;
|
||||
|
||||
//===========================================================================
|
||||
// IJSValueReader extensions implementation
|
||||
//===========================================================================
|
||||
|
||||
// This is a convenience method to call ReadValue for IJSValueReader.
|
||||
template <class T>
|
||||
inline T ReadValue(IJSValueReader const &reader) noexcept {
|
||||
T result;
|
||||
ReadValue(reader, /*out*/ result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// This is a convenience method to call ReadValue for JSValue.
|
||||
template <class T>
|
||||
inline T ReadValue(JSValue const &jsValue) noexcept {
|
||||
T result;
|
||||
ReadValue(jsValue, /*out*/ result);
|
||||
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 {
|
||||
TypeWrapper<JSValue> jsValue = {JSValue::ReadFrom(reader)};
|
||||
ReadValue(jsValue, /*out*/ value);
|
||||
}
|
||||
|
||||
// Try to call ReadValue for IJSValueReader unless it is already called us with TypeWrapper parameter.
|
||||
template <class T, class TJSValue, std::enable_if_t<std::is_same_v<TJSValue, JSValue>, int>>
|
||||
inline void ReadValue(TJSValue const &jsValue, /*out*/ T &value) noexcept {
|
||||
TypeWrapper<IJSValueReader> reader = {MakeJSValueTreeReader(jsValue)};
|
||||
ReadValue(reader, /*out*/ value);
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ std::string &value) noexcept {
|
||||
switch (reader.ValueType()) {
|
||||
case JSValueType::String:
|
||||
value = to_string(reader.GetString());
|
||||
break;
|
||||
case JSValueType::Boolean:
|
||||
value = reader.GetBoolean() ? "true" : "false";
|
||||
break;
|
||||
case JSValueType::Int64:
|
||||
value = std::to_string(reader.GetInt64());
|
||||
break;
|
||||
case JSValueType::Double:
|
||||
value = std::to_string(reader.GetDouble());
|
||||
value.erase(value.find_last_not_of('0') + 1, std::string::npos);
|
||||
value.erase(value.find_last_not_of('.') + 1, std::string::npos);
|
||||
break;
|
||||
default:
|
||||
value = "";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ std::wstring &value) noexcept {
|
||||
switch (reader.ValueType()) {
|
||||
case JSValueType::String:
|
||||
value = reader.GetString();
|
||||
break;
|
||||
case JSValueType::Boolean:
|
||||
value = reader.GetBoolean() ? L"true" : L"false";
|
||||
break;
|
||||
case JSValueType::Int64:
|
||||
value = std::to_wstring(reader.GetInt64());
|
||||
break;
|
||||
case JSValueType::Double:
|
||||
value = std::to_wstring(reader.GetDouble());
|
||||
value.erase(value.find_last_not_of('0') + 1, std::wstring::npos);
|
||||
value.erase(value.find_last_not_of('.') + 1, std::wstring::npos);
|
||||
break;
|
||||
default:
|
||||
value = L"";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ bool &value) noexcept {
|
||||
switch (reader.ValueType()) {
|
||||
case JSValueType::String:
|
||||
value = !to_string(reader.GetString()).empty();
|
||||
break;
|
||||
case JSValueType::Boolean:
|
||||
value = reader.GetBoolean();
|
||||
break;
|
||||
case JSValueType::Int64:
|
||||
value = reader.GetInt64() != 0;
|
||||
break;
|
||||
case JSValueType::Double:
|
||||
value = reader.GetDouble() != 0;
|
||||
break;
|
||||
default:
|
||||
value = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ int8_t &value) noexcept {
|
||||
int64_t val;
|
||||
ReadValue(reader, /*out*/ val);
|
||||
value = static_cast<int8_t>(val);
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ int16_t &value) noexcept {
|
||||
int64_t val;
|
||||
ReadValue(reader, /*out*/ val);
|
||||
value = static_cast<int16_t>(val);
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ int32_t &value) noexcept {
|
||||
int64_t val;
|
||||
ReadValue(reader, /*out*/ val);
|
||||
value = static_cast<int32_t>(val);
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ int64_t &value) noexcept {
|
||||
switch (reader.ValueType()) {
|
||||
case JSValueType::String: {
|
||||
hstring str = reader.GetString();
|
||||
wchar_t *end = nullptr;
|
||||
auto iValue = _wcstoi64(str.data(), &end, 10 /*base*/);
|
||||
if (end == str.data() + str.size()) {
|
||||
value = iValue;
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSValueType::Boolean:
|
||||
value = reader.GetBoolean() ? 1 : 0;
|
||||
break;
|
||||
case JSValueType::Int64:
|
||||
value = reader.GetInt64();
|
||||
break;
|
||||
case JSValueType::Double:
|
||||
value = static_cast<int64_t>(reader.GetDouble());
|
||||
break;
|
||||
default:
|
||||
value = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ uint8_t &value) noexcept {
|
||||
int64_t val;
|
||||
ReadValue(reader, /*out*/ val);
|
||||
value = static_cast<uint8_t>(val);
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ uint16_t &value) noexcept {
|
||||
int64_t val;
|
||||
ReadValue(reader, /*out*/ val);
|
||||
value = static_cast<uint16_t>(val);
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ uint32_t &value) noexcept {
|
||||
int64_t val;
|
||||
ReadValue(reader, /*out*/ val);
|
||||
value = static_cast<uint32_t>(val);
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ uint64_t &value) noexcept {
|
||||
int64_t val;
|
||||
ReadValue(reader, /*out*/ val);
|
||||
value = static_cast<uint64_t>(val);
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ float &value) noexcept {
|
||||
double val;
|
||||
ReadValue(reader, /*out*/ val);
|
||||
value = static_cast<float>(val);
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ double &value) noexcept {
|
||||
switch (reader.ValueType()) {
|
||||
case JSValueType::String: {
|
||||
hstring str = reader.GetString();
|
||||
wchar_t *end = nullptr;
|
||||
auto dvalue = wcstod(str.data(), &end);
|
||||
if (end == str.data() + str.size()) {
|
||||
value = dvalue;
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JSValueType::Boolean:
|
||||
value = reader.GetBoolean() ? 1 : 0;
|
||||
break;
|
||||
case JSValueType::Int64:
|
||||
value = static_cast<double>(reader.GetInt64());
|
||||
break;
|
||||
case JSValueType::Double:
|
||||
value = reader.GetDouble();
|
||||
break;
|
||||
default:
|
||||
value = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, std::enable_if_t<std::is_enum_v<T>, int>>
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ T &value) noexcept {
|
||||
int32_t intValue;
|
||||
ReadValue(reader, intValue);
|
||||
value = static_cast<T>(intValue);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ std::optional<T> &value) noexcept {
|
||||
if (reader.ValueType() != JSValueType::Null) {
|
||||
value = ReadValue<T>(reader);
|
||||
} else {
|
||||
value = std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
// Note that we use std::less<> as a default comparer instead of standard std::less<Key>.
|
||||
// This is to enable use of string-like objects such as std::string_view as key to retrieve values.
|
||||
// While std::less<> is better, the standard cannot have a breaking change to switch to it.
|
||||
template <class T, class TCompare, class TAlloc>
|
||||
inline void ReadValue(
|
||||
IJSValueReader const &reader,
|
||||
/*out*/ std::map<std::string, T, TCompare, TAlloc> &value) noexcept {
|
||||
if (reader.ValueType() == JSValueType::Object) {
|
||||
hstring propertyName;
|
||||
while (reader.GetNextObjectProperty(/*out*/ propertyName)) {
|
||||
value.emplace(to_string(propertyName), ReadValue<T>(reader));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class TCompare, class TAlloc>
|
||||
inline void ReadValue(
|
||||
IJSValueReader const &reader,
|
||||
/*out*/ std::map<std::wstring, T, TCompare, TAlloc> &value) noexcept {
|
||||
if (reader.ValueType() == JSValueType::Object) {
|
||||
hstring propertyName;
|
||||
while (reader.GetNextObjectProperty(/*out*/ propertyName)) {
|
||||
value.emplace(propertyName, ReadValue<T>(reader));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class TAlloc>
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ std::vector<T, TAlloc> &value) noexcept {
|
||||
if (reader.ValueType() == JSValueType::Array) {
|
||||
while (reader.GetNextArrayItem()) {
|
||||
value.push_back(ReadValue<T>(reader));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, size_t... I>
|
||||
inline void ReadTuple(IJSValueReader const &reader, /*out*/ T &tuple, std::index_sequence<I...>) noexcept {
|
||||
ReadArgs(reader, std::get<I>(tuple)...);
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ std::tuple<Ts...> &value) noexcept {
|
||||
ReadTuple(reader, value, std::make_index_sequence<sizeof...(Ts)>{});
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ JSValue &value) noexcept {
|
||||
value = JSValue::ReadFrom(reader);
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ JSValueObject &value) noexcept {
|
||||
value = JSValueObject::ReadFrom(reader);
|
||||
}
|
||||
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ JSValueArray &value) noexcept {
|
||||
value = JSValueArray::ReadFrom(reader);
|
||||
}
|
||||
|
||||
template <class T, std::enable_if_t<!std::is_void_v<decltype(GetStructInfo(static_cast<T *>(nullptr)))>, int>>
|
||||
inline void ReadValue(IJSValueReader const &reader, /*out*/ T &value) noexcept {
|
||||
if (reader.ValueType() == JSValueType::Object) {
|
||||
const auto &fieldMap = StructInfo<T>::FieldMap;
|
||||
hstring propertyName;
|
||||
while (reader.GetNextObjectProperty(/*out*/ propertyName)) {
|
||||
auto it = fieldMap.find(std::wstring_view(propertyName));
|
||||
if (it != fieldMap.end()) {
|
||||
it->second.ReadField(reader, &value);
|
||||
} else {
|
||||
SkipValue<JSValue>(reader); // Skip this property
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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()) {
|
||||
SkipValue<JSValue>(reader); // Read and ignore the value
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class... TArgs>
|
||||
inline void ReadArgs(IJSValueReader const &reader, /*out*/ TArgs &... args) noexcept {
|
||||
// Read as many arguments as we can or return default values.
|
||||
bool success = reader.ValueType() == JSValueType::Array;
|
||||
((success = success && reader.GetNextArrayItem(), args = success ? ReadValue<TArgs>(reader) : TArgs{}), ...);
|
||||
success = success && SkipArrayToEnd(reader);
|
||||
}
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
||||
|
||||
#endif // MICROSOFT_REACTNATIVE_JSVALUEREADER
|
|
@ -0,0 +1,142 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pch.h"
|
||||
#include "JSValueTreeReader.h"
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
//===========================================================================
|
||||
// JSValueTreeReader implementation
|
||||
//===========================================================================
|
||||
|
||||
JSValueTreeReader::StackEntry::StackEntry(const JSValue &value, const JSValueObject::const_iterator &property) noexcept
|
||||
: Value{value}, Property{property} {}
|
||||
|
||||
JSValueTreeReader::StackEntry::StackEntry(const JSValue &value, const JSValueArray::const_iterator &item) noexcept
|
||||
: Value{value}, Item{item} {}
|
||||
|
||||
JSValueTreeReader::JSValueTreeReader(const JSValue &value) noexcept : m_root{value}, m_current{&value} {}
|
||||
|
||||
JSValueTreeReader::JSValueTreeReader(JSValue &&value) noexcept
|
||||
: m_ownedValue{std::move(value)}, m_root{m_ownedValue}, m_current{&m_ownedValue} {}
|
||||
|
||||
JSValueType JSValueTreeReader::ValueType() noexcept {
|
||||
return m_current->Type();
|
||||
}
|
||||
|
||||
bool JSValueTreeReader::GetNextObjectProperty(hstring &propertyName) noexcept {
|
||||
if (!m_isInContainer) {
|
||||
if (auto obj = m_current->TryGetObject()) {
|
||||
const auto &properties = *obj;
|
||||
const auto &property = properties.begin();
|
||||
if (property != properties.end()) {
|
||||
m_stack.emplace_back(*m_current, property);
|
||||
SetCurrentValue(property->second);
|
||||
propertyName = to_hstring(property->first);
|
||||
return true;
|
||||
} else {
|
||||
m_isInContainer = !m_stack.empty();
|
||||
}
|
||||
}
|
||||
} else if (!m_stack.empty()) {
|
||||
auto &entry = m_stack.back();
|
||||
if (auto obj = entry.Value.TryGetObject()) {
|
||||
auto &property = entry.Property;
|
||||
if (++property != obj->end()) {
|
||||
SetCurrentValue(property->second);
|
||||
propertyName = to_hstring(property->first);
|
||||
return true;
|
||||
} else {
|
||||
m_current = &entry.Value;
|
||||
m_stack.pop_back();
|
||||
m_isInContainer = !m_stack.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
propertyName = to_hstring(L"");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JSValueTreeReader::GetNextArrayItem() noexcept {
|
||||
if (!m_isInContainer) {
|
||||
if (auto arr = m_current->TryGetArray()) {
|
||||
const auto &item = arr->begin();
|
||||
if (item != arr->end()) {
|
||||
m_stack.emplace_back(*m_current, item);
|
||||
SetCurrentValue(*item);
|
||||
return true;
|
||||
} else {
|
||||
m_isInContainer = !m_stack.empty();
|
||||
}
|
||||
}
|
||||
} else if (!m_stack.empty()) {
|
||||
auto &entry = m_stack.back();
|
||||
if (auto arr = entry.Value.TryGetArray()) {
|
||||
if (++entry.Item != arr->end()) {
|
||||
SetCurrentValue(*entry.Item);
|
||||
return true;
|
||||
} else {
|
||||
m_current = &entry.Value;
|
||||
m_stack.pop_back();
|
||||
m_isInContainer = !m_stack.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void JSValueTreeReader::SetCurrentValue(const JSValue &value) noexcept {
|
||||
m_current = &value;
|
||||
switch (value.Type()) {
|
||||
case JSValueType::Object:
|
||||
case JSValueType::Array:
|
||||
m_isInContainer = false;
|
||||
break;
|
||||
default:
|
||||
m_isInContainer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hstring JSValueTreeReader::GetString() noexcept {
|
||||
auto s = m_current->TryGetString();
|
||||
return to_hstring(s ? *s : "");
|
||||
}
|
||||
|
||||
bool JSValueTreeReader::GetBoolean() noexcept {
|
||||
auto b = m_current->TryGetBoolean();
|
||||
return b ? *b : false;
|
||||
}
|
||||
|
||||
int64_t JSValueTreeReader::GetInt64() noexcept {
|
||||
auto i = m_current->TryGetInt64();
|
||||
return i ? *i : 0;
|
||||
}
|
||||
|
||||
double JSValueTreeReader::GetDouble() noexcept {
|
||||
auto d = m_current->TryGetDouble();
|
||||
return d ? *d : 0;
|
||||
}
|
||||
|
||||
IJSValueReader MakeJSValueTreeReader(const JSValue &root) noexcept {
|
||||
return make<JSValueTreeReader>(root);
|
||||
}
|
||||
|
||||
IJSValueReader MakeJSValueTreeReader(JSValue &&root) noexcept {
|
||||
return make<JSValueTreeReader>(std::move(root));
|
||||
}
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#ifndef MICROSOFT_REACTNATIVE_JSVALUETREEREADER
|
||||
#define MICROSOFT_REACTNATIVE_JSVALUETREEREADER
|
||||
|
||||
#include "JSValue.h"
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
struct JSValueTreeReader : implements<JSValueTreeReader, IJSValueReader> {
|
||||
JSValueTreeReader(const JSValue &value) noexcept;
|
||||
JSValueTreeReader(JSValue &&value) noexcept;
|
||||
|
||||
public: // IJSValueReader
|
||||
JSValueType ValueType() noexcept;
|
||||
bool GetNextObjectProperty(hstring &propertyName) noexcept;
|
||||
bool GetNextArrayItem() noexcept;
|
||||
hstring GetString() noexcept;
|
||||
bool GetBoolean() noexcept;
|
||||
int64_t GetInt64() noexcept;
|
||||
double GetDouble() noexcept;
|
||||
|
||||
private:
|
||||
struct StackEntry {
|
||||
StackEntry(const JSValue &value, const JSValueObject::const_iterator &property) noexcept;
|
||||
StackEntry(const JSValue &value, const JSValueArray::const_iterator &item) noexcept;
|
||||
|
||||
const JSValue &Value;
|
||||
JSValueArray::const_iterator Item;
|
||||
JSValueObject::const_iterator Property;
|
||||
};
|
||||
|
||||
private:
|
||||
void SetCurrentValue(const JSValue &value) noexcept;
|
||||
|
||||
private:
|
||||
const JSValue m_ownedValue;
|
||||
const JSValue &m_root;
|
||||
const JSValue *m_current;
|
||||
bool m_isInContainer{false};
|
||||
std::vector<StackEntry> m_stack;
|
||||
};
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
||||
|
||||
#endif // MICROSOFT_REACTNATIVE_JSVALUETREEREADER
|
|
@ -0,0 +1,105 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pch.h"
|
||||
#include "JSValueTreeWriter.h"
|
||||
#include "Crash.h"
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
//===========================================================================
|
||||
// JSValueTreeWriter implementation
|
||||
//===========================================================================
|
||||
|
||||
JSValueTreeWriter::JSValueTreeWriter() noexcept {
|
||||
m_containerStack.push(ContainerInfo{ContainerType::None});
|
||||
}
|
||||
|
||||
JSValue JSValueTreeWriter::TakeValue() noexcept {
|
||||
return std::move(m_resultValue);
|
||||
}
|
||||
|
||||
void JSValueTreeWriter::WriteNull() noexcept {
|
||||
WriteValue(JSValue{});
|
||||
}
|
||||
|
||||
void JSValueTreeWriter::WriteBoolean(bool value) noexcept {
|
||||
WriteValue(JSValue{value});
|
||||
}
|
||||
|
||||
void JSValueTreeWriter::WriteInt64(int64_t value) noexcept {
|
||||
WriteValue(JSValue{value});
|
||||
}
|
||||
|
||||
void JSValueTreeWriter::WriteDouble(double value) noexcept {
|
||||
WriteValue(JSValue{value});
|
||||
}
|
||||
|
||||
void JSValueTreeWriter::WriteString(const hstring &value) noexcept {
|
||||
WriteValue(JSValue{to_string(value)});
|
||||
}
|
||||
|
||||
void JSValueTreeWriter::WriteObjectBegin() noexcept {
|
||||
m_containerStack.push(ContainerInfo{ContainerType::Object});
|
||||
}
|
||||
|
||||
void JSValueTreeWriter::WritePropertyName(const winrt::hstring &name) noexcept {
|
||||
auto &top = m_containerStack.top();
|
||||
VerifyElseCrash(top.Type == ContainerType::Object);
|
||||
top.PropertyName = to_string(name);
|
||||
}
|
||||
|
||||
void JSValueTreeWriter::WriteObjectEnd() noexcept {
|
||||
auto &top = m_containerStack.top();
|
||||
VerifyElseCrash(top.Type == ContainerType::Object);
|
||||
JSValue value{std::move(top.Object)};
|
||||
m_containerStack.pop();
|
||||
WriteValue(std::move(value));
|
||||
}
|
||||
|
||||
void JSValueTreeWriter::WriteArrayBegin() noexcept {
|
||||
m_containerStack.push(ContainerInfo{ContainerType::Array});
|
||||
}
|
||||
|
||||
void JSValueTreeWriter::WriteArrayEnd() noexcept {
|
||||
auto &top = m_containerStack.top();
|
||||
VerifyElseCrash(top.Type == ContainerType::Array);
|
||||
JSValue value{std::move(top.Array)};
|
||||
m_containerStack.pop();
|
||||
WriteValue(std::move(value));
|
||||
}
|
||||
|
||||
void JSValueTreeWriter::WriteValue(JSValue &&value) noexcept {
|
||||
auto &top = m_containerStack.top();
|
||||
switch (top.Type) {
|
||||
case ContainerType::None:
|
||||
m_resultValue = std::move(value);
|
||||
break;
|
||||
case ContainerType::Object:
|
||||
top.Object.emplace(std::move(top.PropertyName), std::move(value));
|
||||
break;
|
||||
case ContainerType::Array:
|
||||
top.Array.push_back(std::move(value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
IJSValueWriter MakeJSValueTreeWriter() noexcept {
|
||||
return make<JSValueTreeWriter>();
|
||||
}
|
||||
|
||||
JSValue TakeJSValue(IJSValueWriter const &writer) noexcept {
|
||||
return get_self<JSValueTreeWriter>(writer)->TakeValue();
|
||||
}
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#ifndef MICROSOFT_REACTNATIVE_JSVALUETREEWRITER
|
||||
#define MICROSOFT_REACTNATIVE_JSVALUETREEWRITER
|
||||
|
||||
#include <stack>
|
||||
#include "JSValue.h"
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
// Writes to a tree of JSValue objects.
|
||||
struct JSValueTreeWriter : implements<JSValueTreeWriter, IJSValueWriter> {
|
||||
JSValueTreeWriter() noexcept;
|
||||
JSValue TakeValue() noexcept;
|
||||
|
||||
public: // IJSValueWriter
|
||||
void WriteNull() noexcept;
|
||||
void WriteBoolean(bool value) noexcept;
|
||||
void WriteInt64(int64_t value) noexcept;
|
||||
void WriteDouble(double value) noexcept;
|
||||
void WriteString(const winrt::hstring &value) noexcept;
|
||||
void WriteObjectBegin() noexcept;
|
||||
void WritePropertyName(const winrt::hstring &name) noexcept;
|
||||
void WriteObjectEnd() noexcept;
|
||||
void WriteArrayBegin() noexcept;
|
||||
void WriteArrayEnd() noexcept;
|
||||
|
||||
private:
|
||||
enum struct ContainerType { None, Object, Array };
|
||||
|
||||
struct ContainerInfo {
|
||||
ContainerInfo(ContainerType type) noexcept : Type{std::move(type)} {}
|
||||
|
||||
ContainerType Type{ContainerType::None};
|
||||
JSValueObject Object;
|
||||
JSValueArray Array;
|
||||
std::string PropertyName;
|
||||
};
|
||||
|
||||
private:
|
||||
void WriteValue(JSValue &&value) noexcept;
|
||||
|
||||
private:
|
||||
std::stack<ContainerInfo> m_containerStack;
|
||||
JSValue m_resultValue;
|
||||
};
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
||||
|
||||
#endif // MICROSOFT_REACTNATIVE_JSVALUETREEWRITER
|
|
@ -0,0 +1,284 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#ifndef MICROSOFT_REACTNATIVE_JSVALUEWRITER
|
||||
#define MICROSOFT_REACTNATIVE_JSVALUEWRITER
|
||||
|
||||
#include <winrt/Microsoft.ReactNative.h>
|
||||
#include "JSValue.h"
|
||||
#include "StructInfo.h"
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
//==============================================================================
|
||||
// IJSValueWriter extensions forward declarations
|
||||
//==============================================================================
|
||||
|
||||
void WriteValue(IJSValueWriter const &writer, std::nullptr_t) noexcept;
|
||||
template <class T, std::enable_if_t<std::is_convertible_v<T, std::string_view>, int> = 1>
|
||||
void WriteValue(IJSValueWriter const &writer, T const &value) noexcept;
|
||||
template <class T, std::enable_if_t<std::is_convertible_v<T, std::wstring_view>, int> = 1>
|
||||
void WriteValue(IJSValueWriter const &writer, T const &value) noexcept;
|
||||
void WriteValue(IJSValueWriter const &writer, bool value) noexcept;
|
||||
void WriteValue(IJSValueWriter const &writer, int8_t value) noexcept;
|
||||
void WriteValue(IJSValueWriter const &writer, int16_t value) noexcept;
|
||||
void WriteValue(IJSValueWriter const &writer, int32_t value) noexcept;
|
||||
void WriteValue(IJSValueWriter const &writer, int64_t value) noexcept;
|
||||
void WriteValue(IJSValueWriter const &writer, uint8_t value) noexcept;
|
||||
void WriteValue(IJSValueWriter const &writer, uint16_t value) noexcept;
|
||||
void WriteValue(IJSValueWriter const &writer, uint32_t value) noexcept;
|
||||
void WriteValue(IJSValueWriter const &writer, uint64_t value) noexcept;
|
||||
void WriteValue(IJSValueWriter const &writer, float value) noexcept;
|
||||
void WriteValue(IJSValueWriter const &writer, double value) noexcept;
|
||||
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<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<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 = 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;
|
||||
|
||||
void WriteValue(IJSValueWriter const &writer, JSValue const &value) noexcept;
|
||||
void WriteValue(IJSValueWriter const &writer, JSValueObject const &value) noexcept;
|
||||
void WriteValue(IJSValueWriter const &writer, JSValueArray const &value) noexcept;
|
||||
|
||||
template <class T, std::enable_if_t<!std::is_void_v<decltype(GetStructInfo(static_cast<T *>(nullptr)))>, int> = 1>
|
||||
void WriteValue(IJSValueWriter const &writer, T const &value) noexcept;
|
||||
|
||||
template <class T>
|
||||
void WriteProperty(IJSValueWriter const &writer, std::string_view propertyName, T const &value) noexcept;
|
||||
template <class T>
|
||||
void WriteProperty(IJSValueWriter const &writer, std::wstring_view propertyName, T const &value) noexcept;
|
||||
template <class T>
|
||||
void WriteProperties(IJSValueWriter const &writer, T const &value) noexcept;
|
||||
|
||||
template <class... TArgs>
|
||||
void WriteArgs(IJSValueWriter const &writer, TArgs const &... args) noexcept;
|
||||
|
||||
template <class... TArgs>
|
||||
JSValueArgWriter MakeJSValueArgWriter(TArgs &&... args) noexcept;
|
||||
|
||||
IJSValueWriter MakeJSValueTreeWriter() noexcept;
|
||||
|
||||
//==============================================================================
|
||||
// IJSValueWriter extensions implementation
|
||||
//==============================================================================
|
||||
|
||||
inline void WriteValue(IJSValueWriter const &writer, std::nullptr_t) noexcept {
|
||||
writer.WriteNull();
|
||||
}
|
||||
|
||||
template <class T, std::enable_if_t<std::is_convertible_v<T, std::string_view>, int>>
|
||||
inline void WriteValue(IJSValueWriter const &writer, T const &value) noexcept {
|
||||
writer.WriteString(to_hstring(value));
|
||||
}
|
||||
|
||||
template <class T, std::enable_if_t<std::is_convertible_v<T, std::wstring_view>, int>>
|
||||
inline void WriteValue(IJSValueWriter const &writer, T const &value) noexcept {
|
||||
writer.WriteString(value);
|
||||
}
|
||||
|
||||
inline void WriteValue(IJSValueWriter const &writer, bool value) noexcept {
|
||||
writer.WriteBoolean(value);
|
||||
}
|
||||
|
||||
inline void WriteValue(IJSValueWriter const &writer, int8_t value) noexcept {
|
||||
writer.WriteInt64(value);
|
||||
}
|
||||
|
||||
inline void WriteValue(IJSValueWriter const &writer, int16_t value) noexcept {
|
||||
writer.WriteInt64(value);
|
||||
}
|
||||
|
||||
inline void WriteValue(IJSValueWriter const &writer, int32_t value) noexcept {
|
||||
writer.WriteInt64(value);
|
||||
}
|
||||
|
||||
inline void WriteValue(IJSValueWriter const &writer, int64_t value) noexcept {
|
||||
writer.WriteInt64(value);
|
||||
}
|
||||
|
||||
inline void WriteValue(IJSValueWriter const &writer, uint8_t value) noexcept {
|
||||
writer.WriteInt64(value);
|
||||
}
|
||||
|
||||
inline void WriteValue(IJSValueWriter const &writer, uint16_t value) noexcept {
|
||||
writer.WriteInt64(value);
|
||||
}
|
||||
|
||||
inline void WriteValue(IJSValueWriter const &writer, uint32_t value) noexcept {
|
||||
writer.WriteInt64(value);
|
||||
}
|
||||
|
||||
inline void WriteValue(IJSValueWriter const &writer, uint64_t value) noexcept {
|
||||
writer.WriteInt64(value);
|
||||
}
|
||||
|
||||
inline void WriteValue(IJSValueWriter const &writer, float value) noexcept {
|
||||
writer.WriteDouble(value);
|
||||
}
|
||||
|
||||
inline void WriteValue(IJSValueWriter const &writer, double value) noexcept {
|
||||
writer.WriteDouble(value);
|
||||
}
|
||||
|
||||
template <class T, std::enable_if_t<std::is_enum_v<T>, int>>
|
||||
inline void WriteValue(IJSValueWriter const &writer, T const &value) noexcept {
|
||||
WriteValue(writer, static_cast<int32_t>(value));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void WriteValue(IJSValueWriter const &writer, std::optional<T> const &value) noexcept {
|
||||
if (value.has_value()) {
|
||||
WriteValue(writer, *value);
|
||||
} else {
|
||||
writer.WriteNull();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class TCompare, class TAlloc>
|
||||
inline void WriteValue(IJSValueWriter const &writer, std::map<std::string, T, TCompare, TAlloc> const &value) noexcept {
|
||||
writer.WriteObjectBegin();
|
||||
for (const auto &entry : value) {
|
||||
WriteProperty(writer, entry.first, entry.second);
|
||||
}
|
||||
writer.WriteObjectEnd();
|
||||
}
|
||||
|
||||
template <class T, class TCompare, class TAlloc>
|
||||
inline void WriteValue(
|
||||
IJSValueWriter const &writer,
|
||||
std::map<std::wstring, T, TCompare, TAlloc> const &value) noexcept {
|
||||
writer.WriteObjectBegin();
|
||||
for (const auto &entry : value) {
|
||||
WriteProperty(writer, entry.first, entry.second);
|
||||
}
|
||||
writer.WriteObjectEnd();
|
||||
}
|
||||
|
||||
template <class T, class TAlloc>
|
||||
inline void WriteValue(IJSValueWriter const &writer, std::vector<T, TAlloc> const &value) noexcept {
|
||||
writer.WriteArrayBegin();
|
||||
for (const auto &item : value) {
|
||||
WriteValue(writer, item);
|
||||
}
|
||||
writer.WriteArrayEnd();
|
||||
}
|
||||
|
||||
template <class T, size_t... I>
|
||||
inline void WriteTuple(IJSValueWriter const &writer, T const &tuple, std::index_sequence<I...>) noexcept {
|
||||
WriteArgs(writer, std::get<I>(tuple)...);
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
inline void WriteValue(IJSValueWriter const &writer, std::tuple<Ts...> const &value) noexcept {
|
||||
WriteTuple(writer, value, std::make_index_sequence<sizeof...(Ts)>{});
|
||||
}
|
||||
|
||||
inline void WriteValue(IJSValueWriter const &writer, JSValue const &value) noexcept {
|
||||
value.WriteTo(writer);
|
||||
}
|
||||
|
||||
inline void WriteValue(IJSValueWriter const &writer, JSValueObject const &value) noexcept {
|
||||
value.WriteTo(writer);
|
||||
}
|
||||
|
||||
inline void WriteValue(IJSValueWriter const &writer, JSValueArray const &value) noexcept {
|
||||
value.WriteTo(writer);
|
||||
}
|
||||
|
||||
inline void WriteCustomDirectEventTypeConstant(
|
||||
IJSValueWriter const &writer,
|
||||
std::wstring_view propertyName,
|
||||
std::wstring_view registrationName) noexcept {
|
||||
writer.WritePropertyName(propertyName);
|
||||
writer.WriteObjectBegin();
|
||||
WriteProperty(writer, L"registrationName", registrationName);
|
||||
writer.WriteObjectEnd();
|
||||
}
|
||||
|
||||
inline void WriteCustomDirectEventTypeConstant(
|
||||
IJSValueWriter const &writer,
|
||||
std::string_view propertyName,
|
||||
std::string_view registrationName) noexcept {
|
||||
WriteCustomDirectEventTypeConstant(writer, to_hstring(propertyName), to_hstring(registrationName));
|
||||
}
|
||||
|
||||
inline void WriteCustomDirectEventTypeConstant(IJSValueWriter const &writer, std::wstring_view eventName) noexcept {
|
||||
WriteCustomDirectEventTypeConstant(writer, L"top" + eventName, L"on" + eventName);
|
||||
}
|
||||
|
||||
inline void WriteCustomDirectEventTypeConstant(IJSValueWriter const &writer, std::string_view eventName) noexcept {
|
||||
WriteCustomDirectEventTypeConstant(writer, L"top" + to_hstring(eventName), L"on" + to_hstring(eventName));
|
||||
}
|
||||
|
||||
template <class T, std::enable_if_t<!std::is_void_v<decltype(GetStructInfo(static_cast<T *>(nullptr)))>, int>>
|
||||
inline void WriteValue(IJSValueWriter const &writer, T const &value) noexcept {
|
||||
writer.WriteObjectBegin();
|
||||
for (const auto &fieldEntry : StructInfo<T>::FieldMap) {
|
||||
writer.WritePropertyName(fieldEntry.first);
|
||||
fieldEntry.second.WriteField(writer, &value);
|
||||
}
|
||||
writer.WriteObjectEnd();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void WriteProperty(IJSValueWriter const &writer, std::string_view propertyName, T const &value) noexcept {
|
||||
writer.WritePropertyName(to_hstring(propertyName));
|
||||
WriteValue(writer, value);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void WriteProperty(IJSValueWriter const &writer, std::wstring_view propertyName, T const &value) noexcept {
|
||||
writer.WritePropertyName(propertyName);
|
||||
WriteValue(writer, value);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void WriteProperties(IJSValueWriter const &writer, T const &value) noexcept {
|
||||
auto jsValueWriter = MakeJSValueTreeWriter();
|
||||
WriteValue(jsValueWriter, value);
|
||||
auto jsValue = TakeJSValue(jsValueWriter);
|
||||
for (auto &property : jsValue.AsObject()) {
|
||||
WriteProperty(writer, property.first, property.second);
|
||||
}
|
||||
}
|
||||
|
||||
template <class... TArgs>
|
||||
inline void WriteArgs(IJSValueWriter const &writer, TArgs const &... args) noexcept {
|
||||
writer.WriteArrayBegin();
|
||||
(WriteValue(writer, args), ...);
|
||||
writer.WriteArrayEnd();
|
||||
}
|
||||
|
||||
template <class T, std::enable_if_t<std::is_invocable_v<T, IJSValueWriter const &>, int> = 0>
|
||||
inline JSValueArgWriter MakeJSValueArgWriter(T &&argWriter) noexcept {
|
||||
return std::forward<T>(argWriter);
|
||||
}
|
||||
|
||||
template <class... TArgs>
|
||||
inline JSValueArgWriter MakeJSValueArgWriter(TArgs &&... args) noexcept {
|
||||
return [&args...](IJSValueWriter const &writer) noexcept {
|
||||
WriteArgs(writer, args...);
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
||||
|
||||
#endif // MICROSOFT_REACTNATIVE_JSVALUEWRITER
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pch.h"
|
||||
#include "ModuleRegistration.h"
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
const ModuleRegistration *ModuleRegistration::s_head{nullptr};
|
||||
|
||||
ModuleRegistration::ModuleRegistration(wchar_t const *moduleName) noexcept : m_moduleName{moduleName}, m_next{s_head} {
|
||||
s_head = this;
|
||||
}
|
||||
|
||||
void AddAttributedModules(IReactPackageBuilder const &packageBuilder) noexcept {
|
||||
for (auto const *reg = ModuleRegistration::Head(); reg != nullptr; reg = reg->Next()) {
|
||||
packageBuilder.AddModule(reg->ModuleName(), reg->MakeModuleProvider());
|
||||
}
|
||||
}
|
||||
|
||||
bool TryAddAttributedModule(IReactPackageBuilder const &packageBuilder, std::wstring_view moduleName) noexcept {
|
||||
for (auto const *reg = ModuleRegistration::Head(); reg != nullptr; reg = reg->Next()) {
|
||||
if (moduleName == reg->ModuleName()) {
|
||||
packageBuilder.AddModule(moduleName, reg->MakeModuleProvider());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
|
@ -0,0 +1,114 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#include "winrt/Microsoft.ReactNative.h"
|
||||
|
||||
// We implement optional parameter macros based on the StackOverflow discussion:
|
||||
// https://stackoverflow.com/questions/3046889/optional-parameters-with-c-macros
|
||||
// Please refer to it if you want to understand it works.
|
||||
#define INTERNAL_REACT_GET_ARG_4(arg1, arg2, arg3, arg4, ...) arg4
|
||||
#define INTERNAL_REACT_RECOMPOSER_4(argsWithParentheses) INTERNAL_REACT_GET_ARG_4 argsWithParentheses
|
||||
|
||||
//
|
||||
// The macros below are internal implementation details for macro defined in nativeModules.h
|
||||
//
|
||||
|
||||
// Register struct as a ReactNative module.
|
||||
#define INTERNAL_REACT_MODULE_3_ARGS(moduleStruct, moduleName, eventEmitterName) \
|
||||
struct moduleStruct; \
|
||||
\
|
||||
template <class TDummy> \
|
||||
struct moduleStruct##_ModuleRegistration final : winrt::Microsoft::ReactNative::ModuleRegistration { \
|
||||
moduleStruct##_ModuleRegistration() noexcept : winrt::Microsoft::ReactNative::ModuleRegistration{moduleName} {} \
|
||||
\
|
||||
winrt::Microsoft::ReactNative::ReactModuleProvider MakeModuleProvider() const noexcept override { \
|
||||
return winrt::Microsoft::ReactNative::MakeModuleProvider<moduleStruct>(); \
|
||||
} \
|
||||
\
|
||||
static const moduleStruct##_ModuleRegistration Registration; \
|
||||
}; \
|
||||
\
|
||||
template <class TDummy> \
|
||||
const moduleStruct##_ModuleRegistration<TDummy> moduleStruct##_ModuleRegistration<TDummy>::Registration; \
|
||||
template struct moduleStruct##_ModuleRegistration<int>; \
|
||||
\
|
||||
template <class TRegistry> \
|
||||
constexpr void GetReactModuleInfo(moduleStruct *, TRegistry ®istry) noexcept { \
|
||||
registry.RegisterModule( \
|
||||
moduleName, eventEmitterName, winrt::Microsoft::ReactNative::ReactAttributeId<__COUNTER__>{}); \
|
||||
}
|
||||
|
||||
#define INTERNAL_REACT_MODULE_2_ARGS(moduleStruct, moduleName) \
|
||||
INTERNAL_REACT_MODULE_3_ARGS(moduleStruct, moduleName, L"")
|
||||
|
||||
#define INTERNAL_REACT_MODULE_1_ARG(moduleStruct) INTERNAL_REACT_MODULE_2_ARGS(moduleStruct, L## #moduleStruct)
|
||||
|
||||
#define INTERNAL_REACT_MODULE(...) \
|
||||
INTERNAL_REACT_RECOMPOSER_4( \
|
||||
(__VA_ARGS__, INTERNAL_REACT_MODULE_3_ARGS, INTERNAL_REACT_MODULE_2_ARGS, INTERNAL_REACT_MODULE_1_ARG, ))
|
||||
|
||||
// Provide meta data information about struct member.
|
||||
// For each member with a 'custom attribute' macro we create a static method to provide meta data.
|
||||
// The member Id is generated as a ReactMemberId<__COUNTER__> type.
|
||||
// To enumerate the static methods, we can increment ReactMemberId while static member exists.
|
||||
#define INTERNAL_REACT_MEMBER_4_ARGS(memberKind, member, jsMemberName, jsModuleName) \
|
||||
template <class TStruct, class TVisitor> \
|
||||
constexpr static void GetReactMemberAttribute( \
|
||||
TVisitor &visitor, winrt::Microsoft::ReactNative::ReactAttributeId<__COUNTER__> attributeId) noexcept { \
|
||||
visitor.Visit( \
|
||||
&TStruct::member, \
|
||||
attributeId, \
|
||||
winrt::Microsoft::ReactNative::React##memberKind##Attribute{jsMemberName, jsModuleName}); \
|
||||
}
|
||||
|
||||
#define INTERNAL_REACT_MEMBER_3_ARGS(memberKind, member, jsMemberName) \
|
||||
INTERNAL_REACT_MEMBER_4_ARGS(memberKind, member, jsMemberName, L"")
|
||||
|
||||
#define INTERNAL_REACT_MEMBER_2_ARGS(memberKind, member) INTERNAL_REACT_MEMBER_3_ARGS(memberKind, member, L## #member)
|
||||
|
||||
#define INTERNAL_REACT_MEMBER(...) \
|
||||
INTERNAL_REACT_RECOMPOSER_4( \
|
||||
(__VA_ARGS__, INTERNAL_REACT_MEMBER_4_ARGS, INTERNAL_REACT_MEMBER_3_ARGS, INTERNAL_REACT_MEMBER_2_ARGS, ))
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
struct ModuleRegistration {
|
||||
ModuleRegistration(wchar_t const *moduleName) noexcept;
|
||||
|
||||
virtual ReactModuleProvider MakeModuleProvider() const noexcept = 0;
|
||||
|
||||
static ModuleRegistration const *Head() noexcept {
|
||||
return s_head;
|
||||
}
|
||||
|
||||
ModuleRegistration const *Next() const noexcept {
|
||||
return m_next;
|
||||
}
|
||||
|
||||
wchar_t const *ModuleName() const noexcept {
|
||||
return m_moduleName;
|
||||
}
|
||||
|
||||
private:
|
||||
wchar_t const *m_moduleName{nullptr};
|
||||
ModuleRegistration const *m_next{nullptr};
|
||||
|
||||
static const ModuleRegistration *s_head;
|
||||
};
|
||||
|
||||
void AddAttributedModules(IReactPackageBuilder const &packageBuilder) noexcept;
|
||||
|
||||
bool TryAddAttributedModule(IReactPackageBuilder const &packageBuilder, std::wstring_view moduleName) noexcept;
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,114 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#ifndef MICROSOFT_REACTNATIVE_REACTCONTEXT
|
||||
#define MICROSOFT_REACTNATIVE_REACTCONTEXT
|
||||
|
||||
#if !defined(CORE_ABI) && !defined(__APPLE__)
|
||||
#include <CppWinRTIncludes.h>
|
||||
#endif
|
||||
#include <string_view>
|
||||
#include "JSValueWriter.h"
|
||||
#include "ReactNotificationService.h"
|
||||
#include "ReactPropertyBag.h"
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
// Represents a context of execution for the Native Module.
|
||||
// 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 {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return m_handle ? true : false;
|
||||
}
|
||||
|
||||
ReactPropertyBag Properties() const noexcept {
|
||||
return ReactPropertyBag{m_handle.Properties()};
|
||||
}
|
||||
|
||||
ReactNotificationService Notifications() const noexcept {
|
||||
return ReactNotificationService{m_handle.Notifications()};
|
||||
}
|
||||
|
||||
ReactDispatcher UIDispatcher() const noexcept {
|
||||
return ReactDispatcher{m_handle.UIDispatcher()};
|
||||
}
|
||||
|
||||
ReactDispatcher JSDispatcher() const noexcept {
|
||||
return ReactDispatcher{m_handle.JSDispatcher()};
|
||||
}
|
||||
|
||||
// Call methodName JS function of module with moduleName.
|
||||
// args are either function arguments or a single lambda with 'IJSValueWriter const&' argument.
|
||||
template <class... TArgs>
|
||||
void CallJSFunction(std::wstring_view moduleName, std::wstring_view methodName, TArgs &&... args) const noexcept {
|
||||
m_handle.CallJSFunction(moduleName, methodName, MakeJSValueArgWriter(std::forward<TArgs>(args)...));
|
||||
}
|
||||
|
||||
// Simplifies calls to CallJSFunction to emit events (method named 'emit').
|
||||
// Call eventName JS event of module with eventEmitterName.
|
||||
// args are either function arguments or a single lambda with 'IJSValueWriter const&' argument.
|
||||
template <class... TArgs>
|
||||
void EmitJSEvent(std::wstring_view eventEmitterName, std::wstring_view eventName, TArgs &&... args) const noexcept {
|
||||
m_handle.EmitJSEvent(eventEmitterName, eventName, MakeJSValueArgWriter(std::forward<TArgs>(args)...));
|
||||
}
|
||||
|
||||
#if !defined(CORE_ABI) && !defined(__APPLE__)
|
||||
// Dispatch eventName event to the view.
|
||||
// args are either function arguments or a single lambda with 'IJSValueWriter const&' argument.
|
||||
template <class... TArgs>
|
||||
void DispatchEvent(xaml::FrameworkElement const &view, std::wstring_view eventName, TArgs &&... args) const noexcept {
|
||||
m_handle.DispatchEvent(view, eventName, MakeJSValueArgWriter(std::forward<TArgs>(args)...));
|
||||
}
|
||||
#endif
|
||||
|
||||
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:
|
||||
IReactContext m_handle;
|
||||
};
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
||||
|
||||
#endif // MICROSOFT_REACTNATIVE_REACTCONTEXT
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#ifndef MICROSOFT_REACTNATIVE_REACTDISPATCHER
|
||||
#define MICROSOFT_REACTNATIVE_REACTDISPATCHER
|
||||
|
||||
#include <winrt/Microsoft.ReactNative.h>
|
||||
#include "ReactHandleHelper.h"
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
// Represents a dispatcher queue to invoke work item asynchronously.
|
||||
// It wraps up the IReactDispatcher and adds convenience methods for
|
||||
// working with C++ types.
|
||||
struct ReactDispatcher {
|
||||
ReactDispatcher(std::nullptr_t = nullptr) noexcept {}
|
||||
|
||||
explicit ReactDispatcher(IReactDispatcher const &handle) noexcept : m_handle{handle} {}
|
||||
|
||||
IReactDispatcher const &Handle() const noexcept {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return m_handle ? true : false;
|
||||
}
|
||||
|
||||
void Post(ReactDispatcherCallback const &callback) const noexcept {
|
||||
if (m_handle) {
|
||||
m_handle.Post(callback);
|
||||
}
|
||||
}
|
||||
|
||||
bool HasThreadAccess() const noexcept {
|
||||
return m_handle ? m_handle.HasThreadAccess() : false;
|
||||
}
|
||||
|
||||
static ReactDispatcher CreateSerialDispatcher() noexcept {
|
||||
return ReactDispatcher{ReactDispatcherHelper::CreateSerialDispatcher()};
|
||||
}
|
||||
|
||||
private:
|
||||
IReactDispatcher m_handle;
|
||||
};
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
||||
|
||||
#endif // MICROSOFT_REACTNATIVE_REACTDISPATCHER
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#include "JSValue.h"
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
struct ReactError {
|
||||
std::string Code;
|
||||
std::string Message;
|
||||
JSValueObject UserInfo;
|
||||
};
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#ifndef MICROSOFT_REACTNATIVE_REACTHANDLEHELPER
|
||||
#define MICROSOFT_REACTNATIVE_REACTHANDLEHELPER
|
||||
|
||||
//
|
||||
// Helper methods for types that have Handle() method that return
|
||||
// an IInspectable-inherited value.
|
||||
//
|
||||
|
||||
#include <winrt/Microsoft.ReactNative.h>
|
||||
#include <type_traits>
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
namespace Internal {
|
||||
template <class T>
|
||||
auto TestHandle(int) -> decltype(std::declval<T>().Handle());
|
||||
template <class>
|
||||
auto TestHandle(int *) -> void;
|
||||
} // namespace Internal
|
||||
|
||||
template <class T>
|
||||
inline constexpr bool HasHandleV =
|
||||
std::is_base_of_v<Windows::Foundation::IInspectable, std::decay_t<decltype(Internal::TestHandle<T>(0))>>;
|
||||
|
||||
// True if two types with Handle() have the same handle.
|
||||
template <class T, std::enable_if_t<HasHandleV<T>, int> = 0>
|
||||
inline bool operator==(T const &left, T const &right) noexcept {
|
||||
return left.Handle() == right.Handle();
|
||||
}
|
||||
|
||||
// True if two types with Handle() have different handles.
|
||||
template <class T, std::enable_if_t<HasHandleV<T>, int> = 0>
|
||||
inline bool operator!=(T const &left, T const &right) noexcept {
|
||||
return !(left.Handle() == right.Handle());
|
||||
}
|
||||
|
||||
// True if handle of left is null.
|
||||
template <class T, std::enable_if_t<HasHandleV<T>, int> = 0>
|
||||
inline bool operator==(T const &left, std::nullptr_t) noexcept {
|
||||
return !static_cast<bool>(left.Handle());
|
||||
}
|
||||
|
||||
// True if handle of left is not null.
|
||||
template <class T, std::enable_if_t<HasHandleV<T>, int> = 0>
|
||||
inline bool operator!=(T const &left, std::nullptr_t) noexcept {
|
||||
return static_cast<bool>(left.Handle());
|
||||
}
|
||||
|
||||
// True if handle of right is null.
|
||||
template <class T, std::enable_if_t<HasHandleV<T>, int> = 0>
|
||||
inline bool operator==(std::nullptr_t, T const &right) noexcept {
|
||||
return !static_cast<bool>(right.Handle());
|
||||
}
|
||||
|
||||
// True if handle of left is not null.
|
||||
template <class T, std::enable_if_t<HasHandleV<T>, int> = 0>
|
||||
inline bool operator!=(std::nullptr_t, T const &right) noexcept {
|
||||
return static_cast<bool>(right.Handle());
|
||||
}
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
||||
|
||||
#endif // MICROSOFT_REACTNATIVE_REACTHANDLEHELPER
|
|
@ -0,0 +1,137 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#ifndef MICROSOFT_REACTNATIVE_REACTNONABIVALUE
|
||||
#define MICROSOFT_REACTNATIVE_REACTNONABIVALUE
|
||||
|
||||
#include <winrt/Microsoft.ReactNative.h>
|
||||
#include <utility>
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
namespace implementation {
|
||||
|
||||
// The ReactNonAbiValue implementation that wraps up the non-ABI safe value.
|
||||
// This class is created by winrt::Microsoft::ReactNative::ReactNonAbiValue constructor
|
||||
// that accepts std::in_place of type std::in_place_t as the first parameter.
|
||||
template <class T>
|
||||
struct ReactNonAbiValue : implements<ReactNonAbiValue<T>, IReactNonAbiValue> {
|
||||
// Create ReactNonAbiValue and construct the wrapped value.
|
||||
template <class... TArgs>
|
||||
ReactNonAbiValue(TArgs &&... args) noexcept : m_value{std::forward<TArgs>(args)...} {}
|
||||
|
||||
// Get a pointer to the wrapped value.
|
||||
int64_t GetPtr() const noexcept {
|
||||
return reinterpret_cast<int64_t>(&m_value);
|
||||
}
|
||||
|
||||
private:
|
||||
T m_value{}; // Wrapped non-ABI value.
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
// Use this class to work with non-ABI value wrappers.
|
||||
// This class is a smart pointer to the implementation::ReactNonAbiValue which is
|
||||
// ref-counted and allocated in the heap. The ReactNonAbiValue should be used as if
|
||||
// it would be a winrt::com_ptr<implementation::ReactNonAbiValue>. It has the same behavior in regards
|
||||
// to copy/move semantic.
|
||||
// Use the constructor that accepts std::in_place of type std::in_place_t as the first parameter to allocate
|
||||
// a new instance of implementation::ReactNonAbiValue. The std::in_place allows to disambiguate the calls to
|
||||
// other constructors.
|
||||
template <class T>
|
||||
struct ReactNonAbiValue : Windows::Foundation::IInspectable {
|
||||
// Create a new instance of implementation::ReactNonAbiValue with args and keep a ref-counted pointer to it.
|
||||
template <class... TArgs>
|
||||
ReactNonAbiValue(std::in_place_t, TArgs &&... args) noexcept
|
||||
: IInspectable{make<implementation::ReactNonAbiValue<T>>(std::forward<TArgs>(args)...)} {}
|
||||
|
||||
// Create an empty ReactNonAbiValue.
|
||||
ReactNonAbiValue(std::nullptr_t = nullptr) noexcept {}
|
||||
|
||||
// Create a ReactNonAbiValue with taking the onwership from the provided pointer.
|
||||
ReactNonAbiValue(void *ptr, take_ownership_from_abi_t) noexcept : IInspectable(ptr, take_ownership_from_abi) {}
|
||||
|
||||
// Get a pointer to the value from the object it implements IReactNonAbiValue.
|
||||
// The method is unsafe because it provides no protection in case if the object has a value of different type.
|
||||
// Treat this method as if you would cast to a value type from 'void*' type.
|
||||
// The method returns nullptr if obj doe snot implement the IReactNonAbiValue interface.
|
||||
static T *GetPtrUnsafe(IInspectable const &obj) noexcept {
|
||||
if (IReactNonAbiValue temp = obj.try_as<IReactNonAbiValue>()) {
|
||||
return reinterpret_cast<T *>(temp.GetPtr());
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Get pointer to the stored value.
|
||||
// Return nullptr if ReactNonAbiValue is empty.
|
||||
T *GetPtr() const noexcept {
|
||||
if (IReactNonAbiValue const &temp =
|
||||
*static_cast<IReactNonAbiValue const *>(static_cast<IInspectable const *>(this))) {
|
||||
return reinterpret_cast<T *>(temp.GetPtr());
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Get pointer to the stored value.
|
||||
// Return nullptr if ReactNonAbiValue is empty.
|
||||
T *operator->() const noexcept {
|
||||
return GetPtr();
|
||||
}
|
||||
|
||||
// Get a reference to the stored value.
|
||||
// Crash the app if ReactNonAbiValue is empty.
|
||||
T &operator*() const noexcept {
|
||||
return *GetPtr();
|
||||
}
|
||||
|
||||
// Get a reference to the stored value.
|
||||
// Crash the app if ReactNonAbiValue is empty.
|
||||
T &Value() const noexcept {
|
||||
return *GetPtr();
|
||||
}
|
||||
|
||||
// Call the call operator() for the stored value.
|
||||
// Crash the app if ReactNonAbiValue is empty.
|
||||
template <class... TArgs>
|
||||
auto operator()(TArgs &&... args) const {
|
||||
return (*GetPtr())(std::forward<TArgs>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
// Type traits to check if type T is a IsReactNonAbiValue.
|
||||
template <class T>
|
||||
struct IsReactNonAbiValue : std::false_type {};
|
||||
template <class T>
|
||||
struct IsReactNonAbiValue<ReactNonAbiValue<T>> : std::true_type {};
|
||||
|
||||
// A shortcut for the value of the IsReactNonAbiValue type traits.
|
||||
template <class T>
|
||||
constexpr bool IsReactNonAbiValueV = IsReactNonAbiValue<T>::value;
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
||||
|
||||
#ifndef __APPLE__
|
||||
namespace winrt::impl {
|
||||
// C++/WinRT binding to connect ReactNonAbiValue with the IReactNonAbiValue interface.
|
||||
template <class T>
|
||||
struct default_interface<Microsoft::ReactNative::ReactNonAbiValue<T>> {
|
||||
using type = Microsoft::ReactNative::IReactNonAbiValue;
|
||||
};
|
||||
} // namespace winrt::impl
|
||||
#endif
|
||||
|
||||
#endif // MICROSOFT_REACTNATIVE_REACTNONABIVALUE
|
|
@ -0,0 +1,311 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#ifndef MICROSOFT_REACTNATIVE_REACTNOTIFICATIONSERVICE
|
||||
#define MICROSOFT_REACTNATIVE_REACTNOTIFICATIONSERVICE
|
||||
|
||||
#include "ReactDispatcher.h"
|
||||
#include "ReactPropertyBag.h"
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
// Encapsulates the IReactPropertyName and the notification data type
|
||||
template <class T>
|
||||
struct ReactNotificationId : ReactPropertyName {
|
||||
using NotificationDataType = T;
|
||||
using ReactPropertyName::ReactPropertyName;
|
||||
|
||||
ReactPropertyName const &NotificationName() const noexcept {
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct ReactNotificationSubscription {
|
||||
ReactNotificationSubscription(std::nullptr_t = nullptr) noexcept {}
|
||||
|
||||
explicit ReactNotificationSubscription(IReactNotificationSubscription const &handle) noexcept : m_handle{handle} {}
|
||||
|
||||
IReactNotificationSubscription const &Handle() const noexcept {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return m_handle ? true : false;
|
||||
}
|
||||
|
||||
ReactDispatcher Dispatcher() const noexcept {
|
||||
return ReactDispatcher{m_handle ? m_handle.Dispatcher() : nullptr};
|
||||
}
|
||||
|
||||
// Name of the notification.
|
||||
ReactPropertyName NotificationName() const noexcept {
|
||||
return ReactPropertyName{m_handle ? m_handle.NotificationName() : nullptr};
|
||||
};
|
||||
|
||||
// True if the subscription is still active.
|
||||
// This property is checked before notification handler is invoked.
|
||||
bool IsSubscribed() const noexcept {
|
||||
return m_handle ? m_handle.IsSubscribed() : false;
|
||||
};
|
||||
|
||||
// Remove the subscription.
|
||||
// Because of the multi-threaded nature of the notifications, the handler can be still called
|
||||
// after the Unsubscribe method called if the IsSubscribed property is already checked.
|
||||
// Consider calling the Unsubscribe method and the handler in the same IReactDispatcher
|
||||
// to ensure that no handler is invoked after the Unsubscribe method call.
|
||||
void Unsubscribe() const noexcept {
|
||||
if (m_handle) {
|
||||
m_handle.Unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
IReactNotificationSubscription m_handle;
|
||||
};
|
||||
|
||||
struct ReactNotificationSubscriptionRevoker : ReactNotificationSubscription {
|
||||
ReactNotificationSubscriptionRevoker(std::nullptr_t = nullptr) noexcept : ReactNotificationSubscription{nullptr} {}
|
||||
|
||||
explicit ReactNotificationSubscriptionRevoker(IReactNotificationSubscription const &handle) noexcept
|
||||
: ReactNotificationSubscription{handle} {}
|
||||
|
||||
ReactNotificationSubscriptionRevoker(ReactNotificationSubscriptionRevoker const &) = delete;
|
||||
ReactNotificationSubscriptionRevoker(ReactNotificationSubscriptionRevoker &&) = default;
|
||||
ReactNotificationSubscriptionRevoker &operator=(ReactNotificationSubscriptionRevoker const &) = delete;
|
||||
|
||||
ReactNotificationSubscriptionRevoker &operator=(ReactNotificationSubscriptionRevoker &&other) noexcept {
|
||||
if (this != &other) {
|
||||
Unsubscribe();
|
||||
ReactNotificationSubscription::operator=(std::move(other));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~ReactNotificationSubscriptionRevoker() noexcept {
|
||||
Unsubscribe();
|
||||
}
|
||||
};
|
||||
|
||||
struct ReactNotificationArgsBase {
|
||||
IReactNotificationArgs const &Handle() const noexcept {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return m_handle ? true : false;
|
||||
}
|
||||
|
||||
ReactNotificationSubscription Subscription() const noexcept {
|
||||
return ReactNotificationSubscription{m_handle ? m_handle.Subscription() : nullptr};
|
||||
}
|
||||
|
||||
protected:
|
||||
ReactNotificationArgsBase() = default;
|
||||
|
||||
explicit ReactNotificationArgsBase(IReactNotificationArgs const &handle) noexcept : m_handle{handle} {}
|
||||
|
||||
private:
|
||||
IReactNotificationArgs m_handle;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct ReactNotificationArgs : ReactNotificationArgsBase {
|
||||
ReactNotificationArgs(std::nullptr_t = nullptr) noexcept {}
|
||||
|
||||
explicit ReactNotificationArgs(IReactNotificationArgs const &handle) noexcept : ReactNotificationArgsBase{handle} {}
|
||||
|
||||
auto Data() const noexcept {
|
||||
return ReactPropertyBag::FromObject<T>(Handle() ? Handle().Data() : nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
template <class THandle, class TData>
|
||||
inline constexpr bool IsValidHandlerV =
|
||||
std::is_invocable_v<THandle, Windows::Foundation::IInspectable const &, ReactNotificationArgs<TData> const &>;
|
||||
|
||||
struct ReactNotificationService {
|
||||
// Notification data result type is either T or std::optional<T>.
|
||||
// T is returned for types inherited from IInspectable.
|
||||
// The std::optional<T> is returned for all other types.
|
||||
template <class T>
|
||||
using ResultType = std::conditional_t<std::is_base_of_v<Windows::Foundation::IInspectable, T>, T, std::optional<T>>;
|
||||
|
||||
// Create a new empty instance of ReactNotificationService.
|
||||
ReactNotificationService(std::nullptr_t = nullptr) noexcept {}
|
||||
|
||||
// Creates a new instance of ReactNotificationService with the provided handle.
|
||||
explicit ReactNotificationService(IReactNotificationService const &handle) noexcept : m_handle{handle} {}
|
||||
|
||||
IReactNotificationService const &Handle() const noexcept {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return m_handle ? true : false;
|
||||
}
|
||||
|
||||
template <class TData, class THandler, std::enable_if_t<IsValidHandlerV<THandler, TData>, int> = 0>
|
||||
static ReactNotificationSubscriptionRevoker Subscribe(
|
||||
IReactNotificationService const &handle,
|
||||
winrt::auto_revoke_t,
|
||||
ReactNotificationId<TData> const ¬ificationId,
|
||||
ReactDispatcher const &dispatcher,
|
||||
THandler &&handler) noexcept {
|
||||
IReactNotificationSubscription subscription = handle
|
||||
? handle.Subscribe(
|
||||
notificationId.Handle(),
|
||||
dispatcher.Handle(),
|
||||
[handler = std::forward<THandler>(handler)](
|
||||
Windows::Foundation::IInspectable const &sender, IReactNotificationArgs const &args) noexcept {
|
||||
handler(sender, ReactNotificationArgs<TData>{args});
|
||||
})
|
||||
: nullptr;
|
||||
return ReactNotificationSubscriptionRevoker{subscription};
|
||||
}
|
||||
|
||||
template <class TData, class THandler, std::enable_if_t<IsValidHandlerV<THandler, TData>, int> = 0>
|
||||
static ReactNotificationSubscriptionRevoker Subscribe(
|
||||
IReactNotificationService const &handle,
|
||||
winrt::auto_revoke_t,
|
||||
ReactNotificationId<TData> const ¬ificationId,
|
||||
THandler &&handler) noexcept {
|
||||
return Subscribe(handle, winrt::auto_revoke, notificationId, nullptr, std::forward<THandler>(handler));
|
||||
}
|
||||
|
||||
template <class TData, class THandler, std::enable_if_t<IsValidHandlerV<THandler, TData>, int> = 0>
|
||||
static ReactNotificationSubscription Subscribe(
|
||||
IReactNotificationService const &handle,
|
||||
ReactNotificationId<TData> const ¬ificationId,
|
||||
ReactDispatcher const &dispatcher,
|
||||
THandler &&handler) noexcept {
|
||||
IReactNotificationSubscription subscription = handle
|
||||
? handle.Subscribe(
|
||||
notificationId.Handle(),
|
||||
dispatcher.Handle(),
|
||||
[handler = std::forward<THandler>(handler)](
|
||||
Windows::Foundation::IInspectable const &sender, IReactNotificationArgs const &args) noexcept {
|
||||
handler(sender, ReactNotificationArgs<TData>{args});
|
||||
})
|
||||
: nullptr;
|
||||
return ReactNotificationSubscription{subscription};
|
||||
}
|
||||
|
||||
template <class TData, class THandler, std::enable_if_t<IsValidHandlerV<THandler, TData>, int> = 0>
|
||||
static ReactNotificationSubscription Subscribe(
|
||||
IReactNotificationService const &handle,
|
||||
ReactNotificationId<TData> const ¬ificationId,
|
||||
THandler &&handler) noexcept {
|
||||
return Subscribe(handle, notificationId, nullptr, std::forward<THandler>(handler));
|
||||
}
|
||||
|
||||
template <class TData, class TValue>
|
||||
static void SendNotification(
|
||||
IReactNotificationService const &handle,
|
||||
ReactNotificationId<TData> const ¬ificationId,
|
||||
Windows::Foundation::IInspectable const &sender,
|
||||
TValue &&value) noexcept {
|
||||
if (handle) {
|
||||
handle.SendNotification(
|
||||
notificationId.Handle(), sender, ReactPropertyBag::ToObject<TData>(std::forward<TValue>(value)));
|
||||
}
|
||||
}
|
||||
|
||||
static void SendNotification(
|
||||
IReactNotificationService const &handle,
|
||||
ReactNotificationId<void> const ¬ificationId,
|
||||
Windows::Foundation::IInspectable const &sender) noexcept {
|
||||
if (handle) {
|
||||
handle.SendNotification(notificationId.Handle(), sender, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
template <class TData, class TValue>
|
||||
static void SendNotification(
|
||||
IReactNotificationService const &handle,
|
||||
ReactNotificationId<TData> const ¬ificationId,
|
||||
TValue &&value) noexcept {
|
||||
if (handle) {
|
||||
handle.SendNotification(
|
||||
notificationId.Handle(), nullptr, ReactPropertyBag::ToObject<TData>(std::forward<TValue>(value)));
|
||||
}
|
||||
}
|
||||
|
||||
static void SendNotification(
|
||||
IReactNotificationService const &handle,
|
||||
ReactNotificationId<void> const ¬ificationId) noexcept {
|
||||
if (handle) {
|
||||
handle.SendNotification(notificationId.Handle(), nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
template <class TData, class THandler, std::enable_if_t<IsValidHandlerV<THandler, TData>, int> = 0>
|
||||
ReactNotificationSubscriptionRevoker Subscribe(
|
||||
winrt::auto_revoke_t,
|
||||
ReactNotificationId<TData> const ¬ificationId,
|
||||
ReactDispatcher const &dispatcher,
|
||||
THandler &&handler) const noexcept {
|
||||
return Subscribe(m_handle, winrt::auto_revoke, notificationId, dispatcher, std::forward<THandler>(handler));
|
||||
}
|
||||
|
||||
template <class TData, class THandler, std::enable_if_t<IsValidHandlerV<THandler, TData>, int> = 0>
|
||||
ReactNotificationSubscriptionRevoker
|
||||
Subscribe(winrt::auto_revoke_t, ReactNotificationId<TData> const ¬ificationId, THandler &&handler) const noexcept {
|
||||
return Subscribe(m_handle, winrt::auto_revoke, notificationId, nullptr, std::forward<THandler>(handler));
|
||||
}
|
||||
|
||||
template <class TData, class THandler, std::enable_if_t<IsValidHandlerV<THandler, TData>, int> = 0>
|
||||
ReactNotificationSubscription Subscribe(
|
||||
ReactNotificationId<TData> const ¬ificationId,
|
||||
ReactDispatcher const &dispatcher,
|
||||
THandler &&handler) const noexcept {
|
||||
return Subscribe(m_handle, notificationId, dispatcher, std::forward<THandler>(handler));
|
||||
}
|
||||
|
||||
template <class TData, class THandler, std::enable_if_t<IsValidHandlerV<THandler, TData>, int> = 0>
|
||||
ReactNotificationSubscription Subscribe(ReactNotificationId<TData> const ¬ificationId, THandler &&handler) const
|
||||
noexcept {
|
||||
return Subscribe(m_handle, notificationId, nullptr, std::forward<THandler>(handler));
|
||||
}
|
||||
|
||||
template <class TData, class TValue, std::enable_if_t<!std::is_void_v<TData>, int> = 0>
|
||||
void SendNotification(
|
||||
ReactNotificationId<TData> const ¬ificationId,
|
||||
Windows::Foundation::IInspectable const &sender,
|
||||
TValue &&value) const noexcept {
|
||||
SendNotification(m_handle, notificationId, sender, std::forward<TValue>(value));
|
||||
}
|
||||
|
||||
void SendNotification(
|
||||
ReactNotificationId<void> const ¬ificationId,
|
||||
Windows::Foundation::IInspectable const &sender) const noexcept {
|
||||
SendNotification(m_handle, notificationId, sender);
|
||||
}
|
||||
|
||||
template <class TData, class TValue, std::enable_if_t<!std::is_void_v<TData>, int> = 0>
|
||||
void SendNotification(ReactNotificationId<TData> const ¬ificationId, TValue &&value) const noexcept {
|
||||
SendNotification(m_handle, notificationId, std::forward<TValue>(value));
|
||||
}
|
||||
|
||||
void SendNotification(ReactNotificationId<void> const ¬ificationId) const noexcept {
|
||||
SendNotification(m_handle, notificationId);
|
||||
}
|
||||
|
||||
private:
|
||||
IReactNotificationService m_handle;
|
||||
};
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
||||
|
||||
#endif // MICROSOFT_REACTNATIVE_REACTNOTIFICATIONSERVICE
|
|
@ -0,0 +1,123 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pch.h"
|
||||
#include "ReactPromise.h"
|
||||
#include "JSValueWriter.h"
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
static const char *ErrorDefaultCode = "EUNSPECIFIED";
|
||||
static const char *ErrorDefaultMessage = "Error not specified.";
|
||||
|
||||
// Keys for m_reject's Error object
|
||||
static const char *ErrorMapKeyCode = "code";
|
||||
static const char *ErrorMapKeyMessage = "message";
|
||||
static const char *ErrorMapKeyUserInfo = "userInfo";
|
||||
|
||||
ReactPromiseBase::ReactPromiseBase(
|
||||
IJSValueWriter const &writer,
|
||||
MethodResultCallback const &resolve,
|
||||
MethodResultCallback const &reject) noexcept
|
||||
: m_state{new std::atomic<State>{State::Pending}}, m_writer{writer}, m_resolve{resolve}, m_reject{reject} {}
|
||||
|
||||
ReactPromiseBase::~ReactPromiseBase() noexcept {
|
||||
if (m_state.use_count() == 1) {
|
||||
Reject(L"Promise destroyed.");
|
||||
}
|
||||
}
|
||||
|
||||
// Reject the ReactPromise and report an error.
|
||||
void ReactPromiseBase::Reject(ReactError const &error) const noexcept {
|
||||
if (TrySetState(State::Rejected)) {
|
||||
m_writer.WriteArrayBegin();
|
||||
m_writer.WriteObjectBegin();
|
||||
|
||||
if (!error.Code.empty()) {
|
||||
WriteProperty(m_writer, ErrorMapKeyCode, error.Code);
|
||||
} else {
|
||||
WriteProperty(m_writer, ErrorMapKeyCode, ErrorDefaultCode);
|
||||
}
|
||||
|
||||
if (!error.Message.empty()) {
|
||||
WriteProperty(m_writer, ErrorMapKeyMessage, error.Message);
|
||||
} else {
|
||||
WriteProperty(m_writer, ErrorMapKeyMessage, ErrorDefaultMessage);
|
||||
}
|
||||
|
||||
// For consistency with iOS ensure userInfo key exists, even if we null it.
|
||||
// iOS: /React/Base/RCTUtils.m -> RCTJSErrorFromCodeMessageAndNSError
|
||||
WriteProperty(m_writer, ErrorMapKeyUserInfo, error.UserInfo);
|
||||
|
||||
m_writer.WriteObjectEnd();
|
||||
m_writer.WriteArrayEnd();
|
||||
m_reject(m_writer);
|
||||
}
|
||||
}
|
||||
|
||||
void ReactPromiseBase::Reject(char const *errorMessage) const noexcept {
|
||||
if (TrySetState(State::Rejected)) {
|
||||
m_writer.WriteArrayBegin();
|
||||
m_writer.WriteObjectBegin();
|
||||
|
||||
WriteProperty(m_writer, ErrorMapKeyCode, ErrorDefaultCode);
|
||||
WriteProperty(m_writer, ErrorMapKeyMessage, errorMessage);
|
||||
|
||||
// For consistency with iOS ensure userInfo key exists, even if we null it.
|
||||
// iOS: /React/Base/RCTUtils.m -> RCTJSErrorFromCodeMessageAndNSError
|
||||
WriteProperty(m_writer, ErrorMapKeyUserInfo, nullptr);
|
||||
|
||||
m_writer.WriteObjectEnd();
|
||||
m_writer.WriteArrayEnd();
|
||||
m_reject(m_writer);
|
||||
}
|
||||
}
|
||||
|
||||
void ReactPromiseBase::Reject(wchar_t const *errorMessage) const noexcept {
|
||||
if (TrySetState(State::Rejected)) {
|
||||
m_writer.WriteArrayBegin();
|
||||
m_writer.WriteObjectBegin();
|
||||
|
||||
WriteProperty(m_writer, ErrorMapKeyCode, ErrorDefaultCode);
|
||||
WriteProperty(m_writer, ErrorMapKeyMessage, errorMessage);
|
||||
|
||||
// For consistency with iOS ensure userInfo key exists, even if we null it.
|
||||
// iOS: /React/Base/RCTUtils.m -> RCTJSErrorFromCodeMessageAndNSError
|
||||
WriteProperty(m_writer, ErrorMapKeyUserInfo, nullptr);
|
||||
|
||||
m_writer.WriteObjectEnd();
|
||||
m_writer.WriteArrayEnd();
|
||||
m_reject(m_writer);
|
||||
}
|
||||
}
|
||||
|
||||
bool ReactPromiseBase::TrySetState(State newState) const noexcept {
|
||||
auto state = m_state->load(std::memory_order_relaxed);
|
||||
while (state == State::Pending) {
|
||||
if (m_state->compare_exchange_weak(state, newState, std::memory_order_release, std::memory_order_relaxed)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Successfully resolve the ReactPromise<void>.
|
||||
void ReactPromise<void>::Resolve() const noexcept {
|
||||
if (TrySetState(State::Resolved) && m_resolve) {
|
||||
WriteArgs(m_writer, nullptr);
|
||||
m_resolve(m_writer);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#include "ReactError.h"
|
||||
#include "winrt/Microsoft.ReactNative.h"
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
// ReactPromise represents a JavaScript Promise
|
||||
// which can be passed to the native module as a method parameter.
|
||||
//
|
||||
// Methods with REACT_METHOD attribute that use an ReactPromise as the last parameter
|
||||
// will be marked as "promise" and will return a promise when invoked from JavaScript.
|
||||
|
||||
// Base class that does not depend on template parameter T
|
||||
struct ReactPromiseBase {
|
||||
ReactPromiseBase(
|
||||
IJSValueWriter const &writer,
|
||||
MethodResultCallback const &resolve,
|
||||
MethodResultCallback const &reject) noexcept;
|
||||
|
||||
~ReactPromiseBase() noexcept;
|
||||
|
||||
// Report an Error.
|
||||
void Reject(ReactError const &error) const noexcept;
|
||||
void Reject(char const *errorMessage) const noexcept;
|
||||
void Reject(wchar_t const *errorMessage) const noexcept;
|
||||
|
||||
protected:
|
||||
enum class State { Pending, Resolved, Rejected };
|
||||
|
||||
protected:
|
||||
bool TrySetState(State newState) const noexcept;
|
||||
|
||||
protected:
|
||||
const std::shared_ptr<std::atomic<State>> m_state;
|
||||
const IJSValueWriter m_writer;
|
||||
const MethodResultCallback m_resolve;
|
||||
const MethodResultCallback m_reject;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct ReactPromise : ReactPromiseBase {
|
||||
using ReactPromiseBase::ReactPromiseBase;
|
||||
|
||||
// Successfully resolve the IReactPromise with an optional value.
|
||||
void Resolve(T const &value) const noexcept;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ReactPromise<void> : ReactPromiseBase {
|
||||
using ReactPromiseBase::ReactPromiseBase;
|
||||
|
||||
// Successfully resolve the IReactPromise with an optional value.
|
||||
void Resolve() const noexcept;
|
||||
};
|
||||
|
||||
// Successfully resolve the ReactPromise with an optional value.
|
||||
template <class T>
|
||||
void ReactPromise<T>::Resolve(T const &value) const noexcept {
|
||||
if (TrySetState(State::Resolved) && m_resolve) {
|
||||
WriteArgs(m_writer, value);
|
||||
m_resolve(m_writer);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
|
@ -0,0 +1,316 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#ifndef MICROSOFT_REACTNATIVE_REACTPROPERTYBAG
|
||||
#define MICROSOFT_REACTNATIVE_REACTPROPERTYBAG
|
||||
|
||||
//
|
||||
// ReactPropertyBag is a thread-safe storage of property values.
|
||||
// Internally the value is IInspectable and the key is a name object that represents an
|
||||
// atomized string name. Each name object is defined in the context of a namespace object.
|
||||
// The null or empty namespace object is a global namespace object.
|
||||
// The property name is unique for the same namespace object.
|
||||
// Different namespaces may have properties with the same local names.
|
||||
//
|
||||
// The ReactPropertyBag struct is a wrapper around the ABI-safe IReactPropertyBag interface.
|
||||
// The IReactPropertyBag represents all values as IInspectable object which can wrap any type.
|
||||
// On top of the untyped IReactPropertyBag values, the ReactPropertyBag offers a set of typed
|
||||
// property accessors: Get, GetOrCreate, Remove, and Set.
|
||||
//
|
||||
// To simplify access to properties we offer ReactPropertyId type that helps to
|
||||
// wrap up property name and type into one variable.
|
||||
//
|
||||
// For example, we can define a property to access an integer value:
|
||||
//
|
||||
// const React::ReactPropertyId<int> MyIntProperty{L"MyInt"};
|
||||
//
|
||||
// then we can use it to set property in settings properties during initialization:
|
||||
//
|
||||
// settings.Properties().Set(MyIntProperty, 42);
|
||||
//
|
||||
// The property can be accessed later in a native modules:
|
||||
//
|
||||
// std::optional<int> myInt = context.Properties().Get(MyIntProperty);
|
||||
//
|
||||
// Note that types inherited from IInspectable are returned
|
||||
// directly because their null value may indicated absent property value.
|
||||
// For other types we return std::optional<T>. It has std::nullopt value in case if
|
||||
// no property value is found or if it has a wrong type.
|
||||
//
|
||||
// To pass values through the ABI boundary the non-IInspectable types must be WinRT types
|
||||
// which are described here:
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.foundation.propertytype?view=winrt-18362
|
||||
//
|
||||
// In case if we do not have a requirement to pass values across the DLL/EXE boundary,
|
||||
// we can use the ReactNonAbiValue<T> wrapper to store non-ABI safe values.
|
||||
// The type ReactNonAbiValue<T> is a smart pointer similar to winrt::com_ptr
|
||||
// or winrt::Windows::Foundation::IInspactable. It is treated as IInspectable type and
|
||||
// **is not** wrapped in std::optional. It can be casted to bool to check if it is null.
|
||||
//
|
||||
// For example, we can define a property to use in our DLL or EXE to store std::string:
|
||||
//
|
||||
// const React::ReactPropertyId<React::ReactNonAbValue<std::string>> MyStringProperty{L"MyString"};
|
||||
//
|
||||
// then we can use it to set and get property value:
|
||||
//
|
||||
// context.Properties().Set(MyStringProperty, "Hello");
|
||||
// assert("Hello" == context.Properties().Get(MyStringProperty);
|
||||
//
|
||||
// The first line above creates a new React::ReactNonAbValue<std::string> value that internally.
|
||||
// allocates a ref-counted wrapper React::implementation::ReactNonAbValue<std::string> in the heap.
|
||||
// Then this value is stored in the IReactPropertyBag and can be safely retrieved in the
|
||||
// same DLL or EXE module. Using it from a different module may cause a security bug or a crash.
|
||||
//
|
||||
// Note that for passing the ABI-safe strings we must use the winrt::hstring:
|
||||
//
|
||||
// const React::ReactPropertyId<winrt::hstring> MyAbiSafeStringProperty{L"MyAbiSafeString"};
|
||||
//
|
||||
|
||||
#include <winrt/Microsoft.ReactNative.h>
|
||||
#include <optional>
|
||||
#include "ReactHandleHelper.h"
|
||||
#include "ReactNonAbiValue.h"
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
// ReactPropertyNamespace encapsulates the IReactPropertyNamespace.
|
||||
// It represents an atomic property namespace object.
|
||||
struct ReactPropertyNamespace {
|
||||
ReactPropertyNamespace(std::nullptr_t = nullptr) noexcept {}
|
||||
|
||||
explicit ReactPropertyNamespace(IReactPropertyNamespace const &handle) noexcept : m_handle{handle} {}
|
||||
|
||||
explicit ReactPropertyNamespace(param::hstring const &namespaceName) noexcept
|
||||
: m_handle{ReactPropertyBagHelper::GetNamespace(namespaceName)} {}
|
||||
|
||||
IReactPropertyNamespace const &Handle() const noexcept {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return m_handle ? true : false;
|
||||
}
|
||||
|
||||
static ReactPropertyNamespace Global() noexcept {
|
||||
return ReactPropertyNamespace{ReactPropertyBagHelper::GlobalNamespace()};
|
||||
}
|
||||
|
||||
hstring NamespaceName() const noexcept {
|
||||
return m_handle ? m_handle.NamespaceName() : hstring{};
|
||||
}
|
||||
|
||||
private:
|
||||
IReactPropertyNamespace m_handle;
|
||||
};
|
||||
|
||||
// ReactPropertyName encapsulates the IReactPropertyName.
|
||||
// It represents an atomic property name object that defines a LocalName
|
||||
// within the referenced Namespace.
|
||||
struct ReactPropertyName {
|
||||
ReactPropertyName(std::nullptr_t = nullptr) noexcept {}
|
||||
|
||||
explicit ReactPropertyName(IReactPropertyName const &handle) noexcept : m_handle{handle} {}
|
||||
|
||||
explicit ReactPropertyName(hstring const &localName) noexcept
|
||||
: m_handle{ReactPropertyBagHelper::GetName(nullptr, localName)} {}
|
||||
|
||||
ReactPropertyName(ReactPropertyNamespace const &ns, hstring const &localName) noexcept
|
||||
: m_handle{ReactPropertyBagHelper::GetName(ns.Handle(), localName)} {}
|
||||
|
||||
ReactPropertyName(hstring const &namespaceName, hstring const &localName) noexcept
|
||||
: m_handle{ReactPropertyBagHelper::GetName(ReactPropertyBagHelper::GetNamespace(namespaceName), localName)} {}
|
||||
|
||||
IReactPropertyName const &Handle() const noexcept {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return m_handle ? true : false;
|
||||
}
|
||||
|
||||
ReactPropertyNamespace Namespace() const noexcept {
|
||||
return ReactPropertyNamespace{m_handle ? m_handle.Namespace() : nullptr};
|
||||
}
|
||||
|
||||
hstring NamespaceName() const noexcept {
|
||||
return m_handle ? m_handle.Namespace().NamespaceName() : hstring{};
|
||||
}
|
||||
|
||||
hstring LocalName() const noexcept {
|
||||
return m_handle ? m_handle.LocalName() : hstring{};
|
||||
}
|
||||
|
||||
private:
|
||||
IReactPropertyName m_handle;
|
||||
};
|
||||
|
||||
// Encapsulates the IReactPropertyName and the property type
|
||||
template <class T>
|
||||
struct ReactPropertyId : ReactPropertyName {
|
||||
using PropertyType = T;
|
||||
using ReactPropertyName::ReactPropertyName;
|
||||
};
|
||||
|
||||
// ReactPropertyBag is a wrapper for IReactPropertyBag to store strongly-typed properties in a thread-safe way.
|
||||
// Types inherited from IInspectable are stored directly.
|
||||
// Values of other types are boxed with help of winrt::box_value.
|
||||
// Non-WinRT types are wrapped with the help of BoxedValue template.
|
||||
struct ReactPropertyBag {
|
||||
// Property result type is either T or std::optional<T>.
|
||||
// T is returned for types inherited from IInspectable.
|
||||
// The std::optional<T> is returned for all other types.
|
||||
template <class T>
|
||||
using ResultType = std::conditional_t<std::is_base_of_v<Windows::Foundation::IInspectable, T>, T, std::optional<T>>;
|
||||
|
||||
// Create a new empty instance of ReactPropertyBag.
|
||||
ReactPropertyBag(std::nullptr_t = nullptr) noexcept {}
|
||||
|
||||
// Creates a new instance of ReactPropertyBag with the provided handle.
|
||||
explicit ReactPropertyBag(IReactPropertyBag const &handle) noexcept : m_handle{handle} {}
|
||||
|
||||
// True if handle is not null.
|
||||
explicit operator bool() const noexcept {
|
||||
return m_handle ? true : false;
|
||||
}
|
||||
|
||||
// Get ReactPropertyBag handle.
|
||||
IReactPropertyBag const &Handle() const noexcept {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
// Get property value by property name.
|
||||
template <class T>
|
||||
static ResultType<T> Get(IReactPropertyBag const &handle, ReactPropertyId<T> const &propertyId) noexcept {
|
||||
Windows::Foundation::IInspectable propertyValue = handle ? handle.Get(propertyId.Handle()) : nullptr;
|
||||
return FromObject<T>(propertyValue);
|
||||
}
|
||||
|
||||
// Ensure that property is created by calling valueCreator if needed, and return value by property name.
|
||||
// The TCreateValue must return either T or std::optional<T>. It must have no parameters.
|
||||
template <class T, class TCreateValue>
|
||||
static ResultType<T> GetOrCreate(
|
||||
IReactPropertyBag const &handle,
|
||||
ReactPropertyId<T> const &propertyId,
|
||||
TCreateValue const &createValue) noexcept {
|
||||
Windows::Foundation::IInspectable propertyValue = handle
|
||||
? handle.GetOrCreate(propertyId.Handle(), [&createValue]() noexcept { return ToObject<T>(createValue()); })
|
||||
: nullptr;
|
||||
return FromObject<T>(propertyValue);
|
||||
}
|
||||
|
||||
// Set property value by property name.
|
||||
template <class T, class TValue>
|
||||
static void Set(IReactPropertyBag const &handle, ReactPropertyId<T> const &propertyId, TValue const &value) noexcept {
|
||||
if (handle) {
|
||||
auto propertyValue = ToObject<T>(value);
|
||||
handle.Set(propertyId.Handle(), propertyValue);
|
||||
}
|
||||
}
|
||||
|
||||
// Removes property value by property name.
|
||||
template <class T>
|
||||
static void Remove(IReactPropertyBag const &handle, ReactPropertyId<T> const &propertyId) noexcept {
|
||||
if (handle) {
|
||||
handle.Set(propertyId.Handle(), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Get property value by property name.
|
||||
template <class T>
|
||||
ResultType<T> Get(ReactPropertyId<T> const &propertyId) const noexcept {
|
||||
return Get(m_handle, propertyId);
|
||||
}
|
||||
|
||||
// Ensure that property is created by calling valueCreator if needed, and return value by property name.
|
||||
// The TCreateValue must return either T or std::optional<T>. It must have no parameters.
|
||||
template <class T, class TCreateValue>
|
||||
ResultType<T> GetOrCreate(ReactPropertyId<T> const &propertyId, TCreateValue const &createValue) const noexcept {
|
||||
return GetOrCreate(m_handle, propertyId, createValue);
|
||||
}
|
||||
|
||||
// Set property value by property name.
|
||||
template <class T, class TValue>
|
||||
void Set(ReactPropertyId<T> const &propertyId, TValue const &value) const noexcept {
|
||||
Set(m_handle, propertyId, value);
|
||||
}
|
||||
|
||||
// Removes property value by property name.
|
||||
template <class T>
|
||||
void Remove(ReactPropertyId<T> const &propertyId) const noexcept {
|
||||
Remove(m_handle, propertyId);
|
||||
}
|
||||
|
||||
// Box value to an ABI-safe object.
|
||||
template <class T, class TValue, std::enable_if_t<!IsReactNonAbiValueV<T> || std::is_same_v<T, TValue>, int> = 0>
|
||||
static Windows::Foundation::IInspectable ToObject(TValue const &value) noexcept {
|
||||
// We box WinRT types and return IInspectable-inherited values as-is.
|
||||
// The ReactNonAbiValue<U> is treated as IInspectable-inherited value if TValue=='ReactNonAbiValue<U>'.
|
||||
return box_value(value);
|
||||
}
|
||||
|
||||
// Box value to an ABI-safe object.
|
||||
template <class T, class TValue, std::enable_if_t<IsReactNonAbiValueV<T> && !std::is_same_v<T, TValue>, int> = 0>
|
||||
static Windows::Foundation::IInspectable ToObject(TValue &&value) noexcept {
|
||||
// Create ReactNonAbiValue<U> with newly allocated wrapper for U and pass TValue as an argument to the U
|
||||
// constructor. For example, we can pass TValue=='const char*' to U=='std::string' where
|
||||
// T=='ReactNonAbiValue<std::string>'.
|
||||
return T{std::in_place, std::forward<TValue>(value)};
|
||||
}
|
||||
|
||||
// Box value to an ABI-safe object.
|
||||
template <class T>
|
||||
static Windows::Foundation::IInspectable ToObject(std::optional<T> const &value) noexcept {
|
||||
return value ? ToObject<T>(*value) : nullptr;
|
||||
}
|
||||
|
||||
// Unbox value from an ABI-safe object.
|
||||
template <class T>
|
||||
static auto FromObject(Windows::Foundation::IInspectable const &obj) noexcept {
|
||||
// The code mostly borrowed from the winrt::unbox_value_or implementation to return
|
||||
// empty std::optional in case if obj is null or has a wrong type.
|
||||
if constexpr (std::is_base_of_v<Windows::Foundation::IInspectable, T>) {
|
||||
return obj.try_as<T>();
|
||||
#ifndef __APPLE__
|
||||
} else if constexpr (impl::has_category_v<T>) {
|
||||
if (obj) {
|
||||
#ifdef WINRT_IMPL_IUNKNOWN_DEFINED
|
||||
if constexpr (std::is_same_v<T, GUID>) {
|
||||
if (auto temp = obj.try_as<Windows::Foundation::IReference<guid>>()) {
|
||||
return std::optional<T>{temp.Value()};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (auto temp = obj.try_as<Windows::Foundation::IReference<T>>()) {
|
||||
return std::optional<T>{temp.Value()};
|
||||
}
|
||||
|
||||
if constexpr (std::is_enum_v<T>) {
|
||||
if (auto temp = obj.try_as<Windows::Foundation::IReference<std::underlying_type_t<T>>>()) {
|
||||
return std::optional<T>{static_cast<T>(temp.Value())};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::optional<T>{};
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
IReactPropertyBag m_handle;
|
||||
};
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
||||
|
||||
#endif // MICROSOFT_REACTNATIVE_REACTPROPERTYBAG
|
|
@ -0,0 +1,148 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT
|
||||
//
|
||||
// This file is used in both react-native-windows and react-native-macos
|
||||
// windows: vntext/Microsoft.ReactNative.Cxx
|
||||
// macOS: RNTester/RNTester-macOS/TurboModuleCxx
|
||||
// You are required to commit exactly the same content to both repo
|
||||
// A decision will be made in the near future to prevent from duplicating files
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#ifndef MICROSOFT_REACTNATIVE_STRUCTINFO
|
||||
#define MICROSOFT_REACTNATIVE_STRUCTINFO
|
||||
|
||||
#include "winrt/Microsoft.ReactNative.h"
|
||||
|
||||
// We implement optional parameter macros based on the StackOverflow discussion:
|
||||
// https://stackoverflow.com/questions/3046889/optional-parameters-with-c-macros
|
||||
// Please refer to it if you want to understand it works.
|
||||
#define INTERNAL_REACT_GET_ARG_3(arg1, arg2, arg3, ...) arg3
|
||||
#define INTERNAL_REACT_RECOMPOSER_3(argsWithParentheses) INTERNAL_REACT_GET_ARG_3 argsWithParentheses
|
||||
|
||||
//
|
||||
// These macros are internal implementation details for REACT_STRUCT and REACT_FIELD macros.
|
||||
// Please skip below to read about REACT_STRUCT and REACT_FIELD macros.
|
||||
//
|
||||
|
||||
#define INTERNAL_REACT_STRUCT(structType) \
|
||||
struct structType; \
|
||||
inline winrt::Microsoft::ReactNative::FieldMap GetStructInfo(structType *) noexcept { \
|
||||
winrt::Microsoft::ReactNative::FieldMap fieldMap{}; \
|
||||
winrt::Microsoft::ReactNative::CollectStructFields<structType, __COUNTER__>(fieldMap); \
|
||||
return fieldMap; \
|
||||
}
|
||||
|
||||
#define INTERNAL_REACT_FIELD_2_ARGS(field, fieldName) \
|
||||
template <class TClass> \
|
||||
static void RegisterField( \
|
||||
winrt::Microsoft::ReactNative::FieldMap &fieldMap, \
|
||||
winrt::Microsoft::ReactNative::ReactFieldId<__COUNTER__>) noexcept { \
|
||||
fieldMap.emplace(fieldName, &TClass::field); \
|
||||
}
|
||||
|
||||
#define INTERNAL_REACT_FIELD_1_ARG(field) INTERNAL_REACT_FIELD_2_ARGS(field, L## #field)
|
||||
#define INTERNAL_REACT_FIELD(...) \
|
||||
INTERNAL_REACT_RECOMPOSER_3((__VA_ARGS__, INTERNAL_REACT_FIELD_2_ARGS, INTERNAL_REACT_FIELD_1_ARG, ))
|
||||
|
||||
// REACT_STRUCT(structType)
|
||||
// Arguments:
|
||||
// - structType (required) - the struct name the macro is attached to.
|
||||
//
|
||||
// REACT_STRUCT annotates a C++ struct that then can be serialized and deserialized with IJSValueReader and
|
||||
// IJSValueWriter. With the help of REACT_FIELD it generates FieldMap associated with the struct which then used by
|
||||
// ReactValue and ReactWrite methods.
|
||||
#define REACT_STRUCT(structType) INTERNAL_REACT_STRUCT(structType)
|
||||
|
||||
// REACT_FIELD(field, [opt] fieldName)
|
||||
// Arguments:
|
||||
// - field (required) - the field the macro is attached to.
|
||||
// - fieldName (optional) - the field name visible to JavaScript. Default is the field name.
|
||||
//
|
||||
// REACT_FIELD annotates a field to be added to FieldMap which then used by ReactValue and ReactWrite methods.
|
||||
#define REACT_FIELD(/* field, [opt] fieldName */...) INTERNAL_REACT_FIELD(__VA_ARGS__)(__VA_ARGS__)
|
||||
|
||||
namespace winrt::Microsoft::ReactNative {
|
||||
|
||||
struct FieldInfo;
|
||||
using FieldMap = std::map<std::wstring, FieldInfo, std::less<>>;
|
||||
using FieldReaderType =
|
||||
void (*)(IJSValueReader const & /*reader*/, void * /*obj*/, const uintptr_t * /*fieldPtrStore*/) noexcept;
|
||||
using FieldWriterType =
|
||||
void (*)(IJSValueWriter const & /*writer*/, const void * /*obj*/, const uintptr_t * /*fieldPtrStore*/) noexcept;
|
||||
|
||||
template <class T>
|
||||
void GetStructInfo(T *) {}
|
||||
|
||||
template <class TClass, class TValue>
|
||||
void FieldReader(IJSValueReader const &reader, void *obj, const uintptr_t *fieldPtrStore) noexcept;
|
||||
|
||||
template <class TClass, class TValue>
|
||||
void FieldWriter(IJSValueWriter const &writer, const void *obj, const uintptr_t *fieldPtrStore) noexcept;
|
||||
|
||||
struct FieldInfo {
|
||||
template <class TClass, class TValue>
|
||||
FieldInfo(TValue TClass::*fieldPtr) noexcept
|
||||
: m_fieldReader{FieldReader<TClass, TValue>},
|
||||
m_fieldWriter{FieldWriter<TClass, TValue>},
|
||||
m_fieldPtrStore{*reinterpret_cast<uintptr_t *>(&fieldPtr)} {
|
||||
static_assert(sizeof(m_fieldPtrStore) >= sizeof(fieldPtr));
|
||||
}
|
||||
|
||||
void ReadField(IJSValueReader const &reader, void *obj) const noexcept {
|
||||
m_fieldReader(reader, obj, &m_fieldPtrStore);
|
||||
}
|
||||
|
||||
void WriteField(IJSValueWriter const &writer, const void *obj) const noexcept {
|
||||
m_fieldWriter(writer, obj, &m_fieldPtrStore);
|
||||
}
|
||||
|
||||
private:
|
||||
FieldReaderType m_fieldReader;
|
||||
FieldWriterType m_fieldWriter;
|
||||
const uintptr_t m_fieldPtrStore;
|
||||
};
|
||||
|
||||
template <class TClass, class TValue>
|
||||
void FieldReader(IJSValueReader const &reader, void *obj, const uintptr_t *fieldPtrStore) noexcept {
|
||||
using FieldPtrType = TValue TClass::*;
|
||||
ReadValue(reader, /*out*/ static_cast<TClass *>(obj)->*(*reinterpret_cast<const FieldPtrType *>(fieldPtrStore)));
|
||||
}
|
||||
|
||||
template <class TClass, class TValue>
|
||||
void FieldWriter(IJSValueWriter const &writer, const void *obj, const uintptr_t *fieldPtrStore) noexcept {
|
||||
using FieldPtrType = TValue TClass::*;
|
||||
WriteValue(writer, static_cast<const TClass *>(obj)->*(*reinterpret_cast<const FieldPtrType *>(fieldPtrStore)));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct StructInfo {
|
||||
static const FieldMap FieldMap;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
/*static*/ const FieldMap StructInfo<T>::FieldMap = GetStructInfo(static_cast<T *>(nullptr));
|
||||
|
||||
template <int I>
|
||||
using ReactFieldId = std::integral_constant<int, I>;
|
||||
|
||||
template <class TClass, int I>
|
||||
auto HasRegisterField(FieldMap &fieldMap, ReactFieldId<I> id)
|
||||
-> decltype(TClass::template RegisterField<TClass>(fieldMap, id), std::true_type{});
|
||||
template <class TClass>
|
||||
auto HasRegisterField(...) -> std::false_type;
|
||||
|
||||
template <class TClass, int I>
|
||||
void CollectStructFields(FieldMap &fieldMap) noexcept {
|
||||
if constexpr (decltype(HasRegisterField<TClass>(fieldMap, ReactFieldId<I + 1>{}))::value) {
|
||||
TClass::template RegisterField<TClass>(fieldMap, ReactFieldId<I + 1>{});
|
||||
CollectStructFields<TClass, I + 1>(fieldMap);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace winrt::Microsoft::ReactNative
|
||||
|
||||
#endif // MICROSOFT_REACTNATIVE_STRUCTINFO
|
|
@ -0,0 +1 @@
|
|||
/* dummy file */
|
|
@ -0,0 +1,380 @@
|
|||
#pragma once
|
||||
|
||||
#include "Windows.Foundation.h"
|
||||
|
||||
namespace winrt::Microsoft::ReactNative
|
||||
{
|
||||
|
||||
// IJSValueReader.idl
|
||||
|
||||
enum class JSValueType
|
||||
{
|
||||
Null,
|
||||
Object,
|
||||
Array,
|
||||
String,
|
||||
Boolean,
|
||||
Int64,
|
||||
Double,
|
||||
};
|
||||
|
||||
struct IJSValueReader : Windows::Foundation::IInspectable
|
||||
{
|
||||
struct Itf : Windows::Foundation::IInspectable::Itf
|
||||
{
|
||||
virtual JSValueType ValueType() noexcept = 0;
|
||||
virtual bool GetNextObjectProperty(hstring &propertyName) noexcept = 0;
|
||||
virtual bool GetNextArrayItem() noexcept = 0;
|
||||
virtual hstring GetString() noexcept = 0;
|
||||
virtual bool GetBoolean() noexcept = 0;
|
||||
virtual int64_t GetInt64() noexcept = 0;
|
||||
virtual double GetDouble() noexcept = 0;
|
||||
};
|
||||
|
||||
JSValueType ValueType() const noexcept { return get_itf()->ValueType(); }
|
||||
bool GetNextObjectProperty(hstring &propertyName) const noexcept { return get_itf()->GetNextObjectProperty(propertyName); }
|
||||
bool GetNextArrayItem() const noexcept { return get_itf()->GetNextArrayItem(); }
|
||||
hstring GetString() const noexcept { return get_itf()->GetString(); }
|
||||
bool GetBoolean() const noexcept { return get_itf()->GetBoolean(); }
|
||||
int64_t GetInt64() const noexcept { return get_itf()->GetInt64(); }
|
||||
double GetDouble() const noexcept { return get_itf()->GetDouble(); }
|
||||
|
||||
bool GetNextObjectProperty(const std::wstring_view &propertyName) const noexcept
|
||||
{
|
||||
auto str = std::wstring(propertyName.cbegin(), propertyName.cend());
|
||||
return GetNextObjectProperty(str);
|
||||
}
|
||||
|
||||
WINRT_TO_MAC_MAKE_WINRT_INTERFACE(IJSValueReader)
|
||||
};
|
||||
|
||||
// IJSValueWriter.idl
|
||||
|
||||
struct IJSValueWriter : Windows::Foundation::IInspectable
|
||||
{
|
||||
struct Itf : Windows::Foundation::IInspectable::Itf
|
||||
{
|
||||
virtual void WriteNull() noexcept = 0;
|
||||
virtual void WriteBoolean(bool value) noexcept = 0;
|
||||
virtual void WriteInt64(int64_t value) noexcept = 0;
|
||||
virtual void WriteDouble(double value) noexcept = 0;
|
||||
virtual void WriteString(const winrt::hstring &value) noexcept = 0;
|
||||
virtual void WriteObjectBegin() noexcept = 0;
|
||||
virtual void WritePropertyName(const winrt::hstring &name) noexcept = 0;
|
||||
virtual void WriteObjectEnd() noexcept = 0;
|
||||
virtual void WriteArrayBegin() noexcept = 0;
|
||||
virtual void WriteArrayEnd() noexcept = 0;
|
||||
};
|
||||
|
||||
void WriteNull() const noexcept { get_itf()->WriteNull(); }
|
||||
void WriteBoolean(bool value) const noexcept { get_itf()->WriteBoolean(value); }
|
||||
void WriteInt64(int64_t value) const noexcept { get_itf()->WriteInt64(value); }
|
||||
void WriteDouble(double value) const noexcept { get_itf()->WriteDouble(value); }
|
||||
void WriteString(const winrt::hstring &value) const noexcept { get_itf()->WriteString(value); }
|
||||
void WriteObjectBegin() const noexcept { get_itf()->WriteObjectBegin(); }
|
||||
void WritePropertyName(const winrt::hstring &name) const noexcept { get_itf()->WritePropertyName(name); }
|
||||
void WriteObjectEnd() const noexcept { get_itf()->WriteObjectEnd(); }
|
||||
void WriteArrayBegin() const noexcept { get_itf()->WriteArrayBegin(); }
|
||||
void WriteArrayEnd() const noexcept { get_itf()->WriteArrayEnd(); }
|
||||
|
||||
void WriteString(const wchar_t* value) const noexcept
|
||||
{
|
||||
auto str = std::wstring(value);
|
||||
WriteString(str);
|
||||
}
|
||||
|
||||
void WriteString(const std::wstring_view &value) const noexcept
|
||||
{
|
||||
auto str = std::wstring(value.cbegin(), value.cend());
|
||||
WriteString(str);
|
||||
}
|
||||
|
||||
void WritePropertyName(const std::wstring_view &name) const noexcept
|
||||
{
|
||||
auto str = std::wstring(name.cbegin(), name.cend());
|
||||
WritePropertyName(str);
|
||||
}
|
||||
|
||||
WINRT_TO_MAC_MAKE_WINRT_INTERFACE(IJSValueWriter)
|
||||
};
|
||||
|
||||
using JSValueArgWriter = std::function<void(const IJSValueWriter&)>;
|
||||
|
||||
// IReactPackageBuilder.idl
|
||||
|
||||
struct IReactModuleBuilder;
|
||||
|
||||
using ReactModuleProvider = std::function<void(const IReactModuleBuilder&)>;
|
||||
|
||||
struct IReactPackageBuilder : Windows::Foundation::IInspectable
|
||||
{
|
||||
struct Itf : Windows::Foundation::IInspectable::Itf
|
||||
{
|
||||
virtual void AddModule(const hstring& moduleName, ReactModuleProvider moduleProvider) noexcept = 0;
|
||||
};
|
||||
|
||||
void AddModule(const hstring& moduleName, const ReactModuleProvider& moduleProvider) const noexcept { get_itf()->AddModule(moduleName, moduleProvider); }
|
||||
|
||||
void AddModule(const wchar_t* moduleName, const ReactModuleProvider& moduleProvider) const noexcept
|
||||
{
|
||||
AddModule(moduleName, moduleProvider);
|
||||
}
|
||||
|
||||
void AddModule(const std::wstring_view& moduleName, const ReactModuleProvider& moduleProvider) const noexcept
|
||||
{
|
||||
auto str = std::wstring(moduleName.cbegin(), moduleName.cend());
|
||||
AddModule(str, moduleProvider);
|
||||
}
|
||||
|
||||
WINRT_TO_MAC_MAKE_WINRT_INTERFACE(IReactPackageBuilder)
|
||||
};
|
||||
|
||||
// IReactDispatcher.idl
|
||||
|
||||
using ReactDispatcherCallback = std::function<void()>;
|
||||
|
||||
struct IReactDispatcher : Windows::Foundation::IInspectable
|
||||
{
|
||||
struct Itf : Windows::Foundation::IInspectable::Itf
|
||||
{
|
||||
virtual bool HasThreadAccess() const noexcept = 0;
|
||||
virtual void Post(ReactDispatcherCallback callback) noexcept = 0;
|
||||
};
|
||||
|
||||
bool HasThreadAccess() const noexcept { return get_itf()->HasThreadAccess(); }
|
||||
void Post(const ReactDispatcherCallback& callback) const noexcept { return get_itf()->Post(callback); }
|
||||
|
||||
WINRT_TO_MAC_MAKE_WINRT_INTERFACE(IReactDispatcher)
|
||||
};
|
||||
|
||||
struct ReactDispatcherHelper
|
||||
{
|
||||
static IReactDispatcher CreateSerialDispatcher() noexcept
|
||||
{
|
||||
VerifyElseCrash(false);
|
||||
}
|
||||
};
|
||||
|
||||
// IReactNonAbiValue.idl
|
||||
|
||||
struct IReactNonAbiValue : Windows::Foundation::IInspectable
|
||||
{
|
||||
struct Itf : Windows::Foundation::IInspectable::Itf
|
||||
{
|
||||
virtual int64_t GetPtr() const noexcept = 0;
|
||||
};
|
||||
|
||||
int64_t GetPtr() const noexcept { return get_itf()->GetPtr(); }
|
||||
|
||||
WINRT_TO_MAC_MAKE_WINRT_INTERFACE(IReactNonAbiValue)
|
||||
};
|
||||
|
||||
// IReactPropertyBag.idl
|
||||
|
||||
using ReactCreatePropertyValue = std::function<Windows::Foundation::IInspectable()>;
|
||||
|
||||
struct IReactPropertyNamespace : Windows::Foundation::IInspectable
|
||||
{
|
||||
struct Itf : Windows::Foundation::IInspectable::Itf
|
||||
{
|
||||
virtual hstring NamespaceName() const noexcept = 0;
|
||||
};
|
||||
|
||||
hstring NamespaceName() const noexcept { return get_itf()->NamespaceName(); }
|
||||
|
||||
WINRT_TO_MAC_MAKE_WINRT_INTERFACE(IReactPropertyNamespace)
|
||||
};
|
||||
|
||||
struct IReactPropertyName : Windows::Foundation::IInspectable
|
||||
{
|
||||
struct Itf : Windows::Foundation::IInspectable::Itf
|
||||
{
|
||||
virtual hstring LocalName() const noexcept = 0;
|
||||
virtual IReactPropertyNamespace Namespace() const noexcept = 0;
|
||||
};
|
||||
|
||||
hstring LocalName() const noexcept { return get_itf()->LocalName(); }
|
||||
IReactPropertyNamespace Namespace() const noexcept { return get_itf()->Namespace(); }
|
||||
|
||||
WINRT_TO_MAC_MAKE_WINRT_INTERFACE(IReactPropertyName)
|
||||
};
|
||||
|
||||
struct IReactPropertyBag : Windows::Foundation::IInspectable
|
||||
{
|
||||
struct Itf : Windows::Foundation::IInspectable::Itf
|
||||
{
|
||||
virtual IInspectable Get(IReactPropertyName name) noexcept = 0;
|
||||
virtual IInspectable GetOrCreate(IReactPropertyName name, ReactCreatePropertyValue createValue) noexcept = 0;
|
||||
virtual IInspectable Set(IReactPropertyName name, IInspectable value) noexcept = 0;
|
||||
};
|
||||
|
||||
IInspectable Get(IReactPropertyName name) const noexcept { return get_itf()->Get(name); }
|
||||
IInspectable GetOrCreate(IReactPropertyName name, const ReactCreatePropertyValue& createValue) const noexcept { return get_itf()->GetOrCreate(name, createValue); }
|
||||
IInspectable Set(IReactPropertyName name, IInspectable value) const noexcept { return get_itf()->Set(name, value); }
|
||||
|
||||
WINRT_TO_MAC_MAKE_WINRT_INTERFACE(IReactPropertyBag)
|
||||
};
|
||||
|
||||
struct ReactPropertyBagHelper
|
||||
{
|
||||
static IReactPropertyNamespace GlobalNamespace() noexcept
|
||||
{
|
||||
VerifyElseCrash(false);
|
||||
}
|
||||
|
||||
static IReactPropertyNamespace GetNamespace(const hstring& namespaceName) noexcept
|
||||
{
|
||||
VerifyElseCrash(false);
|
||||
}
|
||||
|
||||
static IReactPropertyName GetName(IReactPropertyNamespace ns, const hstring& localName) noexcept
|
||||
{
|
||||
VerifyElseCrash(false);
|
||||
}
|
||||
|
||||
static IReactPropertyBag CreatePropertyBag()
|
||||
{
|
||||
VerifyElseCrash(false);
|
||||
}
|
||||
};
|
||||
|
||||
// IReactNotificationService.idl
|
||||
|
||||
struct IReactNotificationSubscription : Windows::Foundation::IInspectable
|
||||
{
|
||||
struct Itf : Windows::Foundation::IInspectable::Itf
|
||||
{
|
||||
virtual IReactPropertyName NotificationName() const noexcept = 0;
|
||||
virtual IReactDispatcher Dispatcher() const noexcept = 0;
|
||||
virtual bool IsSubscribed() const noexcept = 0;
|
||||
virtual void Unsubscribe() noexcept = 0;
|
||||
};
|
||||
|
||||
IReactPropertyName NotificationName() const noexcept { return get_itf()->NotificationName(); }
|
||||
IReactDispatcher Dispatcher() const noexcept { return get_itf()->Dispatcher(); }
|
||||
bool IsSubscribed() const noexcept { return get_itf()->IsSubscribed(); }
|
||||
void Unsubscribe() const noexcept { return get_itf()->Unsubscribe(); }
|
||||
|
||||
WINRT_TO_MAC_MAKE_WINRT_INTERFACE(IReactNotificationSubscription)
|
||||
};
|
||||
|
||||
struct IReactNotificationArgs : Windows::Foundation::IInspectable
|
||||
{
|
||||
struct Itf : Windows::Foundation::IInspectable::Itf
|
||||
{
|
||||
virtual IReactNotificationSubscription Subscription() const noexcept = 0;
|
||||
virtual IInspectable Data() const noexcept = 0;
|
||||
};
|
||||
|
||||
IReactNotificationSubscription Subscription() const noexcept { return get_itf()->Subscription(); }
|
||||
IInspectable Data() const noexcept { return get_itf()->Data(); }
|
||||
|
||||
WINRT_TO_MAC_MAKE_WINRT_INTERFACE(IReactNotificationArgs)
|
||||
};
|
||||
|
||||
using ReactNotificationHandler = std::function<void(Windows::Foundation::IInspectable, IReactNotificationArgs)>;
|
||||
|
||||
struct IReactNotificationService : Windows::Foundation::IInspectable
|
||||
{
|
||||
struct Itf : Windows::Foundation::IInspectable::Itf
|
||||
{
|
||||
virtual IReactNotificationSubscription Subscribe(IReactPropertyName notificationName, IReactDispatcher dispatcher, ReactNotificationHandler handler) noexcept = 0;
|
||||
virtual void SendNotification(IReactPropertyName notificationName, IInspectable sender, IInspectable data) noexcept = 0;
|
||||
};
|
||||
|
||||
IReactNotificationSubscription Subscribe(IReactPropertyName notificationName, IReactDispatcher dispatcher, const ReactNotificationHandler& handler) const noexcept
|
||||
{
|
||||
return get_itf()->Subscribe(notificationName, dispatcher, handler);
|
||||
}
|
||||
|
||||
void SendNotification(IReactPropertyName notificationName, IInspectable sender, IInspectable data) const noexcept
|
||||
{
|
||||
return get_itf()->SendNotification(notificationName, sender, data);
|
||||
}
|
||||
|
||||
WINRT_TO_MAC_MAKE_WINRT_INTERFACE(IReactNotificationService)
|
||||
};
|
||||
|
||||
struct ReactNotificationServiceHelper
|
||||
{
|
||||
static IReactNotificationService CreateNotificationService()
|
||||
{
|
||||
VerifyElseCrash(false);
|
||||
}
|
||||
};
|
||||
|
||||
// IReactContext.idl
|
||||
|
||||
struct IReactContext : Windows::Foundation::IInspectable
|
||||
{
|
||||
struct Itf : Windows::Foundation::IInspectable::Itf
|
||||
{
|
||||
virtual IReactPropertyBag Properties() const noexcept = 0;
|
||||
virtual IReactNotificationService Notifications() const noexcept = 0;
|
||||
virtual IReactDispatcher UIDispatcher() const noexcept = 0;
|
||||
virtual IReactDispatcher JSDispatcher() const noexcept = 0;
|
||||
virtual void CallJSFunction(const hstring& moduleName, const hstring& methodName, JSValueArgWriter paramsArgWriter) noexcept = 0;
|
||||
virtual void EmitJSEvent(const hstring& eventEmitterName, const hstring& eventName, JSValueArgWriter paramsArgWriter) noexcept = 0;
|
||||
};
|
||||
|
||||
IReactPropertyBag Properties() const noexcept { return get_itf()->Properties(); }
|
||||
IReactNotificationService Notifications() const noexcept { return get_itf()->Notifications(); }
|
||||
IReactDispatcher UIDispatcher() const noexcept { return get_itf()->UIDispatcher(); }
|
||||
IReactDispatcher JSDispatcher() const noexcept { return get_itf()->JSDispatcher(); }
|
||||
void CallJSFunction(const hstring& moduleName, const hstring& methodName, JSValueArgWriter paramsArgWriter) const noexcept { return get_itf()->CallJSFunction(moduleName, methodName, paramsArgWriter); }
|
||||
void EmitJSEvent(const hstring& eventEmitterName, const hstring& eventName, JSValueArgWriter paramsArgWriter) const noexcept { return get_itf()->EmitJSEvent(eventEmitterName, eventName, paramsArgWriter); }
|
||||
|
||||
WINRT_TO_MAC_MAKE_WINRT_INTERFACE(IReactContext)
|
||||
};
|
||||
|
||||
// IReactModuleBuilder.idl
|
||||
|
||||
using InitializerDelegate = std::function<void(IReactContext)>;
|
||||
|
||||
enum class MethodReturnType
|
||||
{
|
||||
Void,
|
||||
Callback,
|
||||
TwoCallbacks,
|
||||
Promise,
|
||||
};
|
||||
|
||||
using MethodResultCallback = std::function<void(IJSValueWriter)>;
|
||||
|
||||
using MethodDelegate = std::function<void(IJSValueReader, IJSValueWriter, MethodResultCallback, MethodResultCallback)>;
|
||||
|
||||
using SyncMethodDelegate = std::function<void(IJSValueReader, IJSValueWriter)>;
|
||||
|
||||
using ConstantProviderDelegate = std::function<void(IJSValueWriter)>;
|
||||
|
||||
struct IReactModuleBuilder : Windows::Foundation::IInspectable
|
||||
{
|
||||
struct Itf : Windows::Foundation::IInspectable::Itf
|
||||
{
|
||||
virtual void AddInitializer(InitializerDelegate initializer) noexcept = 0;
|
||||
virtual void AddConstantProvider(ConstantProviderDelegate constantProvider) noexcept = 0;
|
||||
virtual void AddMethod(const hstring& name, MethodReturnType returnType, MethodDelegate method) noexcept = 0;
|
||||
virtual void AddSyncMethod(const hstring& name, SyncMethodDelegate method) noexcept = 0;
|
||||
};
|
||||
|
||||
void AddInitializer(InitializerDelegate initializer) const noexcept { return get_itf()->AddInitializer(initializer); }
|
||||
void AddConstantProvider(ConstantProviderDelegate constantProvider) const noexcept { return get_itf()->AddConstantProvider(constantProvider); }
|
||||
void AddMethod(const hstring& name, MethodReturnType returnType, MethodDelegate method) const noexcept { return get_itf()->AddMethod(name, returnType, method); }
|
||||
void AddSyncMethod(const hstring& name, SyncMethodDelegate method) const noexcept { return get_itf()->AddSyncMethod(name, method); }
|
||||
|
||||
void AddMethod(const std::wstring_view& name, MethodReturnType returnType, MethodDelegate method) const noexcept
|
||||
{
|
||||
auto str = std::wstring(name.cbegin(), name.cend());
|
||||
return get_itf()->AddMethod(str, returnType, method);
|
||||
}
|
||||
|
||||
void AddSyncMethod(const std::wstring_view& name, SyncMethodDelegate method) const noexcept
|
||||
{
|
||||
auto str = std::wstring(name.cbegin(), name.cend());
|
||||
return get_itf()->AddSyncMethod(str, method);
|
||||
}
|
||||
|
||||
WINRT_TO_MAC_MAKE_WINRT_INTERFACE(IReactModuleBuilder)
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include <cwchar>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include "../Crash.h"
|
||||
|
||||
inline int64_t _wcstoi64(const wchar_t* str, wchar_t** str_end, int base)
|
||||
{
|
||||
return std::wcstol(str, str_end, base);
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
inline std::wstring operator+(const wchar_t* a, const std::wstring_view& b)
|
||||
{
|
||||
return a + std::wstring(b.cbegin(), b.cend());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace winrt
|
||||
{
|
||||
|
||||
using hstring = std::wstring;
|
||||
|
||||
inline hstring to_hstring(const std::string& s)
|
||||
{
|
||||
return std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().from_bytes(s);
|
||||
}
|
||||
|
||||
inline hstring to_hstring(const char* s)
|
||||
{
|
||||
return std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().from_bytes(s);
|
||||
}
|
||||
|
||||
inline hstring to_hstring(const std::string_view& w)
|
||||
{
|
||||
return to_hstring(std::string(w.cbegin(), w.cend()));
|
||||
}
|
||||
|
||||
inline hstring to_hstring(const std::wstring& s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
inline hstring to_hstring(const wchar_t* s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
inline hstring to_hstring(const std::wstring_view& w)
|
||||
{
|
||||
return to_hstring(std::wstring(w.cbegin(), w.cend()));
|
||||
}
|
||||
|
||||
inline std::string to_string(const hstring& s)
|
||||
{
|
||||
return std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().to_bytes(s);
|
||||
}
|
||||
|
||||
template<typename TClass, typename TInterface>
|
||||
struct implements : TInterface::Itf
|
||||
{
|
||||
using InterfaceHolder = TInterface;
|
||||
};
|
||||
|
||||
template<typename TClass, typename ...TArgs>
|
||||
typename TClass::InterfaceHolder make(TArgs&& ...args)
|
||||
{
|
||||
using TIH = typename TClass::InterfaceHolder;
|
||||
auto obj = std::make_shared<TClass>(std::forward<TArgs>(args)...);
|
||||
std::shared_ptr<typename TIH::Itf> ptr(obj);
|
||||
return TIH(obj);
|
||||
}
|
||||
|
||||
template<typename TClass, typename TInterface>
|
||||
TClass* get_self(const TInterface& itf)
|
||||
{
|
||||
return dynamic_cast<TClass*>(itf.get_itf());
|
||||
}
|
||||
|
||||
struct take_ownership_from_abi_t{};
|
||||
inline const take_ownership_from_abi_t take_ownership_from_abi;
|
||||
|
||||
struct auto_revoke_t{};
|
||||
inline const auto_revoke_t auto_revoke;
|
||||
|
||||
struct fire_and_forget{};
|
||||
|
||||
}
|
||||
|
||||
namespace winrt::param
|
||||
{
|
||||
|
||||
using hstring = winrt::hstring;
|
||||
|
||||
}
|
||||
|
||||
#define WINRT_TO_MAC_MAKE_WINRT_INTERFACE(NAME)\
|
||||
NAME() = default;\
|
||||
NAME(std::nullptr_t){}\
|
||||
NAME(const NAME&) = default;\
|
||||
NAME(NAME&&) = default;\
|
||||
NAME& operator=(const NAME&) = default;\
|
||||
NAME& operator=(NAME&&) = default;\
|
||||
NAME(const std::shared_ptr<Itf>& itf):IInspectable(itf){}\
|
||||
private:\
|
||||
template<typename TClass, typename TInterface>\
|
||||
friend TClass* ::winrt::get_self(const TInterface& itf);\
|
||||
Itf* get_itf() const noexcept { return static_cast<Itf*>(m_itf.get()); }\
|
||||
|
||||
namespace winrt::Windows::Foundation
|
||||
{
|
||||
|
||||
struct IInspectable
|
||||
{
|
||||
struct Itf
|
||||
{
|
||||
virtual ~Itf() = default;
|
||||
};
|
||||
|
||||
IInspectable() noexcept = default;
|
||||
IInspectable(std::nullptr_t) noexcept {}
|
||||
IInspectable(const IInspectable&) noexcept = default;
|
||||
IInspectable(IInspectable&&) noexcept = default;
|
||||
IInspectable& operator=(const IInspectable&) noexcept = default;
|
||||
IInspectable& operator=(IInspectable&&) noexcept = default;
|
||||
operator bool() const noexcept { return m_itf.get() != nullptr; }
|
||||
|
||||
IInspectable(void*, take_ownership_from_abi_t) noexcept
|
||||
{
|
||||
VerifyElseCrash(false);
|
||||
}
|
||||
|
||||
template<typename TInterface>
|
||||
TInterface try_as() const noexcept
|
||||
{
|
||||
return std::dynamic_pointer_cast<typename TInterface::Itf>(m_itf);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Itf> m_itf;
|
||||
|
||||
IInspectable(const std::shared_ptr<Itf>& itf) noexcept
|
||||
: m_itf(itf)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -71,6 +71,11 @@
|
|||
9F153461233AB2C7006DFE44 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9F153460233AB2C7006DFE44 /* Assets.xcassets */; };
|
||||
9F153467233AB2C7006DFE44 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F153466233AB2C7006DFE44 /* main.m */; };
|
||||
A13DC98BDCE5EE508FFA7BE7 /* libPods-RNTester-macOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A355204268D03CF69ABC11D /* libPods-RNTester-macOS.a */; };
|
||||
B20EF9FC250D22480039DCD8 /* JSValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B20EF9FA250D22480039DCD8 /* JSValue.cpp */; };
|
||||
B21F0FC3250D35A8004A26F2 /* JSValueTreeReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B21F0FC1250D35A8004A26F2 /* JSValueTreeReader.cpp */; };
|
||||
B21F0FC4250D35A8004A26F2 /* JSValueTreeWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B21F0FC2250D35A8004A26F2 /* JSValueTreeWriter.cpp */; };
|
||||
B21F0FCA250D4195004A26F2 /* ModuleRegistration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B21F0FC8250D4195004A26F2 /* ModuleRegistration.cpp */; };
|
||||
B2CEBEB8250D898600D92658 /* ReactPromise.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2CEBEB7250D898600D92658 /* ReactPromise.cpp */; };
|
||||
B2F2040A24E76D7600863BE1 /* ScreenshotMacOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = B2F2040924E76D7600863BE1 /* ScreenshotMacOS.mm */; };
|
||||
CDFF3988A89A5269C488653F /* libPods-iosDeviceBuild.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 287A4762E82517B7FACCE7D3 /* libPods-iosDeviceBuild.a */; };
|
||||
E59A0FBD0170A092274A6207 /* libPods-RNTesterUnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 72247071A1BF06D54F0FECC7 /* libPods-RNTesterUnitTests.a */; };
|
||||
|
@ -231,6 +236,31 @@
|
|||
9F15347C233AB2C7006DFE44 /* RNTesterIntegrationTests_macOS.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNTesterIntegrationTests_macOS.m; sourceTree = "<group>"; };
|
||||
9F15347E233AB2C7006DFE44 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
A112BDF7485AEF790F6D3E26 /* Pods-iosDeviceBuild.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iosDeviceBuild.debug.xcconfig"; path = "Pods/Target Support Files/Pods-iosDeviceBuild/Pods-iosDeviceBuild.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
B20EF9F9250D22470039DCD8 /* JSValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSValue.h; path = TurboModuleCxx/JSValue.h; sourceTree = "<group>"; };
|
||||
B20EF9FA250D22480039DCD8 /* JSValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSValue.cpp; path = TurboModuleCxx/JSValue.cpp; sourceTree = "<group>"; };
|
||||
B20EF9FB250D22480039DCD8 /* pch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pch.h; path = TurboModuleCxx/pch.h; sourceTree = "<group>"; };
|
||||
B20EF9FF250D226F0039DCD8 /* Microsoft.ReactNative.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Microsoft.ReactNative.h; path = TurboModuleCxx/winrt/Microsoft.ReactNative.h; sourceTree = "<group>"; };
|
||||
B20EFA00250D236D0039DCD8 /* Crash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Crash.h; path = TurboModuleCxx/Crash.h; sourceTree = "<group>"; };
|
||||
B21F0FBF250D35A8004A26F2 /* JSValueTreeWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSValueTreeWriter.h; path = TurboModuleCxx/JSValueTreeWriter.h; sourceTree = "<group>"; };
|
||||
B21F0FC0250D35A8004A26F2 /* JSValueTreeReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSValueTreeReader.h; path = TurboModuleCxx/JSValueTreeReader.h; sourceTree = "<group>"; };
|
||||
B21F0FC1250D35A8004A26F2 /* JSValueTreeReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSValueTreeReader.cpp; path = TurboModuleCxx/JSValueTreeReader.cpp; sourceTree = "<group>"; };
|
||||
B21F0FC2250D35A8004A26F2 /* JSValueTreeWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSValueTreeWriter.cpp; path = TurboModuleCxx/JSValueTreeWriter.cpp; sourceTree = "<group>"; };
|
||||
B21F0FC5250D39EE004A26F2 /* JSValueWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSValueWriter.h; path = TurboModuleCxx/JSValueWriter.h; sourceTree = "<group>"; };
|
||||
B21F0FC6250D39EE004A26F2 /* JSValueReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSValueReader.h; path = TurboModuleCxx/JSValueReader.h; sourceTree = "<group>"; };
|
||||
B21F0FC7250D39FB004A26F2 /* StructInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StructInfo.h; path = TurboModuleCxx/StructInfo.h; sourceTree = "<group>"; };
|
||||
B21F0FC8250D4195004A26F2 /* ModuleRegistration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ModuleRegistration.cpp; path = TurboModuleCxx/ModuleRegistration.cpp; sourceTree = "<group>"; };
|
||||
B21F0FC9250D4195004A26F2 /* ModuleRegistration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ModuleRegistration.h; path = TurboModuleCxx/ModuleRegistration.h; sourceTree = "<group>"; };
|
||||
B21F0FCB250D6D85004A26F2 /* ReactHandleHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ReactHandleHelper.h; path = TurboModuleCxx/ReactHandleHelper.h; sourceTree = "<group>"; };
|
||||
B21F0FCC250D6D85004A26F2 /* ReactDispatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ReactDispatcher.h; path = TurboModuleCxx/ReactDispatcher.h; sourceTree = "<group>"; };
|
||||
B21F0FCD250D6D85004A26F2 /* ReactPropertyBag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ReactPropertyBag.h; path = TurboModuleCxx/ReactPropertyBag.h; sourceTree = "<group>"; };
|
||||
B21F0FCE250D6D85004A26F2 /* ReactNonAbiValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ReactNonAbiValue.h; path = TurboModuleCxx/ReactNonAbiValue.h; sourceTree = "<group>"; };
|
||||
B21F0FCF250D6D85004A26F2 /* ReactNotificationService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ReactNotificationService.h; path = TurboModuleCxx/ReactNotificationService.h; sourceTree = "<group>"; };
|
||||
B21F0FD0250D6D85004A26F2 /* ReactContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ReactContext.h; path = TurboModuleCxx/ReactContext.h; sourceTree = "<group>"; };
|
||||
B2CEBEB5250D898600D92658 /* ReactPromise.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ReactPromise.h; path = TurboModuleCxx/ReactPromise.h; sourceTree = "<group>"; };
|
||||
B2CEBEB6250D898600D92658 /* ReactError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ReactError.h; path = TurboModuleCxx/ReactError.h; sourceTree = "<group>"; };
|
||||
B2CEBEB7250D898600D92658 /* ReactPromise.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ReactPromise.cpp; path = TurboModuleCxx/ReactPromise.cpp; sourceTree = "<group>"; };
|
||||
B2CEBEB9250D8C8C00D92658 /* NativeModules.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeModules.h; path = TurboModuleCxx/NativeModules.h; sourceTree = "<group>"; };
|
||||
B2CEBEBA250D8D3200D92658 /* Windows.Foundation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Windows.Foundation.h; path = TurboModuleCxx/winrt/Windows.Foundation.h; sourceTree = "<group>"; };
|
||||
B2F2040824E76D7600863BE1 /* ScreenshotMacOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScreenshotMacOS.h; path = NativeModuleExample/ScreenshotMacOS.h; sourceTree = SOURCE_ROOT; };
|
||||
B2F2040924E76D7600863BE1 /* ScreenshotMacOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ScreenshotMacOS.mm; path = NativeModuleExample/ScreenshotMacOS.mm; sourceTree = SOURCE_ROOT; };
|
||||
C81D39A606858D29861E5930 /* Pods-iosSimulatorBuild.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iosSimulatorBuild.debug.xcconfig"; path = "Pods/Target Support Files/Pods-iosSimulatorBuild/Pods-iosSimulatorBuild.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
|
@ -535,6 +565,7 @@
|
|||
9F15345C233AB2C4006DFE44 /* RNTester-macOS */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B20EF9F6250D22000039DCD8 /* TurboModuleCxx */,
|
||||
B2F2040824E76D7600863BE1 /* ScreenshotMacOS.h */,
|
||||
B2F2040924E76D7600863BE1 /* ScreenshotMacOS.mm */,
|
||||
5101985523AD9EE600118BF1 /* Main.storyboard */,
|
||||
|
@ -568,6 +599,46 @@
|
|||
path = "RNTester-macOSIntegrationTests";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B20EF9F6250D22000039DCD8 /* TurboModuleCxx */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B2CEBEB9250D8C8C00D92658 /* NativeModules.h */,
|
||||
B2CEBEB6250D898600D92658 /* ReactError.h */,
|
||||
B2CEBEB7250D898600D92658 /* ReactPromise.cpp */,
|
||||
B2CEBEB5250D898600D92658 /* ReactPromise.h */,
|
||||
B21F0FD0250D6D85004A26F2 /* ReactContext.h */,
|
||||
B21F0FCC250D6D85004A26F2 /* ReactDispatcher.h */,
|
||||
B21F0FCB250D6D85004A26F2 /* ReactHandleHelper.h */,
|
||||
B21F0FCE250D6D85004A26F2 /* ReactNonAbiValue.h */,
|
||||
B21F0FCF250D6D85004A26F2 /* ReactNotificationService.h */,
|
||||
B21F0FCD250D6D85004A26F2 /* ReactPropertyBag.h */,
|
||||
B21F0FC8250D4195004A26F2 /* ModuleRegistration.cpp */,
|
||||
B21F0FC9250D4195004A26F2 /* ModuleRegistration.h */,
|
||||
B21F0FC7250D39FB004A26F2 /* StructInfo.h */,
|
||||
B21F0FC6250D39EE004A26F2 /* JSValueReader.h */,
|
||||
B21F0FC5250D39EE004A26F2 /* JSValueWriter.h */,
|
||||
B21F0FC1250D35A8004A26F2 /* JSValueTreeReader.cpp */,
|
||||
B21F0FC0250D35A8004A26F2 /* JSValueTreeReader.h */,
|
||||
B21F0FC2250D35A8004A26F2 /* JSValueTreeWriter.cpp */,
|
||||
B21F0FBF250D35A8004A26F2 /* JSValueTreeWriter.h */,
|
||||
B20EFA00250D236D0039DCD8 /* Crash.h */,
|
||||
B20EF9FA250D22480039DCD8 /* JSValue.cpp */,
|
||||
B20EF9F9250D22470039DCD8 /* JSValue.h */,
|
||||
B20EF9FB250D22480039DCD8 /* pch.h */,
|
||||
B20EF9FE250D225A0039DCD8 /* winrt */,
|
||||
);
|
||||
name = TurboModuleCxx;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B20EF9FE250D225A0039DCD8 /* winrt */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B2CEBEBA250D8D3200D92658 /* Windows.Foundation.h */,
|
||||
B20EF9FF250D226F0039DCD8 /* Microsoft.ReactNative.h */,
|
||||
);
|
||||
name = winrt;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E7DB20A022B2BA84005AC45F /* RNTesterUnitTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1265,9 +1336,14 @@
|
|||
B2F2040A24E76D7600863BE1 /* ScreenshotMacOS.mm in Sources */,
|
||||
5101985A23AD9F5B00118BF1 /* ViewController.m in Sources */,
|
||||
9F153467233AB2C7006DFE44 /* main.m in Sources */,
|
||||
B2CEBEB8250D898600D92658 /* ReactPromise.cpp in Sources */,
|
||||
B21F0FCA250D4195004A26F2 /* ModuleRegistration.cpp in Sources */,
|
||||
38CB64352445042D009035CC /* RNTesterTurboModuleProvider.mm in Sources */,
|
||||
B21F0FC3250D35A8004A26F2 /* JSValueTreeReader.cpp in Sources */,
|
||||
B21F0FC4250D35A8004A26F2 /* JSValueTreeWriter.cpp in Sources */,
|
||||
9F15345F233AB2C4006DFE44 /* AppDelegate.mm in Sources */,
|
||||
38B2630C2444F628006AB4D5 /* FlexibleSizeExampleView.m in Sources */,
|
||||
B20EF9FC250D22480039DCD8 /* JSValue.cpp in Sources */,
|
||||
38B2630B2444F5EB006AB4D5 /* UpdatePropertiesExampleView.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -1843,6 +1919,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = "RNTester-macOS/RNTester_macOS.entitlements";
|
||||
|
@ -1852,6 +1929,31 @@
|
|||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"${PODS_ROOT}/Headers/Public\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/DoubleConversion\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/FBLazyVector\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/FBReactNativeSpec\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/RCT-Folly\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/RCTRequired\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/RCTTypeSafety\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/React-Core\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/React-RCTTest\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/React-RCTText\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/React-cxxreact\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/React-jsi\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/React-jsiexecutor\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/React-jsinspector\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/ReactCommon\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/Yoga\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/glog\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/hermes\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/libevent\"",
|
||||
"\"$(PODS_ROOT)/boost-for-react-native\"",
|
||||
"\"$(PODS_ROOT)/Headers/Private/React-Core\"",
|
||||
"\"$(SOURCE_ROOT)/RNTester-macOS/TurboModuleCxx\"",
|
||||
);
|
||||
INFOPLIST_FILE = "RNTester-macOS/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -1877,6 +1979,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = "RNTester-macOS/RNTester_macOS.entitlements";
|
||||
|
@ -1887,6 +1990,31 @@
|
|||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"${PODS_ROOT}/Headers/Public\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/DoubleConversion\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/FBLazyVector\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/FBReactNativeSpec\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/RCT-Folly\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/RCTRequired\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/RCTTypeSafety\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/React-Core\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/React-RCTTest\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/React-RCTText\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/React-cxxreact\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/React-jsi\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/React-jsiexecutor\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/React-jsinspector\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/ReactCommon\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/Yoga\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/glog\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/hermes\"",
|
||||
"\"${PODS_ROOT}/Headers/Public/libevent\"",
|
||||
"\"$(PODS_ROOT)/boost-for-react-native\"",
|
||||
"\"$(PODS_ROOT)/Headers/Private/React-Core\"",
|
||||
"\"$(SOURCE_ROOT)/RNTester-macOS/TurboModuleCxx\"",
|
||||
);
|
||||
INFOPLIST_FILE = "RNTester-macOS/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
|
Загрузка…
Ссылка в новой задаче