CSSKeyframesRule::findRule() and deleteRule() should delete the last matching rule...
authordino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Jan 2015 19:39:22 +0000 (19:39 +0000)
committerdino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Jan 2015 19:39:22 +0000 (19:39 +0000)
https://bugs.webkit.org/show_bug.cgi?id=139732

Patch by Sylvain Galineau <galineau@adobe.com> on 2015-01-26
Reviewed by Dean Jackson and Darin Adler.

Source/WebCore:

No new tests because existing tests have been updated to verify this behavior.

* css/CSSKeyframeRule.h:
(WebCore::StyleKeyframe::getKeys): Deleted.
* css/StyleResolver.cpp:
(WebCore::StyleResolver::keyframeStylesForAnimation): use StyleKeyframe::keys().
* css/CSSKeyframeRule.cpp:
(WebCore::StyleKeyframe::parseKeyString): Deleted. Moved to CSSParser.
(WebCore::StyleKeyframe::keyText): Build keyframe selector from Vector<double> representation.
* css/CSSKeyframeRule.h:
(WebCore::StyleKeyframe::setKeyText): parse keyframe selector into Vector<double>.
(WebCore::StyleKeyframe::keys): Added. Returns vector representation of selector keys.
(WebCore::StyleKeyframe::getKeys): Deleted. Now keys().
* css/CSSKeyframesRule.cpp:
(WebCore::StyleRuleKeyframes::findKeyframeIndex): Return last matching rule.
* css/CSSParser.cpp:
(WebCore::CSSParser::parseKeyframeSelector): Added. Moved from StyleKeyframe.
* css/CSSParser.h:
(WebCore::CSSParser::parseKeyframeSelector): Added. Moved from StyleKeyframe.

LayoutTests:

Update existing keyframes OM tests to check for findRule/deleteRule matching order i.e. find/delete last specified rule.

* animations/keyframes-rule-expected.txt:
* animations/keyframes-rule.html:
* animations/unprefixed-keyframes-rule-expected.txt:
* animations/unprefixed-keyframes-rule.html:

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

12 files changed:
LayoutTests/ChangeLog
LayoutTests/animations/keyframes-rule-expected.txt
LayoutTests/animations/keyframes-rule.html
LayoutTests/animations/unprefixed-keyframes-rule-expected.txt
LayoutTests/animations/unprefixed-keyframes-rule.html
Source/WebCore/ChangeLog
Source/WebCore/css/CSSKeyframeRule.cpp
Source/WebCore/css/CSSKeyframeRule.h
Source/WebCore/css/CSSKeyframesRule.cpp
Source/WebCore/css/CSSParser.cpp
Source/WebCore/css/CSSParser.h
Source/WebCore/css/StyleResolver.cpp

index 750325b..6e902e2 100644 (file)
@@ -1,3 +1,17 @@
+2015-01-26  Sylvain Galineau  <galineau@adobe.com>
+
+        CSSKeyframesRule::findRule() and deleteRule() should delete the last matching rule, not the first
+        https://bugs.webkit.org/show_bug.cgi?id=139732
+
+        Reviewed by Dean Jackson and Darin Adler.
+
+        Update existing keyframes OM tests to check for findRule/deleteRule matching order i.e. find/delete last specified rule.
+
+        * animations/keyframes-rule-expected.txt:
+        * animations/keyframes-rule.html:
+        * animations/unprefixed-keyframes-rule-expected.txt:
+        * animations/unprefixed-keyframes-rule.html:
+
 2015-01-27  Chris Dumez  <cdumez@apple.com>
 
         Unreviewed, rebaseline fast/css/css2-system-fonts.html on iOS.
index fc949e1..cf00067 100644 (file)
@@ -75,6 +75,41 @@ PASS rules2.item(0).type is window.CSSRule.KEYFRAME_RULE
 PASS rules2.item(0).keyText is '0%'
 PASS rules2.item(1).keyText is '100%'
 
