Title: [204952] trunk
Revision
204952
Author
[email protected]
Date
2016-08-24 19:40:55 -0700 (Wed, 24 Aug 2016)

Log Message

Implement `CSS.escape` as per CSSOM
https://bugs.webkit.org/show_bug.cgi?id=126337

Patch by Joseph Pecoraro <[email protected]> on 2016-08-24
Reviewed by Dean Jackson.

Source/WebCore:

Test: css3/escape-dom-api.html

* css/CSSOMUtils.cpp:
(WebCore::serializeIdentifier):
Update serialization to match the latest version of the spec:
<https://drafts.csswg.org/cssom/#serialize-an-identifier>
New handling for 0x0, 0x7f, just "-", and "--" is now allowed.

* css/DOMCSSNamespace.cpp:
(WebCore::DOMCSSNamespace::escape):
* css/DOMCSSNamespace.h:
* css/DOMCSSNamespace.idl:
New CSS.escape method.

LayoutTests:

CSS.escape is part of the CSSOM Spec:
https://drafts.csswg.org/cssom/#the-css.escape%28%29-method

Tests:
https://github.com/mathiasbynens/CSS.escape/blob/master/tests/tests.js

Change is based on the Blink change (patch by <[email protected]>) and follow-ups:
<https://chromium.googlesource.com/chromium/blink/+/c1a5ffdc924b089e70cd33ad2726b58cc8312abe>

* css3/escape-dom-api-expected.txt: Added.
* css3/escape-dom-api.html: Added.
New tests, taken from the polyfill.

* fast/css/parsing-css-nonascii-expected.txt:
* fast/css/parsing-css-nonascii.html:
* fast/css/selector-text-escape.html:
Update existing tests now that 0x7f is escaped.

* js/dom/function-removed-after-parsing-expected.txt:
* js/dom/function-removed-after-parsing.html:
Rename use of `CSS.escape` here now that `CSS.escape` exists.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (204951 => 204952)


--- trunk/LayoutTests/ChangeLog	2016-08-25 01:55:04 UTC (rev 204951)
+++ trunk/LayoutTests/ChangeLog	2016-08-25 02:40:55 UTC (rev 204952)
@@ -1,3 +1,32 @@
+2016-08-24  Joseph Pecoraro  <[email protected]>
+
+        Implement `CSS.escape` as per CSSOM
+        https://bugs.webkit.org/show_bug.cgi?id=126337
+
+        Reviewed by Dean Jackson.
+
+        CSS.escape is part of the CSSOM Spec:
+        https://drafts.csswg.org/cssom/#the-css.escape%28%29-method
+
+        Tests:
+        https://github.com/mathiasbynens/CSS.escape/blob/master/tests/tests.js
+
+        Change is based on the Blink change (patch by <[email protected]>) and follow-ups:
+        <https://chromium.googlesource.com/chromium/blink/+/c1a5ffdc924b089e70cd33ad2726b58cc8312abe>
+
+        * css3/escape-dom-api-expected.txt: Added.
+        * css3/escape-dom-api.html: Added.
+        New tests, taken from the polyfill.
+
+        * fast/css/parsing-css-nonascii-expected.txt:
+        * fast/css/parsing-css-nonascii.html:
+        * fast/css/selector-text-escape.html:
+        Update existing tests now that 0x7f is escaped.
+
+        * js/dom/function-removed-after-parsing-expected.txt:
+        * js/dom/function-removed-after-parsing.html:
+        Rename use of `CSS.escape` here now that `CSS.escape` exists.
+
 2016-08-24  Zalan Bujtas  <[email protected]>
 
         ASSERTION FAILED: contentSize >= 0 in WebCore::RenderFlexibleBox::adjustChildSizeForMinAndMax

Added: trunk/LayoutTests/css3/escape-dom-api-expected.txt (0 => 204952)


