Changeset 237347 in webkit


Ignore:
Timestamp:
Oct 22, 2018 11:10:59 PM (5 years ago)
Author:
commit-queue@webkit.org
Message:

Registered custom properties should support syntax parameter for <length> and *
https://bugs.webkit.org/show_bug.cgi?id=190039

Patch by Justin Michaud <Justin Michaud> on 2018-10-22
Reviewed by Antti Koivisto.

LayoutTests/imported/w3c:

Update WPT test results to fail in a new way.

  • web-platform-tests/css/css-properties-values-api/register-property-syntax-parsing-expected.txt:
  • web-platform-tests/css/css-properties-values-api/registered-properties-inheritance-expected.txt:
  • web-platform-tests/css/css-properties-values-api/registered-property-cssom-expected.txt:
  • web-platform-tests/css/css-properties-values-api/typedom.tentative-expected.txt:
  • web-platform-tests/css/css-properties-values-api/var-reference-registered-properties-cycles-expected.txt:
  • web-platform-tests/css/css-properties-values-api/var-reference-registered-properties-expected.txt:

Source/WebCore:

Refactor code so that:

  • All properties applied in StyleResolver::applyMatchedProperties are only applied once.
  • Custom properties are only resolved once, in StyleResolver, when they are applied to the RenderStyle. They were previously resolved every time they were referenced, and again in RenderStyle.
  • The font-size property is applied after its variable references, but before custom properties that depend on it.
  • Cycles are detected at the same time as resolution.
  • MutableStyleProperties' custom properties cannot be set from Javascript or WebKitLegacy if they do not parse for the property's type. If they contain var(--...) references, however, then they can be set because we cannot check if the references are valid from setProperty. This behaviour matches chrome, but is not documented in the spec.
  • Custom property values have more explicit resolved/unresolved state.
  • RenderStyle only ever holds resolved custom properties, and StyleResolver::CascadedProperties only holds unresolved properties.

Tests: css-custom-properties-api/crash.html

css-custom-properties-api/cycles.html
css-custom-properties-api/inline.html

  • css/CSSComputedStyleDeclaration.cpp:

(WebCore::ComputedStyleExtractor::customPropertyValue):

  • css/CSSCustomPropertyValue.cpp:

(WebCore::CSSCustomPropertyValue::equals const):
(WebCore::CSSCustomPropertyValue::customCSSText const):
(WebCore::CSSCustomPropertyValue::tokens const):
(WebCore::CSSCustomPropertyValue::checkVariablesForCycles const): Deleted.
(WebCore::CSSCustomPropertyValue::resolveVariableReferences const): Deleted.
(WebCore::CSSCustomPropertyValue::setResolvedTypedValue): Deleted.

  • css/CSSCustomPropertyValue.h:
  • css/CSSRegisteredCustomProperty.cpp:

(WebCore::CSSRegisteredCustomProperty::CSSRegisteredCustomProperty):

  • css/CSSRegisteredCustomProperty.h:
  • css/CSSStyleSheet.h:
  • css/CSSVariableData.cpp:

(WebCore::CSSVariableData::CSSVariableData):
(WebCore::CSSVariableData::consumeAndUpdateTokens): Deleted.
(WebCore::CSSVariableData::checkVariablesForCycles const): Deleted.
(WebCore::CSSVariableData::checkVariablesForCyclesWithRange const): Deleted.
(WebCore::CSSVariableData::resolveVariableFallback const): Deleted.
(WebCore::CSSVariableData::resolveVariableReference const): Deleted.
(WebCore::CSSVariableData::resolveVariableReferences const): Deleted.
(WebCore::CSSVariableData::resolveTokenRange const): Deleted.

  • css/CSSVariableData.h:

(WebCore::CSSVariableData::create):
(WebCore::CSSVariableData::createResolved): Deleted.
(WebCore::CSSVariableData::needsVariableResolution const): Deleted.
(WebCore::CSSVariableData::CSSVariableData): Deleted.

  • css/CSSVariableReferenceValue.cpp:

(WebCore::resolveVariableFallback):
(WebCore::resolveVariableReference):
(WebCore::resolveTokenRange):
(WebCore::CSSVariableReferenceValue::resolveVariableReferences const):
(WebCore::CSSVariableReferenceValue::checkVariablesForCycles const): Deleted.

  • css/CSSVariableReferenceValue.h:

(WebCore::CSSVariableReferenceValue::create):
(WebCore::CSSVariableReferenceValue::equals const):
(WebCore::CSSVariableReferenceValue::variableDataValue const): Deleted.

  • css/DOMCSSRegisterCustomProperty.cpp:

(WebCore::DOMCSSRegisterCustomProperty::registerProperty):

  • css/PropertySetCSSStyleDeclaration.cpp:

(WebCore::PropertySetCSSStyleDeclaration::setProperty):

  • css/StyleBuilderCustom.h:

(WebCore::StyleBuilderCustom::applyInitialCustomProperty):
(WebCore::StyleBuilderCustom::applyValueCustomProperty):

  • css/StyleProperties.cpp:

(WebCore::MutableStyleProperties::setCustomProperty):

  • css/StyleProperties.h:
  • css/StyleResolver.cpp:

(WebCore::StyleResolver::State::setStyle):
(WebCore::StyleResolver::styleForKeyframe):
(WebCore::StyleResolver::styleForPage):
(WebCore::StyleResolver::applyMatchedProperties):
(WebCore::StyleResolver::applyPropertyToCurrentStyle):
(WebCore::StyleResolver::applyProperty):
(WebCore::StyleResolver::resolvedVariableValue const):
(WebCore::StyleResolver::CascadedProperties::applyDeferredProperties):
(WebCore::StyleResolver::CascadedProperties::Property::apply):
(WebCore::StyleResolver::applyCascadedCustomProperty):
(WebCore::StyleResolver::applyCascadedProperties):

  • css/StyleResolver.h:
  • css/parser/CSSParser.cpp:

(WebCore::CSSParser::parseValueWithVariableReferences):

  • css/parser/CSSParser.h:
  • css/parser/CSSPropertyParser.cpp:

(WebCore::CSSPropertyParser::CSSPropertyParser):
(WebCore::CSSPropertyParser::canParseTypedCustomPropertyValue):
(WebCore::CSSPropertyParser::parseTypedCustomPropertyValue):
(WebCore::CSSPropertyParser::collectParsedCustomPropertyValueDependencies):
(WebCore::CSSPropertyParser::parseValueStart):
(WebCore::CSSPropertyParser::parseSingleValue):

  • css/parser/CSSPropertyParser.h:
  • css/parser/CSSVariableParser.cpp:

(WebCore::CSSVariableParser::parseDeclarationValue):

  • dom/ConstantPropertyMap.cpp:

(WebCore::ConstantPropertyMap::setValueForProperty):
(WebCore::variableDataForPositivePixelLength):
(WebCore::variableDataForPositiveDuration):

  • rendering/style/RenderStyle.cpp:

(WebCore::RenderStyle::checkVariablesInCustomProperties): Deleted.

  • rendering/style/RenderStyle.h:

(WebCore::RenderStyle::setInheritedCustomPropertyValue):
(WebCore::RenderStyle::setNonInheritedCustomPropertyValue):

  • rendering/style/StyleCustomPropertyData.h:

(WebCore::StyleCustomPropertyData::operator== const):
(WebCore::StyleCustomPropertyData::setCustomPropertyValue):
(WebCore::StyleCustomPropertyData::StyleCustomPropertyData):
(): Deleted.

LayoutTests:

Add tests for inline styles, font-size cycles with custom properties, and a crash that was reported.

  • css-custom-properties-api/crash-expected.txt: Added.
  • css-custom-properties-api/crash.html: Added.
  • css-custom-properties-api/cycles-expected.txt: Added.
  • css-custom-properties-api/cycles.html: Added.
  • css-custom-properties-api/inline-expected.txt: Added.
  • css-custom-properties-api/inline.html: Added.
