Skip to content

Commit

Permalink
Consistently assign defaults when prop parsing fails (#36163)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #36163

Changelog:
[General][Fixed] - Fix assertions in Fabric layout and transform prop parsing

Continues D43184380 by adding more graceful fallback paths to the prop parsing logic in Fabric.

Reviewed By: sammy-SC

Differential Revision: D43184994

fbshipit-source-id: 8f2bb6cdc23197a431b914b36523dce8a8af9b54
  • Loading branch information
motiz88 authored and facebook-github-bot committed Feb 15, 2023
1 parent d16c1a0 commit ee4714e
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 25 deletions.
2 changes: 1 addition & 1 deletion ReactCommon/react/renderer/attributedstring/conversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,8 @@ inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
FontVariant &result) {
react_native_expect(value.hasType<std::vector<std::string>>());
result = FontVariant::Default;
react_native_expect(value.hasType<std::vector<std::string>>());
if (value.hasType<std::vector<std::string>>()) {
auto items = std::vector<std::string>{value};
for (const auto &item : items) {
Expand Down
105 changes: 81 additions & 24 deletions ReactCommon/react/renderer/components/view/conversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,11 @@ inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
YGDirection &result) {
result = YGDirectionInherit;
react_native_expect(value.hasType<std::string>());
if (!value.hasType<std::string>()) {
return;
}
auto stringValue = (std::string)value;
if (stringValue == "inherit") {
result = YGDirectionInherit;
Expand All @@ -183,15 +187,19 @@ inline void fromRawValue(
result = YGDirectionRTL;
return;
}
LOG(FATAL) << "Could not parse YGDirection:" << stringValue;
LOG(ERROR) << "Could not parse YGDirection:" << stringValue;
react_native_expect(false);
}

inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
YGFlexDirection &result) {
result = YGFlexDirectionColumn;
react_native_expect(value.hasType<std::string>());
if (!value.hasType<std::string>()) {
return;
}
auto stringValue = (std::string)value;
if (stringValue == "row") {
result = YGFlexDirectionRow;
Expand All @@ -209,15 +217,19 @@ inline void fromRawValue(
result = YGFlexDirectionRowReverse;
return;
}
LOG(FATAL) << "Could not parse YGFlexDirection:" << stringValue;
LOG(ERROR) << "Could not parse YGFlexDirection:" << stringValue;
react_native_expect(false);
}

inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
YGJustify &result) {
result = YGJustifyFlexStart;
react_native_expect(value.hasType<std::string>());
if (!value.hasType<std::string>()) {
return;
}
auto stringValue = (std::string)value;
if (stringValue == "flex-start") {
result = YGJustifyFlexStart;
Expand All @@ -243,15 +255,19 @@ inline void fromRawValue(
result = YGJustifySpaceEvenly;
return;
}
LOG(FATAL) << "Could not parse YGJustify:" << stringValue;
LOG(ERROR) << "Could not parse YGJustify:" << stringValue;
react_native_expect(false);
}

inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
YGAlign &result) {
result = YGAlignStretch;
react_native_expect(value.hasType<std::string>());
if (!value.hasType<std::string>()) {
return;
}
auto stringValue = (std::string)value;
if (stringValue == "auto") {
result = YGAlignAuto;
Expand Down Expand Up @@ -285,15 +301,19 @@ inline void fromRawValue(
result = YGAlignSpaceAround;
return;
}
LOG(FATAL) << "Could not parse YGAlign:" << stringValue;
LOG(ERROR) << "Could not parse YGAlign:" << stringValue;
react_native_expect(false);
}

inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
YGPositionType &result) {
result = YGPositionTypeRelative;
react_native_expect(value.hasType<std::string>());
if (!value.hasType<std::string>()) {
return;
}
auto stringValue = (std::string)value;
if (stringValue == "static") {
result = YGPositionTypeStatic;
Expand All @@ -307,15 +327,19 @@ inline void fromRawValue(
result = YGPositionTypeAbsolute;
return;
}
LOG(FATAL) << "Could not parse YGPositionType:" << stringValue;
LOG(ERROR) << "Could not parse YGPositionType:" << stringValue;
react_native_expect(false);
}

inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
YGWrap &result) {
result = YGWrapNoWrap;
react_native_expect(value.hasType<std::string>());
if (!value.hasType<std::string>()) {
return;
}
auto stringValue = (std::string)value;
if (stringValue == "nowrap") {
result = YGWrapNoWrap;
Expand All @@ -329,15 +353,19 @@ inline void fromRawValue(
result = YGWrapWrapReverse;
return;
}
LOG(FATAL) << "Could not parse YGWrap:" << stringValue;
LOG(ERROR) << "Could not parse YGWrap:" << stringValue;
react_native_expect(false);
}

inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
YGOverflow &result) {
result = YGOverflowVisible;
react_native_expect(value.hasType<std::string>());
if (!value.hasType<std::string>()) {
return;
}
auto stringValue = (std::string)value;
if (stringValue == "visible") {
result = YGOverflowVisible;
Expand All @@ -351,15 +379,19 @@ inline void fromRawValue(
result = YGOverflowScroll;
return;
}
LOG(FATAL) << "Could not parse YGOverflow:" << stringValue;
LOG(ERROR) << "Could not parse YGOverflow:" << stringValue;
react_native_expect(false);
}

inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
YGDisplay &result) {
result = YGDisplayFlex;
react_native_expect(value.hasType<std::string>());
if (!value.hasType<std::string>()) {
return;
}
auto stringValue = (std::string)value;
if (stringValue == "flex") {
result = YGDisplayFlex;
Expand All @@ -369,7 +401,7 @@ inline void fromRawValue(
result = YGDisplayNone;
return;
}
LOG(FATAL) << "Could not parse YGDisplay:" << stringValue;
LOG(ERROR) << "Could not parse YGDisplay:" << stringValue;
react_native_expect(false);
}

Expand Down Expand Up @@ -432,15 +464,20 @@ inline void fromRawValue(
return;
}
}
LOG(FATAL) << "Could not parse YGFloatOptional";
LOG(ERROR) << "Could not parse YGFloatOptional";
react_native_expect(false);
}

inline Float toRadians(const RawValue &value) {
inline Float toRadians(
const RawValue &value,
std::optional<Float> defaultValue) {
if (value.hasType<Float>()) {
return (Float)value;
}
react_native_expect(value.hasType<std::string>());
if (!value.hasType<std::string>() && defaultValue.has_value()) {
return *defaultValue;
}
auto stringValue = (std::string)value;
char *suffixStart;
double num = strtod(
Expand All @@ -456,10 +493,14 @@ inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
Transform &result) {
react_native_expect(value.hasType<std::vector<RawValue>>());
auto transformMatrix = Transform{};
auto configurations = static_cast<std::vector<RawValue>>(value);
react_native_expect(value.hasType<std::vector<RawValue>>());
if (!value.hasType<std::vector<RawValue>>()) {
result = transformMatrix;
return;
}

auto configurations = static_cast<std::vector<RawValue>>(value);
for (const auto &configuration : configurations) {
if (!configuration.hasType<butter::map<std::string, RawValue>>()) {
// TODO: The following checks have to be removed after codegen is shipped.
Expand Down Expand Up @@ -487,14 +528,14 @@ inline void fromRawValue(
transformMatrix =
transformMatrix * Transform::Perspective((Float)parameters);
} else if (operation == "rotateX") {
transformMatrix =
transformMatrix * Transform::Rotate(toRadians(parameters), 0, 0);
transformMatrix = transformMatrix *
Transform::Rotate(toRadians(parameters, 0.0f), 0, 0);
} else if (operation == "rotateY") {
transformMatrix =
transformMatrix * Transform::Rotate(0, toRadians(parameters), 0);
transformMatrix = transformMatrix *
Transform::Rotate(0, toRadians(parameters, 0.0f), 0);
} else if (operation == "rotateZ" || operation == "rotate") {
transformMatrix =
transformMatrix * Transform::Rotate(0, 0, toRadians(parameters));
transformMatrix = transformMatrix *
Transform::Rotate(0, 0, toRadians(parameters, 0.0f));
} else if (operation == "scale") {
auto number = (Float)parameters;
transformMatrix =
Expand All @@ -520,10 +561,10 @@ inline void fromRawValue(
transformMatrix * Transform::Translate(0, (Float)parameters, 0);
} else if (operation == "skewX") {
transformMatrix =
transformMatrix * Transform::Skew(toRadians(parameters), 0);
transformMatrix * Transform::Skew(toRadians(parameters, 0.0f), 0);
} else if (operation == "skewY") {
transformMatrix =
transformMatrix * Transform::Skew(0, toRadians(parameters));
transformMatrix * Transform::Skew(0, toRadians(parameters, 0.0f));
}
}

Expand All @@ -534,7 +575,11 @@ inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
PointerEventsMode &result) {
result = PointerEventsMode::Auto;
react_native_expect(value.hasType<std::string>());
if (!value.hasType<std::string>()) {
return;
}
auto stringValue = (std::string)value;
if (stringValue == "auto") {
result = PointerEventsMode::Auto;
Expand All @@ -552,15 +597,19 @@ inline void fromRawValue(
result = PointerEventsMode::BoxOnly;
return;
}
LOG(FATAL) << "Could not parse PointerEventsMode:" << stringValue;
LOG(ERROR) << "Could not parse PointerEventsMode:" << stringValue;
react_native_expect(false);
}

inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
BackfaceVisibility &result) {
result = BackfaceVisibility::Auto;
react_native_expect(value.hasType<std::string>());
if (!value.hasType<std::string>()) {
return;
}
auto stringValue = (std::string)value;
if (stringValue == "auto") {
result = BackfaceVisibility::Auto;
Expand All @@ -574,15 +623,19 @@ inline void fromRawValue(
result = BackfaceVisibility::Hidden;
return;
}
LOG(FATAL) << "Could not parse BackfaceVisibility:" << stringValue;
LOG(ERROR) << "Could not parse BackfaceVisibility:" << stringValue;
react_native_expect(false);
}

inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
BorderCurve &result) {
result = BorderCurve::Circular;
react_native_expect(value.hasType<std::string>());
if (!value.hasType<std::string>()) {
return;
}
auto stringValue = (std::string)value;
if (stringValue == "circular") {
result = BorderCurve::Circular;
Expand All @@ -592,15 +645,19 @@ inline void fromRawValue(
result = BorderCurve::Continuous;
return;
}
LOG(FATAL) << "Could not parse BorderCurve:" << stringValue;
LOG(ERROR) << "Could not parse BorderCurve:" << stringValue;
react_native_expect(false);
}

inline void fromRawValue(
const PropsParserContext &context,
const RawValue &value,
BorderStyle &result) {
result = BorderStyle::Solid;
react_native_expect(value.hasType<std::string>());
if (!value.hasType<std::string>()) {
return;
}
auto stringValue = (std::string)value;
if (stringValue == "solid") {
result = BorderStyle::Solid;
Expand All @@ -614,7 +671,7 @@ inline void fromRawValue(
result = BorderStyle::Dashed;
return;
}
LOG(FATAL) << "Could not parse BorderStyle:" << stringValue;
LOG(ERROR) << "Could not parse BorderStyle:" << stringValue;
react_native_expect(false);
}

Expand Down

0 comments on commit ee4714e

Please sign in to comment.