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:
Zihan Chen (MSFT) 2020-09-14 12:57:45 -07:00 коммит произвёл GitHub
Родитель 44211a6304
Коммит 1a5abe4bec
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
29 изменённых файлов: 6381 добавлений и 31 удалений

Просмотреть файл

@ -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 &registry) 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 &notificationId,
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 &notificationId,
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 &notificationId,
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 &notificationId,
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 &notificationId,
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 &notificationId,
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 &notificationId,
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 &notificationId) 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 &notificationId,
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 &notificationId, 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 &notificationId,
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 &notificationId, 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 &notificationId,
Windows::Foundation::IInspectable const &sender,
TValue &&value) const noexcept {
SendNotification(m_handle, notificationId, sender, std::forward<TValue>(value));
}
void SendNotification(
ReactNotificationId<void> const &notificationId,
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 &notificationId, TValue &&value) const noexcept {
SendNotification(m_handle, notificationId, std::forward<TValue>(value));
}
void SendNotification(ReactNotificationId<void> const &notificationId) 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)",

0
android-patches/build.sh Normal file → Executable file
Просмотреть файл