Implement the CSS4 'revert' keyword.
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 17 Oct 2015 23:13:43 +0000 (23:13 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 17 Oct 2015 23:13:43 +0000 (23:13 +0000)
https://bugs.webkit.org/show_bug.cgi?id=149702

Reviewed by Simon Fraser.

Source/WebCore:

Added new tests in fast/css and fast/css/variables.

* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:
Add CSSRevertValue to the project and makefiles.

* css/CSSParser.cpp:
(WebCore::parseKeywordValue):
Make sure to handle "revert" in the keyword parsing path (along with inherit/initial/unset).

(WebCore::CSSParser::parseValue):
(WebCore::CSSParser::parseCustomPropertyDeclaration):
At the parser level, "revert" is just like inherit/initial/unset and gets its own special
singleton value, CSSRevertValue.

* css/CSSRevertValue.cpp: Added.
(WebCore::CSSRevertValue::customCSSText):
* css/CSSRevertValue.h: Added.
(WebCore::CSSRevertValue::create):
(WebCore::CSSRevertValue::equals):
(WebCore::CSSRevertValue::CSSRevertValue):
This value is identical to the inherit/initial/unset values, i.e., its own special value
that can be used to indicate a revert when doing style resolution.

* css/CSSValue.cpp:
(WebCore::CSSValue::cssValueType):
(WebCore::CSSValue::equals):
(WebCore::CSSValue::cssText):
(WebCore::CSSValue::destroy):
* css/CSSValue.h:
(WebCore::CSSValue::isInheritedValue):
(WebCore::CSSValue::isInitialValue):
(WebCore::CSSValue::isUnsetValue):
(WebCore::CSSValue::isRevertValue):
Add the RevertClass to CSSValue and make sure it is handled in all the appropriate methods.

* css/CSSValueKeywords.in:
Add the "revert" keyword to the list of allowed CSS keywords.

* css/CSSValuePool.cpp:
(WebCore::CSSValuePool::CSSValuePool):
* css/CSSValuePool.h:
(WebCore::CSSValuePool::createRevertValue):
Add support for a CSSRevertValue singleton, just like inherit/unset/initial.

* css/FontLoader.cpp:
(WebCore::FontLoader::resolveFontStyle):
Add "unset" and "revert" as special keywords to be ignored. This code seems to be turned off,
but patching it anyway.

* css/SelectorChecker.h:
Add a MatchDefault value of 0 to the LinkMatchMask. This enables it to be used as an index
to the correct value in Property (in the style resolution code).

* css/StyleResolver.cpp:
(WebCore::StyleResolver::State::initForStyleResolve):
Delete any lingering old CascadedProperty rollbacks for UA/user rules.

(WebCore::StyleResolver::styleForKeyframe):
(WebCore::StyleResolver::styleForPage):
(WebCore::StyleResolver::applyMatchedProperties):
Pass along the MatchResult as an additional parameter, since we need it to lazily compute
the cascade rollbacks if the "revert" keyword is encountered.

(WebCore::StyleResolver::cascadedPropertiesForRollback):
This method will lazily create and return a new CascadedProperties pointer that is cached
in the StyleResolver's state. This will contain only UA rules (for user reverts) and UA/user
rules (for author reverts). These will only be computed at most once for a given element
when doing a reversion, and they will be computed lazily, i.e., only if a revert is
requested.

(WebCore::StyleResolver::applyProperty):
Pass along the LinkMatchMask and the MatchResult to applyProperty. This way we know specifically
which link type we were computing if we have to revert (so that we roll back and look at the
same index in the reverted version). The MatchResult is passed along because it is needed
to build the CascadedProperties rollbacks.

The basic idea is that if a revert is encountered, the level that the rule came from is
checked. If it is UA level, just treat as "unset." If it is author or user level, get
the correct CascadedProperties rollback and repeat the applyProperty using the property
found in the rollback. If the property is not present in the cascade rollback, then the
revert becomes an unset.

(WebCore::StyleResolver::CascadedProperties::hasCustomProperty):
(WebCore::StyleResolver::CascadedProperties::customProperty):
Helpers used by applyProperty to check on custom properties, since they can revert too
just like a regular property can.

(WebCore::StyleResolver::CascadedProperties::setPropertyInternal):
(WebCore::StyleResolver::CascadedProperties::set):
(WebCore::StyleResolver::CascadedProperties::setDeferred):
Passing along the CascadeLevel (UA, User, Author) so that it can be stored in the Property.
This way when we do property application, we always know where the rule came from so
that the reversion can be handled properly.

(WebCore::StyleResolver::CascadedProperties::addStyleProperties):
(WebCore::cascadeLevelForIndex):
(WebCore::StyleResolver::CascadedProperties::addMatches):
When style properties are added, also figure out the CascadeLevel and pass it along to be
stored in the Property. We use the MatchResult's ranges to know where a property comes from.

(WebCore::StyleResolver::CascadedProperties::applyDeferredProperties):
(WebCore::StyleResolver::CascadedProperties::Property::apply):
(WebCore::StyleResolver::applyCascadedProperties):
Pass along the MatchResult so we know how to build the rollback.

* css/StyleResolver.h:
(WebCore::StyleResolver::State::cascadeLevel):
(WebCore::StyleResolver::State::setCascadeLevel):
(WebCore::StyleResolver::State::authorRollback):
(WebCore::StyleResolver::State::userRollback):
(WebCore::StyleResolver::State::setAuthorRollback):
(WebCore::StyleResolver::State::setUserRollback):
(WebCore::StyleResolver::state):
(WebCore::StyleResolver::cascadeLevel):
(WebCore::StyleResolver::setCascadeLevel):
Move CascadedProperties into the header. Add CascadeLevel to Property. Add the level and
rollbacks to the resolver's state.

LayoutTests:

* fast/css/all-keyword-revert-expected.html: Added.
* fast/css/all-keyword-revert.html: Added.
* fast/css/revert-color-expected.html: Added.
* fast/css/revert-color.html: Added.
* fast/css/revert-margins-expected.html: Added.
* fast/css/revert-margins.html: Added.
* fast/css/variables/all-keyword-revert-expected.html: Added.
* fast/css/variables/all-keyword-revert.html: Added.
* fast/css/variables/revert-inheritance-expected.html: Added.
* fast/css/variables/revert-inheritance.html: Added.
* fast/css/variables/revert-no-inheritance-expected.html: Added.
* fast/css/variables/revert-no-inheritance.html: Added.
* fast/css/variables/revert-variable-reference-expected.html: Added.
* fast/css/variables/revert-variable-reference.html: Added.

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

31 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css/all-keyword-revert-expected.html [new file with mode: 0644]
LayoutTests/fast/css/all-keyword-revert.html [new file with mode: 0644]
LayoutTests/fast/css/revert-color-expected.html [new file with mode: 0644]
LayoutTests/fast/css/revert-color.html [new file with mode: 0644]
LayoutTests/fast/css/revert-margins-expected.html [new file with mode: 0644]
LayoutTests/fast/css/revert-margins.html [new file with mode: 0644]
LayoutTests/fast/css/variables/all-keyword-revert-expected.html [new file with mode: 0644]
LayoutTests/fast/css/variables/all-keyword-revert.html [new file with mode: 0644]
LayoutTests/fast/css/variables/revert-inheritance-expected.html [new file with mode: 0644]
LayoutTests/fast/css/variables/revert-inheritance.html [new file with mode: 0644]
LayoutTests/fast/css/variables/revert-no-inheritance-expected.html [new file with mode: 0644]
LayoutTests/fast/css/variables/revert-no-inheritance.html [new file with mode: 0644]
LayoutTests/fast/css/variables/revert-variable-reference-expected.html [new file with mode: 0644]
LayoutTests/fast/css/variables/revert-variable-reference.html [new file with mode: 0644]
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/objc/DOMCSS.mm
Source/WebCore/css/CSSParser.cpp
Source/WebCore/css/CSSRevertValue.cpp [new file with mode: 0644]
Source/WebCore/css/CSSRevertValue.h [new file with mode: 0644]
Source/WebCore/css/CSSValue.cpp
Source/WebCore/css/CSSValue.h
Source/WebCore/css/CSSValueKeywords.in
Source/WebCore/css/CSSValuePool.cpp
Source/WebCore/css/CSSValuePool.h
Source/WebCore/css/FontLoader.cpp
Source/WebCore/css/SelectorChecker.h
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/css/StyleResolver.h

index 736450a..0a87f61 100644 (file)
@@ -1,3 +1,25 @@
+2015-10-17  David Hyatt  <hyatt@apple.com>
+
+        Implement the CSS4 'revert' keyword.
+        https://bugs.webkit.org/show_bug.cgi?id=149702
+
+        Reviewed by Simon Fraser.
+
+        * fast/css/all-keyword-revert-expected.html: Added.
+        * fast/css/all-keyword-revert.html: Added.
+        * fast/css/revert-color-expected.html: Added.
+        * fast/css/revert-color.html: Added.
+        * fast/css/revert-margins-expected.html: Added.
+        * fast/css/revert-margins.html: Added.
+        * fast/css/variables/all-keyword-revert-expected.html: Added.
+        * fast/css/variables/all-keyword-revert.html: Added.
+        * fast/css/variables/revert-inheritance-expected.html: Added.
+        * fast/css/variables/revert-inheritance.html: Added.
+        * fast/css/variables/revert-no-inheritance-expected.html: Added.
+        * fast/css/variables/revert-no-inheritance.html: Added.
+        * fast/css/variables/revert-variable-reference-expected.html: Added.
+        * fast/css/variables/revert-variable-reference.html: Added.
+
 2015-10-17  Myles C. Maxfield  <mmaxfield@apple.com>
 
         Delete FontPlatformData::allowsLigatures()
diff --git a/LayoutTests/fast/css/all-keyword-revert-expected.html b/LayoutTests/fast/css/all-keyword-revert-expected.html
new file mode 100644 (file)
index 0000000..b0766c0
--- /dev/null
@@ -0,0 +1,11 @@
+<head>
+<style>
+html {
+  font-size: small;
+  background-color: #F0F0F0;
+  color: blue;
+}
+</style>
+</head>
+<body>
+<blockquote id="quote">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</blockquote> Phasellus eget velit sagittis.
\ No newline at end of file
diff --git a/LayoutTests/fast/css/all-keyword-revert.html b/LayoutTests/fast/css/all-keyword-revert.html
new file mode 100644 (file)
index 0000000..4781b4f
--- /dev/null
@@ -0,0 +1,18 @@
+<head>
+<style>
+html {
+  font-size: small;
+  background-color: #F0F0F0;
+  color: blue;
+}
+
+blockquote {
+  display:inline;
+  background-color: skyblue;
+  color: red;
+  all: revert;
+}
+</style>
+</head>
+<body>
+<blockquote id="quote">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</blockquote> Phasellus eget velit sagittis.
\ No newline at end of file
diff --git a/LayoutTests/fast/css/revert-color-expected.html b/LayoutTests/fast/css/revert-color-expected.html
new file mode 100644 (file)
index 0000000..9b51d14
--- /dev/null
@@ -0,0 +1,16 @@
+<head>
+<style>
+html {
+  font-size: small;
+  background-color: #F0F0F0;
+  color: blue;
+}
+
+blockquote { background-color: skyblue; }
+
+</style>
+</head>
+<body>
+<blockquote>This text should be blue.</blockquote>
+</body>
+</html>
diff --git a/LayoutTests/fast/css/revert-color.html b/LayoutTests/fast/css/revert-color.html
new file mode 100644 (file)
index 0000000..927b3b4
--- /dev/null
@@ -0,0 +1,19 @@
+<head>
+<style>
+html {
+  font-size: small;
+  background-color: #F0F0F0;
+  color: blue;
+}
+
+blockquote {
+  background-color: skyblue;
+  color: red;
+  color: revert;
+}
+</style>
+</head>
+<body>
+<blockquote id="quote">This text should be blue.</blockquote>
+</body>
+</html>
diff --git a/LayoutTests/fast/css/revert-margins-expected.html b/LayoutTests/fast/css/revert-margins-expected.html
new file mode 100644 (file)
index 0000000..d1f1d27
--- /dev/null
@@ -0,0 +1,14 @@
+<head>
+<style>
+blockquote {
+  margin-top:0;
+  margin-bottom:0;
+  border:1px solid black;
+}
+</style>
+</head>
+<body>
+<blockquote id="quote">This blockquote should have user agent margins for the left and right but the top and bottom margins should be 0.</blockquote>
+<blockquote id="quote">This blockquote should have user agent margins for the left and right but the top and bottom margins should be 0.</blockquote>
+</body>
+</html>
diff --git a/LayoutTests/fast/css/revert-margins.html b/LayoutTests/fast/css/revert-margins.html
new file mode 100644 (file)
index 0000000..84474b2
--- /dev/null
@@ -0,0 +1,15 @@
+<head>
+<style>
+blockquote {
+  margin:0;
+  margin-right:revert;
+  margin-left:revert;
+  border:1px solid black;
+}
+</style>
+</head>
+<body>
+<blockquote id="quote">This blockquote should have user agent margins for the left and right but the top and bottom margins should be 0.</blockquote>
+<blockquote id="quote">This blockquote should have user agent margins for the left and right but the top and bottom margins should be 0.</blockquote>
+</body>
+</html>
diff --git a/LayoutTests/fast/css/variables/all-keyword-revert-expected.html b/LayoutTests/fast/css/variables/all-keyword-revert-expected.html
new file mode 100644 (file)
index 0000000..941062d
--- /dev/null
@@ -0,0 +1,11 @@
+<head>
+<style>
+html {
+  font-size: small;
+  background-color: #F0F0F0;
+  color: blue;
+}
+</style>
+</head>
+<body>
+<span id="quote">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</span> Phasellus eget velit sagittis.
\ No newline at end of file
diff --git a/LayoutTests/fast/css/variables/all-keyword-revert.html b/LayoutTests/fast/css/variables/all-keyword-revert.html
new file mode 100644 (file)
index 0000000..5ab689e
--- /dev/null
@@ -0,0 +1,19 @@
+<head>
+<title>Test of failed variable lookup because of "revert" on a custom property causing all to reset everything.</title>
+<style>
+html {
+  font-size: small;
+  background-color: #F0F0F0;
+  color: blue;
+  --a: revert;
+}
+
+blockquote {
+  background-color: skyblue;
+  color: red;
+  all: var(--a);
+}
+</style>
+</head>
+<body>
+<blockquote id="quote">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</blockquote> Phasellus eget velit sagittis.
\ No newline at end of file
diff --git a/LayoutTests/fast/css/variables/revert-inheritance-expected.html b/LayoutTests/fast/css/variables/revert-inheritance-expected.html
new file mode 100644 (file)
index 0000000..628466d
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+--><html><head><title>CSS Reftest Reference</title>
+<link href="mailto:cam@mcc.id.au" rel="author" title="Cameron McCormack">
+<style>
+p {
+  color: green;
+}
+</style>
+</head><body><p>This text must be green.</p>
+</body></html>
\ No newline at end of file
diff --git a/LayoutTests/fast/css/variables/revert-inheritance.html b/LayoutTests/fast/css/variables/revert-inheritance.html
new file mode 100644 (file)
index 0000000..bc8eeda
--- /dev/null
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+--><html><head><title>CSS Test: Test declaring a variable whose value is "revert" where there is a variable to inherit from.</title>
+<style>
+body {
+  --a: green;
+  color: crimson;
+}
+p {
+  color: red;
+}
+p {
+  color: orange;
+  --a: revert;
+  color: var(--a);
+}
+</style>
+</head><body><p>This text must be green.</p>
+</body></html>
\ No newline at end of file
diff --git a/LayoutTests/fast/css/variables/revert-no-inheritance-expected.html b/LayoutTests/fast/css/variables/revert-no-inheritance-expected.html
new file mode 100644 (file)
index 0000000..628466d
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+--><html><head><title>CSS Reftest Reference</title>
+<link href="mailto:cam@mcc.id.au" rel="author" title="Cameron McCormack">
+<style>
+p {
+  color: green;
+}
+</style>
+</head><body><p>This text must be green.</p>
+</body></html>
\ No newline at end of file
diff --git a/LayoutTests/fast/css/variables/revert-no-inheritance.html b/LayoutTests/fast/css/variables/revert-no-inheritance.html
new file mode 100644 (file)
index 0000000..5c070c0
--- /dev/null
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+--><html><head><title>CSS Test: Test declaring a variable whose value is "revert" where there is no variable to inherit from.</title>
+<style>
+p {
+  color: red;
+}
+p {
+  color: orange;
+  --a: revert;
+  color: var(--a,green);
+}
+</style>
+</head><body><p>This text must be green.</p>
+</body></html>
\ No newline at end of file
diff --git a/LayoutTests/fast/css/variables/revert-variable-reference-expected.html b/LayoutTests/fast/css/variables/revert-variable-reference-expected.html
new file mode 100644 (file)
index 0000000..628466d
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+--><html><head><title>CSS Reftest Reference</title>
+<link href="mailto:cam@mcc.id.au" rel="author" title="Cameron McCormack">
+<style>
+p {
+  color: green;
+}
+</style>
+</head><body><p>This text must be green.</p>
+</body></html>
\ No newline at end of file
diff --git a/LayoutTests/fast/css/variables/revert-variable-reference.html b/LayoutTests/fast/css/variables/revert-variable-reference.html
new file mode 100644 (file)
index 0000000..6665e38
--- /dev/null
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+--><html><head><title>CSS Test: Test declaring a variable whose value consists of a reference to a variable whose value is "revert".</title>
+<style>
+body {
+  --b: green;
+  color: red;
+}
+p {
+  color: orange;
+  --a: var(--b);
+  --b: revert;
+  color: var(--a);
+}
+</style>
+</head><body><p>This text must be green.</p>
+</body></html>
\ No newline at end of file
index d564bc4..1603752 100644 (file)
@@ -1338,6 +1338,7 @@ set(WebCore_SOURCES
     css/CSSProperty.cpp
     css/CSSPropertySourceData.cpp
     css/CSSReflectValue.cpp
+    css/CSSRevertValue.cpp
     css/CSSRule.cpp
     css/CSSRuleList.cpp
     css/CSSSegmentedFontFace.cpp
index 6d04c46..2adddd3 100644 (file)
@@ -1,3 +1,129 @@
+2015-10-17  David Hyatt  <hyatt@apple.com>
+
+        Implement the CSS4 'revert' keyword.
+        https://bugs.webkit.org/show_bug.cgi?id=149702
+
+        Reviewed by Simon Fraser.
+
+        Added new tests in fast/css and fast/css/variables.
+
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        Add CSSRevertValue to the project and makefiles.
+
+        * css/CSSParser.cpp:
+        (WebCore::parseKeywordValue):
+        Make sure to handle "revert" in the keyword parsing path (along with inherit/initial/unset).
+
+        (WebCore::CSSParser::parseValue):
+        (WebCore::CSSParser::parseCustomPropertyDeclaration):
+        At the parser level, "revert" is just like inherit/initial/unset and gets its own special
+        singleton value, CSSRevertValue.
+
+        * css/CSSRevertValue.cpp: Added.
+        (WebCore::CSSRevertValue::customCSSText):
+        * css/CSSRevertValue.h: Added.
+        (WebCore::CSSRevertValue::create):
+        (WebCore::CSSRevertValue::equals):
+        (WebCore::CSSRevertValue::CSSRevertValue):
+        This value is identical to the inherit/initial/unset values, i.e., its own special value
+        that can be used to indicate a revert when doing style resolution.
+
+        * css/CSSValue.cpp:
+        (WebCore::CSSValue::cssValueType):
+        (WebCore::CSSValue::equals):
+        (WebCore::CSSValue::cssText):
+        (WebCore::CSSValue::destroy):
+        * css/CSSValue.h:
+        (WebCore::CSSValue::isInheritedValue):
+        (WebCore::CSSValue::isInitialValue):
+        (WebCore::CSSValue::isUnsetValue):
+        (WebCore::CSSValue::isRevertValue):
+        Add the RevertClass to CSSValue and make sure it is handled in all the appropriate methods.
+
+        * css/CSSValueKeywords.in:
+        Add the "revert" keyword to the list of allowed CSS keywords.
+
+        * css/CSSValuePool.cpp:
+        (WebCore::CSSValuePool::CSSValuePool):
+        * css/CSSValuePool.h:
+        (WebCore::CSSValuePool::createRevertValue):
+        Add support for a CSSRevertValue singleton, just like inherit/unset/initial.
+
+        * css/FontLoader.cpp:
+        (WebCore::FontLoader::resolveFontStyle):
+        Add "unset" and "revert" as special keywords to be ignored. This code seems to be turned off,
+        but patching it anyway.
+
+        * css/SelectorChecker.h:
+        Add a MatchDefault value of 0 to the LinkMatchMask. This enables it to be used as an index
+        to the correct value in Property (in the style resolution code).
+
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::State::initForStyleResolve):
+        Delete any lingering old CascadedProperty rollbacks for UA/user rules.
+
+        (WebCore::StyleResolver::styleForKeyframe):
+        (WebCore::StyleResolver::styleForPage):
+        (WebCore::StyleResolver::applyMatchedProperties):
+        Pass along the MatchResult as an additional parameter, since we need it to lazily compute
+        the cascade rollbacks if the "revert" keyword is encountered.
+
+        (WebCore::StyleResolver::cascadedPropertiesForRollback):
+        This method will lazily create and return a new CascadedProperties pointer that is cached
+        in the StyleResolver's state. This will contain only UA rules (for user reverts) and UA/user
+        rules (for author reverts). These will only be computed at most once for a given element
+        when doing a reversion, and they will be computed lazily, i.e., only if a revert is
+        requested.
+
+        (WebCore::StyleResolver::applyProperty):
+        Pass along the LinkMatchMask and the MatchResult to applyProperty. This way we know specifically
+        which link type we were computing if we have to revert (so that we roll back and look at the
+        same index in the reverted version). The MatchResult is passed along because it is needed
+        to build the CascadedProperties rollbacks.
+
+        The basic idea is that if a revert is encountered, the level that the rule came from is
+        checked. If it is UA level, just treat as "unset." If it is author or user level, get
+        the correct CascadedProperties rollback and repeat the applyProperty using the property
+        found in the rollback. If the property is not present in the cascade rollback, then the
+        revert becomes an unset.
+
+        (WebCore::StyleResolver::CascadedProperties::hasCustomProperty):
+        (WebCore::StyleResolver::CascadedProperties::customProperty):
+        Helpers used by applyProperty to check on custom properties, since they can revert too
+        just like a regular property can.
+
+        (WebCore::StyleResolver::CascadedProperties::setPropertyInternal):
+        (WebCore::StyleResolver::CascadedProperties::set):
+        (WebCore::StyleResolver::CascadedProperties::setDeferred):
+        Passing along the CascadeLevel (UA, User, Author) so that it can be stored in the Property.
+        This way when we do property application, we always know where the rule came from so
+        that the reversion can be handled properly.
+
+        (WebCore::StyleResolver::CascadedProperties::addStyleProperties):
+        (WebCore::cascadeLevelForIndex):
+        (WebCore::StyleResolver::CascadedProperties::addMatches):
+        When style properties are added, also figure out the CascadeLevel and pass it along to be
+        stored in the Property. We use the MatchResult's ranges to know where a property comes from.
+
+        (WebCore::StyleResolver::CascadedProperties::applyDeferredProperties):
+        (WebCore::StyleResolver::CascadedProperties::Property::apply):
+        (WebCore::StyleResolver::applyCascadedProperties):
+        Pass along the MatchResult so we know how to build the rollback.
+
+        * css/StyleResolver.h:
+        (WebCore::StyleResolver::State::cascadeLevel):
+        (WebCore::StyleResolver::State::setCascadeLevel):
+        (WebCore::StyleResolver::State::authorRollback):
+        (WebCore::StyleResolver::State::userRollback):
+        (WebCore::StyleResolver::State::setAuthorRollback):
+        (WebCore::StyleResolver::State::setUserRollback):
+        (WebCore::StyleResolver::state):
+        (WebCore::StyleResolver::cascadeLevel):
+        (WebCore::StyleResolver::setCascadeLevel):
+        Move CascadedProperties into the header. Add CascadeLevel to Property. Add the level and
+        rollbacks to the resolver's state.
+
 2015-10-17  Myles C. Maxfield  <mmaxfield@apple.com>
 
         Delete FontPlatformData::allowsLigatures()
index 90bcd64..710f74e 100644 (file)
                BC779E171BB227CA00CAA8BF /* StyleCustomPropertyData.h in Headers */ = {isa = PBXBuildFile; fileRef = BC779E151BB226A200CAA8BF /* StyleCustomPropertyData.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BC7D8FEF1BD03B6400FFE540 /* CSSUnsetValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC7D8FED1BD03B6400FFE540 /* CSSUnsetValue.cpp */; };
                BC7D8FF01BD03B6400FFE540 /* CSSUnsetValue.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7D8FEE1BD03B6400FFE540 /* CSSUnsetValue.h */; };
