Changeset 191128 in webkit


Ignore:
Timestamp:
Oct 15, 2015, 12:48:58 PM (10 years ago)
Author:
hyatt@apple.com
Message:

Implement CSS Variables.
https://bugs.webkit.org/show_bug.cgi?id=19660

Reviewed by Dean Jackson.

Source/WebCore:

Added new tests in fast/css/custom-properties and fast/css/variables.

  • CMakeLists.txt:
  • WebCore.xcodeproj/project.pbxproj:

Add CSSVariableValue.cpp and CSSVariableDependentValue.cpp to builds.

  • css/CSSCalculationValue.cpp:

(WebCore::hasDoubleValue):
Handle the new CSS_PARSER_WHITESPACE value.

  • css/CSSComputedStyleDeclaration.cpp:

(WebCore::ComputedStyleExtractor::customPropertyValue):
Patched to make sure style is updated so that dynamic changes to custom properties are reflected
immediately when querying values.

(WebCore::CSSComputedStyleDeclaration::length):
(WebCore::CSSComputedStyleDeclaration::item):
The custom properties table is a reference and not a pointer now.

  • css/CSSCustomPropertyValue.h:

(WebCore::CSSCustomPropertyValue::create):
(WebCore::CSSCustomPropertyValue::createInvalid):
(WebCore::CSSCustomPropertyValue::customCSSText):
(WebCore::CSSCustomPropertyValue::equals):
(WebCore::CSSCustomPropertyValue::isInvalid):
(WebCore::CSSCustomPropertyValue::containsVariables):
(WebCore::CSSCustomPropertyValue::value):
(WebCore::CSSCustomPropertyValue::CSSCustomPropertyValue):
The CSSCustomPropertyValue represents a custom property/value pair in the back end. It holds on
to both the property name and a CSSValueList that has the original parser terms. This class also
doubles as the invalid-at-compute-time value for custom properties when they contain cycles, etc.

  • css/CSSFunctionValue.cpp:

(WebCore::CSSFunctionValue::buildParserValueSubstitutingVariables):

  • css/CSSFunctionValue.h:

(WebCore::CSSFunctionValue::buildParserValueSubstitutingVariables):
Hands back a CSSParserValue for a function with variables replaced with their real values (or fallback).

  • css/CSSGrammar.y.in:

Many changes to support the var() syntax and to handle error conditions and cases.

  • css/CSSParser.cpp:

(WebCore::filterProperties):
Null check the value here. Shouldn't happen, but being paranoid.

(WebCore::CSSParser::parseVariableDependentValue):
This function converts a CSSValueList back into a CSSParserValueList and then passes
it off to the parser. If the result parses, successfully, then the parsed CSSValue is handed back.

(WebCore::CSSParser::parseValue):
Detect when a property value contains variables and simply make a CSSVariableDependentValue to hold
a copy of the parser value list (as a CSSValueList). We defer parsing the list until compute-time
when we know the values of the variables to use.

(WebCore::CSSParser::parseCustomPropertyDeclaration):
Add support for inherit, initial and variable references in custom properties.

(WebCore::CSSParser::detectFunctionTypeToken):
Add support for detection of the "var" token.

(WebCore::CSSParser::realLex):
Fix the parsing of custom properties to allow "--" and to allow them to start with digits, e.g., "--0".

  • css/CSSParser.h:

Add parseVariableDependentValue function for handling variable substitution and subsequent parsing
of the resolved parser value list.

  • css/CSSParserValues.cpp:

(WebCore::CSSParserValueList::containsVariables):
Get rid of the toString() function (no longer needed) and replace it with containsVariables(). This
check is used to figure out if a parser value list has variables and thus needs to defer parsing
until later.

(WebCore::CSSParserValue::createCSSValue):
Add support for the creation of values for variables, CSSVariableValues.

(WebCore::CSSParserValueList::toString): Deleted.
No longer needed.

  • css/CSSParserValues.h:

Add CSSParserVariable as a new kind of parser value. This represents a var() that is encountered
during parsing. It is similar to a function except it has to hold both the reference (custom property name)
and fallback arguments.

  • css/CSSPrimitiveValue.cpp:

(WebCore::isValidCSSUnitTypeForDoubleConversion):
(WebCore::CSSPrimitiveValue::cleanup):
(WebCore::CSSPrimitiveValue::formatNumberForCustomCSSText):
(WebCore::CSSPrimitiveValue::cloneForCSSOM):
(WebCore::CSSPrimitiveValue::equals):
Add support for CSS_PARSER_WHITESPACE as a way of preserving whitespace as a parsed item (variables can
be only whitespace, and this has to be retained).

(WebCore::CSSPrimitiveValue::buildParserValue):
Conversion from a CSSPrimitiveValue back into a parser value is handled by this function.

  • css/CSSPrimitiveValue.h:

(WebCore::CSSPrimitiveValue::isParserOperator):
(WebCore::CSSPrimitiveValue::parserOperator):
Add ability to get parser operator info. Add the buildParserValue declaration.

  • css/CSSValue.cpp:

(WebCore::CSSValue::equals):
(WebCore::CSSValue::cssText):
(WebCore::CSSValue::destroy):
(WebCore::CSSValue::cloneForCSSOM):
(WebCore::CSSValue::isInvalidCustomPropertyValue):

  • css/CSSValue.h:

Add support for variable values and variable dependent values.

  • css/CSSValueList.cpp:

(WebCore::CSSValueList::customCSSText):
Improve serialization to not output extra spaces when a comma operator is a value.

(WebCore::CSSValueList::containsVariables):
Whether or not a CSSVariableValue can be found somewhere within the list (or its descendants).

(WebCore::CSSValueList::checkVariablesForCycles):
Called to check variables for cycles.

(WebCore::CSSValueList::buildParserValueSubstitutingVariables):
(WebCore::CSSValueList::buildParserValueListSubstitutingVariables):
Functions that handle converting the value list to a parser value list while making
variable substitutions along the way.

  • css/CSSValueList.h:

Add the new buildParserXXX functions.

  • css/CSSVariableDependentValue.cpp: Added.

(WebCore::CSSVariableDependentValue::checkVariablesForCycles):

  • css/CSSVariableDependentValue.h: Added.

(WebCore::CSSVariableDependentValue::create):
(WebCore::CSSVariableDependentValue::customCSSText):
(WebCore::CSSVariableDependentValue::equals):
(WebCore::CSSVariableDependentValue::propertyID):
(WebCore::CSSVariableDependentValue::valueList):
(WebCore::CSSVariableDependentValue::CSSVariableDependentValue):
This value represents a list of terms that have not had variables substituted yet. The list
is held by the value so that it can be converted back into a parser value list once the
variable values are known.

  • css/CSSVariableValue.cpp: Added.

(WebCore::CSSVariableValue::CSSVariableValue):
(WebCore::CSSVariableValue::customCSSText):
(WebCore::CSSVariableValue::equals):
(WebCore::CSSVariableValue::buildParserValueListSubstitutingVariables):

  • css/CSSVariableValue.h: Added.

(WebCore::CSSVariableValue::create):
(WebCore::CSSVariableValue::name):
(WebCore::CSSVariableValue::fallbackArguments):
This value represents a var() itself. It knows how to do the substitution of the variable
value and to apply fallback if that value is not present.

  • css/StyleProperties.cpp:

(WebCore::StyleProperties::getPropertyValue):
(WebCore::StyleProperties::borderSpacingValue):
(WebCore::StyleProperties::getLayeredShorthandValue):
(WebCore::StyleProperties::getShorthandValue):
(WebCore::StyleProperties::getCommonValue):
(WebCore::StyleProperties::getPropertyCSSValue):
(WebCore::StyleProperties::getPropertyCSSValueInternal):
(WebCore::StyleProperties::asText):
(WebCore::StyleProperties::copyPropertiesInSet):

  • css/StyleProperties.h:

Patched to factor property fetching into an internal method so that variables can work with shorthands
in the CSS OM.

  • css/StyleResolver.cpp:

(WebCore::StyleResolver::applyProperty):
Resolve variable values at compute time. If they fail to resolve, use inherit or initial as the
value (depending on whether the property inherits by default).

(WebCore::StyleResolver::resolvedVariableValue):
Helper function that calls parseVariableDependentValue and gets the resolved result.

(WebCore::StyleResolver::applyCascadedProperties):
After custom properties have been collected, we check for cycles and perform variable substitutions.
This way we get all the variables replaced before we inherit down the style tree.

  • css/StyleResolver.h:

Add resolvedVariableValue declaration.

  • css/makeprop.pl:

Make sure custom properties are inherited by default.

  • rendering/style/RenderStyle.cpp:

(WebCore::RenderStyle::checkVariablesInCustomProperties):
This function handles updating variables with cycles to be invalid in the RenderStyle. It then also
handles the replacement of variables found in custom properties with resolved values. All custom
properties are either invalid or are real non-variable-dependent value lists after this function
completes.

  • rendering/style/RenderStyle.h:

Add checkVariablesInCustomProperties declaration.

  • rendering/style/StyleCustomPropertyData.h:

(WebCore::StyleCustomPropertyData::create):
(WebCore::StyleCustomPropertyData::copy):
(WebCore::StyleCustomPropertyData::operator==):
(WebCore::StyleCustomPropertyData::operator!=):
(WebCore::StyleCustomPropertyData::setCustomPropertyValue):
(WebCore::StyleCustomPropertyData::getCustomPropertyValue):
(WebCore::StyleCustomPropertyData::values):
(WebCore::StyleCustomPropertyData::hasCustomProperty):
(WebCore::StyleCustomPropertyData::containsVariables):
(WebCore::StyleCustomPropertyData::setContainsVariables):
(WebCore::StyleCustomPropertyData::StyleCustomPropertyData):
Miscellaneous cleanup, and the addition of whether or not the properties still contain variable
dependent values that need to be resolved.

LayoutTests:

  • fast/css/custom-properties/inheritance-expected.html: Added.
  • fast/css/custom-properties/inheritance.html: Added.
  • fast/css/variables: Added.
  • fast/css/variables/custom-property-computed-style-access-expected.html: Added.
  • fast/css/variables/custom-property-computed-style-access.html: Added.
  • fast/css/variables/custom-property-dynamic-update-expected.html: Added.
  • fast/css/variables/custom-property-dynamic-update.html: Added.
  • fast/css/variables/custom-property-simple-cycle-expected.html: Added.
  • fast/css/variables/custom-property-simple-cycle.html: Added.
  • fast/css/variables/inherited-fallback-expected.html: Added.
  • fast/css/variables/inherited-fallback.html: Added.
  • fast/css/variables/invalid-reference-expected.html: Added.
  • fast/css/variables/invalid-reference.html: Added.
  • fast/css/variables/rule-property-get-css-value-expected.html: Added.
  • fast/css/variables/rule-property-get-css-value.html: Added.
  • fast/css/variables/rule-property-get-expected.html: Added.
  • fast/css/variables/rule-property-get.html: Added.
  • fast/css/variables/rule-serialization-expected.html: Added.
  • fast/css/variables/rule-serialization.html: Added.
