yeet
This commit is contained in:
5
node_modules/react-native/ReactCommon/cxxreact/.clang-tidy
generated
vendored
Normal file
5
node_modules/react-native/ReactCommon/cxxreact/.clang-tidy
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
Checks: '>
|
||||
clang-diagnostic-*,
|
||||
'
|
||||
...
|
34
node_modules/react-native/ReactCommon/cxxreact/Android.mk
generated
vendored
Normal file
34
node_modules/react-native/ReactCommon/cxxreact/Android.mk
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
# 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.
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := reactnative
|
||||
|
||||
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp)
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/..
|
||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
|
||||
|
||||
LOCAL_CFLAGS := \
|
||||
-DLOG_TAG=\"ReactNative\"
|
||||
|
||||
LOCAL_CFLAGS += -fexceptions -frtti -Wno-unused-lambda-capture
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := boost jsi callinvoker
|
||||
LOCAL_SHARED_LIBRARIES := jsinspector libfolly_json glog
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
$(call import-module,fb)
|
||||
$(call import-module,folly)
|
||||
$(call import-module,callinvoker)
|
||||
$(call import-module,jsc)
|
||||
$(call import-module,glog)
|
||||
$(call import-module,jsi)
|
||||
$(call import-module,jsinspector)
|
||||
$(call import-module,hermes/inspector)
|
157
node_modules/react-native/ReactCommon/cxxreact/BUCK
generated
vendored
Normal file
157
node_modules/react-native/ReactCommon/cxxreact/BUCK
generated
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
load("@fbsource//tools/build_defs:glob_defs.bzl", "subdir_glob")
|
||||
load("//tools/build_defs/oss:rn_defs.bzl", "ANDROID", "APPLE", "get_android_inspector_flags", "get_apple_compiler_flags", "get_apple_inspector_flags", "get_preprocessor_flags_for_build_mode", "react_native_xplat_target", "rn_xplat_cxx_library")
|
||||
|
||||
CXX_LIBRARY_COMPILER_FLAGS = [
|
||||
"-std=c++14",
|
||||
"-Wall",
|
||||
]
|
||||
|
||||
rn_xplat_cxx_library(
|
||||
name = "module",
|
||||
header_namespace = "",
|
||||
exported_headers = subdir_glob(
|
||||
[
|
||||
("", "CxxModule.h"),
|
||||
("", "JsArgumentHelpers.h"),
|
||||
("", "JsArgumentHelpers-inl.h"),
|
||||
],
|
||||
prefix = "cxxreact",
|
||||
),
|
||||
compiler_flags = CXX_LIBRARY_COMPILER_FLAGS,
|
||||
fbobjc_compiler_flags = get_apple_compiler_flags(),
|
||||
fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"],
|
||||
force_static = True,
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
deps = [
|
||||
"//xplat/folly:molly",
|
||||
],
|
||||
)
|
||||
|
||||
rn_xplat_cxx_library(
|
||||
name = "jsbigstring",
|
||||
srcs = [
|
||||
"JSBigString.cpp",
|
||||
],
|
||||
header_namespace = "",
|
||||
exported_headers = subdir_glob(
|
||||
[("", "JSBigString.h")],
|
||||
prefix = "cxxreact",
|
||||
),
|
||||
compiler_flags = CXX_LIBRARY_COMPILER_FLAGS + [
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
],
|
||||
fbobjc_compiler_flags = get_apple_compiler_flags(),
|
||||
fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"],
|
||||
force_static = True,
|
||||
preprocessor_flags = [
|
||||
"-DWITH_FBREMAP=1",
|
||||
],
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
deps = [
|
||||
"//xplat/folly:memory",
|
||||
"//xplat/folly:molly",
|
||||
"//xplat/folly:scope_guard",
|
||||
],
|
||||
)
|
||||
|
||||
rn_xplat_cxx_library(
|
||||
name = "samplemodule",
|
||||
srcs = ["SampleCxxModule.cpp"],
|
||||
header_namespace = "",
|
||||
exported_headers = ["SampleCxxModule.h"],
|
||||
compiler_flags = CXX_LIBRARY_COMPILER_FLAGS + [
|
||||
"-fno-omit-frame-pointer",
|
||||
"-fexceptions",
|
||||
],
|
||||
fbobjc_compiler_flags = get_apple_compiler_flags(),
|
||||
soname = "libxplat_react_module_samplemodule.$(ext)",
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
deps = [
|
||||
":module",
|
||||
"//xplat/folly:memory",
|
||||
"//xplat/folly:molly",
|
||||
"//xplat/third-party/glog:glog",
|
||||
],
|
||||
)
|
||||
|
||||
CXXREACT_PUBLIC_HEADERS = [
|
||||
"CxxNativeModule.h",
|
||||
"Instance.h",
|
||||
"JSBundleType.h",
|
||||
"JSDeltaBundleClient.h",
|
||||
"JSExecutor.h",
|
||||
"JSIndexedRAMBundle.h",
|
||||
"JSModulesUnbundle.h",
|
||||
"MessageQueueThread.h",
|
||||
"MethodCall.h",
|
||||
"ModuleRegistry.h",
|
||||
"NativeModule.h",
|
||||
"NativeToJsBridge.h",
|
||||
"RAMBundleRegistry.h",
|
||||
"ReactMarker.h",
|
||||
"RecoverableError.h",
|
||||
"SharedProxyCxxModule.h",
|
||||
"SystraceSection.h",
|
||||
]
|
||||
|
||||
rn_xplat_cxx_library(
|
||||
name = "bridge",
|
||||
srcs = glob(
|
||||
["*.cpp"],
|
||||
exclude = [
|
||||
"JSBigString.cpp",
|
||||
"SampleCxxModule.cpp",
|
||||
],
|
||||
),
|
||||
headers = glob(
|
||||
["*.h"],
|
||||
exclude = CXXREACT_PUBLIC_HEADERS,
|
||||
),
|
||||
header_namespace = "",
|
||||
exported_headers = dict([
|
||||
(
|
||||
"cxxreact/%s" % header,
|
||||
header,
|
||||
)
|
||||
for header in CXXREACT_PUBLIC_HEADERS
|
||||
]),
|
||||
compiler_flags = CXX_LIBRARY_COMPILER_FLAGS + [
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
],
|
||||
fbandroid_preprocessor_flags = get_android_inspector_flags(),
|
||||
fbobjc_compiler_flags = get_apple_compiler_flags(),
|
||||
fbobjc_force_static = True,
|
||||
fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"],
|
||||
fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(),
|
||||
macosx_tests_override = [],
|
||||
platforms = (ANDROID, APPLE),
|
||||
preprocessor_flags = [
|
||||
"-DLOG_TAG=\"ReactNative\"",
|
||||
"-DWITH_FBSYSTRACE=1",
|
||||
],
|
||||
tests = [
|
||||
react_native_xplat_target("cxxreact/tests:tests"),
|
||||
],
|
||||
visibility = ["PUBLIC"],
|
||||
deps = [
|
||||
":jsbigstring",
|
||||
":module",
|
||||
"//xplat/fbsystrace:fbsystrace",
|
||||
"//xplat/folly:headers_only",
|
||||
"//xplat/folly:memory",
|
||||
"//xplat/folly:molly",
|
||||
react_native_xplat_target("callinvoker:callinvoker"),
|
||||
react_native_xplat_target("jsinspector:jsinspector"),
|
||||
react_native_xplat_target("microprofiler:microprofiler"),
|
||||
"//xplat/folly:optional",
|
||||
"//xplat/third-party/glog:glog",
|
||||
],
|
||||
)
|
258
node_modules/react-native/ReactCommon/cxxreact/CxxModule.h
generated
vendored
Normal file
258
node_modules/react-native/ReactCommon/cxxreact/CxxModule.h
generated
vendored
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
* 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 <functional>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include <folly/dynamic.h>
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class Instance;
|
||||
|
||||
}
|
||||
} // namespace facebook
|
||||
|
||||
namespace facebook {
|
||||
namespace xplat {
|
||||
namespace module {
|
||||
|
||||
/**
|
||||
* Base class for Catalyst native modules whose implementations are
|
||||
* written in C++. Native methods are represented by instances of the
|
||||
* Method struct. Generally, a derived class will manage an instance
|
||||
* which represents the data for the module, and non-Catalyst-specific
|
||||
* methods can be wrapped in lambdas which convert between
|
||||
* folly::dynamic and native C++ objects. The Callback arguments will
|
||||
* pass through to js functions passed to the analogous javascript
|
||||
* methods. At most two callbacks will be converted. Results should
|
||||
* be passed to the first callback, and errors to the second callback.
|
||||
* Exceptions thrown by a method will be converted to platform
|
||||
* exceptions, and handled however they are handled on that platform.
|
||||
* (TODO mhorowitz #7128529: this exception behavior is not yet
|
||||
* implemented.)
|
||||
*
|
||||
* There are two sets of constructors here. The first set initializes
|
||||
* a Method using a name and anything convertible to a std::function.
|
||||
* This is most useful for registering a lambda as a RN method. There
|
||||
* are overloads to support functions which take no arguments,
|
||||
* arguments only, and zero, one, or two callbacks.
|
||||
*
|
||||
* The second set of methods is similar, but instead of taking a
|
||||
* function, takes the method name, an object, and a pointer to a
|
||||
* method on that object.
|
||||
*/
|
||||
|
||||
class CxxModule {
|
||||
class AsyncTagType {};
|
||||
class SyncTagType {};
|
||||
|
||||
public:
|
||||
typedef std::function<std::unique_ptr<CxxModule>()> Provider;
|
||||
|
||||
typedef std::function<void(std::vector<folly::dynamic>)> Callback;
|
||||
|
||||
constexpr static AsyncTagType AsyncTag = AsyncTagType();
|
||||
constexpr static SyncTagType SyncTag = SyncTagType();
|
||||
|
||||
struct Method {
|
||||
std::string name;
|
||||
|
||||
size_t callbacks;
|
||||
bool isPromise;
|
||||
std::function<void(folly::dynamic, Callback, Callback)> func;
|
||||
|
||||
std::function<folly::dynamic(folly::dynamic)> syncFunc;
|
||||
|
||||
const char *getType() {
|
||||
assert(func || syncFunc);
|
||||
return func ? (isPromise ? "promise" : "async") : "sync";
|
||||
}
|
||||
|
||||
// std::function/lambda ctors
|
||||
|
||||
Method(std::string aname, std::function<void()> &&afunc)
|
||||
: name(std::move(aname)),
|
||||
callbacks(0),
|
||||
isPromise(false),
|
||||
func(std::bind(std::move(afunc))) {}
|
||||
|
||||
Method(std::string aname, std::function<void(folly::dynamic)> &&afunc)
|
||||
: name(std::move(aname)),
|
||||
callbacks(0),
|
||||
isPromise(false),
|
||||
func(std::bind(std::move(afunc), std::placeholders::_1)) {}
|
||||
|
||||
Method(
|
||||
std::string aname,
|
||||
std::function<void(folly::dynamic, Callback)> &&afunc)
|
||||
: name(std::move(aname)),
|
||||
callbacks(1),
|
||||
isPromise(false),
|
||||
func(std::bind(
|
||||
std::move(afunc),
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)) {}
|
||||
|
||||
Method(
|
||||
std::string aname,
|
||||
std::function<void(folly::dynamic, Callback, Callback)> &&afunc)
|
||||
: name(std::move(aname)),
|
||||
callbacks(2),
|
||||
isPromise(true),
|
||||
func(std::move(afunc)) {}
|
||||
|
||||
Method(
|
||||
std::string aname,
|
||||
std::function<void(folly::dynamic, Callback, Callback)> &&afunc,
|
||||
AsyncTagType)
|
||||
: name(std::move(aname)),
|
||||
callbacks(2),
|
||||
isPromise(false),
|
||||
func(std::move(afunc)) {}
|
||||
|
||||
// method pointer ctors
|
||||
|
||||
template <typename T>
|
||||
Method(std::string aname, T *t, void (T::*method)())
|
||||
: name(std::move(aname)),
|
||||
callbacks(0),
|
||||
isPromise(false),
|
||||
func(std::bind(method, t)) {}
|
||||
|
||||
template <typename T>
|
||||
Method(std::string aname, T *t, void (T::*method)(folly::dynamic))
|
||||
: name(std::move(aname)),
|
||||
callbacks(0),
|
||||
isPromise(false),
|
||||
func(std::bind(method, t, std::placeholders::_1)) {}
|
||||
|
||||
template <typename T>
|
||||
Method(std::string aname, T *t, void (T::*method)(folly::dynamic, Callback))
|
||||
: name(std::move(aname)),
|
||||
callbacks(1),
|
||||
isPromise(false),
|
||||
func(std::bind(
|
||||
method,
|
||||
t,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2)) {}
|
||||
|
||||
template <typename T>
|
||||
Method(
|
||||
std::string aname,
|
||||
T *t,
|
||||
void (T::*method)(folly::dynamic, Callback, Callback))
|
||||
: name(std::move(aname)),
|
||||
callbacks(2),
|
||||
isPromise(true),
|
||||
func(std::bind(
|
||||
method,
|
||||
t,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
std::placeholders::_3)) {}
|
||||
|
||||
template <typename T>
|
||||
Method(
|
||||
std::string aname,
|
||||
T *t,
|
||||
void (T::*method)(folly::dynamic, Callback, Callback),
|
||||
AsyncTagType)
|
||||
: name(std::move(aname)),
|
||||
callbacks(2),
|
||||
isPromise(false),
|
||||
func(std::bind(
|
||||
method,
|
||||
t,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
std::placeholders::_3)) {}
|
||||
|
||||
// sync std::function/lambda ctors
|
||||
|
||||
// Overloads for functions returning void give ambiguity errors.
|
||||
// I am not sure if this is a runtime/compiler bug, or a
|
||||
// limitation I do not understand.
|
||||
|
||||
Method(
|
||||
std::string aname,
|
||||
std::function<folly::dynamic()> &&afunc,
|
||||
SyncTagType)
|
||||
: name(std::move(aname)),
|
||||
callbacks(0),
|
||||
isPromise(false),
|
||||
syncFunc([afunc = std::move(afunc)](const folly::dynamic &) {
|
||||
return afunc();
|
||||
}) {}
|
||||
|
||||
Method(
|
||||
std::string aname,
|
||||
std::function<folly::dynamic(folly::dynamic)> &&afunc,
|
||||
SyncTagType)
|
||||
: name(std::move(aname)),
|
||||
callbacks(0),
|
||||
isPromise(false),
|
||||
syncFunc(std::move(afunc)) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* This may block, if necessary to complete cleanup before the
|
||||
* object is destroyed.
|
||||
*/
|
||||
virtual ~CxxModule() {}
|
||||
|
||||
/**
|
||||
* @return the name of this module. This will be the name used to {@code
|
||||
* require()} this module from javascript.
|
||||
*/
|
||||
virtual std::string getName() = 0;
|
||||
|
||||
/**
|
||||
* Each entry in the map will be exported as a property to JS. The
|
||||
* key is the property name, and the value can be anything.
|
||||
*/
|
||||
virtual auto getConstants() -> std::map<std::string, folly::dynamic> {
|
||||
return {};
|
||||
};
|
||||
|
||||
/**
|
||||
* @return a list of methods this module exports to JS.
|
||||
*/
|
||||
virtual auto getMethods() -> std::vector<Method> = 0;
|
||||
|
||||
/**
|
||||
* Called during the construction of CxxNativeModule.
|
||||
*/
|
||||
void setInstance(std::weak_ptr<react::Instance> instance) {
|
||||
instance_ = instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a weak_ptr to the current instance of the bridge.
|
||||
* When used with CxxNativeModule, this gives Cxx modules access to functions
|
||||
* such as `callJSFunction`, allowing them to communicate back to JS outside
|
||||
* of the regular callbacks.
|
||||
*/
|
||||
std::weak_ptr<react::Instance> getInstance() {
|
||||
return instance_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::weak_ptr<react::Instance> instance_;
|
||||
};
|
||||
|
||||
} // namespace module
|
||||
} // namespace xplat
|
||||
} // namespace facebook
|
213
node_modules/react-native/ReactCommon/cxxreact/CxxNativeModule.cpp
generated
vendored
Normal file
213
node_modules/react-native/ReactCommon/cxxreact/CxxNativeModule.cpp
generated
vendored
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* 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 "CxxNativeModule.h"
|
||||
#include "Instance.h"
|
||||
|
||||
#include <folly/json.h>
|
||||
#include <glog/logging.h>
|
||||
#include <iterator>
|
||||
|
||||
#include "JsArgumentHelpers.h"
|
||||
#include "MessageQueueThread.h"
|
||||
#include "SystraceSection.h"
|
||||
|
||||
using facebook::xplat::module::CxxModule;
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
std::function<void(folly::dynamic)> makeCallback(
|
||||
std::weak_ptr<Instance> instance,
|
||||
const folly::dynamic &callbackId) {
|
||||
if (!callbackId.isNumber()) {
|
||||
throw std::invalid_argument("Expected callback(s) as final argument");
|
||||
}
|
||||
|
||||
auto id = callbackId.asInt();
|
||||
return [winstance = std::move(instance), id](folly::dynamic args) {
|
||||
if (auto instance = winstance.lock()) {
|
||||
instance->callJSCallback(id, std::move(args));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* CxxModule::Callback accepts a vector<dynamic>, makeCallback returns
|
||||
* a callback that accepts a dynamic, adapt the second into the first.
|
||||
* TODO: Callback types should be made equal (preferably
|
||||
* function<void(dynamic)>) to avoid the extra copy and indirect call.
|
||||
*/
|
||||
CxxModule::Callback convertCallback(
|
||||
std::function<void(folly::dynamic)> callback) {
|
||||
return [callback = std::move(callback)](std::vector<folly::dynamic> args) {
|
||||
callback(folly::dynamic(
|
||||
std::make_move_iterator(args.begin()),
|
||||
std::make_move_iterator(args.end())));
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string CxxNativeModule::getName() {
|
||||
return name_;
|
||||
}
|
||||
|
||||
std::vector<MethodDescriptor> CxxNativeModule::getMethods() {
|
||||
lazyInit();
|
||||
|
||||
std::vector<MethodDescriptor> descs;
|
||||
for (auto &method : methods_) {
|
||||
descs.emplace_back(method.name, method.getType());
|
||||
}
|
||||
return descs;
|
||||
}
|
||||
|
||||
folly::dynamic CxxNativeModule::getConstants() {
|
||||
lazyInit();
|
||||
|
||||
if (!module_) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
folly::dynamic constants = folly::dynamic::object();
|
||||
for (auto &pair : module_->getConstants()) {
|
||||
constants.insert(std::move(pair.first), std::move(pair.second));
|
||||
}
|
||||
return constants;
|
||||
}
|
||||
|
||||
void CxxNativeModule::invoke(
|
||||
unsigned int reactMethodId,
|
||||
folly::dynamic &¶ms,
|
||||
int callId) {
|
||||
if (reactMethodId >= methods_.size()) {
|
||||
throw std::invalid_argument(folly::to<std::string>(
|
||||
"methodId ",
|
||||
reactMethodId,
|
||||
" out of range [0..",
|
||||
methods_.size(),
|
||||
"]"));
|
||||
}
|
||||
if (!params.isArray()) {
|
||||
throw std::invalid_argument(folly::to<std::string>(
|
||||
"method parameters should be array, but are ", params.typeName()));
|
||||
}
|
||||
|
||||
CxxModule::Callback first;
|
||||
CxxModule::Callback second;
|
||||
|
||||
const auto &method = methods_[reactMethodId];
|
||||
|
||||
if (!method.func) {
|
||||
throw std::runtime_error(folly::to<std::string>(
|
||||
"Method ", method.name, " is synchronous but invoked asynchronously"));
|
||||
}
|
||||
|
||||
if (params.size() < method.callbacks) {
|
||||
throw std::invalid_argument(folly::to<std::string>(
|
||||
"Expected ",
|
||||
method.callbacks,
|
||||
" callbacks, but only ",
|
||||
params.size(),
|
||||
" parameters provided"));
|
||||
}
|
||||
|
||||
if (method.callbacks == 1) {
|
||||
first = convertCallback(makeCallback(instance_, params[params.size() - 1]));
|
||||
} else if (method.callbacks == 2) {
|
||||
first = convertCallback(makeCallback(instance_, params[params.size() - 2]));
|
||||
second =
|
||||
convertCallback(makeCallback(instance_, params[params.size() - 1]));
|
||||
}
|
||||
|
||||
params.resize(params.size() - method.callbacks);
|
||||
|
||||
// I've got a few flawed options here. I can let the C++ exception
|
||||
// propagate, and the registry will log/convert them to java exceptions.
|
||||
// This lets all the java and red box handling work ok, but the only info I
|
||||
// can capture about the C++ exception is the what() string, not the stack.
|
||||
// I can std::terminate() the app. This causes the full, accurate C++
|
||||
// stack trace to be added to logcat by debuggerd. The java state is lost,
|
||||
// but in practice, the java stack is always the same in this case since
|
||||
// the javascript stack is not visible, and the crash is unfriendly to js
|
||||
// developers, but crucial to C++ developers. The what() value is also
|
||||
// lost. Finally, I can catch, log the java stack, then rethrow the C++
|
||||
// exception. In this case I get java and C++ stack data, but the C++
|
||||
// stack is as of the rethrow, not the original throw, both the C++ and
|
||||
// java stacks always look the same.
|
||||
//
|
||||
// I am going with option 2, since that seems like the most useful
|
||||
// choice. It would be nice to be able to get what() and the C++
|
||||
// stack. I'm told that will be possible in the future. TODO
|
||||
// mhorowitz #7128529: convert C++ exceptions to Java
|
||||
|
||||
messageQueueThread_->runOnQueue(
|
||||
[method, params = std::move(params), first, second, callId]() {
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
if (callId != -1) {
|
||||
fbsystrace_end_async_flow(TRACE_TAG_REACT_APPS, "native", callId);
|
||||
}
|
||||
#else
|
||||
(void)(callId);
|
||||
#endif
|
||||
SystraceSection s(method.name.c_str());
|
||||
try {
|
||||
method.func(std::move(params), first, second);
|
||||
} catch (const facebook::xplat::JsArgumentException &ex) {
|
||||
throw;
|
||||
} catch (std::exception &e) {
|
||||
LOG(ERROR) << "std::exception. Method call " << method.name.c_str()
|
||||
<< " failed: " << e.what();
|
||||
std::terminate();
|
||||
} catch (std::string &error) {
|
||||
LOG(ERROR) << "std::string. Method call " << method.name.c_str()
|
||||
<< " failed: " << error.c_str();
|
||||
std::terminate();
|
||||
} catch (...) {
|
||||
LOG(ERROR) << "Method call " << method.name.c_str()
|
||||
<< " failed. unknown error";
|
||||
std::terminate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
MethodCallResult CxxNativeModule::callSerializableNativeHook(
|
||||
unsigned int hookId,
|
||||
folly::dynamic &&args) {
|
||||
if (hookId >= methods_.size()) {
|
||||
throw std::invalid_argument(folly::to<std::string>(
|
||||
"methodId ", hookId, " out of range [0..", methods_.size(), "]"));
|
||||
}
|
||||
|
||||
const auto &method = methods_[hookId];
|
||||
|
||||
if (!method.syncFunc) {
|
||||
throw std::runtime_error(folly::to<std::string>(
|
||||
"Method ", method.name, " is asynchronous but invoked synchronously"));
|
||||
}
|
||||
|
||||
return method.syncFunc(std::move(args));
|
||||
}
|
||||
|
||||
void CxxNativeModule::lazyInit() {
|
||||
if (module_ || !provider_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO 17216751: providers should never return null modules
|
||||
module_ = provider_();
|
||||
provider_ = nullptr;
|
||||
if (module_) {
|
||||
methods_ = module_->getMethods();
|
||||
module_->setInstance(instance_);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
60
node_modules/react-native/ReactCommon/cxxreact/CxxNativeModule.h
generated
vendored
Normal file
60
node_modules/react-native/ReactCommon/cxxreact/CxxNativeModule.h
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 <cxxreact/CxxModule.h>
|
||||
#include <cxxreact/NativeModule.h>
|
||||
|
||||
#ifndef RN_EXPORT
|
||||
#define RN_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class Instance;
|
||||
class MessageQueueThread;
|
||||
|
||||
std::function<void(folly::dynamic)> makeCallback(
|
||||
std::weak_ptr<Instance> instance,
|
||||
const folly::dynamic &callbackId);
|
||||
|
||||
class RN_EXPORT CxxNativeModule : public NativeModule {
|
||||
public:
|
||||
CxxNativeModule(
|
||||
std::weak_ptr<Instance> instance,
|
||||
std::string name,
|
||||
xplat::module::CxxModule::Provider provider,
|
||||
std::shared_ptr<MessageQueueThread> messageQueueThread)
|
||||
: instance_(instance),
|
||||
name_(std::move(name)),
|
||||
provider_(provider),
|
||||
messageQueueThread_(messageQueueThread) {}
|
||||
|
||||
std::string getName() override;
|
||||
std::vector<MethodDescriptor> getMethods() override;
|
||||
folly::dynamic getConstants() override;
|
||||
void invoke(unsigned int reactMethodId, folly::dynamic &¶ms, int callId)
|
||||
override;
|
||||
MethodCallResult callSerializableNativeHook(
|
||||
unsigned int hookId,
|
||||
folly::dynamic &&args) override;
|
||||
|
||||
private:
|
||||
void lazyInit();
|
||||
|
||||
std::weak_ptr<Instance> instance_;
|
||||
std::string name_;
|
||||
xplat::module::CxxModule::Provider provider_;
|
||||
std::shared_ptr<MessageQueueThread> messageQueueThread_;
|
||||
std::unique_ptr<xplat::module::CxxModule> module_;
|
||||
std::vector<xplat::module::CxxModule::Method> methods_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
291
node_modules/react-native/ReactCommon/cxxreact/Instance.cpp
generated
vendored
Normal file
291
node_modules/react-native/ReactCommon/cxxreact/Instance.cpp
generated
vendored
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* 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 "Instance.h"
|
||||
|
||||
#include "JSBigString.h"
|
||||
#include "JSBundleType.h"
|
||||
#include "JSExecutor.h"
|
||||
#include "MessageQueueThread.h"
|
||||
#include "MethodCall.h"
|
||||
#include "NativeToJsBridge.h"
|
||||
#include "RAMBundleRegistry.h"
|
||||
#include "RecoverableError.h"
|
||||
#include "SystraceSection.h"
|
||||
|
||||
#include <cxxreact/JSIndexedRAMBundle.h>
|
||||
#include <folly/MoveWrapper.h>
|
||||
#include <folly/json.h>
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
Instance::~Instance() {
|
||||
if (nativeToJsBridge_) {
|
||||
nativeToJsBridge_->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void Instance::initializeBridge(
|
||||
std::unique_ptr<InstanceCallback> callback,
|
||||
std::shared_ptr<JSExecutorFactory> jsef,
|
||||
std::shared_ptr<MessageQueueThread> jsQueue,
|
||||
std::shared_ptr<ModuleRegistry> moduleRegistry) {
|
||||
callback_ = std::move(callback);
|
||||
moduleRegistry_ = std::move(moduleRegistry);
|
||||
jsQueue->runOnQueueSync([this, &jsef, jsQueue]() mutable {
|
||||
nativeToJsBridge_ = std::make_shared<NativeToJsBridge>(
|
||||
jsef.get(), moduleRegistry_, jsQueue, callback_);
|
||||
|
||||
nativeToJsBridge_->initializeRuntime();
|
||||
|
||||
/**
|
||||
* After NativeToJsBridge is created, the jsi::Runtime should exist.
|
||||
* Also, the JS message queue thread exists. So, it's safe to
|
||||
* schedule all queued up js Calls.
|
||||
*/
|
||||
jsCallInvoker_->setNativeToJsBridgeAndFlushCalls(nativeToJsBridge_);
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_syncMutex);
|
||||
m_syncReady = true;
|
||||
m_syncCV.notify_all();
|
||||
});
|
||||
|
||||
CHECK(nativeToJsBridge_);
|
||||
}
|
||||
|
||||
void Instance::loadBundle(
|
||||
std::unique_ptr<RAMBundleRegistry> bundleRegistry,
|
||||
std::unique_ptr<const JSBigString> string,
|
||||
std::string sourceURL) {
|
||||
callback_->incrementPendingJSCalls();
|
||||
SystraceSection s("Instance::loadBundle", "sourceURL", sourceURL);
|
||||
nativeToJsBridge_->loadBundle(
|
||||
std::move(bundleRegistry), std::move(string), std::move(sourceURL));
|
||||
}
|
||||
|
||||
void Instance::loadBundleSync(
|
||||
std::unique_ptr<RAMBundleRegistry> bundleRegistry,
|
||||
std::unique_ptr<const JSBigString> string,
|
||||
std::string sourceURL) {
|
||||
std::unique_lock<std::mutex> lock(m_syncMutex);
|
||||
m_syncCV.wait(lock, [this] { return m_syncReady; });
|
||||
|
||||
SystraceSection s("Instance::loadBundleSync", "sourceURL", sourceURL);
|
||||
nativeToJsBridge_->loadBundleSync(
|
||||
std::move(bundleRegistry), std::move(string), std::move(sourceURL));
|
||||
}
|
||||
|
||||
void Instance::setSourceURL(std::string sourceURL) {
|
||||
callback_->incrementPendingJSCalls();
|
||||
SystraceSection s("Instance::setSourceURL", "sourceURL", sourceURL);
|
||||
|
||||
nativeToJsBridge_->loadBundle(nullptr, nullptr, std::move(sourceURL));
|
||||
}
|
||||
|
||||
void Instance::loadScriptFromString(
|
||||
std::unique_ptr<const JSBigString> string,
|
||||
std::string sourceURL,
|
||||
bool loadSynchronously) {
|
||||
SystraceSection s("Instance::loadScriptFromString", "sourceURL", sourceURL);
|
||||
if (loadSynchronously) {
|
||||
loadBundleSync(nullptr, std::move(string), std::move(sourceURL));
|
||||
} else {
|
||||
loadBundle(nullptr, std::move(string), std::move(sourceURL));
|
||||
}
|
||||
}
|
||||
|
||||
bool Instance::isIndexedRAMBundle(const char *sourcePath) {
|
||||
std::ifstream bundle_stream(sourcePath, std::ios_base::in);
|
||||
BundleHeader header;
|
||||
|
||||
if (!bundle_stream ||
|
||||
!bundle_stream.read(reinterpret_cast<char *>(&header), sizeof(header))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return parseTypeFromHeader(header) == ScriptTag::RAMBundle;
|
||||
}
|
||||
|
||||
bool Instance::isIndexedRAMBundle(std::unique_ptr<const JSBigString> *script) {
|
||||
BundleHeader header;
|
||||
strncpy(
|
||||
reinterpret_cast<char *>(&header),
|
||||
script->get()->c_str(),
|
||||
sizeof(header));
|
||||
|
||||
return parseTypeFromHeader(header) == ScriptTag::RAMBundle;
|
||||
}
|
||||
|
||||
void Instance::loadRAMBundleFromString(
|
||||
std::unique_ptr<const JSBigString> script,
|
||||
const std::string &sourceURL) {
|
||||
auto bundle = std::make_unique<JSIndexedRAMBundle>(std::move(script));
|
||||
auto startupScript = bundle->getStartupCode();
|
||||
auto registry = RAMBundleRegistry::singleBundleRegistry(std::move(bundle));
|
||||
loadRAMBundle(std::move(registry), std::move(startupScript), sourceURL, true);
|
||||
}
|
||||
|
||||
void Instance::loadRAMBundleFromFile(
|
||||
const std::string &sourcePath,
|
||||
const std::string &sourceURL,
|
||||
bool loadSynchronously) {
|
||||
auto bundle = std::make_unique<JSIndexedRAMBundle>(sourcePath.c_str());
|
||||
auto startupScript = bundle->getStartupCode();
|
||||
auto registry = RAMBundleRegistry::multipleBundlesRegistry(
|
||||
std::move(bundle), JSIndexedRAMBundle::buildFactory());
|
||||
loadRAMBundle(
|
||||
std::move(registry),
|
||||
std::move(startupScript),
|
||||
sourceURL,
|
||||
loadSynchronously);
|
||||
}
|
||||
|
||||
void Instance::loadRAMBundle(
|
||||
std::unique_ptr<RAMBundleRegistry> bundleRegistry,
|
||||
std::unique_ptr<const JSBigString> startupScript,
|
||||
std::string startupScriptSourceURL,
|
||||
bool loadSynchronously) {
|
||||
if (loadSynchronously) {
|
||||
loadBundleSync(
|
||||
std::move(bundleRegistry),
|
||||
std::move(startupScript),
|
||||
std::move(startupScriptSourceURL));
|
||||
} else {
|
||||
loadBundle(
|
||||
std::move(bundleRegistry),
|
||||
std::move(startupScript),
|
||||
std::move(startupScriptSourceURL));
|
||||
}
|
||||
}
|
||||
|
||||
void Instance::setGlobalVariable(
|
||||
std::string propName,
|
||||
std::unique_ptr<const JSBigString> jsonValue) {
|
||||
nativeToJsBridge_->setGlobalVariable(
|
||||
std::move(propName), std::move(jsonValue));
|
||||
}
|
||||
|
||||
void *Instance::getJavaScriptContext() {
|
||||
return nativeToJsBridge_ ? nativeToJsBridge_->getJavaScriptContext()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
bool Instance::isInspectable() {
|
||||
return nativeToJsBridge_ ? nativeToJsBridge_->isInspectable() : false;
|
||||
}
|
||||
|
||||
bool Instance::isBatchActive() {
|
||||
return nativeToJsBridge_ ? nativeToJsBridge_->isBatchActive() : false;
|
||||
}
|
||||
|
||||
void Instance::callJSFunction(
|
||||
std::string &&module,
|
||||
std::string &&method,
|
||||
folly::dynamic &¶ms) {
|
||||
callback_->incrementPendingJSCalls();
|
||||
nativeToJsBridge_->callFunction(
|
||||
std::move(module), std::move(method), std::move(params));
|
||||
}
|
||||
|
||||
void Instance::callJSCallback(uint64_t callbackId, folly::dynamic &¶ms) {
|
||||
SystraceSection s("Instance::callJSCallback");
|
||||
callback_->incrementPendingJSCalls();
|
||||
nativeToJsBridge_->invokeCallback((double)callbackId, std::move(params));
|
||||
}
|
||||
|
||||
void Instance::registerBundle(
|
||||
uint32_t bundleId,
|
||||
const std::string &bundlePath) {
|
||||
nativeToJsBridge_->registerBundle(bundleId, bundlePath);
|
||||
}
|
||||
|
||||
const ModuleRegistry &Instance::getModuleRegistry() const {
|
||||
return *moduleRegistry_;
|
||||
}
|
||||
|
||||
ModuleRegistry &Instance::getModuleRegistry() {
|
||||
return *moduleRegistry_;
|
||||
}
|
||||
|
||||
void Instance::handleMemoryPressure(int pressureLevel) {
|
||||
nativeToJsBridge_->handleMemoryPressure(pressureLevel);
|
||||
}
|
||||
|
||||
std::shared_ptr<CallInvoker> Instance::getJSCallInvoker() {
|
||||
return std::static_pointer_cast<CallInvoker>(jsCallInvoker_);
|
||||
}
|
||||
|
||||
std::shared_ptr<CallInvoker> Instance::getDecoratedNativeCallInvoker(
|
||||
std::shared_ptr<CallInvoker> nativeInvoker) {
|
||||
return nativeToJsBridge_->getDecoratedNativeCallInvoker(nativeInvoker);
|
||||
}
|
||||
|
||||
void Instance::JSCallInvoker::setNativeToJsBridgeAndFlushCalls(
|
||||
std::weak_ptr<NativeToJsBridge> nativeToJsBridge) {
|
||||
std::lock_guard<std::mutex> guard(m_mutex);
|
||||
|
||||
m_shouldBuffer = false;
|
||||
m_nativeToJsBridge = nativeToJsBridge;
|
||||
while (m_workBuffer.size() > 0) {
|
||||
scheduleAsync(std::move(m_workBuffer.front()));
|
||||
m_workBuffer.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void Instance::JSCallInvoker::invokeSync(std::function<void()> &&work) {
|
||||
// TODO: Replace JS Callinvoker with RuntimeExecutor.
|
||||
throw std::runtime_error(
|
||||
"Synchronous native -> JS calls are currently not supported.");
|
||||
}
|
||||
|
||||
void Instance::JSCallInvoker::invokeAsync(std::function<void()> &&work) {
|
||||
std::lock_guard<std::mutex> guard(m_mutex);
|
||||
|
||||
/**
|
||||
* Why is is necessary to queue up async work?
|
||||
*
|
||||
* 1. TurboModuleManager must be created synchronously after the Instance,
|
||||
* before we load the source code. This is when the NativeModule system
|
||||
* is initialized. RCTDevLoadingView shows bundle download progress.
|
||||
* 2. TurboModuleManager requires a JS CallInvoker.
|
||||
* 3. The JS CallInvoker requires the NativeToJsBridge, which is created on
|
||||
* the JS thread in Instance::initializeBridge.
|
||||
*
|
||||
* Therefore, although we don't call invokeAsync before the JS bundle is
|
||||
* executed, this buffering is implemented anyways to ensure that work
|
||||
* isn't discarded.
|
||||
*/
|
||||
if (m_shouldBuffer) {
|
||||
m_workBuffer.push_back(std::move(work));
|
||||
return;
|
||||
}
|
||||
|
||||
scheduleAsync(std::move(work));
|
||||
}
|
||||
|
||||
void Instance::JSCallInvoker::scheduleAsync(std::function<void()> &&work) {
|
||||
if (auto strongNativeToJsBridge = m_nativeToJsBridge.lock()) {
|
||||
strongNativeToJsBridge->runOnExecutorQueue(
|
||||
[work = std::move(work)](JSExecutor *executor) {
|
||||
work();
|
||||
executor->flush();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
172
node_modules/react-native/ReactCommon/cxxreact/Instance.h
generated
vendored
Normal file
172
node_modules/react-native/ReactCommon/cxxreact/Instance.h
generated
vendored
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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 <condition_variable>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include <cxxreact/NativeToJsBridge.h>
|
||||
|
||||
#ifndef RN_EXPORT
|
||||
#define RN_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
namespace folly {
|
||||
struct dynamic;
|
||||
}
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class JSBigString;
|
||||
class JSExecutorFactory;
|
||||
class MessageQueueThread;
|
||||
class ModuleRegistry;
|
||||
class RAMBundleRegistry;
|
||||
|
||||
struct InstanceCallback {
|
||||
virtual ~InstanceCallback() {}
|
||||
virtual void onBatchComplete() {}
|
||||
virtual void incrementPendingJSCalls() {}
|
||||
virtual void decrementPendingJSCalls() {}
|
||||
};
|
||||
|
||||
class RN_EXPORT Instance {
|
||||
public:
|
||||
~Instance();
|
||||
void initializeBridge(
|
||||
std::unique_ptr<InstanceCallback> callback,
|
||||
std::shared_ptr<JSExecutorFactory> jsef,
|
||||
std::shared_ptr<MessageQueueThread> jsQueue,
|
||||
std::shared_ptr<ModuleRegistry> moduleRegistry);
|
||||
|
||||
void initializeRuntime();
|
||||
|
||||
void setSourceURL(std::string sourceURL);
|
||||
|
||||
void loadScriptFromString(
|
||||
std::unique_ptr<const JSBigString> string,
|
||||
std::string sourceURL,
|
||||
bool loadSynchronously);
|
||||
static bool isIndexedRAMBundle(const char *sourcePath);
|
||||
static bool isIndexedRAMBundle(std::unique_ptr<const JSBigString> *string);
|
||||
void loadRAMBundleFromString(
|
||||
std::unique_ptr<const JSBigString> script,
|
||||
const std::string &sourceURL);
|
||||
void loadRAMBundleFromFile(
|
||||
const std::string &sourcePath,
|
||||
const std::string &sourceURL,
|
||||
bool loadSynchronously);
|
||||
void loadRAMBundle(
|
||||
std::unique_ptr<RAMBundleRegistry> bundleRegistry,
|
||||
std::unique_ptr<const JSBigString> startupScript,
|
||||
std::string startupScriptSourceURL,
|
||||
bool loadSynchronously);
|
||||
bool supportsProfiling();
|
||||
void setGlobalVariable(
|
||||
std::string propName,
|
||||
std::unique_ptr<const JSBigString> jsonValue);
|
||||
void *getJavaScriptContext();
|
||||
bool isInspectable();
|
||||
bool isBatchActive();
|
||||
void callJSFunction(
|
||||
std::string &&module,
|
||||
std::string &&method,
|
||||
folly::dynamic &¶ms);
|
||||
void callJSCallback(uint64_t callbackId, folly::dynamic &¶ms);
|
||||
|
||||
// This method is experimental, and may be modified or removed.
|
||||
void registerBundle(uint32_t bundleId, const std::string &bundlePath);
|
||||
|
||||
const ModuleRegistry &getModuleRegistry() const;
|
||||
ModuleRegistry &getModuleRegistry();
|
||||
|
||||
void handleMemoryPressure(int pressureLevel);
|
||||
|
||||
/**
|
||||
* JS CallInvoker is used by TurboModules to schedule work on the JS thread.
|
||||
*
|
||||
* Why is the bridge creating JS CallInvoker?
|
||||
*
|
||||
* - After every Native -> JS call in the TurboModule system, the bridge
|
||||
* needs to flush all queued NativeModule method calls. The bridge must
|
||||
* also dispatch onBatchComplete if the queue of NativeModule method calls
|
||||
* was not empty.
|
||||
*/
|
||||
std::shared_ptr<CallInvoker> getJSCallInvoker();
|
||||
|
||||
/**
|
||||
* Native CallInvoker is used by TurboModules to schedule work on the
|
||||
* NativeModule thread(s).
|
||||
*
|
||||
* Why is the bridge decorating native CallInvoker?
|
||||
*
|
||||
* - The bridge must be informed of all TurboModule async method calls. Why?
|
||||
* When all queued NativeModule method calls are flushed by a call from
|
||||
* Native -> JS, if that queue was non-zero in size, JsToNativeBridge
|
||||
* dispatches onBatchComplete. When we turn our NativeModules to
|
||||
* TurboModuels, there will be less and less pending NativeModule method
|
||||
* calls, so onBatchComplete will not fire as often. Therefore, the bridge
|
||||
* needs to know how many TurboModule async method calls have been completed
|
||||
* since the last time the bridge was flushed. If this number is non-zero,
|
||||
* we fire onBatchComplete.
|
||||
*
|
||||
* Why can't we just create and return a new native CallInvoker?
|
||||
*
|
||||
* - On Android, we have one NativeModule thread. That thread is created and
|
||||
* managed outisde of NativeToJsBridge. On iOS, we have one MethodQueue per
|
||||
* module. Those MethodQueues are also created and managed outside of
|
||||
* NativeToJsBridge. Therefore, we need to pass in a CallInvoker that
|
||||
* schedules work on the respective thread.
|
||||
*/
|
||||
std::shared_ptr<CallInvoker> getDecoratedNativeCallInvoker(
|
||||
std::shared_ptr<CallInvoker> nativeInvoker);
|
||||
|
||||
private:
|
||||
void callNativeModules(folly::dynamic &&calls, bool isEndOfBatch);
|
||||
void loadBundle(
|
||||
std::unique_ptr<RAMBundleRegistry> bundleRegistry,
|
||||
std::unique_ptr<const JSBigString> startupScript,
|
||||
std::string startupScriptSourceURL);
|
||||
void loadBundleSync(
|
||||
std::unique_ptr<RAMBundleRegistry> bundleRegistry,
|
||||
std::unique_ptr<const JSBigString> startupScript,
|
||||
std::string startupScriptSourceURL);
|
||||
|
||||
std::shared_ptr<InstanceCallback> callback_;
|
||||
std::shared_ptr<NativeToJsBridge> nativeToJsBridge_;
|
||||
std::shared_ptr<ModuleRegistry> moduleRegistry_;
|
||||
|
||||
std::mutex m_syncMutex;
|
||||
std::condition_variable m_syncCV;
|
||||
bool m_syncReady = false;
|
||||
|
||||
class JSCallInvoker : public CallInvoker {
|
||||
private:
|
||||
std::weak_ptr<NativeToJsBridge> m_nativeToJsBridge;
|
||||
std::mutex m_mutex;
|
||||
bool m_shouldBuffer = true;
|
||||
std::list<std::function<void()>> m_workBuffer;
|
||||
|
||||
void scheduleAsync(std::function<void()> &&work);
|
||||
|
||||
public:
|
||||
void setNativeToJsBridgeAndFlushCalls(
|
||||
std::weak_ptr<NativeToJsBridge> nativeToJsBridge);
|
||||
void invokeAsync(std::function<void()> &&work) override;
|
||||
void invokeSync(std::function<void()> &&work) override;
|
||||
};
|
||||
|
||||
std::shared_ptr<JSCallInvoker> jsCallInvoker_ =
|
||||
std::make_shared<JSCallInvoker>();
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
157
node_modules/react-native/ReactCommon/cxxreact/JSBigString.cpp
generated
vendored
Normal file
157
node_modules/react-native/ReactCommon/cxxreact/JSBigString.cpp
generated
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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 "JSBigString.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include <folly/Memory.h>
|
||||
#include <folly/ScopeGuard.h>
|
||||
#include <folly/portability/Fcntl.h>
|
||||
#include <folly/portability/SysMman.h>
|
||||
#include <folly/portability/SysStat.h>
|
||||
#include <folly/portability/Unistd.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
JSBigFileString::JSBigFileString(int fd, size_t size, off_t offset /*= 0*/)
|
||||
: m_fd{-1}, m_data{nullptr} {
|
||||
folly::checkUnixError(m_fd = dup(fd), "Could not duplicate file descriptor");
|
||||
|
||||
// Offsets given to mmap must be page aligned. We abstract away that
|
||||
// restriction by sending a page aligned offset to mmap, and keeping track
|
||||
// of the offset within the page that we must alter the mmap pointer by to
|
||||
// get the final desired offset.
|
||||
if (offset != 0) {
|
||||
const static auto ps = sysconf(_SC_PAGESIZE);
|
||||
auto d = lldiv(offset, ps);
|
||||
|
||||
m_mapOff = d.quot;
|
||||
m_pageOff = d.rem;
|
||||
m_size = size + m_pageOff;
|
||||
} else {
|
||||
m_mapOff = 0;
|
||||
m_pageOff = 0;
|
||||
m_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
JSBigFileString::~JSBigFileString() {
|
||||
if (m_data) {
|
||||
munmap((void *)m_data, m_size);
|
||||
}
|
||||
close(m_fd);
|
||||
}
|
||||
|
||||
#ifdef WITH_FBREMAP
|
||||
// Read and advance the pointer.
|
||||
static uint16_t read16(char *&data) {
|
||||
uint16_t result;
|
||||
::memcpy(&result, data, sizeof(result));
|
||||
data += sizeof(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// If the given file has a remapping table header, remap its pages accordingly
|
||||
// and return the byte offset from the beginning to the unwrapped payload.
|
||||
static off_t maybeRemap(char *data, size_t size, int fd) {
|
||||
// A remapped file's size must be a multiple of its page size, so quickly
|
||||
// filter out files with incorrect size, without touching any pages.
|
||||
static const size_t kMinPageSize = 4096;
|
||||
if (size < kMinPageSize || size % kMinPageSize != 0) {
|
||||
return 0;
|
||||
}
|
||||
const auto begin = data;
|
||||
static const uint8_t kRemapMagic[] = {
|
||||
0xc6, 0x1f, 0xbc, 0x03, 0xc1, 0x03, 0x19, 0x1f, 0xa1, 0xd0, 0xeb, 0x73};
|
||||
if (::memcmp(data, kRemapMagic, sizeof(kRemapMagic)) != 0) {
|
||||
return 0;
|
||||
}
|
||||
data += sizeof(kRemapMagic);
|
||||
const size_t filePS = static_cast<size_t>(1) << read16(data);
|
||||
if (size & (filePS - 1)) {
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
// System page size must be at least as granular as the remapping.
|
||||
// TODO: Consider fallback that reads entire file into memory.
|
||||
const size_t systemPS = sysconf(_SC_PAGESIZE);
|
||||
CHECK(filePS >= systemPS)
|
||||
<< "filePS: " << filePS << "systemPS: " << systemPS;
|
||||
}
|
||||
const off_t headerPages = read16(data);
|
||||
uint16_t numMappings = read16(data);
|
||||
size_t curFilePage = headerPages;
|
||||
while (numMappings--) {
|
||||
auto memPage = read16(data) + headerPages;
|
||||
auto numPages = read16(data);
|
||||
if (mmap(
|
||||
begin + memPage * filePS,
|
||||
numPages * filePS,
|
||||
PROT_READ,
|
||||
MAP_FILE | MAP_PRIVATE | MAP_FIXED,
|
||||
fd,
|
||||
curFilePage * filePS) == MAP_FAILED) {
|
||||
CHECK(false) << " memPage: " << memPage << " numPages: " << numPages
|
||||
<< " curFilePage: " << curFilePage << " size: " << size
|
||||
<< " error: " << std::strerror(errno);
|
||||
}
|
||||
curFilePage += numPages;
|
||||
}
|
||||
return headerPages * filePS;
|
||||
}
|
||||
#endif // WITH_FBREMAP
|
||||
|
||||
const char *JSBigFileString::c_str() const {
|
||||
if (m_size == 0) {
|
||||
return "";
|
||||
}
|
||||
if (!m_data) {
|
||||
m_data =
|
||||
(const char *)mmap(0, m_size, PROT_READ, MAP_PRIVATE, m_fd, m_mapOff);
|
||||
CHECK(m_data != MAP_FAILED)
|
||||
<< " fd: " << m_fd << " size: " << m_size << " offset: " << m_mapOff
|
||||
<< " error: " << std::strerror(errno);
|
||||
#ifdef WITH_FBREMAP
|
||||
// Remapping is only attempted when the entire file was requested.
|
||||
if (m_mapOff == 0 && m_pageOff == 0) {
|
||||
m_pageOff = maybeRemap(const_cast<char *>(m_data), m_size, m_fd);
|
||||
}
|
||||
#endif // WITH_FBREMAP
|
||||
}
|
||||
return m_data + m_pageOff;
|
||||
}
|
||||
|
||||
size_t JSBigFileString::size() const {
|
||||
// Ensure mapping has been initialized.
|
||||
c_str();
|
||||
return m_size - m_pageOff;
|
||||
}
|
||||
|
||||
int JSBigFileString::fd() const {
|
||||
return m_fd;
|
||||
}
|
||||
|
||||
std::unique_ptr<const JSBigFileString> JSBigFileString::fromPath(
|
||||
const std::string &sourceURL) {
|
||||
int fd = ::open(sourceURL.c_str(), O_RDONLY);
|
||||
folly::checkUnixError(fd, "Could not open file", sourceURL);
|
||||
SCOPE_EXIT {
|
||||
CHECK(::close(fd) == 0);
|
||||
};
|
||||
|
||||
struct stat fileInfo;
|
||||
folly::checkUnixError(::fstat(fd, &fileInfo), "fstat on bundle failed.");
|
||||
|
||||
return std::make_unique<const JSBigFileString>(fd, fileInfo.st_size);
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
137
node_modules/react-native/ReactCommon/cxxreact/JSBigString.h
generated
vendored
Normal file
137
node_modules/react-native/ReactCommon/cxxreact/JSBigString.h
generated
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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 <folly/Exception.h>
|
||||
|
||||
#ifndef RN_EXPORT
|
||||
#ifdef _MSC_VER
|
||||
#define RN_EXPORT
|
||||
#else
|
||||
#define RN_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
// JSExecutor functions sometimes take large strings, on the order of
|
||||
// megabytes. Copying these can be expensive. Introducing a
|
||||
// move-only, non-CopyConstructible type will let the compiler ensure
|
||||
// that no copies occur. folly::MoveWrapper should be used when a
|
||||
// large string needs to be curried into a std::function<>, which must
|
||||
// by CopyConstructible.
|
||||
|
||||
class JSBigString {
|
||||
public:
|
||||
JSBigString() = default;
|
||||
|
||||
// Not copyable
|
||||
JSBigString(const JSBigString &) = delete;
|
||||
JSBigString &operator=(const JSBigString &) = delete;
|
||||
|
||||
virtual ~JSBigString() {}
|
||||
|
||||
virtual bool isAscii() const = 0;
|
||||
|
||||
// This needs to be a \0 terminated string
|
||||
virtual const char *c_str() const = 0;
|
||||
|
||||
// Length of the c_str without the NULL byte.
|
||||
virtual size_t size() const = 0;
|
||||
};
|
||||
|
||||
// Concrete JSBigString implementation which holds a std::string
|
||||
// instance.
|
||||
class JSBigStdString : public JSBigString {
|
||||
public:
|
||||
JSBigStdString(std::string str, bool isAscii = false)
|
||||
: m_isAscii(isAscii), m_str(std::move(str)) {}
|
||||
|
||||
bool isAscii() const override {
|
||||
return m_isAscii;
|
||||
}
|
||||
|
||||
const char *c_str() const override {
|
||||
return m_str.c_str();
|
||||
}
|
||||
|
||||
size_t size() const override {
|
||||
return m_str.size();
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_isAscii;
|
||||
std::string m_str;
|
||||
};
|
||||
|
||||
// Concrete JSBigString implementation which holds a heap-allocated
|
||||
// buffer, and provides an accessor for writing to it. This can be
|
||||
// used to construct a JSBigString in place, such as by reading from a
|
||||
// file.
|
||||
class RN_EXPORT JSBigBufferString : public JSBigString {
|
||||
public:
|
||||
JSBigBufferString(size_t size) : m_data(new char[size + 1]), m_size(size) {
|
||||
// Guarantee nul-termination. The caller is responsible for
|
||||
// filling in the rest of m_data.
|
||||
m_data[m_size] = '\0';
|
||||
}
|
||||
|
||||
~JSBigBufferString() {
|
||||
delete[] m_data;
|
||||
}
|
||||
|
||||
bool isAscii() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *c_str() const override {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
size_t size() const override {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
char *data() {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
private:
|
||||
char *m_data;
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
// JSBigString interface implemented by a file-backed mmap region.
|
||||
class RN_EXPORT JSBigFileString : public JSBigString {
|
||||
public:
|
||||
JSBigFileString(int fd, size_t size, off_t offset = 0);
|
||||
~JSBigFileString();
|
||||
|
||||
bool isAscii() const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *c_str() const override;
|
||||
|
||||
size_t size() const override;
|
||||
int fd() const;
|
||||
|
||||
static std::unique_ptr<const JSBigFileString> fromPath(
|
||||
const std::string &sourceURL);
|
||||
|
||||
private:
|
||||
int m_fd; // The file descriptor being mmaped
|
||||
size_t m_size; // The size of the mmaped region
|
||||
mutable off_t m_pageOff; // The offset in the mmaped region to the data.
|
||||
off_t m_mapOff; // The offset in the file to the mmaped region.
|
||||
mutable const char *m_data; // Pointer to the mmaped region.
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
42
node_modules/react-native/ReactCommon/cxxreact/JSBundleType.cpp
generated
vendored
Normal file
42
node_modules/react-native/ReactCommon/cxxreact/JSBundleType.cpp
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.
|
||||
*/
|
||||
|
||||
#include "JSBundleType.h"
|
||||
|
||||
#include <folly/Bits.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
static uint32_t constexpr RAMBundleMagicNumber = 0xFB0BD1E5;
|
||||
static uint32_t constexpr BCBundleMagicNumber = 0x6D657300;
|
||||
|
||||
ScriptTag parseTypeFromHeader(const BundleHeader &header) {
|
||||
switch (folly::Endian::little(header.magic)) {
|
||||
case RAMBundleMagicNumber:
|
||||
return ScriptTag::RAMBundle;
|
||||
case BCBundleMagicNumber:
|
||||
return ScriptTag::BCBundle;
|
||||
default:
|
||||
return ScriptTag::String;
|
||||
}
|
||||
}
|
||||
|
||||
const char *stringForScriptTag(const ScriptTag &tag) {
|
||||
switch (tag) {
|
||||
case ScriptTag::String:
|
||||
return "String";
|
||||
case ScriptTag::RAMBundle:
|
||||
return "RAM Bundle";
|
||||
case ScriptTag::BCBundle:
|
||||
return "BC Bundle";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
69
node_modules/react-native/ReactCommon/cxxreact/JSBundleType.h
generated
vendored
Normal file
69
node_modules/react-native/ReactCommon/cxxreact/JSBundleType.h
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 <folly/Portability.h>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#ifndef RN_EXPORT
|
||||
#define RN_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* ScriptTag
|
||||
*
|
||||
* Scripts given to the JS Executors to run could be in any of the following
|
||||
* formats. They are tagged so the executor knows how to run them.
|
||||
*/
|
||||
enum struct ScriptTag {
|
||||
String = 0,
|
||||
RAMBundle,
|
||||
BCBundle,
|
||||
};
|
||||
|
||||
/**
|
||||
* BundleHeader
|
||||
*
|
||||
* RAM bundles and BC bundles begin with headers. For RAM bundles this is
|
||||
* 4 bytes, for BC bundles this is 12 bytes. This structure holds the first 12
|
||||
* bytes from a bundle in a way that gives access to that information.
|
||||
*/
|
||||
FOLLY_PACK_PUSH
|
||||
struct FOLLY_PACK_ATTR BundleHeader {
|
||||
BundleHeader() {
|
||||
std::memset(this, 0, sizeof(BundleHeader));
|
||||
}
|
||||
|
||||
uint32_t magic;
|
||||
uint32_t reserved_;
|
||||
uint32_t version;
|
||||
};
|
||||
FOLLY_PACK_POP
|
||||
|
||||
/**
|
||||
* parseTypeFromHeader
|
||||
*
|
||||
* Takes the first 8 bytes of a bundle, and returns a tag describing the
|
||||
* bundle's format.
|
||||
*/
|
||||
RN_EXPORT ScriptTag parseTypeFromHeader(const BundleHeader &header);
|
||||
|
||||
/**
|
||||
* stringForScriptTag
|
||||
*
|
||||
* Convert an `ScriptTag` enum into a string, useful for emitting in errors
|
||||
* and diagnostic messages.
|
||||
*/
|
||||
RN_EXPORT const char *stringForScriptTag(const ScriptTag &tag);
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
100
node_modules/react-native/ReactCommon/cxxreact/JSDeltaBundleClient.cpp
generated
vendored
Normal file
100
node_modules/react-native/ReactCommon/cxxreact/JSDeltaBundleClient.cpp
generated
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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 "JSDeltaBundleClient.h"
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
namespace {
|
||||
std::string startupCode(const folly::dynamic *pre, const folly::dynamic *post) {
|
||||
std::ostringstream startupCode;
|
||||
|
||||
for (auto section : {pre, post}) {
|
||||
if (section != nullptr) {
|
||||
startupCode << section->getString() << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
return startupCode.str();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void JSDeltaBundleClient::patchModules(const folly::dynamic *modules) {
|
||||
for (const folly::dynamic &pair : *modules) {
|
||||
auto id = pair[0].getInt();
|
||||
auto module = pair[1];
|
||||
modules_[id] = std::move(module.getString());
|
||||
}
|
||||
}
|
||||
|
||||
void JSDeltaBundleClient::patch(const folly::dynamic &delta) {
|
||||
auto const base = delta.get_ptr("base");
|
||||
|
||||
if (base != nullptr && base->asBool()) {
|
||||
clear();
|
||||
|
||||
auto const pre = delta.get_ptr("pre");
|
||||
auto const post = delta.get_ptr("post");
|
||||
|
||||
startupCode_ = startupCode(pre, post);
|
||||
|
||||
const folly::dynamic *modules = delta.get_ptr("modules");
|
||||
if (modules != nullptr) {
|
||||
patchModules(modules);
|
||||
}
|
||||
} else {
|
||||
const folly::dynamic *deleted = delta.get_ptr("deleted");
|
||||
if (deleted != nullptr) {
|
||||
for (const folly::dynamic &id : *deleted) {
|
||||
modules_.erase(id.getInt());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO T37123645 This is deprecated but necessary in order to support older
|
||||
// versions of the Metro server.
|
||||
const folly::dynamic *modules = delta.get_ptr("modules");
|
||||
if (modules != nullptr) {
|
||||
patchModules(modules);
|
||||
}
|
||||
|
||||
const folly::dynamic *added = delta.get_ptr("added");
|
||||
if (added != nullptr) {
|
||||
patchModules(added);
|
||||
}
|
||||
|
||||
const folly::dynamic *modified = delta.get_ptr("modified");
|
||||
if (modified != nullptr) {
|
||||
patchModules(modified);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSModulesUnbundle::Module JSDeltaBundleClient::getModule(
|
||||
uint32_t moduleId) const {
|
||||
auto search = modules_.find(moduleId);
|
||||
if (search != modules_.end()) {
|
||||
return {folly::to<std::string>(search->first, ".js"), search->second};
|
||||
}
|
||||
|
||||
throw JSModulesUnbundle::ModuleNotFound(moduleId);
|
||||
}
|
||||
|
||||
std::unique_ptr<const JSBigString> JSDeltaBundleClient::getStartupCode() const {
|
||||
return std::make_unique<JSBigStdString>(startupCode_);
|
||||
}
|
||||
|
||||
void JSDeltaBundleClient::clear() {
|
||||
modules_.clear();
|
||||
startupCode_.clear();
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
51
node_modules/react-native/ReactCommon/cxxreact/JSDeltaBundleClient.h
generated
vendored
Normal file
51
node_modules/react-native/ReactCommon/cxxreact/JSDeltaBundleClient.h
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <cxxreact/JSBigString.h>
|
||||
#include <cxxreact/JSModulesUnbundle.h>
|
||||
#include <folly/dynamic.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class JSDeltaBundleClient {
|
||||
public:
|
||||
void patch(const folly::dynamic &delta);
|
||||
JSModulesUnbundle::Module getModule(uint32_t moduleId) const;
|
||||
std::unique_ptr<const JSBigString> getStartupCode() const;
|
||||
void clear();
|
||||
|
||||
private:
|
||||
std::unordered_map<uint32_t, std::string> modules_;
|
||||
std::string startupCode_;
|
||||
|
||||
void patchModules(const folly::dynamic *delta);
|
||||
};
|
||||
|
||||
class JSDeltaBundleClientRAMBundle : public JSModulesUnbundle {
|
||||
public:
|
||||
JSDeltaBundleClientRAMBundle(
|
||||
std::shared_ptr<const JSDeltaBundleClient> client)
|
||||
: client_(client) {}
|
||||
|
||||
Module getModule(uint32_t moduleId) const override {
|
||||
return client_->getModule(moduleId);
|
||||
}
|
||||
|
||||
private:
|
||||
const std::shared_ptr<const JSDeltaBundleClient> client_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
27
node_modules/react-native/ReactCommon/cxxreact/JSExecutor.cpp
generated
vendored
Normal file
27
node_modules/react-native/ReactCommon/cxxreact/JSExecutor.cpp
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.
|
||||
*/
|
||||
|
||||
#include "JSExecutor.h"
|
||||
|
||||
#include "RAMBundleRegistry.h"
|
||||
|
||||
#include <folly/Conv.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
std::string JSExecutor::getSyntheticBundlePath(
|
||||
uint32_t bundleId,
|
||||
const std::string &bundlePath) {
|
||||
if (bundleId == RAMBundleRegistry::MAIN_BUNDLE_ID) {
|
||||
return bundlePath;
|
||||
}
|
||||
return folly::to<std::string>("seg-", bundleId, ".js");
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
144
node_modules/react-native/ReactCommon/cxxreact/JSExecutor.h
generated
vendored
Normal file
144
node_modules/react-native/ReactCommon/cxxreact/JSExecutor.h
generated
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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 <cxxreact/NativeModule.h>
|
||||
#include <folly/dynamic.h>
|
||||
|
||||
#ifndef RN_EXPORT
|
||||
#define RN_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class JSBigString;
|
||||
class JSExecutor;
|
||||
class JSModulesUnbundle;
|
||||
class MessageQueueThread;
|
||||
class ModuleRegistry;
|
||||
class RAMBundleRegistry;
|
||||
|
||||
// This interface describes the delegate interface required by
|
||||
// Executor implementations to call from JS into native code.
|
||||
class ExecutorDelegate {
|
||||
public:
|
||||
virtual ~ExecutorDelegate() {}
|
||||
|
||||
virtual std::shared_ptr<ModuleRegistry> getModuleRegistry() = 0;
|
||||
|
||||
virtual void callNativeModules(
|
||||
JSExecutor &executor,
|
||||
folly::dynamic &&calls,
|
||||
bool isEndOfBatch) = 0;
|
||||
virtual MethodCallResult callSerializableNativeHook(
|
||||
JSExecutor &executor,
|
||||
unsigned int moduleId,
|
||||
unsigned int methodId,
|
||||
folly::dynamic &&args) = 0;
|
||||
};
|
||||
|
||||
using NativeExtensionsProvider =
|
||||
std::function<folly::dynamic(const std::string &)>;
|
||||
|
||||
class JSExecutorFactory {
|
||||
public:
|
||||
virtual std::unique_ptr<JSExecutor> createJSExecutor(
|
||||
std::shared_ptr<ExecutorDelegate> delegate,
|
||||
std::shared_ptr<MessageQueueThread> jsQueue) = 0;
|
||||
virtual ~JSExecutorFactory() {}
|
||||
};
|
||||
|
||||
class RN_EXPORT JSExecutor {
|
||||
public:
|
||||
/**
|
||||
* Prepares the JS runtime for React Native by installing global variables.
|
||||
* Called once before any JS is evaluated.
|
||||
*/
|
||||
virtual void initializeRuntime() = 0;
|
||||
/**
|
||||
* Execute an application script bundle in the JS context.
|
||||
*/
|
||||
virtual void loadBundle(
|
||||
std::unique_ptr<const JSBigString> script,
|
||||
std::string sourceURL) = 0;
|
||||
|
||||
/**
|
||||
* Add an application "RAM" bundle registry
|
||||
*/
|
||||
virtual void setBundleRegistry(
|
||||
std::unique_ptr<RAMBundleRegistry> bundleRegistry) = 0;
|
||||
|
||||
/**
|
||||
* Register a file path for an additional "RAM" bundle
|
||||
*/
|
||||
virtual void registerBundle(
|
||||
uint32_t bundleId,
|
||||
const std::string &bundlePath) = 0;
|
||||
|
||||
/**
|
||||
* Executes BatchedBridge.callFunctionReturnFlushedQueue with the module ID,
|
||||
* method ID and optional additional arguments in JS. The executor is
|
||||
* responsible for using Bridge->callNativeModules to invoke any necessary
|
||||
* native modules methods.
|
||||
*/
|
||||
virtual void callFunction(
|
||||
const std::string &moduleId,
|
||||
const std::string &methodId,
|
||||
const folly::dynamic &arguments) = 0;
|
||||
|
||||
/**
|
||||
* Executes BatchedBridge.invokeCallbackAndReturnFlushedQueue with the cbID,
|
||||
* and optional additional arguments in JS and returns the next queue. The
|
||||
* executor is responsible for using Bridge->callNativeModules to invoke any
|
||||
* necessary native modules methods.
|
||||
*/
|
||||
virtual void invokeCallback(
|
||||
const double callbackId,
|
||||
const folly::dynamic &arguments) = 0;
|
||||
|
||||
virtual void setGlobalVariable(
|
||||
std::string propName,
|
||||
std::unique_ptr<const JSBigString> jsonValue) = 0;
|
||||
|
||||
virtual void *getJavaScriptContext() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the underlying executor supports debugging via the
|
||||
* Chrome remote debugging protocol.
|
||||
*/
|
||||
virtual bool isInspectable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The description is displayed in the dev menu, if there is one in
|
||||
* this build. There is a default, but if this method returns a
|
||||
* non-empty string, it will be used instead.
|
||||
*/
|
||||
virtual std::string getDescription() = 0;
|
||||
|
||||
virtual void handleMemoryPressure(__unused int pressureLevel) {}
|
||||
|
||||
virtual void destroy() {}
|
||||
virtual ~JSExecutor() {}
|
||||
|
||||
virtual void flush() {}
|
||||
|
||||
static std::string getSyntheticBundlePath(
|
||||
uint32_t bundleId,
|
||||
const std::string &bundlePath);
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
131
node_modules/react-native/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp
generated
vendored
Normal file
131
node_modules/react-native/ReactCommon/cxxreact/JSIndexedRAMBundle.cpp
generated
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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 "JSIndexedRAMBundle.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
std::function<std::unique_ptr<JSModulesUnbundle>(std::string)>
|
||||
JSIndexedRAMBundle::buildFactory() {
|
||||
return [](const std::string &bundlePath) {
|
||||
return std::make_unique<JSIndexedRAMBundle>(bundlePath.c_str());
|
||||
};
|
||||
}
|
||||
|
||||
JSIndexedRAMBundle::JSIndexedRAMBundle(const char *sourcePath) {
|
||||
m_bundle = std::make_unique<std::ifstream>(sourcePath, std::ifstream::binary);
|
||||
if (!m_bundle) {
|
||||
throw std::ios_base::failure(folly::to<std::string>(
|
||||
"Bundle ", sourcePath, "cannot be opened: ", m_bundle->rdstate()));
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
JSIndexedRAMBundle::JSIndexedRAMBundle(
|
||||
std::unique_ptr<const JSBigString> script) {
|
||||
// tmpStream is needed because m_bundle is std::istream type
|
||||
// which has no member 'write'
|
||||
std::unique_ptr<std::stringstream> tmpStream =
|
||||
std::make_unique<std::stringstream>();
|
||||
tmpStream->write(script->c_str(), script->size());
|
||||
m_bundle = std::move(tmpStream);
|
||||
if (!m_bundle) {
|
||||
throw std::ios_base::failure(folly::to<std::string>(
|
||||
"Bundle from string cannot be opened: ", m_bundle->rdstate()));
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
void JSIndexedRAMBundle::init() {
|
||||
// read in magic header, number of entries, and length of the startup section
|
||||
uint32_t header[3];
|
||||
static_assert(
|
||||
sizeof(header) == 12,
|
||||
"header size must exactly match the input file format");
|
||||
|
||||
readBundle(reinterpret_cast<char *>(header), sizeof(header));
|
||||
const size_t numTableEntries = folly::Endian::little(header[1]);
|
||||
const size_t startupCodeSize = folly::Endian::little(header[2]);
|
||||
|
||||
// allocate memory for meta data and lookup table.
|
||||
m_table = ModuleTable(numTableEntries);
|
||||
m_baseOffset = sizeof(header) + m_table.byteLength();
|
||||
|
||||
// read the lookup table from the file
|
||||
readBundle(
|
||||
reinterpret_cast<char *>(m_table.data.get()), m_table.byteLength());
|
||||
|
||||
// read the startup code
|
||||
m_startupCode = std::unique_ptr<JSBigBufferString>(
|
||||
new JSBigBufferString{startupCodeSize - 1});
|
||||
|
||||
readBundle(m_startupCode->data(), startupCodeSize - 1);
|
||||
}
|
||||
|
||||
JSIndexedRAMBundle::Module JSIndexedRAMBundle::getModule(
|
||||
uint32_t moduleId) const {
|
||||
Module ret;
|
||||
ret.name = folly::to<std::string>(moduleId, ".js");
|
||||
ret.code = getModuleCode(moduleId);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::unique_ptr<const JSBigString> JSIndexedRAMBundle::getStartupCode() {
|
||||
CHECK(m_startupCode)
|
||||
<< "startup code for a RAM Bundle can only be retrieved once";
|
||||
return std::move(m_startupCode);
|
||||
}
|
||||
|
||||
std::string JSIndexedRAMBundle::getModuleCode(const uint32_t id) const {
|
||||
const auto moduleData = id < m_table.numEntries ? &m_table.data[id] : nullptr;
|
||||
|
||||
// entries without associated code have offset = 0 and length = 0
|
||||
const uint32_t length =
|
||||
moduleData ? folly::Endian::little(moduleData->length) : 0;
|
||||
if (length == 0) {
|
||||
throw std::ios_base::failure(
|
||||
folly::to<std::string>("Error loading module", id, "from RAM Bundle"));
|
||||
}
|
||||
|
||||
std::string ret(length - 1, '\0');
|
||||
readBundle(
|
||||
&ret.front(),
|
||||
length - 1,
|
||||
m_baseOffset + folly::Endian::little(moduleData->offset));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void JSIndexedRAMBundle::readBundle(char *buffer, const std::streamsize bytes)
|
||||
const {
|
||||
if (!m_bundle->read(buffer, bytes)) {
|
||||
if (m_bundle->rdstate() & std::ios::eofbit) {
|
||||
throw std::ios_base::failure("Unexpected end of RAM Bundle file");
|
||||
}
|
||||
throw std::ios_base::failure(folly::to<std::string>(
|
||||
"Error reading RAM Bundle: ", m_bundle->rdstate()));
|
||||
}
|
||||
}
|
||||
|
||||
void JSIndexedRAMBundle::readBundle(
|
||||
char *buffer,
|
||||
const std::streamsize bytes,
|
||||
const std::ifstream::pos_type position) const {
|
||||
if (!m_bundle->seekg(position)) {
|
||||
throw std::ios_base::failure(folly::to<std::string>(
|
||||
"Error reading RAM Bundle: ", m_bundle->rdstate()));
|
||||
}
|
||||
readBundle(buffer, bytes);
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
73
node_modules/react-native/ReactCommon/cxxreact/JSIndexedRAMBundle.h
generated
vendored
Normal file
73
node_modules/react-native/ReactCommon/cxxreact/JSIndexedRAMBundle.h
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 <istream>
|
||||
#include <memory>
|
||||
|
||||
#include <cxxreact/JSBigString.h>
|
||||
#include <cxxreact/JSModulesUnbundle.h>
|
||||
|
||||
#ifndef RN_EXPORT
|
||||
#define RN_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class RN_EXPORT JSIndexedRAMBundle : public JSModulesUnbundle {
|
||||
public:
|
||||
static std::function<std::unique_ptr<JSModulesUnbundle>(std::string)>
|
||||
buildFactory();
|
||||
|
||||
// Throws std::runtime_error on failure.
|
||||
JSIndexedRAMBundle(const char *sourceURL);
|
||||
JSIndexedRAMBundle(std::unique_ptr<const JSBigString> script);
|
||||
|
||||
// Throws std::runtime_error on failure.
|
||||
std::unique_ptr<const JSBigString> getStartupCode();
|
||||
// Throws std::runtime_error on failure.
|
||||
Module getModule(uint32_t moduleId) const override;
|
||||
|
||||
private:
|
||||
struct ModuleData {
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
};
|
||||
static_assert(
|
||||
sizeof(ModuleData) == 8,
|
||||
"ModuleData must not have any padding and use sizes matching input files");
|
||||
|
||||
struct ModuleTable {
|
||||
size_t numEntries;
|
||||
std::unique_ptr<ModuleData[]> data;
|
||||
ModuleTable() : numEntries(0){};
|
||||
ModuleTable(size_t entries)
|
||||
: numEntries(entries),
|
||||
data(std::unique_ptr<ModuleData[]>(new ModuleData[numEntries])){};
|
||||
size_t byteLength() const {
|
||||
return numEntries * sizeof(ModuleData);
|
||||
}
|
||||
};
|
||||
|
||||
void init();
|
||||
std::string getModuleCode(const uint32_t id) const;
|
||||
void readBundle(char *buffer, const std::streamsize bytes) const;
|
||||
void readBundle(
|
||||
char *buffer,
|
||||
const std::streamsize bytes,
|
||||
const std::istream::pos_type position) const;
|
||||
|
||||
mutable std::unique_ptr<std::istream> m_bundle;
|
||||
ModuleTable m_table;
|
||||
size_t m_baseOffset;
|
||||
std::unique_ptr<JSBigBufferString> m_startupCode;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
48
node_modules/react-native/ReactCommon/cxxreact/JSModulesUnbundle.h
generated
vendored
Normal file
48
node_modules/react-native/ReactCommon/cxxreact/JSModulesUnbundle.h
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <folly/Conv.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class JSModulesUnbundle {
|
||||
/**
|
||||
* Represents the set of JavaScript modules that the application consists of.
|
||||
* The source code of each module can be retrieved by module ID.
|
||||
*
|
||||
* The class is non-copyable because copying instances might involve copying
|
||||
* several megabytes of memory.
|
||||
*/
|
||||
public:
|
||||
class ModuleNotFound : public std::out_of_range {
|
||||
public:
|
||||
using std::out_of_range::out_of_range;
|
||||
ModuleNotFound(uint32_t moduleId)
|
||||
: std::out_of_range::out_of_range(
|
||||
folly::to<std::string>("Module not found: ", moduleId)) {}
|
||||
};
|
||||
struct Module {
|
||||
std::string name;
|
||||
std::string code;
|
||||
};
|
||||
JSModulesUnbundle() {}
|
||||
virtual ~JSModulesUnbundle() {}
|
||||
virtual Module getModule(uint32_t moduleId) const = 0;
|
||||
|
||||
private:
|
||||
JSModulesUnbundle(const JSModulesUnbundle &) = delete;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
120
node_modules/react-native/ReactCommon/cxxreact/JsArgumentHelpers-inl.h
generated
vendored
Normal file
120
node_modules/react-native/ReactCommon/cxxreact/JsArgumentHelpers-inl.h
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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 <folly/dynamic.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace xplat {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename R, typename M, typename... T>
|
||||
R jsArg1(const folly::dynamic &arg, M asFoo, const T &... desc) {
|
||||
try {
|
||||
return (arg.*asFoo)();
|
||||
} catch (const folly::TypeError &ex) {
|
||||
throw JsArgumentException(folly::to<std::string>(
|
||||
"Error converting javascript arg ", desc..., " to C++: ", ex.what()));
|
||||
} catch (const std::range_error &ex) {
|
||||
throw JsArgumentException(folly::to<std::string>(
|
||||
"Could not convert argument ",
|
||||
desc...,
|
||||
" to required type: ",
|
||||
ex.what()));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename R, typename... T>
|
||||
R jsArg(
|
||||
const folly::dynamic &arg,
|
||||
R (folly::dynamic::*asFoo)() const,
|
||||
const T &... desc) {
|
||||
return detail::jsArg1<R>(arg, asFoo, desc...);
|
||||
}
|
||||
|
||||
template <typename R, typename... T>
|
||||
R jsArg(
|
||||
const folly::dynamic &arg,
|
||||
R (folly::dynamic::*asFoo)() const &,
|
||||
const T &... desc) {
|
||||
return detail::jsArg1<R>(arg, asFoo, desc...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
// NOLINTNEXTLINE (T62192316)
|
||||
typename detail::is_dynamic<T>::type &jsArgAsDynamic(T &&args, size_t n) {
|
||||
try {
|
||||
return args[n];
|
||||
} catch (const std::out_of_range &ex) {
|
||||
// Use 1-base counting for argument description.
|
||||
throw JsArgumentException(folly::to<std::string>(
|
||||
"JavaScript provided ",
|
||||
args.size(),
|
||||
" arguments for C++ method which references at least ",
|
||||
n + 1,
|
||||
" arguments: ",
|
||||
ex.what()));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename R>
|
||||
R jsArgN(
|
||||
const folly::dynamic &args,
|
||||
size_t n,
|
||||
R (folly::dynamic::*asFoo)() const) {
|
||||
return jsArg(jsArgAsDynamic(args, n), asFoo, n);
|
||||
}
|
||||
template <typename R>
|
||||
R jsArgN(
|
||||
const folly::dynamic &args,
|
||||
size_t n,
|
||||
R (folly::dynamic::*asFoo)() const &) {
|
||||
return jsArg(jsArgAsDynamic(args, n), asFoo, n);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
// This is a helper for jsArgAsArray and jsArgAsObject.
|
||||
|
||||
template <typename T>
|
||||
typename detail::is_dynamic<T>::type &jsArgAsType(
|
||||
T &&args,
|
||||
size_t n,
|
||||
const char *required,
|
||||
bool (folly::dynamic::*isFoo)() const) {
|
||||
T &ret = jsArgAsDynamic(args, n);
|
||||
if ((ret.*isFoo)()) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Use 1-base counting for argument description.
|
||||
throw JsArgumentException(folly::to<std::string>(
|
||||
"Argument ",
|
||||
n + 1,
|
||||
" of type ",
|
||||
ret.typeName(),
|
||||
" is not required type ",
|
||||
required));
|
||||
}
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
template <typename T>
|
||||
typename detail::is_dynamic<T>::type &jsArgAsArray(T &&args, size_t n) {
|
||||
return detail::jsArgAsType(args, n, "Array", &folly::dynamic::isArray);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename detail::is_dynamic<T>::type &jsArgAsObject(T &&args, size_t n) {
|
||||
return detail::jsArgAsType(args, n, "Object", &folly::dynamic::isObject);
|
||||
}
|
||||
|
||||
} // namespace xplat
|
||||
} // namespace facebook
|
125
node_modules/react-native/ReactCommon/cxxreact/JsArgumentHelpers.h
generated
vendored
Normal file
125
node_modules/react-native/ReactCommon/cxxreact/JsArgumentHelpers.h
generated
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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 <exception>
|
||||
#include <string>
|
||||
|
||||
#include <folly/Conv.h>
|
||||
#include <folly/dynamic.h>
|
||||
|
||||
// When building a cross-platform module for React Native, arguments passed
|
||||
// from JS are represented as a folly::dynamic. This class provides helpers to
|
||||
// extract arguments from the folly::dynamic to concrete types usable by
|
||||
// cross-platform code, and converting exceptions to a JsArgumentException so
|
||||
// they can be caught and reported to RN consistently. The goal is to make the
|
||||
// jsArgAs... methods at the end simple to use should be most common, but any
|
||||
// non-detail method can be used when needed.
|
||||
|
||||
namespace facebook {
|
||||
namespace xplat {
|
||||
|
||||
class JsArgumentException : public std::logic_error {
|
||||
public:
|
||||
JsArgumentException(const std::string &msg) : std::logic_error(msg) {}
|
||||
};
|
||||
|
||||
// This extracts a single argument by calling the given method pointer on it.
|
||||
// If an exception is thrown, the additional arguments are passed to
|
||||
// folly::to<> to be included in the exception string. This will be most
|
||||
// commonly used when extracting values from non-scalar argument. The second
|
||||
// overload accepts ref-qualified member functions.
|
||||
|
||||
template <typename R, typename... T>
|
||||
R jsArg(
|
||||
const folly::dynamic &arg,
|
||||
R (folly::dynamic::*asFoo)() const,
|
||||
const T &... desc);
|
||||
template <typename R, typename... T>
|
||||
R jsArg(
|
||||
const folly::dynamic &arg,
|
||||
R (folly::dynamic::*asFoo)() const &,
|
||||
const T &... desc);
|
||||
|
||||
// This is like jsArg, but a operates on a dynamic representing an array of
|
||||
// arguments. The argument n is used both to index the array and build the
|
||||
// exception message, if any. It can be used directly, but will more often be
|
||||
// used by the type-specific methods following.
|
||||
|
||||
template <typename R>
|
||||
R jsArgN(
|
||||
const folly::dynamic &args,
|
||||
size_t n,
|
||||
R (folly::dynamic::*asFoo)() const);
|
||||
template <typename R>
|
||||
R jsArgN(
|
||||
const folly::dynamic &args,
|
||||
size_t n,
|
||||
R (folly::dynamic::*asFoo)() const &);
|
||||
|
||||
namespace detail {
|
||||
|
||||
// This is a type helper to implement functions which should work on both const
|
||||
// and non-const folly::dynamic arguments, and return a type with the same
|
||||
// constness. Basically, it causes the templates which use it to be defined
|
||||
// only for types compatible with folly::dynamic.
|
||||
template <typename T>
|
||||
struct is_dynamic {
|
||||
typedef typename std::
|
||||
enable_if<std::is_assignable<folly::dynamic, T>::value, T>::type type;
|
||||
};
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
// Easy to use conversion helpers are here:
|
||||
|
||||
// Extract the n'th arg from the given dynamic, as a dynamic. Throws a
|
||||
// JsArgumentException if there is no n'th arg in the input.
|
||||
template <typename T>
|
||||
typename detail::is_dynamic<T>::type &jsArgAsDynamic(T &&args, size_t n);
|
||||
|
||||
// Extract the n'th arg from the given dynamic, as a dynamic Array. Throws a
|
||||
// JsArgumentException if there is no n'th arg in the input, or it is not an
|
||||
// Array.
|
||||
template <typename T>
|
||||
typename detail::is_dynamic<T>::type &jsArgAsArray(T &&args, size_t n);
|
||||
|
||||
// Extract the n'th arg from the given dynamic, as a dynamic Object. Throws a
|
||||
// JsArgumentException if there is no n'th arg in the input, or it is not an
|
||||
// Object.
|
||||
template <typename T>
|
||||
typename detail::is_dynamic<T>::type &jsArgAsObject(T &&args, size_t n);
|
||||
|
||||
// Extract the n'th arg from the given dynamic, as a bool. Throws a
|
||||
// JsArgumentException if this fails for some reason.
|
||||
inline bool jsArgAsBool(const folly::dynamic &args, size_t n) {
|
||||
return jsArgN(args, n, &folly::dynamic::asBool);
|
||||
}
|
||||
|
||||
// Extract the n'th arg from the given dynamic, as an integer. Throws a
|
||||
// JsArgumentException if this fails for some reason.
|
||||
inline int64_t jsArgAsInt(const folly::dynamic &args, size_t n) {
|
||||
return jsArgN(args, n, &folly::dynamic::asInt);
|
||||
}
|
||||
|
||||
// Extract the n'th arg from the given dynamic, as a double. Throws a
|
||||
// JsArgumentException if this fails for some reason.
|
||||
inline double jsArgAsDouble(const folly::dynamic &args, size_t n) {
|
||||
return jsArgN(args, n, &folly::dynamic::asDouble);
|
||||
}
|
||||
|
||||
// Extract the n'th arg from the given dynamic, as a string. Throws a
|
||||
// JsArgumentException if this fails for some reason.
|
||||
inline std::string jsArgAsString(const folly::dynamic &args, size_t n) {
|
||||
return jsArgN(args, n, &folly::dynamic::asString);
|
||||
}
|
||||
|
||||
} // namespace xplat
|
||||
} // namespace facebook
|
||||
|
||||
#include <cxxreact/JsArgumentHelpers-inl.h>
|
29
node_modules/react-native/ReactCommon/cxxreact/MessageQueueThread.h
generated
vendored
Normal file
29
node_modules/react-native/ReactCommon/cxxreact/MessageQueueThread.h
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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 <condition_variable>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class MessageQueueThread {
|
||||
public:
|
||||
virtual ~MessageQueueThread() {}
|
||||
virtual void runOnQueue(std::function<void()> &&) = 0;
|
||||
// runOnQueueSync and quitSynchronous are dangerous. They should only be
|
||||
// used for initialization and cleanup.
|
||||
virtual void runOnQueueSync(std::function<void()> &&) = 0;
|
||||
// Once quitSynchronous() returns, no further work should run on the queue.
|
||||
virtual void quitSynchronous() = 0;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
89
node_modules/react-native/ReactCommon/cxxreact/MethodCall.cpp
generated
vendored
Normal file
89
node_modules/react-native/ReactCommon/cxxreact/MethodCall.cpp
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.
|
||||
*/
|
||||
|
||||
#include "MethodCall.h"
|
||||
|
||||
#include <folly/json.h>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
#define REQUEST_MODULE_IDS 0
|
||||
#define REQUEST_METHOD_IDS 1
|
||||
#define REQUEST_PARAMSS 2
|
||||
#define REQUEST_CALLID 3
|
||||
|
||||
static const char *errorPrefix = "Malformed calls from JS: ";
|
||||
|
||||
std::vector<MethodCall> parseMethodCalls(folly::dynamic &&jsonData) {
|
||||
if (jsonData.isNull()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!jsonData.isArray()) {
|
||||
throw std::invalid_argument(folly::to<std::string>(
|
||||
errorPrefix, "input isn't array but ", jsonData.typeName()));
|
||||
}
|
||||
|
||||
if (jsonData.size() < REQUEST_PARAMSS + 1) {
|
||||
throw std::invalid_argument(
|
||||
folly::to<std::string>(errorPrefix, "size == ", jsonData.size()));
|
||||
}
|
||||
|
||||
auto &moduleIds = jsonData[REQUEST_MODULE_IDS];
|
||||
auto &methodIds = jsonData[REQUEST_METHOD_IDS];
|
||||
auto ¶ms = jsonData[REQUEST_PARAMSS];
|
||||
int callId = -1;
|
||||
|
||||
if (!moduleIds.isArray() || !methodIds.isArray() || !params.isArray()) {
|
||||
throw std::invalid_argument(folly::to<std::string>(
|
||||
errorPrefix,
|
||||
"not all fields are arrays.\n\n",
|
||||
folly::toJson(jsonData)));
|
||||
}
|
||||
|
||||
if (moduleIds.size() != methodIds.size() ||
|
||||
moduleIds.size() != params.size()) {
|
||||
throw std::invalid_argument(folly::to<std::string>(
|
||||
errorPrefix,
|
||||
"field sizes are different.\n\n",
|
||||
folly::toJson(jsonData)));
|
||||
}
|
||||
|
||||
if (jsonData.size() > REQUEST_CALLID) {
|
||||
if (!jsonData[REQUEST_CALLID].isNumber()) {
|
||||
throw std::invalid_argument(folly::to<std::string>(
|
||||
errorPrefix, "invalid callId", jsonData[REQUEST_CALLID].typeName()));
|
||||
}
|
||||
callId = (int)jsonData[REQUEST_CALLID].asInt();
|
||||
}
|
||||
|
||||
std::vector<MethodCall> methodCalls;
|
||||
for (size_t i = 0; i < moduleIds.size(); i++) {
|
||||
if (!params[i].isArray()) {
|
||||
throw std::invalid_argument(folly::to<std::string>(
|
||||
errorPrefix,
|
||||
"method arguments isn't array but ",
|
||||
params[i].typeName()));
|
||||
}
|
||||
|
||||
methodCalls.emplace_back(
|
||||
moduleIds[i].asInt(),
|
||||
methodIds[i].asInt(),
|
||||
std::move(params[i]),
|
||||
callId);
|
||||
|
||||
// only increment callid if contains valid callid as callid is optional
|
||||
callId += (callId != -1) ? 1 : 0;
|
||||
}
|
||||
|
||||
return methodCalls;
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
36
node_modules/react-native/ReactCommon/cxxreact/MethodCall.h
generated
vendored
Normal file
36
node_modules/react-native/ReactCommon/cxxreact/MethodCall.h
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <folly/dynamic.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
struct MethodCall {
|
||||
int moduleId;
|
||||
int methodId;
|
||||
folly::dynamic arguments;
|
||||
int callId;
|
||||
|
||||
MethodCall(int mod, int meth, folly::dynamic &&args, int cid)
|
||||
: moduleId(mod),
|
||||
methodId(meth),
|
||||
arguments(std::move(args)),
|
||||
callId(cid) {}
|
||||
};
|
||||
|
||||
/// \throws std::invalid_argument
|
||||
std::vector<MethodCall> parseMethodCalls(folly::dynamic &&calls);
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
186
node_modules/react-native/ReactCommon/cxxreact/ModuleRegistry.cpp
generated
vendored
Normal file
186
node_modules/react-native/ReactCommon/cxxreact/ModuleRegistry.cpp
generated
vendored
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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 "ModuleRegistry.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include "NativeModule.h"
|
||||
#include "SystraceSection.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
namespace {
|
||||
|
||||
std::string normalizeName(std::string name) {
|
||||
// TODO mhorowitz #10487027: This is super ugly. We should just
|
||||
// change iOS to emit normalized names, drop the "RK..." from
|
||||
// names hardcoded in Android, and then delete this and the
|
||||
// similar hacks in js.
|
||||
if (name.compare(0, 3, "RCT") == 0) {
|
||||
return name.substr(3);
|
||||
} else if (name.compare(0, 2, "RK") == 0) {
|
||||
return name.substr(2);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ModuleRegistry::ModuleRegistry(
|
||||
std::vector<std::unique_ptr<NativeModule>> modules,
|
||||
ModuleNotFoundCallback callback)
|
||||
: modules_{std::move(modules)}, moduleNotFoundCallback_{callback} {}
|
||||
|
||||
void ModuleRegistry::updateModuleNamesFromIndex(size_t index) {
|
||||
for (; index < modules_.size(); index++) {
|
||||
std::string name = normalizeName(modules_[index]->getName());
|
||||
modulesByName_[name] = index;
|
||||
}
|
||||
}
|
||||
|
||||
void ModuleRegistry::registerModules(
|
||||
std::vector<std::unique_ptr<NativeModule>> modules) {
|
||||
SystraceSection s_("ModuleRegistry::registerModules");
|
||||
if (modules_.empty() && unknownModules_.empty()) {
|
||||
modules_ = std::move(modules);
|
||||
} else {
|
||||
size_t modulesSize = modules_.size();
|
||||
size_t addModulesSize = modules.size();
|
||||
bool addToNames = !modulesByName_.empty();
|
||||
modules_.reserve(modulesSize + addModulesSize);
|
||||
std::move(modules.begin(), modules.end(), std::back_inserter(modules_));
|
||||
if (!unknownModules_.empty()) {
|
||||
for (size_t index = modulesSize; index < modulesSize + addModulesSize;
|
||||
index++) {
|
||||
std::string name = normalizeName(modules_[index]->getName());
|
||||
auto it = unknownModules_.find(name);
|
||||
if (it != unknownModules_.end()) {
|
||||
throw std::runtime_error(folly::to<std::string>(
|
||||
"module ",
|
||||
name,
|
||||
" was required without being registered and is now being registered."));
|
||||
} else if (addToNames) {
|
||||
modulesByName_[name] = index;
|
||||
}
|
||||
}
|
||||
} else if (addToNames) {
|
||||
updateModuleNamesFromIndex(modulesSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> ModuleRegistry::moduleNames() {
|
||||
SystraceSection s_("ModuleRegistry::moduleNames");
|
||||
std::vector<std::string> names;
|
||||
for (size_t i = 0; i < modules_.size(); i++) {
|
||||
std::string name = normalizeName(modules_[i]->getName());
|
||||
modulesByName_[name] = i;
|
||||
names.push_back(std::move(name));
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
folly::Optional<ModuleConfig> ModuleRegistry::getConfig(
|
||||
const std::string &name) {
|
||||
SystraceSection s("ModuleRegistry::getConfig", "module", name);
|
||||
|
||||
// Initialize modulesByName_
|
||||
if (modulesByName_.empty() && !modules_.empty()) {
|
||||
moduleNames();
|
||||
}
|
||||
|
||||
auto it = modulesByName_.find(name);
|
||||
|
||||
if (it == modulesByName_.end()) {
|
||||
if (unknownModules_.find(name) != unknownModules_.end()) {
|
||||
return folly::none;
|
||||
}
|
||||
if (!moduleNotFoundCallback_ || !moduleNotFoundCallback_(name) ||
|
||||
(it = modulesByName_.find(name)) == modulesByName_.end()) {
|
||||
unknownModules_.insert(name);
|
||||
return folly::none;
|
||||
}
|
||||
}
|
||||
size_t index = it->second;
|
||||
|
||||
CHECK(index < modules_.size());
|
||||
NativeModule *module = modules_[index].get();
|
||||
|
||||
// string name, object constants, array methodNames (methodId is index),
|
||||
// [array promiseMethodIds], [array syncMethodIds]
|
||||
folly::dynamic config = folly::dynamic::array(name);
|
||||
|
||||
{
|
||||
SystraceSection s_("ModuleRegistry::getConstants", "module", name);
|
||||
config.push_back(module->getConstants());
|
||||
}
|
||||
|
||||
{
|
||||
SystraceSection s_("ModuleRegistry::getMethods", "module", name);
|
||||
std::vector<MethodDescriptor> methods = module->getMethods();
|
||||
|
||||
folly::dynamic methodNames = folly::dynamic::array;
|
||||
folly::dynamic promiseMethodIds = folly::dynamic::array;
|
||||
folly::dynamic syncMethodIds = folly::dynamic::array;
|
||||
|
||||
for (auto &descriptor : methods) {
|
||||
// TODO: #10487027 compare tags instead of doing string comparison?
|
||||
methodNames.push_back(std::move(descriptor.name));
|
||||
if (descriptor.type == "promise") {
|
||||
promiseMethodIds.push_back(methodNames.size() - 1);
|
||||
} else if (descriptor.type == "sync") {
|
||||
syncMethodIds.push_back(methodNames.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!methodNames.empty()) {
|
||||
config.push_back(std::move(methodNames));
|
||||
if (!promiseMethodIds.empty() || !syncMethodIds.empty()) {
|
||||
config.push_back(std::move(promiseMethodIds));
|
||||
if (!syncMethodIds.empty()) {
|
||||
config.push_back(std::move(syncMethodIds));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.size() == 2 && config[1].empty()) {
|
||||
// no constants or methods
|
||||
return folly::none;
|
||||
} else {
|
||||
return ModuleConfig{index, config};
|
||||
}
|
||||
}
|
||||
|
||||
void ModuleRegistry::callNativeMethod(
|
||||
unsigned int moduleId,
|
||||
unsigned int methodId,
|
||||
folly::dynamic &¶ms,
|
||||
int callId) {
|
||||
if (moduleId >= modules_.size()) {
|
||||
throw std::runtime_error(folly::to<std::string>(
|
||||
"moduleId ", moduleId, " out of range [0..", modules_.size(), ")"));
|
||||
}
|
||||
modules_[moduleId]->invoke(methodId, std::move(params), callId);
|
||||
}
|
||||
|
||||
MethodCallResult ModuleRegistry::callSerializableNativeHook(
|
||||
unsigned int moduleId,
|
||||
unsigned int methodId,
|
||||
folly::dynamic &¶ms) {
|
||||
if (moduleId >= modules_.size()) {
|
||||
throw std::runtime_error(folly::to<std::string>(
|
||||
"moduleId ", moduleId, "out of range [0..", modules_.size(), ")"));
|
||||
}
|
||||
return modules_[moduleId]->callSerializableNativeHook(
|
||||
methodId, std::move(params));
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
87
node_modules/react-native/ReactCommon/cxxreact/ModuleRegistry.h
generated
vendored
Normal file
87
node_modules/react-native/ReactCommon/cxxreact/ModuleRegistry.h
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <cxxreact/JSExecutor.h>
|
||||
#include <folly/Optional.h>
|
||||
#include <folly/dynamic.h>
|
||||
|
||||
#ifndef RN_EXPORT
|
||||
#define RN_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class NativeModule;
|
||||
|
||||
struct ModuleConfig {
|
||||
size_t index;
|
||||
folly::dynamic config;
|
||||
};
|
||||
|
||||
class RN_EXPORT ModuleRegistry {
|
||||
public:
|
||||
// not implemented:
|
||||
// onBatchComplete: see
|
||||
// https://our.intern.facebook.com/intern/tasks/?t=5279396 getModule: only
|
||||
// used by views getAllModules: only used for cleanup; use RAII instead
|
||||
// notifyCatalystInstanceInitialized: this is really only used by view-related
|
||||
// code notifyCatalystInstanceDestroy: use RAII instead
|
||||
|
||||
using ModuleNotFoundCallback = std::function<bool(const std::string &name)>;
|
||||
|
||||
ModuleRegistry(
|
||||
std::vector<std::unique_ptr<NativeModule>> modules,
|
||||
ModuleNotFoundCallback callback = nullptr);
|
||||
void registerModules(std::vector<std::unique_ptr<NativeModule>> modules);
|
||||
|
||||
std::vector<std::string> moduleNames();
|
||||
|
||||
folly::Optional<ModuleConfig> getConfig(const std::string &name);
|
||||
|
||||
void callNativeMethod(
|
||||
unsigned int moduleId,
|
||||
unsigned int methodId,
|
||||
folly::dynamic &¶ms,
|
||||
int callId);
|
||||
MethodCallResult callSerializableNativeHook(
|
||||
unsigned int moduleId,
|
||||
unsigned int methodId,
|
||||
folly::dynamic &&args);
|
||||
|
||||
private:
|
||||
// This is always populated
|
||||
std::vector<std::unique_ptr<NativeModule>> modules_;
|
||||
|
||||
// This is used to extend the population of modulesByName_ if registerModules
|
||||
// is called after moduleNames
|
||||
void updateModuleNamesFromIndex(size_t size);
|
||||
|
||||
// This is only populated if moduleNames() is called. Values are indices into
|
||||
// modules_.
|
||||
std::unordered_map<std::string, size_t> modulesByName_;
|
||||
|
||||
// This is populated with modules that are requested via getConfig but are
|
||||
// unknown. An error will be thrown if they are subsequently added to the
|
||||
// registry.
|
||||
std::unordered_set<std::string> unknownModules_;
|
||||
|
||||
// Function will be called if a module was requested but was not found.
|
||||
// If the function returns true, ModuleRegistry will try to find the module
|
||||
// again (assuming it's registered) If the functon returns false,
|
||||
// ModuleRegistry will not try to find the module and return nullptr instead.
|
||||
ModuleNotFoundCallback moduleNotFoundCallback_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
44
node_modules/react-native/ReactCommon/cxxreact/NativeModule.h
generated
vendored
Normal file
44
node_modules/react-native/ReactCommon/cxxreact/NativeModule.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
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <folly/Optional.h>
|
||||
#include <folly/dynamic.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
struct MethodDescriptor {
|
||||
std::string name;
|
||||
// type is one of js MessageQueue.MethodTypes
|
||||
std::string type;
|
||||
|
||||
MethodDescriptor(std::string n, std::string t)
|
||||
: name(std::move(n)), type(std::move(t)) {}
|
||||
};
|
||||
|
||||
using MethodCallResult = folly::Optional<folly::dynamic>;
|
||||
|
||||
class NativeModule {
|
||||
public:
|
||||
virtual ~NativeModule() {}
|
||||
virtual std::string getName() = 0;
|
||||
virtual std::vector<MethodDescriptor> getMethods() = 0;
|
||||
virtual folly::dynamic getConstants() = 0;
|
||||
virtual void
|
||||
invoke(unsigned int reactMethodId, folly::dynamic &¶ms, int callId) = 0;
|
||||
virtual MethodCallResult callSerializableNativeHook(
|
||||
unsigned int reactMethodId,
|
||||
folly::dynamic &&args) = 0;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
335
node_modules/react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp
generated
vendored
Normal file
335
node_modules/react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp
generated
vendored
Normal file
@ -0,0 +1,335 @@
|
||||
/*
|
||||
* 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 "NativeToJsBridge.h"
|
||||
|
||||
#include <ReactCommon/CallInvoker.h>
|
||||
#include <folly/MoveWrapper.h>
|
||||
#include <folly/json.h>
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include "Instance.h"
|
||||
#include "JSBigString.h"
|
||||
#include "MessageQueueThread.h"
|
||||
#include "MethodCall.h"
|
||||
#include "ModuleRegistry.h"
|
||||
#include "RAMBundleRegistry.h"
|
||||
#include "SystraceSection.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
#include <fbsystrace.h>
|
||||
using fbsystrace::FbSystraceAsyncFlow;
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
// This class manages calls from JS to native code.
|
||||
class JsToNativeBridge : public react::ExecutorDelegate {
|
||||
public:
|
||||
JsToNativeBridge(
|
||||
std::shared_ptr<ModuleRegistry> registry,
|
||||
std::shared_ptr<InstanceCallback> callback)
|
||||
: m_registry(registry), m_callback(callback) {}
|
||||
|
||||
std::shared_ptr<ModuleRegistry> getModuleRegistry() override {
|
||||
return m_registry;
|
||||
}
|
||||
|
||||
bool isBatchActive() {
|
||||
return m_batchHadNativeModuleOrTurboModuleCalls;
|
||||
}
|
||||
|
||||
void callNativeModules(
|
||||
__unused JSExecutor &executor,
|
||||
folly::dynamic &&calls,
|
||||
bool isEndOfBatch) override {
|
||||
CHECK(m_registry || calls.empty())
|
||||
<< "native module calls cannot be completed with no native modules";
|
||||
m_batchHadNativeModuleOrTurboModuleCalls =
|
||||
m_batchHadNativeModuleOrTurboModuleCalls || !calls.empty();
|
||||
|
||||
// An exception anywhere in here stops processing of the batch. This
|
||||
// was the behavior of the Android bridge, and since exception handling
|
||||
// terminates the whole bridge, there's not much point in continuing.
|
||||
for (auto &call : parseMethodCalls(std::move(calls))) {
|
||||
m_registry->callNativeMethod(
|
||||
call.moduleId, call.methodId, std::move(call.arguments), call.callId);
|
||||
}
|
||||
if (isEndOfBatch) {
|
||||
// onBatchComplete will be called on the native (module) queue, but
|
||||
// decrementPendingJSCalls will be called sync. Be aware that the bridge
|
||||
// may still be processing native calls when the bridge idle signaler
|
||||
// fires.
|
||||
if (m_batchHadNativeModuleOrTurboModuleCalls) {
|
||||
m_callback->onBatchComplete();
|
||||
m_batchHadNativeModuleOrTurboModuleCalls = false;
|
||||
}
|
||||
m_callback->decrementPendingJSCalls();
|
||||
}
|
||||
}
|
||||
|
||||
MethodCallResult callSerializableNativeHook(
|
||||
__unused JSExecutor &executor,
|
||||
unsigned int moduleId,
|
||||
unsigned int methodId,
|
||||
folly::dynamic &&args) override {
|
||||
return m_registry->callSerializableNativeHook(
|
||||
moduleId, methodId, std::move(args));
|
||||
}
|
||||
|
||||
void recordTurboModuleAsyncMethodCall() {
|
||||
m_batchHadNativeModuleOrTurboModuleCalls = true;
|
||||
}
|
||||
|
||||
private:
|
||||
// These methods are always invoked from an Executor. The NativeToJsBridge
|
||||
// keeps a reference to the executor, and when destroy() is called, the
|
||||
// executor is destroyed synchronously on its queue.
|
||||
std::shared_ptr<ModuleRegistry> m_registry;
|
||||
std::shared_ptr<InstanceCallback> m_callback;
|
||||
bool m_batchHadNativeModuleOrTurboModuleCalls = false;
|
||||
};
|
||||
|
||||
NativeToJsBridge::NativeToJsBridge(
|
||||
JSExecutorFactory *jsExecutorFactory,
|
||||
std::shared_ptr<ModuleRegistry> registry,
|
||||
std::shared_ptr<MessageQueueThread> jsQueue,
|
||||
std::shared_ptr<InstanceCallback> callback)
|
||||
: m_destroyed(std::make_shared<bool>(false)),
|
||||
m_delegate(std::make_shared<JsToNativeBridge>(registry, callback)),
|
||||
m_executor(jsExecutorFactory->createJSExecutor(m_delegate, jsQueue)),
|
||||
m_executorMessageQueueThread(std::move(jsQueue)),
|
||||
m_inspectable(m_executor->isInspectable()) {}
|
||||
|
||||
// This must be called on the same thread on which the constructor was called.
|
||||
NativeToJsBridge::~NativeToJsBridge() {
|
||||
CHECK(*m_destroyed)
|
||||
<< "NativeToJsBridge::destroy() must be called before deallocating the NativeToJsBridge!";
|
||||
}
|
||||
|
||||
void NativeToJsBridge::initializeRuntime() {
|
||||
runOnExecutorQueue(
|
||||
[](JSExecutor *executor) mutable { executor->initializeRuntime(); });
|
||||
}
|
||||
|
||||
void NativeToJsBridge::loadBundle(
|
||||
std::unique_ptr<RAMBundleRegistry> bundleRegistry,
|
||||
std::unique_ptr<const JSBigString> startupScript,
|
||||
std::string startupScriptSourceURL) {
|
||||
runOnExecutorQueue(
|
||||
[this,
|
||||
bundleRegistryWrap = folly::makeMoveWrapper(std::move(bundleRegistry)),
|
||||
startupScript = folly::makeMoveWrapper(std::move(startupScript)),
|
||||
startupScriptSourceURL =
|
||||
std::move(startupScriptSourceURL)](JSExecutor *executor) mutable {
|
||||
auto bundleRegistry = bundleRegistryWrap.move();
|
||||
if (bundleRegistry) {
|
||||
executor->setBundleRegistry(std::move(bundleRegistry));
|
||||
}
|
||||
try {
|
||||
executor->loadBundle(
|
||||
std::move(*startupScript), std::move(startupScriptSourceURL));
|
||||
} catch (...) {
|
||||
m_applicationScriptHasFailure = true;
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void NativeToJsBridge::loadBundleSync(
|
||||
std::unique_ptr<RAMBundleRegistry> bundleRegistry,
|
||||
std::unique_ptr<const JSBigString> startupScript,
|
||||
std::string startupScriptSourceURL) {
|
||||
if (bundleRegistry) {
|
||||
m_executor->setBundleRegistry(std::move(bundleRegistry));
|
||||
}
|
||||
try {
|
||||
m_executor->loadBundle(
|
||||
std::move(startupScript), std::move(startupScriptSourceURL));
|
||||
} catch (...) {
|
||||
m_applicationScriptHasFailure = true;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void NativeToJsBridge::callFunction(
|
||||
std::string &&module,
|
||||
std::string &&method,
|
||||
folly::dynamic &&arguments) {
|
||||
int systraceCookie = -1;
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
systraceCookie = m_systraceCookie++;
|
||||
FbSystraceAsyncFlow::begin(
|
||||
TRACE_TAG_REACT_CXX_BRIDGE, "JSCall", systraceCookie);
|
||||
#endif
|
||||
|
||||
runOnExecutorQueue([this,
|
||||
module = std::move(module),
|
||||
method = std::move(method),
|
||||
arguments = std::move(arguments),
|
||||
systraceCookie](JSExecutor *executor) {
|
||||
if (m_applicationScriptHasFailure) {
|
||||
LOG(ERROR)
|
||||
<< "Attempting to call JS function on a bad application bundle: "
|
||||
<< module.c_str() << "." << method.c_str() << "()";
|
||||
throw std::runtime_error(
|
||||
"Attempting to call JS function on a bad application bundle: " +
|
||||
module + "." + method + "()");
|
||||
}
|
||||
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
FbSystraceAsyncFlow::end(
|
||||
TRACE_TAG_REACT_CXX_BRIDGE, "JSCall", systraceCookie);
|
||||
SystraceSection s(
|
||||
"NativeToJsBridge::callFunction", "module", module, "method", method);
|
||||
#else
|
||||
(void)(systraceCookie);
|
||||
#endif
|
||||
// This is safe because we are running on the executor's thread: it won't
|
||||
// destruct until after it's been unregistered (which we check above) and
|
||||
// that will happen on this thread
|
||||
executor->callFunction(module, method, arguments);
|
||||
});
|
||||
}
|
||||
|
||||
void NativeToJsBridge::invokeCallback(
|
||||
double callbackId,
|
||||
folly::dynamic &&arguments) {
|
||||
int systraceCookie = -1;
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
systraceCookie = m_systraceCookie++;
|
||||
FbSystraceAsyncFlow::begin(
|
||||
TRACE_TAG_REACT_CXX_BRIDGE, "<callback>", systraceCookie);
|
||||
#endif
|
||||
|
||||
runOnExecutorQueue(
|
||||
[this, callbackId, arguments = std::move(arguments), systraceCookie](
|
||||
JSExecutor *executor) {
|
||||
if (m_applicationScriptHasFailure) {
|
||||
LOG(ERROR)
|
||||
<< "Attempting to call JS callback on a bad application bundle: "
|
||||
<< callbackId;
|
||||
throw std::runtime_error(
|
||||
"Attempting to invoke JS callback on a bad application bundle.");
|
||||
}
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
FbSystraceAsyncFlow::end(
|
||||
TRACE_TAG_REACT_CXX_BRIDGE, "<callback>", systraceCookie);
|
||||
SystraceSection s("NativeToJsBridge::invokeCallback");
|
||||
#else
|
||||
(void)(systraceCookie);
|
||||
#endif
|
||||
executor->invokeCallback(callbackId, arguments);
|
||||
});
|
||||
}
|
||||
|
||||
void NativeToJsBridge::registerBundle(
|
||||
uint32_t bundleId,
|
||||
const std::string &bundlePath) {
|
||||
runOnExecutorQueue([bundleId, bundlePath](JSExecutor *executor) {
|
||||
executor->registerBundle(bundleId, bundlePath);
|
||||
});
|
||||
}
|
||||
|
||||
void NativeToJsBridge::setGlobalVariable(
|
||||
std::string propName,
|
||||
std::unique_ptr<const JSBigString> jsonValue) {
|
||||
runOnExecutorQueue([propName = std::move(propName),
|
||||
jsonValue = folly::makeMoveWrapper(std::move(jsonValue))](
|
||||
JSExecutor *executor) mutable {
|
||||
executor->setGlobalVariable(propName, jsonValue.move());
|
||||
});
|
||||
}
|
||||
|
||||
void *NativeToJsBridge::getJavaScriptContext() {
|
||||
// TODO(cjhopman): this seems unsafe unless we require that it is only called
|
||||
// on the main js queue.
|
||||
return m_executor->getJavaScriptContext();
|
||||
}
|
||||
|
||||
bool NativeToJsBridge::isInspectable() {
|
||||
return m_inspectable;
|
||||
}
|
||||
|
||||
bool NativeToJsBridge::isBatchActive() {
|
||||
return m_delegate->isBatchActive();
|
||||
}
|
||||
|
||||
void NativeToJsBridge::handleMemoryPressure(int pressureLevel) {
|
||||
runOnExecutorQueue([=](JSExecutor *executor) {
|
||||
executor->handleMemoryPressure(pressureLevel);
|
||||
});
|
||||
}
|
||||
|
||||
void NativeToJsBridge::destroy() {
|
||||
// All calls made through runOnExecutorQueue have an early exit if
|
||||
// m_destroyed is true. Setting this before the runOnQueueSync will cause
|
||||
// pending work to be cancelled and we won't have to wait for it.
|
||||
*m_destroyed = true;
|
||||
m_executorMessageQueueThread->runOnQueueSync([this] {
|
||||
m_executor->destroy();
|
||||
m_executorMessageQueueThread->quitSynchronous();
|
||||
m_executor = nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
void NativeToJsBridge::runOnExecutorQueue(
|
||||
std::function<void(JSExecutor *)> task) {
|
||||
if (*m_destroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<bool> isDestroyed = m_destroyed;
|
||||
m_executorMessageQueueThread->runOnQueue(
|
||||
[this, isDestroyed, task = std::move(task)] {
|
||||
if (*isDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The executor is guaranteed to be valid for the duration of the task
|
||||
// because:
|
||||
// 1. the executor is only destroyed after it is unregistered
|
||||
// 2. the executor is unregistered on this queue
|
||||
// 3. we just confirmed that the executor hasn't been unregistered above
|
||||
task(m_executor.get());
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<CallInvoker> NativeToJsBridge::getDecoratedNativeCallInvoker(
|
||||
std::shared_ptr<CallInvoker> nativeInvoker) {
|
||||
class NativeCallInvoker : public CallInvoker {
|
||||
private:
|
||||
std::weak_ptr<JsToNativeBridge> m_jsToNativeBridge;
|
||||
std::shared_ptr<CallInvoker> m_nativeInvoker;
|
||||
|
||||
public:
|
||||
NativeCallInvoker(
|
||||
std::weak_ptr<JsToNativeBridge> jsToNativeBridge,
|
||||
std::shared_ptr<CallInvoker> nativeInvoker)
|
||||
: m_jsToNativeBridge(jsToNativeBridge),
|
||||
m_nativeInvoker(nativeInvoker) {}
|
||||
|
||||
void invokeAsync(std::function<void()> &&func) override {
|
||||
if (auto strongJsToNativeBridge = m_jsToNativeBridge.lock()) {
|
||||
strongJsToNativeBridge->recordTurboModuleAsyncMethodCall();
|
||||
}
|
||||
m_nativeInvoker->invokeAsync(std::move(func));
|
||||
}
|
||||
|
||||
void invokeSync(std::function<void()> &&func) override {
|
||||
m_nativeInvoker->invokeSync(std::move(func));
|
||||
}
|
||||
};
|
||||
|
||||
return std::make_shared<NativeCallInvoker>(m_delegate, nativeInvoker);
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
135
node_modules/react-native/ReactCommon/cxxreact/NativeToJsBridge.h
generated
vendored
Normal file
135
node_modules/react-native/ReactCommon/cxxreact/NativeToJsBridge.h
generated
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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 <atomic>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <ReactCommon/CallInvoker.h>
|
||||
#include <cxxreact/JSExecutor.h>
|
||||
|
||||
namespace folly {
|
||||
struct dynamic;
|
||||
}
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
struct InstanceCallback;
|
||||
class JsToNativeBridge;
|
||||
class MessageQueueThread;
|
||||
class ModuleRegistry;
|
||||
class RAMBundleRegistry;
|
||||
|
||||
// This class manages calls from native code to JS. It also manages
|
||||
// executors and their threads. All functions here can be called from
|
||||
// any thread.
|
||||
//
|
||||
// Except for loadBundleSync(), all void methods will queue
|
||||
// work to run on the jsQueue passed to the ctor, and return
|
||||
// immediately.
|
||||
class NativeToJsBridge {
|
||||
public:
|
||||
friend class JsToNativeBridge;
|
||||
|
||||
/**
|
||||
* This must be called on the main JS thread.
|
||||
*/
|
||||
NativeToJsBridge(
|
||||
JSExecutorFactory *jsExecutorFactory,
|
||||
std::shared_ptr<ModuleRegistry> registry,
|
||||
std::shared_ptr<MessageQueueThread> jsQueue,
|
||||
std::shared_ptr<InstanceCallback> callback);
|
||||
virtual ~NativeToJsBridge();
|
||||
|
||||
/**
|
||||
* Executes a function with the module ID and method ID and any additional
|
||||
* arguments in JS.
|
||||
*/
|
||||
void callFunction(
|
||||
std::string &&module,
|
||||
std::string &&method,
|
||||
folly::dynamic &&args);
|
||||
|
||||
/**
|
||||
* Invokes a callback with the cbID, and optional additional arguments in JS.
|
||||
*/
|
||||
void invokeCallback(double callbackId, folly::dynamic &&args);
|
||||
|
||||
/**
|
||||
* Sets global variables in the JS Context.
|
||||
*/
|
||||
void initializeRuntime();
|
||||
|
||||
/**
|
||||
* Starts the JS application. If bundleRegistry is non-null, then it is
|
||||
* used to fetch JavaScript modules as individual scripts.
|
||||
* Otherwise, the script is assumed to include all the modules.
|
||||
*/
|
||||
void loadBundle(
|
||||
std::unique_ptr<RAMBundleRegistry> bundleRegistry,
|
||||
std::unique_ptr<const JSBigString> startupCode,
|
||||
std::string sourceURL);
|
||||
void loadBundleSync(
|
||||
std::unique_ptr<RAMBundleRegistry> bundleRegistry,
|
||||
std::unique_ptr<const JSBigString> startupCode,
|
||||
std::string sourceURL);
|
||||
|
||||
void registerBundle(uint32_t bundleId, const std::string &bundlePath);
|
||||
void setGlobalVariable(
|
||||
std::string propName,
|
||||
std::unique_ptr<const JSBigString> jsonValue);
|
||||
void *getJavaScriptContext();
|
||||
bool isInspectable();
|
||||
bool isBatchActive();
|
||||
|
||||
void handleMemoryPressure(int pressureLevel);
|
||||
|
||||
/**
|
||||
* Synchronously tears down the bridge and the main executor.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
void runOnExecutorQueue(std::function<void(JSExecutor *)> task);
|
||||
|
||||
/**
|
||||
* Native CallInvoker is used by TurboModules to schedule work on the
|
||||
* NativeModule thread(s).
|
||||
*/
|
||||
std::shared_ptr<CallInvoker> getDecoratedNativeCallInvoker(
|
||||
std::shared_ptr<CallInvoker> nativeInvoker);
|
||||
|
||||
private:
|
||||
// This is used to avoid a race condition where a proxyCallback gets queued
|
||||
// after ~NativeToJsBridge(), on the same thread. In that case, the callback
|
||||
// will try to run the task on m_callback which will have been destroyed
|
||||
// within ~NativeToJsBridge(), thus causing a SIGSEGV.
|
||||
std::shared_ptr<bool> m_destroyed;
|
||||
std::shared_ptr<JsToNativeBridge> m_delegate;
|
||||
std::unique_ptr<JSExecutor> m_executor;
|
||||
std::shared_ptr<MessageQueueThread> m_executorMessageQueueThread;
|
||||
|
||||
// Memoize this on the JS thread, so that it can be inspected from
|
||||
// any thread later. This assumes inspectability doesn't change for
|
||||
// a JSExecutor instance, which is true for all existing implementations.
|
||||
bool m_inspectable;
|
||||
|
||||
// Keep track of whether the JS bundle containing the application logic causes
|
||||
// exception when evaluated initially. If so, more calls to JS will very
|
||||
// likely fail as well, so this flag can help prevent them.
|
||||
bool m_applicationScriptHasFailure = false;
|
||||
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
std::atomic_uint_least32_t m_systraceCookie = ATOMIC_VAR_INIT(0);
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
78
node_modules/react-native/ReactCommon/cxxreact/RAMBundleRegistry.cpp
generated
vendored
Normal file
78
node_modules/react-native/ReactCommon/cxxreact/RAMBundleRegistry.cpp
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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 "RAMBundleRegistry.h"
|
||||
|
||||
#include <folly/String.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
constexpr uint32_t RAMBundleRegistry::MAIN_BUNDLE_ID;
|
||||
|
||||
std::unique_ptr<RAMBundleRegistry> RAMBundleRegistry::singleBundleRegistry(
|
||||
std::unique_ptr<JSModulesUnbundle> mainBundle) {
|
||||
return std::make_unique<RAMBundleRegistry>(std::move(mainBundle));
|
||||
}
|
||||
|
||||
std::unique_ptr<RAMBundleRegistry> RAMBundleRegistry::multipleBundlesRegistry(
|
||||
std::unique_ptr<JSModulesUnbundle> mainBundle,
|
||||
std::function<std::unique_ptr<JSModulesUnbundle>(std::string)> factory) {
|
||||
return std::make_unique<RAMBundleRegistry>(
|
||||
std::move(mainBundle), std::move(factory));
|
||||
}
|
||||
|
||||
RAMBundleRegistry::RAMBundleRegistry(
|
||||
std::unique_ptr<JSModulesUnbundle> mainBundle,
|
||||
std::function<std::unique_ptr<JSModulesUnbundle>(std::string)> factory)
|
||||
: m_factory(std::move(factory)) {
|
||||
m_bundles.emplace(MAIN_BUNDLE_ID, std::move(mainBundle));
|
||||
}
|
||||
|
||||
void RAMBundleRegistry::registerBundle(
|
||||
uint32_t bundleId,
|
||||
std::string bundlePath) {
|
||||
m_bundlePaths.emplace(bundleId, std::move(bundlePath));
|
||||
}
|
||||
|
||||
JSModulesUnbundle::Module RAMBundleRegistry::getModule(
|
||||
uint32_t bundleId,
|
||||
uint32_t moduleId) {
|
||||
if (m_bundles.find(bundleId) == m_bundles.end()) {
|
||||
if (!m_factory) {
|
||||
throw std::runtime_error(
|
||||
"You need to register factory function in order to "
|
||||
"support multiple RAM bundles.");
|
||||
}
|
||||
|
||||
auto bundlePath = m_bundlePaths.find(bundleId);
|
||||
if (bundlePath == m_bundlePaths.end()) {
|
||||
throw std::runtime_error(
|
||||
"In order to fetch RAM bundle from the registry, its file "
|
||||
"path needs to be registered first.");
|
||||
}
|
||||
m_bundles.emplace(bundleId, m_factory(bundlePath->second));
|
||||
}
|
||||
|
||||
auto module = getBundle(bundleId)->getModule(moduleId);
|
||||
if (bundleId == MAIN_BUNDLE_ID) {
|
||||
return module;
|
||||
}
|
||||
return {
|
||||
folly::to<std::string>("seg-", bundleId, '_', std::move(module.name)),
|
||||
std::move(module.code),
|
||||
};
|
||||
}
|
||||
|
||||
JSModulesUnbundle *RAMBundleRegistry::getBundle(uint32_t bundleId) const {
|
||||
return m_bundles.at(bundleId).get();
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
56
node_modules/react-native/ReactCommon/cxxreact/RAMBundleRegistry.h
generated
vendored
Normal file
56
node_modules/react-native/ReactCommon/cxxreact/RAMBundleRegistry.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 <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include <cxxreact/JSModulesUnbundle.h>
|
||||
|
||||
#ifndef RN_EXPORT
|
||||
#define RN_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class RN_EXPORT RAMBundleRegistry {
|
||||
public:
|
||||
constexpr static uint32_t MAIN_BUNDLE_ID = 0;
|
||||
|
||||
static std::unique_ptr<RAMBundleRegistry> singleBundleRegistry(
|
||||
std::unique_ptr<JSModulesUnbundle> mainBundle);
|
||||
static std::unique_ptr<RAMBundleRegistry> multipleBundlesRegistry(
|
||||
std::unique_ptr<JSModulesUnbundle> mainBundle,
|
||||
std::function<std::unique_ptr<JSModulesUnbundle>(std::string)> factory);
|
||||
|
||||
explicit RAMBundleRegistry(
|
||||
std::unique_ptr<JSModulesUnbundle> mainBundle,
|
||||
std::function<std::unique_ptr<JSModulesUnbundle>(std::string)> factory =
|
||||
nullptr);
|
||||
|
||||
RAMBundleRegistry(RAMBundleRegistry &&) = default;
|
||||
RAMBundleRegistry &operator=(RAMBundleRegistry &&) = default;
|
||||
|
||||
void registerBundle(uint32_t bundleId, std::string bundlePath);
|
||||
JSModulesUnbundle::Module getModule(uint32_t bundleId, uint32_t moduleId);
|
||||
virtual ~RAMBundleRegistry(){};
|
||||
|
||||
private:
|
||||
JSModulesUnbundle *getBundle(uint32_t bundleId) const;
|
||||
|
||||
std::function<std::unique_ptr<JSModulesUnbundle>(std::string)> m_factory;
|
||||
std::unordered_map<uint32_t, std::string> m_bundlePaths;
|
||||
std::unordered_map<uint32_t, std::unique_ptr<JSModulesUnbundle>> m_bundles;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
44
node_modules/react-native/ReactCommon/cxxreact/React-cxxreact.podspec
generated
vendored
Normal file
44
node_modules/react-native/ReactCommon/cxxreact/React-cxxreact.podspec
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.
|
||||
|
||||
require "json"
|
||||
|
||||
package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json")))
|
||||
version = package['version']
|
||||
|
||||
source = { :git => 'https://github.com/facebook/react-native.git' }
|
||||
if version == '1000.0.0'
|
||||
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
|
||||
source[:commit] = `git rev-parse HEAD`.strip
|
||||
else
|
||||
source[:tag] = "v#{version}"
|
||||
end
|
||||
|
||||
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
||||
folly_version = '2020.01.13.00'
|
||||
boost_compiler_flags = '-Wno-documentation'
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "React-cxxreact"
|
||||
s.version = version
|
||||
s.summary = "-" # TODO
|
||||
s.homepage = "https://reactnative.dev/"
|
||||
s.license = package["license"]
|
||||
s.author = "Facebook, Inc. and its affiliates"
|
||||
s.platforms = { :ios => "10.0", :tvos => "10.0" }
|
||||
s.source = source
|
||||
s.source_files = "*.{cpp,h}"
|
||||
s.exclude_files = "SampleCxxModule.*"
|
||||
s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags
|
||||
s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/Folly\" \"$(PODS_ROOT)/DoubleConversion\"" }
|
||||
s.header_dir = "cxxreact"
|
||||
|
||||
s.dependency "boost-for-react-native", "1.63.0"
|
||||
s.dependency "DoubleConversion"
|
||||
s.dependency "Folly", folly_version
|
||||
s.dependency "glog"
|
||||
s.dependency "React-jsinspector", version
|
||||
s.dependency "React-callinvoker", version
|
||||
end
|
31
node_modules/react-native/ReactCommon/cxxreact/ReactMarker.cpp
generated
vendored
Normal file
31
node_modules/react-native/ReactCommon/cxxreact/ReactMarker.cpp
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 "ReactMarker.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
namespace ReactMarker {
|
||||
|
||||
#if __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wglobal-constructors"
|
||||
#endif
|
||||
|
||||
LogTaggedMarker logTaggedMarker = nullptr;
|
||||
|
||||
#if __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
void logMarker(const ReactMarkerId markerId) {
|
||||
logTaggedMarker(markerId, nullptr);
|
||||
}
|
||||
|
||||
} // namespace ReactMarker
|
||||
} // namespace react
|
||||
} // namespace facebook
|
49
node_modules/react-native/ReactCommon/cxxreact/ReactMarker.h
generated
vendored
Normal file
49
node_modules/react-native/ReactCommon/cxxreact/ReactMarker.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
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <functional>
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
namespace ReactMarker {
|
||||
|
||||
enum ReactMarkerId {
|
||||
NATIVE_REQUIRE_START,
|
||||
NATIVE_REQUIRE_STOP,
|
||||
RUN_JS_BUNDLE_START,
|
||||
RUN_JS_BUNDLE_STOP,
|
||||
CREATE_REACT_CONTEXT_STOP,
|
||||
JS_BUNDLE_STRING_CONVERT_START,
|
||||
JS_BUNDLE_STRING_CONVERT_STOP,
|
||||
NATIVE_MODULE_SETUP_START,
|
||||
NATIVE_MODULE_SETUP_STOP,
|
||||
REGISTER_JS_SEGMENT_START,
|
||||
REGISTER_JS_SEGMENT_STOP
|
||||
};
|
||||
|
||||
#ifdef __APPLE__
|
||||
using LogTaggedMarker =
|
||||
std::function<void(const ReactMarkerId, const char *tag)>;
|
||||
#else
|
||||
typedef void (*LogTaggedMarker)(const ReactMarkerId, const char *tag);
|
||||
#endif
|
||||
|
||||
#ifndef RN_EXPORT
|
||||
#define RN_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
extern RN_EXPORT LogTaggedMarker logTaggedMarker;
|
||||
|
||||
extern RN_EXPORT void logMarker(const ReactMarkerId markerId);
|
||||
|
||||
} // namespace ReactMarker
|
||||
} // namespace react
|
||||
} // namespace facebook
|
24
node_modules/react-native/ReactCommon/cxxreact/ReactNativeVersion.h
generated
vendored
Normal file
24
node_modules/react-native/ReactCommon/cxxreact/ReactNativeVersion.h
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @generated by scripts/bump-oss-version.js
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
constexpr struct {
|
||||
int32_t Major = 0;
|
||||
int32_t Minor = 63;
|
||||
int32_t Patch = 4;
|
||||
std::string_view Prerelease = "";
|
||||
} ReactNativeVersion;
|
||||
|
||||
} // namespace facebook::react
|
50
node_modules/react-native/ReactCommon/cxxreact/RecoverableError.h
generated
vendored
Normal file
50
node_modules/react-native/ReactCommon/cxxreact/RecoverableError.h
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 <exception>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/**
|
||||
* RecoverableError
|
||||
*
|
||||
* An exception that it is expected we should be able to recover from.
|
||||
*/
|
||||
struct RecoverableError : public std::exception {
|
||||
explicit RecoverableError(const std::string &what_)
|
||||
: m_what{"facebook::react::Recoverable: " + what_} {}
|
||||
|
||||
virtual const char *what() const noexcept override {
|
||||
return m_what.c_str();
|
||||
}
|
||||
|
||||
/**
|
||||
* runRethrowingAsRecoverable
|
||||
*
|
||||
* Helper function that converts any exception of type `E`, thrown within the
|
||||
* `act` routine into a recoverable error with the same message.
|
||||
*/
|
||||
template <typename E>
|
||||
inline static void runRethrowingAsRecoverable(std::function<void()> act) {
|
||||
try {
|
||||
act();
|
||||
} catch (const E &err) {
|
||||
throw RecoverableError(err.what());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_what;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
182
node_modules/react-native/ReactCommon/cxxreact/SampleCxxModule.cpp
generated
vendored
Normal file
182
node_modules/react-native/ReactCommon/cxxreact/SampleCxxModule.cpp
generated
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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 "SampleCxxModule.h"
|
||||
#include <cxxreact/JsArgumentHelpers.h>
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
using namespace folly;
|
||||
|
||||
namespace facebook {
|
||||
namespace xplat {
|
||||
namespace samples {
|
||||
|
||||
std::string Sample::hello() {
|
||||
LOG(WARNING) << "glog: hello, world";
|
||||
return "hello";
|
||||
}
|
||||
|
||||
double Sample::add(double a, double b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
std::string Sample::concat(const std::string &a, const std::string &b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
std::string Sample::repeat(int count, const std::string &str) {
|
||||
std::string ret;
|
||||
for (int i = 0; i < count; i++) {
|
||||
ret += str;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Sample::save(std::map<std::string, std::string> dict) {
|
||||
state_ = std::move(dict);
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> Sample::load() {
|
||||
return state_;
|
||||
}
|
||||
|
||||
void Sample::except() {
|
||||
// TODO mhorowitz #7128529: There's no way to automatically test this
|
||||
// right now.
|
||||
// throw std::runtime_error("oops");
|
||||
}
|
||||
|
||||
void Sample::call_later(int msec, std::function<void()> f) {
|
||||
std::thread t([=] {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(msec));
|
||||
f();
|
||||
});
|
||||
t.detach();
|
||||
}
|
||||
|
||||
double Sample::twice(double n) {
|
||||
return n * 2;
|
||||
}
|
||||
|
||||
SampleCxxModule::SampleCxxModule(std::unique_ptr<Sample> sample)
|
||||
: sample_(std::move(sample)) {}
|
||||
|
||||
std::string SampleCxxModule::getName() {
|
||||
return "Sample";
|
||||
}
|
||||
|
||||
auto SampleCxxModule::getConstants() -> std::map<std::string, folly::dynamic> {
|
||||
return {
|
||||
{"one", 1},
|
||||
{"two", 2},
|
||||
{"animal", "fox"},
|
||||
};
|
||||
}
|
||||
|
||||
auto SampleCxxModule::getMethods() -> std::vector<Method> {
|
||||
return {
|
||||
Method("hello", [this] { sample_->hello(); }),
|
||||
Method(
|
||||
"add",
|
||||
[this](dynamic args, Callback cb) {
|
||||
LOG(WARNING) << "Sample: add => "
|
||||
<< sample_->add(
|
||||
jsArgAsDouble(args, 0), jsArgAsDouble(args, 1));
|
||||
cb({sample_->add(jsArgAsDouble(args, 0), jsArgAsDouble(args, 1))});
|
||||
}),
|
||||
Method(
|
||||
"concat",
|
||||
[this](dynamic args, Callback cb) {
|
||||
cb({sample_->concat(
|
||||
jsArgAsString(args, 0), jsArgAsString(args, 1))});
|
||||
}),
|
||||
Method(
|
||||
"repeat",
|
||||
[this](dynamic args, Callback cb) {
|
||||
cb({sample_->repeat(
|
||||
(int)jsArgAsInt(args, 0), jsArgAsString(args, 1))});
|
||||
}),
|
||||
Method("save", this, &SampleCxxModule::save),
|
||||
Method("load", this, &SampleCxxModule::load),
|
||||
Method(
|
||||
"call_later",
|
||||
[this](dynamic args, Callback cb) {
|
||||
sample_->call_later((int)jsArgAsInt(args, 0), [cb] { cb({}); });
|
||||
}),
|
||||
Method("except", [this] { sample_->except(); }),
|
||||
Method(
|
||||
"twice",
|
||||
[this](dynamic args) -> dynamic {
|
||||
return sample_->twice(jsArgAsDouble(args, 0));
|
||||
},
|
||||
SyncTag),
|
||||
Method(
|
||||
"syncHello",
|
||||
[this]() -> dynamic {
|
||||
sample_->hello();
|
||||
return nullptr;
|
||||
},
|
||||
SyncTag),
|
||||
Method(
|
||||
"addIfPositiveAsPromise",
|
||||
[](dynamic args, Callback cb, Callback cbError) {
|
||||
auto a = jsArgAsDouble(args, 0);
|
||||
auto b = jsArgAsDouble(args, 1);
|
||||
if (a < 0 || b < 0) {
|
||||
cbError({"Negative number!"});
|
||||
} else {
|
||||
cb({a + b});
|
||||
}
|
||||
}),
|
||||
Method(
|
||||
"addIfPositiveAsAsync",
|
||||
[](dynamic args, Callback cb, Callback cbError) {
|
||||
auto a = jsArgAsDouble(args, 0);
|
||||
auto b = jsArgAsDouble(args, 1);
|
||||
if (a < 0 || b < 0) {
|
||||
cbError({"Negative number!"});
|
||||
} else {
|
||||
cb({a + b});
|
||||
}
|
||||
},
|
||||
AsyncTag),
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
void SampleCxxModule::save(folly::dynamic args) {
|
||||
std::map<std::string, std::string> m;
|
||||
for (const auto &p : jsArgN(args, 0, &dynamic::items)) {
|
||||
m.emplace(
|
||||
jsArg(p.first, &dynamic::asString, "map key"),
|
||||
jsArg(p.second, &dynamic::asString, "map value"));
|
||||
}
|
||||
sample_->save(std::move(m));
|
||||
}
|
||||
|
||||
void SampleCxxModule::load(__unused folly::dynamic args, Callback cb) {
|
||||
dynamic d = dynamic::object;
|
||||
for (const auto &p : sample_->load()) {
|
||||
d.insert(p.first, p.second);
|
||||
}
|
||||
cb({d});
|
||||
}
|
||||
|
||||
} // namespace samples
|
||||
} // namespace xplat
|
||||
} // namespace facebook
|
||||
|
||||
// By convention, the function name should be the same as the class name.
|
||||
facebook::xplat::module::CxxModule *SampleCxxModule() {
|
||||
return new facebook::xplat::samples::SampleCxxModule(
|
||||
std::make_unique<facebook::xplat::samples::Sample>());
|
||||
}
|
59
node_modules/react-native/ReactCommon/cxxreact/SampleCxxModule.h
generated
vendored
Normal file
59
node_modules/react-native/ReactCommon/cxxreact/SampleCxxModule.h
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
namespace facebook {
|
||||
namespace xplat {
|
||||
namespace samples {
|
||||
|
||||
// In a less contrived example, Sample would be part of a traditional
|
||||
// C++ library.
|
||||
|
||||
class Sample {
|
||||
public:
|
||||
std::string hello();
|
||||
double add(double a, double b);
|
||||
std::string concat(const std::string &a, const std::string &b);
|
||||
std::string repeat(int count, const std::string &str);
|
||||
void save(std::map<std::string, std::string> dict);
|
||||
std::map<std::string, std::string> load();
|
||||
void call_later(int msec, std::function<void()> f);
|
||||
void except();
|
||||
double twice(double n);
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> state_;
|
||||
};
|
||||
|
||||
class SampleCxxModule : public module::CxxModule {
|
||||
public:
|
||||
SampleCxxModule(std::unique_ptr<Sample> sample);
|
||||
|
||||
std::string getName();
|
||||
|
||||
virtual auto getConstants() -> std::map<std::string, folly::dynamic>;
|
||||
|
||||
virtual auto getMethods() -> std::vector<Method>;
|
||||
|
||||
private:
|
||||
void save(folly::dynamic args);
|
||||
void load(folly::dynamic args, Callback cb);
|
||||
|
||||
std::unique_ptr<Sample> sample_;
|
||||
};
|
||||
|
||||
} // namespace samples
|
||||
} // namespace xplat
|
||||
} // namespace facebook
|
||||
|
||||
extern "C" facebook::xplat::module::CxxModule *SampleCxxModule();
|
42
node_modules/react-native/ReactCommon/cxxreact/SharedProxyCxxModule.h
generated
vendored
Normal file
42
node_modules/react-native/ReactCommon/cxxreact/SharedProxyCxxModule.h
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.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <cxxreact/CxxModule.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace xplat {
|
||||
namespace module {
|
||||
|
||||
// Allows a Cxx-module to be shared or reused across multiple React instances
|
||||
// Caveat: the setInstance call is not forwarded, so usages of getInstance
|
||||
// inside your module (e.g. dispatching events) will always be nullptr.
|
||||
class SharedProxyCxxModule : public CxxModule {
|
||||
public:
|
||||
explicit SharedProxyCxxModule(std::shared_ptr<CxxModule> shared)
|
||||
: shared_(shared) {}
|
||||
|
||||
std::string getName() override {
|
||||
return shared_->getName();
|
||||
}
|
||||
|
||||
auto getConstants() -> std::map<std::string, folly::dynamic> override {
|
||||
return shared_->getConstants();
|
||||
}
|
||||
|
||||
auto getMethods() -> std::vector<Method> override {
|
||||
return shared_->getMethods();
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<CxxModule> shared_;
|
||||
};
|
||||
|
||||
} // namespace module
|
||||
} // namespace xplat
|
||||
} // namespace facebook
|
51
node_modules/react-native/ReactCommon/cxxreact/SystraceSection.h
generated
vendored
Normal file
51
node_modules/react-native/ReactCommon/cxxreact/SystraceSection.h
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
#include <fbsystrace.h>
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/**
|
||||
* This is a convenience class to avoid lots of verbose profiling
|
||||
* #ifdefs. If WITH_FBSYSTRACE is not defined, the optimizer will
|
||||
* remove this completely. If it is defined, it will behave as
|
||||
* FbSystraceSection, with the right tag provided. Use two separate classes to
|
||||
* to ensure that the ODR rule isn't violated, that is, if WITH_FBSYSTRACE has
|
||||
* different values in different files, there is no inconsistency in the sizes
|
||||
* of defined symbols.
|
||||
*/
|
||||
#ifdef WITH_FBSYSTRACE
|
||||
struct ConcreteSystraceSection {
|
||||
public:
|
||||
template <typename... ConvertsToStringPiece>
|
||||
explicit ConcreteSystraceSection(
|
||||
const char *name,
|
||||
ConvertsToStringPiece &&... args)
|
||||
: m_section(TRACE_TAG_REACT_CXX_BRIDGE, name, args...) {}
|
||||
|
||||
private:
|
||||
fbsystrace::FbSystraceSection m_section;
|
||||
};
|
||||
using SystraceSection = ConcreteSystraceSection;
|
||||
#else
|
||||
struct DummySystraceSection {
|
||||
public:
|
||||
template <typename... ConvertsToStringPiece>
|
||||
explicit DummySystraceSection(
|
||||
__unused const char *name,
|
||||
__unused ConvertsToStringPiece &&... args) {}
|
||||
};
|
||||
using SystraceSection = DummySystraceSection;
|
||||
#endif
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
6
node_modules/react-native/ReactCommon/cxxreact/re_worker_requirements
generated
vendored
Normal file
6
node_modules/react-native/ReactCommon/cxxreact/re_worker_requirements
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"bridgeAndroid#android-x86,merge_structure_97d5739e": {
|
||||
"workerSize": "MEDIUM",
|
||||
"platformType": "LINUX"
|
||||
}
|
||||
}
|
71
node_modules/react-native/ReactCommon/cxxreact/tests/BUCK
generated
vendored
Normal file
71
node_modules/react-native/ReactCommon/cxxreact/tests/BUCK
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
load(
|
||||
"//tools/build_defs/oss:rn_defs.bzl",
|
||||
"APPLE",
|
||||
"fb_xplat_cxx_test",
|
||||
"jni_instrumentation_test_lib",
|
||||
"react_native_xplat_target",
|
||||
)
|
||||
|
||||
TEST_SRCS = [
|
||||
"RecoverableErrorTest.cpp",
|
||||
"JSDeltaBundleClientTest.cpp",
|
||||
"jsarg_helpers.cpp",
|
||||
"jsbigstring.cpp",
|
||||
"methodcall.cpp",
|
||||
]
|
||||
|
||||
jni_instrumentation_test_lib(
|
||||
name = "tests",
|
||||
srcs = TEST_SRCS,
|
||||
class_under_test = "com/facebook/react/XplatBridgeTest",
|
||||
compiler_flags = [
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
"-std=c++14",
|
||||
],
|
||||
soname = "libxplat-bridge.so",
|
||||
visibility = [
|
||||
"//fbandroid/instrumentation_tests/...",
|
||||
],
|
||||
deps = [
|
||||
"//xplat/folly:dynamic",
|
||||
"//xplat/third-party/gmock:gtest",
|
||||
"//xplat/third-party/linker_lib:android",
|
||||
"//xplat/third-party/linker_lib:atomic",
|
||||
react_native_xplat_target("cxxreact:bridge"),
|
||||
react_native_xplat_target("cxxreact:jsbigstring"),
|
||||
],
|
||||
)
|
||||
|
||||
fb_xplat_cxx_test(
|
||||
name = "tests",
|
||||
srcs = TEST_SRCS,
|
||||
compiler_flags = [
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
],
|
||||
platforms = APPLE,
|
||||
visibility = [
|
||||
react_native_xplat_target("cxxreact/..."),
|
||||
],
|
||||
deps = [
|
||||
"//xplat/folly:molly",
|
||||
"//xplat/third-party/gmock:gtest",
|
||||
react_native_xplat_target("cxxreact:bridge"),
|
||||
react_native_xplat_target("cxxreact:jsbigstring"),
|
||||
],
|
||||
)
|
||||
|
||||
fb_xplat_cxx_test(
|
||||
name = "jsbigstring_test",
|
||||
srcs = ["jsbigstring.cpp"],
|
||||
compiler_flags = [
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
],
|
||||
deps = [
|
||||
"//xplat/folly:molly",
|
||||
"//xplat/third-party/gmock:gtest",
|
||||
react_native_xplat_target("cxxreact:jsbigstring"),
|
||||
],
|
||||
)
|
133
node_modules/react-native/ReactCommon/cxxreact/tests/JSDeltaBundleClientTest.cpp
generated
vendored
Normal file
133
node_modules/react-native/ReactCommon/cxxreact/tests/JSDeltaBundleClientTest.cpp
generated
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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 <gtest/gtest.h>
|
||||
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <cxxreact/JSDeltaBundleClient.h>
|
||||
#include <folly/dynamic.h>
|
||||
#include <folly/json.h>
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
TEST(JSDeltaBundleClient, PatchStartupCode) {
|
||||
JSDeltaBundleClient client;
|
||||
|
||||
folly::dynamic delta1 = folly::parseJson(R"({
|
||||
"base": true,
|
||||
"revisionId": "rev0",
|
||||
"pre": "pre",
|
||||
"post": "post",
|
||||
"modules": [
|
||||
[0, "0"],
|
||||
[1, "1"]
|
||||
]
|
||||
})");
|
||||
|
||||
client.patch(delta1);
|
||||
|
||||
EXPECT_STREQ(client.getStartupCode()->c_str(), "pre\npost\n");
|
||||
|
||||
folly::dynamic delta2 = folly::parseJson(R"({
|
||||
"base": true,
|
||||
"revisionId": "rev1",
|
||||
"pre": "pre2",
|
||||
"post": "post2",
|
||||
"modules": []
|
||||
})");
|
||||
|
||||
client.patch(delta2);
|
||||
|
||||
EXPECT_STREQ(client.getStartupCode()->c_str(), "pre2\npost2\n");
|
||||
}
|
||||
|
||||
TEST(JSDeltaBundleClient, PatchModule) {
|
||||
JSDeltaBundleClient client;
|
||||
|
||||
folly::dynamic delta1 = folly::parseJson(R"({
|
||||
"base": true,
|
||||
"revisionId": "rev0",
|
||||
"pre": "pre",
|
||||
"post": "post",
|
||||
"modules": [
|
||||
[0, "0"],
|
||||
[1, "1"]
|
||||
]
|
||||
})");
|
||||
|
||||
client.patch(delta1);
|
||||
|
||||
EXPECT_EQ(client.getModule(0).code, "0");
|
||||
EXPECT_EQ(client.getModule(1).code, "1");
|
||||
|
||||
ASSERT_THROW(client.getModule(2), JSModulesUnbundle::ModuleNotFound);
|
||||
|
||||
folly::dynamic delta2 = folly::parseJson(R"({
|
||||
"base": false,
|
||||
"revisionId": "rev1",
|
||||
"added": [
|
||||
[2, "2"]
|
||||
],
|
||||
"modified": [
|
||||
[0, "0.1"]
|
||||
],
|
||||
"deleted": [1]
|
||||
})");
|
||||
|
||||
client.patch(delta2);
|
||||
|
||||
EXPECT_EQ(client.getModule(0).code, "0.1");
|
||||
EXPECT_EQ(client.getModule(2).code, "2");
|
||||
ASSERT_THROW(client.getModule(1), JSModulesUnbundle::ModuleNotFound);
|
||||
|
||||
folly::dynamic delta3 = folly::parseJson(R"({
|
||||
"base": true,
|
||||
"revisionId": "rev2",
|
||||
"pre": "pre",
|
||||
"post": "post",
|
||||
"modules": [
|
||||
[3, "3"],
|
||||
[4, "4"]
|
||||
]
|
||||
})");
|
||||
|
||||
client.patch(delta3);
|
||||
|
||||
ASSERT_THROW(client.getModule(0), JSModulesUnbundle::ModuleNotFound);
|
||||
ASSERT_THROW(client.getModule(1), JSModulesUnbundle::ModuleNotFound);
|
||||
ASSERT_THROW(client.getModule(2), JSModulesUnbundle::ModuleNotFound);
|
||||
|
||||
EXPECT_EQ(client.getModule(3).code, "3");
|
||||
EXPECT_EQ(client.getModule(4).code, "4");
|
||||
}
|
||||
|
||||
TEST(JSDeltaBundleClient, Clear) {
|
||||
JSDeltaBundleClient client;
|
||||
|
||||
folly::dynamic delta1 = folly::parseJson(R"({
|
||||
"base": true,
|
||||
"revisionId": "rev0",
|
||||
"pre": "pre",
|
||||
"post": "post",
|
||||
"modules": [
|
||||
[0, "0"],
|
||||
[1, "1"]
|
||||
]
|
||||
})");
|
||||
|
||||
client.patch(delta1);
|
||||
|
||||
client.clear();
|
||||
|
||||
ASSERT_THROW(client.getModule(0), JSModulesUnbundle::ModuleNotFound);
|
||||
ASSERT_THROW(client.getModule(1), JSModulesUnbundle::ModuleNotFound);
|
||||
|
||||
EXPECT_STREQ(client.getStartupCode()->c_str(), "");
|
||||
}
|
39
node_modules/react-native/ReactCommon/cxxreact/tests/RecoverableErrorTest.cpp
generated
vendored
Normal file
39
node_modules/react-native/ReactCommon/cxxreact/tests/RecoverableErrorTest.cpp
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 <gtest/gtest.h>
|
||||
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <cxxreact/RecoverableError.h>
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
TEST(RecoverableError, RunRethrowingAsRecoverableRecoverTest) {
|
||||
try {
|
||||
RecoverableError::runRethrowingAsRecoverable<std::runtime_error>(
|
||||
[]() { throw std::runtime_error("catch me"); });
|
||||
FAIL() << "Unthrown exception";
|
||||
} catch (const RecoverableError &err) {
|
||||
ASSERT_STREQ(err.what(), "facebook::react::Recoverable: catch me");
|
||||
} catch (...) {
|
||||
FAIL() << "Uncaught exception";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(RecoverableError, RunRethrowingAsRecoverableFallthroughTest) {
|
||||
try {
|
||||
RecoverableError::runRethrowingAsRecoverable<std::runtime_error>(
|
||||
[]() { throw std::logic_error("catch me"); });
|
||||
FAIL() << "Unthrown exception";
|
||||
} catch (const RecoverableError &err) {
|
||||
FAIL() << "Recovered exception that should have fallen through";
|
||||
} catch (const std::exception &err) {
|
||||
ASSERT_STREQ(err.what(), "catch me");
|
||||
}
|
||||
}
|
114
node_modules/react-native/ReactCommon/cxxreact/tests/jsarg_helpers.cpp
generated
vendored
Normal file
114
node_modules/react-native/ReactCommon/cxxreact/tests/jsarg_helpers.cpp
generated
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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 <cxxreact/JsArgumentHelpers.h>
|
||||
|
||||
#include <folly/dynamic.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
using namespace folly;
|
||||
using namespace facebook::xplat;
|
||||
|
||||
#define EXPECT_JSAE(statement, exstr) \
|
||||
do { \
|
||||
try { \
|
||||
statement; \
|
||||
FAIL() << "Expected JsArgumentException(" << (exstr) << ") not thrown"; \
|
||||
} catch (const JsArgumentException &ex) { \
|
||||
EXPECT_EQ(ex.what(), std::string(exstr)); \
|
||||
} \
|
||||
} while (0) // let any other exception escape, gtest will deal.
|
||||
|
||||
TEST(JsArgumentHelpersTest, args) {
|
||||
const bool aBool = true;
|
||||
const int64_t anInt = 17;
|
||||
const double aDouble = 3.14;
|
||||
const string aString = "word";
|
||||
const dynamic anArray = dynamic::array("a", "b", "c");
|
||||
const dynamic anObject = dynamic::object("k1", "v1")("k2", "v2");
|
||||
const string aNumericString = to<string>(anInt);
|
||||
|
||||
folly::dynamic args = dynamic::array(
|
||||
aBool, anInt, aDouble, aString, anArray, anObject, aNumericString);
|
||||
|
||||
EXPECT_EQ(jsArgAsBool(args, 0), aBool);
|
||||
EXPECT_EQ(jsArgAsInt(args, 1), anInt);
|
||||
EXPECT_EQ(jsArgAsDouble(args, 2), aDouble);
|
||||
EXPECT_EQ(jsArgAsString(args, 3), aString);
|
||||
EXPECT_EQ(jsArgAsArray(args, 4), anArray);
|
||||
EXPECT_EQ(jsArgAsObject(args, 5), anObject);
|
||||
|
||||
// const args
|
||||
const folly::dynamic &cargs = args;
|
||||
const folly::dynamic &a4 = jsArgAsArray(cargs, 4);
|
||||
EXPECT_EQ(a4, anArray);
|
||||
EXPECT_EQ(jsArgAsObject(cargs, 5), anObject);
|
||||
|
||||
// helpers returning dynamic should return same object without copying
|
||||
EXPECT_EQ(&jsArgAsArray(args, 4), &(args[4]));
|
||||
EXPECT_EQ(&jsArgAsArray(cargs, 4), &(args[4]));
|
||||
|
||||
// dynamics returned for mutable args should be mutable. The test is that
|
||||
// this compiles.
|
||||
jsArgAsArray(args, 4)[2] = "d";
|
||||
jsArgAsArray(args, 4)[2] = "c";
|
||||
// These fail to compile due to constness.
|
||||
// jsArgAsArray(cargs, 4)[2] = "d";
|
||||
// jsArgAsArray(cargs, 4)[2] = "c";
|
||||
|
||||
// ref-qualified member function tests
|
||||
EXPECT_EQ(jsArgN(args, 3, &folly::dynamic::getString), aString);
|
||||
EXPECT_EQ(jsArg(args[3], &folly::dynamic::getString), aString);
|
||||
|
||||
// conversions
|
||||
EXPECT_EQ(jsArgAsDouble(args, 1), anInt * 1.0);
|
||||
EXPECT_EQ(jsArgAsString(args, 1), aNumericString);
|
||||
EXPECT_EQ(jsArgAsInt(args, 6), anInt);
|
||||
|
||||
// Test exception messages.
|
||||
|
||||
// out_of_range
|
||||
EXPECT_JSAE(
|
||||
jsArgAsBool(args, 7),
|
||||
"JavaScript provided 7 arguments for C++ method which references at least "
|
||||
"8 arguments: out of range in dynamic array");
|
||||
// Conv range_error (invalid value conversion)
|
||||
const std::string exhead = "Could not convert argument 3 to required type: ";
|
||||
const std::string extail = ": Invalid leading character: \"word\"";
|
||||
try {
|
||||
jsArgAsInt(args, 3);
|
||||
FAIL() << "Expected JsArgumentException(" << exhead << "..." << extail
|
||||
<< ") not thrown";
|
||||
} catch (const JsArgumentException &ex) {
|
||||
const std::string exwhat = ex.what();
|
||||
|
||||
EXPECT_GT(exwhat.size(), exhead.size());
|
||||
EXPECT_GT(exwhat.size(), extail.size());
|
||||
|
||||
EXPECT_TRUE(std::equal(exhead.cbegin(), exhead.cend(), exwhat.cbegin()))
|
||||
<< "JsArgumentException('" << exwhat << "') does not begin with '"
|
||||
<< exhead << "'";
|
||||
EXPECT_TRUE(std::equal(extail.crbegin(), extail.crend(), exwhat.crbegin()))
|
||||
<< "JsArgumentException('" << exwhat << "') does not end with '"
|
||||
<< extail << "'";
|
||||
}
|
||||
// inconvertible types
|
||||
EXPECT_JSAE(
|
||||
jsArgAsArray(args, 2),
|
||||
"Argument 3 of type double is not required type Array");
|
||||
EXPECT_JSAE(
|
||||
jsArgAsInt(args, 4),
|
||||
"Error converting javascript arg 4 to C++: "
|
||||
"TypeError: expected dynamic type `int/double/bool/string', but had type `array'");
|
||||
// type predicate failure
|
||||
EXPECT_JSAE(
|
||||
jsArgAsObject(args, 4),
|
||||
"Argument 5 of type array is not required type Object");
|
||||
}
|
106
node_modules/react-native/ReactCommon/cxxreact/tests/jsbigstring.cpp
generated
vendored
Normal file
106
node_modules/react-native/ReactCommon/cxxreact/tests/jsbigstring.cpp
generated
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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 <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <cxxreact/JSBigString.h>
|
||||
#include <folly/File.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace facebook;
|
||||
using namespace facebook::react;
|
||||
|
||||
namespace {
|
||||
int tempFileFromString(std::string contents) {
|
||||
const char *tmpDir = getenv("TMPDIR");
|
||||
if (tmpDir == nullptr)
|
||||
tmpDir = "/tmp";
|
||||
std::string tmp{tmpDir};
|
||||
tmp += "/temp.XXXXXX";
|
||||
|
||||
std::vector<char> tmpBuf{tmp.begin(), tmp.end()};
|
||||
tmpBuf.push_back('\0');
|
||||
|
||||
const int fd = mkstemp(tmpBuf.data());
|
||||
write(fd, contents.c_str(), contents.size() + 1);
|
||||
|
||||
return fd;
|
||||
}
|
||||
}; // namespace
|
||||
|
||||
TEST(JSBigFileString, MapWholeFileTest) {
|
||||
std::string data{"Hello, world"};
|
||||
const auto size = data.length() + 1;
|
||||
|
||||
// Initialise Big String
|
||||
int fd = tempFileFromString("Hello, world");
|
||||
JSBigFileString bigStr{fd, size};
|
||||
|
||||
// Test
|
||||
ASSERT_STREQ(data.c_str(), bigStr.c_str());
|
||||
}
|
||||
|
||||
TEST(JSBigFileString, MapPartTest) {
|
||||
std::string data{"Hello, world"};
|
||||
|
||||
// Sub-string to actually map
|
||||
std::string needle{"or"};
|
||||
off_t offset = data.find(needle);
|
||||
|
||||
// Initialise Big String
|
||||
int fd = tempFileFromString(data);
|
||||
JSBigFileString bigStr{fd, needle.size(), offset};
|
||||
|
||||
// Test
|
||||
EXPECT_EQ(needle.length(), bigStr.size());
|
||||
for (unsigned int i = 0; i < needle.length(); ++i) {
|
||||
EXPECT_EQ(needle[i], bigStr.c_str()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(JSBigFileString, RemapTest) {
|
||||
static const uint8_t kRemapMagic[] = {
|
||||
0xc6, 0x1f, 0xbc, 0x03, 0xc1, 0x03, 0x19, 0x1f, 0xa1, 0xd0, 0xeb, 0x73};
|
||||
std::string data(std::begin(kRemapMagic), std::end(kRemapMagic));
|
||||
auto app = [&data](uint16_t v) {
|
||||
data.append(reinterpret_cast<char *>(&v), sizeof(v));
|
||||
};
|
||||
size_t pageSizeLog2 = 16;
|
||||
app(pageSizeLog2);
|
||||
size_t pageSize = 1 << pageSizeLog2;
|
||||
app(1); // header pages
|
||||
app(2); // num mappings
|
||||
// file page 0 -> memory page 1
|
||||
app(1); // memory page
|
||||
app(1); // num pages
|
||||
// file page 1 -> memory page 0
|
||||
app(0); // memory page
|
||||
app(1); // num pages
|
||||
while (data.size() < pageSize) {
|
||||
app(0);
|
||||
}
|
||||
while (data.size() < pageSize * 2) {
|
||||
app(0x1111);
|
||||
}
|
||||
while (data.size() < pageSize * 3) {
|
||||
app(0x2222);
|
||||
}
|
||||
|
||||
int fd = tempFileFromString(data);
|
||||
JSBigFileString bigStr{fd, data.size()};
|
||||
|
||||
EXPECT_EQ(pageSize * 2, bigStr.size());
|
||||
auto remapped = bigStr.c_str();
|
||||
size_t i = 0;
|
||||
for (; i < pageSize; ++i) {
|
||||
EXPECT_EQ(0x22, remapped[i]);
|
||||
}
|
||||
for (; i < pageSize * 2; ++i) {
|
||||
EXPECT_EQ(0x11, remapped[i]);
|
||||
}
|
||||
}
|
156
node_modules/react-native/ReactCommon/cxxreact/tests/methodcall.cpp
generated
vendored
Normal file
156
node_modules/react-native/ReactCommon/cxxreact/tests/methodcall.cpp
generated
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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 <cxxreact/MethodCall.h>
|
||||
|
||||
#include <folly/json.h>
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
#include <gtest/gtest.h>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
using namespace facebook;
|
||||
using namespace facebook::react;
|
||||
using namespace folly;
|
||||
|
||||
TEST(parseMethodCalls, SingleReturnCallNoArgs) {
|
||||
auto jsText = "[[7],[3],[[]]]";
|
||||
auto returnedCalls = parseMethodCalls(folly::parseJson(jsText));
|
||||
EXPECT_EQ(1, returnedCalls.size());
|
||||
auto returnedCall = returnedCalls[0];
|
||||
EXPECT_EQ(0, returnedCall.arguments.size());
|
||||
EXPECT_EQ(7, returnedCall.moduleId);
|
||||
EXPECT_EQ(3, returnedCall.methodId);
|
||||
}
|
||||
|
||||
TEST(parseMethodCalls, InvalidReturnFormat) {
|
||||
try {
|
||||
auto input = dynamic::object("foo", 1);
|
||||
parseMethodCalls(std::move(input));
|
||||
ADD_FAILURE();
|
||||
} catch (const std::invalid_argument &) {
|
||||
// ignored
|
||||
}
|
||||
try {
|
||||
auto input = dynamic::array(dynamic::object("foo", 1));
|
||||
parseMethodCalls(std::move(input));
|
||||
ADD_FAILURE();
|
||||
} catch (const std::invalid_argument &) {
|
||||
// ignored
|
||||
}
|
||||
try {
|
||||
auto input = dynamic::array(1, 4, dynamic::object("foo", 2));
|
||||
parseMethodCalls(std::move(input));
|
||||
ADD_FAILURE();
|
||||
} catch (const std::invalid_argument &) {
|
||||
// ignored
|
||||
}
|
||||
try {
|
||||
auto input = dynamic::array(
|
||||
dynamic::array(1), dynamic::array(4), dynamic::object("foo", 2));
|
||||
parseMethodCalls(std::move(input));
|
||||
ADD_FAILURE();
|
||||
} catch (const std::invalid_argument &) {
|
||||
// ignored
|
||||
}
|
||||
try {
|
||||
auto input =
|
||||
dynamic::array(dynamic::array(1), dynamic::array(4), dynamic::array());
|
||||
parseMethodCalls(std::move(input));
|
||||
ADD_FAILURE();
|
||||
} catch (const std::invalid_argument &) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
TEST(parseMethodCalls, NumberReturn) {
|
||||
auto jsText = "[[0],[0],[[\"foobar\"]]]";
|
||||
auto returnedCalls = parseMethodCalls(folly::parseJson(jsText));
|
||||
EXPECT_EQ(1, returnedCalls.size());
|
||||
auto returnedCall = returnedCalls[0];
|
||||
EXPECT_EQ(1, returnedCall.arguments.size());
|
||||
EXPECT_EQ(folly::dynamic::STRING, returnedCall.arguments[0].type());
|
||||
EXPECT_EQ("foobar", returnedCall.arguments[0].asString());
|
||||
}
|
||||
|
||||
TEST(parseMethodCalls, StringReturn) {
|
||||
auto jsText = "[[0],[0],[[42.16]]]";
|
||||
auto returnedCalls = parseMethodCalls(folly::parseJson(jsText));
|
||||
EXPECT_EQ(1, returnedCalls.size());
|
||||
auto returnedCall = returnedCalls[0];
|
||||
EXPECT_EQ(1, returnedCall.arguments.size());
|
||||
EXPECT_EQ(folly::dynamic::DOUBLE, returnedCall.arguments[0].type());
|
||||
EXPECT_EQ(42.16, returnedCall.arguments[0].asDouble());
|
||||
}
|
||||
|
||||
TEST(parseMethodCalls, BooleanReturn) {
|
||||
auto jsText = "[[0],[0],[[false]]]";
|
||||
auto returnedCalls = parseMethodCalls(folly::parseJson(jsText));
|
||||
EXPECT_EQ(1, returnedCalls.size());
|
||||
auto returnedCall = returnedCalls[0];
|
||||
EXPECT_EQ(1, returnedCall.arguments.size());
|
||||
EXPECT_EQ(folly::dynamic::BOOL, returnedCall.arguments[0].type());
|
||||
ASSERT_FALSE(returnedCall.arguments[0].asBool());
|
||||
}
|
||||
|
||||
TEST(parseMethodCalls, NullReturn) {
|
||||
auto jsText = "[[0],[0],[[null]]]";
|
||||
auto returnedCalls = parseMethodCalls(folly::parseJson(jsText));
|
||||
EXPECT_EQ(1, returnedCalls.size());
|
||||
auto returnedCall = returnedCalls[0];
|
||||
EXPECT_EQ(1, returnedCall.arguments.size());
|
||||
EXPECT_EQ(folly::dynamic::NULLT, returnedCall.arguments[0].type());
|
||||
}
|
||||
|
||||
TEST(parseMethodCalls, MapReturn) {
|
||||
auto jsText =
|
||||
"[[0],[0],[[{\"foo\": \"hello\", \"bar\": 4.0, \"baz\": true}]]]";
|
||||
auto returnedCalls = parseMethodCalls(folly::parseJson(jsText));
|
||||
EXPECT_EQ(1, returnedCalls.size());
|
||||
auto returnedCall = returnedCalls[0];
|
||||
EXPECT_EQ(1, returnedCall.arguments.size());
|
||||
EXPECT_EQ(folly::dynamic::OBJECT, returnedCall.arguments[0].type());
|
||||
auto &returnedMap = returnedCall.arguments[0];
|
||||
auto foo = returnedMap.at("foo");
|
||||
EXPECT_EQ(folly::dynamic("hello"), foo);
|
||||
auto bar = returnedMap.at("bar");
|
||||
EXPECT_EQ(folly::dynamic(4.0), bar);
|
||||
auto baz = returnedMap.at("baz");
|
||||
EXPECT_EQ(folly::dynamic(true), baz);
|
||||
}
|
||||
|
||||
TEST(parseMethodCalls, ArrayReturn) {
|
||||
auto jsText = "[[0],[0],[[[\"foo\", 42.0, false]]]]";
|
||||
auto returnedCalls = parseMethodCalls(folly::parseJson(jsText));
|
||||
EXPECT_EQ(1, returnedCalls.size());
|
||||
auto returnedCall = returnedCalls[0];
|
||||
EXPECT_EQ(1, returnedCall.arguments.size());
|
||||
EXPECT_EQ(folly::dynamic::ARRAY, returnedCall.arguments[0].type());
|
||||
auto &returnedArray = returnedCall.arguments[0];
|
||||
EXPECT_EQ(3, returnedArray.size());
|
||||
EXPECT_EQ(folly::dynamic("foo"), returnedArray[0]);
|
||||
EXPECT_EQ(folly::dynamic(42.0), returnedArray[1]);
|
||||
EXPECT_EQ(folly::dynamic(false), returnedArray[2]);
|
||||
}
|
||||
|
||||
TEST(parseMethodCalls, ReturnMultipleParams) {
|
||||
auto jsText = "[[0],[0],[[\"foo\", 14, null, false]]]";
|
||||
auto returnedCalls = parseMethodCalls(folly::parseJson(jsText));
|
||||
EXPECT_EQ(1, returnedCalls.size());
|
||||
auto returnedCall = returnedCalls[0];
|
||||
EXPECT_EQ(4, returnedCall.arguments.size());
|
||||
EXPECT_EQ(folly::dynamic::STRING, returnedCall.arguments[0].type());
|
||||
EXPECT_EQ(folly::dynamic::INT64, returnedCall.arguments[1].type());
|
||||
EXPECT_EQ(folly::dynamic::NULLT, returnedCall.arguments[2].type());
|
||||
EXPECT_EQ(folly::dynamic::BOOL, returnedCall.arguments[3].type());
|
||||
}
|
||||
|
||||
TEST(parseMethodCalls, ParseTwoCalls) {
|
||||
auto jsText = "[[0,0],[1,1],[[],[]]]";
|
||||
auto returnedCalls = parseMethodCalls(folly::parseJson(jsText));
|
||||
EXPECT_EQ(2, returnedCalls.size());
|
||||
}
|
Reference in New Issue
Block a user