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 183669 3d0a7747bc93ceb476dabe867265c7ef79830fe4
parent 183668 795c41afe2a651f7338470364163b39c022ad4e0
child 183670 ffa1a2961dd12ae0662fc2e7abd2621cbd47283d
push id26799
push userphilringnalda@gmail.com
push dateSun, 18 May 2014 00:55:16 +0000
treeherdermozilla-central@00ef3a7d7aa7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1008719
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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" },