Location:
trunk
Files:
380 added
29 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r191124 r191128  
     12015-10-14  David Hyatt  <hyatt@apple.com>
     2
     3        Implement CSS Variables.
     4        https://bugs.webkit.org/show_bug.cgi?id=19660
     5
     6        Reviewed by Dean Jackson.
     7
     8        * fast/css/custom-properties/inheritance-expected.html: Added.
     9        * fast/css/custom-properties/inheritance.html: Added.
     10        * fast/css/variables: Added.
     11        * fast/css/variables/custom-property-computed-style-access-expected.html: Added.
     12        * fast/css/variables/custom-property-computed-style-access.html: Added.
     13        * fast/css/variables/custom-property-dynamic-update-expected.html: Added.
     14        * fast/css/variables/custom-property-dynamic-update.html: Added.
     15        * fast/css/variables/custom-property-simple-cycle-expected.html: Added.
     16        * fast/css/variables/custom-property-simple-cycle.html: Added.
     17        * fast/css/variables/inherited-fallback-expected.html: Added.
     18        * fast/css/variables/inherited-fallback.html: Added.
     19        * fast/css/variables/invalid-reference-expected.html: Added.
     20        * fast/css/variables/invalid-reference.html: Added.
     21        * fast/css/variables/rule-property-get-css-value-expected.html: Added.
     22        * fast/css/variables/rule-property-get-css-value.html: Added.
     23        * fast/css/variables/rule-property-get-expected.html: Added.
     24        * fast/css/variables/rule-property-get.html: Added.
     25        * fast/css/variables/rule-serialization-expected.html: Added.
     26        * fast/css/variables/rule-serialization.html: Added.
     27
    1282015-10-15  Ryan Haddad  <ryanhaddad@apple.com>
    229
  • trunk/LayoutTests/TestExpectations

    r191076 r191128  
    668668
    669669webkit.org/b/148922 svg/as-object/svg-in-object-dynamic-attribute-change.html [ Pass ImageOnlyFailure ]
    670 
    671670webkit.org/b/148925 svg/dom/svg-root-lengths.html [ Pass Failure ]
    672671
     
    678677
    679678http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-overrides.html [ Failure Pass ]
     679
     680# Known failures on CSS Variables Test Suite
     681webkit.org/b/150183 fast/css/variables/test-suite/failures/024.html [ ImageOnlyFailure ]
     682webkit.org/b/150183 fast/css/variables/test-suite/failures/025.html [ ImageOnlyFailure ]
     683webkit.org/b/150183 fast/css/variables/test-suite/failures/026.html [ ImageOnlyFailure ]
     684webkit.org/b/150183 fast/css/variables/test-suite/failures/028.html [ ImageOnlyFailure ]
     685webkit.org/b/150183 fast/css/variables/test-suite/failures/030.html [ ImageOnlyFailure ]
     686webkit.org/b/150183 fast/css/variables/test-suite/failures/054.html [ ImageOnlyFailure ]
     687webkit.org/b/150183 fast/css/variables/test-suite/failures/055.html [ ImageOnlyFailure ]
     688webkit.org/b/150183 fast/css/variables/test-suite/failures/056.html [ ImageOnlyFailure ]
     689webkit.org/b/150183 fast/css/variables/test-suite/failures/058.html [ ImageOnlyFailure ]
     690webkit.org/b/150183 fast/css/variables/test-suite/failures/071.html [ ImageOnlyFailure ]
     691webkit.org/b/150183 fast/css/variables/test-suite/failures/081.html [ ImageOnlyFailure ]
     692webkit.org/b/150183 fast/css/variables/test-suite/failures/082.html [ ImageOnlyFailure ]
     693webkit.org/b/150183 fast/css/variables/test-suite/failures/085.html [ ImageOnlyFailure ]
     694webkit.org/b/150183 fast/css/variables/test-suite/failures/086.html [ ImageOnlyFailure ]
     695webkit.org/b/150183 fast/css/variables/test-suite/failures/087.html [ ImageOnlyFailure ]
     696webkit.org/b/150183 fast/css/variables/test-suite/failures/091.html [ ImageOnlyFailure ]
     697webkit.org/b/150183 fast/css/variables/test-suite/failures/103.html [ ImageOnlyFailure ]
     698webkit.org/b/150183 fast/css/variables/test-suite/failures/111.html [ ImageOnlyFailure ]
     699webkit.org/b/150183 fast/css/variables/test-suite/failures/115.html [ ImageOnlyFailure ]
     700webkit.org/b/150183 fast/css/variables/test-suite/failures/126.html [ ImageOnlyFailure ]
     701webkit.org/b/150183 fast/css/variables/test-suite/failures/129.html [ ImageOnlyFailure ]
     702webkit.org/b/150183 fast/css/variables/test-suite/failures/130.html [ ImageOnlyFailure ]
     703webkit.org/b/150183 fast/css/variables/test-suite/failures/134.html [ ImageOnlyFailure ]
     704webkit.org/b/150183 fast/css/variables/test-suite/failures/152.html [ ImageOnlyFailure ]
     705webkit.org/b/150183 fast/css/variables/test-suite/failures/159.html [ ImageOnlyFailure ]
     706webkit.org/b/150183 fast/css/variables/test-suite/failures/161.html [ ImageOnlyFailure ]
     707webkit.org/b/150183 fast/css/variables/test-suite/failures/163.html [ ImageOnlyFailure ]
     708webkit.org/b/150183 fast/css/variables/test-suite/failures/169.html [ ImageOnlyFailure ]
  • trunk/Source/WebCore/CMakeLists.txt

    r190983 r191128  
    13531353    css/CSSValueList.cpp
    13541354    css/CSSValuePool.cpp
     1355    css/CSSVariableDependentValue.cpp
     1356    css/CSSVariableValue.cpp
    13551357    css/DOMWindowCSS.cpp
    13561358    css/DocumentRuleSets.cpp
  • trunk/Source/WebCore/ChangeLog

    r191127 r191128  
     12015-10-14  David Hyatt  <hyatt@apple.com>
     2
     3        Implement CSS Variables.
     4        https://bugs.webkit.org/show_bug.cgi?id=19660
     5
     6        Reviewed by Dean Jackson.
     7
     8        Added new tests in fast/css/custom-properties and fast/css/variables.
     9
     10        * CMakeLists.txt:
     11        * WebCore.xcodeproj/project.pbxproj:
     12        Add CSSVariableValue.cpp and CSSVariableDependentValue.cpp to builds.
     13
     14        * css/CSSCalculationValue.cpp:
     15        (WebCore::hasDoubleValue):
     16        Handle the new CSS_PARSER_WHITESPACE value.
     17
     18        * css/CSSComputedStyleDeclaration.cpp:
     19        (WebCore::ComputedStyleExtractor::customPropertyValue):
     20        Patched to make sure style is updated so that dynamic changes to custom properties are reflected
     21        immediately when querying values.
     22
     23        (WebCore::CSSComputedStyleDeclaration::length):
     24        (WebCore::CSSComputedStyleDeclaration::item):
     25        The custom properties table is a reference and not a pointer now.
     26
     27        * css/CSSCustomPropertyValue.h:
     28        (WebCore::CSSCustomPropertyValue::create):
     29        (WebCore::CSSCustomPropertyValue::createInvalid):
     30        (WebCore::CSSCustomPropertyValue::customCSSText):
     31        (WebCore::CSSCustomPropertyValue::equals):
     32        (WebCore::CSSCustomPropertyValue::isInvalid):
     33        (WebCore::CSSCustomPropertyValue::containsVariables):
     34        (WebCore::CSSCustomPropertyValue::value):
     35        (WebCore::CSSCustomPropertyValue::CSSCustomPropertyValue):
     36        The CSSCustomPropertyValue represents a custom property/value pair in the back end. It holds on
     37        to both the property name and a CSSValueList that has the original parser terms. This class also
     38        doubles as the invalid-at-compute-time value for custom properties when they contain cycles, etc.
     39
     40        * css/CSSFunctionValue.cpp:
     41        (WebCore::CSSFunctionValue::buildParserValueSubstitutingVariables):
     42         * css/CSSFunctionValue.h:
     43        (WebCore::CSSFunctionValue::buildParserValueSubstitutingVariables):
     44        Hands back a CSSParserValue for a function with variables replaced with their real values (or fallback).
     45
     46        * css/CSSGrammar.y.in:
     47        Many changes to support the var() syntax and to handle error conditions and cases.
     48
     49        * css/CSSParser.cpp:
     50        (WebCore::filterProperties):
     51        Null check the value here. Shouldn't happen, but being paranoid.
     52
     53        (WebCore::CSSParser::parseVariableDependentValue):
     54        This function converts a CSSValueList back into a CSSParserValueList and then passes
     55        it off to the parser. If the result parses, successfully, then the parsed CSSValue is handed back.
     56
     57        (WebCore::CSSParser::parseValue):
     58        Detect when a property value contains variables and simply make a CSSVariableDependentValue to hold
     59        a copy of the parser value list (as a CSSValueList). We defer parsing the list until compute-time
     60        when we know the values of the variables to use.
     61
     62        (WebCore::CSSParser::parseCustomPropertyDeclaration):
     63        Add support for inherit, initial and variable references in custom properties.
     64
     65        (WebCore::CSSParser::detectFunctionTypeToken):
     66        Add support for detection of the "var" token.
     67
     68        (WebCore::CSSParser::realLex):
     69        Fix the parsing of custom properties to allow "--" and to allow them to start with digits, e.g., "--0".
     70
     71        * css/CSSParser.h:
     72        Add parseVariableDependentValue function for handling variable substitution and subsequent parsing
     73        of the resolved parser value list.
     74
     75        * css/CSSParserValues.cpp:
     76        (WebCore::CSSParserValueList::containsVariables):
     77        Get rid of the toString() function (no longer needed) and replace it with containsVariables(). This
     78        check is used to figure out if a parser value list has variables and thus needs to defer parsing
     79        until later.
     80
     81        (WebCore::CSSParserValue::createCSSValue):
     82        Add support for the creation of values for variables, CSSVariableValues.
     83
     84        (WebCore::CSSParserValueList::toString): Deleted.
     85        No longer needed.
     86
     87        * css/CSSParserValues.h:
     88        Add CSSParserVariable as a new kind of parser value. This represents a var() that is encountered
     89        during parsing. It is similar to a function except it has to hold both the reference (custom property name)
     90        and fallback arguments.
     91
     92        * css/CSSPrimitiveValue.cpp:
     93        (WebCore::isValidCSSUnitTypeForDoubleConversion):
     94        (WebCore::CSSPrimitiveValue::cleanup):
     95        (WebCore::CSSPrimitiveValue::formatNumberForCustomCSSText):
     96        (WebCore::CSSPrimitiveValue::cloneForCSSOM):
     97        (WebCore::CSSPrimitiveValue::equals):
     98        Add support for CSS_PARSER_WHITESPACE as a way of preserving whitespace as a parsed item (variables can
     99        be only whitespace, and this has to be retained).
     100
     101        (WebCore::CSSPrimitiveValue::buildParserValue):
     102        Conversion from a CSSPrimitiveValue back into a parser value is handled by this function.
     103
     104        * css/CSSPrimitiveValue.h:
     105        (WebCore::CSSPrimitiveValue::isParserOperator):
     106        (WebCore::CSSPrimitiveValue::parserOperator):
     107        Add ability to get parser operator info. Add the buildParserValue declaration.
     108
     109        * css/CSSValue.cpp:
     110        (WebCore::CSSValue::equals):
     111        (WebCore::CSSValue::cssText):
     112        (WebCore::CSSValue::destroy):
     113        (WebCore::CSSValue::cloneForCSSOM):
     114        (WebCore::CSSValue::isInvalidCustomPropertyValue):
     115        * css/CSSValue.h:
     116        Add support for variable values and variable dependent values.
     117
     118        * css/CSSValueList.cpp:
     119        (WebCore::CSSValueList::customCSSText):
     120        Improve serialization to not output extra spaces when a comma operator is a value.
     121
     122        (WebCore::CSSValueList::containsVariables):
     123        Whether or not a CSSVariableValue can be found somewhere within the list (or its descendants).
     124
     125        (WebCore::CSSValueList::checkVariablesForCycles):
     126        Called to check variables for cycles.
     127
     128        (WebCore::CSSValueList::buildParserValueSubstitutingVariables):
     129        (WebCore::CSSValueList::buildParserValueListSubstitutingVariables):
     130        Functions that handle converting the value list to a parser value list while making
     131        variable substitutions along the way.
     132
     133        * css/CSSValueList.h:
     134        Add the new buildParserXXX functions.
     135
     136        * css/CSSVariableDependentValue.cpp: Added.
     137        (WebCore::CSSVariableDependentValue::checkVariablesForCycles):
     138        * css/CSSVariableDependentValue.h: Added.
     139        (WebCore::CSSVariableDependentValue::create):
     140        (WebCore::CSSVariableDependentValue::customCSSText):
     141        (WebCore::CSSVariableDependentValue::equals):
     142        (WebCore::CSSVariableDependentValue::propertyID):
     143        (WebCore::CSSVariableDependentValue::valueList):
     144        (WebCore::CSSVariableDependentValue::CSSVariableDependentValue):
     145        This value represents a list of terms that have not had variables substituted yet. The list
     146        is held by the value so that it can be converted back into a parser value list once the
     147        variable values are known.
     148
     149        * css/CSSVariableValue.cpp: Added.
     150        (WebCore::CSSVariableValue::CSSVariableValue):
     151        (WebCore::CSSVariableValue::customCSSText):
     152        (WebCore::CSSVariableValue::equals):
     153        (WebCore::CSSVariableValue::buildParserValueListSubstitutingVariables):
     154        * css/CSSVariableValue.h: Added.
     155        (WebCore::CSSVariableValue::create):
     156        (WebCore::CSSVariableValue::name):
     157        (WebCore::CSSVariableValue::fallbackArguments):
     158        This value represents a var() itself. It knows how to do the substitution of the variable
     159        value and to apply fallback if that value is not present.
     160
     161        * css/StyleProperties.cpp:
     162        (WebCore::StyleProperties::getPropertyValue):
     163        (WebCore::StyleProperties::borderSpacingValue):
     164        (WebCore::StyleProperties::getLayeredShorthandValue):
     165        (WebCore::StyleProperties::getShorthandValue):
     166        (WebCore::StyleProperties::getCommonValue):
     167        (WebCore::StyleProperties::getPropertyCSSValue):
     168        (WebCore::StyleProperties::getPropertyCSSValueInternal):
     169        (WebCore::StyleProperties::asText):
     170        (WebCore::StyleProperties::copyPropertiesInSet):
     171        * css/StyleProperties.h:
     172        Patched to factor property fetching into an internal method so that variables can work with shorthands
     173        in the CSS OM.
     174
     175        * css/StyleResolver.cpp:
     176        (WebCore::StyleResolver::applyProperty):
     177        Resolve variable values at compute time. If they fail to resolve, use inherit or initial as the
     178        value (depending on whether the property inherits by default).
     179
     180        (WebCore::StyleResolver::resolvedVariableValue):
     181        Helper function that calls parseVariableDependentValue and gets the resolved result.
     182
     183        (WebCore::StyleResolver::applyCascadedProperties):
     184        After custom properties have been collected, we check for cycles and perform variable substitutions.
     185        This way we get all the variables replaced before we inherit down the style tree.
     186
     187        * css/StyleResolver.h:
     188        Add resolvedVariableValue declaration.
     189
     190        * css/makeprop.pl:
     191        Make sure custom properties are inherited by default.
     192
     193        * rendering/style/RenderStyle.cpp:
     194        (WebCore::RenderStyle::checkVariablesInCustomProperties):
     195        This function handles updating variables with cycles to be invalid in the RenderStyle. It then also
     196        handles the replacement of variables found in custom properties with resolved values. All custom
     197        properties are either invalid or are real non-variable-dependent value lists after this function
     198        completes.
     199
     200        * rendering/style/RenderStyle.h:
     201        Add checkVariablesInCustomProperties declaration.
     202
     203        * rendering/style/StyleCustomPropertyData.h:
     204        (WebCore::StyleCustomPropertyData::create):
     205        (WebCore::StyleCustomPropertyData::copy):
     206        (WebCore::StyleCustomPropertyData::operator==):
     207        (WebCore::StyleCustomPropertyData::operator!=):
     208        (WebCore::StyleCustomPropertyData::setCustomPropertyValue):
     209        (WebCore::StyleCustomPropertyData::getCustomPropertyValue):
     210        (WebCore::StyleCustomPropertyData::values):
     211        (WebCore::StyleCustomPropertyData::hasCustomProperty):
     212        (WebCore::StyleCustomPropertyData::containsVariables):
     213        (WebCore::StyleCustomPropertyData::setContainsVariables):
     214        (WebCore::StyleCustomPropertyData::StyleCustomPropertyData):
     215        Miscellaneous cleanup, and the addition of whether or not the properties still contain variable
     216        dependent values that need to be resolved.
     217
    12182015-10-15  Csaba Osztrogonác  <ossy@webkit.org>
    2219
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r191114 r191128  
    26492649                7C4902A218B825F8007D9298 /* DOMWheelEventInternal.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 85989DCA0ACC8BBD00A0BC51 /* DOMWheelEventInternal.h */; };
    26502650                7C4C96DC1AD4483500365A50 /* JSReadableStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C4C96D81AD4483500365A50 /* JSReadableStream.cpp */; };
     2651                7C4C96DC1AD4483500365A51 /* ReadableStreamBuiltins.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C4C96D81AD4483500365A51 /* ReadableStreamBuiltins.cpp */; };
     2652                7C4C96DC1AD4483500365A52 /* CountQueuingStrategyBuiltins.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C4C96D81AD4483500365A52 /* CountQueuingStrategyBuiltins.cpp */; };
    26512653                7C4C96DD1AD4483500365A50 /* JSReadableStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C4C96D91AD4483500365A50 /* JSReadableStream.h */; };
    26522654                7C4C96DE1AD4483500365A50 /* JSReadableStreamReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C4C96DA1AD4483500365A50 /* JSReadableStreamReader.cpp */; };
     
    52865288                BC14028A0E83680800319717 /* ScrollbarThemeComposite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC1402880E83680800319717 /* ScrollbarThemeComposite.cpp */; };
    52875289                BC14028B0E83680800319717 /* ScrollbarThemeComposite.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1402890E83680800319717 /* ScrollbarThemeComposite.h */; settings = {ATTRIBUTES = (Private, ); }; };
     5290                BC1790BB1BB5AB3F0006D13E /* CSSVariableDependentValue.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1790BA1BB5AB3F0006D13E /* CSSVariableDependentValue.h */; settings = {ASSET_TAGS = (); }; };
     5291                BC1790BD1BBB36A80006D13E /* CSSVariableDependentValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC1790BC1BBB36A80006D13E /* CSSVariableDependentValue.cpp */; settings = {ASSET_TAGS = (); }; };
     5292                BC1790C01BBF2C430006D13E /* CSSVariableValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC1790BE1BBF2C430006D13E /* CSSVariableValue.cpp */; settings = {ASSET_TAGS = (); }; };
     5293                BC1790C11BBF2C430006D13E /* CSSVariableValue.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1790BF1BBF2C430006D13E /* CSSVariableValue.h */; settings = {ASSET_TAGS = (); }; };
    52885294                BC17F9660B64EBB8004A65CB /* JSHTMLSelectElementCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC17F9650B64EBB8004A65CB /* JSHTMLSelectElementCustom.cpp */; };
    52895295                BC1A37AD097C715F0019F3D8 /* DOM.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1A3797097C715F0019F3D8 /* DOM.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    1008510091                7C48A6D2191C9D8E00026674 /* WebKitNamespace.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = WebKitNamespace.idl; sourceTree = "<group>"; };
    1008610092                7C4C96D81AD4483500365A50 /* JSReadableStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSReadableStream.cpp; sourceTree = "<group>"; };
     10093                7C4C96D81AD4483500365A51 /* ReadableStreamBuiltins.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReadableStreamBuiltins.cpp; sourceTree = "<group>"; };
     10094                7C4C96D81AD4483500365A52 /* CountQueuingStrategyBuiltins.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CountQueuingStrategyBuiltins.cpp; sourceTree = "<group>"; };
    1008710095                7C4C96D91AD4483500365A50 /* JSReadableStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSReadableStream.h; sourceTree = "<group>"; };
    1008810096                7C4C96DA1AD4483500365A50 /* JSReadableStreamReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSReadableStreamReader.cpp; sourceTree = "<group>"; };
     
    1297912987                BC1402880E83680800319717 /* ScrollbarThemeComposite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScrollbarThemeComposite.cpp; sourceTree = "<group>"; };
    1298012988                BC1402890E83680800319717 /* ScrollbarThemeComposite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollbarThemeComposite.h; sourceTree = "<group>"; };
     12989                BC1790BA1BB5AB3F0006D13E /* CSSVariableDependentValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSVariableDependentValue.h; sourceTree = "<group>"; };
     12990                BC1790BC1BBB36A80006D13E /* CSSVariableDependentValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSVariableDependentValue.cpp; sourceTree = "<group>"; };
     12991                BC1790BE1BBF2C430006D13E /* CSSVariableValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSVariableValue.cpp; sourceTree = "<group>"; };
     12992                BC1790BF1BBF2C430006D13E /* CSSVariableValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSVariableValue.h; sourceTree = "<group>"; };
    1298112993                BC17F9650B64EBB8004A65CB /* JSHTMLSelectElementCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLSelectElementCustom.cpp; sourceTree = "<group>"; };
    1298212994                BC1A3797097C715F0019F3D8 /* DOM.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DOM.h; sourceTree = "<group>"; };
     
    2308423096                                E49BDA0A131FD3E5003C56F0 /* CSSValuePool.cpp */,
    2308523097                                E49BD9F9131FD2ED003C56F0 /* CSSValuePool.h */,
     23098                                BC1790BC1BBB36A80006D13E /* CSSVariableDependentValue.cpp */,
     23099                                BC1790BA1BB5AB3F0006D13E /* CSSVariableDependentValue.h */,
     23100                                BC1790BE1BBF2C430006D13E /* CSSVariableValue.cpp */,
     23101                                BC1790BF1BBF2C430006D13E /* CSSVariableValue.h */,
    2308623102                                A80E6CE10A1989CA007FB8C5 /* DashboardRegion.h */,
    2308723103                                4A4F48A716B0DFC000EDBB29 /* DocumentRuleSets.cpp */,
     
    2432424340                                29A812310FBB9C1D00510293 /* AccessibilityTableRow.h in Headers */,
    2432524341                                A91C9FBF1B6586DE00AFFD54 /* AccessibilityTree.h in Headers */,
     24342                                BC1790C11BBF2C430006D13E /* CSSVariableValue.h in Headers */,
    2432624343                                A91C9FC31B659A6700AFFD54 /* AccessibilityTreeItem.h in Headers */,
    2432724344                                B5D31DFB11CF610B009F22B4 /* ActiveDOMCallback.h in Headers */,
     
    2751927536                                5D5975B319635F1100D00878 /* SystemVersion.h in Headers */,
    2752027537                                A8CFF0510A154F09000A4234 /* TableLayout.h in Headers */,
     27538                                BC1790BB1BB5AB3F0006D13E /* CSSVariableDependentValue.h in Headers */,
    2752127539                                463EB6231B8789E00096ED51 /* TagCollection.h in Headers */,
    2752227540                                F55B3DD61251F12D003EF269 /* TelephoneInputType.h in Headers */,
     
    2830628324                                29A8124B0FBB9CA900510293 /* AXObjectCacheMac.mm in Sources */,
    2830728325                                BCA8C81F11E3D36900812FB7 /* BackForwardController.cpp in Sources */,
     28326                                BC1790C01BBF2C430006D13E /* CSSVariableValue.cpp in Sources */,
    2830828327                                BCA8CA5F11E4E6D100812FB7 /* BackForwardList.cpp in Sources */,
    2830928328                                BC124EE70C2641CD009E2349 /* BarProp.cpp in Sources */,
     
    3092930948                                E180811616FCF9CB00B80D07 /* SynchronousLoaderClient.mm in Sources */,
    3093030949                                442ABCD617D9262F00D30715 /* SynchronousLoaderClientCFNet.cpp in Sources */,
     30950                                BC1790BD1BBB36A80006D13E /* CSSVariableDependentValue.cpp in Sources */,
    3093130951                                26FAE4CE1852E3A5004C8C46 /* SynchronousResourceHandleCFURLConnectionDelegate.cpp in Sources */,
    3093230952                                E45390AE0EAFF4B5003695C8 /* SystemMemoryIOS.cpp in Sources */,
  • trunk/Source/WebCore/css/CSSCalculationValue.cpp

    r188315 r191128  
    138138    case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR:
    139139    case CSSPrimitiveValue::CSS_PARSER_IDENTIFIER:
     140    case CSSPrimitiveValue::CSS_PARSER_WHITESPACE:
    140141    case CSSPrimitiveValue::CSS_COUNTER_NAME:
    141142    case CSSPrimitiveValue::CSS_SHAPE:
  • trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp

    r190663 r191128  
    21092109    if (!styledNode)
    21102110        return nullptr;
     2111   
     2112    if (updateStyleIfNeededForNode(*styledNode)) {
     2113        // The style recalc could have caused the styled node to be discarded or replaced
     2114        // if it was a PseudoElement so we need to update it.
     2115        styledNode = this->styledNode();
     2116    }
    21112117
    21122118    RefPtr<RenderStyle> style = computeRenderStyleForProperty(styledNode, m_pseudoElementSpecifier, CSSPropertyCustom);
     
    36143620        return 0;
    36153621
    3616     const HashMap<AtomicString, RefPtr<CSSValue>>* customProperties = style->customProperties();
    3617     return numComputedProperties + (customProperties ? customProperties->size() : 0);
     3622    return numComputedProperties + style->customProperties().size();
    36183623}
    36193624
     
    36363641    unsigned index = i - numComputedProperties;
    36373642   
    3638     const auto* customProperties = style->customProperties();
    3639     if (!customProperties || index >= customProperties->size())
     3643    const auto& customProperties = style->customProperties();
     3644    if (index >= customProperties.size())
    36403645        return emptyString();
    36413646   
    36423647    Vector<String, 4> results;
    3643     copyKeysToVector(*customProperties, results);
     3648    copyKeysToVector(customProperties, results);
    36443649    return results.at(index);
    36453650}
  • trunk/Source/WebCore/css/CSSCustomPropertyValue.h

    r190231 r191128  
    2929#include "CSSParserValues.h"
    3030#include "CSSValue.h"
     31#include <wtf/RefPtr.h>
    3132#include <wtf/text/WTFString.h>
    3233
     
    3536class CSSCustomPropertyValue : public CSSValue {
    3637public:
    37     static Ref<CSSCustomPropertyValue> create(const AtomicString& name, std::unique_ptr<CSSParserValueList>& valueList)
     38    static Ref<CSSCustomPropertyValue> create(const AtomicString& name, RefPtr<CSSValue>& value)
    3839    {
    39         return adoptRef(*new CSSCustomPropertyValue(name, valueList));
     40        return adoptRef(*new CSSCustomPropertyValue(name, value));
     41    }
     42   
     43    static Ref<CSSCustomPropertyValue> createInvalid()
     44    {
     45        return adoptRef(*new CSSCustomPropertyValue(emptyString(), emptyString()));
    4046    }
    4147   
     
    4450        if (!m_serialized) {
    4551            m_serialized = true;
    46             m_stringValue = m_parserValue ? m_parserValue->toString() : "";
     52            m_stringValue = m_value ? m_value->cssText() : emptyString();
    4753        }
    4854        return m_stringValue;
     
    5561    bool equals(const CSSCustomPropertyValue& other) const { return m_name == other.m_name && customCSSText() == other.customCSSText(); }
    5662
     63    bool isInvalid() const { return !m_value; }
     64    bool containsVariables() const { return m_containsVariables; }
     65
     66    const RefPtr<CSSValue> value() const { return m_value.get(); }
     67
    5768private:
    58     CSSCustomPropertyValue(const AtomicString& name, std::unique_ptr<CSSParserValueList>& valueList)
     69    CSSCustomPropertyValue(const AtomicString& name, RefPtr<CSSValue>& value)
    5970        : CSSValue(CustomPropertyClass)
    6071        , m_name(name)
    61         , m_parserValue(WTF::move(valueList))
    62         , m_serialized(false)
     72        , m_value(value)
     73        , m_containsVariables(value && value->isVariableDependentValue())
     74        , m_serialized(!value)
     75    {
     76    }
     77   
     78    CSSCustomPropertyValue(const AtomicString& name, const String& serializedValue)
     79        : CSSValue(CustomPropertyClass)
     80        , m_name(name)
     81        , m_stringValue(serializedValue)
     82        , m_serialized(true)
    6383    {
    6484    }
    6585
    6686    const AtomicString m_name;
    67     std::unique_ptr<CSSParserValueList> m_parserValue;
     87    RefPtr<CSSValue> m_value;
    6888    mutable String m_stringValue;
     89    bool m_containsVariables { false };
    6990    mutable bool m_serialized;
    7091};
  • trunk/Source/WebCore/css/CSSFunctionValue.cpp

    r177261 r191128  
    6363}
    6464
     65bool CSSFunctionValue::buildParserValueSubstitutingVariables(CSSParserValue* result, const CustomPropertyValueMap& customProperties) const
     66{
     67    result->id = CSSValueInvalid;
     68    result->unit = CSSParserValue::Function;
     69    result->function = new CSSParserFunction;
     70    result->function->name.init(m_name);
     71    bool success = true;
     72    if (m_args) {
     73        CSSParserValueList* argList = new CSSParserValueList;
     74        success = m_args->buildParserValueListSubstitutingVariables(argList, customProperties);
     75        result->function->args.reset(argList);
     76    }
     77    return success;
    6578}
     79
     80}
  • trunk/Source/WebCore/css/CSSFunctionValue.h

    r177261 r191128  
    3333class CSSValueList;
    3434struct CSSParserFunction;
     35struct CSSParserValue;
    3536
    3637class CSSFunctionValue : public CSSValue {
     
    5253    CSSValueList* arguments() const { return m_args.get(); }
    5354
     55    bool buildParserValueSubstitutingVariables(CSSParserValue*, const CustomPropertyValueMap& customProperties) const;
     56   
    5457private:
    5558    explicit CSSFunctionValue(CSSParserFunction*);
  • trunk/Source/WebCore/css/CSSGrammar.y.in

    r190231 r191128  
    8585    case NTHCHILDSELECTORSEPARATOR:
    8686    case LANGFUNCTION:
     87    case VARFUNCTION:
    8788#if ENABLE_CSS_SELECTORS_LEVEL4
    8889    case DIRFUNCTION:
     
    125126
    126127#if ENABLE_CSS_GRID_LAYOUT
    127 %expect 32
     128%expect 39
    128129#else
    129 %expect 31
     130%expect 37
    130131#endif
    131132
     
    240241%token <string> NTHCHILDFUNCTIONS
    241242%token <string> LANGFUNCTION
     243%token <string> VARFUNCTION
    242244
    243245#if ENABLE_CSS_SELECTORS_LEVEL4
     
    297299
    298300// These parser values need to be destroyed because they might be functions.
    299 %type <value> calc_function function min_or_max_function term
    300 %destructor { destroy($$); } calc_function function min_or_max_function term
     301%type <value> calc_function function variable_function min_or_max_function term
     302%destructor { destroy($$); } calc_function function variable_function min_or_max_function term
    301303
    302304%type <id> property
     
    317319%type <character> operator calc_func_operator
    318320
    319 %type <valueList> calc_func_expr calc_func_expr_list calc_func_paren_expr expr key_list maybe_media_value valid_calc_func_expr valid_expr
    320 %destructor { delete $$; } calc_func_expr calc_func_expr_list calc_func_paren_expr expr key_list maybe_media_value valid_calc_func_expr valid_expr
     321%type <valueList> calc_func_expr calc_func_expr_list calc_func_paren_expr expr key_list maybe_media_value valid_calc_func_expr valid_expr whitespace_or_expr maybe_expr
     322%destructor { delete $$; } calc_func_expr calc_func_expr_list calc_func_paren_expr expr key_list maybe_media_value valid_calc_func_expr valid_expr whitespace_or_expr maybe_expr
    321323
    322324%type <string> lang_range
     
    766768            $$ = p->parseValue($3, $7);
    767769            // We just need to know if the declaration is supported as it is written. Rollback any additions.
     770            if ($$)
     771                p->rollbackLastProperties(p->m_parsedProperties.size() - oldParsedProperties);
     772            p->m_valueList = nullptr;
     773        }
     774        p->markPropertyEnd($7, false);
     775    }
     776    |
     777    '(' maybe_space CUSTOM_PROPERTY maybe_space ':' whitespace_or_expr priority ')' maybe_space {
     778        $$ = false;
     779        CSSParser* p = static_cast<CSSParser*>(parser);
     780        std::unique_ptr<CSSParserValueList> propertyValue($6);
     781        if (propertyValue) {
     782            parser->m_valueList = WTF::move(propertyValue);
     783            int oldParsedProperties = p->m_parsedProperties.size();
     784            p->setCustomPropertyName($3);
     785            $$ = p->parseValue(CSSPropertyCustom, $7);
    768786            if ($$)
    769787                p->rollbackLastProperties(p->m_parsedProperties.size() - oldParsedProperties);
     
    15391557
    15401558declaration:
    1541     CUSTOM_PROPERTY maybe_space ':' maybe_space expr priority {
     1559    CUSTOM_PROPERTY maybe_space ':' whitespace_or_expr priority {
    15421560        $$ = false;
    15431561        bool isPropertyParsed = false;
    1544         std::unique_ptr<CSSParserValueList> propertyValue($5);
     1562        std::unique_ptr<CSSParserValueList> propertyValue($4);
    15451563        if (propertyValue) {
    15461564            parser->m_valueList = WTF::move(propertyValue);
    15471565            int oldParsedProperties = parser->m_parsedProperties.size();
    15481566            parser->setCustomPropertyName($1);
    1549             $$ = parser->parseValue(CSSPropertyCustom, $6);
     1567            $$ = parser->parseValue(CSSPropertyCustom, $5);
    15501568            if (!$$)
    15511569                parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties);
     
    15541572            parser->m_valueList = nullptr;
    15551573        }
    1556         parser->markPropertyEnd($6, isPropertyParsed);
     1574        parser->markPropertyEnd($5, isPropertyParsed);
    15571575    }
    15581576    | property ':' maybe_space expr priority {
     
    16241642
    16251643#endif
     1644
     1645whitespace_or_expr:
     1646    WHITESPACE maybe_expr {
     1647        if ($2)
     1648            $$ = $2;
     1649        else {
     1650            CSSParserValue val;
     1651            val.id = CSSValueInvalid;
     1652            val.unit = CSSPrimitiveValue::CSS_PARSER_WHITESPACE;
     1653            val.string.init(emptyString());
     1654            $$ = new CSSParserValueList;
     1655            $$->addValue(val);
     1656        }
     1657    }
     1658    | maybe_space expr { $$ = $2; }
     1659    ;
     1660
     1661maybe_expr: /* empty */ { $$ = nullptr; } | expr { $$ = $1; };
    16261662
    16271663expr: valid_expr | valid_expr expr_recovery { $$ = nullptr; delete $1; } ;
     
    16681704  | function maybe_space
    16691705  | calc_function maybe_space
     1706  | variable_function maybe_space
    16701707  | min_or_max_function maybe_space
    16711708  | '%' maybe_space { /* Handle width: %; */
     
    17431780  ;
    17441781
     1782variable_function:
     1783    VARFUNCTION maybe_space CUSTOM_PROPERTY maybe_space closing_parenthesis {
     1784        CSSParserVariable* var = new CSSParserVariable;
     1785        var->name = $3;
     1786        var->args = nullptr;
     1787        $$.id = CSSValueInvalid;
     1788        $$.unit = CSSParserValue::Variable;
     1789        $$.variable = var;
     1790    }
     1791    | VARFUNCTION maybe_space CUSTOM_PROPERTY maybe_space ',' maybe_space expr closing_parenthesis {
     1792        CSSParserVariable* var = new CSSParserVariable;
     1793        var->name = $3;
     1794        var->args = std::unique_ptr<CSSParserValueList>($7);
     1795        $$.id = CSSValueInvalid;
     1796        $$.unit = CSSParserValue::Variable;
     1797        $$.variable = var;
     1798    }
     1799    | VARFUNCTION maybe_space CUSTOM_PROPERTY maybe_space ',' maybe_space closing_parenthesis {
     1800        CSSParserVariable* var = new CSSParserVariable;
     1801        var->name = $3;
     1802        var->args = std::unique_ptr<CSSParserValueList>(new CSSParserValueList());
     1803        $$.id = CSSValueInvalid;
     1804        $$.unit = CSSParserValue::Variable;
     1805        $$.variable = var;
     1806    }
     1807    // Error handling cases
     1808    | VARFUNCTION maybe_space CUSTOM_PROPERTY maybe_space ',' closing_parenthesis {
     1809        $$.id = CSSValueInvalid;
     1810        $$.unit = 0;
     1811        YYERROR;
     1812    }
     1813    | VARFUNCTION maybe_space CUSTOM_PROPERTY maybe_space ',' maybe_space invalid_var_fallback maybe_space closing_parenthesis {
     1814        $$.id = CSSValueInvalid;
     1815        $$.unit = 0;
     1816        YYERROR;
     1817    }
     1818    | VARFUNCTION maybe_space CUSTOM_PROPERTY maybe_space ',' maybe_space priority closing_parenthesis {
     1819        $$.id = CSSValueInvalid;
     1820        $$.unit = 0;
     1821        YYERROR;
     1822    }
     1823    | VARFUNCTION maybe_space expr closing_parenthesis {
     1824        $$.id = CSSValueInvalid;
     1825        $$.unit = 0;
     1826        YYERROR;
     1827    }
     1828    | VARFUNCTION maybe_space expr_recovery closing_parenthesis {
     1829        $$.id = CSSValueInvalid;
     1830        $$.unit = 0;
     1831        YYERROR;
     1832    }
     1833    ;
     1834
     1835invalid_var_fallback:
     1836    '!' | ';';
     1837
    17451838calc_func_term:
    17461839  unary_term
     1840  | variable_function { $$ = $1; }
    17471841  | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
    17481842  ;
     
    18941988
    18951989opening_parenthesis:
    1896     '(' | FUNCTION | CALCFUNCTION | MATCHESFUNCTION | MAXFUNCTION | MINFUNCTION | ANYFUNCTION | NOTFUNCTION | LANGFUNCTION
     1990    '(' | FUNCTION | VARFUNCTION | CALCFUNCTION | MATCHESFUNCTION | MAXFUNCTION | MINFUNCTION | ANYFUNCTION | NOTFUNCTION | LANGFUNCTION
    18971991#if ENABLE_CSS_SELECTORS_LEVEL4
    18981992    | DIRFUNCTION | ROLEFUNCTION
  • trunk/Source/WebCore/css/CSSParser.cpp

    r191002 r191128  
    6666#include "CSSValueList.h"
    6767#include "CSSValuePool.h"
     68#include "CSSVariableDependentValue.h"
    6869#include "Counter.h"
    6970#include "Document.h"
     
    16031604       
    16041605        if (property.id() == CSSPropertyCustom) {
    1605             const AtomicString& name = downcast<CSSCustomPropertyValue>(*property.value()).name();
    1606             if (seenCustomProperties.contains(name))
    1607                 continue;
    1608             seenCustomProperties.add(name);
    1609             output[--unusedEntries] = property;
     1606            if (property.value()) {
     1607                const AtomicString& name = downcast<CSSCustomPropertyValue>(*property.value()).name();
     1608                if (seenCustomProperties.contains(name))
     1609                    continue;
     1610                seenCustomProperties.add(name);
     1611                output[--unusedEntries] = property;
     1612            }
    16101613            continue;
    16111614        }
     
    19091912}
    19101913
     1914RefPtr<CSSValue> CSSParser::parseVariableDependentValue(CSSPropertyID propID, const CSSVariableDependentValue& dependentValue, const CustomPropertyValueMap& customProperties)
     1915{
     1916    m_valueList.reset(new CSSParserValueList());
     1917    if (!dependentValue.valueList()->buildParserValueListSubstitutingVariables(m_valueList.get(), customProperties))
     1918        return nullptr;
     1919    bool parsed = parseValue(dependentValue.propertyID(), false);
     1920    if (!parsed)
     1921        return nullptr;
     1922    for (size_t i = 0; i < m_parsedProperties.size(); ++i) {
     1923        if (m_parsedProperties[i].id() == propID)
     1924            return m_parsedProperties[i].value();
     1925    }
     1926    return nullptr;
     1927}
     1928
    19111929bool CSSParser::parseValue(CSSPropertyID propId, bool important)
    19121930{
     
    19141932        return false;
    19151933   
    1916     if (propId == CSSPropertyCustom) {
    1917         // FIXME: For now put this ahead of inherit/initial processing.
    1918         // Eventually we want to support initial and inherit.
    1919         return parseCustomPropertyDeclaration(important);
    1920     }
    1921 
    19221934    ValueWithCalculation valueWithCalculation(*m_valueList->current());
    19231935    CSSValueID id = valueWithCalculation.value().id;
     1936   
     1937    if (propId == CSSPropertyCustom)
     1938        return parseCustomPropertyDeclaration(important, id);
     1939
     1940    if (m_valueList->containsVariables()) {
     1941        RefPtr<CSSValueList> valueList = CSSValueList::createFromParserValueList(*m_valueList);
     1942        addExpandedPropertyForValue(propId, CSSVariableDependentValue::create(valueList, propId), important);
     1943        return true;
     1944    }
    19241945
    19251946    auto& cssValuePool = CSSValuePool::singleton();
     
    41694190}
    41704191
    4171 bool CSSParser::parseCustomPropertyDeclaration(bool important)
     4192bool CSSParser::parseCustomPropertyDeclaration(bool important, CSSValueID id)
    41724193{
    41734194    if (m_customPropertyName.isEmpty() || !m_valueList)
    41744195        return false;
    4175     addProperty(CSSPropertyCustom, CSSCustomPropertyValue::create(m_customPropertyName, m_valueList), important, false);
     4196   
     4197    auto& cssValuePool = CSSValuePool::singleton();
     4198    RefPtr<CSSValue> value;
     4199    if (id == CSSValueInherit)
     4200        value = cssValuePool.createInheritedValue();
     4201    else if (id == CSSValueInitial)
     4202        value = cssValuePool.createExplicitInitialValue();
     4203    else {
     4204        RefPtr<CSSValueList> valueList = CSSValueList::createFromParserValueList(*m_valueList);
     4205        if (m_valueList->containsVariables())
     4206            value = CSSVariableDependentValue::create(valueList, CSSPropertyCustom);
     4207        else
     4208            value = valueList;
     4209    }
     4210
     4211    addProperty(CSSPropertyCustom, CSSCustomPropertyValue::create(m_customPropertyName, value), important, false);
    41764212    return true;
    41774213}
     
    1147211508            return true;
    1147311509        }
     11510        if (isASCIIAlphaCaselessEqual(name[0], 'v') && isASCIIAlphaCaselessEqual(name[1], 'a') && isASCIIAlphaCaselessEqual(name[2], 'r')) {
     11511            m_token = VARFUNCTION;
     11512            return true;
     11513        }
    1147411514#if ENABLE(VIDEO_TRACK)
    1147511515        if (isASCIIAlphaCaselessEqual(name[0], 'c') && isASCIIAlphaCaselessEqual(name[1], 'u') && isASCIIAlphaCaselessEqual(name[2], 'e')) {
     
    1216012200            resultString.setLength(result - tokenStart<SrcCharacterType>());
    1216112201            yylval->string = resultString;
    12162         } else if (currentCharacter<SrcCharacterType>()[0] == '-' && isIdentifierStartAfterDash(currentCharacter<SrcCharacterType>() + 1)) {
     12202        } else if (currentCharacter<SrcCharacterType>()[0] == '-' && currentCharacter<SrcCharacterType>()[1] == '>') {
     12203            currentCharacter<SrcCharacterType>() += 2;
     12204            m_token = SGML_CD;
     12205        } else if (currentCharacter<SrcCharacterType>()[0] == '-') {
    1216312206            --currentCharacter<SrcCharacterType>();
    1216412207            parseIdentifier(result, resultString, hasEscape);
    1216512208            m_token = CUSTOM_PROPERTY;
    1216612209            yylval->string = resultString;
    12167         } else if (currentCharacter<SrcCharacterType>()[0] == '-' && currentCharacter<SrcCharacterType>()[1] == '>') {
    12168             currentCharacter<SrcCharacterType>() += 2;
    12169             m_token = SGML_CD;
    1217012210        } else if (UNLIKELY(m_parsingMode == NthChildMode)) {
    1217112211            // "-[0-9]+n" is always an NthChild.
  • trunk/Source/WebCore/css/CSSParser.h

    r190663 r191128  
    5858class CSSBasicShapeInset;
    5959class CSSGridLineNamesValue;
     60class CSSVariableDependentValue;
    6061class Document;
    6162class Element;
     
    145146    bool parseAlt(CSSPropertyID, bool important);
    146147   
    147     bool parseCustomPropertyDeclaration(bool important);
     148    bool parseCustomPropertyDeclaration(bool important, CSSValueID);
    148149   
    149150    RefPtr<CSSValue> parseAttr(CSSParserValueList& args);
     
    472473    void setCustomPropertyName(const AtomicString& propertyName) { m_customPropertyName = propertyName; }
    473474
     475    RefPtr<CSSValue> parseVariableDependentValue(CSSPropertyID, const CSSVariableDependentValue&, const CustomPropertyValueMap& customProperties);
     476
    474477private:
    475478    bool is8BitSource() { return m_is8BitSource; }
  • trunk/Source/WebCore/css/CSSParserValues.cpp

    r190231 r191128  
    2222#include "CSSParserValues.h"
    2323
     24#include "CSSCustomPropertyValue.h"
    2425#include "CSSPrimitiveValue.h"
    2526#include "CSSFunctionValue.h"
    2627#include "CSSSelector.h"
    2728#include "CSSSelectorList.h"
     29#include "CSSVariableValue.h"
    2830#include "SelectorPseudoTypeMap.h"
    2931#include <wtf/text/StringBuilder.h>
     
    6870}
    6971
    70 String CSSParserValueList::toString()
    71 {
    72     // Build up a set of CSSValues and serialize them using cssText, separating multiple values
    73     // with spaces.
    74     // FIXME: Teach CSSParserValues how to serialize so that we don't have to create CSSValues
    75     // just to perform this serialization.
    76     StringBuilder builder;
     72bool CSSParserValueList::containsVariables() const
     73{
    7774    for (unsigned i = 0; i < size(); i++) {
    78         if (i)
    79             builder.append(' ');
    80         RefPtr<CSSValue> cssValue = valueAt(i)->createCSSValue();
    81         if (!cssValue)
    82             return "";
    83         builder.append(cssValue->cssText());
    84     }
    85     return builder.toString().lower();
     75        auto* parserValue = &m_values[i];
     76        if (parserValue->unit == CSSParserValue::Variable)
     77            return true;
     78        if (parserValue->unit == CSSParserValue::Function && parserValue->function->args
     79            && parserValue->function->args->containsVariables())
     80            return true;
     81        if (parserValue->unit == CSSParserValue::ValueList && parserValue->valueList->containsVariables())
     82            return true;
     83    }
     84    return false;
    8685}
    8786
     
    9998    if (unit == CSSParserValue::Function)
    10099        return CSSFunctionValue::create(function);
     100    if (unit == CSSParserValue::Variable)
     101        return CSSVariableValue::create(variable);
    101102    if (unit == CSSParserValue::ValueList)
    102103        return CSSValueList::createFromParserValueList(*valueList);
     104
    103105    if (unit >= CSSParserValue::Q_EMS)
    104106        return CSSPrimitiveValue::createAllowingMarginQuirk(fValue, CSSPrimitiveValue::CSS_EMS);
     
    115117    case CSSPrimitiveValue::CSS_URI:
    116118    case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR:
     119    case CSSPrimitiveValue::CSS_DIMENSION:
     120    case CSSPrimitiveValue::CSS_UNICODE_RANGE:
     121    case CSSPrimitiveValue::CSS_PARSER_WHITESPACE:
    117122        return CSSPrimitiveValue::create(string, primitiveUnit);
    118123    case CSSPrimitiveValue::CSS_PERCENTAGE:
     
    142147        return CSSPrimitiveValue::create(fValue, primitiveUnit);
    143148    case CSSPrimitiveValue::CSS_UNKNOWN:
    144     case CSSPrimitiveValue::CSS_DIMENSION:
    145149    case CSSPrimitiveValue::CSS_ATTR:
    146150    case CSSPrimitiveValue::CSS_COUNTER:
     
    154158    case CSSPrimitiveValue::CSS_DASHBOARD_REGION:
    155159#endif
    156     case CSSPrimitiveValue::CSS_UNICODE_RANGE:
    157160    case CSSPrimitiveValue::CSS_PARSER_OPERATOR:
    158161    case CSSPrimitiveValue::CSS_PARSER_INTEGER:
  • trunk/Source/WebCore/css/CSSParserValues.h

    r190231 r191128  
    2626#include "CSSValueList.h"
    2727#include <wtf/text/AtomicString.h>
     28#include <wtf/text/AtomicStringHash.h>
    2829#include <wtf/text/WTFString.h>
    2930
     
    108109
    109110struct CSSParserFunction;
     111struct CSSParserVariable;
    110112
    111113struct CSSParserValue {
     
    117119        CSSParserString string;
    118120        CSSParserFunction* function;
     121        CSSParserVariable* variable;
    119122        CSSParserValueList* valueList;
    120123    };
     
    124127        ValueList = 0x100002,
    125128        Q_EMS     = 0x100003,
     129        Variable  = 0x100004
    126130    };
    127131    int unit;
     
    171175   
    172176    String toString();
     177   
     178    bool containsVariables() const;
    173179
    174180private:
     
    182188    CSSParserString name;
    183189    std::unique_ptr<CSSParserValueList> args;
     190};
     191
     192struct CSSParserVariable {
     193    WTF_MAKE_FAST_ALLOCATED;
     194public:
     195    CSSParserString name; // The custom property name
     196    std::unique_ptr<CSSParserValueList> args; // The fallback args
    184197};
    185198
  • trunk/Source/WebCore/css/CSSPrimitiveValue.cpp

    r189646 r191128  
    118118    case CSSPrimitiveValue::CSS_PARSER_INTEGER:
    119119    case CSSPrimitiveValue::CSS_PARSER_OPERATOR:
     120    case CSSPrimitiveValue::CSS_PARSER_WHITESPACE:
    120121    case CSSPrimitiveValue::CSS_RECT:
    121122    case CSSPrimitiveValue::CSS_QUAD:
     
    453454    case CSS_COUNTER_NAME:
    454455    case CSS_PARSER_HEXCOLOR:
     456    case CSS_PARSER_WHITESPACE:
    455457        if (m_value.string)
    456458            m_value.string->deref();
     
    11441146    }
    11451147    case CSS_PARSER_IDENTIFIER:
    1146         return quoteCSSStringIfNeeded(m_value.string);
     1148        return m_value.string;
     1149    case CSS_PARSER_WHITESPACE:
     1150        return " ";
    11471151    case CSS_CALC:
    11481152        return m_value.calc->cssText();
     
    12791283    case CSS_PARSER_OPERATOR:
    12801284    case CSS_PARSER_IDENTIFIER:
     1285    case CSS_PARSER_WHITESPACE:
    12811286    case CSS_PARSER_HEXCOLOR:
    12821287        ASSERT_NOT_REACHED();
     
    13381343    case CSS_PARSER_IDENTIFIER:
    13391344    case CSS_PARSER_HEXCOLOR:
     1345    case CSS_PARSER_WHITESPACE:
    13401346        return equal(m_value.string, other.m_value.string);
    13411347    case CSS_COUNTER:
     
    13691375}
    13701376
     1377bool CSSPrimitiveValue::buildParserValue(CSSParserValue* result) const
     1378{
     1379    switch (m_primitiveUnitType) {
     1380    case CSS_VALUE_ID:
     1381        result->id = m_value.valueID;
     1382        result->unit = CSSPrimitiveValue::CSS_IDENT;
     1383        result->string.init(valueName(m_value.valueID));
     1384        break;
     1385    case CSS_PARSER_IDENTIFIER:
     1386        result->id = CSSValueInvalid;
     1387        result->unit = CSSPrimitiveValue::CSS_IDENT;
     1388        result->string.init(m_value.string);
     1389        break;
     1390    case CSS_NUMBER:
     1391    case CSS_PERCENTAGE:
     1392    case CSS_EMS:
     1393    case CSS_EXS:
     1394    case CSS_REMS:
     1395    case CSS_PX:
     1396    case CSS_CM:
     1397#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY)
     1398    case CSS_DPPX:
     1399    case CSS_DPI:
     1400    case CSS_DPCM:
     1401#endif
     1402    case CSS_MM:
     1403    case CSS_IN:
     1404    case CSS_PT:
     1405    case CSS_PC:
     1406    case CSS_DEG:
     1407    case CSS_RAD:
     1408    case CSS_GRAD:
     1409    case CSS_MS:
     1410    case CSS_S:
     1411    case CSS_HZ:
     1412    case CSS_KHZ:
     1413    case CSS_TURN:
     1414    case CSS_VW:
     1415    case CSS_VH:
     1416    case CSS_VMIN:
     1417    case CSS_DIMENSION:
     1418    case CSS_FR:
     1419        result->fValue = m_value.num;
     1420        result->unit = m_primitiveUnitType;
     1421        break;
     1422    case CSS_PARSER_INTEGER:
     1423        result->fValue = m_value.num;
     1424        result->unit = CSSPrimitiveValue::CSS_NUMBER;
     1425        result->isInt = true;
     1426        break;
     1427    case CSS_PARSER_OPERATOR:
     1428        result->iValue = m_value.parserOperator;
     1429        result->unit = CSSParserValue::Operator;
     1430        break;
     1431    case CSS_STRING:
     1432    case CSS_URI:
     1433    case CSS_ATTR:
     1434    case CSS_COUNTER_NAME:
     1435    case CSS_PARSER_HEXCOLOR:
     1436        result->string.init(m_value.string);
     1437        result->unit = m_primitiveUnitType;
     1438        break;
     1439    case CSS_PARSER_WHITESPACE:
     1440        return false;
     1441    default:
     1442        ASSERT_NOT_REACHED();
     1443        break;
     1444    }
     1445   
     1446    return true;
     1447}
     1448
    13711449} // namespace WebCore
  • trunk/Source/WebCore/css/CSSPrimitiveValue.h

    r188512 r191128  
    4545class RenderStyle;
    4646class CSSBasicShape;
     47struct CSSParserValue;
    4748
    4849#if ENABLE(CSS_SCROLL_SNAP)
     
    154155
    155156        CSS_PROPERTY_ID = 117,
    156         CSS_VALUE_ID = 118
     157        CSS_VALUE_ID = 118,
     158       
     159        // More internal parse stuff for CSS variables
     160        CSS_PARSER_WHITESPACE = 119
    157161    };
    158162
     
    233237    bool isValueID() const { return m_primitiveUnitType == CSS_VALUE_ID; }
    234238    bool isFlex() const { return primitiveType() == CSS_FR; }
     239   
     240    bool isParserOperator() const { return primitiveType() == CSS_PARSER_OPERATOR; }
     241    int parserOperator() const { return isParserOperator() ? m_value.parserOperator : 0; }
    235242
    236243    static Ref<CSSPrimitiveValue> createIdentifier(CSSValueID valueID) { return adoptRef(*new CSSPrimitiveValue(valueID)); }
     
    267274
    268275    double computeDegrees() const;
    269 
     276   
     277    bool buildParserValue(CSSParserValue*) const;
     278   
    270279    enum TimeUnit { Seconds, Milliseconds };
    271280    template <typename T, TimeUnit timeUnit> T computeTime() const
  • trunk/Source/WebCore/css/CSSValue.cpp

    r190209 r191128  
    5656#include "CSSUnicodeRangeValue.h"
    5757#include "CSSValueList.h"
     58#include "CSSVariableDependentValue.h"
     59#include "CSSVariableValue.h"
    5860#include "SVGColor.h"
    5961#include "SVGPaint.h"
     
    240242        case CustomPropertyClass:
    241243            return compareCSSValues<CSSCustomPropertyValue>(*this, other);
    242        
     244        case VariableDependentClass:
     245            return compareCSSValues<CSSVariableDependentValue>(*this, other);
     246        case VariableClass:
     247            return compareCSSValues<CSSVariableValue>(*this, other);
    243248        default:
    244249            ASSERT_NOT_REACHED();
     
    337342    case CustomPropertyClass:
    338343        return downcast<CSSCustomPropertyValue>(*this).customCSSText();
     344    case VariableDependentClass:
     345        return downcast<CSSVariableDependentValue>(*this).customCSSText();
     346    case VariableClass:
     347        return downcast<CSSVariableValue>(*this).customCSSText();
    339348    }
    340349
     
    463472    case CustomPropertyClass:
    464473        delete downcast<CSSCustomPropertyValue>(this);
     474        return;
     475    case VariableDependentClass:
     476        delete downcast<CSSVariableDependentValue>(this);
     477        return;
     478    case VariableClass:
     479        delete downcast<CSSVariableValue>(this);
    465480        return;
    466481    }
     
    496511}
    497512
    498 }
     513bool CSSValue::isInvalidCustomPropertyValue() const
     514{
     515    return isCustomPropertyValue() && downcast<CSSCustomPropertyValue>(*this).isInvalid();
     516}
     517
     518}
  • trunk/Source/WebCore/css/CSSValue.h

    r190209 r191128  
    6161
    6262    String cssText() const;
     63
    6364    void setCssText(const String&, ExceptionCode&) { } // FIXME: Not implemented.
    6465
     
    7576    bool isCursorImageValue() const { return m_classType == CursorImageClass; }
    7677    bool isCustomPropertyValue() const { return m_classType == CustomPropertyClass; }
     78    bool isInvalidCustomPropertyValue() const;
     79    bool isVariableDependentValue() const { return m_classType == VariableDependentClass; }
     80    bool isVariableValue() const { return m_classType == VariableClass; }
    7781    bool isFunctionValue() const { return m_classType == FunctionClass; }
    7882    bool isFontFeatureValue() const { return m_classType == FontFeatureClass; }
     
    179183        CSSContentDistributionClass,
    180184        CustomPropertyClass,
    181        
     185        VariableDependentClass,
     186        VariableClass,
     187
    182188        // List class types must appear after ValueListClass.
    183189        ValueListClass,
     
    236242private:
    237243    unsigned m_classType : ClassTypeBits; // ClassType
     244   
     245friend class CSSValueList;
    238246};
    239247
     
    267275}
    268276
     277typedef HashMap<AtomicString, RefPtr<CSSValue>> CustomPropertyValueMap;
     278
    269279} // namespace WebCore
    270280
  • trunk/Source/WebCore/css/CSSValueList.cpp

    r188315 r191128  
    2222#include "CSSValueList.h"
    2323
     24#include "CSSFunctionValue.h"
    2425#include "CSSParserValues.h"
     26#include "CSSPrimitiveValue.h"
     27#include "CSSVariableDependentValue.h"
     28#include "CSSVariableValue.h"
    2529#include <wtf/text/StringBuilder.h>
    2630
     
    115119
    116120    for (auto& value : m_values) {
    117         if (!result.isEmpty())
     121        bool suppressSeparator = false;
     122        if (m_valueListSeparator == SpaceSeparator && value->isPrimitiveValue()) {
     123            auto* primitiveValue = &downcast<CSSPrimitiveValue>(*value.ptr());
     124            if (primitiveValue->parserOperator() == ',')
     125                suppressSeparator = true;
     126        }
     127        if (!suppressSeparator && !result.isEmpty())
    118128            result.append(separator);
    119129        result.append(value.get().cssText());
     
    175185}
    176186
     187
     188bool CSSValueList::containsVariables() const
     189{
     190    for (unsigned i = 0; i < m_values.size(); i++) {
     191        if (m_values[i]->isVariableValue())
     192            return true;
     193        if (m_values[i]->isFunctionValue()) {
     194            auto& functionValue = downcast<CSSFunctionValue>(*item(i));
     195            CSSValueList* args = functionValue.arguments();
     196            if (args && args->containsVariables())
     197                return true;
     198        } else if (m_values[i]->isValueList()) {
     199            auto& listValue = downcast<CSSValueList>(*item(i));
     200            if (listValue.containsVariables())
     201                return true;
     202        }
     203    }
     204    return false;
     205}
     206
     207bool CSSValueList::checkVariablesForCycles(CustomPropertyValueMap& customProperties, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const
     208{
     209    for (unsigned i = 0; i < m_values.size(); i++) {
     210        auto* value = item(i);
     211        if (value->isVariableValue()) {
     212            auto& variableValue = downcast<CSSVariableValue>(*value);
     213            if (seenProperties.contains(variableValue.name()))
     214                return false;
     215            RefPtr<CSSValue> value = customProperties.get(variableValue.name());
     216            if (value && value->isVariableDependentValue() && !downcast<CSSVariableDependentValue>(*value).checkVariablesForCycles(variableValue.name(), customProperties, seenProperties, invalidProperties))
     217                return false;
     218
     219            // Have to check the fallback values.
     220            auto* fallbackArgs = variableValue.fallbackArguments();
     221            if (!fallbackArgs || !fallbackArgs->length())
     222                continue;
     223           
     224            if (!fallbackArgs->checkVariablesForCycles(customProperties, seenProperties, invalidProperties))
     225                return false;
     226        } else if (value->isFunctionValue()) {
     227            auto& functionValue = downcast<CSSFunctionValue>(*value);
     228            auto* args = functionValue.arguments();
     229            if (args && !args->checkVariablesForCycles(customProperties, seenProperties, invalidProperties))
     230                return false;
     231        } else if (value->isValueList()) {
     232            auto& listValue = downcast<CSSValueList>(*value);
     233            if (!listValue.checkVariablesForCycles(customProperties, seenProperties, invalidProperties))
     234                return false;
     235        }
     236    }
     237    return true;
     238}
     239
     240bool CSSValueList::buildParserValueSubstitutingVariables(CSSParserValue* result, const CustomPropertyValueMap& customProperties) const
     241{
     242    result->id = CSSValueInvalid;
     243    result->unit = CSSParserValue::ValueList;
     244    result->valueList = new CSSParserValueList();
     245    return buildParserValueListSubstitutingVariables(result->valueList, customProperties);
     246}
     247
     248bool CSSValueList::buildParserValueListSubstitutingVariables(CSSParserValueList* parserList, const CustomPropertyValueMap& customProperties) const
     249{
     250    for (unsigned i = 0; i < m_values.size(); ++i) {
     251        CSSParserValue result;
     252        result.id = CSSValueInvalid;
     253        switch (m_values[i]->classType()) {
     254        case FunctionClass:
     255            if (!downcast<CSSFunctionValue>(*m_values[i].ptr()).buildParserValueSubstitutingVariables(&result, customProperties))
     256                return false;
     257            parserList->addValue(result);
     258            break;
     259        case ValueListClass:
     260            if (!downcast<CSSValueList>(*m_values[i].ptr()).buildParserValueSubstitutingVariables(&result, customProperties))
     261                return false;
     262            parserList->addValue(result);
     263            break;
     264        case VariableClass: {
     265            if (!downcast<CSSVariableValue>(*m_values[i].ptr()).buildParserValueListSubstitutingVariables(parserList, customProperties))
     266                return false;
     267            break;
     268        }
     269        case PrimitiveClass:
     270            // FIXME: Will have to change this if we start preserving invalid tokens.
     271            if (downcast<CSSPrimitiveValue>(*m_values[i].ptr()).buildParserValue(&result))
     272                parserList->addValue(result);
     273            break;
     274        default:
     275            ASSERT_NOT_REACHED();
     276            break;
     277            return false;
     278        }
     279    }
     280    return true;
     281}
     282   
    177283} // namespace WebCore
  • trunk/Source/WebCore/css/CSSValueList.h

    r188315 r191128  
    2828namespace WebCore {
    2929
     30struct CSSParserValue;
    3031class CSSParserValueList;
    3132
     
    7980    Ref<CSSValueList> cloneForCSSOM() const;
    8081
     82    bool containsVariables() const;
     83    bool checkVariablesForCycles(CustomPropertyValueMap& customProperties, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const;
     84   
     85    bool buildParserValueListSubstitutingVariables(CSSParserValueList*, const CustomPropertyValueMap& customProperties) const;
     86    bool buildParserValueSubstitutingVariables(CSSParserValue*, const CustomPropertyValueMap& customProperties) const;
     87   
    8188protected:
    8289    CSSValueList(ClassType, ValueListSeparator);
  • trunk/Source/WebCore/css/StyleProperties.cpp

    r190231 r191128  
    3030#include "CSSValueList.h"
    3131#include "CSSValuePool.h"
     32#include "CSSVariableDependentValue.h"
    3233#include "Document.h"
    3334#include "PropertySetCSSStyleDeclaration.h"
     
    210211        return getLayeredShorthandValue(webkitAnimationShorthand());
    211212    case CSSPropertyMarker: {
    212         RefPtr<CSSValue> value = getPropertyCSSValue(CSSPropertyMarkerStart);
     213        RefPtr<CSSValue> value = getPropertyCSSValueInternal(CSSPropertyMarkerStart);
    213214        if (value)
    214215            return value->cssText();
     
    232233String StyleProperties::borderSpacingValue(const StylePropertyShorthand& shorthand) const
    233234{
    234     RefPtr<CSSValue> horizontalValue = getPropertyCSSValue(shorthand.properties()[0]);
    235     RefPtr<CSSValue> verticalValue = getPropertyCSSValue(shorthand.properties()[1]);
     235    RefPtr<CSSValue> horizontalValue = getPropertyCSSValueInternal(shorthand.properties()[0]);
     236    if (horizontalValue && horizontalValue->isVariableDependentValue())
     237        return horizontalValue->cssText();
     238   
     239    RefPtr<CSSValue> verticalValue = getPropertyCSSValueInternal(shorthand.properties()[1]);
    236240
    237241    // While standard border-spacing property does not allow specifying border-spacing-vertical without
     
    376380
    377381    for (unsigned i = 0; i < size; ++i) {
    378         values[i] = getPropertyCSSValue(shorthand.properties()[i]);
     382        values[i] = getPropertyCSSValueInternal(shorthand.properties()[i]);
    379383        if (values[i]) {
     384            if (values[i]->isVariableDependentValue())
     385                return values[i]->cssText();
    380386            if (values[i]->isBaseValueList())
    381387                numLayers = std::max(downcast<CSSValueList>(*values[i]).length(), numLayers);
     
    512518    for (unsigned i = 0; i < shorthand.length(); ++i) {
    513519        if (!isPropertyImplicit(shorthand.properties()[i])) {
    514             RefPtr<CSSValue> value = getPropertyCSSValue(shorthand.properties()[i]);
     520            RefPtr<CSSValue> value = getPropertyCSSValueInternal(shorthand.properties()[i]);
    515521            if (!value)
    516522                return String();
     523            if (value->isVariableDependentValue())
     524                return value->cssText();
    517525            String valueText = value->cssText();
    518526            if (!i)
     
    541549    bool lastPropertyWasImportant = false;
    542550    for (unsigned i = 0; i < shorthand.length(); ++i) {
    543         RefPtr<CSSValue> value = getPropertyCSSValue(shorthand.properties()[i]);
     551        RefPtr<CSSValue> value = getPropertyCSSValueInternal(shorthand.properties()[i]);
    544552        // FIXME: CSSInitialValue::cssText should generate the right value.
    545553        if (!value)
    546554            return String();
     555        if (value->isVariableDependentValue())
     556            return value->cssText();
    547557        String text = value->cssText();
    548558        if (text.isNull())
     
    591601PassRefPtr<CSSValue> StyleProperties::getPropertyCSSValue(CSSPropertyID propertyID) const
    592602{
     603    PassRefPtr<CSSValue> value = getPropertyCSSValueInternal(propertyID);
     604    if (value && value->isVariableDependentValue()) {
     605        auto& dependentValue = downcast<CSSVariableDependentValue>(*value);
     606        if (dependentValue.propertyID() != propertyID)
     607            return CSSCustomPropertyValue::createInvalid(); // Have to return special "pending-substitution" value.
     608    }
     609    return value;
     610}
     611
     612PassRefPtr<CSSValue> StyleProperties::getPropertyCSSValueInternal(CSSPropertyID propertyID) const
     613{
    593614    int foundPropertyIndex = findPropertyIndex(propertyID);
    594615    if (foundPropertyIndex == -1)
     
    879900        CSSPropertyID borderFallbackShorthandProperty = CSSPropertyInvalid;
    880901        String value;
    881 
    882         switch (propertyID) {
    883         case CSSPropertyAnimationName:
    884         case CSSPropertyAnimationDuration:
    885         case CSSPropertyAnimationTimingFunction:
    886         case CSSPropertyAnimationDelay:
    887         case CSSPropertyAnimationIterationCount:
    888         case CSSPropertyAnimationDirection:
    889         case CSSPropertyAnimationFillMode:
    890             shorthandPropertyID = CSSPropertyAnimation;
    891             break;
    892         case CSSPropertyBackgroundPositionX:
    893             positionXPropertyIndex = n;
    894             continue;
    895         case CSSPropertyBackgroundPositionY:
    896             positionYPropertyIndex = n;
    897             continue;
    898         case CSSPropertyBackgroundRepeatX:
    899             repeatXPropertyIndex = n;
    900             continue;
    901         case CSSPropertyBackgroundRepeatY:
    902             repeatYPropertyIndex = n;
    903             continue;
    904         case CSSPropertyBorderTopWidth:
    905         case CSSPropertyBorderRightWidth:
    906         case CSSPropertyBorderBottomWidth:
    907         case CSSPropertyBorderLeftWidth:
    908             if (!borderFallbackShorthandProperty)
    909                 borderFallbackShorthandProperty = CSSPropertyBorderWidth;
    910             FALLTHROUGH;
    911         case CSSPropertyBorderTopStyle:
    912         case CSSPropertyBorderRightStyle:
    913         case CSSPropertyBorderBottomStyle:
    914         case CSSPropertyBorderLeftStyle:
    915             if (!borderFallbackShorthandProperty)
    916                 borderFallbackShorthandProperty = CSSPropertyBorderStyle;
    917             FALLTHROUGH;
    918         case CSSPropertyBorderTopColor:
    919         case CSSPropertyBorderRightColor:
    920         case CSSPropertyBorderBottomColor:
    921         case CSSPropertyBorderLeftColor:
    922             if (!borderFallbackShorthandProperty)
    923                 borderFallbackShorthandProperty = CSSPropertyBorderColor;
    924 
    925             // FIXME: Deal with cases where only some of border-(top|right|bottom|left) are specified.
    926             ASSERT(CSSPropertyBorder - firstCSSProperty < shorthandPropertyAppeared.size());
    927             if (!shorthandPropertyAppeared[CSSPropertyBorder - firstCSSProperty]) {
    928                 value = borderPropertyValue(ReturnNullOnUncommonValues);
    929                 if (value.isNull())
    930                     shorthandPropertyAppeared.set(CSSPropertyBorder - firstCSSProperty);
    931                 else
     902       
     903        if (property.value() && property.value()->isVariableDependentValue()) {
     904            auto& dependentValue = downcast<CSSVariableDependentValue>(*property.value());
     905            if (dependentValue.propertyID() != propertyID)
     906                shorthandPropertyID = dependentValue.propertyID();
     907        } else {
     908            switch (propertyID) {
     909            case CSSPropertyAnimationName:
     910            case CSSPropertyAnimationDuration:
     911            case CSSPropertyAnimationTimingFunction:
     912            case CSSPropertyAnimationDelay:
     913            case CSSPropertyAnimationIterationCount:
     914            case CSSPropertyAnimationDirection:
     915            case CSSPropertyAnimationFillMode:
     916                shorthandPropertyID = CSSPropertyAnimation;
     917                break;
     918            case CSSPropertyBackgroundPositionX:
     919                positionXPropertyIndex = n;
     920                continue;
     921            case CSSPropertyBackgroundPositionY:
     922                positionYPropertyIndex = n;
     923                continue;
     924            case CSSPropertyBackgroundRepeatX:
     925                repeatXPropertyIndex = n;
     926                continue;
     927            case CSSPropertyBackgroundRepeatY:
     928                repeatYPropertyIndex = n;
     929                continue;
     930            case CSSPropertyBorderTopWidth:
     931            case CSSPropertyBorderRightWidth:
     932            case CSSPropertyBorderBottomWidth:
     933            case CSSPropertyBorderLeftWidth:
     934                if (!borderFallbackShorthandProperty)
     935                    borderFallbackShorthandProperty = CSSPropertyBorderWidth;
     936                FALLTHROUGH;
     937            case CSSPropertyBorderTopStyle:
     938            case CSSPropertyBorderRightStyle:
     939            case CSSPropertyBorderBottomStyle:
     940            case CSSPropertyBorderLeftStyle:
     941                if (!borderFallbackShorthandProperty)
     942                    borderFallbackShorthandProperty = CSSPropertyBorderStyle;
     943                FALLTHROUGH;
     944            case CSSPropertyBorderTopColor:
     945            case CSSPropertyBorderRightColor:
     946            case CSSPropertyBorderBottomColor:
     947            case CSSPropertyBorderLeftColor:
     948                if (!borderFallbackShorthandProperty)
     949                    borderFallbackShorthandProperty = CSSPropertyBorderColor;
     950
     951                // FIXME: Deal with cases where only some of border-(top|right|bottom|left) are specified.
     952                ASSERT(CSSPropertyBorder - firstCSSProperty < shorthandPropertyAppeared.size());
     953                if (!shorthandPropertyAppeared[CSSPropertyBorder - firstCSSProperty]) {
     954                    value = borderPropertyValue(ReturnNullOnUncommonValues);
     955                    if (value.isNull())
     956                        shorthandPropertyAppeared.set(CSSPropertyBorder - firstCSSProperty);
     957                    else
     958                        shorthandPropertyID = CSSPropertyBorder;
     959                } else if (shorthandPropertyUsed[CSSPropertyBorder - firstCSSProperty])
    932960                    shorthandPropertyID = CSSPropertyBorder;
    933             } else if (shorthandPropertyUsed[CSSPropertyBorder - firstCSSProperty])
    934                 shorthandPropertyID = CSSPropertyBorder;
    935             if (!shorthandPropertyID)
    936                 shorthandPropertyID = borderFallbackShorthandProperty;
    937             break;
    938         case CSSPropertyWebkitBorderHorizontalSpacing:
    939         case CSSPropertyWebkitBorderVerticalSpacing:
    940             shorthandPropertyID = CSSPropertyBorderSpacing;
    941             break;
    942         case CSSPropertyFontFamily:
    943         case CSSPropertyLineHeight:
    944         case CSSPropertyFontSize:
    945         case CSSPropertyFontStyle:
    946         case CSSPropertyFontVariant:
    947         case CSSPropertyFontWeight:
    948             // Don't use CSSPropertyFont because old UAs can't recognize them but are important for editing.
    949             break;
    950         case CSSPropertyListStyleType:
    951         case CSSPropertyListStylePosition:
    952         case CSSPropertyListStyleImage:
    953             shorthandPropertyID = CSSPropertyListStyle;
    954             break;
    955         case CSSPropertyMarginTop:
    956         case CSSPropertyMarginRight:
    957         case CSSPropertyMarginBottom:
    958         case CSSPropertyMarginLeft:
    959             shorthandPropertyID = CSSPropertyMargin;
    960             break;
    961         case CSSPropertyOutlineWidth:
    962         case CSSPropertyOutlineStyle:
    963         case CSSPropertyOutlineColor:
    964             shorthandPropertyID = CSSPropertyOutline;
    965             break;
    966         case CSSPropertyOverflowX:
    967         case CSSPropertyOverflowY:
    968             shorthandPropertyID = CSSPropertyOverflow;
    969             break;
    970         case CSSPropertyPaddingTop:
    971         case CSSPropertyPaddingRight:
    972         case CSSPropertyPaddingBottom:
    973         case CSSPropertyPaddingLeft:
    974             shorthandPropertyID = CSSPropertyPadding;
    975             break;
    976         case CSSPropertyTransitionProperty:
    977         case CSSPropertyTransitionDuration:
    978         case CSSPropertyTransitionTimingFunction:
    979         case CSSPropertyTransitionDelay:
    980             shorthandPropertyID = CSSPropertyTransition;
    981             break;
    982         case CSSPropertyWebkitAnimationName:
    983         case CSSPropertyWebkitAnimationDuration:
    984         case CSSPropertyWebkitAnimationTimingFunction:
    985         case CSSPropertyWebkitAnimationDelay:
    986         case CSSPropertyWebkitAnimationIterationCount:
    987         case CSSPropertyWebkitAnimationDirection:
    988         case CSSPropertyWebkitAnimationFillMode:
    989             shorthandPropertyID = CSSPropertyWebkitAnimation;
    990             break;
    991         case CSSPropertyFlexDirection:
    992         case CSSPropertyFlexWrap:
    993             shorthandPropertyID = CSSPropertyFlexFlow;
    994             break;
    995         case CSSPropertyFlexBasis:
    996         case CSSPropertyFlexGrow:
    997         case CSSPropertyFlexShrink:
    998             shorthandPropertyID = CSSPropertyFlex;
    999             break;
    1000         case CSSPropertyWebkitMaskPositionX:
    1001         case CSSPropertyWebkitMaskPositionY:
    1002         case CSSPropertyWebkitMaskRepeatX:
    1003         case CSSPropertyWebkitMaskRepeatY:
    1004         case CSSPropertyWebkitMaskImage:
    1005         case CSSPropertyWebkitMaskRepeat:
    1006         case CSSPropertyWebkitMaskPosition:
    1007         case CSSPropertyWebkitMaskClip:
    1008         case CSSPropertyWebkitMaskOrigin:
    1009             shorthandPropertyID = CSSPropertyWebkitMask;
    1010             break;
    1011         case CSSPropertyPerspectiveOriginX:
    1012         case CSSPropertyPerspectiveOriginY:
    1013             shorthandPropertyID = CSSPropertyPerspectiveOrigin;
    1014             break;
    1015         case CSSPropertyTransformOriginX:
    1016         case CSSPropertyTransformOriginY:
    1017         case CSSPropertyTransformOriginZ:
    1018             shorthandPropertyID = CSSPropertyTransformOrigin;
    1019             break;
    1020         case CSSPropertyWebkitTransitionProperty:
    1021         case CSSPropertyWebkitTransitionDuration:
    1022         case CSSPropertyWebkitTransitionTimingFunction:
    1023         case CSSPropertyWebkitTransitionDelay:
    1024             shorthandPropertyID = CSSPropertyWebkitTransition;
    1025             break;
    1026         default:
    1027             break;
     961                if (!shorthandPropertyID)
     962                    shorthandPropertyID = borderFallbackShorthandProperty;
     963                break;
     964            case CSSPropertyWebkitBorderHorizontalSpacing:
     965            case CSSPropertyWebkitBorderVerticalSpacing:
     966                shorthandPropertyID = CSSPropertyBorderSpacing;
     967                break;
     968            case CSSPropertyFontFamily:
     969            case CSSPropertyLineHeight:
     970            case CSSPropertyFontSize:
     971            case CSSPropertyFontStyle:
     972            case CSSPropertyFontVariant:
     973            case CSSPropertyFontWeight:
     974                // Don't use CSSPropertyFont because old UAs can't recognize them but are important for editing.
     975                break;
     976            case CSSPropertyListStyleType:
     977            case CSSPropertyListStylePosition:
     978            case CSSPropertyListStyleImage:
     979                shorthandPropertyID = CSSPropertyListStyle;
     980                break;
     981            case CSSPropertyMarginTop:
     982            case CSSPropertyMarginRight:
     983            case CSSPropertyMarginBottom:
     984            case CSSPropertyMarginLeft:
     985                shorthandPropertyID = CSSPropertyMargin;
     986                break;
     987            case CSSPropertyOutlineWidth:
     988            case CSSPropertyOutlineStyle:
     989            case CSSPropertyOutlineColor:
     990                shorthandPropertyID = CSSPropertyOutline;
     991                break;
     992            case CSSPropertyOverflowX:
     993            case CSSPropertyOverflowY:
     994                shorthandPropertyID = CSSPropertyOverflow;
     995                break;
     996            case CSSPropertyPaddingTop:
     997            case CSSPropertyPaddingRight:
     998            case CSSPropertyPaddingBottom:
     999            case CSSPropertyPaddingLeft:
     1000                shorthandPropertyID = CSSPropertyPadding;
     1001                break;
     1002            case CSSPropertyTransitionProperty:
     1003            case CSSPropertyTransitionDuration:
     1004            case CSSPropertyTransitionTimingFunction:
     1005            case CSSPropertyTransitionDelay:
     1006                shorthandPropertyID = CSSPropertyTransition;
     1007                break;
     1008            case CSSPropertyWebkitAnimationName:
     1009            case CSSPropertyWebkitAnimationDuration:
     1010            case CSSPropertyWebkitAnimationTimingFunction:
     1011            case CSSPropertyWebkitAnimationDelay:
     1012            case CSSPropertyWebkitAnimationIterationCount:
     1013            case CSSPropertyWebkitAnimationDirection:
     1014            case CSSPropertyWebkitAnimationFillMode:
     1015                shorthandPropertyID = CSSPropertyWebkitAnimation;
     1016                break;
     1017            case CSSPropertyFlexDirection:
     1018            case CSSPropertyFlexWrap:
     1019                shorthandPropertyID = CSSPropertyFlexFlow;
     1020                break;
     1021            case CSSPropertyFlexBasis:
     1022            case CSSPropertyFlexGrow:
     1023            case CSSPropertyFlexShrink:
     1024                shorthandPropertyID = CSSPropertyFlex;
     1025                break;
     1026            case CSSPropertyWebkitMaskPositionX:
     1027            case CSSPropertyWebkitMaskPositionY:
     1028            case CSSPropertyWebkitMaskRepeatX:
     1029            case CSSPropertyWebkitMaskRepeatY:
     1030            case CSSPropertyWebkitMaskImage:
     1031            case CSSPropertyWebkitMaskRepeat:
     1032            case CSSPropertyWebkitMaskPosition:
     1033            case CSSPropertyWebkitMaskClip:
     1034            case CSSPropertyWebkitMaskOrigin:
     1035                shorthandPropertyID = CSSPropertyWebkitMask;
     1036                break;
     1037            case CSSPropertyPerspectiveOriginX:
     1038            case CSSPropertyPerspectiveOriginY:
     1039                shorthandPropertyID = CSSPropertyPerspectiveOrigin;
     1040                break;
     1041            case CSSPropertyTransformOriginX:
     1042            case CSSPropertyTransformOriginY:
     1043            case CSSPropertyTransformOriginZ:
     1044                shorthandPropertyID = CSSPropertyTransformOrigin;
     1045                break;
     1046            case CSSPropertyWebkitTransitionProperty:
     1047            case CSSPropertyWebkitTransitionDuration:
     1048            case CSSPropertyWebkitTransitionTimingFunction:
     1049            case CSSPropertyWebkitTransitionDelay:
     1050                shorthandPropertyID = CSSPropertyWebkitTransition;
     1051                break;
     1052            default:
     1053                break;
     1054            }
    10281055        }
    10291056
     
    13191346    list.reserveInitialCapacity(length);
    13201347    for (unsigned i = 0; i < length; ++i) {
    1321         RefPtr<CSSValue> value = getPropertyCSSValue(set[i]);
     1348        RefPtr<CSSValue> value = getPropertyCSSValueInternal(set[i]);
    13221349        if (value)
    13231350            list.append(CSSProperty(set[i], value.release(), false));
  • trunk/Source/WebCore/css/StyleProperties.h

    r190209 r191128  
    153153    String fontValue() const;
    154154    void appendFontLonghandValueIfExplicit(CSSPropertyID, StringBuilder& result, String& value) const;
    155 
     155   
     156    PassRefPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID) const;
     157   
    156158    friend class PropertySetCSSStyleDeclaration;
    157159};
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r190845 r191128  
    4242#include "CSSFontValue.h"
    4343#include "CSSFunctionValue.h"
     44#include "CSSInheritedValue.h"
     45#include "CSSInitialValue.h"
    4446#include "CSSKeyframeRule.h"
    4547#include "CSSKeyframesRule.h"
     
    5759#include "CSSTimingFunctionValue.h"
    5860#include "CSSValueList.h"
     61#include "CSSVariableDependentValue.h"
    5962#include "CachedImage.h"
    6063#include "CachedResourceLoader.h"
     
    18791882
    18801883    State& state = m_state;
     1884   
     1885    RefPtr<CSSValue> valueToApply = value;
     1886    if (value->isVariableDependentValue()) {
     1887        valueToApply = resolvedVariableValue(id, *downcast<CSSVariableDependentValue>(value));
     1888        if (!valueToApply) {
     1889            if (CSSProperty::isInheritedProperty(id))
     1890                valueToApply = CSSInheritedValue::create();
     1891            else
     1892                valueToApply = CSSInitialValue::createExplicit();
     1893        }
     1894    }
    18811895
    18821896    if (CSSProperty::isDirectionAwareProperty(id)) {
    18831897        CSSPropertyID newId = CSSProperty::resolveDirectionAwareProperty(id, state.style()->direction(), state.style()->writingMode());
    18841898        ASSERT(newId != id);
    1885         return applyProperty(newId, value);
    1886     }
    1887 
    1888     bool isInherit = state.parentStyle() && value->isInheritedValue();
    1889     bool isInitial = value->isInitialValue() || (!state.parentStyle() && value->isInheritedValue());
     1899        return applyProperty(newId, valueToApply.get());
     1900    }
     1901   
     1902    CSSValue* valueToCheckForInheritInitial = valueToApply.get();
     1903    if (id == CSSPropertyCustom) {
     1904        CSSCustomPropertyValue* customProperty = &downcast<CSSCustomPropertyValue>(*valueToApply);
     1905        valueToCheckForInheritInitial = customProperty->value().get();
     1906    }
     1907
     1908    bool isInherit = state.parentStyle() && valueToCheckForInheritInitial->isInheritedValue();
     1909    bool isInitial = valueToCheckForInheritInitial->isInitialValue() || (!state.parentStyle() && valueToCheckForInheritInitial->isInheritedValue());
    18901910
    18911911    ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
     
    19001920   
    19011921    if (id == CSSPropertyCustom) {
    1902         CSSCustomPropertyValue* customProperty = &downcast<CSSCustomPropertyValue>(*value);
    1903         state.style()->setCustomPropertyValue(customProperty->name(), value);
     1922        CSSCustomPropertyValue* customProperty = &downcast<CSSCustomPropertyValue>(*valueToApply);
     1923        if (isInherit) {
     1924            RefPtr<CSSValue> customVal = state.parentStyle()->getCustomPropertyValue(customProperty->name());
     1925            if (!customVal)
     1926                customVal = CSSCustomPropertyValue::createInvalid();
     1927            state.style()->setCustomPropertyValue(customProperty->name(), customVal);
     1928        } else if (isInitial)
     1929            state.style()->setCustomPropertyValue(customProperty->name(), CSSCustomPropertyValue::createInvalid());
     1930        else
     1931            state.style()->setCustomPropertyValue(customProperty->name(), customProperty->value());
    19041932        return;
    19051933    }
    19061934
    19071935    // Use the generated StyleBuilder.
    1908     StyleBuilder::applyProperty(id, *this, *value, isInitial, isInherit);
     1936    StyleBuilder::applyProperty(id, *this, *valueToApply, isInitial, isInherit);
     1937}
     1938
     1939RefPtr<CSSValue> StyleResolver::resolvedVariableValue(CSSPropertyID propID, const CSSVariableDependentValue& value)
     1940{
     1941    CSSParser parser(m_state.document());
     1942    return parser.parseVariableDependentValue(propID, value, m_state.style()->customProperties());
    19091943}
    19101944
     
    26742708        property.apply(*this);
    26752709    }
     2710   
     2711    if (firstProperty == CSSPropertyCustom)
     2712        m_state.style()->checkVariablesInCustomProperties();
    26762713}
    26772714
  • trunk/Source/WebCore/css/StyleResolver.h

    r190347 r191128  
    470470
    471471    void applyProperty(CSSPropertyID, CSSValue*);
     472    RefPtr<CSSValue> resolvedVariableValue(CSSPropertyID, const CSSVariableDependentValue&);
    472473
    473474    void applySVGProperty(CSSPropertyID, CSSValue*);
  • trunk/Source/WebCore/css/makeprop.pl

    r190209 r191128  
    237237static const bool isInheritedPropertyTable[numCSSProperties + $numPredefinedProperties] = {
    238238    false, // CSSPropertyInvalid
    239     false, // CSSPropertyCustom
     239    true, // CSSPropertyCustom
    240240EOF
    241241
  • trunk/Source/WebCore/rendering/style/RenderStyle.cpp

    r191017 r191128  
    2525
    2626#include "ContentData.h"
     27#include "CSSCustomPropertyValue.h"
     28#include "CSSPropertyNames.h"
     29#include "CSSVariableDependentValue.h"
    2730#include "CursorList.h"
    28 #include "CSSPropertyNames.h"
    2931#include "FloatRoundedRect.h"
    3032#include "FontCascade.h"
     
    19881990#endif
    19891991
     1992void RenderStyle::checkVariablesInCustomProperties()
     1993{
     1994    if (!rareInheritedData->m_customProperties->containsVariables())
     1995        return;
     1996   
     1997    // Our first pass checks the variables for validity and replaces any properties that became
     1998    // invalid with empty values.
     1999    auto& customProperties = rareInheritedData.access()->m_customProperties.access()->values();
     2000    HashSet<AtomicString> invalidProperties;
     2001    for (auto entry : customProperties) {
     2002        if (!entry.value->isVariableDependentValue())
     2003            continue;
     2004        HashSet<AtomicString> seenProperties;
     2005        downcast<CSSVariableDependentValue>(*entry.value).checkVariablesForCycles(entry.key, customProperties, seenProperties, invalidProperties);
     2006    }
     2007   
     2008    // Now insert invalid values.
     2009    if (!invalidProperties.isEmpty()) {
     2010        RefPtr<CSSValue> invalidValue = CSSCustomPropertyValue::createInvalid();
     2011        for (auto& property : invalidProperties)
     2012            customProperties.set(property, invalidValue);
     2013    }
     2014
     2015    // Now that all of the properties have been tested for validity and replaced with
     2016    // invalid values if they failed, we can perform variable substitution on the valid values.
     2017    Vector<RefPtr<CSSCustomPropertyValue>> resolvedValues;
     2018    for (auto entry : customProperties) {
     2019        if (!entry.value->isVariableDependentValue())
     2020            continue;
     2021       
     2022        CSSParserValueList parserList;
     2023        RefPtr<CSSCustomPropertyValue> result;
     2024        if (!downcast<CSSVariableDependentValue>(*entry.value).valueList()->buildParserValueListSubstitutingVariables(&parserList, customProperties)) {
     2025            RefPtr<CSSValue> invalidResult = CSSCustomPropertyValue::createInvalid();
     2026            result = CSSCustomPropertyValue::create(entry.key, invalidResult);
     2027        } else {
     2028            RefPtr<CSSValue> newValueList = CSSValueList::createFromParserValueList(parserList);
     2029            result = CSSCustomPropertyValue::create(entry.key, newValueList);
     2030        }
     2031        resolvedValues.append(result);
     2032    }
     2033   
     2034    // With all results computed, we can now mutate our table to eliminate the variables and
     2035    // hold the final values. This way when we inherit, we don't end up resubstituting variables, etc.
     2036    for (auto& resolvedValue : resolvedValues)
     2037        customProperties.set(resolvedValue->name(), resolvedValue->value());
     2038
     2039    rareInheritedData.access()->m_customProperties.access()->setContainsVariables(false);
     2040}
     2041
    19902042} // namespace WebCore
  • trunk/Source/WebCore/rendering/style/RenderStyle.h

    r190754 r191128  
    519519    RefPtr<CSSValue> getCustomPropertyValue(const AtomicString& name) const { return rareInheritedData->m_customProperties->getCustomPropertyValue(name); }
    520520    bool hasCustomProperty(const AtomicString& name) const { return rareInheritedData->m_customProperties->hasCustomProperty(name); }
    521     const HashMap<AtomicString, RefPtr<CSSValue>>* customProperties() const { return &(rareInheritedData->m_customProperties->m_values); }
     521    const CustomPropertyValueMap& customProperties() const { return rareInheritedData->m_customProperties->m_values; }
    522522
    523523    void setHasViewportUnits(bool hasViewportUnits = true) { noninherited_flags.setHasViewportUnits(hasViewportUnits); }
     
    12021202    TrailingWord trailingWord() const { return static_cast<TrailingWord>(rareInheritedData->trailingWord); }
    12031203#endif
    1204        
     1204   
     1205    void checkVariablesInCustomProperties();
     1206
    12051207// attribute setter methods
    12061208
  • trunk/Source/WebCore/rendering/style/StyleCustomPropertyData.h

    r190231 r191128  
    2323#define StyleCustomPropertyData_h
    2424
     25#include "CSSValue.h"
    2526#include <wtf/Forward.h>
    2627#include <wtf/HashMap.h>
     
    3132namespace WebCore {
    3233
    33 class CSSValue;
    34 
    3534class StyleCustomPropertyData : public RefCounted<StyleCustomPropertyData> {
    3635public:
     
    3837    Ref<StyleCustomPropertyData> copy() const { return adoptRef(*new StyleCustomPropertyData(*this)); }
    3938   
    40     bool operator==(const StyleCustomPropertyData& o) const { return m_values == o.m_values; }
     39    bool operator==(const StyleCustomPropertyData& o) const
     40    {
     41        if (m_containsVariables != o.m_containsVariables)
     42            return false;
     43       
     44        if (m_values.size() != o.m_values.size())
     45            return false;
     46       
     47        for (WTF::KeyValuePair<AtomicString, RefPtr<CSSValue>> entry : m_values) {
     48            RefPtr<CSSValue> other = o.m_values.get(entry.key);
     49            if (!other || !entry.value->equals(*other))
     50                return false;
     51        }
     52        return true;
     53    }
     54
    4155    bool operator!=(const StyleCustomPropertyData &o) const { return !(*this == o); }
    4256   
    43     void setCustomPropertyValue(const AtomicString& name, const RefPtr<CSSValue>& value) { m_values.set(name, value); }
     57    void setCustomPropertyValue(const AtomicString& name, const RefPtr<CSSValue>& value)
     58    {
     59        m_values.set(name, value);
     60        if (value->isVariableDependentValue())
     61            m_containsVariables = true;
     62    }
     63
    4464    RefPtr<CSSValue> getCustomPropertyValue(const AtomicString& name) const { return m_values.get(name); }
     65    CustomPropertyValueMap& values() { return m_values; }
     66   
    4567    bool hasCustomProperty(const AtomicString& name) const { return m_values.contains(name); }
     68   
     69    bool containsVariables() const { return m_containsVariables; }
     70    void setContainsVariables(bool containsVariables) { m_containsVariables = containsVariables; }
    4671
    47     HashMap<AtomicString, RefPtr<CSSValue>> m_values;
    48    
     72    CustomPropertyValueMap m_values;
     73    bool m_containsVariables { false };
     74
    4975private:
    5076    explicit StyleCustomPropertyData()
     
    5379    StyleCustomPropertyData(const StyleCustomPropertyData& other)
    5480        : RefCounted<StyleCustomPropertyData>()
    55         , m_values(HashMap<AtomicString, RefPtr<CSSValue>>(other.m_values))
     81        , m_values(CustomPropertyValueMap(other.m_values))
     82        , m_containsVariables(other.m_containsVariables)
    5683    { }
    5784};
Note: See TracChangeset for help on using the changeset viewer.