+               BC7D8FF31BD1A47900FFE540 /* CSSRevertValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC7D8FF11BD1A47900FFE540 /* CSSRevertValue.cpp */; settings = {ASSET_TAGS = (); }; };
+               BC7D8FF41BD1A47900FFE540 /* CSSRevertValue.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7D8FF21BD1A47900FFE540 /* CSSRevertValue.h */; settings = {ASSET_TAGS = (); }; };
                BC7F44A80B9E324E00A9D081 /* ImageObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7F44A70B9E324E00A9D081 /* ImageObserver.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BC7FA6200D1F0CBD00DB22A9 /* LiveNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC7FA61E0D1F0CBD00DB22A9 /* LiveNodeList.cpp */; };
                BC7FA6210D1F0CBD00DB22A9 /* LiveNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7FA61F0D1F0CBD00DB22A9 /* LiveNodeList.h */; };
                BC7B2AF80450824100A8000F /* Scrollbar.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Scrollbar.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                BC7D8FED1BD03B6400FFE540 /* CSSUnsetValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSUnsetValue.cpp; sourceTree = "<group>"; };
                BC7D8FEE1BD03B6400FFE540 /* CSSUnsetValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSUnsetValue.h; sourceTree = "<group>"; };
+               BC7D8FF11BD1A47900FFE540 /* CSSRevertValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSRevertValue.cpp; sourceTree = "<group>"; };
+               BC7D8FF21BD1A47900FFE540 /* CSSRevertValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSRevertValue.h; sourceTree = "<group>"; };
                BC7F44A70B9E324E00A9D081 /* ImageObserver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ImageObserver.h; sourceTree = "<group>"; };
                BC7FA61E0D1F0CBD00DB22A9 /* LiveNodeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LiveNodeList.cpp; sourceTree = "<group>"; };
                BC7FA61F0D1F0CBD00DB22A9 /* LiveNodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiveNodeList.h; sourceTree = "<group>"; };
                                9362640A0DE1137D009D5A00 /* CSSReflectionDirection.h */,
                                BC5A12DD0DC0414800C9AFAD /* CSSReflectValue.cpp */,
                                BC5A12DE0DC0414800C9AFAD /* CSSReflectValue.h */,
