Skip to content

Commit 2f48ad9

Browse files
author
Maciej Skrzypkowski
committed
New characters escaped in serialize_name
Added escape of NULL (U+0000) char and escape for characters in the range [\1-\1f] (U+0001 to U+001F) or U+007F according to https://drafts.csswg.org/cssom/#serialize-an-identifier Needed for proper CSS tests servo/servo#10685
1 parent 1950c75 commit 2f48ad9

File tree

2 files changed

+75
-3
lines changed

2 files changed

+75
-3
lines changed

src/serializer.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,14 +196,14 @@ fn serialize_name<W>(value: &str, dest: &mut W) -> fmt::Result where W:fmt::Writ
196196
let escaped = match b {
197197
b'0'...b'9' | b'A'...b'Z' | b'a'...b'z' | b'_' | b'-' => continue,
198198
_ if !b.is_ascii() => continue,
199-
b'\n' => Some("\\A "),
200-
b'\r' => Some("\\D "),
201-
b'\x0C' => Some("\\C "),
199+
b'\0' => Some("\u{FFFD}"),
202200
_ => None,
203201
};
204202
try!(dest.write_str(&value[chunk_start..i]));
205203
if let Some(escaped) = escaped {
206204
try!(dest.write_str(escaped));
205+
} else if (b >= b'\x01' && b <= b'\x1F') || b == b'\x7F' {
206+
try!(write!(dest, "\\{:x} ", b));
207207
} else {
208208
try!(write!(dest, "\\{}", b as char));
209209
}

src/tests.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,78 @@ fn line_delimited() {
493493
assert_eq!(input.next(), Err(()));
494494
}
495495

