Skip to content
Permalink
Browse files
[@Property] Support <image> and <url> syntax
https://bugs.webkit.org/show_bug.cgi?id=249088
rdar://103224027

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/registered-property-initial-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/css/css-properties-values-api/typedom-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/css/css-properties-values-api/url-resolution-expected.txt:
* Source/WebCore/css/CSSCustomPropertyValue.cpp:
(WebCore::CSSCustomPropertyValue::customCSSText const):
* Source/WebCore/css/CSSCustomPropertyValue.h:
* Source/WebCore/css/DOMCSSRegisterCustomProperty.cpp:
(WebCore::DOMCSSRegisterCustomProperty::registerProperty):

Pass the correct CSSParserContext.

* Source/WebCore/css/parser/CSSPropertyParser.cpp:
(WebCore::CSSPropertyParser::parseTypedCustomPropertyValue):
(WebCore::CSSPropertyParser::parseCustomPropertyValueWithSyntaxDefinition):
* Source/WebCore/css/parser/CSSPropertyParser.h:
* Source/WebCore/css/parser/CSSPropertySyntax.cpp:
(WebCore::CSSPropertySyntax::parseComponent):
* Source/WebCore/css/parser/CSSPropertySyntax.h:

Canonical link: https://commits.webkit.org/257701@main
  • Loading branch information
anttijk committed Dec 11, 2022
1 parent 5f7b839 commit 65a79bcd6331c1c40495abf5d7f692e3567deb1f
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 70 deletions.
@@ -55,9 +55,9 @@ FAIL syntax:'<transform-list>', initialValue:'scale(2)' is valid The given initi
FAIL syntax:'<transform-list>', initialValue:'translateX(2px) rotate(20deg)' is valid The given initial value does not parse for the given syntax.
PASS syntax:'<color>', initialValue:'rgb(12, 34, 56)' is valid
PASS syntax:'<color>', initialValue:'lightgoldenrodyellow' is valid
FAIL syntax:'<image>', initialValue:'url(a)' is valid The given initial value does not parse for the given syntax.
FAIL syntax:'<image>', initialValue:'linear-gradient(yellow, blue)' is valid The given initial value does not parse for the given syntax.
FAIL syntax:'<url>', initialValue:'url(a)' is valid The given initial value does not parse for the given syntax.
PASS syntax:'<image>', initialValue:'url(a)' is valid
PASS syntax:'<image>', initialValue:'linear-gradient(yellow, blue)' is valid
PASS syntax:'<url>', initialValue:'url(a)' is valid
PASS syntax:'banana', initialValue:'banana' is valid
PASS syntax:'bAnAnA', initialValue:'bAnAnA' is valid
PASS syntax:'ba-na-nya', initialValue:'ba-na-nya' is valid
@@ -12,7 +12,7 @@ PASS Initial value for <color> correctly computed [purple]
FAIL Initial value for <transform-function> correctly computed [rotate(42deg)] The given initial value does not parse for the given syntax.
FAIL Initial value for <transform-list> correctly computed [scale(calc(2 + 2))] The given initial value does not parse for the given syntax.
FAIL Initial value for <transform-list> correctly computed [scale(calc(2 + 1)) translateX(calc(3px + 1px))] The given initial value does not parse for the given syntax.
FAIL Initial value for <url> correctly computed [url(a)] The given initial value does not parse for the given syntax.
PASS Initial value for <url> correctly computed [url(a)]
FAIL Initial value for <url>+ correctly computed [url(a) url(a)] The given initial value does not parse for the given syntax.
PASS Initial inherited value can be substituted [purple, color]
PASS Initial non-inherited value can be substituted [pink, background-color]

Large diffs are not rendered by default.

@@ -1,20 +1,20 @@

