yeet
This commit is contained in:
93
node_modules/react-native/ReactCommon/fabric/uimanager/BUCK
generated
vendored
Normal file
93
node_modules/react-native/ReactCommon/fabric/uimanager/BUCK
generated
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
load("@fbsource//tools/build_defs/apple:flag_defs.bzl", "get_preprocessor_flags_for_build_mode")
|
||||
load(
|
||||
"//tools/build_defs/oss:rn_defs.bzl",
|
||||
"ANDROID",
|
||||
"APPLE",
|
||||
"CXX",
|
||||
"fb_xplat_cxx_test",
|
||||
"get_apple_compiler_flags",
|
||||
"get_apple_inspector_flags",
|
||||
"react_native_xplat_target",
|
||||
"rn_xplat_cxx_library",
|
||||
"subdir_glob",
|
||||
)
|
||||
|
||||
APPLE_COMPILER_FLAGS = get_apple_compiler_flags()
|
||||
|
||||
rn_xplat_cxx_library(
|
||||
name = "uimanager",
|
||||
srcs = glob(
|
||||
["**/*.cpp"],
|
||||
exclude = glob(["tests/**/*.cpp"]),
|
||||
),
|
||||
headers = glob(
|
||||
["**/*.h"],
|
||||
exclude = glob(["tests/**/*.h"]),
|
||||
),
|
||||
header_namespace = "",
|
||||
exported_headers = subdir_glob(
|
||||
[
|
||||
("", "*.h"),
|
||||
],
|
||||
prefix = "react/uimanager",
|
||||
),
|
||||
compiler_flags = [
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
"-std=c++14",
|
||||
"-Wall",
|
||||
],
|
||||
fbobjc_compiler_flags = APPLE_COMPILER_FLAGS,
|
||||
fbobjc_labels = ["supermodule:ios/default/public.react_native.infra"],
|
||||
fbobjc_preprocessor_flags = get_preprocessor_flags_for_build_mode() + get_apple_inspector_flags(),
|
||||
force_static = True,
|
||||
macosx_tests_override = [],
|
||||
platforms = (ANDROID, APPLE, CXX),
|
||||
preprocessor_flags = [
|
||||
"-DLOG_TAG=\"ReactNative\"",
|
||||
"-DWITH_FBSYSTRACE=1",
|
||||
],
|
||||
tests = [":tests"],
|
||||
visibility = ["PUBLIC"],
|
||||
deps = [
|
||||
"//xplat/fbsystrace:fbsystrace",
|
||||
"//xplat/folly:headers_only",
|
||||
"//xplat/folly:memory",
|
||||
"//xplat/folly:molly",
|
||||
"//xplat/jsi:JSIDynamic",
|
||||
"//xplat/jsi:jsi",
|
||||
"//xplat/third-party/glog:glog",
|
||||
react_native_xplat_target("config:config"),
|
||||
react_native_xplat_target("fabric/components/view:view"),
|
||||
react_native_xplat_target("fabric/mounting:mounting"),
|
||||
react_native_xplat_target("fabric/core:core"),
|
||||
react_native_xplat_target("fabric/debug:debug"),
|
||||
react_native_xplat_target("utils:utils"),
|
||||
],
|
||||
)
|
||||
|
||||
fb_xplat_cxx_test(
|
||||
name = "tests",
|
||||
srcs = glob(["tests/**/*.cpp"]),
|
||||
headers = glob(["tests/**/*.h"]),
|
||||
compiler_flags = [
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
"-std=c++14",
|
||||
"-Wall",
|
||||
],
|
||||
contacts = ["oncall+react_native@xmail.facebook.com"],
|
||||
platforms = (ANDROID, APPLE, CXX),
|
||||
deps = [
|
||||
":uimanager",
|
||||
"//xplat/folly:molly",
|
||||
"//xplat/third-party/gmock:gtest",
|
||||
react_native_xplat_target("config:config"),
|
||||
react_native_xplat_target("fabric/components/activityindicator:activityindicator"),
|
||||
react_native_xplat_target("fabric/components/image:image"),
|
||||
react_native_xplat_target("fabric/components/root:root"),
|
||||
react_native_xplat_target("fabric/components/scrollview:scrollview"),
|
||||
react_native_xplat_target("fabric/components/view:view"),
|
||||
"//xplat/js/react-native-github:generated_components-rncore",
|
||||
],
|
||||
)
|
34
node_modules/react-native/ReactCommon/fabric/uimanager/ComponentDescriptorFactory.h
generated
vendored
Normal file
34
node_modules/react-native/ReactCommon/fabric/uimanager/ComponentDescriptorFactory.h
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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <react/core/ComponentDescriptor.h>
|
||||
#include <react/core/EventDispatcher.h>
|
||||
#include <react/utils/ContextContainer.h>
|
||||
|
||||
#include "ComponentDescriptorRegistry.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/**
|
||||
* A factory to provide hosting app specific set of ComponentDescriptor's.
|
||||
* Each app must provide an implementation of the static class method which
|
||||
* should register its specific set of supported components.
|
||||
*/
|
||||
using ComponentRegistryFactory =
|
||||
std::function<SharedComponentDescriptorRegistry(
|
||||
EventDispatcher::Weak const &eventDispatcher,
|
||||
ContextContainer::Shared const &contextContainer)>;
|
||||
|
||||
ComponentRegistryFactory getDefaultComponentRegistryFactory();
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
73
node_modules/react-native/ReactCommon/fabric/uimanager/ComponentDescriptorProvider.h
generated
vendored
Normal file
73
node_modules/react-native/ReactCommon/fabric/uimanager/ComponentDescriptorProvider.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 <react/core/ComponentDescriptor.h>
|
||||
#include <react/core/EventDispatcher.h>
|
||||
#include <react/utils/ContextContainer.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* Callable signature that represents the signature of `ComponentDescriptor`
|
||||
* constructor. The callable returns a unique pointer conveniently represents an
|
||||
* abstract type and ownership of the newly created object.
|
||||
*/
|
||||
using ComponentDescriptorConstructor = ComponentDescriptor::Unique(
|
||||
ComponentDescriptorParameters const ¶meters);
|
||||
|
||||
/*
|
||||
* Represents a unified way to construct an instance of a particular stored
|
||||
* `ComponentDescriptor` class. C++ does not allow to create pointers to
|
||||
* constructors, so we have to have such data structure to manipulate a
|
||||
* collection of classes.
|
||||
*
|
||||
* Note: The actual values of `handle` and `name` for some components depend on
|
||||
* `flavor`. The provider is valid if instantiated by `constructor` object with
|
||||
* given `flavor` exposes the same values of `handle` and `name`.
|
||||
*/
|
||||
class ComponentDescriptorProvider final {
|
||||
public:
|
||||
ComponentHandle handle;
|
||||
ComponentName name;
|
||||
ComponentDescriptor::Flavor flavor;
|
||||
ComponentDescriptorConstructor *constructor;
|
||||
};
|
||||
|
||||
/*
|
||||
* Creates a `ComponentDescriptor` for given `ComponentDescriptorParameters`.
|
||||
*/
|
||||
template <typename ComponentDescriptorT>
|
||||
ComponentDescriptor::Unique concreteComponentDescriptorConstructor(
|
||||
ComponentDescriptorParameters const ¶meters) {
|
||||
static_assert(
|
||||
std::is_base_of<ComponentDescriptor, ComponentDescriptorT>::value,
|
||||
"ComponentDescriptorT must be a descendant of ComponentDescriptor");
|
||||
|
||||
return std::make_unique<ComponentDescriptorT const>(parameters);
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a `ComponentDescriptorProvider` for given `ComponentDescriptor`
|
||||
* class.
|
||||
*/
|
||||
template <typename ComponentDescriptorT>
|
||||
ComponentDescriptorProvider concreteComponentDescriptorProvider() {
|
||||
static_assert(
|
||||
std::is_base_of<ComponentDescriptor, ComponentDescriptorT>::value,
|
||||
"ComponentDescriptorT must be a descendant of ComponentDescriptor");
|
||||
|
||||
return {ComponentDescriptorT::ConcreteShadowNode::Handle(),
|
||||
ComponentDescriptorT::ConcreteShadowNode::Name(),
|
||||
nullptr,
|
||||
&concreteComponentDescriptorConstructor<ComponentDescriptorT>};
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
84
node_modules/react-native/ReactCommon/fabric/uimanager/ComponentDescriptorProviderRegistry.cpp
generated
vendored
Normal file
84
node_modules/react-native/ReactCommon/fabric/uimanager/ComponentDescriptorProviderRegistry.cpp
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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 "ComponentDescriptorProviderRegistry.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
void ComponentDescriptorProviderRegistry::add(
|
||||
ComponentDescriptorProvider provider) const {
|
||||
std::unique_lock<better::shared_mutex> lock(mutex_);
|
||||
|
||||
/*
|
||||
// TODO: T57583139
|
||||
The assert is temporarily disabled to reduce the volume of the signal.
|
||||
assert(
|
||||
componentDescriptorProviders_.find(provider.handle) ==
|
||||
componentDescriptorProviders_.end() &&
|
||||
"Attempt to register an already registered ComponentDescriptorProvider.");
|
||||
*/
|
||||
|
||||
if (componentDescriptorProviders_.find(provider.handle) !=
|
||||
componentDescriptorProviders_.end()) {
|
||||
// Re-registering a provider makes no sense because it's copyable: already
|
||||
// registered one is as good as any new can be.
|
||||
return;
|
||||
}
|
||||
|
||||
componentDescriptorProviders_.insert({provider.handle, provider});
|
||||
|
||||
for (auto const &weakRegistry : componentDescriptorRegistries_) {
|
||||
auto registry = weakRegistry.lock();
|
||||
if (!registry) {
|
||||
continue;
|
||||
}
|
||||
|
||||
registry->add(provider);
|
||||
}
|
||||
}
|
||||
|
||||
void ComponentDescriptorProviderRegistry::setComponentDescriptorProviderRequest(
|
||||
ComponentDescriptorProviderRequest componentDescriptorProviderRequest)
|
||||
const {
|
||||
std::shared_lock<better::shared_mutex> lock(mutex_);
|
||||
componentDescriptorProviderRequest_ = componentDescriptorProviderRequest;
|
||||
}
|
||||
|
||||
void ComponentDescriptorProviderRegistry::request(
|
||||
ComponentName componentName) const {
|
||||
ComponentDescriptorProviderRequest componentDescriptorProviderRequest;
|
||||
|
||||
{
|
||||
std::shared_lock<better::shared_mutex> lock(mutex_);
|
||||
componentDescriptorProviderRequest = componentDescriptorProviderRequest_;
|
||||
}
|
||||
|
||||
if (componentDescriptorProviderRequest) {
|
||||
componentDescriptorProviderRequest(componentName);
|
||||
}
|
||||
}
|
||||
|
||||
ComponentDescriptorRegistry::Shared
|
||||
ComponentDescriptorProviderRegistry::createComponentDescriptorRegistry(
|
||||
ComponentDescriptorParameters const ¶meters) const {
|
||||
std::shared_lock<better::shared_mutex> lock(mutex_);
|
||||
|
||||
auto registry =
|
||||
std::make_shared<ComponentDescriptorRegistry const>(parameters, *this);
|
||||
|
||||
for (auto const &pair : componentDescriptorProviders_) {
|
||||
registry->add(pair.second);
|
||||
}
|
||||
|
||||
componentDescriptorRegistries_.push_back(registry);
|
||||
|
||||
return registry;
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
71
node_modules/react-native/ReactCommon/fabric/uimanager/ComponentDescriptorProviderRegistry.h
generated
vendored
Normal file
71
node_modules/react-native/ReactCommon/fabric/uimanager/ComponentDescriptorProviderRegistry.h
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <better/mutex.h>
|
||||
|
||||
#include <react/core/ComponentDescriptor.h>
|
||||
#include <react/uimanager/ComponentDescriptorProvider.h>
|
||||
#include <react/uimanager/ComponentDescriptorRegistry.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
using ComponentDescriptorProviderRequest =
|
||||
std::function<void(ComponentName componentName)>;
|
||||
|
||||
/*
|
||||
* Registry of `ComponentDescriptorProvider`s (and managed
|
||||
* `ComponentDescriptorRegistry`s). The class maintains a list of
|
||||
* `ComponentDescriptorRegistry`s (retaining pointers weakly) and update them
|
||||
* accordingly to changes in the provider registry.
|
||||
*/
|
||||
class ComponentDescriptorProviderRegistry final {
|
||||
public:
|
||||
/*
|
||||
* Adds a `ComponentDescriptorProvider`s and update the managed
|
||||
* `ComponentDescriptorRegistry`s accordingly.
|
||||
* The methods can be called on any thread.
|
||||
*/
|
||||
void add(ComponentDescriptorProvider provider) const;
|
||||
|
||||
/*
|
||||
* ComponenDescriptorRegistry will call the `request` in case if a component
|
||||
* with given name wasn't registered yet.
|
||||
* The request handler must register a ComponentDescripor with requested name
|
||||
* synchronously during handling the request.
|
||||
* The request can be called on any thread.
|
||||
* The methods can be called on any thread.
|
||||
*/
|
||||
void setComponentDescriptorProviderRequest(
|
||||
ComponentDescriptorProviderRequest request) const;
|
||||
|
||||
/*
|
||||
* Creates managed `ComponentDescriptorRegistry` based on a stored list of
|
||||
* `ComponentDescriptorProvider`s and given `ComponentDescriptorParameters`.
|
||||
* The methods can be called on any thread.
|
||||
*/
|
||||
ComponentDescriptorRegistry::Shared createComponentDescriptorRegistry(
|
||||
ComponentDescriptorParameters const ¶meters) const;
|
||||
|
||||
private:
|
||||
friend class ComponentDescriptorRegistry;
|
||||
|
||||
void request(ComponentName componentName) const;
|
||||
|
||||
mutable better::shared_mutex mutex_;
|
||||
mutable std::vector<std::weak_ptr<ComponentDescriptorRegistry const>>
|
||||
componentDescriptorRegistries_;
|
||||
mutable better::map<ComponentHandle, ComponentDescriptorProvider const>
|
||||
componentDescriptorProviders_;
|
||||
mutable ComponentDescriptorProviderRequest
|
||||
componentDescriptorProviderRequest_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
210
node_modules/react-native/ReactCommon/fabric/uimanager/ComponentDescriptorRegistry.cpp
generated
vendored
Normal file
210
node_modules/react-native/ReactCommon/fabric/uimanager/ComponentDescriptorRegistry.cpp
generated
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* 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 "ComponentDescriptorRegistry.h"
|
||||
|
||||
#include <react/core/ShadowNodeFragment.h>
|
||||
#include <react/uimanager/ComponentDescriptorProviderRegistry.h>
|
||||
#include <react/uimanager/primitives.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
ComponentDescriptorRegistry::ComponentDescriptorRegistry(
|
||||
ComponentDescriptorParameters const ¶meters,
|
||||
ComponentDescriptorProviderRegistry const &providerRegistry)
|
||||
: parameters_(parameters), providerRegistry_(providerRegistry) {}
|
||||
|
||||
void ComponentDescriptorRegistry::add(
|
||||
ComponentDescriptorProvider componentDescriptorProvider) const {
|
||||
std::unique_lock<better::shared_mutex> lock(mutex_);
|
||||
|
||||
auto componentDescriptor = componentDescriptorProvider.constructor(
|
||||
{parameters_.eventDispatcher,
|
||||
parameters_.contextContainer,
|
||||
componentDescriptorProvider.flavor});
|
||||
assert(
|
||||
componentDescriptor->getComponentHandle() ==
|
||||
componentDescriptorProvider.handle);
|
||||
assert(
|
||||
componentDescriptor->getComponentName() ==
|
||||
componentDescriptorProvider.name);
|
||||
|
||||
auto sharedComponentDescriptor = std::shared_ptr<ComponentDescriptor const>(
|
||||
std::move(componentDescriptor));
|
||||
_registryByHandle[componentDescriptorProvider.handle] =
|
||||
sharedComponentDescriptor;
|
||||
_registryByName[componentDescriptorProvider.name] = sharedComponentDescriptor;
|
||||
}
|
||||
|
||||
void ComponentDescriptorRegistry::registerComponentDescriptor(
|
||||
SharedComponentDescriptor componentDescriptor) const {
|
||||
ComponentHandle componentHandle = componentDescriptor->getComponentHandle();
|
||||
_registryByHandle[componentHandle] = componentDescriptor;
|
||||
|
||||
ComponentName componentName = componentDescriptor->getComponentName();
|
||||
_registryByName[componentName] = componentDescriptor;
|
||||
}
|
||||
|
||||
static std::string componentNameByReactViewName(std::string viewName) {
|
||||
// We need this function only for the transition period;
|
||||
// eventually, all names will be unified.
|
||||
|
||||
std::string rctPrefix("RCT");
|
||||
if (std::mismatch(rctPrefix.begin(), rctPrefix.end(), viewName.begin())
|
||||
.first == rctPrefix.end()) {
|
||||
// If `viewName` has "RCT" prefix, remove it.
|
||||
viewName.erase(0, rctPrefix.length());
|
||||
}
|
||||
|
||||
// Fabric uses slightly new names for Text components because of differences
|
||||
// in semantic.
|
||||
if (viewName == "Text") {
|
||||
return "Paragraph";
|
||||
}
|
||||
|
||||
// TODO T63839307: remove this condition after deleting TextInlineImage from
|
||||
// Paper
|
||||
if (viewName == "TextInlineImage") {
|
||||
return "Image";
|
||||
}
|
||||
if (viewName == "VirtualText") {
|
||||
return "Text";
|
||||
}
|
||||
|
||||
if (viewName == "ImageView") {
|
||||
return "Image";
|
||||
}
|
||||
|
||||
if (viewName == "AndroidHorizontalScrollView") {
|
||||
return "ScrollView";
|
||||
}
|
||||
|
||||
if (viewName == "RKShimmeringView") {
|
||||
return "ShimmeringView";
|
||||
}
|
||||
|
||||
if (viewName == "RefreshControl") {
|
||||
return "PullToRefreshView";
|
||||
}
|
||||
|
||||
if (viewName == "AndroidProgressBar") {
|
||||
return "ActivityIndicatorView";
|
||||
}
|
||||
|
||||
// We need this temporarily for testing purposes until we have proper
|
||||
// implementation of core components.
|
||||
if (viewName == "ScrollContentView" ||
|
||||
viewName == "AndroidHorizontalScrollContentView" // Android
|
||||
) {
|
||||
return "View";
|
||||
}
|
||||
|
||||
// iOS-only
|
||||
if (viewName == "MultilineTextInputView" ||
|
||||
viewName == "SinglelineTextInputView") {
|
||||
return "TextInput";
|
||||
}
|
||||
|
||||
return viewName;
|
||||
}
|
||||
|
||||
ComponentDescriptor const &ComponentDescriptorRegistry::at(
|
||||
std::string const &componentName) const {
|
||||
std::shared_lock<better::shared_mutex> lock(mutex_);
|
||||
|
||||
auto unifiedComponentName = componentNameByReactViewName(componentName);
|
||||
|
||||
auto it = _registryByName.find(unifiedComponentName);
|
||||
if (it == _registryByName.end()) {
|
||||
mutex_.unlock_shared();
|
||||
providerRegistry_.request(unifiedComponentName.c_str());
|
||||
mutex_.lock_shared();
|
||||
|
||||
it = _registryByName.find(unifiedComponentName);
|
||||
|
||||
/*
|
||||
* TODO: T54849676
|
||||
* Uncomment the `assert` after the following block that checks
|
||||
* `_fallbackComponentDescriptor` is no longer needed. The assert assumes
|
||||
* that `componentDescriptorProviderRequest` is always not null and register
|
||||
* some component on every single request.
|
||||
*/
|
||||
// assert(it != _registryByName.end());
|
||||
}
|
||||
|
||||
if (it == _registryByName.end()) {
|
||||
if (_fallbackComponentDescriptor == nullptr) {
|
||||
throw std::invalid_argument(
|
||||
("Unable to find componentDescriptor for " + unifiedComponentName)
|
||||
.c_str());
|
||||
}
|
||||
return *_fallbackComponentDescriptor.get();
|
||||
}
|
||||
|
||||
return *it->second;
|
||||
}
|
||||
|
||||
ComponentDescriptor const *ComponentDescriptorRegistry::
|
||||
findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN(
|
||||
ComponentHandle componentHandle) const {
|
||||
std::shared_lock<better::shared_mutex> lock(mutex_);
|
||||
|
||||
auto iterator = _registryByHandle.find(componentHandle);
|
||||
if (iterator == _registryByHandle.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return iterator->second.get();
|
||||
}
|
||||
|
||||
ComponentDescriptor const &ComponentDescriptorRegistry::at(
|
||||
ComponentHandle componentHandle) const {
|
||||
std::shared_lock<better::shared_mutex> lock(mutex_);
|
||||
|
||||
return *_registryByHandle.at(componentHandle);
|
||||
}
|
||||
|
||||
SharedShadowNode ComponentDescriptorRegistry::createNode(
|
||||
Tag tag,
|
||||
std::string const &viewName,
|
||||
SurfaceId surfaceId,
|
||||
folly::dynamic const &propsDynamic,
|
||||
SharedEventTarget const &eventTarget) const {
|
||||
auto unifiedComponentName = componentNameByReactViewName(viewName);
|
||||
auto const &componentDescriptor = this->at(unifiedComponentName);
|
||||
|
||||
auto family = componentDescriptor.createFamily(
|
||||
ShadowNodeFamilyFragment{tag, surfaceId, nullptr},
|
||||
std::move(eventTarget));
|
||||
auto const props =
|
||||
componentDescriptor.cloneProps(nullptr, RawProps(propsDynamic));
|
||||
auto const state =
|
||||
componentDescriptor.createInitialState(ShadowNodeFragment{props}, family);
|
||||
|
||||
return componentDescriptor.createShadowNode(
|
||||
{
|
||||
/* .props = */ props,
|
||||
/* .children = */ ShadowNodeFragment::childrenPlaceholder(),
|
||||
/* .state = */ state,
|
||||
},
|
||||
family);
|
||||
}
|
||||
|
||||
void ComponentDescriptorRegistry::setFallbackComponentDescriptor(
|
||||
SharedComponentDescriptor descriptor) {
|
||||
_fallbackComponentDescriptor = descriptor;
|
||||
registerComponentDescriptor(descriptor);
|
||||
}
|
||||
|
||||
ComponentDescriptor::Shared
|
||||
ComponentDescriptorRegistry::getFallbackComponentDescriptor() const {
|
||||
return _fallbackComponentDescriptor;
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
89
node_modules/react-native/ReactCommon/fabric/uimanager/ComponentDescriptorRegistry.h
generated
vendored
Normal file
89
node_modules/react-native/ReactCommon/fabric/uimanager/ComponentDescriptorRegistry.h
generated
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <better/map.h>
|
||||
#include <better/mutex.h>
|
||||
|
||||
#include <react/core/ComponentDescriptor.h>
|
||||
#include <react/uimanager/ComponentDescriptorProvider.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class ComponentDescriptorProviderRegistry;
|
||||
class ComponentDescriptorRegistry;
|
||||
|
||||
using SharedComponentDescriptorRegistry =
|
||||
std::shared_ptr<const ComponentDescriptorRegistry>;
|
||||
|
||||
/*
|
||||
* Registry of particular `ComponentDescriptor`s.
|
||||
*/
|
||||
class ComponentDescriptorRegistry {
|
||||
public:
|
||||
using Shared = std::shared_ptr<const ComponentDescriptorRegistry>;
|
||||
|
||||
/*
|
||||
* Creates an object with stored `ComponentDescriptorParameters` which will
|
||||
* be used later to create `ComponentDescriptor`s.
|
||||
*/
|
||||
ComponentDescriptorRegistry(
|
||||
ComponentDescriptorParameters const ¶meters,
|
||||
ComponentDescriptorProviderRegistry const &providerRegistry);
|
||||
|
||||
/*
|
||||
* This is broken. Please do not use.
|
||||
* If you requesting a ComponentDescriptor and unsure that it's there, you are
|
||||
* doing something wrong.
|
||||
*/
|
||||
ComponentDescriptor const *
|
||||
findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN(
|
||||
ComponentHandle componentHandle) const;
|
||||
|
||||
ComponentDescriptor const &at(std::string const &componentName) const;
|
||||
ComponentDescriptor const &at(ComponentHandle componentHandle) const;
|
||||
|
||||
ShadowNode::Shared createNode(
|
||||
Tag tag,
|
||||
std::string const &viewName,
|
||||
SurfaceId surfaceId,
|
||||
folly::dynamic const &props,
|
||||
SharedEventTarget const &eventTarget) const;
|
||||
|
||||
void setFallbackComponentDescriptor(SharedComponentDescriptor descriptor);
|
||||
ComponentDescriptor::Shared getFallbackComponentDescriptor() const;
|
||||
|
||||
private:
|
||||
friend class ComponentDescriptorProviderRegistry;
|
||||
|
||||
void registerComponentDescriptor(
|
||||
SharedComponentDescriptor componentDescriptor) const;
|
||||
|
||||
/*
|
||||
* Creates a `ComponentDescriptor` using specified
|
||||
* `ComponentDescriptorProvider` and stored `ComponentDescriptorParameters`,
|
||||
* and then adds that to the registry.
|
||||
* To be used by `ComponentDescriptorProviderRegistry` only.
|
||||
* Thread safe.
|
||||
*/
|
||||
void add(ComponentDescriptorProvider componentDescriptorProvider) const;
|
||||
|
||||
mutable better::shared_mutex mutex_;
|
||||
mutable better::map<ComponentHandle, SharedComponentDescriptor>
|
||||
_registryByHandle;
|
||||
mutable better::map<std::string, SharedComponentDescriptor> _registryByName;
|
||||
ComponentDescriptor::Shared _fallbackComponentDescriptor;
|
||||
ComponentDescriptorParameters parameters_{};
|
||||
ComponentDescriptorProviderRegistry const &providerRegistry_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
344
node_modules/react-native/ReactCommon/fabric/uimanager/Scheduler.cpp
generated
vendored
Normal file
344
node_modules/react-native/ReactCommon/fabric/uimanager/Scheduler.cpp
generated
vendored
Normal file
@ -0,0 +1,344 @@
|
||||
/*
|
||||
* 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 "Scheduler.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
#include <react/core/LayoutContext.h>
|
||||
#include <react/debug/SystraceSection.h>
|
||||
#include <react/uimanager/ComponentDescriptorRegistry.h>
|
||||
#include <react/uimanager/UIManager.h>
|
||||
#include <react/uimanager/UIManagerBinding.h>
|
||||
#include <react/uimanager/UITemplateProcessor.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
Scheduler::Scheduler(
|
||||
SchedulerToolbox schedulerToolbox,
|
||||
SchedulerDelegate *delegate) {
|
||||
runtimeExecutor_ = schedulerToolbox.runtimeExecutor;
|
||||
|
||||
reactNativeConfig_ =
|
||||
schedulerToolbox.contextContainer
|
||||
->at<std::shared_ptr<const ReactNativeConfig>>("ReactNativeConfig");
|
||||
|
||||
auto uiManager = std::make_shared<UIManager>();
|
||||
auto eventOwnerBox = std::make_shared<EventBeat::OwnerBox>();
|
||||
|
||||
auto eventPipe = [uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const EventTarget *eventTarget,
|
||||
const std::string &type,
|
||||
const ValueFactory &payloadFactory) {
|
||||
uiManager->visitBinding([&](UIManagerBinding const &uiManagerBinding) {
|
||||
uiManagerBinding.dispatchEvent(
|
||||
runtime, eventTarget, type, payloadFactory);
|
||||
});
|
||||
};
|
||||
|
||||
auto statePipe = [uiManager](StateUpdate const &stateUpdate) {
|
||||
uiManager->updateState(stateUpdate);
|
||||
};
|
||||
|
||||
eventDispatcher_ = std::make_shared<EventDispatcher>(
|
||||
eventPipe,
|
||||
statePipe,
|
||||
schedulerToolbox.synchronousEventBeatFactory,
|
||||
schedulerToolbox.asynchronousEventBeatFactory,
|
||||
eventOwnerBox);
|
||||
|
||||
eventOwnerBox->owner = eventDispatcher_;
|
||||
|
||||
componentDescriptorRegistry_ = schedulerToolbox.componentRegistryFactory(
|
||||
eventDispatcher_, schedulerToolbox.contextContainer);
|
||||
|
||||
rootComponentDescriptor_ = std::make_unique<const RootComponentDescriptor>(
|
||||
ComponentDescriptorParameters{eventDispatcher_, nullptr, nullptr});
|
||||
|
||||
uiManager->setDelegate(this);
|
||||
uiManager->setComponentDescriptorRegistry(componentDescriptorRegistry_);
|
||||
|
||||
runtimeExecutor_([=](jsi::Runtime &runtime) {
|
||||
auto uiManagerBinding = UIManagerBinding::createAndInstallIfNeeded(runtime);
|
||||
uiManagerBinding->attach(uiManager);
|
||||
});
|
||||
|
||||
auto componentDescriptorRegistryKey =
|
||||
"ComponentDescriptorRegistry_DO_NOT_USE_PRETTY_PLEASE";
|
||||
schedulerToolbox.contextContainer->erase(componentDescriptorRegistryKey);
|
||||
schedulerToolbox.contextContainer->insert(
|
||||
componentDescriptorRegistryKey,
|
||||
std::weak_ptr<ComponentDescriptorRegistry const>(
|
||||
componentDescriptorRegistry_));
|
||||
|
||||
delegate_ = delegate;
|
||||
uiManager_ = uiManager;
|
||||
}
|
||||
|
||||
Scheduler::~Scheduler() {
|
||||
LOG(WARNING) << "Scheduler::~Scheduler() was called (address: " << this
|
||||
<< ").";
|
||||
|
||||
// All Surfaces must be explicitly stopped before destroying `Scheduler`.
|
||||
// The idea is that `UIManager` is allowed to call `Scheduler` only if the
|
||||
// corresponding `ShadowTree` instance exists.
|
||||
|
||||
// The thread-safety of this operation is guaranteed by this requirement.
|
||||
uiManager_->setDelegate(nullptr);
|
||||
|
||||
// Then, let's verify that the requirement was satisfied.
|
||||
auto surfaceIds = std::vector<SurfaceId>{};
|
||||
uiManager_->getShadowTreeRegistry().enumerate(
|
||||
[&](ShadowTree const &shadowTree, bool &stop) {
|
||||
surfaceIds.push_back(shadowTree.getSurfaceId());
|
||||
});
|
||||
|
||||
assert(
|
||||
surfaceIds.size() == 0 &&
|
||||
"Scheduler was destroyed with outstanding Surfaces.");
|
||||
|
||||
if (surfaceIds.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(ERROR) << "Scheduler was destroyed with outstanding Surfaces.";
|
||||
|
||||
// If we are here, that means assert didn't fire which indicates that we in
|
||||
// production.
|
||||
|
||||
// Now we have still-running surfaces, which is no good, no good.
|
||||
// That's indeed a sign of a severe issue on the application layer.
|
||||
// At this point, we don't have much to lose, so we are trying to unmount all
|
||||
// outstanding `ShadowTree`s to prevent all stored JSI entities from
|
||||
// overliving the `Scheduler`. (Unmounting `ShadowNode`s disables
|
||||
// `EventEmitter`s which destroys JSI objects.)
|
||||
for (auto surfaceId : surfaceIds) {
|
||||
uiManager_->getShadowTreeRegistry().visit(
|
||||
surfaceId,
|
||||
[](ShadowTree const &shadowTree) { shadowTree.commitEmptyTree(); });
|
||||
}
|
||||
}
|
||||
|
||||
void Scheduler::startSurface(
|
||||
SurfaceId surfaceId,
|
||||
const std::string &moduleName,
|
||||
const folly::dynamic &initialProps,
|
||||
const LayoutConstraints &layoutConstraints,
|
||||
const LayoutContext &layoutContext) const {
|
||||
SystraceSection s("Scheduler::startSurface");
|
||||
|
||||
auto shadowTree = std::make_unique<ShadowTree>(
|
||||
surfaceId,
|
||||
layoutConstraints,
|
||||
layoutContext,
|
||||
*rootComponentDescriptor_,
|
||||
*uiManager_);
|
||||
|
||||
auto uiManager = uiManager_;
|
||||
|
||||
uiManager->getShadowTreeRegistry().add(std::move(shadowTree));
|
||||
|
||||
runtimeExecutor_([=](jsi::Runtime &runtime) {
|
||||
uiManager->visitBinding([&](UIManagerBinding const &uiManagerBinding) {
|
||||
uiManagerBinding.startSurface(
|
||||
runtime, surfaceId, moduleName, initialProps);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void Scheduler::renderTemplateToSurface(
|
||||
SurfaceId surfaceId,
|
||||
const std::string &uiTemplate) {
|
||||
SystraceSection s("Scheduler::renderTemplateToSurface");
|
||||
try {
|
||||
if (uiTemplate.size() == 0) {
|
||||
return;
|
||||
}
|
||||
NativeModuleRegistry nMR;
|
||||
auto tree = UITemplateProcessor::buildShadowTree(
|
||||
uiTemplate,
|
||||
surfaceId,
|
||||
folly::dynamic::object(),
|
||||
*componentDescriptorRegistry_,
|
||||
nMR,
|
||||
reactNativeConfig_);
|
||||
|
||||
uiManager_->getShadowTreeRegistry().visit(
|
||||
surfaceId, [=](const ShadowTree &shadowTree) {
|
||||
return shadowTree.tryCommit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
return std::make_shared<RootShadowNode>(
|
||||
*oldRootShadowNode,
|
||||
ShadowNodeFragment{
|
||||
/* .props = */ ShadowNodeFragment::propsPlaceholder(),
|
||||
/* .children = */
|
||||
std::make_shared<SharedShadowNodeList>(
|
||||
SharedShadowNodeList{tree}),
|
||||
});
|
||||
});
|
||||
});
|
||||
} catch (const std::exception &e) {
|
||||
LOG(ERROR) << " >>>> EXCEPTION <<< rendering uiTemplate in "
|
||||
<< "Scheduler::renderTemplateToSurface: " << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
void Scheduler::stopSurface(SurfaceId surfaceId) const {
|
||||
SystraceSection s("Scheduler::stopSurface");
|
||||
|
||||
// Note, we have to do in inside `visit` function while the Shadow Tree
|
||||
// is still being registered.
|
||||
uiManager_->getShadowTreeRegistry().visit(
|
||||
surfaceId, [](ShadowTree const &shadowTree) {
|
||||
// As part of stopping a Surface, we need to properly destroy all
|
||||
// mounted views, so we need to commit an empty tree to trigger all
|
||||
// side-effects that will perform that.
|
||||
shadowTree.commitEmptyTree();
|
||||
});
|
||||
|
||||
// Waiting for all concurrent commits to be finished and unregistering the
|
||||
// `ShadowTree`.
|
||||
uiManager_->getShadowTreeRegistry().remove(surfaceId);
|
||||
|
||||
// We execute JavaScript/React part of the process at the very end to minimize
|
||||
// any visible side-effects of stopping the Surface. Any possible commits from
|
||||
// the JavaScript side will not be able to reference a `ShadowTree` and will
|
||||
// fail silently.
|
||||
auto uiManager = uiManager_;
|
||||
runtimeExecutor_([=](jsi::Runtime &runtime) {
|
||||
uiManager->visitBinding([&](UIManagerBinding const &uiManagerBinding) {
|
||||
uiManagerBinding.stopSurface(runtime, surfaceId);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Size Scheduler::measureSurface(
|
||||
SurfaceId surfaceId,
|
||||
const LayoutConstraints &layoutConstraints,
|
||||
const LayoutContext &layoutContext) const {
|
||||
SystraceSection s("Scheduler::measureSurface");
|
||||
|
||||
Size size;
|
||||
uiManager_->getShadowTreeRegistry().visit(
|
||||
surfaceId, [&](const ShadowTree &shadowTree) {
|
||||
shadowTree.tryCommit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
auto rootShadowNode =
|
||||
oldRootShadowNode->clone(layoutConstraints, layoutContext);
|
||||
rootShadowNode->layoutIfNeeded();
|
||||
size = rootShadowNode->getLayoutMetrics().frame.size;
|
||||
return nullptr;
|
||||
});
|
||||
});
|
||||
return size;
|
||||
}
|
||||
|
||||
MountingCoordinator::Shared Scheduler::findMountingCoordinator(
|
||||
SurfaceId surfaceId) const {
|
||||
MountingCoordinator::Shared mountingCoordinator = nullptr;
|
||||
uiManager_->getShadowTreeRegistry().visit(
|
||||
surfaceId, [&](const ShadowTree &shadowTree) {
|
||||
mountingCoordinator = shadowTree.getMountingCoordinator();
|
||||
});
|
||||
return mountingCoordinator;
|
||||
}
|
||||
|
||||
void Scheduler::constraintSurfaceLayout(
|
||||
SurfaceId surfaceId,
|
||||
const LayoutConstraints &layoutConstraints,
|
||||
const LayoutContext &layoutContext) const {
|
||||
SystraceSection s("Scheduler::constraintSurfaceLayout");
|
||||
|
||||
uiManager_->getShadowTreeRegistry().visit(
|
||||
surfaceId, [&](ShadowTree const &shadowTree) {
|
||||
shadowTree.commit([&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
return oldRootShadowNode->clone(layoutConstraints, layoutContext);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ComponentDescriptor const *
|
||||
Scheduler::findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN(
|
||||
ComponentHandle handle) const {
|
||||
return componentDescriptorRegistry_
|
||||
->findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN(handle);
|
||||
}
|
||||
|
||||
#pragma mark - Delegate
|
||||
|
||||
void Scheduler::setDelegate(SchedulerDelegate *delegate) {
|
||||
delegate_ = delegate;
|
||||
}
|
||||
|
||||
SchedulerDelegate *Scheduler::getDelegate() const {
|
||||
return delegate_;
|
||||
}
|
||||
|
||||
#pragma mark - UIManagerDelegate
|
||||
|
||||
void Scheduler::uiManagerDidFinishTransaction(
|
||||
MountingCoordinator::Shared const &mountingCoordinator) {
|
||||
SystraceSection s("Scheduler::uiManagerDidFinishTransaction");
|
||||
|
||||
if (delegate_) {
|
||||
delegate_->schedulerDidFinishTransaction(mountingCoordinator);
|
||||
}
|
||||
}
|
||||
|
||||
void Scheduler::uiManagerDidCreateShadowNode(
|
||||
const ShadowNode::Shared &shadowNode) {
|
||||
SystraceSection s("Scheduler::uiManagerDidCreateShadowNode");
|
||||
|
||||
if (delegate_) {
|
||||
auto shadowView = ShadowView(*shadowNode);
|
||||
delegate_->schedulerDidRequestPreliminaryViewAllocation(
|
||||
shadowNode->getSurfaceId(), shadowView);
|
||||
}
|
||||
}
|
||||
|
||||
void Scheduler::uiManagerDidDispatchCommand(
|
||||
const ShadowNode::Shared &shadowNode,
|
||||
std::string const &commandName,
|
||||
folly::dynamic const args) {
|
||||
SystraceSection s("Scheduler::uiManagerDispatchCommand");
|
||||
|
||||
if (delegate_) {
|
||||
auto shadowView = ShadowView(*shadowNode);
|
||||
delegate_->schedulerDidDispatchCommand(shadowView, commandName, args);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set JS responder for a view
|
||||
*/
|
||||
void Scheduler::uiManagerDidSetJSResponder(
|
||||
SurfaceId surfaceId,
|
||||
const ShadowNode::Shared &shadowNode,
|
||||
bool blockNativeResponder) {
|
||||
if (delegate_) {
|
||||
// TODO: the first shadowView paramenter, should be the first parent that
|
||||
// is non virtual.
|
||||
auto shadowView = ShadowView(*shadowNode);
|
||||
delegate_->schedulerDidSetJSResponder(
|
||||
surfaceId, shadowView, shadowView, blockNativeResponder);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the JSResponder for a view
|
||||
*/
|
||||
void Scheduler::uiManagerDidClearJSResponder() {
|
||||
if (delegate_) {
|
||||
delegate_->schedulerDidClearJSResponder();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
118
node_modules/react-native/ReactCommon/fabric/uimanager/Scheduler.h
generated
vendored
Normal file
118
node_modules/react-native/ReactCommon/fabric/uimanager/Scheduler.h
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include <react/components/root/RootComponentDescriptor.h>
|
||||
#include <react/config/ReactNativeConfig.h>
|
||||
#include <react/core/ComponentDescriptor.h>
|
||||
#include <react/core/LayoutConstraints.h>
|
||||
#include <react/uimanager/ComponentDescriptorFactory.h>
|
||||
#include <react/uimanager/ComponentDescriptorRegistry.h>
|
||||
#include <react/uimanager/SchedulerDelegate.h>
|
||||
#include <react/uimanager/SchedulerToolbox.h>
|
||||
#include <react/uimanager/UIManagerBinding.h>
|
||||
#include <react/uimanager/UIManagerDelegate.h>
|
||||
#include <react/utils/ContextContainer.h>
|
||||
#include <react/utils/RuntimeExecutor.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* Scheduler coordinates Shadow Tree updates and event flows.
|
||||
*/
|
||||
class Scheduler final : public UIManagerDelegate {
|
||||
public:
|
||||
Scheduler(SchedulerToolbox schedulerToolbox, SchedulerDelegate *delegate);
|
||||
~Scheduler();
|
||||
|
||||
#pragma mark - Surface Management
|
||||
|
||||
void startSurface(
|
||||
SurfaceId surfaceId,
|
||||
const std::string &moduleName,
|
||||
const folly::dynamic &initialProps,
|
||||
const LayoutConstraints &layoutConstraints = {},
|
||||
const LayoutContext &layoutContext = {}) const;
|
||||
|
||||
void renderTemplateToSurface(
|
||||
SurfaceId surfaceId,
|
||||
const std::string &uiTemplate);
|
||||
|
||||
void stopSurface(SurfaceId surfaceId) const;
|
||||
|
||||
Size measureSurface(
|
||||
SurfaceId surfaceId,
|
||||
const LayoutConstraints &layoutConstraints,
|
||||
const LayoutContext &layoutContext) const;
|
||||
|
||||
/*
|
||||
* Applies given `layoutConstraints` and `layoutContext` to a Surface.
|
||||
* The user interface will be relaid out as a result. The operation will be
|
||||
* performed synchronously (including mounting) if the method is called
|
||||
* on the main thread.
|
||||
* Can be called from any thread.
|
||||
*/
|
||||
void constraintSurfaceLayout(
|
||||
SurfaceId surfaceId,
|
||||
const LayoutConstraints &layoutConstraints,
|
||||
const LayoutContext &layoutContext) const;
|
||||
|
||||
/*
|
||||
* This is broken. Please do not use.
|
||||
* `ComponentDescriptor`s are not designed to be used outside of `UIManager`,
|
||||
* there is no any garantees about their lifetime.
|
||||
*/
|
||||
ComponentDescriptor const *
|
||||
findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN(
|
||||
ComponentHandle handle) const;
|
||||
|
||||
MountingCoordinator::Shared findMountingCoordinator(
|
||||
SurfaceId surfaceId) const;
|
||||
|
||||
#pragma mark - Delegate
|
||||
|
||||
/*
|
||||
* Sets and gets the Scheduler's delegate.
|
||||
* If you requesting a ComponentDescriptor and unsure that it's there, you are
|
||||
* doing something wrong.
|
||||
*/
|
||||
void setDelegate(SchedulerDelegate *delegate);
|
||||
SchedulerDelegate *getDelegate() const;
|
||||
|
||||
#pragma mark - UIManagerDelegate
|
||||
|
||||
void uiManagerDidFinishTransaction(
|
||||
MountingCoordinator::Shared const &mountingCoordinator) override;
|
||||
void uiManagerDidCreateShadowNode(
|
||||
const ShadowNode::Shared &shadowNode) override;
|
||||
void uiManagerDidDispatchCommand(
|
||||
const ShadowNode::Shared &shadowNode,
|
||||
std::string const &commandName,
|
||||
folly::dynamic const args) override;
|
||||
void uiManagerDidSetJSResponder(
|
||||
SurfaceId surfaceId,
|
||||
const ShadowNode::Shared &shadowView,
|
||||
bool blockNativeResponder) override;
|
||||
void uiManagerDidClearJSResponder() override;
|
||||
|
||||
private:
|
||||
SchedulerDelegate *delegate_;
|
||||
SharedComponentDescriptorRegistry componentDescriptorRegistry_;
|
||||
std::unique_ptr<const RootComponentDescriptor> rootComponentDescriptor_;
|
||||
RuntimeExecutor runtimeExecutor_;
|
||||
std::shared_ptr<UIManager> uiManager_;
|
||||
std::shared_ptr<const ReactNativeConfig> reactNativeConfig_;
|
||||
EventDispatcher::Shared eventDispatcher_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
62
node_modules/react-native/ReactCommon/fabric/uimanager/SchedulerDelegate.h
generated
vendored
Normal file
62
node_modules/react-native/ReactCommon/fabric/uimanager/SchedulerDelegate.h
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 <react/core/ReactPrimitives.h>
|
||||
#include <react/mounting/MountingCoordinator.h>
|
||||
#include <react/mounting/ShadowView.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* Abstract class for Scheduler's delegate.
|
||||
*/
|
||||
class SchedulerDelegate {
|
||||
public:
|
||||
/*
|
||||
* Called right after Scheduler computed (and laid out) a new updated version
|
||||
* of the tree and calculated a set of mutations which are sufficient
|
||||
* to construct a new one.
|
||||
*/
|
||||
virtual void schedulerDidFinishTransaction(
|
||||
MountingCoordinator::Shared const &mountingCoordinator) = 0;
|
||||
|
||||
/*
|
||||
* Called right after a new ShadowNode was created.
|
||||
*/
|
||||
virtual void schedulerDidRequestPreliminaryViewAllocation(
|
||||
SurfaceId surfaceId,
|
||||
const ShadowView &shadowView) = 0;
|
||||
|
||||
virtual void schedulerDidDispatchCommand(
|
||||
const ShadowView &shadowView,
|
||||
std::string const &commandName,
|
||||
folly::dynamic const args) = 0;
|
||||
|
||||
/*
|
||||
* Set JS responder for a view
|
||||
*/
|
||||
virtual void schedulerDidSetJSResponder(
|
||||
SurfaceId surfaceId,
|
||||
const ShadowView &shadowView,
|
||||
const ShadowView &initialShadowView,
|
||||
bool blockNativeResponder) = 0;
|
||||
|
||||
/*
|
||||
* Clear the JSResponder for a view
|
||||
*/
|
||||
virtual void schedulerDidClearJSResponder() = 0;
|
||||
|
||||
virtual ~SchedulerDelegate() noexcept = default;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
8
node_modules/react-native/ReactCommon/fabric/uimanager/SchedulerToolbox.cpp
generated
vendored
Normal file
8
node_modules/react-native/ReactCommon/fabric/uimanager/SchedulerToolbox.cpp
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
/*
|
||||
* 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 "SchedulerToolbox.h"
|
49
node_modules/react-native/ReactCommon/fabric/uimanager/SchedulerToolbox.h
generated
vendored
Normal file
49
node_modules/react-native/ReactCommon/fabric/uimanager/SchedulerToolbox.h
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/core/EventBeat.h>
|
||||
#include <react/uimanager/ComponentDescriptorFactory.h>
|
||||
#include <react/utils/ContextContainer.h>
|
||||
#include <react/utils/RuntimeExecutor.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* Contains all external dependencies of Scheduler.
|
||||
* Copyable.
|
||||
*/
|
||||
struct SchedulerToolbox final {
|
||||
/*
|
||||
* Represents general purpose DI container for product components/needs.
|
||||
* Must not be `nullptr`.
|
||||
*/
|
||||
ContextContainer::Shared contextContainer;
|
||||
|
||||
/*
|
||||
* Represents externally managed, lazily available collection of components.
|
||||
*/
|
||||
ComponentRegistryFactory componentRegistryFactory;
|
||||
|
||||
/*
|
||||
* Represents running JavaScript VM and associated execution queue.
|
||||
*/
|
||||
RuntimeExecutor runtimeExecutor;
|
||||
|
||||
/*
|
||||
* Asynchronous & synchronous event beats.
|
||||
* Represent connections with the platform-specific run loops and general
|
||||
* purpose background queue.
|
||||
*/
|
||||
EventBeat::Factory asynchronousEventBeatFactory;
|
||||
EventBeat::Factory synchronousEventBeatFactory;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
294
node_modules/react-native/ReactCommon/fabric/uimanager/UIManager.cpp
generated
vendored
Normal file
294
node_modules/react-native/ReactCommon/fabric/uimanager/UIManager.cpp
generated
vendored
Normal file
@ -0,0 +1,294 @@
|
||||
/*
|
||||
* 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 "UIManager.h"
|
||||
|
||||
#include <react/core/ShadowNodeFragment.h>
|
||||
#include <react/debug/SystraceSection.h>
|
||||
#include <react/graphics/Geometry.h>
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
UIManager::~UIManager() {
|
||||
LOG(WARNING) << "UIManager::~UIManager() was called (address: " << this
|
||||
<< ").";
|
||||
}
|
||||
|
||||
SharedShadowNode UIManager::createNode(
|
||||
Tag tag,
|
||||
std::string const &name,
|
||||
SurfaceId surfaceId,
|
||||
const RawProps &rawProps,
|
||||
SharedEventTarget eventTarget) const {
|
||||
SystraceSection s("UIManager::createNode");
|
||||
|
||||
auto &componentDescriptor = componentDescriptorRegistry_->at(name);
|
||||
auto fallbackDescriptor =
|
||||
componentDescriptorRegistry_->getFallbackComponentDescriptor();
|
||||
|
||||
auto family = componentDescriptor.createFamily(
|
||||
ShadowNodeFamilyFragment{tag, surfaceId, nullptr},
|
||||
std::move(eventTarget));
|
||||
auto const props = componentDescriptor.cloneProps(nullptr, rawProps);
|
||||
auto const state =
|
||||
componentDescriptor.createInitialState(ShadowNodeFragment{props}, family);
|
||||
|
||||
auto shadowNode = componentDescriptor.createShadowNode(
|
||||
ShadowNodeFragment{
|
||||
/* .props = */
|
||||
fallbackDescriptor != nullptr &&
|
||||
fallbackDescriptor->getComponentHandle() ==
|
||||
componentDescriptor.getComponentHandle()
|
||||
? componentDescriptor.cloneProps(
|
||||
props, RawProps(folly::dynamic::object("name", name)))
|
||||
: props,
|
||||
/* .children = */ ShadowNodeFragment::childrenPlaceholder(),
|
||||
/* .state = */ state,
|
||||
},
|
||||
family);
|
||||
|
||||
if (delegate_) {
|
||||
delegate_->uiManagerDidCreateShadowNode(shadowNode);
|
||||
}
|
||||
|
||||
return shadowNode;
|
||||
}
|
||||
|
||||
SharedShadowNode UIManager::cloneNode(
|
||||
const ShadowNode::Shared &shadowNode,
|
||||
const SharedShadowNodeSharedList &children,
|
||||
const RawProps *rawProps) const {
|
||||
SystraceSection s("UIManager::cloneNode");
|
||||
|
||||
auto &componentDescriptor = shadowNode->getComponentDescriptor();
|
||||
auto clonedShadowNode = componentDescriptor.cloneShadowNode(
|
||||
*shadowNode,
|
||||
{
|
||||
/* .props = */
|
||||
rawProps ? componentDescriptor.cloneProps(
|
||||
shadowNode->getProps(), *rawProps)
|
||||
: ShadowNodeFragment::propsPlaceholder(),
|
||||
/* .children = */ children,
|
||||
});
|
||||
|
||||
return clonedShadowNode;
|
||||
}
|
||||
|
||||
void UIManager::appendChild(
|
||||
const ShadowNode::Shared &parentShadowNode,
|
||||
const ShadowNode::Shared &childShadowNode) const {
|
||||
SystraceSection s("UIManager::appendChild");
|
||||
|
||||
auto &componentDescriptor = parentShadowNode->getComponentDescriptor();
|
||||
componentDescriptor.appendChild(parentShadowNode, childShadowNode);
|
||||
}
|
||||
|
||||
void UIManager::completeSurface(
|
||||
SurfaceId surfaceId,
|
||||
const SharedShadowNodeUnsharedList &rootChildren) const {
|
||||
SystraceSection s("UIManager::completeSurface");
|
||||
|
||||
shadowTreeRegistry_.visit(surfaceId, [&](ShadowTree const &shadowTree) {
|
||||
shadowTree.commit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
return std::make_shared<RootShadowNode>(
|
||||
*oldRootShadowNode,
|
||||
ShadowNodeFragment{
|
||||
/* .props = */ ShadowNodeFragment::propsPlaceholder(),
|
||||
/* .children = */ rootChildren,
|
||||
});
|
||||
},
|
||||
true);
|
||||
});
|
||||
}
|
||||
|
||||
void UIManager::setJSResponder(
|
||||
const ShadowNode::Shared &shadowNode,
|
||||
const bool blockNativeResponder) const {
|
||||
if (delegate_) {
|
||||
delegate_->uiManagerDidSetJSResponder(
|
||||
shadowNode->getSurfaceId(), shadowNode, blockNativeResponder);
|
||||
}
|
||||
}
|
||||
|
||||
void UIManager::clearJSResponder() const {
|
||||
if (delegate_) {
|
||||
delegate_->uiManagerDidClearJSResponder();
|
||||
}
|
||||
}
|
||||
|
||||
ShadowNode::Shared const *UIManager::getNewestCloneOfShadowNode(
|
||||
ShadowNode::Shared const &shadowNode) const {
|
||||
auto findNewestChildInParent =
|
||||
[&](auto const &parentNode) -> ShadowNode::Shared const * {
|
||||
for (auto const &child : parentNode.getChildren()) {
|
||||
if (ShadowNode::sameFamily(*child, *shadowNode)) {
|
||||
return &child;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
ShadowNode const *ancestorShadowNode;
|
||||
shadowTreeRegistry_.visit(
|
||||
shadowNode->getSurfaceId(), [&](ShadowTree const &shadowTree) {
|
||||
shadowTree.tryCommit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
ancestorShadowNode = oldRootShadowNode.get();
|
||||
return nullptr;
|
||||
},
|
||||
true);
|
||||
});
|
||||
|
||||
auto ancestors = shadowNode->getFamily().getAncestors(*ancestorShadowNode);
|
||||
|
||||
return findNewestChildInParent(ancestors.rbegin()->first.get());
|
||||
}
|
||||
|
||||
ShadowNode::Shared UIManager::findNodeAtPoint(
|
||||
ShadowNode::Shared const &node,
|
||||
Point point) const {
|
||||
return LayoutableShadowNode::findNodeAtPoint(
|
||||
*getNewestCloneOfShadowNode(node), point);
|
||||
}
|
||||
|
||||
void UIManager::setNativeProps(
|
||||
ShadowNode const &shadowNode,
|
||||
RawProps const &rawProps) const {
|
||||
SystraceSection s("UIManager::setNativeProps");
|
||||
|
||||
auto &componentDescriptor = shadowNode.getComponentDescriptor();
|
||||
auto props = componentDescriptor.cloneProps(shadowNode.getProps(), rawProps);
|
||||
|
||||
shadowTreeRegistry_.visit(
|
||||
shadowNode.getSurfaceId(), [&](ShadowTree const &shadowTree) {
|
||||
shadowTree.tryCommit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
return std::static_pointer_cast<RootShadowNode>(
|
||||
oldRootShadowNode->cloneTree(
|
||||
shadowNode.getFamily(),
|
||||
[&](ShadowNode const &oldShadowNode) {
|
||||
return oldShadowNode.clone({
|
||||
/* .props = */ props,
|
||||
});
|
||||
}));
|
||||
},
|
||||
true);
|
||||
});
|
||||
}
|
||||
|
||||
LayoutMetrics UIManager::getRelativeLayoutMetrics(
|
||||
ShadowNode const &shadowNode,
|
||||
ShadowNode const *ancestorShadowNode,
|
||||
LayoutableShadowNode::LayoutInspectingPolicy policy) const {
|
||||
SystraceSection s("UIManager::getRelativeLayoutMetrics");
|
||||
|
||||
if (!ancestorShadowNode) {
|
||||
shadowTreeRegistry_.visit(
|
||||
shadowNode.getSurfaceId(), [&](ShadowTree const &shadowTree) {
|
||||
shadowTree.tryCommit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
ancestorShadowNode = oldRootShadowNode.get();
|
||||
return nullptr;
|
||||
},
|
||||
true);
|
||||
});
|
||||
}
|
||||
|
||||
auto layoutableShadowNode =
|
||||
traitCast<LayoutableShadowNode const *>(&shadowNode);
|
||||
auto layoutableAncestorShadowNode =
|
||||
traitCast<LayoutableShadowNode const *>(ancestorShadowNode);
|
||||
|
||||
if (!layoutableShadowNode || !layoutableAncestorShadowNode) {
|
||||
return EmptyLayoutMetrics;
|
||||
}
|
||||
|
||||
return layoutableShadowNode->getRelativeLayoutMetrics(
|
||||
*layoutableAncestorShadowNode, policy);
|
||||
}
|
||||
|
||||
void UIManager::updateState(StateUpdate const &stateUpdate) const {
|
||||
auto &callback = stateUpdate.callback;
|
||||
auto &family = stateUpdate.family;
|
||||
auto &componentDescriptor = family->getComponentDescriptor();
|
||||
|
||||
shadowTreeRegistry_.visit(
|
||||
family->getSurfaceId(), [&](ShadowTree const &shadowTree) {
|
||||
shadowTree.tryCommit([&](RootShadowNode::Shared const
|
||||
&oldRootShadowNode) {
|
||||
return std::static_pointer_cast<
|
||||
RootShadowNode>(oldRootShadowNode->cloneTree(
|
||||
*family, [&](ShadowNode const &oldShadowNode) {
|
||||
auto newData =
|
||||
callback(oldShadowNode.getState()->getDataPointer());
|
||||
auto newState =
|
||||
componentDescriptor.createState(*family, newData);
|
||||
|
||||
return oldShadowNode.clone({
|
||||
/* .props = */ ShadowNodeFragment::propsPlaceholder(),
|
||||
/* .children = */ ShadowNodeFragment::childrenPlaceholder(),
|
||||
/* .state = */ newState,
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void UIManager::dispatchCommand(
|
||||
const ShadowNode::Shared &shadowNode,
|
||||
std::string const &commandName,
|
||||
folly::dynamic const args) const {
|
||||
if (delegate_) {
|
||||
delegate_->uiManagerDidDispatchCommand(shadowNode, commandName, args);
|
||||
}
|
||||
}
|
||||
|
||||
void UIManager::setComponentDescriptorRegistry(
|
||||
const SharedComponentDescriptorRegistry &componentDescriptorRegistry) {
|
||||
componentDescriptorRegistry_ = componentDescriptorRegistry;
|
||||
}
|
||||
|
||||
void UIManager::setDelegate(UIManagerDelegate *delegate) {
|
||||
delegate_ = delegate;
|
||||
}
|
||||
|
||||
UIManagerDelegate *UIManager::getDelegate() {
|
||||
return delegate_;
|
||||
}
|
||||
|
||||
void UIManager::visitBinding(
|
||||
std::function<void(UIManagerBinding const &uiManagerBinding)> callback)
|
||||
const {
|
||||
if (!uiManagerBinding_) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(*uiManagerBinding_);
|
||||
}
|
||||
|
||||
ShadowTreeRegistry const &UIManager::getShadowTreeRegistry() const {
|
||||
return shadowTreeRegistry_;
|
||||
}
|
||||
|
||||
#pragma mark - ShadowTreeDelegate
|
||||
|
||||
void UIManager::shadowTreeDidFinishTransaction(
|
||||
ShadowTree const &shadowTree,
|
||||
MountingCoordinator::Shared const &mountingCoordinator) const {
|
||||
SystraceSection s("UIManager::shadowTreeDidFinishTransaction");
|
||||
|
||||
if (delegate_) {
|
||||
delegate_->uiManagerDidFinishTransaction(mountingCoordinator);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
128
node_modules/react-native/ReactCommon/fabric/uimanager/UIManager.h
generated
vendored
Normal file
128
node_modules/react-native/ReactCommon/fabric/uimanager/UIManager.h
generated
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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/Optional.h>
|
||||
#include <folly/dynamic.h>
|
||||
#include <jsi/jsi.h>
|
||||
|
||||
#include <react/core/ShadowNode.h>
|
||||
#include <react/core/StateData.h>
|
||||
#include <react/mounting/ShadowTree.h>
|
||||
#include <react/mounting/ShadowTreeDelegate.h>
|
||||
#include <react/mounting/ShadowTreeRegistry.h>
|
||||
#include <react/uimanager/ComponentDescriptorRegistry.h>
|
||||
#include <react/uimanager/UIManagerDelegate.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class UIManagerBinding;
|
||||
|
||||
class UIManager final : public ShadowTreeDelegate {
|
||||
public:
|
||||
~UIManager();
|
||||
|
||||
void setComponentDescriptorRegistry(
|
||||
const SharedComponentDescriptorRegistry &componentDescriptorRegistry);
|
||||
|
||||
/*
|
||||
* Sets and gets the UIManager's delegate.
|
||||
* The delegate is stored as a raw pointer, so the owner must null
|
||||
* the pointer before being destroyed.
|
||||
*/
|
||||
void setDelegate(UIManagerDelegate *delegate);
|
||||
UIManagerDelegate *getDelegate();
|
||||
|
||||
/*
|
||||
* Provides access to a UIManagerBindging.
|
||||
* The `callback` methods will not be called if the internal pointer to
|
||||
* `UIManagerBindging` is `nullptr`.
|
||||
* The callback is called synchronously on the same thread.
|
||||
*/
|
||||
void visitBinding(
|
||||
std::function<void(UIManagerBinding const &uiManagerBinding)> callback)
|
||||
const;
|
||||
|
||||
#pragma mark - ShadowTreeDelegate
|
||||
|
||||
void shadowTreeDidFinishTransaction(
|
||||
ShadowTree const &shadowTree,
|
||||
MountingCoordinator::Shared const &mountingCoordinator) const override;
|
||||
|
||||
private:
|
||||
friend class UIManagerBinding;
|
||||
friend class Scheduler;
|
||||
|
||||
ShadowNode::Shared createNode(
|
||||
Tag tag,
|
||||
std::string const &componentName,
|
||||
SurfaceId surfaceId,
|
||||
const RawProps &props,
|
||||
SharedEventTarget eventTarget) const;
|
||||
|
||||
ShadowNode::Shared cloneNode(
|
||||
const ShadowNode::Shared &shadowNode,
|
||||
const SharedShadowNodeSharedList &children = nullptr,
|
||||
const RawProps *rawProps = nullptr) const;
|
||||
|
||||
void appendChild(
|
||||
const ShadowNode::Shared &parentShadowNode,
|
||||
const ShadowNode::Shared &childShadowNode) const;
|
||||
|
||||
void completeSurface(
|
||||
SurfaceId surfaceId,
|
||||
const SharedShadowNodeUnsharedList &rootChildren) const;
|
||||
|
||||
void setNativeProps(ShadowNode const &shadowNode, RawProps const &rawProps)
|
||||
const;
|
||||
|
||||
void setJSResponder(
|
||||
const ShadowNode::Shared &shadowNode,
|
||||
const bool blockNativeResponder) const;
|
||||
|
||||
void clearJSResponder() const;
|
||||
|
||||
ShadowNode::Shared findNodeAtPoint(
|
||||
ShadowNode::Shared const &shadowNode,
|
||||
Point point) const;
|
||||
|
||||
ShadowNode::Shared const *getNewestCloneOfShadowNode(
|
||||
ShadowNode::Shared const &shadowNode) const;
|
||||
|
||||
/*
|
||||
* Returns layout metrics of given `shadowNode` relative to
|
||||
* `ancestorShadowNode` (relative to the root node in case if provided
|
||||
* `ancestorShadowNode` is nullptr).
|
||||
*/
|
||||
LayoutMetrics getRelativeLayoutMetrics(
|
||||
ShadowNode const &shadowNode,
|
||||
ShadowNode const *ancestorShadowNode,
|
||||
LayoutableShadowNode::LayoutInspectingPolicy policy) const;
|
||||
|
||||
/*
|
||||
* Creates a new shadow node with given state data, clones what's necessary
|
||||
* and performs a commit.
|
||||
*/
|
||||
void updateState(StateUpdate const &stateUpdate) const;
|
||||
|
||||
void dispatchCommand(
|
||||
const ShadowNode::Shared &shadowNode,
|
||||
std::string const &commandName,
|
||||
folly::dynamic const args) const;
|
||||
|
||||
ShadowTreeRegistry const &getShadowTreeRegistry() const;
|
||||
|
||||
SharedComponentDescriptorRegistry componentDescriptorRegistry_;
|
||||
UIManagerDelegate *delegate_;
|
||||
UIManagerBinding *uiManagerBinding_;
|
||||
ShadowTreeRegistry shadowTreeRegistry_{};
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
605
node_modules/react-native/ReactCommon/fabric/uimanager/UIManagerBinding.cpp
generated
vendored
Normal file
605
node_modules/react-native/ReactCommon/fabric/uimanager/UIManagerBinding.cpp
generated
vendored
Normal file
@ -0,0 +1,605 @@
|
||||
/*
|
||||
* 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 "UIManagerBinding.h"
|
||||
|
||||
#include <react/debug/SystraceSection.h>
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <jsi/JSIDynamic.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
static jsi::Object getModule(
|
||||
jsi::Runtime &runtime,
|
||||
const std::string &moduleName) {
|
||||
auto batchedBridge =
|
||||
runtime.global().getPropertyAsObject(runtime, "__fbBatchedBridge");
|
||||
auto getCallableModule =
|
||||
batchedBridge.getPropertyAsFunction(runtime, "getCallableModule");
|
||||
auto module = getCallableModule
|
||||
.callWithThis(
|
||||
runtime,
|
||||
batchedBridge,
|
||||
{jsi::String::createFromUtf8(runtime, moduleName)})
|
||||
.asObject(runtime);
|
||||
return module;
|
||||
}
|
||||
|
||||
std::shared_ptr<UIManagerBinding> UIManagerBinding::createAndInstallIfNeeded(
|
||||
jsi::Runtime &runtime) {
|
||||
auto uiManagerModuleName = "nativeFabricUIManager";
|
||||
|
||||
auto uiManagerValue =
|
||||
runtime.global().getProperty(runtime, uiManagerModuleName);
|
||||
if (uiManagerValue.isUndefined()) {
|
||||
// The global namespace does not have an instance of the binding;
|
||||
// we need to create, install and return it.
|
||||
auto uiManagerBinding = std::make_shared<UIManagerBinding>();
|
||||
auto object = jsi::Object::createFromHostObject(runtime, uiManagerBinding);
|
||||
runtime.global().setProperty(
|
||||
runtime, uiManagerModuleName, std::move(object));
|
||||
return uiManagerBinding;
|
||||
}
|
||||
|
||||
// The global namespace already has an instance of the binding;
|
||||
// we need to return that.
|
||||
auto uiManagerObject = uiManagerValue.asObject(runtime);
|
||||
return uiManagerObject.getHostObject<UIManagerBinding>(runtime);
|
||||
}
|
||||
|
||||
UIManagerBinding::~UIManagerBinding() {
|
||||
LOG(WARNING) << "UIManager::~UIManager() was called (address: " << this
|
||||
<< ").";
|
||||
|
||||
// We must detach the `UIBinding` on deallocation to prevent accessing
|
||||
// deallocated `UIManagerBinding`.
|
||||
// Since `UIManagerBinding` retains `UIManager`, `UIManager` always overlive
|
||||
// `UIManagerBinding`, therefore we don't need similar logic in `UIManager`'s
|
||||
// destructor.
|
||||
attach(nullptr);
|
||||
}
|
||||
|
||||
void UIManagerBinding::attach(std::shared_ptr<UIManager> const &uiManager) {
|
||||
if (uiManager_) {
|
||||
uiManager_->uiManagerBinding_ = nullptr;
|
||||
}
|
||||
|
||||
uiManager_ = uiManager;
|
||||
|
||||
if (uiManager_) {
|
||||
uiManager_->uiManagerBinding_ = this;
|
||||
}
|
||||
}
|
||||
|
||||
void UIManagerBinding::startSurface(
|
||||
jsi::Runtime &runtime,
|
||||
SurfaceId surfaceId,
|
||||
const std::string &moduleName,
|
||||
const folly::dynamic &initalProps) const {
|
||||
folly::dynamic parameters = folly::dynamic::object();
|
||||
parameters["rootTag"] = surfaceId;
|
||||
parameters["initialProps"] = initalProps;
|
||||
parameters["fabric"] = true;
|
||||
|
||||
if (runtime.global().hasProperty(runtime, "RN$SurfaceRegistry")) {
|
||||
auto registry =
|
||||
runtime.global().getPropertyAsObject(runtime, "RN$SurfaceRegistry");
|
||||
auto method = registry.getPropertyAsFunction(runtime, "renderSurface");
|
||||
|
||||
method.call(
|
||||
runtime,
|
||||
{jsi::String::createFromUtf8(runtime, moduleName),
|
||||
jsi::valueFromDynamic(runtime, parameters)});
|
||||
} else {
|
||||
auto module = getModule(runtime, "AppRegistry");
|
||||
auto method = module.getPropertyAsFunction(runtime, "runApplication");
|
||||
|
||||
method.callWithThis(
|
||||
runtime,
|
||||
module,
|
||||
{jsi::String::createFromUtf8(runtime, moduleName),
|
||||
jsi::valueFromDynamic(runtime, parameters)});
|
||||
}
|
||||
}
|
||||
|
||||
void UIManagerBinding::stopSurface(jsi::Runtime &runtime, SurfaceId surfaceId)
|
||||
const {
|
||||
if (runtime.global().hasProperty(runtime, "RN$stopSurface")) {
|
||||
auto method =
|
||||
runtime.global().getPropertyAsFunction(runtime, "RN$stopSurface");
|
||||
method.call(runtime, {jsi::Value{surfaceId}});
|
||||
} else {
|
||||
auto module = getModule(runtime, "ReactFabric");
|
||||
auto method =
|
||||
module.getPropertyAsFunction(runtime, "unmountComponentAtNode");
|
||||
|
||||
method.callWithThis(runtime, module, {jsi::Value{surfaceId}});
|
||||
}
|
||||
}
|
||||
|
||||
void UIManagerBinding::dispatchEvent(
|
||||
jsi::Runtime &runtime,
|
||||
const EventTarget *eventTarget,
|
||||
const std::string &type,
|
||||
const ValueFactory &payloadFactory) const {
|
||||
SystraceSection s("UIManagerBinding::dispatchEvent");
|
||||
|
||||
auto payload = payloadFactory(runtime);
|
||||
|
||||
auto instanceHandle = eventTarget
|
||||
? [&]() {
|
||||
auto instanceHandle = eventTarget->getInstanceHandle(runtime);
|
||||
if (instanceHandle.isUndefined()) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
|
||||
// Mixing `target` into `payload`.
|
||||
assert(payload.isObject());
|
||||
payload.asObject(runtime).setProperty(runtime, "target", eventTarget->getTag());
|
||||
return instanceHandle;
|
||||
}()
|
||||
: jsi::Value::null();
|
||||
|
||||
auto &eventHandlerWrapper =
|
||||
static_cast<const EventHandlerWrapper &>(*eventHandler_);
|
||||
|
||||
eventHandlerWrapper.callback.call(
|
||||
runtime,
|
||||
{std::move(instanceHandle),
|
||||
jsi::String::createFromUtf8(runtime, type),
|
||||
std::move(payload)});
|
||||
}
|
||||
|
||||
void UIManagerBinding::invalidate() const {
|
||||
uiManager_->setDelegate(nullptr);
|
||||
}
|
||||
|
||||
jsi::Value UIManagerBinding::get(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::PropNameID &name) {
|
||||
auto methodName = name.utf8(runtime);
|
||||
|
||||
// Convert shared_ptr<UIManager> to a raw ptr
|
||||
// Why? Because:
|
||||
// 1) UIManagerBinding strongly retains UIManager. The JS VM
|
||||
// strongly retains UIManagerBinding (through the JSI).
|
||||
// These functions are JSI functions and are only called via
|
||||
// the JS VM; if the JS VM is torn down, those functions can't
|
||||
// execute and these lambdas won't execute.
|
||||
// 2) The UIManager is only deallocated when all references to it
|
||||
// are deallocated, including the UIManagerBinding. That only
|
||||
// happens when the JS VM is deallocated. So, the raw pointer
|
||||
// is safe.
|
||||
//
|
||||
// Even if it's safe, why not just use shared_ptr anyway as
|
||||
// extra insurance?
|
||||
// 1) Using shared_ptr or weak_ptr when they're not needed is
|
||||
// a pessimisation. It's more instructions executed without
|
||||
// any additional value in this case.
|
||||
// 2) How and when exactly these lambdas is deallocated is
|
||||
// complex. Adding shared_ptr to them which causes the UIManager
|
||||
// to potentially live longer is unnecessary, complicated cognitive
|
||||
// overhead.
|
||||
// 3) There is a strong suspicion that retaining UIManager from
|
||||
// these C++ lambdas, which are retained by an object that is held onto
|
||||
// by the JSI, caused some crashes upon deallocation of the
|
||||
// Scheduler and JS VM. This could happen if, for instance, C++
|
||||
// semantics cause these lambda to not be deallocated until
|
||||
// a CPU tick (or more) after the JS VM is deallocated.
|
||||
UIManager *uiManager = uiManager_.get();
|
||||
|
||||
// Semantic: Creates a new node with given pieces.
|
||||
if (methodName == "createNode") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
5,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
return valueFromShadowNode(
|
||||
runtime,
|
||||
uiManager->createNode(
|
||||
tagFromValue(runtime, arguments[0]),
|
||||
stringFromValue(runtime, arguments[1]),
|
||||
surfaceIdFromValue(runtime, arguments[2]),
|
||||
RawProps(runtime, arguments[3]),
|
||||
eventTargetFromValue(runtime, arguments[4], arguments[0])));
|
||||
});
|
||||
}
|
||||
|
||||
// Semantic: Clones the node with *same* props and *same* children.
|
||||
if (methodName == "cloneNode") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
1,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
return valueFromShadowNode(
|
||||
runtime,
|
||||
uiManager->cloneNode(shadowNodeFromValue(runtime, arguments[0])));
|
||||
});
|
||||
}
|
||||
|
||||
if (methodName == "setJSResponder") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
uiManager->setJSResponder(
|
||||
shadowNodeFromValue(runtime, arguments[0]),
|
||||
arguments[1].getBool());
|
||||
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
}
|
||||
|
||||
if (methodName == "findNodeAtPoint") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
auto node = shadowNodeFromValue(runtime, arguments[0]);
|
||||
auto locationX = (Float)arguments[1].getNumber();
|
||||
auto locationY = (Float)arguments[2].getNumber();
|
||||
auto onSuccessFunction =
|
||||
arguments[3].getObject(runtime).getFunction(runtime);
|
||||
auto targetNode =
|
||||
uiManager->findNodeAtPoint(node, Point{locationX, locationY});
|
||||
auto &eventTarget = targetNode->getEventEmitter()->eventTarget_;
|
||||
|
||||
EventEmitter::DispatchMutex().lock();
|
||||
eventTarget->retain(runtime);
|
||||
auto instanceHandle = eventTarget->getInstanceHandle(runtime);
|
||||
eventTarget->release(runtime);
|
||||
EventEmitter::DispatchMutex().unlock();
|
||||
|
||||
onSuccessFunction.call(runtime, std::move(instanceHandle));
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
}
|
||||
|
||||
if (methodName == "clearJSResponder") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
0,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
uiManager->clearJSResponder();
|
||||
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
}
|
||||
|
||||
// Semantic: Clones the node with *same* props and *empty* children.
|
||||
if (methodName == "cloneNodeWithNewChildren") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
1,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
return valueFromShadowNode(
|
||||
runtime,
|
||||
uiManager->cloneNode(
|
||||
shadowNodeFromValue(runtime, arguments[0]),
|
||||
ShadowNode::emptySharedShadowNodeSharedList()));
|
||||
});
|
||||
}
|
||||
|
||||
// Semantic: Clones the node with *given* props and *same* children.
|
||||
if (methodName == "cloneNodeWithNewProps") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
const auto &rawProps = RawProps(runtime, arguments[1]);
|
||||
return valueFromShadowNode(
|
||||
runtime,
|
||||
uiManager->cloneNode(
|
||||
shadowNodeFromValue(runtime, arguments[0]),
|
||||
nullptr,
|
||||
&rawProps));
|
||||
});
|
||||
}
|
||||
|
||||
// Semantic: Clones the node with *given* props and *empty* children.
|
||||
if (methodName == "cloneNodeWithNewChildrenAndProps") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
const auto &rawProps = RawProps(runtime, arguments[1]);
|
||||
return valueFromShadowNode(
|
||||
runtime,
|
||||
uiManager->cloneNode(
|
||||
shadowNodeFromValue(runtime, arguments[0]),
|
||||
ShadowNode::emptySharedShadowNodeSharedList(),
|
||||
&rawProps));
|
||||
});
|
||||
}
|
||||
|
||||
if (methodName == "appendChild") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
uiManager->appendChild(
|
||||
shadowNodeFromValue(runtime, arguments[0]),
|
||||
shadowNodeFromValue(runtime, arguments[1]));
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
}
|
||||
|
||||
if (methodName == "createChildSet") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
1,
|
||||
[](jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
auto shadowNodeList =
|
||||
std::make_shared<SharedShadowNodeList>(SharedShadowNodeList({}));
|
||||
return valueFromShadowNodeList(runtime, shadowNodeList);
|
||||
});
|
||||
}
|
||||
|
||||
if (methodName == "appendChildToSet") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
2,
|
||||
[](jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
auto shadowNodeList = shadowNodeListFromValue(runtime, arguments[0]);
|
||||
auto shadowNode = shadowNodeFromValue(runtime, arguments[1]);
|
||||
shadowNodeList->push_back(shadowNode);
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
}
|
||||
|
||||
if (methodName == "completeRoot") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
uiManager->completeSurface(
|
||||
surfaceIdFromValue(runtime, arguments[0]),
|
||||
shadowNodeListFromValue(runtime, arguments[1]));
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
}
|
||||
|
||||
if (methodName == "registerEventHandler") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
1,
|
||||
[this](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
auto eventHandler =
|
||||
arguments[0].getObject(runtime).getFunction(runtime);
|
||||
eventHandler_ =
|
||||
std::make_unique<EventHandlerWrapper>(std::move(eventHandler));
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
}
|
||||
|
||||
if (methodName == "getRelativeLayoutMetrics") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
auto layoutMetrics = uiManager->getRelativeLayoutMetrics(
|
||||
*shadowNodeFromValue(runtime, arguments[0]),
|
||||
shadowNodeFromValue(runtime, arguments[1]).get(),
|
||||
{/* .includeTransform = */ true});
|
||||
auto frame = layoutMetrics.frame;
|
||||
auto result = jsi::Object(runtime);
|
||||
result.setProperty(runtime, "left", frame.origin.x);
|
||||
result.setProperty(runtime, "top", frame.origin.y);
|
||||
result.setProperty(runtime, "width", frame.size.width);
|
||||
result.setProperty(runtime, "height", frame.size.height);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
if (methodName == "dispatchCommand") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
3,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
uiManager->dispatchCommand(
|
||||
shadowNodeFromValue(runtime, arguments[0]),
|
||||
stringFromValue(runtime, arguments[1]),
|
||||
commandArgsFromValue(runtime, arguments[2]));
|
||||
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
}
|
||||
|
||||
// Legacy API
|
||||
if (methodName == "measureLayout") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
4,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
auto layoutMetrics = uiManager->getRelativeLayoutMetrics(
|
||||
*shadowNodeFromValue(runtime, arguments[0]),
|
||||
shadowNodeFromValue(runtime, arguments[1]).get(),
|
||||
{/* .includeTransform = */ false});
|
||||
|
||||
if (layoutMetrics == EmptyLayoutMetrics) {
|
||||
auto onFailFunction =
|
||||
arguments[2].getObject(runtime).getFunction(runtime);
|
||||
onFailFunction.call(runtime);
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
|
||||
auto onSuccessFunction =
|
||||
arguments[3].getObject(runtime).getFunction(runtime);
|
||||
auto frame = layoutMetrics.frame;
|
||||
|
||||
onSuccessFunction.call(
|
||||
runtime,
|
||||
{jsi::Value{runtime, (double)frame.origin.x},
|
||||
jsi::Value{runtime, (double)frame.origin.y},
|
||||
jsi::Value{runtime, (double)frame.size.width},
|
||||
jsi::Value{runtime, (double)frame.size.height}});
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
}
|
||||
|
||||
if (methodName == "measure") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
auto layoutMetrics = uiManager->getRelativeLayoutMetrics(
|
||||
*shadowNodeFromValue(runtime, arguments[0]),
|
||||
nullptr,
|
||||
{/* .includeTransform = */ true});
|
||||
auto frame = layoutMetrics.frame;
|
||||
auto onSuccessFunction =
|
||||
arguments[1].getObject(runtime).getFunction(runtime);
|
||||
|
||||
onSuccessFunction.call(
|
||||
runtime,
|
||||
{0,
|
||||
0,
|
||||
jsi::Value{runtime, (double)frame.size.width},
|
||||
jsi::Value{runtime, (double)frame.size.height},
|
||||
jsi::Value{runtime, (double)frame.origin.x},
|
||||
jsi::Value{runtime, (double)frame.origin.y}});
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
}
|
||||
|
||||
if (methodName == "measureInWindow") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
auto layoutMetrics = uiManager->getRelativeLayoutMetrics(
|
||||
*shadowNodeFromValue(runtime, arguments[0]),
|
||||
nullptr,
|
||||
{/* .includeTransform = */ true});
|
||||
|
||||
auto onSuccessFunction =
|
||||
arguments[1].getObject(runtime).getFunction(runtime);
|
||||
auto frame = layoutMetrics.frame;
|
||||
|
||||
onSuccessFunction.call(
|
||||
runtime,
|
||||
{jsi::Value{runtime, (double)frame.origin.x},
|
||||
jsi::Value{runtime, (double)frame.origin.y},
|
||||
jsi::Value{runtime, (double)frame.size.width},
|
||||
jsi::Value{runtime, (double)frame.size.height}});
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
}
|
||||
|
||||
if (methodName == "setNativeProps") {
|
||||
return jsi::Function::createFromHostFunction(
|
||||
runtime,
|
||||
name,
|
||||
2,
|
||||
[uiManager](
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &thisValue,
|
||||
const jsi::Value *arguments,
|
||||
size_t count) -> jsi::Value {
|
||||
uiManager->setNativeProps(
|
||||
*shadowNodeFromValue(runtime, arguments[0]),
|
||||
RawProps(runtime, arguments[1]));
|
||||
|
||||
return jsi::Value::undefined();
|
||||
});
|
||||
}
|
||||
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
88
node_modules/react-native/ReactCommon/fabric/uimanager/UIManagerBinding.h
generated
vendored
Normal file
88
node_modules/react-native/ReactCommon/fabric/uimanager/UIManagerBinding.h
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <jsi/jsi.h>
|
||||
#include <react/uimanager/UIManager.h>
|
||||
#include <react/uimanager/primitives.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* Exposes UIManager to JavaScript realm.
|
||||
*/
|
||||
class UIManagerBinding : public jsi::HostObject {
|
||||
public:
|
||||
/*
|
||||
* Installs UIManagerBinding into JavaScript runtime if needed.
|
||||
* Creates and sets `UIManagerBinding` into the global namespace.
|
||||
* In case if the global namespace already has a `UIManagerBinding` installed,
|
||||
* returns that.
|
||||
* Thread synchronization must be enforced externally.
|
||||
*/
|
||||
static std::shared_ptr<UIManagerBinding> createAndInstallIfNeeded(
|
||||
jsi::Runtime &runtime);
|
||||
|
||||
~UIManagerBinding();
|
||||
|
||||
/*
|
||||
* Establish a relationship between `UIManager` and `UIManagerBinding` by
|
||||
* setting internal pointers to each other.
|
||||
* Must be called on JavaScript thread or during VM destruction.
|
||||
*/
|
||||
void attach(std::shared_ptr<UIManager> const &uiManager);
|
||||
|
||||
/*
|
||||
* Starts React Native Surface with given id, moduleName, and props.
|
||||
* Thread synchronization must be enforced externally.
|
||||
*/
|
||||
void startSurface(
|
||||
jsi::Runtime &runtime,
|
||||
SurfaceId surfaceId,
|
||||
const std::string &moduleName,
|
||||
const folly::dynamic &initalProps) const;
|
||||
|
||||
/*
|
||||
* Stops React Native Surface with given id.
|
||||
* Thread synchronization must be enforced externally.
|
||||
*/
|
||||
void stopSurface(jsi::Runtime &runtime, SurfaceId surfaceId) const;
|
||||
|
||||
/*
|
||||
* Delivers raw event data to JavaScript.
|
||||
* Thread synchronization must be enforced externally.
|
||||
*/
|
||||
void dispatchEvent(
|
||||
jsi::Runtime &runtime,
|
||||
const EventTarget *eventTarget,
|
||||
const std::string &type,
|
||||
const ValueFactory &payloadFactory) const;
|
||||
|
||||
/*
|
||||
* Invalidates the binding and underlying UIManager.
|
||||
* Allows to save some resources and prevents UIManager's delegate to be
|
||||
* called.
|
||||
* Calling public methods of this class after calling this method is UB.
|
||||
* Can be called on any thread.
|
||||
*/
|
||||
void invalidate() const;
|
||||
|
||||
/*
|
||||
* `jsi::HostObject` specific overloads.
|
||||
*/
|
||||
jsi::Value get(jsi::Runtime &runtime, const jsi::PropNameID &name) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<UIManager> uiManager_;
|
||||
std::unique_ptr<const EventHandler> eventHandler_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
62
node_modules/react-native/ReactCommon/fabric/uimanager/UIManagerDelegate.h
generated
vendored
Normal file
62
node_modules/react-native/ReactCommon/fabric/uimanager/UIManagerDelegate.h
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 <react/core/ReactPrimitives.h>
|
||||
#include <react/core/ShadowNode.h>
|
||||
#include <react/mounting/MountingCoordinator.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* Abstract class for UIManager's delegate.
|
||||
*/
|
||||
class UIManagerDelegate {
|
||||
public:
|
||||
/*
|
||||
* Called right after a new/updated Shadow Node tree is constructed.
|
||||
* For this moment the tree is already laid out and sealed.
|
||||
*/
|
||||
virtual void uiManagerDidFinishTransaction(
|
||||
MountingCoordinator::Shared const &mountingCoordinator) = 0;
|
||||
|
||||
/*
|
||||
* Called each time when UIManager constructs a new Shadow Node. Receiver
|
||||
* might use this to optimistically allocate a new native view
|
||||
* instances.
|
||||
*/
|
||||
virtual void uiManagerDidCreateShadowNode(
|
||||
const ShadowNode::Shared &shadowNode) = 0;
|
||||
|
||||
/*
|
||||
* Called when UIManager wants to dispatch a command to the mounting layer.
|
||||
*/
|
||||
virtual void uiManagerDidDispatchCommand(
|
||||
const ShadowNode::Shared &shadowNode,
|
||||
std::string const &commandName,
|
||||
folly::dynamic const args) = 0;
|
||||
|
||||
/*
|
||||
* Set JS responder for a view
|
||||
*/
|
||||
virtual void uiManagerDidSetJSResponder(
|
||||
SurfaceId surfaceId,
|
||||
ShadowNode::Shared const &shadowView,
|
||||
bool blockNativeResponder) = 0;
|
||||
|
||||
/*
|
||||
* Clear the JSResponder for a view
|
||||
*/
|
||||
virtual void uiManagerDidClearJSResponder() = 0;
|
||||
|
||||
virtual ~UIManagerDelegate() noexcept = default;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
155
node_modules/react-native/ReactCommon/fabric/uimanager/UITemplateProcessor.cpp
generated
vendored
Normal file
155
node_modules/react-native/ReactCommon/fabric/uimanager/UITemplateProcessor.cpp
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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 "UITemplateProcessor.h"
|
||||
|
||||
#include <folly/json.h>
|
||||
#include <glog/logging.h>
|
||||
#include <react/components/view/ViewComponentDescriptor.h>
|
||||
#include <react/components/view/ViewProps.h>
|
||||
#include <react/components/view/ViewShadowNode.h>
|
||||
#include <react/core/ComponentDescriptor.h>
|
||||
#include <react/core/LayoutContext.h>
|
||||
#include <react/core/ShadowNodeFragment.h>
|
||||
#include <react/debug/DebugStringConvertible.h>
|
||||
#include <react/debug/DebugStringConvertibleItem.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
bool constexpr DEBUG_FLY = false;
|
||||
|
||||
struct RBCContext {
|
||||
const Tag rootTag;
|
||||
const std::vector<SharedShadowNode> &nodes;
|
||||
const std::vector<folly::dynamic> ®isters;
|
||||
const ComponentDescriptorRegistry &componentDescriptorRegistry;
|
||||
const NativeModuleRegistry &nativeModuleRegistry;
|
||||
};
|
||||
|
||||
// TODO: use RBCContext instead of all the separate arguments.
|
||||
SharedShadowNode UITemplateProcessor::runCommand(
|
||||
const folly::dynamic &command,
|
||||
SurfaceId surfaceId,
|
||||
std::vector<SharedShadowNode> &nodes,
|
||||
std::vector<folly::dynamic> ®isters,
|
||||
const ComponentDescriptorRegistry &componentDescriptorRegistry,
|
||||
const NativeModuleRegistry &nativeModuleRegistry,
|
||||
const std::shared_ptr<const ReactNativeConfig> reactNativeConfig) {
|
||||
const std::string &opcode = command[0].asString();
|
||||
const int tagOffset = 420000;
|
||||
// TODO: change to integer codes and a switch statement
|
||||
if (opcode == "createNode") {
|
||||
int tag = command[1].asInt();
|
||||
const auto &type = command[2].asString();
|
||||
const auto parentTag = command[3].asInt();
|
||||
const auto &props = command[4];
|
||||
nodes[tag] = componentDescriptorRegistry.createNode(
|
||||
tag + tagOffset, type, surfaceId, props, nullptr);
|
||||
if (parentTag > -1) { // parentTag == -1 indicates root node
|
||||
auto parentShadowNode = nodes[parentTag];
|
||||
auto const &componentDescriptor = componentDescriptorRegistry.at(
|
||||
parentShadowNode->getComponentHandle());
|
||||
componentDescriptor.appendChild(parentShadowNode, nodes[tag]);
|
||||
}
|
||||
} else if (opcode == "returnRoot") {
|
||||
if (DEBUG_FLY) {
|
||||
LOG(INFO)
|
||||
<< "(stop) UITemplateProcessor inject serialized 'server rendered' view tree";
|
||||
}
|
||||
return nodes[command[1].asInt()];
|
||||
} else if (opcode == "loadNativeBool") {
|
||||
int registerNumber = command[1].asInt();
|
||||
std::string param = command[4][0].asString();
|
||||
registers[registerNumber] = reactNativeConfig->getBool(param);
|
||||
} else if (opcode == "conditional") {
|
||||
int registerNumber = command[1].asInt();
|
||||
auto conditionDynamic = registers[registerNumber];
|
||||
if (conditionDynamic.isNull()) {
|
||||
// TODO: provide original command or command line?
|
||||
auto err = std::runtime_error(
|
||||
"register " + command[1].asString() + " wasn't loaded before access");
|
||||
throw err;
|
||||
} else if (conditionDynamic.type() != folly::dynamic::BOOL) {
|
||||
// TODO: provide original command or command line?
|
||||
auto err = std::runtime_error(
|
||||
"register " + command[1].asString() + " had type '" +
|
||||
conditionDynamic.typeName() +
|
||||
"' but needs to be 'boolean' for conditionals");
|
||||
throw err;
|
||||
}
|
||||
const auto &nextCommands =
|
||||
conditionDynamic.asBool() ? command[2] : command[3];
|
||||
for (const auto &nextCommand : nextCommands) {
|
||||
runCommand(
|
||||
nextCommand,
|
||||
surfaceId,
|
||||
nodes,
|
||||
registers,
|
||||
componentDescriptorRegistry,
|
||||
nativeModuleRegistry,
|
||||
reactNativeConfig);
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("Unsupported opcode: " + command[0].asString());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SharedShadowNode UITemplateProcessor::buildShadowTree(
|
||||
const std::string &jsonStr,
|
||||
SurfaceId surfaceId,
|
||||
const folly::dynamic ¶ms,
|
||||
const ComponentDescriptorRegistry &componentDescriptorRegistry,
|
||||
const NativeModuleRegistry &nativeModuleRegistry,
|
||||
const std::shared_ptr<const ReactNativeConfig> reactNativeConfig) {
|
||||
if (DEBUG_FLY) {
|
||||
LOG(INFO)
|
||||
<< "(strt) UITemplateProcessor inject hardcoded 'server rendered' view tree";
|
||||
}
|
||||
|
||||
std::string content = jsonStr;
|
||||
for (const auto ¶m : params.items()) {
|
||||
const auto &key = param.first.asString();
|
||||
size_t start_pos = content.find(key);
|
||||
if (start_pos != std::string::npos) {
|
||||
content.replace(start_pos, key.length(), param.second.asString());
|
||||
}
|
||||
}
|
||||
auto parsed = folly::parseJson(content);
|
||||
auto commands = parsed["commands"];
|
||||
std::vector<SharedShadowNode> nodes(commands.size() * 2);
|
||||
std::vector<folly::dynamic> registers(32);
|
||||
for (const auto &command : commands) {
|
||||
try {
|
||||
if (DEBUG_FLY) {
|
||||
LOG(INFO) << "try to run command " << folly::toJson(command);
|
||||
}
|
||||
auto ret = runCommand(
|
||||
command,
|
||||
surfaceId,
|
||||
nodes,
|
||||
registers,
|
||||
componentDescriptorRegistry,
|
||||
nativeModuleRegistry,
|
||||
reactNativeConfig);
|
||||
if (ret != nullptr) {
|
||||
return ret;
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
LOG(ERROR) << " >>> Exception <<< running previous command '"
|
||||
<< folly::toJson(command) << "': '" << e.what() << "'";
|
||||
}
|
||||
}
|
||||
LOG(ERROR) << "react ui template missing returnRoot command :(";
|
||||
throw std::runtime_error(
|
||||
"Missing returnRoot command in template content:\n" + content);
|
||||
return SharedShadowNode{};
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
66
node_modules/react-native/ReactCommon/fabric/uimanager/UITemplateProcessor.h
generated
vendored
Normal file
66
node_modules/react-native/ReactCommon/fabric/uimanager/UITemplateProcessor.h
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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 <folly/dynamic.h>
|
||||
|
||||
#include <react/config/ReactNativeConfig.h>
|
||||
#include <react/core/ShadowNode.h>
|
||||
#include <react/uimanager/ComponentDescriptorRegistry.h>
|
||||
#include <react/uimanager/UIManagerDelegate.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
// Temporary NativeModuleRegistry definition
|
||||
using NativeModuleCallFn =
|
||||
std::function<folly::dynamic(const std::string &, const folly::dynamic &)>;
|
||||
|
||||
class NativeModuleRegistry {
|
||||
public:
|
||||
void registerModule(
|
||||
const std::string &moduleName,
|
||||
NativeModuleCallFn callFn) {
|
||||
modules_.emplace(moduleName, callFn);
|
||||
}
|
||||
|
||||
folly::dynamic call(
|
||||
const std::string &moduleName,
|
||||
const std::string &methodName,
|
||||
const folly::dynamic &args) const {
|
||||
return modules_.at(moduleName)(methodName, args);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, NativeModuleCallFn> modules_;
|
||||
};
|
||||
|
||||
class UITemplateProcessor {
|
||||
public:
|
||||
static ShadowNode::Shared buildShadowTree(
|
||||
const std::string &jsonStr,
|
||||
int rootTag,
|
||||
const folly::dynamic ¶ms,
|
||||
const ComponentDescriptorRegistry &componentDescriptorRegistry,
|
||||
const NativeModuleRegistry &nativeModuleRegistry,
|
||||
const std::shared_ptr<const ReactNativeConfig> reactNativeConfig);
|
||||
|
||||
private:
|
||||
static ShadowNode::Shared runCommand(
|
||||
const folly::dynamic &command,
|
||||
Tag rootTag,
|
||||
std::vector<SharedShadowNode> &nodes,
|
||||
std::vector<folly::dynamic> ®isters,
|
||||
const ComponentDescriptorRegistry &componentDescriptorRegistry,
|
||||
const NativeModuleRegistry &nativeModuleRegistry,
|
||||
const std::shared_ptr<const ReactNativeConfig> reactNativeConfig);
|
||||
};
|
||||
} // namespace react
|
||||
} // namespace facebook
|
101
node_modules/react-native/ReactCommon/fabric/uimanager/primitives.h
generated
vendored
Normal file
101
node_modules/react-native/ReactCommon/fabric/uimanager/primitives.h
generated
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <jsi/JSIDynamic.h>
|
||||
#include <jsi/jsi.h>
|
||||
#include <react/core/EventHandler.h>
|
||||
#include <react/core/ShadowNode.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
struct EventHandlerWrapper : public EventHandler {
|
||||
EventHandlerWrapper(jsi::Function eventHandler)
|
||||
: callback(std::move(eventHandler)) {}
|
||||
|
||||
jsi::Function callback;
|
||||
};
|
||||
|
||||
struct ShadowNodeWrapper : public jsi::HostObject {
|
||||
ShadowNodeWrapper(SharedShadowNode shadowNode)
|
||||
: shadowNode(std::move(shadowNode)) {}
|
||||
|
||||
ShadowNode::Shared shadowNode;
|
||||
};
|
||||
|
||||
struct ShadowNodeListWrapper : public jsi::HostObject {
|
||||
ShadowNodeListWrapper(SharedShadowNodeUnsharedList shadowNodeList)
|
||||
: shadowNodeList(shadowNodeList) {}
|
||||
|
||||
SharedShadowNodeUnsharedList shadowNodeList;
|
||||
};
|
||||
|
||||
inline static ShadowNode::Shared shadowNodeFromValue(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &value) {
|
||||
return value.getObject(runtime)
|
||||
.getHostObject<ShadowNodeWrapper>(runtime)
|
||||
->shadowNode;
|
||||
}
|
||||
|
||||
inline static jsi::Value valueFromShadowNode(
|
||||
jsi::Runtime &runtime,
|
||||
const ShadowNode::Shared &shadowNode) {
|
||||
return jsi::Object::createFromHostObject(
|
||||
runtime, std::make_shared<ShadowNodeWrapper>(shadowNode));
|
||||
}
|
||||
|
||||
inline static SharedShadowNodeUnsharedList shadowNodeListFromValue(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &value) {
|
||||
return value.getObject(runtime)
|
||||
.getHostObject<ShadowNodeListWrapper>(runtime)
|
||||
->shadowNodeList;
|
||||
}
|
||||
|
||||
inline static jsi::Value valueFromShadowNodeList(
|
||||
jsi::Runtime &runtime,
|
||||
const SharedShadowNodeUnsharedList &shadowNodeList) {
|
||||
return jsi::Object::createFromHostObject(
|
||||
runtime, std::make_unique<ShadowNodeListWrapper>(shadowNodeList));
|
||||
}
|
||||
|
||||
inline static SharedEventTarget eventTargetFromValue(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &eventTargetValue,
|
||||
const jsi::Value &tagValue) {
|
||||
return std::make_shared<EventTarget>(
|
||||
runtime, eventTargetValue, tagValue.getNumber());
|
||||
}
|
||||
|
||||
inline static Tag tagFromValue(jsi::Runtime &runtime, const jsi::Value &value) {
|
||||
return (Tag)value.getNumber();
|
||||
}
|
||||
|
||||
inline static SurfaceId surfaceIdFromValue(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &value) {
|
||||
return (SurfaceId)value.getNumber();
|
||||
}
|
||||
|
||||
inline static std::string stringFromValue(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &value) {
|
||||
return value.getString(runtime).utf8(runtime);
|
||||
}
|
||||
|
||||
inline static folly::dynamic commandArgsFromValue(
|
||||
jsi::Runtime &runtime,
|
||||
const jsi::Value &value) {
|
||||
return jsi::dynamicFromValue(runtime, value);
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
17
node_modules/react-native/ReactCommon/fabric/uimanager/tests/FabricUIManagerTest.cpp
generated
vendored
Normal file
17
node_modules/react-native/ReactCommon/fabric/uimanager/tests/FabricUIManagerTest.cpp
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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 <gtest/gtest.h>
|
||||
#include <react/uimanager/UIManager.h>
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
TEST(UIManagerTest, testSomething) {
|
||||
// TODO
|
||||
}
|
168
node_modules/react-native/ReactCommon/fabric/uimanager/tests/UITemplateProcessorTest.cpp
generated
vendored
Normal file
168
node_modules/react-native/ReactCommon/fabric/uimanager/tests/UITemplateProcessorTest.cpp
generated
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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 <exception>
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <react/uimanager/ComponentDescriptorFactory.h>
|
||||
#include <react/uimanager/UITemplateProcessor.h>
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
#include <react/components/rncore/ComponentDescriptors.h>
|
||||
#include <react/components/scrollview/ScrollViewComponentDescriptor.h>
|
||||
#include <react/components/view/ViewComponentDescriptor.h>
|
||||
#include <react/config/ReactNativeConfig.h>
|
||||
#include <react/uimanager/ComponentDescriptorFactory.h>
|
||||
#include <react/uimanager/ComponentDescriptorProviderRegistry.h>
|
||||
#include <react/uimanager/ComponentDescriptorRegistry.h>
|
||||
#include <react/utils/ContextContainer.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
static ComponentRegistryFactory getComponentRegistryFactory() {
|
||||
return [](const EventDispatcher::Weak &eventDispatcher,
|
||||
const ContextContainer::Shared &contextContainer) {
|
||||
ComponentDescriptorProviderRegistry providerRegistry{};
|
||||
providerRegistry.add(
|
||||
concreteComponentDescriptorProvider<ViewComponentDescriptor>());
|
||||
providerRegistry.add(
|
||||
concreteComponentDescriptorProvider<ScrollViewComponentDescriptor>());
|
||||
providerRegistry.add(concreteComponentDescriptorProvider<
|
||||
ActivityIndicatorViewComponentDescriptor>());
|
||||
return providerRegistry.createComponentDescriptorRegistry(
|
||||
{eventDispatcher, contextContainer});
|
||||
};
|
||||
}
|
||||
|
||||
bool mockSimpleTestValue_;
|
||||
|
||||
NativeModuleRegistry buildNativeModuleRegistry();
|
||||
|
||||
NativeModuleRegistry buildNativeModuleRegistry() {
|
||||
NativeModuleRegistry nMR;
|
||||
nMR.registerModule(
|
||||
"MobileConfig",
|
||||
[&](const std::string &methodName, const folly::dynamic &args) {
|
||||
return mockSimpleTestValue_;
|
||||
});
|
||||
return nMR;
|
||||
}
|
||||
|
||||
class MockReactNativeConfig : public ReactNativeConfig {
|
||||
public:
|
||||
MockReactNativeConfig() {}
|
||||
bool getBool(const std::string ¶m) const override {
|
||||
return mockSimpleTestValue_;
|
||||
}
|
||||
|
||||
std::string getString(const std::string ¶m) const override {
|
||||
return "";
|
||||
}
|
||||
|
||||
int64_t getInt64(const std::string ¶m) const override {
|
||||
return 0;
|
||||
}
|
||||
|
||||
double getDouble(const std::string ¶m) const override {
|
||||
return 0.0;
|
||||
}
|
||||
};
|
||||
|
||||
std::shared_ptr<const ReactNativeConfig> mockReactNativeConfig_ =
|
||||
std::make_shared<const MockReactNativeConfig>();
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
||||
TEST(UITemplateProcessorTest, testSimpleBytecode) {
|
||||
auto surfaceId = 11;
|
||||
auto eventDispatcher = std::shared_ptr<EventDispatcher const>();
|
||||
auto componentDescriptorRegistry =
|
||||
getComponentRegistryFactory()(eventDispatcher, nullptr);
|
||||
auto nativeModuleRegistry = buildNativeModuleRegistry();
|
||||
|
||||
auto bytecode = R"delim({"version":0.1,"commands":[
|
||||
["createNode",2,"RCTView",-1,{"opacity": 0.5, "testId": "root"}],
|
||||
["createNode",4,"RCTView",2,{"testId": "child"}],
|
||||
["returnRoot",2]
|
||||
]})delim";
|
||||
|
||||
mockSimpleTestValue_ = true;
|
||||
|
||||
auto root1 = UITemplateProcessor::buildShadowTree(
|
||||
bytecode,
|
||||
surfaceId,
|
||||
folly::dynamic::object(),
|
||||
*componentDescriptorRegistry,
|
||||
nativeModuleRegistry,
|
||||
mockReactNativeConfig_);
|
||||
#ifndef NDEBUG
|
||||
LOG(INFO) << std::endl << root1->getDebugDescription();
|
||||
#endif
|
||||
auto props1 = std::dynamic_pointer_cast<const ViewProps>(root1->getProps());
|
||||
EXPECT_NEAR(props1->opacity, 0.5, 0.001);
|
||||
ASSERT_STREQ(props1->testId.c_str(), "root");
|
||||
auto children1 = root1->getChildren();
|
||||
EXPECT_EQ(children1.size(), 1);
|
||||
auto child_props1 =
|
||||
std::dynamic_pointer_cast<const ViewProps>(children1.at(0)->getProps());
|
||||
ASSERT_STREQ(child_props1->testId.c_str(), "child");
|
||||
}
|
||||
|
||||
TEST(UITemplateProcessorTest, testConditionalBytecode) {
|
||||
auto surfaceId = 11;
|
||||
auto eventDispatcher = std::shared_ptr<EventDispatcher const>();
|
||||
auto componentDescriptorRegistry =
|
||||
getComponentRegistryFactory()(eventDispatcher, nullptr);
|
||||
auto nativeModuleRegistry = buildNativeModuleRegistry();
|
||||
|
||||
auto bytecode = R"delim({"version":0.1,"commands":[
|
||||
["createNode",2,"RCTView",-1,{"testId": "root"}],
|
||||
["loadNativeBool",1,"MobileConfig","getBool",["qe:simple_test"]],
|
||||
["conditional",1,
|
||||
[["createNode",4,"RCTView",2,{"testId": "cond_true"}]],
|
||||
[["createNode",4,"RCTView",2,{"testId": "cond_false"}]]
|
||||
],
|
||||
["returnRoot",2]
|
||||
]})delim";
|
||||
|
||||
mockSimpleTestValue_ = true;
|
||||
|
||||
auto root1 = UITemplateProcessor::buildShadowTree(
|
||||
bytecode,
|
||||
surfaceId,
|
||||
folly::dynamic::object(),
|
||||
*componentDescriptorRegistry,
|
||||
nativeModuleRegistry,
|
||||
mockReactNativeConfig_);
|
||||
#ifndef NDEBUG
|
||||
LOG(INFO) << std::endl << root1->getDebugDescription();
|
||||
#endif
|
||||
auto props1 = std::dynamic_pointer_cast<const ViewProps>(root1->getProps());
|
||||
ASSERT_STREQ(props1->testId.c_str(), "root");
|
||||
auto children1 = root1->getChildren();
|
||||
EXPECT_EQ(children1.size(), 1);
|
||||
auto child_props1 =
|
||||
std::dynamic_pointer_cast<const ViewProps>(children1.at(0)->getProps());
|
||||
ASSERT_STREQ(child_props1->testId.c_str(), "cond_true");
|
||||
|
||||
mockSimpleTestValue_ = false;
|
||||
|
||||
auto root2 = UITemplateProcessor::buildShadowTree(
|
||||
bytecode,
|
||||
surfaceId,
|
||||
folly::dynamic::object(),
|
||||
*componentDescriptorRegistry,
|
||||
nativeModuleRegistry,
|
||||
mockReactNativeConfig_);
|
||||
auto child_props2 = std::dynamic_pointer_cast<const ViewProps>(
|
||||
root2->getChildren().at(0)->getProps());
|
||||
ASSERT_STREQ(child_props2->testId.c_str(), "cond_false");
|
||||
}
|
Reference in New Issue
Block a user