Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace facebook::react {

static bool
hasValue(const RawProps& rawProps, bool defaultValue, const char* name) {
auto rawValue = rawProps.at(name, nullptr, nullptr);
auto rawValue = rawProps.at(name);

// No change to prop - use default
if (rawValue == nullptr) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,8 @@ AccessibilityProps::AccessibilityProps(
role = sourceProps.role;
accessibilityTraits = sourceProps.accessibilityTraits;
} else {
auto* accessibilityRoleValue =
rawProps.at("accessibilityRole", nullptr, nullptr);
auto* roleValue = rawProps.at("role", nullptr, nullptr);
auto* accessibilityRoleValue = rawProps.at("accessibilityRole");
auto* roleValue = rawProps.at("role");

auto* precedentRoleValue =
roleValue != nullptr ? roleValue : accessibilityRoleValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,20 @@ BaseViewProps::BaseViewProps(
: convertRawProp(
context,
rawProps,
"border",
"Radius",
CascadedRectangleCornersNames{
.topLeft = "borderTopLeftRadius",
.topRight = "borderTopRightRadius",
.bottomLeft = "borderBottomLeftRadius",
.bottomRight = "borderBottomRightRadius",
.topStart = "borderTopStartRadius",
.topEnd = "borderTopEndRadius",
.bottomStart = "borderBottomStartRadius",
.bottomEnd = "borderBottomEndRadius",
.endEnd = "borderEndEndRadius",
.endStart = "borderEndStartRadius",
.startEnd = "borderStartEndRadius",
.startStart = "borderStartStartRadius",
.all = "borderRadius"},
sourceProps.borderRadii,
{})),
borderColors(
Expand All @@ -94,8 +106,19 @@ BaseViewProps::BaseViewProps(
: convertRawProp(
context,
rawProps,
"border",
"Color",
CascadedRectangleEdgesNames{
.left = "borderLeftColor",
.right = "borderRightColor",
.top = "borderTopColor",
.bottom = "borderBottomColor",
.start = "borderStartColor",
.end = "borderEndColor",
.horizontal = "borderHorizontalColor",
.vertical = "borderVerticalColor",
.block = "borderBlockColor",
.blockEnd = "borderBlockEndColor",
.blockStart = "borderBlockStartColor",
.all = "borderColor"},
sourceProps.borderColors,
{})),
borderCurves(
Expand All @@ -104,8 +127,20 @@ BaseViewProps::BaseViewProps(
: convertRawProp(
context,
rawProps,
"border",
"Curve",
CascadedRectangleCornersNames{
.topLeft = "borderTopLeftCurve",
.topRight = "borderTopRightCurve",
.bottomLeft = "borderBottomLeftCurve",
.bottomRight = "borderBottomRightCurve",
.topStart = "borderTopStartCurve",
.topEnd = "borderTopEndCurve",
.bottomStart = "borderBottomStartCurve",
.bottomEnd = "borderBottomEndCurve",
.endEnd = "borderEndEndCurve",
.endStart = "borderEndStartCurve",
.startEnd = "borderStartEndCurve",
.startStart = "borderStartStartCurve",
.all = "borderCurve"},
sourceProps.borderCurves,
{})),
borderStyles(
Expand All @@ -114,8 +149,19 @@ BaseViewProps::BaseViewProps(
: convertRawProp(
context,
rawProps,
"border",
"Style",
CascadedRectangleEdgesNames{
.left = "borderLeftStyle",
.right = "borderRightStyle",
.top = "borderTopStyle",
.bottom = "borderBottomStyle",
.start = "borderStartStyle",
.end = "borderEndStyle",
.horizontal = "borderHorizontalStyle",
.vertical = "borderVerticalStyle",
.block = "borderBlockStyle",
.blockEnd = "borderBlockEndStyle",
.blockStart = "borderBlockStartStyle",
.all = "borderStyle"},
sourceProps.borderStyles,
{})),
outlineColor(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ convertRawProp(const PropsParserContext &context, const RawProps &rawProps, cons
convertRawProp(context, rawProps, "maxHeight", sourceValue.maxDimension(yoga::Dimension::Height), {}));

{
const auto *rawValue = rawProps.at("aspectRatio", nullptr, nullptr);
const auto *rawValue = rawProps.at("aspectRatio");
if (rawValue != nullptr) {
yogaStyle.setAspectRatio(rawValue->hasValue() ? convertAspectRatio(context, *rawValue) : yogaStyle.aspectRatio());
} else {
Expand All @@ -371,43 +371,67 @@ convertRawProp(const PropsParserContext &context, const RawProps &rawProps, cons
return yogaStyle;
}

struct CascadedRectangleCornersNames {
const char *topLeft;
const char *topRight;
const char *bottomLeft;
const char *bottomRight;
const char *topStart;
const char *topEnd;
const char *bottomStart;
const char *bottomEnd;
const char *endEnd;
const char *endStart;
const char *startEnd;
const char *startStart;
const char *all;
};

struct CascadedRectangleEdgesNames {
const char *left;
const char *right;
const char *top;
const char *bottom;
const char *start;
const char *end;
const char *horizontal;
const char *vertical;
const char *block;
const char *blockEnd;
const char *blockStart;
const char *all;
};

// This can be deleted when non-iterator ViewProp parsing is deleted
template <typename T>
static inline CascadedRectangleCorners<T> convertRawProp(
const PropsParserContext &context,
const RawProps &rawProps,
const char *prefix,
const char *suffix,
const CascadedRectangleCornersNames &names,
const CascadedRectangleCorners<T> &sourceValue,
const CascadedRectangleCorners<T> &defaultValue)
{
CascadedRectangleCorners<T> result;

result.topLeft =
convertRawProp(context, rawProps, "TopLeft", sourceValue.topLeft, defaultValue.topLeft, prefix, suffix);
result.topRight =
convertRawProp(context, rawProps, "TopRight", sourceValue.topRight, defaultValue.topRight, prefix, suffix);
result.topLeft = convertRawProp(context, rawProps, names.topLeft, sourceValue.topLeft, defaultValue.topLeft);
result.topRight = convertRawProp(context, rawProps, names.topRight, sourceValue.topRight, defaultValue.topRight);
result.bottomLeft =
convertRawProp(context, rawProps, "BottomLeft", sourceValue.bottomLeft, defaultValue.bottomLeft, prefix, suffix);
result.bottomRight = convertRawProp(
context, rawProps, "BottomRight", sourceValue.bottomRight, defaultValue.bottomRight, prefix, suffix);

result.topStart =
convertRawProp(context, rawProps, "TopStart", sourceValue.topStart, defaultValue.topStart, prefix, suffix);
result.topEnd = convertRawProp(context, rawProps, "TopEnd", sourceValue.topEnd, defaultValue.topEnd, prefix, suffix);
result.bottomStart = convertRawProp(
context, rawProps, "BottomStart", sourceValue.bottomStart, defaultValue.bottomStart, prefix, suffix);
result.bottomEnd =
convertRawProp(context, rawProps, "BottomEnd", sourceValue.bottomEnd, defaultValue.bottomEnd, prefix, suffix);
result.endEnd = convertRawProp(context, rawProps, "EndEnd", sourceValue.endEnd, defaultValue.endEnd, prefix, suffix);
result.endStart =
convertRawProp(context, rawProps, "EndStart", sourceValue.endStart, defaultValue.endStart, prefix, suffix);
result.startEnd =
convertRawProp(context, rawProps, "StartEnd", sourceValue.startEnd, defaultValue.startEnd, prefix, suffix);
convertRawProp(context, rawProps, names.bottomLeft, sourceValue.bottomLeft, defaultValue.bottomLeft);
result.bottomRight =
convertRawProp(context, rawProps, names.bottomRight, sourceValue.bottomRight, defaultValue.bottomRight);

result.topStart = convertRawProp(context, rawProps, names.topStart, sourceValue.topStart, defaultValue.topStart);
result.topEnd = convertRawProp(context, rawProps, names.topEnd, sourceValue.topEnd, defaultValue.topEnd);
result.bottomStart =
convertRawProp(context, rawProps, names.bottomStart, sourceValue.bottomStart, defaultValue.bottomStart);
result.bottomEnd = convertRawProp(context, rawProps, names.bottomEnd, sourceValue.bottomEnd, defaultValue.bottomEnd);
result.endEnd = convertRawProp(context, rawProps, names.endEnd, sourceValue.endEnd, defaultValue.endEnd);
result.endStart = convertRawProp(context, rawProps, names.endStart, sourceValue.endStart, defaultValue.endStart);
result.startEnd = convertRawProp(context, rawProps, names.startEnd, sourceValue.startEnd, defaultValue.startEnd);
result.startStart =
convertRawProp(context, rawProps, "StartStart", sourceValue.startStart, defaultValue.startStart, prefix, suffix);
convertRawProp(context, rawProps, names.startStart, sourceValue.startStart, defaultValue.startStart);

result.all = convertRawProp(context, rawProps, "", sourceValue.all, defaultValue.all, prefix, suffix);
result.all = convertRawProp(context, rawProps, names.all, sourceValue.all, defaultValue.all);

return result;
}
Expand All @@ -416,31 +440,28 @@ template <typename T>
static inline CascadedRectangleEdges<T> convertRawProp(
const PropsParserContext &context,
const RawProps &rawProps,
const char *prefix,
const char *suffix,
const CascadedRectangleEdgesNames &names,
const CascadedRectangleEdges<T> &sourceValue,
const CascadedRectangleEdges<T> &defaultValue)
{
CascadedRectangleEdges<T> result;

result.left = convertRawProp(context, rawProps, "Left", sourceValue.left, defaultValue.left, prefix, suffix);
result.right = convertRawProp(context, rawProps, "Right", sourceValue.right, defaultValue.right, prefix, suffix);
result.top = convertRawProp(context, rawProps, "Top", sourceValue.top, defaultValue.top, prefix, suffix);
result.bottom = convertRawProp(context, rawProps, "Bottom", sourceValue.bottom, defaultValue.bottom, prefix, suffix);
result.left = convertRawProp(context, rawProps, names.left, sourceValue.left, defaultValue.left);
result.right = convertRawProp(context, rawProps, names.right, sourceValue.right, defaultValue.right);
result.top = convertRawProp(context, rawProps, names.top, sourceValue.top, defaultValue.top);
result.bottom = convertRawProp(context, rawProps, names.bottom, sourceValue.bottom, defaultValue.bottom);

result.start = convertRawProp(context, rawProps, "Start", sourceValue.start, defaultValue.start, prefix, suffix);
result.end = convertRawProp(context, rawProps, "End", sourceValue.end, defaultValue.end, prefix, suffix);
result.start = convertRawProp(context, rawProps, names.start, sourceValue.start, defaultValue.start);
result.end = convertRawProp(context, rawProps, names.end, sourceValue.end, defaultValue.end);
result.horizontal =
convertRawProp(context, rawProps, "Horizontal", sourceValue.horizontal, defaultValue.horizontal, prefix, suffix);
result.vertical =
convertRawProp(context, rawProps, "Vertical", sourceValue.vertical, defaultValue.vertical, prefix, suffix);
result.block = convertRawProp(context, rawProps, "Block", sourceValue.block, defaultValue.block, prefix, suffix);
result.blockEnd =
convertRawProp(context, rawProps, "BlockEnd", sourceValue.blockEnd, defaultValue.blockEnd, prefix, suffix);
convertRawProp(context, rawProps, names.horizontal, sourceValue.horizontal, defaultValue.horizontal);
result.vertical = convertRawProp(context, rawProps, names.vertical, sourceValue.vertical, defaultValue.vertical);
result.block = convertRawProp(context, rawProps, names.block, sourceValue.block, defaultValue.block);
result.blockEnd = convertRawProp(context, rawProps, names.blockEnd, sourceValue.blockEnd, defaultValue.blockEnd);
result.blockStart =
convertRawProp(context, rawProps, "BlockStart", sourceValue.blockStart, defaultValue.blockStart, prefix, suffix);
convertRawProp(context, rawProps, names.blockStart, sourceValue.blockStart, defaultValue.blockStart);

result.all = convertRawProp(context, rawProps, "", sourceValue.all, defaultValue.all, prefix, suffix);
result.all = convertRawProp(context, rawProps, names.all, sourceValue.all, defaultValue.all);

return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<ConcreteProps>;
const bool useIteratorSetter = kSupportsIteratorSetter && ReactNativeFeatureFlags::enableCppPropsIteratorSetter();

std::shared_ptr<ConcreteProps> 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() &&
Expand All @@ -134,19 +155,23 @@ 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()) {

if constexpr (kSupportsIteratorSetter) {
if (useIteratorSetter) {
#ifdef RN_SERIALIZABLE_STATE
const auto &dynamic =
fallbackToDynamicRawPropsAccumulation ? shadowNodeProps->rawProps : static_cast<folly::dynamic>(rawProps);
#else
const auto &dynamic = static_cast<folly::dynamic>(rawProps);
if (fallbackToDynamicRawPropsAccumulation) {
// Accumulation already merged the source's rawProps with the input;
// iterate the merged dynamic so setProp sees the unioned set.
for (const auto &pair : shadowNodeProps->rawProps.items()) {
const auto &name = pair.first.getString();
shadowNodeProps->setProp(context, RAW_PROPS_KEY_HASH(name), name.c_str(), RawValue(pair.second));
}
return shadowNodeProps;
}
#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));
rawProps.forEachItem([&](const char *name, const RawValue &value) {
shadowNodeProps->setProp(context, RAW_PROPS_KEY_HASH(name), name, value);
});
}
}
return shadowNodeProps;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,32 @@ 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)
{
return std::make_shared<PropsT>(
context, baseProps ? static_cast<const PropsT &>(*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<PropsT>(baseProps ? static_cast<const PropsT &>(*baseProps) : *defaultSharedProps());
}

#ifdef RN_SERIALIZABLE_STATE
static void initializeDynamicProps(
UnsharedConcreteProps props,
Expand Down
Loading
Loading