goscript 0.1.4 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/cmd/go_js_wasm_exec/main.go +201 -0
- package/cmd/go_js_wasm_exec/main_test.go +83 -0
- package/cmd/goscript/{cmd_compile.go → cmd-compile.go} +7 -0
- package/cmd/goscript/cmd-test.go +14 -0
- package/cmd/goscript/cmd-test_test.go +1 -1
- package/cmd/goscript-wasm/main.go +38 -6
- package/compiler/compile-request.go +12 -9
- package/compiler/compliance_test.go +0 -1
- package/compiler/config.go +2 -0
- package/compiler/diagnostic.go +104 -12
- package/compiler/diagnostic_test.go +106 -0
- package/compiler/gotest/request.go +28 -0
- package/compiler/gotest/runner.go +354 -44
- package/compiler/gotest/runner_test.go +293 -1
- package/compiler/gotest/testdata/browserapi/browserapi_test.go +20 -0
- package/compiler/gotest/testdata/browserapi/go.mod +3 -0
- package/compiler/index.test.ts +23 -0
- package/compiler/lowered-program.go +33 -24
- package/compiler/lowering.go +746 -194
- package/compiler/lowering_bench_test.go +42 -27
- package/compiler/lowering_internal_test.go +18 -0
- package/compiler/override-facts.go +15 -0
- package/compiler/override-parity-verifier.go +450 -0
- package/compiler/override-parity.go +122 -0
- package/compiler/override-registry_test.go +559 -0
- package/compiler/protobuf-ts-binding.go +567 -0
- package/compiler/protobuf-ts-binding_test.go +402 -0
- package/compiler/runtime-contract.go +4 -0
- package/compiler/runtime-contract_test.go +2 -0
- package/compiler/semantic-model-types.go +9 -4
- package/compiler/semantic-model.go +282 -70
- package/compiler/semantic-model_test.go +82 -1
- package/compiler/service.go +21 -1
- package/compiler/skeleton_test.go +118 -10
- package/compiler/typescript-emitter.go +128 -13
- package/compiler/wasm/compile_test.go +37 -4
- package/compiler/{wasm_api.go → wasm-api.go} +57 -7
- package/dist/gs/builtin/hostio.js +5 -0
- package/dist/gs/builtin/hostio.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +13 -2
- package/dist/gs/builtin/slice.js +187 -6
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +13 -5
- package/dist/gs/builtin/type.js +153 -60
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/builtin/varRef.d.ts +11 -0
- package/dist/gs/builtin/varRef.js +57 -2
- package/dist/gs/builtin/varRef.js.map +1 -1
- package/dist/gs/bytes/buffer.gs.js +1 -1
- package/dist/gs/bytes/buffer.gs.js.map +1 -1
- package/dist/gs/bytes/reader.gs.js +1 -1
- package/dist/gs/bytes/reader.gs.js.map +1 -1
- package/dist/gs/compress/zlib/index.d.ts +10 -3
- package/dist/gs/compress/zlib/index.js +50 -16
- package/dist/gs/compress/zlib/index.js.map +1 -1
- package/dist/gs/encoding/json/index.d.ts +114 -0
- package/dist/gs/encoding/json/index.js +544 -36
- package/dist/gs/encoding/json/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +101 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +589 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.d.ts +1 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +17 -11
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/errors.js +54 -30
- package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
- package/dist/gs/go/scanner/index.d.ts +2 -0
- package/dist/gs/go/scanner/index.js +29 -5
- package/dist/gs/go/scanner/index.js.map +1 -1
- package/dist/gs/go/token/index.js +22 -6
- package/dist/gs/go/token/index.js.map +1 -1
- package/dist/gs/hash/index.d.ts +6 -0
- package/dist/gs/hash/index.js +20 -0
- package/dist/gs/hash/index.js.map +1 -1
- package/dist/gs/internal/byteorder/index.js +2 -2
- package/dist/gs/internal/byteorder/index.js.map +1 -1
- package/dist/gs/internal/goarch/index.d.ts +43 -3
- package/dist/gs/internal/goarch/index.js +42 -10
- package/dist/gs/internal/goarch/index.js.map +1 -1
- package/dist/gs/io/fs/fs.js +26 -14
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/io/fs/readdir.js +4 -2
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/fs/sub.js +8 -1
- package/dist/gs/io/fs/sub.js.map +1 -1
- package/dist/gs/io/io.d.ts +2 -0
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/math/bits/index.d.ts +5 -0
- package/dist/gs/math/bits/index.js +16 -4
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/mime/index.d.ts +16 -0
- package/dist/gs/mime/index.js +315 -6
- package/dist/gs/mime/index.js.map +1 -1
- package/dist/gs/net/http/httptest/index.d.ts +12 -0
- package/dist/gs/net/http/httptest/index.js +85 -6
- package/dist/gs/net/http/httptest/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +300 -5
- package/dist/gs/net/http/index.js +1598 -58
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/os/dir_unix.gs.js +1 -1
- package/dist/gs/os/dir_unix.gs.js.map +1 -1
- package/dist/gs/os/error.gs.js +1 -1
- package/dist/gs/os/error.gs.js.map +1 -1
- package/dist/gs/os/exec.gs.d.ts +1 -0
- package/dist/gs/os/exec.gs.js +4 -8
- package/dist/gs/os/exec.gs.js.map +1 -1
- package/dist/gs/os/exec_posix.gs.js +1 -1
- package/dist/gs/os/exec_posix.gs.js.map +1 -1
- package/dist/gs/os/index.d.ts +1 -1
- package/dist/gs/os/index.js +1 -1
- package/dist/gs/os/index.js.map +1 -1
- package/dist/gs/os/proc.gs.d.ts +4 -0
- package/dist/gs/os/proc.gs.js +12 -6
- package/dist/gs/os/proc.gs.js.map +1 -1
- package/dist/gs/os/root_js.gs.js +1 -1
- package/dist/gs/os/root_js.gs.js.map +1 -1
- package/dist/gs/os/types.gs.js +1 -1
- package/dist/gs/os/types.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.js +1 -1
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.js +1 -1
- package/dist/gs/os/types_unix.gs.js.map +1 -1
- package/dist/gs/path/path.js +11 -7
- package/dist/gs/path/path.js.map +1 -1
- package/dist/gs/reflect/index.d.ts +5 -4
- package/dist/gs/reflect/index.js +4 -3
- package/dist/gs/reflect/index.js.map +1 -1
- package/dist/gs/reflect/map.js +15 -0
- package/dist/gs/reflect/map.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +25 -6
- package/dist/gs/reflect/type.js +1475 -228
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/reflect/types.d.ts +14 -6
- package/dist/gs/reflect/types.js +35 -1
- package/dist/gs/reflect/types.js.map +1 -1
- package/dist/gs/reflect/value.d.ts +1 -0
- package/dist/gs/reflect/value.js +83 -41
- package/dist/gs/reflect/value.js.map +1 -1
- package/dist/gs/reflect/visiblefields.js +4 -140
- package/dist/gs/reflect/visiblefields.js.map +1 -1
- package/dist/gs/runtime/pprof/index.d.ts +8 -2
- package/dist/gs/runtime/pprof/index.js +50 -30
- package/dist/gs/runtime/pprof/index.js.map +1 -1
- package/dist/gs/runtime/runtime.js +5 -4
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/runtime/trace/index.js +5 -19
- package/dist/gs/runtime/trace/index.js.map +1 -1
- package/dist/gs/strconv/atoi.gs.js +1 -1
- package/dist/gs/strconv/atoi.gs.js.map +1 -1
- package/dist/gs/strconv/complex.gs.d.ts +3 -0
- package/dist/gs/strconv/complex.gs.js +148 -0
- package/dist/gs/strconv/complex.gs.js.map +1 -0
- package/dist/gs/strconv/index.d.ts +1 -0
- package/dist/gs/strconv/index.js +1 -0
- package/dist/gs/strconv/index.js.map +1 -1
- package/dist/gs/strings/builder.js +1 -1
- package/dist/gs/strings/reader.js +9 -5
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/strings/replace.js +15 -7
- package/dist/gs/strings/replace.js.map +1 -1
- package/dist/gs/strings/strings.d.ts +5 -0
- package/dist/gs/strings/strings.js +57 -5
- package/dist/gs/strings/strings.js.map +1 -1
- package/dist/gs/sync/atomic/doc_64.gs.js +7 -6
- package/dist/gs/sync/atomic/doc_64.gs.js.map +1 -1
- package/dist/gs/sync/atomic/type.gs.js +9 -9
- package/dist/gs/sync/atomic/type.gs.js.map +1 -1
- package/dist/gs/sync/atomic/value.gs.js +2 -2
- package/dist/gs/sync/atomic/value.gs.js.map +1 -1
- package/dist/gs/syscall/env.js +22 -14
- package/dist/gs/syscall/env.js.map +1 -1
- package/dist/gs/testing/testing.js +55 -13
- package/dist/gs/testing/testing.js.map +1 -1
- package/dist/gs/time/time.d.ts +24 -1
- package/dist/gs/time/time.js +43 -3
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unique/index.js +7 -1
- package/dist/gs/unique/index.js.map +1 -1
- package/go.mod +3 -3
- package/go.sum +16 -0
- package/gs/builtin/hostio.test.ts +16 -0
- package/gs/builtin/hostio.ts +7 -0
- package/gs/builtin/runtime-contract.test.ts +246 -21
- package/gs/builtin/slice.ts +269 -24
- package/gs/builtin/type.ts +226 -59
- package/gs/builtin/varRef.ts +85 -2
- package/gs/bytes/buffer.gs.ts +1 -1
- package/gs/bytes/reader.gs.ts +1 -1
- package/gs/compress/zlib/index.test.ts +62 -1
- package/gs/compress/zlib/index.ts +53 -16
- package/gs/compress/zlib/parity.json +51 -0
- package/gs/encoding/json/index.test.ts +360 -6
- package/gs/encoding/json/index.ts +679 -38
- package/gs/encoding/json/parity.json +81 -0
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +373 -3
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +893 -1
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +18 -0
- package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +17 -11
- package/gs/github.com/pkg/errors/errors.ts +54 -30
- package/gs/go/scanner/index.test.ts +39 -56
- package/gs/go/scanner/index.ts +33 -5
- package/gs/go/scanner/parity.json +27 -0
- package/gs/go/token/index.ts +22 -6
- package/gs/hash/index.test.ts +20 -33
- package/gs/hash/index.ts +28 -0
- package/gs/hash/parity.json +21 -0
- package/gs/internal/byteorder/index.test.ts +2 -2
- package/gs/internal/byteorder/index.ts +2 -2
- package/gs/internal/goarch/index.test.ts +32 -0
- package/gs/internal/goarch/index.ts +45 -13
- package/gs/internal/goarch/parity.json +144 -0
- package/gs/io/fs/fs.ts +26 -14
- package/gs/io/fs/readdir.ts +4 -4
- package/gs/io/fs/sub.ts +8 -1
- package/gs/io/io.ts +1 -0
- package/gs/io/parity.json +162 -0
- package/gs/math/bits/index.test.ts +14 -1
- package/gs/math/bits/index.ts +23 -4
- package/gs/math/bits/parity.json +156 -0
- package/gs/mime/index.test.ts +90 -0
- package/gs/mime/index.ts +369 -6
- package/gs/mime/parity.json +36 -0
- package/gs/net/http/httptest/index.test.ts +98 -2
- package/gs/net/http/httptest/index.ts +101 -6
- package/gs/net/http/httptest/parity.json +15 -0
- package/gs/net/http/index.test.ts +781 -12
- package/gs/net/http/index.ts +1860 -139
- package/gs/net/http/meta.json +16 -1
- package/gs/net/http/parity.json +193 -0
- package/gs/os/dir_unix.gs.ts +1 -1
- package/gs/os/error.gs.ts +1 -1
- package/gs/os/exec.gs.ts +4 -8
- package/gs/os/exec_posix.gs.ts +1 -1
- package/gs/os/index.test.ts +9 -0
- package/gs/os/index.ts +1 -0
- package/gs/os/parity.json +9 -0
- package/gs/os/proc.gs.ts +18 -5
- package/gs/os/proc.test.ts +26 -0
- package/gs/os/root_js.gs.ts +1 -1
- package/gs/os/types.gs.ts +1 -1
- package/gs/os/types_js.gs.ts +1 -1
- package/gs/os/types_unix.gs.ts +1 -1
- package/gs/path/path.ts +11 -7
- package/gs/reflect/field.test.ts +37 -15
- package/gs/reflect/function-types.test.ts +518 -22
- package/gs/reflect/index.ts +8 -6
- package/gs/reflect/map.ts +20 -0
- package/gs/reflect/meta.json +6 -4
- package/gs/reflect/parity.json +234 -0
- package/gs/reflect/sliceat.test.ts +156 -0
- package/gs/reflect/structof.test.ts +401 -0
- package/gs/reflect/type.ts +1961 -317
- package/gs/reflect/typefor.test.ts +530 -10
- package/gs/reflect/types.ts +43 -18
- package/gs/reflect/value.ts +105 -45
- package/gs/reflect/visiblefields.ts +5 -168
- package/gs/runtime/parity.json +24 -0
- package/gs/runtime/pprof/index.test.ts +29 -7
- package/gs/runtime/pprof/index.ts +56 -30
- package/gs/runtime/pprof/parity.json +27 -0
- package/gs/runtime/runtime.test.ts +3 -1
- package/gs/runtime/runtime.ts +4 -3
- package/gs/runtime/trace/index.test.ts +5 -3
- package/gs/runtime/trace/index.ts +8 -20
- package/gs/runtime/trace/parity.json +36 -0
- package/gs/strconv/atoi.gs.ts +1 -1
- package/gs/strconv/complex.gs.ts +174 -0
- package/gs/strconv/complex.test.ts +65 -0
- package/gs/strconv/index.ts +1 -0
- package/gs/strconv/parity.json +120 -0
- package/gs/strings/builder.ts +1 -1
- package/gs/strings/parity.json +186 -0
- package/gs/strings/reader.ts +9 -5
- package/gs/strings/replace.ts +15 -7
- package/gs/strings/strings.test.ts +22 -2
- package/gs/strings/strings.ts +64 -6
- package/gs/sync/atomic/doc_64.gs.ts +6 -7
- package/gs/sync/atomic/doc_64.test.ts +43 -0
- package/gs/sync/atomic/type.gs.ts +9 -9
- package/gs/sync/atomic/value.gs.ts +2 -2
- package/gs/syscall/env.ts +29 -14
- package/gs/testing/testing.test.ts +67 -0
- package/gs/testing/testing.ts +87 -19
- package/gs/time/parity.json +225 -0
- package/gs/time/time.test.ts +20 -2
- package/gs/time/time.ts +49 -7
- package/gs/unique/index.ts +7 -1
- package/package.json +4 -2
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +0 -217
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +0 -926
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +0 -1
- package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +0 -38
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +0 -1361
- package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +0 -46
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
package compiler
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"errors"
|
|
6
|
+
"go/ast"
|
|
7
|
+
"os"
|
|
8
|
+
"path/filepath"
|
|
9
|
+
"strings"
|
|
10
|
+
"testing"
|
|
11
|
+
|
|
12
|
+
"golang.org/x/tools/go/packages"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
func TestProtobufTypeScriptBindingSkipsPbGoEmission(t *testing.T) {
|
|
16
|
+
dir := t.TempDir()
|
|
17
|
+
writeTestFile(t, dir, "go.mod", "module example.test/protobufbinding\n\ngo 1.25\n")
|
|
18
|
+
writeTestFile(t, dir, "foo.pb.go", `package protobufbinding
|
|
19
|
+
|
|
20
|
+
type Foo struct {
|
|
21
|
+
Name string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type Object struct {
|
|
25
|
+
Name string
|
|
26
|
+
}
|
|
27
|
+
`)
|
|
28
|
+
writeTestFile(t, dir, "foo.pb.ts", `export interface Foo {
|
|
29
|
+
name?: string
|
|
30
|
+
}
|
|
31
|
+
export const Foo = {} as any
|
|
32
|
+
export interface Object$ {
|
|
33
|
+
name?: string
|
|
34
|
+
}
|
|
35
|
+
export const Object$ = {} as any
|
|
36
|
+
`)
|
|
37
|
+
writeTestFile(t, dir, "use.go", `package protobufbinding
|
|
38
|
+
|
|
39
|
+
func NewFoo() Foo {
|
|
40
|
+
return Foo{Name: "bound"}
|
|
41
|
+
}
|
|
42
|
+
`)
|
|
43
|
+
|
|
44
|
+
out := filepath.Join(dir, "out")
|
|
45
|
+
comp, err := NewCompiler(&Config{
|
|
46
|
+
Dir: dir,
|
|
47
|
+
OutputPath: out,
|
|
48
|
+
ProtobufTypeScriptBinding: true,
|
|
49
|
+
}, nil, nil)
|
|
50
|
+
if err != nil {
|
|
51
|
+
t.Fatal(err)
|
|
52
|
+
}
|
|
53
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
54
|
+
t.Fatalf("compile with protobuf TypeScript binding: %v", err)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
pkgDir := filepath.Join(out, "@goscript", "example.test", "protobufbinding")
|
|
58
|
+
if _, err := os.Stat(filepath.Join(pkgDir, "foo.pb.gs.ts")); !errors.Is(err, os.ErrNotExist) {
|
|
59
|
+
t.Fatalf("bound protobuf file should not emit foo.pb.gs.ts, stat err=%v", err)
|
|
60
|
+
}
|
|
61
|
+
binding := readTestFile(t, filepath.Join(pkgDir, "foo.pb.ts"))
|
|
62
|
+
if !strings.Contains(binding, `import * as __protobuf_ts`) || !strings.Contains(binding, `foo.pb.js`) ||
|
|
63
|
+
!strings.Contains(binding, `class Foo`) || !strings.Contains(binding, `__protobufTypeScriptMessage = __protobuf_ts.Foo`) {
|
|
64
|
+
t.Fatalf("binding file should adapt sibling foo.pb.js, got:\n%s", binding)
|
|
65
|
+
}
|
|
66
|
+
if !strings.Contains(binding, `class Object`) || !strings.Contains(binding, `__protobufTypeScriptMessage = __protobuf_ts.Object$`) {
|
|
67
|
+
t.Fatalf("binding file should use protobuf-es-lite safe identifier for Object, got:\n%s", binding)
|
|
68
|
+
}
|
|
69
|
+
if !strings.Contains(binding, `__protobufTypeScriptMessage = __protobuf_ts.Foo;`) ||
|
|
70
|
+
!strings.Contains(binding, `__protobufTypeScriptFields = {};`) {
|
|
71
|
+
t.Fatalf("binding metadata assignments should be semicolon-terminated to avoid ASI calls, got:\n%s", binding)
|
|
72
|
+
}
|
|
73
|
+
index := readTestFile(t, filepath.Join(pkgDir, "index.ts"))
|
|
74
|
+
if !strings.Contains(index, `export { Foo, Object } from "./foo.pb.ts"`) {
|
|
75
|
+
t.Fatalf("package index should re-export binding file, got:\n%s", index)
|
|
76
|
+
}
|
|
77
|
+
use := readTestFile(t, filepath.Join(pkgDir, "use.gs.ts"))
|
|
78
|
+
if !strings.Contains(use, `from "./foo.pb.ts"`) {
|
|
79
|
+
t.Fatalf("non-protobuf file should import bound protobuf declarations, got:\n%s", use)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
func TestProtobufTypeScriptBindingEmitsMetadataForPreservedOneofFiles(t *testing.T) {
|
|
84
|
+
dir := t.TempDir()
|
|
85
|
+
writeTestFile(t, dir, "go.mod", "module example.test/oneofpb\n\ngo 1.25\n")
|
|
86
|
+
writeTestFile(t, dir, "foo.pb.go", "package oneofpb\n\n"+
|
|
87
|
+
"type Inner struct {\n"+
|
|
88
|
+
"\tName string `protobuf:\"bytes,1,opt,name=name,proto3\" json:\"name,omitempty\"`\n"+
|
|
89
|
+
"}\n\n"+
|
|
90
|
+
"type Wrapper struct {\n"+
|
|
91
|
+
"\tInner *Inner `protobuf:\"bytes,1,opt,name=inner,proto3\" json:\"inner,omitempty\"`\n"+
|
|
92
|
+
"\tChoice isWrapper_Choice `protobuf_oneof:\"choice\"`\n"+
|
|
93
|
+
"}\n\n"+
|
|
94
|
+
"type isWrapper_Choice interface { isWrapper_Choice() }\n\n"+
|
|
95
|
+
"type Wrapper_StringValue struct {\n"+
|
|
96
|
+
"\tStringValue string `protobuf:\"bytes,2,opt,name=string_value,json=stringValue,proto3,oneof\"`\n"+
|
|
97
|
+
"}\n\n"+
|
|
98
|
+
"func (*Wrapper_StringValue) isWrapper_Choice() {}\n")
|
|
99
|
+
writeTestFile(t, dir, "foo.pb.ts", `export interface Inner {
|
|
100
|
+
name?: string
|
|
101
|
+
}
|
|
102
|
+
export const Inner = {} as any
|
|
103
|
+
export interface Wrapper {
|
|
104
|
+
inner?: Inner
|
|
105
|
+
}
|
|
106
|
+
export const Wrapper = {} as any
|
|
107
|
+
`)
|
|
108
|
+
|
|
109
|
+
out := filepath.Join(dir, "out")
|
|
110
|
+
comp, err := NewCompiler(&Config{
|
|
111
|
+
Dir: dir,
|
|
112
|
+
OutputPath: out,
|
|
113
|
+
ProtobufTypeScriptBinding: true,
|
|
114
|
+
}, nil, nil)
|
|
115
|
+
if err != nil {
|
|
116
|
+
t.Fatal(err)
|
|
117
|
+
}
|
|
118
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
119
|
+
t.Fatalf("compile with protobuf TypeScript binding: %v", err)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
binding := readTestFile(t, filepath.Join(out, "@goscript", "example.test", "oneofpb", "foo.pb.ts"))
|
|
123
|
+
if !strings.Contains(binding, `import * as __protobuf_ts`) ||
|
|
124
|
+
!strings.Contains(binding, `(Wrapper as any).__protobufTypeScriptMessage = __protobuf_ts.Wrapper;`) ||
|
|
125
|
+
!strings.Contains(binding, `(Wrapper as any).__protobufTypeScriptFields = {"inner": Inner};`) {
|
|
126
|
+
t.Fatalf("oneof-preserved protobuf file should still expose TypeScript metadata, got:\n%s", binding)
|
|
127
|
+
}
|
|
128
|
+
if strings.Contains(binding, `__protobuf_ts.Wrapper_StringValue`) {
|
|
129
|
+
t.Fatalf("oneof wrapper structs should not reference missing TypeScript exports, got:\n%s", binding)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
func TestProtobufTypeScriptBindingPreservesCustomJSONMethods(t *testing.T) {
|
|
134
|
+
dir := t.TempDir()
|
|
135
|
+
writeTestFile(t, dir, "go.mod", "module example.test/custompbjson\n\ngo 1.25\n")
|
|
136
|
+
writeTestFile(t, dir, "foo.pb.go", `package custompbjson
|
|
137
|
+
|
|
138
|
+
type Foo struct {
|
|
139
|
+
Config []byte
|
|
140
|
+
}
|
|
141
|
+
`)
|
|
142
|
+
writeTestFile(t, dir, "foo.pb.ts", `export interface Foo {
|
|
143
|
+
config?: Uint8Array
|
|
144
|
+
}
|
|
145
|
+
export const Foo = {} as any
|
|
146
|
+
`)
|
|
147
|
+
writeTestFile(t, dir, "foo-json.go", `package custompbjson
|
|
148
|
+
|
|
149
|
+
func (x *Foo) UnmarshalJSON(b []byte) error {
|
|
150
|
+
x.Config = b
|
|
151
|
+
return nil
|
|
152
|
+
}
|
|
153
|
+
`)
|
|
154
|
+
|
|
155
|
+
out := filepath.Join(dir, "out")
|
|
156
|
+
comp, err := NewCompiler(&Config{
|
|
157
|
+
Dir: dir,
|
|
158
|
+
OutputPath: out,
|
|
159
|
+
ProtobufTypeScriptBinding: true,
|
|
160
|
+
}, nil, nil)
|
|
161
|
+
if err != nil {
|
|
162
|
+
t.Fatal(err)
|
|
163
|
+
}
|
|
164
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
165
|
+
t.Fatalf("compile with protobuf TypeScript binding: %v", err)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
binding := readTestFile(t, filepath.Join(out, "@goscript", "example.test", "custompbjson", "foo.pb.ts"))
|
|
169
|
+
if strings.Contains(binding, `UnmarshalBoundMessageJSON(Foo`) {
|
|
170
|
+
t.Fatalf("custom JSON method should not be replaced by generic protobuf helper, got:\n%s", binding)
|
|
171
|
+
}
|
|
172
|
+
if !strings.Contains(binding, `.Config = b`) {
|
|
173
|
+
t.Fatalf("custom JSON method body should be preserved, got:\n%s", binding)
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
func TestProtobufTypeScriptBindingPreservesJSONGraphWithCustomNestedMessage(t *testing.T) {
|
|
178
|
+
dir := t.TempDir()
|
|
179
|
+
writeTestFile(t, dir, "go.mod", "module example.test/nestedcustompbjson\n\ngo 1.25\n")
|
|
180
|
+
writeTestFile(t, dir, "foo.pb.go", `package nestedcustompbjson
|
|
181
|
+
|
|
182
|
+
type Foo struct {
|
|
183
|
+
Items []*Item
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
type Item struct {
|
|
187
|
+
Config []byte
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
func generatedFooJSONMarker(x *Foo) error {
|
|
191
|
+
return nil
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
func (x *Foo) UnmarshalJSON(b []byte) error {
|
|
195
|
+
return generatedFooJSONMarker(x)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
func (x *Foo) UnmarshalProtoJSON(s any) {
|
|
199
|
+
}
|
|
200
|
+
`)
|
|
201
|
+
writeTestFile(t, dir, "foo.pb.ts", `export interface Foo {
|
|
202
|
+
items?: Item[]
|
|
203
|
+
}
|
|
204
|
+
export const Foo = {} as any
|
|
205
|
+
export interface Item {
|
|
206
|
+
config?: Uint8Array
|
|
207
|
+
}
|
|
208
|
+
export const Item = {} as any
|
|
209
|
+
`)
|
|
210
|
+
writeTestFile(t, dir, "item-json.go", `package nestedcustompbjson
|
|
211
|
+
|
|
212
|
+
func (x *Item) UnmarshalJSON(b []byte) error {
|
|
213
|
+
x.Config = b
|
|
214
|
+
return nil
|
|
215
|
+
}
|
|
216
|
+
`)
|
|
217
|
+
|
|
218
|
+
out := filepath.Join(dir, "out")
|
|
219
|
+
comp, err := NewCompiler(&Config{
|
|
220
|
+
Dir: dir,
|
|
221
|
+
OutputPath: out,
|
|
222
|
+
ProtobufTypeScriptBinding: true,
|
|
223
|
+
}, nil, nil)
|
|
224
|
+
if err != nil {
|
|
225
|
+
t.Fatal(err)
|
|
226
|
+
}
|
|
227
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
228
|
+
t.Fatalf("compile with protobuf TypeScript binding: %v", err)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
binding := readTestFile(t, filepath.Join(out, "@goscript", "example.test", "nestedcustompbjson", "foo.pb.ts"))
|
|
232
|
+
if strings.Contains(binding, `UnmarshalBoundMessageJSON(Foo`) {
|
|
233
|
+
t.Fatalf("outer message with nested custom JSON should keep generated JSON body, got:\n%s", binding)
|
|
234
|
+
}
|
|
235
|
+
if !strings.Contains(binding, `generatedFooJSONMarker`) {
|
|
236
|
+
t.Fatalf("outer generated JSON body should be preserved, got:\n%s", binding)
|
|
237
|
+
}
|
|
238
|
+
if strings.Contains(binding, `UnmarshalBoundMessageJSON(Item`) {
|
|
239
|
+
t.Fatalf("nested custom JSON method should not be replaced, got:\n%s", binding)
|
|
240
|
+
}
|
|
241
|
+
if !strings.Contains(binding, `.Config = b`) {
|
|
242
|
+
t.Fatalf("nested custom JSON method body should be preserved, got:\n%s", binding)
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
func TestProtobufTypeScriptBindingPreservesJSONGraphWithImportedCustomNestedMessage(t *testing.T) {
|
|
247
|
+
dir := t.TempDir()
|
|
248
|
+
writeTestFile(t, dir, "go.mod", "module example.test/importedcustompbjson\n\ngo 1.25\n")
|
|
249
|
+
writeTestFile(t, dir, "inner/inner.pb.go", `package inner
|
|
250
|
+
|
|
251
|
+
type Inner struct {
|
|
252
|
+
Config []byte
|
|
253
|
+
}
|
|
254
|
+
`)
|
|
255
|
+
writeTestFile(t, dir, "inner/inner.pb.ts", `export interface Inner {
|
|
256
|
+
config?: Uint8Array
|
|
257
|
+
}
|
|
258
|
+
export const Inner = {} as any
|
|
259
|
+
`)
|
|
260
|
+
writeTestFile(t, dir, "inner/inner-json.go", `package inner
|
|
261
|
+
|
|
262
|
+
func (x *Inner) UnmarshalJSON(b []byte) error {
|
|
263
|
+
x.Config = b
|
|
264
|
+
return nil
|
|
265
|
+
}
|
|
266
|
+
`)
|
|
267
|
+
writeTestFile(t, dir, "outer.pb.go", `package importedcustompbjson
|
|
268
|
+
|
|
269
|
+
import "example.test/importedcustompbjson/inner"
|
|
270
|
+
|
|
271
|
+
type Outer struct {
|
|
272
|
+
Inner *inner.Inner
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
func generatedOuterJSONMarker(x *Outer) error {
|
|
276
|
+
return nil
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
func (x *Outer) UnmarshalJSON(b []byte) error {
|
|
280
|
+
return generatedOuterJSONMarker(x)
|
|
281
|
+
}
|
|
282
|
+
`)
|
|
283
|
+
writeTestFile(t, dir, "outer.pb.ts", `import type { Inner } from './inner/inner.pb.js'
|
|
284
|
+
|
|
285
|
+
export interface Outer {
|
|
286
|
+
inner?: Inner
|
|
287
|
+
}
|
|
288
|
+
export const Outer = {} as any
|
|
289
|
+
`)
|
|
290
|
+
|
|
291
|
+
out := filepath.Join(dir, "out")
|
|
292
|
+
comp, err := NewCompiler(&Config{
|
|
293
|
+
Dir: dir,
|
|
294
|
+
OutputPath: out,
|
|
295
|
+
ProtobufTypeScriptBinding: true,
|
|
296
|
+
}, nil, nil)
|
|
297
|
+
if err != nil {
|
|
298
|
+
t.Fatal(err)
|
|
299
|
+
}
|
|
300
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
301
|
+
t.Fatalf("compile with protobuf TypeScript binding: %v", err)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
binding := readTestFile(t, filepath.Join(out, "@goscript", "example.test", "importedcustompbjson", "outer.pb.ts"))
|
|
305
|
+
if strings.Contains(binding, `UnmarshalBoundMessageJSON(Outer`) {
|
|
306
|
+
t.Fatalf("outer message with imported nested custom JSON should keep generated JSON body, got:\n%s", binding)
|
|
307
|
+
}
|
|
308
|
+
if !strings.Contains(binding, `generatedOuterJSONMarker`) {
|
|
309
|
+
t.Fatalf("outer generated JSON body should be preserved, got:\n%s", binding)
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
func TestProtobufTypeScriptBindingReportsMissingSibling(t *testing.T) {
|
|
314
|
+
dir := t.TempDir()
|
|
315
|
+
writeTestFile(t, dir, "go.mod", "module example.test/missingpbts\n\ngo 1.25\n")
|
|
316
|
+
writeTestFile(t, dir, "foo.pb.go", `package missingpbts
|
|
317
|
+
|
|
318
|
+
type Foo struct{}
|
|
319
|
+
`)
|
|
320
|
+
|
|
321
|
+
comp, err := NewCompiler(&Config{
|
|
322
|
+
Dir: dir,
|
|
323
|
+
OutputPath: filepath.Join(dir, "out"),
|
|
324
|
+
ProtobufTypeScriptBinding: true,
|
|
325
|
+
}, nil, nil)
|
|
326
|
+
if err != nil {
|
|
327
|
+
t.Fatal(err)
|
|
328
|
+
}
|
|
329
|
+
result, err := comp.CompilePackages(context.Background(), ".")
|
|
330
|
+
if err == nil {
|
|
331
|
+
t.Fatal("expected missing sibling .pb.ts to fail")
|
|
332
|
+
}
|
|
333
|
+
if result == nil {
|
|
334
|
+
t.Fatal("expected diagnostics result")
|
|
335
|
+
}
|
|
336
|
+
for _, diag := range result.Diagnostics {
|
|
337
|
+
if diag.Code == "goscript/protobuf-ts-binding:missing" {
|
|
338
|
+
return
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
t.Fatalf("missing protobuf binding diagnostic not found: %#v", result.Diagnostics)
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
func TestProtobufTypeScriptBindingSkipsFilesOutsideSourceRoot(t *testing.T) {
|
|
345
|
+
dir := t.TempDir()
|
|
346
|
+
outside := filepath.Join(t.TempDir(), "outside.pb.go")
|
|
347
|
+
writeTestFile(t, dir, "go.mod", "module example.test/outsidepb\n\ngo 1.25\n")
|
|
348
|
+
writeTestFile(t, dir, "use.go", `package outsidepb
|
|
349
|
+
`)
|
|
350
|
+
|
|
351
|
+
semPkg := &semanticPackage{
|
|
352
|
+
pkgPath: "example.test/outsidepb",
|
|
353
|
+
source: &packages.Package{
|
|
354
|
+
CompiledGoFiles: []string{outside},
|
|
355
|
+
GoFiles: []string{outside},
|
|
356
|
+
Syntax: make([]*ast.File, 1),
|
|
357
|
+
},
|
|
358
|
+
}
|
|
359
|
+
bindings, diagnostics := protobufTypeScriptBindings(semPkg, LoweringOptions{
|
|
360
|
+
SourceRoot: dir,
|
|
361
|
+
OutputPath: filepath.Join(dir, "out"),
|
|
362
|
+
ProtobufTypeScriptBinding: true,
|
|
363
|
+
})
|
|
364
|
+
if len(diagnostics) != 0 {
|
|
365
|
+
t.Fatalf("outside source root diagnostics = %#v", diagnostics)
|
|
366
|
+
}
|
|
367
|
+
if len(bindings) != 0 {
|
|
368
|
+
t.Fatalf("outside source root bindings = %#v", bindings)
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
func TestProtobufTypeScriptBindingRootFindsParentModule(t *testing.T) {
|
|
373
|
+
dir := t.TempDir()
|
|
374
|
+
writeTestFile(t, dir, "go.mod", "module example.test/root\n\ngo 1.25\n")
|
|
375
|
+
nested := filepath.Join(dir, ".bldr", "build", "plugin")
|
|
376
|
+
if err := os.MkdirAll(nested, 0o755); err != nil {
|
|
377
|
+
t.Fatal(err)
|
|
378
|
+
}
|
|
379
|
+
if got := protobufTypeScriptBindingRoot(nested); got != dir {
|
|
380
|
+
t.Fatalf("binding root = %q, want %q", got, dir)
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
func writeTestFile(t *testing.T, root, rel, data string) {
|
|
385
|
+
t.Helper()
|
|
386
|
+
path := filepath.Join(root, rel)
|
|
387
|
+
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
388
|
+
t.Fatal(err)
|
|
389
|
+
}
|
|
390
|
+
if err := os.WriteFile(path, []byte(data), 0o644); err != nil {
|
|
391
|
+
t.Fatal(err)
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
func readTestFile(t *testing.T, path string) string {
|
|
396
|
+
t.Helper()
|
|
397
|
+
data, err := os.ReadFile(path)
|
|
398
|
+
if err != nil {
|
|
399
|
+
t.Fatal(err)
|
|
400
|
+
}
|
|
401
|
+
return string(data)
|
|
402
|
+
}
|
|
@@ -105,6 +105,8 @@ const (
|
|
|
105
105
|
RuntimeHelperSliceStringOrBytes RuntimeHelper = "slice.sliceStringOrBytes"
|
|
106
106
|
RuntimeHelperIndexRef RuntimeHelper = "slice.indexRef"
|
|
107
107
|
RuntimeHelperIndexAddress RuntimeHelper = "slice.indexAddress"
|
|
108
|
+
RuntimeHelperIndexByteAddress RuntimeHelper = "slice.indexByteAddress"
|
|
109
|
+
RuntimeHelperUnsafePointerRef RuntimeHelper = "slice.unsafePointerRef"
|
|
108
110
|
|
|
109
111
|
RuntimeHelperMakeMap RuntimeHelper = "map.makeMap"
|
|
110
112
|
RuntimeHelperMapGet RuntimeHelper = "map.mapGet"
|
|
@@ -333,6 +335,8 @@ func runtimeHelperContracts() []RuntimeHelperContract {
|
|
|
333
335
|
runtimeHelper(RuntimeHelperSliceStringOrBytes, "sliceStringOrBytes", RuntimeHelperCategorySlice),
|
|
334
336
|
runtimeHelper(RuntimeHelperIndexRef, "indexRef", RuntimeHelperCategorySlice),
|
|
335
337
|
runtimeHelper(RuntimeHelperIndexAddress, "indexAddress", RuntimeHelperCategorySlice),
|
|
338
|
+
runtimeHelper(RuntimeHelperIndexByteAddress, "indexByteAddress", RuntimeHelperCategorySlice),
|
|
339
|
+
runtimeHelper(RuntimeHelperUnsafePointerRef, "unsafePointerRef", RuntimeHelperCategorySlice),
|
|
336
340
|
runtimeHelper(RuntimeHelperMakeMap, "makeMap", RuntimeHelperCategoryMap),
|
|
337
341
|
runtimeHelper(RuntimeHelperMapGet, "mapGet", RuntimeHelperCategoryMap),
|
|
338
342
|
runtimeHelper(RuntimeHelperMapSet, "mapSet", RuntimeHelperCategoryMap),
|
|
@@ -25,6 +25,8 @@ func TestRuntimeContractOwnsBuiltinImportAndHelpers(t *testing.T) {
|
|
|
25
25
|
RuntimeHelperMakeSlice: RuntimeHelperCategorySlice,
|
|
26
26
|
RuntimeHelperAppend: RuntimeHelperCategorySlice,
|
|
27
27
|
RuntimeHelperIndexAddress: RuntimeHelperCategorySlice,
|
|
28
|
+
RuntimeHelperIndexByteAddress: RuntimeHelperCategorySlice,
|
|
29
|
+
RuntimeHelperUnsafePointerRef: RuntimeHelperCategorySlice,
|
|
28
30
|
RuntimeHelperMakeMap: RuntimeHelperCategoryMap,
|
|
29
31
|
RuntimeHelperMapGet: RuntimeHelperCategoryMap,
|
|
30
32
|
RuntimeHelperNewError: RuntimeHelperCategoryError,
|
|
@@ -12,12 +12,14 @@ type SemanticModel struct {
|
|
|
12
12
|
addressTaken map[types.Object]bool
|
|
13
13
|
needsVarRef map[types.Object]bool
|
|
14
14
|
functions map[*types.Func]*semanticFunction
|
|
15
|
+
functionCallers map[*types.Func][]*semanticFunction
|
|
15
16
|
functionsByFullName map[string]*semanticFunction
|
|
16
17
|
functionLookupMisses map[*types.Func]bool
|
|
17
18
|
functionFullNames map[*types.Func]string
|
|
18
19
|
types map[*types.Named]*semanticType
|
|
19
20
|
values map[types.Object]*semanticValue
|
|
20
21
|
generatedImports map[string]map[string]bool
|
|
22
|
+
generatedImportTypes map[string]map[types.Type]bool
|
|
21
23
|
interfaceImplementations []semanticInterfaceImplementation
|
|
22
24
|
asyncInterfaceMethods map[string]bool
|
|
23
25
|
asyncInterfaceMethodObjs map[*types.Func]bool
|
|
@@ -66,6 +68,10 @@ type semanticField struct {
|
|
|
66
68
|
doc string
|
|
67
69
|
tag string
|
|
68
70
|
embedded bool
|
|
71
|
+
pkgPath string
|
|
72
|
+
index []int
|
|
73
|
+
offset int64
|
|
74
|
+
exported bool
|
|
69
75
|
}
|
|
70
76
|
|
|
71
77
|
type semanticValue struct {
|
|
@@ -92,10 +98,9 @@ type semanticFunction struct {
|
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
type semanticInterfaceImplementation struct {
|
|
95
|
-
typ
|
|
96
|
-
iface
|
|
97
|
-
pointer
|
|
98
|
-
asyncMethods map[string]bool
|
|
101
|
+
typ *types.Named
|
|
102
|
+
iface *types.Named
|
|
103
|
+
pointer bool
|
|
99
104
|
}
|
|
100
105
|
|
|
101
106
|
type semanticInterfaceImplementationGraphEntry struct {
|