496+
#[test]
497+
fn identifier_serialization() {
498+
// Null bytes
499+
assert_eq!(Token::Ident("\0".into()).to_css_string(), "\u{FFFD}");
500+
assert_eq!(Token::Ident("a\0".into()).to_css_string(), "a\u{FFFD}");
501+
assert_eq!(Token::Ident("\0b".into()).to_css_string(), "\u{FFFD}b");
502+
assert_eq!(Token::Ident("a\0b".into()).to_css_string(), "a\u{FFFD}b");
503+
504+
// Replacement character
505+
assert_eq!(Token::Ident("\u{FFFD}".into()).to_css_string(), "\u{FFFD}");
506+
assert_eq!(Token::Ident("a\u{FFFD}".into()).to_css_string(), "a\u{FFFD}");
507+
assert_eq!(Token::Ident("\u{FFFD}b".into()).to_css_string(), "\u{FFFD}b");
508+
assert_eq!(Token::Ident("a\u{FFFD}b".into()).to_css_string(), "a\u{FFFD}b");
509+
510+
// Number prefix
511+
assert_eq!(Token::Ident("0a".into()).to_css_string(), "\\30 a");
512+
assert_eq!(Token::Ident("1a".into()).to_css_string(), "\\31 a");
513+
assert_eq!(Token::Ident("2a".into()).to_css_string(), "\\32 a");
514+
assert_eq!(Token::Ident("3a".into()).to_css_string(), "\\33 a");
515+
assert_eq!(Token::Ident("4a".into()).to_css_string(), "\\34 a");
516+
assert_eq!(Token::Ident("5a".into()).to_css_string(), "\\35 a");
517+
assert_eq!(Token::Ident("6a".into()).to_css_string(), "\\36 a");
518+
assert_eq!(Token::Ident("7a".into()).to_css_string(), "\\37 a");
519+
assert_eq!(Token::Ident("8a".into()).to_css_string(), "\\38 a");
520+
assert_eq!(Token::Ident("9a".into()).to_css_string(), "\\39 a");
521+
522+
// Letter number prefix
523+
assert_eq!(Token::Ident("a0b".into()).to_css_string(), "a0b");
524+
assert_eq!(Token::Ident("a1b".into()).to_css_string(), "a1b");
525+
assert_eq!(Token::Ident("a2b".into()).to_css_string(), "a2b");
526+
assert_eq!(Token::Ident("a3b".into()).to_css_string(), "a3b");
527+
assert_eq!(Token::Ident("a4b".into()).to_css_string(), "a4b");
528+
assert_eq!(Token::Ident("a5b".into()).to_css_string(), "a5b");
529+
assert_eq!(Token::Ident("a6b".into()).to_css_string(), "a6b");
530+
assert_eq!(Token::Ident("a7b".into()).to_css_string(), "a7b");
531+
assert_eq!(Token::Ident("a8b".into()).to_css_string(), "a8b");
532+
assert_eq!(Token::Ident("a9b".into()).to_css_string(), "a9b");
533+
534+
// Dash number prefix
535+
assert_eq!(Token::Ident("-0a".into()).to_css_string(), "-\\30 a");
536+
assert_eq!(Token::Ident("-1a".into()).to_css_string(), "-\\31 a");
537+
assert_eq!(Token::Ident("-2a".into()).to_css_string(), "-\\32 a");
538+
assert_eq!(Token::Ident("-3a".into()).to_css_string(), "-\\33 a");
539+
assert_eq!(Token::Ident("-4a".into()).to_css_string(), "-\\34 a");
540+
assert_eq!(Token::Ident("-5a".into()).to_css_string(), "-\\35 a");
541+
assert_eq!(Token::Ident("-6a".into()).to_css_string(), "-\\36 a");
542+
assert_eq!(Token::Ident("-7a".into()).to_css_string(), "-\\37 a");
543+
assert_eq!(Token::Ident("-8a".into()).to_css_string(), "-\\38 a");
544+
assert_eq!(Token::Ident("-9a".into()).to_css_string(), "-\\39 a");
545+
546+
// Double dash prefix
547+
assert_eq!(Token::Ident("--a".into()).to_css_string(), "--a");
548+
549+
// Various tests
550+
assert_eq!(Token::Ident("\x01\x02\x1E\x1F".into()).to_css_string(), "\\1 \\2 \\1e \\1f ");
551+
assert_eq!(Token::Ident("\u{0080}\x2D\x5F\u{00A9}".into()).to_css_string(), "\u{0080}\x2D\x5F\u{00A9}");
552+
assert_eq!(Token::Ident("\x7F\u{0080}\u{0081}\u{0082}\u{0083}\u{0084}\u{0085}\u{0086}\u{0087}\u{0088}\u{0089}\
553+
\u{008A}\u{008B}\u{008C}\u{008D}\u{008E}\u{008F}\u{0090}\u{0091}\u{0092}\u{0093}\u{0094}\u{0095}\u{0096}\
554+
\u{0097}\u{0098}\u{0099}\u{009A}\u{009B}\u{009C}\u{009D}\u{009E}\u{009F}".into()).to_css_string(),
555+
"\\7f \u{0080}\u{0081}\u{0082}\u{0083}\u{0084}\u{0085}\u{0086}\u{0087}\u{0088}\u{0089}\u{008A}\u{008B}\u{008C}\
556+
\u{008D}\u{008E}\u{008F}\u{0090}\u{0091}\u{0092}\u{0093}\u{0094}\u{0095}\u{0096}\u{0097}\u{0098}\u{0099}\
557+
\u{009A}\u{009B}\u{009C}\u{009D}\u{009E}\u{009F}");
558+
assert_eq!(Token::Ident("\u{00A0}\u{00A1}\u{00A2}".into()).to_css_string(), "\u{00A0}\u{00A1}\u{00A2}");
559+
assert_eq!(Token::Ident("a0123456789b".into()).to_css_string(), "a0123456789b");
560+
assert_eq!(Token::Ident("abcdefghijklmnopqrstuvwxyz".into()).to_css_string(), "abcdefghijklmnopqrstuvwxyz");
561+
assert_eq!(Token::Ident("ABCDEFGHIJKLMNOPQRSTUVWXYZ".into()).to_css_string(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
562+
assert_eq!(Token::Ident("\x20\x21\x78\x79".into()).to_css_string(), "\\ \\!xy");
563+
564+
// astral symbol (U+1D306 TETRAGRAM FOR CENTRE)
565+
assert_eq!(Token::Ident("\u{1D306}".into()).to_css_string(), "\u{1D306}");
566+
}
567+
496568
impl ToJson for Color {
497569
fn to_json(&self) -> json::Json {
498570
match *self {

0 commit comments

Comments
 (0)