+                               BC7D8FF11BD1A47900FFE540 /* CSSRevertValue.cpp */,
+                               BC7D8FF21BD1A47900FFE540 /* CSSRevertValue.h */,
                                A80E6CDC0A1989CA007FB8C5 /* CSSRule.cpp */,
                                A80E6CE30A1989CA007FB8C5 /* CSSRule.h */,
                                14CF7A7009F5CF9A00EB3665 /* CSSRule.idl */,
                                E125F82C1822CFEC00D84CD9 /* CryptoAlgorithmSHA1.h in Headers */,
                                E19AC3EF1824DC7900349426 /* CryptoAlgorithmSHA224.h in Headers */,
                                E19AC3F11824DC7900349426 /* CryptoAlgorithmSHA256.h in Headers */,
-                               836CB1F81BD1E41800AF1591 /* JSHTMLTableDataCellElement.h in Headers */,
                                E19AC3F31824DC7900349426 /* CryptoAlgorithmSHA384.h in Headers */,
                                E19AC3F51824DC7900349426 /* CryptoAlgorithmSHA512.h in Headers */,
                                E1FE136718343A1000892F13 /* CryptoDigest.h in Headers */,
                                82E3D8DF122EA0D1003AE5BC /* CSSPropertySourceData.h in Headers */,
                                9362640B0DE1137D009D5A00 /* CSSReflectionDirection.h in Headers */,
                                BC5A12E00DC0414800C9AFAD /* CSSReflectValue.h in Headers */,
