From 1def9fdbc99b1caaf87936c231d208cb906e85a4 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Tue, 4 Feb 2025 21:51:21 -0800 Subject: [PATCH] Allow parsing lists of compound data types (#49188) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/49188 This allows creating lists of a compound data type, storing each element as a variant of the possible types, instead of as the specified type. Changelog: [Internal] Reviewed By: lenaic Differential Revision: D69142157 fbshipit-source-id: d742d81a6517b24f24827727cd777550f2ad274f --- .../react/renderer/css/CSSCompoundDataType.h | 6 +++- .../ReactCommon/react/renderer/css/CSSList.h | 36 +++++++++++++++---- .../react/renderer/css/tests/CSSListTest.cpp | 20 +++++++++++ 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/css/CSSCompoundDataType.h b/packages/react-native/ReactCommon/react/renderer/css/CSSCompoundDataType.h index 58abadc1898..51c2e09b501 100644 --- a/packages/react-native/ReactCommon/react/renderer/css/CSSCompoundDataType.h +++ b/packages/react-native/ReactCommon/react/renderer/css/CSSCompoundDataType.h @@ -21,13 +21,17 @@ struct CSSCompoundDataTypeMarker {}; template struct CSSCompoundDataType : public detail::CSSCompoundDataTypeMarker {}; +template +concept CSSValidCompoundDataType = + std::is_base_of_v; + /** * A concrete data type, or a compound data type which represents multiple other * data types. */ template concept CSSMaybeCompoundDataType = - CSSDataType || std::is_base_of_v; + CSSDataType || CSSValidCompoundDataType; namespace detail { diff --git a/packages/react-native/ReactCommon/react/renderer/css/CSSList.h b/packages/react-native/ReactCommon/react/renderer/css/CSSList.h index ff5582f75ed..99c5cb9d860 100644 --- a/packages/react-native/ReactCommon/react/renderer/css/CSSList.h +++ b/packages/react-native/ReactCommon/react/renderer/css/CSSList.h @@ -8,17 +8,26 @@ #pragma once #include +#include #include +#include #include #include namespace facebook::react { -template -struct CSSList : public std::vector {}; +template +struct CSSList; template +struct CSSList : public std::vector {}; + +template +struct CSSList + : public std::vector> {}; + +template struct CSSDataTypeParser> { static inline auto consume(CSSSyntaxParser& parser) -> std::optional> { @@ -26,7 +35,18 @@ struct CSSDataTypeParser> { for (auto nextValue = parseNextCSSValue(parser); !std::holds_alternative(nextValue); nextValue = parseNextCSSValue(parser, Delim)) { - result.push_back(std::move(std::get(nextValue))); + // Copy from the variant of possible values to the element (either the + // concrete type, or a variant of compound types which exlcudes the + // possibility of std::monostate for parse error) + std::visit( + [&](auto&& v) { + if constexpr (!std::is_same_v< + std::remove_cvref_t, + std::monostate>) { + result.push_back(std::forward(v)); + } + }, + nextValue); } if (result.empty()) { @@ -38,17 +58,19 @@ struct CSSDataTypeParser> { }; /** - * Represents a comma-separated repetition of a given single type. + * Represents a comma-separated repetition of a single type, or compound type + * (represented as a variant of possible types). * https://www.w3.org/TR/css-values-4/#mult-comma */ -template +template using CSSCommaSeparatedList = CSSList; /** - * Represents a whitespace-separated repetition of a given single type. + * Represents a whitespace-separated repetition of a single type, or compound + * type (represented as a variant of possible types). * https://www.w3.org/TR/css-values-4/#component-combinators */ -template +template using CSSWhitespaceSeparatedList = CSSList; diff --git a/packages/react-native/ReactCommon/react/renderer/css/tests/CSSListTest.cpp b/packages/react-native/ReactCommon/react/renderer/css/tests/CSSListTest.cpp index 599f48967b7..b622dcd2821 100644 --- a/packages/react-native/ReactCommon/react/renderer/css/tests/CSSListTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/css/tests/CSSListTest.cpp @@ -6,6 +6,8 @@ */ #include +#include +#include #include #include #include @@ -130,4 +132,22 @@ TEST(CSSList, extra_commas) { EXPECT_TRUE(std::holds_alternative(suffixCommaValue)); } +TEST(CSSList, compound_data_type) { + using NumberLengthList = + CSSCommaSeparatedList>; + + auto compoundType = parseCSSProperty("10px,20"); + + EXPECT_TRUE(std::holds_alternative(compoundType)); + auto& list = std::get(compoundType); + + EXPECT_EQ(list.size(), 2); + EXPECT_TRUE(std::holds_alternative(list[0])); + EXPECT_EQ(std::get(list[0]).value, 10); + EXPECT_EQ(std::get(list[0]).unit, CSSLengthUnit::Px); + + EXPECT_TRUE(std::holds_alternative(list[1])); + EXPECT_EQ(std::get(list[1]).value, 20); +} + } // namespace facebook::react