Giter Site home page Giter Site logo

gopherjs / gopherjs Goto Github PK

View Code? Open in Web Editor NEW
12.4K 12.4K 558.0 6.89 MB

A compiler from Go to JavaScript for running Go code in a browser

License: BSD 2-Clause "Simplified" License

Go 90.39% Python 0.05% C++ 0.51% Shell 0.21% JavaScript 8.84%
compiler go golang hacktoberfest javascript

gopherjs's Introduction

GopherJS - A compiler from Go to JavaScript

GoDoc Sourcegraph Circle CI

GopherJS compiles Go code (go.dev) to pure JavaScript code. Its main purpose is to give you the opportunity to write front-end code in Go which will still run in all browsers.

Help us make GopherJS better!

What's new?

  • 2024-02-24: Go 1.19 support is available!
  • 2022-08-18: Go 1.18 support is available!
  • 2021-09-19: Go 1.17 support is available!
  • 2021-08-23: Go Modules are now fully supported.
  • 2021-06-19: Complete syscall/js package implementation compatible with the upstream Go 1.16.
  • 2021-04-04: Go 1.16 is now officially supported! πŸŽ‰ πŸŽ‰ πŸŽ‰

Playground

Give GopherJS a try on the GopherJS Playground.

What is supported?

Nearly everything, including Goroutines (compatibility documentation). Performance is quite good in most cases, see HTML5 game engine benchmark. Cgo is not supported.

Installation and Usage

GopherJS requires Go 1.19 or newer. If you need an older Go version, you can use an older GopherJS release.

Install GopherJS with go install:

go install github.com/gopherjs/[email protected]  # Or replace 'v1.19.0-beta1' with another version.

If your local Go distribution as reported by go version is newer than Go 1.19, then you need to set the GOPHERJS_GOROOT environment variable to a directory that contains a Go 1.19 distribution. For example:

go install golang.org/dl/go1.19.13@latest
go1.19.13 download
export GOPHERJS_GOROOT="$(go1.19.13 env GOROOT)"  # Also add this line to your .profile or equivalent.

Now you can use gopherjs build [package], gopherjs build [files] or gopherjs install [package] which behave similar to the go tool. For main packages, these commands create a .js file and .js.map source map in the current directory or in $GOPATH/bin. The generated JavaScript file can be used as usual in a website. Use gopherjs help [command] to get a list of possible command line flags, e.g. for minification and automatically watching for changes.

gopherjs uses your platform's default GOOS value when generating code. Supported GOOS values are: linux, darwin. If you're on a different platform (e.g., Windows or FreeBSD), you'll need to set the GOOS environment variable to a supported value. For example, GOOS=linux gopherjs build [package].

Note: GopherJS will try to write compiled object files of the core packages to your $GOROOT/pkg directory. If that fails, it will fall back to $GOPATH/pkg.

gopherjs run, gopherjs test

If you want to use gopherjs run or gopherjs test to run the generated code locally, install Node.js 10.0.0 (or newer), and the source-map-support module:

npm install --global source-map-support

On supported GOOS platforms, it's possible to make system calls (file system access, etc.) available. See doc/syscalls.md for instructions on how to do so.

gopherjs serve

gopherjs serve is a useful command you can use during development. It will start an HTTP server serving on ":8080" by default, then dynamically compile your Go packages with GopherJS and serve them.

For example, navigating to http://localhost:8080/example.com/user/project/ should compile and run the Go package example.com/user/project. The generated JavaScript output will be served at http://localhost:8080/example.com/user/project/project.js (the .js file name will be equal to the base directory name). If the directory contains index.html it will be served, otherwise a minimal index.html that includes <script src="project.js"></script> will be provided, causing the JavaScript to be executed. All other static files will be served too.

Refreshing in the browser will rebuild the served files if needed. Compilation errors will be displayed in terminal, and in browser console. Additionally, it will serve $GOROOT and $GOPATH for sourcemaps.

If you include an argument, it will be the root from which everything is served. For example, if you run gopherjs serve github.com/user/project then the generated JavaScript for the package github.com/user/project/mypkg will be served at http://localhost:8080/mypkg/mypkg.js.

Environment Variables

There are some GopherJS-specific environment variables:

  • GOPHERJS_GOROOT - if set, GopherJS uses this value as the default GOROOT value, instead of using the system GOROOT as the default GOROOT value
  • GOPHERJS_SKIP_VERSION_CHECK - if set to true, GopherJS will not check Go version in the GOROOT for compatibility with the GopherJS release. This is primarily useful for testing GopherJS against unreleased versions of Go.

Performance Tips

Community

Getting started

Interacting with the DOM

The package github.com/gopherjs/gopherjs/js (see documentation) provides functions for interacting with native JavaScript APIs. For example the line

document.write("Hello world!");

would look like this in Go:

js.Global.Get("document").Call("write", "Hello world!")

You may also want use the DOM bindings, the jQuery bindings (see TodoMVC Example) or the AngularJS bindings. Those are some of the bindings to JavaScript APIs and libraries by community members.