+                               BC7D8FF41BD1A47900FFE540 /* CSSRevertValue.h in Headers */,
                                A80E6D0D0A1989CA007FB8C5 /* CSSRule.h in Headers */,
                                A80E6CF20A1989CA007FB8C5 /* CSSRuleList.h in Headers */,
                                371F51A10D262FA000ECE0D5 /* CSSSegmentedFontFace.h in Headers */,
                                A871DB2B0A150BD600B12A68 /* HTMLTableCaptionElement.h in Headers */,
                                A871DB2A0A150BD600B12A68 /* HTMLTableCellElement.h in Headers */,
                                A871DB2F0A150BD600B12A68 /* HTMLTableColElement.h in Headers */,
+                               836BAD221BD1CA670037356A /* HTMLTableDataCellElement.h in Headers */,
                                A871DB270A150BD600B12A68 /* HTMLTableElement.h in Headers */,
+                               836BAD211BD1CA670037356A /* HTMLTableHeaderCellElement.h in Headers */,
                                A871DB2C0A150BD600B12A68 /* HTMLTablePartElement.h in Headers */,
                                A871DB310A150BD600B12A68 /* HTMLTableRowElement.h in Headers */,
                                93442C9E0D2B335C00338FF9 /* HTMLTableRowsCollection.h in Headers */,
                                BCA169A30BFD55B40019CA76 /* JSHTMLTableCaptionElement.h in Headers */,
                                BC06EDE40BFD6D0D00856E9D /* JSHTMLTableCellElement.h in Headers */,
                                BC06ED9E0BFD660600856E9D /* JSHTMLTableColElement.h in Headers */,
+                               836CB1F81BD1E41800AF1591 /* JSHTMLTableDataCellElement.h in Headers */,
                                BC06EE050BFD71AA00856E9D /* JSHTMLTableElement.h in Headers */,
+                               836CB1F61BD1E41800AF1591 /* JSHTMLTableHeaderCellElement.h in Headers */,
                                BC06EDA00BFD660600856E9D /* JSHTMLTableRowElement.h in Headers */,
                                BC06ED070BFD5BAE00856E9D /* JSHTMLTableSectionElement.h in Headers */,
                                D6489D26166FFCF1007C031B /* JSHTMLTemplateElement.h in Headers */,
                                8542A7930AE5C93F00DF58DF /* JSSVGRect.h in Headers */,
                                B2FA3DEE0AB75A6F000E5AC4 /* JSSVGRectElement.h in Headers */,
                                B2FA3DF10AB75A6F000E5AC4 /* JSSVGRenderingIntent.h in Headers */,
-                               836CB1F61BD1E41800AF1591 /* JSHTMLTableHeaderCellElement.h in Headers */,
                                B2FA3DF30AB75A6F000E5AC4 /* JSSVGScriptElement.h in Headers */,
                                B2FA3DF50AB75A6F000E5AC4 /* JSSVGSetElement.h in Headers */,
                                B2FA3DF70AB75A6F000E5AC4 /* JSSVGStopElement.h in Headers */,
                                9393E605151A9A1800066F06 /* StyleCachedImageSet.h in Headers */,
                                9DAC7C571AF2CB6400437C44 /* StyleContentAlignmentData.h in Headers */,
                                BC779E171BB227CA00CAA8BF /* StyleCustomPropertyData.h in Headers */,
-                               836BAD211BD1CA670037356A /* HTMLTableHeaderCellElement.h in Headers */,
                                BC5EB67F0E81D4A700B25965 /* StyleDashboardRegion.h in Headers */,
                                A8C4A7FD09D563270003AC8D /* StyledElement.h in Headers */,
                                BC5EB8B90E8201BD00B25965 /* StyleDeprecatedFlexibleBoxData.h in Headers */,
                                43A625F813B3304000AC94B8 /* SVGAnimatedColor.h in Headers */,
                                08D46CE3127AD5FC0089694B /* SVGAnimatedEnumeration.h in Headers */,
                                71FB967B1383D64600AC8A4C /* SVGAnimatedEnumerationPropertyTearOff.h in Headers */,
-                               836BAD221BD1CA670037356A /* HTMLTableDataCellElement.h in Headers */,
                                0823D159127AD6AC000EBC95 /* SVGAnimatedInteger.h in Headers */,
                                71E623D1151F72A60036E2F4 /* SVGAnimatedIntegerOptionalInteger.h in Headers */,
                                089021A9126EF5DE0092D5EA /* SVGAnimatedLength.h in Headers */,
                                1ABA76CA11D20E50004C201C /* CSSPropertyNames.cpp in Sources */,
                                82E3D8DE122EA0D1003AE5BC /* CSSPropertySourceData.cpp in Sources */,
                                BC5A12DF0DC0414800C9AFAD /* CSSReflectValue.cpp in Sources */,
+                               BC7D8FF31BD1A47900FFE540 /* CSSRevertValue.cpp in Sources */,
                                A80E6D060A1989CA007FB8C5 /* CSSRule.cpp in Sources */,
                                A80E6D090A1989CA007FB8C5 /* CSSRuleList.cpp in Sources */,
                                371F51A20D262FA000ECE0D5 /* CSSSegmentedFontFace.cpp in Sources */,
                                BCA169A20BFD55B40019CA76 /* JSHTMLTableCaptionElement.cpp in Sources */,
                                BC06EDE30BFD6D0D00856E9D /* JSHTMLTableCellElement.cpp in Sources */,
                                BC06ED9D0BFD660600856E9D /* JSHTMLTableColElement.cpp in Sources */,
+                               836CB1F91BD1E41800AF1591 /* JSHTMLTableDataCellElement.cpp in Sources */,
                                BC06EE040BFD71AA00856E9D /* JSHTMLTableElement.cpp in Sources */,
+                               836CB1F71BD1E41800AF1591 /* JSHTMLTableHeaderCellElement.cpp in Sources */,
                                BC06ED9F0BFD660600856E9D /* JSHTMLTableRowElement.cpp in Sources */,
                                BC06ED060BFD5BAE00856E9D /* JSHTMLTableSectionElement.cpp in Sources */,
                                D6489D25166FFCF1007C031B /* JSHTMLTemplateElement.cpp in Sources */,
                                5824ABAA1AE849C8009074B7 /* RenderTreePosition.cpp in Sources */,
                                E44614510CD68A3500FADA75 /* RenderVideo.cpp in Sources */,
                                BCEA4867097D93020094C9E4 /* RenderView.cpp in Sources */,
-                               836CB1F71BD1E41800AF1591 /* JSHTMLTableHeaderCellElement.cpp in Sources */,
                                BE20507D18A458BF0080647E /* RenderVTTCue.cpp in Sources */,
                                A871DFE50A15376B00B12A68 /* RenderWidget.cpp in Sources */,
                                F5528DA61AC1033E000EF7AD /* ReplaceDeleteFromTextNodeCommand.cpp in Sources */,
                                A136A00C1134DBD200CC8D50 /* XMLHttpRequestProgressEventThrottle.cpp in Sources */,
                                BCDFD48F0E305290009D10AD /* XMLHttpRequestUpload.cpp in Sources */,
                                A833C80C0A2CF25600D57664 /* XMLNames.cpp in Sources */,
-                               836CB1F91BD1E41800AF1591 /* JSHTMLTableDataCellElement.cpp in Sources */,
                                E15A36D91104572700B7B639 /* XMLNSNames.cpp in Sources */,
                                1ACE53EA0A8D18E70022947D /* XMLSerializer.cpp in Sources */,
                                5905ADBF1302F3CE00F116DF /* XMLTreeViewer.cpp in Sources */,
