Skip to content

Commit 6d4ada3

Browse files
authored
Merge pull request gopherjs#1120 from nevkontakte/go1.18
Various standard library and compiler fixes to support Go 1.18
2 parents 76289a7 + 28ce160 commit 6d4ada3

File tree

15 files changed

+229
-42
lines changed

15 files changed

+229
-42
lines changed

.std_test_pkg_exclusions

+2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
embed/internal/embedtest
2+
encoding/xml
23
go/build
34
go/internal/srcimporter
45
go/types
56
internal/abi
7+
internal/intern
68
internal/syscall/windows
79
internal/syscall/windows/registry
810
internal/syscall/windows/sysdll

compiler/gopherjspkg/fs_vfsdata.go

+9-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler/natives/fs_vfsdata.go

+64-26
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//go:build js
2+
3+
package intern
4+
5+
var (
6+
eth0 = &Value{cmpVal: "eth0"}
7+
eth1 = &Value{cmpVal: "eth1"}
8+
)
9+
10+
func get(k key) *Value {
11+
// Interning implementation in this package unavoidably relies upon
12+
// runtime.SetFinalizer(), which GopherJS doesn't support (at least until it
13+
// is considered safe to use the WeakMap API). Without working finalizers
14+
// using this package would create memory leaks.
15+
//
16+
// Considering that this package is supposed to serve as an optimization tool,
17+
// it is better to make it explicitly unusable and work around it at the call
18+
// sites.
19+
20+
// net/netip tests use intern API with a few fixed values. It is easier to
21+
// special-case them here than to override the entire test set.
22+
if k.isString && k.s == "eth0" {
23+
return eth0
24+
} else if k.isString && k.s == "eth1" {
25+
return eth1
26+
}
27+
28+
panic("internal/intern is not supported by GopherJS")
29+
}

compiler/natives/src/math/math.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ var math = js.Global.Get("Math")
1111
var _zero float64 = 0
1212
var posInf = 1 / _zero
1313
var negInf = -1 / _zero
14-
var nan = 0 / _zero
14+
15+
// Usually, NaN can be obtained in JavaScript with `0 / 0` operation. However,
16+
// in V8, `0 / _zero` yields a bitwise-different value of NaN compared to the
17+
// default NaN or `0 / 0`. Unfortunately, Go compiler forbids division by zero,
18+
// so we have to get this value from prelude.
19+
var nan = js.Global.Get("$NaN").Float()
1520