PASS Unregistered property resolves against document (URL token)
PASS Unregistered property resolves against document (URL function)
FAIL Registered non-inherited <url> resolves against sheet (URL token) Unknown url format: none
FAIL Registered non-inherited <url> resolves against sheet (URL function) Unknown url format: none
FAIL Registered inherited <url> resolves against sheet (URL token) Unknown url format: none
FAIL Registered inherited <url> resolves against sheet (URL function) Unknown url format: none
FAIL Registered inherited <url> resolves against sheet (Child node, URL token) Unknown url format: none
FAIL Registered inherited <url> resolves against sheet (Child node, URL function) Unknown url format: none
FAIL Registered property with unregistered var reference resolves against sheet (URL token) Unknown url format: none
FAIL Registered property with unregistered var reference resolves against sheet. (URL function) Unknown url format: none
FAIL Registered property with registered var reference resolves against sheet of referenced property (URL token) Unknown url format: none
FAIL Registered property with registered var reference resolves against sheet of referenced property (URL function) Unknown url format: none
FAIL Unregistered property with registered var reference resolves against sheet of referenced property (URL token) Unknown url format: none
FAIL Unregistered property with registered var reference resolves against sheet of referenced property (URL function) Unknown url format: none
FAIL Multiple (registered) var reference resolve against respective sheets (URL token) Unknown url format: none
FAIL Multiple (registered) var reference resolve against respective sheets (URL function) Unknown url format: none
FAIL Registered UTF16BE-encoded var reference resolve against sheet (URL token) Unknown url format: none
FAIL Registered UTF16BE-encoded var reference resolve against sheet (URL function) Unknown url format: none
PASS Registered non-inherited <url> resolves against sheet (URL token)
PASS Registered non-inherited <url> resolves against sheet (URL function)
PASS Registered inherited <url> resolves against sheet (URL token)
PASS Registered inherited <url> resolves against sheet (URL function)
PASS Registered inherited <url> resolves against sheet (Child node, URL token)
PASS Registered inherited <url> resolves against sheet (Child node, URL function)
PASS Registered property with unregistered var reference resolves against sheet (URL token)
PASS Registered property with unregistered var reference resolves against sheet. (URL function)
PASS Registered property with registered var reference resolves against sheet of referenced property (URL token)
PASS Registered property with registered var reference resolves against sheet of referenced property (URL function)
PASS Unregistered property with registered var reference resolves against sheet of referenced property (URL token)
PASS Unregistered property with registered var reference resolves against sheet of referenced property (URL function)
PASS Multiple (registered) var reference resolve against respective sheets (URL token)
PASS Multiple (registered) var reference resolve against respective sheets (URL function)
PASS Registered UTF16BE-encoded var reference resolve against sheet (URL token)
PASS Registered UTF16BE-encoded var reference resolve against sheet (URL function)

@@ -70,6 +70,11 @@ String CSSCustomPropertyValue::customCSSText() const
return CSSPrimitiveValue::create(value.value, value.unitType)->cssText();
}, [&](const StyleColor& value) {
return serializationForCSS(value);
}, [&](const RefPtr<StyleImage>& value) {
// FIXME: This is not right for gradients that use `currentcolor`. There should be a way preserve it.
return value->computedStyleValue(RenderStyle::defaultStyle())->cssText();
}, [&](const String& value) {
return serializeURL(value);
});
};

@@ -30,7 +30,7 @@
#include "CSSVariableReferenceValue.h"
#include "Length.h"
#include "StyleColor.h"
#include <variant>
#include "StyleImage.h"

