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/ConcreteComponentDescriptor.h b/packages/react-native/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h index 495702a08b8d..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 @@ -112,9 +123,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 +166,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/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/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/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..bf0e80e751a4 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.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; }); @@ -4126,7 +4135,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; @@ -4196,6 +4205,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 { @@ -8255,6 +8266,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); @@ -9939,6 +9951,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 a10464aed19c..bda400f6cf01 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api @@ -794,6 +794,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; }); @@ -3980,7 +3989,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; @@ -4040,6 +4049,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 { @@ -8019,6 +8030,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); @@ -9565,6 +9577,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 b357d56bfc81..1d32ac6e8199 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.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; }); @@ -4123,7 +4132,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; @@ -4193,6 +4202,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 { @@ -8246,6 +8257,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); @@ -9792,6 +9804,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 4dd76e3aa931..ec5ebfcfbd01 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api @@ -3651,6 +3651,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; }); @@ -6313,7 +6322,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; @@ -6413,6 +6422,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 { @@ -10236,6 +10247,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; @@ -11837,6 +11849,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 16e2dc5a0c80..dd4fc400ec86 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api @@ -3638,6 +3638,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; }); @@ -6195,7 +6204,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; @@ -6285,6 +6294,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 { @@ -10052,6 +10063,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; @@ -11525,6 +11537,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 48d9cc57fdb4..16d88094e2ec 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api @@ -3651,6 +3651,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; }); @@ -6310,7 +6319,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; @@ -6410,6 +6419,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 { @@ -10227,6 +10238,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; @@ -11700,6 +11712,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 e40ffd1a5777..08954c9b197f 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.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; }); @@ -2731,7 +2740,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; @@ -2778,6 +2787,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 { @@ -6345,6 +6356,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; @@ -6999,6 +7011,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 2c5d2474a718..e03820e6f920 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api @@ -403,6 +403,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; }); @@ -2625,7 +2634,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; @@ -2662,6 +2671,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 { @@ -6173,6 +6184,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; @@ -6827,6 +6839,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 8c562f2e7322..428fe8441bb7 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.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; }); @@ -2728,7 +2737,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; @@ -2775,6 +2784,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 { @@ -6336,6 +6347,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; @@ -6990,6 +7002,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);