+findRule matching order: from last to first specified
+PASS keyframesFindLast.type is window.CSSRule.KEYFRAMES_RULE
+PASS keyframesFindLast.name is 'test-find-last'
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '10% { left: 10px; }'
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '10% { left: 10px; }'
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+FAIL rule.cssText should be 10%,20%  { left: 10px; }. Was 10%,20% { left: 1020px; }.
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+FAIL rule.cssText should be 10%,20%  { left: 10px; }. Was 10%,20% { left: 1020px; }.
+PASS rule is null
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '0% { left: 0px; }'
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '100% { left: 100px; }'
+
+deleteRule matching order: from last to first specified
+PASS keyframesDeleteLast.type is window.CSSRule.KEYFRAMES_RULE
+PASS keyframesDeleteLast.name is 'test-delete-last'
+PASS rulesDeleteLast.length is 8
+PASS rulesDeleteLast.length is 7
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '10% { left: 10px; }'
+PASS rulesDeleteLast.length is 6
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '10%,20% { left: 1020px; }'
+PASS rulesDeleteLast.length is 6
+PASS rulesDeleteLast.length is 5
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '0% { left: 0px; }'
+PASS rulesDeleteLast.length is 4
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '100% { left: 100px; }'
+
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 9a65e91..6299dbb 100644 (file)
     50% { left: 30px; }
     to { left: 20px; }
   }
+  @-webkit-keyframes test-find-last {
+    from { left: -1px;  }
+    0% { left: 0px; }
+    10% { left: -1px; }
+    10% { left: 10px;}
+    10%, 20% { left: -1px;   }
+    10%,20% { left: 1020px; }
+    100% { left: -1px; }
+    to { left: 100px; }
+  }
+  @-webkit-keyframes test-delete-last {
+    from { left: 0px;  }
+    0% { left: -1px; }
+    10% { left: 10px; }
+    10% { left: -1px;}
+    10%, 20% { left: 1020px;   }
+    10%,20% { left: -1px; }
+    100% { left: 100px; }
+    to { left: -1px; }
+  }
+
 </style>
 <script src="../resources/js-test-pre.js"></script>
 </head>
@@ -168,6 +189,68 @@ shouldBe("rules2.item(0).keyText", "'0%'");
 shouldBe("rules2.item(1).keyText", "'100%'");
 
 debug("");
+debug("findRule matching order: from last to first specified");
+
+var keyframesFindLast = document.styleSheets.item(0).cssRules.item(3);
+shouldBe("keyframesFindLast.type", "window.CSSRule.KEYFRAMES_RULE");
+shouldBe("keyframesFindLast.name", "'test-find-last'");
+
+
+rule = keyframesFindLast.findRule("10%");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'10% { left: 10px; }'");
+rule = keyframesFindLast.findRule("10.0%");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'10% { left: 10px; }'");
+rule = keyframesFindLast.findRule("10%,20%");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'10%,20%  { left: 10px; }'");
+rule = keyframesFindLast.findRule("   10%, 20% ");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'10%,20%  { left: 10px; }'");
+rule = keyframesFindLast.findRule("20%, 10% ");
+shouldBe("rule", "null");
+rule = keyframesFindLast.findRule("from");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'0% { left: 0px; }'");
+rule = keyframesFindLast.findRule("100%");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'100% { left: 100px; }'");
+
+debug("");
+debug("deleteRule matching order: from last to first specified");
+
+var keyframesDeleteLast = document.styleSheets.item(0).cssRules.item(4);
+shouldBe("keyframesDeleteLast.type", "window.CSSRule.KEYFRAMES_RULE");
+shouldBe("keyframesDeleteLast.name", "'test-delete-last'");
+
+var rulesDeleteLast = keyframesDeleteLast.cssRules;
+shouldBe("rulesDeleteLast.length", "8");
+
+keyframesDeleteLast.deleteRule("10%");
+shouldBe("rulesDeleteLast.length", "7");
+rule = keyframesDeleteLast.findRule("10%");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'10% { left: 10px; }'");
+keyframesDeleteLast.deleteRule("10%,20%");
+shouldBe("rulesDeleteLast.length", "6");
+rule = keyframesDeleteLast.findRule("10%,20%");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'10%,20% { left: 1020px; }'");
+keyframesDeleteLast.deleteRule("20%, 10% ");
+shouldBe("rulesDeleteLast.length", "6");
+keyframesDeleteLast.deleteRule("from");
+shouldBe("rulesDeleteLast.length", "5");
+rule = keyframesDeleteLast.findRule("from");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'0% { left: 0px; }'");
+keyframesDeleteLast.deleteRule("100%");
+shouldBe("rulesDeleteLast.length", "4");
+rule = keyframesDeleteLast.findRule("100%");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'100% { left: 100px; }'");
+
+debug("");
 
 </script>
 <script src="../resources/js-test-post.js"></script>
index ca0f548..d88f10f 100644 (file)
@@ -75,6 +75,41 @@ PASS rules2.item(0).type is window.CSSRule.KEYFRAME_RULE
 PASS rules2.item(0).keyText is '0%'
 PASS rules2.item(1).keyText is '100%'
 