Location:
trunk
Files:
6 added
34 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r237345 r237347  
     12018-10-22  Justin Michaud  <justin_michaud@apple.com>
     2
     3        Registered custom properties should support syntax parameter for <length> and *
     4        https://bugs.webkit.org/show_bug.cgi?id=190039
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Add tests for inline styles, font-size cycles with custom properties, and a crash that was reported.
     9
     10        * css-custom-properties-api/crash-expected.txt: Added.
     11        * css-custom-properties-api/crash.html: Added.
     12        * css-custom-properties-api/cycles-expected.txt: Added.
     13        * css-custom-properties-api/cycles.html: Added.
     14        * css-custom-properties-api/inline-expected.txt: Added.
     15        * css-custom-properties-api/inline.html: Added.
     16
    1172018-10-22  Ryan Haddad  <ryanhaddad@apple.com>
    218
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r237341 r237347  
     12018-10-22  Justin Michaud  <justin_michaud@apple.com>
     2
     3        Registered custom properties should support syntax parameter for <length> and *
     4        https://bugs.webkit.org/show_bug.cgi?id=190039
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Update WPT test results to fail in a new way.
     9
     10        * web-platform-tests/css/css-properties-values-api/register-property-syntax-parsing-expected.txt:
     11        * web-platform-tests/css/css-properties-values-api/registered-properties-inheritance-expected.txt:
     12        * web-platform-tests/css/css-properties-values-api/registered-property-cssom-expected.txt:
     13        * web-platform-tests/css/css-properties-values-api/typedom.tentative-expected.txt:
     14        * web-platform-tests/css/css-properties-values-api/var-reference-registered-properties-cycles-expected.txt:
     15        * web-platform-tests/css/css-properties-values-api/var-reference-registered-properties-expected.txt:
     16
    1172018-10-12  Jiewen Tan  <jiewen_tan@apple.com>
    218
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-properties-values-api/register-property-syntax-parsing-expected.txt

    r236895 r237347  
    11
    2 FAIL syntax:'*', initialValue:'a' is valid The given initial value does not parse for the given syntax.
     2PASS syntax:'*', initialValue:'a' is valid
    33FAIL syntax:' * ', initialValue:'b' is valid The given initial value does not parse for the given syntax.
    44PASS syntax:'<length>', initialValue:'2px' is valid
     
    1010FAIL syntax:'<color> | <image> | <url> | <integer> | <angle>', initialValue:'red' is valid The given initial value does not parse for the given syntax.
    1111FAIL syntax:'<time> | <resolution> | <transform-list> | <custom-ident>', initialValue:'red' is valid The given initial value does not parse for the given syntax.
    12 FAIL syntax:'*', initialValue:':> hello' is valid The given initial value does not parse for the given syntax.
    13 FAIL syntax:'*', initialValue:'([ brackets ]) { yay (??)}' is valid The given initial value does not parse for the given syntax.
    14 FAIL syntax:'*', initialValue:'yep 'this is valid too'' is valid The given initial value does not parse for the given syntax.
    15 FAIL syntax:'*', initialValue:'unmatched opening bracket is valid :(' is valid The given initial value does not parse for the given syntax.
    16 FAIL syntax:'*', initialValue:'"' is valid The given initial value does not parse for the given syntax.
     12PASS syntax:'*', initialValue:':> hello' is valid
     13PASS syntax:'*', initialValue:'([ brackets ]) { yay (??)}' is valid
     14PASS syntax:'*', initialValue:'yep 'this is valid too'' is valid
     15PASS syntax:'*', initialValue:'unmatched opening bracket is valid :(' is valid
     16PASS syntax:'*', initialValue:'"' is valid
    1717PASS syntax:'<length>', initialValue:'0' is valid
    1818PASS syntax:'<length>', initialValue:'10px /*:)*/' is valid
     
    6565|       na\r|nya', initialValue:'nya' is valid The given initial value does not parse for the given syntax.
    6666FAIL syntax:'null', initialValue:'null' is valid The given initial value does not parse for the given syntax.
    67 FAIL syntax:'undefined', initialValue:'undefined' is valid The given initial value does not parse for the given syntax.
     67PASS syntax:'undefined', initialValue:'undefined' is valid
    6868FAIL syntax:'array', initialValue:'array' is valid The given initial value does not parse for the given syntax.
    6969PASS syntax:'banana,nya', initialValue:'banana' is invalid
     
    8787FAIL syntax:'<length>|INHERIT', initialValue:'10px' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
    8888FAIL syntax:'<percentage>|unsEt', initialValue:'2%' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
    89 PASS syntax:'*', initialValue:'initial' is invalid
    90 PASS syntax:'*', initialValue:'inherit' is invalid
    91 PASS syntax:'*', initialValue:'unset' is invalid
    92 PASS syntax:'*', initialValue:'revert' is invalid
     89FAIL syntax:'*', initialValue:'initial' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
     90FAIL syntax:'*', initialValue:'inherit' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
     91FAIL syntax:'*', initialValue:'unset' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
     92FAIL syntax:'*', initialValue:'revert' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
    9393PASS syntax:'<custom-ident>', initialValue:'initial' is invalid
    9494PASS syntax:'<custom-ident>+', initialValue:'foo inherit bar' is invalid
    95 PASS syntax:'*', initialValue:')' is invalid
    96 PASS syntax:'*', initialValue:'([)]' is invalid
    97 PASS syntax:'*', initialValue:'whee!' is invalid
    98 PASS syntax:'*', initialValue:'"
    99 ' is invalid
    100 PASS syntax:'*', initialValue:'url(moo '')' is invalid
    101 PASS syntax:'*', initialValue:'semi;colon' is invalid
    102 PASS syntax:'*', initialValue:'var(invalid var ref)' is invalid
    103 PASS syntax:'*', initialValue:'var(--foo)' is invalid
     95FAIL syntax:'*', initialValue:')' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
     96FAIL syntax:'*', initialValue:'([)]' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
     97FAIL syntax:'*', initialValue:'whee!' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
     98FAIL syntax:'*', initialValue:'"
     99' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
     100FAIL syntax:'*', initialValue:'url(moo '')' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
     101FAIL syntax:'*', initialValue:'semi;colon' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
     102FAIL syntax:'*', initialValue:'var(invalid var ref)' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
     103FAIL syntax:'*', initialValue:'var(--foo)' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
    104104PASS syntax:'banana', initialValue:'bAnAnA' is invalid
    105105PASS syntax:'<length>', initialValue:'var(--moo)' is invalid
     
    108108FAIL syntax:'<length>', initialValue:'calc(5px + 10%)' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
    109109PASS syntax:'<length>', initialValue:'calc(5px * 3px / 6px)' is invalid
    110 PASS syntax:'<length>', initialValue:'10em' is invalid
     110FAIL syntax:'<length>', initialValue:'10em' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
    111111FAIL syntax:'<length>', initialValue:'10vmin' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
    112 PASS syntax:'<length>', initialValue:'calc(4px + 3em)' is invalid
    113 PASS syntax:'<length>', initialValue:'calc(4px + calc(8 * 2em))' is invalid
    114 PASS syntax:'<length>+', initialValue:'calc(2ex + 16px)' is invalid
     112FAIL syntax:'<length>', initialValue:'calc(4px + 3em)' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
     113FAIL syntax:'<length>', initialValue:'calc(4px + calc(8 * 2em))' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
     114FAIL syntax:'<length>+', initialValue:'calc(2ex + 16px)' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
    115115PASS syntax:'<length>+', initialValue:'10px calc(20px + 4rem)' is invalid
    116116PASS syntax:'<percentage> | <length>+', initialValue:'calc(100vh - 10px) 30px' is invalid
    117117PASS syntax:'<length>', initialValue:'10px;' is invalid
    118 PASS syntax:'<length-percentage>', initialValue:'calc(2px + 10% + 7ex)' is invalid
     118FAIL syntax:'<length-percentage>', initialValue:'calc(2px + 10% + 7ex)' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
    119119FAIL syntax:'<percentage>', initialValue:'0' is invalid assert_throws: function "() => CSS.registerProperty({name: name, syntax: syntax, initialValue: initialValue, inherits: false})" did not throw
    120120PASS syntax:'<integer>', initialValue:'1.0' is invalid
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-properties-values-api/registered-properties-inheritance-expected.txt

    r236828 r237347  
    33PASS Explicitly inheriting from a parent with an invalid value results in initial value.
    44PASS Explicitly inheriting from a parent with no value results in initial value.
    5 FAIL Reference to undefined variable results in inherited value assert_equals: expected "42px" but got "0px"
    6 FAIL Reference to syntax-incompatible variable results in inherited value assert_equals: expected "42px" but got "0px"
     5PASS Reference to undefined variable results in inherited value
     6PASS Reference to syntax-incompatible variable results in inherited value
    77
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-properties-values-api/registered-property-cssom-expected.txt

    r236828 r237347  
    33FAIL CSS.registerProperty The given initial value does not parse for the given syntax.
    44FAIL Formerly valid values are still readable from inline styles but are computed as the unset value assert_equals: expected "blue" but got "hello"
    5 FAIL Values not matching the registered type can't be set assert_equals: expected "5" but got "hi"
     5FAIL Values not matching the registered type can't be set assert_equals: expected "hello" but got "20"
    66FAIL Values can be removed from inline styles assert_equals: expected "red" but got " red"
    7 FAIL Stylesheets can be modified by CSSOM assert_equals: expected "10px" but got "0px"
     7PASS Stylesheets can be modified by CSSOM
    88FAIL Valid values can be set on inline styles assert_equals: expected "blue" but got " blue"
    99
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-properties-values-api/typedom.tentative-expected.txt

    r236828 r237347  
    33Harness Error (FAIL), message = ReferenceError: Can't find variable: CSSUnparsedValue
    44
    5 FAIL Computed * is reified as CSSUnparsedValue The given initial value does not parse for the given syntax.
     5FAIL Computed * is reified as CSSUnparsedValue target.computedStyleMap is not a function. (In 'target.computedStyleMap()', 'target.computedStyleMap' is undefined)
    66FAIL Computed <angle> is reified as CSSUnitValue The given initial value does not parse for the given syntax.
    77FAIL Computed <color> is reified as CSSStyleValue The given initial value does not parse for the given syntax.
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-properties-values-api/var-reference-registered-properties-cycles-expected.txt

    r236828 r237347  
    11
    2 FAIL A var() cycle between two registered properties is handled correctly. assert_equals: expected "2px" but got "3px"
    3 FAIL A var() cycle between a registered properties and an unregistered property is handled correctly. assert_equals: expected "1px" but got "2px"
     2PASS A var() cycle between two registered properties is handled correctly.
     3PASS A var() cycle between a registered properties and an unregistered property is handled correctly.
    44PASS A var() cycle between a two unregistered properties is handled correctly.
    5 FAIL A var() cycle between a syntax:'*' property and an unregistered property is handled correctly. The given initial value does not parse for the given syntax.
     5PASS A var() cycle between a syntax:'*' property and an unregistered property is handled correctly.
    66
  • trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-properties-values-api/var-reference-registered-properties-expected.txt

    r236828 r237347  
    11
    2 FAIL var() references work with registered properties assert_equals: expected "15px" but got "10%"
     2FAIL var() references work with registered properties assert_equals: expected "  10px" but got " 10px"
    33FAIL References to registered var()-properties work in registered lists assert_equals: expected "1px, 10px, 2px" but got "0px"
    44FAIL References to mixed registered and unregistered var()-properties work in registered lists assert_equals: expected "1px, 20px, 10px, 2px" but got "0px"
  • trunk/Source/WebCore/ChangeLog

    r237344 r237347  
     12018-10-22  Justin Michaud  <justin_michaud@apple.com>
     2
     3        Registered custom properties should support syntax parameter for <length> and *
     4        https://bugs.webkit.org/show_bug.cgi?id=190039
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Refactor code so that:
     9        - All properties applied in StyleResolver::applyMatchedProperties are only applied once.
     10        - Custom properties are only resolved once, in StyleResolver, when they are applied to the RenderStyle. They were previously resolved
     11          every time they were referenced, and again in RenderStyle.
     12        - The font-size property is applied after its variable references, but before custom properties that depend on it.
     13        - Cycles are detected at the same time as resolution.
     14        - MutableStyleProperties' custom properties cannot be set from Javascript or WebKitLegacy if they do not parse for the property's type.
     15          If they contain var(--...) references, however, then they can be set because we cannot check if the references are valid from setProperty.
     16          This behaviour matches chrome, but is not documented in the spec.
     17        - Custom property values have more explicit resolved/unresolved state.
     18        - RenderStyle only ever holds resolved custom properties, and StyleResolver::CascadedProperties only holds unresolved properties.
     19
     20        Tests: css-custom-properties-api/crash.html
     21               css-custom-properties-api/cycles.html
     22               css-custom-properties-api/inline.html
     23
     24        * css/CSSComputedStyleDeclaration.cpp:
     25        (WebCore::ComputedStyleExtractor::customPropertyValue):
     26        * css/CSSCustomPropertyValue.cpp:
     27        (WebCore::CSSCustomPropertyValue::equals const):
     28        (WebCore::CSSCustomPropertyValue::customCSSText const):
     29        (WebCore::CSSCustomPropertyValue::tokens const):
     30        (WebCore::CSSCustomPropertyValue::checkVariablesForCycles const): Deleted.
     31        (WebCore::CSSCustomPropertyValue::resolveVariableReferences const): Deleted.
     32        (WebCore::CSSCustomPropertyValue::setResolvedTypedValue): Deleted.
     33        * css/CSSCustomPropertyValue.h:
     34        * css/CSSRegisteredCustomProperty.cpp:
     35        (WebCore::CSSRegisteredCustomProperty::CSSRegisteredCustomProperty):
     36        * css/CSSRegisteredCustomProperty.h:
     37        * css/CSSStyleSheet.h:
     38        * css/CSSVariableData.cpp:
     39        (WebCore::CSSVariableData::CSSVariableData):
     40        (WebCore::CSSVariableData::consumeAndUpdateTokens): Deleted.
     41        (WebCore::CSSVariableData::checkVariablesForCycles const): Deleted.
     42        (WebCore::CSSVariableData::checkVariablesForCyclesWithRange const): Deleted.
     43        (WebCore::CSSVariableData::resolveVariableFallback const): Deleted.
     44        (WebCore::CSSVariableData::resolveVariableReference const): Deleted.
     45        (WebCore::CSSVariableData::resolveVariableReferences const): Deleted.
     46        (WebCore::CSSVariableData::resolveTokenRange const): Deleted.
     47        * css/CSSVariableData.h:
     48        (WebCore::CSSVariableData::create):
     49        (WebCore::CSSVariableData::createResolved): Deleted.
     50        (WebCore::CSSVariableData::needsVariableResolution const): Deleted.
     51        (WebCore::CSSVariableData::CSSVariableData): Deleted.
     52        * css/CSSVariableReferenceValue.cpp:
     53        (WebCore::resolveVariableFallback):
     54        (WebCore::resolveVariableReference):
     55        (WebCore::resolveTokenRange):
     56        (WebCore::CSSVariableReferenceValue::resolveVariableReferences const):
     57        (WebCore::CSSVariableReferenceValue::checkVariablesForCycles const): Deleted.
     58        * css/CSSVariableReferenceValue.h:
     59        (WebCore::CSSVariableReferenceValue::create):
     60        (WebCore::CSSVariableReferenceValue::equals const):
     61        (WebCore::CSSVariableReferenceValue::variableDataValue const): Deleted.
     62        * css/DOMCSSRegisterCustomProperty.cpp:
     63        (WebCore::DOMCSSRegisterCustomProperty::registerProperty):
     64        * css/PropertySetCSSStyleDeclaration.cpp:
     65        (WebCore::PropertySetCSSStyleDeclaration::setProperty):
     66        * css/StyleBuilderCustom.h:
     67        (WebCore::StyleBuilderCustom::applyInitialCustomProperty):
     68        (WebCore::StyleBuilderCustom::applyValueCustomProperty):
     69        * css/StyleProperties.cpp:
     70        (WebCore::MutableStyleProperties::setCustomProperty):
     71        * css/StyleProperties.h:
     72        * css/StyleResolver.cpp:
     73        (WebCore::StyleResolver::State::setStyle):
     74        (WebCore::StyleResolver::styleForKeyframe):
     75        (WebCore::StyleResolver::styleForPage):
     76        (WebCore::StyleResolver::applyMatchedProperties):
     77        (WebCore::StyleResolver::applyPropertyToCurrentStyle):
     78        (WebCore::StyleResolver::applyProperty):
     79        (WebCore::StyleResolver::resolvedVariableValue const):
     80        (WebCore::StyleResolver::CascadedProperties::applyDeferredProperties):
     81        (WebCore::StyleResolver::CascadedProperties::Property::apply):
     82        (WebCore::StyleResolver::applyCascadedCustomProperty):
     83        (WebCore::StyleResolver::applyCascadedProperties):
     84        * css/StyleResolver.h:
     85        * css/parser/CSSParser.cpp:
     86        (WebCore::CSSParser::parseValueWithVariableReferences):
     87        * css/parser/CSSParser.h:
     88        * css/parser/CSSPropertyParser.cpp:
     89        (WebCore::CSSPropertyParser::CSSPropertyParser):
     90        (WebCore::CSSPropertyParser::canParseTypedCustomPropertyValue):
     91        (WebCore::CSSPropertyParser::parseTypedCustomPropertyValue):
     92        (WebCore::CSSPropertyParser::collectParsedCustomPropertyValueDependencies):
     93        (WebCore::CSSPropertyParser::parseValueStart):
     94        (WebCore::CSSPropertyParser::parseSingleValue):
     95        * css/parser/CSSPropertyParser.h:
     96        * css/parser/CSSVariableParser.cpp:
     97        (WebCore::CSSVariableParser::parseDeclarationValue):
     98        * dom/ConstantPropertyMap.cpp:
     99        (WebCore::ConstantPropertyMap::setValueForProperty):
     100        (WebCore::variableDataForPositivePixelLength):
     101        (WebCore::variableDataForPositiveDuration):
     102        * rendering/style/RenderStyle.cpp:
     103        (WebCore::RenderStyle::checkVariablesInCustomProperties): Deleted.
     104        * rendering/style/RenderStyle.h:
     105        (WebCore::RenderStyle::setInheritedCustomPropertyValue):
     106        (WebCore::RenderStyle::setNonInheritedCustomPropertyValue):
     107        * rendering/style/StyleCustomPropertyData.h:
     108        (WebCore::StyleCustomPropertyData::operator== const):
     109        (WebCore::StyleCustomPropertyData::setCustomPropertyValue):
     110        (WebCore::StyleCustomPropertyData::StyleCustomPropertyData):
     111        (): Deleted.
     112
    11132018-10-22  Justin Michaud  <justin_michaud@apple.com>
    2114
  • trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp

    r237266 r237347  
    26132613    auto* value = style->getCustomProperty(propertyName);
    26142614
    2615     if (registered) {
    2616         // TODO this should be done based on the syntax
    2617         if (value && value->resolvedTypedValue())
    2618             return zoomAdjustedPixelValueForLength(*value->resolvedTypedValue(), *style);
    2619 
    2620         if (registered->initialValue() && registered->initialValue()->resolvedTypedValue())
    2621             return zoomAdjustedPixelValueForLength(*registered->initialValue()->resolvedTypedValue(), *style);
    2622 
     2615    if (registered && !value)
     2616        return registered->initialValueCopy();
     2617
     2618    if (!value)
    26232619        return nullptr;
    2624     }
    2625 
    2626     if (value)
     2620
     2621    auto visitor = WTF::makeVisitor([&](const Ref<CSSVariableReferenceValue>&) {
     2622        ASSERT_NOT_REACHED();
     2623        return RefPtr<CSSValue>();
     2624    }, [&](const CSSValueID&) {
    26272625        return CSSCustomPropertyValue::create(*value);
    2628 
    2629     return nullptr;
     2626    }, [&](const Ref<CSSVariableData>&) {
     2627        return CSSCustomPropertyValue::create(*value);
     2628    }, [&](const Length& value) {
     2629        return zoomAdjustedPixelValueForLength(value, *style);
     2630    });
     2631    return WTF::visit(visitor, value->value());
    26302632}
    26312633
  • trunk/Source/WebCore/css/CSSCustomPropertyValue.cpp

    r236895 r237347  
    2828#include "CSSTokenizer.h"
    2929
     30namespace WebCore {
    3031
    31 namespace WebCore {
     32bool CSSCustomPropertyValue::equals(const CSSCustomPropertyValue& other) const
     33{
     34    if (m_name != other.m_name || m_value.index() != other.m_value.index())
     35        return false;
     36    auto visitor = WTF::makeVisitor([&](const Ref<CSSVariableReferenceValue>& value) {
     37        return value.get() == WTF::get<Ref<CSSVariableReferenceValue>>(other.m_value).get();
     38    }, [&](const CSSValueID& value) {
     39        return value == WTF::get<CSSValueID>(other.m_value);
     40    }, [&](const Ref<CSSVariableData>& value) {
     41        return value.get() == WTF::get<Ref<CSSVariableData>>(other.m_value).get();
     42    }, [&](const Length& value) {
     43        return value == WTF::get<Length>(other.m_value);
     44    });
     45    return WTF::visit(visitor, m_value);
     46}
    3247
    3348String CSSCustomPropertyValue::customCSSText() const
     
    3550    if (!m_serialized) {
    3651        m_serialized = true;
    37         if (m_resolvedTypedValue) // FIXME: Unit should be based on syntax.
    38             m_stringValue = CSSPrimitiveValue::create(m_resolvedTypedValue->value(), CSSPrimitiveValue::CSS_PX)->cssText();
    39         else if (m_value)
    40             m_stringValue = m_value->tokenRange().serialize();
    41         else if (m_valueId != CSSValueInvalid)
    42             m_stringValue = getValueName(m_valueId);
    43         else
    44             m_stringValue = emptyString();
     52
     53        auto visitor = WTF::makeVisitor([&](const Ref<CSSVariableReferenceValue>& value) {
     54            m_stringValue = value->cssText();
     55        }, [&](const CSSValueID& value) {
     56            m_stringValue = getValueName(value);
     57        }, [&](const Ref<CSSVariableData>& value) {
     58            m_stringValue = value->tokenRange().serialize();
     59        }, [&](const Length& value) {
     60            m_stringValue = CSSPrimitiveValue::create(value.value(), CSSPrimitiveValue::CSS_PX)->cssText();
     61        });
     62        WTF::visit(visitor, m_value);
    4563    }
    4664    return m_stringValue;
    4765}
    4866
    49 Vector<CSSParserToken> CSSCustomPropertyValue::tokens(const CSSRegisteredCustomPropertySet& registeredProperties, const RenderStyle& style) const
     67Vector<CSSParserToken> CSSCustomPropertyValue::tokens() const
    5068{
    51     if (m_resolvedTypedValue) {
    52         Vector<CSSParserToken> result;
     69    Vector<CSSParserToken> result;
     70
     71    auto visitor = WTF::makeVisitor([&](const Ref<CSSVariableReferenceValue>&) {
     72        ASSERT_NOT_REACHED();
     73    }, [&](const CSSValueID&) {
     74        // Do nothing
     75    }, [&](const Ref<CSSVariableData>& value) {
     76        result.appendVector(value->tokens());
     77    }, [&](const Length&) {
    5378        CSSTokenizer tokenizer(cssText());
    5479
     
    5681        while (!tokenizerRange.atEnd())
    5782            result.append(tokenizerRange.consume());
     83    });
     84    WTF::visit(visitor, m_value);
    5885
    59         return result;
    60     }
    61 
    62     if (!m_value)
    63         return { };
    64 
    65     if (m_containsVariables) {
    66         Vector<CSSParserToken> result;
    67         // FIXME: Avoid doing this work more than once.
    68         RefPtr<CSSVariableData> resolvedData = m_value->resolveVariableReferences(registeredProperties, style);
    69         if (resolvedData)
    70             result.appendVector(resolvedData->tokens());
    71 
    72         return result;
    73     }
    74 
    75     return m_value->tokens();
    76 }
    77 
    78 bool CSSCustomPropertyValue::checkVariablesForCycles(const AtomicString& name, const RenderStyle& style, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const
    79 {
    80     ASSERT(containsVariables());
    81     if (m_value)
    82         return m_value->checkVariablesForCycles(name, style, seenProperties, invalidProperties);
    83     return true;
    84 }
    85 
    86 void CSSCustomPropertyValue::resolveVariableReferences(const CSSRegisteredCustomPropertySet& registeredProperties, Vector<Ref<CSSCustomPropertyValue>>& resolvedValues, const RenderStyle& style) const
    87 {
    88     ASSERT(containsVariables());
    89     if (!m_value)
    90         return;
    91    
    92     ASSERT(m_value->needsVariableResolution());
    93     RefPtr<CSSVariableData> resolvedData = m_value->resolveVariableReferences(registeredProperties, style);
    94     if (resolvedData)
    95         resolvedValues.append(CSSCustomPropertyValue::createWithVariableData(m_name, resolvedData.releaseNonNull()));
    96     else
    97         resolvedValues.append(CSSCustomPropertyValue::createWithID(m_name, CSSValueInvalid));
    98 }
    99 
    100 void CSSCustomPropertyValue::setResolvedTypedValue(Length length)
    101 {
    102     ASSERT(length.isSpecified());
    103     m_resolvedTypedValue = WTFMove(length);
     86    return result;
    10487}
    10588
  • trunk/Source/WebCore/css/CSSCustomPropertyValue.h

    r236895 r237347  
    2828#include "CSSRegisteredCustomProperty.h"
    2929#include "CSSValue.h"
    30 #include "CSSVariableData.h"
     30#include "CSSVariableReferenceValue.h"
    3131#include "Length.h"
    3232#include <wtf/RefPtr.h>
     33#include <wtf/Variant.h>
    3334#include <wtf/text/WTFString.h>
    3435
     
    3637
    3738class CSSParserToken;
     39class CSSVariableReferenceValue;
    3840class RenderStyle;
    3941
    4042class CSSCustomPropertyValue final : public CSSValue {
    4143public:
    42     static Ref<CSSCustomPropertyValue> createWithVariableData(const AtomicString& name, Ref<CSSVariableData>&& value)
     44    using VariantValue = Variant<Ref<CSSVariableReferenceValue>, CSSValueID, Ref<CSSVariableData>, Length>;
     45
     46    static Ref<CSSCustomPropertyValue> createUnresolved(const AtomicString& name, Ref<CSSVariableReferenceValue>&& value)
    4347    {
    44         return adoptRef(*new CSSCustomPropertyValue(name, WTFMove(value)));
     48        return adoptRef(*new CSSCustomPropertyValue(name, { WTFMove(value) }));
     49    }
     50
     51    static Ref<CSSCustomPropertyValue> createUnresolved(const AtomicString& name, CSSValueID value)
     52    {
     53        return adoptRef(*new CSSCustomPropertyValue(name, { value }));
     54    }
     55
     56    static Ref<CSSCustomPropertyValue> createWithID(const AtomicString& name, CSSValueID id)
     57    {
     58        ASSERT(id == CSSValueInherit || id == CSSValueInitial || id == CSSValueUnset || id == CSSValueRevert || id == CSSValueInvalid);
     59        return adoptRef(*new CSSCustomPropertyValue(name, { id }));
     60    }
     61
     62    static Ref<CSSCustomPropertyValue> createSyntaxAll(const AtomicString& name, Ref<CSSVariableData>&& value)
     63    {
     64        return adoptRef(*new CSSCustomPropertyValue(name, { WTFMove(value) }));
    4565    }
    4666   
    47     static Ref<CSSCustomPropertyValue> createWithID(const AtomicString& name, CSSValueID value)
     67    static Ref<CSSCustomPropertyValue> createSyntaxLength(const AtomicString& name, Length value)
    4868    {
    49         return adoptRef(*new CSSCustomPropertyValue(name, value));
    50     }
    51    
    52     static Ref<CSSCustomPropertyValue> createInvalid()
    53     {
    54         return adoptRef(*new CSSCustomPropertyValue(emptyString(), emptyString()));
     69        return adoptRef(*new CSSCustomPropertyValue(name, { WTFMove(value) }));
    5570    }
    5671
     
    6378
    6479    const AtomicString& name() const { return m_name; }
    65    
    66     bool equals(const CSSCustomPropertyValue& other) const { return m_name == other.m_name && m_value == other.m_value && m_valueId == other.m_valueId; }
     80    bool isResolved() const  { return !WTF::holds_alternative<Ref<CSSVariableReferenceValue>>(m_value); }
     81    bool isUnset() const  { return WTF::holds_alternative<CSSValueID>(m_value) && WTF::get<CSSValueID>(m_value) == CSSValueUnset; }
     82    bool isInvalid() const  { return WTF::holds_alternative<CSSValueID>(m_value) && WTF::get<CSSValueID>(m_value) == CSSValueInvalid; }
    6783
    68     bool containsVariables() const { ASSERT(!m_containsVariables || !m_resolvedTypedValue); return m_containsVariables; }
    69     bool checkVariablesForCycles(const AtomicString& name, const RenderStyle&, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const;
     84    const VariantValue& value() const { return m_value; }
    7085
    71     void resolveVariableReferences(const CSSRegisteredCustomPropertySet&, Vector<Ref<CSSCustomPropertyValue>>&, const RenderStyle&) const;
    72 
    73     CSSValueID valueID() const { return m_valueId; }
    74     CSSVariableData* value() const { return m_value.get(); }
    75     Vector<CSSParserToken> tokens(const CSSRegisteredCustomPropertySet&, const RenderStyle&) const;
    76 
    77     const std::optional<Length>& resolvedTypedValue() const { return m_resolvedTypedValue; }
    78     void setResolvedTypedValue(Length);
     86    Vector<CSSParserToken> tokens() const;
     87    bool equals(const CSSCustomPropertyValue& other) const;
    7988
    8089private:
    81     CSSCustomPropertyValue(const AtomicString& name, const String& serializedValue)
    82         : CSSValue(CustomPropertyClass)
    83         , m_name(name)
    84         , m_stringValue(serializedValue)
    85         , m_serialized(true)
    86     {
    87     }
    88 
    89     CSSCustomPropertyValue(const AtomicString& name, CSSValueID id)
    90         : CSSValue(CustomPropertyClass)
    91         , m_name(name)
    92         , m_valueId(id)
    93     {
    94         ASSERT(id == CSSValueInherit || id == CSSValueInitial || id == CSSValueUnset || id == CSSValueRevert || id == CSSValueInvalid);
    95     }
    96    
    97     CSSCustomPropertyValue(const AtomicString& name, Ref<CSSVariableData>&& value)
     90    CSSCustomPropertyValue(const AtomicString& name, VariantValue&& value)
    9891        : CSSValue(CustomPropertyClass)
    9992        , m_name(name)
    10093        , m_value(WTFMove(value))
    101         , m_valueId(CSSValueInternalVariableValue)
    102         , m_containsVariables(m_value->needsVariableResolution())
     94        , m_serialized(false)
    10395    {
    10496    }
     
    10799        : CSSValue(CustomPropertyClass)
    108100        , m_name(other.m_name)
    109         , m_value(other.m_value.copyRef())
    110         , m_valueId(other.m_valueId)
     101        , m_value(CSSValueUnset)
    111102        , m_stringValue(other.m_stringValue)
    112         , m_containsVariables(other.m_containsVariables)
    113103        , m_serialized(other.m_serialized)
    114         , m_resolvedTypedValue(other.m_resolvedTypedValue)
    115104    {
     105        // No copy constructor for Ref<CSSVariableData>, so we have to do this ourselves
     106        auto visitor = WTF::makeVisitor([&](const Ref<CSSVariableReferenceValue>& value) {
     107            m_value = value.copyRef();
     108        }, [&](const CSSValueID& value) {
     109            m_value = value;
     110        }, [&](const Ref<CSSVariableData>& value) {
     111            m_value = value.copyRef();
     112        }, [&](const Length& value) {
     113            m_value = value;
     114        });
     115        WTF::visit(visitor, other.m_value);
    116116    }
    117117   
    118118    const AtomicString m_name;
    119    
    120     RefPtr<CSSVariableData> m_value;
    121     CSSValueID m_valueId { CSSValueInvalid };
     119    VariantValue m_value;
    122120   
    123121    mutable String m_stringValue;
    124     bool m_containsVariables { false };
    125122    mutable bool m_serialized { false };
    126 
    127     // FIXME: It should not be possible to express an invalid state, such as containsVariables() && resolvedTypedValue().
    128     std::optional<Length> m_resolvedTypedValue;
    129123};
    130124
  • trunk/Source/WebCore/css/CSSRegisteredCustomProperty.cpp

    r236828 r237347  
    3131namespace WebCore {
    3232
    33 CSSRegisteredCustomProperty::CSSRegisteredCustomProperty(const String& name, bool inherits, RefPtr<CSSCustomPropertyValue>&& initialValue)
     33CSSRegisteredCustomProperty::CSSRegisteredCustomProperty(const String& name, const String& syntax, bool inherits, RefPtr<CSSCustomPropertyValue>&& initialValue)
    3434    : name(name)
     35    , syntax(syntax)
    3536    , inherits(inherits)
    3637    , m_initialValue(WTFMove(initialValue))
  • trunk/Source/WebCore/css/CSSRegisteredCustomProperty.h

    r236828 r237347  
    3434struct CSSRegisteredCustomProperty {
    3535    const String name;
    36     /* TODO syntax */
     36    const String syntax;
    3737    const bool inherits;
    3838
    39     CSSRegisteredCustomProperty(const String& name, bool inherits, RefPtr<CSSCustomPropertyValue>&& initialValue);
     39    CSSRegisteredCustomProperty(const String& name, const String& syntax, bool inherits, RefPtr<CSSCustomPropertyValue>&& initialValue);
    4040
    4141    const CSSCustomPropertyValue* initialValue() const { return m_initialValue.get(); }
  • trunk/Source/WebCore/css/CSSVariableData.cpp

    r236895 r237347  
    6161}
    6262
    63 void CSSVariableData::consumeAndUpdateTokens(const CSSParserTokenRange& range)
     63CSSVariableData::CSSVariableData(const CSSParserTokenRange& range)
    6464{
    6565    StringBuilder stringBuilder;
     
    7878}
    7979
    80 CSSVariableData::CSSVariableData(const CSSParserTokenRange& range, bool needsVariableResolution)
    81     : m_needsVariableResolution(needsVariableResolution)
    82 {
    83     consumeAndUpdateTokens(range);
    84 }
    85 
    86 bool CSSVariableData::checkVariablesForCycles(const AtomicString& name, const RenderStyle& style, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const
    87 {
    88     if (invalidProperties.contains(name))
    89         return false;
    90    
    91     HashSet<AtomicString> newSeenProperties = seenProperties;
    92     newSeenProperties.add(name);
    93    
    94     bool valid = checkVariablesForCyclesWithRange(m_tokens, style, newSeenProperties, invalidProperties);
    95     if (!valid)
    96         invalidProperties.add(name);
    97    
    98     return valid;
    99 }
    100    
    101 bool CSSVariableData::checkVariablesForCyclesWithRange(CSSParserTokenRange range, const RenderStyle& style, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const
    102 {
    103     while (!range.atEnd()) {
    104         if (range.peek().functionId() == CSSValueVar || range.peek().functionId() == CSSValueEnv) {
    105             CSSParserTokenRange block = range.consumeBlock();
    106            
    107             block.consumeWhitespace();
    108             ASSERT(block.peek().type() == IdentToken);
    109             AtomicString variableName = block.consumeIncludingWhitespace().value().toAtomicString();
    110             ASSERT(block.atEnd() || block.peek().type() == CommaToken);
    111             if (seenProperties.contains(variableName))
    112                 return false;
    113 
    114             auto* value = style.getCustomProperty(variableName);
    115             if (value && value->containsVariables() && !value->checkVariablesForCycles(variableName, style, seenProperties, invalidProperties))
    116                 return false;
    117 
    118             if (range.peek().type() == CommaToken) {
    119                 // Fallback.
    120                 range.consume();
    121                 return checkVariablesForCyclesWithRange(block, style, seenProperties, invalidProperties);
    122             }
    123         } else
    124             range.consume();
    125     }
    126     return true;
    127 }
    128 
    129 bool CSSVariableData::resolveVariableFallback(const CSSRegisteredCustomPropertySet& registeredProperties, CSSParserTokenRange range, Vector<CSSParserToken>& result, const RenderStyle& style) const
    130 {
    131     if (range.atEnd())
    132         return false;
    133     ASSERT(range.peek().type() == CommaToken);
    134     range.consume();
    135     return resolveTokenRange(registeredProperties, range, result, style);
    136 }
    137 
    138 bool CSSVariableData::resolveVariableReference(const CSSRegisteredCustomPropertySet& registeredProperties, CSSParserTokenRange range, Vector<CSSParserToken>& result, const RenderStyle& style) const
    139 {
    140     range.consumeWhitespace();
    141     ASSERT(range.peek().type() == IdentToken);
    142     AtomicString variableName = range.consumeIncludingWhitespace().value().toAtomicString();
    143     ASSERT(range.atEnd() || (range.peek().type() == CommaToken));
    144    
    145     auto* property = style.getCustomProperty(variableName);
    146     if (property && property->resolvedTypedValue()) {
    147         result.appendVector(property->tokens(registeredProperties, style));
    148         return true;
    149     }
    150 
    151     if (!property || !property->value()) {
    152         auto* registered = registeredProperties.get(variableName);
    153         if (registered && registered->initialValue())
    154             property = registered->initialValue();
    155         else
    156             return resolveVariableFallback(registeredProperties, range, result, style);
    157     }
    158     ASSERT(property);
    159     result.appendVector(property->tokens(registeredProperties, style));
    160    
    161     return true;
    162 }
    163 
    164 RefPtr<CSSVariableData> CSSVariableData::resolveVariableReferences(const CSSRegisteredCustomPropertySet& registeredProperties, const RenderStyle& style) const
    165 {
    166     Vector<CSSParserToken> resolvedTokens;
    167     CSSParserTokenRange range = m_tokens;
    168     if (!resolveTokenRange(registeredProperties, range, resolvedTokens, style))
    169         return nullptr;
    170     return CSSVariableData::createResolved(resolvedTokens, *this);
    171 }
    172    
    173 bool CSSVariableData::resolveTokenRange(const CSSRegisteredCustomPropertySet& registeredProperties, CSSParserTokenRange range, Vector<CSSParserToken>& result, const RenderStyle& style) const
    174 {
    175     bool success = true;
    176     while (!range.atEnd()) {
    177         if (range.peek().functionId() == CSSValueVar || range.peek().functionId() == CSSValueEnv)
    178             success &= resolveVariableReference(registeredProperties, range.consumeBlock(), result, style);
    179         else
    180             result.append(range.consume());
    181     }
    182     return success;
    183 }
    184 
    18580} // namespace WebCore
  • trunk/Source/WebCore/css/CSSVariableData.h

    r236828 r237347  
    4444    WTF_MAKE_FAST_ALLOCATED;
    4545public:
    46     static Ref<CSSVariableData> create(const CSSParserTokenRange& range, bool needsVariableResolution = true)
     46    static Ref<CSSVariableData> create(const CSSParserTokenRange& range)
    4747    {
    48         return adoptRef(*new CSSVariableData(range, needsVariableResolution));
    49     }
    50 
    51     static Ref<CSSVariableData> createResolved(const Vector<CSSParserToken>& resolvedTokens, const CSSVariableData& unresolvedData)
    52     {
    53         return adoptRef(*new CSSVariableData(resolvedTokens, unresolvedData.m_backingString));
     48        return adoptRef(*new CSSVariableData(range));
    5449    }
    5550
     
    6055    bool operator==(const CSSVariableData& other) const;
    6156
    62     bool needsVariableResolution() const { return m_needsVariableResolution; }
    63 
    64     bool checkVariablesForCycles(const AtomicString& name, const RenderStyle&, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const;
    65 
    66     RefPtr<CSSVariableData> resolveVariableReferences(const CSSRegisteredCustomPropertySet&, const RenderStyle&) const;
    67     bool resolveTokenRange(const CSSRegisteredCustomPropertySet&, CSSParserTokenRange, Vector<CSSParserToken>&, const RenderStyle&) const;
    68 
    6957private:
    70     CSSVariableData(const CSSParserTokenRange&, bool needsVariableResolution);
    71 
    72     // We can safely copy the tokens (which have raw pointers to substrings) because
    73     // StylePropertySets contain references to CSSCustomPropertyValues, which
    74     // point to the unresolved CSSVariableData values that own the backing strings
    75     // this will potentially reference.
    76     CSSVariableData(const Vector<CSSParserToken>& resolvedTokens, String backingString)
    77         : m_backingString(backingString)
    78         , m_tokens(resolvedTokens)
    79         , m_needsVariableResolution(false)
    80     { }
    81 
    82     void consumeAndUpdateTokens(const CSSParserTokenRange&);
     58    CSSVariableData(const CSSParserTokenRange&);
    8359    template<typename CharacterType> void updateTokens(const CSSParserTokenRange&);
    84    
    85     bool checkVariablesForCyclesWithRange(CSSParserTokenRange, const RenderStyle&, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const;
    86     bool resolveVariableReference(const CSSRegisteredCustomPropertySet&, CSSParserTokenRange, Vector<CSSParserToken>&, const RenderStyle&) const;
    87     bool resolveVariableFallback(const CSSRegisteredCustomPropertySet&, CSSParserTokenRange, Vector<CSSParserToken>&, const RenderStyle&) const;
    8860
    8961    String m_backingString;
    9062    Vector<CSSParserToken> m_tokens;
    91     const bool m_needsVariableResolution;
    9263
    9364    // FIXME-NEWPARSER: We want to cache StyleProperties once we support @apply.
  • trunk/Source/WebCore/css/CSSVariableReferenceValue.cpp

    r236828 r237347  
    3131#include "CSSVariableReferenceValue.h"
    3232
     33#include "RenderStyle.h"
     34#include "StyleResolver.h"
     35
    3336namespace WebCore {
    3437
     
    4144    return m_stringValue;
    4245}
    43    
    44 bool CSSVariableReferenceValue::checkVariablesForCycles(const AtomicString& name, const RenderStyle& style, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const
     46
     47static bool resolveTokenRange(CSSParserTokenRange, Vector<CSSParserToken>&, ApplyCascadedPropertyState&);
     48
     49static bool resolveVariableFallback(CSSParserTokenRange range, Vector<CSSParserToken>& result, ApplyCascadedPropertyState& state)
    4550{
    46     ASSERT(m_data);
    47     return m_data->checkVariablesForCycles(name, style, seenProperties, invalidProperties);
     51    if (range.atEnd())
     52        return false;
     53    ASSERT(range.peek().type() == CommaToken);
     54    range.consume();
     55    return resolveTokenRange(range, result, state);
     56}
     57
     58static bool resolveVariableReference(CSSParserTokenRange range, Vector<CSSParserToken>& result, ApplyCascadedPropertyState& state)
     59{
     60    auto& registeredProperties = state.styleResolver->document().getCSSRegisteredCustomPropertySet();
     61    auto& style = *state.styleResolver->style();
     62
     63    range.consumeWhitespace();
     64    ASSERT(range.peek().type() == IdentToken);
     65    String variableName = range.consumeIncludingWhitespace().value().toString();
     66    ASSERT(range.atEnd() || (range.peek().type() == CommaToken));
     67
     68    // Apply this variable first, in case it is still unresolved
     69    state.styleResolver->applyCascadedCustomProperty(variableName, state);
     70
     71    // Apply fallback to detect cycles
     72    Vector<CSSParserToken> fallbackResult;
     73    resolveVariableFallback(CSSParserTokenRange(range), fallbackResult, state);
     74
     75    auto* property = style.getCustomProperty(variableName);
     76
     77    if (!property || property->isUnset() || property->isInvalid()) {
     78        auto* registered = registeredProperties.get(variableName);
     79        if (registered && registered->initialValue())
     80            property = registered->initialValue();
     81        else
     82            return resolveVariableFallback(range, result, state);
     83    }
     84
     85    ASSERT(property->isResolved());
     86    result.appendVector(property->tokens());
     87
     88    return true;
     89}
     90
     91static bool resolveTokenRange(CSSParserTokenRange range, Vector<CSSParserToken>& result, ApplyCascadedPropertyState& state)
     92{
     93    bool success = true;
     94    while (!range.atEnd()) {
     95        if (range.peek().functionId() == CSSValueVar || range.peek().functionId() == CSSValueEnv)
     96            success &= resolveVariableReference(range.consumeBlock(), result, state);
     97        else
     98            result.append(range.consume());
     99    }
     100    return success;
     101}
     102
     103RefPtr<CSSVariableData> CSSVariableReferenceValue::resolveVariableReferences(ApplyCascadedPropertyState& state) const
     104{
     105    Vector<CSSParserToken> resolvedTokens;
     106    CSSParserTokenRange range = m_data->tokenRange();
     107
     108    if (!resolveTokenRange(range, resolvedTokens, state))
     109        return nullptr;
     110
     111    return CSSVariableData::create(resolvedTokens);
    48112}
    49113
  • trunk/Source/WebCore/css/CSSVariableReferenceValue.h

    r236828 r237347  
    3030#pragma once
    3131
     32#include "CSSParserToken.h"
     33#include "CSSParserTokenRange.h"
    3234#include "CSSValue.h"
    3335#include "CSSVariableData.h"
     36#include <wtf/HashSet.h>
    3437#include <wtf/RefPtr.h>
     38#include <wtf/text/WTFString.h>
    3539
    3640namespace WebCore {
    3741
     42struct ApplyCascadedPropertyState;
     43class CSSParserTokenRange;
     44
    3845class CSSVariableReferenceValue : public CSSValue {
    3946public:
    40     static Ref<CSSVariableReferenceValue> create(Ref<CSSVariableData>&& data)
     47    static Ref<CSSVariableReferenceValue> create(const CSSParserTokenRange& range)
    4148    {
    42         return adoptRef(*new CSSVariableReferenceValue(WTFMove(data)));
     49        return adoptRef(*new CSSVariableReferenceValue(CSSVariableData::create(range)));
    4350    }
    4451
    45     CSSVariableData* variableDataValue() const
    46     {
    47         return m_data.get();
    48     }
    49 
    50     bool equals(const CSSVariableReferenceValue& other) const { return m_data == other.m_data; }
     52    bool equals(const CSSVariableReferenceValue& other) const { return m_data.get() == other.m_data.get(); }
    5153    String customCSSText() const;
    5254
    53     bool checkVariablesForCycles(const AtomicString& name, const RenderStyle&, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const;
     55    RefPtr<CSSVariableData> resolveVariableReferences(ApplyCascadedPropertyState&) const;
    5456
    5557private:
     
    6062    }
    6163
    62     RefPtr<CSSVariableData> m_data;
     64    Ref<CSSVariableData> m_data;
    6365    mutable String m_stringValue;
    6466    mutable bool m_serialized { false };
  • trunk/Source/WebCore/css/DOMCSSRegisterCustomProperty.cpp

    r236895 r237347  
    2929#include "CSSCustomPropertyValue.h"
    3030#include "CSSPropertyNames.h"
     31#include "CSSPropertyParser.h"
    3132#include "CSSRegisteredCustomProperty.h"
    3233#include "CSSTokenizer.h"
     
    3435#include "Document.h"
    3536#include "StyleBuilderConverter.h"
    36 #include "StyleResolver.h"
    3737#include <wtf/text/WTFString.h>
    3838
     
    4343    RefPtr<CSSCustomPropertyValue> initialValue;
    4444    if (!descriptor.initialValue.isEmpty()) {
    45         initialValue = CSSCustomPropertyValue::createWithVariableData(descriptor.name, CSSVariableData::create(CSSParserTokenRange(Vector<CSSParserToken>()), false));
    46         CSSParser parser(document);
     45        CSSTokenizer tokenizer(descriptor.initialValue);
    4746        StyleResolver styleResolver(document);
    4847
    49         auto primitiveVal = parser.parseSingleValue(CSSPropertyCustom, descriptor.initialValue);
    50         if (!primitiveVal || !primitiveVal->isPrimitiveValue())
     48        // We need to initialize this so that we can successfully parse computationally dependent values (like em units).
     49        // We don't actually need the values to be accurate, since they will be rejected later anyway
     50        styleResolver.state().setStyle(styleResolver.defaultStyleForElement());
     51        styleResolver.updateFont();
     52
     53        initialValue = CSSPropertyParser::parseTypedCustomPropertyValue(descriptor.name, descriptor.syntax, tokenizer.tokenRange(), styleResolver, strictCSSParserContext());
     54
     55        if (!initialValue || !initialValue->isResolved())
    5156            return Exception { SyntaxError, "The given initial value does not parse for the given syntax." };
    5257
    5358        HashSet<CSSPropertyID> dependencies;
    54         primitiveVal->collectDirectComputationalDependencies(dependencies);
    55         primitiveVal->collectDirectRootComputationalDependencies(dependencies);
     59        initialValue->collectDirectComputationalDependencies(dependencies);
     60        initialValue->collectDirectRootComputationalDependencies(dependencies);
    5661
    5762        if (!dependencies.isEmpty())
    5863            return Exception { SyntaxError, "The given initial value must be computationally independent." };
    59 
    60         initialValue->setResolvedTypedValue(StyleBuilderConverter::convertLength(styleResolver, *primitiveVal));
    6164    }
    6265
    63     CSSRegisteredCustomProperty property { descriptor.name, descriptor.inherits, WTFMove(initialValue) };
     66    CSSRegisteredCustomProperty property { descriptor.name, descriptor.syntax, descriptor.inherits, WTFMove(initialValue) };
    6467    if (!document.registerCSSProperty(WTFMove(property)))
    6568        return Exception { InvalidModificationError, "This property has already been registered." };
     69
     70    document.styleScope().didChangeStyleSheetEnvironment();
    6671
    6772    return { };
  • trunk/Source/WebCore/css/PropertySetCSSStyleDeclaration.cpp

    r233122 r237347  
    227227{
    228228    StyleAttributeMutationScope mutationScope(this);
     229
     230    if (!willMutate())
     231        return { };
     232
     233    Document* document = nullptr;
     234
     235    if (parentElement())
     236        document = &parentElement()->document();
     237    else
     238        document = parentStyleSheet()->ownerDocument();
    229239   
    230240    CSSPropertyID propertyID = cssPropertyID(propertyName);
     
    232242        propertyID = CSSPropertyCustom;
    233243    if (!propertyID)
    234         return { };
    235 
    236     if (!willMutate())
    237244        return { };
    238245
     
    243250    bool changed;
    244251    if (propertyID == CSSPropertyCustom)
    245         changed = m_propertySet->setCustomProperty(propertyName, value, important, cssParserContext());
     252        changed = m_propertySet->setCustomProperty(document, propertyName, value, important, cssParserContext());
    246253    else
    247254        changed = m_propertySet->setProperty(propertyID, value, important, cssParserContext());
  • trunk/Source/WebCore/css/StyleBuilderCustom.h

    r236828 r237347  
    18801880inline void StyleBuilderCustom::applyInitialCustomProperty(StyleResolver& styleResolver, const CSSRegisteredCustomProperty* registered, const AtomicString& name)
    18811881{
    1882     if (registered) {
     1882    if (registered && registered->initialValue()) {
    18831883        auto initialValue = registered->initialValueCopy();
    18841884        applyValueCustomProperty(styleResolver, registered, *initialValue);
     
    18861886    }
    18871887
    1888     auto invalid = CSSCustomPropertyValue::createWithID(name, CSSValueInvalid);
     1888    auto invalid = CSSCustomPropertyValue::createUnresolved(name, CSSValueInvalid);
    18891889    applyValueCustomProperty(styleResolver, registered, invalid.get());
    18901890}
     
    19011901inline void StyleBuilderCustom::applyValueCustomProperty(StyleResolver& styleResolver, const CSSRegisteredCustomProperty* registered, CSSCustomPropertyValue& value)
    19021902{
     1903    ASSERT(value.isResolved());
    19031904    const auto& name = value.name();
    19041905
    19051906    if (!registered || registered->inherits)
    1906         styleResolver.style()->setInheritedCustomPropertyValue(name, makeRef(value), registered);
     1907        styleResolver.style()->setInheritedCustomPropertyValue(name, makeRef(value));
    19071908    else
    1908         styleResolver.style()->setNonInheritedCustomPropertyValue(name, makeRef(value), registered);
     1909        styleResolver.style()->setNonInheritedCustomPropertyValue(name, makeRef(value));
    19091910}
    19101911
  • trunk/Source/WebCore/css/StyleProperties.cpp

    r236278 r237347  
    2929#include "CSSParser.h"
    3030#include "CSSPendingSubstitutionValue.h"
     31#include "CSSPropertyParser.h"
     32#include "CSSTokenizer.h"
    3133#include "CSSValueKeywords.h"
    3234#include "CSSValueList.h"
     
    780782}
    781783
    782 bool MutableStyleProperties::setCustomProperty(const String& propertyName, const String& value, bool important, CSSParserContext parserContext)
     784bool MutableStyleProperties::setCustomProperty(const Document* document, const String& propertyName, const String& value, bool important, CSSParserContext parserContext)
    783785{
    784786    // Setting the value to an empty string just removes the property in both IE and Gecko.
     
    788790
    789791    parserContext.mode = cssParserMode();
     792
     793    String syntax = "*";
     794    auto* registered = document ? document->getCSSRegisteredCustomPropertySet().get(propertyName) : nullptr;
     795
     796    if (registered)
     797        syntax = registered->syntax;
     798
     799    CSSTokenizer tokenizer(value);
     800    if (!CSSPropertyParser::canParseTypedCustomPropertyValue(syntax, tokenizer.tokenRange(), parserContext))
     801        return false;
     802
    790803    // When replacing an existing property value, this moves the property to the end of the list.
    791804    // Firefox preserves the position, and MSIE moves the property to the beginning.
  • trunk/Source/WebCore/css/StyleProperties.h

    r236278 r237347  
    250250
    251251    // Methods for querying and altering CSS custom properties.
    252     bool setCustomProperty(const String& propertyName, const String& value, bool important, CSSParserContext);
     252    bool setCustomProperty(const Document*, const String& propertyName, const String& value, bool important, CSSParserContext);
    253253    bool removeCustomProperty(const String& propertyName, String* returnText = nullptr);
    254254
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r236828 r237347  
    322322}
    323323
    324 inline void StyleResolver::State::setStyle(std::unique_ptr<RenderStyle> style)
     324void StyleResolver::State::setStyle(std::unique_ptr<RenderStyle> style)
    325325{
    326326    m_style = WTFMove(style);
     
    430430    cascade.addNormalMatches(result, 0, result.matchedProperties().size() - 1);
    431431
    432     // Resolve custom properties first.
    433     applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &result);
    434 
    435     applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &result);
     432    ApplyCascadedPropertyState applyState { this, &cascade, &result };
     433    applyCascadedProperties(firstCSSProperty, lastHighPriorityProperty, applyState);
    436434
    437435    // If our font got dirtied, update it now.
    438436    updateFont();
    439437
    440     // Now do rest of the properties.
    441     applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &result);
     438    // Now resolve remaining custom properties and the rest, in any order
     439    for (auto it = cascade.customProperties().begin(); it != cascade.customProperties().end(); ++it)
     440        applyCascadedCustomProperty(it->key, applyState);
     441    applyCascadedProperties(firstLowPriorityProperty, lastCSSProperty, applyState);
    442442
    443443    // If our font got dirtied by one of the non-essential font props, update it a second time.
    444444    updateFont();
    445445
    446     cascade.applyDeferredProperties(*this, &result);
     446    cascade.applyDeferredProperties(*this, applyState);
    447447
    448448    adjustRenderStyle(*state.style(), *state.parentStyle(), nullptr, nullptr);
     
    636636    cascade.addNormalMatches(result, 0, result.matchedProperties().size() - 1);
    637637
    638     // Resolve custom properties first.
    639     applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &result);
    640 
    641     applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &result);
     638    ApplyCascadedPropertyState applyState { this, &cascade, &result };
     639    applyCascadedProperties(firstCSSProperty, lastHighPriorityProperty, applyState);
    642640
    643641    // If our font got dirtied, update it now.
    644642    updateFont();
    645643
    646     applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &result);
    647 
    648     cascade.applyDeferredProperties(*this, &result);
     644    // Now resolve remaining custom properties and the rest, in any order
     645    for (auto it = cascade.customProperties().begin(); it != cascade.customProperties().end(); ++it)
     646        applyCascadedCustomProperty(it->key, applyState);
     647    applyCascadedProperties(firstLowPriorityProperty, lastCSSProperty, applyState);
     648
     649    cascade.applyDeferredProperties(*this, applyState);
    649650
    650651    // Now return the style.
     
    13721373        cascade.addImportantMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
    13731374
    1374         applyCascadedProperties(cascade, CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition, &matchResult);
     1375        ApplyCascadedPropertyState applyState { this, &cascade, &matchResult };
     1376
     1377        applyCascadedProperties(CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition, applyState);
    13751378        adjustStyleForInterCharacterRuby();
    13761379
    1377         // Resolve custom variables first.
    1378         applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &matchResult);
    1379 
    1380         // Start by applying properties that other properties may depend on.
    1381         applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &matchResult);
    1382 
     1380        applyCascadedProperties(firstCSSProperty, lastHighPriorityProperty, applyState);
     1381
     1382        // If our font got dirtied, update it now.
    13831383        updateFont();
    1384         applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &matchResult);
     1384
     1385        // Now resolve remaining custom properties and the rest, in any order
     1386        for (auto it = cascade.customProperties().begin(); it != cascade.customProperties().end(); ++it)
     1387            applyCascadedCustomProperty(it->key, applyState);
     1388        applyCascadedProperties(firstLowPriorityProperty, lastCSSProperty, applyState);
    13851389
    13861390        state.cacheBorderAndBackground();
     
    13931397    cascade.addImportantMatches(matchResult, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
    13941398
    1395     // Resolve custom properties first.
    1396     applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &matchResult);
    1397 
    1398     applyCascadedProperties(cascade, CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition, &matchResult);
    1399 
    1400     // Adjust the font size to be smaller if ruby-position is inter-character.
     1399
     1400    ApplyCascadedPropertyState applyState { this, &cascade, &matchResult };
     1401
     1402    applyCascadedProperties(CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition, applyState);
    14011403    adjustStyleForInterCharacterRuby();
    14021404
    1403     // Start by applying properties that other properties may depend on.
    1404     applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &matchResult);
     1405    applyCascadedProperties(firstCSSProperty, lastHighPriorityProperty, applyState);
    14051406
    14061407    // If the effective zoom value changes, we can't use the matched properties cache. Start over.
     
    14151416        return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache);
    14161417
    1417     // Apply properties that no other properties depend on.
    1418     applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &matchResult);
     1418    // Now resolve remaining custom properties and the rest, in any order
     1419    for (auto it = cascade.customProperties().begin(); it != cascade.customProperties().end(); ++it)
     1420        applyCascadedCustomProperty(it->key, applyState);
     1421    applyCascadedProperties(firstLowPriorityProperty, lastCSSProperty, applyState);
    14191422
    14201423    // Finally, some properties must be applied in the order they were parsed.
    14211424    // There are some CSS properties that affect the same RenderStyle values,
    14221425    // so to preserve behavior, we queue them up during cascade and flush here.
    1423     cascade.applyDeferredProperties(*this, &matchResult);
     1426    cascade.applyDeferredProperties(*this, applyState);
    14241427
    14251428    ASSERT(!state.fontDirty());
     
    14421445void StyleResolver::applyPropertyToCurrentStyle(CSSPropertyID id, CSSValue* value)
    14431446{
     1447    ApplyCascadedPropertyState applyState { this, nullptr, nullptr };
    14441448    if (value)
    1445         applyProperty(id, value);
     1449        applyProperty(id, value, applyState);
    14461450}
    14471451
     
    16101614}
    16111615
    1612 void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value, SelectorChecker::LinkMatchMask linkMatchMask, const MatchResult* matchResult)
    1613 {
     1616void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value, ApplyCascadedPropertyState& applyState, SelectorChecker::LinkMatchMask linkMatchMask)
     1617{
     1618    auto* matchResult = applyState.matchResult;
    16141619    ASSERT_WITH_MESSAGE(!isShorthandCSSProperty(id), "Shorthand property id = %d wasn't expanded at parsing time", id);
    16151620
     
    16181623    RefPtr<CSSValue> valueToApply = value;
    16191624    if (value->hasVariableReferences()) {
    1620         valueToApply = resolvedVariableValue(id, *value);
    1621         if (!valueToApply) {
     1625        valueToApply = resolvedVariableValue(id, *value, applyState);
     1626        // If appliedProperties already has this id, then we detected a cycle, and this value should be unset.
     1627        if (!valueToApply || applyState.appliedProperties.contains(id)) {
    16221628            if (CSSProperty::isInheritedProperty(id))
    16231629                valueToApply = CSSValuePool::singleton().createInheritedValue();
     
    16301636        CSSPropertyID newId = CSSProperty::resolveDirectionAwareProperty(id, state.style()->direction(), state.style()->writingMode());
    16311637        ASSERT(newId != id);
    1632         return applyProperty(newId, valueToApply.get(), linkMatchMask, matchResult);
     1638        return applyProperty(newId, valueToApply.get(), applyState, linkMatchMask);
    16331639    }
    16341640
     
    16411647    if (id == CSSPropertyCustom) {
    16421648        customPropertyValue = &downcast<CSSCustomPropertyValue>(*valueToApply);
    1643         customPropertyValueID = customPropertyValue->valueID();
     1649        ASSERT(customPropertyValue->isResolved());
     1650        if (WTF::holds_alternative<CSSValueID>(customPropertyValue->value()))
     1651            customPropertyValueID = WTF::get<CSSValueID>(customPropertyValue->value());
    16441652        auto& name = customPropertyValue->name();
    16451653        customPropertyRegistered = document().getCSSRegisteredCustomPropertySet().get(name);
     
    16681676                    auto property = rollback->customProperty(customPropertyValue->name());
    16691677                    if (property.cssValue[linkMatchMask])
    1670                         applyProperty(property.id, property.cssValue[linkMatchMask], linkMatchMask, matchResult);
     1678                        applyProperty(property.id, property.cssValue[linkMatchMask], applyState, linkMatchMask);
    16711679                    return;
    16721680                }
     
    16741682                auto& property = rollback->property(id);
    16751683                if (property.cssValue[linkMatchMask])
    1676                     applyProperty(property.id, property.cssValue[linkMatchMask], linkMatchMask, matchResult);
     1684                    applyProperty(property.id, property.cssValue[linkMatchMask], applyState, linkMatchMask);
    16771685                return;
    16781686            }
     
    17031711}
    17041712
    1705 RefPtr<CSSValue> StyleResolver::resolvedVariableValue(CSSPropertyID propID, const CSSValue& value) const
     1713RefPtr<CSSValue> StyleResolver::resolvedVariableValue(CSSPropertyID propID, const CSSValue& value, ApplyCascadedPropertyState& state) const
    17061714{
    17071715    CSSParser parser(document());
    1708     return parser.parseValueWithVariableReferences(propID, value, document().getCSSRegisteredCustomPropertySet(), *m_state.style());
     1716    return parser.parseValueWithVariableReferences(propID, value, state);
    17091717}
    17101718
     
    22282236}
    22292237
    2230 void StyleResolver::CascadedProperties::applyDeferredProperties(StyleResolver& resolver, const MatchResult* matchResult)
     2238void StyleResolver::CascadedProperties::applyDeferredProperties(StyleResolver& resolver, ApplyCascadedPropertyState& applyState)
    22312239{
    22322240    for (auto& property : m_deferredProperties)
    2233         property.apply(resolver, matchResult);
    2234 }
    2235 
    2236 void StyleResolver::CascadedProperties::Property::apply(StyleResolver& resolver, const MatchResult* matchResult)
     2241        property.apply(resolver, applyState);
     2242}
     2243
     2244void StyleResolver::CascadedProperties::Property::apply(StyleResolver& resolver, ApplyCascadedPropertyState& applyState)
    22372245{
    22382246    State& state = resolver.state();
     
    22432251        state.setApplyPropertyToRegularStyle(true);
    22442252        state.setApplyPropertyToVisitedLinkStyle(false);
    2245         resolver.applyProperty(id, cssValue[SelectorChecker::MatchDefault], SelectorChecker::MatchDefault, matchResult);
     2253        resolver.applyProperty(id, cssValue[SelectorChecker::MatchDefault], applyState, SelectorChecker::MatchDefault);
    22462254    }
    22472255
     
    22522260        state.setApplyPropertyToRegularStyle(true);
    22532261        state.setApplyPropertyToVisitedLinkStyle(false);
    2254         resolver.applyProperty(id, cssValue[SelectorChecker::MatchLink], SelectorChecker::MatchLink, matchResult);
     2262        resolver.applyProperty(id, cssValue[SelectorChecker::MatchLink], applyState, SelectorChecker::MatchLink);
    22552263    }
    22562264
     
    22582266        state.setApplyPropertyToRegularStyle(false);
    22592267        state.setApplyPropertyToVisitedLinkStyle(true);
    2260         resolver.applyProperty(id, cssValue[SelectorChecker::MatchVisited], SelectorChecker::MatchVisited, matchResult);
     2268        resolver.applyProperty(id, cssValue[SelectorChecker::MatchVisited], applyState, SelectorChecker::MatchVisited);
    22612269    }
    22622270
     
    22652273}
    22662274
    2267 void StyleResolver::applyCascadedProperties(CascadedProperties& cascade, int firstProperty, int lastProperty, const MatchResult* matchResult)
     2275void StyleResolver::applyCascadedCustomProperty(const String& name, ApplyCascadedPropertyState& state)
     2276{
     2277    if (state.appliedCustomProperties.contains(name) || !state.cascade->customProperties().contains(name))
     2278        return;
     2279
     2280    auto property = state.cascade->customProperties().get(name);
     2281
     2282    for (auto index : { SelectorChecker::MatchDefault, SelectorChecker::MatchLink, SelectorChecker::MatchVisited }) {
     2283        if (!property.cssValue[index])
     2284            continue;
     2285        if (index != SelectorChecker::MatchDefault && this->state().style()->insideLink() == InsideLink::NotInside)
     2286            continue;
     2287
     2288        Ref<CSSCustomPropertyValue> valueToApply = CSSCustomPropertyValue::create(downcast<CSSCustomPropertyValue>(*property.cssValue[index]));
     2289
     2290        if (state.inProgressPropertiesCustom.contains(name)) {
     2291            // We are in a cycle, so reset the value.
     2292            state.appliedCustomProperties.add(name);
     2293            // Resolve this value so that we reset its dependencies
     2294            if (WTF::holds_alternative<Ref<CSSVariableReferenceValue>>(valueToApply->value()))
     2295                resolvedVariableValue(CSSPropertyCustom, valueToApply.get(), state);
     2296            valueToApply = CSSCustomPropertyValue::createWithID(name, CSSValueUnset);
     2297        }
     2298
     2299        state.inProgressPropertiesCustom.add(name);
     2300
     2301        if (WTF::holds_alternative<Ref<CSSVariableReferenceValue>>(valueToApply->value())) {
     2302            RefPtr<CSSValue> parsedValue = resolvedVariableValue(CSSPropertyCustom, valueToApply.get(), state);
     2303
     2304            if (!parsedValue)
     2305                parsedValue = CSSCustomPropertyValue::createWithID(name, CSSValueUnset);
     2306
     2307            valueToApply = downcast<CSSCustomPropertyValue>(*parsedValue);
     2308        }
     2309
     2310        if (state.inProgressPropertiesCustom.contains(name)) {
     2311            if (index == SelectorChecker::MatchDefault) {
     2312                this->state().setApplyPropertyToRegularStyle(true);
     2313                this->state().setApplyPropertyToVisitedLinkStyle(false);
     2314            }
     2315
     2316            if (index == SelectorChecker::MatchLink) {
     2317                this->state().setApplyPropertyToRegularStyle(true);
     2318                this->state().setApplyPropertyToVisitedLinkStyle(false);
     2319            }
     2320
     2321            if (index == SelectorChecker::MatchVisited) {
     2322                this->state().setApplyPropertyToRegularStyle(false);
     2323                this->state().setApplyPropertyToVisitedLinkStyle(true);
     2324            }
     2325            applyProperty(CSSPropertyCustom, valueToApply.ptr(), state, index);
     2326        }
     2327        state.inProgressPropertiesCustom.remove(name);
     2328        state.appliedCustomProperties.add(name);
     2329    }
     2330}
     2331
     2332void StyleResolver::applyCascadedProperties(int firstProperty, int lastProperty, ApplyCascadedPropertyState& state)
    22682333{
    22692334    for (int id = firstProperty; id <= lastProperty; ++id) {
    22702335        CSSPropertyID propertyID = static_cast<CSSPropertyID>(id);
    2271         if (!cascade.hasProperty(propertyID))
     2336        if (!state.cascade->hasProperty(propertyID))
    22722337            continue;
    2273         if (propertyID == CSSPropertyCustom) {
    2274             // Apply font size first, since custom properties may rely on it for relative unit calculations
    2275             // Once it is applied and the custom property values are set, it will be applied again, which should
    2276             // handle any font-size properties that rely on registered custom properties.
    2277             // FIXME cycles should be detected.
    2278             if (cascade.hasProperty(CSSPropertyFontSize))
    2279                 cascade.property(CSSPropertyFontSize).apply(*this, matchResult);
    2280             updateFont();
    2281 
    2282             HashMap<AtomicString, CascadedProperties::Property>::iterator end = cascade.customProperties().end();
    2283             for (HashMap<AtomicString, CascadedProperties::Property>::iterator it = cascade.customProperties().begin(); it != end; ++it)
    2284                 it->value.apply(*this, matchResult);
    2285             m_state.style()->checkVariablesInCustomProperties(document().getCSSRegisteredCustomPropertySet(), m_state.parentStyle(), *this);
     2338        ASSERT(propertyID != CSSPropertyCustom);
     2339        auto& property = state.cascade->property(propertyID);
     2340        ASSERT(!shouldApplyPropertyInParseOrder(propertyID));
     2341
     2342        if (state.inProgressProperties.contains(propertyID)) {
     2343            // We are in a cycle (eg. setting font size using registered custom property value containing em)
     2344            // So this value should be unset
     2345            state.appliedProperties.add(propertyID);
     2346            // This property is in a cycle, and only the root of the call stack will have firstProperty != lastProperty.
     2347            ASSERT(firstProperty == lastProperty);
    22862348            continue;
    22872349        }
    2288         auto& property = cascade.property(propertyID);
    2289         ASSERT(!shouldApplyPropertyInParseOrder(propertyID));
    2290         property.apply(*this, matchResult);
     2350
     2351        state.inProgressProperties.add(propertyID);
     2352        property.apply(*this, state);
     2353        state.appliedProperties.add(propertyID);
     2354        state.inProgressProperties.remove(propertyID);
    22912355    }
    22922356}
  • trunk/Source/WebCore/css/StyleResolver.h

    r236828 r237347  
    268268
    269269        struct Property {
    270             void apply(StyleResolver&, const MatchResult*);
     270            void apply(StyleResolver&, ApplyCascadedPropertyState&);
    271271
    272272            CSSPropertyID id;
     
    282282        void addImportantMatches(const MatchResult&, int startIndex, int endIndex, bool inheritedOnly = false);
    283283
    284         void applyDeferredProperties(StyleResolver&, const MatchResult*);
     284        void applyDeferredProperties(StyleResolver&, ApplyCascadedPropertyState&);
    285285
    286286        HashMap<AtomicString, Property>& customProperties() { return m_customProperties; }
     
    303303        WritingMode m_writingMode;
    304304    };
    305    
     305
     306    void applyCascadedProperties(int firstProperty, int lastProperty, ApplyCascadedPropertyState&);
     307    void applyCascadedCustomProperty(const String& name, ApplyCascadedPropertyState&);
     308
    306309private:
    307310    // This function fixes up the default font size if it detects that the current generic font family has changed. -dwh
     
    322325    void applyMatchedProperties(const MatchResult&, const Element&, ShouldUseMatchedPropertiesCache = UseMatchedPropertiesCache);
    323326
    324     void applyCascadedProperties(CascadedProperties&, int firstProperty, int lastProperty, const MatchResult*);
    325327    void cascadeMatches(CascadedProperties&, const MatchResult&, bool important, int startIndex, int endIndex, bool inheritedOnly);
    326328
     
    456458    void setTextOrientation(TextOrientation textOrientation) { m_state.setTextOrientation(textOrientation); }
    457459
    458     RefPtr<CSSValue> resolvedVariableValue(CSSPropertyID, const CSSValue&) const;
     460    RefPtr<CSSValue> resolvedVariableValue(CSSPropertyID, const CSSValue&, ApplyCascadedPropertyState&) const;
    459461
    460462private:
    461463    void cacheBorderAndBackground();
    462464
    463     void applyProperty(CSSPropertyID, CSSValue*, SelectorChecker::LinkMatchMask = SelectorChecker::MatchDefault, const MatchResult* = nullptr);
     465    void applyProperty(CSSPropertyID, CSSValue*, ApplyCascadedPropertyState&, SelectorChecker::LinkMatchMask = SelectorChecker::MatchDefault);
    464466
    465467    void applySVGProperty(CSSPropertyID, CSSValue*);
     
    525527};
    526528
     529// State to use when applying properties, to keep track of which custom and high-priority
     530// properties have been resolved.
     531struct ApplyCascadedPropertyState {
     532    StyleResolver* styleResolver;
     533    StyleResolver::CascadedProperties* cascade;
     534    const StyleResolver::MatchResult* matchResult;
     535    HashSet<CSSPropertyID> appliedProperties = { };
     536    HashSet<String> appliedCustomProperties = { };
     537    HashSet<CSSPropertyID> inProgressProperties = { };
     538    HashSet<String> inProgressPropertiesCustom = { };
     539};
     540
     541
    527542inline bool StyleResolver::hasSelectorForAttribute(const Element& element, const AtomicString &attributeName) const
    528543{
  • trunk/Source/WebCore/css/parser/CSSParser.cpp

    r236828 r237347  
    4848#include "Settings.h"
    4949#include "StyleColor.h"
     50#include "StyleResolver.h"
    5051#include "StyleRule.h"
    5152#include "StyleSheetContents.h"
     
    178179}
    179180
    180 RefPtr<CSSValue> CSSParser::parseValueWithVariableReferences(CSSPropertyID propID, const CSSValue& value, const CSSRegisteredCustomPropertySet& registeredProperties, const RenderStyle& style)
    181 {
     181RefPtr<CSSValue> CSSParser::parseValueWithVariableReferences(CSSPropertyID propID, const CSSValue& value, ApplyCascadedPropertyState& state)
     182{
     183    ASSERT((propID == CSSPropertyCustom && value.isCustomPropertyValue()) || (propID != CSSPropertyCustom && !value.isCustomPropertyValue()));
     184    auto& style = *state.styleResolver->style();
    182185    auto direction = style.direction();
    183186    auto writingMode = style.writingMode();
     
    191194            shorthandID = CSSProperty::resolveDirectionAwareProperty(shorthandID, direction, writingMode);
    192195        CSSVariableReferenceValue* shorthandValue = pendingSubstitution.shorthandValue();
    193         const CSSVariableData* variableData = shorthandValue->variableDataValue();
    194         ASSERT(variableData);
    195        
    196         Vector<CSSParserToken> resolvedTokens;
    197         if (!variableData->resolveTokenRange(registeredProperties, variableData->tokens(), resolvedTokens, style))
     196
     197        auto resolvedData = shorthandValue->resolveVariableReferences(state);
     198        if (!resolvedData)
    198199            return nullptr;
     200        Vector<CSSParserToken> resolvedTokens = resolvedData->tokens();
    199201       
    200202        ParsedPropertyVector parsedProperties;
     
    210212    }
    211213
    212     const CSSVariableData* variableData = nullptr;
    213 
    214214    if (value.isVariableReferenceValue()) {
    215215        const CSSVariableReferenceValue& valueWithReferences = downcast<CSSVariableReferenceValue>(value);
    216         variableData = valueWithReferences.variableDataValue();
    217         ASSERT(variableData);
     216        auto resolvedData = valueWithReferences.resolveVariableReferences(state);
     217        if (!resolvedData)
     218            return nullptr;
     219        return CSSPropertyParser::parseSingleValue(propID, resolvedData->tokens(), m_context);
    218220    }
    219221
    220     if (value.isCustomPropertyValue()) {
    221         const CSSCustomPropertyValue& customPropValue = downcast<CSSCustomPropertyValue>(value);
    222 
    223         if (customPropValue.resolvedTypedValue())
    224             return CSSPrimitiveValue::create(*customPropValue.resolvedTypedValue(), style);
    225 
    226         variableData = customPropValue.value();
    227     }
    228 
    229     if (!variableData)
    230         return nullptr;
    231 
    232     Vector<CSSParserToken> resolvedTokens;
    233     if (!variableData->resolveTokenRange(registeredProperties, variableData->tokens(), resolvedTokens, style))
    234         return nullptr;
    235 
    236     return CSSPropertyParser::parseSingleValue(propID, resolvedTokens, m_context);
     222    const auto& customPropValue = downcast<CSSCustomPropertyValue>(value);
     223    const auto& valueWithReferences = WTF::get<Ref<CSSVariableReferenceValue>>(customPropValue.value()).get();
     224
     225    auto& name = downcast<CSSCustomPropertyValue>(value).name();
     226    auto* registered = state.styleResolver->document().getCSSRegisteredCustomPropertySet().get(name);
     227    auto& syntax = registered ? registered->syntax : "*";
     228    auto resolvedData = valueWithReferences.resolveVariableReferences(state);
     229
     230    if (!resolvedData)
     231        return nullptr;
     232
     233    // FIXME handle REM cycles.
     234    HashSet<CSSPropertyID> dependencies;
     235    CSSPropertyParser::collectParsedCustomPropertyValueDependencies(syntax, false, dependencies, resolvedData->tokens(), m_context);
     236
     237    for (auto id : dependencies)
     238        state.styleResolver->applyCascadedProperties(id, id, state);
     239
     240    return CSSPropertyParser::parseTypedCustomPropertyValue(name, syntax, resolvedData->tokens(), *state.styleResolver, m_context);
    237241}
    238242
  • trunk/Source/WebCore/css/parser/CSSParser.h

    r236828 r237347  
    3131namespace WebCore {
    3232
     33struct ApplyCascadedPropertyState;
    3334class CSSParserObserver;
    3435class CSSSelectorList;
     
    7879    void parseSelector(const String&, CSSSelectorList&);
    7980
    80     RefPtr<CSSValue> parseValueWithVariableReferences(CSSPropertyID, const CSSValue&, const CSSRegisteredCustomPropertySet&, const RenderStyle&);
     81    RefPtr<CSSValue> parseValueWithVariableReferences(CSSPropertyID, const CSSValue&, ApplyCascadedPropertyState&);
    8182
    8283    static Color parseColor(const String&, bool strict = false);
  • trunk/Source/WebCore/css/parser/CSSPropertyParser.cpp

    r237266 r237347  
    3838#include "CSSCursorImageValue.h"
    3939#include "CSSCustomIdentValue.h"
     40#include "CSSCustomPropertyValue.h"
    4041#include "CSSFontFaceSrcValue.h"
    4142#include "CSSFontFeatureValue.h"
     
    7475#include "SVGPathByteStream.h"
    7576#include "SVGPathUtilities.h"
     77#include "StyleBuilderConverter.h"
    7678#include "StylePropertyShorthand.h"
    7779#include "StylePropertyShorthandFunctions.h"
     80#include "StyleResolver.h"
    7881#include <bitset>
    7982#include <memory>
     
    214217using namespace CSSPropertyParserHelpers;
    215218
    216 CSSPropertyParser::CSSPropertyParser(const CSSParserTokenRange& range, const CSSParserContext& context, Vector<CSSProperty, 256>* parsedProperties)
     219CSSPropertyParser::CSSPropertyParser(const CSSParserTokenRange& range, const CSSParserContext& context, Vector<CSSProperty, 256>* parsedProperties, bool consumeWhitespace)
    217220    : m_range(range)
    218221    , m_context(context)
    219222    , m_parsedProperties(parsedProperties)
    220223{
    221     m_range.consumeWhitespace();
     224    if (consumeWhitespace)
     225        m_range.consumeWhitespace();
    222226}
    223227
     
    277281        return nullptr;
    278282    return value;
     283}
     284
     285bool CSSPropertyParser::canParseTypedCustomPropertyValue(const String& syntax, const CSSParserTokenRange& tokens, const CSSParserContext& context)
     286{
     287    CSSPropertyParser parser(tokens, context, nullptr);
     288    return parser.canParseTypedCustomPropertyValue(syntax);
     289}
     290
     291RefPtr<CSSCustomPropertyValue> CSSPropertyParser::parseTypedCustomPropertyValue(const String& name, const String& syntax, const CSSParserTokenRange& tokens, const StyleResolver& styleResolver, const CSSParserContext& context)
     292{
     293    CSSPropertyParser parser(tokens, context, nullptr, false);
     294    RefPtr<CSSCustomPropertyValue> value = parser.parseTypedCustomPropertyValue(name, syntax, styleResolver);
     295    if (!value || !parser.m_range.atEnd())
     296        return nullptr;
     297    return value;
     298}
     299
     300void CSSPropertyParser::collectParsedCustomPropertyValueDependencies(const String& syntax, bool isRoot, HashSet<CSSPropertyID>& dependencies, const CSSParserTokenRange& tokens, const CSSParserContext& context)
     301{
     302    CSSPropertyParser parser(tokens, context, nullptr);
     303    parser.collectParsedCustomPropertyValueDependencies(syntax, isRoot, dependencies);
    279304}
    280305
     
    321346
    322347    if (CSSVariableParser::containsValidVariableReferences(originalRange, m_context)) {
    323         RefPtr<CSSVariableReferenceValue> variable = CSSVariableReferenceValue::create(CSSVariableData::create(originalRange));
     348        RefPtr<CSSVariableReferenceValue> variable = CSSVariableReferenceValue::create(originalRange);
    324349
    325350        if (isShorthand) {
     
    38873912    case CSSPropertyWidth:
    38883913    case CSSPropertyHeight:
    3889     case CSSPropertyCustom: // FIXME: parsing a registered custom property should be based on its syntax.
    38903914        return consumeWidthOrHeight(m_range, m_context, UnitlessQuirk::Allow);
    38913915    case CSSPropertyMinInlineSize:
     
    42574281}
    42584282
     4283bool CSSPropertyParser::canParseTypedCustomPropertyValue(const String& syntax)
     4284{
     4285    if (syntax != "*") {
     4286        m_range.consumeWhitespace();
     4287
     4288        // First check for keywords
     4289        CSSValueID id = m_range.peek().id();
     4290        if (id == CSSValueInherit || id == CSSValueInitial || id == CSSValueRevert)
     4291            return true;
     4292
     4293        auto localRange = m_range;
     4294        while (!localRange.atEnd()) {
     4295            auto id = localRange.consume().functionId();
     4296            if (id == CSSValueVar || id == CSSValueEnv)
     4297                return true; // For variables, we just permit everything
     4298        }
     4299
     4300        auto primitiveVal = consumeWidthOrHeight(m_range, m_context);
     4301        if (primitiveVal && primitiveVal->isPrimitiveValue() && m_range.atEnd())
     4302            return true;
     4303        return false;
     4304    }
     4305
     4306    return true;
     4307}
     4308
     4309void CSSPropertyParser::collectParsedCustomPropertyValueDependencies(const String& syntax, bool isRoot, HashSet<CSSPropertyID>& dependencies)
     4310{
     4311    if (syntax != "*") {
     4312        m_range.consumeWhitespace();
     4313        auto primitiveVal = consumeWidthOrHeight(m_range, m_context);
     4314        if (!m_range.atEnd())
     4315            return;
     4316        if (primitiveVal && primitiveVal->isPrimitiveValue()) {
     4317            primitiveVal->collectDirectComputationalDependencies(dependencies);
     4318            if (isRoot)
     4319                primitiveVal->collectDirectRootComputationalDependencies(dependencies);
     4320        }
     4321    }
     4322}
     4323
     4324RefPtr<CSSCustomPropertyValue> CSSPropertyParser::parseTypedCustomPropertyValue(const String& name, const String& syntax, const StyleResolver& styleResolver)
     4325{
     4326    if (syntax != "*") {
     4327        m_range.consumeWhitespace();
     4328        auto primitiveVal = consumeWidthOrHeight(m_range, m_context);
     4329        if (primitiveVal && primitiveVal->isPrimitiveValue())
     4330            return CSSCustomPropertyValue::createSyntaxLength(name, StyleBuilderConverter::convertLength(styleResolver, *primitiveVal));
     4331    } else {
     4332        auto propertyValue = CSSCustomPropertyValue::createSyntaxAll(name, CSSVariableData::create(m_range));
     4333        while (!m_range.atEnd())
     4334            m_range.consume();
     4335        return { WTFMove(propertyValue) };
     4336    }
     4337
     4338    return nullptr;
     4339}
     4340
    42594341static RefPtr<CSSValueList> consumeFontFaceUnicodeRange(CSSParserTokenRange& range)
    42604342{
  • trunk/Source/WebCore/css/parser/CSSPropertyParser.h

    r237266 r237347  
    3333class StylePropertyShorthand;
    3434class StyleSheetContents;
     35class StyleResolver;
    3536   
    3637// Inputs: PropertyID, isImportant bool, CSSParserTokenRange.
     
    4647    // Parses a non-shorthand CSS property
    4748    static RefPtr<CSSValue> parseSingleValue(CSSPropertyID, const CSSParserTokenRange&, const CSSParserContext&);
     49    static bool canParseTypedCustomPropertyValue(const String& syntax, const CSSParserTokenRange&, const CSSParserContext&);
     50    static RefPtr<CSSCustomPropertyValue> parseTypedCustomPropertyValue(const String& name, const String& syntax, const CSSParserTokenRange&, const StyleResolver&, const CSSParserContext&);
     51    static void collectParsedCustomPropertyValueDependencies(const String& syntax, bool isRoot, HashSet<CSSPropertyID>& dependencies, const CSSParserTokenRange&, const CSSParserContext&);
    4852
    4953private:
    50     CSSPropertyParser(const CSSParserTokenRange&, const CSSParserContext&, Vector<CSSProperty, 256>*);
     54    CSSPropertyParser(const CSSParserTokenRange&, const CSSParserContext&, Vector<CSSProperty, 256>*, bool consumeWhitespace = true);
    5155
    5256    // FIXME: Rename once the CSSParserValue-based parseValue is removed
     
    5458    bool consumeCSSWideKeyword(CSSPropertyID, bool important);
    5559    RefPtr<CSSValue> parseSingleValue(CSSPropertyID, CSSPropertyID = CSSPropertyInvalid);
     60    bool canParseTypedCustomPropertyValue(const String& syntax);
     61    RefPtr<CSSCustomPropertyValue> parseTypedCustomPropertyValue(const String& name, const String& syntax, const StyleResolver&);
     62    void collectParsedCustomPropertyValueDependencies(const String& syntax, bool isRoot, HashSet<CSSPropertyID>& dependencies);
    5663
    5764    bool inQuirksMode() const { return m_context.mode == HTMLQuirksMode; }
  • trunk/Source/WebCore/css/parser/CSSVariableParser.cpp

    r233520 r237347  
    190190        return nullptr;
    191191    if (type == CSSValueInternalVariableValue)
    192         return CSSCustomPropertyValue::createWithVariableData(variableName, CSSVariableData::create(range, hasReferences || hasAtApplyRule));
    193     return CSSCustomPropertyValue::createWithID(variableName, type);
     192        return CSSCustomPropertyValue::createUnresolved(variableName, CSSVariableReferenceValue::create(range));
     193    return CSSCustomPropertyValue::createUnresolved(variableName, type);
    194194}
    195195
  • trunk/Source/WebCore/dom/ConstantPropertyMap.cpp

    r234098 r237347  
    9191
    9292    auto& name = nameForProperty(property);
    93     m_values->set(name, CSSCustomPropertyValue::createWithVariableData(name, WTFMove(data)));
     93    m_values->set(name, CSSCustomPropertyValue::createSyntaxAll(name, WTFMove(data)));
    9494}
    9595
     
    111111    Vector<CSSParserToken> tokens { token };
    112112    CSSParserTokenRange tokenRange(tokens);
    113     return CSSVariableData::create(tokenRange, false);
     113    return CSSVariableData::create(tokenRange);
    114114}
    115115
     
    123123    Vector<CSSParserToken> tokens { token };
    124124    CSSParserTokenRange tokenRange(tokens);
    125     return CSSVariableData::create(tokenRange, false);
     125    return CSSVariableData::create(tokenRange);
    126126}
    127127
  • trunk/Source/WebCore/rendering/style/RenderStyle.cpp

    r236828 r237347  
    23002300}
    23012301
    2302 void RenderStyle::checkVariablesInCustomProperties(const CSSRegisteredCustomPropertySet& registeredProperties, const RenderStyle* parentStyle, const StyleResolver& styleResolver)
    2303 {
    2304     bool shouldUpdateInherited = m_rareInheritedData->customProperties->containsVariables || m_rareInheritedData->customProperties->containsUnresolvedRegisteredProperties;
    2305     bool shouldUpdateNonInherited = m_rareNonInheritedData->customProperties->containsVariables || m_rareNonInheritedData->customProperties->containsUnresolvedRegisteredProperties;
    2306     auto* inheritedPropertyData = shouldUpdateInherited ? &m_rareInheritedData.access().customProperties.access() : nullptr;
    2307     auto* nonInheritedPropertyData = shouldUpdateNonInherited ? &m_rareNonInheritedData.access().customProperties.access() : nullptr;
    2308 
    2309     HashSet<AtomicString> invalidProperties;
    2310 
    2311     for (auto* customPropertyData : { inheritedPropertyData, nonInheritedPropertyData }) {
    2312         if (!customPropertyData)
    2313             continue;
    2314 
    2315         // Our first pass checks the variables for validity and replaces any properties that became
    2316         // invalid with empty values.
    2317         auto& customProperties = customPropertyData->values;
    2318         for (auto& entry : customProperties) {
    2319             if (!entry.value->containsVariables())
    2320                 continue;
    2321             HashSet<AtomicString> seenProperties;
    2322             entry.value->checkVariablesForCycles(entry.key, *this, seenProperties, invalidProperties);
    2323         }
    2324 
    2325         auto invalidValue = CSSCustomPropertyValue::createInvalid();
    2326 
    2327         // Now insert invalid values, or defaults if the property is registered.
    2328         if (!invalidProperties.isEmpty()) {
    2329             for (auto& property : invalidProperties) {
    2330                 if (!customProperties.contains(property))
    2331                     continue;
    2332                
    2333                 const RefPtr<CSSCustomPropertyValue>* parentProperty = nullptr;
    2334                 if (parentStyle) {
    2335                     auto iterator = parentStyle->inheritedCustomProperties().find(property);
    2336                     if (iterator != parentStyle->inheritedCustomProperties().end() && iterator.get() && iterator.get()->value)
    2337                         parentProperty = &iterator.get()->value;
    2338                 }
    2339 
    2340                 auto* registered = registeredProperties.get(property);
    2341 
    2342                 if (registered && registered->inherits && parentProperty)
    2343                     customProperties.set(property, parentProperty->copyRef());
    2344                 else if (registered && registered->initialValue())
    2345                     customProperties.set(property, registered->initialValueCopy());
    2346                 else
    2347                     customProperties.set(property, invalidValue.copyRef());
    2348             }
    2349         }
    2350 
    2351         // Now that all of the properties have been tested for validity and replaced with
    2352         // invalid values if they failed, we can perform variable substitution on the valid values.
    2353         Vector<Ref<CSSCustomPropertyValue>> resolvedValues;
    2354         for (auto entry : customProperties) {
    2355             if (!entry.value->containsVariables())
    2356                 continue;
    2357             entry.value->resolveVariableReferences(registeredProperties, resolvedValues, *this);
    2358         }
    2359 
    2360         // With all results computed, we can now mutate our table to eliminate the variables and
    2361         // hold the final values. This way when we inherit, we don't end up resubstituting variables, etc.
    2362         for (auto& resolvedValue : resolvedValues)
    2363             customProperties.set(resolvedValue->name(), resolvedValue.copyRef());
    2364 
    2365         // Finally we can resolve registered custom properties to their typed values.
    2366         for (auto& entry : customProperties) {
    2367             auto& name = entry.value->name();
    2368             auto* registered = registeredProperties.get(name);
    2369 
    2370             if (!registered)
    2371                 continue;
    2372 
    2373             auto primitiveVal = styleResolver.resolvedVariableValue(CSSPropertyCustom, *entry.value);
    2374             if (!primitiveVal || !primitiveVal->isPrimitiveValue())
    2375                 entry.value = invalidValue.copyRef();
    2376             else
    2377                 entry.value->setResolvedTypedValue(StyleBuilderConverter::convertLength(styleResolver, *primitiveVal));
    2378         }
    2379 
    2380         customPropertyData->containsVariables = false;
    2381         customPropertyData->containsUnresolvedRegisteredProperties = false;
    2382     }
    2383 }
    2384 
    23852302float RenderStyle::outlineWidth() const
    23862303{
  • trunk/Source/WebCore/rendering/style/RenderStyle.h

    r237266 r237347  
    187187    const CustomPropertyValueMap& nonInheritedCustomProperties() const { return m_rareNonInheritedData->customProperties->values; }
    188188    const CSSCustomPropertyValue* getCustomProperty(const AtomicString&) const;
    189     void setInheritedCustomPropertyValue(const AtomicString& name, Ref<CSSCustomPropertyValue>&& value, bool isRegistered = false) { return m_rareInheritedData.access().customProperties.access().setCustomPropertyValue(name, WTFMove(value), isRegistered); }
    190     void setNonInheritedCustomPropertyValue(const AtomicString& name, Ref<CSSCustomPropertyValue>&& value, bool isRegistered = false) { return m_rareNonInheritedData.access().customProperties.access().setCustomPropertyValue(name, WTFMove(value), isRegistered); }
     189    void setInheritedCustomPropertyValue(const AtomicString& name, Ref<CSSCustomPropertyValue>&& value) { return m_rareInheritedData.access().customProperties.access().setCustomPropertyValue(name, WTFMove(value)); }
     190    void setNonInheritedCustomPropertyValue(const AtomicString& name, Ref<CSSCustomPropertyValue>&& value) { return m_rareNonInheritedData.access().customProperties.access().setCustomPropertyValue(name, WTFMove(value)); }
    191191
    192192    void setHasViewportUnits(bool v = true) { m_nonInheritedFlags.hasViewportUnits = v; }
     
    795795    ApplePayButtonType applePayButtonType() const { return static_cast<ApplePayButtonType>(m_rareNonInheritedData->applePayButtonType); }
    796796#endif
    797 
    798     void checkVariablesInCustomProperties(const CSSRegisteredCustomPropertySet&, const RenderStyle* parentStyle, const StyleResolver&);
    799797
    800798// attribute setter methods
  • trunk/Source/WebCore/rendering/style/StyleCustomPropertyData.h

    r236828 r237347  
    2323
    2424#include "CSSCustomPropertyValue.h"
     25#include "CSSVariableReferenceValue.h"
    2526#include <wtf/Forward.h>
    2627#include <wtf/HashMap.h>
     
    3839    bool operator==(const StyleCustomPropertyData& other) const
    3940    {
    40         if (containsVariables != other.containsVariables)
    41             return false;
    42 
    4341        if (values.size() != other.values.size())
    4442            return false;
     
    5553    bool operator!=(const StyleCustomPropertyData& other) const { return !(*this == other); }
    5654   
    57     void setCustomPropertyValue(const AtomicString& name, Ref<CSSCustomPropertyValue>&& value, bool isRegistered)
     55    void setCustomPropertyValue(const AtomicString& name, Ref<CSSCustomPropertyValue>&& value)
    5856    {
    59         if (value->containsVariables())
    60             containsVariables = true;
    61         if (isRegistered)
    62             containsUnresolvedRegisteredProperties = true;
    6357        values.set(name, WTFMove(value));
    6458    }
    6559
    6660    CustomPropertyValueMap values;
    67     bool containsVariables { false };
    68     bool containsUnresolvedRegisteredProperties { false };
    6961
    7062private:
     
    7365        : RefCounted<StyleCustomPropertyData>()
    7466        , values(other.values)
    75         , containsVariables(other.containsVariables)
    76         , containsUnresolvedRegisteredProperties(other.containsUnresolvedRegisteredProperties)
    7767    { }
    7868};
Note: See TracChangeset for help on using the changeset viewer.