Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

html/template: recognize text/babel as synonym for text/javascript #20561

Closed
ghost opened this issue Jun 2, 2017 · 31 comments
Closed

html/template: recognize text/babel as synonym for text/javascript #20561

ghost opened this issue Jun 2, 2017 · 31 comments
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@ghost
Copy link

ghost commented Jun 2, 2017

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

1.8.3

What operating system and processor architecture are you using (go env)?

set GOARCH=amd64
set GOBIN=
set GOEXE=.exe
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=E:\Go\Studio
set GORACE=
set GOROOT=E:\Go\Golang
set GOTOOLDIR=E:\Go\Golang\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
set CXX=g++
set CGO_ENABLED=1
set PKG_CONFIG=pkg-config
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2

What did you do?

month ago ,I use go 1.7.4, today I upgrade go to 1.8.3,find the object can't right display in the template,so I compare the source 1.7.4 and 1.8.3, find the difference in text/template next, I don't understand why change this,the template can not parse json object right,and not give a option to user!

1.8.3:

// If data is a reflect.Value, the template applies to the concrete
// value that the reflect.Value holds, as in fmt.Print.

func (t *Template) execute(wr io.Writer, data interface{}) (err error) {
	defer errRecover(&err)
	value, ok := data.(reflect.Value)
	if !ok {
		value = reflect.ValueOf(data)

	}
	....
	return
}

1.7.4

func (t *Template) execute(wr io.Writer, data interface{}) (err error) {
	defer errRecover(&err)
	value := reflect.ValueOf(data)
        ...
	return
}

What did you expect to see?

how to solve the problem ?

@odeke-em
Copy link
Member

odeke-em commented Jun 3, 2017

@jmesyan thanks for the issue. Would you mind giving more detail on the exact problem for example a reproducible snippet of your bug? That way we can try to diagnose the problem and see what the bug is.

@odeke-em odeke-em added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Jun 3, 2017
@ALTree ALTree changed the title why go1.8 text/template object value can not return right data? text/template: why go1.8 object value can not return right data? Jun 3, 2017
@ghost
Copy link
Author

ghost commented Jun 3, 2017

make a example:

I hava a mysql database ,a table named grade to record the grade info, it has two fields-gid,gname.
I set the read struct next:

type Grade struct {
    Gid  int64
    Gname string
}

I select the data from the database by a mysql Third-Party Libraries and show in the template

models:
func GetGradeList() []Grade {
     sql := "select * from grade"
     condition := make([]interface{}, 0)
     result, err := DB.Select(sql, condition)
     utils.CheckError(err)
     var res []Grade 
    json.Unmarshal([]byte(result), &res)
    return res
}

controller:
...
list := models.GetGradeList()
fmt.Fprint(w, list) //I print the origin list in the browser
data := map[string]interface{}{
		"list": list,
}
...
t, err := t.ParseFiles(displayView)
if err != nil {
     fmt.Fprintf(w, "parse template error: %s", err.Error())
    return
}
err = t.Execute(w, data)
if err != nil {
	fmt.Fprint(w, err.Error())
}
...

views:
<script type="text/javascript">
...
var list = {{.list}}
console.log(list) //I print the template parse data in the browser
...
</script>

finally, I find in the go version 1.8.3 and 1.7.4 the origin print is the same,just like this:
[{1 grade1} {2 grade2} ...]

but the template parse data is different:
1.8.3 -[{1 grade1} {2 grade2} ...]
1.7.4-[{"Gid":1, "Gname":"grade1"}, {"Gid":2, "Gname":"grade2"},...]

The result of 1.7.4 is what i want, hope solve the problem quickly!

@vcabbage
Copy link
Member

vcabbage commented Jun 4, 2017

Please confirm whether you're using text/template or html/template as the results are formatted differently.

Here's an example comparing each: https://play.golang.org/p/j8wlM0lN8x

The results of that example are the same for Go 1.6, 1.7, and 1.8.

@ghost
Copy link
Author

ghost commented Jun 5, 2017

I am sure the problem, if use 1.8.3 the javascript can't traverse the list right @traverse

@vcabbage
Copy link
Member

vcabbage commented Jun 5, 2017

I understand, but the behavior has not change between releases. It appears that html/template has the behavior you want. Please try using html/template instead of text/template.

@ghost
Copy link
Author

ghost commented Jun 5, 2017

i use the html/template,and the html/template use the text/template , i find the problem in the text template, when i replace the 1.8.3 source code html and text module with 1.7.4 ,the javascript parse right!@traverse

@vcabbage
Copy link
Member

vcabbage commented Jun 5, 2017

@jmesyan I posted an example above showing the different results with using html/template and text/template. The output is below. From my understanding of the issue you want the output shown under "html/template". Is that correct?

text/template:

<script type="text/javascript">
var list = [{1 Name1} {2 Name2}]
console.log(list)
</script>

html/template:

<script type="text/javascript">
var list = [{"Gid":1,"Gname":"Name1"},{"Gid":2,"Gname":"Name2"}]
console.log(list)
</script>

