Skip to content

Go 1.17 support #1043

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

Merged
merged 50 commits into from
Sep 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
a69a95d
Bump Upstream Go version to 1.17rc1
flimzy Jul 22, 2021
5e8e181
Update third-party dependencies
flimzy Jul 29, 2021
c596904
Apply 'go fmt -w -s .' to conform to 1.17 standards
flimzy Jul 22, 2021
7517cba
Set runtime.Version() output as a constant for now
flimzy Jul 22, 2021
21b4595
math/rand: Rename test package from `rand` to `rand_test` to match up…
flimzy Jul 29, 2021
c8a1588
reflect: New implementation of `New`
flimzy Jul 29, 2021
1b42d68
ed25519: Disable some tests
flimzy Jul 29, 2021
845d590
Disable tests for broken packages:
flimzy Jul 22, 2021
b4beee2
Add (failing) test for slice-to-array-pointer conversion added in Go …
flimzy Jul 29, 2021
b153701
Copy 1.16's version of *os.File.WriteString, which doesn't use unsafe
flimzy Aug 5, 2021
5a893b7
Fix a few doc typos, and tighten up some code a bit
flimzy Aug 5, 2021
0c5d57d
Hack around go/build.defaultToolTags
flimzy Aug 5, 2021
9680b1b
Disable some fixedbug tests that don't work in GopherJS
flimzy Aug 5, 2021
02663f3
Support go1.17 slice to array pointer conversion.
nevkontakte Aug 8, 2021
bc3fd14
Implement reflect support for slice to array pointer conversion.
nevkontakte Aug 14, 2021
cc76e63
Preserve nil slices when converting between different slice types.
nevkontakte Aug 14, 2021
d58f2e3
Fix reflect.TestMethodPkgPath test.
nevkontakte Sep 6, 2021
a055c1d
reflect: ArrayOf() panics if array length is negative.
nevkontakte Sep 6, 2021
5f41a3b
Use desiredType instead of underlying when converting slice to array.
nevkontakte Sep 6, 2021
afc51e1
Update VFS.
nevkontakte Sep 6, 2021
5be4748
Merge pull request #1055 from nevkontakte/wip-go1.17
nevkontakte Sep 7, 2021
839156b
Rewrite index operator on array-pointer into an explicit dereference.
nevkontakte Sep 11, 2021
a31dbb8
Provide correct constructor for names array-pointer types.
nevkontakte Sep 11, 2021
d35909a
reflect: Fix conversion between different array pointer types.
nevkontakte Sep 12, 2021
cb1f7e8
reflect: Fix slice length check in Value.CanConvert.
nevkontakte Sep 12, 2021
54dda39
Update VFS and minified prelude.
nevkontakte Sep 12, 2021
6a42cad
Merge pull request #1057 from nevkontakte/wip-go1.17
nevkontakte Sep 13, 2021
4dda1bf
sync/atomic: Implement new Swap and CompareAndSwap methods of Value.
nevkontakte Sep 14, 2021
04eeecb
Update VFS with sync/atomic.
nevkontakte Sep 14, 2021
d80c496
Merge pull request #1058 from nevkontakte/wip-go1.17
nevkontakte Sep 15, 2021
80278a6
Get `hash/maphash` to work again
flimzy Sep 17, 2021
f97fb25
Merge pull request #1059 from gopherjs/hashmap
flimzy Sep 17, 2021
1ead41d
Ignore tests for internal/abi package.
nevkontakte Sep 15, 2021
6d23e7f
Fix internal/poll package for Go 1.17.
nevkontakte Sep 17, 2021
e835da2
Update VFS for `internal/poll`.
nevkontakte Sep 17, 2021
8b97c5a
Merge pull request #1061 from nevkontakte/wip-go1.17
nevkontakte Sep 17, 2021
54c7e77
Fix PkgPath of the unsafe.Pointer type.
nevkontakte Sep 17, 2021
ffaebd7
Update minified prelude.
nevkontakte Sep 17, 2021
d60ba2c
Fix compiler panic when assigning to a named pointer type.
nevkontakte Sep 17, 2021
a0dbb0e
Mark `fixedbugs/issue23017.go` as a known failure.
nevkontakte Sep 17, 2021
f7183f9
Merge pull request #1064 from nevkontakte/wip-go1.17
nevkontakte Sep 18, 2021
1c5f51f
runtime: Version() returns Go version provided by the compiler.
nevkontakte Sep 18, 2021
866eb02
Update VFS for `runtime`.
nevkontakte Sep 18, 2021
5890279
Update Go version to test against to 1.17.1.
nevkontakte Sep 18, 2021
41f8453
Merge pull request #1065 from nevkontakte/wip-go1.17
nevkontakte Sep 18, 2021
c05f513
Reduce the number of quickcheck iterations for edwards25519.
nevkontakte Sep 18, 2021
2550e90
Update VFS.
nevkontakte Sep 18, 2021
3873393
Merge pull request #1066 from nevkontakte/wip-go1.17
nevkontakte Sep 18, 2021
267d5db
Update README for Go 1.17.
nevkontakte Sep 18, 2021
7fa979d
Update build constraints on the compiler to require Go 1.17.
nevkontakte Sep 18, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .std_test_pkg_exclusions
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ go/internal/gccgoimporter
go/internal/gcimporter
go/internal/srcimporter
go/types
internal/abi
internal/syscall/unix
internal/syscall/windows
internal/syscall/windows/registry
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ GopherJS compiles Go code ([golang.org](https://golang.org/)) to pure JavaScript

### What's new?

- 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!** 🎉 🎉 🎉

Expand All @@ -22,7 +24,7 @@ Nearly everything, including Goroutines ([compatibility documentation](https://g

### Installation and Usage

GopherJS [requires Go 1.16 or newer](https://github.com/gopherjs/gopherjs/blob/master/doc/compatibility.md#go-version-compatibility). If you need an older Go
GopherJS [requires Go 1.17 or newer](https://github.com/gopherjs/gopherjs/blob/master/doc/compatibility.md#go-version-compatibility). If you need an older Go
version, you can use an [older Gopher release](https://github.com/gopherjs/gopherjs/releases).

Get or update GopherJS and dependencies with:
Expand All @@ -31,12 +33,12 @@ Get or update GopherJS and dependencies with:
go get -u github.com/gopherjs/gopherjs
```

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

```
go get golang.org/dl/go1.16.3
go1.16.3 download
export GOPHERJS_GOROOT="$(go1.16.3 env GOROOT)" # Also add this line to your .profile or equivalent.
go get golang.org/dl/go1.17.1
go1.17.1 download
export GOPHERJS_GOROOT="$(go1.17.1 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.
Expand Down
7 changes: 6 additions & 1 deletion build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,11 @@ func (s *Session) InstallSuffix() string {
return ""
}

// GoRelease returns Go release version this session is building with.
func (s *Session) GoRelease() string {
return compiler.GoRelease(s.options.GOROOT)
}

func (s *Session) BuildDir(packagePath string, importPath string, pkgObj string) error {
if s.Watcher != nil {
s.Watcher.Add(packagePath)
Expand Down Expand Up @@ -778,7 +783,7 @@ func (s *Session) WriteCommandPackage(archive *compiler.Archive, pkgObj string)
if err != nil {
return err
}
return compiler.WriteProgramCode(deps, sourceMapFilter)
return compiler.WriteProgramCode(deps, sourceMapFilter, s.GoRelease())
}

func NewMappingCallback(m *sourcemap.Map, goroot, gopath string, localMap bool) func(generatedLine, generatedColumn int, originalPos token.Position) {
Expand Down
4 changes: 2 additions & 2 deletions build/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
// cachePath is the base path for GopherJS's own build cache.
//
// It serves a similar function to the Go build cache, but is a lot more
// simlistic and therefore not compatible with Go. We use this cache directory
// simplistic and therefore not compatible with Go. We use this cache directory
// to store build artifacts for packages loaded from a module, for which PkgObj
// provided by go/build points inside the module source tree, which can cause
// inconvenience with version control, etc.
Expand All @@ -28,7 +28,7 @@ var cachePath = func() string {
// returned by go/build.
func cachedPath(orig string) string {
if orig == "" {
panic(fmt.Errorf("CachedPath() must not be used with an empty string"))
panic("CachedPath() must not be used with an empty string")
}
sum := fmt.Sprintf("%x", sha256.Sum256([]byte(orig)))
return filepath.Join(cachePath, sum[0:2], sum)
Expand Down
8 changes: 6 additions & 2 deletions build/versionhack/versionhack.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
// However, it naively assumes that the go tool version in the PATH matches the
// version that was used to build GopherJS and disables module support whenever
// ReleaseTags in the context are set to anything other than the default. This,
// unfortunately, isn't very helpful since gopherjs may be build by a Go version
// unfortunately, isn't very helpful since gopherjs may be built by a Go version
// other than the PATH's default.
//
// Luckily, even if go tool version is mismatches, it's only used for discovery
// Luckily, even if go tool version is mismatched, it's only used for discovery
// of the package locations, and go/build evaluates build constraints on its own
// with ReleaseTags we've passed.
//
Expand All @@ -37,6 +37,10 @@ import (
//go:linkname releaseTags go/build.defaultReleaseTags
var releaseTags []string

//go:linkname toolTags go/build.defaultToolTags
var toolTags []string

func init() {
releaseTags = build.Default.ReleaseTags[:compiler.GoVersion]
toolTags = []string{}
}
2 changes: 1 addition & 1 deletion circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ workflows:
parameters:
go_version:
type: string
default: "1.16.7"
default: "1.17.1"
nvm_version:
type: string
default: "0.38.0"
Expand Down
9 changes: 6 additions & 3 deletions compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ type dceInfo struct {
methodFilter string
}

func WriteProgramCode(pkgs []*Archive, w *SourceMapFilter) error {
func WriteProgramCode(pkgs []*Archive, w *SourceMapFilter, goVersion string) error {
mainPkg := pkgs[len(pkgs)-1]
minify := mainPkg.Minified

Expand Down Expand Up @@ -242,6 +242,10 @@ func WriteProgramCode(pkgs []*Archive, w *SourceMapFilter) error {
if _, err := w.Write([]byte("\"use strict\";\n(function() {\n\n")); err != nil {
return err
}
if _, err := w.Write([]byte(fmt.Sprintf("var $goVersion = %q;\n", goVersion))); err != nil {
return err
}

preludeJS := prelude.Prelude
if minify {
preludeJS = prelude.Minified
Expand All @@ -260,10 +264,9 @@ func WriteProgramCode(pkgs []*Archive, w *SourceMapFilter) error {
}
}

if _, err := w.Write([]byte("$synthesizeMethods();\n$initAllLinknames();var $mainPkg = $packages[\"" + string(mainPkg.ImportPath) + "\"];\n$packages[\"runtime\"].$init();\n$go($mainPkg.$init, []);\n$flushConsole();\n\n}).call(this);\n")); err != nil {
if _, err := w.Write([]byte("$synthesizeMethods();\n$initAllLinknames();\nvar $mainPkg = $packages[\"" + string(mainPkg.ImportPath) + "\"];\n$packages[\"runtime\"].$init();\n$go($mainPkg.$init, []);\n$flushConsole();\n\n}).call(this);\n")); err != nil {
return err
}

return nil
}

Expand Down
40 changes: 28 additions & 12 deletions compiler/expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ func (fc *funcContext) translateExpr(expr ast.Expr) *expression {

switch t.Underlying().(type) {
case *types.Struct, *types.Array:
// JavaScript's pass-by-reference semantics makes passing array's or
// struct's object semantically equivalent to passing a pointer
// TODO(nevkontakte): Evaluate if performance gain justifies complexity
// introduced by the special case.
return fc.translateExpr(e.X)
}

Expand Down Expand Up @@ -426,10 +430,6 @@ func (fc *funcContext) translateExpr(expr ast.Expr) *expression {
return fc.formatExpr("$equal(%e, %e, %s)", e.X, e.Y, fc.typeName(t))
case *types.Interface:
return fc.formatExpr("$interfaceIsEqual(%s, %s)", fc.translateImplicitConversion(e.X, t), fc.translateImplicitConversion(e.Y, t))
case *types.Pointer:
if _, ok := u.Elem().Underlying().(*types.Array); ok {
return fc.formatExpr("$equal(%s, %s, %s)", fc.translateImplicitConversion(e.X, t), fc.translateImplicitConversion(e.Y, t), fc.typeName(u.Elem()))
}
case *types.Basic:
if isBoolean(u) {
if b, ok := analysis.BoolValue(e.X, fc.pkgCtx.Info.Info); ok && b {
Expand All @@ -450,11 +450,22 @@ func (fc *funcContext) translateExpr(expr ast.Expr) *expression {

case *ast.IndexExpr:
switch t := fc.pkgCtx.TypeOf(e.X).Underlying().(type) {
case *types.Array, *types.Pointer:
case *types.Pointer:
if _, ok := t.Elem().Underlying().(*types.Array); !ok {
// Should never happen in type-checked code.
panic(fmt.Errorf("non-array pointers can't be used with index expression"))
}
// Rewrite arrPtr[i] → (*arrPtr)[i] to concentrate array dereferencing
// logic in one place.
x := &ast.StarExpr{
Star: e.X.Pos(),
X: e.X,
}
astutil.SetType(fc.pkgCtx.Info.Info, t.Elem(), x)
e.X = x
return fc.translateExpr(e)
case *types.Array:
pattern := rangeCheck("%1e[%2f]", fc.pkgCtx.Types[e.Index].Value != nil, true)
if _, ok := t.(*types.Pointer); ok { // check pointer for nix (attribute getter causes a panic)
pattern = `(%1e.nilCheck, ` + pattern + `)`
}
return fc.formatExpr(pattern, e.X, e.Index)
case *types.Slice:
return fc.formatExpr(rangeCheck("%1e.$array[%1e.$offset + %2f]", fc.pkgCtx.Types[e.Index].Value != nil, false), e.X, e.Index)
Expand Down Expand Up @@ -823,6 +834,7 @@ func (fc *funcContext) makeReceiver(e *ast.SelectorExpr) *expression {

recv := fc.translateImplicitConversionWithCloning(x, methodsRecvType)
if isWrapped(recvType) {
// Wrap JS-native value to have access to the Go type's methods.
recv = fc.formatExpr("new %s(%s)", fc.typeName(methodsRecvType), recv)
}
return recv
Expand Down Expand Up @@ -1031,7 +1043,7 @@ func (fc *funcContext) translateConversion(expr ast.Expr, desiredType types.Type
case t.Kind() == types.UnsafePointer:
if unary, isUnary := expr.(*ast.UnaryExpr); isUnary && unary.Op == token.AND {
if indexExpr, isIndexExpr := unary.X.(*ast.IndexExpr); isIndexExpr {
return fc.formatExpr("$sliceToArray(%s)", fc.translateConversionToSlice(indexExpr.X, types.NewSlice(types.Typ[types.Uint8])))
return fc.formatExpr("$sliceToNativeArray(%s)", fc.translateConversionToSlice(indexExpr.X, types.NewSlice(types.Typ[types.Uint8])))
}
if ident, isIdent := unary.X.(*ast.Ident); isIdent && ident.Name == "_zero" {
return fc.formatExpr("new Uint8Array(0)")
Expand Down Expand Up @@ -1075,8 +1087,12 @@ func (fc *funcContext) translateConversion(expr ast.Expr, desiredType types.Type
break
}

switch u := t.Elem().Underlying().(type) {
switch ptrElType := t.Elem().Underlying().(type) {
case *types.Array: // (*[N]T)(expr) — converting expr to a pointer to an array.
if _, ok := exprType.Underlying().(*types.Slice); ok {
return fc.formatExpr("$sliceToGoArray(%e, %s)", expr, fc.typeName(desiredType))
}
// TODO(nevkontakte): Is this just for aliased types (e.g. `type a [4]byte`)?
return fc.translateExpr(expr)
case *types.Struct: // (*StructT)(expr) — converting expr to a pointer to a struct.
if fc.pkgCtx.Pkg.Path() == "syscall" && types.Identical(exprType, types.Typ[types.UnsafePointer]) {
Expand All @@ -1086,7 +1102,7 @@ func (fc *funcContext) translateConversion(expr ast.Expr, desiredType types.Type
// indeed pointing at a byte array.
array := fc.newVariable("_array")
target := fc.newVariable("_struct")
return fc.formatExpr("(%s = %e, %s = %e, %s, %s)", array, expr, target, fc.zeroValue(t.Elem()), fc.loadStruct(array, target, u), target)
return fc.formatExpr("(%s = %e, %s = %e, %s, %s)", array, expr, target, fc.zeroValue(t.Elem()), fc.loadStruct(array, target, ptrElType), target)
}
// Convert between structs of different types but identical layouts,
// for example:
Expand Down Expand Up @@ -1152,7 +1168,7 @@ func (fc *funcContext) translateImplicitConversion(expr ast.Expr, desiredType ty

switch desiredType.Underlying().(type) {
case *types.Slice:
return fc.formatExpr("$subslice(new %1s(%2e.$array), %2e.$offset, %2e.$offset + %2e.$length)", fc.typeName(desiredType), expr)
return fc.formatExpr("$convertSliceType(%1e, %2s)", expr, fc.typeName(desiredType))

case *types.Interface:
if typesutil.IsJsObject(exprType) {
Expand Down
1 change: 1 addition & 0 deletions compiler/gopherjspkg/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
package gopherjspkg

//go:generate vfsgendev -source="github.com/gopherjs/gopherjs/compiler/gopherjspkg".FS -tag=gopherjsdev
//go:generate gofmt -w -s fs_vfsdata.go
1 change: 1 addition & 0 deletions compiler/gopherjspkg/fs.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build gopherjsdev
// +build gopherjsdev

package gopherjspkg
Expand Down
Loading