]> Cypherpunks.ru repositories - gostls13.git/commitdiff
text/template: undo reflect.Value wrapping for short-circuit and/or
authorIan Lance Taylor <iant@golang.org>
Fri, 1 Oct 2021 19:32:41 +0000 (12:32 -0700)
committerIan Lance Taylor <iant@golang.org>
Fri, 1 Oct 2021 23:51:16 +0000 (23:51 +0000)
For #31103

Change-Id: I9c0aa64f95f564de31a4c178e3930584d41316bb
Reviewed-on: https://go-review.googlesource.com/c/go/+/353610
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
src/text/template/exec.go
src/text/template/exec_test.go

index fce3b0abbf7d50eaf9fe4b6d394d6e3b55bc6a46..9a4c9e29dd3071bdb32315417960c946cbf5a61c 100644 (file)
@@ -714,6 +714,13 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node
                s.errorf("can't call method/function %q with %d results", name, typ.NumOut())
        }
 
+       unwrap := func(v reflect.Value) reflect.Value {
+               if v.Type() == reflectValueType {
+                       v = v.Interface().(reflect.Value)
+               }
+               return v
+       }
+
        // Special case for builtin and/or, which short-circuit.
        if isBuiltin && (name == "and" || name == "or") {
                argType := typ.In(0)
@@ -721,13 +728,13 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node
                for _, arg := range args {
                        v = s.evalArg(dot, argType, arg).Interface().(reflect.Value)
                        if truth(v) == (name == "or") {
-                               return v
+                               return unwrap(v)
                        }
                }
                if final != missingVal {
                        v = s.validateType(final, argType)
                }
-               return v
+               return unwrap(v)
        }
 
        // Build the arg list.
@@ -767,10 +774,7 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node
                s.at(node)
                s.errorf("error calling %s: %w", name, err)
        }
-       if v.Type() == reflectValueType {
-               v = v.Interface().(reflect.Value)
-       }
-       return v
+       return unwrap(v)
 }
 
 // canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero.
index a0432a588d08915163484d53d2413265ad756e68..1a839a641b05c3ca0999e4931d473b1d45a5ab49 100644 (file)
@@ -491,6 +491,7 @@ var execTests = []execTest{
        {"or pipe-false", "{{0 | or 0}}", "0", nil, true},
        {"boolean if", "{{if and true 1 `hi`}}TRUE{{else}}FALSE{{end}}", "TRUE", tVal, true},
        {"boolean if not", "{{if and true 1 `hi` | not}}TRUE{{else}}FALSE{{end}}", "FALSE", nil, true},
+       {"boolean if pipe", "{{if true | not | and 1}}TRUE{{else}}FALSE{{end}}", "FALSE", nil, true},
 
        // Indexing.
        {"slice[0]", "{{index .SI 0}}", "3", tVal, true},