Delete native UI template (#39487)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/39487

changelog: [internal]

renderTemplateToSurface isn't used, let's remove it.

Reviewed By: javache

Differential Revision: D49313868

fbshipit-source-id: 9019d5b4adbd23632f27dd61bc18a97b447575d4
This commit is contained in:
Samuel Susla
2023-10-06 07:44:50 -07:00
committed by Facebook GitHub Bot
parent d0f750e15d
commit 1719a072fd
21 changed files with 6 additions and 554 deletions
@@ -1237,8 +1237,7 @@ public class ReactInstanceManager {
reactRoot.getRootViewGroup(),
initialProperties == null
? new WritableNativeMap()
: Arguments.fromBundle(initialProperties),
reactRoot.getInitialUITemplate());
: Arguments.fromBundle(initialProperties));
reactRoot.setRootViewTag(rootTag);
reactRoot.runApplication();
}
@@ -94,7 +94,6 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
private @Nullable ReactInstanceManager mReactInstanceManager;
private @Nullable String mJSModuleName;
private @Nullable Bundle mAppProperties;
private @Nullable String mInitialUITemplate;
private @Nullable CustomGlobalLayoutListener mCustomGlobalLayoutListener;
private @Nullable ReactRootViewEventListener mRootViewEventListener;
private int mRootViewTag =
@@ -452,14 +451,6 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
startReactApplication(reactInstanceManager, moduleName, null);
}
/** {@see #startReactApplication(ReactInstanceManager, String, android.os.Bundle, String)} */
public void startReactApplication(
ReactInstanceManager reactInstanceManager,
String moduleName,
@Nullable Bundle initialProperties) {
startReactApplication(reactInstanceManager, moduleName, initialProperties, null);
}
/**
* Schedule rendering of the react component rendered by the JS application from the given JS
* module (@{param moduleName}) using provided {@param reactInstanceManager} to attach to the JS
@@ -470,8 +461,7 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
public void startReactApplication(
ReactInstanceManager reactInstanceManager,
String moduleName,
@Nullable Bundle initialProperties,
@Nullable String initialUITemplate) {
@Nullable Bundle initialProperties) {
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "startReactApplication");
try {
UiThreadUtil.assertOnUiThread();
@@ -486,7 +476,6 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
mReactInstanceManager = reactInstanceManager;
mJSModuleName = moduleName;
mAppProperties = initialProperties;
mInitialUITemplate = initialUITemplate;
mReactInstanceManager.createReactContextInBackground();
// if in this experiment, we initialize the root earlier in startReactApplication
@@ -651,11 +640,6 @@ public class ReactRootView extends FrameLayout implements RootView, ReactRoot {
return mAppProperties;
}
@Override
public @Nullable String getInitialUITemplate() {
return mInitialUITemplate;
}
@ThreadConfined(UI)
public void setAppProperties(@Nullable Bundle appProperties) {
UiThreadUtil.assertOnUiThread();
@@ -21,8 +21,7 @@ public interface UIManager extends JSIModule, PerformanceCounter {
@UiThread
@ThreadConfined(UI)
@Deprecated
<T extends View> int addRootView(
final T rootView, WritableMap initialProps, @Nullable String initialUITemplate);
<T extends View> int addRootView(final T rootView, WritableMap initialProps);
/** Registers a new root view with width and height. */
@AnyThread
@@ -33,8 +33,6 @@ public interface Binding {
boolean isRTL,
boolean doLeftAndRightSwapInRTL);
public void renderTemplateToSurface(int surfaceId, String uiTemplate);
public void stopSurface(int surfaceId);
public void setPixelDensity(float pointScaleFactor);
@@ -63,9 +63,6 @@ public class BindingImpl implements Binding {
boolean isRTL,
boolean doLeftAndRightSwapInRTL);
@Override
public native void renderTemplateToSurface(int surfaceId, String uiTemplate);
@Override
public native void stopSurface(int surfaceId);
@@ -237,8 +237,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
@UiThread
@ThreadConfined(UI)
@Deprecated
public <T extends View> int addRootView(
final T rootView, final WritableMap initialProps, final @Nullable String initialUITemplate) {
public <T extends View> int addRootView(final T rootView, final WritableMap initialProps) {
ReactSoftExceptionLogger.logSoftException(
TAG,
new IllegalViewOperationException(
@@ -256,9 +255,6 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
FLog.d(TAG, "Starting surface for module: %s and reactTag: %d", moduleName, rootTag);
}
mBinding.startSurface(rootTag, moduleName, (NativeMap) initialProps);
if (initialUITemplate != null) {
mBinding.renderTemplateToSurface(rootTag, initialUITemplate);
}
return rootTag;
}
@@ -25,9 +25,6 @@ public interface ReactRoot {
@Nullable
Bundle getAppProperties();
@Nullable
String getInitialUITemplate();
String getJSModuleName();
/** Fabric or Default UI Manager, see {@link UIManagerType} */
@@ -313,7 +313,7 @@ public class UIManagerModule extends ReactContextBaseJavaModule
}
public <T extends View> int addRootView(final T rootView) {
return addRootView(rootView, null, null);
return addRootView(rootView, null);
}
/**
@@ -341,8 +341,7 @@ public class UIManagerModule extends ReactContextBaseJavaModule
* <p>TODO(6242243): Make addRootView thread safe NB: this method is horribly not-thread-safe.
*/
@Override
public <T extends View> int addRootView(
final T rootView, WritableMap initialProps, @Nullable String initialUITemplate) {
public <T extends View> int addRootView(final T rootView, WritableMap initialProps) {
Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "UIManagerModule.addRootView");
final int tag = ReactRootViewTagGenerator.getNextRootViewTag();
final ReactApplicationContext reactApplicationContext = getReactApplicationContext();
@@ -77,7 +77,6 @@ add_react_common_subdir(react/renderer/componentregistry)
add_react_common_subdir(react/renderer/mounting)
add_react_common_subdir(react/renderer/scheduler)
add_react_common_subdir(react/renderer/telemetry)
add_react_common_subdir(react/renderer/templateprocessor)
add_react_common_subdir(react/renderer/uimanager)
add_react_common_subdir(react/renderer/core)
add_react_common_subdir(react/renderer/element)
@@ -164,7 +163,6 @@ add_executable(reactnative_unittest
${REACT_COMMON_DIR}/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp
${REACT_COMMON_DIR}/react/renderer/runtimescheduler/tests/SchedulerPriorityTest.cpp
${REACT_COMMON_DIR}/react/renderer/telemetry/tests/TransactionTelemetryTest.cpp
${REACT_COMMON_DIR}/react/renderer/templateprocessor/tests/UITemplateProcessorTest.cpp
${REACT_COMMON_DIR}/react/renderer/textlayoutmanager/tests/TextLayoutManagerTest.cpp
${REACT_COMMON_DIR}/react/renderer/uimanager/tests/FabricUIManagerTest.cpp
@@ -209,7 +207,6 @@ add_executable(reactnative_unittest
react_render_graphics
react_render_mapbuffer
react_render_mounting
react_render_templateprocessor
react_render_textlayoutmanager
react_render_uimanager
react_utils
@@ -219,21 +219,6 @@ void Binding::startSurfaceWithConstraints(
mountingManager->onSurfaceStart(surfaceId);
}
void Binding::renderTemplateToSurface(jint surfaceId, jstring uiTemplate) {
SystraceSection s("FabricUIManagerBinding::renderTemplateToSurface");
auto scheduler = getScheduler();
if (!scheduler) {
LOG(ERROR) << "Binding::renderTemplateToSurface: scheduler disappeared";
return;
}
auto env = jni::Environment::current();
const char* nativeString = env->GetStringUTFChars(uiTemplate, JNI_FALSE);
scheduler->renderTemplateToSurface(surfaceId, nativeString);
env->ReleaseStringUTFChars(uiTemplate, nativeString);
}
void Binding::stopSurface(jint surfaceId) {
SystraceSection s("FabricUIManagerBinding::stopSurface");
@@ -581,8 +566,6 @@ void Binding::registerNatives() {
"getInspectorDataForInstance", Binding::getInspectorDataForInstance),
makeNativeMethod(
"startSurfaceWithConstraints", Binding::startSurfaceWithConstraints),
makeNativeMethod(
"renderTemplateToSurface", Binding::renderTemplateToSurface),
makeNativeMethod("stopSurface", Binding::stopSurface),
makeNativeMethod("setConstraints", Binding::setConstraints),
makeNativeMethod("setPixelDensity", Binding::setPixelDensity),
@@ -88,8 +88,6 @@ class Binding : public jni::HybridClass<Binding>,
jboolean isRTL,
jboolean doLeftAndRightSwapInRTL);
void renderTemplateToSurface(jint surfaceId, jstring uiTemplate);
void stopSurface(jint surfaceId);
void registerSurface(SurfaceHandlerBinding* surfaceHandler);
@@ -38,7 +38,6 @@ target_link_libraries(
react_render_runtimescheduler
react_render_scheduler
react_render_telemetry
react_render_templateprocessor
react_render_textlayoutmanager
react_render_uimanager
react_utils
@@ -121,33 +121,6 @@ bool ComponentDescriptorRegistry::hasComponentDescriptorAt(
return iterator != _registryByHandle.end();
}
ShadowNode::Shared ComponentDescriptorRegistry::createNode(
Tag tag,
const std::string& viewName,
SurfaceId surfaceId,
const folly::dynamic& propsDynamic,
const InstanceHandle::Shared& instanceHandle) const {
auto unifiedComponentName = componentNameByReactViewName(viewName);
const auto& componentDescriptor = this->at(unifiedComponentName);
const auto fragment =
ShadowNodeFamilyFragment{tag, surfaceId, instanceHandle};
auto family = componentDescriptor.createFamily(fragment);
const auto props = componentDescriptor.cloneProps(
PropsParserContext{surfaceId, *contextContainer_.get()},
nullptr,
RawProps(propsDynamic));
const auto state = componentDescriptor.createInitialState(props, family);
return componentDescriptor.createShadowNode(
{
/* .props = */ props,
/* .children = */ ShadowNodeFragment::childrenPlaceholder(),
/* .state = */ state,
},
family);
}
void ComponentDescriptorRegistry::setFallbackComponentDescriptor(
const SharedComponentDescriptor& descriptor) {
_fallbackComponentDescriptor = descriptor;
@@ -54,13 +54,6 @@ class ComponentDescriptorRegistry {
bool hasComponentDescriptorAt(ComponentHandle componentHandle) const;
ShadowNode::Shared createNode(
Tag tag,
const std::string& viewName,
SurfaceId surfaceId,
const folly::dynamic& props,
const InstanceHandle::Shared& instanceHandle) const;
void setFallbackComponentDescriptor(
const SharedComponentDescriptor& descriptor);
ComponentDescriptor::Shared getFallbackComponentDescriptor() const;
@@ -32,7 +32,6 @@ target_link_libraries(react_render_scheduler
react_render_graphics
react_render_mounting
react_render_runtimescheduler
react_render_templateprocessor
react_render_uimanager
react_utils
rrc_root
@@ -18,7 +18,6 @@
#include <react/renderer/mounting/MountingOverrideDelegate.h>
#include <react/renderer/mounting/ShadowViewMutation.h>
#include <react/renderer/runtimescheduler/RuntimeScheduler.h>
#include <react/renderer/templateprocessor/UITemplateProcessor.h>
#include <react/renderer/uimanager/UIManager.h>
#include <react/renderer/uimanager/UIManagerBinding.h>
@@ -256,44 +255,6 @@ void Scheduler::unregisterSurface(
surfaceHandler.setUIManager(nullptr);
}
void Scheduler::renderTemplateToSurface(
SurfaceId surfaceId,
const std::string& uiTemplate) {
SystraceSection s("Scheduler::renderTemplateToSurface");
try {
if (uiTemplate.empty()) {
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 const& oldRootShadowNode) {
return std::make_shared<RootShadowNode>(
oldRootShadowNode,
ShadowNodeFragment{
/* .props = */ ShadowNodeFragment::propsPlaceholder(),
/* .children = */
std::make_shared<ShadowNode::ListOfShared>(
ShadowNode::ListOfShared{tree}),
});
},
{/* default commit options */});
});
} catch (const std::exception& e) {
LOG(ERROR) << " >>>> EXCEPTION <<< rendering uiTemplate in "
<< "Scheduler::renderTemplateToSurface: " << e.what();
}
}
const ComponentDescriptor*
Scheduler::findComponentDescriptorByHandle_DO_NOT_USE_THIS_IS_BROKEN(
ComponentHandle handle) const {
@@ -54,10 +54,6 @@ class Scheduler final : public UIManagerDelegate {
InspectorData getInspectorDataForInstance(
const EventEmitter& eventEmitter) const noexcept;
void renderTemplateToSurface(
SurfaceId surfaceId,
const std::string& uiTemplate);
/*
* This is broken. Please do not use.
* `ComponentDescriptor`s are not designed to be used outside of `UIManager`,
@@ -1,33 +0,0 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE on)
add_compile_options(
-fexceptions
-frtti
-std=c++20
-Wall
-Wpedantic
-Wno-gnu-zero-variadic-macro-arguments
-DLOG_TAG=\"Fabric\")
file(GLOB react_render_templateprocessor_SRC CONFIGURE_DEPENDS *.cpp)
add_library(react_render_templateprocessor SHARED ${react_render_templateprocessor_SRC})
target_include_directories(react_render_templateprocessor PUBLIC ${REACT_COMMON_DIR})
target_link_libraries(react_render_templateprocessor
folly_runtime
glog
jsi
react_config
react_render_componentregistry
react_render_core
react_render_debug
react_render_uimanager
react_utils
)
@@ -1,153 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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/renderer/components/view/ViewComponentDescriptor.h>
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/components/view/ViewShadowNode.h>
#include <react/renderer/core/ComponentDescriptor.h>
#include <react/renderer/core/LayoutContext.h>
#include <react/renderer/core/ShadowNodeFragment.h>
#include <react/renderer/debug/DebugStringConvertible.h>
#include <react/renderer/debug/DebugStringConvertibleItem.h>
namespace facebook::react {
bool constexpr DEBUG_FLY = false;
struct RBCContext {
const Tag rootTag;
const std::vector<ShadowNode::Shared>& nodes;
const std::vector<folly::dynamic>& registers;
const ComponentDescriptorRegistry& componentDescriptorRegistry;
const NativeModuleRegistry& nativeModuleRegistry;
};
// TODO: use RBCContext instead of all the separate arguments.
ShadowNode::Shared UITemplateProcessor::runCommand(
const folly::dynamic& command,
SurfaceId surfaceId,
std::vector<ShadowNode::Shared>& nodes,
std::vector<folly::dynamic>& registers,
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") {
Tag tag = static_cast<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[static_cast<size_t>(parentTag)];
const auto& 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[static_cast<Tag>(command[1].asInt())];
} else if (opcode == "loadNativeBool") {
auto registerNumber = static_cast<size_t>(command[1].asInt());
std::string param = command[4][0].asString();
registers[registerNumber] = reactNativeConfig->getBool(param);
} else if (opcode == "conditional") {
auto registerNumber = static_cast<size_t>(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;
}
ShadowNode::Shared UITemplateProcessor::buildShadowTree(
const std::string& jsonStr,
SurfaceId surfaceId,
const folly::dynamic& params,
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& param : 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<ShadowNode::Shared> 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 ShadowNode::Shared{};
}
} // namespace facebook::react
@@ -1,64 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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/renderer/componentregistry/ComponentDescriptorRegistry.h>
#include <react/renderer/core/ShadowNode.h>
#include <react/renderer/uimanager/UIManagerDelegate.h>
namespace facebook::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 surfaceId,
const folly::dynamic& params,
const ComponentDescriptorRegistry& componentDescriptorRegistry,
const NativeModuleRegistry& nativeModuleRegistry,
const std::shared_ptr<const ReactNativeConfig>& reactNativeConfig);
private:
static ShadowNode::Shared runCommand(
const folly::dynamic& command,
Tag surfaceId,
std::vector<ShadowNode::Shared>& nodes,
std::vector<folly::dynamic>& registers,
const ComponentDescriptorRegistry& componentDescriptorRegistry,
const NativeModuleRegistry& nativeModuleRegistry,
const std::shared_ptr<const ReactNativeConfig>& reactNativeConfig);
};
} // namespace facebook::react
@@ -1,166 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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/renderer/componentregistry/ComponentDescriptorFactory.h>
#include <react/renderer/templateprocessor/UITemplateProcessor.h>
using namespace facebook::react;
#include <react/config/ReactNativeConfig.h>
#include <react/renderer/componentregistry/ComponentDescriptorFactory.h>
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
#include <react/renderer/componentregistry/ComponentDescriptorRegistry.h>
#include <react/renderer/components/rncore/ComponentDescriptors.h>
#include <react/renderer/components/scrollview/ScrollViewComponentDescriptor.h>
#include <react/renderer/components/view/ViewComponentDescriptor.h>
#include <react/utils/ContextContainer.h>
namespace facebook::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& /*unused*/, const folly::dynamic& /*unused*/) {
return mockSimpleTestValue_;
});
return nMR;
}
class MockReactNativeConfig : public ReactNativeConfig {
public:
MockReactNativeConfig() = default;
bool getBool(const std::string& /*param*/) const override {
return mockSimpleTestValue_;
}
std::string getString(const std::string& /*param*/) const override {
return "";
}
int64_t getInt64(const std::string& /*param*/) const override {
return 0;
}
double getDouble(const std::string& /*param*/) const override {
return 0.0;
}
};
std::shared_ptr<const ReactNativeConfig> mockReactNativeConfig_ =
std::make_shared<const MockReactNativeConfig>();
} // namespace facebook::react
TEST(UITemplateProcessorTest, testSimpleBytecode) {
auto surfaceId = 11;
auto eventDispatcher = std::shared_ptr<const EventDispatcher>();
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::static_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::static_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<const EventDispatcher>();
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::static_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::static_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::static_pointer_cast<const ViewProps>(
root2->getChildren().at(0)->getProps());
ASSERT_STREQ(child_props2->testId.c_str(), "cond_false");
}