[CSS Parser] Add the main parser implementation
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 11 Sep 2016 18:11:42 +0000 (18:11 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 11 Sep 2016 18:11:42 +0000 (18:11 +0000)
https://bugs.webkit.org/show_bug.cgi?id=161813

Reviewed by Dean Jackson.

This patch adds the main CSSParserImpl that handles stylesheet and rule parsing. All parsing starts with this
class (it will eventually be invoked from the CSSParser). This patch also adds @supports parsing.

* WebCore.xcodeproj/project.pbxproj:
* css/CSSKeyframeRule.cpp:
(WebCore::StyleKeyframe::StyleKeyframe):
* css/CSSKeyframeRule.h:
* css/StyleRule.cpp:
(WebCore::StyleRuleBase::destroy):
(WebCore::StyleRuleBase::copy):
(WebCore::StyleRuleBase::createCSSOMWrapper):
(WebCore::StyleRuleCharset::StyleRuleCharset):
(WebCore::StyleRuleCharset::~StyleRuleCharset):
(WebCore::StyleRuleNamespace::StyleRuleNamespace):
(WebCore::StyleRuleNamespace::~StyleRuleNamespace):
* css/StyleRule.h:
(WebCore::StyleRuleBase::isNamespaceRule):
(isType):
(WebCore::StyleRuleBase::isKeyframesRule): Deleted.
* css/StyleSheetContents.cpp:
(WebCore::traverseSubresourcesInRules):
* css/parser/CSSParserImpl.cpp: Added.
(WebCore::CSSParserImpl::CSSParserImpl):
(WebCore::CSSParserImpl::parseValue):
(WebCore::CSSParserImpl::parseVariableValue):
(WebCore::filterProperties):
(WebCore::createStyleProperties):
(WebCore::CSSParserImpl::parseInlineStyleDeclaration):
(WebCore::CSSParserImpl::parseDeclarationList):
(WebCore::CSSParserImpl::parseRule):
(WebCore::CSSParserImpl::parseStyleSheet):
(WebCore::CSSParserImpl::parsePageSelector):
(WebCore::CSSParserImpl::parseCustomPropertySet):
(WebCore::CSSParserImpl::parseKeyframeKeyList):
(WebCore::CSSParserImpl::supportsDeclaration):
(WebCore::CSSParserImpl::parseDeclarationListForInspector):
(WebCore::CSSParserImpl::parseStyleSheetForInspector):
(WebCore::computeNewAllowedRules):
(WebCore::CSSParserImpl::consumeRuleList):
(WebCore::CSSParserImpl::consumeAtRule):
(WebCore::CSSParserImpl::consumeQualifiedRule):
(WebCore::consumeStringOrURI):
(WebCore::CSSParserImpl::consumeCharsetRule):
(WebCore::CSSParserImpl::consumeImportRule):
(WebCore::CSSParserImpl::consumeNamespaceRule):
(WebCore::CSSParserImpl::consumeMediaRule):
(WebCore::CSSParserImpl::consumeSupportsRule):
(WebCore::CSSParserImpl::consumeViewportRule):
(WebCore::CSSParserImpl::consumeFontFaceRule):
(WebCore::CSSParserImpl::consumeKeyframesRule):
(WebCore::CSSParserImpl::consumePageRule):
(WebCore::CSSParserImpl::consumeKeyframeStyleRule):
(WebCore::observeSelectors):
(WebCore::CSSParserImpl::consumeStyleRule):
(WebCore::CSSParserImpl::consumeDeclarationList):
(WebCore::CSSParserImpl::consumeDeclaration):
(WebCore::CSSParserImpl::consumeVariableValue):
(WebCore::CSSParserImpl::consumeDeclarationValue):
(WebCore::CSSParserImpl::consumeKeyframeKeyList):
* css/parser/CSSParserImpl.h: Added.
* css/parser/CSSParserValues.cpp:
(WebCore::CSSParserSelector::parsePagePseudoSelector):
* css/parser/CSSParserValues.h:
* css/parser/CSSPropertyParser.cpp:
(WebCore::CSSPropertyParser::parseValue):
* css/parser/CSSSupportsParser.cpp: Added.
(WebCore::CSSSupportsParser::supportsCondition):
(WebCore::CSSSupportsParser::consumeCondition):
(WebCore::CSSSupportsParser::consumeNegation):
(WebCore::CSSSupportsParser::consumeConditionInParenthesis):
* css/parser/CSSSupportsParser.h: Added.
(WebCore::CSSSupportsParser::CSSSupportsParser):

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

15 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSKeyframeRule.cpp
Source/WebCore/css/CSSKeyframeRule.h
Source/WebCore/css/StyleRule.cpp
Source/WebCore/css/StyleRule.h
Source/WebCore/css/StyleSheetContents.cpp
Source/WebCore/css/parser/CSSParserImpl.cpp [new file with mode: 0644]
Source/WebCore/css/parser/CSSParserImpl.h [new file with mode: 0644]
Source/WebCore/css/parser/CSSParserValues.cpp
Source/WebCore/css/parser/CSSParserValues.h
Source/WebCore/css/parser/CSSPropertyParser.cpp
Source/WebCore/css/parser/CSSSupportsParser.cpp [new file with mode: 0644]
Source/WebCore/css/parser/CSSSupportsParser.h [new file with mode: 0644]

index f4eac1d..4391203 100644 (file)
@@ -1353,6 +1353,7 @@ set(WebCore_SOURCES
     css/parser/CSSParser.cpp
     css/parser/CSSParserFastPaths.cpp
     css/parser/CSSParserIdioms.cpp
+    css/parser/CSSParserImpl.cpp
     css/parser/CSSParserObserverWrapper.cpp
     css/parser/CSSParserToken.cpp
     css/parser/CSSParserTokenRange.cpp
@@ -1360,6 +1361,7 @@ set(WebCore_SOURCES
     css/parser/CSSPropertyParser.cpp
     css/parser/CSSPropertyParserHelpers.cpp
     css/parser/CSSSelectorParser.cpp
+    css/parser/CSSSupportsParser.cpp
     css/parser/CSSTokenizer.cpp
     css/parser/CSSTokenizerInputStream.cpp
     css/parser/MediaQueryBlockWatcher.cpp
index 8fe8e18..6f2a304 100644 (file)
@@ -1,3 +1,83 @@
+2016-09-11  Dave Hyatt  <hyatt@apple.com>
+
+        [CSS Parser] Add the main parser implementation
+        https://bugs.webkit.org/show_bug.cgi?id=161813
+
+        Reviewed by Dean Jackson.
+
+        This patch adds the main CSSParserImpl that handles stylesheet and rule parsing. All parsing starts with this
+        class (it will eventually be invoked from the CSSParser). This patch also adds @supports parsing.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSKeyframeRule.cpp:
+        (WebCore::StyleKeyframe::StyleKeyframe):
+        * css/CSSKeyframeRule.h:
+        * css/StyleRule.cpp:
+        (WebCore::StyleRuleBase::destroy):
+        (WebCore::StyleRuleBase::copy):
+        (WebCore::StyleRuleBase::createCSSOMWrapper):
+        (WebCore::StyleRuleCharset::StyleRuleCharset):
+        (WebCore::StyleRuleCharset::~StyleRuleCharset):
+        (WebCore::StyleRuleNamespace::StyleRuleNamespace):
+        (WebCore::StyleRuleNamespace::~StyleRuleNamespace):
+        * css/StyleRule.h:
+        (WebCore::StyleRuleBase::isNamespaceRule):
+        (isType):
+        (WebCore::StyleRuleBase::isKeyframesRule): Deleted.
+        * css/StyleSheetContents.cpp:
+        (WebCore::traverseSubresourcesInRules):
+        * css/parser/CSSParserImpl.cpp: Added.
+        (WebCore::CSSParserImpl::CSSParserImpl):
+        (WebCore::CSSParserImpl::parseValue):
+        (WebCore::CSSParserImpl::parseVariableValue):
+        (WebCore::filterProperties):
+        (WebCore::createStyleProperties):
+        (WebCore::CSSParserImpl::parseInlineStyleDeclaration):
+        (WebCore::CSSParserImpl::parseDeclarationList):
+        (WebCore::CSSParserImpl::parseRule):
+        (WebCore::CSSParserImpl::parseStyleSheet):
+        (WebCore::CSSParserImpl::parsePageSelector):
+        (WebCore::CSSParserImpl::parseCustomPropertySet):
+        (WebCore::CSSParserImpl::parseKeyframeKeyList):
+        (WebCore::CSSParserImpl::supportsDeclaration):
+        (WebCore::CSSParserImpl::parseDeclarationListForInspector):
+        (WebCore::CSSParserImpl::parseStyleSheetForInspector):
+        (WebCore::computeNewAllowedRules):
+        (WebCore::CSSParserImpl::consumeRuleList):
+        (WebCore::CSSParserImpl::consumeAtRule):
+        (WebCore::CSSParserImpl::consumeQualifiedRule):
+        (WebCore::consumeStringOrURI):
+        (WebCore::CSSParserImpl::consumeCharsetRule):
+        (WebCore::CSSParserImpl::consumeImportRule):
+        (WebCore::CSSParserImpl::consumeNamespaceRule):
+        (WebCore::CSSParserImpl::consumeMediaRule):
+        (WebCore::CSSParserImpl::consumeSupportsRule):
+        (WebCore::CSSParserImpl::consumeViewportRule):
+        (WebCore::CSSParserImpl::consumeFontFaceRule):
+        (WebCore::CSSParserImpl::consumeKeyframesRule):
+        (WebCore::CSSParserImpl::consumePageRule):
+        (WebCore::CSSParserImpl::consumeKeyframeStyleRule):
+        (WebCore::observeSelectors):
+        (WebCore::CSSParserImpl::consumeStyleRule):
+        (WebCore::CSSParserImpl::consumeDeclarationList):
+        (WebCore::CSSParserImpl::consumeDeclaration):
+        (WebCore::CSSParserImpl::consumeVariableValue):
+        (WebCore::CSSParserImpl::consumeDeclarationValue):
+        (WebCore::CSSParserImpl::consumeKeyframeKeyList):
+        * css/parser/CSSParserImpl.h: Added.
+        * css/parser/CSSParserValues.cpp:
+        (WebCore::CSSParserSelector::parsePagePseudoSelector):
+        * css/parser/CSSParserValues.h:
+        * css/parser/CSSPropertyParser.cpp:
+        (WebCore::CSSPropertyParser::parseValue):
+        * css/parser/CSSSupportsParser.cpp: Added.
+        (WebCore::CSSSupportsParser::supportsCondition):
+        (WebCore::CSSSupportsParser::consumeCondition):
+        (WebCore::CSSSupportsParser::consumeNegation):
+        (WebCore::CSSSupportsParser::consumeConditionInParenthesis):
+        * css/parser/CSSSupportsParser.h: Added.
+        (WebCore::CSSSupportsParser::CSSSupportsParser):
+
 2016-09-11  Tim Horton  <timothy_horton@apple.com>
 
         Candidates that don't end in spaces shouldn't have spaces arbitrarily appended to them
index e8a74de..75923bf 100644 (file)
                94DE5C821D7F3A1400164F2A /* CSSAtRuleID.h in Headers */ = {isa = PBXBuildFile; fileRef = 94DE5C801D7F39D000164F2A /* CSSAtRuleID.h */; };
                94DE5C8D1D80802700164F2A /* CSSSelectorParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94DE5C8B1D80801500164F2A /* CSSSelectorParser.cpp */; };
                94DE5C8E1D80802700164F2A /* CSSSelectorParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 94DE5C8C1D80801500164F2A /* CSSSelectorParser.h */; };
+               94DE5C911D83011D00164F2A /* CSSSupportsParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94DE5C8F1D8300CB00164F2A /* CSSSupportsParser.cpp */; };
+               94DE5C921D83011D00164F2A /* CSSSupportsParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 94DE5C901D8300CB00164F2A /* CSSSupportsParser.h */; };
+               94DE5C951D8301BD00164F2A /* CSSParserImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94DE5C931D8301B000164F2A /* CSSParserImpl.cpp */; };
+               94DE5C961D8301BD00164F2A /* CSSParserImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 94DE5C941D8301B000164F2A /* CSSParserImpl.h */; };
                96ABA42314BCB80E00D56204 /* GraphicsContext3DOpenGLCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 96ABA42214BCB80E00D56204 /* GraphicsContext3DOpenGLCommon.cpp */; };
                9703E1BF15DC4E37001F24C8 /* JSVoidCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97E9EC8B15DC492F004F2E71 /* JSVoidCallback.cpp */; };
                97059977107D975200A50A7C /* PolicyCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97059973107D975200A50A7C /* PolicyCallback.cpp */; };
                94DE5C801D7F39D000164F2A /* CSSAtRuleID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSAtRuleID.h; path = parser/CSSAtRuleID.h; sourceTree = "<group>"; };
                94DE5C8B1D80801500164F2A /* CSSSelectorParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CSSSelectorParser.cpp; path = parser/CSSSelectorParser.cpp; sourceTree = "<group>"; };
                94DE5C8C1D80801500164F2A /* CSSSelectorParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSSelectorParser.h; path = parser/CSSSelectorParser.h; sourceTree = "<group>"; };
+               94DE5C8F1D8300CB00164F2A /* CSSSupportsParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CSSSupportsParser.cpp; path = parser/CSSSupportsParser.cpp; sourceTree = "<group>"; };
+               94DE5C901D8300CB00164F2A /* CSSSupportsParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSSupportsParser.h; path = parser/CSSSupportsParser.h; sourceTree = "<group>"; };
+               94DE5C931D8301B000164F2A /* CSSParserImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CSSParserImpl.cpp; path = parser/CSSParserImpl.cpp; sourceTree = "<group>"; };
+               94DE5C941D8301B000164F2A /* CSSParserImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSSParserImpl.h; path = parser/CSSParserImpl.h; sourceTree = "<group>"; };
                950C4C02BED8936F818E2F99 /* JSSVGGraphicsElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSSVGGraphicsElement.h; sourceTree = "<group>"; };
                96ABA42214BCB80E00D56204 /* GraphicsContext3DOpenGLCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GraphicsContext3DOpenGLCommon.cpp; sourceTree = "<group>"; };
                97059973107D975200A50A7C /* PolicyCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolicyCallback.cpp; sourceTree = "<group>"; };
                                949C76FF1D6E1D8C00C0DE4F /* CSSParserFastPaths.h */,
                                94DE5C7D1D78CB2500164F2A /* CSSParserIdioms.cpp */,
                                946D37431D6CF7880077084F /* CSSParserIdioms.h */,
