Pull in latest Go template source
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Fri, 29 Jan 2021 16:15:42 +0000 (17:15 +0100)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Thu, 18 Feb 2021 13:11:48 +0000 (14:11 +0100)
scripts/fork_go_templates/main.go
tpl/internal/go_templates/htmltemplate/examplefiles_test.go
tpl/internal/go_templates/htmltemplate/exec_test.go
tpl/internal/go_templates/htmltemplate/template.go
tpl/internal/go_templates/testenv/testenv.go
tpl/internal/go_templates/testenv/testenv_windows.go
tpl/internal/go_templates/texttemplate/examplefiles_test.go
tpl/internal/go_templates/texttemplate/exec.go
tpl/internal/go_templates/texttemplate/exec_test.go
tpl/internal/go_templates/texttemplate/helper.go
tpl/internal/go_templates/texttemplate/link_test.go

index 4f8bb93d74f7c74234811191003ad83ce5694f7d..7aab23c35480014fe284830d586dc85c2ae7ab4f 100644 (file)
@@ -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 ...")
 
index ae763184e3c8cfcf6a3359054cf2953751ac411e..4c693fba3410ff7ec4b910c21efe3d9405f4bc9f 100644 (file)
@@ -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)
        }
index 7af58295843c3c599e881142221d02ab3f10e3ad..cfca536b416fcb827cb234050f5fc7b2f1a2226c 100644 (file)
@@ -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)
+       }
+}
index 132a4102b04fa5dee3d97cde26002fa4e349343c..26301896942f30fd250c3be191d183e4662af963 100644 (file)
@@ -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
 }
 
index 5bd91591a94db3d6a12ed7d30a009b08503ec27e..e0a0b4ec6dad26a3280bc27576c50fc510e9d14e 100644 (file)
@@ -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 {
index eb8d6ac1650385b80bc1dcaea382d37a6b85d35e..4802b139518e3e24bc7a428168707028540daea6 100644 (file)
@@ -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())
        }
index 8a78a018e61fa4078fd956627a94aef5c9f30d32..5a95b7078eb7225fa072e154c2d4a5f3d85c3001 100644 (file)
@@ -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)
        }
index ca6a1a07146466fc589ac24300b282bb1af03430..8b387123436b520850c31df558ac225e6c5618e9 100644 (file)
@@ -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()
index 3f16b6eb6ca19f7bbdb4249e288bd538342778c5..88de0fd498ee463a38200dc08cc62ab56867ff64 100644 (file)
@@ -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)
+       }
+}
index 8269fa28c50d3d0b9c94898969a49f0f3d15369c..57905e613a43640a1de6c3d5bd390981af6ce215 100644 (file)
@@ -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
 }
 
index 3db8c21e3aa8234286a18a86fd3ba970c31557ee..e602b0e7e87d15d76acb053c9b6b3fc537269ec2 100644 (file)
@@ -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)
        }