aboutsummaryrefslogtreecommitdiff
path: root/src/text/template/parse
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2018-02-05 15:50:29 -0800
committerIan Lance Taylor <iant@golang.org>2018-02-06 05:00:01 +0000
commitfd7331a821a6b79d5f2f82075c032ac459670d7d (patch)
tree1cc0bc54fd8c5ca07a2fe30bd059b9a5d80cb485 /src/text/template/parse
parentf54f780d2f4ed47da4bed87c37f7219df1b9879b (diff)
downloadgo-fd7331a821a6b79d5f2f82075c032ac459670d7d.tar.xz
text/template: revert CL 66410 "add break, continue actions in ranges"
The new break and continue actions do not work in html/template, and fixing them requires thinking about security issues that seem too tricky at this stage of the release. We will try again for 1.11. Original CL description: text/template: add break, continue actions in ranges Adds the two range control actions "break" and "continue". They act the same as the Go keywords break and continue, but are simplified in that only the innermost range statement can be broken out of or continued. Fixes #20531 Updates #20531 Updates #23683 Change-Id: Ia7fd3c409163e3bcb5dc42947ae90b15bdf89853 Reviewed-on: https://go-review.googlesource.com/92155 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/text/template/parse')
-rw-r--r--src/text/template/parse/lex.go4
-rw-r--r--src/text/template/parse/lex_test.go6
-rw-r--r--src/text/template/parse/node.go64
-rw-r--r--src/text/template/parse/parse.go44
-rw-r--r--src/text/template/parse/parse_test.go12
5 files changed, 7 insertions, 123 deletions
diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go
index da766cc7c3..e112cb7714 100644
--- a/src/text/template/parse/lex.go
+++ b/src/text/template/parse/lex.go
@@ -60,8 +60,6 @@ const (
// Keywords appear after all the rest.
itemKeyword // used only to delimit the keywords
itemBlock // block keyword
- itemBreak // break keyword
- itemContinue // continue keyword
itemDot // the cursor, spelled '.'
itemDefine // define keyword
itemElse // else keyword
@@ -76,8 +74,6 @@ const (
var key = map[string]itemType{
".": itemDot,
"block": itemBlock,
- "break": itemBreak,
- "continue": itemContinue,
"define": itemDefine,
"else": itemElse,
"end": itemEnd,
diff --git a/src/text/template/parse/lex_test.go b/src/text/template/parse/lex_test.go
index ca7c3f64bc..cb01cd98b6 100644
--- a/src/text/template/parse/lex_test.go
+++ b/src/text/template/parse/lex_test.go
@@ -192,7 +192,7 @@ var lexTests = []lexTest{
tRight,
tEOF,
}},
- {"keywords", "{{range if else end with break continue}}", []item{
+ {"keywords", "{{range if else end with}}", []item{
tLeft,
mkItem(itemRange, "range"),
tSpace,
@@ -203,10 +203,6 @@ var lexTests = []lexTest{
mkItem(itemEnd, "end"),
tSpace,
mkItem(itemWith, "with"),
- tSpace,
- mkItem(itemBreak, "break"),
- tSpace,
- mkItem(itemContinue, "continue"),
tRight,
tEOF,
}},
diff --git a/src/text/template/parse/node.go b/src/text/template/parse/node.go
index 7e16349b31..55ff46c17a 100644
--- a/src/text/template/parse/node.go
+++ b/src/text/template/parse/node.go
@@ -69,8 +69,6 @@ const (
NodeTemplate // A template invocation action.
NodeVariable // A $ variable.
NodeWith // A with action.
- NodeBreak // A break action.
- NodeContinue // A continue action.
)
// Nodes.
@@ -798,68 +796,6 @@ func (r *RangeNode) Copy() Node {
return r.tr.newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
}
-// BreakNode represents a {{break}} action.
-type BreakNode struct {
- NodeType
- Pos
- tr *Tree
-}
-
-func (t *Tree) newBreak(pos Pos) *BreakNode {
- return &BreakNode{NodeType: NodeBreak, Pos: pos, tr: t}
-}
-
-func (b *BreakNode) Type() NodeType {
- return b.NodeType
-}
-
-func (b *BreakNode) String() string {
- return "{{break}}"
-}
-
-func (b *BreakNode) Copy() Node {
- return b.tr.newBreak(b.Pos)
-}
-
-func (b *BreakNode) Position() Pos {
- return b.Pos
-}
-
-func (b *BreakNode) tree() *Tree {
- return b.tr
-}
-
-// ContinueNode represents a {{continue}} action.
-type ContinueNode struct {
- NodeType
- Pos
- tr *Tree
-}
-
-func (t *Tree) newContinue(pos Pos) *ContinueNode {
- return &ContinueNode{NodeType: NodeContinue, Pos: pos, tr: t}
-}
-
-func (c *ContinueNode) Type() NodeType {
- return c.NodeType
-}
-
-func (c *ContinueNode) String() string {
- return "{{continue}}"
-}
-
-func (c *ContinueNode) Copy() Node {
- return c.tr.newContinue(c.Pos)
-}
-
-func (c *ContinueNode) Position() Pos {
- return c.Pos
-}
-
-func (c *ContinueNode) tree() *Tree {
- return c.tr
-}
-
// WithNode represents a {{with}} action and its commands.
type WithNode struct {
BranchNode
diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go
index ad9c051978..a91a544ce0 100644
--- a/src/text/template/parse/parse.go
+++ b/src/text/template/parse/parse.go
@@ -23,13 +23,12 @@ type Tree struct {
Root *ListNode // top-level root of the tree.
text string // text parsed to create the template (or its parent)
// Parsing only; cleared after parse.
- funcs []map[string]interface{}
- lex *lexer
- token [3]item // three-token lookahead for parser.
- peekCount int
- vars []string // variables defined at the moment.
- treeSet map[string]*Tree
- rangeDepth int // nesting level of range loops.
+ funcs []map[string]interface{}
+ lex *lexer
+ token [3]item // three-token lookahead for parser.
+ peekCount int
+ vars []string // variables defined at the moment.
+ treeSet map[string]*Tree
}
// Copy returns a copy of the Tree. Any parsing state is discarded.
@@ -220,7 +219,6 @@ func (t *Tree) stopParse() {
t.vars = nil
t.funcs = nil
t.treeSet = nil
- t.rangeDepth = 0
}
// Parse parses the template definition string to construct a representation of
@@ -375,10 +373,6 @@ func (t *Tree) action() (n Node) {
return t.templateControl()
case itemWith:
return t.withControl()
- case itemBreak:
- return t.breakControl()
- case itemContinue:
- return t.continueControl()
}
t.backup()
token := t.peek()
@@ -459,13 +453,7 @@ func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int
defer t.popVars(len(t.vars))
pipe = t.pipeline(context)
var next Node
- if context == "range" {
- t.rangeDepth++
- }
list, next = t.itemList()
- if context == "range" {
- t.rangeDepth--
- }
switch next.Type() {
case nodeEnd: //done
case nodeElse:
@@ -510,26 +498,6 @@ func (t *Tree) rangeControl() Node {
return t.newRange(t.parseControl(false, "range"))
}
-// Break:
-// {{break}}
-// Break keyword is past.
-func (t *Tree) breakControl() Node {
- if t.rangeDepth == 0 {
- t.errorf("unexpected break outside of range")
- }
- return t.newBreak(t.expect(itemRightDelim, "break").pos)
-}
-
-// Continue:
-// {{continue}}
-// Continue keyword is past.
-func (t *Tree) continueControl() Node {
- if t.rangeDepth == 0 {
- t.errorf("unexpected continue outside of range")
- }
- return t.newContinue(t.expect(itemRightDelim, "continue").pos)
-}
-
// With:
// {{with pipeline}} itemList {{end}}
// {{with pipeline}} itemList {{else}} itemList {{end}}
diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go
index aade33ea48..81f14aca98 100644
--- a/src/text/template/parse/parse_test.go
+++ b/src/text/template/parse/parse_test.go
@@ -218,12 +218,6 @@ var parseTests = []parseTest{
`{{range $x := .SI}}{{.}}{{end}}`},
{"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError,
`{{range $x, $y := .SI}}{{.}}{{end}}`},
- {"range []int with break", "{{range .SI}}{{break}}{{.}}{{end}}", noError,
- `{{range .SI}}{{break}}{{.}}{{end}}`},
- {"range []int with break in else", "{{range .SI}}{{range .SI}}{{.}}{{else}}{{break}}{{end}}{{end}}", noError,
- `{{range .SI}}{{range .SI}}{{.}}{{else}}{{break}}{{end}}{{end}}`},
- {"range []int with continue", "{{range .SI}}{{continue}}{{.}}{{end}}", noError,
- `{{range .SI}}{{continue}}{{.}}{{end}}`},
{"constants", "{{range .SI 1 -3.2i true false 'a' nil}}{{end}}", noError,
`{{range .SI 1 -3.2i true false 'a' nil}}{{end}}`},
{"template", "{{template `x`}}", noError,
@@ -294,12 +288,6 @@ var parseTests = []parseTest{
{"empty pipeline", `{{printf "%d" ( ) }}`, hasError, ""},
// Missing pipeline in block
{"block definition", `{{block "foo"}}hello{{end}}`, hasError, ""},
- // Invalid range control
- {"break outside of range", `{{break}}`, hasError, ""},
- {"break in range else, outside of range", `{{range .}}{{.}}{{else}}{{break}}{{end}}`, hasError, ""},
- {"continue outside of range", `{{continue}}`, hasError, ""},
- {"continue in range else, outside of range", `{{range .}}{{.}}{{else}}{{continue}}{{end}}`, hasError, ""},
- {"additional break data", `{{range .}}{{break label}}{{end}}`, hasError, ""},
}
var builtins = map[string]interface{}{