+                               94DE5C931D8301B000164F2A /* CSSParserImpl.cpp */,
+                               94DE5C941D8301B000164F2A /* CSSParserImpl.h */,
                                946D372A1D6CB28B0077084F /* CSSParserMode.h */,
                                949C770A1D6E49C300C0DE4F /* CSSParserObserver.h */,
                                949C77061D6E48ED00C0DE4F /* CSSParserObserverWrapper.cpp */,
                                949C77031D6E393500C0DE4F /* CSSPropertyParserHelpers.h */,
                                94DE5C8B1D80801500164F2A /* CSSSelectorParser.cpp */,
                                94DE5C8C1D80801500164F2A /* CSSSelectorParser.h */,
+                               94DE5C8F1D8300CB00164F2A /* CSSSupportsParser.cpp */,
+                               94DE5C901D8300CB00164F2A /* CSSSupportsParser.h */,
                                946D37341D6CDF980077084F /* CSSTokenizer.cpp */,
                                946D37371D6CDF980077084F /* CSSTokenizer.h */,
                                946D37351D6CDF980077084F /* CSSTokenizerInputStream.cpp */,
                                7D4C96DD1AD4483500365A50 /* JSFetchHeaders.h in Headers */,
                                7E4C96DD1AD4483500365A50 /* JSFetchRequest.h in Headers */,
                                8E4C96DD1AD4483500365A50 /* JSFetchResponse.h in Headers */,
+                               94DE5C961D8301BD00164F2A /* CSSParserImpl.h in Headers */,
                                BC00F0150E0A189500FD04E3 /* JSFile.h in Headers */,
                                2E3BC0CB117D3E0800B9409A /* JSFileError.h in Headers */,
                                898785F1122E1E87003AABDA /* JSFileException.h in Headers */,
                                1A3586E015264C450022A659 /* RenderMultiColumnFlowThread.h in Headers */,
                                9493B6C11D74B4120088E780 /* MediaQueryParser.h in Headers */,
                                BCE32B9C1517C0B200F542EC /* RenderMultiColumnSet.h in Headers */,
+                               94DE5C921D83011D00164F2A /* CSSSupportsParser.h in Headers */,
                                BC1A7D9818FCB5B000421879 /* RenderMultiColumnSpannerPlaceholder.h in Headers */,
                                8AC822FD180FC03300FB64D5 /* RenderNamedFlowFragment.h in Headers */,
                                BC85F23D151915E000BC17BE /* RenderNamedFlowThread.h in Headers */,
                                59A85EA2119D68D900DEF1EF /* DeviceOrientationEvent.cpp in Sources */,
                                267725FC1A5B3AD9003C24DD /* DFA.cpp in Sources */,
                                5C9A7A751AA0F6EA00958ACF /* DFABytecodeCompiler.cpp in Sources */,
+                               94DE5C911D83011D00164F2A /* CSSSupportsParser.cpp in Sources */,
                                5C9A7A761AA0F6ED00958ACF /* DFABytecodeInterpreter.cpp in Sources */,
                                26A807841B18F97700E219BE /* DFACombiner.cpp in Sources */,
                                26A517FD1AB92238006335DF /* DFAMinimizer.cpp in Sources */,
                                418F88040FF957AE0080F045 /* JSAbstractWorker.cpp in Sources */,
                                FDA15EC912B03F50003A583A /* JSAnalyserNode.cpp in Sources */,
                                31A795C61888BADC00382F90 /* JSANGLEInstancedArrays.cpp in Sources */,
+                               94DE5C951D8301BD00164F2A /* CSSParserImpl.cpp in Sources */,
                                12A253E21C8FFF6600C22295 /* JSAnimatable.cpp in Sources */,
                                120DE3FE1C87E18800B6D4DD /* JSAnimationEffect.cpp in Sources */,
                                3198480B1A1E6CE400A13318 /* JSAnimationEvent.cpp in Sources */,