index bb1630c..98f2cbe 100644 (file)
@@ -125,6 +125,7 @@ Class kitClass(WebCore::CSSValue* impl)
         case WebCore::CSSValue::CSS_INHERIT:
         case WebCore::CSSValue::CSS_INITIAL:
         case WebCore::CSSValue::CSS_UNSET:
+        case WebCore::CSSValue::CSS_REVERT:
             return [DOMCSSValue class];
         case WebCore::CSSValue::CSS_CUSTOM:
             return [DOMCSSValue class];
index cc4c8dc..d0fa961 100644 (file)
@@ -57,6 +57,7 @@
 #include "CSSPrimitiveValueMappings.h"
 #include "CSSPropertySourceData.h"
 #include "CSSReflectValue.h"
+#include "CSSRevertValue.h"
 #include "CSSSelector.h"
 #include "CSSShadowValue.h"
 #include "CSSStyleSheet.h"
@@ -1197,10 +1198,10 @@ static CSSParser::ParseResult parseKeywordValue(MutableStyleProperties* declarat
     if (!isKeywordPropertyID(propertyId)) {
         // All properties accept the values of "initial" and "inherit".
         String lowerCaseString = string.lower();
-        if (lowerCaseString != "initial" && lowerCaseString != "inherit" && lowerCaseString != "unset")
+        if (lowerCaseString != "initial" && lowerCaseString != "inherit" && lowerCaseString != "unset" && lowerCaseString != "revert")
             return CSSParser::ParseResult::Error;
 
-        // Parse initial/inherit/unset shorthands using the CSSParser.
+        // Parse initial/inherit/unset/revert shorthands using the CSSParser.
         if (shorthandForProperty(propertyId).length())
             return CSSParser::ParseResult::Error;
     }
@@ -1219,6 +1220,8 @@ static CSSParser::ParseResult parseKeywordValue(MutableStyleProperties* declarat
         value = CSSValuePool::singleton().createExplicitInitialValue();
     else if (valueID == CSSValueUnset)
         value = CSSValuePool::singleton().createUnsetValue();
+    else if (valueID == CSSValueRevert)
+        value = CSSValuePool::singleton().createRevertValue();
     else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext, styleSheetContents))
         value = CSSValuePool::singleton().createIdentifierValue(valueID);
     else
@@ -1965,6 +1968,11 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important)
             return false;
         addExpandedPropertyForValue(propId, cssValuePool.createUnsetValue(), important);
         return true;
+    } else if (id == CSSValueRevert) {
+        if (num != 1)
+            return false;
+        addExpandedPropertyForValue(propId, cssValuePool.createRevertValue(), important);
+        return true;
     }
     
     if (propId == CSSPropertyAll)
@@ -4213,6 +4221,8 @@ bool CSSParser::parseCustomPropertyDeclaration(bool important, CSSValueID id)
         value = cssValuePool.createExplicitInitialValue();
     else if (id == CSSValueUnset)
         value = cssValuePool.createUnsetValue();
+    else if (id == CSSValueRevert)
+        value = cssValuePool.createRevertValue();
     else {
         RefPtr<CSSValueList> valueList = CSSValueList::createFromParserValueList(*m_valueList);
         if (m_valueList->containsVariables())
diff --git a/Source/WebCore/css/CSSRevertValue.cpp b/Source/WebCore/css/CSSRevertValue.cpp
new file mode 100644 (file)
index 0000000..9a63ef9
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 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 "CSSRevertValue.h"
+
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+String CSSRevertValue::customCSSText() const
+{
+    return ASCIILiteral("Revert");
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSRevertValue.h b/Source/WebCore/css/CSSRevertValue.h
new file mode 100644 (file)
index 0000000..22235a4
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef CSSRevertValue_h
+#define CSSRevertValue_h
+
+#include "CSSValue.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class CSSRevertValue : public CSSValue {
+public:
+    static Ref<CSSRevertValue> create()
+    {
+        return adoptRef(*new CSSRevertValue);
+    }
+
+    String customCSSText() const;
+
+    bool equals(const CSSRevertValue&) const { return true; }
+
+private:
+    CSSRevertValue()
+        : CSSValue(RevertClass)
+    {
+    }
+};
+
+} // namespace WebCore
+
+SPECIALIZE_TYPE_TRAITS_CSS_VALUE(CSSRevertValue, isRevertValue())
+
+#endif // CSSRevertValue_h
index 6a7a6d2..2298205 100644 (file)
@@ -114,6 +114,8 @@ CSSValue::Type CSSValue::cssValueType() const
         return CSS_INITIAL;
     if (isUnsetValue())
         return CSS_UNSET;
+    if (isRevertValue())
+        return CSS_REVERT;
     return CSS_CUSTOM;
 }
 
@@ -203,6 +205,8 @@ bool CSSValue::equals(const CSSValue& other) const
             return compareCSSValues<CSSInitialValue>(*this, other);
         case UnsetClass:
             return compareCSSValues<CSSUnsetValue>(*this, other);
+        case RevertClass:
+            return compareCSSValues<CSSRevertValue>(*this, other);
 #if ENABLE(CSS_GRID_LAYOUT)
         case GridLineNamesClass:
             return compareCSSValues<CSSGridLineNamesValue>(*this, other);
@@ -305,6 +309,8 @@ String CSSValue::cssText() const
         return downcast<CSSInitialValue>(*this).customCSSText();
     case UnsetClass:
         return downcast<CSSUnsetValue>(*this).customCSSText();
+    case RevertClass:
+        return downcast<CSSRevertValue>(*this).customCSSText();
 #if ENABLE(CSS_GRID_LAYOUT)
     case GridLineNamesClass:
         return downcast<CSSGridLineNamesValue>(*this).customCSSText();
@@ -417,6 +423,9 @@ void CSSValue::destroy()
     case UnsetClass:
         delete downcast<CSSUnsetValue>(this);
         return;
+    case RevertClass:
+        delete downcast<CSSRevertValue>(this);
+        return;
 #if ENABLE(CSS_GRID_LAYOUT)
     case GridLineNamesClass:
         delete downcast<CSSGridLineNamesValue>(this);
index 58f3785..59dc617 100644 (file)
@@ -47,7 +47,8 @@ public:
         CSS_VALUE_LIST = 2,
         CSS_CUSTOM = 3,
         CSS_INITIAL = 4,
-        CSS_UNSET = 5
+        CSS_UNSET = 5,
+        CSS_REVERT = 6
     };
 
     // Override RefCounted's deref() to ensure operator delete is called on
@@ -94,6 +95,7 @@ public:
     bool isInheritedValue() const { return m_classType == InheritedClass; }
     bool isInitialValue() const { return m_classType == InitialClass; }
     bool isUnsetValue() const { return m_classType == UnsetClass; }
+    bool isRevertValue() const { return m_classType == RevertClass; }
     bool treatAsInitialValue(CSSPropertyID) const;
     bool treatAsInheritedValue(CSSPropertyID) const;
     bool isLinearGradientValue() const { return m_classType == LinearGradientClass; }
@@ -169,6 +171,7 @@ protected:
         InheritedClass,
         InitialClass,
         UnsetClass,
+        RevertClass,
 
         ReflectClass,
         ShadowClass,
index 63a89c6..dd484fd 100644 (file)
@@ -4,6 +4,7 @@
 inherit
 initial
 unset
+revert
 
 //
 // CSS_PROP_OUTLINE_STYLE
index d71c0ff..0d62472 100644 (file)
@@ -45,6 +45,7 @@ CSSValuePool::CSSValuePool()
     , m_implicitInitialValue(CSSInitialValue::createImplicit())
     , m_explicitInitialValue(CSSInitialValue::createExplicit())
     , m_unsetValue(CSSUnsetValue::create())
+    , m_revertValue(CSSRevertValue::create())
     , m_colorTransparent(CSSPrimitiveValue::createColor(Color::transparent))
     , m_colorWhite(CSSPrimitiveValue::createColor(Color::white))
     , m_colorBlack(CSSPrimitiveValue::createColor(Color::black))
index 53e8836..a16ec46 100644 (file)
@@ -31,6 +31,7 @@
 #include "CSSInitialValue.h"
 #include "CSSPrimitiveValue.h"
 #include "CSSPropertyNames.h"
+#include "CSSRevertValue.h"
 #include "CSSUnsetValue.h"
 #include "CSSValueKeywords.h"
 #include <utility>
@@ -56,6 +57,7 @@ public:
     Ref<CSSInitialValue> createImplicitInitialValue() { return m_implicitInitialValue.copyRef(); }
     Ref<CSSInitialValue> createExplicitInitialValue() { return m_explicitInitialValue.copyRef(); }
     Ref<CSSUnsetValue> createUnsetValue() { return m_unsetValue.copyRef(); }
+    Ref<CSSRevertValue> createRevertValue() { return m_revertValue.copyRef(); }
     Ref<CSSPrimitiveValue> createIdentifierValue(CSSValueID identifier);
     Ref<CSSPrimitiveValue> createIdentifierValue(CSSPropertyID identifier);
     Ref<CSSPrimitiveValue> createColorValue(unsigned rgbValue);
