[CSS Parser] Implement CSS variables
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 27 Oct 2016 22:05:01 +0000 (22:05 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 27 Oct 2016 22:05:01 +0000 (22:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=164075

Reviewed by Dean Jackson.

* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:
Add CSSCustomPropertyValue.cpp to the project.

* css/CSSCustomPropertyValue.cpp: Added.
(WebCore::CSSCustomPropertyValue::checkVariablesForCycles):
(WebCore::CSSCustomPropertyValue::resolveVariableReferences):
* css/CSSCustomPropertyValue.h:
These functions abstract the old and new implementations of CSS
variables so that the callers don't have to worry about it.

* css/CSSValue.cpp:
(WebCore::CSSValue::equals):
Make sure CSSVariableReferenceValue and CSSPendingSubstitutionValue
have equals implemented.

(WebCore::CSSValue::isInvalidCustomPropertyValue): Deleted.
This code was dead and never called.

* css/CSSValue.h:
(WebCore::CSSValue::isCustomPropertyValue):
(WebCore::CSSValue::hasVariableReferences):
Add a helper function for asking if a CSSValue has variable references.
This abstracts the old and new implementations so that callers can
ask if the value has variables without caring which implementation is
being used.

* css/CSSValueList.cpp:
(WebCore::CSSValueList::checkVariablesForCycles):
* css/CSSValueList.h:
In order to abstract the old and new variables implementations, custom
properties now store CSSCustomPropertyValue as their values instead of
raw values. The old implementation needs to be patched to deal with this
wrapper being present now.

* css/CSSVariableData.cpp:
(WebCore::CSSVariableData::checkVariablesForCycles):
(WebCore::CSSVariableData::checkVariablesForCyclesWithRange):
(WebCore::CSSVariableData::resolveVariableFallback):
(WebCore::CSSVariableData::resolveVariableReference):
(WebCore::CSSVariableData::resolveVariableReferences):
(WebCore::CSSVariableData::resolveTokenRange):
* css/CSSVariableData.h:
Implementation of cycle checking and variable resolution. The logic of
this implementation is the same as the old. It walks CSSParserTokens
instead of the old CSSParser structures.

* css/CSSVariableReferenceValue.cpp:
(WebCore::CSSVariableReferenceValue::customCSSText):
Add support for serialization caching, just like the old implementation
had in CSSVariableDependentValue.

(WebCore::CSSVariableReferenceValue::checkVariablesForCycles):
* css/CSSVariableReferenceValue.h:
Add cycle checking and variable resolution helper functions.

* css/CSSVariableValue.cpp:
(WebCore::CSSVariableValue::buildParserValueListSubstitutingVariables):
Patched to account for the change in storage of custom properties to
have custom property value wrappers.

* css/StyleProperties.cpp:
(WebCore::StyleProperties::getPropertyValue):
(WebCore::StyleProperties::borderSpacingValue):
(WebCore::StyleProperties::getLayeredShorthandValue):
(WebCore::StyleProperties::getShorthandValue):
(WebCore::StyleProperties::getCommonValue):
(WebCore::StyleProperties::getPropertyCSSValue):
(WebCore::StyleProperties::asText):
Clean up the resolution of pending substitution values. Instead of hacking
it into every possible StyleShorthandProperty crawling function, obtain
the shorthand for the property up front, access the first longhand, and
if we see a pending substitution value, perform the substitution.

* css/StyleResolver.cpp:
(WebCore::StyleResolver::MatchResult::addMatchedProperties):
(WebCore::StyleResolver::applyProperty):
(WebCore::StyleResolver::resolvedVariableValue):
* css/StyleResolver.h:
Add support for the new implementation in all the same places as the old.

* css/parser/CSSParser.cpp:
(WebCore::CSSParser::parseInlineStyleDeclaration):
(WebCore::CSSParser::parseValueWithVariableReferences):
(WebCore::CSSParser::parseVariableDependentValue): Deleted.
* css/parser/CSSParser.h:
Rename parseVariableDependentValue to parseValueWithVariableReferences,
since it is operating on three distinct value types now. Turn on new
parser support for parseInlineStyleDeclaration.

* css/parser/CSSParserImpl.cpp:
(WebCore::filterProperties):
(WebCore::CSSParserImpl::parseVariableValue): Deleted.
(WebCore::CSSParserImpl::parseCustomPropertySet): Deleted.
* css/parser/CSSParserImpl.h:
Remove parser functions that aren't relevant to our implementation
of CSS variables.

* css/parser/CSSVariableParser.cpp:
(WebCore::classifyVariableRange):
Add support for the CSS4 'revert' keyword to the new variable parser.

* rendering/style/RenderStyle.cpp:
(WebCore::RenderStyle::checkVariablesInCustomProperties):
Modified to store CSSCustomPropertyValues as the values always now and
to use the method abstractions on CSSCustomPropertyValue to resolve
cycles and perform substitutions.

* rendering/style/RenderStyle.h:
(WebCore::RenderStyle::setCustomPropertyValue):
(WebCore::RenderStyle::getCustomPropertyValue):
* rendering/style/StyleCustomPropertyData.h:
(WebCore::StyleCustomPropertyData::operator==):
(WebCore::StyleCustomPropertyData::setCustomPropertyValue):
(WebCore::StyleCustomPropertyData::getCustomPropertyValue):
Tighten up the map to store CSSCustomPropertyValue instead of just
CSSValue.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208006 268f45cc-cd09-0410-ab3c-d52691b4dbfc

25 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSCustomPropertyValue.cpp [new file with mode: 0644]
Source/WebCore/css/CSSCustomPropertyValue.h
Source/WebCore/css/CSSValue.cpp
Source/WebCore/css/CSSValue.h
Source/WebCore/css/CSSValueList.cpp
Source/WebCore/css/CSSValueList.h
Source/WebCore/css/CSSVariableData.cpp
Source/WebCore/css/CSSVariableData.h
Source/WebCore/css/CSSVariableReferenceValue.cpp
Source/WebCore/css/CSSVariableReferenceValue.h
Source/WebCore/css/CSSVariableValue.cpp
Source/WebCore/css/StyleProperties.cpp
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/css/StyleResolver.h
Source/WebCore/css/parser/CSSParser.cpp
Source/WebCore/css/parser/CSSParser.h
Source/WebCore/css/parser/CSSParserImpl.cpp
Source/WebCore/css/parser/CSSParserImpl.h
Source/WebCore/css/parser/CSSVariableParser.cpp
Source/WebCore/rendering/style/RenderStyle.cpp
Source/WebCore/rendering/style/RenderStyle.h
Source/WebCore/rendering/style/StyleCustomPropertyData.h

index 7cef284..9f89fa5 100644 (file)
@@ -1271,6 +1271,7 @@ set(WebCore_SOURCES
     css/CSSCrossfadeValue.cpp
     css/CSSCursorImageValue.cpp
     css/CSSCustomIdentValue.cpp
+    css/CSSCustomPropertyValue.cpp
     css/CSSDefaultStyleSheets.cpp
     css/CSSFilterImageValue.cpp
     css/FontFaceSet.cpp
index 65f4aac..31399af 100644 (file)
@@ -1,3 +1,128 @@
+2016-10-27  Dave Hyatt  <hyatt@apple.com>
+
+        [CSS Parser] Implement CSS variables
+        https://bugs.webkit.org/show_bug.cgi?id=164075
+
+        Reviewed by Dean Jackson.
+
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        Add CSSCustomPropertyValue.cpp to the project.
+
+        * css/CSSCustomPropertyValue.cpp: Added.
+        (WebCore::CSSCustomPropertyValue::checkVariablesForCycles):
+        (WebCore::CSSCustomPropertyValue::resolveVariableReferences):
+        * css/CSSCustomPropertyValue.h:
+        These functions abstract the old and new implementations of CSS
+        variables so that the callers don't have to worry about it.
+
+        * css/CSSValue.cpp:
+        (WebCore::CSSValue::equals):
+        Make sure CSSVariableReferenceValue and CSSPendingSubstitutionValue
+        have equals implemented.
+
+        (WebCore::CSSValue::isInvalidCustomPropertyValue): Deleted.
+        This code was dead and never called.
+
+        * css/CSSValue.h:
+        (WebCore::CSSValue::isCustomPropertyValue):
+        (WebCore::CSSValue::hasVariableReferences):
+        Add a helper function for asking if a CSSValue has variable references.
+        This abstracts the old and new implementations so that callers can
+        ask if the value has variables without caring which implementation is
+        being used.
+
+        * css/CSSValueList.cpp:
+        (WebCore::CSSValueList::checkVariablesForCycles):
+        * css/CSSValueList.h:
+        In order to abstract the old and new variables implementations, custom
+        properties now store CSSCustomPropertyValue as their values instead of
+        raw values. The old implementation needs to be patched to deal with this
+        wrapper being present now.
+
+        * css/CSSVariableData.cpp:
+        (WebCore::CSSVariableData::checkVariablesForCycles):
+        (WebCore::CSSVariableData::checkVariablesForCyclesWithRange):
+        (WebCore::CSSVariableData::resolveVariableFallback):
+        (WebCore::CSSVariableData::resolveVariableReference):
+        (WebCore::CSSVariableData::resolveVariableReferences):
+        (WebCore::CSSVariableData::resolveTokenRange):
+        * css/CSSVariableData.h:
+        Implementation of cycle checking and variable resolution. The logic of
+        this implementation is the same as the old. It walks CSSParserTokens
+        instead of the old CSSParser structures.
+
+        * css/CSSVariableReferenceValue.cpp:
+        (WebCore::CSSVariableReferenceValue::customCSSText):
+        Add support for serialization caching, just like the old implementation
+        had in CSSVariableDependentValue.
+
+        (WebCore::CSSVariableReferenceValue::checkVariablesForCycles):
+        * css/CSSVariableReferenceValue.h:
+        Add cycle checking and variable resolution helper functions.
+
+        * css/CSSVariableValue.cpp:
+        (WebCore::CSSVariableValue::buildParserValueListSubstitutingVariables):
+        Patched to account for the change in storage of custom properties to
+        have custom property value wrappers.
+
+        * css/StyleProperties.cpp:
+        (WebCore::StyleProperties::getPropertyValue):
+        (WebCore::StyleProperties::borderSpacingValue):
+        (WebCore::StyleProperties::getLayeredShorthandValue):
+        (WebCore::StyleProperties::getShorthandValue):
+        (WebCore::StyleProperties::getCommonValue):
+        (WebCore::StyleProperties::getPropertyCSSValue):
+        (WebCore::StyleProperties::asText):
+        Clean up the resolution of pending substitution values. Instead of hacking
+        it into every possible StyleShorthandProperty crawling function, obtain
+        the shorthand for the property up front, access the first longhand, and
+        if we see a pending substitution value, perform the substitution.
+
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::MatchResult::addMatchedProperties):
+        (WebCore::StyleResolver::applyProperty):
+        (WebCore::StyleResolver::resolvedVariableValue):
+        * css/StyleResolver.h:
+        Add support for the new implementation in all the same places as the old.
+
+        * css/parser/CSSParser.cpp:
+        (WebCore::CSSParser::parseInlineStyleDeclaration):
+        (WebCore::CSSParser::parseValueWithVariableReferences):
+        (WebCore::CSSParser::parseVariableDependentValue): Deleted.
+        * css/parser/CSSParser.h:
+        Rename parseVariableDependentValue to parseValueWithVariableReferences,
+        since it is operating on three distinct value types now. Turn on new
+        parser support for parseInlineStyleDeclaration.
+
+        * css/parser/CSSParserImpl.cpp:
+        (WebCore::filterProperties):
+        (WebCore::CSSParserImpl::parseVariableValue): Deleted.
+        (WebCore::CSSParserImpl::parseCustomPropertySet): Deleted.
+        * css/parser/CSSParserImpl.h:
+        Remove parser functions that aren't relevant to our implementation
+        of CSS variables.
+
+        * css/parser/CSSVariableParser.cpp:
+        (WebCore::classifyVariableRange):
+        Add support for the CSS4 'revert' keyword to the new variable parser.
+
+        * rendering/style/RenderStyle.cpp:
+        (WebCore::RenderStyle::checkVariablesInCustomProperties):
+        Modified to store CSSCustomPropertyValues as the values always now and
+        to use the method abstractions on CSSCustomPropertyValue to resolve
+        cycles and perform substitutions.
+
+        * rendering/style/RenderStyle.h:
+        (WebCore::RenderStyle::setCustomPropertyValue):
+        (WebCore::RenderStyle::getCustomPropertyValue):
+        * rendering/style/StyleCustomPropertyData.h:
+        (WebCore::StyleCustomPropertyData::operator==):
+        (WebCore::StyleCustomPropertyData::setCustomPropertyValue):
+        (WebCore::StyleCustomPropertyData::getCustomPropertyValue):
+        Tighten up the map to store CSSCustomPropertyValue instead of just
+        CSSValue.
+
 2016-10-27  Zalan Bujtas  <zalan@apple.com>
 
         RenderMultiColumnFlowThread::processPossibleSpannerDescendant should take RenderObject& instead of RenderObject*
index 159a6eb..28469e8 100644 (file)
                9444CBE31D8861980073A074 /* CSSCustomIdentValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9444CBE21D8861580073A074 /* CSSCustomIdentValue.cpp */; };
                9444CBE41D8861990073A074 /* CSSCustomIdentValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9444CBE11D8861580073A074 /* CSSCustomIdentValue.h */; };
                9444CBE71D8861C20073A074 /* CSSVariableData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9444CBDE1D8861580073A074 /* CSSVariableData.cpp */; };
