From d1293f6d44af538bfc3639e4a5e374181eade40f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Mon, 16 Dec 2024 06:03:03 -0800 Subject: [PATCH] Allow creating empty surfaces without using AppRegistry initialization paths (#48262) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/48262 Changelog: [internal] At the moment, we can't start surfaces in Fabric without calling `AppRegistry.runApplication`. This is completely unnecessary in cases like Fantom, where the creation of the surface is done manually from JS and we render to it immediately after (so we don't need to call into JS again to run AppRegistry). Reviewed By: javache Differential Revision: D67199971 fbshipit-source-id: e6402686b6f544a4a7651f6a21a57891ca6be3d1 --- .../renderer/scheduler/SurfaceHandler.cpp | 18 +++++++++++++----- .../react/renderer/scheduler/SurfaceHandler.h | 8 ++++++++ .../renderer/scheduler/SurfaceManager.cpp | 7 +++++++ .../react/renderer/scheduler/SurfaceManager.h | 5 +++++ .../react/renderer/uimanager/UIManager.cpp | 5 +++++ .../react/renderer/uimanager/UIManager.h | 2 ++ 6 files changed, 40 insertions(+), 5 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp b/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp index 7b3ca3f19c3..be385ea00c5 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp @@ -22,6 +22,10 @@ SurfaceHandler::SurfaceHandler( parameters_.surfaceId = surfaceId; } +SurfaceHandler::SurfaceHandler(SurfaceId surfaceId) noexcept { + parameters_.surfaceId = surfaceId; +} + SurfaceHandler::SurfaceHandler(SurfaceHandler&& other) noexcept { operator=(std::move(other)); } @@ -81,11 +85,15 @@ void SurfaceHandler::start() const noexcept { link_.shadowTree = shadowTree.get(); - link_.uiManager->startSurface( - std::move(shadowTree), - parameters.moduleName, - parameters.props, - parameters_.displayMode); + if (!parameters.moduleName.empty()) { + link_.uiManager->startSurface( + std::move(shadowTree), + parameters.moduleName, + parameters.props, + parameters_.displayMode); + } else { + link_.uiManager->startEmptySurface(std::move(shadowTree)); + } link_.status = Status::Running; diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceHandler.h b/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceHandler.h index 4963e237950..6985f15468b 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceHandler.h +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceHandler.h @@ -62,6 +62,14 @@ class SurfaceHandler { * Can be constructed anytime with a `moduleName` and a `surfaceId`. */ SurfaceHandler(const std::string& moduleName, SurfaceId surfaceId) noexcept; + + /* + * Can be constructed anytime with a `surfaceId`. + * As the module name is not passed, the surface will have to be rendered + * manually by the caller (AppRegistry will not be called). + */ + SurfaceHandler(SurfaceId surfaceId) noexcept; + virtual ~SurfaceHandler() noexcept; /* diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceManager.cpp b/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceManager.cpp index 3d8d484efe7..65e3548ccb2 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceManager.cpp @@ -37,6 +37,13 @@ void SurfaceManager::startSurface( }); } +void SurfaceManager::startEmptySurface( + SurfaceId surfaceId, + const LayoutConstraints& layoutConstraints, + const LayoutContext& layoutContext) const noexcept { + startSurface(surfaceId, "", {}, layoutConstraints, layoutContext); +} + void SurfaceManager::stopSurface(SurfaceId surfaceId) const noexcept { visit(surfaceId, [&](const SurfaceHandler& surfaceHandler) { surfaceHandler.stop(); diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceManager.h b/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceManager.h index 404185818ac..db6a7499243 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceManager.h +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/SurfaceManager.h @@ -37,6 +37,11 @@ class SurfaceManager final { const LayoutConstraints& layoutConstraints = {}, const LayoutContext& layoutContext = {}) const noexcept; + void startEmptySurface( + SurfaceId surfaceId, + const LayoutConstraints& layoutConstraints = {}, + const LayoutContext& layoutContext = {}) const noexcept; + void stopSurface(SurfaceId surfaceId) const noexcept; Size measureSurface( diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp index 9b9fe24cbe7..2241c3aa96a 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp @@ -242,6 +242,11 @@ void UIManager::startSurface( }); } +void UIManager::startEmptySurface(ShadowTree::Unique&& shadowTree) const { + SystraceSection s("UIManager::startEmptySurface"); + shadowTreeRegistry_.add(std::move(shadowTree)); +} + void UIManager::setSurfaceProps( SurfaceId surfaceId, const std::string& moduleName, diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h index a84845d9a03..cdd4f2d3ccd 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.h @@ -108,6 +108,8 @@ class UIManager final : public ShadowTreeDelegate { const folly::dynamic& props, DisplayMode displayMode) const; + void startEmptySurface(ShadowTree::Unique&& shadowTree) const; + void setSurfaceProps( SurfaceId surfaceId, const std::string& moduleName,