From 2bf2c9707824e00e198e61997e62ef038b0b296b Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 30 Jun 2026 02:57:43 -0700 Subject: [PATCH 1/3] Remove unused ViewShadowNodeProps subclass Summary: ViewShadowNodeProps was a thin subclass of ViewProps that only forwarded its constructor. After the feature flag propagation logic was removed, the subclass serves no purpose. This change: - Removes the ViewShadowNodeProps class and replaces it with a type alias to ViewProps - Updates ViewShadowNode to use ViewProps directly in its ConcreteViewShadowNode base - Updates YogaLayoutableShadowNode::swapLeftAndRightInViewProps to cast to ViewProps - Updates all test files that instantiated ViewShadowNodeProps to use ViewProps instead - Fixes AvatarFranzPreviewViewComponentView to initialize _props with defaultSharedProps() to avoid null oldProps in updateProps This simplifies the View component type hierarchy and removes dead code. Changelog: [Internal] Differential Revision: D110095190 --- .../components/view/ViewShadowNode.cpp | 6 --- .../renderer/components/view/ViewShadowNode.h | 14 +------ .../view/YogaLayoutableShadowNode.cpp | 3 +- .../components/view/tests/LayoutTest.cpp | 10 ++--- .../components/view/tests/ViewTest.cpp | 19 +++++----- .../core/tests/FindNodeAtPointTest.cpp | 14 +++---- .../core/tests/LayoutableShadowNodeTest.cpp | 38 +++++++++---------- .../renderer/element/tests/ElementTest.cpp | 6 +-- .../tests/DifferentiatorUnflattenTest.cpp | 2 +- .../mounting/tests/OrderIndexTest.cpp | 2 +- .../tests/ShadowTreeLifeCycleTest.cpp | 2 +- .../mounting/tests/StackingContextTest.cpp | 2 +- .../tests/FindShadowNodeByTagTest.cpp | 2 +- .../tests/PointerEventsProcessorTest.cpp | 8 ++-- .../api-snapshots/ReactAndroidDebugCxx.api | 8 +--- .../api-snapshots/ReactAndroidNewarchCxx.api | 8 +--- .../api-snapshots/ReactAndroidReleaseCxx.api | 8 +--- .../api-snapshots/ReactAppleDebugCxx.api | 8 +--- .../api-snapshots/ReactAppleNewarchCxx.api | 8 +--- .../api-snapshots/ReactAppleReleaseCxx.api | 8 +--- .../api-snapshots/ReactCommonDebugCxx.api | 8 +--- .../api-snapshots/ReactCommonNewarchCxx.api | 8 +--- .../api-snapshots/ReactCommonReleaseCxx.api | 8 +--- 23 files changed, 73 insertions(+), 127 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp index af30883b21fc..a166a90546c6 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp @@ -14,12 +14,6 @@ namespace facebook::react { // NOLINTNEXTLINE(facebook-hte-CArray,modernize-avoid-c-arrays) const char ViewComponentName[] = "View"; -ViewShadowNodeProps::ViewShadowNodeProps( - const PropsParserContext& context, - const ViewShadowNodeProps& sourceProps, - const RawProps& rawProps) - : ViewProps(context, sourceProps, rawProps) {}; - ViewShadowNode::ViewShadowNode( const ShadowNodeFragment& fragment, const ShadowNodeFamily::Shared& family, diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.h b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.h index b3195934440a..bc1a94e52ede 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.h @@ -15,22 +15,12 @@ namespace facebook::react { // NOLINTNEXTLINE(modernize-avoid-c-arrays) extern const char ViewComponentName[]; -/** - * Implementation of the ViewProps that propagates feature flag. - */ -class ViewShadowNodeProps final : public ViewProps { - public: - ViewShadowNodeProps() = default; - ViewShadowNodeProps( - const PropsParserContext &context, - const ViewShadowNodeProps &sourceProps, - const RawProps &rawProps); -}; +using ViewShadowNodeProps = ViewProps; /* * `ShadowNode` for component. */ -class ViewShadowNode final : public ConcreteViewShadowNode { +class ViewShadowNode final : public ConcreteViewShadowNode { public: ViewShadowNode(const ShadowNodeFragment &fragment, const ShadowNodeFamily::Shared &family, ShadowNodeTraits traits); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp index f7adbe14ef60..ebe98db8eb4d 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp @@ -1017,8 +1017,7 @@ void YogaLayoutableShadowNode::swapLeftAndRightInYogaStyleProps() { void YogaLayoutableShadowNode::swapLeftAndRightInViewProps() { if (auto viewShadowNode = dynamic_cast(this)) { // TODO: Do not mutate props directly. - auto& props = - const_cast(viewShadowNode->getConcreteProps()); + auto& props = const_cast(viewShadowNode->getConcreteProps()); // Swap border node values, borderRadii, borderColors and borderStyles. if (props.borderRadii.topLeft.has_value()) { diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp index a5a24224d084..c8c2c58ef07f 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/tests/LayoutTest.cpp @@ -86,7 +86,7 @@ class LayoutTest : public ::testing::Test { .reference(viewShadowNodeA_) .tag(2) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.setPositionType(yoga::PositionType::Absolute); @@ -99,7 +99,7 @@ class LayoutTest : public ::testing::Test { .reference(viewShadowNodeAB_) .tag(3) .props([=] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.setPositionType(yoga::PositionType::Absolute); @@ -127,7 +127,7 @@ class LayoutTest : public ::testing::Test { .reference(viewShadowNodeABC_) .tag(4) .props([=] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; @@ -147,7 +147,7 @@ class LayoutTest : public ::testing::Test { .reference(viewShadowNodeABCD_) .tag(5) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.setPositionType(yoga::PositionType::Absolute); @@ -162,7 +162,7 @@ class LayoutTest : public ::testing::Test { .reference(viewShadowNodeABE_) .tag(6) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.setPositionType(yoga::PositionType::Absolute); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp index e9aa7b30eff2..1fa9d32e15c1 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/tests/ViewTest.cpp @@ -51,7 +51,7 @@ class YogaDirtyFlagTest : public ::testing::Test { /* * Some non-default props. */ - auto mutableViewProps = std::make_shared(); + auto mutableViewProps = std::make_shared(); auto &props = *mutableViewProps; props.nativeId = "native Id"; props.opacity = 0.5; @@ -113,7 +113,7 @@ TEST_F(YogaDirtyFlagTest, changingNonLayoutSubPropsMustNotDirtyYogaNode) { */ auto newRootShadowNode = rootShadowNode_->cloneTree( innerShadowNode_->getFamily(), [](const ShadowNode& oldShadowNode) { - auto viewProps = std::make_shared(); + auto viewProps = std::make_shared(); auto& props = *viewProps; props.nativeId = "some new native Id"; @@ -136,7 +136,7 @@ TEST_F(YogaDirtyFlagTest, changingLayoutSubPropsMustDirtyYogaNode) { */ auto newRootShadowNode = rootShadowNode_->cloneTree( innerShadowNode_->getFamily(), [](const ShadowNode& oldShadowNode) { - auto viewProps = std::make_shared(); + auto viewProps = std::make_shared(); auto& props = *viewProps; props.yogaStyle.setAlignContent(yoga::Align::Baseline); @@ -243,7 +243,7 @@ TEST_F(YogaDirtyFlagTest, clonedPropsPreserveAspectRatio) { auto newRootShadowNode = rootShadowNode_->cloneTree( innerShadowNode_->getFamily(), [&](const ShadowNode& oldShadowNode) { // First clone: set aspectRatio to 1.5 - auto viewProps = std::make_shared(); + auto viewProps = std::make_shared(); viewProps->yogaStyle.setAspectRatio(yoga::FloatOptional(1.5f)); auto nodeWithAspectRatio = oldShadowNode.clone(ShadowNodeFragment{.props = viewProps}); @@ -255,8 +255,7 @@ TEST_F(YogaDirtyFlagTest, clonedPropsPreserveAspectRatio) { auto clonedProps = componentDescriptor.cloneProps( parserContext, nodeWithAspectRatio->getProps(), RawProps()); - auto& clonedViewProps = - static_cast(*clonedProps); + auto& clonedViewProps = static_cast(*clonedProps); EXPECT_TRUE(clonedViewProps.yogaStyle.aspectRatio().isDefined()); EXPECT_EQ(clonedViewProps.yogaStyle.aspectRatio().unwrap(), 1.5f); @@ -303,7 +302,7 @@ class YogaCloneTest : public ::testing::Test { .reference(parentShadowNode_) .tag(2) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.setFlexDirection(yoga::FlexDirection::Row); @@ -320,7 +319,7 @@ class YogaCloneTest : public ::testing::Test { .reference(childAShadowNode_) .tag(3) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->yogaStyle.setDimension( yoga::Dimension::Width, yoga::StyleSizeLength::points(100)); @@ -333,7 +332,7 @@ class YogaCloneTest : public ::testing::Test { .reference(childBShadowNode_) .tag(4) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->yogaStyle.setDimension( yoga::Dimension::Width, yoga::StyleSizeLength::points(100)); @@ -346,7 +345,7 @@ class YogaCloneTest : public ::testing::Test { .reference(childCShadowNode_) .tag(5) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->yogaStyle.setDimension( yoga::Dimension::Width, yoga::StyleSizeLength::points(100)); diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/FindNodeAtPointTest.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/FindNodeAtPointTest.cpp index ea14d216265e..c3438eda1bd4 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/FindNodeAtPointTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/FindNodeAtPointTest.cpp @@ -126,7 +126,7 @@ TEST(FindNodeAtPointTest, viewIsScaled) { Element() .tag(3) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->transform = Transform::Scale(0.5, 0.5, 0); return sharedProps; }) @@ -199,7 +199,7 @@ TEST(FindNodeAtPointTest, overlappingViewsWithZIndex) { Element() .tag(2) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->zIndex = 1; auto &yogaStyle = sharedProps->yogaStyle; yogaStyle.setPositionType(yoga::PositionType::Absolute); @@ -235,7 +235,7 @@ TEST(FindNodeAtPointTest, overlappingViewsWithParentPointerEventsBoxOnly) { Element() .tag(1) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->pointerEvents = PointerEventsMode::BoxOnly; return sharedProps; }) @@ -277,7 +277,7 @@ TEST(FindNodeAtPointTest, overlappingViewsWithParentPointerEventsBoxNone) { Element() .tag(1) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->pointerEvents = PointerEventsMode::BoxNone; return sharedProps; }) @@ -290,7 +290,7 @@ TEST(FindNodeAtPointTest, overlappingViewsWithParentPointerEventsBoxNone) { Element() .tag(2) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->zIndex = 1; auto &yogaStyle = sharedProps->yogaStyle; yogaStyle.setPositionType(yoga::PositionType::Absolute); @@ -326,7 +326,7 @@ TEST(FindNodeAtPointTest, overlappingViewsWithParentPointerEventsNone) { Element() .tag(1) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->pointerEvents = PointerEventsMode::None; return sharedProps; }) @@ -339,7 +339,7 @@ TEST(FindNodeAtPointTest, overlappingViewsWithParentPointerEventsNone) { Element() .tag(2) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->zIndex = 1; auto &yogaStyle = sharedProps->yogaStyle; yogaStyle.setPositionType(yoga::PositionType::Absolute); diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/LayoutableShadowNodeTest.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/LayoutableShadowNodeTest.cpp index 575221be7a33..c974595b4fd2 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/LayoutableShadowNodeTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/LayoutableShadowNodeTest.cpp @@ -291,7 +291,7 @@ TEST(LayoutableShadowNodeTest, relativeLayoutMetricsOnTransformedNode) { shadowNode.setLayoutMetrics(layoutMetrics); }) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->transform = Transform::Scale(0.5, 0.5, 1); return sharedProps; }) @@ -340,7 +340,7 @@ TEST(LayoutableShadowNodeTest, noOverflow) { }).children({ Element() .props([=] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(100)); @@ -351,7 +351,7 @@ TEST(LayoutableShadowNodeTest, noOverflow) { .children({ Element() .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.setPositionType(yoga::PositionType::Absolute); @@ -405,7 +405,7 @@ TEST(LayoutableShadowNodeTest, overflowInsetFrameToRightAndDown) { }).children({ Element() .props([=] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(100)); @@ -416,7 +416,7 @@ TEST(LayoutableShadowNodeTest, overflowInsetFrameToRightAndDown) { .children({ Element() .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.setPositionType(yoga::PositionType::Absolute); @@ -471,7 +471,7 @@ TEST(LayoutableShadowNodeTest, overflowInsetFrameToLeftAndTop) { }).children({ Element() .props([=] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(100)); @@ -482,7 +482,7 @@ TEST(LayoutableShadowNodeTest, overflowInsetFrameToLeftAndTop) { .children({ Element() .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.setPositionType(yoga::PositionType::Absolute); @@ -541,7 +541,7 @@ TEST(LayoutableShadowNodeTest, overflowInsetFrameToAllSides) { }).children({ Element() .props([=] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(100)); @@ -552,7 +552,7 @@ TEST(LayoutableShadowNodeTest, overflowInsetFrameToAllSides) { .children({ Element() .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.setPositionType(yoga::PositionType::Absolute); @@ -564,7 +564,7 @@ TEST(LayoutableShadowNodeTest, overflowInsetFrameToAllSides) { }), Element() .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; auto &yogaStyle = props.yogaStyle; yogaStyle.setPositionType(yoga::PositionType::Absolute); @@ -620,7 +620,7 @@ TEST(LayoutableShadowNodeTest, relativeLayoutMetricsOnTransformedParent) { .children({ Element() .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->transform = Transform::Scale(0.5, 0.5, 1); return sharedProps; }) @@ -755,7 +755,7 @@ TEST( .children({ Element() .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->transform = Transform::Scale(0.5, 0.5, 1); return sharedProps; }) @@ -840,7 +840,7 @@ TEST(LayoutableShadowNodeTest, relativeLayoutMetricsOnSameTransformedNode) { auto element = Element() .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->transform = Transform::Scale(2, 2, 1); return sharedProps; }) @@ -1017,7 +1017,7 @@ TEST(LayoutableShadowNodeTest, invertedVerticalView) { auto element = Element() .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->transform = Transform::VerticalInversion(); // Inverted return sharedProps; }) @@ -1093,7 +1093,7 @@ TEST(LayoutableShadowNodeTest, nestedInvertedVerticalView) { auto element = Element() .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->transform = Transform::VerticalInversion(); // Inverted return sharedProps; }) @@ -1179,7 +1179,7 @@ TEST(LayoutableShadowNodeTest, nestedDoubleInvertedVerticalView) { auto element = Element() .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->transform = Transform::VerticalInversion(); // Inverted return sharedProps; }) @@ -1195,7 +1195,7 @@ TEST(LayoutableShadowNodeTest, nestedDoubleInvertedVerticalView) { layoutMetrics.frame.size = {.width=100, .height=200}; shadowNode.setLayoutMetrics(layoutMetrics); }).props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->transform = Transform::VerticalInversion(); // Inverted return sharedProps; }).children({ @@ -1259,7 +1259,7 @@ TEST(LayoutableShadowNodeTest, invertedHorizontalView) { auto element = Element() .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->transform = Transform::HorizontalInversion(); // Inverted return sharedProps; }) @@ -1331,7 +1331,7 @@ TEST(LayoutableShadowNodeTest, nestedInvertedHorizontalView) { auto element = Element() .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); sharedProps->transform = Transform::HorizontalInversion(); // Inverted return sharedProps; }) diff --git a/packages/react-native/ReactCommon/react/renderer/element/tests/ElementTest.cpp b/packages/react-native/ReactCommon/react/renderer/element/tests/ElementTest.cpp index 3f577136a53e..5dfde50211e4 100644 --- a/packages/react-native/ReactCommon/react/renderer/element/tests/ElementTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/element/tests/ElementTest.cpp @@ -26,7 +26,7 @@ TEST(ElementTest, testNormalCases) { auto shadowNodeAB = std::shared_ptr{}; auto shadowNodeABA = std::shared_ptr{}; - auto propsAA = std::make_shared(); + auto propsAA = std::make_shared(); propsAA->nativeId = "node AA"; // clang-format off @@ -51,7 +51,7 @@ TEST(ElementTest, testNormalCases) { .reference(shadowNodeAB) .tag(3) .props([]() { - auto props = std::make_shared(); + auto props = std::make_shared(); props->nativeId = "node AB"; return props; }) @@ -60,7 +60,7 @@ TEST(ElementTest, testNormalCases) { .reference(shadowNodeABA) .tag(4) .props([]() { - auto props = std::make_shared(); + auto props = std::make_shared(); props->nativeId = "node ABA"; return props; }) diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/tests/DifferentiatorUnflattenTest.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/tests/DifferentiatorUnflattenTest.cpp index 6e886866e16e..e0e65f3e98ad 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/tests/DifferentiatorUnflattenTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/tests/DifferentiatorUnflattenTest.cpp @@ -112,7 +112,7 @@ class DifferentiatorUnflattenTest : public ::testing::Test { rootShadowNode_ = std::static_pointer_cast(rootShadowNode_->cloneTree( node->getFamily(), [&](const ShadowNode& oldShadowNode) { - auto viewProps = std::make_shared(); + auto viewProps = std::make_shared(); callback(*viewProps); return oldShadowNode.clone( ShadowNodeFragment{.props = viewProps}); diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/tests/OrderIndexTest.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/tests/OrderIndexTest.cpp index 3196a12487e0..fd37963f476b 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/tests/OrderIndexTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/tests/OrderIndexTest.cpp @@ -82,7 +82,7 @@ class OrderIndexTest : public ::testing::Test { rootShadowNode_ = std::static_pointer_cast(rootShadowNode_->cloneTree( node->getFamily(), [&](const ShadowNode& oldShadowNode) { - auto viewProps = std::make_shared(); + auto viewProps = std::make_shared(); callback(*viewProps); return oldShadowNode.clone( ShadowNodeFragment{.props = viewProps}); diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/tests/ShadowTreeLifeCycleTest.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/tests/ShadowTreeLifeCycleTest.cpp index 772814b0dfa2..0b9f648f30cf 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/tests/ShadowTreeLifeCycleTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/tests/ShadowTreeLifeCycleTest.cpp @@ -445,7 +445,7 @@ TEST_F(ShadowTreeLifecycleTest, moveFirstChildToLast) { auto builder = simpleComponentBuilder(); auto makeProps = [](const std::string& id) { - auto props = std::make_shared(); + auto props = std::make_shared(); props->nativeId = id; return props; }; diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp index 9d1651057864..42421a23729b 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/tests/StackingContextTest.cpp @@ -162,7 +162,7 @@ class StackingContextTest : public ::testing::Test { rootShadowNode_ = std::static_pointer_cast(rootShadowNode_->cloneTree( node->getFamily(), [&](const ShadowNode& oldShadowNode) { - auto viewProps = std::make_shared(); + auto viewProps = std::make_shared(); callback(*viewProps); return oldShadowNode.clone( ShadowNodeFragment{.props = viewProps}); diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/tests/FindShadowNodeByTagTest.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/tests/FindShadowNodeByTagTest.cpp index 46f4cfb57645..f2ac197f0c01 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/tests/FindShadowNodeByTagTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/tests/FindShadowNodeByTagTest.cpp @@ -85,7 +85,7 @@ class FindShadowNodeByTagTest : public ::testing::Test { .tag(viewTag_) .surfaceId(surfaceId_) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto& yogaStyle = sharedProps->yogaStyle; yogaStyle.setDimension( yoga::Dimension::Width, diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/tests/PointerEventsProcessorTest.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/tests/PointerEventsProcessorTest.cpp index 79f90dc15b93..f868cf4d0f20 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/tests/PointerEventsProcessorTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/tests/PointerEventsProcessorTest.cpp @@ -101,7 +101,7 @@ class PointerEventsProcessorTest : public ::testing::Test { .surfaceId(surfaceId_) .reference(nodeA_) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; listenToAllPointerEvents(props); auto &yogaStyle = props.yogaStyle; @@ -119,7 +119,7 @@ class PointerEventsProcessorTest : public ::testing::Test { .surfaceId(surfaceId_) .reference(nodeAA_) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; listenToAllPointerEvents(props); auto &yogaStyle = props.yogaStyle; @@ -133,7 +133,7 @@ class PointerEventsProcessorTest : public ::testing::Test { .surfaceId(surfaceId_) .reference(nodeB_) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; listenToAllPointerEvents(props); auto &yogaStyle = props.yogaStyle; @@ -151,7 +151,7 @@ class PointerEventsProcessorTest : public ::testing::Test { .surfaceId(surfaceId_) .reference(nodeBB_) .props([] { - auto sharedProps = std::make_shared(); + auto sharedProps = std::make_shared(); auto &props = *sharedProps; listenToAllPointerEvents(props); auto &yogaStyle = props.yogaStyle; diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api index 5a33e7d7d9da..a360d98fce0c 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api @@ -732,6 +732,7 @@ using facebook::react::ValueFactory = std::function; using facebook::react::ViewProps = facebook::react::HostPlatformViewProps; +using facebook::react::ViewShadowNodeProps = facebook::react::ViewProps; using facebook::react::VirtualViewComponentDescriptor = facebook::react::ConcreteComponentDescriptor; using facebook::react::parsePlatformColorFn = facebook::react::SharedColor(*)(const facebook::react::ContextContainer&, int32_t, const facebook::react::RawValue&); template @@ -5413,16 +5414,11 @@ class facebook::react::ViewComponentDescriptor : public facebook::react::Concret public ViewComponentDescriptor(const facebook::react::ComponentDescriptorParameters& parameters); } -class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { +class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { public ViewShadowNode(const facebook::react::ShadowNode& sourceShadowNode, const facebook::react::ShadowNodeFragment& fragment); public ViewShadowNode(const facebook::react::ShadowNodeFragment& fragment, const facebook::react::ShadowNodeFamily::Shared& family, facebook::react::ShadowNodeTraits traits); } -class facebook::react::ViewShadowNodeProps : public facebook::react::HostPlatformViewProps { - public ViewShadowNodeProps() = default; - public ViewShadowNodeProps(const facebook::react::PropsParserContext& context, const facebook::react::ViewShadowNodeProps& sourceProps, const facebook::react::RawProps& rawProps); -} - class facebook::react::ViewTransitionModule : public facebook::react::UIManagerViewTransitionDelegate, public facebook::react::UIManagerCommitHook, public facebook::react::MountingOverrideDelegate { public virtual bool shouldOverridePullTransaction() const override; public virtual facebook::react::RootShadowNode::Unshared shadowTreeWillCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& oldRootShadowNode, const facebook::react::RootShadowNode::Unshared& newRootShadowNode, const facebook::react::ShadowTreeCommitOptions& commitOptions) noexcept override; diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api index a10464aed19c..e521b074ce85 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api @@ -731,6 +731,7 @@ using facebook::react::ValueFactory = std::function; using facebook::react::ViewProps = facebook::react::HostPlatformViewProps; +using facebook::react::ViewShadowNodeProps = facebook::react::ViewProps; using facebook::react::VirtualViewComponentDescriptor = facebook::react::ConcreteComponentDescriptor; using facebook::react::parsePlatformColorFn = facebook::react::SharedColor(*)(const facebook::react::ContextContainer&, int32_t, const facebook::react::RawValue&); template @@ -5227,16 +5228,11 @@ class facebook::react::ViewComponentDescriptor : public facebook::react::Concret public ViewComponentDescriptor(const facebook::react::ComponentDescriptorParameters& parameters); } -class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { +class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { public ViewShadowNode(const facebook::react::ShadowNode& sourceShadowNode, const facebook::react::ShadowNodeFragment& fragment); public ViewShadowNode(const facebook::react::ShadowNodeFragment& fragment, const facebook::react::ShadowNodeFamily::Shared& family, facebook::react::ShadowNodeTraits traits); } -class facebook::react::ViewShadowNodeProps : public facebook::react::HostPlatformViewProps { - public ViewShadowNodeProps() = default; - public ViewShadowNodeProps(const facebook::react::PropsParserContext& context, const facebook::react::ViewShadowNodeProps& sourceProps, const facebook::react::RawProps& rawProps); -} - class facebook::react::ViewTransitionModule : public facebook::react::UIManagerViewTransitionDelegate, public facebook::react::UIManagerCommitHook, public facebook::react::MountingOverrideDelegate { public virtual bool shouldOverridePullTransaction() const override; public virtual facebook::react::RootShadowNode::Unshared shadowTreeWillCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& oldRootShadowNode, const facebook::react::RootShadowNode::Unshared& newRootShadowNode, const facebook::react::ShadowTreeCommitOptions& commitOptions) noexcept override; diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api index b357d56bfc81..fc6a7f8949e4 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api @@ -732,6 +732,7 @@ using facebook::react::ValueFactory = std::function; using facebook::react::ViewProps = facebook::react::HostPlatformViewProps; +using facebook::react::ViewShadowNodeProps = facebook::react::ViewProps; using facebook::react::VirtualViewComponentDescriptor = facebook::react::ConcreteComponentDescriptor; using facebook::react::parsePlatformColorFn = facebook::react::SharedColor(*)(const facebook::react::ContextContainer&, int32_t, const facebook::react::RawValue&); template @@ -5404,16 +5405,11 @@ class facebook::react::ViewComponentDescriptor : public facebook::react::Concret public ViewComponentDescriptor(const facebook::react::ComponentDescriptorParameters& parameters); } -class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { +class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { public ViewShadowNode(const facebook::react::ShadowNode& sourceShadowNode, const facebook::react::ShadowNodeFragment& fragment); public ViewShadowNode(const facebook::react::ShadowNodeFragment& fragment, const facebook::react::ShadowNodeFamily::Shared& family, facebook::react::ShadowNodeTraits traits); } -class facebook::react::ViewShadowNodeProps : public facebook::react::HostPlatformViewProps { - public ViewShadowNodeProps() = default; - public ViewShadowNodeProps(const facebook::react::PropsParserContext& context, const facebook::react::ViewShadowNodeProps& sourceProps, const facebook::react::RawProps& rawProps); -} - class facebook::react::ViewTransitionModule : public facebook::react::UIManagerViewTransitionDelegate, public facebook::react::UIManagerCommitHook, public facebook::react::MountingOverrideDelegate { public virtual bool shouldOverridePullTransaction() const override; public virtual facebook::react::RootShadowNode::Unshared shadowTreeWillCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& oldRootShadowNode, const facebook::react::RootShadowNode::Unshared& newRootShadowNode, const facebook::react::ShadowTreeCommitOptions& commitOptions) noexcept override; diff --git a/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api index 4dd76e3aa931..5db822c2e8bc 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api @@ -3596,6 +3596,7 @@ using facebook::react::ValueFactory = std::function; using facebook::react::ViewProps = facebook::react::HostPlatformViewProps; +using facebook::react::ViewShadowNodeProps = facebook::react::ViewProps; using facebook::react::VirtualViewComponentDescriptor = facebook::react::ConcreteComponentDescriptor; using facebook::react::parsePlatformColorFn = facebook::react::SharedColor(*)(const facebook::react::ContextContainer&, int32_t, const facebook::react::RawValue&); template @@ -7589,16 +7590,11 @@ class facebook::react::ViewComponentDescriptor : public facebook::react::Concret public ViewComponentDescriptor(const facebook::react::ComponentDescriptorParameters& parameters); } -class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { +class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { public ViewShadowNode(const facebook::react::ShadowNode& sourceShadowNode, const facebook::react::ShadowNodeFragment& fragment); public ViewShadowNode(const facebook::react::ShadowNodeFragment& fragment, const facebook::react::ShadowNodeFamily::Shared& family, facebook::react::ShadowNodeTraits traits); } -class facebook::react::ViewShadowNodeProps : public facebook::react::HostPlatformViewProps { - public ViewShadowNodeProps() = default; - public ViewShadowNodeProps(const facebook::react::PropsParserContext& context, const facebook::react::ViewShadowNodeProps& sourceProps, const facebook::react::RawProps& rawProps); -} - class facebook::react::ViewTransitionModule : public facebook::react::UIManagerViewTransitionDelegate, public facebook::react::UIManagerCommitHook, public facebook::react::MountingOverrideDelegate { public virtual bool shouldOverridePullTransaction() const override; public virtual facebook::react::RootShadowNode::Unshared shadowTreeWillCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& oldRootShadowNode, const facebook::react::RootShadowNode::Unshared& newRootShadowNode, const facebook::react::ShadowTreeCommitOptions& commitOptions) noexcept override; diff --git a/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api index 16e2dc5a0c80..f17f0b02df5c 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api @@ -3583,6 +3583,7 @@ using facebook::react::ValueFactory = std::function; using facebook::react::ViewProps = facebook::react::HostPlatformViewProps; +using facebook::react::ViewShadowNodeProps = facebook::react::ViewProps; using facebook::react::VirtualViewComponentDescriptor = facebook::react::ConcreteComponentDescriptor; using facebook::react::parsePlatformColorFn = facebook::react::SharedColor(*)(const facebook::react::ContextContainer&, int32_t, const facebook::react::RawValue&); template @@ -7431,16 +7432,11 @@ class facebook::react::ViewComponentDescriptor : public facebook::react::Concret public ViewComponentDescriptor(const facebook::react::ComponentDescriptorParameters& parameters); } -class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { +class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { public ViewShadowNode(const facebook::react::ShadowNode& sourceShadowNode, const facebook::react::ShadowNodeFragment& fragment); public ViewShadowNode(const facebook::react::ShadowNodeFragment& fragment, const facebook::react::ShadowNodeFamily::Shared& family, facebook::react::ShadowNodeTraits traits); } -class facebook::react::ViewShadowNodeProps : public facebook::react::HostPlatformViewProps { - public ViewShadowNodeProps() = default; - public ViewShadowNodeProps(const facebook::react::PropsParserContext& context, const facebook::react::ViewShadowNodeProps& sourceProps, const facebook::react::RawProps& rawProps); -} - class facebook::react::ViewTransitionModule : public facebook::react::UIManagerViewTransitionDelegate, public facebook::react::UIManagerCommitHook, public facebook::react::MountingOverrideDelegate { public virtual bool shouldOverridePullTransaction() const override; public virtual facebook::react::RootShadowNode::Unshared shadowTreeWillCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& oldRootShadowNode, const facebook::react::RootShadowNode::Unshared& newRootShadowNode, const facebook::react::ShadowTreeCommitOptions& commitOptions) noexcept override; diff --git a/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api index 48d9cc57fdb4..6efb67807861 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api @@ -3596,6 +3596,7 @@ using facebook::react::ValueFactory = std::function; using facebook::react::ViewProps = facebook::react::HostPlatformViewProps; +using facebook::react::ViewShadowNodeProps = facebook::react::ViewProps; using facebook::react::VirtualViewComponentDescriptor = facebook::react::ConcreteComponentDescriptor; using facebook::react::parsePlatformColorFn = facebook::react::SharedColor(*)(const facebook::react::ContextContainer&, int32_t, const facebook::react::RawValue&); template @@ -7580,16 +7581,11 @@ class facebook::react::ViewComponentDescriptor : public facebook::react::Concret public ViewComponentDescriptor(const facebook::react::ComponentDescriptorParameters& parameters); } -class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { +class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { public ViewShadowNode(const facebook::react::ShadowNode& sourceShadowNode, const facebook::react::ShadowNodeFragment& fragment); public ViewShadowNode(const facebook::react::ShadowNodeFragment& fragment, const facebook::react::ShadowNodeFamily::Shared& family, facebook::react::ShadowNodeTraits traits); } -class facebook::react::ViewShadowNodeProps : public facebook::react::HostPlatformViewProps { - public ViewShadowNodeProps() = default; - public ViewShadowNodeProps(const facebook::react::PropsParserContext& context, const facebook::react::ViewShadowNodeProps& sourceProps, const facebook::react::RawProps& rawProps); -} - class facebook::react::ViewTransitionModule : public facebook::react::UIManagerViewTransitionDelegate, public facebook::react::UIManagerCommitHook, public facebook::react::MountingOverrideDelegate { public virtual bool shouldOverridePullTransaction() const override; public virtual facebook::react::RootShadowNode::Unshared shadowTreeWillCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& oldRootShadowNode, const facebook::react::RootShadowNode::Unshared& newRootShadowNode, const facebook::react::ShadowTreeCommitOptions& commitOptions) noexcept override; diff --git a/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api index e40ffd1a5777..7edcb2738efb 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api @@ -349,6 +349,7 @@ using facebook::react::ValueFactory = std::function; using facebook::react::ViewProps = facebook::react::HostPlatformViewProps; +using facebook::react::ViewShadowNodeProps = facebook::react::ViewProps; using facebook::react::VirtualViewComponentDescriptor = facebook::react::ConcreteComponentDescriptor; using facebook::react::parsePlatformColorFn = facebook::react::SharedColor(*)(const facebook::react::ContextContainer&, int32_t, const facebook::react::RawValue&); template @@ -3853,16 +3854,11 @@ class facebook::react::ViewComponentDescriptor : public facebook::react::Concret public ViewComponentDescriptor(const facebook::react::ComponentDescriptorParameters& parameters); } -class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { +class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { public ViewShadowNode(const facebook::react::ShadowNode& sourceShadowNode, const facebook::react::ShadowNodeFragment& fragment); public ViewShadowNode(const facebook::react::ShadowNodeFragment& fragment, const facebook::react::ShadowNodeFamily::Shared& family, facebook::react::ShadowNodeTraits traits); } -class facebook::react::ViewShadowNodeProps : public facebook::react::HostPlatformViewProps { - public ViewShadowNodeProps() = default; - public ViewShadowNodeProps(const facebook::react::PropsParserContext& context, const facebook::react::ViewShadowNodeProps& sourceProps, const facebook::react::RawProps& rawProps); -} - class facebook::react::ViewTransitionModule : public facebook::react::UIManagerViewTransitionDelegate, public facebook::react::UIManagerCommitHook, public facebook::react::MountingOverrideDelegate { public virtual bool shouldOverridePullTransaction() const override; public virtual facebook::react::RootShadowNode::Unshared shadowTreeWillCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& oldRootShadowNode, const facebook::react::RootShadowNode::Unshared& newRootShadowNode, const facebook::react::ShadowTreeCommitOptions& commitOptions) noexcept override; diff --git a/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api index 2c5d2474a718..d7f3c4120d60 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api @@ -348,6 +348,7 @@ using facebook::react::ValueFactory = std::function; using facebook::react::ViewProps = facebook::react::HostPlatformViewProps; +using facebook::react::ViewShadowNodeProps = facebook::react::ViewProps; using facebook::react::VirtualViewComponentDescriptor = facebook::react::ConcreteComponentDescriptor; using facebook::react::parsePlatformColorFn = facebook::react::SharedColor(*)(const facebook::react::ContextContainer&, int32_t, const facebook::react::RawValue&); template @@ -3707,16 +3708,11 @@ class facebook::react::ViewComponentDescriptor : public facebook::react::Concret public ViewComponentDescriptor(const facebook::react::ComponentDescriptorParameters& parameters); } -class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { +class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { public ViewShadowNode(const facebook::react::ShadowNode& sourceShadowNode, const facebook::react::ShadowNodeFragment& fragment); public ViewShadowNode(const facebook::react::ShadowNodeFragment& fragment, const facebook::react::ShadowNodeFamily::Shared& family, facebook::react::ShadowNodeTraits traits); } -class facebook::react::ViewShadowNodeProps : public facebook::react::HostPlatformViewProps { - public ViewShadowNodeProps() = default; - public ViewShadowNodeProps(const facebook::react::PropsParserContext& context, const facebook::react::ViewShadowNodeProps& sourceProps, const facebook::react::RawProps& rawProps); -} - class facebook::react::ViewTransitionModule : public facebook::react::UIManagerViewTransitionDelegate, public facebook::react::UIManagerCommitHook, public facebook::react::MountingOverrideDelegate { public virtual bool shouldOverridePullTransaction() const override; public virtual facebook::react::RootShadowNode::Unshared shadowTreeWillCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& oldRootShadowNode, const facebook::react::RootShadowNode::Unshared& newRootShadowNode, const facebook::react::ShadowTreeCommitOptions& commitOptions) noexcept override; diff --git a/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api index 8c562f2e7322..5537fec6eef6 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api @@ -349,6 +349,7 @@ using facebook::react::ValueFactory = std::function; using facebook::react::ViewProps = facebook::react::HostPlatformViewProps; +using facebook::react::ViewShadowNodeProps = facebook::react::ViewProps; using facebook::react::VirtualViewComponentDescriptor = facebook::react::ConcreteComponentDescriptor; using facebook::react::parsePlatformColorFn = facebook::react::SharedColor(*)(const facebook::react::ContextContainer&, int32_t, const facebook::react::RawValue&); template @@ -3844,16 +3845,11 @@ class facebook::react::ViewComponentDescriptor : public facebook::react::Concret public ViewComponentDescriptor(const facebook::react::ComponentDescriptorParameters& parameters); } -class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { +class facebook::react::ViewShadowNode : public facebook::react::ConcreteViewShadowNode { public ViewShadowNode(const facebook::react::ShadowNode& sourceShadowNode, const facebook::react::ShadowNodeFragment& fragment); public ViewShadowNode(const facebook::react::ShadowNodeFragment& fragment, const facebook::react::ShadowNodeFamily::Shared& family, facebook::react::ShadowNodeTraits traits); } -class facebook::react::ViewShadowNodeProps : public facebook::react::HostPlatformViewProps { - public ViewShadowNodeProps() = default; - public ViewShadowNodeProps(const facebook::react::PropsParserContext& context, const facebook::react::ViewShadowNodeProps& sourceProps, const facebook::react::RawProps& rawProps); -} - class facebook::react::ViewTransitionModule : public facebook::react::UIManagerViewTransitionDelegate, public facebook::react::UIManagerCommitHook, public facebook::react::MountingOverrideDelegate { public virtual bool shouldOverridePullTransaction() const override; public virtual facebook::react::RootShadowNode::Unshared shadowTreeWillCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& oldRootShadowNode, const facebook::react::RootShadowNode::Unshared& newRootShadowNode, const facebook::react::ShadowTreeCommitOptions& commitOptions) noexcept override; From 0d77d9387aafef3023d21345816757da4b774c31 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 30 Jun 2026 10:14:40 -0700 Subject: [PATCH 2/3] Route `enableCppPropsIteratorSetter` through a copy ctor + `RawProps::forEachItem` (#57328) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Pull Request resolved: https://github.com/react/react-native/pull/57328 Today the iterator-setter path in `ConcreteComponentDescriptor::cloneProps` runs three sequential walks over the input — `RawProps::parse(parser)` (builds `keyIndexToValueIndex_` for `convertRawProp`), `static_cast(rawProps)` (materializes a `folly::dynamic` via `jsi::dynamicFromValue` in JSI mode), and then `dynamic.items()` to dispatch `setProp`. Only the third is actually used: `convertRawProp` is never called on the iterator-setter branch, and the `folly::dynamic` materialization exists only as iteration scaffolding. Restructure so the runtime flag picks one of two construction paths up front: - **Iterator-setter** — copy-construct from `sourceProps` via the (re-enabled) `Props` copy ctor, then walk `rawProps` in-place via the new `RawProps::forEachItem` helper and route each entry through `setProp`. `parse()` is skipped entirely; the `folly::dynamic` materialization is skipped in `Mode::JSI`. - **Classic** — unchanged: `parse()` + 3-arg `convertRawProp`-driven ctor. `forEachItem` switches on `RawProps::Mode`: - `Mode::JSI` — walks `value_.asObject(*runtime_).getPropertyNames(...)` and constructs `RawValue` from each `jsi::Value` directly, no `folly::dynamic` in between. - `Mode::Dynamic` — iterates `dynamic_.items()` (same as today). - `Mode::Empty` — no-op. A new `HasIteratorSetterCtor` concept (`std::copy_constructible`) documents the contract and feeds a `static_assert` in `cloneProps`, so a future Props type that deletes its copy ctor fails at compile time rather than silently diverging at runtime between the two flag states. The `RN_SERIALIZABLE_STATE` Props 2.0 accumulation branch keeps its existing dynamic-iteration shape — when `fallbackToDynamicRawPropsAccumulation` is true, `initializeDynamicProps` has already merged the source's rawProps with the input onto `shadowNodeProps->rawProps`, so we iterate that merged dynamic rather than the raw input. The per-field `flag ? sourceProps.X : convertRawProp(...)` ternaries across every Props .cpp file become dead in the flag-on path (the copy ctor handles those fields) but are still functional in the flag-off path. They get removed in a follow-up cleanup; this diff is structurally non-breaking on either flag state. Changelog: [Internal] Differential Revision: D109568749 --- .../Components/View/__tests__/View-itest.js | 1 + .../core/ConcreteComponentDescriptor.h | 44 ++++-- .../react/renderer/core/ConcreteShadowNode.h | 19 +++ .../ReactCommon/react/renderer/core/Props.cpp | 8 +- .../ReactCommon/react/renderer/core/Props.h | 64 ++++++++- .../react/renderer/core/RawProps.h | 39 +++++ .../core/tests/ComponentDescriptorTest.cpp | 8 ++ .../renderer/core/tests/PropsConceptsTest.cpp | 135 ++++++++++++++++++ .../react/renderer/uimanager/UIManager.cpp | 23 +-- .../api-snapshots/ReactAndroidDebugCxx.api | 16 ++- .../api-snapshots/ReactAndroidNewarchCxx.api | 16 ++- .../api-snapshots/ReactAndroidReleaseCxx.api | 16 ++- .../api-snapshots/ReactAppleDebugCxx.api | 16 ++- .../api-snapshots/ReactAppleNewarchCxx.api | 16 ++- .../api-snapshots/ReactAppleReleaseCxx.api | 16 ++- .../api-snapshots/ReactCommonDebugCxx.api | 16 ++- .../api-snapshots/ReactCommonNewarchCxx.api | 16 ++- .../api-snapshots/ReactCommonReleaseCxx.api | 16 ++- 18 files changed, 443 insertions(+), 42 deletions(-) create mode 100644 packages/react-native/ReactCommon/react/renderer/core/tests/PropsConceptsTest.cpp diff --git a/packages/react-native/Libraries/Components/View/__tests__/View-itest.js b/packages/react-native/Libraries/Components/View/__tests__/View-itest.js index 240babf7ddc4..4ca19b624719 100644 --- a/packages/react-native/Libraries/Components/View/__tests__/View-itest.js +++ b/packages/react-native/Libraries/Components/View/__tests__/View-itest.js @@ -6,6 +6,7 @@ * * @flow strict-local * @fantom_flags enableNativeCSSParsing:* + * @fantom_flags enableCppPropsIteratorSetter:* * @format */ diff --git a/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h index 495702a08b8d..2945e433c383 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h @@ -112,9 +112,30 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { ShadowNodeT::filterRawProps(rawProps); } - rawProps.parse(rawPropsParser_); + // Two construction paths: + // - Iterator-setter (only available when `ConcreteProps` satisfies + // `HasIteratorSetterCtor` AND the runtime flag is on): copy-construct + // from sourceProps, then walk rawProps in-place via `forEachItem` and + // route each entry through `setProp`. Skips both + // `RawProps::parse(parser)` and the `folly::dynamic` materialization + // that the legacy path needed. + // - Classic (the fallback for any `ConcreteProps` that doesn't opt in, + // and the only path when the flag is off): parse + per-field + // `convertRawProp` via the 3-arg ctor. + constexpr bool kSupportsIteratorSetter = HasIteratorSetterCtor; + const bool useIteratorSetter = kSupportsIteratorSetter && ReactNativeFeatureFlags::enableCppPropsIteratorSetter(); + + std::shared_ptr shadowNodeProps; + if constexpr (kSupportsIteratorSetter) { + if (useIteratorSetter) { + shadowNodeProps = ShadowNodeT::Props(props); + } + } + if (!useIteratorSetter) { + rawProps.parse(rawPropsParser_); + shadowNodeProps = ShadowNodeT::Props(context, rawProps, props); + } - auto shadowNodeProps = ShadowNodeT::Props(context, rawProps, props); #ifdef RN_SERIALIZABLE_STATE bool fallbackToDynamicRawPropsAccumulation = true; if (ReactNativeFeatureFlags::enableExclusivePropsUpdateAndroid() && @@ -134,19 +155,12 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { ShadowNodeT::initializeDynamicProps(shadowNodeProps, rawProps, props); } #endif - // Use the new-style iterator - // Note that we just check if `Props` has this flag set, no matter - // the type of ShadowNode; it acts as the single global flag. - if (ReactNativeFeatureFlags::enableCppPropsIteratorSetter()) { -#ifdef RN_SERIALIZABLE_STATE - const auto &dynamic = - fallbackToDynamicRawPropsAccumulation ? shadowNodeProps->rawProps : static_cast(rawProps); -#else - const auto &dynamic = static_cast(rawProps); -#endif - for (const auto &pair : dynamic.items()) { - const auto &name = pair.first.getString(); - shadowNodeProps->setProp(context, RAW_PROPS_KEY_HASH(name), name.c_str(), RawValue(pair.second)); + + if constexpr (kSupportsIteratorSetter) { + if (useIteratorSetter) { + rawProps.forEachItem([&](std::string_view name, const RawValue &value) { + shadowNodeProps->setProp(context, RAW_PROPS_KEY_HASH(name), name.data(), value); + }); } } return shadowNodeProps; diff --git a/packages/react-native/ReactCommon/react/renderer/core/ConcreteShadowNode.h b/packages/react-native/ReactCommon/react/renderer/core/ConcreteShadowNode.h index cbddd0d8b446..ac069108548c 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ConcreteShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ConcreteShadowNode.h @@ -71,6 +71,13 @@ class ConcreteShadowNode : public BaseShadowNodeT { return BaseShadowNodeT::BaseTraits(); } + /* + * Classic / parse path: construct `PropsT` by parsing `rawProps` field-by- + * field via the 3-arg `(context, sourceProps, rawProps)` constructor. + * `ConcreteComponentDescriptor::cloneProps` calls this when the + * iterator-setter path is disabled (per-class via the + * `HasIteratorSetterCtor` concept, or globally via the runtime flag). + */ static UnsharedConcreteProps Props(const PropsParserContext &context, const RawProps &rawProps, const Props::Shared &baseProps = nullptr) { @@ -78,6 +85,18 @@ class ConcreteShadowNode : public BaseShadowNodeT { context, baseProps ? static_cast(*baseProps) : *defaultSharedProps(), rawProps); } + /* + * Iterator-setter path: copy-construct `PropsT` from `baseProps` only. + * `ConcreteComponentDescriptor::cloneProps` then walks `rawProps` via + * `RawProps::forEachItem` and overwrites individual fields through + * `PropsT::setProp`. Available when `PropsT` satisfies + * `HasIteratorSetterCtor`. + */ + static UnsharedConcreteProps Props(const Props::Shared &baseProps) + { + return std::make_shared(baseProps ? static_cast(*baseProps) : *defaultSharedProps()); + } + #ifdef RN_SERIALIZABLE_STATE static void initializeDynamicProps( UnsharedConcreteProps props, diff --git a/packages/react-native/ReactCommon/react/renderer/core/Props.cpp b/packages/react-native/ReactCommon/react/renderer/core/Props.cpp index aca087d296e4..6c668c044184 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/Props.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/Props.cpp @@ -29,13 +29,7 @@ Props::Props( rawProps, "nativeID", sourceProps.nativeId, - {})) { -#ifdef RN_SERIALIZABLE_STATE - if (!ReactNativeFeatureFlags::enableExclusivePropsUpdateAndroid()) { - initializeDynamicProps(sourceProps, rawProps, filterObjectKeys); - } -#endif -} + {})) {} void Props::setProp( const PropsParserContext& context, diff --git a/packages/react-native/ReactCommon/react/renderer/core/Props.h b/packages/react-native/ReactCommon/react/renderer/core/Props.h index ad3e264d31e2..a197824f1bff 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/Props.h +++ b/packages/react-native/ReactCommon/react/renderer/core/Props.h @@ -41,7 +41,7 @@ class Props : public virtual Sealable, public virtual DebugStringConvertible { virtual ~Props() = default; #endif - Props(const Props &other) = delete; + Props(const Props &other) = default; Props &operator=(const Props &other) = delete; /** @@ -84,4 +84,66 @@ class Props : public virtual Sealable, public virtual DebugStringConvertible { #endif }; +namespace detail { + +/* + * Extracts the class type from a pointer-to-member-function expression. + * Used in unevaluated context only. + */ +template +auto memberFunctionClass(T C::*) -> C; + +} // namespace detail + +/* + * Internal: `T` declares its OWN `setProp` (not just inherits one from a + * base class). `&T::setProp` resolves to a pointer-to-member-function whose + * class part is the level where `setProp` was actually declared — if `T` + * inherits without overriding, that class is some base, not `T`. + * + * Distinguishing own-declaration from inherited-declaration matters because + * `setProp` is non-virtual. A subclass that adds fields but forgets to + * override `setProp` would silently inherit its parent's switch — and the new + * fields would never be reached by the iterator-setter dispatch. + */ +template +concept DeclaresOwnSetProp = std::is_same_v; + +/* + * Internal: `T` exposes a `setProp(ctx, hash, name, value) -> void` callable + * with the canonical Props signature, declared on `T` itself. + */ +template +concept HasSetProp = DeclaresOwnSetProp && + requires(T &t, const PropsParserContext &ctx, RawPropsPropNameHash hash, const char *name, const RawValue &value) { + { t.setProp(ctx, hash, name, value) } -> std::same_as; + }; + +/* + * Marks a Props type as supporting the iterator-setter construction path used + * by `ConcreteComponentDescriptor::cloneProps` when + * `enableCppPropsIteratorSetter` is on. The contract is: + * + * 1. The type is copy-constructible from a source Props (so `cloneProps` + * can build the new Props by copy and then overwrite individual fields). + * 2. The type descends from `Props`, anchoring the `setProp` chain in the + * `Props::setProp` base case. + * 3. The type declares its OWN `setProp` with the canonical signature — + * not inherited — so the iterator dispatch reaches every field that the + * type adds beyond its base. + * + * `setProp` is non-virtual; subclasses chain explicitly via + * `Parent::setProp(...)`. The chain integrity beyond `T` is enforced by the + * compiler at each level's `setProp` body — if a subclass calls + * `Parent::setProp(...)` and `Parent` does not define one, the build fails + * at that call site. This concept guards the entry point (`T` itself) and + * relies on those per-level calls to keep the chain whole. + * + * When the concept is NOT satisfied for some `ConcreteProps`, + * `cloneProps` falls through to the classic per-field `convertRawProp` path + * for that component regardless of the runtime flag. + */ +template +concept HasIteratorSetterCtor = std::copy_constructible && std::derived_from && HasSetProp; + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/RawProps.h b/packages/react-native/ReactCommon/react/renderer/core/RawProps.h index 0abfce1c8256..e6f5c07def98 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/RawProps.h +++ b/packages/react-native/ReactCommon/react/renderer/core/RawProps.h @@ -97,6 +97,45 @@ class RawProps final { // compatibility with callers that pass prefix/suffix separately. const RawValue *at(const char *name, const char *prefix, const char *suffix) const noexcept; + /* + * Iterates the underlying source object and invokes `fn(name, value)` for + * each entry, in source order. Skips parsing — does NOT require a prior + * `parse(parser)` call. For `Mode::JSI` this walks the JSI object in-place + * (no `folly::dynamic` materialization). For `Mode::Dynamic` it walks + * `dynamic_.items()`. For `Mode::Empty` it is a no-op. + * + * The callback signature is `void(std::string_view name, const RawValue &value)`. + * The view points into storage owned by `forEachItem` for the duration of + * the call and is null-terminated (i.e. `name.data()` is a valid C string). + */ + template + void forEachItem(Fn fn) const + { + switch (mode_) { + case Mode::Empty: + return; + case Mode::JSI: { + auto object = value_.asObject(*runtime_); + auto names = object.getPropertyNames(*runtime_); + auto count = names.size(*runtime_); + for (size_t i = 0; i < count; ++i) { + auto name = names.getValueAtIndex(*runtime_, i).getString(*runtime_); + auto propValue = object.getProperty(*runtime_, name); + auto nameUtf8 = name.utf8(*runtime_); + fn(std::string_view{nameUtf8}, RawValue{*runtime_, std::move(propValue)}); + } + return; + } + case Mode::Dynamic: + for (const auto &pair : dynamic_.items()) { + fn(std::string_view{pair.first.getString()}, RawValue{pair.second}); + } + return; + default: + return; + } + } + private: friend class RawPropsParser; diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/ComponentDescriptorTest.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/ComponentDescriptorTest.cpp index 4b3538da3479..1a79845be624 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/ComponentDescriptorTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/ComponentDescriptorTest.cpp @@ -7,12 +7,20 @@ #include +#include #include #include "TestComponent.h" using namespace facebook::react; +static_assert( + HasIteratorSetterCtor, + "base `Props` must itself satisfy `HasIteratorSetterCtor` — it is copy-constructible, " + "derived from itself, and declares its own `setProp`. If this fails, " + "`ConcreteComponentDescriptor::cloneProps` will silently fall back to the classic " + "path for any concrete props whose nearest setProp-declaring ancestor is `Props` itself."); + TEST(ComponentDescriptorTest, createShadowNode) { auto eventDispatcher = std::shared_ptr(); SharedComponentDescriptor descriptor = diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/PropsConceptsTest.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/PropsConceptsTest.cpp new file mode 100644 index 000000000000..656bd0612448 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/PropsConceptsTest.cpp @@ -0,0 +1,135 @@ +/* + * 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 +#include +#include +#include +#include + +using namespace facebook::react; + +namespace { + +// Mimics the shape the React Native codegen emits for +// `codegenNativeComponent(...)` (see +// `react-native-codegen/src/generators/components/GeneratePropsH.js` +// `ClassTemplate`): default ctor, the 3-arg classic ctor with +// `convertRawProp` in its initializer list, public prop fields, and +// NO `setProp` override. +class CodegenStyleProps : public Props { + public: + CodegenStyleProps() = default; + CodegenStyleProps( + const PropsParserContext& context, + const CodegenStyleProps& sourceProps, + const RawProps& rawProps) + : Props(context, sourceProps, rawProps), + customField(convertRawProp( + context, + rawProps, + "customField", + sourceProps.customField, + 0)) {} + + int customField{0}; +}; + +// Mimics a hand-written Props subclass that opts in to the +// iterator-setter path by declaring its own `setProp`. +class HandWrittenSetPropProps : public Props { + public: + HandWrittenSetPropProps() = default; + HandWrittenSetPropProps( + const PropsParserContext& context, + const HandWrittenSetPropProps& sourceProps, + const RawProps& rawProps) + : Props(context, sourceProps, rawProps), + customField(sourceProps.customField) {} + + void setProp( + const PropsParserContext& context, + RawPropsPropNameHash hash, + const char* propName, + const RawValue& value) { + Props::setProp(context, hash, propName, value); + switch (hash) { + case CONSTEXPR_RAW_PROPS_KEY_HASH("customField"): + fromRawValue(context, value, customField, 0); + return; + } + } + + int customField{0}; +}; + +// A subclass of a hand-written setProp class that does NOT redeclare +// `setProp`. Acts like a downstream specialization (e.g. how +// `ViewShadowNodeProps` extends `ViewProps`). The concept must reject +// this — otherwise the iterator-setter dispatch would silently miss +// `extraField`. +class InheritedSetPropProps : public HandWrittenSetPropProps { + public: + InheritedSetPropProps() = default; + InheritedSetPropProps( + const PropsParserContext& context, + const InheritedSetPropProps& sourceProps, + const RawProps& rawProps) + : HandWrittenSetPropProps(context, sourceProps, rawProps), + extraField(sourceProps.extraField) {} + + int extraField{0}; +}; + +// `using Base::setProp;` is sugar — it doesn't constitute "own" +// declaration. Concept must still reject. +class UsingDeclSetPropProps : public HandWrittenSetPropProps { + public: + using HandWrittenSetPropProps::setProp; +}; + +// Concept axioms — fail the build if the iterator-setter dispatch ever +// regresses to silently accepting classes that inherit `setProp`. +static_assert( + !DeclaresOwnSetProp, + "Codegen'd Props classes don't declare setProp — concept must reject them."); +static_assert( + !HasSetProp, + "HasSetProp requires DeclaresOwnSetProp."); +static_assert( + !HasIteratorSetterCtor, + "Codegen'd Props must fall through to the classic cloneProps path. " + "If this fires, the iterator-setter would skip every field the codegen'd " + "ctor populates via convertRawProp, leaving the component unrendered."); + +static_assert(DeclaresOwnSetProp); +static_assert(HasSetProp); +static_assert(HasIteratorSetterCtor); + +static_assert( + !DeclaresOwnSetProp, + "A subclass that inherits setProp without redeclaring it must not " + "satisfy the concept — its new fields would be skipped."); +static_assert(!HasIteratorSetterCtor); + +static_assert( + !DeclaresOwnSetProp, + "`using Base::setProp;` is not an own declaration."); +static_assert(!HasIteratorSetterCtor); + +// Baselines: `Props` itself owns `setProp`, so it satisfies the concept. +static_assert(DeclaresOwnSetProp); +static_assert(HasIteratorSetterCtor); + +} // namespace + +// gtest entry so the file participates in the test binary (the +// static_asserts above are the real check — this just keeps gtest's +// test discovery happy). +TEST(PropsConceptsTest, ConceptAxiomsCompile) { + SUCCEED(); +} diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp index 32929b3a4717..d7f442640b3b 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp @@ -76,20 +76,23 @@ std::shared_ptr UIManager::createNode( {.tag = tag, .surfaceId = surfaceId, .instanceHandle = std::move(instanceHandle)}); - const auto props = componentDescriptor.cloneProps( + auto props = componentDescriptor.cloneProps( propsParserContext, nullptr, std::move(rawProps)); - const auto state = componentDescriptor.createInitialState(props, family); + auto state = componentDescriptor.createInitialState(props, family); + + // Add a "name" prop if this is the fallback component + if (fallbackDescriptor != nullptr && + fallbackDescriptor->getComponentHandle() == + componentDescriptor.getComponentHandle()) { + props = componentDescriptor.cloneProps( + propsParserContext, + props, + RawProps(folly::dynamic::object("name", name))); + } auto shadowNode = componentDescriptor.createShadowNode( ShadowNodeFragment{ - .props = fallbackDescriptor != nullptr && - fallbackDescriptor->getComponentHandle() == - componentDescriptor.getComponentHandle() - ? componentDescriptor.cloneProps( - propsParserContext, - props, - RawProps(folly::dynamic::object("name", name))) - : props, + .props = props, .children = ShadowNodeFragment::childrenPlaceholder(), .state = state, }, diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api index a360d98fce0c..5401d204d67e 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api @@ -796,6 +796,15 @@ concept facebook::react::CSSSyntaxVisitorReturn = std::is_default_constructible_ template concept facebook::react::CSSValidCompoundDataType = facebook::react::detail::is_variant_of_data_types::value; template +concept facebook::react::DeclaresOwnSetProp = std::is_same_v; +template +concept facebook::react::HasIteratorSetterCtor = std::copy_constructible && std::derived_from && HasSetProp; +template +concept facebook::react::HasSetProp = DeclaresOwnSetProp && +requires(T& t, const facebook::react::PropsParserContext& ctx, facebook::react::RawPropsPropNameHash hash, const char* name, const facebook::react::RawValue& value) { + { t.setProp(ctx, hash, name, value) } -> std::same_as; +}; +template concept facebook::react::Hashable = !std::is_same_v&& (requires(T a) { { std::hash{}(a) } -> std::convertible_to; }); @@ -4127,7 +4136,7 @@ class facebook::react::PreparedTextCacheKey { class facebook::react::Props : public virtual facebook::react::Sealable, public virtual facebook::react::DebugStringConvertible { public Props() = default; - public Props(const facebook::react::Props& other) = delete; + public Props(const facebook::react::Props& other) = default; public Props(const facebook::react::PropsParserContext& context, const facebook::react::Props& sourceProps, const facebook::react::RawProps& rawProps, const std::function& filterObjectKeys = nullptr); public facebook::react::Props& operator=(const facebook::react::Props& other) = delete; public folly::dynamic rawProps; @@ -4197,6 +4206,8 @@ class facebook::react::RawProps { public folly::dynamic toDynamic(const std::function& filterObjectKeys = nullptr) const; public operator folly::dynamic() const; public void parse(const facebook::react::RawPropsParser& parser) noexcept; + template + public void forEachItem(Fn fn) const; } enum facebook::react::RawProps::Mode { @@ -8251,6 +8262,7 @@ class facebook::react::ConcreteShadowNode : public BaseShadowNodeT { public static facebook::react::ComponentHandle Handle(); public static facebook::react::ComponentName Name(); public static facebook::react::ConcreteShadowNode::ConcreteStateData initialStateData(const facebook::react::Props::Shared&, const facebook::react::ShadowNodeFamily::Shared&, const facebook::react::ComponentDescriptor&); + public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::Props::Shared& baseProps); public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::PropsParserContext& context, const facebook::react::RawProps& rawProps, const facebook::react::Props::Shared& baseProps = nullptr); public static facebook::react::ShadowNodeTraits BaseTraits(); public static void initializeDynamicProps(facebook::react::ConcreteShadowNode::UnsharedConcreteProps props, const facebook::react::RawProps& rawProps, const facebook::react::Props::Shared& baseProps = nullptr); @@ -9935,6 +9947,8 @@ template std::optional facebook::react::detail::parseLegacyHslFunction(facebook::react::CSSValueParser& parser); template std::optional facebook::react::detail::parseModernHslFunction(facebook::react::CSSValueParser& parser); +template +C facebook::react::detail::memberFunctionClass(T C::*); template constexpr std::optional facebook::react::detail::normalizeComponent(const std::variant& component, float baseValue); diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api index e521b074ce85..ece78dc811d2 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api @@ -795,6 +795,15 @@ concept facebook::react::CSSSyntaxVisitorReturn = std::is_default_constructible_ template concept facebook::react::CSSValidCompoundDataType = facebook::react::detail::is_variant_of_data_types::value; template +concept facebook::react::DeclaresOwnSetProp = std::is_same_v; +template +concept facebook::react::HasIteratorSetterCtor = std::copy_constructible && std::derived_from && HasSetProp; +template +concept facebook::react::HasSetProp = DeclaresOwnSetProp && +requires(T& t, const facebook::react::PropsParserContext& ctx, facebook::react::RawPropsPropNameHash hash, const char* name, const facebook::react::RawValue& value) { + { t.setProp(ctx, hash, name, value) } -> std::same_as; +}; +template concept facebook::react::Hashable = !std::is_same_v&& (requires(T a) { { std::hash{}(a) } -> std::convertible_to; }); @@ -3981,7 +3990,7 @@ class facebook::react::PreparedTextCacheKey { class facebook::react::Props : public virtual facebook::react::Sealable, public virtual facebook::react::DebugStringConvertible { public Props() = default; - public Props(const facebook::react::Props& other) = delete; + public Props(const facebook::react::Props& other) = default; public Props(const facebook::react::PropsParserContext& context, const facebook::react::Props& sourceProps, const facebook::react::RawProps& rawProps, const std::function& filterObjectKeys = nullptr); public facebook::react::Props& operator=(const facebook::react::Props& other) = delete; public folly::dynamic rawProps; @@ -4041,6 +4050,8 @@ class facebook::react::RawProps { public folly::dynamic toDynamic(const std::function& filterObjectKeys = nullptr) const; public operator folly::dynamic() const; public void parse(const facebook::react::RawPropsParser& parser) noexcept; + template + public void forEachItem(Fn fn) const; } enum facebook::react::RawProps::Mode { @@ -8015,6 +8026,7 @@ class facebook::react::ConcreteShadowNode : public BaseShadowNodeT { public static facebook::react::ComponentHandle Handle(); public static facebook::react::ComponentName Name(); public static facebook::react::ConcreteShadowNode::ConcreteStateData initialStateData(const facebook::react::Props::Shared&, const facebook::react::ShadowNodeFamily::Shared&, const facebook::react::ComponentDescriptor&); + public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::Props::Shared& baseProps); public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::PropsParserContext& context, const facebook::react::RawProps& rawProps, const facebook::react::Props::Shared& baseProps = nullptr); public static facebook::react::ShadowNodeTraits BaseTraits(); public static void initializeDynamicProps(facebook::react::ConcreteShadowNode::UnsharedConcreteProps props, const facebook::react::RawProps& rawProps, const facebook::react::Props::Shared& baseProps = nullptr); @@ -9561,6 +9573,8 @@ template std::optional facebook::react::detail::parseLegacyHslFunction(facebook::react::CSSValueParser& parser); template std::optional facebook::react::detail::parseModernHslFunction(facebook::react::CSSValueParser& parser); +template +C facebook::react::detail::memberFunctionClass(T C::*); template constexpr std::optional facebook::react::detail::normalizeComponent(const std::variant& component, float baseValue); diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api index fc6a7f8949e4..4f8c02523741 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api @@ -796,6 +796,15 @@ concept facebook::react::CSSSyntaxVisitorReturn = std::is_default_constructible_ template concept facebook::react::CSSValidCompoundDataType = facebook::react::detail::is_variant_of_data_types::value; template +concept facebook::react::DeclaresOwnSetProp = std::is_same_v; +template +concept facebook::react::HasIteratorSetterCtor = std::copy_constructible && std::derived_from && HasSetProp; +template +concept facebook::react::HasSetProp = DeclaresOwnSetProp && +requires(T& t, const facebook::react::PropsParserContext& ctx, facebook::react::RawPropsPropNameHash hash, const char* name, const facebook::react::RawValue& value) { + { t.setProp(ctx, hash, name, value) } -> std::same_as; +}; +template concept facebook::react::Hashable = !std::is_same_v&& (requires(T a) { { std::hash{}(a) } -> std::convertible_to; }); @@ -4124,7 +4133,7 @@ class facebook::react::PreparedTextCacheKey { class facebook::react::Props : public virtual facebook::react::Sealable, public virtual facebook::react::DebugStringConvertible { public Props() = default; - public Props(const facebook::react::Props& other) = delete; + public Props(const facebook::react::Props& other) = default; public Props(const facebook::react::PropsParserContext& context, const facebook::react::Props& sourceProps, const facebook::react::RawProps& rawProps, const std::function& filterObjectKeys = nullptr); public facebook::react::Props& operator=(const facebook::react::Props& other) = delete; public folly::dynamic rawProps; @@ -4194,6 +4203,8 @@ class facebook::react::RawProps { public folly::dynamic toDynamic(const std::function& filterObjectKeys = nullptr) const; public operator folly::dynamic() const; public void parse(const facebook::react::RawPropsParser& parser) noexcept; + template + public void forEachItem(Fn fn) const; } enum facebook::react::RawProps::Mode { @@ -8242,6 +8253,7 @@ class facebook::react::ConcreteShadowNode : public BaseShadowNodeT { public static facebook::react::ComponentHandle Handle(); public static facebook::react::ComponentName Name(); public static facebook::react::ConcreteShadowNode::ConcreteStateData initialStateData(const facebook::react::Props::Shared&, const facebook::react::ShadowNodeFamily::Shared&, const facebook::react::ComponentDescriptor&); + public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::Props::Shared& baseProps); public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::PropsParserContext& context, const facebook::react::RawProps& rawProps, const facebook::react::Props::Shared& baseProps = nullptr); public static facebook::react::ShadowNodeTraits BaseTraits(); public static void initializeDynamicProps(facebook::react::ConcreteShadowNode::UnsharedConcreteProps props, const facebook::react::RawProps& rawProps, const facebook::react::Props::Shared& baseProps = nullptr); @@ -9788,6 +9800,8 @@ template std::optional facebook::react::detail::parseLegacyHslFunction(facebook::react::CSSValueParser& parser); template std::optional facebook::react::detail::parseModernHslFunction(facebook::react::CSSValueParser& parser); +template +C facebook::react::detail::memberFunctionClass(T C::*); template constexpr std::optional facebook::react::detail::normalizeComponent(const std::variant& component, float baseValue); diff --git a/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api index 5db822c2e8bc..58bb75f66dc7 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api @@ -3652,6 +3652,15 @@ concept facebook::react::CSSSyntaxVisitorReturn = std::is_default_constructible_ template concept facebook::react::CSSValidCompoundDataType = facebook::react::detail::is_variant_of_data_types::value; template +concept facebook::react::DeclaresOwnSetProp = std::is_same_v; +template +concept facebook::react::HasIteratorSetterCtor = std::copy_constructible && std::derived_from && HasSetProp; +template +concept facebook::react::HasSetProp = DeclaresOwnSetProp && +requires(T& t, const facebook::react::PropsParserContext& ctx, facebook::react::RawPropsPropNameHash hash, const char* name, const facebook::react::RawValue& value) { + { t.setProp(ctx, hash, name, value) } -> std::same_as; +}; +template concept facebook::react::Hashable = !std::is_same_v&& (requires(T a) { { std::hash{}(a) } -> std::convertible_to; }); @@ -6314,7 +6323,7 @@ class facebook::react::PreparedTextCacheKey { class facebook::react::Props : public virtual facebook::react::Sealable, public virtual facebook::react::DebugStringConvertible { public Props() = default; - public Props(const facebook::react::Props& other) = delete; + public Props(const facebook::react::Props& other) = default; public Props(const facebook::react::PropsParserContext& context, const facebook::react::Props& sourceProps, const facebook::react::RawProps& rawProps, const std::function& filterObjectKeys = nullptr); public facebook::react::Props& operator=(const facebook::react::Props& other) = delete; public std::string nativeId; @@ -6414,6 +6423,8 @@ class facebook::react::RawProps { public folly::dynamic toDynamic(const std::function& filterObjectKeys = nullptr) const; public operator folly::dynamic() const; public void parse(const facebook::react::RawPropsParser& parser) noexcept; + template + public void forEachItem(Fn fn) const; } enum facebook::react::RawProps::Mode { @@ -10232,6 +10243,7 @@ class facebook::react::ConcreteShadowNode : public BaseShadowNodeT { public static facebook::react::ComponentHandle Handle(); public static facebook::react::ComponentName Name(); public static facebook::react::ConcreteShadowNode::ConcreteStateData initialStateData(const facebook::react::Props::Shared&, const facebook::react::ShadowNodeFamily::Shared&, const facebook::react::ComponentDescriptor&); + public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::Props::Shared& baseProps); public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::PropsParserContext& context, const facebook::react::RawProps& rawProps, const facebook::react::Props::Shared& baseProps = nullptr); public static facebook::react::ShadowNodeTraits BaseTraits(); public using ConcreteEventEmitter = EventEmitterT; @@ -11833,6 +11845,8 @@ template std::optional facebook::react::detail::parseLegacyHslFunction(facebook::react::CSSValueParser& parser); template std::optional facebook::react::detail::parseModernHslFunction(facebook::react::CSSValueParser& parser); +template +C facebook::react::detail::memberFunctionClass(T C::*); template constexpr std::optional facebook::react::detail::normalizeComponent(const std::variant& component, float baseValue); diff --git a/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api index f17f0b02df5c..c0a25d8706d4 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api @@ -3639,6 +3639,15 @@ concept facebook::react::CSSSyntaxVisitorReturn = std::is_default_constructible_ template concept facebook::react::CSSValidCompoundDataType = facebook::react::detail::is_variant_of_data_types::value; template +concept facebook::react::DeclaresOwnSetProp = std::is_same_v; +template +concept facebook::react::HasIteratorSetterCtor = std::copy_constructible && std::derived_from && HasSetProp; +template +concept facebook::react::HasSetProp = DeclaresOwnSetProp && +requires(T& t, const facebook::react::PropsParserContext& ctx, facebook::react::RawPropsPropNameHash hash, const char* name, const facebook::react::RawValue& value) { + { t.setProp(ctx, hash, name, value) } -> std::same_as; +}; +template concept facebook::react::Hashable = !std::is_same_v&& (requires(T a) { { std::hash{}(a) } -> std::convertible_to; }); @@ -6196,7 +6205,7 @@ class facebook::react::PreparedTextCacheKey { class facebook::react::Props : public virtual facebook::react::Sealable, public virtual facebook::react::DebugStringConvertible { public Props() = default; - public Props(const facebook::react::Props& other) = delete; + public Props(const facebook::react::Props& other) = default; public Props(const facebook::react::PropsParserContext& context, const facebook::react::Props& sourceProps, const facebook::react::RawProps& rawProps, const std::function& filterObjectKeys = nullptr); public facebook::react::Props& operator=(const facebook::react::Props& other) = delete; public std::string nativeId; @@ -6286,6 +6295,8 @@ class facebook::react::RawProps { public folly::dynamic toDynamic(const std::function& filterObjectKeys = nullptr) const; public operator folly::dynamic() const; public void parse(const facebook::react::RawPropsParser& parser) noexcept; + template + public void forEachItem(Fn fn) const; } enum facebook::react::RawProps::Mode { @@ -10048,6 +10059,7 @@ class facebook::react::ConcreteShadowNode : public BaseShadowNodeT { public static facebook::react::ComponentHandle Handle(); public static facebook::react::ComponentName Name(); public static facebook::react::ConcreteShadowNode::ConcreteStateData initialStateData(const facebook::react::Props::Shared&, const facebook::react::ShadowNodeFamily::Shared&, const facebook::react::ComponentDescriptor&); + public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::Props::Shared& baseProps); public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::PropsParserContext& context, const facebook::react::RawProps& rawProps, const facebook::react::Props::Shared& baseProps = nullptr); public static facebook::react::ShadowNodeTraits BaseTraits(); public using ConcreteEventEmitter = EventEmitterT; @@ -11521,6 +11533,8 @@ template std::optional facebook::react::detail::parseLegacyHslFunction(facebook::react::CSSValueParser& parser); template std::optional facebook::react::detail::parseModernHslFunction(facebook::react::CSSValueParser& parser); +template +C facebook::react::detail::memberFunctionClass(T C::*); template constexpr std::optional facebook::react::detail::normalizeComponent(const std::variant& component, float baseValue); diff --git a/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api index 6efb67807861..4e834b9310b0 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api @@ -3652,6 +3652,15 @@ concept facebook::react::CSSSyntaxVisitorReturn = std::is_default_constructible_ template concept facebook::react::CSSValidCompoundDataType = facebook::react::detail::is_variant_of_data_types::value; template +concept facebook::react::DeclaresOwnSetProp = std::is_same_v; +template +concept facebook::react::HasIteratorSetterCtor = std::copy_constructible && std::derived_from && HasSetProp; +template +concept facebook::react::HasSetProp = DeclaresOwnSetProp && +requires(T& t, const facebook::react::PropsParserContext& ctx, facebook::react::RawPropsPropNameHash hash, const char* name, const facebook::react::RawValue& value) { + { t.setProp(ctx, hash, name, value) } -> std::same_as; +}; +template concept facebook::react::Hashable = !std::is_same_v&& (requires(T a) { { std::hash{}(a) } -> std::convertible_to; }); @@ -6311,7 +6320,7 @@ class facebook::react::PreparedTextCacheKey { class facebook::react::Props : public virtual facebook::react::Sealable, public virtual facebook::react::DebugStringConvertible { public Props() = default; - public Props(const facebook::react::Props& other) = delete; + public Props(const facebook::react::Props& other) = default; public Props(const facebook::react::PropsParserContext& context, const facebook::react::Props& sourceProps, const facebook::react::RawProps& rawProps, const std::function& filterObjectKeys = nullptr); public facebook::react::Props& operator=(const facebook::react::Props& other) = delete; public std::string nativeId; @@ -6411,6 +6420,8 @@ class facebook::react::RawProps { public folly::dynamic toDynamic(const std::function& filterObjectKeys = nullptr) const; public operator folly::dynamic() const; public void parse(const facebook::react::RawPropsParser& parser) noexcept; + template + public void forEachItem(Fn fn) const; } enum facebook::react::RawProps::Mode { @@ -10223,6 +10234,7 @@ class facebook::react::ConcreteShadowNode : public BaseShadowNodeT { public static facebook::react::ComponentHandle Handle(); public static facebook::react::ComponentName Name(); public static facebook::react::ConcreteShadowNode::ConcreteStateData initialStateData(const facebook::react::Props::Shared&, const facebook::react::ShadowNodeFamily::Shared&, const facebook::react::ComponentDescriptor&); + public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::Props::Shared& baseProps); public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::PropsParserContext& context, const facebook::react::RawProps& rawProps, const facebook::react::Props::Shared& baseProps = nullptr); public static facebook::react::ShadowNodeTraits BaseTraits(); public using ConcreteEventEmitter = EventEmitterT; @@ -11696,6 +11708,8 @@ template std::optional facebook::react::detail::parseLegacyHslFunction(facebook::react::CSSValueParser& parser); template std::optional facebook::react::detail::parseModernHslFunction(facebook::react::CSSValueParser& parser); +template +C facebook::react::detail::memberFunctionClass(T C::*); template constexpr std::optional facebook::react::detail::normalizeComponent(const std::variant& component, float baseValue); diff --git a/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api index 7edcb2738efb..4c1112b3c47a 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api @@ -405,6 +405,15 @@ concept facebook::react::CSSSyntaxVisitorReturn = std::is_default_constructible_ template concept facebook::react::CSSValidCompoundDataType = facebook::react::detail::is_variant_of_data_types::value; template +concept facebook::react::DeclaresOwnSetProp = std::is_same_v; +template +concept facebook::react::HasIteratorSetterCtor = std::copy_constructible && std::derived_from && HasSetProp; +template +concept facebook::react::HasSetProp = DeclaresOwnSetProp && +requires(T& t, const facebook::react::PropsParserContext& ctx, facebook::react::RawPropsPropNameHash hash, const char* name, const facebook::react::RawValue& value) { + { t.setProp(ctx, hash, name, value) } -> std::same_as; +}; +template concept facebook::react::Hashable = !std::is_same_v&& (requires(T a) { { std::hash{}(a) } -> std::convertible_to; }); @@ -2732,7 +2741,7 @@ class facebook::react::PreparedTextCacheKey { class facebook::react::Props : public virtual facebook::react::Sealable, public virtual facebook::react::DebugStringConvertible { public Props() = default; - public Props(const facebook::react::Props& other) = delete; + public Props(const facebook::react::Props& other) = default; public Props(const facebook::react::PropsParserContext& context, const facebook::react::Props& sourceProps, const facebook::react::RawProps& rawProps, const std::function& filterObjectKeys = nullptr); public facebook::react::Props& operator=(const facebook::react::Props& other) = delete; public std::string nativeId; @@ -2779,6 +2788,8 @@ class facebook::react::RawProps { public folly::dynamic toDynamic(const std::function& filterObjectKeys = nullptr) const; public operator folly::dynamic() const; public void parse(const facebook::react::RawPropsParser& parser) noexcept; + template + public void forEachItem(Fn fn) const; } enum facebook::react::RawProps::Mode { @@ -6341,6 +6352,7 @@ class facebook::react::ConcreteShadowNode : public BaseShadowNodeT { public static facebook::react::ComponentHandle Handle(); public static facebook::react::ComponentName Name(); public static facebook::react::ConcreteShadowNode::ConcreteStateData initialStateData(const facebook::react::Props::Shared&, const facebook::react::ShadowNodeFamily::Shared&, const facebook::react::ComponentDescriptor&); + public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::Props::Shared& baseProps); public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::PropsParserContext& context, const facebook::react::RawProps& rawProps, const facebook::react::Props::Shared& baseProps = nullptr); public static facebook::react::ShadowNodeTraits BaseTraits(); public using ConcreteEventEmitter = EventEmitterT; @@ -6995,6 +7007,8 @@ template std::optional facebook::react::detail::parseLegacyHslFunction(facebook::react::CSSValueParser& parser); template std::optional facebook::react::detail::parseModernHslFunction(facebook::react::CSSValueParser& parser); +template +C facebook::react::detail::memberFunctionClass(T C::*); template constexpr std::optional facebook::react::detail::normalizeComponent(const std::variant& component, float baseValue); diff --git a/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api index d7f3c4120d60..b6f69a46ab95 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api @@ -404,6 +404,15 @@ concept facebook::react::CSSSyntaxVisitorReturn = std::is_default_constructible_ template concept facebook::react::CSSValidCompoundDataType = facebook::react::detail::is_variant_of_data_types::value; template +concept facebook::react::DeclaresOwnSetProp = std::is_same_v; +template +concept facebook::react::HasIteratorSetterCtor = std::copy_constructible && std::derived_from && HasSetProp; +template +concept facebook::react::HasSetProp = DeclaresOwnSetProp && +requires(T& t, const facebook::react::PropsParserContext& ctx, facebook::react::RawPropsPropNameHash hash, const char* name, const facebook::react::RawValue& value) { + { t.setProp(ctx, hash, name, value) } -> std::same_as; +}; +template concept facebook::react::Hashable = !std::is_same_v&& (requires(T a) { { std::hash{}(a) } -> std::convertible_to; }); @@ -2626,7 +2635,7 @@ class facebook::react::PreparedTextCacheKey { class facebook::react::Props : public virtual facebook::react::Sealable, public virtual facebook::react::DebugStringConvertible { public Props() = default; - public Props(const facebook::react::Props& other) = delete; + public Props(const facebook::react::Props& other) = default; public Props(const facebook::react::PropsParserContext& context, const facebook::react::Props& sourceProps, const facebook::react::RawProps& rawProps, const std::function& filterObjectKeys = nullptr); public facebook::react::Props& operator=(const facebook::react::Props& other) = delete; public std::string nativeId; @@ -2663,6 +2672,8 @@ class facebook::react::RawProps { public folly::dynamic toDynamic(const std::function& filterObjectKeys = nullptr) const; public operator folly::dynamic() const; public void parse(const facebook::react::RawPropsParser& parser) noexcept; + template + public void forEachItem(Fn fn) const; } enum facebook::react::RawProps::Mode { @@ -6169,6 +6180,7 @@ class facebook::react::ConcreteShadowNode : public BaseShadowNodeT { public static facebook::react::ComponentHandle Handle(); public static facebook::react::ComponentName Name(); public static facebook::react::ConcreteShadowNode::ConcreteStateData initialStateData(const facebook::react::Props::Shared&, const facebook::react::ShadowNodeFamily::Shared&, const facebook::react::ComponentDescriptor&); + public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::Props::Shared& baseProps); public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::PropsParserContext& context, const facebook::react::RawProps& rawProps, const facebook::react::Props::Shared& baseProps = nullptr); public static facebook::react::ShadowNodeTraits BaseTraits(); public using ConcreteEventEmitter = EventEmitterT; @@ -6823,6 +6835,8 @@ template std::optional facebook::react::detail::parseLegacyHslFunction(facebook::react::CSSValueParser& parser); template std::optional facebook::react::detail::parseModernHslFunction(facebook::react::CSSValueParser& parser); +template +C facebook::react::detail::memberFunctionClass(T C::*); template constexpr std::optional facebook::react::detail::normalizeComponent(const std::variant& component, float baseValue); diff --git a/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api index 5537fec6eef6..84299a8c4efd 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api @@ -405,6 +405,15 @@ concept facebook::react::CSSSyntaxVisitorReturn = std::is_default_constructible_ template concept facebook::react::CSSValidCompoundDataType = facebook::react::detail::is_variant_of_data_types::value; template +concept facebook::react::DeclaresOwnSetProp = std::is_same_v; +template +concept facebook::react::HasIteratorSetterCtor = std::copy_constructible && std::derived_from && HasSetProp; +template +concept facebook::react::HasSetProp = DeclaresOwnSetProp && +requires(T& t, const facebook::react::PropsParserContext& ctx, facebook::react::RawPropsPropNameHash hash, const char* name, const facebook::react::RawValue& value) { + { t.setProp(ctx, hash, name, value) } -> std::same_as; +}; +template concept facebook::react::Hashable = !std::is_same_v&& (requires(T a) { { std::hash{}(a) } -> std::convertible_to; }); @@ -2729,7 +2738,7 @@ class facebook::react::PreparedTextCacheKey { class facebook::react::Props : public virtual facebook::react::Sealable, public virtual facebook::react::DebugStringConvertible { public Props() = default; - public Props(const facebook::react::Props& other) = delete; + public Props(const facebook::react::Props& other) = default; public Props(const facebook::react::PropsParserContext& context, const facebook::react::Props& sourceProps, const facebook::react::RawProps& rawProps, const std::function& filterObjectKeys = nullptr); public facebook::react::Props& operator=(const facebook::react::Props& other) = delete; public std::string nativeId; @@ -2776,6 +2785,8 @@ class facebook::react::RawProps { public folly::dynamic toDynamic(const std::function& filterObjectKeys = nullptr) const; public operator folly::dynamic() const; public void parse(const facebook::react::RawPropsParser& parser) noexcept; + template + public void forEachItem(Fn fn) const; } enum facebook::react::RawProps::Mode { @@ -6332,6 +6343,7 @@ class facebook::react::ConcreteShadowNode : public BaseShadowNodeT { public static facebook::react::ComponentHandle Handle(); public static facebook::react::ComponentName Name(); public static facebook::react::ConcreteShadowNode::ConcreteStateData initialStateData(const facebook::react::Props::Shared&, const facebook::react::ShadowNodeFamily::Shared&, const facebook::react::ComponentDescriptor&); + public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::Props::Shared& baseProps); public static facebook::react::ConcreteShadowNode::UnsharedConcreteProps Props(const facebook::react::PropsParserContext& context, const facebook::react::RawProps& rawProps, const facebook::react::Props::Shared& baseProps = nullptr); public static facebook::react::ShadowNodeTraits BaseTraits(); public using ConcreteEventEmitter = EventEmitterT; @@ -6986,6 +6998,8 @@ template std::optional facebook::react::detail::parseLegacyHslFunction(facebook::react::CSSValueParser& parser); template std::optional facebook::react::detail::parseModernHslFunction(facebook::react::CSSValueParser& parser); +template +C facebook::react::detail::memberFunctionClass(T C::*); template constexpr std::optional facebook::react::detail::normalizeComponent(const std::variant& component, float baseValue); From ad40a523804d670a2461bc808c21fbd53f6d62ab Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 30 Jun 2026 10:18:44 -0700 Subject: [PATCH 3/3] Skip `RawPropsParser::prepare()` when the iterator-setter path is active (#57329) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Pull Request resolved: https://github.com/react/react-native/pull/57329 `RawPropsParser::prepare()` runs in `ConcreteComponentDescriptor`'s constructor and builds the parser's `keys_` vector + `nameToIndex_` length-bucketed map by walking every `convertRawProp` call in a probe construction of `ConcreteProps`. The cost is O(n²) in the number of props (the comment in `RawPropsParser::at` notes 4950 lookups for a 100-prop class) and is paid once per component class at app startup. Those data structures are consumed **only** by `RawProps::at()`, which is reached exclusively through the classic per-field `convertRawProp` path. The iterator-setter path skips `parse()` entirely (see the prior diff in the stack), so the prepared parser is dead weight when both: 1. `HasIteratorSetterCtor` is satisfied (i.e. the type opts into the iterator-setter path), AND 2. `enableCppPropsIteratorSetter()` is on at runtime. Guard the call accordingly. Classes that don't satisfy the concept always run `prepare()` (they can only use the classic path); when the runtime flag is off, all classes run it (since they all fall back to classic). Changelog: [Internal] Reviewed By: christophpurrer, lenaic Differential Revision: D109569571 --- .../renderer/core/ConcreteComponentDescriptor.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h index 2945e433c383..5c5773028d31 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h @@ -48,7 +48,18 @@ class ConcreteComponentDescriptor : public ComponentDescriptor { RawPropsParser &&rawPropsParser = {}) : ComponentDescriptor(parameters, std::move(rawPropsParser)) { - rawPropsParser_.prepare(); + // The parser's `keys_` / `nameToIndex_` are only consumed by + // `RawProps::at()`, which is reached exclusively through the classic + // per-field `convertRawProp` path. When `ConcreteProps` opts into the + // iterator-setter path and the runtime flag is on, `parse()` is never + // called, so the O(n²) preparation here is wasted. Skip it. + if constexpr (HasIteratorSetterCtor) { + if (!ReactNativeFeatureFlags::enableCppPropsIteratorSetter()) { + rawPropsParser_.prepare(); + } + } else { + rawPropsParser_.prepare(); + } } ComponentHandle getComponentHandle() const override