{`Go "jump" \`, `Go \"jump\" \\`},
{`Yukihiro says "今日は世界"`, `Yukihiro says \"今日は世界\"`},
{"unprintable \uFDFF", `unprintable \uFDFF`},
+ {`<html>`, `\x3Chtml\x3E`},
}
for _, tc := range testCases {
s := JSEscapeString(tc.in)
jsBackslash = []byte(`\\`)
jsApos = []byte(`\'`)
jsQuot = []byte(`\"`)
+ jsLt = []byte(`\x3C`)
+ jsGt = []byte(`\x3E`)
)
for i := 0; i < len(b); i++ {
c := b[i]
- if ' ' <= c && c < utf8.RuneSelf && c != '\\' && c != '"' && c != '\'' {
+ if !jsIsSpecial(int(c)) {
// fast path: nothing to do
continue
}
w.Write(b[last:i])
if c < utf8.RuneSelf {
- // Quotes and slashes get quoted.
+ // Quotes, slashes and angle brackets get quoted.
// Control characters get written as \u00XX.
switch c {
case '\\':
w.Write(jsApos)
case '"':
w.Write(jsQuot)
+ case '<':
+ w.Write(jsLt)
+ case '>':
+ w.Write(jsGt)
default:
w.Write(jsLowUni)
t, b := c>>4, c&0x0f
func jsIsSpecial(rune int) bool {
switch rune {
- case '\\', '\'', '"':
+ case '\\', '\'', '"', '<', '>':
return true
}
return rune < ' ' || utf8.RuneSelf <= rune