hugo

Unnamed repository; edit this file 'description' to name the repository.

git clone git://git.shimmy1996.com/hugo.git
commit ccb822eb5afad210432eb46ec3727e3536a87f58
parent 21e9eb18acc2a2f8d8b97f096615b836e65091a2
Author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Date:   Fri, 29 Jan 2021 17:15:42 +0100

Pull in latest Go template source

Diffstat:
Mscripts/fork_go_templates/main.go | 2+-
Mtpl/internal/go_templates/htmltemplate/examplefiles_test.go | 3+--
Mtpl/internal/go_templates/htmltemplate/exec_test.go | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtpl/internal/go_templates/htmltemplate/template.go | 4++--
Mtpl/internal/go_templates/testenv/testenv.go | 8+++-----
Mtpl/internal/go_templates/testenv/testenv_windows.go | 3+--
Mtpl/internal/go_templates/texttemplate/examplefiles_test.go | 3+--
Mtpl/internal/go_templates/texttemplate/exec.go | 4++++
Mtpl/internal/go_templates/texttemplate/exec_test.go | 13+++++++++++++
Mtpl/internal/go_templates/texttemplate/helper.go | 4++--
Mtpl/internal/go_templates/texttemplate/link_test.go | 7+++----
11 files changed, 157 insertions(+), 20 deletions(-)
diff --git a/scripts/fork_go_templates/main.go b/scripts/fork_go_templates/main.go
@@ -18,7 +18,7 @@ import (
 
 func main() {
 	// TODO(bep) git checkout tag
-	// The current is built with Go version da54dfb6a1f3bef827b9ec3780c98fde77a97d11 / go1.16dev
+	// The current is built with Go version c8bd8010ff7c0115bf186443119216ba51f09d2b / go1.16dev
 	fmt.Println("Forking ...")
 	defer fmt.Println("Done ...")
 
diff --git a/tpl/internal/go_templates/htmltemplate/examplefiles_test.go b/tpl/internal/go_templates/htmltemplate/examplefiles_test.go
@@ -8,7 +8,6 @@ package template_test
 
 import (
 	"io"
-	"io/ioutil"
 	"log"
 	"os"
 	"path/filepath"
@@ -23,7 +22,7 @@ type templateFile struct {
 }
 
 func createTestDir(files []templateFile) string {
-	dir, err := ioutil.TempDir("", "template")
+	dir, err := os.MkdirTemp("", "template")
 	if err != nil {
 		log.Fatal(err)
 	}
diff --git a/tpl/internal/go_templates/htmltemplate/exec_test.go b/tpl/internal/go_templates/htmltemplate/exec_test.go
@@ -13,9 +13,11 @@ import (
 	"errors"
 	"flag"
 	"fmt"
+	htmltemplate "html/template"
 	"io"
 	"reflect"
 	"strings"
+	"sync"
 	"testing"
 
 	template "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate"
@@ -1709,3 +1711,127 @@ func TestIssue31810(t *testing.T) {
 		t.Errorf("%s got %q, expected %q", textCall, b.String(), "result")
 	}
 }
+
+// Issue 39807. There was a race applying escapeTemplate.
+
+const raceText = `
+{{- define "jstempl" -}}
+var v = "v";
+{{- end -}}
+<script type="application/javascript">
+{{ template "jstempl" $ }}
+</script>
+`
+
+func TestEscapeRace(t *testing.T) {
+	t.Skip("this test currently fails with -race; see issue #39807")
+
+	tmpl := New("")
+	_, err := tmpl.New("templ.html").Parse(raceText)
+	if err != nil {
+		t.Fatal(err)
+	}
+	const count = 20
+	for i := 0; i < count; i++ {
+		_, err := tmpl.New(fmt.Sprintf("x%d.html", i)).Parse(`{{ template "templ.html" .}}`)
+		if err != nil {
+			t.Fatal(err)
+		}
+	}
+
+	var wg sync.WaitGroup
+	for i := 0; i < 10; i++ {
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			for j := 0; j < count; j++ {
+				sub := tmpl.Lookup(fmt.Sprintf("x%d.html", j))
+				if err := sub.Execute(io.Discard, nil); err != nil {
+					t.Error(err)
+				}
+			}
+		}()
+	}
+	wg.Wait()
+}
+
+func TestRecursiveExecute(t *testing.T) {
+	tmpl := New("")
+
+	recur := func() (htmltemplate.HTML, error) {
+		var sb strings.Builder
+		if err := tmpl.ExecuteTemplate(&sb, "subroutine", nil); err != nil {
+			t.Fatal(err)
+		}
+		return htmltemplate.HTML(sb.String()), nil
+	}
+
+	m := FuncMap{
+		"recur": recur,
+	}
+
+	top, err := tmpl.New("x.html").Funcs(m).Parse(`{{recur}}`)
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, err = tmpl.New("subroutine").Parse(`<a href="/x?p={{"'a<b'"}}">`)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err := top.Execute(io.Discard, nil); err != nil {
+		t.Fatal(err)
+	}
+}
+
+// recursiveInvoker is for TestRecursiveExecuteViaMethod.
+type recursiveInvoker struct {
+	t    *testing.T
+	tmpl *Template
+}
+
+func (r *recursiveInvoker) Recur() (string, error) {
+	var sb strings.Builder
+	if err := r.tmpl.ExecuteTemplate(&sb, "subroutine", nil); err != nil {
+		r.t.Fatal(err)
+	}
+	return sb.String(), nil
+}
+
+func TestRecursiveExecuteViaMethod(t *testing.T) {
+	tmpl := New("")
+	top, err := tmpl.New("x.html").Parse(`{{.Recur}}`)
+	if err != nil {
+		t.Fatal(err)
+	}
+	_, err = tmpl.New("subroutine").Parse(`<a href="/x?p={{"'a<b'"}}">`)
+	if err != nil {
+		t.Fatal(err)
+	}
+	r := &recursiveInvoker{
+		t:    t,
+		tmpl: tmpl,
+	}
+	if err := top.Execute(io.Discard, r); err != nil {
+		t.Fatal(err)
+	}
+}
+
+// Issue 43295.
+func TestTemplateFuncsAfterClone(t *testing.T) {
+	s := `{{ f . }}`
+	want := "test"
+	orig := New("orig").Funcs(map[string]interface{}{
+		"f": func(in string) string {
+			return in
+		},
+	}).New("child")
+
+	overviewTmpl := Must(Must(orig.Clone()).Parse(s))
+	var out strings.Builder
+	if err := overviewTmpl.Execute(&out, want); err != nil {
+		t.Fatal(err)
+	}
+	if got := out.String(); got != want {
+		t.Fatalf("got %q; want %q", got, want)
+	}
+}
diff --git a/tpl/internal/go_templates/htmltemplate/template.go b/tpl/internal/go_templates/htmltemplate/template.go
@@ -8,7 +8,7 @@ import (
 	"fmt"
 	"io"
 	"io/fs"
-	"io/ioutil"
+	"os"
 	"path"
 	"path/filepath"
 	"sync"
@@ -524,7 +524,7 @@ func parseFS(t *Template, fsys fs.FS, patterns []string) (*Template, error) {
 
 func readFileOS(file string) (name string, b []byte, err error) {
 	name = filepath.Base(file)
-	b, err = ioutil.ReadFile(file)
+	b, err = os.ReadFile(file)
 	return
 }
 
diff --git a/tpl/internal/go_templates/testenv/testenv.go b/tpl/internal/go_templates/testenv/testenv.go
@@ -13,6 +13,7 @@ package testenv
 import (
 	"errors"
 	"flag"
+	"github.com/gohugoio/hugo/tpl/internal/go_templates/cfg"
 	"os"
 	"os/exec"
 	"path/filepath"
@@ -21,9 +22,6 @@ import (
 	"strings"
 	"sync"
 	"testing"
-
-	"github.com/cli/safeexec"
-	"github.com/gohugoio/hugo/tpl/internal/go_templates/cfg"
 )
 
 // Builder reports the name of the builder running this test
@@ -109,7 +107,7 @@ func GoTool() (string, error) {
 	if _, err := os.Stat(path); err == nil {
 		return path, nil
 	}
-	goBin, err := safeexec.LookPath("go" + exeSuffix)
+	goBin, err := exec.LookPath("go" + exeSuffix)
 	if err != nil {
 		return "", errors.New("cannot find go tool: " + err.Error())
 	}
@@ -154,7 +152,7 @@ func MustHaveExecPath(t testing.TB, path string) {
 
 	err, found := execPaths.Load(path)
 	if !found {
-		_, err = safeexec.LookPath(path)
+		_, err = exec.LookPath(path)
 		err, _ = execPaths.LoadOrStore(path, err)
 	}
 	if err != nil {
diff --git a/tpl/internal/go_templates/testenv/testenv_windows.go b/tpl/internal/go_templates/testenv/testenv_windows.go
@@ -5,7 +5,6 @@
 package testenv
 
 import (
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"sync"
@@ -16,7 +15,7 @@ var symlinkOnce sync.Once
 var winSymlinkErr error
 
 func initWinHasSymlink() {
-	tmpdir, err := ioutil.TempDir("", "symtest")
+	tmpdir, err := os.MkdirTemp("", "symtest")
 	if err != nil {
 		panic("failed to create temp directory: " + err.Error())
 	}
diff --git a/tpl/internal/go_templates/texttemplate/examplefiles_test.go b/tpl/internal/go_templates/texttemplate/examplefiles_test.go
@@ -8,7 +8,6 @@ package template_test
 
 import (
 	"io"
-	"io/ioutil"
 	"log"
 	"os"
 	"path/filepath"
@@ -22,7 +21,7 @@ type templateFile struct {
 }
 
 func createTestDir(files []templateFile) string {
-	dir, err := ioutil.TempDir("", "template")
+	dir, err := os.MkdirTemp("", "template")
 	if err != nil {
 		log.Fatal(err)
 	}
diff --git a/tpl/internal/go_templates/texttemplate/exec.go b/tpl/internal/go_templates/texttemplate/exec.go
@@ -373,6 +373,10 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
 		if val.IsNil() {
 			break
 		}
+		if val.Type().ChanDir() == reflect.SendDir {
+			s.errorf("range over send-only channel %v", val)
+			break
+		}
 		i := 0
 		for ; ; i++ {
 			elem, ok := val.Recv()
diff --git a/tpl/internal/go_templates/texttemplate/exec_test.go b/tpl/internal/go_templates/texttemplate/exec_test.go
@@ -1699,3 +1699,16 @@ func TestIssue31810(t *testing.T) {
 		t.Errorf("%s got %q, expected %q", textCall, b.String(), "result")
 	}
 }
+
+// Issue 43065, range over send only channel
+func TestIssue43065(t *testing.T) {
+	var b bytes.Buffer
+	tmp := Must(New("").Parse(`{{range .}}{{end}}`))
+	ch := make(chan<- int)
+	err := tmp.Execute(&b, ch)
+	if err == nil {
+		t.Error("expected err got nil")
+	} else if !strings.Contains(err.Error(), "range over send-only channel") {
+		t.Errorf("%s", err)
+	}
+}
diff --git a/tpl/internal/go_templates/texttemplate/helper.go b/tpl/internal/go_templates/texttemplate/helper.go
@@ -9,7 +9,7 @@ package template
 import (
 	"fmt"
 	"io/fs"
-	"io/ioutil"
+	"os"
 	"path"
 	"path/filepath"
 )
@@ -164,7 +164,7 @@ func parseFS(t *Template, fsys fs.FS, patterns []string) (*Template, error) {
 
 func readFileOS(file string) (name string, b []byte, err error) {
 	name = filepath.Base(file)
-	b, err = ioutil.ReadFile(file)
+	b, err = os.ReadFile(file)
 	return
 }
 
diff --git a/tpl/internal/go_templates/texttemplate/link_test.go b/tpl/internal/go_templates/texttemplate/link_test.go
@@ -9,7 +9,6 @@ package template_test
 import (
 	"bytes"
 	"github.com/gohugoio/hugo/tpl/internal/go_templates/testenv"
-	"io/ioutil"
 	"os"
 	"os/exec"
 	"path/filepath"
@@ -42,13 +41,13 @@ func main() {
 	t.Used()
 }
 `
-	td, err := ioutil.TempDir("", "text_template_TestDeadCodeElimination")
+	td, err := os.MkdirTemp("", "text_template_TestDeadCodeElimination")
 	if err != nil {
 		t.Fatal(err)
 	}
 	defer os.RemoveAll(td)
 
-	if err := ioutil.WriteFile(filepath.Join(td, "x.go"), []byte(prog), 0644); err != nil {
+	if err := os.WriteFile(filepath.Join(td, "x.go"), []byte(prog), 0644); err != nil {
 		t.Fatal(err)
 	}
 	cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "x.exe", "x.go")
@@ -56,7 +55,7 @@ func main() {
 	if out, err := cmd.CombinedOutput(); err != nil {
 		t.Fatalf("go build: %v, %s", err, out)
 	}
-	slurp, err := ioutil.ReadFile(filepath.Join(td, "x.exe"))
+	slurp, err := os.ReadFile(filepath.Join(td, "x.exe"))
 	if err != nil {
 		t.Fatal(err)
 	}