Skip to content
Permalink
Browse files
[@Property] Parse identifier list syntax
https://bugs.webkit.org/show_bug.cgi?id=249161
<rdar://problem/103262360>

Reviewed by Alan Baradlay.

* LayoutTests/imported/w3c/web-platform-tests/css/css-properties-values-api/register-property-syntax-parsing-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/css/css-properties-values-api/typedom-expected.txt:
* Source/WebCore/css/parser/CSSPropertySyntax.cpp:
(WebCore::CSSPropertySyntax::parseComponent):

Allow ident+ and ident# syntax.

(WebCore::CSSPropertySyntax::parse):
(WebCore::CSSPropertySyntax::typeForTypeName):

Factor into a function.

* Source/WebCore/css/parser/CSSPropertySyntax.h:

Canonical link: https://commits.webkit.org/257786@main
  • Loading branch information
anttijk committed Dec 13, 2022
1 parent beacee6 commit 009a0ee1bc61a302f337561e47ef1458f0d6a462
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 48 deletions.
@@ -65,7 +65,7 @@ PASS syntax:'banana', initialValue:'banan\61' is valid
PASS syntax:'banan\61', initialValue:'banana' is valid
PASS syntax:'<custom-ident>', initialValue:'banan\61' is valid
PASS syntax:'big | bigger | BIGGER', initialValue:'bigger' is valid
FAIL syntax:'foo+|bar', initialValue:'foo foo foo' is valid Invalid property syntax definition.
FAIL syntax:'foo+|bar', initialValue:'foo foo foo' is valid The given initial value does not parse for the given syntax.
PASS syntax:'banana ', initialValue:'banana' is valid
PASS syntax:'
banana\r
@@ -193,8 +193,8 @@ PASS CSSUnitValue rejected by set() for syntax <length># [attributeStyleMap]
PASS CSSUnitValue rejected by set() for syntax <length># [styleMap]
PASS Appending a string to * is not allowed [attributeStyleMap]
PASS Appending a string to * is not allowed [styleMap]
FAIL Appending a string to foo+ is not allowed [attributeStyleMap] Invalid property syntax definition.
FAIL Appending a string to foo+ is not allowed [styleMap] Invalid property syntax definition.
PASS Appending a string to foo+ is not allowed [attributeStyleMap]
PASS Appending a string to foo+ is not allowed [styleMap]
PASS Appending a string to <angle>+ is not allowed [attributeStyleMap]
PASS Appending a string to <angle>+ is not allowed [styleMap]
PASS Appending a string to <color>+ is not allowed [attributeStyleMap]
@@ -227,8 +227,8 @@ PASS Appending a string to <length># is not allowed [attributeStyleMap]
PASS Appending a string to <length># is not allowed [styleMap]
PASS Appending a CSSKeywordValue to * is not allowed [attributeStyleMap]
PASS Appending a CSSKeywordValue to * is not allowed [styleMap]
FAIL Appending a CSSKeywordValue to foo+ is not allowed [attributeStyleMap] Invalid property syntax definition.
FAIL Appending a CSSKeywordValue to foo+ is not allowed [styleMap] Invalid property syntax definition.
PASS Appending a CSSKeywordValue to foo+ is not allowed [attributeStyleMap]
PASS Appending a CSSKeywordValue to foo+ is not allowed [styleMap]
PASS Appending a CSSUnitValue to <angle>+ is not allowed [attributeStyleMap]
PASS Appending a CSSUnitValue to <angle>+ is not allowed [styleMap]
PASS Appending a CSSKeywordValue to <custom-ident>+ is not allowed [attributeStyleMap]
@@ -34,6 +34,14 @@ namespace WebCore {
template<typename CharacterType>
auto CSSPropertySyntax::parseComponent(StringParsingBuffer<CharacterType> buffer) -> std::optional<Component>
{
auto consumeMultiplier = [&] {
if (skipExactly(buffer, '+'))
return Multiplier::SpaceList;
if (skipExactly(buffer, '#'))
return Multiplier::CommaList;
return Multiplier::Single;
};

if (skipExactly(buffer, '<')) {
auto begin = buffer.position();
skipUntil(buffer, '>');
@@ -44,64 +52,45 @@ auto CSSPropertySyntax::parseComponent(StringParsingBuffer<CharacterType> buffer
if (!skipExactly(buffer, '>'))
return { };

auto multiplier = [&] {
if (skipExactly(buffer, '+'))
return Multiplier::SpaceList;
if (skipExactly(buffer, '#'))
return Multiplier::CommaList;
return Multiplier::Single;
}();
auto multiplier = consumeMultiplier();

skipWhile<isCSSSpace>(buffer);
if (!buffer.atEnd())
return { };

if (dataTypeName == "length"_s)
return Component { Type::Length, multiplier };
if (dataTypeName == "length-percentage"_s)
return Component { Type::LengthPercentage, multiplier };
if (dataTypeName == "custom-ident"_s)
return Component { Type::CustomIdent, multiplier };
if (dataTypeName == "percentage"_s)
return Component { Type::Percentage, multiplier };
if (dataTypeName == "integer"_s)
return Component { Type::Integer, multiplier };
if (dataTypeName == "number"_s)
return Component { Type::Number, multiplier };
if (dataTypeName == "angle"_s)
return Component { Type::Angle, multiplier };
if (dataTypeName == "time"_s)
return Component { Type::Time, multiplier };
if (dataTypeName == "resolution"_s)
return Component { Type::Resolution, multiplier };
if (dataTypeName == "color"_s)
return Component { Type::Color, multiplier };
if (dataTypeName == "image"_s)
return Component { Type::Image, multiplier };
if (dataTypeName == "url"_s)
return Component { Type::URL, multiplier };

return Component { Type::Unknown, multiplier };
auto type = typeForTypeName(dataTypeName);
return Component { type, multiplier };
}

auto tokenizer = CSSTokenizer::tryCreate(buffer.stringViewOfCharactersRemaining().toStringWithoutCopying());
if (!tokenizer)
return { };
auto begin = buffer.position();
while (buffer.hasCharactersRemaining() && (*buffer != '+' && *buffer != '#'))
++buffer;

auto range = tokenizer->tokenRange();
range.consumeWhitespace();
if (range.peek().type() != IdentToken || !isValidCustomIdentifier(range.peek().id()))
return { };
auto ident = [&] {
auto tokenizer = CSSTokenizer::tryCreate(StringView(begin, buffer.position() - begin).toStringWithoutCopying());
if (!tokenizer)
return nullAtom();

auto range = tokenizer->tokenRange();
range.consumeWhitespace();
if (range.peek().type() != IdentToken || !isValidCustomIdentifier(range.peek().id()))
return nullAtom();

auto value = range.consumeIncludingWhitespace().value();
return range.atEnd() ? value.toAtomString() : nullAtom();
}();

auto ident = range.consumeIncludingWhitespace().value();
if (!range.atEnd())
if (ident.isNull())
return { };

return Component { Type::CustomIdent, Multiplier::Single, ident.toAtomString() };
auto multiplier = consumeMultiplier();

return Component { Type::CustomIdent, multiplier, ident };
}

std::optional<CSSPropertySyntax> CSSPropertySyntax::parse(StringView syntax)
{
// The format doesn't quite parse with CSSTokenizer.
return readCharactersForParsing(syntax, [&](auto buffer) -> std::optional<CSSPropertySyntax> {
skipWhile<isCSSSpace>(buffer);

@@ -137,4 +126,34 @@ std::optional<CSSPropertySyntax> CSSPropertySyntax::parse(StringView syntax)
});
}

auto CSSPropertySyntax::typeForTypeName(StringView dataTypeName) -> Type
{
if (dataTypeName == "length"_s)
return Type::Length;
if (dataTypeName == "length-percentage"_s)
return Type::LengthPercentage;
if (dataTypeName == "custom-ident"_s)
return Type::CustomIdent;
if (dataTypeName == "percentage"_s)
return Type::Percentage;
if (dataTypeName == "integer"_s)
return Type::Integer;
if (dataTypeName == "number"_s)
return Type::Number;
if (dataTypeName == "angle"_s)
return Type::Angle;
if (dataTypeName == "time"_s)
return Type::Time;
if (dataTypeName == "resolution"_s)
return Type::Resolution;
if (dataTypeName == "color"_s)
return Type::Color;
if (dataTypeName == "image"_s)
return Type::Image;
if (dataTypeName == "url"_s)
return Type::URL;

return Type::Unknown;
}

}
@@ -69,6 +69,7 @@ struct CSSPropertySyntax {

private:
template<typename CharacterType> static std::optional<Component> parseComponent(StringParsingBuffer<CharacterType>);
static Type typeForTypeName(StringView);
};

}

0 comments on commit 009a0ee

Please sign in to comment.