Providing library functions for use in other JavaScript code

Set a global variable to a map that contains the functions:

package main

import "github.com/gopherjs/gopherjs/js"

func main() {
	js.Global.Set("pet", map[string]interface{}{
		"New": New,
	})
}

type Pet struct {
	name string
}

func New(name string) *js.Object {
	return js.MakeWrapper(&Pet{name})
}

func (p *Pet) Name() string {
	return p.name
}

func (p *Pet) SetName(name string) {
	p.name = name
}

For more details see Jason Stone's blog post about GopherJS.

Architecture

General

GopherJS emulates a 32-bit environment. This means that int, uint and uintptr have a precision of 32 bits. However, the explicit 64-bit integer types int64 and uint64 are supported.

The GOOS value of this environment is js, and the GOARCH value is ecmascript. You may use these values in build constraints when writing platform-specific code. (GopherJS 1.17 and older used js as the GOARCH value.)

Application Lifecycle

The main function is executed as usual after all init functions have run. JavaScript callbacks can also invoke Go functions, even after the main function has exited. Therefore the end of the main function should not be regarded as the end of the application and does not end the execution of other goroutines.

In the browser, calling os.Exit (e.g. indirectly by log.Fatal) also does not terminate the execution of the program. For convenience, it calls runtime.Goexit to immediately terminate the calling goroutine.

Goroutines

Goroutines are fully supported by GopherJS. The only restriction is that you need to start a new goroutine if you want to use blocking code called from external JavaScript:

js.Global.Get("myButton").Call("addEventListener", "click", func() {
  go func() {
    [...]
    someBlockingFunction()
    [...]
  }()
})

How it works:

JavaScript has no concept of concurrency (except web workers, but those are too strictly separated to be used for goroutines). Because of that, instructions in JavaScript are never blocking. A blocking call would effectively freeze the responsiveness of your web page, so calls with callback arguments are used instead.

