@@ -27,9 +27,7 @@ type Template struct {
27
27
// template's in sync.
28
28
text * template.Template
29
29
// The underlying template's parse tree, updated to be HTML-safe.
30
- Tree * parse.Tree
31
- // The original functions, before wrapping.
32
- funcMap FuncMap
30
+ Tree * parse.Tree
33
31
* nameSpace // common to all associated templates
34
32
}
35
33
@@ -42,6 +40,8 @@ type nameSpace struct {
42
40
set map [string ]* Template
43
41
escaped bool
44
42
esc escaper
43
+ // The original functions, before wrapping.
44
+ funcMap FuncMap
45
45
}
46
46
47
47
// Templates returns a slice of the templates associated with t, including t
@@ -260,7 +260,6 @@ func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error
260
260
nil ,
261
261
text ,
262
262
text .Tree ,
263
- nil ,
264
263
t .nameSpace ,
265
264
}
266
265
t .set [name ] = ret
@@ -287,14 +286,19 @@ func (t *Template) Clone() (*Template, error) {
287
286
}
288
287
ns := & nameSpace {set : make (map [string ]* Template )}
289
288
ns .esc = makeEscaper (ns )
289
+ if t .nameSpace .funcMap != nil {
290
+ ns .funcMap = make (FuncMap , len (t .nameSpace .funcMap ))
291
+ for name , fn := range t .nameSpace .funcMap {
292
+ ns .funcMap [name ] = fn
293
+ }
294
+ }
295
+ wrapFuncs (ns , textClone , ns .funcMap )
290
296
ret := & Template {
291
297
nil ,
292
298
textClone ,
293
299
textClone .Tree ,
294
- t .funcMap ,
295
300
ns ,
296
301
}
297
- ret .wrapFuncs ()
298
302
ret .set [ret .Name ()] = ret
299
303
for _ , x := range textClone .Templates () {
300
304
name := x .Name ()
@@ -307,10 +311,8 @@ func (t *Template) Clone() (*Template, error) {
307
311
nil ,
308
312
x ,
309
313
x .Tree ,
310
- src .funcMap ,
311
314
ret .nameSpace ,
312
315
}
313
- tc .wrapFuncs ()
314
316
ret .set [name ] = tc
315
317
}
316
318
// Return the template associated with the name of this template.
@@ -325,7 +327,6 @@ func New(name string) *Template {
325
327
nil ,
326
328
template .New (name ),
327
329
nil ,
328
- nil ,
329
330
ns ,
330
331
}
331
332
tmpl .set [name ] = tmpl
@@ -351,7 +352,6 @@ func (t *Template) new(name string) *Template {
351
352
nil ,
352
353
t .text .New (name ),
353
354
nil ,
354
- nil ,
355
355
t .nameSpace ,
356
356
}
357
357
if existing , ok := tmpl .set [name ]; ok {
@@ -382,23 +382,31 @@ type FuncMap map[string]interface{}
382
382
// type. However, it is legal to overwrite elements of the map. The return
383
383
// value is the template, so calls can be chained.
384
384
func (t * Template ) Funcs (funcMap FuncMap ) * Template {
385
- t .funcMap = funcMap
386
- t .wrapFuncs ()
385
+ t .nameSpace .mu .Lock ()
386
+ if t .nameSpace .funcMap == nil {
387
+ t .nameSpace .funcMap = make (FuncMap , len (funcMap ))
388
+ }
389
+ for name , fn := range funcMap {
390
+ t .nameSpace .funcMap [name ] = fn
391
+ }
392
+ t .nameSpace .mu .Unlock ()
393
+
394
+ wrapFuncs (t .nameSpace , t .text , funcMap )
387
395
return t
388
396
}
389
397
390
398
// wrapFuncs records the functions with text/template. We wrap them to
391
399
// unlock the nameSpace. See TestRecursiveExecute for a test case.
392
- func ( t * Template ) wrapFuncs ( ) {
393
- if len (t . funcMap ) == 0 {
400
+ func wrapFuncs ( ns * nameSpace , textTemplate * template. Template , funcMap FuncMap ) {
401
+ if len (funcMap ) == 0 {
394
402
return
395
403
}
396
- tfuncs := make (template.FuncMap , len (t . funcMap ))
397
- for name , fn := range t . funcMap {
404
+ tfuncs := make (template.FuncMap , len (funcMap ))
405
+ for name , fn := range funcMap {
398
406
fnv := reflect .ValueOf (fn )
399
407
wrapper := func (args []reflect.Value ) []reflect.Value {
400
- t . nameSpace .mu .RUnlock ()
401
- defer t . nameSpace .mu .RLock ()
408
+ ns .mu .RUnlock ()
409
+ defer ns .mu .RLock ()
402
410
if fnv .Type ().IsVariadic () {
403
411
return fnv .CallSlice (args )
404
412
} else {
@@ -408,7 +416,7 @@ func (t *Template) wrapFuncs() {
408
416
wrapped := reflect .MakeFunc (fnv .Type (), wrapper )
409
417
tfuncs [name ] = wrapped .Interface ()
410
418
}
411
- t . text .Funcs (tfuncs )
419
+ textTemplate .Funcs (tfuncs )
412
420
}
413
421
414
422
// Delims sets the action delimiters to the specified strings, to be used in
0 commit comments