--- trunk/LayoutTests/css3/escape-dom-api-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/css3/escape-dom-api-expected.txt	2016-08-25 02:40:55 UTC (rev 204952)
@@ -0,0 +1,69 @@
+Test window.CSS.escape()
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS CSS.escape.length is 1
+PASS CSS.escape('\0') is "�"
+PASS CSS.escape('a\0') is "a�"
+PASS CSS.escape('\0b') is "�b"
+PASS CSS.escape('a\0b') is "a�b"
+PASS CSS.escape('�') is "�"
+PASS CSS.escape('a�') is "a�"
+PASS CSS.escape('�b') is "�b"
+PASS CSS.escape('a�b') is "a�b"
+PASS CSS.escape() threw exception TypeError: Not enough arguments.
+PASS CSS.escape(undefined) is "undefined"
+PASS CSS.escape(true) is "true"
+PASS CSS.escape(false) is "false"
+PASS CSS.escape(null) is "null"
+PASS CSS.escape('') is ""
+PASS CSS.escape('') is "\\1 \\2 \\1e \\1f "
+PASS CSS.escape('0a') is "\\30 a"
+PASS CSS.escape('1a') is "\\31 a"
+PASS CSS.escape('2a') is "\\32 a"
+PASS CSS.escape('3a') is "\\33 a"
+PASS CSS.escape('4a') is "\\34 a"
+PASS CSS.escape('5a') is "\\35 a"
+PASS CSS.escape('6a') is "\\36 a"
+PASS CSS.escape('7a') is "\\37 a"
+PASS CSS.escape('8a') is "\\38 a"
+PASS CSS.escape('9a') is "\\39 a"
+PASS CSS.escape('a0b') is "a0b"
+PASS CSS.escape('a1b') is "a1b"
+PASS CSS.escape('a2b') is "a2b"
+PASS CSS.escape('a3b') is "a3b"
+PASS CSS.escape('a4b') is "a4b"
+PASS CSS.escape('a5b') is "a5b"
+PASS CSS.escape('a6b') is "a6b"
+PASS CSS.escape('a7b') is "a7b"
+PASS CSS.escape('a8b') is "a8b"
+PASS CSS.escape('a9b') is "a9b"
+PASS CSS.escape('-0a') is "-\\30 a"
+PASS CSS.escape('-1a') is "-\\31 a"
+PASS CSS.escape('-2a') is "-\\32 a"
+PASS CSS.escape('-3a') is "-\\33 a"
+PASS CSS.escape('-4a') is "-\\34 a"
+PASS CSS.escape('-5a') is "-\\35 a"
+PASS CSS.escape('-6a') is "-\\36 a"
+PASS CSS.escape('-7a') is "-\\37 a"
+PASS CSS.escape('-8a') is "-\\38 a"
+PASS CSS.escape('-9a') is "-\\39 a"
+PASS CSS.escape('-') is "\\-"
+PASS CSS.escape('-a') is "-a"
+PASS CSS.escape('--') is "--"
+PASS CSS.escape('--a') is "--a"
+PASS CSS.escape('€-_©') is "€-_©"
+PASS CSS.escape('€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ') is "\\7f €‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ"
+PASS CSS.escape(' ¡¢') is " ¡¢"
+PASS CSS.escape('a0123456789b') is "a0123456789b"
+PASS CSS.escape('abcdefghijklmnopqrstuvwxyz') is "abcdefghijklmnopqrstuvwxyz"
+PASS CSS.escape('ABCDEFGHIJKLMNOPQRSTUVWXYZ') is "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+PASS CSS.escape(' !xy') is "\\ \\!xy"
+PASS CSS.escape('𝌆') is "𝌆"
+PASS CSS.escape('í¼†') is "í¼†"
+PASS CSS.escape('í ´') is "í ´"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/css3/escape-dom-api.html (0 => 204952)


