1
0
mirror of https://github.com/golang/go synced 2024-11-07 15:36:23 -07:00

text/template: wrap errors returned by template functions instead of stringifying them

Fixes #34201

Change-Id: Ic2e2967e4b01167345cf38bd006cabb206a64377
GitHub-Last-Rev: 5d0c485655
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>
This commit is contained in:
Adrien Delorme 2021-03-05 15:59:12 +00:00 committed by Daniel Martí
parent 67b9ecb23b
commit d4247f5167
3 changed files with 27 additions and 2 deletions

View 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)

View 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

View 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)