+findRule matching order: from last to first specified
+PASS keyframesFindLast.type is window.CSSRule.KEYFRAMES_RULE
+PASS keyframesFindLast.name is 'test-find-last'
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '10% { left: 10px; }'
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '10% { left: 10px; }'
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+FAIL rule.cssText should be 10%,20%  { left: 10px; }. Was 10%,20% { left: 1020px; }.
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+FAIL rule.cssText should be 10%,20%  { left: 10px; }. Was 10%,20% { left: 1020px; }.
+PASS rule is null
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '0% { left: 0px; }'
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '100% { left: 100px; }'
+
+deleteRule matching order: from last to first specified
+PASS keyframesDeleteLast.type is window.CSSRule.KEYFRAMES_RULE
+PASS keyframesDeleteLast.name is 'test-delete-last'
+PASS rulesDeleteLast.length is 8
+PASS rulesDeleteLast.length is 7
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '10% { left: 10px; }'
+PASS rulesDeleteLast.length is 6
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '10%,20% { left: 1020px; }'
+PASS rulesDeleteLast.length is 6
+PASS rulesDeleteLast.length is 5
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '0% { left: 0px; }'
+PASS rulesDeleteLast.length is 4
+PASS rule.type is window.CSSRule.KEYFRAME_RULE
+PASS rule.cssText is '100% { left: 100px; }'
+
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 50a0b67..1686eb8 100644 (file)
     50% { left: 30px; }
     to { left: 20px; }
   }
+  @keyframes test-find-last {
+    from { left: -1px;  }
+    0% { left: 0px; }
+    10% { left: -1px; }
+    10% { left: 10px;}
+    10%, 20% { left: -1px;   }
+    10%,20% { left: 1020px; }
+    100% { left: -1px; }
+    to { left: 100px; }
+  }
+  @keyframes test-delete-last {
+    from { left: 0px;  }
+    0% { left: -1px; }
+    10% { left: 10px; }
+    10% { left: -1px;}
+    10%, 20% { left: 1020px;   }
+    10%,20% { left: -1px; }
+    100% { left: 100px; }
+    to { left: -1px; }
+  }
+
 </style>
 <script src="../resources/js-test-pre.js"></script>
 </head>
@@ -168,6 +189,68 @@ shouldBe("rules2.item(0).keyText", "'0%'");
 shouldBe("rules2.item(1).keyText", "'100%'");
 
 debug("");
+debug("findRule matching order: from last to first specified");
+
+var keyframesFindLast = document.styleSheets.item(0).cssRules.item(3);
+shouldBe("keyframesFindLast.type", "window.CSSRule.KEYFRAMES_RULE");
+shouldBe("keyframesFindLast.name", "'test-find-last'");
+
+
+rule = keyframesFindLast.findRule("10%");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'10% { left: 10px; }'");
+rule = keyframesFindLast.findRule("10.0%");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'10% { left: 10px; }'");
+rule = keyframesFindLast.findRule("10%,20%");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'10%,20%  { left: 10px; }'");
+rule = keyframesFindLast.findRule("   10%, 20% ");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'10%,20%  { left: 10px; }'");
+rule = keyframesFindLast.findRule("20%, 10% ");
+shouldBe("rule", "null");
+rule = keyframesFindLast.findRule("from");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'0% { left: 0px; }'");
+rule = keyframesFindLast.findRule("100%");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'100% { left: 100px; }'");
+
+debug("");
+debug("deleteRule matching order: from last to first specified");
+
+var keyframesDeleteLast = document.styleSheets.item(0).cssRules.item(4);
+shouldBe("keyframesDeleteLast.type", "window.CSSRule.KEYFRAMES_RULE");
+shouldBe("keyframesDeleteLast.name", "'test-delete-last'");
+
+var rulesDeleteLast = keyframesDeleteLast.cssRules;
+shouldBe("rulesDeleteLast.length", "8");
+
+keyframesDeleteLast.deleteRule("10%");
+shouldBe("rulesDeleteLast.length", "7");
+rule = keyframesDeleteLast.findRule("10%");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'10% { left: 10px; }'");
+keyframesDeleteLast.deleteRule("10%,20%");
+shouldBe("rulesDeleteLast.length", "6");
+rule = keyframesDeleteLast.findRule("10%,20%");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'10%,20% { left: 1020px; }'");
+keyframesDeleteLast.deleteRule("20%, 10% ");
+shouldBe("rulesDeleteLast.length", "6");
+keyframesDeleteLast.deleteRule("from");
+shouldBe("rulesDeleteLast.length", "5");
+rule = keyframesDeleteLast.findRule("from");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'0% { left: 0px; }'");
+keyframesDeleteLast.deleteRule("100%");
+shouldBe("rulesDeleteLast.length", "4");
+rule = keyframesDeleteLast.findRule("100%");
+shouldBe("rule.type", "window.CSSRule.KEYFRAME_RULE");
+shouldBe("rule.cssText", "'100% { left: 100px; }'");
+
+debug("");
 
 </script>
 <script src="../resources/js-test-post.js"></script>
