diff --git a/hugolib/template_test.go b/hugolib/template_test.go
index 9f04aabdd..29993120d 100644
--- a/hugolib/template_test.go
+++ b/hugolib/template_test.go
@@ -566,6 +566,24 @@ title: P1
}
+func TestTemplateGoIssues(t *testing.T) {
+ b := newTestSitesBuilder(t)
+
+ b.WithTemplatesAdded(
+ "index.html", `
+{{ $title := "a & b" }}
+
+`,
+ )
+
+ b.Build(BuildCfg{})
+
+ b.AssertFileContent("public/index.html", `
+
+
+`)
+}
+
func collectIdentities(set map[identity.Identity]bool, provider identity.Provider) {
if ids, ok := provider.(identity.IdentitiesProvider); ok {
for _, id := range ids.GetIdentities() {
diff --git a/scripts/fork_go_templates/main.go b/scripts/fork_go_templates/main.go
index d9d056797..04202b254 100644
--- a/scripts/fork_go_templates/main.go
+++ b/scripts/fork_go_templates/main.go
@@ -17,7 +17,7 @@ import (
func main() {
// TODO(bep) git checkout tag
- // The current is built with Go version 9341fe073e6f7742c9d61982084874560dac2014 / go1.13.5
+ // The current is built with Go version b68fa57c599720d33a2d735782969ce95eabf794 / go1.15dev
fmt.Println("Forking ...")
defer fmt.Println("Done ...")
@@ -55,6 +55,8 @@ var (
textTemplateReplacers = strings.NewReplacer(
`"text/template/`, `"github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/`,
`"internal/fmtsort"`, `"github.com/gohugoio/hugo/tpl/internal/go_templates/fmtsort"`,
+ `"internal/testenv"`, `"github.com/gohugoio/hugo/tpl/internal/go_templates/testenv"`,
+ "TestLinkerGC", "_TestLinkerGC",
// Rename types and function that we want to overload.
"type state struct", "type stateOld struct",
"func (s *state) evalFunction", "func (s *state) evalFunctionOld",
@@ -63,6 +65,10 @@ var (
"func isTrue(val reflect.Value) (truth, ok bool) {", "func isTrueOld(val reflect.Value) (truth, ok bool) {",
)
+ testEnvReplacers = strings.NewReplacer(
+ `"internal/cfg"`, `"github.com/gohugoio/hugo/tpl/internal/go_templates/cfg"`,
+ )
+
htmlTemplateReplacers = strings.NewReplacer(
`. "html/template"`, `. "github.com/gohugoio/hugo/tpl/internal/go_templates/htmltemplate"`,
`"html/template"`, `template "github.com/gohugoio/hugo/tpl/internal/go_templates/htmltemplate"`,
@@ -116,6 +122,13 @@ var goPackages = []goPackage{
goPackage{srcPkg: "internal/fmtsort", dstPkg: "fmtsort", rewriter: func(name string) {
rewrite(name, `"internal/fmtsort" -> "github.com/gohugoio/hugo/tpl/internal/go_templates/fmtsort"`)
}},
+ goPackage{srcPkg: "internal/testenv", dstPkg: "testenv",
+ replacer: func(name, content string) string { return testEnvReplacers.Replace(content) }, rewriter: func(name string) {
+ rewrite(name, `"internal/testenv" -> "github.com/gohugoio/hugo/tpl/internal/go_templates/testenv"`)
+ }},
+ goPackage{srcPkg: "internal/cfg", dstPkg: "cfg", rewriter: func(name string) {
+ rewrite(name, `"internal/cfg" -> "github.com/gohugoio/hugo/tpl/internal/go_templates/cfg"`)
+ }},
}
var fs = afero.NewOsFs()
diff --git a/tpl/internal/go_templates/cfg/cfg.go b/tpl/internal/go_templates/cfg/cfg.go
new file mode 100644
index 000000000..bdbe9df3e
--- /dev/null
+++ b/tpl/internal/go_templates/cfg/cfg.go
@@ -0,0 +1,64 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package cfg holds configuration shared by the Go command and internal/testenv.
+// Definitions that don't need to be exposed outside of cmd/go should be in
+// cmd/go/internal/cfg instead of this package.
+package cfg
+
+// KnownEnv is a list of environment variables that affect the operation
+// of the Go command.
+const KnownEnv = `
+ AR
+ CC
+ CGO_CFLAGS
+ CGO_CFLAGS_ALLOW
+ CGO_CFLAGS_DISALLOW
+ CGO_CPPFLAGS
+ CGO_CPPFLAGS_ALLOW
+ CGO_CPPFLAGS_DISALLOW
+ CGO_CXXFLAGS
+ CGO_CXXFLAGS_ALLOW
+ CGO_CXXFLAGS_DISALLOW
+ CGO_ENABLED
+ CGO_FFLAGS
+ CGO_FFLAGS_ALLOW
+ CGO_FFLAGS_DISALLOW
+ CGO_LDFLAGS
+ CGO_LDFLAGS_ALLOW
+ CGO_LDFLAGS_DISALLOW
+ CXX
+ FC
+ GCCGO
+ GO111MODULE
+ GO386
+ GOARCH
+ GOARM
+ GOBIN
+ GOCACHE
+ GOENV
+ GOEXE
+ GOFLAGS
+ GOGCCFLAGS
+ GOHOSTARCH
+ GOHOSTOS
+ GOINSECURE
+ GOMIPS
+ GOMIPS64
+ GOMODCACHE
+ GONOPROXY
+ GONOSUMDB
+ GOOS
+ GOPATH
+ GOPPC64
+ GOPRIVATE
+ GOPROXY
+ GOROOT
+ GOSUMDB
+ GOTMPDIR
+ GOTOOLDIR
+ GOWASM
+ GO_EXTLINK_ENABLED
+ PKG_CONFIG
+`
diff --git a/tpl/internal/go_templates/fmtsort/sort.go b/tpl/internal/go_templates/fmtsort/sort.go
index 70a305a3a..b01229bd0 100644
--- a/tpl/internal/go_templates/fmtsort/sort.go
+++ b/tpl/internal/go_templates/fmtsort/sort.go
@@ -53,12 +53,16 @@ func Sort(mapValue reflect.Value) *SortedMap {
if mapValue.Type().Kind() != reflect.Map {
return nil
}
- key := make([]reflect.Value, mapValue.Len())
- value := make([]reflect.Value, len(key))
+ // Note: this code is arranged to not panic even in the presence
+ // of a concurrent map update. The runtime is responsible for
+ // yelling loudly if that happens. See issue 33275.
+ n := mapValue.Len()
+ key := make([]reflect.Value, 0, n)
+ value := make([]reflect.Value, 0, n)
iter := mapValue.MapRange()
- for i := 0; iter.Next(); i++ {
- key[i] = iter.Key()
- value[i] = iter.Value()
+ for iter.Next() {
+ key = append(key, iter.Key())
+ value = append(value, iter.Value())
}
sorted := &SortedMap{
Key: key,
diff --git a/tpl/internal/go_templates/fmtsort/sort_test.go b/tpl/internal/go_templates/fmtsort/sort_test.go
index 601ec9d25..364c5bf6d 100644
--- a/tpl/internal/go_templates/fmtsort/sort_test.go
+++ b/tpl/internal/go_templates/fmtsort/sort_test.go
@@ -119,7 +119,7 @@ var sortTests = []sortTest{
"PTR0:0 PTR1:1 PTR2:2",
},
{
- map[toy]string{toy{7, 2}: "72", toy{7, 1}: "71", toy{3, 4}: "34"},
+ map[toy]string{{7, 2}: "72", {7, 1}: "71", {3, 4}: "34"},
"{3 4}:34 {7 1}:71 {7 2}:72",
},
{
diff --git a/tpl/internal/go_templates/htmltemplate/content_test.go b/tpl/internal/go_templates/htmltemplate/content_test.go
index 2a1abfbfb..b5de701d3 100644
--- a/tpl/internal/go_templates/htmltemplate/content_test.go
+++ b/tpl/internal/go_templates/htmltemplate/content_test.go
@@ -21,7 +21,7 @@ func TestTypedContent(t *testing.T) {
htmltemplate.HTML(`Hello, World &tc!`),
htmltemplate.HTMLAttr(` dir="ltr"`),
htmltemplate.JS(`c && alert("Hello, World!");`),
- htmltemplate.JSStr(`Hello, World & O'Reilly\x21`),
+ htmltemplate.JSStr(`Hello, World & O'Reilly\u0021`),
htmltemplate.URL(`greeting=H%69,&addressee=(World)`),
htmltemplate.Srcset(`greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`),
htmltemplate.URL(`,foo/,`),
@@ -73,7 +73,7 @@ func TestTypedContent(t *testing.T) {
`Hello, World &tc!`,
` dir="ltr"`,
`c && alert("Hello, World!");`,
- `Hello, World & O'Reilly\x21`,
+ `Hello, World & O'Reilly\u0021`,
`greeting=H%69,&addressee=(World)`,
`greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
`,foo/,`,
@@ -103,7 +103,7 @@ func TestTypedContent(t *testing.T) {
`Hello, World &tc!`,
` dir="ltr"`,
`c && alert("Hello, World!");`,
- `Hello, World & O'Reilly\x21`,
+ `Hello, World & O'Reilly\u0021`,
`greeting=H%69,&addressee=(World)`,
`greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
`,foo/,`,
@@ -118,7 +118,7 @@ func TestTypedContent(t *testing.T) {
`Hello, World &tc!`,
` dir="ltr"`,
`c && alert("Hello, World!");`,
- `Hello, World & O'Reilly\x21`,
+ `Hello, World & O'Reilly\u0021`,
`greeting=H%69,&addressee=(World)`,
`greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
`,foo/,`,
@@ -133,7 +133,7 @@ func TestTypedContent(t *testing.T) {
`Hello, <b>World</b> &tc!`,
` dir="ltr"`,
`c && alert("Hello, World!");`,
- `Hello, World & O'Reilly\x21`,
+ `Hello, World & O'Reilly\u0021`,
`greeting=H%69,&addressee=(World)`,
`greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
`,foo/,`,
@@ -149,7 +149,7 @@ func TestTypedContent(t *testing.T) {
// Not escaped.
`c && alert("Hello, World!");`,
// Escape sequence not over-escaped.
- `"Hello, World & O'Reilly\x21"`,
+ `"Hello, World & O'Reilly\u0021"`,
`"greeting=H%69,\u0026addressee=(World)"`,
`"greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w"`,
`",foo/,"`,
@@ -165,7 +165,7 @@ func TestTypedContent(t *testing.T) {
// Not JS escaped but HTML escaped.
`c && alert("Hello, World!");`,
// Escape sequence not over-escaped.
- `"Hello, World & O'Reilly\x21"`,
+ `"Hello, World & O'Reilly\u0021"`,
`"greeting=H%69,\u0026addressee=(World)"`,
`"greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w"`,
`",foo/,"`,
@@ -174,30 +174,30 @@ func TestTypedContent(t *testing.T) {
{
``,
[]string{
- `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
- `a[href =~ \x22\/\/example.com\x22]#foo`,
- `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
- ` dir=\x22ltr\x22`,
- `c \x26\x26 alert(\x22Hello, World!\x22);`,
+ `\u003cb\u003e \u0022foo%\u0022 O\u0027Reilly \u0026bar;`,
+ `a[href =~ \u0022\/\/example.com\u0022]#foo`,
+ `Hello, \u003cb\u003eWorld\u003c\/b\u003e \u0026amp;tc!`,
+ ` dir=\u0022ltr\u0022`,
+ `c \u0026\u0026 alert(\u0022Hello, World!\u0022);`,
// Escape sequence not over-escaped.
- `Hello, World \x26 O\x27Reilly\x21`,
- `greeting=H%69,\x26addressee=(World)`,
- `greeting=H%69,\x26addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`,
+ `Hello, World \u0026 O\u0027Reilly\u0021`,
+ `greeting=H%69,\u0026addressee=(World)`,
+ `greeting=H%69,\u0026addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`,
`,foo\/,`,
},
},
{
``,
[]string{
- `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
- `a[href =~ \x22\/\/example.com\x22]#foo`,
- `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
- ` dir=\x22ltr\x22`,
- `c \x26\x26 alert(\x22Hello, World!\x22);`,
+ `\u003cb\u003e \u0022foo%\u0022 O\u0027Reilly \u0026bar;`,
+ `a[href =~ \u0022\/\/example.com\u0022]#foo`,
+ `Hello, \u003cb\u003eWorld\u003c\/b\u003e \u0026amp;tc!`,
+ ` dir=\u0022ltr\u0022`,
+ `c \u0026\u0026 alert(\u0022Hello, World!\u0022);`,
// Escape sequence not over-escaped.
- `Hello, World \x26 O\x27Reilly\x21`,
- `greeting=H%69,\x26addressee=(World)`,
- `greeting=H%69,\x26addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`,
+ `Hello, World \u0026 O\u0027Reilly\u0021`,
+ `greeting=H%69,\u0026addressee=(World)`,
+ `greeting=H%69,\u0026addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`,
`,foo\/,`,
},
},
@@ -211,7 +211,7 @@ func TestTypedContent(t *testing.T) {
// Not escaped.
`c && alert("Hello, World!");`,
// Escape sequence not over-escaped.
- `"Hello, World & O'Reilly\x21"`,
+ `"Hello, World & O'Reilly\u0021"`,
`"greeting=H%69,\u0026addressee=(World)"`,
`"greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w"`,
`",foo/,"`,
@@ -227,7 +227,7 @@ func TestTypedContent(t *testing.T) {
`Hello, World &tc!`,
` dir="ltr"`,
`c && alert("Hello, World!");`,
- `Hello, World & O'Reilly\x21`,
+ `Hello, World & O'Reilly\u0021`,
`greeting=H%69,&addressee=(World)`,
`greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
`,foo/,`,
@@ -236,15 +236,15 @@ func TestTypedContent(t *testing.T) {
{
`