]> Cypherpunks repositories - gostls13.git/commitdiff
text/template: fix handing of nil arguments to functions
authorGustavo Niemeyer <gustavo@niemeyer.net>
Mon, 19 Dec 2011 00:14:11 +0000 (22:14 -0200)
committerGustavo Niemeyer <gustavo@niemeyer.net>
Mon, 19 Dec 2011 00:14:11 +0000 (22:14 -0200)
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5494070

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

index b74bc3b01c90847363d7f19e6d1b6a518d8a2256..ba20fff89dfbdf4dbe39381c7697dba924f662bb 100644 (file)
@@ -497,7 +497,13 @@ func (s *state) evalCall(dot, fun reflect.Value, name string, args []parse.Node,
 // validateType guarantees that the value is valid and assignable to the type.
 func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value {
        if !value.IsValid() {
-               s.errorf("invalid value; expected %s", typ)
+               switch typ.Kind() {
+               case reflect.Interface, reflect.Ptr, reflect.Chan, reflect.Map, reflect.Slice, reflect.Func:
+                       // An untyped nil interface{}. Accept as a proper nil value.
+                       value = reflect.Zero(typ)
+               default:
+                       s.errorf("invalid value; expected %s", typ)
+               }
        }
        if !value.Type().AssignableTo(typ) {
                // Does one dereference or indirection work? We could do more, as we
index cf3c41572816f578b98a539db57b85e8bc975d4e..e33988b86c0930a1b60971c3ecbe596587f363af 100644 (file)
@@ -157,6 +157,10 @@ func (t *T) Method2(a uint16, b string) string {
        return fmt.Sprintf("Method2: %d %s", a, b)
 }
 
+func (t *T) Method3(v interface{}) string {
+       return fmt.Sprintf("Method3: %v", v)
+}
+
 func (t *T) MAdd(a int, b []int) []int {
        v := make([]int, len(b))
        for i, x := range b {
@@ -293,6 +297,7 @@ var execTests = []execTest{
        {".Method2(3, .X)", "-{{.Method2 3 .X}}-", "-Method2: 3 x-", tVal, true},
        {".Method2(.U16, `str`)", "-{{.Method2 .U16 `str`}}-", "-Method2: 16 str-", tVal, true},
        {".Method2(.U16, $x)", "{{if $x := .X}}-{{.Method2 .U16 $x}}{{end}}-", "-Method2: 16 x-", tVal, true},
+       {".Method3(nil)", "-{{.Method3 .MXI.unset}}-", "-Method3: <nil>-", tVal, true},
        {"method on var", "{{if $x := .}}-{{$x.Method2 .U16 $x.X}}{{end}}-", "-Method2: 16 x-", tVal, true},
        {"method on chained var",
                "{{range .MSIone}}{{if $.U.TrueFalse $.True}}{{$.U.TrueFalse $.True}}{{else}}WRONG{{end}}{{end}}",
@@ -322,6 +327,8 @@ var execTests = []execTest{
        {"if slice", "{{if .SI}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true},
        {"if emptymap", "{{if .MSIEmpty}}NON-EMPTY{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
        {"if map", "{{if .MSI}}NON-EMPTY{{else}}EMPTY{{end}}", "NON-EMPTY", tVal, true},
+       {"if map unset", "{{if .MXI.none}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true},
+       {"if map not unset", "{{if not .MXI.none}}ZERO{{else}}NON-ZERO{{end}}", "ZERO", tVal, true},
        {"if $x with $y int", "{{if $x := true}}{{with $y := .I}}{{$x}},{{$y}}{{end}}{{end}}", "true,17", tVal, true},
        {"if $x with $x int", "{{if $x := true}}{{with $x := .I}}{{$x}},{{end}}{{$x}}{{end}}", "17,true", tVal, true},