Skip to content

Commit

Permalink
Go 1.10 support (version bump to GopherJS 1.10-1). (gopherjs#755)
Browse files Browse the repository at this point in the history
Merge pull request gopherjs#755 from branch go1.10.
  • Loading branch information
dmitshur authored Feb 26, 2018
2 parents 3926a9f + 4ebbd33 commit 4e9f423
Show file tree
Hide file tree
Showing 25 changed files with 378 additions and 208 deletions.
1 change: 1 addition & 0 deletions build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ func importWithSrcDir(path string, srcDir string, mode build.ImportMode, install
pkg.GoFiles = exclude(pkg.GoFiles, "fd_poll_runtime.go")
case "crypto/rand":
pkg.GoFiles = []string{"rand.go", "util.go"}
pkg.TestGoFiles = exclude(pkg.TestGoFiles, "rand_linux_test.go") // Don't want linux-specific tests (since linux-specific package files are excluded too).
}

if len(pkg.CgoFiles) > 0 {
Expand Down
2 changes: 1 addition & 1 deletion circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ machine:

dependencies:
pre:
- cd /usr/local && sudo rm -rf go && curl https://storage.googleapis.com/golang/go1.9.linux-amd64.tar.gz | sudo tar -xz && sudo chmod a+w go/src/path/filepath
- cd /usr/local && sudo rm -rf go && curl https://storage.googleapis.com/golang/go1.10.linux-amd64.tar.gz | sudo tar -xz && sudo chmod a+w go/src/path/filepath
post:
- mv ./gopherjs $HOME/bin
- npm install --global node-gyp
Expand Down
2 changes: 1 addition & 1 deletion compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

var sizes32 = &types.StdSizes{WordSize: 4, MaxAlign: 8}
var reservedKeywords = make(map[string]bool)
var _ = ___GOPHERJS_REQUIRES_GO_VERSION_1_9___ // Compile error on other Go versions, because they're not supported.
var _ = ___GOPHERJS_REQUIRES_GO_VERSION_1_10___ // Compile error on other Go versions, because they're not supported.

func init() {
for _, keyword := range []string{"abstract", "arguments", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "debugger", "default", "delete", "do", "double", "else", "enum", "eval", "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if", "implements", "import", "in", "instanceof", "int", "interface", "let", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "typeof", "undefined", "var", "void", "volatile", "while", "with", "yield"} {
Expand Down
279 changes: 147 additions & 132 deletions compiler/natives/fs_vfsdata.go

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions compiler/natives/src/bytes/bytes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"testing"
)

func TestEqualNearPageBoundary(t *testing.T) {
t.Skip()
func dangerousSlice(t *testing.T) []byte {
t.Skip("dangerousSlice relies on syscall.Getpagesize, which GopherJS doesn't implement")

panic("unreachable")
}
6 changes: 6 additions & 0 deletions compiler/natives/src/encoding/gob/gob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,9 @@ func TestEndToEnd(t *testing.T) {
t.Errorf("nil map received")
}
}

func TestTypeRace(t *testing.T) {
// encoding/gob currently uses nosync. This test uses sync.WaitGroup and
// cannot succeed when nosync is used.
t.Skip("using nosync")
}
31 changes: 31 additions & 0 deletions compiler/natives/src/internal/poll/fd_poll_js.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,34 @@ func (*FD) SetWriteDeadline(t time.Time) error { return nil }
func PollDescriptor() uintptr {
return ^uintptr(0)
}

// Copy of sync.runtime_Semacquire.
func runtime_Semacquire(s *uint32) {
if *s == 0 {
ch := make(chan bool)
semWaiters[s] = append(semWaiters[s], ch)
<-ch
}
*s--
}

// Copy of sync.runtime_Semrelease.
func runtime_Semrelease(s *uint32) {
*s++

w := semWaiters[s]
if len(w) == 0 {
return
}

ch := w[0]
w = w[1:]
semWaiters[s] = w
if len(w) == 0 {
delete(semWaiters, s)
}

ch <- true
}

var semWaiters = make(map[*uint32][]chan bool)
6 changes: 5 additions & 1 deletion compiler/natives/src/io/io_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ func TestMultiWriter_WriteStringSingleAlloc(t *testing.T) {
}

func TestMultiReaderFlatten(t *testing.T) {
t.Skip()
t.Skip("test relies on runtime.Callers and runtime.CallersFrames, which GopherJS doesn't support")
}

func TestMultiWriterSingleChainFlatten(t *testing.T) {
t.Skip("test relies on runtime.Callers and runtime.CallersFrames, which GopherJS doesn't support")
}

func TestMultiReaderFreesExhaustedReaders(t *testing.T) {
Expand Down
4 changes: 0 additions & 4 deletions compiler/natives/src/math/math.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,6 @@ func Cosh(x float64) float64 {
return math.Call("cosh", x).Float()
}

func Dim(x, y float64) float64 {
return dim(x, y)
}

func Erf(x float64) float64 {
return erf(x)
}
Expand Down
111 changes: 69 additions & 42 deletions compiler/natives/src/reflect/reflect.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func reflectType(typ *js.Object) *rtype {
rt := &rtype{
size: uintptr(typ.Get("size").Int()),
kind: uint8(typ.Get("kind").Int()),
str: newNameOff(newName(internalStr(typ.Get("string")), "", "", typ.Get("exported").Bool())),
str: newNameOff(newName(internalStr(typ.Get("string")), "", typ.Get("exported").Bool())),
}
js.InternalObject(rt).Set("jsType", typ)
typ.Set("reflectType", js.InternalObject(rt))
Expand All @@ -57,12 +57,12 @@ func reflectType(typ *js.Object) *rtype {
for i := range reflectMethods {
m := methodSet.Index(i)
reflectMethods[i] = method{
name: newNameOff(newName(internalStr(m.Get("name")), "", "", internalStr(m.Get("pkg")) == "")),
name: newNameOff(newName(internalStr(m.Get("name")), "", internalStr(m.Get("pkg")) == "")),
mtyp: newTypeOff(reflectType(m.Get("typ"))),
}
}
ut := &uncommonType{
pkgPath: newNameOff(newName(internalStr(typ.Get("pkg")), "", "", false)),
pkgPath: newNameOff(newName(internalStr(typ.Get("pkg")), "", false)),
mcount: uint16(methodSet.Length()),
_methods: reflectMethods,
}
Expand Down Expand Up @@ -116,13 +116,13 @@ func reflectType(typ *js.Object) *rtype {
for i := range imethods {
m := methods.Index(i)
imethods[i] = imethod{
name: newNameOff(newName(internalStr(m.Get("name")), "", "", internalStr(m.Get("pkg")) == "")),
name: newNameOff(newName(internalStr(m.Get("name")), "", internalStr(m.Get("pkg")) == "")),
typ: newTypeOff(reflectType(m.Get("typ"))),
}
}
setKindType(rt, &interfaceType{
rtype: *rt,
pkgPath: newName(internalStr(typ.Get("pkg")), "", "", false),
pkgPath: newName(internalStr(typ.Get("pkg")), "", false),
methods: imethods,
})
case Map:
Expand All @@ -148,14 +148,14 @@ func reflectType(typ *js.Object) *rtype {
offsetAnon |= 1
}
reflectFields[i] = structField{
name: newName(internalStr(f.Get("name")), internalStr(f.Get("tag")), "", f.Get("exported").Bool()),
name: newName(internalStr(f.Get("name")), internalStr(f.Get("tag")), f.Get("exported").Bool()),
typ: reflectType(f.Get("typ")),
offsetAnon: offsetAnon,
}
}
setKindType(rt, &structType{
rtype: *rt,
pkgPath: newName(internalStr(typ.Get("pkgPath")), "", "", false),
pkgPath: newName(internalStr(typ.Get("pkgPath")), "", false),
fields: reflectFields,
})
}
Expand Down Expand Up @@ -213,34 +213,21 @@ type name struct {
type nameData struct {
name string
tag string
pkgPath string
exported bool
}

var nameMap = make(map[*byte]*nameData)

func (n name) name() (s string) {
return nameMap[n.bytes].name
}

func (n name) tag() (s string) {
return nameMap[n.bytes].tag
}
func (n name) name() (s string) { return nameMap[n.bytes].name }
func (n name) tag() (s string) { return nameMap[n.bytes].tag }
func (n name) pkgPath() string { return "" }
func (n name) isExported() bool { return nameMap[n.bytes].exported }

func (n name) pkgPath() string {
return nameMap[n.bytes].pkgPath
}

func (n name) isExported() bool {
return nameMap[n.bytes].exported
}

func newName(n, tag, pkgPath string, exported bool) name {
func newName(n, tag string, exported bool) name {
b := new(byte)
nameMap[b] = &nameData{
name: n,
tag: tag,
pkgPath: pkgPath,
exported: exported,
}
return name{
Expand Down Expand Up @@ -491,7 +478,7 @@ func loadScalar(p unsafe.Pointer, n uintptr) uintptr {
return js.InternalObject(p).Call("$get").Unsafe()
}

func makechan(typ *rtype, size uint64) (ch unsafe.Pointer) {
func makechan(typ *rtype, size int) (ch unsafe.Pointer) {
ctyp := (*chanType)(unsafe.Pointer(typ))
return unsafe.Pointer(js.Global.Get("$Chan").New(jsType(ctyp.elem), size).Unsafe())
}
Expand Down Expand Up @@ -597,7 +584,7 @@ func cvtDirect(v Value, typ Type) Value {
default:
panic(&ValueError{"reflect.Convert", k})
}
return Value{typ.common(), unsafe.Pointer(val.Unsafe()), v.flag&(flagRO|flagIndir) | flag(typ.Kind())}
return Value{typ.common(), unsafe.Pointer(val.Unsafe()), v.flag.ro() | v.flag&flagIndir | flag(typ.Kind())}
}

func Copy(dst, src Value) int {
Expand All @@ -611,12 +598,18 @@ func Copy(dst, src Value) int {
dst.mustBeExported()

sk := src.kind()
var stringCopy bool
if sk != Array && sk != Slice {
panic(&ValueError{"reflect.Copy", sk})
stringCopy = sk == String && dst.typ.Elem().Kind() == Uint8
if !stringCopy {
panic(&ValueError{"reflect.Copy", sk})
}
}
src.mustBeExported()

typesMustMatch("reflect.Copy", dst.typ.Elem(), src.typ.Elem())
if !stringCopy {
typesMustMatch("reflect.Copy", dst.typ.Elem(), src.typ.Elem())
}

dstVal := dst.object()
if dk == Array {
Expand All @@ -628,6 +621,9 @@ func Copy(dst, src Value) int {
srcVal = jsType(SliceOf(src.typ.Elem())).New(srcVal)
}

if stringCopy {
return js.Global.Call("$copyString", dstVal, srcVal).Int()
}
return js.Global.Call("$copySlice", dstVal, srcVal).Int()
}

Expand All @@ -645,11 +641,11 @@ func methodReceiver(op string, v Value, i int) (_, t *rtype, fn unsafe.Pointer)
t = tt.typeOff(m.typ)
prop = tt.nameOff(m.name).name()
} else {
ut := v.typ.uncommon()
if ut == nil || uint(i) >= uint(ut.mcount) {
ms := v.typ.exportedMethods()
if uint(i) >= uint(len(ms)) {
panic("reflect: internal error: invalid method index")
}
m := ut.methods()[i]
m := ms[i]
if !v.typ.nameOff(m.name).isExported() {
panic("reflect: " + op + " of unexported method")
}
Expand Down Expand Up @@ -702,7 +698,7 @@ func makeMethodValue(op string, v Value) Value {
fv := js.MakeFunc(func(this *js.Object, arguments []*js.Object) interface{} {
return js.InternalObject(fn).Call("apply", rcvr, arguments)
})
return Value{v.Type().common(), unsafe.Pointer(fv.Unsafe()), v.flag&flagRO | flag(Func)}
return Value{v.Type().common(), unsafe.Pointer(fv.Unsafe()), v.flag.ro() | flag(Func)}
}

func (t *rtype) pointers() bool {
Expand Down Expand Up @@ -796,6 +792,39 @@ func (v Value) object() *js.Object {
return js.InternalObject(v.ptr)
}

func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value {
if v.flag&flagMethod != 0 {
v = makeMethodValue(context, v)
}

switch {
case directlyAssignable(dst, v.typ):
// Overwrite type so that they match.
// Same memory layout, so no harm done.
fl := v.flag&(flagAddr|flagIndir) | v.flag.ro()
fl |= flag(dst.Kind())
return Value{dst, v.ptr, fl}

case implements(dst, v.typ):
if target == nil {
target = unsafe_New(dst)
}
// GopherJS: Skip the v.Kind() == Interface && v.IsNil() if statement
// from upstream. ifaceE2I below does not panic, and it needs
// to run, given its custom implementation.
x := valueInterface(v, false)
if dst.NumMethod() == 0 {
*(*interface{})(target) = x
} else {
ifaceE2I(dst, x, target)
}
return Value{dst, target, flagIndir | flag(Interface)}
}

// Failed.
panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String())
}

var callHelper = js.Global.Get("$call").Interface().(func(...interface{}) *js.Object)

func (v Value) call(op string, in []Value) []Value {
Expand Down Expand Up @@ -932,7 +961,7 @@ func (v Value) Elem() Value {
return Value{}
}
typ := reflectType(val.Get("constructor"))
return makeValue(typ, val.Get("$val"), v.flag&flagRO)
return makeValue(typ, val.Get("$val"), v.flag.ro())

case Ptr:
if v.IsNil() {
Expand Down Expand Up @@ -1053,8 +1082,7 @@ func (v Value) Index(i int) Value {
panic("reflect: array index out of range")
}
typ := tt.elem
fl := v.flag & (flagRO | flagIndir | flagAddr)
fl |= flag(typ.Kind())
fl := v.flag&(flagIndir|flagAddr) | v.flag.ro() | flag(typ.Kind())

a := js.InternalObject(v.ptr)
if fl&flagIndir != 0 && typ.Kind() != Array && typ.Kind() != Struct {
Expand All @@ -1072,8 +1100,7 @@ func (v Value) Index(i int) Value {
}
tt := (*sliceType)(unsafe.Pointer(v.typ))
typ := tt.elem
fl := flagAddr | flagIndir | v.flag&flagRO
fl |= flag(typ.Kind())
fl := flagAddr | flagIndir | v.flag.ro() | flag(typ.Kind())

i += s.Get("$offset").Int()
a := s.Get("$array")
Expand All @@ -1090,9 +1117,9 @@ func (v Value) Index(i int) Value {
if i < 0 || i >= len(str) {
panic("reflect: string index out of range")
}
fl := v.flag&flagRO | flag(Uint8)
fl := v.flag.ro() | flag(Uint8) | flagIndir
c := str[i]
return Value{uint8Type, unsafe.Pointer(&c), fl | flagIndir}
return Value{uint8Type, unsafe.Pointer(&c), fl}

default:
panic(&ValueError{"reflect.Value.Index", k})
Expand Down Expand Up @@ -1258,7 +1285,7 @@ func (v Value) Slice(i, j int) Value {
panic("reflect.Value.Slice: slice index out of bounds")
}

return makeValue(typ, js.Global.Call("$subslice", s, i, j), v.flag&flagRO)
return makeValue(typ, js.Global.Call("$subslice", s, i, j), v.flag.ro())
}

func (v Value) Slice3(i, j, k int) Value {
Expand Down Expand Up @@ -1290,7 +1317,7 @@ func (v Value) Slice3(i, j, k int) Value {
panic("reflect.Value.Slice3: slice index out of bounds")
}

return makeValue(typ, js.Global.Call("$subslice", s, i, j, k), v.flag&flagRO)
return makeValue(typ, js.Global.Call("$subslice", s, i, j, k), v.flag.ro())
}

func (v Value) Close() {
Expand Down
Loading

0 comments on commit 4e9f423

Please sign in to comment.