-               9444CBE81D8861C20073A074 /* CSSVariableData.h in Headers */ = {isa = PBXBuildFile; fileRef = 9444CBDD1D8861580073A074 /* CSSVariableData.h */; };
+               9444CBE81D8861C20073A074 /* CSSVariableData.h in Headers */ = {isa = PBXBuildFile; fileRef = 9444CBDD1D8861580073A074 /* CSSVariableData.h */; settings = {ATTRIBUTES = (Private, ); }; };
                9444CBE91D8861CA0073A074 /* CSSVariableReferenceValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9444CBDC1D8861580073A074 /* CSSVariableReferenceValue.cpp */; };
-               9444CBEA1D8861CA0073A074 /* CSSVariableReferenceValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9444CBDB1D8861580073A074 /* CSSVariableReferenceValue.h */; };
+               9444CBEA1D8861CA0073A074 /* CSSVariableReferenceValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9444CBDB1D8861580073A074 /* CSSVariableReferenceValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
                946D372D1D6CB2940077084F /* CSSParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 946D37281D6CB28B0077084F /* CSSParser.cpp */; };
                946D372E1D6CB2940077084F /* CSSParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 946D37291D6CB28B0077084F /* CSSParser.h */; settings = {ATTRIBUTES = (Private, ); }; };
                946D372F1D6CB2940077084F /* CSSParserMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 946D372A1D6CB28B0077084F /* CSSParserMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
                946D37491D6D06280077084F /* CSSMarkup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 946D37471D6D060C0077084F /* CSSMarkup.cpp */; };
                946D374A1D6D06280077084F /* CSSMarkup.h in Headers */ = {isa = PBXBuildFile; fileRef = 946D37481D6D060C0077084F /* CSSMarkup.h */; };
                946D374D1D6D08A60077084F /* CSSParserTokenRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 946D374B1D6D07F50077084F /* CSSParserTokenRange.cpp */; };