index e367f0a..45c5f8a 100644 (file)
 namespace WebCore {
 
 StyleKeyframe::StyleKeyframe(Ref<StyleProperties>&& properties)
-    : m_properties(WTFMove(properties))
+    : StyleRuleBase(Keyframe, 0)
+    , m_properties(WTFMove(properties))
 {
 }
 
+StyleKeyframe::StyleKeyframe(std::unique_ptr<Vector<double>> keys, Ref<StyleProperties>&& properties)
+    : StyleRuleBase(Keyframe, 0)
+    , m_properties(WTFMove(properties))
+    , m_keys(*keys)
+{
+}
+    
 StyleKeyframe::~StyleKeyframe()
 {
 }
index 70372df..d8e5fa4 100644 (file)
@@ -36,13 +36,19 @@ class CSSStyleDeclaration;
 class StyleRuleCSSStyleDeclaration;
 class CSSKeyframesRule;
 
-class StyleKeyframe final : public RefCounted<StyleKeyframe> {
-    WTF_MAKE_FAST_ALLOCATED;
+// FIXME-NEWPARSER: Rename this to StyleRuleKeyframe
+class StyleKeyframe final : public StyleRuleBase {
 public:
+    // FIXME-NEWPARSER: Remove this create function once we get rid of the old parser.
     static Ref<StyleKeyframe> create(Ref<StyleProperties>&& properties)
     {
         return adoptRef(*new StyleKeyframe(WTFMove(properties)));
     }
+
+    static Ref<StyleKeyframe> create(std::unique_ptr<Vector<double>> keys, Ref<StyleProperties>&& properties)
+    {
+        return adoptRef(*new StyleKeyframe(WTFMove(keys), WTFMove(properties)));
+    }
     ~StyleKeyframe();
 
     String keyText() const;
@@ -63,6 +69,7 @@ public:
 
 private:
     explicit StyleKeyframe(Ref<StyleProperties>&&);
+    StyleKeyframe(std::unique_ptr<Vector<double>>, Ref<StyleProperties>&&);
 
     Ref<StyleProperties> m_properties;
     Vector<double> m_keys;
index 9c5d441..1ec31a8 100644 (file)
@@ -90,9 +90,14 @@ void StyleRuleBase::destroy()
         delete downcast<StyleRuleViewport>(this);
         return;
 #endif
+    case Namespace:
+        delete downcast<StyleRuleNamespace>(this);
+        return;
+    case Keyframe:
+        delete downcast<StyleKeyframe>(this);
+        return;
     case Unknown:
     case Charset:
-    case Keyframe:
 #if !ENABLE(CSS_REGIONS)
     case Region:
 #endif
@@ -126,7 +131,8 @@ Ref<StyleRuleBase> StyleRuleBase::copy() const
         return downcast<StyleRuleViewport>(*this).copy();
 #endif
     case Import:
-        // FIXME: Copy import rules.
+    case Namespace:
+        // FIXME: Copy import and namespace rules.
         break;
     case Unknown:
     case Charset:
@@ -179,6 +185,7 @@ RefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet, CS
 #endif
     case Unknown:
     case Charset:
+    case Namespace: // FIXME: Add support for CSSNamespaceRule.
     case Keyframe:
 #if !ENABLE(CSS_REGIONS)
     case Region:
@@ -396,4 +403,36 @@ MutableStyleProperties& StyleRuleViewport::mutableProperties()
 }
 #endif // ENABLE(CSS_DEVICE_ADAPTATION)
 
+StyleRuleCharset::StyleRuleCharset()
+    : StyleRuleBase(Charset, 0)
+{
+}
+
+StyleRuleCharset::StyleRuleCharset(const StyleRuleCharset& o)
+    : StyleRuleBase(o)
+{
+}
+
+StyleRuleCharset::~StyleRuleCharset()
+{
+}
+
+StyleRuleNamespace::StyleRuleNamespace(AtomicString prefix, AtomicString uri)
+    : StyleRuleBase(Namespace, 0)
+    , m_prefix(prefix)
+    , m_uri(uri)
+{
+}
+
+StyleRuleNamespace::StyleRuleNamespace(const StyleRuleNamespace& o)
+    : StyleRuleBase(o)
+    , m_prefix(o.m_prefix)
+    , m_uri(o.m_uri)
+{
+}
+
+StyleRuleNamespace::~StyleRuleNamespace()
+{
+}
+
 } // namespace WebCore
index 0ad0b59..0bfc02b 100644 (file)
@@ -33,6 +33,7 @@ class CSSStyleRule;
 class CSSStyleSheet;
 class MediaQuerySet;
 class MutableStyleProperties;
+class StyleKeyframe;
 class StyleProperties;
 
 class StyleRuleBase : public WTF::RefCountedBase {
@@ -48,6 +49,7 @@ public:
         Page,
         Keyframes,
         Keyframe, // Not used. These are internally non-rule StyleKeyframe objects.
+        Namespace,
         Supports = 12,
 #if ENABLE(CSS_DEVICE_ADAPTATION)
         Viewport = 15,
@@ -60,6 +62,8 @@ public:
     bool isCharsetRule() const { return type() == Charset; }
     bool isFontFaceRule() const { return type() == FontFace; }
     bool isKeyframesRule() const { return type() == Keyframes; }
+    bool isKeyframeRule() const { return type() == Keyframe; }
+    bool isNamespaceRule() const { return type() == Namespace; }
     bool isMediaRule() const { return type() == Media; }
     bool isPageRule() const { return type() == Page; }
     bool isStyleRule() const { return type() == Style; }
@@ -144,7 +148,6 @@ public:
 
     Ref<StyleRuleFontFace> copy() const { return adoptRef(*new StyleRuleFontFace(*this)); }
 
-
 private:
     explicit StyleRuleFontFace(Ref<StyleProperties>&&);
     StyleRuleFontFace(const StyleRuleFontFace&);
@@ -265,6 +268,42 @@ private:
 };
 #endif // ENABLE(CSS_DEVICE_ADAPTATION)
 
+// This is only used by the CSS parser.
+class StyleRuleCharset final : public StyleRuleBase {
+public:
+    static Ref<StyleRuleCharset> create() { return adoptRef(*new StyleRuleCharset()); }
+    
+    ~StyleRuleCharset();
+    
+    Ref<StyleRuleCharset> copy() const { return adoptRef(*new StyleRuleCharset(*this)); }
+
+private:
+    explicit StyleRuleCharset();
+    StyleRuleCharset(const StyleRuleCharset&);
+};
+
+class StyleRuleNamespace final : public StyleRuleBase {
+public:
+    static Ref<StyleRuleNamespace> create(AtomicString prefix, AtomicString uri)
+    {
+        return adoptRef(*new StyleRuleNamespace(prefix, uri));
+    }
+    
+    ~StyleRuleNamespace();
+
+    Ref<StyleRuleNamespace> copy() const { return adoptRef(*new StyleRuleNamespace(*this)); }
+    
+    AtomicString prefix() const { return m_prefix; }
+    AtomicString uri() const { return m_uri; }
+
+private:
+    StyleRuleNamespace(AtomicString prefix, AtomicString uri);
+    StyleRuleNamespace(const StyleRuleNamespace&);
+    
+    AtomicString m_prefix;
+    AtomicString m_uri;
+};
+    
 } // namespace WebCore
 
 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRule)
@@ -296,3 +335,12 @@ SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRuleViewport)
     static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isViewportRule(); }
 SPECIALIZE_TYPE_TRAITS_END()
 #endif // ENABLE(CSS_DEVICE_ADAPTATION)
