summaryrefslogtreecommitdiff
path: root/libgo/go/html/template
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/html/template')
-rw-r--r--libgo/go/html/template/css.go2
-rw-r--r--libgo/go/html/template/error.go6
-rw-r--r--libgo/go/html/template/escape.go10
-rw-r--r--libgo/go/html/template/escape_test.go16
-rw-r--r--libgo/go/html/template/template.go38
5 files changed, 49 insertions, 23 deletions
diff --git a/libgo/go/html/template/css.go b/libgo/go/html/template/css.go
index b0a2f013d29..3bcd9849831 100644
--- a/libgo/go/html/template/css.go
+++ b/libgo/go/html/template/css.go
@@ -106,7 +106,7 @@ func isHex(c byte) bool {
// hexDecode decodes a short hex digit sequence: "10" -> 16.
func hexDecode(s []byte) rune {
- n := rune(0)
+ n := '\x00'
for _, c := range s {
n <<= 4
switch {
diff --git a/libgo/go/html/template/error.go b/libgo/go/html/template/error.go
index 9622d7e48ee..dcac7489676 100644
--- a/libgo/go/html/template/error.go
+++ b/libgo/go/html/template/error.go
@@ -183,11 +183,11 @@ const (
func (e *Error) Error() string {
if e.Line != 0 {
- return fmt.Sprintf("exp/template/html:%s:%d: %s", e.Name, e.Line, e.Description)
+ return fmt.Sprintf("html/template:%s:%d: %s", e.Name, e.Line, e.Description)
} else if e.Name != "" {
- return fmt.Sprintf("exp/template/html:%s: %s", e.Name, e.Description)
+ return fmt.Sprintf("html/template:%s: %s", e.Name, e.Description)
}
- return "exp/template/html: " + e.Description
+ return "html/template: " + e.Description
}
// errorf creates an error given a format string f and args.
diff --git a/libgo/go/html/template/escape.go b/libgo/go/html/template/escape.go
index 2f6be3b6c21..c6f723ae4a4 100644
--- a/libgo/go/html/template/escape.go
+++ b/libgo/go/html/template/escape.go
@@ -486,9 +486,17 @@ func (e *escaper) escapeTree(c context, name string, line int) (context, string)
}
t := e.template(name)
if t == nil {
+ // Two cases: The template exists but is empty, or has never been mentioned at
+ // all. Distinguish the cases in the error messages.
+ if e.tmpl.set[name] != nil {
+ return context{
+ state: stateError,
+ err: errorf(ErrNoSuchTemplate, line, "%q is an incomplete or empty template", name),
+ }, dname
+ }
return context{
state: stateError,
- err: errorf(ErrNoSuchTemplate, line, "no such template %s", name),
+ err: errorf(ErrNoSuchTemplate, line, "no such template %q", name),
}, dname
}
if dname != name {
diff --git a/libgo/go/html/template/escape_test.go b/libgo/go/html/template/escape_test.go
index cdeed48b822..a57f9826b5b 100644
--- a/libgo/go/html/template/escape_test.go
+++ b/libgo/go/html/template/escape_test.go
@@ -654,7 +654,7 @@ func TestEscape(t *testing.T) {
for _, test := range tests {
tmpl := New(test.name)
// TODO: Move noescape into template/func.go
- tmpl.Funcs(template.FuncMap{
+ tmpl.Funcs(FuncMap{
"noescape": func(a ...interface{}) string {
return fmt.Sprint(a...)
},
@@ -792,7 +792,7 @@ func TestEscapeSet(t *testing.T) {
// pred is a template function that returns the predecessor of a
// natural number for testing recursive templates.
- fns := template.FuncMap{"pred": func(a ...interface{}) (interface{}, error) {
+ fns := FuncMap{"pred": func(a ...interface{}) (interface{}, error) {
if len(a) == 1 {
if i, _ := a[0].(int); i > 0 {
return i - 1, nil
@@ -928,7 +928,7 @@ func TestErrors(t *testing.T) {
},
{
`{{template "foo"}}`,
- "z:1: no such template foo",
+ "z:1: no such template \"foo\"",
},
{
`<div{{template "y"}}>` +
@@ -944,23 +944,23 @@ func TestErrors(t *testing.T) {
},
{
`<input type=button value=onclick=>`,
- `exp/template/html:z: "=" in unquoted attr: "onclick="`,
+ `html/template:z: "=" in unquoted attr: "onclick="`,
},
{
`<input type=button value= onclick=>`,
- `exp/template/html:z: "=" in unquoted attr: "onclick="`,
+ `html/template:z: "=" in unquoted attr: "onclick="`,
},
{
`<input type=button value= 1+1=2>`,
- `exp/template/html:z: "=" in unquoted attr: "1+1=2"`,
+ `html/template:z: "=" in unquoted attr: "1+1=2"`,
},
{
"<a class=`foo>",
- "exp/template/html:z: \"`\" in unquoted attr: \"`foo\"",
+ "html/template:z: \"`\" in unquoted attr: \"`foo\"",
},
{
`<a style=font:'Arial'>`,
- `exp/template/html:z: "'" in unquoted attr: "font:'Arial'"`,
+ `html/template:z: "'" in unquoted attr: "font:'Arial'"`,
},
{
`<a=foo>`,
diff --git a/libgo/go/html/template/template.go b/libgo/go/html/template/template.go
index fa2ed18874c..9ffe41413a8 100644
--- a/libgo/go/html/template/template.go
+++ b/libgo/go/html/template/template.go
@@ -49,20 +49,28 @@ func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
// ExecuteTemplate applies the template associated with t that has the given
// name to the specified data object and writes the output to wr.
-func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) (err error) {
+func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
+ tmpl, err := t.lookupAndEscapeTemplate(wr, name)
+ if err != nil {
+ return err
+ }
+ return tmpl.text.Execute(wr, data)
+}
+
+// lookupAndEscapeTemplate guarantees that the template with the given name
+// is escaped, or returns an error if it cannot be. It returns the named
+// template.
+func (t *Template) lookupAndEscapeTemplate(wr io.Writer, name string) (tmpl *Template, err error) {
t.nameSpace.mu.Lock()
- tmpl := t.set[name]
+ defer t.nameSpace.mu.Unlock()
+ tmpl = t.set[name]
if (tmpl == nil) != (t.text.Lookup(name) == nil) {
panic("html/template internal error: template escaping out of sync")
}
if tmpl != nil && !tmpl.escaped {
err = escapeTemplates(tmpl, name)
}
- t.nameSpace.mu.Unlock()
- if err != nil {
- return
- }
- return t.text.ExecuteTemplate(wr, name, data)
+ return tmpl, err
}
// Parse parses a string into a template. Nested template definitions
@@ -146,12 +154,20 @@ func (t *Template) Name() string {
return t.text.Name()
}
+// FuncMap is the type of the map defining the mapping from names to
+// functions. Each function must have either a single return value, or two
+// return values of which the second has type error. In that case, if the
+// second (error) argument evaluates to non-nil during execution, execution
+// terminates and Execute returns that error. FuncMap has the same base type
+// as template.FuncMap, copied here so clients need not import "text/template".
+type FuncMap map[string]interface{}
+
// Funcs adds the elements of the argument map to the template's function map.
// It panics if a value in the map is not a function with appropriate return
// type. However, it is legal to overwrite elements of the map. The return
// value is the template, so calls can be chained.
-func (t *Template) Funcs(funcMap template.FuncMap) *Template {
- t.text.Funcs(funcMap)
+func (t *Template) Funcs(funcMap FuncMap) *Template {
+ t.text.Funcs(template.FuncMap(funcMap))
return t
}
@@ -175,7 +191,9 @@ func (t *Template) Lookup(name string) *Template {
// Must panics if err is non-nil in the same way as template.Must.
func Must(t *Template, err error) *Template {
- t.text = template.Must(t.text, err)
+ if err != nil {
+ panic(err)
+ }
return t
}