@ghost
Copy link
Author

ghost commented Jun 5, 2017

no , it is all out buy html/template, but the 1.8.3 is not a object, the javascript cannot parse it right@vcabbage

@vcabbage
Copy link
Member

vcabbage commented Jun 5, 2017

Javascript, in my browser, parses this correctly:

<script type="text/javascript">
var list = [{"Gid":1,"Gname":"Name1"},{"Gid":2,"Gname":"Name2"}]
console.log(list)
</script>

That was produced with Go 1.8.3, using this example:

package main

import (
	"fmt"
	html "html/template"
	"os"
	text "text/template"
)

var textTmpl = text.Must(text.New("").Parse(`<script type="text/javascript">
var list = {{.list}}
console.log(list)
</script>`))

var htmlTmpl = html.Must(html.New("").Parse(`<script type="text/javascript">
var list = {{.list}}
console.log(list)
</script>`))

type Grade struct {
	Gid   int64
	Gname string
}

func main() {
	list := []Grade{
		{1, "Name1"},
		{2, "Name2"},
	}

	data := map[string]interface{}{
		"list": list,
	}

	fmt.Printf("text/template:\n\n")
	textTmpl.Execute(os.Stdout, data)

	fmt.Printf("\n\nhtml/template:\n\n")
	htmlTmpl.Execute(os.Stdout, data)
}

You can run it yourself here: https://play.golang.org/p/j8wlM0lN8x

@ghost
Copy link
Author

ghost commented Jun 5, 2017

my result:

Unavailable For Legal Reasons

If you believe this is in error, please file an issue.

@vcabbage
Copy link
Member

vcabbage commented Jun 5, 2017

Ah, sorry, can you run the example I posted above on your computer?

@ghost
Copy link
Author

ghost commented Jun 5, 2017

you out put is http.ResponseWriter?

@ghost
Copy link
Author

ghost commented Jun 5, 2017

I have test your example, it is right in the html/template, but the out device is http.ResponseWriter is different, you can try

@vcabbage
Copy link
Member

vcabbage commented Jun 5, 2017

No, I was just putting it into an html file. Here's an example that serves via http. Note that setting content-type to "text/html" is required for the browser to render it as HTML.

package main

import (
	"fmt"
	html "html/template"
	"log"
	"net/http"
	text "text/template"
)

var textTmpl = text.Must(text.New("").Parse(`<script type="text/javascript">
var list = {{.list}}
console.log(list)
</script>`))

var htmlTmpl = html.Must(html.New("").Parse(`<script type="text/javascript">
var list = {{.list}}
console.log(list)
</script>`))

type Grade struct {
	Gid   int64
	Gname string
}

func main() {
	list := []Grade{
		{1, "Name1"},
		{2, "Name2"},
	}

	data := map[string]interface{}{
		"list": list,
	}

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("content-type", "text/html")

		fmt.Fprintf(w, "text/template:\n\n")
		textTmpl.Execute(w, data)

		fmt.Fprintf(w, "\n\nhtml/template:\n\n")
		htmlTmpl.Execute(w, data)
	})

	log.Fatal(http.ListenAndServe("localhost:8080", nil))
}

@ghost
Copy link
Author

ghost commented Jun 5, 2017

I found the problem ,i use the react babel to parse the data ,you put in the <script type="text/babel">,it is not right @vcabbage

@vcabbage
Copy link
Member

vcabbage commented Jun 5, 2017

We have established that Javascript can parse this then, correct? Do you still believe there is an error with Go? I am uncertain on how to proceed without a concrete example of what Go is doing incorrectly.

@ghost
Copy link
Author

ghost commented Jun 5, 2017

but in the 1.7.4 ,the <script type="text/babel"> can parse data right

@ghost
Copy link
Author

ghost commented Jun 5, 2017

this must have some problem

@vcabbage
Copy link
Member

vcabbage commented Jun 5, 2017

I see the issue now. 1.8 checks the script type in order to fix a different bug. However, "text/babel" is not one of the expected tags. Here's the CL where it was implemented https://go-review.googlesource.com/c/14336/ (ffd1c78)

I'm not sure how best to handle this, cc'ing the author of that CL for thoughts.

/cc @nodirt

@vcabbage vcabbage added NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. and removed WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. labels Jun 5, 2017
@vcabbage vcabbage changed the title text/template: why go1.8 object value can not return right data? html/template: JS is not escaped for when script type is "text/babel" Jun 5, 2017
@vcabbage vcabbage changed the title html/template: JS is not escaped for when script type is "text/babel" html/template: JS is not escaped when script type is "text/babel" Jun 5, 2017
@nodirt
Copy link
Contributor

nodirt commented Jun 5, 2017

The problem can be solved on the user side by moving the variables initialized in a template to a separate <script type="text/javascript"> tag:

<script type="text/javascript">
var list = {{.list}};
console.log(list)
</script>

<script type="text/babel">
// Application logic that uses list
</script>