--- trunk/LayoutTests/css3/escape-dom-api.html	                        (rev 0)
+++ trunk/LayoutTests/css3/escape-dom-api.html	2016-08-25 02:40:55 UTC (rev 204952)
@@ -0,0 +1,86 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script>
+    // Test from https://github.com/mathiasbynens/CSS.escape
+    description("Test window.CSS.escape()");
+
+    shouldBe("CSS.escape.length", "1");
+
+    shouldBeEqualToString("CSS.escape('\0')", "\ufffd");
+    shouldBeEqualToString("CSS.escape('a\0')", "a\ufffd");
+    shouldBeEqualToString("CSS.escape('\0b')", "\ufffdb");
+    shouldBeEqualToString("CSS.escape('a\0b')", "a\ufffdb");
+
+    shouldBeEqualToString("CSS.escape('\ufffd')", "\ufffd");
+    shouldBeEqualToString("CSS.escape('a\ufffd')", "a\ufffd");
+    shouldBeEqualToString("CSS.escape('\ufffdb')", "\ufffdb");
+    shouldBeEqualToString("CSS.escape('a\ufffdb')", "a\ufffdb");
+
+    shouldThrow("CSS.escape()");
+    shouldBeEqualToString("CSS.escape(undefined)", "undefined");
+    shouldBeEqualToString("CSS.escape(true)", "true");
+    shouldBeEqualToString("CSS.escape(false)", "false");
+    shouldBeEqualToString("CSS.escape(null)", "null");
+    shouldBeEqualToString("CSS.escape('')", "");
+
+    shouldBeEqualToString("CSS.escape('\x01\x02\x1E\x1F')", "\\1 \\2 \\1e \\1f ");
+
+    shouldBeEqualToString("CSS.escape('0a')", "\\30 a");
+    shouldBeEqualToString("CSS.escape('1a')", "\\31 a");
+    shouldBeEqualToString("CSS.escape('2a')", "\\32 a");
+    shouldBeEqualToString("CSS.escape('3a')", "\\33 a");
+    shouldBeEqualToString("CSS.escape('4a')", "\\34 a");
+    shouldBeEqualToString("CSS.escape('5a')", "\\35 a");
+    shouldBeEqualToString("CSS.escape('6a')", "\\36 a");
+    shouldBeEqualToString("CSS.escape('7a')", "\\37 a");
+    shouldBeEqualToString("CSS.escape('8a')", "\\38 a");
+    shouldBeEqualToString("CSS.escape('9a')", "\\39 a");
+
+    shouldBeEqualToString("CSS.escape('a0b')", "a0b");
+    shouldBeEqualToString("CSS.escape('a1b')", "a1b");
+    shouldBeEqualToString("CSS.escape('a2b')", "a2b");
+    shouldBeEqualToString("CSS.escape('a3b')", "a3b");
+    shouldBeEqualToString("CSS.escape('a4b')", "a4b");
+    shouldBeEqualToString("CSS.escape('a5b')", "a5b");
+    shouldBeEqualToString("CSS.escape('a6b')", "a6b");
+    shouldBeEqualToString("CSS.escape('a7b')", "a7b");
+    shouldBeEqualToString("CSS.escape('a8b')", "a8b");
+    shouldBeEqualToString("CSS.escape('a9b')", "a9b");
+
+    shouldBeEqualToString("CSS.escape('-0a')", "-\\30 a");
+    shouldBeEqualToString("CSS.escape('-1a')", "-\\31 a");
+    shouldBeEqualToString("CSS.escape('-2a')", "-\\32 a");
+    shouldBeEqualToString("CSS.escape('-3a')", "-\\33 a");
+    shouldBeEqualToString("CSS.escape('-4a')", "-\\34 a");
+    shouldBeEqualToString("CSS.escape('-5a')", "-\\35 a");
+    shouldBeEqualToString("CSS.escape('-6a')", "-\\36 a");
+    shouldBeEqualToString("CSS.escape('-7a')", "-\\37 a");
+    shouldBeEqualToString("CSS.escape('-8a')", "-\\38 a");
+    shouldBeEqualToString("CSS.escape('-9a')", "-\\39 a");
+
+    shouldBeEqualToString("CSS.escape('-')", "\\-");
+    shouldBeEqualToString("CSS.escape('-a')", "-a");
+    shouldBeEqualToString("CSS.escape('--')", "--");
+    shouldBeEqualToString("CSS.escape('--a')", "--a");
+
+    shouldBeEqualToString("CSS.escape('\x80\x2D\x5F\xA9')", "\x80\x2D\x5F\xA9");
+    shouldBeEqualToString("CSS.escape('\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F')", "\\7f \x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F");
+    shouldBeEqualToString("CSS.escape('\xA0\xA1\xA2')", "\xA0\xA1\xA2");
+    shouldBeEqualToString("CSS.escape('a0123456789b')", "a0123456789b");
+    shouldBeEqualToString("CSS.escape('abcdefghijklmnopqrstuvwxyz')", "abcdefghijklmnopqrstuvwxyz");
+    shouldBeEqualToString("CSS.escape('ABCDEFGHIJKLMNOPQRSTUVWXYZ')", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+
+    shouldBeEqualToString("CSS.escape('\x20\x21\x78\x79')", "\\ \\!xy");
+
+    // astral symbol (U+1D306 TETRAGRAM FOR CENTRE)
+    shouldBeEqualToString("CSS.escape('\uD834\uDF06')", "\uD834\uDF06");
+    // lone surrogates
+    shouldBeEqualToString("CSS.escape('\uDF06')", '\uDF06');
+    shouldBeEqualToString("CSS.escape('\uD834')", '\uD834');
+</script>
+</body>
+</html>

Modified: trunk/LayoutTests/fast/css/parsing-css-nonascii-expected.txt (204951 => 204952)


--- trunk/LayoutTests/fast/css/parsing-css-nonascii-expected.txt	2016-08-25 01:55:04 UTC (rev 204951)
+++ trunk/LayoutTests/fast/css/parsing-css-nonascii-expected.txt	2016-08-25 02:40:55 UTC (rev 204952)
@@ -4,7 +4,7 @@
 
 Rules from the stylesheet:
 
-#a127_\ { color: red; }
+#a127_\7f  { color: red; }
 #a128_€ { color: red; }
 #b128_€ { color: green; }
 #a159_Ÿ { color: red; }
@@ -15,7 +15,7 @@
 #b384_ƀ { color: green; }
 Expected result:
 
-#a127_\ { color: red; }
+#a127_\7f  { color: red; }
 #a128_€ { color: red; }
 #b128_€ { color: green; }
 #a159_Ÿ { color: red; }

Modified: trunk/LayoutTests/fast/css/parsing-css-nonascii.html (204951 => 204952)


--- trunk/LayoutTests/fast/css/parsing-css-nonascii.html	2016-08-25 01:55:04 UTC (rev 204951)
+++ trunk/LayoutTests/fast/css/parsing-css-nonascii.html	2016-08-25 02:40:55 UTC (rev 204952)
@@ -5,7 +5,7 @@
 /*
   === Warning ===
 
-  This file intentionally contains scpecial characters which
+  This file intentionally contains special characters which
   cannot be displayed by some text editors. Please
   carefully edit the file.
 */
@@ -64,7 +64,7 @@
 
 <p>Expected result:</p>
 
-<pre id="expected">#a127_\ { color: red; }
+<pre id="expected">#a127_\7f  { color: red; }
 #a128_€ { color: red; }
 #b128_€ { color: green; }
 #a159_Ÿ { color: red; }

Modified: trunk/LayoutTests/fast/css/selector-text-escape.html (204951 => 204952)


--- trunk/LayoutTests/fast/css/selector-text-escape.html	2016-08-25 01:55:04 UTC (rev 204951)
+++ trunk/LayoutTests/fast/css/selector-text-escape.html	2016-08-25 02:40:55 UTC (rev 204952)
@@ -93,7 +93,7 @@
     ".\\39 _class",
     ".-\\30 _class",
     ".-\\39 _class",
-    ".-\\-_class",
+    ".--_class",
     ".\x81_class",
     ".日本語_class",
     ".𐐀_class",

Modified: trunk/LayoutTests/js/dom/function-removed-after-parsing-expected.txt (204951 => 204952)


--- trunk/LayoutTests/js/dom/function-removed-after-parsing-expected.txt	2016-08-25 01:55:04 UTC (rev 204951)
+++ trunk/LayoutTests/js/dom/function-removed-after-parsing-expected.txt	2016-08-25 02:40:55 UTC (rev 204952)
@@ -1,2 +1,2 @@
-window.CSS.escape still here
+window.CSS.layoutTestEscape still here
 

Modified: trunk/LayoutTests/js/dom/function-removed-after-parsing.html (204951 => 204952)


--- trunk/LayoutTests/js/dom/function-removed-after-parsing.html	2016-08-25 01:55:04 UTC (rev 204951)
+++ trunk/LayoutTests/js/dom/function-removed-after-parsing.html	2016-08-25 02:40:55 UTC (rev 204952)
@@ -2,6 +2,9 @@
 <!--
 NOTE: This intentionally does not use description() and does not include js-test-post because
 doing either of those things made the bug go away.
+
+NOTE: This intentionally does not use the name `CSS.escape` because that function exists now but
+did not when this test was added. The name was changed to `CSS.layoutTestEscape` for this test.
 -->
   <script src=""
   <script type='text/_javascript_'>
@@ -20,9 +23,9 @@
 	InvalidCharacterError.prototype = new Error;
 	InvalidCharacterError.prototype.name = 'InvalidCharacterError';
 
-	if (!CSS.escape) {
+	if (!CSS.layoutTestEscape) {
 		// https://drafts.csswg.org/cssom/#serialize-an-identifier
-		CSS.escape = function(value) {
+		CSS.layoutTestEscape = function(value) {
 			var string = String(value);
 			var length = string.length;
 			var index = -1;
@@ -107,14 +110,14 @@
       testRunner.dumpAsText(window.enablePixelTesting);
       testRunner.waitUntilDone();
     } catch (e) { }
-    if (!window.CSS.escape) {
-      debug('window.CSS.escape not loaded');
+    if (!window.CSS.layoutTestEscape) {
+      debug('window.CSS.layoutTestEscape not loaded');
     }
     setTimeout(function() {
-      if (window.CSS.escape)
-        debug("window.CSS.escape still here");
+      if (window.CSS.layoutTestEscape)
+        debug("window.CSS.layoutTestEscape still here");
       else
-        debug('window.CSS.escape missing in event');
+        debug('window.CSS.layoutTestEscape missing in event');
       try {
         testRunner.notifyDone();
       } catch (e) { }

Modified: trunk/Source/WebCore/ChangeLog (204951 => 204952)


--- trunk/Source/WebCore/ChangeLog	2016-08-25 01:55:04 UTC (rev 204951)
+++ trunk/Source/WebCore/ChangeLog	2016-08-25 02:40:55 UTC (rev 204952)
@@ -1,3 +1,24 @@
+2016-08-24  Joseph Pecoraro  <[email protected]>
+
+        Implement `CSS.escape` as per CSSOM
+        https://bugs.webkit.org/show_bug.cgi?id=126337
+
+        Reviewed by Dean Jackson.
+
+        Test: css3/escape-dom-api.html
+
+        * css/CSSOMUtils.cpp:
+        (WebCore::serializeIdentifier):
+        Update serialization to match the latest version of the spec:
+        <https://drafts.csswg.org/cssom/#serialize-an-identifier>
+        New handling for 0x0, 0x7f, just "-", and "--" is now allowed.
+
+        * css/DOMCSSNamespace.cpp:
+        (WebCore::DOMCSSNamespace::escape):
+        * css/DOMCSSNamespace.h:
+        * css/DOMCSSNamespace.idl:
+        New CSS.escape method.
+
 2016-08-24  Zalan Bujtas  <[email protected]>
 
         ASSERTION FAILED: contentSize >= 0 in WebCore::RenderFlexibleBox::adjustChildSizeForMinAndMax

Modified: trunk/Source/WebCore/css/CSSOMUtils.cpp (204951 => 204952)


--- trunk/Source/WebCore/css/CSSOMUtils.cpp	2016-08-25 01:55:04 UTC (rev 204951)
+++ trunk/Source/WebCore/css/CSSOMUtils.cpp	2016-08-25 02:40:55 UTC (rev 204952)
@@ -57,11 +57,18 @@
     unsigned index = 0;
     while (index < identifier.length()) {
         UChar32 c = identifier.characterStartingAt(index);
+        if (!c) {
+            // Check for lone surrogate which characterStartingAt does not return.
+            c = identifier[index];
+        }
+
         index += U16_LENGTH(c);
 
-        if (c <= 0x1f || (0x30 <= c && c <= 0x39 && (isFirst || (isSecond && isFirstCharHyphen))))
+        if (!c)
+            appendTo.append(0xfffd);
+        else if (c <= 0x1f || c == 0x7f || (0x30 <= c && c <= 0x39 && (isFirst || (isSecond && isFirstCharHyphen))))
             serializeCharacterAsCodePoint(c, appendTo);
-        else if (c == 0x2d && isSecond && isFirstCharHyphen)
+        else if (c == 0x2d && isFirst && index == identifier.length())
             serializeCharacter(c, appendTo);
         else if (0x80 <= c || c == 0x2d || c == 0x5f || (0x30 <= c && c <= 0x39) || (0x41 <= c && c <= 0x5a) || (0x61 <= c && c <= 0x7a))
             appendTo.append(c);
@@ -72,9 +79,8 @@
             isFirst = false;
             isSecond = true;
             isFirstCharHyphen = (c == 0x2d);
-        } else if (isSecond) {
+        } else if (isSecond)
             isSecond = false;
-        }
     }
 }
 

Modified: trunk/Source/WebCore/css/DOMCSSNamespace.cpp (204951 => 204952)


--- trunk/Source/WebCore/css/DOMCSSNamespace.cpp	2016-08-25 01:55:04 UTC (rev 204951)
+++ trunk/Source/WebCore/css/DOMCSSNamespace.cpp	2016-08-25 02:40:55 UTC (rev 204952)
@@ -30,8 +30,10 @@
 #include "config.h"
 #include "DOMCSSNamespace.h"
 
+#include "CSSOMUtils.h"
 #include "CSSParser.h"
 #include "StyleProperties.h"
+#include <wtf/text/StringBuilder.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
@@ -77,4 +79,11 @@
     return parser.parseSupportsCondition(conditionText);
 }
 
+String DOMCSSNamespace::escape(const String& ident)
+{
+    StringBuilder builder;
+    serializeIdentifier(ident, builder);
+    return builder.toString();
 }
+
+}

Modified: trunk/Source/WebCore/css/DOMCSSNamespace.h (204951 => 204952)


--- trunk/Source/WebCore/css/DOMCSSNamespace.h	2016-08-25 01:55:04 UTC (rev 204951)
+++ trunk/Source/WebCore/css/DOMCSSNamespace.h	2016-08-25 02:40:55 UTC (rev 204952)
@@ -38,6 +38,7 @@
 public:
     static bool supports(const String& property, const String& value);
     static bool supports(const String& conditionText);
+    static String escape(const String& ident);
 };
 
 }

Modified: trunk/Source/WebCore/css/DOMCSSNamespace.idl (204951 => 204952)


--- trunk/Source/WebCore/css/DOMCSSNamespace.idl	2016-08-25 01:55:04 UTC (rev 204951)
+++ trunk/Source/WebCore/css/DOMCSSNamespace.idl	2016-08-25 02:40:55 UTC (rev 204952)
@@ -33,4 +33,5 @@
 ] interface DOMCSSNamespace {
     static boolean supports(DOMString property, DOMString value);
     static boolean supports(DOMString conditionText);
+    static DOMString escape(DOMString ident);
 };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to