diff --git a/ReactCommon/react/renderer/core/RawValue.h b/ReactCommon/react/renderer/core/RawValue.h index c69f9e43ceacde..d541f11a16ed9d 100644 --- a/ReactCommon/react/renderer/core/RawValue.h +++ b/ReactCommon/react/renderer/core/RawValue.h @@ -96,7 +96,7 @@ class RawValue { * Casts the value to a specified type. */ template - explicit operator T() const { + explicit operator T() const noexcept { return castValue(dynamic_, (T *)nullptr); } @@ -212,36 +212,40 @@ class RawValue { return RawValue(dynamic); } - static bool castValue(const folly::dynamic &dynamic, bool *type) { + static bool castValue(const folly::dynamic &dynamic, bool *type) noexcept { return dynamic.getBool(); } - static int castValue(const folly::dynamic &dynamic, int *type) { + static int castValue(const folly::dynamic &dynamic, int *type) noexcept { return static_cast(dynamic.asInt()); } - static int64_t castValue(const folly::dynamic &dynamic, int64_t *type) { + static int64_t castValue( + const folly::dynamic &dynamic, + int64_t *type) noexcept { return dynamic.asInt(); } - static float castValue(const folly::dynamic &dynamic, float *type) { + static float castValue(const folly::dynamic &dynamic, float *type) noexcept { return static_cast(dynamic.asDouble()); } - static double castValue(const folly::dynamic &dynamic, double *type) { + static double castValue( + const folly::dynamic &dynamic, + double *type) noexcept { return dynamic.asDouble(); } static std::string castValue( const folly::dynamic &dynamic, - std::string *type) { + std::string *type) noexcept { return dynamic.getString(); } template static std::vector castValue( const folly::dynamic &dynamic, - std::vector *type) { + std::vector *type) noexcept { react_native_assert(dynamic.isArray()); auto result = std::vector{}; result.reserve(dynamic.size()); @@ -254,7 +258,7 @@ class RawValue { template static std::vector> castValue( const folly::dynamic &dynamic, - std::vector> *type) { + std::vector> *type) noexcept { react_native_assert(dynamic.isArray()); auto result = std::vector>{}; result.reserve(dynamic.size()); @@ -267,7 +271,7 @@ class RawValue { template static butter::map castValue( const folly::dynamic &dynamic, - butter::map *type) { + butter::map *type) noexcept { react_native_assert(dynamic.isObject()); auto result = butter::map{}; for (const auto &item : dynamic.items()) { diff --git a/ReactCommon/react/renderer/core/propsConversions.h b/ReactCommon/react/renderer/core/propsConversions.h index c4221f977567f9..adbc07860736a0 100644 --- a/ReactCommon/react/renderer/core/propsConversions.h +++ b/ReactCommon/react/renderer/core/propsConversions.h @@ -10,9 +10,9 @@ #include #include +#include #include #include -#include #include #include #include @@ -43,18 +43,18 @@ template void fromRawValue( const PropsParserContext &context, RawValue const &rawValue, - T &result) { - result = (T)rawValue; + std::optional &result) { + T res{}; + fromRawValue(context, rawValue, res); + result = std::optional(res); } template void fromRawValue( const PropsParserContext &context, RawValue const &rawValue, - std::optional &result) { - T resultValue; - fromRawValue(context, rawValue, resultValue); - result = std::optional{std::move(resultValue)}; + T &result) { + result = (T)rawValue; } template @@ -119,6 +119,7 @@ T convertRawProp( char const *namePrefix = nullptr, char const *nameSuffix = nullptr) { const auto *rawValue = rawProps.at(name, namePrefix, nameSuffix); + if (LIKELY(rawValue == nullptr)) { return sourceValue; } @@ -129,18 +130,35 @@ T convertRawProp( return defaultValue; } - try { - T result; - fromRawValue(context, *rawValue, result); - return result; - } catch (const std::exception &e) { - // In case of errors, log the error and fall back to the default - RawPropsKey key{namePrefix, name, nameSuffix}; - // TODO: report this using ErrorUtils so it's more visible to the user - LOG(ERROR) << "Error while converting prop '" - << static_cast(key) << "': " << e.what(); + T result; + fromRawValue(context, *rawValue, result); + return result; +} + +template +static std::optional convertRawProp( + const PropsParserContext &context, + RawProps const &rawProps, + char const *name, + std::optional const &sourceValue, + std::optional const &defaultValue, + char const *namePrefix = nullptr, + char const *nameSuffix = nullptr) { + const auto *rawValue = rawProps.at(name, namePrefix, nameSuffix); + + if (LIKELY(rawValue == nullptr)) { + return sourceValue; + } + + // Special case: `null` always means `the prop was removed, use default + // value`. + if (UNLIKELY(!rawValue->hasValue())) { return defaultValue; } + + T result; + fromRawValue(context, *rawValue, result); + return std::optional{result}; } } // namespace react