-               946D374E1D6D08AA0077084F /* CSSParserTokenRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 946D374C1D6D07F50077084F /* CSSParserTokenRange.h */; };
+               946D374E1D6D08AA0077084F /* CSSParserTokenRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 946D374C1D6D07F50077084F /* CSSParserTokenRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
                9493B6BE1D74B4120088E780 /* MediaQueryBlockWatcher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9493B6B61D74B3950088E780 /* MediaQueryBlockWatcher.cpp */; };
                9493B6BF1D74B4120088E780 /* MediaQueryBlockWatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 9493B6B71D74B3950088E780 /* MediaQueryBlockWatcher.h */; };
                9493B6C01D74B4120088E780 /* MediaQueryParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9493B6B81D74B3950088E780 /* MediaQueryParser.cpp */; };
                949C77081D6E498700C0DE4F /* CSSParserObserverWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949C77061D6E48ED00C0DE4F /* CSSParserObserverWrapper.cpp */; };
                949C77091D6E498700C0DE4F /* CSSParserObserverWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 949C77071D6E48ED00C0DE4F /* CSSParserObserverWrapper.h */; };
                949C770B1D6E49ED00C0DE4F /* CSSParserObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 949C770A1D6E49C300C0DE4F /* CSSParserObserver.h */; };
+               94D4AC621DC24C8E0080F02D /* CSSCustomPropertyValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94D4AC611DC24C810080F02D /* CSSCustomPropertyValue.cpp */; };
                94DE5C7E1D78CB2E00164F2A /* CSSParserIdioms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94DE5C7D1D78CB2500164F2A /* CSSParserIdioms.cpp */; };
                94DE5C811D7F3A1400164F2A /* CSSAtRuleID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94DE5C7F1D7F39D000164F2A /* CSSAtRuleID.cpp */; };
                94DE5C821D7F3A1400164F2A /* CSSAtRuleID.h in Headers */ = {isa = PBXBuildFile; fileRef = 94DE5C801D7F39D000164F2A /* CSSAtRuleID.h */; };
                BC128B01137C8D4600CAC845 /* RenderGrid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC128B00137C8D4600CAC845 /* RenderGrid.cpp */; };
                BC14028A0E83680800319717 /* ScrollbarThemeComposite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC1402880E83680800319717 /* ScrollbarThemeComposite.cpp */; };
                BC14028B0E83680800319717 /* ScrollbarThemeComposite.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1402890E83680800319717 /* ScrollbarThemeComposite.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               BC1790BB1BB5AB3F0006D13E /* CSSVariableDependentValue.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1790BA1BB5AB3F0006D13E /* CSSVariableDependentValue.h */; };
+               BC1790BB1BB5AB3F0006D13E /* CSSVariableDependentValue.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1790BA1BB5AB3F0006D13E /* CSSVariableDependentValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BC1790BD1BBB36A80006D13E /* CSSVariableDependentValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC1790BC1BBB36A80006D13E /* CSSVariableDependentValue.cpp */; };
                BC1790C01BBF2C430006D13E /* CSSVariableValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC1790BE1BBF2C430006D13E /* CSSVariableValue.cpp */; };
                BC1790C11BBF2C430006D13E /* CSSVariableValue.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1790BF1BBF2C430006D13E /* CSSVariableValue.h */; };
                949C77061D6E48ED00C0DE4F /* CSSParserObserverWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CSSParserObserverWrapper.cpp; path = parser/CSSParserObserverWrapper.cpp; sourceTree = "<group>"; };
                949C77071D6E48ED00C0DE4F /* CSSParserObserverWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSParserObserverWrapper.h; path = parser/CSSParserObserverWrapper.h; sourceTree = "<group>"; };
                949C770A1D6E49C300C0DE4F /* CSSParserObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSParserObserver.h; path = parser/CSSParserObserver.h; sourceTree = "<group>"; };
+               94D4AC611DC24C810080F02D /* CSSCustomPropertyValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSCustomPropertyValue.cpp; sourceTree = "<group>"; };
                94DE5C7D1D78CB2500164F2A /* CSSParserIdioms.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CSSParserIdioms.cpp; path = parser/CSSParserIdioms.cpp; sourceTree = "<group>"; };
                94DE5C7F1D7F39D000164F2A /* CSSAtRuleID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CSSAtRuleID.cpp; path = parser/CSSAtRuleID.cpp; sourceTree = "<group>"; };
                94DE5C801D7F39D000164F2A /* CSSAtRuleID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSAtRuleID.h; path = parser/CSSAtRuleID.h; sourceTree = "<group>"; };
                                AA0978EE0ABAA6E100874480 /* CSSCursorImageValue.h */,
                                9444CBE21D8861580073A074 /* CSSCustomIdentValue.cpp */,
                                9444CBE11D8861580073A074 /* CSSCustomIdentValue.h */,
+                               94D4AC611DC24C810080F02D /* CSSCustomPropertyValue.cpp */,
                                BC779E131BB215BB00CAA8BF /* CSSCustomPropertyValue.h */,
                                4A9CC81516BB9AC600EC645A /* CSSDefaultStyleSheets.cpp */,
                                4A9CC81616BB9AC600EC645A /* CSSDefaultStyleSheets.h */,
                                B2FA3D5A0AB75A6F000E5AC4 /* JSSVGClipPathElement.cpp in Sources */,
                                B2FA3D5C0AB75A6F000E5AC4 /* JSSVGColor.cpp in Sources */,
                                B2FA3D5E0AB75A6F000E5AC4 /* JSSVGComponentTransferFunctionElement.cpp in Sources */,
+                               94D4AC621DC24C8E0080F02D /* CSSCustomPropertyValue.cpp in Sources */,
                                B2FA3D600AB75A6F000E5AC4 /* JSSVGCursorElement.cpp in Sources */,
                                B2FA3D620AB75A6F000E5AC4 /* JSSVGDefsElement.cpp in Sources */,
                                B2FA3D640AB75A6F000E5AC4 /* JSSVGDescElement.cpp in Sources */,
diff --git a/Source/WebCore/css/CSSCustomPropertyValue.cpp b/Source/WebCore/css/CSSCustomPropertyValue.cpp
new file mode 100644 (file)
index 0000000..c5201f8
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CSSCustomPropertyValue.h"
+
+#include "CSSParserValues.h"
+
+namespace WebCore {
+
+bool CSSCustomPropertyValue::checkVariablesForCycles(const AtomicString& name, CustomPropertyValueMap& customProperties, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const
+{
+    ASSERT(containsVariables());
+    if (m_deprecatedValue && m_deprecatedValue->isVariableDependentValue())
+        return downcast<CSSVariableDependentValue>(*m_deprecatedValue).checkVariablesForCycles(name, customProperties, seenProperties, invalidProperties);
+    if (m_value)
+        return m_value->checkVariablesForCycles(name, customProperties, seenProperties, invalidProperties);
+    return true;
+}
+
+void CSSCustomPropertyValue::resolveVariableReferences(const CustomPropertyValueMap& customProperties, Vector<Ref<CSSCustomPropertyValue>>& resolvedValues) const
+{
+    ASSERT(containsVariables());
+    if (m_deprecatedValue && m_deprecatedValue->isVariableDependentValue()) {
+        CSSParserValueList parserList;
+        if (!downcast<CSSVariableDependentValue>(*m_deprecatedValue).valueList().buildParserValueListSubstitutingVariables(&parserList, customProperties))
+            resolvedValues.append(CSSCustomPropertyValue::create(m_name, CSSCustomPropertyValue::createInvalid()));
+        else
+            resolvedValues.append(CSSCustomPropertyValue::create(m_name, CSSValueList::createFromParserValueList(parserList)));
+        return;
+    }
+    
+    if (!m_value)
+        return;
+    
+    ASSERT(m_value->needsVariableResolution());
+    RefPtr<CSSVariableData> resolvedData = m_value->resolveVariableReferences(customProperties);
+    if (resolvedData)
+        resolvedValues.append(CSSCustomPropertyValue::createWithVariableData(m_name, resolvedData.releaseNonNull()));
+    else
+        resolvedValues.append(CSSCustomPropertyValue::create(m_name, CSSCustomPropertyValue::createInvalid()));
+}
+
+}
index 9e92bb2..b4ad052 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "CSSValue.h"
 #include "CSSVariableData.h"
+#include "CSSVariableDependentValue.h"
 #include <wtf/RefPtr.h>
 #include <wtf/text/WTFString.h>
 
@@ -73,13 +74,17 @@ public:
 
     const AtomicString& name() const { return m_name; }
     
-    // FIXME: Should arguably implement equals on our internal values, but serialization to compare is probably fine.
-    bool equals(const CSSCustomPropertyValue& other) const { return m_name == other.m_name && customCSSText() == other.customCSSText(); }
+    bool equals(const CSSCustomPropertyValue& other) const { return m_name == other.m_name && m_deprecatedValue == other.m_deprecatedValue && m_value == other.m_value && m_valueId == other.m_valueId; }
 
-    bool isInvalid() const { return !m_value; }
     bool containsVariables() const { return m_containsVariables; }
+    bool checkVariablesForCycles(const AtomicString& name, CustomPropertyValueMap&, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const;
+
+    void resolveVariableReferences(const CustomPropertyValueMap&, Vector<Ref<CSSCustomPropertyValue>>&) const;
 
     const RefPtr<CSSValue> deprecatedValue() const { return m_deprecatedValue.get(); }
+    
+    CSSValueID valueID() const { return m_valueId; }
+    CSSVariableData* value() const { return m_value.get(); }
 
 private:
     CSSCustomPropertyValue(const AtomicString& name, Ref<CSSValue>&& value)
@@ -87,7 +92,6 @@ private:
         , m_name(name)
         , m_deprecatedValue(WTFMove(value))
         , m_containsVariables(m_deprecatedValue->isVariableDependentValue())
-        , m_serialized(false)
     {
     }
     
@@ -124,7 +128,7 @@ private:
     
     mutable String m_stringValue;
     bool m_containsVariables { false };
-    mutable bool m_serialized;
+    mutable bool m_serialized { false };
 };
 
 } // namespace WebCore