index a9b5faa..096ffa4 100644 (file)
@@ -1,3 +1,30 @@
+2015-01-26  Sylvain Galineau  <galineau@adobe.com>
+
+        CSSKeyframesRule::findRule() and deleteRule() should delete the last matching rule, not the first
+        https://bugs.webkit.org/show_bug.cgi?id=139732
+
+        Reviewed by Dean Jackson and Darin Adler.
+
+        No new tests because existing tests have been updated to verify this behavior.
+
+        * css/CSSKeyframeRule.h:
+        (WebCore::StyleKeyframe::getKeys): Deleted.
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::keyframeStylesForAnimation): use StyleKeyframe::keys().
+        * css/CSSKeyframeRule.cpp:
+        (WebCore::StyleKeyframe::parseKeyString): Deleted. Moved to CSSParser.
+        (WebCore::StyleKeyframe::keyText): Build keyframe selector from Vector<double> representation.
+        * css/CSSKeyframeRule.h:
+        (WebCore::StyleKeyframe::setKeyText): parse keyframe selector into Vector<double>.
+        (WebCore::StyleKeyframe::keys): Added. Returns vector representation of selector keys.
+        (WebCore::StyleKeyframe::getKeys): Deleted. Now keys().
+        * css/CSSKeyframesRule.cpp:
+        (WebCore::StyleRuleKeyframes::findKeyframeIndex): Return last matching rule.
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::parseKeyframeSelector): Added. Moved from StyleKeyframe.
+        * css/CSSParser.h:
+        (WebCore::CSSParser::parseKeyframeSelector): Added. Moved from StyleKeyframe.
+
 2015-01-26  Geoffrey Garen  <ggaren@apple.com>
 
         Use FastMalloc (bmalloc) instead of BlockAllocator for GC pages
index 829f084..3c39901 100644 (file)
@@ -49,33 +49,18 @@ MutableStyleProperties& StyleKeyframe::mutableProperties()
     return downcast<MutableStyleProperties>(m_properties.get());
 }
 
-/* static */
-void StyleKeyframe::parseKeyString(const String& s, Vector<double>& keys)
+String StyleKeyframe::keyText() const
 {
-    keys.clear();
-    Vector<String> strings;
-    s.split(',', strings);
+    StringBuilder keyText;
 
-    for (size_t i = 0; i < strings.size(); ++i) {
-        double key = -1;
-        String cur = strings[i].stripWhiteSpace();
-
-        // For now the syntax MUST be 'xxx%' or 'from' or 'to', where xxx is a legal floating point number
-        if (cur == "from")
-            key = 0;
-        else if (cur == "to")
-            key = 1;
-        else if (cur.endsWith('%')) {
-            double k = cur.substring(0, cur.length() - 1).toDouble();
-            if (k >= 0 && k <= 100)
-                key = k / 100;
-        }
-        if (key < 0) {
-            keys.clear();
-            return;
-        }
-        keys.append(key);
+    for (size_t i = 0; i < m_keys.size(); ++i) {
+        if (i)
+            keyText.append(',');
+        keyText.appendNumber(m_keys.at(i) * 100);
+        keyText.append('%');
     }
+
+    return keyText.toString();
 }
 
 String StyleKeyframe::cssText() const
index 4303c0f..2dae409 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef CSSKeyframeRule_h
 #define CSSKeyframeRule_h
 
+#include "CSSParser.h"
 #include "CSSRule.h"
 #include "StyleProperties.h"
 
@@ -44,25 +45,21 @@ public:
     }
     ~StyleKeyframe();
 
-    String keyText() const { return m_key; }
-    void setKeyText(const String& s) { m_key = s; }
+    String keyText() const;
+    void setKeyText(const String& text) { m_keys = CSSParser::parseKeyframeSelector(text); }
+
+    const Vector<double>& keys() const { return m_keys; };
 
-    void getKeys(Vector<double>& keys) const   { parseKeyString(m_key, keys); }
-    
     const StyleProperties& properties() const { return m_properties; }
     MutableStyleProperties& mutableProperties();
-    
+
     String cssText() const;
 
 private:
     explicit StyleKeyframe(Ref<StyleProperties>&&);
