This adds a new lock protecting "tmpl".
This is a copy of https://golang.org/cl/257817 by Andreas Fleig,
updated for current tip, and updated to start running the
html/template TestEscapeRace test.
Thanks to @bep for providing the test case.
For #39807Fixes#47042
Change-Id: Ic8874484290283a49116812eeaffb8608346dc70
Reviewed-on: https://go-review.googlesource.com/c/go/+/316669
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
(cherry picked from commit 496d7c6914)
Reviewed-on: https://go-review.googlesource.com/c/go/+/348580
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
The comment "If the name is the name of this template, overwrite this template."
is incorrect and should be "is not" instead. This comment is no longer
required once the docs are updated to mention this behaviour instead.
Fixes#34695
Change-Id: I773495b2194d7bb7619b13c1a28cbc76e8f69aac
Reviewed-on: https://go-review.googlesource.com/c/go/+/199139
Reviewed-by: Rob Pike <r@golang.org>
Template.New calls t.init, which allocates several items that
are immediately rewritten by copy, so avoid the call to New
Change-Id: I16c7cb001bbcd14cf547c1a2db2734a2f8214e7e
Reviewed-on: https://go-review.googlesource.com/c/go/+/182757
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
In particular, the returned template isn't independent from the parent.
For example, it can't be parsed concurrently with other children
templates. Only methods which are explicitly safe for concurrent use,
like Execute, may be used concurrently.
Fixes#30281.
Change-Id: Idc84bf4199c035316cdb83b950fd4a8f2a71cd0c
Reviewed-on: https://go-review.googlesource.com/c/go/+/172297
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
It's always nil, so simplify its signature. Found with unparam.
Change-Id: I45dd0f868ec2f5de98a970776be686417c8d73b6
Reviewed-on: https://go-review.googlesource.com/95235
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This was a subtle bug introduced in the previous release's fix for
issue 16156.
The definition of empty template was broken, causing the answer
to depend on the order of templates in the map.
Fixes#16156 (for real).
Fixes#19294.
Fixes#19204.
Change-Id: I1cd915c94534cad3116d83bd158cbc28700510b9
Reviewed-on: https://go-review.googlesource.com/38420
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Any method that affects the parse must happen before parsing.
This obvious point is clear, but it's not clear to some that the
set of defined functions affect the parse.
Fixes#18971
Change-Id: I8b7f8c8cf85b028c18e5ca3b9797de92ea910669
Reviewed-on: https://go-review.googlesource.com/38413
Reviewed-by: Ian Lance Taylor <iant@golang.org>
All prior versions of Go have allowed redefining empty templates
to become non-empty. Unfortunately, that has never consistently
taken effect in html/template after the first execution:
// define and execute
t := template.New("root")
t.Parse(`{{define "T"}}{{end}}<a href="{{template "T"}}">`)
t.Execute(w, nil) // <a href="">
// redefine
t.Parse(`{{define "T"}}my.url{{end}}`) // succeeds, but ignored
t.Execute(w, nil) // <a href="">
When Go 1.6 added {{block...}} to text/template, that loosened the
redefinition rules to allow redefinition at any time. The loosening was
undone a bit in html/template, although inconsistently:
// define and execute
t := template.New("root")
t.Parse(`{{define "T"}}body{{end}}`)
t.Lookup("T").Execute(ioutil.Discard, nil)
// attempt to redefine
t.Parse(`{{define "T"}}body{{end}}`) // rejected in all Go versions
t.Lookup("T").Parse("body") // OK as of Go 1.6, likely unintentionally
Like in the empty->non-empty case, whether future execution takes
notice of a redefinition basically can't be explained without going into
the details of the template escape analysis.
Address both the original inconsistencies in whether a redefinition
would have any effect and the new inconsistencies about whether a
redefinition is allowed by adopting a new rule: no parsing or modifying
any templates after the first execution of any template in the same set.
Template analysis begins at first execution, and once template analysis
has begun, we simply don't have the right logic to update the analysis
for incremental modifications (and never have).
If this new rule breaks existing uses of templates that we decide need
to be supported, we can try to invalidate all escape analysis for the
entire set after any modifications. But let's wait on that until we know
we need to and why.
Also fix documentation of text/template redefinition policy
(redefinition is always OK).
Fixes#15761.
Change-Id: I7d58d7c08a7d9df2440ee0d651a5b2ecaff3006c
Reviewed-on: https://go-review.googlesource.com/31464
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
Make two important points clearer:
- Giving a template definition containing
nothing but spaces has no effect.
- Giving a template definition containing
non-spaces can only be done once per template.
Fixes#16912.
Fixes#16913.
Fixes#17360.
Change-Id: Ie3971b83ab148b7c8bb800fe4a21579566378e3e
Reviewed-on: https://go-review.googlesource.com/31459
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
This change adds a new "block" keyword that permits the definition
of templates inline inside existing templates, and loosens the
restriction on template redefinition. Templates may now be redefined,
but in the html/template package they may only be redefined before
the template is executed (and therefore escaped).
The intention is that such inline templates can be redefined by
subsequent template definitions, permitting a kind of template
"inheritance" or "overlay". (See the example for details.)
Fixes#3812
Change-Id: I733cb5332c1c201c235f759cc64333462e70dc27
Reviewed-on: https://go-review.googlesource.com/14005
Reviewed-by: Rob Pike <r@golang.org>
There was no verification in Funcs that the map had valid names,
which meant that the error could only be caught when parsing
the template that tried to use them. Fix this by validating the names
in Funcs and panicking before parsing if there is a bad name.
This is arguably an API change, since it didn't trigger a panic
before, but Funcs did already panic if the function itself was no
good, so I argue it's an acceptable change to add more sanity
checks.
Fixes#9685.
Change-Id: Iabf1d0602c49d830f3ed71ca1ccc7eb9a5521ff5
Reviewed-on: https://go-review.googlesource.com/14562
Reviewed-by: Andrew Gerrand <adg@golang.org>
This is follow-up to CL10607
- Refactor AddParseTree() to use t.associate()
- Refactor Parse() to use AddParseTree() to put entries into common structure
- Clone() should not put entry in t.tmpl for undefined template
- Clarify documentation for Templates()
- Clarify documentation for AddParseTree() to include the error case
Updates #10910
Uodates #10926
Includes test cases for most of the above changes
Change-Id: I25b2fce6f9651272866f881acf44e4dbca04a4a8
Reviewed-on: https://go-review.googlesource.com/10622
Reviewed-by: Rob Pike <r@golang.org>
Run-TryBot: Rob Pike <r@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Due to the requirements of parsing template definitions that mention
other templates that are not yet defined, a Template can be in two states:
defined and undefined. Thus, although one calls New, the resulting
template has no definition even though it exists as a data structure.
Thus, for example, will return nil for a template that is named but not
yet defined.
Fixes#10910Fixes#10926
Clarify the documentation a little to explain this,
Also tidy up the code a little and remove a spurious call to init.
Change-Id: I22cc083291500bca424e83dc12807e0de7b00b7a
Reviewed-on: https://go-review.googlesource.com/10641
Reviewed-by: Andrew Gerrand <adg@golang.org>
t.init() should be called at the time of template creation
i.e, template.New() and t.New() instead of later in the process.
- Removed calls of t.init() from t.Parse(), t.Execute(), t.Funcs()
- Also got rid of t.common != nil checks as it should never be nil
Fixes#10879
Change-Id: I1b7ac812f02c841ae80037babce7e2b0a2df13e8
Reviewed-on: https://go-review.googlesource.com/10240
Reviewed-by: Rob Pike <r@golang.org>
The Template objects are supposed to be goroutine-safe once they
have been parsed. This includes the text and html ones.
For html/template, the escape mechanism is triggered at execution
time. It may alter the internal structures of the template, so
a mutex protects them against concurrent accesses.
The text/template package is free of any synchronization primitive.
A race condition may occur when nested templates are escaped:
the escape algorithm alters the function maps of the associated
text templates, while a concurrent template execution may access
the function maps in read mode.
The less invasive fix I have found is to introduce a RWMutex in
text/template to protect the function maps. This is unfortunate
but it should be effective.
Fixes#9945
Change-Id: I1edb73c0ed0f1fcddd2f1516230b548b92ab1269
Reviewed-on: https://go-review.googlesource.com/10101
Reviewed-by: Rob Pike <r@golang.org>
Add one option, which is the motivating example, a way to control
what happens when a map is indexed with a key that is not in the map.
Rather than do something specific for that case, we provide a simple
general option mechanism to avoid adding API if something else
comes up. This general approach also makes it easy for html/template
to track (and adapt, should that become important).
New method: Option(option string...). The option strings are key=value
pairs or just simple strings (no =).
New option:
missingkey: Control the behavior during execution if a map is
indexed with a key that is not present in the map.
"missingkey=default" or "missingkey=invalid"
The default behavior: Do nothing and continue execution.
If printed, the result of the index operation is the string
"<no value>".
"missingkey=zero"
The operation returns the zero value for the map type's element.
"missingkey=error"
Execution stops immediately with an error.
Fixes#6288.
Change-Id: Id811e2b99dc05aff324d517faac113ef3c25293a
Reviewed-on: https://go-review.googlesource.com/8462
Reviewed-by: Robert Griesemer <gri@golang.org>