]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1] text/template: exec should accept interface value as valid.
authorUgorji Nwoke <ugorji@gmail.com>
Wed, 13 Jun 2012 20:24:09 +0000 (16:24 -0400)
committerRob Pike <r@golang.org>
Wed, 13 Jun 2012 20:24:09 +0000 (16:24 -0400)
««« backport 4c05c319570b
text/template: exec should accept interface value as valid.

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 feb434a3be97f115a5047ae33156dda6dbbe2cc3..aba21ce28f55c0d0ccf9f390bdcf66f52ef60f4b 100644 (file)
@@ -518,6 +518,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 37d25f470cd5890c043a834995eca7f4f5ab5f0b..f4ae50f0ee9dcaa7183ab3f81926a864d01a4a35 100644 (file)
@@ -311,6 +311,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},
@@ -507,6 +508,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{
@@ -516,6 +521,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