-    
-    static void parseKeyString(const String&, Vector<double>& keys);
-    
+
     Ref<StyleProperties> m_properties;
-    // FIXME: This should be a parsed vector of floats.
-    // comma separated list of keys
-    String m_key;
+    Vector<double> m_keys;
 };
 
 class CSSKeyframeRule final : public CSSRule {
@@ -73,7 +70,7 @@ public:
     virtual void reattach(StyleRuleBase&) override;
 
     String keyText() const { return m_keyframe->keyText(); }
-    void setKeyText(const String& s) { m_keyframe->setKeyText(s); }
+    void setKeyText(const String& text) { m_keyframe->setKeyText(text); }
 
     CSSStyleDeclaration& style();
 
index 779ce3b..0952326 100644 (file)
@@ -72,18 +72,13 @@ void StyleRuleKeyframes::wrapperRemoveKeyframe(unsigned index)
 
 int StyleRuleKeyframes::findKeyframeIndex(const String& key) const
 {
-    String percentageString;
-    if (equalIgnoringCase(key, "from"))
-        percentageString = ASCIILiteral("0%");
-    else if (equalIgnoringCase(key, "to"))
-        percentageString = ASCIILiteral("100%");
-    else
-        percentageString = key;
-    
-    for (unsigned i = 0; i < m_keyframes.size(); ++i) {
-        if (m_keyframes[i]->keyText() == percentageString)
+    Vector<double>&& keys = CSSParser::parseKeyframeSelector(key);
+
+    for (size_t i = m_keyframes.size(); i--; ) {
+        if (m_keyframes[i]->keys() == keys)
             return i;
     }
+
     return -1;
 }
 
index 03e9f59..9f67151 100644 (file)
@@ -76,6 +76,8 @@
 #include "RenderTheme.h"
 #include "RuntimeEnabledFeatures.h"
 #include "SVGParserUtilities.h"
+#include "SelectorChecker.h"
+#include "SelectorCheckerTestFunctions.h"
 #include "Settings.h"
 #include "StyleProperties.h"
 #include "StylePropertyShorthand.h"
@@ -4682,6 +4684,36 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationProperty(AnimationParseContext& co
     return nullptr;
 }
 
+/* static */
+Vector<double> CSSParser::parseKeyframeSelector(const String& selector) {
+    Vector<double> keys;
+    Vector<String> strings;
+    selector.split(',', strings);
+
+    for (size_t i = 0; i < strings.size(); ++i) {
+        double key = -1;
+        String cur = strings[i].stripWhiteSpace();
+
+        // For now the syntax MUST be 'xxx%' or 'from' or 'to', where xxx is a legal floating point number
+        if (equalIgnoringASCIICase(cur, "from"))
+            key = 0;
+        else if (equalIgnoringASCIICase(cur, "to"))
+            key = 1;
+        else if (cur.endsWith('%')) {
+            double k = cur.substring(0, cur.length() - 1).toDouble();
+            if (k >= 0 && k <= 100)
+                key = k / 100;
+        }
+        if (key < 0) {
+            keys.clear();
+            break;
+        }
+        keys.append(key);
+    }
+
+    return keys;
+}
+
 bool CSSParser::parseTransformOriginShorthand(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2, RefPtr<CSSValue>& value3)
 {
     parse2ValuesFillPosition(*m_valueList, value1, value2);
index 141bd3c..f9f6f76 100644 (file)
@@ -171,6 +171,7 @@ public:
     PassRefPtr<CSSValue> parseAnimationPlayState();
     PassRefPtr<CSSValue> parseAnimationProperty(AnimationParseContext&);
     PassRefPtr<CSSValue> parseAnimationTimingFunction();
+    static Vector<double> parseKeyframeSelector(const String&);
 
     bool parseTransformOriginShorthand(RefPtr<CSSValue>&, RefPtr<CSSValue>&, RefPtr<CSSValue>&);
     bool parseCubicBezierTimingFunctionValue(CSSParserValueList& args, double& result);
index f86b5be..80d1781 100644 (file)
@@ -890,10 +890,8 @@ void StyleResolver::keyframeStylesForAnimation(Element* e, const RenderStyle* el
         keyframeValue.setStyle(styleForKeyframe(elementStyle, keyframe, keyframeValue));
 
         // Add this keyframe style to all the indicated key times
-        Vector<double> keys;
-        keyframe->getKeys(keys);
-        for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
-            keyframeValue.setKey(keys[keyIndex]);
+        for (auto& key: keyframe->keys()) {
+            keyframeValue.setKey(key);
             list.insert(keyframeValue);
         }
     }