From b803d713e83b4f36906dfc0b4962eef737ff1790 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Wed, 25 Feb 2026 20:02:20 -0800 Subject: [PATCH] Refactor ParagraphComponentDescriptor to support subclassing (#55634) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/55634 Extract ParagraphComponentDescriptor logic into a template base class BaseParagraphComponentDescriptor so that other paragraph-like component descriptors can reuse the same TextLayoutManager wiring. Remove `final` from ParagraphShadowNode to allow subclassing. Move TextLayoutManagerKey from extern linkage in .cpp to constexpr in the new header. This is a pure refactor with no behavioral change. Changelog: [Internal] Reviewed By: cortinico Differential Revision: D93829402 --- .../text/BaseParagraphComponentDescriptor.h | 49 +++++++++++++++++++ .../text/ParagraphComponentDescriptor.cpp | 14 ------ .../text/ParagraphComponentDescriptor.h | 31 ++---------- .../components/text/ParagraphShadowNode.h | 2 +- 4 files changed, 53 insertions(+), 43 deletions(-) create mode 100644 packages/react-native/ReactCommon/react/renderer/components/text/BaseParagraphComponentDescriptor.h delete mode 100644 packages/react-native/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.cpp diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/BaseParagraphComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/components/text/BaseParagraphComponentDescriptor.h new file mode 100644 index 000000000000..8c7c8aab798f --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/components/text/BaseParagraphComponentDescriptor.h @@ -0,0 +1,49 @@ +/* + * 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 +#include +#include + +namespace facebook::react { + +constexpr const char *const TextLayoutManagerKey = "TextLayoutManager"; + +template +class BaseParagraphComponentDescriptor : public ConcreteComponentDescriptor { + public: + explicit BaseParagraphComponentDescriptor(const ComponentDescriptorParameters ¶meters) + : ConcreteComponentDescriptor(parameters), + textLayoutManager_(getManagerByName(this->contextContainer_, TextLayoutManagerKey)) + { + } + + ComponentName getComponentName() const override + { + return ShadowNodeT::Name(); + } + + protected: + void adopt(ShadowNode &shadowNode) const override + { + ConcreteComponentDescriptor::adopt(shadowNode); + + auto ¶graphShadowNode = static_cast(shadowNode); + + // `ParagraphShadowNode` uses `TextLayoutManager` to measure text content + // and communicate text rendering metrics to mounting layer. + paragraphShadowNode.setTextLayoutManager(textLayoutManager_); + } + + private: + // Every `ParagraphShadowNode` has a reference to a shared `TextLayoutManager` + const std::shared_ptr textLayoutManager_; +}; + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.cpp b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.cpp deleted file mode 100644 index ee4e014b6564..000000000000 --- a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.cpp +++ /dev/null @@ -1,14 +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 "ParagraphComponentDescriptor.h" - -namespace facebook::react { - -extern const char TextLayoutManagerKey[] = "TextLayoutManager"; - -} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.h index 3ed1a2a7aefc..3f64c6e8cb7a 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.h @@ -7,41 +7,16 @@ #pragma once +#include #include -#include -#include -#include namespace facebook::react { - -extern const char TextLayoutManagerKey[]; - /* * Descriptor for component. */ -class ParagraphComponentDescriptor final : public ConcreteComponentDescriptor { +class ParagraphComponentDescriptor final : public BaseParagraphComponentDescriptor { public: - explicit ParagraphComponentDescriptor(const ComponentDescriptorParameters ¶meters) - : ConcreteComponentDescriptor(parameters), - textLayoutManager_(getManagerByName(contextContainer_, TextLayoutManagerKey)) - { - } - - protected: - void adopt(ShadowNode &shadowNode) const override - { - ConcreteComponentDescriptor::adopt(shadowNode); - - auto ¶graphShadowNode = static_cast(shadowNode); - - // `ParagraphShadowNode` uses `TextLayoutManager` to measure text content - // and communicate text rendering metrics to mounting layer. - paragraphShadowNode.setTextLayoutManager(textLayoutManager_); - } - - private: - // Every `ParagraphShadowNode` has a reference to a shared `TextLayoutManager` - const std::shared_ptr textLayoutManager_; + using BaseParagraphComponentDescriptor::BaseParagraphComponentDescriptor; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphShadowNode.h b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphShadowNode.h index e8510a7705df..704088cbaae6 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphShadowNode.h @@ -26,7 +26,7 @@ extern const char ParagraphComponentName[]; * containing and displaying text. Text content is represented as nested * and components. */ -class ParagraphShadowNode final +class ParagraphShadowNode : public ConcreteViewShadowNode, public BaseTextShadowNode { public: