aboutsummaryrefslogtreecommitdiff
path: root/src/text/template
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2015-05-28 13:49:20 -0700
committerKeith Randall <khr@golang.org>2015-05-28 13:51:18 -0700
commit067e8dfd82163ddcbde248dbe5a1187a417e5d36 (patch)
tree7bfb46b901d03498c7739c92bec21d81d3a2c485 /src/text/template
parent247786c1745abc0c7185f7c15ca256edf68ed6d6 (diff)
parentccc037699e2966b7c79ba84c67471cef5e67a3b8 (diff)
downloadgo-067e8dfd82163ddcbde248dbe5a1187a417e5d36.tar.xz
[dev.ssa] Merge remote-tracking branch 'origin/master' into mergebranch
Semi-regular merge of tip to dev.ssa. Complicated a bit by the move of cmd/internal/* to cmd/compile/internal/*. Change-Id: I1c66d3c29bb95cce4a53c5a3476373aa5245303d
Diffstat (limited to 'src/text/template')
-rw-r--r--src/text/template/exec.go2
-rw-r--r--src/text/template/exec_test.go8
-rw-r--r--src/text/template/funcs.go2
-rw-r--r--src/text/template/template.go12
4 files changed, 21 insertions, 3 deletions
diff --git a/src/text/template/exec.go b/src/text/template/exec.go
index e6e1287993..ebafb4b5dc 100644
--- a/src/text/template/exec.go
+++ b/src/text/template/exec.go
@@ -660,7 +660,7 @@ func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) refle
case *parse.PipeNode:
return s.validateType(s.evalPipeline(dot, arg), typ)
case *parse.IdentifierNode:
- return s.evalFunction(dot, arg, arg, nil, zero)
+ return s.validateType(s.evalFunction(dot, arg, arg, nil, zero), typ)
case *parse.ChainNode:
return s.validateType(s.evalChainNode(dot, arg, nil, zero), typ)
}
diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go
index abce27ff3d..0f1ad62380 100644
--- a/src/text/template/exec_test.go
+++ b/src/text/template/exec_test.go
@@ -531,6 +531,8 @@ var execTests = []execTest{
{"bug14a", "{{(nil).True}}", "", tVal, false},
{"bug14b", "{{$x := nil}}{{$x.anything}}", "", tVal, false},
{"bug14c", `{{$x := (1.0)}}{{$y := ("hello")}}{{$x.anything}}{{$y.true}}`, "", tVal, false},
+ // Didn't call validateType on function results. Issue 10800.
+ {"bug15", "{{valueString returnInt}}", "", tVal, false},
}
func zeroArgs() string {
@@ -570,6 +572,11 @@ func valueString(v string) string {
return "value is ignored"
}
+// returnInt returns an int
+func returnInt() int {
+ return 7
+}
+
func add(args ...int) int {
sum := 0
for _, x := range args {
@@ -611,6 +618,7 @@ func testExecute(execTests []execTest, template *Template, t *testing.T) {
"makemap": makemap,
"mapOfThree": mapOfThree,
"oneArg": oneArg,
+ "returnInt": returnInt,
"stringer": stringer,
"typeOf": typeOf,
"valueString": valueString,
diff --git a/src/text/template/funcs.go b/src/text/template/funcs.go
index cdd187bda2..ccd0dfc80d 100644
--- a/src/text/template/funcs.go
+++ b/src/text/template/funcs.go
@@ -92,6 +92,8 @@ func goodFunc(typ reflect.Type) bool {
// findFunction looks for a function in the template, and global map.
func findFunction(name string, tmpl *Template) (reflect.Value, bool) {
if tmpl != nil && tmpl.common != nil {
+ tmpl.muFuncs.RLock()
+ defer tmpl.muFuncs.RUnlock()
if fn := tmpl.execFuncs[name]; fn.IsValid() {
return fn, true
}
diff --git a/src/text/template/template.go b/src/text/template/template.go
index 8611faad9f..a7c5c8cd2c 100644
--- a/src/text/template/template.go
+++ b/src/text/template/template.go
@@ -7,18 +7,20 @@ package template
import (
"fmt"
"reflect"
+ "sync"
"text/template/parse"
)
// common holds the information shared by related templates.
type common struct {
- tmpl map[string]*Template
+ tmpl map[string]*Template
+ option option
// We use two maps, one for parsing and one for execution.
// This separation makes the API cleaner since it doesn't
// expose reflection to the client.
+ muFuncs sync.RWMutex // protects parseFuncs and execFuncs
parseFuncs FuncMap
execFuncs map[string]reflect.Value
- option option
}
// Template is the representation of a parsed template. The *parse.Tree
@@ -84,6 +86,8 @@ func (t *Template) Clone() (*Template, error) {
tmpl := v.copy(nt.common)
nt.tmpl[k] = tmpl
}
+ t.muFuncs.RLock()
+ defer t.muFuncs.RUnlock()
for k, v := range t.parseFuncs {
nt.parseFuncs[k] = v
}
@@ -146,6 +150,8 @@ func (t *Template) Delims(left, right string) *Template {
// value is the template, so calls can be chained.
func (t *Template) Funcs(funcMap FuncMap) *Template {
t.init()
+ t.muFuncs.Lock()
+ defer t.muFuncs.Unlock()
addValueFuncs(t.execFuncs, funcMap)
addFuncs(t.parseFuncs, funcMap)
return t
@@ -169,7 +175,9 @@ func (t *Template) Lookup(name string) *Template {
// can contain text other than space, comments, and template definitions.)
func (t *Template) Parse(text string) (*Template, error) {
t.init()
+ t.muFuncs.RLock()
trees, err := parse.Parse(t.name, text, t.leftDelim, t.rightDelim, t.parseFuncs, builtins)
+ t.muFuncs.RUnlock()
if err != nil {
return nil, err
}