1621
func Acos(x float64) float64 {
1722
return math.Call("acos", x).Float()

compiler/natives/src/net/http/http_wasm_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ func init() {
1111
// TODO(nevkontakte): We could test our real implementations if we mock out
1212
// browser APIs and redirect them to the fake networking stack, but this is
1313
// not easy.
14-
useFakeNetwork = true
14+
jsFetchMissing = true
1515
DefaultTransport = &Transport{}
1616
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//go:build js
2+
3+
package netip
4+
5+
import (
6+
"fmt"
7+
"internal/intern"
8+
)
9+
10+
//gopherjs:prune-original
11+
func MkAddr(u Uint128, z any) Addr {
12+
switch z := z.(type) {
13+
case *intern.Value:
14+
return Addr{u, z.Get().(string)}
15+
case string:
16+
return Addr{u, z}
17+
default:
18+
panic(fmt.Errorf("unexpected type %T of the z argument"))
19+
}
20+
}
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//go:build js
2+
3+
package netip
4+
5+
type Addr struct {
6+
addr uint128
7+
// Unlike the upstream, we store the string directly instead of trying to
8+
// use internal/intern package for optimization.
9+
z string
10+
}
11+
12+
var (
13+
// Sentinel values for different zones. \x00 character makes it unlikely for
14+
// the sentinel value to clash with any real-life IPv6 zone index.
15+
z0 = ""
16+
z4 = "\x00ipv4"
17+
z6noz = "\x00ipv6noz"
18+
)
19+
20+
//gopherjs:prune-original
21+
func (ip Addr) Zone() string {
22+
if ip.z == z4 || ip.z == z6noz {
23+
return ""
24+
}
25+
return ip.z
26+
}
27+
28+
//gopherjs:prune-original
29+
func (ip Addr) WithZone(zone string) Addr {
30+
if !ip.Is6() {
31+
return ip
32+
}
33+
if zone == "" {
34+
ip.z = z6noz
35+
return ip
36+
}
37+
ip.z = zone
38+
return ip
39+
}

compiler/natives/src/reflect/reflect.go

+19
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,25 @@ func mapdelete(t *rtype, m unsafe.Pointer, key unsafe.Pointer) {
660660
js.InternalObject(m).Delete(k)
661661
}
662662

663+
// TODO(nevkonatkte): The following three "faststr" implementations are meant to
664+
// perform better for the common case of string-keyed maps (see upstream:
665+
// https://github.com/golang/go/commit/23832ba2e2fb396cda1dacf3e8afcb38ec36dcba)
666+
// However, the stubs below will perform the same or worse because of the extra
667+
// string-to-pointer conversion. Not sure how to fix this without significant
668+
// code duplication, however.
669+
670+
func mapaccess_faststr(t *rtype, m unsafe.Pointer, key string) (val unsafe.Pointer) {
671+
return mapaccess(t, m, unsafe.Pointer(&key))
672+
}
673+
674+
func mapassign_faststr(t *rtype, m unsafe.Pointer, key string, val unsafe.Pointer) {
675+
mapassign(t, m, unsafe.Pointer(&key), val)
676+
}
677+
678+
func mapdelete_faststr(t *rtype, m unsafe.Pointer, key string) {
679+
mapdelete(t, m, unsafe.Pointer(&key))
680+
}
681+
663682
type hiter struct {
664683
t Type
665684
m *js.Object // Underlying map object.

compiler/natives/src/strings/strings.go

+7
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,10 @@ func (b *Builder) copyCheck() {
6666
panic("strings: illegal use of non-zero Builder copied by value")
6767
}
6868
}
69+
70+
func Clone(s string) string {
71+
// Since in the JavaScript runtime we don't have access the the string's
72+
// baking memory, we let the engine's garbage collector deal with substring
73+
// memory overheads and simply return the string as-is.
74+
return s
75+
}

compiler/natives/src/strings/strings_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,7 @@ func TestBuilderGrow(t *testing.T) {
1616
func TestCompareStrings(t *testing.T) {
1717
t.Skip("unsafeString not supported in GopherJS")
1818
}
19+
20+
func TestClone(t *testing.T) {
21+
t.Skip("conversion to reflect.StringHeader is not supported in GopherJS")
22+
}

compiler/package.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ func Compile(importPath string, files []*ast.File, fileSet *token.FileSet, impor
134134
return
135135
}
136136
// Some other unexpected panic, catch the stack trace and return as an error.
137-
err = bailout(e)
137+
err = bailout(fmt.Errorf("unexpected compiler panic while building package %q: %v", importPath, e))
138138
}()
139139

140140
// Files must be in the same order to get reproducible JS
@@ -645,7 +645,8 @@ func (fc *funcContext) initArgs(ty types.Type) string {
645645
}
646646
return fmt.Sprintf(`"%s", [%s]`, pkgPath, strings.Join(fields, ", "))
647647
default:
648-
panic("invalid type")
648+
err := bailout(fmt.Errorf("%v has unexpected type %T", ty, ty))
649+
panic(err)
649650
}
650651
}
651652

compiler/prelude/prelude.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const Prelude = prelude + numeric + types + goroutines + jsmapping
77

88
const prelude = `Error.stackTraceLimit = Infinity;
99
10+
var $NaN = NaN;
1011
var $global, $module;
1112
if (typeof window !== "undefined") { /* web page */
1213
$global = window;
@@ -201,7 +202,7 @@ var $sliceToGoArray = function(slice, arrayPtrType) {
201202
return arrayPtrType.nil; // Nil slice converts to nil array pointer.
202203
}
203204
if (slice.$array.constructor !== Array) {
204-
return slice.$array.subarray(slice.$offset, slice.$offset + slice.$length);
205+
return slice.$array.subarray(slice.$offset, slice.$offset + arrayType.len);
205206
}
206207
if (slice.$offset == 0 && slice.$length == slice.$capacity && slice.$length == arrayType.len) {
207208
return slice.$array;

compiler/prelude/prelude_min.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/slice_to_array_ptr_test.go

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package tests
22

3-
import "testing"
3+
import (
4+
"runtime"
5+
"testing"
6+
)
47

58
// https://tip.golang.org/ref/spec#Conversions_from_slice_to_array_pointer
69
func TestSliceToArrayPointerConversion(t *testing.T) {
@@ -75,6 +78,25 @@ func TestSliceToArrayPointerConversion(t *testing.T) {
7578
t.Error("u0 should not be nil")
7679
}
7780
})
81+
82+
t.Run("SliceToShorterArray", func(t *testing.T) {
83+
s[0] = 'x'
84+
s[1] = 'y'
85+
s4 := (*[1]byte)(s[:])
86+
if got := s4[0]; got != 'x' {
87+
t.Errorf("Got s0[0] = %q, want 'x'", got)
88+
}
89+
if got := len(s4); got != 1 {
90+
t.Errorf("Got len(s0) = %d, want 1.", got)
91+
}
92+
93+
// Verify that the backing array size has been reduced to match the Go
94+
// type. If not, a "source too large" runtime exception will be thrown
95+
// upon the copy attempt.
96+
s5 := [1]byte{}
97+
s5 = *s4
98+
runtime.KeepAlive(s5)
99+
})
78100
})
79101

80102
t.Run("String", func(t *testing.T) {

0 commit comments

Comments
 (0)