yeet
This commit is contained in:
5
node_modules/react-native/ReactCommon/turbomodule/.clang-tidy
generated
vendored
Normal file
5
node_modules/react-native/ReactCommon/turbomodule/.clang-tidy
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
Checks: '>
|
||||
clang-diagnostic-*,
|
||||
'
|
||||
...
|
86
node_modules/react-native/ReactCommon/turbomodule/core/BUCK
generated
vendored
Normal file
86
node_modules/react-native/ReactCommon/turbomodule/core/BUCK
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "OBJC_ARC_PREPROCESSOR_FLAGS", "get_preprocessor_flags_for_build_mode", "get_static_library_ios_flags")
|
||||
load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "react_native_target", "react_native_xplat_target", "rn_xplat_cxx_library", "subdir_glob")
|
||||
|
||||
rn_xplat_cxx_library(
|
||||
name = "core",
|
||||
srcs = glob(
|
||||
["*.cpp"],
|
||||
),
|
||||
header_namespace = "",
|
||||
exported_headers = subdir_glob(
|
||||
[
|
||||
("", "*.h"),
|
||||
],
|
||||
prefix = "ReactCommon",
|
||||
),
|
||||
compiler_flags = [
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
"-std=c++14",
|
||||
"-Wall",
|
||||
],
|
||||
fbandroid_deps = [
|
||||
react_native_target("jni/react/jni:jni"),
|
||||
],
|
||||
fbandroid_exported_headers = subdir_glob(
|
||||
[
|
||||
("platform/android", "*.h"),
|
||||
],
|
||||
prefix = "ReactCommon",
|
||||
),
|
||||
fbandroid_srcs = glob(
|
||||
[
|
||||
"platform/android/**/*.cpp",
|
||||
],
|
||||
),
|
||||
fbobjc_compiler_flags = [
|
||||
"-Wall",
|
||||
"-fobjc-arc-exceptions",
|
||||
],
|
||||
fbobjc_inherited_buck_flags = get_static_library_ios_flags(),
|
||||
fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"],
|
||||
fbobjc_preprocessor_flags = OBJC_ARC_PREPROCESSOR_FLAGS + get_preprocessor_flags_for_build_mode(),
|
||||
force_static = True,
|
||||
ios_deps = [
|
||||
"//xplat/FBBaseLite:FBBaseLite",
|
||||
"//xplat/js/react-native-github:RCTCxxModule",
|
||||
"//xplat/js/react-native-github:ReactInternal",
|
||||
],
|
||||
ios_exported_headers = subdir_glob(
|
||||
[
|
||||
("platform/ios", "*.h"),
|
||||
],
|
||||
prefix = "ReactCommon",
|
||||
),
|
||||
ios_frameworks = [
|
||||
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
|
||||
],
|
||||
ios_srcs = glob(
|
||||
[
|
||||
"platform/ios/**/*.cpp",
|
||||
"platform/ios/**/*.mm",
|
||||
],
|
||||
),
|
||||
platforms = (ANDROID, APPLE),
|
||||
preprocessor_flags = [
|
||||
"-DLOG_TAG=\"ReactNative\"",
|
||||
"-DWITH_FBSYSTRACE=1",
|
||||
],
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
deps = [
|
||||
"//xplat/fbsystrace:fbsystrace",
|
||||
"//xplat/folly:headers_only",
|
||||
"//xplat/folly:memory",
|
||||
"//xplat/folly:molly",
|
||||
"//xplat/jsi:JSIDynamic",
|
||||
"//xplat/third-party/glog:glog",
|
||||
react_native_xplat_target("cxxreact:bridge"),
|
||||
react_native_xplat_target("cxxreact:module"),
|
||||
react_native_xplat_target("callinvoker:callinvoker"),
|
||||
],
|
||||
exported_deps = [
|
||||
"//xplat/jsi:jsi",
|
||||
],
|
||||
)
|
52
node_modules/react-native/ReactCommon/turbomodule/core/LongLivedObject.cpp
generated
vendored
Normal file
52
node_modules/react-native/ReactCommon/turbomodule/core/LongLivedObject.cpp
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "LongLivedObject.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
// LongLivedObjectCollection
|
||||
LongLivedObjectCollection &LongLivedObjectCollection::get() {
|
||||
static LongLivedObjectCollection instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
LongLivedObjectCollection::LongLivedObjectCollection() {}
|
||||
|
||||
void LongLivedObjectCollection::add(std::shared_ptr<LongLivedObject> so) const {
|
||||
std::lock_guard<std::mutex> lock(collectionMutex_);
|
||||
collection_.insert(so);
|
||||
}
|
||||
|
||||
void LongLivedObjectCollection::remove(const LongLivedObject *o) const {
|
||||
std::lock_guard<std::mutex> lock(collectionMutex_);
|
||||
auto p = collection_.begin();
|
||||
for (; p != collection_.end(); p++) {
|
||||
if (p->get() == o) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (p != collection_.end()) {
|
||||
collection_.erase(p);
|
||||
}
|
||||
}
|
||||
|
||||
void LongLivedObjectCollection::clear() const {
|
||||
std::lock_guard<std::mutex> lock(collectionMutex_);
|
||||
collection_.clear();
|
||||
}
|
||||
|
||||
// LongLivedObject
|
||||
LongLivedObject::LongLivedObject() {}
|
||||
|
||||
void LongLivedObject::allowRelease() {
|
||||
LongLivedObjectCollection::get().remove(this);
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
56
node_modules/react-native/ReactCommon/turbomodule/core/LongLivedObject.h
generated
vendored
Normal file
56
node_modules/react-native/ReactCommon/turbomodule/core/LongLivedObject.h
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/**
|
||||
* A simple wrapper class that can be registered to a collection that keep it
|
||||
* alive for extended period of time. This object can be removed from the
|
||||
* collection when needed.
|
||||
*
|
||||
* The subclass of this class must be created using std::make_shared<T>().
|
||||
* After creation, add it to the `LongLivedObjectCollection`.
|
||||
* When done with the object, call `allowRelease()` to allow the OS to release
|
||||
* it.
|
||||
*/
|
||||
class LongLivedObject {
|
||||
public:
|
||||
void allowRelease();
|
||||
|
||||
protected:
|
||||
LongLivedObject();
|
||||
};
|
||||
|
||||
/**
|
||||
* A singleton, thread-safe, write-only collection for the `LongLivedObject`s.
|
||||
*/
|
||||
class LongLivedObjectCollection {
|
||||
public:
|
||||
static LongLivedObjectCollection &get();
|
||||
|
||||
LongLivedObjectCollection(LongLivedObjectCollection const &) = delete;
|
||||
void operator=(LongLivedObjectCollection const &) = delete;
|
||||
|
||||
void add(std::shared_ptr<LongLivedObject> o) const;
|
||||
void remove(const LongLivedObject *o) const;
|
||||
void clear() const;
|
||||
|
||||
private:
|
||||
LongLivedObjectCollection();
|
||||
mutable std::unordered_set<std::shared_ptr<LongLivedObject>> collection_;
|
||||
mutable std::mutex collectionMutex_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
207
node_modules/react-native/ReactCommon/turbomodule/core/TurboCxxModule.cpp
generated
vendored
Normal file
207
node_modules/react-native/ReactCommon/turbomodule/core/TurboCxxModule.cpp
generated
vendored
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "TurboCxxModule.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <ReactCommon/TurboModuleUtils.h>
|
||||
#include <jsi/JSIDynamic.h>
|
||||
|
||||
using namespace facebook;
|
||||
using namespace facebook::xplat::module;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
namespace {
|
||||
CxxModule::Callback makeTurboCxxModuleCallback(
|
||||
jsi::Runtime &runtime,
|
||||
std::weak_ptr<CallbackWrapper> weakWrapper) {
|
||||
return [weakWrapper,
|
||||
wrapperWasCalled = false](std::vector<folly::dynamic> args) mutable {
|
||||
if (wrapperWasCalled) {
|
||||
throw std::runtime_error("callback arg cannot be called more than once");
|
||||
}
|
||||
|
||||
auto strongWrapper = weakWrapper.lock();
|
||||
if (!strongWrapper) {
|
||||
return;
|
||||
}
|
||||
|
||||
strongWrapper->jsInvoker().invokeAsync([weakWrapper, args]() {
|
||||
auto strongWrapper2 = weakWrapper.lock();
|
||||
if (!strongWrapper2) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<jsi::Value> innerArgs;
|
||||
for (auto &a : args) {
|
||||
innerArgs.push_back(
|
||||
jsi::valueFromDynamic(strongWrapper2->runtime(), a));
|
||||
}
|
||||
strongWrapper2->callback().call(
|
||||
strongWrapper2->runtime(),
|
||||
(const jsi::Value *)innerArgs.data(),
|
||||
innerArgs.size());
|
||||
|
||||
strongWrapper2->destroy();
|
||||
});
|
||||
|
||||
wrapperWasCalled = true;
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TurboCxxModule::TurboCxxModule(
|
||||
std::unique_ptr<CxxModule> cxxModule,
|
||||
std::shared_ptr<CallInvoker> jsInvoker)
|
||||
: TurboModule(cxxModule->getName(), jsInvoker),
|
||||
cxxMethods_(cxxModule->getMethods()),
|
||||
cxxModule_(std::move(cxxModule)) {}
|
||||
|
||||
jsi::Value TurboCxxModule::get(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::PropNameID &propName) {
|
||||
std::string propNameUtf8 = propName.utf8(runtime);
|
||||
|
||||
if (propNameUtf8 == "getConstants") {
|
||||
// This is special cased because `getConstants()` is already a part of
|
||||
// CxxModule.
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
propName,
|
||||
0,
|
||||
[this](
|
||||
jsi::Runtime &rt,
|
||||
const jsi::Value &thisVal,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
jsi::Object result(rt);
|
||||
auto constants = cxxModule_->getConstants();
|
||||
for (auto &pair : constants) {
|
||||
result.setProperty(
|
||||
rt, pair.first.c_str(), jsi::valueFromDynamic(rt, pair.second));
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
for (auto &method : cxxMethods_) {
|
||||
if (method.name == propNameUtf8) {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
propName,
|
||||
0,
|
||||
[this, propNameUtf8](
|
||||
jsi::Runtime &rt,
|
||||
const jsi::Value &thisVal,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
return invokeMethod(rt, VoidKind, propNameUtf8, args, count);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
|
||||
jsi::Value TurboCxxModule::invokeMethod(
|
||||
jsi::Runtime &runtime,
|
||||
TurboModuleMethodValueKind valueKind,
|
||||
const std::string &methodName,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
auto it = cxxMethods_.begin();
|
||||
for (; it != cxxMethods_.end(); it++) {
|
||||
auto method = *it;
|
||||
if (method.name == methodName) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (it == cxxMethods_.end()) {
|
||||
throw std::runtime_error(
|
||||
"Function '" + methodName + "' cannot be found on cxxmodule: " + name_);
|
||||
}
|
||||
|
||||
auto method = *it;
|
||||
|
||||
if (method.syncFunc) {
|
||||
auto innerArgs = folly::dynamic::array();
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
innerArgs.push_back(jsi::dynamicFromValue(runtime, args[i]));
|
||||
}
|
||||
return jsi::valueFromDynamic(
|
||||
runtime, method.syncFunc(std::move(innerArgs)));
|
||||
} else if (method.func && !method.isPromise) {
|
||||
// Async method.
|
||||
CxxModule::Callback first;
|
||||
CxxModule::Callback second;
|
||||
|
||||
if (count < method.callbacks) {
|
||||
throw std::invalid_argument(folly::to<std::string>(
|
||||
"Expected ",
|
||||
method.callbacks,
|
||||
" callbacks, but only ",
|
||||
count,
|
||||
" parameters provided"));
|
||||
}
|
||||
|
||||
if (method.callbacks == 1) {
|
||||
auto wrapper = CallbackWrapper::createWeak(
|
||||
args[count - 1].getObject(runtime).getFunction(runtime),
|
||||
runtime,
|
||||
jsInvoker_);
|
||||
first = makeTurboCxxModuleCallback(runtime, wrapper);
|
||||
} else if (method.callbacks == 2) {
|
||||
auto wrapper1 = CallbackWrapper::createWeak(
|
||||
args[count - 2].getObject(runtime).getFunction(runtime),
|
||||
runtime,
|
||||
jsInvoker_);
|
||||
auto wrapper2 = CallbackWrapper::createWeak(
|
||||
args[count - 1].getObject(runtime).getFunction(runtime),
|
||||
runtime,
|
||||
jsInvoker_);
|
||||
first = makeTurboCxxModuleCallback(runtime, wrapper1);
|
||||
second = makeTurboCxxModuleCallback(runtime, wrapper2);
|
||||
}
|
||||
|
||||
auto innerArgs = folly::dynamic::array();
|
||||
for (size_t i = 0; i < count - method.callbacks; i++) {
|
||||
innerArgs.push_back(jsi::dynamicFromValue(runtime, args[i]));
|
||||
}
|
||||
|
||||
method.func(std::move(innerArgs), first, second);
|
||||
} else if (method.isPromise) {
|
||||
return createPromiseAsJSIValue(
|
||||
runtime,
|
||||
[method, args, count, this](
|
||||
jsi::Runtime &rt, std::shared_ptr<Promise> promise) {
|
||||
auto resolveWrapper = CallbackWrapper::createWeak(
|
||||
promise->resolve_.getFunction(rt), rt, jsInvoker_);
|
||||
auto rejectWrapper = CallbackWrapper::createWeak(
|
||||
promise->reject_.getFunction(rt), rt, jsInvoker_);
|
||||
CxxModule::Callback resolve =
|
||||
makeTurboCxxModuleCallback(rt, resolveWrapper);
|
||||
CxxModule::Callback reject =
|
||||
makeTurboCxxModuleCallback(rt, rejectWrapper);
|
||||
|
||||
auto innerArgs = folly::dynamic::array();
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
innerArgs.push_back(jsi::dynamicFromValue(rt, args[i]));
|
||||
}
|
||||
|
||||
method.func(std::move(innerArgs), resolve, reject);
|
||||
});
|
||||
}
|
||||
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
49
node_modules/react-native/ReactCommon/turbomodule/core/TurboCxxModule.h
generated
vendored
Normal file
49
node_modules/react-native/ReactCommon/turbomodule/core/TurboCxxModule.h
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <cxxreact/CxxModule.h>
|
||||
|
||||
#include "TurboModule.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/**
|
||||
* A helper class to convert the legacy CxxModule instance to a TurboModule
|
||||
* instance. This should be used only for migration purpose (to TurboModule),
|
||||
* since it's not very performant due to a lot of back-and-forth value
|
||||
* conversions between folly::dynamic and jsi::Value.
|
||||
*/
|
||||
class JSI_EXPORT TurboCxxModule : public TurboModule {
|
||||
public:
|
||||
TurboCxxModule(
|
||||
std::unique_ptr<facebook::xplat::module::CxxModule> cxxModule,
|
||||
std::shared_ptr<CallInvoker> jsInvoker);
|
||||
|
||||
virtual facebook::jsi::Value get(
|
||||
facebook::jsi::Runtime &runtime,
|
||||
const facebook::jsi::PropNameID &propName) override;
|
||||
|
||||
jsi::Value invokeMethod(
|
||||
jsi::Runtime &runtime,
|
||||
TurboModuleMethodValueKind valueKind,
|
||||
const std::string &methodName,
|
||||
const jsi::Value *args,
|
||||
size_t count);
|
||||
|
||||
private:
|
||||
std::vector<facebook::xplat::module::CxxModule::Method> cxxMethods_;
|
||||
std::unique_ptr<facebook::xplat::module::CxxModule> cxxModule_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
44
node_modules/react-native/ReactCommon/turbomodule/core/TurboModule.cpp
generated
vendored
Normal file
44
node_modules/react-native/ReactCommon/turbomodule/core/TurboModule.cpp
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "TurboModule.h"
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
TurboModule::TurboModule(
|
||||
const std::string &name,
|
||||
std::shared_ptr<CallInvoker> jsInvoker)
|
||||
: name_(name), jsInvoker_(jsInvoker) {}
|
||||
|
||||
TurboModule::~TurboModule() {}
|
||||
|
||||
jsi::Value TurboModule::get(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::PropNameID &propName) {
|
||||
std::string propNameUtf8 = propName.utf8(runtime);
|
||||
auto p = methodMap_.find(propNameUtf8);
|
||||
if (p == methodMap_.end()) {
|
||||
// Method was not found, let JS decide what to do.
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
MethodMetadata meta = p->second;
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
propName,
|
||||
meta.argCount,
|
||||
[this, meta](
|
||||
facebook::jsi::Runtime &rt,
|
||||
const facebook::jsi::Value &thisVal,
|
||||
const facebook::jsi::Value *args,
|
||||
size_t count) { return meta.invoker(rt, *this, args, count); });
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
71
node_modules/react-native/ReactCommon/turbomodule/core/TurboModule.h
generated
vendored
Normal file
71
node_modules/react-native/ReactCommon/turbomodule/core/TurboModule.h
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
#include <ReactCommon/CallInvoker.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/**
|
||||
* For now, support the same set of return types as existing impl.
|
||||
* This can be improved to support richer typed objects.
|
||||
*/
|
||||
enum TurboModuleMethodValueKind {
|
||||
VoidKind,
|
||||
BooleanKind,
|
||||
NumberKind,
|
||||
StringKind,
|
||||
ObjectKind,
|
||||
ArrayKind,
|
||||
FunctionKind,
|
||||
PromiseKind,
|
||||
};
|
||||
|
||||
/**
|
||||
* Base HostObject class for every module to be exposed to JS
|
||||
*/
|
||||
class JSI_EXPORT TurboModule : public facebook::jsi::HostObject {
|
||||
public:
|
||||
TurboModule(const std::string &name, std::shared_ptr<CallInvoker> jsInvoker);
|
||||
virtual ~TurboModule();
|
||||
|
||||
virtual facebook::jsi::Value get(
|
||||
facebook::jsi::Runtime &runtime,
|
||||
const facebook::jsi::PropNameID &propName) override;
|
||||
|
||||
const std::string name_;
|
||||
std::shared_ptr<CallInvoker> jsInvoker_;
|
||||
|
||||
protected:
|
||||
struct MethodMetadata {
|
||||
size_t argCount;
|
||||
facebook::jsi::Value (*invoker)(
|
||||
facebook::jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const facebook::jsi::Value *args,
|
||||
size_t count);
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, MethodMetadata> methodMap_;
|
||||
};
|
||||
|
||||
/**
|
||||
* An app/platform-specific provider function to get an instance of a module
|
||||
* given a name.
|
||||
*/
|
||||
using TurboModuleProviderFunctionType =
|
||||
std::function<std::shared_ptr<TurboModule>(const std::string &name)>;
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
82
node_modules/react-native/ReactCommon/turbomodule/core/TurboModuleBinding.cpp
generated
vendored
Normal file
82
node_modules/react-native/ReactCommon/turbomodule/core/TurboModuleBinding.cpp
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "TurboModuleBinding.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <ReactCommon/LongLivedObject.h>
|
||||
#include <cxxreact/SystraceSection.h>
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/**
|
||||
* Public API to install the TurboModule system.
|
||||
*/
|
||||
TurboModuleBinding::TurboModuleBinding(
|
||||
const TurboModuleProviderFunctionType &&moduleProvider)
|
||||
: moduleProvider_(std::move(moduleProvider)) {}
|
||||
|
||||
void TurboModuleBinding::install(
|
||||
jsi::Runtime &runtime,
|
||||
const TurboModuleProviderFunctionType &&moduleProvider) {
|
||||
runtime.global().setProperty(
|
||||
runtime,
|
||||
"__turboModuleProxy",
|
||||
jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
jsi::PropNameID::forAscii(runtime, "__turboModuleProxy"),
|
||||
1,
|
||||
[binding =
|
||||
std::make_shared<TurboModuleBinding>(std::move(moduleProvider))](
|
||||
jsi::Runtime &rt,
|
||||
const jsi::Value &thisVal,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
return binding->jsProxy(rt, thisVal, args, count);
|
||||
}));
|
||||
}
|
||||
|
||||
TurboModuleBinding::~TurboModuleBinding() {
|
||||
LongLivedObjectCollection::get().clear();
|
||||
}
|
||||
|
||||
std::shared_ptr<TurboModule> TurboModuleBinding::getModule(
|
||||
const std::string &name) {
|
||||
std::shared_ptr<TurboModule> module = nullptr;
|
||||
{
|
||||
SystraceSection s("TurboModuleBinding::getModule", "module", name);
|
||||
module = moduleProvider_(name);
|
||||
}
|
||||
return module;
|
||||
}
|
||||
|
||||
jsi::Value TurboModuleBinding::jsProxy(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisVal,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
if (count != 1) {
|
||||
throw std::invalid_argument(
|
||||
"TurboModuleBinding::jsProxy arg count must be 1");
|
||||
}
|
||||
std::string moduleName = args[0].getString(runtime).utf8(runtime);
|
||||
std::shared_ptr<TurboModule> module = getModule(moduleName);
|
||||
|
||||
if (module == nullptr) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
|
||||
return jsi::Object::createFromHostObject(runtime, std::move(module));
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
56
node_modules/react-native/ReactCommon/turbomodule/core/TurboModuleBinding.h
generated
vendored
Normal file
56
node_modules/react-native/ReactCommon/turbomodule/core/TurboModuleBinding.h
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <ReactCommon/TurboModule.h>
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class JSCallInvoker;
|
||||
|
||||
/**
|
||||
* Represents the JavaScript binding for the TurboModule system.
|
||||
*/
|
||||
class TurboModuleBinding {
|
||||
public:
|
||||
/*
|
||||
* Installs TurboModuleBinding into JavaScript runtime.
|
||||
* Thread synchronization must be enforced externally.
|
||||
*/
|
||||
static void install(
|
||||
jsi::Runtime &runtime,
|
||||
const TurboModuleProviderFunctionType &&moduleProvider);
|
||||
|
||||
TurboModuleBinding(const TurboModuleProviderFunctionType &&moduleProvider);
|
||||
virtual ~TurboModuleBinding();
|
||||
|
||||
/**
|
||||
* Get an TurboModule instance for the given module name.
|
||||
*/
|
||||
std::shared_ptr<TurboModule> getModule(const std::string &name);
|
||||
|
||||
private:
|
||||
/**
|
||||
* A lookup function exposed to JS to get an instance of a TurboModule
|
||||
* for the given name.
|
||||
*/
|
||||
jsi::Value jsProxy(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisVal,
|
||||
const jsi::Value *args,
|
||||
size_t count);
|
||||
|
||||
TurboModuleProviderFunctionType moduleProvider_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
105
node_modules/react-native/ReactCommon/turbomodule/core/TurboModuleUtils.cpp
generated
vendored
Normal file
105
node_modules/react-native/ReactCommon/turbomodule/core/TurboModuleUtils.cpp
generated
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "TurboModuleUtils.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
static jsi::Value deepCopyJSIValue(jsi::Runtime &rt, const jsi::Value &value) {
|
||||
if (value.isNull()) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
|
||||
if (value.isBool()) {
|
||||
return jsi::Value(value.getBool());
|
||||
}
|
||||
|
||||
if (value.isNumber()) {
|
||||
return jsi::Value(value.getNumber());
|
||||
}
|
||||
|
||||
if (value.isString()) {
|
||||
return value.getString(rt);
|
||||
}
|
||||
|
||||
if (value.isObject()) {
|
||||
jsi::Object o = value.getObject(rt);
|
||||
if (o.isArray(rt)) {
|
||||
return deepCopyJSIArray(rt, o.getArray(rt));
|
||||
}
|
||||
if (o.isFunction(rt)) {
|
||||
return o.getFunction(rt);
|
||||
}
|
||||
return deepCopyJSIObject(rt, o);
|
||||
}
|
||||
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
|
||||
jsi::Object deepCopyJSIObject(jsi::Runtime &rt, const jsi::Object &obj) {
|
||||
jsi::Object copy(rt);
|
||||
jsi::Array propertyNames = obj.getPropertyNames(rt);
|
||||
size_t size = propertyNames.size(rt);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
jsi::String name = propertyNames.getValueAtIndex(rt, i).getString(rt);
|
||||
jsi::Value value = obj.getProperty(rt, name);
|
||||
copy.setProperty(rt, name, deepCopyJSIValue(rt, value));
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
jsi::Array deepCopyJSIArray(jsi::Runtime &rt, const jsi::Array &arr) {
|
||||
size_t size = arr.size(rt);
|
||||
jsi::Array copy(rt, size);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
copy.setValueAtIndex(
|
||||
rt, i, deepCopyJSIValue(rt, arr.getValueAtIndex(rt, i)));
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
Promise::Promise(jsi::Runtime &rt, jsi::Function resolve, jsi::Function reject)
|
||||
: runtime_(rt), resolve_(std::move(resolve)), reject_(std::move(reject)) {}
|
||||
|
||||
void Promise::resolve(const jsi::Value &result) {
|
||||
resolve_.call(runtime_, result);
|
||||
}
|
||||
|
||||
void Promise::reject(const std::string &message) {
|
||||
jsi::Object error(runtime_);
|
||||
error.setProperty(
|
||||
runtime_, "message", jsi::String::createFromUtf8(runtime_, message));
|
||||
reject_.call(runtime_, error);
|
||||
}
|
||||
|
||||
jsi::Value createPromiseAsJSIValue(
|
||||
jsi::Runtime &rt,
|
||||
const PromiseSetupFunctionType func) {
|
||||
jsi::Function JSPromise = rt.global().getPropertyAsFunction(rt, "Promise");
|
||||
jsi::Function fn = jsi::Function::createFromHostFunction(
|
||||
rt,
|
||||
jsi::PropNameID::forAscii(rt, "fn"),
|
||||
2,
|
||||
[func](
|
||||
jsi::Runtime &rt2,
|
||||
const jsi::Value &thisVal,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
jsi::Function resolve = args[0].getObject(rt2).getFunction(rt2);
|
||||
jsi::Function reject = args[1].getObject(rt2).getFunction(rt2);
|
||||
auto wrapper = std::make_shared<Promise>(
|
||||
rt2, std::move(resolve), std::move(reject));
|
||||
func(rt2, wrapper);
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
|
||||
return JSPromise.callAsConstructor(rt, fn);
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
89
node_modules/react-native/ReactCommon/turbomodule/core/TurboModuleUtils.h
generated
vendored
Normal file
89
node_modules/react-native/ReactCommon/turbomodule/core/TurboModuleUtils.h
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include <folly/Optional.h>
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
#include <ReactCommon/CallInvoker.h>
|
||||
#include <ReactCommon/LongLivedObject.h>
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
jsi::Object deepCopyJSIObject(jsi::Runtime &rt, const jsi::Object &obj);
|
||||
jsi::Array deepCopyJSIArray(jsi::Runtime &rt, const jsi::Array &arr);
|
||||
|
||||
struct Promise : public LongLivedObject {
|
||||
Promise(jsi::Runtime &rt, jsi::Function resolve, jsi::Function reject);
|
||||
|
||||
void resolve(const jsi::Value &result);
|
||||
void reject(const std::string &error);
|
||||
|
||||
jsi::Runtime &runtime_;
|
||||
jsi::Function resolve_;
|
||||
jsi::Function reject_;
|
||||
};
|
||||
|
||||
using PromiseSetupFunctionType =
|
||||
std::function<void(jsi::Runtime &rt, std::shared_ptr<Promise>)>;
|
||||
jsi::Value createPromiseAsJSIValue(
|
||||
jsi::Runtime &rt,
|
||||
const PromiseSetupFunctionType func);
|
||||
|
||||
// Helper for passing jsi::Function arg to other methods.
|
||||
class CallbackWrapper : public LongLivedObject {
|
||||
private:
|
||||
CallbackWrapper(
|
||||
jsi::Function &&callback,
|
||||
jsi::Runtime &runtime,
|
||||
std::shared_ptr<CallInvoker> jsInvoker)
|
||||
: callback_(std::move(callback)),
|
||||
runtime_(runtime),
|
||||
jsInvoker_(std::move(jsInvoker)) {}
|
||||
|
||||
jsi::Function callback_;
|
||||
jsi::Runtime &runtime_;
|
||||
std::shared_ptr<CallInvoker> jsInvoker_;
|
||||
|
||||
public:
|
||||
static std::weak_ptr<CallbackWrapper> createWeak(
|
||||
jsi::Function &&callback,
|
||||
jsi::Runtime &runtime,
|
||||
std::shared_ptr<CallInvoker> jsInvoker) {
|
||||
auto wrapper = std::shared_ptr<CallbackWrapper>(
|
||||
new CallbackWrapper(std::move(callback), runtime, jsInvoker));
|
||||
LongLivedObjectCollection::get().add(wrapper);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
// Delete the enclosed jsi::Function
|
||||
void destroy() {
|
||||
allowRelease();
|
||||
}
|
||||
|
||||
jsi::Function &callback() {
|
||||
return callback_;
|
||||
}
|
||||
|
||||
jsi::Runtime &runtime() {
|
||||
return runtime_;
|
||||
}
|
||||
|
||||
CallInvoker &jsInvoker() {
|
||||
return *(jsInvoker_);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
647
node_modules/react-native/ReactCommon/turbomodule/core/platform/android/JavaTurboModule.cpp
generated
vendored
Normal file
647
node_modules/react-native/ReactCommon/turbomodule/core/platform/android/JavaTurboModule.cpp
generated
vendored
Normal file
@ -0,0 +1,647 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
#include <ReactCommon/TurboModule.h>
|
||||
#include <jsi/JSIDynamic.h>
|
||||
#include <react/jni/NativeMap.h>
|
||||
#include <react/jni/ReadableNativeMap.h>
|
||||
#include <react/jni/WritableNativeMap.h>
|
||||
|
||||
#include "JavaTurboModule.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
JavaTurboModule::JavaTurboModule(
|
||||
const std::string &name,
|
||||
jni::alias_ref<JTurboModule> instance,
|
||||
std::shared_ptr<CallInvoker> jsInvoker,
|
||||
std::shared_ptr<CallInvoker> nativeInvoker)
|
||||
: TurboModule(name, jsInvoker),
|
||||
instance_(jni::make_global(instance)),
|
||||
nativeInvoker_(nativeInvoker) {}
|
||||
|
||||
namespace {
|
||||
|
||||
jni::local_ref<JCxxCallbackImpl::JavaPart> createJavaCallbackFromJSIFunction(
|
||||
jsi::Function &&function,
|
||||
jsi::Runtime &rt,
|
||||
std::shared_ptr<CallInvoker> jsInvoker) {
|
||||
auto weakWrapper =
|
||||
react::CallbackWrapper::createWeak(std::move(function), rt, jsInvoker);
|
||||
|
||||
std::function<void(folly::dynamic)> fn =
|
||||
[weakWrapper,
|
||||
wrapperWasCalled = false](folly::dynamic responses) mutable {
|
||||
if (wrapperWasCalled) {
|
||||
throw std::runtime_error(
|
||||
"callback 2 arg cannot be called more than once");
|
||||
}
|
||||
|
||||
auto strongWrapper = weakWrapper.lock();
|
||||
if (!strongWrapper) {
|
||||
return;
|
||||
}
|
||||
|
||||
strongWrapper->jsInvoker().invokeAsync([weakWrapper, responses]() {
|
||||
auto strongWrapper2 = weakWrapper.lock();
|
||||
if (!strongWrapper2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO (T43155926) valueFromDynamic already returns a Value array.
|
||||
// Don't iterate again
|
||||
jsi::Value args =
|
||||
jsi::valueFromDynamic(strongWrapper2->runtime(), responses);
|
||||
auto argsArray = args.getObject(strongWrapper2->runtime())
|
||||
.asArray(strongWrapper2->runtime());
|
||||
std::vector<jsi::Value> result;
|
||||
for (size_t i = 0; i < argsArray.size(strongWrapper2->runtime());
|
||||
i++) {
|
||||
result.emplace_back(
|
||||
strongWrapper2->runtime(),
|
||||
argsArray.getValueAtIndex(strongWrapper2->runtime(), i));
|
||||
}
|
||||
strongWrapper2->callback().call(
|
||||
strongWrapper2->runtime(),
|
||||
(const jsi::Value *)result.data(),
|
||||
result.size());
|
||||
|
||||
strongWrapper2->destroy();
|
||||
});
|
||||
|
||||
wrapperWasCalled = true;
|
||||
};
|
||||
return JCxxCallbackImpl::newObjectCxxArgs(fn);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string to_string(T v) {
|
||||
std::ostringstream stream;
|
||||
stream << v;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
// This is used for generating short exception strings.
|
||||
std::string stringifyJSIValue(const jsi::Value &v, jsi::Runtime *rt = nullptr) {
|
||||
if (v.isUndefined()) {
|
||||
return "undefined";
|
||||
}
|
||||
|
||||
if (v.isNull()) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
if (v.isBool()) {
|
||||
return std::string("a boolean (") + (v.getBool() ? "true" : "false") + ")";
|
||||
}
|
||||
|
||||
if (v.isNumber()) {
|
||||
return "a number (" + to_string(v.getNumber()) + ")";
|
||||
}
|
||||
|
||||
if (v.isString()) {
|
||||
return "a string (\"" + v.getString(*rt).utf8(*rt) + "\")";
|
||||
}
|
||||
|
||||
assert(v.isObject() && "Expecting object.");
|
||||
return rt != nullptr && v.getObject(*rt).isFunction(*rt) ? "a function"
|
||||
: "an object";
|
||||
}
|
||||
|
||||
class JavaTurboModuleArgumentConversionException : public std::runtime_error {
|
||||
public:
|
||||
JavaTurboModuleArgumentConversionException(
|
||||
const std::string &expectedType,
|
||||
int index,
|
||||
const std::string &methodName,
|
||||
const jsi::Value *arg,
|
||||
jsi::Runtime *rt)
|
||||
: std::runtime_error(
|
||||
"Expected argument " + to_string(index) + " of method \"" +
|
||||
methodName + "\" to be a " + expectedType + ", but got " +
|
||||
stringifyJSIValue(*arg, rt)) {}
|
||||
};
|
||||
|
||||
class JavaTurboModuleInvalidArgumentTypeException : public std::runtime_error {
|
||||
public:
|
||||
JavaTurboModuleInvalidArgumentTypeException(
|
||||
const std::string &actualType,
|
||||
int argIndex,
|
||||
const std::string &methodName)
|
||||
: std::runtime_error(
|
||||
"Called method \"" + methodName + "\" with unsupported type " +
|
||||
actualType + " at argument " + to_string(argIndex)) {}
|
||||
};
|
||||
|
||||
class JavaTurboModuleInvalidArgumentCountException : public std::runtime_error {
|
||||
public:
|
||||
JavaTurboModuleInvalidArgumentCountException(
|
||||
const std::string &methodName,
|
||||
int actualArgCount,
|
||||
int expectedArgCount)
|
||||
: std::runtime_error(
|
||||
"TurboModule method \"" + methodName + "\" called with " +
|
||||
to_string(actualArgCount) +
|
||||
" arguments (expected argument count: " +
|
||||
to_string(expectedArgCount) + ").") {}
|
||||
};
|
||||
|
||||
/**
|
||||
* See
|
||||
* https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html
|
||||
* for a description of Java method signature structure.
|
||||
*/
|
||||
std::vector<std::string> getMethodArgTypesFromSignature(
|
||||
const std::string &methodSignature) {
|
||||
std::vector<std::string> methodArgs;
|
||||
|
||||
for (auto it = methodSignature.begin(); it != methodSignature.end();
|
||||
it += 1) {
|
||||
if (*it == '(') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*it == ')') {
|
||||
break;
|
||||
}
|
||||
|
||||
std::string type;
|
||||
|
||||
if (*it == '[') {
|
||||
type += *it;
|
||||
it += 1;
|
||||
}
|
||||
|
||||
if (*it == 'L') {
|
||||
for (; it != methodSignature.end(); it += 1) {
|
||||
type += *it;
|
||||
|
||||
if (*it == ';') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
type += *it;
|
||||
}
|
||||
|
||||
methodArgs.push_back(type);
|
||||
}
|
||||
|
||||
return methodArgs;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// fnjni already does this conversion, but since we are using plain JNI, this
|
||||
// needs to be done again
|
||||
// TODO (axe) Reuse existing implementation as needed - the exist in
|
||||
// MethodInvoker.cpp
|
||||
JNIArgs JavaTurboModule::convertJSIArgsToJNIArgs(
|
||||
JNIEnv *env,
|
||||
jsi::Runtime &rt,
|
||||
std::string methodName,
|
||||
std::vector<std::string> methodArgTypes,
|
||||
const jsi::Value *args,
|
||||
size_t count,
|
||||
std::shared_ptr<CallInvoker> jsInvoker,
|
||||
TurboModuleMethodValueKind valueKind) {
|
||||
unsigned int expectedArgumentCount = valueKind == PromiseKind
|
||||
? methodArgTypes.size() - 1
|
||||
: methodArgTypes.size();
|
||||
|
||||
if (expectedArgumentCount != count) {
|
||||
throw JavaTurboModuleInvalidArgumentCountException(
|
||||
methodName, count, expectedArgumentCount);
|
||||
}
|
||||
|
||||
JNIArgs jniArgs(valueKind == PromiseKind ? count + 1 : count);
|
||||
auto &jargs = jniArgs.args_;
|
||||
auto &globalRefs = jniArgs.globalRefs_;
|
||||
|
||||
auto makeGlobalIfNecessary =
|
||||
[&globalRefs, env, valueKind](jobject obj) -> jobject {
|
||||
if (valueKind == VoidKind) {
|
||||
jobject globalObj = env->NewGlobalRef(obj);
|
||||
globalRefs.push_back(globalObj);
|
||||
env->DeleteLocalRef(obj);
|
||||
return globalObj;
|
||||
}
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
jclass booleanClass = nullptr;
|
||||
jclass doubleClass = nullptr;
|
||||
|
||||
for (unsigned int argIndex = 0; argIndex < count; argIndex += 1) {
|
||||
std::string type = methodArgTypes.at(argIndex);
|
||||
|
||||
const jsi::Value *arg = &args[argIndex];
|
||||
jvalue *jarg = &jargs[argIndex];
|
||||
|
||||
if (type == "D") {
|
||||
if (!arg->isNumber()) {
|
||||
throw JavaTurboModuleArgumentConversionException(
|
||||
"number", argIndex, methodName, arg, &rt);
|
||||
}
|
||||
|
||||
jarg->d = arg->getNumber();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == "Z") {
|
||||
if (!arg->isBool()) {
|
||||
throw JavaTurboModuleArgumentConversionException(
|
||||
"boolean", argIndex, methodName, arg, &rt);
|
||||
}
|
||||
|
||||
jarg->z = (jboolean)arg->getBool();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(type == "Ljava/lang/Double;" || type == "Ljava/lang/Boolean;" ||
|
||||
type == "Ljava/lang/String;" ||
|
||||
type == "Lcom/facebook/react/bridge/ReadableArray;" ||
|
||||
type == "Lcom/facebook/react/bridge/Callback;" ||
|
||||
type == "Lcom/facebook/react/bridge/ReadableMap;")) {
|
||||
throw JavaTurboModuleInvalidArgumentTypeException(
|
||||
type, argIndex, methodName);
|
||||
}
|
||||
|
||||
if (arg->isNull() || arg->isUndefined()) {
|
||||
jarg->l = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == "Ljava/lang/Double;") {
|
||||
if (!arg->isNumber()) {
|
||||
throw JavaTurboModuleArgumentConversionException(
|
||||
"number", argIndex, methodName, arg, &rt);
|
||||
}
|
||||
|
||||
if (doubleClass == nullptr) {
|
||||
doubleClass = env->FindClass("java/lang/Double");
|
||||
}
|
||||
|
||||
jmethodID doubleConstructor =
|
||||
env->GetMethodID(doubleClass, "<init>", "(D)V");
|
||||
jarg->l = makeGlobalIfNecessary(
|
||||
env->NewObject(doubleClass, doubleConstructor, arg->getNumber()));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == "Ljava/lang/Boolean;") {
|
||||
if (!arg->isBool()) {
|
||||
throw JavaTurboModuleArgumentConversionException(
|
||||
"boolean", argIndex, methodName, arg, &rt);
|
||||
}
|
||||
|
||||
if (booleanClass == nullptr) {
|
||||
booleanClass = env->FindClass("java/lang/Boolean");
|
||||
}
|
||||
|
||||
jmethodID booleanConstructor =
|
||||
env->GetMethodID(booleanClass, "<init>", "(Z)V");
|
||||
jarg->l = makeGlobalIfNecessary(
|
||||
env->NewObject(booleanClass, booleanConstructor, arg->getBool()));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == "Ljava/lang/String;") {
|
||||
if (!arg->isString()) {
|
||||
throw JavaTurboModuleArgumentConversionException(
|
||||
"string", argIndex, methodName, arg, &rt);
|
||||
}
|
||||
|
||||
jarg->l = makeGlobalIfNecessary(
|
||||
env->NewStringUTF(arg->getString(rt).utf8(rt).c_str()));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == "Lcom/facebook/react/bridge/ReadableArray;") {
|
||||
if (!(arg->isObject() && arg->getObject(rt).isArray(rt))) {
|
||||
throw JavaTurboModuleArgumentConversionException(
|
||||
"Array", argIndex, methodName, arg, &rt);
|
||||
}
|
||||
|
||||
auto dynamicFromValue = jsi::dynamicFromValue(rt, *arg);
|
||||
auto jParams =
|
||||
ReadableNativeArray::newObjectCxxArgs(std::move(dynamicFromValue));
|
||||
jarg->l = makeGlobalIfNecessary(jParams.release());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == "Lcom/facebook/react/bridge/Callback;") {
|
||||
if (!(arg->isObject() && arg->getObject(rt).isFunction(rt))) {
|
||||
throw JavaTurboModuleArgumentConversionException(
|
||||
"Function", argIndex, methodName, arg, &rt);
|
||||
}
|
||||
|
||||
jsi::Function fn = arg->getObject(rt).getFunction(rt);
|
||||
jarg->l = makeGlobalIfNecessary(
|
||||
createJavaCallbackFromJSIFunction(std::move(fn), rt, jsInvoker)
|
||||
.release());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == "Lcom/facebook/react/bridge/ReadableMap;") {
|
||||
if (!(arg->isObject())) {
|
||||
throw JavaTurboModuleArgumentConversionException(
|
||||
"Object", argIndex, methodName, arg, &rt);
|
||||
}
|
||||
|
||||
auto dynamicFromValue = jsi::dynamicFromValue(rt, *arg);
|
||||
auto jParams =
|
||||
ReadableNativeMap::createWithContents(std::move(dynamicFromValue));
|
||||
jarg->l = makeGlobalIfNecessary(jParams.release());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return jniArgs;
|
||||
}
|
||||
|
||||
jsi::Value convertFromJMapToValue(JNIEnv *env, jsi::Runtime &rt, jobject arg) {
|
||||
// We currently use Java Argument.makeNativeMap() method to do this conversion
|
||||
// This could also be done purely in C++, but iterative over map methods
|
||||
// but those may end up calling reflection methods anyway
|
||||
// TODO (axe) Investigate the best way to convert Java Map to Value
|
||||
jclass jArguments = env->FindClass("com/facebook/react/bridge/Arguments");
|
||||
static jmethodID jMakeNativeMap = env->GetStaticMethodID(
|
||||
jArguments,
|
||||
"makeNativeMap",
|
||||
"(Ljava/util/Map;)Lcom/facebook/react/bridge/WritableNativeMap;");
|
||||
auto constants =
|
||||
(jobject)env->CallStaticObjectMethod(jArguments, jMakeNativeMap, arg);
|
||||
auto jResult = jni::adopt_local(constants);
|
||||
auto result = jni::static_ref_cast<NativeMap::jhybridobject>(jResult);
|
||||
return jsi::valueFromDynamic(rt, result->cthis()->consume());
|
||||
}
|
||||
|
||||
jsi::Value JavaTurboModule::invokeJavaMethod(
|
||||
jsi::Runtime &runtime,
|
||||
TurboModuleMethodValueKind valueKind,
|
||||
const std::string &methodName,
|
||||
const std::string &methodSignature,
|
||||
const jsi::Value *args,
|
||||
size_t argCount) {
|
||||
JNIEnv *env = jni::Environment::current();
|
||||
auto instance = instance_.get();
|
||||
|
||||
/**
|
||||
* To account for jclasses and other misc LocalReferences we create.
|
||||
*/
|
||||
unsigned int buffer = 6;
|
||||
/**
|
||||
* For promises, we have to create a resolve fn, a reject fn, and a promise
|
||||
* object. For normal returns, we just create the return object.
|
||||
*/
|
||||
unsigned int maxReturnObjects = 3;
|
||||
|
||||
/**
|
||||
* When the return type is void, all JNI LocalReferences are converted to
|
||||
* GlobalReferences. The LocalReferences are then promptly deleted
|
||||
* after the conversion.
|
||||
*/
|
||||
unsigned int actualArgCount = valueKind == VoidKind ? 0 : argCount;
|
||||
unsigned int estimatedLocalRefCount =
|
||||
actualArgCount + maxReturnObjects + buffer;
|
||||
|
||||
/**
|
||||
* This will push a new JNI stack frame for the LocalReferences in this
|
||||
* function call. When the stack frame for invokeJavaMethod is popped,
|
||||
* all LocalReferences are deleted.
|
||||
*
|
||||
* In total, there can be at most kJniLocalRefMax (= 512) Jni
|
||||
* LocalReferences alive at a time. estimatedLocalRefCount is provided
|
||||
* so that PushLocalFrame can throw an out of memory error when the total
|
||||
* number of alive LocalReferences is estimatedLocalRefCount smaller than
|
||||
* kJniLocalRefMax.
|
||||
*/
|
||||
jni::JniLocalScope scope(env, estimatedLocalRefCount);
|
||||
|
||||
jclass cls = env->GetObjectClass(instance);
|
||||
jmethodID methodID =
|
||||
env->GetMethodID(cls, methodName.c_str(), methodSignature.c_str());
|
||||
|
||||
// If the method signature doesn't match, show a redbox here instead of
|
||||
// crashing later.
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
|
||||
// TODO(T43933641): Refactor to remove this special-casing
|
||||
if (methodName == "getConstants") {
|
||||
auto constantsMap = (jobject)env->CallObjectMethod(instance, methodID);
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
|
||||
if (constantsMap == nullptr) {
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
|
||||
return convertFromJMapToValue(env, runtime, constantsMap);
|
||||
}
|
||||
|
||||
std::vector<std::string> methodArgTypes =
|
||||
getMethodArgTypesFromSignature(methodSignature);
|
||||
|
||||
JNIArgs jniArgs = convertJSIArgsToJNIArgs(
|
||||
env,
|
||||
runtime,
|
||||
methodName,
|
||||
methodArgTypes,
|
||||
args,
|
||||
argCount,
|
||||
jsInvoker_,
|
||||
valueKind);
|
||||
|
||||
auto &jargs = jniArgs.args_;
|
||||
auto &globalRefs = jniArgs.globalRefs_;
|
||||
|
||||
switch (valueKind) {
|
||||
case VoidKind: {
|
||||
nativeInvoker_->invokeAsync(
|
||||
[jargs, globalRefs, methodID, instance_ = instance_]() mutable
|
||||
-> void {
|
||||
/**
|
||||
* TODO(ramanpreet): Why do we have to require the environment
|
||||
* again? Why does JNI crash when we use the env from the upper
|
||||
* scope?
|
||||
*/
|
||||
JNIEnv *env = jni::Environment::current();
|
||||
|
||||
env->CallVoidMethodA(instance_.get(), methodID, jargs.data());
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
|
||||
for (auto globalRef : globalRefs) {
|
||||
env->DeleteGlobalRef(globalRef);
|
||||
}
|
||||
});
|
||||
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
case BooleanKind: {
|
||||
std::string returnType =
|
||||
methodSignature.substr(methodSignature.find_last_of(')') + 1);
|
||||
if (returnType == "Ljava/lang/Boolean;") {
|
||||
auto returnObject =
|
||||
(jobject)env->CallObjectMethodA(instance, methodID, jargs.data());
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
|
||||
if (returnObject == nullptr) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
|
||||
jclass booleanClass = env->FindClass("java/lang/Boolean");
|
||||
jmethodID booleanValueMethod =
|
||||
env->GetMethodID(booleanClass, "booleanValue", "()Z");
|
||||
bool returnBoolean =
|
||||
(bool)env->CallBooleanMethod(returnObject, booleanValueMethod);
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
|
||||
return jsi::Value(returnBoolean);
|
||||
}
|
||||
|
||||
bool returnBoolean =
|
||||
(bool)env->CallBooleanMethodA(instance, methodID, jargs.data());
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
|
||||
return jsi::Value(returnBoolean);
|
||||
}
|
||||
case NumberKind: {
|
||||
std::string returnType =
|
||||
methodSignature.substr(methodSignature.find_last_of(')') + 1);
|
||||
if (returnType == "Ljava/lang/Double;") {
|
||||
auto returnObject =
|
||||
(jobject)env->CallObjectMethodA(instance, methodID, jargs.data());
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
|
||||
if (returnObject == nullptr) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
|
||||
jclass doubleClass = env->FindClass("java/lang/Double");
|
||||
jmethodID doubleValueMethod =
|
||||
env->GetMethodID(doubleClass, "doubleValue", "()D");
|
||||
double returnDouble =
|
||||
(double)env->CallDoubleMethod(returnObject, doubleValueMethod);
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
|
||||
return jsi::Value(returnDouble);
|
||||
}
|
||||
|
||||
double returnDouble =
|
||||
(double)env->CallDoubleMethodA(instance, methodID, jargs.data());
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
|
||||
return jsi::Value(returnDouble);
|
||||
}
|
||||
case StringKind: {
|
||||
auto returnString =
|
||||
(jstring)env->CallObjectMethodA(instance, methodID, jargs.data());
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
|
||||
if (returnString == nullptr) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
const char *js = env->GetStringUTFChars(returnString, nullptr);
|
||||
std::string result = js;
|
||||
env->ReleaseStringUTFChars(returnString, js);
|
||||
return jsi::Value(runtime, jsi::String::createFromUtf8(runtime, result));
|
||||
}
|
||||
case ObjectKind: {
|
||||
auto returnObject =
|
||||
(jobject)env->CallObjectMethodA(instance, methodID, jargs.data());
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
|
||||
if (returnObject == nullptr) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
auto jResult = jni::adopt_local(returnObject);
|
||||
auto result = jni::static_ref_cast<NativeMap::jhybridobject>(jResult);
|
||||
return jsi::valueFromDynamic(runtime, result->cthis()->consume());
|
||||
}
|
||||
case ArrayKind: {
|
||||
auto returnObject =
|
||||
(jobject)env->CallObjectMethodA(instance, methodID, jargs.data());
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
|
||||
if (returnObject == nullptr) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
auto jResult = jni::adopt_local(returnObject);
|
||||
auto result = jni::static_ref_cast<NativeArray::jhybridobject>(jResult);
|
||||
return jsi::valueFromDynamic(runtime, result->cthis()->consume());
|
||||
}
|
||||
case PromiseKind: {
|
||||
jsi::Function Promise =
|
||||
runtime.global().getPropertyAsFunction(runtime, "Promise");
|
||||
|
||||
jsi::Function promiseConstructorArg = jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
jsi::PropNameID::forAscii(runtime, "fn"),
|
||||
2,
|
||||
[this, &jargs, argCount, instance, methodID, env](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisVal,
|
||||
const jsi::Value *promiseConstructorArgs,
|
||||
size_t promiseConstructorArgCount) {
|
||||
if (promiseConstructorArgCount != 2) {
|
||||
throw std::invalid_argument("Promise fn arg count must be 2");
|
||||
}
|
||||
|
||||
jsi::Function resolveJSIFn =
|
||||
promiseConstructorArgs[0].getObject(runtime).getFunction(
|
||||
runtime);
|
||||
jsi::Function rejectJSIFn =
|
||||
promiseConstructorArgs[1].getObject(runtime).getFunction(
|
||||
runtime);
|
||||
|
||||
auto resolve = createJavaCallbackFromJSIFunction(
|
||||
std::move(resolveJSIFn), runtime, jsInvoker_)
|
||||
.release();
|
||||
auto reject = createJavaCallbackFromJSIFunction(
|
||||
std::move(rejectJSIFn), runtime, jsInvoker_)
|
||||
.release();
|
||||
|
||||
jclass jPromiseImpl =
|
||||
env->FindClass("com/facebook/react/bridge/PromiseImpl");
|
||||
jmethodID jPromiseImplConstructor = env->GetMethodID(
|
||||
jPromiseImpl,
|
||||
"<init>",
|
||||
"(Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V");
|
||||
|
||||
jobject promise = env->NewObject(
|
||||
jPromiseImpl, jPromiseImplConstructor, resolve, reject);
|
||||
|
||||
jargs[argCount].l = promise;
|
||||
env->CallVoidMethodA(instance, methodID, jargs.data());
|
||||
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
|
||||
jsi::Value promise =
|
||||
Promise.callAsConstructor(runtime, promiseConstructorArg);
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
|
||||
return promise;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error(
|
||||
"Unable to find method module: " + methodName + "(" +
|
||||
methodSignature + ")");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
64
node_modules/react-native/ReactCommon/turbomodule/core/platform/android/JavaTurboModule.h
generated
vendored
Normal file
64
node_modules/react-native/ReactCommon/turbomodule/core/platform/android/JavaTurboModule.h
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <ReactCommon/TurboModule.h>
|
||||
#include <ReactCommon/TurboModuleUtils.h>
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <jsi/jsi.h>
|
||||
#include <react/jni/JCallback.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
struct JNIArgs {
|
||||
JNIArgs(size_t count) : args_(count) {}
|
||||
std::vector<jvalue> args_;
|
||||
std::vector<jobject> globalRefs_;
|
||||
};
|
||||
|
||||
struct JTurboModule : jni::JavaClass<JTurboModule> {
|
||||
static auto constexpr kJavaDescriptor =
|
||||
"Lcom/facebook/react/turbomodule/core/interfaces/TurboModule;";
|
||||
};
|
||||
|
||||
class JSI_EXPORT JavaTurboModule : public TurboModule {
|
||||
public:
|
||||
JavaTurboModule(
|
||||
const std::string &name,
|
||||
jni::alias_ref<JTurboModule> instance,
|
||||
std::shared_ptr<CallInvoker> jsInvoker,
|
||||
std::shared_ptr<CallInvoker> nativeInvoker);
|
||||
jsi::Value invokeJavaMethod(
|
||||
jsi::Runtime &runtime,
|
||||
TurboModuleMethodValueKind valueKind,
|
||||
const std::string &methodName,
|
||||
const std::string &methodSignature,
|
||||
const jsi::Value *args,
|
||||
size_t argCount);
|
||||
|
||||
private:
|
||||
jni::global_ref<JTurboModule> instance_;
|
||||
std::shared_ptr<CallInvoker> nativeInvoker_;
|
||||
|
||||
JNIArgs convertJSIArgsToJNIArgs(
|
||||
JNIEnv *env,
|
||||
jsi::Runtime &rt,
|
||||
std::string methodName,
|
||||
std::vector<std::string> methodArgTypes,
|
||||
const jsi::Value *args,
|
||||
size_t count,
|
||||
std::shared_ptr<CallInvoker> jsInvoker,
|
||||
TurboModuleMethodValueKind valueKind);
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
229
node_modules/react-native/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.h
generated
vendored
Normal file
229
node_modules/react-native/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.h
generated
vendored
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <memory>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <React/RCTBridge.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTModuleMethod.h>
|
||||
#import <ReactCommon/CallInvoker.h>
|
||||
#import <ReactCommon/TurboModule.h>
|
||||
#import <ReactCommon/TurboModuleUtils.h>
|
||||
#import <string>
|
||||
#import <unordered_map>
|
||||
|
||||
#define RCT_IS_TURBO_MODULE_CLASS(klass) \
|
||||
((RCTTurboModuleEnabled() && [(klass) conformsToProtocol:@protocol(RCTTurboModule)]))
|
||||
#define RCT_IS_TURBO_MODULE_INSTANCE(module) RCT_IS_TURBO_MODULE_CLASS([(module) class])
|
||||
|
||||
typedef int MethodCallId;
|
||||
|
||||
/**
|
||||
* This interface exists to allow the application to collect performance
|
||||
* metrics of the TurboModule system. By implementing each function, you can
|
||||
* hook into various stages of TurboModule creation and method dispatch (both async and sync).
|
||||
*
|
||||
* Note:
|
||||
* - TurboModule async method invocations can interleave, so methodCallId should be used as a unique id for a method
|
||||
* call.
|
||||
*/
|
||||
@protocol RCTTurboModulePerformanceLogger
|
||||
// Create TurboModule JS Object
|
||||
- (void)createTurboModuleStart:(const char *)moduleName;
|
||||
- (void)createTurboModuleEnd:(const char *)moduleName;
|
||||
- (void)createTurboModuleCacheHit:(const char *)moduleName;
|
||||
- (void)getCppTurboModuleFromTMMDelegateStart:(const char *)moduleName;
|
||||
- (void)getCppTurboModuleFromTMMDelegateEnd:(const char *)moduleName;
|
||||
- (void)getTurboModuleFromRCTTurboModuleStart:(const char *)moduleName;
|
||||
- (void)getTurboModuleFromRCTTurboModuleEnd:(const char *)moduleName;
|
||||
- (void)getTurboModuleFromRCTCxxModuleStart:(const char *)moduleName;
|
||||
- (void)getTurboModuleFromRCTCxxModuleEnd:(const char *)moduleName;
|
||||
- (void)getTurboModuleFromTMMDelegateStart:(const char *)moduleName;
|
||||
- (void)getTurboModuleFromTMMDelegateEnd:(const char *)moduleName;
|
||||
|
||||
// Create RCTTurboModule object
|
||||
- (void)createRCTTurboModuleStart:(const char *)moduleName;
|
||||
- (void)createRCTTurboModuleEnd:(const char *)moduleName;
|
||||
- (void)createRCTTurboModuleCacheHit:(const char *)moduleName;
|
||||
- (void)getRCTTurboModuleClassStart:(const char *)moduleName;
|
||||
- (void)getRCTTurboModuleClassEnd:(const char *)moduleName;
|
||||
- (void)getRCTTurboModuleInstanceStart:(const char *)moduleName;
|
||||
- (void)getRCTTurboModuleInstanceEnd:(const char *)moduleName;
|
||||
- (void)setupRCTTurboModuleDispatch:(const char *)moduleName;
|
||||
- (void)setupRCTTurboModuleStart:(const char *)moduleName;
|
||||
- (void)setupRCTTurboModuleEnd:(const char *)moduleName;
|
||||
- (void)attachRCTBridgeToRCTTurboModuleStart:(const char *)moduleName;
|
||||
- (void)attachRCTBridgeToRCTTurboModuleEnd:(const char *)moduleName;
|
||||
- (void)attachMethodQueueToRCTTurboModuleStart:(const char *)moduleName;
|
||||
- (void)attachMethodQueueToRCTTurboModuleEnd:(const char *)moduleName;
|
||||
- (void)registerRCTTurboModuleForFrameUpdatesStart:(const char *)moduleName;
|
||||
- (void)registerRCTTurboModuleForFrameUpdatesEnd:(const char *)moduleName;
|
||||
- (void)dispatchDidInitializeModuleNotificationForRCTTurboModuleStart:(const char *)moduleName;
|
||||
- (void)dispatchDidInitializeModuleNotificationForRCTTurboModuleEnd:(const char *)moduleName;
|
||||
|
||||
// Sync method invocation
|
||||
- (void)syncMethodCallStart:(const char *)moduleName
|
||||
methodName:(const char *)methodName
|
||||
methodCallId:(MethodCallId)methodCallId;
|
||||
- (void)syncMethodCallEnd:(const char *)moduleName
|
||||
methodName:(const char *)methodName
|
||||
methodCallId:(MethodCallId)methodCallId;
|
||||
- (void)syncMethodCallArgumentConversionStart:(const char *)moduleName
|
||||
methodName:(const char *)methodName
|
||||
methodCallId:(MethodCallId)methodCallId;
|
||||
- (void)syncMethodCallArgumentConversionEnd:(const char *)moduleName
|
||||
methodName:(const char *)methodName
|
||||
methodCallId:(MethodCallId)methodCallId;
|
||||
- (void)syncRCTTurboModuleMethodCallStart:(const char *)moduleName
|
||||
methodName:(const char *)methodName
|
||||
methodCallId:(MethodCallId)methodCallId;
|
||||
- (void)syncRCTTurboModuleMethodCallEnd:(const char *)moduleName
|
||||
methodName:(const char *)methodName
|
||||
methodCallId:(MethodCallId)methodCallId;
|
||||
- (void)syncMethodCallReturnConversionStart:(const char *)moduleName
|
||||
methodName:(const char *)methodName
|
||||
methodCallId:(MethodCallId)methodCallId;
|
||||
- (void)syncMethodCallReturnConversionEnd:(const char *)moduleName
|
||||
methodName:(const char *)methodName
|
||||
methodCallId:(MethodCallId)methodCallId;
|
||||
|
||||
// Async method invocation
|
||||
- (void)asyncMethodCallStart:(const char *)moduleName
|
||||
methodName:(const char *)methodName
|
||||
methodCallId:(MethodCallId)methodCallId;
|
||||
- (void)asyncMethodCallEnd:(const char *)moduleName
|
||||
methodName:(const char *)methodName
|
||||
methodCallId:(MethodCallId)methodCallId;
|
||||
- (void)asyncMethodCallArgumentConversionStart:(const char *)moduleName
|
||||
methodName:(const char *)methodName
|
||||
methodCallId:(MethodCallId)methodCallId;
|
||||
- (void)asyncMethodCallArgumentConversionEnd:(const char *)moduleName
|
||||
methodName:(const char *)methodName
|
||||
methodCallId:(MethodCallId)methodCallId;
|
||||
- (void)asyncRCTTurboModuleMethodCallDispatch:(const char *)moduleName
|
||||
methodName:(const char *)methodName
|
||||
methodCallId:(MethodCallId)methodCallId;
|
||||
- (void)asyncRCTTurboModuleMethodCallStart:(const char *)moduleName
|
||||
methodName:(const char *)methodName
|
||||
methodCallId:(MethodCallId)methodCallId;
|
||||
- (void)asyncRCTTurboModuleMethodCallEnd:(const char *)moduleName
|
||||
methodName:(const char *)methodName
|
||||
methodCallId:(MethodCallId)methodCallId;
|
||||
@end
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class Instance;
|
||||
|
||||
/**
|
||||
* ObjC++ specific TurboModule base class.
|
||||
*/
|
||||
class JSI_EXPORT ObjCTurboModule : public TurboModule {
|
||||
public:
|
||||
ObjCTurboModule(
|
||||
const std::string &name,
|
||||
id<RCTTurboModule> instance,
|
||||
std::shared_ptr<CallInvoker> jsInvoker,
|
||||
std::shared_ptr<CallInvoker> nativeInvoker,
|
||||
id<RCTTurboModulePerformanceLogger> perfLogger);
|
||||
|
||||
jsi::Value invokeObjCMethod(
|
||||
jsi::Runtime &runtime,
|
||||
TurboModuleMethodValueKind valueKind,
|
||||
const std::string &methodName,
|
||||
SEL selector,
|
||||
const jsi::Value *args,
|
||||
size_t count);
|
||||
|
||||
id<RCTTurboModule> instance_;
|
||||
std::shared_ptr<CallInvoker> nativeInvoker_;
|
||||
|
||||
protected:
|
||||
void setMethodArgConversionSelector(NSString *methodName, int argIndex, NSString *fnName);
|
||||
|
||||
private:
|
||||
/**
|
||||
* TODO(ramanpreet):
|
||||
* Investigate an optimization that'll let us get rid of this NSMutableDictionary.
|
||||
*/
|
||||
NSMutableDictionary<NSString *, NSMutableArray *> *methodArgConversionSelectors_;
|
||||
NSDictionary<NSString *, NSArray<NSString *> *> *methodArgumentTypeNames_;
|
||||
NSString *getArgumentTypeName(NSString *methodName, int argIndex);
|
||||
id<RCTTurboModulePerformanceLogger> performanceLogger_;
|
||||
|
||||
/**
|
||||
* Required for performance logging async method invocations.
|
||||
* This field is static because two nth async method calls from different
|
||||
* TurboModules can interleave, and should therefore be treated as two distinct calls.
|
||||
*/
|
||||
static MethodCallId methodCallId_;
|
||||
|
||||
static MethodCallId getNewMethodCallId();
|
||||
|
||||
NSInvocation *getMethodInvocation(
|
||||
jsi::Runtime &runtime,
|
||||
TurboModuleMethodValueKind returnType,
|
||||
const char *methodName,
|
||||
SEL selector,
|
||||
const jsi::Value *args,
|
||||
size_t count,
|
||||
NSMutableArray *retainedObjectsForInvocation,
|
||||
MethodCallId methodCallId);
|
||||
jsi::Value performMethodInvocation(
|
||||
jsi::Runtime &runtime,
|
||||
TurboModuleMethodValueKind returnType,
|
||||
const char *methodName,
|
||||
NSInvocation *inv,
|
||||
NSMutableArray *retainedObjectsForInvocation,
|
||||
MethodCallId methodCallId);
|
||||
|
||||
BOOL hasMethodArgConversionSelector(NSString *methodName, int argIndex);
|
||||
SEL getMethodArgConversionSelector(NSString *methodName, int argIndex);
|
||||
|
||||
using PromiseInvocationBlock = void (^)(RCTPromiseResolveBlock resolveWrapper, RCTPromiseRejectBlock rejectWrapper);
|
||||
jsi::Value
|
||||
createPromise(jsi::Runtime &runtime, std::shared_ptr<react::CallInvoker> jsInvoker, PromiseInvocationBlock invoke);
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
||||
@protocol RCTTurboModule <NSObject>
|
||||
@optional
|
||||
/**
|
||||
* Used by TurboModules to get access to other TurboModules.
|
||||
*
|
||||
* Usage:
|
||||
* Place `@synthesize turboModuleLookupDelegate = _turboModuleLookupDelegate`
|
||||
* in the @implementation section of your TurboModule.
|
||||
*/
|
||||
@property (nonatomic, weak) id<RCTTurboModuleLookupDelegate> turboModuleLookupDelegate;
|
||||
|
||||
@optional
|
||||
// This should be required, after migration is done.
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* These methods are all implemented by RCTCxxBridge, which subclasses RCTBridge. Hence, they must only be used in
|
||||
* contexts where the concrete class of an RCTBridge instance is RCTCxxBridge. This happens, for example, when
|
||||
* [RCTCxxBridgeDelegate jsExecutorFactoryForBridge:(RCTBridge *)] is invoked by RCTCxxBridge.
|
||||
*
|
||||
* TODO: Consolidate this extension with the one in RCTSurfacePresenter.
|
||||
*/
|
||||
@interface RCTBridge (RCTTurboModule)
|
||||
- (std::shared_ptr<facebook::react::CallInvoker>)jsCallInvoker;
|
||||
- (std::shared_ptr<facebook::react::CallInvoker>)decorateNativeCallInvoker:
|
||||
(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker;
|
||||
@end
|
706
node_modules/react-native/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.mm
generated
vendored
Normal file
706
node_modules/react-native/ReactCommon/turbomodule/core/platform/ios/RCTTurboModule.mm
generated
vendored
Normal file
@ -0,0 +1,706 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTTurboModule.h"
|
||||
|
||||
#import <objc/message.h>
|
||||
#import <objc/runtime.h>
|
||||
#import <sstream>
|
||||
#import <vector>
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTConvert.h>
|
||||
#import <React/RCTCxxConvert.h>
|
||||
#import <React/RCTManagedPointer.h>
|
||||
#import <React/RCTModuleMethod.h>
|
||||
#import <React/RCTUtils.h>
|
||||
#import <ReactCommon/CallInvoker.h>
|
||||
#import <ReactCommon/LongLivedObject.h>
|
||||
#import <ReactCommon/TurboModule.h>
|
||||
#import <ReactCommon/TurboModuleUtils.h>
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
/**
|
||||
* All static helper functions are ObjC++ specific.
|
||||
*/
|
||||
static jsi::Value convertNSNumberToJSIBoolean(jsi::Runtime &runtime, NSNumber *value)
|
||||
{
|
||||
return jsi::Value((bool)[value boolValue]);
|
||||
}
|
||||
|
||||
static jsi::Value convertNSNumberToJSINumber(jsi::Runtime &runtime, NSNumber *value)
|
||||
{
|
||||
return jsi::Value([value doubleValue]);
|
||||
}
|
||||
|
||||
static jsi::String convertNSStringToJSIString(jsi::Runtime &runtime, NSString *value)
|
||||
{
|
||||
return jsi::String::createFromUtf8(runtime, [value UTF8String] ?: "");
|
||||
}
|
||||
|
||||
static jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value);
|
||||
static jsi::Object convertNSDictionaryToJSIObject(jsi::Runtime &runtime, NSDictionary *value)
|
||||
{
|
||||
jsi::Object result = jsi::Object(runtime);
|
||||
for (NSString *k in value) {
|
||||
result.setProperty(runtime, [k UTF8String], convertObjCObjectToJSIValue(runtime, value[k]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static jsi::Array convertNSArrayToJSIArray(jsi::Runtime &runtime, NSArray *value)
|
||||
{
|
||||
jsi::Array result = jsi::Array(runtime, value.count);
|
||||
for (size_t i = 0; i < value.count; i++) {
|
||||
result.setValueAtIndex(runtime, i, convertObjCObjectToJSIValue(runtime, value[i]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::vector<jsi::Value> convertNSArrayToStdVector(jsi::Runtime &runtime, NSArray *value)
|
||||
{
|
||||
std::vector<jsi::Value> result;
|
||||
for (size_t i = 0; i < value.count; i++) {
|
||||
result.emplace_back(convertObjCObjectToJSIValue(runtime, value[i]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value)
|
||||
{
|
||||
if ([value isKindOfClass:[NSString class]]) {
|
||||
return convertNSStringToJSIString(runtime, (NSString *)value);
|
||||
} else if ([value isKindOfClass:[NSNumber class]]) {
|
||||
if ([value isKindOfClass:[@YES class]]) {
|
||||
return convertNSNumberToJSIBoolean(runtime, (NSNumber *)value);
|
||||
}
|
||||
return convertNSNumberToJSINumber(runtime, (NSNumber *)value);
|
||||
} else if ([value isKindOfClass:[NSDictionary class]]) {
|
||||
return convertNSDictionaryToJSIObject(runtime, (NSDictionary *)value);
|
||||
} else if ([value isKindOfClass:[NSArray class]]) {
|
||||
return convertNSArrayToJSIArray(runtime, (NSArray *)value);
|
||||
} else if (value == (id)kCFNull) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
|
||||
static id convertJSIValueToObjCObject(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &value,
|
||||
std::shared_ptr<react::CallInvoker> jsInvoker);
|
||||
static NSString *convertJSIStringToNSString(jsi::Runtime &runtime, const jsi::String &value)
|
||||
{
|
||||
return [NSString stringWithUTF8String:value.utf8(runtime).c_str()];
|
||||
}
|
||||
|
||||
static NSArray *
|
||||
convertJSIArrayToNSArray(jsi::Runtime &runtime, const jsi::Array &value, std::shared_ptr<react::CallInvoker> jsInvoker)
|
||||
{
|
||||
size_t size = value.size(runtime);
|
||||
NSMutableArray *result = [NSMutableArray new];
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
// Insert kCFNull when it's `undefined` value to preserve the indices.
|
||||
[result
|
||||
addObject:convertJSIValueToObjCObject(runtime, value.getValueAtIndex(runtime, i), jsInvoker) ?: (id)kCFNull];
|
||||
}
|
||||
return [result copy];
|
||||
}
|
||||
|
||||
static NSDictionary *convertJSIObjectToNSDictionary(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Object &value,
|
||||
std::shared_ptr<react::CallInvoker> jsInvoker)
|
||||
{
|
||||
jsi::Array propertyNames = value.getPropertyNames(runtime);
|
||||
size_t size = propertyNames.size(runtime);
|
||||
NSMutableDictionary *result = [NSMutableDictionary new];
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
jsi::String name = propertyNames.getValueAtIndex(runtime, i).getString(runtime);
|
||||
NSString *k = convertJSIStringToNSString(runtime, name);
|
||||
id v = convertJSIValueToObjCObject(runtime, value.getProperty(runtime, name), jsInvoker);
|
||||
if (v) {
|
||||
result[k] = v;
|
||||
}
|
||||
}
|
||||
return [result copy];
|
||||
}
|
||||
|
||||
static RCTResponseSenderBlock convertJSIFunctionToCallback(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Function &value,
|
||||
std::shared_ptr<react::CallInvoker> jsInvoker);
|
||||
static id convertJSIValueToObjCObject(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &value,
|
||||
std::shared_ptr<react::CallInvoker> jsInvoker)
|
||||
{
|
||||
if (value.isUndefined() || value.isNull()) {
|
||||
return nil;
|
||||
}
|
||||
if (value.isBool()) {
|
||||
return @(value.getBool());
|
||||
}
|
||||
if (value.isNumber()) {
|
||||
return @(value.getNumber());
|
||||
}
|
||||
if (value.isString()) {
|
||||
return convertJSIStringToNSString(runtime, value.getString(runtime));
|
||||
}
|
||||
if (value.isObject()) {
|
||||
jsi::Object o = value.getObject(runtime);
|
||||
if (o.isArray(runtime)) {
|
||||
return convertJSIArrayToNSArray(runtime, o.getArray(runtime), jsInvoker);
|
||||
}
|
||||
if (o.isFunction(runtime)) {
|
||||
return convertJSIFunctionToCallback(runtime, std::move(o.getFunction(runtime)), jsInvoker);
|
||||
}
|
||||
return convertJSIObjectToNSDictionary(runtime, o, jsInvoker);
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unsupported jsi::jsi::Value kind");
|
||||
}
|
||||
|
||||
static RCTResponseSenderBlock convertJSIFunctionToCallback(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Function &value,
|
||||
std::shared_ptr<react::CallInvoker> jsInvoker)
|
||||
{
|
||||
auto weakWrapper = react::CallbackWrapper::createWeak(value.getFunction(runtime), runtime, jsInvoker);
|
||||
BOOL __block wrapperWasCalled = NO;
|
||||
return ^(NSArray *responses) {
|
||||
if (wrapperWasCalled) {
|
||||
throw std::runtime_error("callback arg cannot be called more than once");
|
||||
}
|
||||
|
||||
auto strongWrapper = weakWrapper.lock();
|
||||
if (!strongWrapper) {
|
||||
return;
|
||||
}
|
||||
|
||||
strongWrapper->jsInvoker().invokeAsync([weakWrapper, responses]() {
|
||||
auto strongWrapper2 = weakWrapper.lock();
|
||||
if (!strongWrapper2) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<jsi::Value> args = convertNSArrayToStdVector(strongWrapper2->runtime(), responses);
|
||||
strongWrapper2->callback().call(strongWrapper2->runtime(), (const jsi::Value *)args.data(), args.size());
|
||||
strongWrapper2->destroy();
|
||||
});
|
||||
|
||||
wrapperWasCalled = YES;
|
||||
};
|
||||
}
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
jsi::Value ObjCTurboModule::createPromise(
|
||||
jsi::Runtime &runtime,
|
||||
std::shared_ptr<react::CallInvoker> jsInvoker,
|
||||
PromiseInvocationBlock invoke)
|
||||
{
|
||||
if (!invoke) {
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
|
||||
jsi::Function Promise = runtime.global().getPropertyAsFunction(runtime, "Promise");
|
||||
|
||||
// Note: the passed invoke() block is not retained by default, so let's retain it here to help keep it longer.
|
||||
// Otherwise, there's a risk of it getting released before the promise function below executes.
|
||||
PromiseInvocationBlock invokeCopy = [invoke copy];
|
||||
jsi::Function fn = jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
jsi::PropNameID::forAscii(runtime, "fn"),
|
||||
2,
|
||||
[invokeCopy, jsInvoker](jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, size_t count) {
|
||||
if (count != 2) {
|
||||
throw std::invalid_argument(
|
||||
"Promise must pass constructor function two args. Passed " + std::to_string(count) + " args.");
|
||||
}
|
||||
if (!invokeCopy) {
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
|
||||
auto weakResolveWrapper =
|
||||
react::CallbackWrapper::createWeak(args[0].getObject(rt).getFunction(rt), rt, jsInvoker);
|
||||
auto weakRejectWrapper =
|
||||
react::CallbackWrapper::createWeak(args[1].getObject(rt).getFunction(rt), rt, jsInvoker);
|
||||
|
||||
__block BOOL resolveWasCalled = NO;
|
||||
__block BOOL rejectWasCalled = NO;
|
||||
|
||||
RCTPromiseResolveBlock resolveBlock = ^(id result) {
|
||||
if (rejectWasCalled) {
|
||||
throw std::runtime_error("Tried to resolve a promise after it's already been rejected.");
|
||||
}
|
||||
|
||||
if (resolveWasCalled) {
|
||||
throw std::runtime_error("Tried to resolve a promise more than once.");
|
||||
}
|
||||
|
||||
auto strongResolveWrapper = weakResolveWrapper.lock();
|
||||
auto strongRejectWrapper = weakRejectWrapper.lock();
|
||||
if (!strongResolveWrapper || !strongRejectWrapper) {
|
||||
return;
|
||||
}
|
||||
|
||||
strongResolveWrapper->jsInvoker().invokeAsync([weakResolveWrapper, weakRejectWrapper, result]() {
|
||||
auto strongResolveWrapper2 = weakResolveWrapper.lock();
|
||||
auto strongRejectWrapper2 = weakRejectWrapper.lock();
|
||||
if (!strongResolveWrapper2 || !strongRejectWrapper2) {
|
||||
return;
|
||||
}
|
||||
|
||||
jsi::Runtime &rt = strongResolveWrapper2->runtime();
|
||||
jsi::Value arg = convertObjCObjectToJSIValue(rt, result);
|
||||
strongResolveWrapper2->callback().call(rt, arg);
|
||||
|
||||
strongResolveWrapper2->destroy();
|
||||
strongRejectWrapper2->destroy();
|
||||
});
|
||||
|
||||
resolveWasCalled = YES;
|
||||
};
|
||||
|
||||
RCTPromiseRejectBlock rejectBlock = ^(NSString *code, NSString *message, NSError *error) {
|
||||
if (resolveWasCalled) {
|
||||
throw std::runtime_error("Tried to reject a promise after it's already been resolved.");
|
||||
}
|
||||
|
||||
if (rejectWasCalled) {
|
||||
throw std::runtime_error("Tried to reject a promise more than once.");
|
||||
}
|
||||
|
||||
auto strongResolveWrapper = weakResolveWrapper.lock();
|
||||
auto strongRejectWrapper = weakRejectWrapper.lock();
|
||||
if (!strongResolveWrapper || !strongRejectWrapper) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSDictionary *jsError = RCTJSErrorFromCodeMessageAndNSError(code, message, error);
|
||||
strongRejectWrapper->jsInvoker().invokeAsync([weakResolveWrapper, weakRejectWrapper, jsError]() {
|
||||
auto strongResolveWrapper2 = weakResolveWrapper.lock();
|
||||
auto strongRejectWrapper2 = weakRejectWrapper.lock();
|
||||
if (!strongResolveWrapper2 || !strongRejectWrapper2) {
|
||||
return;
|
||||
}
|
||||
|
||||
jsi::Runtime &rt = strongRejectWrapper2->runtime();
|
||||
jsi::Value arg = convertNSDictionaryToJSIObject(rt, jsError);
|
||||
strongRejectWrapper2->callback().call(rt, arg);
|
||||
|
||||
strongResolveWrapper2->destroy();
|
||||
strongRejectWrapper2->destroy();
|
||||
});
|
||||
|
||||
rejectWasCalled = YES;
|
||||
};
|
||||
|
||||
invokeCopy(resolveBlock, rejectBlock);
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
|
||||
return Promise.callAsConstructor(runtime, fn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform method invocation on a specific queue as configured by the module class.
|
||||
* This serves as a backward-compatible support for RCTBridgeModule's methodQueue API.
|
||||
*
|
||||
* In the future:
|
||||
* - This methodQueue support may be removed for simplicity and consistency with Android.
|
||||
* - ObjC module methods will be always be called from JS thread.
|
||||
* They may decide to dispatch to a different queue as needed.
|
||||
*/
|
||||
jsi::Value ObjCTurboModule::performMethodInvocation(
|
||||
jsi::Runtime &runtime,
|
||||
TurboModuleMethodValueKind returnType,
|
||||
const char *methodName,
|
||||
NSInvocation *inv,
|
||||
NSMutableArray *retainedObjectsForInvocation,
|
||||
MethodCallId methodCallId)
|
||||
{
|
||||
__block id result;
|
||||
jsi::Runtime *rt = &runtime;
|
||||
__weak id<RCTTurboModule> weakModule = instance_;
|
||||
id<RCTTurboModulePerformanceLogger> performanceLogger = performanceLogger_;
|
||||
const char *moduleName = name_.c_str();
|
||||
const bool isSync = returnType != VoidKind && returnType != PromiseKind;
|
||||
|
||||
void (^block)() = ^{
|
||||
if (!weakModule) {
|
||||
return;
|
||||
}
|
||||
|
||||
id<RCTTurboModule> strongModule = weakModule;
|
||||
|
||||
if (isSync) {
|
||||
[performanceLogger syncRCTTurboModuleMethodCallStart:moduleName methodName:methodName methodCallId:methodCallId];
|
||||
} else {
|
||||
[performanceLogger asyncRCTTurboModuleMethodCallStart:moduleName methodName:methodName methodCallId:methodCallId];
|
||||
}
|
||||
|
||||
[inv invokeWithTarget:strongModule];
|
||||
[retainedObjectsForInvocation removeAllObjects];
|
||||
|
||||
if (returnType == VoidKind) {
|
||||
[performanceLogger asyncRCTTurboModuleMethodCallEnd:moduleName methodName:methodName methodCallId:methodCallId];
|
||||
return;
|
||||
}
|
||||
void *rawResult;
|
||||
[inv getReturnValue:&rawResult];
|
||||
result = (__bridge id)rawResult;
|
||||
[performanceLogger syncRCTTurboModuleMethodCallEnd:moduleName methodName:methodName methodCallId:methodCallId];
|
||||
};
|
||||
|
||||
if (returnType == VoidKind) {
|
||||
nativeInvoker_->invokeAsync([block]() -> void { block(); });
|
||||
} else {
|
||||
nativeInvoker_->invokeSync([block]() -> void { block(); });
|
||||
}
|
||||
|
||||
// VoidKind can't be null
|
||||
// PromiseKind, and FunctionKind must throw errors always
|
||||
if (returnType != VoidKind && returnType != PromiseKind && returnType != FunctionKind &&
|
||||
(result == (id)kCFNull || result == nil)) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
|
||||
jsi::Value returnValue = jsi::Value::undefined();
|
||||
[performanceLogger_ syncMethodCallReturnConversionStart:moduleName methodName:methodName methodCallId:methodCallId];
|
||||
|
||||
// TODO: Re-use value conversion logic from existing impl, if possible.
|
||||
switch (returnType) {
|
||||
case VoidKind: {
|
||||
break;
|
||||
}
|
||||
case BooleanKind: {
|
||||
returnValue = convertNSNumberToJSIBoolean(*rt, (NSNumber *)result);
|
||||
break;
|
||||
}
|
||||
case NumberKind: {
|
||||
returnValue = convertNSNumberToJSINumber(*rt, (NSNumber *)result);
|
||||
break;
|
||||
}
|
||||
case StringKind: {
|
||||
returnValue = convertNSStringToJSIString(*rt, (NSString *)result);
|
||||
break;
|
||||
}
|
||||
case ObjectKind: {
|
||||
returnValue = convertNSDictionaryToJSIObject(*rt, (NSDictionary *)result);
|
||||
break;
|
||||
}
|
||||
case ArrayKind: {
|
||||
returnValue = convertNSArrayToJSIArray(*rt, (NSArray *)result);
|
||||
break;
|
||||
}
|
||||
case FunctionKind:
|
||||
throw std::runtime_error("convertInvocationResultToJSIValue: FunctionKind is not supported yet.");
|
||||
case PromiseKind:
|
||||
throw std::runtime_error("convertInvocationResultToJSIValue: PromiseKind wasn't handled properly.");
|
||||
}
|
||||
|
||||
[performanceLogger_ syncMethodCallReturnConversionEnd:moduleName methodName:methodName methodCallId:methodCallId];
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a method name, and an argument index, return type of that argument.
|
||||
* Prerequisite: You must wrap the method declaration inside some variant of the
|
||||
* RCT_EXPORT_METHOD macro.
|
||||
*
|
||||
* This method returns nil if the method for which you're querying the argument type
|
||||
* is not wrapped in an RCT_EXPORT_METHOD.
|
||||
*
|
||||
* Note: This is only being introduced for backward compatibility. It will be removed
|
||||
* in the future.
|
||||
*/
|
||||
NSString *ObjCTurboModule::getArgumentTypeName(NSString *methodName, int argIndex)
|
||||
{
|
||||
if (!methodArgumentTypeNames_) {
|
||||
NSMutableDictionary<NSString *, NSArray<NSString *> *> *methodArgumentTypeNames = [NSMutableDictionary new];
|
||||
|
||||
unsigned int numberOfMethods;
|
||||
Class cls = [instance_ class];
|
||||
Method *methods = class_copyMethodList(object_getClass(cls), &numberOfMethods);
|
||||
|
||||
if (methods) {
|
||||
for (unsigned int i = 0; i < numberOfMethods; i++) {
|
||||
SEL s = method_getName(methods[i]);
|
||||
NSString *mName = NSStringFromSelector(s);
|
||||
if (![mName hasPrefix:@"__rct_export__"]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Message dispatch logic from old infra
|
||||
RCTMethodInfo *(*getMethodInfo)(id, SEL) = (__typeof__(getMethodInfo))objc_msgSend;
|
||||
RCTMethodInfo *methodInfo = getMethodInfo(cls, s);
|
||||
|
||||
NSArray<RCTMethodArgument *> *arguments;
|
||||
NSString *otherMethodName = RCTParseMethodSignature(methodInfo->objcName, &arguments);
|
||||
|
||||
NSMutableArray *argumentTypes = [NSMutableArray arrayWithCapacity:[arguments count]];
|
||||
for (int j = 0; j < [arguments count]; j += 1) {
|
||||
[argumentTypes addObject:arguments[j].type];
|
||||
}
|
||||
|
||||
NSString *normalizedOtherMethodName = [otherMethodName componentsSeparatedByString:@":"][0];
|
||||
methodArgumentTypeNames[normalizedOtherMethodName] = argumentTypes;
|
||||
}
|
||||
|
||||
free(methods);
|
||||
}
|
||||
|
||||
methodArgumentTypeNames_ = methodArgumentTypeNames;
|
||||
}
|
||||
|
||||
if (methodArgumentTypeNames_[methodName]) {
|
||||
assert([methodArgumentTypeNames_[methodName] count] > argIndex);
|
||||
return methodArgumentTypeNames_[methodName][argIndex];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSInvocation *ObjCTurboModule::getMethodInvocation(
|
||||
jsi::Runtime &runtime,
|
||||
TurboModuleMethodValueKind returnType,
|
||||
const char *methodName,
|
||||
SEL selector,
|
||||
const jsi::Value *args,
|
||||
size_t count,
|
||||
NSMutableArray *retainedObjectsForInvocation,
|
||||
MethodCallId methodCallId)
|
||||
{
|
||||
const bool isSync = returnType != VoidKind && returnType != PromiseKind;
|
||||
const char *moduleName = name_.c_str();
|
||||
const id<RCTTurboModule> module = instance_;
|
||||
|
||||
if (isSync) {
|
||||
[performanceLogger_ syncMethodCallArgumentConversionStart:moduleName
|
||||
methodName:methodName
|
||||
methodCallId:methodCallId];
|
||||
} else {
|
||||
[performanceLogger_ asyncMethodCallArgumentConversionStart:moduleName
|
||||
methodName:methodName
|
||||
methodCallId:methodCallId];
|
||||
}
|
||||
|
||||
NSInvocation *inv =
|
||||
[NSInvocation invocationWithMethodSignature:[[module class] instanceMethodSignatureForSelector:selector]];
|
||||
[inv setSelector:selector];
|
||||
|
||||
NSMethodSignature *methodSignature = [[module class] instanceMethodSignatureForSelector:selector];
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
const jsi::Value *arg = &args[i];
|
||||
const std::string objCArgType = [methodSignature getArgumentTypeAtIndex:i + 2];
|
||||
|
||||
if (arg->isBool()) {
|
||||
bool v = arg->getBool();
|
||||
|
||||
/**
|
||||
* JS type checking ensures the Objective C argument here is either a BOOL or NSNumber*.
|
||||
*/
|
||||
if (objCArgType == @encode(id)) {
|
||||
id objCArg = [NSNumber numberWithBool:v];
|
||||
[inv setArgument:(void *)&objCArg atIndex:i + 2];
|
||||
[retainedObjectsForInvocation addObject:objCArg];
|
||||
} else {
|
||||
[inv setArgument:(void *)&v atIndex:i + 2];
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg->isNumber()) {
|
||||
double v = arg->getNumber();
|
||||
|
||||
/**
|
||||
* JS type checking ensures the Objective C argument here is either a double or NSNumber*.
|
||||
*/
|
||||
if (objCArgType == @encode(id)) {
|
||||
id objCArg = [NSNumber numberWithDouble:v];
|
||||
[inv setArgument:(void *)&objCArg atIndex:i + 2];
|
||||
[retainedObjectsForInvocation addObject:objCArg];
|
||||
} else {
|
||||
[inv setArgument:(void *)&v atIndex:i + 2];
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert arg to ObjC objects.
|
||||
*/
|
||||
id objCArg = convertJSIValueToObjCObject(runtime, *arg, jsInvoker_);
|
||||
|
||||
if (objCArg) {
|
||||
NSString *methodNameNSString = @(methodName);
|
||||
|
||||
/**
|
||||
* Convert objects using RCTConvert.
|
||||
*/
|
||||
if (objCArgType == @encode(id)) {
|
||||
NSString *argumentType = getArgumentTypeName(methodNameNSString, i);
|
||||
if (argumentType != nil) {
|
||||
NSString *rctConvertMethodName = [NSString stringWithFormat:@"%@:", argumentType];
|
||||
SEL rctConvertSelector = NSSelectorFromString(rctConvertMethodName);
|
||||
|
||||
if ([RCTConvert respondsToSelector:rctConvertSelector]) {
|
||||
// Message dispatch logic from old infra
|
||||
id (*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend;
|
||||
id convertedObjCArg = convert([RCTConvert class], rctConvertSelector, objCArg);
|
||||
|
||||
[inv setArgument:(void *)&convertedObjCArg atIndex:i + 2];
|
||||
if (convertedObjCArg) {
|
||||
[retainedObjectsForInvocation addObject:convertedObjCArg];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert objects using RCTCxxConvert to structs.
|
||||
*/
|
||||
if ([objCArg isKindOfClass:[NSDictionary class]] && hasMethodArgConversionSelector(methodNameNSString, i)) {
|
||||
SEL methodArgConversionSelector = getMethodArgConversionSelector(methodNameNSString, i);
|
||||
|
||||
// Message dispatch logic from old infra (link: https://git.io/fjf3U)
|
||||
RCTManagedPointer *(*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend;
|
||||
RCTManagedPointer *box = convert([RCTCxxConvert class], methodArgConversionSelector, objCArg);
|
||||
|
||||
void *pointer = box.voidPointer;
|
||||
[inv setArgument:&pointer atIndex:i + 2];
|
||||
[retainedObjectsForInvocation addObject:box];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert converted args unmodified.
|
||||
*/
|
||||
[inv setArgument:(void *)&objCArg atIndex:i + 2];
|
||||
if (objCArg) {
|
||||
[retainedObjectsForInvocation addObject:objCArg];
|
||||
}
|
||||
}
|
||||
|
||||
if (isSync) {
|
||||
[performanceLogger_ syncMethodCallArgumentConversionEnd:moduleName methodName:methodName methodCallId:methodCallId];
|
||||
} else {
|
||||
[performanceLogger_ asyncMethodCallArgumentConversionEnd:moduleName
|
||||
methodName:methodName
|
||||
methodCallId:methodCallId];
|
||||
}
|
||||
|
||||
return inv;
|
||||
}
|
||||
|
||||
ObjCTurboModule::ObjCTurboModule(
|
||||
const std::string &name,
|
||||
id<RCTTurboModule> instance,
|
||||
std::shared_ptr<CallInvoker> jsInvoker,
|
||||
std::shared_ptr<CallInvoker> nativeInvoker,
|
||||
id<RCTTurboModulePerformanceLogger> perfLogger)
|
||||
: TurboModule(name, jsInvoker), instance_(instance), nativeInvoker_(nativeInvoker), performanceLogger_(perfLogger)
|
||||
{
|
||||
}
|
||||
|
||||
MethodCallId ObjCTurboModule::methodCallId_{0};
|
||||
|
||||
MethodCallId ObjCTurboModule::getNewMethodCallId()
|
||||
{
|
||||
return methodCallId_++;
|
||||
}
|
||||
|
||||
jsi::Value ObjCTurboModule::invokeObjCMethod(
|
||||
jsi::Runtime &runtime,
|
||||
TurboModuleMethodValueKind returnType,
|
||||
const std::string &methodNameStr,
|
||||
SEL selector,
|
||||
const jsi::Value *args,
|
||||
size_t count)
|
||||
{
|
||||
MethodCallId methodCallId = getNewMethodCallId();
|
||||
const bool isSync = returnType != VoidKind && returnType != PromiseKind;
|
||||
const char *moduleName = name_.c_str();
|
||||
const char *methodName = methodNameStr.c_str();
|
||||
|
||||
if (isSync) {
|
||||
[performanceLogger_ syncMethodCallStart:moduleName methodName:methodName methodCallId:methodCallId];
|
||||
} else {
|
||||
[performanceLogger_ asyncMethodCallStart:moduleName methodName:methodName methodCallId:methodCallId];
|
||||
}
|
||||
|
||||
NSMutableArray *retainedObjectsForInvocation = [NSMutableArray arrayWithCapacity:count + 2];
|
||||
NSInvocation *inv = getMethodInvocation(
|
||||
runtime, returnType, methodName, selector, args, count, retainedObjectsForInvocation, methodCallId);
|
||||
|
||||
jsi::Value returnValue = returnType == PromiseKind
|
||||
? createPromise(
|
||||
runtime,
|
||||
jsInvoker_,
|
||||
^(RCTPromiseResolveBlock resolveBlock, RCTPromiseRejectBlock rejectBlock) {
|
||||
[inv setArgument:(void *)&resolveBlock atIndex:count + 2];
|
||||
[inv setArgument:(void *)&rejectBlock atIndex:count + 3];
|
||||
[retainedObjectsForInvocation addObject:resolveBlock];
|
||||
[retainedObjectsForInvocation addObject:rejectBlock];
|
||||
// The return type becomes void in the ObjC side.
|
||||
performMethodInvocation(runtime, VoidKind, methodName, inv, retainedObjectsForInvocation, methodCallId);
|
||||
})
|
||||
: performMethodInvocation(runtime, returnType, methodName, inv, retainedObjectsForInvocation, methodCallId);
|
||||
|
||||
if (isSync) {
|
||||
[performanceLogger_ syncMethodCallEnd:moduleName methodName:methodName methodCallId:methodCallId];
|
||||
} else {
|
||||
[performanceLogger_ asyncMethodCallEnd:moduleName methodName:methodName methodCallId:methodCallId];
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
BOOL ObjCTurboModule::hasMethodArgConversionSelector(NSString *methodName, int argIndex)
|
||||
{
|
||||
return methodArgConversionSelectors_ && methodArgConversionSelectors_[methodName] &&
|
||||
![methodArgConversionSelectors_[methodName][argIndex] isEqual:[NSNull null]];
|
||||
}
|
||||
|
||||
SEL ObjCTurboModule::getMethodArgConversionSelector(NSString *methodName, int argIndex)
|
||||
{
|
||||
assert(hasMethodArgConversionSelector(methodName, argIndex));
|
||||
return (SEL)((NSValue *)methodArgConversionSelectors_[methodName][argIndex]).pointerValue;
|
||||
}
|
||||
|
||||
void ObjCTurboModule::setMethodArgConversionSelector(NSString *methodName, int argIndex, NSString *fnName)
|
||||
{
|
||||
if (!methodArgConversionSelectors_) {
|
||||
methodArgConversionSelectors_ = [NSMutableDictionary new];
|
||||
}
|
||||
|
||||
if (!methodArgConversionSelectors_[methodName]) {
|
||||
auto metaData = methodMap_.at([methodName UTF8String]);
|
||||
auto argCount = metaData.argCount;
|
||||
|
||||
methodArgConversionSelectors_[methodName] = [NSMutableArray arrayWithCapacity:argCount];
|
||||
for (int i = 0; i < argCount; i += 1) {
|
||||
[methodArgConversionSelectors_[methodName] addObject:[NSNull null]];
|
||||
}
|
||||
}
|
||||
|
||||
SEL selector = NSSelectorFromString(fnName);
|
||||
NSValue *selectorValue = [NSValue valueWithPointer:selector];
|
||||
|
||||
methodArgConversionSelectors_[methodName][argIndex] = selectorValue;
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
56
node_modules/react-native/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.h
generated
vendored
Normal file
56
node_modules/react-native/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.h
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTTurboModule.h"
|
||||
|
||||
@protocol RCTTurboModuleManagerDelegate <NSObject>
|
||||
|
||||
// TODO: Move to xplat codegen.
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
|
||||
instance:(id<RCTTurboModule>)instance
|
||||
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:
|
||||
(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger;
|
||||
|
||||
@optional
|
||||
|
||||
/**
|
||||
* Given a module name, return its actual class. If not provided, basic ObjC class lookup is performed.
|
||||
*/
|
||||
- (Class)getModuleClassFromName:(const char *)name;
|
||||
|
||||
/**
|
||||
* Given a module class, provide an instance for it. If not provided, default initializer is used.
|
||||
*/
|
||||
- (id<RCTTurboModule>)getModuleInstanceFromClass:(Class)moduleClass;
|
||||
|
||||
/**
|
||||
* Create an instance of a TurboModule without relying on any ObjC++ module instance.
|
||||
*/
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
|
||||
jsInvoker:
|
||||
(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTTurboModuleManager : NSObject <RCTTurboModuleLookupDelegate>
|
||||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
||||
delegate:(id<RCTTurboModuleManagerDelegate>)delegate
|
||||
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker;
|
||||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
||||
delegate:(id<RCTTurboModuleManagerDelegate>)delegate
|
||||
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
performanceLogger:(id<RCTTurboModulePerformanceLogger>)performanceLogger;
|
||||
|
||||
- (void)installJSBindingWithRuntime:(facebook::jsi::Runtime *)runtime;
|
||||
|
||||
- (void)invalidate;
|
||||
|
||||
@end
|
648
node_modules/react-native/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm
generated
vendored
Normal file
648
node_modules/react-native/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm
generated
vendored
Normal file
@ -0,0 +1,648 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTTurboModuleManager.h"
|
||||
|
||||
#import <atomic>
|
||||
#import <cassert>
|
||||
#import <mutex>
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import <React/RCTBridge+Private.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import <React/RCTCxxModule.h>
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTModuleData.h>
|
||||
#import <React/RCTPerformanceLogger.h>
|
||||
#import <React/RCTUtils.h>
|
||||
#import <ReactCommon/TurboCxxModule.h>
|
||||
#import <ReactCommon/TurboModuleBinding.h>
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
/**
|
||||
* A global variable whose address we use to associate method queues to id<RCTTurboModule> objects.
|
||||
*/
|
||||
static char kAssociatedMethodQueueKey;
|
||||
|
||||
namespace {
|
||||
class MethodQueueNativeCallInvoker : public facebook::react::CallInvoker {
|
||||
private:
|
||||
dispatch_queue_t methodQueue_;
|
||||
|
||||
public:
|
||||
MethodQueueNativeCallInvoker(dispatch_queue_t methodQueue) : methodQueue_(methodQueue) {}
|
||||
void invokeAsync(std::function<void()> &&work) override
|
||||
{
|
||||
if (methodQueue_ == RCTJSThread) {
|
||||
work();
|
||||
return;
|
||||
}
|
||||
|
||||
__block auto retainedWork = std::move(work);
|
||||
dispatch_async(methodQueue_, ^{
|
||||
retainedWork();
|
||||
});
|
||||
}
|
||||
|
||||
void invokeSync(std::function<void()> &&work) override
|
||||
{
|
||||
if (methodQueue_ == RCTJSThread) {
|
||||
work();
|
||||
return;
|
||||
}
|
||||
|
||||
__block auto retainedWork = std::move(work);
|
||||
dispatch_sync(methodQueue_, ^{
|
||||
retainedWork();
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Fallback lookup since RCT class prefix is sometimes stripped in the existing NativeModule system.
|
||||
// This will be removed in the future.
|
||||
static Class getFallbackClassFromName(const char *name)
|
||||
{
|
||||
Class moduleClass = NSClassFromString([NSString stringWithUTF8String:name]);
|
||||
if (!moduleClass) {
|
||||
moduleClass = NSClassFromString([NSString stringWithFormat:@"RCT%s", name]);
|
||||
}
|
||||
return moduleClass;
|
||||
}
|
||||
|
||||
@implementation RCTTurboModuleManager {
|
||||
jsi::Runtime *_runtime;
|
||||
std::shared_ptr<facebook::react::CallInvoker> _jsInvoker;
|
||||
id<RCTTurboModulePerformanceLogger> _performanceLogger;
|
||||
__weak id<RCTTurboModuleManagerDelegate> _delegate;
|
||||
__weak RCTBridge *_bridge;
|
||||
/**
|
||||
* TODO(T48018690):
|
||||
* All modules are currently long-lived.
|
||||
* We need to come up with a mechanism to allow modules to specify whether
|
||||
* they want to be long-lived or short-lived.
|
||||
*/
|
||||
std::unordered_map<std::string, id<RCTTurboModule>> _rctTurboModuleCache;
|
||||
std::unordered_map<std::string, std::shared_ptr<react::TurboModule>> _turboModuleCache;
|
||||
|
||||
/**
|
||||
* _rctTurboModuleCache can be accessed by multiple threads at once via
|
||||
* the provideRCTTurboModule method. This can lead to races. Therefore, we
|
||||
* need to protect access to this unordered_map.
|
||||
*
|
||||
* Note:
|
||||
* There's no need to protect access to _turboModuleCache because that cache
|
||||
* is only accessed within provideTurboModule, which is only invoked by the
|
||||
* JS thread.
|
||||
*/
|
||||
std::mutex _rctTurboModuleCacheLock;
|
||||
std::atomic<bool> _invalidating;
|
||||
}
|
||||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
||||
delegate:(id<RCTTurboModuleManagerDelegate>)delegate
|
||||
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
{
|
||||
return [self initWithBridge:bridge delegate:delegate jsInvoker:jsInvoker performanceLogger:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
||||
delegate:(id<RCTTurboModuleManagerDelegate>)delegate
|
||||
jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
performanceLogger:(id<RCTTurboModulePerformanceLogger>)performanceLogger
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_jsInvoker = jsInvoker;
|
||||
_delegate = delegate;
|
||||
_bridge = bridge;
|
||||
_invalidating = false;
|
||||
_performanceLogger = performanceLogger;
|
||||
|
||||
// Necessary to allow NativeModules to lookup TurboModules
|
||||
[bridge setRCTTurboModuleLookupDelegate:self];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(bridgeWillInvalidateModules:)
|
||||
name:RCTBridgeWillInvalidateModulesNotification
|
||||
object:_bridge.parentBridge];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(bridgeDidInvalidateModules:)
|
||||
name:RCTBridgeDidInvalidateModulesNotification
|
||||
object:_bridge.parentBridge];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)notifyAboutTurboModuleSetup:(const char *)name
|
||||
{
|
||||
NSString *moduleName = [[NSString alloc] initWithUTF8String:name];
|
||||
if (moduleName) {
|
||||
int64_t setupTime = [self->_bridge.performanceLogger durationForTag:RCTPLTurboModuleSetup];
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTDidSetupModuleNotification
|
||||
object:nil
|
||||
userInfo:@{
|
||||
RCTDidSetupModuleNotificationModuleNameKey : moduleName,
|
||||
RCTDidSetupModuleNotificationSetupTimeKey : @(setupTime)
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a name for a TurboModule, return a C++ object which is the instance
|
||||
* of that TurboModule C++ class. This class wraps the TurboModule's ObjC instance.
|
||||
* If no TurboModule ObjC class exist with the provided name, abort program.
|
||||
*
|
||||
* Note: All TurboModule instances are cached, which means they're all long-lived
|
||||
* (for now).
|
||||
*/
|
||||
|
||||
- (std::shared_ptr<react::TurboModule>)provideTurboModule:(const char *)moduleName
|
||||
{
|
||||
auto turboModuleLookup = _turboModuleCache.find(moduleName);
|
||||
if (turboModuleLookup != _turboModuleCache.end()) {
|
||||
[_performanceLogger createTurboModuleCacheHit:moduleName];
|
||||
return turboModuleLookup->second;
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 1: Look for pure C++ modules.
|
||||
* Pure C++ modules get priority.
|
||||
*/
|
||||
if ([_delegate respondsToSelector:@selector(getTurboModule:jsInvoker:)]) {
|
||||
[_performanceLogger getCppTurboModuleFromTMMDelegateStart:moduleName];
|
||||
auto turboModule = [_delegate getTurboModule:moduleName jsInvoker:_jsInvoker];
|
||||
[_performanceLogger getCppTurboModuleFromTMMDelegateEnd:moduleName];
|
||||
if (turboModule != nullptr) {
|
||||
_turboModuleCache.insert({moduleName, turboModule});
|
||||
return turboModule;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 2: Look for platform-specific modules.
|
||||
*/
|
||||
[_performanceLogger createRCTTurboModuleStart:moduleName];
|
||||
id<RCTTurboModule> module = [self provideRCTTurboModule:moduleName];
|
||||
[_performanceLogger createRCTTurboModuleEnd:moduleName];
|
||||
|
||||
// If we request that a TurboModule be created, its respective ObjC class must exist
|
||||
// If the class doesn't exist, then provideRCTTurboModule returns nil
|
||||
if (!module) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Class moduleClass = [module class];
|
||||
|
||||
dispatch_queue_t methodQueue = (dispatch_queue_t)objc_getAssociatedObject(module, &kAssociatedMethodQueueKey);
|
||||
|
||||
/**
|
||||
* Step 2c: Create and native CallInvoker from the TurboModule's method queue.
|
||||
*/
|
||||
std::shared_ptr<facebook::react::CallInvoker> nativeInvoker =
|
||||
std::make_shared<MethodQueueNativeCallInvoker>(methodQueue);
|
||||
|
||||
/**
|
||||
* Have RCTCxxBridge decorate native CallInvoker, so that it's aware of TurboModule async method calls.
|
||||
* This helps the bridge fire onBatchComplete as readily as it should.
|
||||
*/
|
||||
if ([_bridge respondsToSelector:@selector(decorateNativeCallInvoker:)]) {
|
||||
nativeInvoker = [_bridge decorateNativeCallInvoker:nativeInvoker];
|
||||
}
|
||||
|
||||
// If RCTTurboModule supports creating its own C++ TurboModule object,
|
||||
// allow it to do so.
|
||||
if ([module respondsToSelector:@selector(getTurboModuleWithJsInvoker:nativeInvoker:perfLogger:)]) {
|
||||
[_performanceLogger getTurboModuleFromRCTTurboModuleStart:moduleName];
|
||||
auto turboModule = [module getTurboModuleWithJsInvoker:_jsInvoker
|
||||
nativeInvoker:nativeInvoker
|
||||
perfLogger:_performanceLogger];
|
||||
[_performanceLogger getTurboModuleFromRCTTurboModuleEnd:moduleName];
|
||||
assert(turboModule != nullptr);
|
||||
_turboModuleCache.insert({moduleName, turboModule});
|
||||
return turboModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 2d: If the moduleClass is a legacy CxxModule, return a TurboCxxModule instance that
|
||||
* wraps CxxModule.
|
||||
*/
|
||||
if ([moduleClass isSubclassOfClass:RCTCxxModule.class]) {
|
||||
// Use TurboCxxModule compat class to wrap the CxxModule instance.
|
||||
// This is only for migration convenience, despite less performant.
|
||||
[_performanceLogger getTurboModuleFromRCTCxxModuleStart:moduleName];
|
||||
auto turboModule = std::make_shared<react::TurboCxxModule>([((RCTCxxModule *)module) createModule], _jsInvoker);
|
||||
[_performanceLogger getTurboModuleFromRCTCxxModuleEnd:moduleName];
|
||||
_turboModuleCache.insert({moduleName, turboModule});
|
||||
return turboModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 2e: Return an exact sub-class of ObjC TurboModule
|
||||
*/
|
||||
[_performanceLogger getTurboModuleFromTMMDelegateStart:moduleName];
|
||||
auto turboModule = [_delegate getTurboModule:moduleName
|
||||
instance:module
|
||||
jsInvoker:_jsInvoker
|
||||
nativeInvoker:nativeInvoker
|
||||
perfLogger:_performanceLogger];
|
||||
[_performanceLogger getTurboModuleFromTMMDelegateEnd:moduleName];
|
||||
if (turboModule != nullptr) {
|
||||
_turboModuleCache.insert({moduleName, turboModule});
|
||||
}
|
||||
return turboModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a name for a TurboModule, return an ObjC object which is the instance
|
||||
* of that TurboModule ObjC class. If no TurboModule exist with the provided name,
|
||||
* return nil.
|
||||
*
|
||||
* Note: All TurboModule instances are cached, which means they're all long-lived
|
||||
* (for now).
|
||||
*/
|
||||
- (id<RCTTurboModule>)provideRCTTurboModule:(const char *)moduleName
|
||||
{
|
||||
Class moduleClass;
|
||||
id<RCTTurboModule> module = nil;
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_rctTurboModuleCacheLock);
|
||||
|
||||
auto rctTurboModuleCacheLookup = _rctTurboModuleCache.find(moduleName);
|
||||
if (rctTurboModuleCacheLookup != _rctTurboModuleCache.end()) {
|
||||
[_performanceLogger createRCTTurboModuleCacheHit:moduleName];
|
||||
return rctTurboModuleCacheLookup->second;
|
||||
}
|
||||
|
||||
if (_invalidating) {
|
||||
// Don't allow creating new instances while invalidating.
|
||||
return nil;
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 2a: Resolve platform-specific class.
|
||||
*/
|
||||
[_performanceLogger getRCTTurboModuleClassStart:moduleName];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(getModuleClassFromName:)]) {
|
||||
moduleClass = [_delegate getModuleClassFromName:moduleName];
|
||||
}
|
||||
|
||||
if (!moduleClass) {
|
||||
moduleClass = getFallbackClassFromName(moduleName);
|
||||
}
|
||||
|
||||
[_performanceLogger getRCTTurboModuleClassEnd:moduleName];
|
||||
|
||||
if (![moduleClass conformsToProtocol:@protocol(RCTTurboModule)]) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 2b: Ask hosting application/delegate to instantiate this class
|
||||
*/
|
||||
[_performanceLogger getRCTTurboModuleInstanceStart:moduleName];
|
||||
|
||||
if ([_delegate respondsToSelector:@selector(getModuleInstanceFromClass:)]) {
|
||||
module = [_delegate getModuleInstanceFromClass:moduleClass];
|
||||
} else {
|
||||
module = [moduleClass new];
|
||||
}
|
||||
|
||||
[_performanceLogger getRCTTurboModuleInstanceEnd:moduleName];
|
||||
|
||||
if ([module respondsToSelector:@selector(setTurboModuleLookupDelegate:)]) {
|
||||
[module setTurboModuleLookupDelegate:self];
|
||||
}
|
||||
|
||||
_rctTurboModuleCache.insert({moduleName, module});
|
||||
}
|
||||
|
||||
[self setUpRCTTurboModule:module moduleName:moduleName];
|
||||
return module;
|
||||
}
|
||||
|
||||
- (void)setUpRCTTurboModule:(id<RCTTurboModule>)module moduleName:(const char *)moduleName
|
||||
{
|
||||
__weak id<RCTBridgeModule> weakModule = (id<RCTBridgeModule>)module;
|
||||
__weak RCTBridge *weakBridge = _bridge;
|
||||
id<RCTTurboModulePerformanceLogger> performanceLogger = _performanceLogger;
|
||||
|
||||
auto setUpTurboModule = ^{
|
||||
if (!weakModule) {
|
||||
return;
|
||||
}
|
||||
|
||||
[performanceLogger setupRCTTurboModuleStart:moduleName];
|
||||
|
||||
id<RCTBridgeModule> strongModule = weakModule;
|
||||
RCTBridge *strongBridge = weakBridge;
|
||||
|
||||
/**
|
||||
* It is reasonable for NativeModules to not want/need the bridge.
|
||||
* In such cases, they won't have `@synthesize bridge = _bridge` in their
|
||||
* implementation, and a `- (RCTBridge *) bridge { ... }` method won't be
|
||||
* generated by the ObjC runtime. The property will also not be backed
|
||||
* by an ivar, which makes writing to it unsafe. Therefore, we check if
|
||||
* this method exists to know if we can safely set the bridge to the
|
||||
* NativeModule.
|
||||
*/
|
||||
if ([strongModule respondsToSelector:@selector(bridge)] && strongBridge) {
|
||||
[performanceLogger attachRCTBridgeToRCTTurboModuleStart:moduleName];
|
||||
|
||||
/**
|
||||
* Just because a NativeModule has the `bridge` method, it doesn't mean
|
||||
* that it has synthesized the bridge in its implementation. Therefore,
|
||||
* we need to surround the code that sets the bridge to the NativeModule
|
||||
* inside a try/catch. This catches the cases where the NativeModule
|
||||
* author specifies a `bridge` method manually.
|
||||
*/
|
||||
@try {
|
||||
/**
|
||||
* RCTBridgeModule declares the bridge property as readonly.
|
||||
* Therefore, when authors of NativeModules synthesize the bridge
|
||||
* via @synthesize bridge = bridge;, the ObjC runtime generates
|
||||
* only a - (RCTBridge *) bridge: { ... } method. No setter is
|
||||
* generated, so we have have to rely on the KVC API of ObjC to set
|
||||
* the bridge property of these NativeModules.
|
||||
*/
|
||||
[(id)strongModule setValue:strongBridge forKey:@"bridge"];
|
||||
} @catch (NSException *exception) {
|
||||
RCTLogError(
|
||||
@"%@ has no setter or ivar for its bridge, which is not "
|
||||
"permitted. You must either @synthesize the bridge property, "
|
||||
"or provide your own setter method.",
|
||||
RCTBridgeModuleNameForClass([strongModule class]));
|
||||
}
|
||||
|
||||
[performanceLogger attachRCTBridgeToRCTTurboModuleEnd:moduleName];
|
||||
}
|
||||
|
||||
/**
|
||||
* Some modules need their own queues, but don't provide any, so we need to create it for them.
|
||||
* These modules typically have the following:
|
||||
* `@synthesize methodQueue = _methodQueue`
|
||||
*/
|
||||
|
||||
[performanceLogger attachMethodQueueToRCTTurboModuleStart:moduleName];
|
||||
|
||||
dispatch_queue_t methodQueue = nil;
|
||||
BOOL moduleHasMethodQueueGetter = [strongModule respondsToSelector:@selector(methodQueue)];
|
||||
|
||||
if (moduleHasMethodQueueGetter) {
|
||||
methodQueue = [strongModule methodQueue];
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: RCTJSThread, which is a valid method queue, is defined as (id)kCFNull. It should rightfully not enter the
|
||||
* following if condition's block.
|
||||
*/
|
||||
if (!methodQueue) {
|
||||
NSString *methodQueueName = [NSString stringWithFormat:@"com.facebook.react.%sQueue", moduleName];
|
||||
methodQueue = dispatch_queue_create(methodQueueName.UTF8String, DISPATCH_QUEUE_SERIAL);
|
||||
|
||||
if (moduleHasMethodQueueGetter) {
|
||||
/**
|
||||
* If the module has a method queue getter, two cases are possible:
|
||||
* - We @synthesized the method queue. In this case, the getter will initially return nil.
|
||||
* - We had a custom methodQueue function on the NativeModule. If we got this far, then that getter returned
|
||||
* nil.
|
||||
*
|
||||
* Therefore, we do a try/catch and use ObjC's KVC API and try to assign the method queue to the NativeModule.
|
||||
* In case 1, we'll succeed. In case 2, an exception will be thrown, which we'll ignore.
|
||||
*/
|
||||
|
||||
@try {
|
||||
[(id)strongModule setValue:methodQueue forKey:@"methodQueue"];
|
||||
} @catch (NSException *exception) {
|
||||
RCTLogError(
|
||||
@"%@ has no setter or ivar for its methodQueue, which is not "
|
||||
"permitted. You must either @synthesize the bridge property, "
|
||||
"or provide your own setter method.",
|
||||
RCTBridgeModuleNameForClass([strongModule class]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach method queue to id<RCTTurboModule> object.
|
||||
* This is necessary because the id<RCTTurboModule> object can be eagerly created/initialized before the method
|
||||
* queue is required. The method queue is required for an id<RCTTurboModule> for JS -> Native calls. So, we need it
|
||||
* before we create the id<RCTTurboModule>'s TurboModule jsi::HostObject in provideTurboModule:.
|
||||
*/
|
||||
objc_setAssociatedObject(strongModule, &kAssociatedMethodQueueKey, methodQueue, OBJC_ASSOCIATION_RETAIN);
|
||||
|
||||
[performanceLogger attachMethodQueueToRCTTurboModuleEnd:moduleName];
|
||||
|
||||
/**
|
||||
* NativeModules that implement the RCTFrameUpdateObserver protocol
|
||||
* require registration with RCTDisplayLink.
|
||||
*
|
||||
* TODO(T55504345): Investigate whether we can improve this after TM
|
||||
* rollout.
|
||||
*/
|
||||
if (strongBridge) {
|
||||
[performanceLogger registerRCTTurboModuleForFrameUpdatesStart:moduleName];
|
||||
RCTModuleData *data = [[RCTModuleData alloc] initWithModuleInstance:strongModule bridge:strongBridge];
|
||||
[strongBridge registerModuleForFrameUpdates:strongModule withModuleData:data];
|
||||
[performanceLogger registerRCTTurboModuleForFrameUpdatesEnd:moduleName];
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast that this TurboModule was created.
|
||||
*
|
||||
* TODO(T41180176): Investigate whether we can delete this after TM
|
||||
* rollout.
|
||||
*/
|
||||
[performanceLogger dispatchDidInitializeModuleNotificationForRCTTurboModuleStart:moduleName];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
postNotificationName:RCTDidInitializeModuleNotification
|
||||
object:strongBridge
|
||||
userInfo:@{@"module" : module, @"bridge" : RCTNullIfNil([strongBridge parentBridge])}];
|
||||
[performanceLogger dispatchDidInitializeModuleNotificationForRCTTurboModuleEnd:moduleName];
|
||||
|
||||
[performanceLogger setupRCTTurboModuleEnd:moduleName];
|
||||
};
|
||||
|
||||
/**
|
||||
* TODO(T64991809): Fix TurboModule race:
|
||||
* - When NativeModules that don't require main queue setup are required from different threads, they'll
|
||||
* concurrently run setUpRCTTurboModule:
|
||||
*/
|
||||
if ([[module class] respondsToSelector:@selector(requiresMainQueueSetup)] &&
|
||||
[[module class] requiresMainQueueSetup]) {
|
||||
/**
|
||||
* If the main thread synchronously calls into JS that creates a TurboModule,
|
||||
* we could deadlock. This behaviour is migrated over from the legacy NativeModule
|
||||
* system.
|
||||
*
|
||||
* TODO(T63807674): Investigate the right migration plan off of this
|
||||
*/
|
||||
[_performanceLogger setupRCTTurboModuleDispatch:moduleName];
|
||||
RCTUnsafeExecuteOnMainQueueSync(setUpTurboModule);
|
||||
} else {
|
||||
setUpTurboModule();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)installJSBindingWithRuntime:(jsi::Runtime *)runtime
|
||||
{
|
||||
_runtime = runtime;
|
||||
|
||||
if (!_runtime) {
|
||||
// jsi::Runtime doesn't exist when attached to Chrome debugger.
|
||||
return;
|
||||
}
|
||||
|
||||
__weak __typeof(self) weakSelf = self;
|
||||
|
||||
react::TurboModuleBinding::install(
|
||||
*_runtime,
|
||||
[weakSelf,
|
||||
performanceLogger = _performanceLogger](const std::string &name) -> std::shared_ptr<react::TurboModule> {
|
||||
if (!weakSelf) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
__strong __typeof(self) strongSelf = weakSelf;
|
||||
|
||||
auto moduleName = name.c_str();
|
||||
auto moduleWasNotInitialized = ![strongSelf moduleIsInitialized:moduleName];
|
||||
if (moduleWasNotInitialized) {
|
||||
[strongSelf->_bridge.performanceLogger markStartForTag:RCTPLTurboModuleSetup];
|
||||
}
|
||||
|
||||
[performanceLogger createTurboModuleStart:moduleName];
|
||||
|
||||
/**
|
||||
* By default, all TurboModules are long-lived.
|
||||
* Additionally, if a TurboModule with the name `name` isn't found, then we
|
||||
* trigger an assertion failure.
|
||||
*/
|
||||
auto turboModule = [strongSelf provideTurboModule:moduleName];
|
||||
|
||||
[performanceLogger createTurboModuleEnd:moduleName];
|
||||
|
||||
if (moduleWasNotInitialized && [strongSelf moduleIsInitialized:moduleName]) {
|
||||
[strongSelf->_bridge.performanceLogger markStopForTag:RCTPLTurboModuleSetup];
|
||||
[strongSelf notifyAboutTurboModuleSetup:moduleName];
|
||||
}
|
||||
|
||||
return turboModule;
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark RCTTurboModuleLookupDelegate
|
||||
|
||||
- (id)moduleForName:(const char *)moduleName
|
||||
{
|
||||
return [self moduleForName:moduleName warnOnLookupFailure:YES];
|
||||
}
|
||||
|
||||
- (id)moduleForName:(const char *)moduleName warnOnLookupFailure:(BOOL)warnOnLookupFailure
|
||||
{
|
||||
id<RCTTurboModule> module = [self provideRCTTurboModule:moduleName];
|
||||
|
||||
if (warnOnLookupFailure && !module) {
|
||||
RCTLogError(@"Unable to find module for %@", [NSString stringWithUTF8String:moduleName]);
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
- (BOOL)moduleIsInitialized:(const char *)moduleName
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_rctTurboModuleCacheLock);
|
||||
return _rctTurboModuleCache.find(std::string(moduleName)) != _rctTurboModuleCache.end();
|
||||
}
|
||||
|
||||
#pragma mark Invalidation logic
|
||||
|
||||
- (void)bridgeWillInvalidateModules:(NSNotification *)notification
|
||||
{
|
||||
RCTBridge *bridge = notification.userInfo[@"bridge"];
|
||||
if (bridge != _bridge) {
|
||||
return;
|
||||
}
|
||||
|
||||
_invalidating = true;
|
||||
}
|
||||
|
||||
- (void)bridgeDidInvalidateModules:(NSNotification *)notification
|
||||
{
|
||||
RCTBridge *bridge = notification.userInfo[@"bridge"];
|
||||
if (bridge != _bridge) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, id<RCTTurboModule>> rctCacheCopy;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_rctTurboModuleCacheLock);
|
||||
rctCacheCopy.insert(_rctTurboModuleCache.begin(), _rctTurboModuleCache.end());
|
||||
}
|
||||
|
||||
// Backward-compatibility: RCTInvalidating handling.
|
||||
dispatch_group_t moduleInvalidationGroup = dispatch_group_create();
|
||||
for (const auto &p : rctCacheCopy) {
|
||||
id<RCTTurboModule> module = p.second;
|
||||
if ([module respondsToSelector:@selector(invalidate)]) {
|
||||
if ([module respondsToSelector:@selector(methodQueue)]) {
|
||||
dispatch_queue_t methodQueue = [module performSelector:@selector(methodQueue)];
|
||||
if (methodQueue) {
|
||||
dispatch_group_enter(moduleInvalidationGroup);
|
||||
[bridge
|
||||
dispatchBlock:^{
|
||||
[((id<RCTInvalidating>)module) invalidate];
|
||||
dispatch_group_leave(moduleInvalidationGroup);
|
||||
}
|
||||
queue:methodQueue];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
[((id<RCTInvalidating>)module) invalidate];
|
||||
}
|
||||
}
|
||||
|
||||
if (dispatch_group_wait(moduleInvalidationGroup, dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC))) {
|
||||
RCTLogError(@"TurboModuleManager: Timed out waiting for modules to be invalidated");
|
||||
}
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_rctTurboModuleCacheLock);
|
||||
_rctTurboModuleCache.clear();
|
||||
}
|
||||
|
||||
_turboModuleCache.clear();
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
std::unordered_map<std::string, id<RCTTurboModule>> rctCacheCopy;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_rctTurboModuleCacheLock);
|
||||
rctCacheCopy.insert(_rctTurboModuleCache.begin(), _rctTurboModuleCache.end());
|
||||
}
|
||||
|
||||
// Backward-compatibility: RCTInvalidating handling, but not adhering to desired methodQueue.
|
||||
for (const auto &p : rctCacheCopy) {
|
||||
id<RCTTurboModule> module = p.second;
|
||||
if ([module respondsToSelector:@selector(invalidate)]) {
|
||||
[((id<RCTInvalidating>)module) invalidate];
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_rctTurboModuleCacheLock);
|
||||
_rctTurboModuleCache.clear();
|
||||
}
|
||||
|
||||
_turboModuleCache.clear();
|
||||
}
|
||||
|
||||
@end
|
79
node_modules/react-native/ReactCommon/turbomodule/samples/BUCK
generated
vendored
Normal file
79
node_modules/react-native/ReactCommon/turbomodule/samples/BUCK
generated
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "OBJC_ARC_PREPROCESSOR_FLAGS", "get_preprocessor_flags_for_build_mode", "get_static_library_ios_flags")
|
||||
load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "react_native_target", "react_native_xplat_target", "rn_xplat_cxx_library", "subdir_glob")
|
||||
|
||||
rn_xplat_cxx_library(
|
||||
name = "samples",
|
||||
srcs = glob(["*.cpp"]),
|
||||
header_namespace = "",
|
||||
exported_headers = subdir_glob(
|
||||
[
|
||||
("", "*.h"),
|
||||
],
|
||||
prefix = "ReactCommon",
|
||||
),
|
||||
compiler_flags = [
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
"-std=c++14",
|
||||
"-Wall",
|
||||
],
|
||||
fbandroid_deps = [
|
||||
react_native_target("jni/react/jni:jni"),
|
||||
],
|
||||
fbandroid_exported_headers = subdir_glob(
|
||||
[
|
||||
("platform/android", "*.h"),
|
||||
],
|
||||
prefix = "ReactCommon",
|
||||
),
|
||||
fbandroid_srcs = glob(
|
||||
[
|
||||
"platform/android/**/*.cpp",
|
||||
],
|
||||
),
|
||||
fbobjc_compiler_flags = [
|
||||
"-Wall",
|
||||
"-fobjc-arc-exceptions",
|
||||
],
|
||||
fbobjc_inherited_buck_flags = get_static_library_ios_flags(),
|
||||
fbobjc_preprocessor_flags = OBJC_ARC_PREPROCESSOR_FLAGS + get_preprocessor_flags_for_build_mode(),
|
||||
force_static = True,
|
||||
ios_deps = [
|
||||
"//xplat/FBBaseLite:FBBaseLite",
|
||||
"//xplat/js:RCTLinking",
|
||||
"//xplat/js:RCTPushNotification",
|
||||
"//xplat/js/react-native-github:RCTCxxBridge",
|
||||
"//xplat/js/react-native-github:RCTCxxModule",
|
||||
"//xplat/js/react-native-github:ReactInternal",
|
||||
],
|
||||
ios_exported_headers = subdir_glob(
|
||||
[
|
||||
("platform/ios", "*.h"),
|
||||
],
|
||||
prefix = "ReactCommon",
|
||||
),
|
||||
ios_frameworks = [
|
||||
"$SDKROOT/System/Library/Frameworks/Foundation.framework",
|
||||
],
|
||||
ios_srcs = glob(
|
||||
[
|
||||
"platform/ios/**/*.cpp",
|
||||
"platform/ios/**/*.mm",
|
||||
],
|
||||
),
|
||||
platforms = (ANDROID, APPLE),
|
||||
preprocessor_flags = [
|
||||
"-DLOG_TAG=\"ReactNative\"",
|
||||
"-DWITH_FBSYSTRACE=1",
|
||||
],
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
deps = [
|
||||
react_native_xplat_target("cxxreact:module"),
|
||||
],
|
||||
exported_deps = [
|
||||
"//xplat/jsi:jsi",
|
||||
react_native_xplat_target("turbomodule/core:core"),
|
||||
],
|
||||
)
|
141
node_modules/react-native/ReactCommon/turbomodule/samples/NativeSampleTurboCxxModuleSpecJSI.cpp
generated
vendored
Normal file
141
node_modules/react-native/ReactCommon/turbomodule/samples/NativeSampleTurboCxxModuleSpecJSI.cpp
generated
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "NativeSampleTurboCxxModuleSpecJSI.h"
|
||||
|
||||
// NOTE: This entire file should be codegen'ed.
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
static jsi::Value __hostFunction_NativeSampleTurboCxxModuleSpecJSI_voidFunc(
|
||||
jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
static_cast<NativeSampleTurboCxxModuleSpecJSI *>(&turboModule)->voidFunc(rt);
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
|
||||
static jsi::Value __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getBool(
|
||||
jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
return jsi::Value(
|
||||
static_cast<NativeSampleTurboCxxModuleSpecJSI *>(&turboModule)
|
||||
->getBool(rt, args[0].getBool()));
|
||||
}
|
||||
|
||||
static jsi::Value __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getNumber(
|
||||
jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
return jsi::Value(
|
||||
static_cast<NativeSampleTurboCxxModuleSpecJSI *>(&turboModule)
|
||||
->getNumber(rt, args[0].getNumber()));
|
||||
}
|
||||
|
||||
static jsi::Value __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getString(
|
||||
jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
return static_cast<NativeSampleTurboCxxModuleSpecJSI *>(&turboModule)
|
||||
->getString(rt, args[0].getString(rt));
|
||||
}
|
||||
|
||||
static jsi::Value __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getArray(
|
||||
jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
return static_cast<NativeSampleTurboCxxModuleSpecJSI *>(&turboModule)
|
||||
->getArray(rt, args[0].getObject(rt).getArray(rt));
|
||||
}
|
||||
|
||||
static jsi::Value __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getObject(
|
||||
jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
return static_cast<NativeSampleTurboCxxModuleSpecJSI *>(&turboModule)
|
||||
->getObject(rt, args[0].getObject(rt));
|
||||
}
|
||||
|
||||
static jsi::Value __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getValue(
|
||||
jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
return static_cast<NativeSampleTurboCxxModuleSpecJSI *>(&turboModule)
|
||||
->getValue(
|
||||
rt,
|
||||
args[0].getNumber(),
|
||||
args[1].getString(rt),
|
||||
args[2].getObject(rt));
|
||||
}
|
||||
|
||||
static jsi::Value
|
||||
__hostFunction_NativeSampleTurboCxxModuleSpecJSI_getValueWithCallback(
|
||||
jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
static_cast<NativeSampleTurboCxxModuleSpecJSI *>(&turboModule)
|
||||
->getValueWithCallback(
|
||||
rt, std::move(args[0].getObject(rt).getFunction(rt)));
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
|
||||
static jsi::Value
|
||||
__hostFunction_NativeSampleTurboCxxModuleSpecJSI_getValueWithPromise(
|
||||
jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
return static_cast<NativeSampleTurboCxxModuleSpecJSI *>(&turboModule)
|
||||
->getValueWithPromise(rt, args[0].getBool());
|
||||
}
|
||||
|
||||
static jsi::Value __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getConstants(
|
||||
jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const jsi::Value *args,
|
||||
size_t count) {
|
||||
return static_cast<NativeSampleTurboCxxModuleSpecJSI *>(&turboModule)
|
||||
->getConstants(rt);
|
||||
}
|
||||
|
||||
NativeSampleTurboCxxModuleSpecJSI::NativeSampleTurboCxxModuleSpecJSI(
|
||||
std::shared_ptr<CallInvoker> jsInvoker)
|
||||
: TurboModule("SampleTurboCxxModule", jsInvoker) {
|
||||
methodMap_["voidFunc"] = MethodMetadata{
|
||||
0, __hostFunction_NativeSampleTurboCxxModuleSpecJSI_voidFunc};
|
||||
methodMap_["getBool"] = MethodMetadata{
|
||||
1, __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getBool};
|
||||
methodMap_["getNumber"] = MethodMetadata{
|
||||
1, __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getNumber};
|
||||
methodMap_["getString"] = MethodMetadata{
|
||||
1, __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getString};
|
||||
methodMap_["getArray"] = MethodMetadata{
|
||||
1, __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getArray};
|
||||
methodMap_["getObject"] = MethodMetadata{
|
||||
1, __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getObject};
|
||||
methodMap_["getValue"] = MethodMetadata{
|
||||
3, __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getValue};
|
||||
methodMap_["getValueWithCallback"] = MethodMetadata{
|
||||
1, __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getValueWithCallback};
|
||||
methodMap_["getValueWithPromise"] = MethodMetadata{
|
||||
1, __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getValueWithPromise};
|
||||
methodMap_["getConstants"] = MethodMetadata{
|
||||
0, __hostFunction_NativeSampleTurboCxxModuleSpecJSI_getConstants};
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
43
node_modules/react-native/ReactCommon/turbomodule/samples/NativeSampleTurboCxxModuleSpecJSI.h
generated
vendored
Normal file
43
node_modules/react-native/ReactCommon/turbomodule/samples/NativeSampleTurboCxxModuleSpecJSI.h
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <ReactCommon/TurboModule.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
// TODO: This definition should be codegen'ed for type-safety purpose.
|
||||
class JSI_EXPORT NativeSampleTurboCxxModuleSpecJSI : public TurboModule {
|
||||
protected:
|
||||
NativeSampleTurboCxxModuleSpecJSI(std::shared_ptr<CallInvoker> jsInvoker);
|
||||
|
||||
public:
|
||||
virtual void voidFunc(jsi::Runtime &rt) = 0;
|
||||
virtual bool getBool(jsi::Runtime &rt, bool arg) = 0;
|
||||
virtual double getNumber(jsi::Runtime &rt, double arg) = 0;
|
||||
virtual jsi::String getString(jsi::Runtime &rt, const jsi::String &arg) = 0;
|
||||
virtual jsi::Array getArray(jsi::Runtime &rt, const jsi::Array &arg) = 0;
|
||||
virtual jsi::Object getObject(jsi::Runtime &rt, const jsi::Object &arg) = 0;
|
||||
virtual jsi::Object getValue(
|
||||
jsi::Runtime &rt,
|
||||
double x,
|
||||
const jsi::String &y,
|
||||
const jsi::Object &z) = 0;
|
||||
virtual void getValueWithCallback(
|
||||
jsi::Runtime &rt,
|
||||
const jsi::Function &callback) = 0;
|
||||
virtual jsi::Value getValueWithPromise(jsi::Runtime &rt, bool error) = 0;
|
||||
virtual jsi::Object getConstants(jsi::Runtime &rt) = 0;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
94
node_modules/react-native/ReactCommon/turbomodule/samples/SampleTurboCxxModule.cpp
generated
vendored
Normal file
94
node_modules/react-native/ReactCommon/turbomodule/samples/SampleTurboCxxModule.cpp
generated
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "SampleTurboCxxModule.h"
|
||||
|
||||
#import <ReactCommon/TurboModuleUtils.h>
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
SampleTurboCxxModule::SampleTurboCxxModule(
|
||||
std::shared_ptr<CallInvoker> jsInvoker)
|
||||
: NativeSampleTurboCxxModuleSpecJSI(jsInvoker) {}
|
||||
|
||||
void SampleTurboCxxModule::voidFunc(jsi::Runtime &rt) {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
bool SampleTurboCxxModule::getBool(jsi::Runtime &rt, bool arg) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
double SampleTurboCxxModule::getNumber(jsi::Runtime &rt, double arg) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
jsi::String SampleTurboCxxModule::getString(
|
||||
jsi::Runtime &rt,
|
||||
const jsi::String &arg) {
|
||||
return jsi::String::createFromUtf8(rt, arg.utf8(rt));
|
||||
}
|
||||
|
||||
jsi::Array SampleTurboCxxModule::getArray(
|
||||
jsi::Runtime &rt,
|
||||
const jsi::Array &arg) {
|
||||
return deepCopyJSIArray(rt, arg);
|
||||
}
|
||||
|
||||
jsi::Object SampleTurboCxxModule::getObject(
|
||||
jsi::Runtime &rt,
|
||||
const jsi::Object &arg) {
|
||||
return deepCopyJSIObject(rt, arg);
|
||||
}
|
||||
|
||||
jsi::Object SampleTurboCxxModule::getValue(
|
||||
jsi::Runtime &rt,
|
||||
double x,
|
||||
const jsi::String &y,
|
||||
const jsi::Object &z) {
|
||||
// Note: return type isn't type-safe.
|
||||
jsi::Object result(rt);
|
||||
result.setProperty(rt, "x", jsi::Value(x));
|
||||
result.setProperty(rt, "y", jsi::String::createFromUtf8(rt, y.utf8(rt)));
|
||||
result.setProperty(rt, "z", deepCopyJSIObject(rt, z));
|
||||
return result;
|
||||
}
|
||||
|
||||
void SampleTurboCxxModule::getValueWithCallback(
|
||||
jsi::Runtime &rt,
|
||||
const jsi::Function &callback) {
|
||||
callback.call(rt, jsi::String::createFromUtf8(rt, "value from callback!"));
|
||||
}
|
||||
|
||||
jsi::Value SampleTurboCxxModule::getValueWithPromise(
|
||||
jsi::Runtime &rt,
|
||||
bool error) {
|
||||
return createPromiseAsJSIValue(
|
||||
rt, [error](jsi::Runtime &rt2, std::shared_ptr<Promise> promise) {
|
||||
if (error) {
|
||||
promise->reject("intentional promise rejection");
|
||||
} else {
|
||||
promise->resolve(jsi::String::createFromUtf8(rt2, "result!"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
jsi::Object SampleTurboCxxModule::getConstants(jsi::Runtime &rt) {
|
||||
// Note: return type isn't type-safe.
|
||||
jsi::Object result(rt);
|
||||
result.setProperty(rt, "const1", jsi::Value(true));
|
||||
result.setProperty(rt, "const2", jsi::Value(375));
|
||||
result.setProperty(
|
||||
rt, "const3", jsi::String::createFromUtf8(rt, "something"));
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
44
node_modules/react-native/ReactCommon/turbomodule/samples/SampleTurboCxxModule.h
generated
vendored
Normal file
44
node_modules/react-native/ReactCommon/turbomodule/samples/SampleTurboCxxModule.h
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#import <memory>
|
||||
|
||||
#import "NativeSampleTurboCxxModuleSpecJSI.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/**
|
||||
* A sample implementation of the C++ spec. In practice, this class can just
|
||||
* extend jsi::HostObject directly, but using the spec provides build-time
|
||||
* type-safety.
|
||||
*/
|
||||
class SampleTurboCxxModule : public NativeSampleTurboCxxModuleSpecJSI {
|
||||
public:
|
||||
SampleTurboCxxModule(std::shared_ptr<CallInvoker> jsInvoker);
|
||||
|
||||
void voidFunc(jsi::Runtime &rt) override;
|
||||
bool getBool(jsi::Runtime &rt, bool arg) override;
|
||||
double getNumber(jsi::Runtime &rt, double arg) override;
|
||||
jsi::String getString(jsi::Runtime &rt, const jsi::String &arg) override;
|
||||
jsi::Array getArray(jsi::Runtime &rt, const jsi::Array &arg) override;
|
||||
jsi::Object getObject(jsi::Runtime &rt, const jsi::Object &arg) override;
|
||||
jsi::Object getValue(
|
||||
jsi::Runtime &rt,
|
||||
double x,
|
||||
const jsi::String &y,
|
||||
const jsi::Object &z) override;
|
||||
void getValueWithCallback(jsi::Runtime &rt, const jsi::Function &callback)
|
||||
override;
|
||||
jsi::Value getValueWithPromise(jsi::Runtime &rt, bool error) override;
|
||||
jsi::Object getConstants(jsi::Runtime &rt) override;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
53
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.h
generated
vendored
Normal file
53
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.h
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
// NOTE: This entire file should be codegen'ed.
|
||||
|
||||
#import <vector>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <React/RCTBridgeModule.h>
|
||||
|
||||
#import <ReactCommon/RCTTurboModule.h>
|
||||
|
||||
/**
|
||||
* The ObjC protocol based on the JS Flow type for SampleTurboModule.
|
||||
*/
|
||||
@protocol NativeSampleTurboModuleSpec <RCTBridgeModule, RCTTurboModule>
|
||||
|
||||
- (void)voidFunc;
|
||||
- (NSNumber *)getBool:(BOOL)arg;
|
||||
- (NSNumber *)getNumber:(double)arg;
|
||||
- (NSString *)getString:(NSString *)arg;
|
||||
- (NSArray<id<NSObject>> *)getArray:(NSArray *)arg;
|
||||
- (NSDictionary *)getObject:(NSDictionary *)arg;
|
||||
- (NSDictionary *)getValue:(double)x y:(NSString *)y z:(NSDictionary *)z;
|
||||
- (void)getValueWithCallback:(RCTResponseSenderBlock)callback;
|
||||
- (void)getValueWithPromise:(BOOL)error resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject;
|
||||
- (NSDictionary *)constantsToExport;
|
||||
- (NSDictionary *)getConstants;
|
||||
|
||||
@end
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/**
|
||||
* The iOS TurboModule impl specific to SampleTurboModule.
|
||||
*/
|
||||
class JSI_EXPORT NativeSampleTurboModuleSpecJSI : public ObjCTurboModule {
|
||||
public:
|
||||
NativeSampleTurboModuleSpecJSI(
|
||||
id<RCTTurboModule> instance,
|
||||
std::shared_ptr<CallInvoker> jsInvoker,
|
||||
std::shared_ptr<CallInvoker> nativeInvoker,
|
||||
id<RCTTurboModulePerformanceLogger> perfLogger);
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
136
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.mm
generated
vendored
Normal file
136
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/RCTNativeSampleTurboModuleSpec.mm
generated
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTNativeSampleTurboModuleSpec.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc(
|
||||
facebook::jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const facebook::jsi::Value *args,
|
||||
size_t count)
|
||||
{
|
||||
return static_cast<ObjCTurboModule &>(turboModule)
|
||||
.invokeObjCMethod(rt, VoidKind, "voidFunc", @selector(voidFunc), args, count);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getBool(
|
||||
facebook::jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const facebook::jsi::Value *args,
|
||||
size_t count)
|
||||
{
|
||||
return static_cast<ObjCTurboModule &>(turboModule)
|
||||
.invokeObjCMethod(rt, BooleanKind, "getBool", @selector(getBool:), args, count);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber(
|
||||
facebook::jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const facebook::jsi::Value *args,
|
||||
size_t count)
|
||||
{
|
||||
return static_cast<ObjCTurboModule &>(turboModule)
|
||||
.invokeObjCMethod(rt, NumberKind, "getNumber", @selector(getNumber:), args, count);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getString(
|
||||
facebook::jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const facebook::jsi::Value *args,
|
||||
size_t count)
|
||||
{
|
||||
return static_cast<ObjCTurboModule &>(turboModule)
|
||||
.invokeObjCMethod(rt, StringKind, "getString", @selector(getString:), args, count);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getArray(
|
||||
facebook::jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const facebook::jsi::Value *args,
|
||||
size_t count)
|
||||
{
|
||||
return static_cast<ObjCTurboModule &>(turboModule)
|
||||
.invokeObjCMethod(rt, ArrayKind, "getArray", @selector(getArray:), args, count);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getObject(
|
||||
facebook::jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const facebook::jsi::Value *args,
|
||||
size_t count)
|
||||
{
|
||||
return static_cast<ObjCTurboModule &>(turboModule)
|
||||
.invokeObjCMethod(rt, ObjectKind, "getObject", @selector(getObject:), args, count);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValue(
|
||||
facebook::jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const facebook::jsi::Value *args,
|
||||
size_t count)
|
||||
{
|
||||
return static_cast<ObjCTurboModule &>(turboModule)
|
||||
.invokeObjCMethod(rt, ObjectKind, "getValue", @selector(getValue:y:z:), args, count);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback(
|
||||
facebook::jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const facebook::jsi::Value *args,
|
||||
size_t count)
|
||||
{
|
||||
return static_cast<ObjCTurboModule &>(turboModule)
|
||||
.invokeObjCMethod(rt, VoidKind, "getValueWithCallback", @selector(getValueWithCallback:), args, count);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise(
|
||||
facebook::jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const facebook::jsi::Value *args,
|
||||
size_t count)
|
||||
{
|
||||
return static_cast<ObjCTurboModule &>(turboModule)
|
||||
.invokeObjCMethod(
|
||||
rt, PromiseKind, "getValueWithPromise", @selector(getValueWithPromise:resolve:reject:), args, count);
|
||||
}
|
||||
|
||||
static facebook::jsi::Value __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants(
|
||||
facebook::jsi::Runtime &rt,
|
||||
TurboModule &turboModule,
|
||||
const facebook::jsi::Value *args,
|
||||
size_t count)
|
||||
{
|
||||
return static_cast<ObjCTurboModule &>(turboModule)
|
||||
.invokeObjCMethod(rt, ObjectKind, "getConstants", @selector(getConstants), args, count);
|
||||
}
|
||||
|
||||
NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(
|
||||
id<RCTTurboModule> instance,
|
||||
std::shared_ptr<CallInvoker> jsInvoker,
|
||||
std::shared_ptr<CallInvoker> nativeInvoker,
|
||||
id<RCTTurboModulePerformanceLogger> perfLogger)
|
||||
: ObjCTurboModule("SampleTurboModule", instance, jsInvoker, nativeInvoker, perfLogger)
|
||||
{
|
||||
methodMap_["voidFunc"] = MethodMetadata{0, __hostFunction_NativeSampleTurboModuleSpecJSI_voidFunc};
|
||||
methodMap_["getBool"] = MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getBool};
|
||||
methodMap_["getNumber"] = MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getNumber};
|
||||
methodMap_["getString"] = MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getString};
|
||||
methodMap_["getArray"] = MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArray};
|
||||
methodMap_["getObject"] = MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getObject};
|
||||
methodMap_["getValue"] = MethodMetadata{3, __hostFunction_NativeSampleTurboModuleSpecJSI_getValue};
|
||||
methodMap_["getValueWithCallback"] =
|
||||
MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithCallback};
|
||||
methodMap_["getValueWithPromise"] =
|
||||
MethodMetadata{1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise};
|
||||
methodMap_["getConstants"] = MethodMetadata{0, __hostFunction_NativeSampleTurboModuleSpecJSI_getConstants};
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
27
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboCxxModule.h
generated
vendored
Normal file
27
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboCxxModule.h
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#import <React/RCTCxxModule.h>
|
||||
#import <ReactCommon/RCTTurboModule.h>
|
||||
|
||||
/**
|
||||
* Sample backward-compatible RCTCxxModule-based module.
|
||||
* With jsi::HostObject, this class is no longer necessary, but the system supports it for
|
||||
* backward compatibility.
|
||||
*/
|
||||
@interface RCTSampleTurboCxxModule_v1 : RCTCxxModule <RCTTurboModule>
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* Second variant of a sample backward-compatible RCTCxxModule-based module.
|
||||
*/
|
||||
@interface RCTSampleTurboCxxModule_v2 : RCTCxxModule <RCTTurboModule>
|
||||
|
||||
@end
|
42
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboCxxModule.mm
generated
vendored
Normal file
42
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboCxxModule.mm
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTSampleTurboCxxModule.h"
|
||||
|
||||
#import <ReactCommon/SampleTurboCxxModule.h>
|
||||
#import <cxxreact/CxxModule.h>
|
||||
#import "SampleTurboCxxModuleLegacyImpl.h"
|
||||
|
||||
using namespace facebook;
|
||||
|
||||
// ObjC++ wrapper.
|
||||
@implementation RCTSampleTurboCxxModule_v1
|
||||
|
||||
RCT_EXPORT_MODULE();
|
||||
|
||||
- (std::shared_ptr<react::TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<react::CallInvoker>)jsInvoker
|
||||
{
|
||||
return std::make_shared<react::SampleTurboCxxModule>(jsInvoker);
|
||||
}
|
||||
|
||||
- (std::unique_ptr<xplat::module::CxxModule>)createModule
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTSampleTurboCxxModule_v2
|
||||
|
||||
RCT_EXPORT_MODULE();
|
||||
|
||||
- (std::unique_ptr<xplat::module::CxxModule>)createModule
|
||||
{
|
||||
return std::make_unique<react::SampleTurboCxxModuleLegacyImpl>();
|
||||
}
|
||||
|
||||
@end
|
18
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboModule.h
generated
vendored
Normal file
18
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboModule.h
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RCTNativeSampleTurboModuleSpec.h"
|
||||
|
||||
/**
|
||||
* Sample iOS-specific impl of a TurboModule, conforming to the spec protocol.
|
||||
* This class is also 100% compatible with the NativeModule system.
|
||||
*/
|
||||
@interface RCTSampleTurboModule : NSObject <NativeSampleTurboModuleSpec>
|
||||
|
||||
@end
|
132
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboModule.mm
generated
vendored
Normal file
132
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/RCTSampleTurboModule.mm
generated
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import "RCTSampleTurboModule.h"
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@implementation RCTSampleTurboModule
|
||||
|
||||
// Backward-compatible export
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
@synthesize turboModuleLookupDelegate = _turboModuleLookupDelegate;
|
||||
|
||||
// Backward-compatible queue configuration
|
||||
+ (BOOL)requiresMainQueueSetup
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return dispatch_get_main_queue();
|
||||
}
|
||||
|
||||
- (std::shared_ptr<facebook::react::TurboModule>)
|
||||
getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
|
||||
nativeInvoker:(std::shared_ptr<facebook::react::CallInvoker>)nativeInvoker
|
||||
perfLogger:(id<RCTTurboModulePerformanceLogger>)perfLogger
|
||||
{
|
||||
return std::make_shared<NativeSampleTurboModuleSpecJSI>(self, jsInvoker, nativeInvoker, perfLogger);
|
||||
}
|
||||
|
||||
// Backward compatible invalidation
|
||||
- (void)invalidate
|
||||
{
|
||||
// Actually do nothing here.
|
||||
NSLog(@"Invalidating RCTSampleTurboModule...");
|
||||
}
|
||||
|
||||
- (NSDictionary *)getConstants
|
||||
{
|
||||
UIScreen *mainScreen = UIScreen.mainScreen;
|
||||
CGSize screenSize = mainScreen.bounds.size;
|
||||
|
||||
return @{
|
||||
@"const1" : @YES,
|
||||
@"const2" : @(screenSize.width),
|
||||
@"const3" : @"something",
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: Remove once fully migrated to TurboModule.
|
||||
- (NSDictionary *)constantsToExport
|
||||
{
|
||||
return [self getConstants];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(voidFunc)
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSNumber *, getBool : (BOOL)arg)
|
||||
{
|
||||
return @(arg);
|
||||
}
|
||||
|
||||
RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSNumber *, getNumber : (double)arg)
|
||||
{
|
||||
return @(arg);
|
||||
}
|
||||
|
||||
RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSString *, getString : (NSString *)arg)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
|
||||
RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSArray<id<NSObject>> *, getArray : (NSArray *)arg)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
|
||||
RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSDictionary *, getObject : (NSDictionary *)arg)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
|
||||
RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSDictionary *, getValue : (double)x y : (NSString *)y z : (NSDictionary *)z)
|
||||
{
|
||||
return @{
|
||||
@"x" : @(x),
|
||||
@"y" : y ?: [NSNull null],
|
||||
@"z" : z ?: [NSNull null],
|
||||
};
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getValueWithCallback : (RCTResponseSenderBlock)callback)
|
||||
{
|
||||
if (!callback) {
|
||||
return;
|
||||
}
|
||||
callback(@[ @"value from callback!" ]);
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getValueWithPromise
|
||||
: (BOOL)error resolve
|
||||
: (RCTPromiseResolveBlock)resolve reject
|
||||
: (RCTPromiseRejectBlock)reject)
|
||||
{
|
||||
if (!resolve || !reject) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
reject(
|
||||
@"code_1",
|
||||
@"intentional promise rejection",
|
||||
[NSError errorWithDomain:@"RCTSampleTurboModule" code:1 userInfo:nil]);
|
||||
} else {
|
||||
resolve(@"result!");
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
148
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.cpp
generated
vendored
Normal file
148
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.cpp
generated
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "SampleTurboCxxModuleLegacyImpl.h"
|
||||
|
||||
#include <cxxreact/JsArgumentHelpers.h>
|
||||
|
||||
using namespace facebook::xplat::module;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
SampleTurboCxxModuleLegacyImpl::SampleTurboCxxModuleLegacyImpl() {}
|
||||
|
||||
std::string SampleTurboCxxModuleLegacyImpl::getName() {
|
||||
return "SampleTurboCxxModule_v2";
|
||||
}
|
||||
|
||||
std::map<std::string, folly::dynamic>
|
||||
SampleTurboCxxModuleLegacyImpl::getConstants() {
|
||||
return {
|
||||
{"const1", true},
|
||||
{"const2", 375},
|
||||
{"const3", "something"},
|
||||
};
|
||||
};
|
||||
|
||||
std::vector<CxxModule::Method> SampleTurboCxxModuleLegacyImpl::getMethods() {
|
||||
return {
|
||||
CxxModule::Method(
|
||||
"voidFunc", [this](folly::dynamic args) { voidFunc(); }),
|
||||
CxxModule::Method(
|
||||
"getBool",
|
||||
[this](folly::dynamic args) {
|
||||
return getBool(xplat::jsArgAsBool(args, 0));
|
||||
},
|
||||
CxxModule::SyncTag),
|
||||
CxxModule::Method(
|
||||
"getNumber",
|
||||
[this](folly::dynamic args) {
|
||||
return getNumber(xplat::jsArgAsDouble(args, 0));
|
||||
},
|
||||
CxxModule::SyncTag),
|
||||
CxxModule::Method(
|
||||
"getString",
|
||||
[this](folly::dynamic args) {
|
||||
return getString(xplat::jsArgAsString(args, 0));
|
||||
},
|
||||
CxxModule::SyncTag),
|
||||
CxxModule::Method(
|
||||
"getString",
|
||||
[this](folly::dynamic args) {
|
||||
return getString(xplat::jsArgAsString(args, 0));
|
||||
},
|
||||
CxxModule::SyncTag),
|
||||
CxxModule::Method(
|
||||
"getArray",
|
||||
[this](folly::dynamic args) {
|
||||
return getArray(xplat::jsArgAsArray(args, 0));
|
||||
},
|
||||
CxxModule::SyncTag),
|
||||
CxxModule::Method(
|
||||
"getObject",
|
||||
[this](folly::dynamic args) {
|
||||
return getObject(xplat::jsArgAsObject(args, 0));
|
||||
},
|
||||
CxxModule::SyncTag),
|
||||
CxxModule::Method(
|
||||
"getValue",
|
||||
[this](folly::dynamic args) {
|
||||
return getValue(
|
||||
xplat::jsArgAsDouble(args, 0),
|
||||
xplat::jsArgAsString(args, 1),
|
||||
xplat::jsArgAsObject(args, 2));
|
||||
},
|
||||
CxxModule::SyncTag),
|
||||
CxxModule::Method(
|
||||
"getValueWithCallback",
|
||||
[this](folly::dynamic args, CxxModule::Callback callback) {
|
||||
getValueWithCallback(callback);
|
||||
}),
|
||||
CxxModule::Method(
|
||||
"getValueWithPromise",
|
||||
[this](
|
||||
folly::dynamic args,
|
||||
CxxModule::Callback resolve,
|
||||
CxxModule::Callback reject) {
|
||||
getValueWithPromise(xplat::jsArgAsBool(args, 0), resolve, reject);
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
void SampleTurboCxxModuleLegacyImpl::voidFunc() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
bool SampleTurboCxxModuleLegacyImpl::getBool(bool arg) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
double SampleTurboCxxModuleLegacyImpl::getNumber(double arg) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
std::string SampleTurboCxxModuleLegacyImpl::getString(const std::string &arg) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
folly::dynamic SampleTurboCxxModuleLegacyImpl::getArray(
|
||||
const folly::dynamic &arg) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
folly::dynamic SampleTurboCxxModuleLegacyImpl::getObject(
|
||||
const folly::dynamic &arg) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
folly::dynamic SampleTurboCxxModuleLegacyImpl::getValue(
|
||||
double x,
|
||||
const std::string &y,
|
||||
const folly::dynamic &z) {
|
||||
return folly::dynamic::object("x", x)("y", y)("z", z);
|
||||
}
|
||||
|
||||
void SampleTurboCxxModuleLegacyImpl::getValueWithCallback(
|
||||
const CxxModule::Callback &callback) {
|
||||
callback({"value from callback!"});
|
||||
}
|
||||
|
||||
void SampleTurboCxxModuleLegacyImpl::getValueWithPromise(
|
||||
bool error,
|
||||
const CxxModule::Callback &resolve,
|
||||
const CxxModule::Callback &reject) {
|
||||
if (!error) {
|
||||
resolve({"result!"});
|
||||
} else {
|
||||
reject(
|
||||
{folly::dynamic::object("message", "intentional promise rejection")});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
45
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.h
generated
vendored
Normal file
45
node_modules/react-native/ReactCommon/turbomodule/samples/platform/ios/SampleTurboCxxModuleLegacyImpl.h
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#import <cxxreact/CxxModule.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/**
|
||||
* A sample CxxModule (legacy system) implementation.
|
||||
*/
|
||||
class SampleTurboCxxModuleLegacyImpl
|
||||
: public facebook::xplat::module::CxxModule {
|
||||
public:
|
||||
SampleTurboCxxModuleLegacyImpl();
|
||||
|
||||
std::string getName() override;
|
||||
std::map<std::string, folly::dynamic> getConstants() override;
|
||||
std::vector<facebook::xplat::module::CxxModule::Method> getMethods() override;
|
||||
|
||||
// API
|
||||
void voidFunc();
|
||||
bool getBool(bool arg);
|
||||
double getNumber(double arg);
|
||||
std::string getString(const std::string &arg);
|
||||
folly::dynamic getArray(const folly::dynamic &arg);
|
||||
folly::dynamic getObject(const folly::dynamic &arg);
|
||||
folly::dynamic
|
||||
getValue(double x, const std::string &y, const folly::dynamic &z);
|
||||
void getValueWithCallback(
|
||||
const facebook::xplat::module::CxxModule::Callback &callback);
|
||||
void getValueWithPromise(
|
||||
bool error,
|
||||
const facebook::xplat::module::CxxModule::Callback &resolve,
|
||||
const facebook::xplat::module::CxxModule::Callback &reject);
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
Reference in New Issue
Block a user