]> Cypherpunks repositories - gostls13.git/commitdiff
text/template: wrap errors returned by template functions instead of stringifying...
authorAdrien Delorme <azr@users.noreply.github.com>
Fri, 5 Mar 2021 15:59:12 +0000 (15:59 +0000)
committerDaniel Martí <mvdan@mvdan.cc>
Fri, 5 Mar 2021 18:00:44 +0000 (18:00 +0000)
Fixes #34201

Change-Id: Ic2e2967e4b01167345cf38bd006cabb206a64377
GitHub-Last-Rev: 5d0c4856550614484a8dbfb68c37aa1abcfcc529
GitHub-Pull-Request: golang/go#42398
Reviewed-on: https://go-review.googlesource.com/c/go/+/267838
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
Trust: Daniel Martí <mvdan@mvdan.cc>
Trust: Pontus Leitzler <leitzler@gmail.com>
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Go Bot <gobot@golang.org>

src/text/template/exec.go
src/text/template/exec_test.go
src/text/template/funcs.go

index 4637b2035f42a20b451bdae8198215aff60483bf..f1305a29a0de31d739642e5a7cbb4205b58df2d0 100644 (file)
@@ -727,7 +727,7 @@ func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, a
        // error to the caller.
        if err != nil {
                s.at(node)
-               s.errorf("error calling %s: %v", name, err)
+               s.errorf("error calling %s: %w", name, err)
        }
        if v.Type() == reflectValueType {
                v = v.Interface().(reflect.Value)
index 1a129ed5afdf71b7493d4fff03607858573fe2da..255b111b34bf3c9676b7f8fe8df7c1e8f7160907 100644 (file)
@@ -902,6 +902,28 @@ func TestExecError(t *testing.T) {
        }
 }
 
+type CustomError struct{}
+
+func (*CustomError) Error() string { return "heyo !" }
+
+// Check that a custom error can be returned.
+func TestExecError_CustomError(t *testing.T) {
+       failingFunc := func() (string, error) {
+               return "", &CustomError{}
+       }
+       tmpl := Must(New("top").Funcs(FuncMap{
+               "err": failingFunc,
+       }).Parse("{{ err }}"))
+
+       var b bytes.Buffer
+       err := tmpl.Execute(&b, nil)
+
+       var e *CustomError
+       if !errors.As(err, &e) {
+               t.Fatalf("expected custom error; got %s", err)
+       }
+}
+
 func TestJSEscaping(t *testing.T) {
        testCases := []struct {
                in, exp string
index 1b6940a84ae0d702f5775b8ca85efddd3b15afbb..9dd332c06800f2b25460ebc87744e849730d0d5c 100644 (file)
@@ -23,6 +23,9 @@ import (
 // return value evaluates to non-nil during execution, execution terminates and
 // Execute returns that error.
 //
+// Errors returned by Execute wrap the underlying error; call errors.As to
+// uncover them.
+//
 // When template execution invokes a function with an argument list, that list
 // must be assignable to the function's parameter types. Functions meant to
 // apply to arguments of arbitrary type can use parameters of type interface{} or
@@ -344,7 +347,7 @@ func call(fn reflect.Value, args ...reflect.Value) (reflect.Value, error) {
 
                var err error
                if argv[i], err = prepareArg(arg, argType); err != nil {
-                       return reflect.Value{}, fmt.Errorf("arg %d: %s", i, err)
+                       return reflect.Value{}, fmt.Errorf("arg %d: %w", i, err)
                }
        }
        return safeCall(fn, argv)