Move surface registry code out of UIManagerBinding

Summary:
changelog: [internal]

Just moving code that doesn't belong to UIManagerBinding out of the class.

Reviewed By: philIip

Differential Revision: D33060412

fbshipit-source-id: 2d54929072cef14fd1fa6b70bde382ae21ecff45
This commit is contained in:
Samuel Susla authored and Facebook GitHub Bot committed 2021-12-15 10:52:15 -08:00
1 parent 34c4fdb8e2
commit d902a89b40
8 files changed
+263 -203

No files matched your search

@@ -0,0 +1,105 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "SurfaceRegistryBinding.h"
#include <react/renderer/debug/SystraceSection.h>
#include <react/renderer/uimanager/bindingUtils.h>
#include <react/renderer/uimanager/primitives.h>
#include "bindingUtils.h"
namespace facebook::react {
void SurfaceRegistryBinding::startSurface(
jsi::Runtime &runtime,
SurfaceId surfaceId,
std::string const &moduleName,
folly::dynamic const &initalProps,
DisplayMode displayMode) {
SystraceSection s("SurfaceRegistryBinding::startSurface");
folly::dynamic parameters = folly::dynamic::object();
parameters["rootTag"] = surfaceId;
parameters["initialProps"] = initalProps;
parameters["fabric"] = true;
if (moduleName != "LogBox" &&
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),
jsi::Value(runtime, displayModeToInt(displayMode))});
} else {
callMethodOfModule(
runtime,
"AppRegistry",
"runApplication",
{jsi::String::createFromUtf8(runtime, moduleName),
jsi::valueFromDynamic(runtime, parameters),
jsi::Value(runtime, displayModeToInt(displayMode))});
}
}
void SurfaceRegistryBinding::setSurfaceProps(
jsi::Runtime &runtime,
SurfaceId surfaceId,
std::string const &moduleName,
folly::dynamic const &initalProps,
DisplayMode displayMode) {
SystraceSection s("UIManagerBinding::setSurfaceProps");
folly::dynamic parameters = folly::dynamic::object();
parameters["rootTag"] = surfaceId;
parameters["initialProps"] = initalProps;
parameters["fabric"] = true;
if (moduleName != "LogBox" &&
runtime.global().hasProperty(runtime, "RN$SurfaceRegistry")) {
auto registry =
runtime.global().getPropertyAsObject(runtime, "RN$SurfaceRegistry");
auto method = registry.getPropertyAsFunction(runtime, "setSurfaceProps");
method.call(
runtime,
{jsi::String::createFromUtf8(runtime, moduleName),
jsi::valueFromDynamic(runtime, parameters),
jsi::Value(runtime, displayModeToInt(displayMode))});
} else {
callMethodOfModule(
runtime,
"AppRegistry",
"setSurfaceProps",
{jsi::String::createFromUtf8(runtime, moduleName),
jsi::valueFromDynamic(runtime, parameters),
jsi::Value(runtime, displayModeToInt(displayMode))});
}
}
void SurfaceRegistryBinding::stopSurface(
jsi::Runtime &runtime,
SurfaceId surfaceId) {
auto global = runtime.global();
if (global.hasProperty(runtime, "RN$Bridgeless")) {
if (!global.hasProperty(runtime, "RN$stopSurface")) {
// ReactFabric module has not been loaded yet; there's no surface to stop.
return;
}
// Bridgeless mode uses a custom JSI binding instead of callable module.
global.getPropertyAsFunction(runtime, "RN$stopSurface")
.call(runtime, {jsi::Value{surfaceId}});
} else {
callMethodOfModule(
runtime,
"ReactFabric",
"unmountComponentAtNode",
{jsi::Value{surfaceId}});
}
}
} // namespace facebook::react
@@ -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 <jsi/jsi.h>
#include <react/renderer/core/ReactPrimitives.h>
namespace facebook::react {
class SurfaceRegistryBinding final {
public:
SurfaceRegistryBinding() = delete;
/*
* Starts React Native Surface with given id, moduleName, and props.
* Thread synchronization must be enforced externally.
*/
static void startSurface(
jsi::Runtime &runtime,
SurfaceId surfaceId,
std::string const &moduleName,
folly::dynamic const &initalProps,
DisplayMode displayMode);
/*
* Updates the React Native Surface identified with surfaceId and moduleName
* with the given props.
* Thread synchronization must be enforced externally.
*/
static void setSurfaceProps(
jsi::Runtime &runtime,
SurfaceId surfaceId,
std::string const &moduleName,
folly::dynamic const &initalProps,
DisplayMode displayMode);
/*
* Stops React Native Surface with given id.
* Thread synchronization must be enforced externally.
*/
static void stopSurface(jsi::Runtime &runtime, SurfaceId surfaceId);
};
} // namespace facebook::react
@@ -12,6 +12,7 @@
#include <react/renderer/core/ShadowNodeFragment.h>
#include <react/renderer/debug/SystraceSection.h>
#include <react/renderer/graphics/Geometry.h>
#include <react/renderer/uimanager/SurfaceRegistryBinding.h>
#include <react/renderer/uimanager/UIManagerBinding.h>
#include <react/renderer/uimanager/UIManagerCommitHook.h>
@@ -169,12 +170,7 @@ void UIManager::startSurface(
runtimeExecutor_([=](jsi::Runtime &runtime) {
SystraceSection s("UIManager::startSurface::onRuntime");
auto uiManagerBinding = UIManagerBinding::getBinding(runtime);
if (!uiManagerBinding) {
return;
}
uiManagerBinding->startSurface(
SurfaceRegistryBinding::startSurface(
runtime, surfaceId, moduleName, props, displayMode);
});
}
@@ -187,12 +183,7 @@ void UIManager::setSurfaceProps(
SystraceSection s("UIManager::setSurfaceProps");
runtimeExecutor_([=](jsi::Runtime &runtime) {
auto uiManagerBinding = UIManagerBinding::getBinding(runtime);
if (!uiManagerBinding) {
return;
}
uiManagerBinding->setSurfaceProps(
SurfaceRegistryBinding::setSurfaceProps(
runtime, surfaceId, moduleName, props, displayMode);
});
}
@@ -212,12 +203,7 @@ ShadowTree::Unique UIManager::stopSurface(SurfaceId surfaceId) const {
// the JavaScript side will not be able to reference a `ShadowTree` and will
// fail silently.
runtimeExecutor_([=](jsi::Runtime &runtime) {
auto uiManagerBinding = UIManagerBinding::getBinding(runtime);
if (!uiManagerBinding) {
return;
}
uiManagerBinding->stopSurface(runtime, surfaceId);
SurfaceRegistryBinding::stopSurface(runtime, surfaceId);
});
if (leakChecker_) {
@@ -15,49 +15,10 @@
#include <react/renderer/runtimescheduler/RuntimeSchedulerBinding.h>
#include <react/renderer/uimanager/primitives.h>
#include "bindingUtils.h"
namespace facebook::react {
static jsi::Value getModule(
jsi::Runtime &runtime,
std::string const &moduleName) {
auto batchedBridge =
runtime.global().getPropertyAsObject(runtime, "__fbBatchedBridge");
auto getCallableModule =
batchedBridge.getPropertyAsFunction(runtime, "getCallableModule");
auto moduleAsValue = getCallableModule.callWithThis(
runtime,
batchedBridge,
{jsi::String::createFromUtf8(runtime, moduleName)});
if (!moduleAsValue.isObject()) {
LOG(ERROR) << "getModule of " << moduleName << " is not an object";
}
react_native_assert(moduleAsValue.isObject());
return moduleAsValue;
}
static bool checkBatchedBridgeIsActive(jsi::Runtime &runtime) {
if (!runtime.global().hasProperty(runtime, "__fbBatchedBridge")) {
LOG(ERROR)
<< "getPropertyAsObject: property '__fbBatchedBridge' is undefined, expected an Object";
return false;
}
return true;
}
static bool checkGetCallableModuleIsActive(jsi::Runtime &runtime) {
if (!checkBatchedBridgeIsActive(runtime)) {
return false;
}
auto batchedBridge =
runtime.global().getPropertyAsObject(runtime, "__fbBatchedBridge");
if (!batchedBridge.hasProperty(runtime, "getCallableModule")) {
LOG(ERROR)
<< "getPropertyAsFunction: function 'getCallableModule' is undefined, expected a Function";
return false;
}
return true;
}
void UIManagerBinding::createAndInstallIfNeeded(
jsi::Runtime &runtime,
RuntimeExecutor const &runtimeExecutor,
@@ -101,29 +62,6 @@ UIManagerBinding::~UIManagerBinding() {
<< this << ").";
}
static jsi::Value callMethodOfModule(
jsi::Runtime &runtime,
std::string const &moduleName,
std::string const &methodName,
std::initializer_list<jsi::Value> args) {
if (checkGetCallableModuleIsActive(runtime)) {
auto module = getModule(runtime, moduleName);
if (module.isObject()) {
jsi::Object object = module.asObject(runtime);
react_native_assert(object.hasProperty(runtime, methodName.c_str()));
if (object.hasProperty(runtime, methodName.c_str())) {
auto method = object.getPropertyAsFunction(runtime, methodName.c_str());
return method.callWithThis(runtime, object, args);
} else {
LOG(ERROR) << "getPropertyAsFunction: property '" << methodName
<< "' is undefined, expected a Function";
}
}
}
return jsi::Value::undefined();
}
jsi::Value UIManagerBinding::getInspectorDataForInstance(
jsi::Runtime &runtime,
EventEmitter const &eventEmitter) const {
@@ -151,94 +89,6 @@ jsi::Value UIManagerBinding::getInspectorDataForInstance(
{std::move(instanceHandle)});
}
void UIManagerBinding::startSurface(
jsi::Runtime &runtime,
SurfaceId surfaceId,
std::string const &moduleName,
folly::dynamic const &initalProps,
DisplayMode displayMode) const {
SystraceSection s("UIManagerBinding::startSurface");
folly::dynamic parameters = folly::dynamic::object();
parameters["rootTag"] = surfaceId;
parameters["initialProps"] = initalProps;
parameters["fabric"] = true;
if (moduleName != "LogBox" &&
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),
jsi::Value(runtime, displayModeToInt(displayMode))});
} else {
callMethodOfModule(
runtime,
"AppRegistry",
"runApplication",
{jsi::String::createFromUtf8(runtime, moduleName),
jsi::valueFromDynamic(runtime, parameters),
jsi::Value(runtime, displayModeToInt(displayMode))});
}
}
void UIManagerBinding::setSurfaceProps(
jsi::Runtime &runtime,
SurfaceId surfaceId,
std::string const &moduleName,
folly::dynamic const &initalProps,
DisplayMode displayMode) const {
SystraceSection s("UIManagerBinding::setSurfaceProps");
folly::dynamic parameters = folly::dynamic::object();
parameters["rootTag"] = surfaceId;
parameters["initialProps"] = initalProps;
parameters["fabric"] = true;
if (moduleName != "LogBox" &&
runtime.global().hasProperty(runtime, "RN$SurfaceRegistry")) {
auto registry =
runtime.global().getPropertyAsObject(runtime, "RN$SurfaceRegistry");
auto method = registry.getPropertyAsFunction(runtime, "setSurfaceProps");
method.call(
runtime,
{jsi::String::createFromUtf8(runtime, moduleName),
jsi::valueFromDynamic(runtime, parameters),
jsi::Value(runtime, displayModeToInt(displayMode))});
} else {
callMethodOfModule(
runtime,
"AppRegistry",
"setSurfaceProps",
{jsi::String::createFromUtf8(runtime, moduleName),
jsi::valueFromDynamic(runtime, parameters),
jsi::Value(runtime, displayModeToInt(displayMode))});
}
}
void UIManagerBinding::stopSurface(jsi::Runtime &runtime, SurfaceId surfaceId)
const {
auto global = runtime.global();
if (global.hasProperty(runtime, "RN$Bridgeless")) {
if (!global.hasProperty(runtime, "RN$stopSurface")) {
// ReactFabric module has not been loaded yet; there's no surface to stop.
return;
}
// Bridgeless mode uses a custom JSI binding instead of callable module.
global.getPropertyAsFunction(runtime, "RN$stopSurface")
.call(runtime, {jsi::Value{surfaceId}});
} else {
callMethodOfModule(
runtime,
"ReactFabric",
"unmountComponentAtNode",
{jsi::Value{surfaceId}});
}
}
void UIManagerBinding::dispatchEvent(
jsi::Runtime &runtime,
EventTarget const *eventTarget,
@@ -43,39 +43,10 @@ class UIManagerBinding : public jsi::HostObject {
~UIManagerBinding();
/*
* Starts React Native Surface with given id, moduleName, and props.
* Thread synchronization must be enforced externally.
*/
void startSurface(
jsi::Runtime &runtime,
SurfaceId surfaceId,
std::string const &moduleName,
folly::dynamic const &initalProps,
DisplayMode displayMode) const;
/*
* Updates the React Native Surface identified with surfaceId and moduleName
* with the given props.
* Thread synchronization must be enforced externally.
*/
void setSurfaceProps(
jsi::Runtime &runtime,
SurfaceId surfaceId,
std::string const &moduleName,
folly::dynamic const &props,
DisplayMode displayMode) const;
jsi::Value getInspectorDataForInstance(
jsi::Runtime &runtime,
EventEmitter const &eventEmitter) 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.
@@ -0,0 +1,79 @@
/*
* 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 "bindingUtils.h"
#include <glog/logging.h>
#include <react/debug/react_native_assert.h>
namespace facebook::react {
static jsi::Value getModule(
jsi::Runtime &runtime,
std::string const &moduleName) {
auto batchedBridge =
runtime.global().getPropertyAsObject(runtime, "__fbBatchedBridge");
auto getCallableModule =
batchedBridge.getPropertyAsFunction(runtime, "getCallableModule");
auto moduleAsValue = getCallableModule.callWithThis(
runtime,
batchedBridge,
{jsi::String::createFromUtf8(runtime, moduleName)});
if (!moduleAsValue.isObject()) {
LOG(ERROR) << "getModule of " << moduleName << " is not an object";
}
react_native_assert(moduleAsValue.isObject());
return moduleAsValue;
}
static bool checkBatchedBridgeIsActive(jsi::Runtime &runtime) {
if (!runtime.global().hasProperty(runtime, "__fbBatchedBridge")) {
LOG(ERROR)
<< "getPropertyAsObject: property '__fbBatchedBridge' is undefined, expected an Object";
return false;
}
return true;
}
static bool checkGetCallableModuleIsActive(jsi::Runtime &runtime) {
if (!checkBatchedBridgeIsActive(runtime)) {
return false;
}
auto batchedBridge =
runtime.global().getPropertyAsObject(runtime, "__fbBatchedBridge");
if (!batchedBridge.hasProperty(runtime, "getCallableModule")) {
LOG(ERROR)
<< "getPropertyAsFunction: function 'getCallableModule' is undefined, expected a Function";
return false;
}
return true;
}
jsi::Value callMethodOfModule(
jsi::Runtime &runtime,
std::string const &moduleName,
std::string const &methodName,
std::initializer_list<jsi::Value> args) {
if (checkGetCallableModuleIsActive(runtime)) {
auto module = getModule(runtime, moduleName);
if (module.isObject()) {
jsi::Object object = module.asObject(runtime);
react_native_assert(object.hasProperty(runtime, methodName.c_str()));
if (object.hasProperty(runtime, methodName.c_str())) {
auto method = object.getPropertyAsFunction(runtime, methodName.c_str());
return method.callWithThis(runtime, object, args);
} else {
LOG(ERROR) << "getPropertyAsFunction: property '" << methodName
<< "' is undefined, expected a Function";
}
}
}
return jsi::Value::undefined();
}
} // namespace facebook::react
@@ -0,0 +1,20 @@
/*
* 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 <jsi/jsi.h>
namespace facebook::react {
jsi::Value callMethodOfModule(
jsi::Runtime &runtime,
std::string const &moduleName,
std::string const &methodName,
std::initializer_list<jsi::Value> args);
} // namespace facebook::react
+4 -4
View File
@@ -881,7 +881,7 @@ SPEC CHECKSUMS:
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
FBLazyVector: b81a2b70c72d8b0aefb652cea22c11e9ffd02949
FBReactNativeSpec: 02b0c2bc3cf30c9ab1d5af08c22b5573bc6af06c
FBReactNativeSpec: 140e95aa3cc1f6084938f6b8123bb0c4398325d1
Flipper: 30e8eeeed6abdc98edaf32af0cda2f198be4b733
Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c
Flipper-DoubleConversion: 57ffbe81ef95306cc9e69c4aa3aeeeeb58a6a28c
@@ -901,7 +901,7 @@ SPEC CHECKSUMS:
React: f64c9f6db5428717922a3292ba6a448615a2e143
React-callinvoker: c5d61e29df57793f0dc10ec2bc01c846f863e51f
React-Codegen: 2256e335ccce7326eeca6d7a668e05c4de259289
React-Core: 22bc86b79dd931dbfb7fd2af91a35a98d41ceb64
React-Core: 50d95abfb3c60d95e33a4b74e05e2a414bea4b73
React-CoreModules: a8e2bdc1ebbf8d440478456197abd58d1691f61a
React-cxxreact: cfc1663dae1ea52b465bbf021ef7b1527c5dc80c
React-Fabric: 002345cff43721617e0a3c0866f6f76bae8c50ff
@@ -923,10 +923,10 @@ SPEC CHECKSUMS:
React-RCTTest: 12bbd7fc2e72bd9920dc7286c5b8ef96639582b6
React-RCTText: e9146b2c0550a83d1335bfe2553760070a2d75c7
React-RCTVibration: 50be9c390f2da76045ef0dfdefa18b9cf9f35cfa
React-rncore: 5293698ae0222ddbaf47ce6193591b5fe3cb826c
React-rncore: 90798d1c013f1c62d0066c5618ddf8681c7a7c22
React-runtimeexecutor: 4b0c6eb341c7d3ceb5e2385cb0fdb9bf701024f3
ReactCommon: 7a2714d1128f965392b6f99a8b390e3aa38c9569
ScreenshotManager: 99830e1bd3d2b595ef092bb20fe9bb644deb9082
ScreenshotManager: ccf2b410b3c59385b26b8460a58cca8a8aca5e85
Yoga: c0d06f5380d34e939f55420669a60fe08b79bd75
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a