mirror of
https://github.com/golang/go
synced 2024-11-19 21:04:43 -07:00
html/template: handle nils during indirection
Fixes #5982. R=golang-dev, r CC=golang-dev https://golang.org/cl/12387043
This commit is contained in:
parent
67f2ca3530
commit
53d9b6fcf3
@ -74,6 +74,9 @@ const (
|
|||||||
// indirect returns the value, after dereferencing as many times
|
// indirect returns the value, after dereferencing as many times
|
||||||
// as necessary to reach the base type (or nil).
|
// as necessary to reach the base type (or nil).
|
||||||
func indirect(a interface{}) interface{} {
|
func indirect(a interface{}) interface{} {
|
||||||
|
if a == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr {
|
if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr {
|
||||||
// Avoid creating a reflect.Value if it's not a pointer.
|
// Avoid creating a reflect.Value if it's not a pointer.
|
||||||
return a
|
return a
|
||||||
@ -94,6 +97,9 @@ var (
|
|||||||
// as necessary to reach the base type (or nil) or an implementation of fmt.Stringer
|
// as necessary to reach the base type (or nil) or an implementation of fmt.Stringer
|
||||||
// or error,
|
// or error,
|
||||||
func indirectToStringerOrError(a interface{}) interface{} {
|
func indirectToStringerOrError(a interface{}) interface{} {
|
||||||
|
if a == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
v := reflect.ValueOf(a)
|
v := reflect.ValueOf(a)
|
||||||
for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
|
for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
|
||||||
v = v.Elem()
|
v = v.Elem()
|
||||||
|
@ -259,3 +259,28 @@ func TestStringer(t *testing.T) {
|
|||||||
t.Errorf("expected %q got %q", expect, b.String())
|
t.Errorf("expected %q got %q", expect, b.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://code.google.com/p/go/issues/detail?id=5982
|
||||||
|
func TestEscapingNilNonemptyInterfaces(t *testing.T) {
|
||||||
|
tmpl := Must(New("x").Parse("{{.E}}"))
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
t.Errorf("panic during template execution: %v", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
got := new(bytes.Buffer)
|
||||||
|
testData := struct{ E error }{} // any non-empty interface here will do; error is just ready at hand
|
||||||
|
tmpl.Execute(got, testData)
|
||||||
|
|
||||||
|
// Use this data instead of just hard-coding "<nil>" to avoid
|
||||||
|
// dependencies on the html escaper and the behavior of fmt w.r.t. nil.
|
||||||
|
want := new(bytes.Buffer)
|
||||||
|
data := struct{ E string }{E: fmt.Sprint(nil)}
|
||||||
|
tmpl.Execute(want, data)
|
||||||
|
|
||||||
|
if !bytes.Equal(want.Bytes(), got.Bytes()) {
|
||||||
|
t.Errorf("expected %q got %q", string(want.Bytes()), string(got.Bytes()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user