+
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleRuleNamespace)
+    static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isNamespaceRule(); }
+SPECIALIZE_TYPE_TRAITS_END()
+
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleKeyframe)
+static bool isType(const WebCore::StyleRuleBase& rule) { return rule.isKeyframeRule(); }
+SPECIALIZE_TYPE_TRAITS_END()
+
index 68287ab..e4cad95 100644 (file)
@@ -460,6 +460,7 @@ static bool traverseSubresourcesInRules(const Vector<RefPtr<StyleRuleBase>>& rul
 #endif
         case StyleRuleBase::Page:
         case StyleRuleBase::Keyframes:
+        case StyleRuleBase::Namespace:
         case StyleRuleBase::Unknown:
         case StyleRuleBase::Charset:
         case StyleRuleBase::Keyframe:
diff --git a/Source/WebCore/css/parser/CSSParserImpl.cpp b/Source/WebCore/css/parser/CSSParserImpl.cpp
new file mode 100644 (file)
index 0000000..35be366
--- /dev/null
@@ -0,0 +1,834 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// 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:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * 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.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "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 THE COPYRIGHT
+// OWNER 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 "CSSParserImpl.h"
+
+#include "CSSAtRuleID.h"
+#include "CSSCustomPropertyValue.h"
+#include "CSSKeyframeRule.h"
+#include "CSSKeyframesRule.h"
+#include "CSSParserObserver.h"
+#include "CSSParserObserverWrapper.h"
+#include "CSSParserValues.h" // FIXME-NEWPARSER We need to move CSSParserSelector to its own file.
+#include "CSSPropertyParser.h"
+#include "CSSSelectorParser.h"
+#include "CSSStyleSheet.h"
+#include "CSSSupportsParser.h"
+#include "CSSTokenizer.h"
+// FIXME-NEWPARSER: #include "CSSVariableParser.h"
+#include "Document.h"
+#include "Element.h"
+#include "MediaQueryParser.h"
+#include "StyleProperties.h"
+#include "StyleRuleImport.h"
+#include "StyleSheetContents.h"
+
+#include <bitset>
+#include <memory>
+
+namespace WebCore {
+
+CSSParserImpl::CSSParserImpl(const CSSParserContext& context, StyleSheetContents* styleSheet)
+    : m_context(context)
+    , m_styleSheet(styleSheet)
+    , m_observerWrapper(nullptr)
+{
+}
+
+bool CSSParserImpl::parseValue(MutableStyleProperties* declaration, CSSPropertyID unresolvedProperty, const String& string, bool important, const CSSParserContext& context)
+{
+    CSSParserImpl parser(context);
+    StyleRule::Type ruleType = StyleRule::Style;
+#if ENABLE(CSS_DEVICE_ADAPTATION)
+    if (declaration->cssParserMode() == CSSViewportRuleMode)
+        ruleType = StyleRule::Viewport;
+#endif
+    CSSTokenizer::Scope scope(string);
+    parser.consumeDeclarationValue(scope.tokenRange(), unresolvedProperty, important, ruleType);
+    if (parser.m_parsedProperties.isEmpty())
+        return false;
+    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.
+    for (size_t i = input.size(); i--; ) {
+        const CSSProperty& property = input[i];
+        if (property.isImportant() != important)
+            continue;
+        const unsigned propertyIDIndex = property.id() - firstCSSProperty;
+        
+        if (property.id() == CSSPropertyCustom) {
+            if (property.value()) {
+                auto& name = downcast<CSSCustomPropertyValue>(*property.value()).name();
+                if (!seenCustomProperties.add(name).isNewEntry)
+                    continue;
+                output[--unusedEntries] = property;
+            }
+            continue;
+        }
+        
+        // FIXME-NEWPARSER: We won't support @apply yet.
+        /*else if (property.id() == CSSPropertyApplyAtRule) {
+         // FIXME: Do we need to do anything here?
+         } */
+        
+        if (seenProperties.test(propertyIDIndex))
+            continue;
+        seenProperties.set(propertyIDIndex);
+
+        output[--unusedEntries] = property;
+    }
+}
+
+static Ref<ImmutableStyleProperties> createStyleProperties(ParsedPropertyVector& parsedProperties, CSSParserMode mode)
+{
+    std::bitset<numCSSProperties> seenProperties;
+    size_t unusedEntries = parsedProperties.size();
+    ParsedPropertyVector results(unusedEntries);
+    HashSet<AtomicString> seenCustomProperties;
+
+    filterProperties(true, parsedProperties, results, unusedEntries, seenProperties, seenCustomProperties);
+    filterProperties(false, parsedProperties, results, unusedEntries, seenProperties, seenCustomProperties);
+
+    Ref<ImmutableStyleProperties> result = ImmutableStyleProperties::create(results.data() + unusedEntries, results.size() - unusedEntries, mode);
+    parsedProperties.clear();
+    return result;
+}
+
+Ref<ImmutableStyleProperties> CSSParserImpl::parseInlineStyleDeclaration(const String& string, Element* element)
+{
+    Document& document = element->document();
+    CSSParserContext context = CSSParserContext(document.elementSheet().contents().parserContext());
+    CSSParserMode mode = element->isHTMLElement() && !document.inQuirksMode() ? HTMLStandardMode : HTMLQuirksMode;
+    context.mode = mode;
+    CSSParserImpl parser(context, &document.elementSheet().contents());
+    CSSTokenizer::Scope scope(string);
+    parser.consumeDeclarationList(scope.tokenRange(), StyleRule::Style);
+    return createStyleProperties(parser.m_parsedProperties, mode);
+}
+
+bool CSSParserImpl::parseDeclarationList(MutableStyleProperties* declaration, const String& string, const CSSParserContext& context)
+{
+    CSSParserImpl parser(context);
+    StyleRule::Type ruleType = StyleRule::Style;
+#if ENABLE(CSS_DEVICE_ADAPTATION)
+    if (declaration->cssParserMode() == CSSViewportRuleMode)
+        ruleType = StyleRule::Viewport;
+#endif
+    CSSTokenizer::Scope scope(string);
+    parser.consumeDeclarationList(scope.tokenRange(), ruleType);
+    if (parser.m_parsedProperties.isEmpty())
+        return false;
+
+    std::bitset<numCSSProperties> seenProperties;
+    size_t unusedEntries = parser.m_parsedProperties.size();
+    ParsedPropertyVector results(unusedEntries);
+    HashSet<AtomicString> seenCustomProperties;
+    filterProperties(true, parser.m_parsedProperties, results, unusedEntries, seenProperties, seenCustomProperties);
+    filterProperties(false, parser.m_parsedProperties, results, unusedEntries, seenProperties, seenCustomProperties);
+    if (unusedEntries)
+        results.remove(0, unusedEntries);
+    return declaration->addParsedProperties(results);
+}
+
+RefPtr<StyleRuleBase> CSSParserImpl::parseRule(const String& string, const CSSParserContext& context, StyleSheetContents* styleSheet, AllowedRulesType allowedRules)
+{
+    CSSParserImpl parser(context, styleSheet);
+    CSSTokenizer::Scope scope(string);
+    CSSParserTokenRange range = scope.tokenRange();
+    range.consumeWhitespace();
+    if (range.atEnd())
+        return nullptr; // Parse error, empty rule
+    RefPtr<StyleRuleBase> rule;
+    if (range.peek().type() == AtKeywordToken)
+        rule = parser.consumeAtRule(range, allowedRules);
+    else
+        rule = parser.consumeQualifiedRule(range, allowedRules);
+    if (!rule)
+        return nullptr; // Parse error, failed to consume rule
+    range.consumeWhitespace();
+    if (!rule || !range.atEnd())
+        return nullptr; // Parse error, trailing garbage
+    return rule;
+}
+
+void CSSParserImpl::parseStyleSheet(const String& string, const CSSParserContext& context, StyleSheetContents* styleSheet)
+{
+    CSSTokenizer::Scope scope(string);
+    CSSParserImpl parser(context, styleSheet);
+    bool firstRuleValid = parser.consumeRuleList(scope.tokenRange(), TopLevelRuleList, [&styleSheet](RefPtr<StyleRuleBase> rule) {
+        if (rule->isCharsetRule())
+            return;
+        styleSheet->parserAppendRule(rule.releaseNonNull());
+    });
+    styleSheet->setHasSyntacticallyValidCSSHeader(firstRuleValid);
+}
+
+CSSSelectorList CSSParserImpl::parsePageSelector(CSSParserTokenRange range, StyleSheetContents* styleSheet)
+{
+    // We only support a small subset of the css-page spec.
+    range.consumeWhitespace();
+    AtomicString typeSelector;
+    if (range.peek().type() == IdentToken)
+        typeSelector = range.consume().value().toAtomicString();
+
+    AtomicString pseudo;
+    if (range.peek().type() == ColonToken) {
+        range.consume();
+        if (range.peek().type() != IdentToken)
+            return CSSSelectorList();
+        pseudo = range.consume().value().toAtomicString();
+    }
+
+    range.consumeWhitespace();
+    if (!range.atEnd())
+        return CSSSelectorList(); // Parse error; extra tokens in @page selector
+
+    std::unique_ptr<CSSParserSelector> selector;
+    if (!typeSelector.isNull() && pseudo.isNull())
+        selector = std::unique_ptr<CSSParserSelector>(new CSSParserSelector(QualifiedName(nullAtom, typeSelector, styleSheet->defaultNamespace())));
+    else {
+        selector = std::unique_ptr<CSSParserSelector>(new CSSParserSelector);
+        if (!pseudo.isNull()) {
+            selector = std::unique_ptr<CSSParserSelector>(CSSParserSelector::parsePagePseudoSelector(pseudo));
+            if (!selector || selector->pseudoElementType() == CSSSelector::PseudoElementUnknown)
+                return CSSSelectorList();
+        }
+        if (!typeSelector.isNull())
+            selector->prependTagSelector(QualifiedName(nullAtom, typeSelector, styleSheet->defaultNamespace()));
+    }
+
+    selector->setForPage();
+    Vector<std::unique_ptr<CSSParserSelector>> selectorVector;
+    selectorVector.append(WTFMove(selector));
+    CSSSelectorList selectorList;
+    selectorList.adoptSelectorVector(selectorVector);
+    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());
+}
+
+bool CSSParserImpl::supportsDeclaration(CSSParserTokenRange& range)
+{
+    ASSERT(m_parsedProperties.isEmpty());
+    consumeDeclaration(range, StyleRule::Style);
+    bool result = !m_parsedProperties.isEmpty();
+    m_parsedProperties.clear();
+    return result;
+}
+
+void CSSParserImpl::parseDeclarationListForInspector(const String& declaration, const CSSParserContext& context, CSSParserObserver& observer)
+{
+    CSSParserImpl parser(context);
+    CSSParserObserverWrapper wrapper(observer);
+    parser.m_observerWrapper = &wrapper;
+    CSSTokenizer::Scope scope(declaration, wrapper);
+    observer.startRuleHeader(StyleRule::Style, 0);
+    observer.endRuleHeader(1);
+    parser.consumeDeclarationList(scope.tokenRange(), StyleRule::Style);
+}
+
+void CSSParserImpl::parseStyleSheetForInspector(const String& string, const CSSParserContext& context, StyleSheetContents* styleSheet, CSSParserObserver& observer)
+{
+    CSSParserImpl parser(context, styleSheet);
+    CSSParserObserverWrapper wrapper(observer);
+    parser.m_observerWrapper = &wrapper;
+    CSSTokenizer::Scope scope(string, wrapper);
+    bool firstRuleValid = parser.consumeRuleList(scope.tokenRange(), TopLevelRuleList, [&styleSheet](RefPtr<StyleRuleBase> rule) {
+        if (rule->isCharsetRule())
+            return;
+        styleSheet->parserAppendRule(rule.releaseNonNull());
+    });
+    styleSheet->setHasSyntacticallyValidCSSHeader(firstRuleValid);
+}
+
+static CSSParserImpl::AllowedRulesType computeNewAllowedRules(CSSParserImpl::AllowedRulesType allowedRules, StyleRuleBase* rule)
+{
+    if (!rule || allowedRules == CSSParserImpl::KeyframeRules || allowedRules == CSSParserImpl::NoRules)
+        return allowedRules;
+    ASSERT(allowedRules <= CSSParserImpl::RegularRules);
+    if (rule->isCharsetRule() || rule->isImportRule())
+        return CSSParserImpl::AllowImportRules;
+    if (rule->isNamespaceRule())
+        return CSSParserImpl::AllowNamespaceRules;
+    return CSSParserImpl::RegularRules;
+}
+
+template<typename T>
+bool CSSParserImpl::consumeRuleList(CSSParserTokenRange range, RuleListType ruleListType, const T callback)
+{
+    AllowedRulesType allowedRules = RegularRules;
+    switch (ruleListType) {
+    case TopLevelRuleList:
+        allowedRules = AllowCharsetRules;
+        break;
+    case RegularRuleList:
+        allowedRules = RegularRules;
+        break;
+    case KeyframesRuleList:
+        allowedRules = KeyframeRules;
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+
+    bool seenRule = false;
+    bool firstRuleValid = false;
+    while (!range.atEnd()) {
+        RefPtr<StyleRuleBase> rule;
+        switch (range.peek().type()) {
+        case WhitespaceToken:
+            range.consumeWhitespace();
+            continue;
+        case AtKeywordToken:
+            rule = consumeAtRule(range, allowedRules);
+            break;
+        case CDOToken:
+        case CDCToken:
+            if (ruleListType == TopLevelRuleList) {
+                range.consume();
+                continue;
+            }
+            FALLTHROUGH;
+        default:
+            rule = consumeQualifiedRule(range, allowedRules);
+            break;
+        }
+        if (!seenRule) {
+            seenRule = true;
+            firstRuleValid = rule;
+        }
+        if (rule) {
+            allowedRules = computeNewAllowedRules(allowedRules, rule.get());
+            callback(rule);
+        }
+    }
+
+    return firstRuleValid;
+}
+
+RefPtr<StyleRuleBase> CSSParserImpl::consumeAtRule(CSSParserTokenRange& range, AllowedRulesType allowedRules)
+{
+    ASSERT(range.peek().type() == AtKeywordToken);
+    const StringView name = range.consumeIncludingWhitespace().value();
+    const CSSParserToken* preludeStart = &range.peek();
+    while (!range.atEnd() && range.peek().type() != LeftBraceToken && range.peek().type() != SemicolonToken)
+        range.consumeComponentValue();
+
+    CSSParserTokenRange prelude = range.makeSubRange(preludeStart, &range.peek());
+    CSSAtRuleID id = cssAtRuleID(name);
+    
+    if (range.atEnd() || range.peek().type() == SemicolonToken) {
+        range.consume();
+        if (allowedRules == AllowCharsetRules && id == CSSAtRuleCharset)
+            return consumeCharsetRule(prelude);
+        if (allowedRules <= AllowImportRules && id == CSSAtRuleImport)
+            return consumeImportRule(prelude);
+        if (allowedRules <= AllowNamespaceRules && id == CSSAtRuleNamespace)
+            return consumeNamespaceRule(prelude);
+        // FIXME-NEWPARSER: Support "apply"
+        /*if (allowedRules == ApplyRules && id == CSSAtRuleApply) {
+            consumeApplyRule(prelude);
+            return nullptr; // consumeApplyRule just updates m_parsedProperties
+        }*/
+        return nullptr; // Parse error, unrecognised at-rule without block
+    }
+
+    CSSParserTokenRange block = range.consumeBlock();
+    if (allowedRules == KeyframeRules)
+        return nullptr; // Parse error, no at-rules supported inside @keyframes
+    if (allowedRules == NoRules || allowedRules == ApplyRules)
+        return nullptr; // Parse error, no at-rules with blocks supported inside declaration lists
+
+    ASSERT(allowedRules <= RegularRules);
+
+    switch (id) {
+    case CSSAtRuleMedia:
+        return consumeMediaRule(prelude, block);
+    case CSSAtRuleSupports:
+        return consumeSupportsRule(prelude, block);
+#if ENABLE(CSS_DEVICE_ADAPTATION)
+    case CSSAtRuleViewport:
+        return consumeViewportRule(prelude, block);
+#endif
+    case CSSAtRuleFontFace:
+        return consumeFontFaceRule(prelude, block);
+    case CSSAtRuleWebkitKeyframes:
+        return consumeKeyframesRule(true, prelude, block);
+    case CSSAtRuleKeyframes:
+        return consumeKeyframesRule(false, prelude, block);
+    case CSSAtRulePage:
+        return consumePageRule(prelude, block);
+    default:
+        return nullptr; // Parse error, unrecognised at-rule with block
+    }
+}
+
+RefPtr<StyleRuleBase> CSSParserImpl::consumeQualifiedRule(CSSParserTokenRange& range, AllowedRulesType allowedRules)
+{
+    const CSSParserToken* preludeStart = &range.peek();
+    while (!range.atEnd() && range.peek().type() != LeftBraceToken)
+        range.consumeComponentValue();
+
+    if (range.atEnd())
+        return nullptr; // Parse error, EOF instead of qualified rule block
+
+    CSSParserTokenRange prelude = range.makeSubRange(preludeStart, &range.peek());
+    CSSParserTokenRange block = range.consumeBlock();
+
+    if (allowedRules <= RegularRules)
+        return consumeStyleRule(prelude, block);
+    if (allowedRules == KeyframeRules)
+        return consumeKeyframeStyleRule(prelude, block);
+
+    ASSERT_NOT_REACHED();
+    return nullptr;
+}
+
+// This may still consume tokens if it fails
+static AtomicString consumeStringOrURI(CSSParserTokenRange& range)
+{
+    const CSSParserToken& token = range.peek();
+
+    if (token.type() == StringToken || token.type() == UrlToken)
+        return range.consumeIncludingWhitespace().value().toAtomicString();
+
+    if (token.type() != FunctionToken || !equalIgnoringASCIICase(token.value(), "url"))
+        return AtomicString();
+
+    CSSParserTokenRange contents = range.consumeBlock();
+    const CSSParserToken& uri = contents.consumeIncludingWhitespace();
+    if (uri.type() == BadStringToken || !contents.atEnd())
+        return AtomicString();
+    return uri.value().toAtomicString();
+}
+
+RefPtr<StyleRuleCharset> CSSParserImpl::consumeCharsetRule(CSSParserTokenRange prelude)
+{
+    const CSSParserToken& string = prelude.consumeIncludingWhitespace();
+    if (string.type() != StringToken || !prelude.atEnd())
+        return nullptr; // Parse error, expected a single string
+    return StyleRuleCharset::create();
+}
+
+RefPtr<StyleRuleImport> CSSParserImpl::consumeImportRule(CSSParserTokenRange prelude)
+{
+    AtomicString uri(consumeStringOrURI(prelude));
+    if (uri.isNull())
+        return nullptr; // Parse error, expected string or URI
+
+    if (m_observerWrapper) {
+        unsigned endOffset = m_observerWrapper->endOffset(prelude);
+        m_observerWrapper->observer().startRuleHeader(StyleRule::Import, m_observerWrapper->startOffset(prelude));
+        m_observerWrapper->observer().endRuleHeader(endOffset);
+        m_observerWrapper->observer().startRuleBody(endOffset);
+        m_observerWrapper->observer().endRuleBody(endOffset);
+    }
+
+    return StyleRuleImport::create(uri, MediaQueryParser::parseMediaQuerySet(prelude).releaseNonNull());
+}
+
+RefPtr<StyleRuleNamespace> CSSParserImpl::consumeNamespaceRule(CSSParserTokenRange prelude)
+{
+    AtomicString namespacePrefix;
+    if (prelude.peek().type() == IdentToken)
+        namespacePrefix = prelude.consumeIncludingWhitespace().value().toAtomicString();
+
+    AtomicString uri(consumeStringOrURI(prelude));
+    if (uri.isNull() || !prelude.atEnd())
+        return nullptr; // Parse error, expected string or URI
+
+    return StyleRuleNamespace::create(namespacePrefix, uri);
+}
+
+RefPtr<StyleRuleMedia> CSSParserImpl::consumeMediaRule(CSSParserTokenRange prelude, CSSParserTokenRange block)
+{
+    Vector<RefPtr<StyleRuleBase>> rules;
+
+    if (m_observerWrapper) {
+        m_observerWrapper->observer().startRuleHeader(StyleRule::Media, m_observerWrapper->startOffset(prelude));
+        m_observerWrapper->observer().endRuleHeader(m_observerWrapper->endOffset(prelude));
+        m_observerWrapper->observer().startRuleBody(m_observerWrapper->previousTokenStartOffset(block));
+    }
+
+    consumeRuleList(block, RegularRuleList, [&rules](RefPtr<StyleRuleBase> rule) {
+        rules.append(rule);
+    });
+
+    if (m_observerWrapper)
+        m_observerWrapper->observer().endRuleBody(m_observerWrapper->endOffset(block));
+
+    return StyleRuleMedia::create(MediaQueryParser::parseMediaQuerySet(prelude).releaseNonNull(), rules);
+}
+
+RefPtr<StyleRuleSupports> CSSParserImpl::consumeSupportsRule(CSSParserTokenRange prelude, CSSParserTokenRange block)
+{
+    CSSSupportsParser::SupportsResult supported = CSSSupportsParser::supportsCondition(prelude, *this);
+    if (supported == CSSSupportsParser::Invalid)
+        return nullptr; // Parse error, invalid @supports condition
+
+    if (m_observerWrapper) {
+        m_observerWrapper->observer().startRuleHeader(StyleRule::Supports, m_observerWrapper->startOffset(prelude));
+        m_observerWrapper->observer().endRuleHeader(m_observerWrapper->endOffset(prelude));
+        m_observerWrapper->observer().startRuleBody(m_observerWrapper->previousTokenStartOffset(block));
+    }
+
+    Vector<RefPtr<StyleRuleBase>> rules;
+    consumeRuleList(block, RegularRuleList, [&rules](RefPtr<StyleRuleBase> rule) {
+        rules.append(rule);
+    });
+
+    if (m_observerWrapper)
+        m_observerWrapper->observer().endRuleBody(m_observerWrapper->endOffset(block));
+
+    return StyleRuleSupports::create(prelude.serialize().stripWhiteSpace(), supported, rules);
+}
+
+#if ENABLE(CSS_DEVICE_ADAPTATION)
+RefPtr<StyleRuleViewport> CSSParserImpl::consumeViewportRule(CSSParserTokenRange prelude, CSSParserTokenRange block)
+{
+    if (!prelude.atEnd())
+        return nullptr; // Parser error; @viewport prelude should be empty
+
+    if (m_observerWrapper) {
+        unsigned endOffset = m_observerWrapper->endOffset(prelude);
+        m_observerWrapper->observer().startRuleHeader(StyleRule::Viewport, m_observerWrapper->startOffset(prelude));
+        m_observerWrapper->observer().endRuleHeader(endOffset);
+        m_observerWrapper->observer().startRuleBody(endOffset);
+        m_observerWrapper->observer().endRuleBody(endOffset);
+    }
+
+    consumeDeclarationList(block, StyleRule::Viewport);
+    return StyleRuleViewport::create(createStyleProperties(m_parsedProperties, CSSViewportRuleMode));
+}
+#endif
+
+RefPtr<StyleRuleFontFace> CSSParserImpl::consumeFontFaceRule(CSSParserTokenRange prelude, CSSParserTokenRange block)
+{
+    if (!prelude.atEnd())
+        return nullptr; // Parse error; @font-face prelude should be empty
+
+    if (m_observerWrapper) {
+        unsigned endOffset = m_observerWrapper->endOffset(prelude);
+        m_observerWrapper->observer().startRuleHeader(StyleRule::FontFace, m_observerWrapper->startOffset(prelude));
+        m_observerWrapper->observer().endRuleHeader(endOffset);
+        m_observerWrapper->observer().startRuleBody(endOffset);
+        m_observerWrapper->observer().endRuleBody(endOffset);
+    }
+
+    consumeDeclarationList(block, StyleRule::FontFace);
+    return StyleRuleFontFace::create(createStyleProperties(m_parsedProperties, m_context.mode));
+}
+
+RefPtr<StyleRuleKeyframes> CSSParserImpl::consumeKeyframesRule(bool webkitPrefixed, CSSParserTokenRange prelude, CSSParserTokenRange block)
+{
+    CSSParserTokenRange rangeCopy = prelude; // For inspector callbacks
+    const CSSParserToken& nameToken = prelude.consumeIncludingWhitespace();
+    if (!prelude.atEnd())
+        return nullptr; // Parse error; expected single non-whitespace token in @keyframes header
+
+    String name;
+    if (nameToken.type() == IdentToken) {
+        name = nameToken.value().toString();
+    } else if (nameToken.type() == StringToken && webkitPrefixed)
+        name = nameToken.value().toString();
+    else
+        return nullptr; // Parse error; expected ident token in @keyframes header
+
+    if (m_observerWrapper) {
+        m_observerWrapper->observer().startRuleHeader(StyleRule::Keyframes, m_observerWrapper->startOffset(rangeCopy));
+        m_observerWrapper->observer().endRuleHeader(m_observerWrapper->endOffset(prelude));
+        m_observerWrapper->observer().startRuleBody(m_observerWrapper->previousTokenStartOffset(block));
+        m_observerWrapper->observer().endRuleBody(m_observerWrapper->endOffset(block));
+    }
+
+    RefPtr<StyleRuleKeyframes> keyframeRule = StyleRuleKeyframes::create();
+    consumeRuleList(block, KeyframesRuleList, [keyframeRule](RefPtr<StyleRuleBase> keyframe) {
+        RefPtr<StyleKeyframe> key = static_cast<StyleKeyframe*>(keyframe.get());
+        keyframeRule->parserAppendKeyframe(key.releaseNonNull());
+    });
+    keyframeRule->setName(name);
+    // FIXME-NEWPARSER: Find out why this is done. Behavior difference when prefixed?
+    // keyframeRule->setVendorPrefixed(webkitPrefixed);
+    return keyframeRule;
+}
+
+RefPtr<StyleRulePage> CSSParserImpl::consumePageRule(CSSParserTokenRange prelude, CSSParserTokenRange block)
+{
+    CSSSelectorList selectorList = parsePageSelector(prelude, m_styleSheet.get());
+    if (!selectorList.isValid())
+        return nullptr; // Parse error, invalid @page selector
+
+    if (m_observerWrapper) {
+        unsigned endOffset = m_observerWrapper->endOffset(prelude);
+        m_observerWrapper->observer().startRuleHeader(StyleRule::Page, m_observerWrapper->startOffset(prelude));
+        m_observerWrapper->observer().endRuleHeader(endOffset);
+    }
+
+    consumeDeclarationList(block, StyleRule::Style);
+    
+    RefPtr<StyleRulePage> page = StyleRulePage::create(createStyleProperties(m_parsedProperties, m_context.mode));
+    page->wrapperAdoptSelectorList(selectorList);
+    return page;
+}
+
+// FIXME-NEWPARSER: Support "apply"
+/*void CSSParserImpl::consumeApplyRule(CSSParserTokenRange prelude)
+{
+    const CSSParserToken& ident = prelude.consumeIncludingWhitespace();
+    if (!prelude.atEnd() || !CSSVariableParser::isValidVariableName(ident))
+        return; // Parse error, expected a single custom property name
+    m_parsedProperties.append(CSSProperty(
+        CSSPropertyApplyAtRule,
+        *CSSCustomIdentValue::create(ident.value().toString())));
+}
+*/
+    
+RefPtr<StyleKeyframe> CSSParserImpl::consumeKeyframeStyleRule(CSSParserTokenRange prelude, CSSParserTokenRange block)
+{
+    std::unique_ptr<Vector<double>> keyList = consumeKeyframeKeyList(prelude);
+    if (!keyList)
+        return nullptr;
+
+    if (m_observerWrapper) {
+        m_observerWrapper->observer().startRuleHeader(StyleRule::Keyframe, m_observerWrapper->startOffset(prelude));
+        m_observerWrapper->observer().endRuleHeader(m_observerWrapper->endOffset(prelude));
+    }
+
+    consumeDeclarationList(block, StyleRule::Keyframe);
+    return StyleKeyframe::create(WTFMove(keyList), createStyleProperties(m_parsedProperties, m_context.mode));
+}
+
+static void observeSelectors(CSSParserObserverWrapper& wrapper, CSSParserTokenRange selectors)
+{
+    // This is easier than hooking into the CSSSelectorParser
+    selectors.consumeWhitespace();
+    CSSParserTokenRange originalRange = selectors;
+    wrapper.observer().startRuleHeader(StyleRule::Style, wrapper.startOffset(originalRange));
+
+    while (!selectors.atEnd()) {
+        const CSSParserToken* selectorStart = &selectors.peek();
+        while (!selectors.atEnd() && selectors.peek().type() != CommaToken)
+            selectors.consumeComponentValue();
+        CSSParserTokenRange selector = selectors.makeSubRange(selectorStart, &selectors.peek());
+        selectors.consumeIncludingWhitespace();
+
+        wrapper.observer().observeSelector(wrapper.startOffset(selector), wrapper.endOffset(selector));
+    }
+
+    wrapper.observer().endRuleHeader(wrapper.endOffset(originalRange));
+}
+
+RefPtr<StyleRule> CSSParserImpl::consumeStyleRule(CSSParserTokenRange prelude, CSSParserTokenRange block)
+{
+    CSSSelectorList selectorList = CSSSelectorParser::parseSelector(prelude, m_context, m_styleSheet.get());
+    if (!selectorList.isValid())
+        return nullptr; // Parse error, invalid selector list
+
+    if (m_observerWrapper)
+        observeSelectors(*m_observerWrapper, prelude);
+
+    consumeDeclarationList(block, StyleRule::Style);
+
+    // FIXME-NEWPARSER: Line number is in the StyleRule constructor (gross), need to figure this out.
+    RefPtr<StyleRule> rule = StyleRule::create(0, createStyleProperties(m_parsedProperties, m_context.mode));
+    rule->wrapperAdoptSelectorList(selectorList);
+    return rule;
+}
+
+void CSSParserImpl::consumeDeclarationList(CSSParserTokenRange range, StyleRule::Type ruleType)
+{
+    ASSERT(m_parsedProperties.isEmpty());
+
+    bool useObserver = m_observerWrapper && (ruleType == StyleRule::Style || ruleType == StyleRule::Keyframe);
+    if (useObserver) {
+        m_observerWrapper->observer().startRuleBody(m_observerWrapper->previousTokenStartOffset(range));
+        m_observerWrapper->skipCommentsBefore(range, true);
+    }
+
+    while (!range.atEnd()) {
+        switch (range.peek().type()) {
+        case WhitespaceToken:
+        case SemicolonToken:
+            range.consume();
+            break;
+        case IdentToken: {
+            const CSSParserToken* declarationStart = &range.peek();
+
+            if (useObserver)
+                m_observerWrapper->yieldCommentsBefore(range);
+
+            while (!range.atEnd() && range.peek().type() != SemicolonToken)
+                range.consumeComponentValue();
+
+            consumeDeclaration(range.makeSubRange(declarationStart, &range.peek()), ruleType);
+
+            if (useObserver)
+                m_observerWrapper->skipCommentsBefore(range, false);
+            break;
+        }
+        case AtKeywordToken: {
+            // FIXME-NEWPARSER: Support apply
+            AllowedRulesType allowedRules = /* ruleType == StyleRule::Style && RuntimeEnabledFeatures::cssApplyAtRulesEnabled() ? ApplyRules :*/ NoRules;
+            RefPtr<StyleRuleBase> rule = consumeAtRule(range, allowedRules);
+            ASSERT_UNUSED(rule, !rule);
+            break;
+        }
+        default: // Parse error, unexpected token in declaration list
+            while (!range.atEnd() && range.peek().type() != SemicolonToken)
+                range.consumeComponentValue();
+            break;
+        }
+    }
+
+    // Yield remaining comments
+    if (useObserver) {
+        m_observerWrapper->yieldCommentsBefore(range);
+        m_observerWrapper->observer().endRuleBody(m_observerWrapper->endOffset(range));
+    }
+}
+
+void CSSParserImpl::consumeDeclaration(CSSParserTokenRange range, StyleRule::Type ruleType)
+{
+    CSSParserTokenRange rangeCopy = range; // For inspector callbacks
+
+    ASSERT(range.peek().type() == IdentToken);
+    const CSSParserToken& token = range.consumeIncludingWhitespace();
+    CSSPropertyID unresolvedProperty = token.parseAsUnresolvedCSSPropertyID();
+    if (range.consume().type() != ColonToken)
+        return; // Parse error
+
+    bool important = false;
+    const CSSParserToken* declarationValueEnd = range.end();
+    const CSSParserToken* last = range.end() - 1;
+    while (last->type() == WhitespaceToken)
+        --last;
+    if (last->type() == IdentToken && equalIgnoringASCIICase(last->value(), "important")) {
+        --last;
+        while (last->type() == WhitespaceToken)
+            --last;
+        if (last->type() == DelimiterToken && last->delimiter() == '!') {
+            important = true;
+            declarationValueEnd = last;
+        }
+    }
+
+    size_t propertiesCount = m_parsedProperties.size();
+    // FIXME-NEWPARSER: Support variables
+    /*if (unresolvedProperty == CSSPropertyInvalid && CSSVariableParser::isValidVariableName(token)) {
+        AtomicString variableName = token.value().toAtomicString();
+        consumeVariableValue(range.makeSubRange(&range.peek(), declarationValueEnd), variableName, important);
+    }*/
+
+    if (important && (ruleType == StyleRule::FontFace || ruleType == StyleRule::Keyframe))
+        return;
+
+    if (unresolvedProperty != CSSPropertyInvalid)
+        consumeDeclarationValue(range.makeSubRange(&range.peek(), declarationValueEnd), unresolvedProperty, important, ruleType);
+
+    if (m_observerWrapper && (ruleType == StyleRule::Style || ruleType == StyleRule::Keyframe)) {
+        m_observerWrapper->observer().observeProperty(
+            m_observerWrapper->startOffset(rangeCopy), m_observerWrapper->endOffset(rangeCopy),
+            important, m_parsedProperties.size() != propertiesCount);
+    }
+}
+
+void CSSParserImpl::consumeVariableValue(CSSParserTokenRange /* range */, const AtomicString& /*variableName */, bool /* important */)
+{
+    // FIXME-NEWPARSER: Support variables
+    // if (CSSCustomPropertyDeclaration* value = CSSVariableParser::parseDeclarationValue(variableName, range))
+    //     m_parsedProperties.append(CSSProperty(CSSPropertyVariable, *value, important));
+}
+
+void CSSParserImpl::consumeDeclarationValue(CSSParserTokenRange range, CSSPropertyID unresolvedProperty, bool important, StyleRule::Type ruleType)
+{
+    CSSPropertyParser::parseValue(unresolvedProperty, important, range, m_context, m_parsedProperties, ruleType);
+}
+
+std::unique_ptr<Vector<double>> CSSParserImpl::consumeKeyframeKeyList(CSSParserTokenRange range)
+{
+    std::unique_ptr<Vector<double>> result = std::unique_ptr<Vector<double>>(new Vector<double>);
+    while (true) {
+        range.consumeWhitespace();
+        const CSSParserToken& token = range.consumeIncludingWhitespace();
+        if (token.type() == PercentageToken && token.numericValue() >= 0 && token.numericValue() <= 100)
+            result->append(token.numericValue() / 100);
+        else if (token.type() == IdentToken && equalIgnoringASCIICase(token.value(), "from"))
+            result->append(0);
+        else if (token.type() == IdentToken && equalIgnoringASCIICase(token.value(), "to"))
+            result->append(1);
+        else
+            return nullptr; // Parser error, invalid value in keyframe selector
+        if (range.atEnd())
+            return result;
+        if (range.consume().type() != CommaToken)
+            return nullptr; // Parser error
+    }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/parser/CSSParserImpl.h b/Source/WebCore/css/parser/CSSParserImpl.h
new file mode 100644 (file)
index 0000000..2b0869c
--- /dev/null
@@ -0,0 +1,152 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// 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:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * 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.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "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 THE COPYRIGHT
+// OWNER 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.
+
+#pragma once
+
+#include "CSSParserMode.h"
+#include "CSSParserTokenRange.h"
+#include "CSSProperty.h"
+#include "CSSPropertyNames.h"
+#include "CSSPropertySourceData.h"
+#include "StyleRule.h"
+
+#include <memory>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class CSSParserObserver;
+class CSSParserObserverWrapper;
+class CSSSelectorList;
+class StyleKeyframe;
+class StyleRule;
+class StyleRuleBase;
+class StyleRuleCharset;
+class StyleRuleFontFace;
+class StyleRuleImport;
+class StyleRuleKeyframes;
+class StyleRuleMedia;
+class StyleRuleNamespace;
+class StyleRulePage;
+class StyleRuleSupports;
+class StyleRuleViewport;
+class StyleSheetContents;
+class ImmutableStyleProperties;
+class Element;
+class MutableStyleProperties;
+
+class CSSParserImpl {
+    WTF_MAKE_NONCOPYABLE(CSSParserImpl);
+public:
+    CSSParserImpl(const CSSParserContext&, StyleSheetContents* = nullptr);
+
+    enum AllowedRulesType {
+        // As per css-syntax, css-cascade and css-namespaces, @charset rules
+        // must come first, followed by @import then @namespace.
+        // AllowImportRules actually means we allow @import and any rules thay
+        // may follow it, i.e. @namespace rules and regular rules.
+        // AllowCharsetRules and AllowNamespaceRules behave similarly.
+        AllowCharsetRules,
+        AllowImportRules,
+        AllowNamespaceRules,
+        RegularRules,
+        KeyframeRules,
+        ApplyRules, // For @apply inside style rules
+        NoRules, // For parsing at-rules inside declaration lists
+    };
+
+    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&);
+
+    static void parseDeclarationListForInspector(const String&, const CSSParserContext&, CSSParserObserver&);
+    static void parseStyleSheetForInspector(const String&, const CSSParserContext&, StyleSheetContents*, CSSParserObserver&);
+
+private:
+    enum RuleListType {
+        TopLevelRuleList,
+        RegularRuleList,
+        KeyframesRuleList
+    };
+
+    // Returns whether the first encountered rule was valid
+    template<typename T>
+    bool consumeRuleList(CSSParserTokenRange, RuleListType, T callback);
+
+    // These two functions update the range they're given
+    RefPtr<StyleRuleBase> consumeAtRule(CSSParserTokenRange&, AllowedRulesType);
+    RefPtr<StyleRuleBase> consumeQualifiedRule(CSSParserTokenRange&, AllowedRulesType);
+
+    static RefPtr<StyleRuleCharset> consumeCharsetRule(CSSParserTokenRange prelude);
+    RefPtr<StyleRuleImport> consumeImportRule(CSSParserTokenRange prelude);
+    RefPtr<StyleRuleNamespace> consumeNamespaceRule(CSSParserTokenRange prelude);
+    RefPtr<StyleRuleMedia> consumeMediaRule(CSSParserTokenRange prelude, CSSParserTokenRange block);
+    RefPtr<StyleRuleSupports> consumeSupportsRule(CSSParserTokenRange prelude, CSSParserTokenRange block);
+    RefPtr<StyleRuleViewport> consumeViewportRule(CSSParserTokenRange prelude, CSSParserTokenRange block);
+    RefPtr<StyleRuleFontFace> consumeFontFaceRule(CSSParserTokenRange prelude, CSSParserTokenRange block);
+    RefPtr<StyleRuleKeyframes> consumeKeyframesRule(bool webkitPrefixed, CSSParserTokenRange prelude, CSSParserTokenRange block);
+    RefPtr<StyleRulePage> consumePageRule(CSSParserTokenRange prelude, CSSParserTokenRange block);
+    // Updates m_parsedProperties
+    
+    // FIXME-NEWPARSER: Support "apply"
+    // void consumeApplyRule(CSSParserTokenRange prelude);
+
+    RefPtr<StyleKeyframe> consumeKeyframeStyleRule(CSSParserTokenRange prelude, CSSParserTokenRange block);
+    RefPtr<StyleRule> consumeStyleRule(CSSParserTokenRange prelude, CSSParserTokenRange block);
+
+    void consumeDeclarationList(CSSParserTokenRange, StyleRule::Type);
+    void consumeDeclaration(CSSParserTokenRange, StyleRule::Type);
+    void consumeDeclarationValue(CSSParserTokenRange, CSSPropertyID, bool important, StyleRule::Type);
+    void consumeVariableValue(CSSParserTokenRange, const AtomicString& propertyName, bool important);
+
+    static std::unique_ptr<Vector<double>> consumeKeyframeKeyList(CSSParserTokenRange);
+
+    // FIXME: Can we build StylePropertySets directly?
+    // FIXME: Investigate using a smaller inline buffer
+    ParsedPropertyVector m_parsedProperties;
+    const CSSParserContext& m_context;
+
+    RefPtr<StyleSheetContents> m_styleSheet;
+
+    // For the inspector
+    CSSParserObserverWrapper* m_observerWrapper;
+};
+
+} // namespace WebCore
index c136bb1..b98957e 100644 (file)
@@ -199,6 +199,24 @@ CSSParserSelector* CSSParserSelector::parsePagePseudoSelector(const CSSParserStr
     return selector.release();
 }
 
+CSSParserSelector* CSSParserSelector::parsePagePseudoSelector(const AtomicString& pseudoTypeString)
+{
+    CSSSelector::PagePseudoClassType pseudoType;
+    if (equalLettersIgnoringASCIICase(pseudoTypeString, "first"))
+        pseudoType = CSSSelector::PagePseudoClassFirst;
+    else if (equalLettersIgnoringASCIICase(pseudoTypeString, "left"))
+        pseudoType = CSSSelector::PagePseudoClassLeft;
+    else if (equalLettersIgnoringASCIICase(pseudoTypeString, "right"))
+        pseudoType = CSSSelector::PagePseudoClassRight;
+    else
+        return nullptr;
+    
+    auto selector = std::make_unique<CSSParserSelector>();
+    selector->m_selector->setMatch(CSSSelector::PagePseudoClass);
+    selector->m_selector->setPagePseudoType(pseudoType);
+    return selector.release();
+}
+
 CSSParserSelector* CSSParserSelector::parsePseudoElementSelector(CSSParserString& pseudoTypeString)
 {
     pseudoTypeString.convertToASCIILowercaseInPlace();
index a919415..6cb368c 100644 (file)
@@ -203,6 +203,7 @@ enum class CSSParserSelectorCombinator {
 class CSSParserSelector {
     WTF_MAKE_FAST_ALLOCATED;
 public:
+    // FIXME-NEWPARSER: Remove the CSSParserString-based parsing functions once the old parser is gone.
     static CSSParserSelector* parsePagePseudoSelector(const CSSParserString& pseudoTypeString);
     static CSSParserSelector* parsePseudoElementSelector(CSSParserString& pseudoTypeString);
     static CSSParserSelector* parsePseudoElementCueFunctionSelector(const CSSParserString& functionIdentifier, Vector<std::unique_ptr<CSSParserSelector>>*);
@@ -212,6 +213,7 @@ public:
 
     static CSSParserSelector* parsePseudoClassSelectorFromStringView(StringView&);
     static CSSParserSelector* parsePseudoElementSelectorFromStringView(StringView&);
+    static CSSParserSelector* parsePagePseudoSelector(const AtomicString&);
     
     CSSParserSelector();
     explicit CSSParserSelector(const QualifiedName&);
index 0b7bf70..e60f964 100644 (file)
@@ -235,11 +235,15 @@ void CSSPropertyParser::addExpandedPropertyForValue(CSSPropertyID property, cons
     for (unsigned i = 0; i < shorthandLength; ++i)
         addProperty(longhands[i], property, value, important);
 }
-
-bool CSSPropertyParser::parseValue(CSSPropertyID unresolvedProperty, bool important,
-    const CSSParserTokenRange& range, const CSSParserContext& context,
-    Vector<CSSProperty, 256>& parsedProperties, StyleRule::Type ruleType)
+*/
+    
+bool CSSPropertyParser::parseValue(CSSPropertyID /*unresolvedProperty*/, bool /*important*/,
+    const CSSParserTokenRange& /*range*/, const CSSParserContext& /*context*/,
+    ParsedPropertyVector& /*parsedProperties*/, StyleRule::Type /*ruleType*/)
 {
+    return false;
+    
+    /*
     int parsedPropertiesSize = parsedProperties.size();
 
     CSSPropertyParser parser(range, context, &parsedProperties);
@@ -263,8 +267,9 @@ bool CSSPropertyParser::parseValue(CSSPropertyID unresolvedProperty, bool import
         parsedProperties.shrink(parsedPropertiesSize);
 
     return parseSuccess;
+     */
 }
-
+/*
 const CSSValue* CSSPropertyParser::parseSingleValue(
     CSSPropertyID property, const CSSParserTokenRange& range, const CSSParserContext& context)
 {
diff --git a/Source/WebCore/css/parser/CSSSupportsParser.cpp b/Source/WebCore/css/parser/CSSSupportsParser.cpp
new file mode 100644 (file)
index 0000000..8ed8d18
--- /dev/null
@@ -0,0 +1,119 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// 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:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * 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.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "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 THE COPYRIGHT
+// OWNER 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 "CSSSupportsParser.h"
+
+#include "CSSParserImpl.h"
+
+namespace WebCore {
+
+CSSSupportsParser::SupportsResult CSSSupportsParser::supportsCondition(CSSParserTokenRange range, CSSParserImpl& parser)
+{
+    // FIXME: The spec allows leading whitespace in @supports but not CSS.supports,
+    // but major browser vendors allow it in CSS.supports also.
+    range.consumeWhitespace();
+    return CSSSupportsParser(parser).consumeCondition(range);
+}
+
+enum ClauseType { Unresolved, Conjunction, Disjunction };
+
+CSSSupportsParser::SupportsResult CSSSupportsParser::consumeCondition(CSSParserTokenRange range)
+{
+    if (range.peek().type() == IdentToken)
+        return consumeNegation(range);
+
+    bool result;
+    ClauseType clauseType = Unresolved;
+
+    while (true) {
+        SupportsResult nextResult = consumeConditionInParenthesis(range);
+        if (nextResult == Invalid)
+            return Invalid;
+        bool nextSupported = nextResult;
+        if (clauseType == Unresolved)
+            result = nextSupported;
+        else if (clauseType == Conjunction)
+            result &= nextSupported;
+        else
+            result |= nextSupported;
+
+        if (range.atEnd())
+            break;
+        if (range.consumeIncludingWhitespace().type() != WhitespaceToken)
+            return Invalid;
+        if (range.atEnd())
+            break;
+
+        const CSSParserToken& token = range.consume();
+        if (token.type() != IdentToken)
+            return Invalid;
+        if (clauseType == Unresolved)
+            clauseType = token.value().length() == 3 ? Conjunction : Disjunction;
+        if ((clauseType == Conjunction && !equalIgnoringASCIICase(token.value(), "and"))
+            || (clauseType == Disjunction && !equalIgnoringASCIICase(token.value(), "or")))
+            return Invalid;
+
+        if (range.consumeIncludingWhitespace().type() != WhitespaceToken)
+            return Invalid;
+    }
+    return result ? Supported : Unsupported;
+}
+
+CSSSupportsParser::SupportsResult CSSSupportsParser::consumeNegation(CSSParserTokenRange range)
+{
+    ASSERT(range.peek().type() == IdentToken);
+    if (!equalIgnoringASCIICase(range.consume().value(), "not"))
+        return Invalid;
+    if (range.consumeIncludingWhitespace().type() != WhitespaceToken)
+        return Invalid;
+    SupportsResult result = consumeConditionInParenthesis(range);
+    range.consumeWhitespace();
+    if (!range.atEnd() || result == Invalid)
+        return Invalid;
+    return result ? Unsupported : Supported;
+}
+
+CSSSupportsParser::SupportsResult CSSSupportsParser::consumeConditionInParenthesis(CSSParserTokenRange& range)
+{
+    if (range.peek().type() == FunctionToken) {
+        range.consumeComponentValue();
+        return Unsupported;
+    }
+    if (range.peek().type() != LeftParenthesisToken)
+        return Invalid;
+    CSSParserTokenRange innerRange = range.consumeBlock();
+    innerRange.consumeWhitespace();
+    SupportsResult result = consumeCondition(innerRange);
+    if (result != Invalid)
+        return result;
+    return innerRange.peek().type() == IdentToken && m_parser.supportsDeclaration(innerRange) ? Supported : Unsupported;
+}
+
+} // namespace blink
diff --git a/Source/WebCore/css/parser/CSSSupportsParser.h b/Source/WebCore/css/parser/CSSSupportsParser.h
new file mode 100644 (file)
index 0000000..f484424
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// 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:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * 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.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "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 THE COPYRIGHT
+// OWNER 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.
+
+#pragma once
+
+namespace WebCore {
+
+class CSSParserImpl;
+class CSSParserTokenRange;
+
+class CSSSupportsParser {
+public:
+    enum SupportsResult {
+        Unsupported = false,
+        Supported = true,
+        Invalid
+    };
+
+    static SupportsResult supportsCondition(CSSParserTokenRange, CSSParserImpl&);
+
+private:
+    CSSSupportsParser(CSSParserImpl& parser)
+        : m_parser(parser) { }
+
+    SupportsResult consumeCondition(CSSParserTokenRange);
+    SupportsResult consumeNegation(CSSParserTokenRange);
+
+    SupportsResult consumeConditionInParenthesis(CSSParserTokenRange&);
+
+    CSSParserImpl& m_parser;
+};
+
+} // namespace WebCore