GopherJS does some heavy lifting to work around this restriction: Whenever an instruction is blocking (e.g. communicating with a channel that isn't ready), the whole stack will unwind (= all functions return) and the goroutine will be put to sleep. Then another goroutine which is ready to resume gets picked and its stack with all local variables will be restored.

GopherJS Development

If you're looking to make changes to the GopherJS compiler, see Developer Guidelines for additional developer information.

gopherjs's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gopherjs's Issues

How do you plan to test gopherjs to make it robust?

I think a project like gopherjs has to test each language feature very carefully because it will be the basis of everything else and no bug should be allowed. However, I have not seen many tests under gopherjs. Do you have any plans to improve this situation?

Another related question is: how to test a Go-written Javascript program? Can it compile with GC and run locally? Or do I have to run and debug with Javascript in browser?

A map whose key is an array doesn't work

For example, the following code can be compiled but panics:

package main

type Key [2]int

func main() {
    m := map[Key]int{
        Key{1, 2}: 3,
    }
    print(m)
}
panic: undefined is not a function 

Make it usable as library

Hi,

great package so far.

What I am missing is to be able to include gopherjs as library without the CLI tool, as in

package main

import "github.com/gopherjs/gopherjs/compiler"
import "strings"

func main() {
    c := compiler.New(compiler.Options{})
   js, err := c.Translate([]byte(`[here some package code]`))
   // and
  pkg :=  c.NewPackage()
  pkg.AddFile("a.go", strings.NewReader(`[here some package code]`))
  pkg.AddFile("b.go", strings.NewReader(`[here some package code]`))
  js, err = pkg.Translate()
}

That would make it possible to generate the content of the "files" that are translated
without having to use the shell and open up more possibilities (and reusage of packages via import from the outer package).

Any way to get to `module.exports`?

Hi,

I have very little knowledge about JavaScript/Node.js/Atom packages, so take this question with a grain of salt.

It seems one can currently "export" a Go func to be accessible to the external JavaScript environment, say, on a webpage, by doing this:

package main

import "github.com/gopherjs/gopherjs/js"

func Foo() string { return "hello from Go" }

func main() {
    js.Global.Set("Foo", Foo)
}

The js.Global.Set("Foo", Foo) line ends up producing $global.Foo = $externalize(Foo, ($funcType([], [$String], false)));, and $global is set to window for a web page.

However, I am looking to be able to have something equivalent to this in the generated javascript, in order to be able to require() it:

module.exports.Foo = $externalize(Foo, ($funcType([], [$String], false)));

Is there any way to achieve this with the current GopherJS?

If not, can a var Module Object be added to github.com/gopherjs/gopherjs/js so that it is possible?

UTF8 Handling

Hi,

I noticed something when passing strings with utf8 from go to js.
The characters are treated wrong somehow. β„’ comes out as Γ’οΏ½Β’ for instance.

I made a small demo here

Is this known and if this what's the proper way to work with it? I don't want to pipe all my data through the templating engine..

p.s.: I'm still blown away by the amount of stdlib that is working with gopherjs. AWESOME job!

p.p.s: i know document.write is bad bad bad but I just wanted get some generated html without involving jquery. i cleaned it up using proper dom api, the updated version is here

'defer' with a simple function call doesn't work

For example, the following code is compiled but fails:

package main

import (
    "github.com/gopherjs/gopherjs/js"
)

func main() {
    defer js.Global.Call("alert", "Hello, JavaScript")
}
panic: Cannot read property 'apply' of undefined 

Using an anonymous function, it works without errors:

package main

import (
    "github.com/gopherjs/gopherjs/js"
)

func main() {
    defer func() {
        js.Global.Call("alert", "Hello, JavaScript")
    }()
}

After change to externalizing struct: How to use Watch.Js with an object from gopherjs now?

I use watch.js for inspecting changes of the models created with Gopherjs, it has been working (if i switch to my gopherjs fork it's gonna work). However after the change so that externalizing a struct means copying it, it doesn't work anymore.
How do I solve this problem? Is there a way to bypass it or something? (I implement html data binding with watch.js, so I need this).
Or could you consider reverting the change? Is it possible and why is copying better? The old thing in my fork worked quite well for me.

Can go$val be renamed or configurable?

Gopherjs generated js code uses go$val = this heavily to reference the object
itself. This is usually ok. But when I do some gopherjs bindings of avalon.js(a js MVVM framework much like Angular.js but more simpler) I got a fatal
problem.

MVVM frameworkes like Angular.js generally would scan the ViewModel definded by javascript, that's the same with avalon.js. But the special value
go$val = this(i.e. structs) generated by gopherjs will cause avalon.js run into a cycling reference state which cause js code to exit. I don't konw whether Angular.js would suffer the same problem, but in avalon.js there's no way to easily solve this problem.

Like Angular.js, avalon.js use a special name pattern, $ prefixed names,
to skip value scanning.

So I wonder could go$val be rename or configurable when doing js compile
in gopherjs build?

Missing ast.ParenExpr case?

compiler.translateExpr(), in the branch for translating exprs of type ast.UnaryExpr, seems to be missing a case for unary exprs of subtype ast.ParenExpr right around line 180 of compiler/expression.go.

Date ←→ time.Time conversion is broken

Input:

func main() {
    js.Global("eval").Invoke("console.log(new Date())")
    date := js.Global("eval").Invoke("new Date()").Interface()
    js.Global("console").Call("log", date)
}

Output:

Tue Jan 21 2014 02:04:32 GMT+0100 (CET)
Fri Mar 20 1970 06:54:27 GMT+0100 (CET)

Have a way to import net/http / share routes between client and server

Frankly, I don't know if this is even possible ;-)

It would be great, if routes, defined for the server, could be reused by JavaScript generated with gopherjs.

If the routes would reside in a package on their own, they could be imported by the server and a gopherjs package.

The only problem is, that any reasonable Go router has to deal with http.Handler and that requires net/http and that is not supported by gopherjs.

Although I have no idea, if there could be a way around this (since net/http makes use of CGO via net package), I just wanted to raise the issue, since it would be sooo useful to be able to share routes between server and client (to let the route return correct parameterized URLs for AJAX etc).

Maybe someone comes up with an idea...

better CLI

better flag library, proper flag documentation, etc.

LoadLocation Call in time package

package main

import (
    "fmt"
    "math"
    "time"
)

func calcDuration(hrStart, minStart, hrEnd, minEnd int) (hrDiff, minDiff int) {

    // next line crashes on Win7/go1.3, systemcalls not supported:
    //pt, _ := time.LoadLocation("Europe/Lisbon")

    //this works fine:
    pt := time.UTC

    yr, mo, dy := time.Now().Date()

    t1 := time.Date(yr, mo, dy, hrStart, minStart, 0, 0, pt)
    t2 := time.Date(yr, mo, dy, hrEnd, minEnd, 0, 0, pt)

    overallDiff := t2.Sub(t1).Minutes()
    hrDiff = int(math.Floor(overallDiff / 60))
    minDiff = int(math.Mod(overallDiff, 60))

    return
}

func main() {

    hr, mi := calcDuration(8, 15, 19, 35)
    fmt.Printf("Duration: %d hours and %d minutes.\n", hr, mi)
}

the "time.LoadLocation" call causes a System call, at least on Windows.
I don't know how hard it is to implement this, but could you at least
make a hint in the compatibility doc ?

Panic in runtime from changes made today.

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x28 pc=0x8c6d]

goroutine 1 [running]:
runtime.panic(0x251000, 0x5551b9)
/Users/ajhager/opt/go/src/pkg/runtime/panic.c:266 +0xb6
main.writeCommandPackage(0x2106b42a0, 0x210c93d10, 0xa, 0x0, 0x0)
/Users/ajhager/go/src/github.com/neelance/gopherjs/tool.go:561 +0x3ad
main.tool(0x0, 0x0)
/Users/ajhager/go/src/github.com/neelance/gopherjs/tool.go:124 +0x501
main.main()
/Users/ajhager/go/src/github.com/neelance/gopherjs/tool.go:77 +0x26

This is the error I get when trying to 'gopherjs build' botmark at the moment. I am trying to figure out a clearer diagnosis, but I can't find something obviously specific to enj.

time.Now().String() should work

Trying to convert a time.Time object to a string might not work. It is because this seems to need the access to a file where zones are defined if the Time includes a locale. As far as I know, a Time object with UTC (like a Time created by time.Parse()) doesn't cause problems. For example, on my locale machine:

package main

import (
        "time"
)

func main() {
        print(time.Now().String())
}

can be compiled, but the JavaScript file results in:

Uncaught Error: syscalls not available test.js:1145
go$panic test.js:1145
go$packages.syscall.syscall syscall_unix.go:33
go$packages.syscall.go$pkg.Syscall syscall_unix.go:41
go$packages.syscall.go$pkg.Open zsyscall_darwin_amd64.go:833
go$packages.time.readFile sys_unix.go:23
go$packages.time.loadZoneFile zoneinfo_read.go:206
go$packages.time.initLocal zoneinfo_unix.go:59
go$packages.sync.Once.Ptr.Do once.go:40
go$packages.time.Location.Ptr.get zoneinfo.go:69
go$packages.time.Time.Ptr.locabs time.go:272
go$packages.time.Time.Ptr.Format format.go:415
go$packages.time.Time.Ptr.String format.go:400
go$packages.main.go$pkg.main test.go:9
(anonymous function) test.go:9
(anonymous function)

I wonder if I could use Time object without accessing any files. As JavaScript's Time knows the local locale, time.Now().String() should be able to work.

Fluent js Setters

Could you return the current Object in the js.Set and js.SetIndex Functions ? This would allow to use a fluent/chaining api for those who want it but would not have any impact on those who don't want to use chaining ?

Example:
someJsobject.Set("prop1", "val1").Set("prop2", "val2")

Methods all left out when converting from Go struct to js

Js objects converted from Go struct should still have all the methods as js prototype functions. Could it be supported? I think it's important.
my usecase: I'm writing something based on rivetsjs and want to use something like this. I tried converting a Go struct to js, but the methods are all leaved out so the only workaround seems to be using a function property instead. However that's very ugly and there's no way to access the object itself.

panic when compiling Go code with blank identifier as receiver.

Easily reproducible on the GopherJS playground:

package main

import (
    "fmt"
    "github.com/gopherjs/gopherjs/js"
)

type someStruct struct {
}

func (_ someStruct) SomeMethod() int { return 0 }

func main() {
    fmt.Println("Hello, playground")
    js.Global.Call("alert", "Hello, JavaScript")
    println("Hello, JS console")
}

(It also happens with pointer receiver.)

Everything is okay if you omit the receiver name:

func (someStruct) SomeMethod() int { return 0 }

Here's a panic trace from running gopherjs with some offending code, in case it's helpful.

$ gopherjs build try_goph.go
ast.Walk: unexpected node type *compiler.Thispanic: ast.Walk

goroutine 1 [running]:
runtime.panic(0x230580, 0x21072fd60)
    /usr/local/go/src/pkg/runtime/panic.c:266 +0xb6
go/ast.Walk(0x6bdf58, 0x21072fd40, 0x6bdda8, 0x21075c220)
    /usr/local/go/src/pkg/go/ast/walk.go:363 +0x663
github.com/gopherjs/gopherjs/compiler.(*funcContext).translateStmt(0x21075a3c0, 0x6bdcb0, 0x210759580, 0x2d7050, 0x0)
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/compiler/statements.go:403 +0x6cb8
github.com/gopherjs/gopherjs/compiler.(*funcContext).translateStmtList(0x21075a3c0, 0x21075c240, 0x2, 0x2)
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/compiler/statements.go:18 +0x7b
github.com/gopherjs/gopherjs/compiler.funcΒ·027()
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/compiler/package.go:594 +0xf9
github.com/gopherjs/gopherjs/compiler.funcΒ·031()
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/compiler/package.go:634 +0x977
github.com/gopherjs/gopherjs/compiler.(*funcContext).CatchOutput(0x21075a3c0, 0x1, 0x221085c340, 0x21073a880, 0x21073a880, ...)
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/compiler/utils.go:50 +0x61
github.com/gopherjs/gopherjs/compiler.(*funcContext).translateFunctionBody(0x21075a3c0, 0x1, 0x21075c240, 0x2, 0x2, ...)
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/compiler/package.go:635 +0x2e2
github.com/gopherjs/gopherjs/compiler.(*funcContext).translateFunction(0x21075a140, 0x21073a8a0, 0x2107573c0, 0x21075c240, 0x2, ...)
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/compiler/package.go:555 +0x4e4
github.com/gopherjs/gopherjs/compiler.funcΒ·026(0x210757f00, 0x27, 0x21075c200, 0x19, 0x1, ...)
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/compiler/package.go:478 +0x664
github.com/gopherjs/gopherjs/compiler.(*funcContext).translateToplevelFunction(0x21075a140, 0x2106f6fc0, 0x0, 0x22988, 0x2b71e0)
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/compiler/package.go:507 +0x775
github.com/gopherjs/gopherjs/compiler.funcΒ·020()
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/compiler/package.go:234 +0x47
github.com/gopherjs/gopherjs/compiler.funcΒ·016(0x6bd218, 0x210759000, 0x210757ea0, 0x10, 0x10, ...)
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/compiler/package.go:180 +0x66
github.com/gopherjs/gopherjs/compiler.Compile(0x2e2010, 0x4, 0x2106ec198, 0x1, 0x1, ...)
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/compiler/package.go:235 +0x2752
github.com/gopherjs/gopherjs/build.(*Session).BuildPackage(0x21073a5e0, 0x2106f6ba0, 0x22988, 0x2233c0)
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/build/build.go:352 +0xa78
github.com/gopherjs/gopherjs/build.(*Session).BuildFiles(0x21073a5e0, 0x2106f6020, 0x1, 0x1, 0x21072f6d0, ...)
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/build/build.go:228 +0xfc
main.funcΒ·001(0x0, 0x1d00000000000005)
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/tool.go:85 +0x5df
main.handleError(0x221085def8, 0x21073a5e0)
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/tool.go:385 +0x31
main.main()
    /Users/Dmitri/Dropbox/Work/2013/GoLanding/src/github.com/gopherjs/gopherjs/tool.go:62 +0x71b

Dead link in README.md

Hi,

the godoc link in the Using the builder as a libary section returns 404.
I guess the jslib package got renamed to compiler but I'm to new to gopherjs to know.

Doesn't avoid future reserved words

Hi, great work on this software - it works very well!

A minor flaw I found is that it doesn't avoid future reserved javascript keywords such as int and short - it can generate code like var int;.

It doesn't seem to matter to browsers but it means the clojure compiler won't parse the code - something that would be very desirable given the typical amount of javascript code gopherjs generates.

Bug: Printing the struct shows the fields's value, but printing the field gets "undefined"

I came across this wierd bug when developing go-angularjs.
https://github.com/gopherjs/go-angularjs/blob/master/http.go
around line 177
Printing r gives

&{Method:{<...> Headers:{Value:map[Accept:application/json, text/plain, */*]} TransformReq:{Value:<nil>}}}

While r.Headers gives undefined. I think it's a gopherjs bug.

Full generated code:
https://gist.github.com/phaikawl/11312585
Error occurs at about line 16050.

Create a JS library from a Go pkg.

I'd like to be able to write some Go utility packages and produce a corresponding JS library, to be used by external JS code.

For example, making a go package as:

package foo // in src/github.com/blah
func RandomNumber() int { return 4; }

should produce a js lib foo.js that I can load and then call something like

var randomlyChosenNumber = $go["github.com/blah/foo"].RandomNumber();

in my JS without requiring me to define a main package in Go and without polluting the js namespace unnecessarily.

Reflection bug?

I'm facing an issue with gopherjs, it can be a bug related to reflection and the js mechanism.
The faulty part is here on line 91-92: link.
It seems that the assignment from the js.Object as passed in by javascript to the reflected field of type js.Object in the struct doesn't work as expected. I guess it's due to the js.Object in the reflected struct being empty (not interpolated by gopherjs as a special struct?). So @neelance what do you think? Did you handle this case?

GopherJS writes to GOPATH workspace when doing build.

It seems the CLI interface tries to mimic the go command. But it has an unexpected difference. The go command only writes stuff to your $GOPATH/pkg when you do go install, but it uses temporary folders when you do go build.

Using gopherjs build seems to write to my $GOPATH/pkg every time.

Hello World crashes

The following program doesn't seem to work:

[email protected] $ cat test.go
package main

import (
    "fmt"
)

func main() {
    fmt.Println("Hello, Antoine")
}

With go:

[email protected] $ go run test.go
Hello, Antoine

With gopherjs:

[email protected] $ gopherjs run test.go

module.js:340
    throw err;
          ^
Error: Cannot find module 'syscall'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at go$packages.syscall.syscall (/private/var/folders/6p/65vhfdlj4tz4cqqjbw85jzh40000gn/T/test.go.674897673:1834:20)
    at go$packages.syscall.go$pkg.Syscall (/private/var/folders/6p/65vhfdlj4tz4cqqjbw85jzh40000gn/T/test.go.674897673:1843:7)
    at go$packages.syscall.write (/private/var/folders/6p/65vhfdlj4tz4cqqjbw85jzh40000gn/T/test.go.674897673:2274:12)
    at Object.go$packages.syscall.go$pkg.Write (/private/var/folders/6p/65vhfdlj4tz4cqqjbw85jzh40000gn/T/test.go.674897673:2085:12)
    at go$packages.os.File.Ptr.write (/private/var/folders/6p/65vhfdlj4tz4cqqjbw85jzh40000gn/T/test.go.674897673:5008:21)
    at go$packages.os.File.Ptr.Write (/private/var/folders/6p/65vhfdlj4tz4cqqjbw85jzh40000gn/T/test.go.674897673:4713:14)
    at go$packages.fmt.go$pkg.Fprintln (/private/var/folders/6p/65vhfdlj4tz4cqqjbw85jzh40000gn/T/test.go.674897673:10308:14)
    at Object.go$packages.fmt.go$pkg.Println (/private/var/folders/6p/65vhfdlj4tz4cqqjbw85jzh40000gn/T/test.go.674897673:10316:12)
    at Object.go$packages.main.go$pkg.main (/private/var/folders/6p/65vhfdlj4tz4cqqjbw85jzh40000gn/T/test.go.674897673:11385:7)
    at /private/var/folders/6p/65vhfdlj4tz4cqqjbw85jzh40000gn/T/test.go.674897673:11417:21
    at Object.<anonymous> (/private/var/folders/6p/65vhfdlj4tz4cqqjbw85jzh40000gn/T/test.go.674897673:11419:3)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:901:3
could not run Node.js: exit status 8
[email protected] $

The same is true in a browser:

[email protected] $ gopherjs build
[email protected] $ open index.html

screen shot 2014-05-07 at 10 48 31

json.Unmarshal doesn't work

I know reflect is broken now, but I'm reporting this just in case.

The below code works on the Playground, but doesn't work on my local machine.

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
)

type Foo struct {
    A int
}

func main() {
    s := `{"A": 1}`
    fooType := reflect.TypeOf((*Foo)(nil)).Elem()
    foo := reflect.New(fooType).Interface() 
    fmt.Printf("%v\n", foo)
    if err := json.Unmarshal([]byte(s), &foo); err != nil {
        panic(err)
    }
    fmt.Printf("%v\n", foo)
}
Uncaught TypeError: undefined is not a function

Address-of on field access on pointer dereference incorrect

&foo().a (equivalent to &(*foo()).a, assuming either is correct) produces a pointer that invokes foo each time it's dereferenced, instead of calling foo when the pointer is created.

Full example:

type foo struct {
    a int
}

func bar() *foo {
    fmt.Println("bar() called")
    return &foo{ 42 }
}

func main() {
    q := &bar().a
    fmt.Println("pointer created")
    *q = 40
    fmt.Println(*q)
}

I haven't tried it, but I suspect the same issue occurs (possibly more subtly) with &(*baz).aβ€”once the pointer has been produced by this expression, it should be independent of future values of the baz pointer.

Strange build error

I was not able to reproduce it with another package, therefore...

If I build this package

package main
import "github.com/go-on/ractive/0_4_0/ractive"

func main() {
    _ = ractive.New
}

I get the following error:

./main.go:4:2: could not import github.com/go-on/ractive/0_4_0/ractive (asn1: structure error: sequence tag mismatch)
./main.go:8:6: undeclared name: ractive

However if I open the file

github.com/go-on/ractive/0_4_0/ractive/ractive.go

in my editor and save it (without changing anything), then the next gopher build works. Running gopher build a second time triggers the error above.

"permission denied" errors when doing `gopherjs build` of sample program.

First of all, this looks like a really cool project and it's great to see how far you got! I tried it just got the following problem.

$ cat play_js.go 
package main

import "fmt"

func main() {
    alert("Hello, JavaScript")
    fmt.Println("Hello, playground")
}

func alert(msg string) {}

const js_alert = `window.alert(msg);`
$ gopherjs build play_js.go 
/Users/Dmitri/Desktop/play_js.go:3:8: could not import fmt (/usr/local/go/src/pkg/fmt/print.go:10:2: could not import os (/usr/local/go/src/pkg/os/dir_unix.go:11:2: could not import syscall (/usr/local/go/src/pkg/syscall/exec_bsd.go:10:2: could not import runtime (open /usr/local/go/src/pkg/runtime/zgoarch_js.go: permission denied))))
$ ls -la /usr/local/go/src/pkg/fmt/print.go
-rw-r--r--  1 root  wheel  30639 28 Nov 13:42 /usr/local/go/src/pkg/fmt/print.go

Any idea why that'd be? The files in my GOROOT are readable by user, group, others.

Running go version go1.2 darwin/amd64 on OS X 10.9.

Cannot fmt.Println a js.Object

(Tested in the playground)

package main

import (
    "fmt"
    "github.com/neelance/gopherjs/js"
)

func main() {
    fmt.Println(js.Global("window"))
}
TypeError: Object function Window() { [native code] } has no method 'reflectType'
    at Object.go$packages.reflect.ValueOf (http://neelance.github.io/gopherjs-playground/gopherjs-playground.js:26333:28)
    at go$packages.fmt.pp.Ptr.printArg (http://neelance.github.io/gopherjs-playground/gopherjs-playground.js:28521:57)
    at go$packages.fmt.pp.Ptr.doPrint (http://neelance.github.io/gopherjs-playground/gopherjs-playground.js:28928:19)
    at go$packages.fmt.Fprintln (http://neelance.github.io/gopherjs-playground/gopherjs-playground.js:27961:5)
    at Object.go$packages.fmt.Println (http://neelance.github.io/gopherjs-playground/gopherjs-playground.js:27970:14)
    at Object.go$packages.main.main [as main] (eval at <anonymous> (http://neelance.github.io/gopherjs-playground/gopherjs-playground.js:65880:14), <anonymous>:6:7)
    at eval (eval at <anonymous> (http://neelance.github.io/gopherjs-playground/gopherjs-playground.js:65880:14), <anonymous>:157:21)
    at eval (native)
    at go$packages.github.com/neelance/gopherjs-playground.evalScript (http://neelance.github.io/gopherjs-playground/gopherjs-playground.js:65880:14)
    at h.app.NewController.run (http://neelance.github.io/gopherjs-playground/gopherjs-playground.js:65813:5)
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js:162:407
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js:179:83
    at h.$eval (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js:102:293)
    at h.$apply (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js:103:48)
    at HTMLInputElement.<anonymous> (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js:179:65)
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js:27:208
    at q (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js:7:380)
    at HTMLInputElement.Zc.c (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js:27:190) angular.js:9413

GopherJS created some strange directory paths for compiled files.

I've just discovered a really puzzling directory, which seems to have been produced by gopherjs incorrectly. My GOPATH contains two workspaces /Users/Dmitri/Dropbox/Work/2013/GoLand and /Users/Dmitri/Dropbox/Work/2013/GoLanding. But there's folder is named /Users/Dmitri/Dropbox/Work/2013/GoLanding:/, and inside it, there is /Users/Dmitri/Dropbox/Work/2013/GoLanding:/Users/Dmitri/...

$ tree /Users/Dmitri/Dropbox/Work/2013/GoLanding:/
/Users/Dmitri/Dropbox/Work/2013/GoLanding:/
└── Users
    └── Dmitri
        β”œβ”€β”€ Dropbox
        β”‚Β Β  └── Work
        β”‚Β Β      └── 2013
        β”‚Β Β          └── GoLand
        β”‚Β Β              └── pkg
        β”‚Β Β                  β”œβ”€β”€ darwin_amd64_js
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ runtime.a
        β”‚Β Β                  β”‚Β Β  └── syscall.a
        β”‚Β Β                  β”œβ”€β”€ darwin_amd64_js-min
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ runtime.a
        β”‚Β Β                  β”‚Β Β  └── syscall.a
        β”‚Β Β                  β”œβ”€β”€ darwin_js
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ bufio.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ bytes.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ errors.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ flag.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ fmt.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ go
        β”‚Β Β                  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ scanner.a
        β”‚Β Β                  β”‚Β Β  β”‚Β Β  └── token.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ io
        β”‚Β Β                  β”‚Β Β  β”‚Β Β  └── ioutil.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ io.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ math.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ os
        β”‚Β Β                  β”‚Β Β  β”‚Β Β  └── exec.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ os.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ path
        β”‚Β Β                  β”‚Β Β  β”‚Β Β  └── filepath.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ reflect.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ regexp
        β”‚Β Β                  β”‚Β Β  β”‚Β Β  └── syntax.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ regexp.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ runtime
        β”‚Β Β                  β”‚Β Β  β”‚Β Β  └── pprof.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ sort.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ strconv.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ strings.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ sync
        β”‚Β Β                  β”‚Β Β  β”‚Β Β  └── atomic.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ sync.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ testing.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ text
        β”‚Β Β                  β”‚Β Β  β”‚Β Β  └── tabwriter.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ time.a
        β”‚Β Β                  β”‚Β Β  β”œβ”€β”€ unicode
        β”‚Β Β                  β”‚Β Β  β”‚Β Β  └── utf8.a
        β”‚Β Β                  β”‚Β Β  └── unicode.a
        β”‚Β Β                  └── darwin_js-min
        β”‚Β Β                      β”œβ”€β”€ bufio.a
        β”‚Β Β                      β”œβ”€β”€ bytes.a
        β”‚Β Β                      β”œβ”€β”€ errors.a
        β”‚Β Β                      β”œβ”€β”€ flag.a
        β”‚Β Β                      β”œβ”€β”€ fmt.a
        β”‚Β Β                      β”œβ”€β”€ io
        β”‚Β Β                      β”‚Β Β  └── ioutil.a
        β”‚Β Β                      β”œβ”€β”€ io.a
        β”‚Β Β                      β”œβ”€β”€ math.a
        β”‚Β Β                      β”œβ”€β”€ os
        β”‚Β Β                      β”‚Β Β  └── exec.a
        β”‚Β Β                      β”œβ”€β”€ os.a
        β”‚Β Β                      β”œβ”€β”€ path
        β”‚Β Β                      β”‚Β Β  └── filepath.a
        β”‚Β Β                      β”œβ”€β”€ reflect.a
        β”‚Β Β                      β”œβ”€β”€ regexp
        β”‚Β Β                      β”‚Β Β  └── syntax.a
        β”‚Β Β                      β”œβ”€β”€ regexp.a
        β”‚Β Β                      β”œβ”€β”€ runtime
        β”‚Β Β                      β”‚Β Β  └── pprof.a
        β”‚Β Β                      β”œβ”€β”€ sort.a
        β”‚Β Β                      β”œβ”€β”€ strconv.a
        β”‚Β Β                      β”œβ”€β”€ strings.a
        β”‚Β Β                      β”œβ”€β”€ sync
        β”‚Β Β                      β”‚Β Β  └── atomic.a
        β”‚Β Β                      β”œβ”€β”€ sync.a
        β”‚Β Β                      β”œβ”€β”€ testing.a
        β”‚Β Β                      β”œβ”€β”€ text
        β”‚Β Β                      β”‚Β Β  └── tabwriter.a
        β”‚Β Β                      β”œβ”€β”€ time.a
        β”‚Β Β                      β”œβ”€β”€ unicode
        β”‚Β Β                      β”‚Β Β  └── utf8.a
        β”‚Β Β                      └── unicode.a
        └── Local
            └── GoTrLand:
                └── Users
                    └── Dmitri
                        └── Dropbox
                            └── Work
                                └── 2013
                                    └── GoLand
                                        └── pkg
                                            β”œβ”€β”€ darwin_amd64_js
                                            β”‚Β Β  β”œβ”€β”€ runtime.a
                                            β”‚Β Β  └── syscall.a
                                            β”œβ”€β”€ darwin_amd64_js-min
                                            β”‚Β Β  β”œβ”€β”€ runtime.a
                                            β”‚Β Β  └── syscall.a
                                            β”œβ”€β”€ darwin_js
                                            β”‚Β Β  β”œβ”€β”€ bufio.a
                                            β”‚Β Β  β”œβ”€β”€ bytes.a
                                            β”‚Β Β  β”œβ”€β”€ errors.a
                                            β”‚Β Β  β”œβ”€β”€ fmt.a
                                            β”‚Β Β  β”œβ”€β”€ io
                                            β”‚Β Β  β”‚Β Β  └── ioutil.a
                                            β”‚Β Β  β”œβ”€β”€ io.a
                                            β”‚Β Β  β”œβ”€β”€ math.a
                                            β”‚Β Β  β”œβ”€β”€ os
                                            β”‚Β Β  β”‚Β Β  └── exec.a
                                            β”‚Β Β  β”œβ”€β”€ os.a
                                            β”‚Β Β  β”œβ”€β”€ path
                                            β”‚Β Β  β”‚Β Β  └── filepath.a
                                            β”‚Β Β  β”œβ”€β”€ reflect.a
                                            β”‚Β Β  β”œβ”€β”€ regexp
                                            β”‚Β Β  β”‚Β Β  └── syntax.a
                                            β”‚Β Β  β”œβ”€β”€ regexp.a
                                            β”‚Β Β  β”œβ”€β”€ sort.a
                                            β”‚Β Β  β”œβ”€β”€ strconv.a
                                            β”‚Β Β  β”œβ”€β”€ strings.a
                                            β”‚Β Β  β”œβ”€β”€ sync
                                            β”‚Β Β  β”‚Β Β  └── atomic.a
                                            β”‚Β Β  β”œβ”€β”€ sync.a
                                            β”‚Β Β  β”œβ”€β”€ time.a
                                            β”‚Β Β  β”œβ”€β”€ unicode
                                            β”‚Β Β  β”‚Β Β  └── utf8.a
                                            β”‚Β Β  └── unicode.a
                                            └── darwin_js-min
                                                β”œβ”€β”€ bufio.a
                                                β”œβ”€β”€ bytes.a
                                                β”œβ”€β”€ errors.a
                                                β”œβ”€β”€ fmt.a
                                                β”œβ”€β”€ io
                                                β”‚Β Β  └── ioutil.a
                                                β”œβ”€β”€ io.a
                                                β”œβ”€β”€ math.a
                                                β”œβ”€β”€ os
                                                β”‚Β Β  └── exec.a
                                                β”œβ”€β”€ os.a
                                                β”œβ”€β”€ path
                                                β”‚Β Β  └── filepath.a
                                                β”œβ”€β”€ reflect.a
                                                β”œβ”€β”€ regexp
                                                β”‚Β Β  └── syntax.a
                                                β”œβ”€β”€ regexp.a
                                                β”œβ”€β”€ sort.a
                                                β”œβ”€β”€ strconv.a
                                                β”œβ”€β”€ strings.a
                                                β”œβ”€β”€ sync
                                                β”‚Β Β  └── atomic.a
                                                β”œβ”€β”€ sync.a
                                                β”œβ”€β”€ time.a
                                                β”œβ”€β”€ unicode
                                                β”‚Β Β  └── utf8.a
                                                └── unicode.a

53 directories, 102 files

It looks like something went wrong in calculating paths. This is on OS X. I highly recommend using path/filepath and funcs like http://godoc.org/path/filepath#Join that are safe to use across different OSes (if you're not already), rather than joining strings by hand.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.