index 4edd9ab..08c928f 100644 (file)
@@ -245,6 +245,10 @@ bool CSSValue::equals(const CSSValue& other) const
             return compareCSSValues<CSSContentDistributionValue>(*this, other);
         case CustomPropertyClass:
             return compareCSSValues<CSSCustomPropertyValue>(*this, other);
+        case VariableReferenceClass:
+            return compareCSSValues<CSSVariableReferenceValue>(*this, other);
+        case PendingSubstitutionValueClass:
+            return compareCSSValues<CSSPendingSubstitutionValue>(*this, other);
         case VariableDependentClass:
             return compareCSSValues<CSSVariableDependentValue>(*this, other);
         case VariableClass:
@@ -552,11 +556,6 @@ RefPtr<CSSValue> CSSValue::cloneForCSSOM() const
     }
 }
 
-bool CSSValue::isInvalidCustomPropertyValue() const
-{
-    return isCustomPropertyValue() && downcast<CSSCustomPropertyValue>(*this).isInvalid();
-}
-
 bool CSSValue::treatAsInheritedValue(CSSPropertyID propertyID) const
 {
     return classType() == InheritedClass || (classType() == UnsetClass && CSSProperty::isInheritedProperty(propertyID));
index 6f5e4da..62330ac 100644 (file)
@@ -30,6 +30,7 @@
 
 namespace WebCore {
 
+class CSSCustomPropertyValue;
 class CachedResource;
 class StyleSheetContents;
 
@@ -78,7 +79,6 @@ public:
     bool isCrossfadeValue() const { return m_classType == CrossfadeClass; }
     bool isCursorImageValue() const { return m_classType == CursorImageClass; }
     bool isCustomPropertyValue() const { return m_classType == CustomPropertyClass; }
-    bool isInvalidCustomPropertyValue() const;
     bool isVariableDependentValue() const { return m_classType == VariableDependentClass; }
     bool isVariableValue() const { return m_classType == VariableClass; }
     bool isFunctionValue() const { return m_classType == FunctionClass; }
@@ -129,6 +129,8 @@ public:
     bool isCustomIdentValue() const { return m_classType == CustomIdentClass; }
     bool isVariableReferenceValue() const { return m_classType == VariableReferenceClass; }
     bool isPendingSubstitutionValue() const { return m_classType == PendingSubstitutionValueClass; }
+    
+    bool hasVariableReferences() const { return isVariableDependentValue() || isVariableReferenceValue() || isPendingSubstitutionValue(); }
 
     bool isCSSOMSafe() const { return m_isCSSOMSafe; }
     bool isSubtypeExposedToCSSOM() const
@@ -300,7 +302,7 @@ inline bool compareCSSValue(const Ref<CSSValueType>& first, const Ref<CSSValueTy
     return first.get().equals(second);
 }
 
-typedef HashMap<AtomicString, RefPtr<CSSValue>> CustomPropertyValueMap;
+typedef HashMap<AtomicString, RefPtr<CSSCustomPropertyValue>> CustomPropertyValueMap;
 
 } // namespace WebCore
 
index eacde93..258e748 100644 (file)
@@ -21,6 +21,7 @@
 #include "config.h"
 #include "CSSValueList.h"
 
+#include "CSSCustomPropertyValue.h"
 #include "CSSFunctionValue.h"
 #include "CSSParserValues.h"
 #include "CSSPrimitiveValue.h"
@@ -206,8 +207,8 @@ bool CSSValueList::checkVariablesForCycles(CustomPropertyValueMap& customPropert
             auto& variableValue = downcast<CSSVariableValue>(*value);
             if (seenProperties.contains(variableValue.name()))
                 return false;
-            RefPtr<CSSValue> value = customProperties.get(variableValue.name());
-            if (value && value->isVariableDependentValue() && !downcast<CSSVariableDependentValue>(*value).checkVariablesForCycles(variableValue.name(), customProperties, seenProperties, invalidProperties))
+            RefPtr<CSSCustomPropertyValue> value = customProperties.get(variableValue.name());
+            if (value && value->containsVariables() && !downcast<CSSVariableDependentValue>(*(value->deprecatedValue())).checkVariablesForCycles(variableValue.name(), customProperties, seenProperties, invalidProperties))
                 return false;
 
             // Have to check the fallback values.
index c50bb03..ec23149 100644 (file)
@@ -26,6 +26,7 @@
 
 namespace WebCore {
 
+class CSSCustomPropertyValue;
 struct CSSParserValue;
 class CSSParserValueList;
 
index 3d53e8f..4b61f8c 100644 (file)
@@ -30,6 +30,7 @@
 #include "config.h"
 #include "CSSVariableData.h"
 
+#include "CSSCustomPropertyValue.h"
 #include "CSSParser.h"
 #include "CSSParserTokenRange.h"
 #include <wtf/text/StringBuilder.h>
@@ -81,4 +82,100 @@ CSSVariableData::CSSVariableData(const CSSParserTokenRange& range, bool needsVar
     consumeAndUpdateTokens(range);
 }
 
+bool CSSVariableData::checkVariablesForCycles(const AtomicString& name, CustomPropertyValueMap& customProperties, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const
+{
+    if (invalidProperties.contains(name))
+        return false;
+    
+    HashSet<AtomicString> newSeenProperties = seenProperties;
+    newSeenProperties.add(name);
+    
+    bool valid = checkVariablesForCyclesWithRange(m_tokens, customProperties, newSeenProperties, invalidProperties);
+    if (!valid)
+        invalidProperties.add(name);
+    
+    return valid;
+}
+    
+bool CSSVariableData::checkVariablesForCyclesWithRange(CSSParserTokenRange range, CustomPropertyValueMap& customProperties, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const
+{
+    while (!range.atEnd()) {
+        if (range.peek().functionId() == CSSValueVar) {
+            CSSParserTokenRange block = range.consumeBlock();
+            
+            block.consumeWhitespace();
+            ASSERT(block.peek().type() == IdentToken);
+            AtomicString variableName = block.consumeIncludingWhitespace().value().toAtomicString();
+            ASSERT(block.atEnd() || block.peek().type() == CommaToken);
+            if (seenProperties.contains(variableName))
+                return false;
+
+            RefPtr<CSSCustomPropertyValue> value = customProperties.get(variableName);
+            if (value && value->containsVariables() && !value->checkVariablesForCycles(variableName, customProperties, seenProperties, invalidProperties))
+                return false;
+
+            if (range.peek().type() == CommaToken) {
+                // Fallback.
+                range.consume();
+                return checkVariablesForCyclesWithRange(block, customProperties, seenProperties, invalidProperties);
+            }
+        } else
+            range.consume();
+    }
+    return true;
+}
+
+bool CSSVariableData::resolveVariableFallback(const CustomPropertyValueMap& customProperties, CSSParserTokenRange range, Vector<CSSParserToken>& result) const
+{
+    if (range.atEnd())
+        return false;
+    ASSERT(range.peek().type() == CommaToken);
+    range.consume();
+    return resolveTokenRange(customProperties, range, result);
+}
+    
+bool CSSVariableData::resolveVariableReference(const CustomPropertyValueMap& customProperties, CSSParserTokenRange range, Vector<CSSParserToken>& result) const
+{
+    range.consumeWhitespace();
+    ASSERT(range.peek().type() == IdentToken);
+    AtomicString variableName = range.consumeIncludingWhitespace().value().toAtomicString();
+    ASSERT(range.atEnd() || (range.peek().type() == CommaToken));
+    
+    RefPtr<CSSCustomPropertyValue> property = customProperties.get(variableName);
+    if (!property || !property->value())
+        return resolveVariableFallback(customProperties, range, result);
+    
+    if (property->containsVariables()) {
+        // FIXME: Avoid doing this work more than once.
+        RefPtr<CSSVariableData> resolvedData = property->value()->resolveVariableReferences(customProperties);
+        if (!resolvedData)
+            return false;
+        result.appendVector(resolvedData->tokens());
+    } else
+        result.appendVector(property->value()->tokens());
+    
+    return true;
+}
+
+RefPtr<CSSVariableData> CSSVariableData::resolveVariableReferences(const CustomPropertyValueMap& customProperties) const
+{
+    Vector<CSSParserToken> resolvedTokens;
+    CSSParserTokenRange range = m_tokens;
+    if (!resolveTokenRange(customProperties, range, resolvedTokens))
+        return nullptr;
+    return CSSVariableData::createResolved(resolvedTokens, *this);
+}
+    
+bool CSSVariableData::resolveTokenRange(const CustomPropertyValueMap& customProperties, CSSParserTokenRange range, Vector<CSSParserToken>& result) const
+{
+    bool success = true;
+    while (!range.atEnd()) {
+        if (range.peek().functionId() == CSSValueVar)
+            success &= resolveVariableReference(customProperties, range.consumeBlock(), result);
+        else
+            result.append(range.consume());
+    }
+    return success;
+}
+
 } // namespace WebCore
index d6f8bae..3f76ee3 100644 (file)
@@ -59,6 +59,11 @@ public:
 
     bool needsVariableResolution() const { return m_needsVariableResolution; }
 
+    bool checkVariablesForCycles(const AtomicString& name, CustomPropertyValueMap&, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const;
+
+    RefPtr<CSSVariableData> resolveVariableReferences(const CustomPropertyValueMap& customProperties) const;
+    bool resolveTokenRange(const CustomPropertyValueMap&, CSSParserTokenRange, Vector<CSSParserToken>&) const;
+
 private:
     CSSVariableData(const CSSParserTokenRange&, bool needsVariableResolution);
 
@@ -74,6 +79,10 @@ private:
 
     void consumeAndUpdateTokens(const CSSParserTokenRange&);
     template<typename CharacterType> void updateTokens(const CSSParserTokenRange&);
+    
+    bool checkVariablesForCyclesWithRange(CSSParserTokenRange, CustomPropertyValueMap&, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const;
+    bool resolveVariableReference(const CustomPropertyValueMap&, CSSParserTokenRange, Vector<CSSParserToken>&) const;
+    bool resolveVariableFallback(const CustomPropertyValueMap&, CSSParserTokenRange, Vector<CSSParserToken>&) const;
 
     String m_backingString;
     Vector<CSSParserToken> m_tokens;
index 44f264c..2af5218 100644 (file)
@@ -34,8 +34,17 @@ namespace WebCore {
 
 String CSSVariableReferenceValue::customCSSText() const
 {
-    // We may want to consider caching this value.
-    return m_data->tokenRange().serialize();
+    if (!m_serialized) {
+        m_serialized = true;
+        m_stringValue = m_data->tokenRange().serialize();
+    }
+    return m_stringValue;
+}
+    
+bool CSSVariableReferenceValue::checkVariablesForCycles(const AtomicString& name, CustomPropertyValueMap& customProperties, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const
+{
+    ASSERT(m_data);
+    return m_data->checkVariablesForCycles(name, customProperties, seenProperties, invalidProperties);
 }
 
 } // namespace WebCore
index e7cccea..537f78a 100644 (file)
@@ -50,6 +50,8 @@ public:
     bool equals(const CSSVariableReferenceValue& other) const { return m_data == other.m_data; }
     String customCSSText() const;
 
+    bool checkVariablesForCycles(const AtomicString& name, CustomPropertyValueMap&, HashSet<AtomicString>& seenProperties, HashSet<AtomicString>& invalidProperties) const;
+
 private:
     CSSVariableReferenceValue(Ref<CSSVariableData>&& data)
         : CSSValue(VariableReferenceClass)
@@ -58,6 +60,8 @@ private:
     }
 
     RefPtr<CSSVariableData> m_data;
+    mutable String m_stringValue;
+    mutable bool m_serialized { false };
 };
 
 } // namespace WebCore
index 330b9a8..c0bb314 100644 (file)
@@ -69,10 +69,11 @@ bool CSSVariableValue::equals(const CSSVariableValue& other) const
 
 bool CSSVariableValue::buildParserValueListSubstitutingVariables(CSSParserValueList* resultList, const CustomPropertyValueMap& customProperties) const
 {
-    if (RefPtr<CSSValue> value = customProperties.get(m_name)) {
-        if (value->isValueList())
+    if (RefPtr<CSSCustomPropertyValue> customPropertyValue = customProperties.get(m_name)) {
+        auto value = customPropertyValue->deprecatedValue();
+        if (value && value->isValueList())
             return downcast<CSSValueList>(*value).buildParserValueListSubstitutingVariables(resultList, customProperties);
-        if (value->isVariableDependentValue())
+        if (value && value->isVariableDependentValue())
             return downcast<CSSVariableDependentValue>(*value).valueList().buildParserValueListSubstitutingVariables(resultList, customProperties);
     }
 
index 66b59cc..305332d 100644 (file)
@@ -26,6 +26,7 @@
 #include "CSSComputedStyleDeclaration.h"
 #include "CSSCustomPropertyValue.h"
 #include "CSSParser.h"
+#include "CSSPendingSubstitutionValue.h"
 #include "CSSValueKeywords.h"
 #include "CSSValueList.h"
 #include "CSSValuePool.h"
@@ -126,6 +127,17 @@ String StyleProperties::getPropertyValue(CSSPropertyID propertyID) const
     if (value)
         return value->cssText();
 
+    const StylePropertyShorthand& shorthand = shorthandForProperty(propertyID);
+    if (shorthand.length()) {
+        RefPtr<CSSValue> value = getPropertyCSSValueInternal(shorthand.properties()[0]);
+        if (!value)
+            return String();
+        if (value->isVariableDependentValue())
+            return value->cssText();
+        if (value->isPendingSubstitutionValue())
+            return downcast<CSSPendingSubstitutionValue>(*value).shorthandValue()->cssText();
+    }
+
     // Shorthand and 4-values properties
     switch (propertyID) {
     case CSSPropertyAll:
@@ -232,9 +244,6 @@ String StyleProperties::getCustomPropertyValue(const String& propertyName) const
 String StyleProperties::borderSpacingValue(const StylePropertyShorthand& shorthand) const
 {
     RefPtr<CSSValue> horizontalValue = getPropertyCSSValueInternal(shorthand.properties()[0]);
-    if (horizontalValue && horizontalValue->isVariableDependentValue())
-        return horizontalValue->cssText();
-    
     RefPtr<CSSValue> verticalValue = getPropertyCSSValueInternal(shorthand.properties()[1]);
 
     // While standard border-spacing property does not allow specifying border-spacing-vertical without
@@ -385,8 +394,6 @@ String StyleProperties::getLayeredShorthandValue(const StylePropertyShorthand& s
             // http://www.w3.org/TR/cssom-1/#serialize-a-css-declaration-block.
             return String();
         }
-        if (values[i]->isVariableDependentValue())
-            return values[i]->cssText();
         if (values[i]->isBaseValueList())
             numLayers = std::max(downcast<CSSValueList>(*values[i]).length(), numLayers);
         else
@@ -525,8 +532,6 @@ String StyleProperties::getShorthandValue(const StylePropertyShorthand& shorthan
             RefPtr<CSSValue> value = getPropertyCSSValueInternal(shorthand.properties()[i]);
             if (!value)
                 return String();
-            if (value->isVariableDependentValue())
-                return value->cssText();
             String valueText = value->cssText();
             if (!i)
                 commonValue = valueText;
@@ -554,11 +559,9 @@ String StyleProperties::getCommonValue(const StylePropertyShorthand& shorthand)
     bool lastPropertyWasImportant = false;
     for (unsigned i = 0; i < shorthand.length(); ++i) {
         RefPtr<CSSValue> value = getPropertyCSSValueInternal(shorthand.properties()[i]);
-        // FIXME: CSSInitialValue::cssText should generate the right value.
         if (!value)
             return String();
-        if (value->isVariableDependentValue())
-            return value->cssText();
+        // FIXME: CSSInitialValue::cssText should generate the right value.
         String text = value->cssText();
         if (text.isNull())
             return String();
@@ -611,6 +614,7 @@ RefPtr<CSSValue> StyleProperties::getPropertyCSSValue(CSSPropertyID propertyID)
         if (dependentValue.propertyID() != propertyID)
             return CSSCustomPropertyValue::createInvalid(); // Have to return special "pending-substitution" value.
     }
+
     return value;
 }
 
@@ -868,6 +872,10 @@ String StyleProperties::asText() const
             auto& dependentValue = downcast<CSSVariableDependentValue>(*property.value());
             if (dependentValue.propertyID() != propertyID)
                 shorthandPropertyID = dependentValue.propertyID();
+        } else if (property.value() && property.value()->isPendingSubstitutionValue()) {
+            auto& substitutionValue = downcast<CSSPendingSubstitutionValue>(*property.value());
+            shorthandPropertyID = substitutionValue.shorthandPropertyId();
+            value = substitutionValue.shorthandValue()->cssText();
         } else {
             switch (propertyID) {
             case CSSPropertyAnimationName:
index 26bbbb7..2ba03a0 100644 (file)
@@ -233,7 +233,7 @@ void StyleResolver::MatchResult::addMatchedProperties(const StyleProperties& pro
                     break;
                 }
 
-                if (value.isVariableDependentValue()) {
+                if (value.hasVariableReferences()) {
                     isCacheable = false;
                     break;
                 }
@@ -1586,8 +1586,8 @@ void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value, SelectorChe
     State& state = m_state;
     
     RefPtr<CSSValue> valueToApply = value;
-    if (value->isVariableDependentValue()) {
-        valueToApply = resolvedVariableValue(id, *downcast<CSSVariableDependentValue>(value));
+    if (value->hasVariableReferences()) {
+        valueToApply = resolvedVariableValue(id, *value);
         if (!valueToApply) {
             if (CSSProperty::isInheritedProperty(id))
                 valueToApply = CSSValuePool::singleton().createInheritedValue();
@@ -1604,17 +1604,23 @@ void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value, SelectorChe
     
     CSSValue* valueToCheckForInheritInitial = valueToApply.get();
     CSSCustomPropertyValue* customPropertyValue = nullptr;
+    CSSValueID customPropertyValueID = CSSValueInvalid;
     
     if (id == CSSPropertyCustom) {
+        // FIXME-NEWPARSER: Can clean this up once old parser is gone and remove
+        // the deprecatedValue call and the valueToCheckForInheritInitial variable.
         customPropertyValue = &downcast<CSSCustomPropertyValue>(*valueToApply);
         valueToCheckForInheritInitial = customPropertyValue->deprecatedValue().get();
+        customPropertyValueID = customPropertyValue->valueID();
+        if (customPropertyValueID != CSSValueInvalid)
+            valueToCheckForInheritInitial = valueToApply.get();
     }
 
-    bool isInherit = state.parentStyle() && valueToCheckForInheritInitial->isInheritedValue();
-    bool isInitial = valueToCheckForInheritInitial->isInitialValue() || (!state.parentStyle() && valueToCheckForInheritInitial->isInheritedValue());
+    bool isInherit = state.parentStyle() ? valueToCheckForInheritInitial->isInheritedValue() || customPropertyValueID == CSSValueInherit : false;
+    bool isInitial = valueToCheckForInheritInitial->isInitialValue() || customPropertyValueID == CSSValueInitial || (!state.parentStyle() && (valueToCheckForInheritInitial->isInheritedValue() || customPropertyValueID == CSSValueInherit));
     
-    bool isUnset = valueToCheckForInheritInitial->isUnsetValue();
-    bool isRevert = valueToCheckForInheritInitial->isRevertValue();
+    bool isUnset = valueToCheckForInheritInitial->isUnsetValue() || customPropertyValueID == CSSValueUnset;
+    bool isRevert = valueToCheckForInheritInitial->isRevertValue() || customPropertyValueID == CSSValueRevert;
 
     if (isRevert) {
         if (cascadeLevel() == UserAgentLevel || !matchResult)
@@ -1666,14 +1672,14 @@ void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value, SelectorChe
     if (id == CSSPropertyCustom) {
         CSSCustomPropertyValue* customProperty = &downcast<CSSCustomPropertyValue>(*valueToApply);
         if (isInherit) {
-            RefPtr<CSSValue> customVal = state.parentStyle()->getCustomPropertyValue(customProperty->name());
+            RefPtr<CSSCustomPropertyValue> customVal = state.parentStyle()->getCustomPropertyValue(customProperty->name());
             if (!customVal)
                 customVal = CSSCustomPropertyValue::createInvalid();
             state.style()->setCustomPropertyValue(customProperty->name(), customVal);
         } else if (isInitial)
             state.style()->setCustomPropertyValue(customProperty->name(), CSSCustomPropertyValue::createInvalid());
         else
-            state.style()->setCustomPropertyValue(customProperty->name(), customProperty->deprecatedValue());
+            state.style()->setCustomPropertyValue(customProperty->name(), customProperty);
         return;
     }
 
@@ -1681,10 +1687,10 @@ void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value, SelectorChe
     StyleBuilder::applyProperty(id, *this, *valueToApply, isInitial, isInherit);
 }
 
-RefPtr<CSSValue> StyleResolver::resolvedVariableValue(CSSPropertyID propID, const CSSVariableDependentValue& value)
+RefPtr<CSSValue> StyleResolver::resolvedVariableValue(CSSPropertyID propID, const CSSValue& value)
 {
     CSSParser parser(m_state.document());
-    return parser.parseVariableDependentValue(propID, value, m_state.style()->customProperties(), m_state.style()->direction(), m_state.style()->writingMode());
+    return parser.parseValueWithVariableReferences(propID, value, m_state.style()->customProperties(), m_state.style()->direction(), m_state.style()->writingMode());
 }
 
 RefPtr<StyleImage> StyleResolver::styleImage(CSSValue& value)
index 636b95d..e77baa3 100644 (file)
@@ -469,7 +469,7 @@ private:
     void cacheBorderAndBackground();
 
     void applyProperty(CSSPropertyID, CSSValue*, SelectorChecker::LinkMatchMask = SelectorChecker::MatchDefault, const MatchResult* = nullptr);
-    RefPtr<CSSValue> resolvedVariableValue(CSSPropertyID, const CSSVariableDependentValue&);
+    RefPtr<CSSValue> resolvedVariableValue(CSSPropertyID, const CSSValue&);
 
     void applySVGProperty(CSSPropertyID, CSSValue*);
 
index 55be7a1..1a8a46e 100644 (file)
 #include "CSSPageRule.h"
 #include "CSSParserFastPaths.h"
 #include "CSSParserImpl.h"
+#include "CSSPendingSubstitutionValue.h"
 #include "CSSPrimitiveValue.h"
 #include "CSSPrimitiveValueMappings.h"
+#include "CSSPropertyParser.h"
 #include "CSSPropertySourceData.h"
 #include "CSSReflectValue.h"
 #include "CSSRevertValue.h"
@@ -75,6 +77,7 @@
 #include "CSSValueList.h"
 #include "CSSValuePool.h"
 #include "CSSVariableDependentValue.h"
+#include "CSSVariableReferenceValue.h"
 #include "Counter.h"
 #include "Document.h"
 #include "FloatConversion.h"
@@ -1432,6 +1435,10 @@ Ref<ImmutableStyleProperties> CSSParser::parseInlineStyleDeclaration(const Strin
 {
     CSSParserContext context(element->document());
     context.mode = strictToCSSParserMode(element->isHTMLElement() && !element->document().inQuirksMode());
+
+    if (context.useNewParser)
+        return CSSParserImpl::parseInlineStyleDeclaration(string, element);
+
     return CSSParser(context).parseDeclaration(string, nullptr);
 }
 
@@ -1796,23 +1803,68 @@ void CSSParser::addExpandedPropertyForValue(CSSPropertyID propId, Ref<CSSValue>&
         addProperty(longhands[i], value.copyRef(), important);
 }
 
-RefPtr<CSSValue> CSSParser::parseVariableDependentValue(CSSPropertyID propID, const CSSVariableDependentValue& dependentValue, const CustomPropertyValueMap& customProperties, TextDirection direction, WritingMode writingMode)
+RefPtr<CSSValue> CSSParser::parseValueWithVariableReferences(CSSPropertyID propID, const CSSValue& value, const CustomPropertyValueMap& customProperties, TextDirection direction, WritingMode writingMode)
 {
-    m_valueList.reset(new CSSParserValueList());
-    if (!dependentValue.valueList().buildParserValueListSubstitutingVariables(m_valueList.get(), customProperties))
-        return nullptr;
+    if (value.isVariableDependentValue()) {
+        const CSSVariableDependentValue& dependentValue = downcast<CSSVariableDependentValue>(value);
+        m_valueList.reset(new CSSParserValueList());
+        if (!dependentValue.valueList().buildParserValueListSubstitutingVariables(m_valueList.get(), customProperties))
+            return nullptr;
+
+        CSSPropertyID dependentValuePropertyID = dependentValue.propertyID();
+        if (CSSProperty::isDirectionAwareProperty(dependentValuePropertyID))
+            dependentValuePropertyID = CSSProperty::resolveDirectionAwareProperty(dependentValuePropertyID, direction, writingMode);
 
-    CSSPropertyID dependentValuePropertyID = dependentValue.propertyID();
-    if (CSSProperty::isDirectionAwareProperty(dependentValuePropertyID))
-        dependentValuePropertyID = CSSProperty::resolveDirectionAwareProperty(dependentValuePropertyID, direction, writingMode);
+        if (!parseValue(dependentValuePropertyID, false))
+            return nullptr;
 
-    if (!parseValue(dependentValuePropertyID, false))
+        for (auto& property : m_parsedProperties) {
+            if (property.id() == propID)
+                return property.value();
+        }
+        
+        return nullptr;
+    }
+    
+    if (value.isPendingSubstitutionValue()) {
+        // FIXME: Should have a resolvedShorthands cache to stop this from being done
+        // over and over for each longhand value.
+        const CSSPendingSubstitutionValue& pendingSubstitution = downcast<CSSPendingSubstitutionValue>(value);
+        CSSPropertyID shorthandID = pendingSubstitution.shorthandPropertyId();
+        if (CSSProperty::isDirectionAwareProperty(shorthandID))
+            shorthandID = CSSProperty::resolveDirectionAwareProperty(shorthandID, direction, writingMode);
+        CSSVariableReferenceValue* shorthandValue = pendingSubstitution.shorthandValue();
+        const CSSVariableData* variableData = shorthandValue->variableDataValue();
+        ASSERT(variableData);
+        
+        Vector<CSSParserToken> resolvedTokens;
+        if (!variableData->resolveTokenRange(customProperties, variableData->tokens(), resolvedTokens))
+            return nullptr;
+        
+        ParsedPropertyVector parsedProperties;
+        if (!CSSPropertyParser::parseValue(shorthandID, false, resolvedTokens, m_context, parsedProperties, StyleRule::Style))
+            return nullptr;
+        
+        for (auto& property : parsedProperties) {
+            if (property.id() == propID)
+                return property.value();
+        }
+        
         return nullptr;
+    }
 
-    for (auto& property : m_parsedProperties) {
-        if (property.id() == propID)
-            return property.value();
+    if (value.isVariableReferenceValue()) {
+        const CSSVariableReferenceValue& valueWithReferences = downcast<CSSVariableReferenceValue>(value);
+        const CSSVariableData* variableData = valueWithReferences.variableDataValue();
+        ASSERT(variableData);
+        
+        Vector<CSSParserToken> resolvedTokens;
+        if (!variableData->resolveTokenRange(customProperties, variableData->tokens(), resolvedTokens))
+            return nullptr;
+        
+        return CSSPropertyParser::parseSingleValue(propID, resolvedTokens, m_context);
     }
+    
     return nullptr;
 }
 
index 6f9ce36..ee66213 100644 (file)
@@ -494,7 +494,7 @@ public:
 
     void setCustomPropertyName(const AtomicString& propertyName) { m_customPropertyName = propertyName; }
 
-    RefPtr<CSSValue> parseVariableDependentValue(CSSPropertyID, const CSSVariableDependentValue&, const CustomPropertyValueMap& customProperties, TextDirection, WritingMode);
+    RefPtr<CSSValue> parseValueWithVariableReferences(CSSPropertyID, const CSSValue&, const CustomPropertyValueMap& customProperties, TextDirection, WritingMode);
 
 private:
     bool is8BitSource() { return m_is8BitSource; }
index f41d1e3..c124b9a 100644 (file)
@@ -77,16 +77,6 @@ bool CSSParserImpl::parseValue(MutableStyleProperties* declaration, CSSPropertyI
     return declaration->addParsedProperties(parser.m_parsedProperties);
 }
 
-bool CSSParserImpl::parseVariableValue(MutableStyleProperties* declaration, const AtomicString& propertyName, const String& value, bool important, const CSSParserContext& context)
-{
-    CSSParserImpl parser(context);
-    CSSTokenizer::Scope scope(value);
-    parser.consumeVariableValue(scope.tokenRange(), propertyName, important);
-    if (parser.m_parsedProperties.isEmpty())
-        return false;
-    return declaration->addParsedProperties(parser.m_parsedProperties);
-}
-
 static inline void filterProperties(bool important, const ParsedPropertyVector& input, ParsedPropertyVector& output, size_t& unusedEntries, std::bitset<numCSSProperties>& seenProperties, HashSet<AtomicString>& seenCustomProperties)
 {
     // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found.
@@ -97,11 +87,10 @@ static inline void filterProperties(bool important, const ParsedPropertyVector&
         const unsigned propertyIDIndex = property.id() - firstCSSProperty;
         
         if (property.id() == CSSPropertyCustom) {
-            CSSCustomPropertyValue* customValue = downcast<CSSCustomPropertyValue>(property.value());
-            const AtomicString& name = customValue->name();
-            if (seenCustomProperties.contains(name))
+            auto& name = downcast<CSSCustomPropertyValue>(*property.value()).name();
+            if (!seenCustomProperties.add(name).isNewEntry)
                 continue;
-            seenCustomProperties.add(name);
+            output[--unusedEntries] = property;
             continue;
         }
         
@@ -243,29 +232,6 @@ CSSSelectorList CSSParserImpl::parsePageSelector(CSSParserTokenRange range, Styl
     return selectorList;
 }
 
-RefPtr<ImmutableStyleProperties> CSSParserImpl::parseCustomPropertySet(CSSParserTokenRange range)
-{
-    range.consumeWhitespace();
-    if (range.peek().type() != LeftBraceToken)
-        return nullptr;
-    CSSParserTokenRange block = range.consumeBlock();
-    range.consumeWhitespace();
-    if (!range.atEnd())
-        return nullptr;
-    CSSParserImpl parser(strictCSSParserContext());
-    parser.consumeDeclarationList(block, StyleRule::Style);
-
-    // FIXME-NEWPARSER: We dont support @apply yet.
-    // Drop nested @apply rules. Seems nicer to do this here instead of making
-    // a different StyleRule type
-    /*for (size_t i = parser.m_parsedProperties.size(); i--; ) {
-        if (parser.m_parsedProperties[i].id() == CSSPropertyApplyAtRule)
-            parser.m_parsedProperties.remove(i);
-    }*/
-
-    return createStyleProperties(parser.m_parsedProperties, HTMLStandardMode);
-}
-
 std::unique_ptr<Vector<double>> CSSParserImpl::parseKeyframeKeyList(const String& keyList)
 {
     return consumeKeyframeKeyList(CSSTokenizer::Scope(keyList).tokenRange());
index c0b1578..ea632a8 100644 (file)
@@ -83,15 +83,12 @@ public:
     };
 
     static bool parseValue(MutableStyleProperties*, CSSPropertyID, const String&, bool important, const CSSParserContext&);
-    static bool parseVariableValue(MutableStyleProperties*, const AtomicString& propertyName, const String&, bool important, const CSSParserContext&);
     static Ref<ImmutableStyleProperties> parseInlineStyleDeclaration(const String&, Element*);
     static bool parseDeclarationList(MutableStyleProperties*, const String&, const CSSParserContext&);
     static RefPtr<StyleRuleBase> parseRule(const String&, const CSSParserContext&, StyleSheetContents*, AllowedRulesType);
     static void parseStyleSheet(const String&, const CSSParserContext&, StyleSheetContents*);
     static CSSSelectorList parsePageSelector(CSSParserTokenRange, StyleSheetContents*);
 
-    static RefPtr<ImmutableStyleProperties> parseCustomPropertySet(CSSParserTokenRange);
-
     static std::unique_ptr<Vector<double>> parseKeyframeKeyList(const String&);
 
     bool supportsDeclaration(CSSParserTokenRange&);
index 4cbcd23..6acda4f 100644 (file)
@@ -130,7 +130,7 @@ static CSSValueID classifyVariableRange(CSSParserTokenRange range, bool& hasRefe
     range.consumeWhitespace();
     if (range.peek().type() == IdentToken) {
         CSSValueID id = range.consumeIncludingWhitespace().id();
-        if (range.atEnd() && (id == CSSValueInherit || id == CSSValueInitial || id == CSSValueUnset))
+        if (range.atEnd() && (id == CSSValueInherit || id == CSSValueInitial || id == CSSValueUnset || id == CSSValueRevert))
             return id;
     }
 
index 0800dcf..4275967 100644 (file)
@@ -2036,10 +2036,10 @@ void RenderStyle::checkVariablesInCustomProperties()
     auto& customProperties = rareInheritedData.access()->m_customProperties.access()->values();
     HashSet<AtomicString> invalidProperties;
     for (auto entry : customProperties) {
-        if (!entry.value->isVariableDependentValue())
+        if (!entry.value->containsVariables())
             continue;
         HashSet<AtomicString> seenProperties;
-        downcast<CSSVariableDependentValue>(*entry.value).checkVariablesForCycles(entry.key, customProperties, seenProperties, invalidProperties);
+        entry.value->checkVariablesForCycles(entry.key, customProperties, seenProperties, invalidProperties);
     }
     
     // Now insert invalid values.
@@ -2053,20 +2053,15 @@ void RenderStyle::checkVariablesInCustomProperties()
     // invalid values if they failed, we can perform variable substitution on the valid values.
     Vector<Ref<CSSCustomPropertyValue>> resolvedValues;
     for (auto entry : customProperties) {
-        if (!entry.value->isVariableDependentValue())
+        if (!entry.value->containsVariables())
             continue;
-        
-        CSSParserValueList parserList;
-        if (!downcast<CSSVariableDependentValue>(*entry.value).valueList().buildParserValueListSubstitutingVariables(&parserList, customProperties))
-            resolvedValues.append(CSSCustomPropertyValue::create(entry.key, CSSCustomPropertyValue::createInvalid()));
-        else
-            resolvedValues.append(CSSCustomPropertyValue::create(entry.key, CSSValueList::createFromParserValueList(parserList)));
+        entry.value->resolveVariableReferences(customProperties, resolvedValues);
     }
     
     // With all results computed, we can now mutate our table to eliminate the variables and
     // hold the final values. This way when we inherit, we don't end up resubstituting variables, etc.
     for (auto& resolvedValue : resolvedValues)
-        customProperties.set(resolvedValue->name(), resolvedValue->deprecatedValue());
+        customProperties.set(resolvedValue->name(), resolvedValue.copyRef());
 
     rareInheritedData.access()->m_customProperties.access()->setContainsVariables(false);
 }
index dd44b16..4eb92bb 100644 (file)
@@ -527,8 +527,8 @@ public:
 
     const PseudoStyleCache* cachedPseudoStyles() const { return m_cachedPseudoStyles.get(); }
 
-    void setCustomPropertyValue(const AtomicString& name, const RefPtr<CSSValue>& value) { rareInheritedData.access()->m_customProperties.access()->setCustomPropertyValue(name, value); }
-    RefPtr<CSSValue> getCustomPropertyValue(const AtomicString& name) const { return rareInheritedData->m_customProperties->getCustomPropertyValue(name); }
+    void setCustomPropertyValue(const AtomicString& name, const RefPtr<CSSCustomPropertyValue>& value) { rareInheritedData.access()->m_customProperties.access()->setCustomPropertyValue(name, value); }
+    RefPtr<CSSCustomPropertyValue> getCustomPropertyValue(const AtomicString& name) const { return rareInheritedData->m_customProperties->getCustomPropertyValue(name); }
     bool hasCustomProperty(const AtomicString& name) const { return rareInheritedData->m_customProperties->hasCustomProperty(name); }
     const CustomPropertyValueMap& customProperties() const { return rareInheritedData->m_customProperties->m_values; }
 
index c0a1968..c4e09f4 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef StyleCustomPropertyData_h
 #define StyleCustomPropertyData_h
 
-#include "CSSValue.h"
+#include "CSSCustomPropertyValue.h"
 #include <wtf/Forward.h>
 #include <wtf/HashMap.h>
 #include <wtf/RefCounted.h>
@@ -44,8 +44,8 @@ public:
         if (m_values.size() != o.m_values.size())
             return false;
         
-        for (WTF::KeyValuePair<AtomicString, RefPtr<CSSValue>> entry : m_values) {
-            RefPtr<CSSValue> other = o.m_values.get(entry.key);
+        for (WTF::KeyValuePair<AtomicString, RefPtr<CSSCustomPropertyValue>> entry : m_values) {
+            RefPtr<CSSCustomPropertyValue> other = o.m_values.get(entry.key);
             if (!other || !entry.value->equals(*other))
                 return false;
         }
@@ -54,14 +54,14 @@ public:
 
     bool operator!=(const StyleCustomPropertyData &o) const { return !(*this == o); }
     
-    void setCustomPropertyValue(const AtomicString& name, const RefPtr<CSSValue>& value)
+    void setCustomPropertyValue(const AtomicString& name, const RefPtr<CSSCustomPropertyValue>& value)
     {
         m_values.set(name, value);
-        if (value->isVariableDependentValue())
+        if (value->containsVariables())
             m_containsVariables = true;
     }
 
-    RefPtr<CSSValue> getCustomPropertyValue(const AtomicString& name) const { return m_values.get(name); }
+    RefPtr<CSSCustomPropertyValue> getCustomPropertyValue(const AtomicString& name) const { return m_values.get(name); }
     CustomPropertyValueMap& values() { return m_values; }
     
     bool hasCustomProperty(const AtomicString& name) const { return m_values.contains(name); }