]> Cypherpunks repositories - gostls13.git/commitdiff
text/template: fix truth handling of typed interface nils in if and with
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sun, 10 Mar 2019 21:43:45 +0000 (21:43 +0000)
committerRob Pike <r@golang.org>
Tue, 14 May 2019 00:50:42 +0000 (00:50 +0000)
Before this commit, the two logically equivalent conditionals below would
produce different output:

    {{ if not .NonEmptyInterfaceTypedNil }}OK{{ else }}{{ end }}
    {{ if .NonEmptyInterfaceTypedNil }}{{ else }}OK{{ end }}

The functions `not`, `or`, and `and` all use the same `truth` function, which
unwraps any concrete interface value before passing it to `isTrue`.

`if` and `with` also use `isTrue` to establish truth, but was missing the
interface indirect call.

Fixes #30501

Change-Id: I9c49eed41e737d8f162e39bef1c3b82fd5518fed
GitHub-Last-Rev: 95fc2c82f26d24a457de4deaa7e5756718fbf07c
GitHub-Pull-Request: golang/go#30534
Reviewed-on: https://go-review.googlesource.com/c/go/+/164958
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>

src/text/template/exec.go
src/text/template/exec_test.go

index 0e2ab0e211e08ffcb54fabc60ed030c6ed549692..4db63bfa09dc651ef2d164397e7dd519d467cf87 100644 (file)
@@ -285,7 +285,7 @@ func (s *state) walk(dot reflect.Value, node parse.Node) {
 func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.PipeNode, list, elseList *parse.ListNode) {
        defer s.pop(s.mark())
        val := s.evalPipeline(dot, pipe)
-       truth, ok := isTrue(val)
+       truth, ok := isTrue(indirectInterface(val))
        if !ok {
                s.errorf("if/with can't use %v", val)
        }
index a95631718c190f03cf046e292d731ea7ec0a35ad..c45df89d59ff61d536ae69f00aea2df76964d0e3 100644 (file)
@@ -413,6 +413,7 @@ var execTests = []execTest{
        {"if true", "{{if true}}TRUE{{end}}", "TRUE", tVal, true},
        {"if false", "{{if false}}TRUE{{else}}FALSE{{end}}", "FALSE", tVal, true},
        {"if nil", "{{if nil}}TRUE{{end}}", "", tVal, false},
+       {"if on typed nil interface value", "{{if .NonEmptyInterfaceTypedNil}}TRUE{{ end }}", "", tVal, true},
        {"if 1", "{{if 1}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true},
        {"if 0", "{{if 0}}NON-ZERO{{else}}ZERO{{end}}", "ZERO", tVal, true},
        {"if 1.5", "{{if 1.5}}NON-ZERO{{else}}ZERO{{end}}", "NON-ZERO", tVal, true},
@@ -515,6 +516,7 @@ var execTests = []execTest{
        {"with $x int", "{{with $x := .I}}{{$x}}{{end}}", "17", tVal, true},
        {"with $x struct.U.V", "{{with $x := $}}{{$x.U.V}}{{end}}", "v", tVal, true},
        {"with variable and action", "{{with $x := $}}{{$y := $.U.V}}{{$y}}{{end}}", "v", tVal, true},
+       {"with on typed nil interface value", "{{with .NonEmptyInterfaceTypedNil}}TRUE{{ end }}", "", tVal, true},
 
        // Range.
        {"range []int", "{{range .SI}}-{{.}}-{{end}}", "-3--4--5-", tVal, true},