]> Cypherpunks repositories - gostls13.git/commitdiff
text/template: exec should accept interface value as valid.
authorUgorji Nwoke <ugorji@gmail.com>
Tue, 22 May 2012 22:21:35 +0000 (15:21 -0700)
committerRob Pike <r@golang.org>
Tue, 22 May 2012 22:21:35 +0000 (15:21 -0700)
Currently, if you pass some data to a template as an interface (e.g. interface{})
and extract that value that value as a parameter for a function, it fails, saying
wrong type.

This is because it is only looking at the interface type, not the interface content.

This CL uses the underlying content as the parameter to the func.

Fixes #3642.

R=golang-dev, r, r
CC=golang-dev
https://golang.org/cl/6218052

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

index 0c633e6bab7f66185d83c720064e3a05d94f0556..5fad5ccecbd87141a7e46b92ead74506085984b1 100644 (file)
@@ -520,6 +520,13 @@ func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Valu
                }
        }
        if !value.Type().AssignableTo(typ) {
+               if value.Kind() == reflect.Interface && !value.IsNil() {
+                       value = value.Elem()
+                       if value.Type().AssignableTo(typ) {
+                               return value
+                       }
+                       // fallthrough
+               }
                // Does one dereference or indirection work? We could do more, as we
                // do with method receivers, but that gets messy and method receivers
                // are much more constrained, so it makes more sense there than here.
index 8f6c67bbaa6b6092ca7d1804b7faf374a444b7a4..c8a30139773b49a2ff6fdf544b5240ec345d3894 100644 (file)
@@ -314,6 +314,7 @@ var execTests = []execTest{
        {".VariadicFuncInt", "{{call .VariadicFuncInt 33 `he` `llo`}}", "33=<he+llo>", tVal, true},
        {"if .BinaryFunc call", "{{ if .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{end}}", "[1=2]", tVal, true},
        {"if not .BinaryFunc call", "{{ if not .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{else}}No{{end}}", "No", tVal, true},
+       {"Interface Call", `{{stringer .S}}`, "foozle", map[string]interface{}{"S": bytes.NewBufferString("foozle")}, true},
 
        // Erroneous function calls (check args).
        {".BinaryFuncTooFew", "{{call .BinaryFunc `1`}}", "", tVal, false},
@@ -512,6 +513,10 @@ func vfunc(V, *V) string {
        return "vfunc"
 }
 
+func stringer(s fmt.Stringer) string {
+       return s.String()
+}
+
 func testExecute(execTests []execTest, template *Template, t *testing.T) {
        b := new(bytes.Buffer)
        funcs := FuncMap{
@@ -521,6 +526,7 @@ func testExecute(execTests []execTest, template *Template, t *testing.T) {
                "typeOf":   typeOf,
                "vfunc":    vfunc,
                "zeroArgs": zeroArgs,
+               "stringer": stringer,
        }
        for _, test := range execTests {
                var tmpl *Template