]> Cypherpunks repositories - gostls13.git/commitdiff
html/template: always write untyped nil as JS null
authorDaniel Martí <mvdan@mvdan.cc>
Wed, 25 Apr 2018 02:45:53 +0000 (11:45 +0900)
committerDaniel Martí <mvdan@mvdan.cc>
Wed, 9 May 2018 04:09:29 +0000 (04:09 +0000)
text/template recently added support for passing untyped nil as function
call arguments, as those would be mixed up with "missing argument"
values before. See CL 95215.

html/template now needs a small change to adapt to that new possibility.
In particular, when printing values as JS bytes, its code was written
under the assumption that the values would never be untyped nil - that
is, the reflect.Value would always be valid.

Short-circuit indirectToJSONMarshaler on an untyped nil, to avoid the
panic and fall back to the existing " null " output. Before this change
and on 1.10, printing a typed nil and an untyped nil resulted in:

null ""

After this change, one will get:

null null

Fixes #24717.

Change-Id: I03cd10ef64b96e837bacc9ccf4cf25624d80de1c
Reviewed-on: https://go-review.googlesource.com/109215
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rhys Hiltner <rhys@justin.tv>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/html/template/js.go
src/html/template/js_test.go

index 239395f8d3a53bb26d911b3089a3df23ee716722..e02fdb97517e1c3a282bab56b22f8bb92d9775d9 100644 (file)
@@ -123,6 +123,14 @@ var jsonMarshalType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
 // indirectToJSONMarshaler returns the value, after dereferencing as many times
 // as necessary to reach the base type (or nil) or an implementation of json.Marshal.
 func indirectToJSONMarshaler(a interface{}) interface{} {
+       // text/template now supports passing untyped nil as a func call
+       // argument, so we must support it. Otherwise we'd panic below, as one
+       // cannot call the Type or Interface methods on an invalid
+       // reflect.Value. See golang.org/issue/18716.
+       if a == nil {
+               return nil
+       }
+
        v := reflect.ValueOf(a)
        for !v.Type().Implements(jsonMarshalType) && v.Kind() == reflect.Ptr && !v.IsNil() {
                v = v.Elem()
index 7484f60b54dc6fc6cc8aaa20ffedcb33c028569a..cf2a0d298739f7bcc45a0512a0d7f2e8a2b19940 100644 (file)
@@ -149,6 +149,7 @@ func TestJSValEscaper(t *testing.T) {
                {"]]>", `"]]\u003e"`},
                {"</script", `"\u003c/script"`},
                {"\U0001D11E", "\"\U0001D11E\""}, // or "\uD834\uDD1E"
+               {nil, " null "},
        }
 
        for _, test := range tests {