diff --git a/compiler/natives/src/encoding/gob/gob.go b/compiler/natives/src/encoding/gob/gob.go new file mode 100644 index 000000000..f21315171 --- /dev/null +++ b/compiler/natives/src/encoding/gob/gob.go @@ -0,0 +1,40 @@ +//go:build js +// +build js + +package gob + +import ( + "reflect" + "sync" +) + +type typeInfo struct { + id typeId + encInit sync.Mutex + + // temporarily replacement of atomic.Pointer[encEngine] for go1.20 without generics. + encoder atomicEncEnginePointer + wire *wireType +} + +type atomicEncEnginePointer struct { + v *encEngine +} + +func (x *atomicEncEnginePointer) Load() *encEngine { return x.v } +func (x *atomicEncEnginePointer) Store(val *encEngine) { x.v = val } + +// temporarily replacement of growSlice[E any] for go1.20 without generics. +func growSlice(v reflect.Value, ps any, length int) { + vps := reflect.ValueOf(ps) + vs := vps.Elem() + zero := reflect.Zero(vs.Elem().Type()) + vs.Set(reflect.Append(vs, zero)) + cp := vs.Cap() + if cp > length { + cp = length + } + vs.Set(vs.Slice(0, cp)) + v.Set(vs) + vps.Set(vs.Addr()) +} diff --git a/compiler/natives/src/go/token/position.go b/compiler/natives/src/go/token/position.go index 6a1ee0c15..436c48380 100644 --- a/compiler/natives/src/go/token/position.go +++ b/compiler/natives/src/go/token/position.go @@ -20,3 +20,11 @@ type atomicFilePointer struct { func (x *atomicFilePointer) Load() *File { return x.v } func (x *atomicFilePointer) Store(val *File) { x.v = val } + +func (x *atomicFilePointer) CompareAndSwap(old, new *File) bool { + if x.v == old { + x.v = new + return true + } + return false +} diff --git a/compiler/natives/src/internal/godebug/godebug.go b/compiler/natives/src/internal/godebug/godebug.go new file mode 100644 index 000000000..4fff419b5 --- /dev/null +++ b/compiler/natives/src/internal/godebug/godebug.go @@ -0,0 +1,83 @@ +//go:build js +// +build js + +package godebug + +import ( + "sync" +) + +type Setting struct { + name string + once sync.Once + + // temporarily replacement of atomic.Pointer[string] for go1.20 without generics. + value *atomicStringPointer +} + +type atomicStringPointer struct { + v *string +} + +func (x *atomicStringPointer) Load() *string { return x.v } +func (x *atomicStringPointer) Store(val *string) { x.v = val } + +func (s *Setting) Value() string { + s.once.Do(func() { + v, ok := cache.Load(s.name) + if !ok { + // temporarily replacement of atomic.Pointer[string] for go1.20 without generics. + p := new(atomicStringPointer) + p.Store(&empty) + v, _ = cache.LoadOrStore(s.name, p) + } + // temporarily replacement of atomic.Pointer[string] for go1.20 without generics. + s.value = v.(*atomicStringPointer) + }) + return *s.value.Load() +} + +func update(def, env string) { + updateMu.Lock() + defer updateMu.Unlock() + + did := make(map[string]bool) + parse(did, env) + parse(did, def) + + cache.Range(func(name, v any) bool { + if !did[name.(string)] { + // temporarily replacement of atomic.Pointer[string] for go1.20 without generics. + v.(*atomicStringPointer).Store(&empty) + } + return true + }) +} + +func parse(did map[string]bool, s string) { + end := len(s) + eq := -1 + for i := end - 1; i >= -1; i-- { + if i == -1 || s[i] == ',' { + if eq >= 0 { + name, value := s[i+1:eq], s[eq+1:end] + if !did[name] { + did[name] = true + v, ok := cache.Load(name) + if !ok { + // temporarily replacement of atomic.Pointer[string] for go1.20 without generics. + p := new(atomicStringPointer) + p.Store(&empty) + v, _ = cache.LoadOrStore(name, p) + } + // temporarily replacement of atomic.Pointer[string] for go1.20 without generics. + v.(*atomicStringPointer).Store(&value) + } + } + eq = -1 + end = i + } else if s[i] == '=' { + eq = i + } + } +} diff --git a/compiler/natives/src/net/http/http.go b/compiler/natives/src/net/http/http.go index 8fd607c4d..f82c0363c 100644 --- a/compiler/natives/src/net/http/http.go +++ b/compiler/natives/src/net/http/http.go @@ -6,10 +6,15 @@ package http import ( "bufio" "bytes" + "context" + "crypto/tls" "errors" "io" + "net" "net/textproto" "strconv" + "sync" + "sync/atomic" "github.com/gopherjs/gopherjs/js" ) @@ -113,3 +118,30 @@ func (t *XHRTransport) CancelRequest(req *Request) { xhr.Call("abort") } } + +type conn struct { + server *Server + cancelCtx context.CancelFunc + rwc net.Conn + remoteAddr string + tlsState *tls.ConnectionState + werr error + r *connReader + bufr *bufio.Reader + bufw *bufio.Writer + lastMethod string + + // temporarily replacement of `atomic.Pointer[response]` for go1.20 without generics. + curReq atomicResponsePointer + + curState atomic.Uint64 + mu sync.Mutex + hijackedv bool +} + +type atomicResponsePointer struct { + v *response +} + +func (x *atomicResponsePointer) Load() *response { return x.v } +func (x *atomicResponsePointer) Store(val *response) { x.v = val } diff --git a/compiler/natives/src/sync/atomic/atomic.go b/compiler/natives/src/sync/atomic/atomic.go index 1cbfe65f9..d993f3b80 100644 --- a/compiler/natives/src/sync/atomic/atomic.go +++ b/compiler/natives/src/sync/atomic/atomic.go @@ -221,5 +221,19 @@ func sameType(x, y interface{}) bool { return js.InternalObject(x).Get("constructor") == js.InternalObject(y).Get("constructor") } -//gopherjs:purge for go1.19 without generics +// Override pointer so that the type check in the source code is satisfied +// but remove the fields and methods for go1.20 without generics. +// See https://cs.opensource.google/go/go/+/refs/tags/go1.20.14:src/sync/atomic/type.go;l=40 type Pointer[T any] struct{} + +//gopherjs:purge for go1.20 without generics +func (x *Pointer[T]) Load() *T + +//gopherjs:purge for go1.20 without generics +func (x *Pointer[T]) Store(val *T) + +//gopherjs:purge for go1.20 without generics +func (x *Pointer[T]) Swap(new *T) (old *T) + +//gopherjs:purge for go1.20 without generics +func (x *Pointer[T]) CompareAndSwap(old, new *T) (swapped bool) diff --git a/compiler/natives/src/time/export_test.go b/compiler/natives/src/time/export_test.go new file mode 100644 index 000000000..5cd3fc6ab --- /dev/null +++ b/compiler/natives/src/time/export_test.go @@ -0,0 +1,9 @@ +//go:build js +// +build js + +package time + +// replaced `parseRFC3339[string]` for go1.20 temporarily without generics. +var ParseRFC3339 = func(s string, local *Location) (Time, bool) { + return parseRFC3339(s, local) +}