@@ -74,6 +76,7 @@ private:
     Ref<CSSInitialValue> m_implicitInitialValue;
     Ref<CSSInitialValue> m_explicitInitialValue;
     Ref<CSSUnsetValue> m_unsetValue;
+    Ref<CSSRevertValue> m_revertValue;
 
     RefPtr<CSSPrimitiveValue> m_identifierValueCache[numCSSValueKeywords];
 
index fd55a9e..dde133c 100644 (file)
@@ -300,7 +300,7 @@ bool FontLoader::resolveFontStyle(const String& fontString, FontCascade& font)
         return false;
     
     String fontValue = parsedStyle->getPropertyValue(CSSPropertyFont);
-    if (fontValue == "inherit" || fontValue == "initial")
+    if (fontValue == "inherit" || fontValue == "initial" || fontValue == "unset" || fontValue == "revert")
         return false;
 
     RefPtr<RenderStyle> style = RenderStyle::create();
index 20243b0..006711f 100644 (file)
@@ -102,7 +102,7 @@ public:
     static bool matchesFocusPseudoClass(const Element*);
     static bool checkExactAttribute(const Element*, const CSSSelector*, const QualifiedName& selectorAttributeName, const AtomicStringImpl* value);
 
-    enum LinkMatchMask { MatchLink = 1, MatchVisited = 2, MatchAll = MatchLink | MatchVisited };
+    enum LinkMatchMask { MatchDefault = 0, MatchLink = 1, MatchVisited = 2, MatchAll = MatchLink | MatchVisited };
     static unsigned determineLinkMatchType(const CSSSelector*);
 
 private:
index ab8900e..0a424ad 100644 (file)
@@ -173,42 +173,6 @@ using namespace HTMLNames;
 static const CSSPropertyID lastHighPriorityProperty = CSSPropertyFontSynthesis;
 static const CSSPropertyID firstLowPriorityProperty = static_cast<CSSPropertyID>(lastHighPriorityProperty + 1);
 
-class StyleResolver::CascadedProperties {
-public:
-    CascadedProperties(TextDirection, WritingMode);
-
-    struct Property {
-        void apply(StyleResolver&);
-
-        CSSPropertyID id;
-        CSSValue* cssValue[3];
-    };
-
-    bool hasProperty(CSSPropertyID id) const;
-    Property& property(CSSPropertyID);
-    void addMatches(const MatchResult&, bool important, int startIndex, int endIndex, bool inheritedOnly = false);
-
-    void set(CSSPropertyID, CSSValue&, unsigned linkMatchType);
-    void setDeferred(CSSPropertyID, CSSValue&, unsigned linkMatchType);
-
-    void applyDeferredProperties(StyleResolver&);
-
-    HashMap<AtomicString, Property>& customProperties() { return m_customProperties; }
-    
-private:
-    void addStyleProperties(const StyleProperties&, StyleRule&, bool isImportant, bool inheritedOnly, PropertyWhitelistType, unsigned linkMatchType);
-    static void setPropertyInternal(Property&, CSSPropertyID, CSSValue&, unsigned linkMatchType);
-
-    Property m_properties[numCSSProperties + 2];
-    std::bitset<numCSSProperties + 2> m_propertyIsPresent;
-
-    Vector<Property, 8> m_deferredProperties;
-    HashMap<AtomicString, Property> m_customProperties;
-
-    TextDirection m_direction;
-    WritingMode m_writingMode;
-};
-
 static void extractDirectionAndWritingMode(const RenderStyle&, const StyleResolver::MatchResult&, TextDirection&, WritingMode&);
 
 RenderStyle* StyleResolver::s_styleNotYetAvailable;
@@ -440,6 +404,9 @@ inline void StyleResolver::State::initForStyleResolve(Document& document, Elemen
     m_style = nullptr;
     m_pendingImageProperties.clear();
     m_fontDirty = false;
+    
+    m_authorRollback = nullptr;
+    m_userRollback = nullptr;
 
     updateConversionData();
 }
@@ -854,20 +821,20 @@ Ref<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* elementStyle
     cascade.addMatches(result, false, 0, result.matchedProperties().size() - 1);
     
     // Resolve custom properties first.
-    applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom);
+    applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &result);
 
-    applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty);
+    applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &result);
 
     // If our font got dirtied, update it now.
     updateFont();
 
     // Now do rest of the properties.
-    applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty);
+    applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &result);
 
     // If our font got dirtied by one of the non-essential font props, update it a second time.
     updateFont();
 
-    cascade.applyDeferredProperties(*this);
+    cascade.applyDeferredProperties(*this, &result);
 
     // Start loading resources referenced by this style.
     loadPendingResources();
@@ -1022,16 +989,16 @@ Ref<RenderStyle> StyleResolver::styleForPage(int pageIndex)
     cascade.addMatches(result, false, 0, result.matchedProperties().size() - 1);
 
     // Resolve custom properties first.
-    applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom);
+    applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &result);
 
-    applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty);
+    applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &result);
 
     // If our font got dirtied, update it now.
     updateFont();
 
-    applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty);
+    applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &result);
 
-    cascade.applyDeferredProperties(*this);
+    cascade.applyDeferredProperties(*this, &result);
 
     // Start loading resources referenced by this style.
     loadPendingResources();
@@ -1697,17 +1664,17 @@ void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const
         cascade.addMatches(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
         cascade.addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
 
-        applyCascadedProperties(cascade, CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition);
+        applyCascadedProperties(cascade, CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition, &matchResult);
         adjustStyleForInterCharacterRuby();
     
         // Resolve custom variables first.
-        applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom);
+        applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &matchResult);
 
         // Start by applying properties that other properties may depend on.
-        applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty);
+        applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &matchResult);
     
         updateFont();
-        applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty);
+        applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &matchResult);
 
         state.cacheBorderAndBackground();
     }
@@ -1719,15 +1686,15 @@ void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const
     cascade.addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
     
     // Resolve custom properties first.
-    applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom);
+    applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &matchResult);
 
-    applyCascadedProperties(cascade, CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition);
+    applyCascadedProperties(cascade, CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition, &matchResult);
     
     // Adjust the font size to be smaller if ruby-position is inter-character.
     adjustStyleForInterCharacterRuby();
 
     // Start by applying properties that other properties may depend on.
-    applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty);
+    applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &matchResult);
 
     // If the effective zoom value changes, we can't use the matched properties cache. Start over.
     if (cacheItem && cacheItem->renderStyle->effectiveZoom() != state.style()->effectiveZoom())
@@ -1741,12 +1708,12 @@ void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const
         return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache);
 
     // Apply properties that no other properties depend on.
-    applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty);
+    applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &matchResult);
 
     // Finally, some properties must be applied in the order they were parsed.
     // There are some CSS properties that affect the same RenderStyle values,
     // so to preserve behavior, we queue them up during cascade and flush here.
-    cascade.applyDeferredProperties(*this);
+    cascade.applyDeferredProperties(*this, &matchResult);
 
     // Start loading resources referenced by this style.
     loadPendingResources();
@@ -1876,7 +1843,50 @@ bool StyleResolver::useSVGZoomRulesForLength()
     return is<SVGElement>(m_state.element()) && !(is<SVGSVGElement>(*m_state.element()) && m_state.element()->parentNode());
 }
 
