Bug 1008719. CSS syntax got changed to allow identifiers starting with "--", so update our escaping code accordingly. r=dholbert
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 15 May 2014 10:26:53 -0700
changeset 183678 3d0a7747bc93ceb476dabe867265c7ef79830fe4
parent 183677 795c41afe2a651f7338470364163b39c022ad4e0
child 183679 ffa1a2961dd12ae0662fc2e7abd2621cbd47283d
push id6844
push userphilringnalda@gmail.com
push dateSun, 18 May 2014 01:12:08 +0000
treeherderfx-team@41a54c8add09 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1008719
milestone32.0a1
Bug 1008719. CSS syntax got changed to allow identifiers starting with "--", so update our escaping code accordingly. r=dholbert
layout/style/nsStyleUtil.cpp
layout/style/test/test_css_escape_api.html
layout/style/test/test_parser_diagnostics_unprintables.html
--- a/layout/style/nsStyleUtil.cpp
+++ b/layout/style/nsStyleUtil.cpp
@@ -76,50 +76,51 @@ void nsStyleUtil::AppendEscapedCSSString
 
   aReturn.Append(quoteChar);
 }
 
 /* static */ bool
 nsStyleUtil::AppendEscapedCSSIdent(const nsAString& aIdent, nsAString& aReturn)
 {
   // The relevant parts of the CSS grammar are:
-  //   ident    [-]?{nmstart}{nmchar}*
+  //   ident    ([-]?{nmstart}|[-][-]){nmchar}*
   //   nmstart  [_a-z]|{nonascii}|{escape}
   //   nmchar   [_a-z0-9-]|{nonascii}|{escape}
   //   nonascii [^\0-\177]
   //   escape   {unicode}|\\[^\n\r\f0-9a-f]
   //   unicode  \\[0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?
-  // from http://www.w3.org/TR/CSS21/syndata.html#tokenization
+  // from http://www.w3.org/TR/CSS21/syndata.html#tokenization but
+  // modified for idents by
+  // http://dev.w3.org/csswg/cssom/#serialize-an-identifier and
+  // http://dev.w3.org/csswg/css-syntax/#would-start-an-identifier
 
   const char16_t* in = aIdent.BeginReading();
   const char16_t* const end = aIdent.EndReading();
 
   if (in == end)
     return true;
 
   // A leading dash does not need to be escaped as long as it is not the
   // *only* character in the identifier.
-  if (in + 1 != end && *in == '-') {
+  if (*in == '-') {
+    if (in + 1 == end) {
+      aReturn.Append(char16_t('\\'));
+      aReturn.Append(char16_t('-'));
+      return true;
+    }
+
     aReturn.Append(char16_t('-'));
     ++in;
   }
 
   // Escape a digit at the start (including after a dash),
   // numerically.  If we didn't escape it numerically, it would get
   // interpreted as a numeric escape for the wrong character.
-  // A second dash immediately after a leading dash must also be
-  // escaped, but this may be done symbolically.
-  if (in != end && (*in == '-' ||
-                    ('0' <= *in && *in <= '9'))) {
-    if (*in == '-') {
-      aReturn.Append(char16_t('\\'));
-      aReturn.Append(char16_t('-'));
-    } else {
-      aReturn.AppendPrintf("\\%hX ", *in);
-    }
+  if (in != end && ('0' <= *in && *in <= '9')) {
+    aReturn.AppendPrintf("\\%hX ", *in);
     ++in;
   }
 
   for (; in != end; ++in) {
     char16_t ch = *in;
     if (ch == 0x00) {
       return false;
     }
--- a/layout/style/test/test_css_escape_api.html
+++ b/layout/style/test/test_css_escape_api.html
@@ -61,17 +61,17 @@ is(CSS.escape('-2a'), '-\\32 a', "escapi
 is(CSS.escape('-3a'), '-\\33 a', "escapingFailed Char: -3a");
 is(CSS.escape('-4a'), '-\\34 a', "escapingFailed Char: -4a");
 is(CSS.escape('-5a'), '-\\35 a', "escapingFailed Char: -5a");
 is(CSS.escape('-6a'), '-\\36 a', "escapingFailed Char: -6a");
 is(CSS.escape('-7a'), '-\\37 a', "escapingFailed Char: -7a");
 is(CSS.escape('-8a'), '-\\38 a', "escapingFailed Char: -8a");
 is(CSS.escape('-9a'), '-\\39 a', "escapingFailed Char: -9a");
 
-is(CSS.escape('--a'), '-\\-a', "escapingFailed Char: --a");
+is(CSS.escape('--a'), '--a', 'Should not need to escape leading "--"');
 
 is(CSS.escape('\x80\x2D\x5F\xA9'), '\\80 \x2D\x5F\xA9', "escapingFailed Char: \\x80\\x2D\\x5F\\xA9");
 is(CSS.escape('\xA0\xA1\xA2'), '\xA0\xA1\xA2', "escapingFailed Char: \\xA0\\xA1\\xA2");
 is(CSS.escape('a0123456789b'), 'a0123456789b', "escapingFailed Char: a0123465789");
 is(CSS.escape('abcdefghijklmnopqrstuvwxyz'), 'abcdefghijklmnopqrstuvwxyz', "escapingFailed Char: abcdefghijklmnopqrstuvwxyz");
 is(CSS.escape('ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', "escapingFailed Char: ABCDEFGHIJKLMNOPQRSTUVWXYZBCDEFGHIJKLMNOPQRSTUVWXYZ");
 
 is(CSS.escape('\x20\x21\x78\x79'), '\\ \\!xy', "escapingFailed Char: \\x20\\x21\\x78\\x79");
--- a/layout/style/test/test_parser_diagnostics_unprintables.html
+++ b/layout/style/test/test_parser_diagnostics_unprintables.html
@@ -69,17 +69,17 @@ const substitutions = [
   { t: "\\32 ",  i: "\\32 ",  s: "2"  },
   { t: "\\33 ",  i: "\\33 ",  s: "3"  },
   { t: "\\34 ",  i: "\\34 ",  s: "4"  },
   { t: "\\35 ",  i: "\\35 ",  s: "5"  },
   { t: "\\36 ",  i: "\\36 ",  s: "6"  },
   { t: "\\37 ",  i: "\\37 ",  s: "7"  },
   { t: "\\38 ",  i: "\\38 ",  s: "8"  },
   { t: "\\39 ",  i: "\\39 ",  s: "9"  },
-  { t: "-\\-",   i: "-\\-",   s: "--" },
+  { t: "-\\-",   i: "--",     s: "--" },
   { t: "-\\30 ", i: "-\\30 ", s: "-0" },
   { t: "-\\31 ", i: "-\\31 ", s: "-1" },
   { t: "-\\32 ", i: "-\\32 ", s: "-2" },
   { t: "-\\33 ", i: "-\\33 ", s: "-3" },
   { t: "-\\34 ", i: "-\\34 ", s: "-4" },
   { t: "-\\35 ", i: "-\\35 ", s: "-5" },
   { t: "-\\36 ", i: "-\\36 ", s: "-6" },
   { t: "-\\37 ", i: "-\\37 ", s: "-7" },