namespace WebCore {

@@ -44,7 +44,7 @@ class CSSCustomPropertyValue final : public CSSValue {

bool operator==(const NumericSyntaxValue&) const = default;
};
using SyntaxValue = std::variant<Length, NumericSyntaxValue, StyleColor>;
using SyntaxValue = std::variant<Length, NumericSyntaxValue, StyleColor, RefPtr<StyleImage>, String>;

using VariantValue = std::variant<std::monostate, Ref<CSSVariableReferenceValue>, CSSValueID, Ref<CSSVariableData>, SyntaxValue>;

@@ -83,6 +83,16 @@ class CSSCustomPropertyValue final : public CSSValue {
return adoptRef(*new CSSCustomPropertyValue(name, { SyntaxValue { WTFMove(color) } }));
}

static Ref<CSSCustomPropertyValue> createForImageSyntax(const AtomString& name, RefPtr<StyleImage> image)
{
return adoptRef(*new CSSCustomPropertyValue(name, { SyntaxValue { WTFMove(image) } }));
}

static Ref<CSSCustomPropertyValue> createForURLSyntax(const AtomString& name, String url)
{
return adoptRef(*new CSSCustomPropertyValue(name, { SyntaxValue { WTFMove(url) } }));
}

static Ref<CSSCustomPropertyValue> create(const CSSCustomPropertyValue& other)
{
return adoptRef(*new CSSCustomPropertyValue(other));
@@ -67,7 +67,7 @@ ExceptionOr<void> DOMCSSRegisterCustomProperty::registerProperty(Document& docum
auto parentStyle = RenderStyle::clone(*style);
Style::Builder dummyBuilder(*style, { document, parentStyle }, matchResult, { });

initialValue = CSSPropertyParser::parseTypedCustomPropertyValue(descriptor.name, descriptor.syntax, tokenizer.tokenRange(), dummyBuilder.state(), strictCSSParserContext());
initialValue = CSSPropertyParser::parseTypedCustomPropertyValue(descriptor.name, descriptor.syntax, tokenizer.tokenRange(), dummyBuilder.state(), { document });

if (!initialValue || !initialValue->isResolved())
return Exception { SyntaxError, "The given initial value does not parse for the given syntax."_s };
@@ -256,7 +256,7 @@ bool CSSPropertyParser::canParseTypedCustomPropertyValue(const String& syntax, c
return parser.canParseTypedCustomPropertyValue(syntax);
}

RefPtr<CSSCustomPropertyValue> CSSPropertyParser::parseTypedCustomPropertyValue(const AtomString& name, const String& syntax, const CSSParserTokenRange& tokens, const Style::BuilderState& builderState, const CSSParserContext& context)
RefPtr<CSSCustomPropertyValue> CSSPropertyParser::parseTypedCustomPropertyValue(const AtomString& name, const String& syntax, const CSSParserTokenRange& tokens, Style::BuilderState& builderState, const CSSParserContext& context)
{
CSSPropertyParser parser(tokens, context, nullptr, false);
RefPtr<CSSCustomPropertyValue> value = parser.parseTypedCustomPropertyValue(name, syntax, builderState);
@@ -360,6 +360,10 @@ std::pair<RefPtr<CSSValue>, CSSPropertySyntax::Type> CSSPropertyParser::parseCus
return consumeAngle(m_range, m_context.mode);
case CSSPropertySyntax::Type::Color:
return consumeColor(m_range, m_context);
case CSSPropertySyntax::Type::Image:
return consumeImage(m_range, m_context, { AllowedImageType::URLFunction, AllowedImageType::GeneratedImage });
case CSSPropertySyntax::Type::URL:
return consumeURL(m_range);
case CSSPropertySyntax::Type::Unknown:
return nullptr;
}
@@ -408,7 +412,7 @@ void CSSPropertyParser::collectParsedCustomPropertyValueDependencies(const Strin
}
}

RefPtr<CSSCustomPropertyValue> CSSPropertyParser::parseTypedCustomPropertyValue(const AtomString& name, const String& syntax, const Style::BuilderState& builderState)
RefPtr<CSSCustomPropertyValue> CSSPropertyParser::parseTypedCustomPropertyValue(const AtomString& name, const String& syntax, Style::BuilderState& builderState)
{
auto syntaxDefinition = CSSPropertySyntax::parse(syntax);
if (syntaxDefinition.isEmpty())
@@ -425,32 +429,39 @@ RefPtr<CSSCustomPropertyValue> CSSPropertyParser::parseTypedCustomPropertyValue(
if (!value)
return nullptr;

if (!is<CSSPrimitiveValue>(*value))
return nullptr;

auto& primitiveValue = downcast<CSSPrimitiveValue>(*value);
auto* primitiveValue = dynamicDowncast<CSSPrimitiveValue>(value.get());

switch (syntaxType) {
case CSSPropertySyntax::Type::Universal:
ASSERT_NOT_REACHED();
return nullptr;
case CSSPropertySyntax::Type::LengthPercentage:
case CSSPropertySyntax::Type::Length: {
auto length = Style::BuilderConverter::convertLength(builderState, primitiveValue);
auto length = Style::BuilderConverter::convertLength(builderState, *primitiveValue);
return CSSCustomPropertyValue::createForLengthSyntax(name, WTFMove(length));
}
case CSSPropertySyntax::Type::Percentage:
return CSSCustomPropertyValue::createForNumericSyntax(name, primitiveValue.doubleValue(), CSSUnitType::CSS_PERCENTAGE);
return CSSCustomPropertyValue::createForNumericSyntax(name, primitiveValue->doubleValue(), CSSUnitType::CSS_PERCENTAGE);
case CSSPropertySyntax::Type::Integer:
return CSSCustomPropertyValue::createForNumericSyntax(name, primitiveValue.intValue(), CSSUnitType::CSS_INTEGER);
return CSSCustomPropertyValue::createForNumericSyntax(name, primitiveValue->intValue(), CSSUnitType::CSS_INTEGER);
case CSSPropertySyntax::Type::Number:
return CSSCustomPropertyValue::createForNumericSyntax(name, primitiveValue.doubleValue(), CSSUnitType::CSS_NUMBER);
return CSSCustomPropertyValue::createForNumericSyntax(name, primitiveValue->doubleValue(), CSSUnitType::CSS_NUMBER);
case CSSPropertySyntax::Type::Angle:
return CSSCustomPropertyValue::createForNumericSyntax(name, primitiveValue.computeDegrees(), CSSUnitType::CSS_DEG);
return CSSCustomPropertyValue::createForNumericSyntax(name, primitiveValue->computeDegrees(), CSSUnitType::CSS_DEG);
case CSSPropertySyntax::Type::Color: {
auto color = builderState.colorFromPrimitiveValue(primitiveValue, Style::ForVisitedLink::No);
auto color = builderState.colorFromPrimitiveValue(*primitiveValue, Style::ForVisitedLink::No);
return CSSCustomPropertyValue::createForColorSyntax(name, color);
}
case CSSPropertySyntax::Type::Image: {
auto styleImage = builderState.createStyleImage(*value);
if (!styleImage)
return nullptr;
return CSSCustomPropertyValue::createForImageSyntax(name, WTFMove(styleImage));
}
case CSSPropertySyntax::Type::URL: {
auto url = m_context.completeURL(primitiveValue->stringValue());
return CSSCustomPropertyValue::createForURLSyntax(name, url.resolvedURL.string());
}
case CSSPropertySyntax::Type::CustomIdent: {
auto tokenizer = CSSTokenizer::tryCreate(value->cssText());
if (!tokenizer)
@@ -52,7 +52,7 @@ class CSSPropertyParser {
// Parses a non-shorthand CSS property
static RefPtr<CSSValue> parseSingleValue(CSSPropertyID, const CSSParserTokenRange&, const CSSParserContext&);
static bool canParseTypedCustomPropertyValue(const String& syntax, const CSSParserTokenRange&, const CSSParserContext&);
static RefPtr<CSSCustomPropertyValue> parseTypedCustomPropertyValue(const AtomString& name, const String& syntax, const CSSParserTokenRange&, const Style::BuilderState&, const CSSParserContext&);
static RefPtr<CSSCustomPropertyValue> parseTypedCustomPropertyValue(const AtomString& name, const String& syntax, const CSSParserTokenRange&, Style::BuilderState&, const CSSParserContext&);
static void collectParsedCustomPropertyValueDependencies(const String& syntax, bool isRoot, HashSet<CSSPropertyID>& dependencies, const CSSParserTokenRange&, const CSSParserContext&);

static RefPtr<CSSValue> parseCounterStyleDescriptor(CSSPropertyID, CSSParserTokenRange&, const CSSParserContext&);
@@ -66,7 +66,7 @@ class CSSPropertyParser {
RefPtr<CSSValue> parseSingleValue(CSSPropertyID, CSSPropertyID = CSSPropertyInvalid);
std::pair<RefPtr<CSSValue>, CSSPropertySyntax::Type> parseCustomPropertyValueWithSyntaxDefinition(const CSSPropertySyntax::Definition&);
bool canParseTypedCustomPropertyValue(const String& syntax);
RefPtr<CSSCustomPropertyValue> parseTypedCustomPropertyValue(const AtomString& name, const String& syntax, const Style::BuilderState&);
RefPtr<CSSCustomPropertyValue> parseTypedCustomPropertyValue(const AtomString& name, const String& syntax, Style::BuilderState&);
void collectParsedCustomPropertyValueDependencies(const String& syntax, bool isRoot, HashSet<CSSPropertyID>& dependencies);

bool inQuirksMode() const { return m_context.mode == HTMLQuirksMode; }
@@ -72,6 +72,10 @@ auto CSSPropertySyntax::parseComponent(StringParsingBuffer<CharacterType> buffer
return Component { Type::Angle, 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 };
}
@@ -40,6 +40,8 @@ class CSSPropertySyntax {
Number,
Angle,
Color,
Image,
URL,
CustomIdent,
Unknown
};

0 comments on commit 65a79bc

Please sign in to comment.