-void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
+StyleResolver::CascadedProperties* StyleResolver::cascadedPropertiesForRollback(const MatchResult& matchResult)
+{
+    ASSERT(cascadeLevel() != UserAgentLevel);
+    
+    TextDirection direction;
+    WritingMode writingMode;
+    extractDirectionAndWritingMode(*state().style(), matchResult, direction, writingMode);
+
+    if (cascadeLevel() == AuthorLevel) {
+        CascadedProperties* authorRollback = state().authorRollback();
+        if (authorRollback)
+            return authorRollback;
+        
+        auto newAuthorRollback(std::make_unique<CascadedProperties>(direction, writingMode));
+        
+        // This special rollback cascade contains UA rules and user rules but no author rules.
+        newAuthorRollback->addMatches(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
+        newAuthorRollback->addMatches(matchResult, false, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, false);
+        newAuthorRollback->addMatches(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, false);
+        newAuthorRollback->addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
+    
+        state().setAuthorRollback(newAuthorRollback);
+        return state().authorRollback();
+    }
+    
+    if (cascadeLevel() == UserLevel) {
+        CascadedProperties* userRollback = state().userRollback();
+        if (userRollback)
+            return userRollback;
+        
+        auto newUserRollback(std::make_unique<CascadedProperties>(direction, writingMode));
+        
+        // This special rollback cascade contains only UA rules.
+        newUserRollback->addMatches(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
+        newUserRollback->addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
+    
+        state().setUserRollback(newUserRollback);
+        return state().userRollback();
+    }
+    
+    return nullptr;
+}
+
+void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value, SelectorChecker::LinkMatchMask linkMatchMask, const MatchResult* matchResult)
 {
     ASSERT_WITH_MESSAGE(!isShorthandCSSProperty(id), "Shorthand property id = %d wasn't expanded at parsing time", id);
 
@@ -1896,25 +1906,60 @@ void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
     if (CSSProperty::isDirectionAwareProperty(id)) {
         CSSPropertyID newId = CSSProperty::resolveDirectionAwareProperty(id, state.style()->direction(), state.style()->writingMode());
         ASSERT(newId != id);
-        return applyProperty(newId, valueToApply.get());
+        return applyProperty(newId, valueToApply.get(), linkMatchMask, matchResult);
     }
     
     CSSValue* valueToCheckForInheritInitial = valueToApply.get();
+    CSSCustomPropertyValue* customPropertyValue = nullptr;
+    
     if (id == CSSPropertyCustom) {
-        CSSCustomPropertyValue* customProperty = &downcast<CSSCustomPropertyValue>(*valueToApply);
-        valueToCheckForInheritInitial = customProperty->value().get();
+        customPropertyValue = &downcast<CSSCustomPropertyValue>(*valueToApply);
+        valueToCheckForInheritInitial = customPropertyValue->value().get();
     }
 
     bool isInherit = state.parentStyle() && valueToCheckForInheritInitial->isInheritedValue();
     bool isInitial = valueToCheckForInheritInitial->isInitialValue() || (!state.parentStyle() && valueToCheckForInheritInitial->isInheritedValue());
     
-    if (valueToCheckForInheritInitial->isUnsetValue()) {
+    bool isUnset = valueToCheckForInheritInitial->isUnsetValue();
+    bool isRevert = valueToCheckForInheritInitial->isRevertValue();
+
+    if (isRevert) {
+        if (cascadeLevel() == UserAgentLevel || !matchResult)
+            isUnset = true;
+        else {
+            // Fetch the correct rollback object from the state, building it if necessary.
+            // This requires having the original MatchResult available.
+            auto* rollback = cascadedPropertiesForRollback(*matchResult);
+            ASSERT(rollback);
+
+            // With the cascade built, we need to obtain the property and apply it. If the property is
+            // not present, then we behave like "unset." Otherwise we apply the property instead of
+            // our own.
+            if (customPropertyValue) {
+                if (rollback->hasCustomProperty(customPropertyValue->name())) {
+                    auto property = rollback->customProperty(customPropertyValue->name());
+                    if (property.cssValue[linkMatchMask])
+                        applyProperty(property.id, property.cssValue[linkMatchMask], linkMatchMask, matchResult);
+                    return;
+                }
+            } else if (rollback->hasProperty(id)) {
+                auto& property = rollback->property(id);
+                if (property.cssValue[linkMatchMask])
+                    applyProperty(property.id, property.cssValue[linkMatchMask], linkMatchMask, matchResult);
+                return;
+            }
+        
+            isUnset = true;
+        }
+    }
+    
+    if (isUnset) {
         if (CSSProperty::isInheritedProperty(id))
             isInherit = true;
         else
             isInitial = true;
     }
-    
+
     ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
 
     if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
@@ -2568,10 +2613,21 @@ inline StyleResolver::CascadedProperties::Property& StyleResolver::CascadedPrope
     return m_properties[id];
 }
 
-void StyleResolver::CascadedProperties::setPropertyInternal(Property& property, CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType)
+inline bool StyleResolver::CascadedProperties::hasCustomProperty(const String& name) const
+{
+    return m_customProperties.contains(name);
+}
+
+inline StyleResolver::CascadedProperties::Property StyleResolver::CascadedProperties::customProperty(const String& name) const
+{
+    return m_customProperties.get(name);
+}
+
+void StyleResolver::CascadedProperties::setPropertyInternal(Property& property, CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel)
 {
     ASSERT(linkMatchType <= SelectorChecker::MatchAll);
     property.id = id;
+    property.level = cascadeLevel;
     if (linkMatchType == SelectorChecker::MatchAll) {
         property.cssValue[0] = &cssValue;
         property.cssValue[SelectorChecker::MatchLink] = &cssValue;
@@ -2580,7 +2636,7 @@ void StyleResolver::CascadedProperties::setPropertyInternal(Property& property,
         property.cssValue[linkMatchType] = &cssValue;
 }
 
-void StyleResolver::CascadedProperties::set(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType)
+void StyleResolver::CascadedProperties::set(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel)
 {
     if (CSSProperty::isDirectionAwareProperty(id))
         id = CSSProperty::resolveDirectionAwareProperty(id, m_direction, m_writingMode);
@@ -2597,11 +2653,11 @@ void StyleResolver::CascadedProperties::set(CSSPropertyID id, CSSValue& cssValue
             Property property;
             property.id = id;
             memset(property.cssValue, 0, sizeof(property.cssValue));
-            setPropertyInternal(property, id, cssValue, linkMatchType);
+            setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
             customProperties().set(customValue.name(), property);
         } else {
             Property property = customProperties().get(customValue.name());
-            setPropertyInternal(property, id, cssValue, linkMatchType);
+            setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
             customProperties().set(customValue.name(), property);
         }
         return;
@@ -2610,21 +2666,21 @@ void StyleResolver::CascadedProperties::set(CSSPropertyID id, CSSValue& cssValue
     if (!m_propertyIsPresent[id])
         memset(property.cssValue, 0, sizeof(property.cssValue));
     m_propertyIsPresent.set(id);
-    setPropertyInternal(property, id, cssValue, linkMatchType);
+    setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
 }
 
-void StyleResolver::CascadedProperties::setDeferred(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType)
+void StyleResolver::CascadedProperties::setDeferred(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel)
 {
     ASSERT(!CSSProperty::isDirectionAwareProperty(id));
     ASSERT(shouldApplyPropertyInParseOrder(id));
 
     Property property;
     memset(property.cssValue, 0, sizeof(property.cssValue));
-    setPropertyInternal(property, id, cssValue, linkMatchType);
+    setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
     m_deferredProperties.append(property);
 }
 
-void StyleResolver::CascadedProperties::addStyleProperties(const StyleProperties& properties, StyleRule&, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType, unsigned linkMatchType)
+void StyleResolver::CascadedProperties::addStyleProperties(const StyleProperties& properties, StyleRule&, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType, unsigned linkMatchType, CascadeLevel cascadeLevel)
 {
     for (unsigned i = 0, count = properties.propertyCount(); i < count; ++i) {
         auto current = properties.propertyAt(i);
@@ -2646,12 +2702,21 @@ void StyleResolver::CascadedProperties::addStyleProperties(const StyleProperties
 #endif
 
         if (shouldApplyPropertyInParseOrder(propertyID))
-            setDeferred(propertyID, *current.value(), linkMatchType);
+            setDeferred(propertyID, *current.value(), linkMatchType, cascadeLevel);
         else
-            set(propertyID, *current.value(), linkMatchType);
+            set(propertyID, *current.value(), linkMatchType, cascadeLevel);
     }
 }
 
+static CascadeLevel cascadeLevelForIndex(const StyleResolver::MatchResult& matchResult, int index)
+{
+    if (index >= matchResult.ranges.firstUARule && index <= matchResult.ranges.lastUARule)
+        return UserAgentLevel;
+    if (index >= matchResult.ranges.firstUserRule && index <= matchResult.ranges.lastUserRule)
+        return UserLevel;
+    return AuthorLevel;
+}
+
 void StyleResolver::CascadedProperties::addMatches(const MatchResult& matchResult, bool important, int startIndex, int endIndex, bool inheritedOnly)
 {
     if (startIndex == -1)
@@ -2659,24 +2724,26 @@ void StyleResolver::CascadedProperties::addMatches(const MatchResult& matchResul
 
     for (int i = startIndex; i <= endIndex; ++i) {
         const MatchedProperties& matchedProperties = matchResult.matchedProperties()[i];
-        addStyleProperties(*matchedProperties.properties, *matchResult.matchedRules[i], important, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType), matchedProperties.linkMatchType);
+        addStyleProperties(*matchedProperties.properties, *matchResult.matchedRules[i], important, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType), matchedProperties.linkMatchType,
+            cascadeLevelForIndex(matchResult, i));
     }
 }
 
-void StyleResolver::CascadedProperties::applyDeferredProperties(StyleResolver& resolver)
+void StyleResolver::CascadedProperties::applyDeferredProperties(StyleResolver& resolver, const MatchResult* matchResult)
 {
     for (auto& property : m_deferredProperties)
-        property.apply(resolver);
+        property.apply(resolver, matchResult);
 }
 
-void StyleResolver::CascadedProperties::Property::apply(StyleResolver& resolver)
+void StyleResolver::CascadedProperties::Property::apply(StyleResolver& resolver, const MatchResult* matchResult)
 {
     State& state = resolver.state();
+    state.setCascadeLevel(level);
 
-    if (cssValue[0]) {
+    if (cssValue[SelectorChecker::MatchDefault]) {
         state.setApplyPropertyToRegularStyle(true);
         state.setApplyPropertyToVisitedLinkStyle(false);
-        resolver.applyProperty(id, cssValue[0]);
+        resolver.applyProperty(id, cssValue[SelectorChecker::MatchDefault], SelectorChecker::MatchDefault, matchResult);
     }
 
     if (state.style()->insideLink() == NotInsideLink)
@@ -2685,20 +2752,20 @@ void StyleResolver::CascadedProperties::Property::apply(StyleResolver& resolver)
     if (cssValue[SelectorChecker::MatchLink]) {
         state.setApplyPropertyToRegularStyle(true);
         state.setApplyPropertyToVisitedLinkStyle(false);
-        resolver.applyProperty(id, cssValue[SelectorChecker::MatchLink]);
+        resolver.applyProperty(id, cssValue[SelectorChecker::MatchLink], SelectorChecker::MatchLink, matchResult);
     }
 
     if (cssValue[SelectorChecker::MatchVisited]) {
         state.setApplyPropertyToRegularStyle(false);
         state.setApplyPropertyToVisitedLinkStyle(true);
-        resolver.applyProperty(id, cssValue[SelectorChecker::MatchVisited]);
+        resolver.applyProperty(id, cssValue[SelectorChecker::MatchVisited], SelectorChecker::MatchVisited, matchResult);
     }
 
     state.setApplyPropertyToRegularStyle(true);
     state.setApplyPropertyToVisitedLinkStyle(false);
 }
 
-void StyleResolver::applyCascadedProperties(CascadedProperties& cascade, int firstProperty, int lastProperty)
+void StyleResolver::applyCascadedProperties(CascadedProperties& cascade, int firstProperty, int lastProperty, const MatchResult* matchResult)
 {
     for (int id = firstProperty; id <= lastProperty; ++id) {
         CSSPropertyID propertyID = static_cast<CSSPropertyID>(id);
@@ -2707,12 +2774,12 @@ void StyleResolver::applyCascadedProperties(CascadedProperties& cascade, int fir
         if (propertyID == CSSPropertyCustom) {
             HashMap<AtomicString, CascadedProperties::Property>::iterator end = cascade.customProperties().end();
             for (HashMap<AtomicString, CascadedProperties::Property>::iterator it = cascade.customProperties().begin(); it != end; ++it)
-                it->value.apply(*this);
+                it->value.apply(*this, matchResult);
             continue;
         }
         auto& property = cascade.property(propertyID);
         ASSERT(!shouldApplyPropertyInParseOrder(propertyID));
-        property.apply(*this);
+        property.apply(*this, matchResult);
     }
     
     if (firstProperty == CSSPropertyCustom)
index 358fbaa..ae71a67 100644 (file)
@@ -38,6 +38,7 @@
 #include "SelectorFilter.h"
 #include "StyleInheritedData.h"
 #include "ViewportStyleResolver.h"
+#include <bitset>
 #include <memory>
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
@@ -120,6 +121,12 @@ enum RuleMatchingBehavior {
     MatchOnlyUserAgentRules,
 };
 
+enum CascadeLevel {
+    UserAgentLevel,
+    AuthorLevel,
+    UserLevel
+};
+
 class PseudoStyleRequest {
 public:
     PseudoStyleRequest(PseudoId pseudoId, RenderScrollbar* scrollbar = nullptr, ScrollbarPart scrollbarPart = NoPart)
@@ -194,6 +201,8 @@ public:
     Vector<RefPtr<StyleRule>> pseudoStyleRulesForElement(Element*, PseudoId, unsigned rulesToInclude = AllButEmptyCSSRules);
 
 public:
+    struct MatchResult;
+
     void applyPropertyToStyle(CSSPropertyID, CSSValue*, RenderStyle*);
 
     void applyPropertyToCurrentStyle(CSSPropertyID, CSSValue*);
@@ -284,6 +293,45 @@ public:
     private:
         Vector<MatchedProperties, 64> m_matchedProperties;
     };
+    
+    class CascadedProperties {
+    public:
+        CascadedProperties(TextDirection, WritingMode);
+
+        struct Property {
+            void apply(StyleResolver&, const MatchResult*);
+
+            CSSPropertyID id;
+            CascadeLevel level;
+            CSSValue* cssValue[3];
+        };
+
+        bool hasProperty(CSSPropertyID) const;
+        Property& property(CSSPropertyID);
+        void addMatches(const MatchResult&, bool important, int startIndex, int endIndex, bool inheritedOnly = false);
+
+        void set(CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel);
+        void setDeferred(CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel);
+
+        void applyDeferredProperties(StyleResolver&, const MatchResult*);
+
+        HashMap<AtomicString, Property>& customProperties() { return m_customProperties; }
+        bool hasCustomProperty(const String&) const;
+        Property customProperty(const String&) const;
+        
+    private:
+        void addStyleProperties(const StyleProperties&, StyleRule&, bool isImportant, bool inheritedOnly, PropertyWhitelistType, unsigned linkMatchType, CascadeLevel);
+        static void setPropertyInternal(Property&, CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel);
+
+        Property m_properties[numCSSProperties + 2];
+        std::bitset<numCSSProperties + 2> m_propertyIsPresent;
+
+        Vector<Property, 8> m_deferredProperties;
+        HashMap<AtomicString, Property> m_customProperties;
+
+        TextDirection m_direction;
+        WritingMode m_writingMode;
+    };
 
 private:
     // This function fixes up the default font size if it detects that the current generic font family has changed. -dwh
@@ -305,9 +353,7 @@ private:
     enum ShouldUseMatchedPropertiesCache { DoNotUseMatchedPropertiesCache = 0, UseMatchedPropertiesCache };
     void applyMatchedProperties(const MatchResult&, const Element*, ShouldUseMatchedPropertiesCache = UseMatchedPropertiesCache);
 
-    class CascadedProperties;
-
-    void applyCascadedProperties(CascadedProperties&, int firstProperty, int lastProperty);
+    void applyCascadedProperties(CascadedProperties&, int firstProperty, int lastProperty, const MatchResult*);
     void cascadeMatches(CascadedProperties&, const MatchResult&, bool important, int startIndex, int endIndex, bool inheritedOnly);
 
     static bool isValidRegionStyleProperty(CSSPropertyID);
@@ -376,7 +422,7 @@ public:
         bool applyPropertyToRegularStyle() const { return m_applyPropertyToRegularStyle; }
         bool applyPropertyToVisitedLinkStyle() const { return m_applyPropertyToVisitedLinkStyle; }
         PendingImagePropertyMap& pendingImageProperties() { return m_pendingImageProperties; }
-
+        
         Vector<RefPtr<ReferenceFilterOperation>>& filtersWithPendingSVGDocuments() { return m_filtersWithPendingSVGDocuments; }
 
         void setFontDirty(bool isDirty) { m_fontDirty = isDirty; }
@@ -402,6 +448,15 @@ public:
 
         CSSToLengthConversionData cssToLengthConversionData() const { return m_cssToLengthConversionData; }
 
+        CascadeLevel cascadeLevel() const { return m_cascadeLevel; }
+        void setCascadeLevel(CascadeLevel level) { m_cascadeLevel = level; }
+        
+        CascadedProperties* authorRollback() const { return m_authorRollback.get(); }
+        CascadedProperties* userRollback() const { return m_userRollback.get(); }
+        
+        void setAuthorRollback(std::unique_ptr<CascadedProperties>& rollback) { m_authorRollback = WTF::move(rollback); }
+        void setUserRollback(std::unique_ptr<CascadedProperties>& rollback) { m_userRollback = WTF::move(rollback); }
+        
     private:
         void updateConversionData();
 
@@ -434,6 +489,10 @@ public:
         Color m_backgroundColor;
 
         CSSToLengthConversionData m_cssToLengthConversionData;
+        
+        CascadeLevel m_cascadeLevel { UserAgentLevel };
+        std::unique_ptr<CascadedProperties> m_authorRollback;
+        std::unique_ptr<CascadedProperties> m_userRollback;
     };
 
     State& state() { return m_state; }
@@ -451,6 +510,11 @@ public:
     bool applyPropertyToRegularStyle() const { return m_state.applyPropertyToRegularStyle(); }
     bool applyPropertyToVisitedLinkStyle() const { return m_state.applyPropertyToVisitedLinkStyle(); }
 
+    CascadeLevel cascadeLevel() const { return m_state.cascadeLevel(); }
+    void setCascadeLevel(CascadeLevel level) { m_state.setCascadeLevel(level); }
+    
+    CascadedProperties* cascadedPropertiesForRollback(const MatchResult&);
+
     CSSToStyleMap* styleMap() { return &m_styleMap; }
     InspectorCSSOMWrappers& inspectorCSSOMWrappers() { return m_inspectorCSSOMWrappers; }
     const FontCascadeDescription& fontDescription() { return m_state.fontDescription(); }
@@ -468,7 +532,7 @@ private:
 
     bool canShareStyleWithControl(StyledElement*) const;
 
-    void applyProperty(CSSPropertyID, CSSValue*);
+    void applyProperty(CSSPropertyID, CSSValue*, SelectorChecker::LinkMatchMask = SelectorChecker::MatchDefault, const MatchResult* = nullptr);
     RefPtr<CSSValue> resolvedVariableValue(CSSPropertyID, const CSSVariableDependentValue&);
 
     void applySVGProperty(CSSPropertyID, CSSValue*);