Skip to content

Commit 743de70

Browse files
NickGerlemanfacebook-github-bot
authored andcommitted
Add CSSComponentValueDelimiter::CommaOrWhitespace (#48769)
Summary: Pull Request resolved: #48769 Must function notations do not require delimiting commas, with color function "legacy" syntax being an exception. E.g. ``` rgb() = [ <legacy-rgb-syntax> | <modern-rgb-syntax> ] rgba() = [ <legacy-rgba-syntax> | <modern-rgba-syntax> ] <legacy-rgb-syntax> = rgb( <percentage>#{3} , <alpha-value>? ) | rgb( <number>#{3} , <alpha-value>? ) <legacy-rgba-syntax> = rgba( <percentage>#{3} , <alpha-value>? ) | rgba( <number>#{3} , <alpha-value>? ) <modern-rgb-syntax> = rgb( [ <number> | <percentage> | none]{3} [ / [<alpha-value> | none] ]? ) <modern-rgba-syntax> = rgba( [ <number> | <percentage> | none]{3} [ / [<alpha-value> | none] ]? ) ``` Theoretically, this should mean an expression like `rgb(1, 2 0)`, which mixes both comma and whitespace delimeters would be malformed, but both Chrome, and RN's existing `normalize-color` package support this, so to make this pattern easier, we add the ability to scan based on using either whitespace or comma as component value delimiter. Interestingly, the current spec revision also allows `rgb` function with alpha, or `rgba` function without alpha, which Chrome correctly supports, but `normalize-color` does not. Changelog: [Internal] Reviewed By: joevilches Differential Revision: D68349385 fbshipit-source-id: 05cd756ee20227af4d9ec20edc9e7cfc8cc2c071
1 parent c33dd62 commit 743de70

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

packages/react-native/ReactCommon/react/renderer/css/CSSSyntaxParser.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ concept CSSUniqueComponentValueVisitors =
9393
enum class CSSComponentValueDelimiter {
9494
Comma,
9595
Whitespace,
96+
CommaOrWhitespace,
9697
None,
9798
};
9899

@@ -212,6 +213,13 @@ struct CSSComponentValueVisitorDispatcher {
212213
case CSSComponentValueDelimiter::Whitespace:
213214
parser.consumeWhitespace();
214215
break;
216+
case CSSComponentValueDelimiter::CommaOrWhitespace:
217+
parser.consumeWhitespace();
218+
if (parser.peek().type() == CSSTokenType::Comma) {
219+
parser.consumeToken();
220+
}
221+
parser.consumeWhitespace();
222+
break;
215223
case CSSComponentValueDelimiter::None:
216224
break;
217225
}

packages/react-native/ReactCommon/react/renderer/css/tests/CSSSyntaxParserTest.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,52 @@ TEST(CSSSyntaxParser, single_function_with_comma_delimited_args) {
155155
EXPECT_EQ(funcArgs, expectedArgs);
156156
}
157157

158+
TEST(CSSSyntaxParser, single_function_with_mixed_delimited_args) {
159+
CSSSyntaxParser parser{"rgb(100, 200 50 )"};
160+
161+
auto funcArgs = parser.consumeComponentValue<std::array<uint8_t, 3>>(
162+
[&](const CSSFunctionBlock& function, CSSSyntaxParser& blockParser) {
163+
EXPECT_EQ(function.name, "rgb");
164+
165+
std::array<uint8_t, 3> rgb{};
166+
167+
rgb[0] = blockParser.consumeComponentValue<uint8_t>(
168+
CSSComponentValueDelimiter::None,
169+
[](const CSSPreservedToken& token) {
170+
EXPECT_EQ(token.type(), CSSTokenType::Number);
171+
EXPECT_EQ(token.numericValue(), 100);
172+
return static_cast<uint8_t>(token.numericValue());
173+
});
174+
175+
rgb[1] = blockParser.consumeComponentValue<uint8_t>(
176+
CSSComponentValueDelimiter::CommaOrWhitespace,
177+
[](const CSSPreservedToken& token) {
178+
EXPECT_EQ(token.type(), CSSTokenType::Number);
179+
EXPECT_EQ(token.numericValue(), 200);
180+
return static_cast<uint8_t>(token.numericValue());
181+
});
182+
183+
rgb[2] = blockParser.consumeComponentValue<uint8_t>(
184+
CSSComponentValueDelimiter::CommaOrWhitespace,
185+
[](const CSSPreservedToken& token) {
186+
EXPECT_EQ(token.type(), CSSTokenType::Number);
187+
EXPECT_EQ(token.numericValue(), 50);
188+
return static_cast<uint8_t>(token.numericValue());
189+
});
190+
191+
auto hasMoreTokens = blockParser.consumeComponentValue<bool>(
192+
CSSComponentValueDelimiter::Whitespace,
193+
[](const CSSPreservedToken& /*token*/) { return true; });
194+
195+
EXPECT_FALSE(hasMoreTokens);
196+
197+
return rgb;
198+
});
199+
200+
std::array<uint8_t, 3> expectedArgs{{100, 200, 50}};
201+
EXPECT_EQ(funcArgs, expectedArgs);
202+
}
203+
158204
TEST(CSSSyntaxParser, complex) {
159205
CSSSyntaxParser parser{"foo(a bar())baz() 12px"};
160206

0 commit comments

Comments
 (0)