In my opinion html/template in 1.8 works correctly for this scenario. There is a list of MIME types for scripts derived from HTML5 spec, RFC7231 and RFC4329. I don't think stdlib should make an exception for the non-standard text/babel.

@ghost
Copy link
Author

ghost commented Jun 5, 2017

the react have been heavily used,i think go should compatible the scirpt tag, use two kind scirpt tag feel so cumbersome@nodirt

@nodirt
Copy link
Contributor

nodirt commented Jun 5, 2017

please explain how html/template package is incompatible with <script> tag. I looked at the <script> spec again. It says:

If the user agent does not support the scripting language given by the script block's type for this script element, then the user agent must abort these steps at this point. The script is not executed.

This implies that unless the script type (text/babel) is supported (it is not), the script contents shouldn't be interpreted by the user agent (html/template), in particular it should be treated as text/javascript.

Please explain what's the problem in having two tags. Note that I am suggesting to move only variable definitions to the <script type="text/javascript"> tag. The rest of the code can stay inside <script type="text/babel"> tag.

@rsc
Copy link
Contributor

rsc commented Jun 5, 2017

In Go 1.8 we started looking at the script type, so that we'd only apply escaping to text/javascript (and variants along those lines), because some people had text/template (NOT Go's text/template) and that was getting incorrectly processed. Without the html/template package knowing that text/babel means, it's unclear what it should do. It only knows about javascript.

It's true that this changed in Go 1.8, but we think it changed for the better.

It's unclear whether there should be an "opt-in" mechanism in html/template to mean "treat this script exactly like we treat javascript". But note that it would have to be compatible in an unspecified way for that to work.

@ghost
Copy link
Author

ghost commented Jun 6, 2017

in my opinion ,if go want widely used, better compatible with text/babel

@vcabbage
Copy link
Member

vcabbage commented Jun 6, 2017

A few for/against reasons to escape text/babel as though it is javascript, from my point of view.

Background: text/babel is used by the very popular Babel compiler to translate ES2015+ to ES5 in the browser. Alternatively, ES2015+ code can be compiled to ES5 before rendering in the browser.

Against:

For:

  • It's presumably not included in standards because the contents should only be interpreted by the Babel JS library, not browsers.
  • Not escaping the contents is a change in behavior from previous versions of Go.
  • The only other similar types I could find are text/jsx (deprecated in favor of babel) and text/typescript (not widely used). Additional custom types to be added would likely be rare.

In my opinion, the change is minimal enough to be reasonable and restores backward compatibility.

@bradfitz
Copy link
Contributor

bradfitz commented Jun 7, 2017

What's the relation between this bug and #18569? Superficially they sound similar.

@vcabbage
Copy link
Member

vcabbage commented Jun 7, 2017

@bradfitz From my reading this and #18569 are similar, but not necessarily the same. Both are due to script tags with a type other than one of the recognized javascript types.

This issue relates to not applying JavaScript escaping. (Should be recognized as JavaScript, but it's not.)

#18569 is about the application of HTML escaping. (Doesn't necessarily need to be recognized as JavaScript, but the HTML escaping corrupts the custom tags/symbols.)

@rsc
Copy link
Contributor

rsc commented Jun 14, 2017

Is Babel a strict subset of Javascript? If not, then I don't see how we guarantee to process it correctly by blindly pretending it is Javascript.

@vcabbage
Copy link
Member

vcabbage commented Jun 14, 2017

@rsc ECMAScript is the Javascript language spec. Babel compiles ECMAScript 2015+ to ECMAScript 5 so that developers can write their code using the latest language features without worrying about users with older browsers or browsers that don't implement the latest spec yet.

@rsc
Copy link
Contributor

rsc commented Jun 14, 2017

OK, I did not understand that Babel is not some made-up language of its own but just the name of the tool, and that for some reason the script tag is using the name of the tool instead of the name of the language it contains. But now I understand. If the intent is that script with type=text/babel is always (maybe slightly newer) Javascript, then I can see processing it as Javascript in html/template. I think it's probably too late for Go 1.9, but we can try this for Go 1.10.

Is there some way to use Babel with script type=text/javascript instead?

@rsc rsc changed the title html/template: JS is not escaped when script type is "text/babel" html/template: recognize text/babel as synonym for text/javascript Jun 14, 2017
@rsc rsc added NeedsFix The path to resolution is known, but the work has not been done. and removed NeedsDecision Feedback is required from experts, contributors, and/or the community before a change can be made. labels Jun 14, 2017
@rsc rsc added this to the Go1.10 milestone Jun 14, 2017
@vcabbage
Copy link
Member

I believe text/babel is used so that the browser doesn't attempt to execute the contents of the script tag before Babel has a chance to compile it.

The more typical way of using Babel in production would be to compile to ES5 as a build step, rather than doing it client side with text/babel. Using text/babel is more for prototyping.

@ghost ghost closed this as completed Jun 15, 2017
@golang golang locked and limited conversation to collaborators Jun 15, 2018
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

6 participants