diff --git a/src/html/template/css.go b/src/html/template/css.go
index 1587af8385..eb92fc92b5 100644
--- a/src/html/template/css.go
+++ b/src/html/template/css.go
@@ -7,6 +7,7 @@ package template
import (
"bytes"
"fmt"
+ "strings"
"unicode"
"unicode/utf8"
)
@@ -156,7 +157,7 @@ func isCSSSpace(b byte) bool {
// cssEscaper escapes HTML and CSS special characters using \+ escapes.
func cssEscaper(args ...interface{}) string {
s, _ := stringify(args...)
- var b bytes.Buffer
+ var b strings.Builder
r, w, written := rune(0), 0, 0
for i := 0; i < len(s); i += w {
// See comment in htmlEscaper.
@@ -168,6 +169,9 @@ func cssEscaper(args ...interface{}) string {
default:
continue
}
+ if written == 0 {
+ b.Grow(len(s))
+ }
b.WriteString(s[written:i])
b.WriteString(repl)
written = i + w
diff --git a/src/html/template/html.go b/src/html/template/html.go
index 2ea5a7d4bc..13a0cd0436 100644
--- a/src/html/template/html.go
+++ b/src/html/template/html.go
@@ -137,7 +137,7 @@ var htmlNospaceNormReplacementTable = []string{
// htmlReplacer returns s with runes replaced according to replacementTable
// and when badRunes is true, certain bad runes are allowed through unescaped.
func htmlReplacer(s string, replacementTable []string, badRunes bool) string {
- written, b := 0, new(bytes.Buffer)
+ written, b := 0, new(strings.Builder)
r, w := rune(0), 0
for i := 0; i < len(s); i += w {
// Cannot use 'for range s' because we need to preserve the width
@@ -146,6 +146,9 @@ func htmlReplacer(s string, replacementTable []string, badRunes bool) string {
r, w = utf8.DecodeRuneInString(s[i:])
if int(r) < len(replacementTable) {
if repl := replacementTable[r]; len(repl) != 0 {
+ if written == 0 {
+ b.Grow(len(s))
+ }
b.WriteString(s[written:i])
b.WriteString(repl)
written = i + w
@@ -154,6 +157,9 @@ func htmlReplacer(s string, replacementTable []string, badRunes bool) string {
// No-op.
// IE does not allow these ranges in unquoted attrs.
} else if 0xfdd0 <= r && r <= 0xfdef || 0xfff0 <= r && r <= 0xffff {
+ if written == 0 {
+ b.Grow(len(s))
+ }
fmt.Fprintf(b, "%s%x;", s[written:i], r)
written = i + w
}
diff --git a/src/html/template/js.go b/src/html/template/js.go
index 872f6786b3..04c7c325db 100644
--- a/src/html/template/js.go
+++ b/src/html/template/js.go
@@ -187,7 +187,7 @@ func jsValEscaper(args ...interface{}) string {
}
first, _ := utf8.DecodeRune(b)
last, _ := utf8.DecodeLastRune(b)
- var buf bytes.Buffer
+ var buf strings.Builder
// Prevent IdentifierNames and NumericLiterals from running into
// keywords: in, instanceof, typeof, void
pad := isJSIdentPart(first) || isJSIdentPart(last)
@@ -217,7 +217,7 @@ func jsValEscaper(args ...interface{}) string {
if pad {
buf.WriteByte(' ')
}
- b = buf.Bytes()
+ return buf.String()
}
return string(b)
}
@@ -253,7 +253,7 @@ func jsRegexpEscaper(args ...interface{}) string {
// It also replaces runes U+2028 and U+2029 with the raw strings `\u2028` and
// `\u2029`.
func replace(s string, replacementTable []string) string {
- var b bytes.Buffer
+ var b strings.Builder
r, w, written := rune(0), 0, 0
for i := 0; i < len(s); i += w {
// See comment in htmlEscaper.
@@ -269,6 +269,9 @@ func replace(s string, replacementTable []string) string {
default:
continue
}
+ if written == 0 {
+ b.Grow(len(s))
+ }
b.WriteString(s[written:i])
b.WriteString(repl)
written = i + w