goscript 0.2.2 → 0.2.3
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/compiler/gotest/testdata/browserapi/browserapi_test.go +36 -0
- package/compiler/lowering.go +223 -9
- package/compiler/override-registry_test.go +50 -0
- package/compiler/protobuf-ts-binding.go +154 -6
- package/compiler/protobuf-ts-binding_test.go +7 -2
- package/compiler/runtime-contract.go +2 -0
- package/compiler/runtime-contract_test.go +1 -0
- package/compiler/semantic-model.go +16 -0
- package/compiler/semantic-model_test.go +38 -0
- package/compiler/skeleton_test.go +473 -15
- package/compiler/typescript-emitter.go +4 -0
- package/dist/gs/builtin/builtin.js +7 -9
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/defer.js +2 -2
- package/dist/gs/builtin/hostio.js +5 -5
- package/dist/gs/builtin/hostio.js.map +1 -1
- package/dist/gs/builtin/map.js +2 -1
- package/dist/gs/builtin/map.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +3 -0
- package/dist/gs/builtin/slice.js +39 -0
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.js +49 -0
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/compress/zlib/index.js +5 -2
- package/dist/gs/compress/zlib/index.js.map +1 -1
- package/dist/gs/crypto/ecdh/index.js +27 -8
- package/dist/gs/crypto/ecdh/index.js.map +1 -1
- package/dist/gs/crypto/ed25519/index.js +3 -3
- package/dist/gs/crypto/ed25519/index.js.map +1 -1
- package/dist/gs/crypto/rand/index.js +6 -3
- package/dist/gs/crypto/rand/index.js.map +1 -1
- package/dist/gs/embed/index.js +9 -3
- package/dist/gs/embed/index.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +1 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +33 -0
- package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
- package/dist/gs/github.com/mr-tron/base58/base58/index.js +4 -1
- package/dist/gs/github.com/mr-tron/base58/base58/index.js.map +1 -1
- package/dist/gs/golang.org/x/crypto/scrypt/index.d.ts +2 -0
- package/dist/gs/golang.org/x/crypto/scrypt/index.js +39 -0
- package/dist/gs/golang.org/x/crypto/scrypt/index.js.map +1 -0
- package/dist/gs/hash/fnv/index.js +13 -5
- package/dist/gs/hash/fnv/index.js.map +1 -1
- package/dist/gs/io/fs/glob.d.ts +3 -3
- package/dist/gs/io/fs/glob.js +8 -8
- package/dist/gs/io/fs/glob.js.map +1 -1
- package/dist/gs/io/fs/readdir.d.ts +2 -2
- package/dist/gs/io/fs/readdir.js +13 -74
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/fs/sub.js +4 -4
- package/dist/gs/io/fs/sub.js.map +1 -1
- package/dist/gs/io/fs/walk.js +1 -1
- package/dist/gs/io/fs/walk.js.map +1 -1
- package/dist/gs/maps/iter.js.map +1 -1
- package/dist/gs/maps/maps.js.map +1 -1
- package/dist/gs/mime/index.js +5 -2
- package/dist/gs/mime/index.js.map +1 -1
- package/dist/gs/net/http/httptest/index.js +6 -3
- package/dist/gs/net/http/httptest/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +16 -4
- package/dist/gs/net/http/index.js +236 -40
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/net/http/pprof/index.js.map +1 -1
- package/dist/gs/reflect/iter.js +1 -1
- package/dist/gs/reflect/iter.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +2 -0
- package/dist/gs/reflect/type.js +53 -21
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/runtime/pprof/index.js.map +1 -1
- package/dist/gs/runtime/runtime.js +2 -2
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/runtime/trace/index.js.map +1 -1
- package/dist/gs/slices/slices.d.ts +1 -1
- package/dist/gs/slices/slices.js +37 -4
- package/dist/gs/slices/slices.js.map +1 -1
- package/gs/builtin/builtin.ts +11 -14
- package/gs/builtin/defer.ts +2 -2
- package/gs/builtin/hostio.ts +5 -5
- package/gs/builtin/map.ts +4 -1
- package/gs/builtin/slice.test.ts +14 -0
- package/gs/builtin/slice.ts +64 -0
- package/gs/builtin/type.ts +72 -0
- package/gs/bytes/bytes.test.ts +14 -13
- package/gs/compress/zlib/index.test.ts +19 -5
- package/gs/compress/zlib/index.ts +16 -7
- package/gs/context/context.test.ts +3 -1
- package/gs/crypto/ecdh/index.test.ts +6 -2
- package/gs/crypto/ecdh/index.ts +49 -12
- package/gs/crypto/ed25519/index.ts +20 -7
- package/gs/crypto/rand/index.ts +6 -3
- package/gs/embed/index.test.ts +3 -3
- package/gs/embed/index.ts +9 -3
- package/gs/fmt/fmt.test.ts +29 -4
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +126 -0
- package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +46 -0
- package/gs/github.com/mr-tron/base58/base58/index.ts +9 -3
- package/gs/github.com/zeebo/blake3/internal/consts/index.test.ts +2 -8
- package/gs/golang.org/x/crypto/scrypt/index.test.ts +81 -0
- package/gs/golang.org/x/crypto/scrypt/index.ts +54 -0
- package/gs/golang.org/x/crypto/scrypt/meta.json +5 -0
- package/gs/hash/fnv/index.test.ts +1 -8
- package/gs/hash/fnv/index.ts +27 -10
- package/gs/io/fs/glob.ts +13 -10
- package/gs/io/fs/meta.json +2 -0
- package/gs/io/fs/readdir.test.ts +63 -2
- package/gs/io/fs/readdir.ts +33 -30
- package/gs/io/fs/sub.ts +4 -4
- package/gs/io/fs/walk.ts +1 -1
- package/gs/maps/iter.ts +9 -9
- package/gs/maps/maps.ts +4 -4
- package/gs/math/bits/index.test.ts +10 -1
- package/gs/mime/index.test.ts +33 -15
- package/gs/mime/index.ts +9 -2
- package/gs/net/http/httptest/index.test.ts +17 -3
- package/gs/net/http/httptest/index.ts +8 -3
- package/gs/net/http/index.test.ts +645 -123
- package/gs/net/http/index.ts +548 -113
- package/gs/net/http/pprof/index.ts +24 -6
- package/gs/os/file_unix_js.test.ts +22 -0
- package/gs/reflect/iter.ts +4 -2
- package/gs/reflect/map.test.ts +56 -1
- package/gs/reflect/type.ts +76 -37
- package/gs/runtime/pprof/index.test.ts +7 -1
- package/gs/runtime/pprof/index.ts +5 -1
- package/gs/runtime/runtime.test.ts +7 -0
- package/gs/runtime/runtime.ts +2 -4
- package/gs/runtime/trace/index.test.ts +9 -1
- package/gs/runtime/trace/index.ts +5 -1
- package/gs/slices/meta.json +3 -0
- package/gs/slices/slices.test.ts +59 -21
- package/gs/slices/slices.ts +61 -20
- package/gs/strconv/complex.test.ts +17 -3
- package/gs/sync/atomic/doc_64.test.ts +2 -9
- package/gs/sync/sync.test.ts +18 -8
- package/gs/syscall/js/index.test.ts +9 -4
- package/package.json +5 -4
|
@@ -2491,7 +2491,7 @@ func TestCompilePackagesAssertsInterfaceMethodReceivers(t *testing.T) {
|
|
|
2491
2491
|
text := string(content)
|
|
2492
2492
|
for _, want := range []string{
|
|
2493
2493
|
"export type FileInfo = {",
|
|
2494
|
-
"$.println($.pointerValue<Exclude<FileInfo, null>>(info).Name())",
|
|
2494
|
+
"$.println(await $.pointerValue<Exclude<FileInfo, null>>(info).Name())",
|
|
2495
2495
|
} {
|
|
2496
2496
|
if !strings.Contains(text, want) {
|
|
2497
2497
|
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
@@ -2593,7 +2593,7 @@ func TestCompilePackagesBoxesTypedNilInterfaceValues(t *testing.T) {
|
|
|
2593
2593
|
text := string(content)
|
|
2594
2594
|
for _, want := range []string{
|
|
2595
2595
|
"return $.interfaceValue<Animal | null>(FindDog(), \"*main.Dog\")",
|
|
2596
|
-
"$.println($.pointerValue<Exclude<Animal, null>>(animal).Name())",
|
|
2596
|
+
"$.println(await $.pointerValue<Exclude<Animal, null>>(animal).Name())",
|
|
2597
2597
|
"let a: Animal | null = $.interfaceValue<Animal | null>(dog, \"*main.Dog\")",
|
|
2598
2598
|
} {
|
|
2599
2599
|
if !strings.Contains(text, want) {
|
|
@@ -2700,16 +2700,16 @@ func TestCompilePackagesEmitsGenericMethodsAliasesAndDictionaries(t *testing.T)
|
|
|
2700
2700
|
"public Get(): any",
|
|
2701
2701
|
"export function NewBox(__typeArgs: $.GenericTypeArgs | undefined, value: any): Box",
|
|
2702
2702
|
"export function ZeroValue(__typeArgs: $.GenericTypeArgs | undefined): any",
|
|
2703
|
-
"export function CallString(__typeArgs: $.GenericTypeArgs | undefined, v: any): string",
|
|
2703
|
+
"export async function CallString(__typeArgs: $.GenericTypeArgs | undefined, v: any): globalThis.Promise<string>",
|
|
2704
2704
|
"export function Sum<T>(__typeArgs: $.GenericTypeArgs | undefined, vals: $.Slice<T>): any",
|
|
2705
2705
|
"export function Copy<T>(__typeArgs: $.GenericTypeArgs | undefined, vals: $.Slice<T>): $.Slice<T>",
|
|
2706
|
-
"return $.
|
|
2706
|
+
"return $.appendSlice($.arrayToSlice<T>([]), vals)",
|
|
2707
2707
|
"let seen: Set = $.makeMap<number, {}>()",
|
|
2708
2708
|
"$.mapSet(seen, 1, {})",
|
|
2709
2709
|
"$.genericZero(__typeArgs, \"T\", null)",
|
|
2710
|
-
"$.callGenericMethod(__typeArgs, \"T\", \"String\", v)",
|
|
2710
|
+
"await $.callGenericMethod(__typeArgs, \"T\", \"String\", v)",
|
|
2711
2711
|
"ZeroValue({T: { type: { kind: $.TypeKind.Basic, name: \"int\", typeName: \"main.MyInt\" }, zero: () => 0, methods: {String: (receiver: any, ...args: any[]) => (MyInt_String as any)(($.isVarRef(receiver) ? receiver.value : receiver), ...args)}, methodSignatures: [{ name: \"String\", args: [], returns: [{ name: \"_r0\", type: { kind: $.TypeKind.Basic, name: \"string\" } }] }] }})",
|
|
2712
|
-
"CallString({T: { type: { kind: $.TypeKind.Basic, name: \"int\", typeName: \"main.MyInt\" }, zero: () => 0, methods: {String: (receiver: any, ...args: any[]) => (MyInt_String as any)(($.isVarRef(receiver) ? receiver.value : receiver), ...args)}, methodSignatures: [{ name: \"String\", args: [], returns: [{ name: \"_r0\", type: { kind: $.TypeKind.Basic, name: \"string\" } }] }] }}, zero)",
|
|
2712
|
+
"await CallString({T: { type: { kind: $.TypeKind.Basic, name: \"int\", typeName: \"main.MyInt\" }, zero: () => 0, methods: {String: (receiver: any, ...args: any[]) => (MyInt_String as any)(($.isVarRef(receiver) ? receiver.value : receiver), ...args)}, methodSignatures: [{ name: \"String\", args: [], returns: [{ name: \"_r0\", type: { kind: $.TypeKind.Basic, name: \"string\" } }] }] }}, zero)",
|
|
2713
2713
|
"Sum({T: { type: { kind: $.TypeKind.Basic, name: \"int\", typeName: \"main.MyInt\" }, zero: () => 0, methods: {String: (receiver: any, ...args: any[]) => (MyInt_String as any)(($.isVarRef(receiver) ? receiver.value : receiver), ...args)}, methodSignatures: [{ name: \"String\", args: [], returns: [{ name: \"_r0\", type: { kind: $.TypeKind.Basic, name: \"string\" } }] }] }}, null)",
|
|
2714
2714
|
} {
|
|
2715
2715
|
if !strings.Contains(text, want) {
|
|
@@ -2740,11 +2740,17 @@ func TestCompilePackagesInfersGenericTypeArgsFromNamedArgument(t *testing.T) {
|
|
|
2740
2740
|
" f := entries[key.name].factory",
|
|
2741
2741
|
" return f.(func() T)()",
|
|
2742
2742
|
"}",
|
|
2743
|
+
"type typedLoader[T any] struct { value T }",
|
|
2744
|
+
"func (t *typedLoader[T]) Load() T { return t.value }",
|
|
2745
|
+
"func GetTyped[T any](v any) T {",
|
|
2746
|
+
" src := v.(interface { Load() T })",
|
|
2747
|
+
" return src.Load()",
|
|
2748
|
+
"}",
|
|
2743
2749
|
"var loader = NewKey[Source](\"source\")",
|
|
2744
2750
|
"func Use() int {",
|
|
2745
2751
|
" Register(loader, func() Source { return &auto{} })",
|
|
2746
2752
|
" src := Get(loader)",
|
|
2747
|
-
" return src.Load()",
|
|
2753
|
+
" return src.Load() + GetTyped[int](&typedLoader[int]{value: 5})",
|
|
2748
2754
|
"}",
|
|
2749
2755
|
"",
|
|
2750
2756
|
}, "\n"),
|
|
@@ -2766,8 +2772,9 @@ func TestCompilePackagesInfersGenericTypeArgsFromNamedArgument(t *testing.T) {
|
|
|
2766
2772
|
text := string(content)
|
|
2767
2773
|
for _, want := range []string{
|
|
2768
2774
|
"await Get({T: { type: \"genericnamedarg.Source\", zero: () => null, methods: {Load: (receiver: any, ...args: any[]) => receiver.Load(...args)} }}, $.markAsStructValue($.cloneStructValue(loader)))",
|
|
2769
|
-
"return await $.mustTypeAssert<(() => any | globalThis.Promise<any>) | null>(f, ({ kind: $.TypeKind.Function, params: [], results: [{ kind: $.TypeKind.Interface, methods: [] }] } as $.FunctionTypeInfo))!()",
|
|
2770
|
-
"
|
|
2775
|
+
"return await $.mustTypeAssert<(() => any | globalThis.Promise<any>) | null>(f, ({ kind: $.TypeKind.Function, params: [], results: [__typeArgs?.[\"T\"]?.type ?? { kind: $.TypeKind.Interface, methods: [] }] } as $.FunctionTypeInfo))!()",
|
|
2776
|
+
"$.mustTypeAssert<any>(v, { kind: $.TypeKind.Interface, methods: [{ name: \"Load\", args: [], returns: [{ name: \"_r0\", type: __typeArgs?.[\"T\"]?.type ?? { kind: $.TypeKind.Interface, methods: [] } }] }] })",
|
|
2777
|
+
"return await $.pointerValue<Exclude<Source, null>>(src).Load()",
|
|
2771
2778
|
} {
|
|
2772
2779
|
if !strings.Contains(text, want) {
|
|
2773
2780
|
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
@@ -3054,12 +3061,16 @@ func TestCompilePackagesAwaitsFmtWriterOverrides(t *testing.T) {
|
|
|
3054
3061
|
for _, want := range []string{
|
|
3055
3062
|
"export async function Use",
|
|
3056
3063
|
"await fmt.Fprintf(",
|
|
3064
|
+
"$.pointerValue<writer>(w).buf = $.appendSlice($.pointerValue<writer>(w).buf, p)",
|
|
3057
3065
|
"return err",
|
|
3058
3066
|
} {
|
|
3059
3067
|
if !strings.Contains(text, want) {
|
|
3060
3068
|
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
3061
3069
|
}
|
|
3062
3070
|
}
|
|
3071
|
+
if strings.Contains(text, "...(p ?? [])") {
|
|
3072
|
+
t.Fatalf("append with slice expansion used JavaScript argument spreading:\n%s", text)
|
|
3073
|
+
}
|
|
3063
3074
|
}
|
|
3064
3075
|
|
|
3065
3076
|
func TestCompilePackagesImportsSelectedExternalFieldTypes(t *testing.T) {
|
|
@@ -3613,7 +3624,7 @@ func TestCompilePackagesPropagatesAsyncThroughInstantiatedNamedInterface(t *test
|
|
|
3613
3624
|
}
|
|
3614
3625
|
}
|
|
3615
3626
|
|
|
3616
|
-
func
|
|
3627
|
+
func TestCompilePackagesAwaitsUnmarkedAnonymousInterfaceMethodInsideAsyncCaller(t *testing.T) {
|
|
3617
3628
|
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
3618
3629
|
"go.mod": "module example.test/anonymousifaceawait\n\ngo 1.25.3\n",
|
|
3619
3630
|
"main.go": strings.Join([]string{
|
|
@@ -3647,8 +3658,8 @@ func TestCompilePackagesDoesNotAwaitUnmarkedAnonymousInterfaceMethod(t *testing.
|
|
|
3647
3658
|
t.Fatal(err.Error())
|
|
3648
3659
|
}
|
|
3649
3660
|
text := string(content)
|
|
3650
|
-
if strings.Contains(text, "return await $.pointerValue<any>(w).WaitValueChange(ctx, old, null)") {
|
|
3651
|
-
t.Fatalf("anonymous interface method call
|
|
3661
|
+
if !strings.Contains(text, "return await $.pointerValue<any>(w).WaitValueChange(ctx, old, null)") {
|
|
3662
|
+
t.Fatalf("anonymous interface method call inside async caller was not awaited:\n%s", text)
|
|
3652
3663
|
}
|
|
3653
3664
|
}
|
|
3654
3665
|
|
|
@@ -3657,7 +3668,8 @@ func TestCompilePackagesDoesNotInheritAsyncIntoSyncFunctionLiteral(t *testing.T)
|
|
|
3657
3668
|
"go.mod": "module example.test/syncfunclit\n\ngo 1.25.3\n",
|
|
3658
3669
|
"main.go": strings.Join([]string{
|
|
3659
3670
|
"package syncfunclit",
|
|
3660
|
-
"type Directive
|
|
3671
|
+
"type Directive struct{}",
|
|
3672
|
+
"func (Directive) GetDirective() any { return nil }",
|
|
3661
3673
|
"type Bridge struct{ keep func(Directive) (bool, error) }",
|
|
3662
3674
|
"func NewBridge(keep func(Directive) (bool, error)) *Bridge { return &Bridge{keep: keep} }",
|
|
3663
3675
|
"func Execute(ch <-chan struct{}) error {",
|
|
@@ -3691,11 +3703,103 @@ func TestCompilePackagesDoesNotInheritAsyncIntoSyncFunctionLiteral(t *testing.T)
|
|
|
3691
3703
|
t.Fatal(err.Error())
|
|
3692
3704
|
}
|
|
3693
3705
|
text := string(content)
|
|
3694
|
-
if strings.Contains(text, "await
|
|
3706
|
+
if strings.Contains(text, "await Directive.prototype.GetDirective.call(di)") {
|
|
3695
3707
|
t.Fatalf("sync function literal inherited async await:\n%s", text)
|
|
3696
3708
|
}
|
|
3697
3709
|
}
|
|
3698
3710
|
|
|
3711
|
+
func TestCompilePackagesMarksFunctionLiteralAsyncForInterfaceMethodCall(t *testing.T) {
|
|
3712
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
3713
|
+
"go.mod": "module example.test/funclitifaceawait\n\ngo 1.25.3\n",
|
|
3714
|
+
"main.go": strings.Join([]string{
|
|
3715
|
+
"package funclitifaceawait",
|
|
3716
|
+
"type Ref struct{}",
|
|
3717
|
+
"type BlockWithRefs interface {",
|
|
3718
|
+
" ApplyBlockRef(uint32, *Ref) error",
|
|
3719
|
+
"}",
|
|
3720
|
+
"func Each(cb func(BlockWithRefs) error) error { return nil }",
|
|
3721
|
+
"func Copy(ref *Ref) error {",
|
|
3722
|
+
" return Each(func(block BlockWithRefs) error {",
|
|
3723
|
+
" if err := block.ApplyBlockRef(7, ref); err != nil {",
|
|
3724
|
+
" return err",
|
|
3725
|
+
" }",
|
|
3726
|
+
" return nil",
|
|
3727
|
+
" })",
|
|
3728
|
+
"}",
|
|
3729
|
+
"",
|
|
3730
|
+
}, "\n"),
|
|
3731
|
+
})
|
|
3732
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
3733
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
3734
|
+
if err != nil {
|
|
3735
|
+
t.Fatal(err.Error())
|
|
3736
|
+
}
|
|
3737
|
+
|
|
3738
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
3739
|
+
t.Fatal(err.Error())
|
|
3740
|
+
}
|
|
3741
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "funclitifaceawait", "main.gs.ts")
|
|
3742
|
+
content, err := os.ReadFile(outputFile)
|
|
3743
|
+
if err != nil {
|
|
3744
|
+
t.Fatal(err.Error())
|
|
3745
|
+
}
|
|
3746
|
+
text := string(content)
|
|
3747
|
+
for _, want := range []string{
|
|
3748
|
+
"$.functionValue(async (block: BlockWithRefs | null): globalThis.Promise<$.GoError> => {",
|
|
3749
|
+
"let err = await $.pointerValue<Exclude<BlockWithRefs, null>>(block).ApplyBlockRef($.uint(7, 32), ref)",
|
|
3750
|
+
} {
|
|
3751
|
+
if !strings.Contains(text, want) {
|
|
3752
|
+
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
}
|
|
3756
|
+
|
|
3757
|
+
func TestCompilePackagesMarksFunctionLiteralAsyncForInterfaceMethodTypeSwitch(t *testing.T) {
|
|
3758
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
3759
|
+
"go.mod": "module example.test/funclittypeswitchawait\n\ngo 1.25.3\n",
|
|
3760
|
+
"main.go": strings.Join([]string{
|
|
3761
|
+
"package funclittypeswitchawait",
|
|
3762
|
+
"type GetPeer struct{}",
|
|
3763
|
+
"type Directive interface{ GetDirective() any }",
|
|
3764
|
+
"type Bridge struct{ keep func(Directive) (bool, error) }",
|
|
3765
|
+
"func NewBridge(keep func(Directive) (bool, error)) *Bridge { return &Bridge{keep: keep} }",
|
|
3766
|
+
"func Build() *Bridge {",
|
|
3767
|
+
" return NewBridge(func(di Directive) (bool, error) {",
|
|
3768
|
+
" switch di.GetDirective().(type) {",
|
|
3769
|
+
" case GetPeer:",
|
|
3770
|
+
" return false, nil",
|
|
3771
|
+
" }",
|
|
3772
|
+
" return true, nil",
|
|
3773
|
+
" })",
|
|
3774
|
+
"}",
|
|
3775
|
+
"",
|
|
3776
|
+
}, "\n"),
|
|
3777
|
+
})
|
|
3778
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
3779
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
3780
|
+
if err != nil {
|
|
3781
|
+
t.Fatal(err.Error())
|
|
3782
|
+
}
|
|
3783
|
+
|
|
3784
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
3785
|
+
t.Fatal(err.Error())
|
|
3786
|
+
}
|
|
3787
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "funclittypeswitchawait", "main.gs.ts")
|
|
3788
|
+
content, err := os.ReadFile(outputFile)
|
|
3789
|
+
if err != nil {
|
|
3790
|
+
t.Fatal(err.Error())
|
|
3791
|
+
}
|
|
3792
|
+
text := string(content)
|
|
3793
|
+
for _, want := range []string{
|
|
3794
|
+
"$.functionValue(async (di: Directive | null): globalThis.Promise<[boolean, $.GoError]> => {",
|
|
3795
|
+
"const __goscriptTypeSwitchValue = await $.pointerValue<Exclude<Directive, null>>(di).GetDirective()",
|
|
3796
|
+
} {
|
|
3797
|
+
if !strings.Contains(text, want) {
|
|
3798
|
+
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
|
|
3699
3803
|
func TestCompilePackagesMarksRangeFuncAsyncWhenBodyAwaits(t *testing.T) {
|
|
3700
3804
|
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
3701
3805
|
"go.mod": "module example.test/rangefuncawaitbody\n\ngo 1.25.3\n",
|
|
@@ -3917,6 +4021,179 @@ func TestCompilePackagesPropagatesAsyncInterfaceMethodsFromTestImports(t *testin
|
|
|
3917
4021
|
}
|
|
3918
4022
|
}
|
|
3919
4023
|
|
|
4024
|
+
func TestCompilePackagesAwaitsAsyncInterfaceMethodSingleResultAssignment(t *testing.T) {
|
|
4025
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
4026
|
+
"go.mod": "module example.test/asyncifaceassign\n\ngo 1.25.3\n",
|
|
4027
|
+
"iface/controller.go": strings.Join([]string{
|
|
4028
|
+
"package iface",
|
|
4029
|
+
"import \"context\"",
|
|
4030
|
+
"type Controller interface {",
|
|
4031
|
+
" Execute(context.Context) error",
|
|
4032
|
+
"}",
|
|
4033
|
+
"",
|
|
4034
|
+
}, "\n"),
|
|
4035
|
+
"impl/controller.go": strings.Join([]string{
|
|
4036
|
+
"package impl",
|
|
4037
|
+
"import (",
|
|
4038
|
+
" \"context\"",
|
|
4039
|
+
" \"example.test/asyncifaceassign/iface\"",
|
|
4040
|
+
")",
|
|
4041
|
+
"type Controller struct { ch chan struct{} }",
|
|
4042
|
+
"func NewController() iface.Controller {",
|
|
4043
|
+
" return &Controller{ch: make(chan struct{}, 1)}",
|
|
4044
|
+
"}",
|
|
4045
|
+
"func (c *Controller) Execute(ctx context.Context) error {",
|
|
4046
|
+
" select {",
|
|
4047
|
+
" case <-c.ch:",
|
|
4048
|
+
" return nil",
|
|
4049
|
+
" case <-ctx.Done():",
|
|
4050
|
+
" return ctx.Err()",
|
|
4051
|
+
" }",
|
|
4052
|
+
"}",
|
|
4053
|
+
"",
|
|
4054
|
+
}, "\n"),
|
|
4055
|
+
"use.go": strings.Join([]string{
|
|
4056
|
+
"package asyncifaceassign",
|
|
4057
|
+
"import (",
|
|
4058
|
+
" \"context\"",
|
|
4059
|
+
" \"example.test/asyncifaceassign/iface\"",
|
|
4060
|
+
")",
|
|
4061
|
+
"func Run(ctx context.Context, c iface.Controller) error {",
|
|
4062
|
+
" err := c.Execute(ctx)",
|
|
4063
|
+
" return err",
|
|
4064
|
+
"}",
|
|
4065
|
+
"",
|
|
4066
|
+
}, "\n"),
|
|
4067
|
+
})
|
|
4068
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
4069
|
+
service := NewCompileService()
|
|
4070
|
+
_, err := service.Compile(context.Background(), &CompileRequest{
|
|
4071
|
+
Patterns: []string{".", "./iface", "./impl"},
|
|
4072
|
+
Dir: moduleDir,
|
|
4073
|
+
OutputPath: outputDir,
|
|
4074
|
+
DependencyMode: DependencyModeAll,
|
|
4075
|
+
RuntimeEmissionMode: RuntimeEmissionModeEmit,
|
|
4076
|
+
})
|
|
4077
|
+
if err != nil {
|
|
4078
|
+
t.Fatal(err.Error())
|
|
4079
|
+
}
|
|
4080
|
+
|
|
4081
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "asyncifaceassign", "use.gs.ts")
|
|
4082
|
+
content, err := os.ReadFile(outputFile)
|
|
4083
|
+
if err != nil {
|
|
4084
|
+
t.Fatal(err.Error())
|
|
4085
|
+
}
|
|
4086
|
+
text := string(content)
|
|
4087
|
+
if want := "let err = await $.pointerValue<Exclude<iface.Controller, null>>(c).Execute(ctx)"; !strings.Contains(text, want) {
|
|
4088
|
+
t.Fatalf("single-result async interface assignment was not awaited:\n%s", text)
|
|
4089
|
+
}
|
|
4090
|
+
}
|
|
4091
|
+
|
|
4092
|
+
func TestCompilePackagesAwaitsInterfaceMethodCallInsideAsyncCallerWithoutKnownImplementation(t *testing.T) {
|
|
4093
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
4094
|
+
"go.mod": "module example.test/asyncifaceunknownimpl\n\ngo 1.25.3\n",
|
|
4095
|
+
"iface/controller.go": strings.Join([]string{
|
|
4096
|
+
"package iface",
|
|
4097
|
+
"import \"context\"",
|
|
4098
|
+
"type Controller interface {",
|
|
4099
|
+
" Execute(context.Context) error",
|
|
4100
|
+
"}",
|
|
4101
|
+
"",
|
|
4102
|
+
}, "\n"),
|
|
4103
|
+
"use.go": strings.Join([]string{
|
|
4104
|
+
"package asyncifaceunknownimpl",
|
|
4105
|
+
"import (",
|
|
4106
|
+
" \"context\"",
|
|
4107
|
+
" \"example.test/asyncifaceunknownimpl/iface\"",
|
|
4108
|
+
")",
|
|
4109
|
+
"func Run(ctx context.Context, c iface.Controller, ready <-chan struct{}) error {",
|
|
4110
|
+
" select {",
|
|
4111
|
+
" case <-ready:",
|
|
4112
|
+
" default:",
|
|
4113
|
+
" }",
|
|
4114
|
+
" err := c.Execute(ctx)",
|
|
4115
|
+
" return err",
|
|
4116
|
+
"}",
|
|
4117
|
+
"",
|
|
4118
|
+
}, "\n"),
|
|
4119
|
+
})
|
|
4120
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
4121
|
+
service := NewCompileService()
|
|
4122
|
+
_, err := service.Compile(context.Background(), &CompileRequest{
|
|
4123
|
+
Patterns: []string{".", "./iface"},
|
|
4124
|
+
Dir: moduleDir,
|
|
4125
|
+
OutputPath: outputDir,
|
|
4126
|
+
DependencyMode: DependencyModeAll,
|
|
4127
|
+
RuntimeEmissionMode: RuntimeEmissionModeEmit,
|
|
4128
|
+
})
|
|
4129
|
+
if err != nil {
|
|
4130
|
+
t.Fatal(err.Error())
|
|
4131
|
+
}
|
|
4132
|
+
|
|
4133
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "asyncifaceunknownimpl", "use.gs.ts")
|
|
4134
|
+
content, err := os.ReadFile(outputFile)
|
|
4135
|
+
if err != nil {
|
|
4136
|
+
t.Fatal(err.Error())
|
|
4137
|
+
}
|
|
4138
|
+
text := string(content)
|
|
4139
|
+
if want := "let err = await $.pointerValue<Exclude<iface.Controller, null>>(c).Execute(ctx)"; !strings.Contains(text, want) {
|
|
4140
|
+
t.Fatalf("async caller did not await interface method with unknown implementation:\n%s", text)
|
|
4141
|
+
}
|
|
4142
|
+
}
|
|
4143
|
+
|
|
4144
|
+
func TestCompilePackagesMarksNamedFunctionAsyncForInterfaceMethodCallWithoutKnownImplementation(t *testing.T) {
|
|
4145
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
4146
|
+
"go.mod": "module example.test/syncifaceunknownimpl\n\ngo 1.25.3\n",
|
|
4147
|
+
"iface/controller.go": strings.Join([]string{
|
|
4148
|
+
"package iface",
|
|
4149
|
+
"import \"context\"",
|
|
4150
|
+
"type Controller interface {",
|
|
4151
|
+
" Execute(context.Context) error",
|
|
4152
|
+
"}",
|
|
4153
|
+
"",
|
|
4154
|
+
}, "\n"),
|
|
4155
|
+
"use.go": strings.Join([]string{
|
|
4156
|
+
"package syncifaceunknownimpl",
|
|
4157
|
+
"import (",
|
|
4158
|
+
" \"context\"",
|
|
4159
|
+
" \"example.test/syncifaceunknownimpl/iface\"",
|
|
4160
|
+
")",
|
|
4161
|
+
"func Run(ctx context.Context, c iface.Controller) error {",
|
|
4162
|
+
" err := c.Execute(ctx)",
|
|
4163
|
+
" return err",
|
|
4164
|
+
"}",
|
|
4165
|
+
"",
|
|
4166
|
+
}, "\n"),
|
|
4167
|
+
})
|
|
4168
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
4169
|
+
service := NewCompileService()
|
|
4170
|
+
_, err := service.Compile(context.Background(), &CompileRequest{
|
|
4171
|
+
Patterns: []string{".", "./iface"},
|
|
4172
|
+
Dir: moduleDir,
|
|
4173
|
+
OutputPath: outputDir,
|
|
4174
|
+
DependencyMode: DependencyModeAll,
|
|
4175
|
+
RuntimeEmissionMode: RuntimeEmissionModeEmit,
|
|
4176
|
+
})
|
|
4177
|
+
if err != nil {
|
|
4178
|
+
t.Fatal(err.Error())
|
|
4179
|
+
}
|
|
4180
|
+
|
|
4181
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "syncifaceunknownimpl", "use.gs.ts")
|
|
4182
|
+
content, err := os.ReadFile(outputFile)
|
|
4183
|
+
if err != nil {
|
|
4184
|
+
t.Fatal(err.Error())
|
|
4185
|
+
}
|
|
4186
|
+
text := string(content)
|
|
4187
|
+
for _, want := range []string{
|
|
4188
|
+
"export async function Run(ctx: context.Context | null, c: iface.Controller | null): globalThis.Promise<$.GoError>",
|
|
4189
|
+
"let err = await $.pointerValue<Exclude<iface.Controller, null>>(c).Execute(ctx)",
|
|
4190
|
+
} {
|
|
4191
|
+
if !strings.Contains(text, want) {
|
|
4192
|
+
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
4193
|
+
}
|
|
4194
|
+
}
|
|
4195
|
+
}
|
|
4196
|
+
|
|
3920
4197
|
func TestCompilePackagesMarksSelectReturningIfElseCasesUnreachable(t *testing.T) {
|
|
3921
4198
|
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
3922
4199
|
"go.mod": "module example.test/select-if-else\n\ngo 1.25.3\n",
|
|
@@ -4151,6 +4428,148 @@ func TestCompilePackagesParenthesizesAsyncFieldReceivers(t *testing.T) {
|
|
|
4151
4428
|
}
|
|
4152
4429
|
}
|
|
4153
4430
|
|
|
4431
|
+
func TestCompilePackagesAwaitsAsyncMethodValuesInAssignmentsAndReceivers(t *testing.T) {
|
|
4432
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
4433
|
+
"go.mod": "module example.test/asyncmethodvalues\n\ngo 1.25.3\n",
|
|
4434
|
+
"main.go": strings.Join([]string{
|
|
4435
|
+
"package asyncmethodvalues",
|
|
4436
|
+
"import \"reflect\"",
|
|
4437
|
+
"type Entry struct { value any }",
|
|
4438
|
+
"type Holder struct { entry *Entry }",
|
|
4439
|
+
"func (e *Entry) WithField(key string, value any) *Entry {",
|
|
4440
|
+
" return e.WithFields(map[string]any{key: value})",
|
|
4441
|
+
"}",
|
|
4442
|
+
"func (e *Entry) WithFields(fields map[string]any) *Entry {",
|
|
4443
|
+
" for _, value := range fields {",
|
|
4444
|
+
" if t := reflect.TypeOf(value); t != nil {",
|
|
4445
|
+
" switch {",
|
|
4446
|
+
" case t.Kind() == reflect.Func:",
|
|
4447
|
+
" e.value = value",
|
|
4448
|
+
" }",
|
|
4449
|
+
" }",
|
|
4450
|
+
" }",
|
|
4451
|
+
" return e",
|
|
4452
|
+
"}",
|
|
4453
|
+
"func (e *Entry) Warn(msg string) {}",
|
|
4454
|
+
"func Use(entry *Entry) {",
|
|
4455
|
+
" le := entry.WithField(\"first\", func(){})",
|
|
4456
|
+
" h := Holder{entry: entry.WithField(\"holder\", func(){})}",
|
|
4457
|
+
" _ = h",
|
|
4458
|
+
" le.WithField(\"second\", func(){}).Warn(\"done\")",
|
|
4459
|
+
"}",
|
|
4460
|
+
"",
|
|
4461
|
+
}, "\n"),
|
|
4462
|
+
})
|
|
4463
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
4464
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
4465
|
+
if err != nil {
|
|
4466
|
+
t.Fatal(err.Error())
|
|
4467
|
+
}
|
|
4468
|
+
|
|
4469
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
4470
|
+
t.Fatal(err.Error())
|
|
4471
|
+
}
|
|
4472
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "asyncmethodvalues", "main.gs.ts")
|
|
4473
|
+
content, err := os.ReadFile(outputFile)
|
|
4474
|
+
if err != nil {
|
|
4475
|
+
t.Fatal(err.Error())
|
|
4476
|
+
}
|
|
4477
|
+
text := string(content)
|
|
4478
|
+
for _, want := range []string{
|
|
4479
|
+
"public async WithField(key: string, value: any): globalThis.Promise<Entry | $.VarRef<Entry> | null>",
|
|
4480
|
+
"let le: Entry | $.VarRef<Entry> | null = await Entry.prototype.WithField.call(entry, \"first\",",
|
|
4481
|
+
"const __goscriptLiteralField0 = await Entry.prototype.WithField.call(entry, \"holder\",",
|
|
4482
|
+
"Entry.prototype.Warn.call(await Entry.prototype.WithField.call(le, \"second\",",
|
|
4483
|
+
} {
|
|
4484
|
+
if !strings.Contains(text, want) {
|
|
4485
|
+
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
4486
|
+
}
|
|
4487
|
+
}
|
|
4488
|
+
for _, bad := range []string{
|
|
4489
|
+
"let le: Entry | $.VarRef<Entry> | null = Entry.prototype.WithField.call",
|
|
4490
|
+
"const __goscriptLiteralField0 = Entry.prototype.WithField.call",
|
|
4491
|
+
"Entry.prototype.Warn.call(Entry.prototype.WithField.call",
|
|
4492
|
+
} {
|
|
4493
|
+
if strings.Contains(text, bad) {
|
|
4494
|
+
t.Fatalf("async method value was consumed without await at %q:\n%s", bad, text)
|
|
4495
|
+
}
|
|
4496
|
+
}
|
|
4497
|
+
}
|
|
4498
|
+
|
|
4499
|
+
func TestCompilePackagesKeepsErrorInterfaceErrorSynchronous(t *testing.T) {
|
|
4500
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
4501
|
+
"go.mod": "module example.test/syncerrorstring\n\ngo 1.25.3\n",
|
|
4502
|
+
"main.go": strings.Join([]string{
|
|
4503
|
+
"package syncerrorstring",
|
|
4504
|
+
"type wrappedError struct {",
|
|
4505
|
+
" cause error",
|
|
4506
|
+
" msg string",
|
|
4507
|
+
"}",
|
|
4508
|
+
"func (w *wrappedError) Error() string {",
|
|
4509
|
+
" return w.msg + \": \" + w.cause.Error()",
|
|
4510
|
+
"}",
|
|
4511
|
+
"type healthError struct {",
|
|
4512
|
+
" cause error",
|
|
4513
|
+
" health string",
|
|
4514
|
+
"}",
|
|
4515
|
+
"type HealthError interface {",
|
|
4516
|
+
" error",
|
|
4517
|
+
" GetHealth() string",
|
|
4518
|
+
"}",
|
|
4519
|
+
"func (h *healthError) Error() string {",
|
|
4520
|
+
" if h.cause != nil {",
|
|
4521
|
+
" return h.cause.Error()",
|
|
4522
|
+
" }",
|
|
4523
|
+
" return h.health",
|
|
4524
|
+
"}",
|
|
4525
|
+
"func (h *healthError) GetHealth() string { return h.health }",
|
|
4526
|
+
"type baseError string",
|
|
4527
|
+
"func (b baseError) Error() string { return string(b) }",
|
|
4528
|
+
"func NewWrapped() error {",
|
|
4529
|
+
" return &wrappedError{msg: \"load\", cause: &healthError{cause: baseError(\"missing\")}}",
|
|
4530
|
+
"}",
|
|
4531
|
+
"func ReadHealthError(h HealthError) string {",
|
|
4532
|
+
" return h.Error()",
|
|
4533
|
+
"}",
|
|
4534
|
+
"",
|
|
4535
|
+
}, "\n"),
|
|
4536
|
+
})
|
|
4537
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
4538
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
4539
|
+
if err != nil {
|
|
4540
|
+
t.Fatal(err.Error())
|
|
4541
|
+
}
|
|
4542
|
+
|
|
4543
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
4544
|
+
t.Fatal(err.Error())
|
|
4545
|
+
}
|
|
4546
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "syncerrorstring", "main.gs.ts")
|
|
4547
|
+
content, err := os.ReadFile(outputFile)
|
|
4548
|
+
if err != nil {
|
|
4549
|
+
t.Fatal(err.Error())
|
|
4550
|
+
}
|
|
4551
|
+
text := string(content)
|
|
4552
|
+
for _, want := range []string{
|
|
4553
|
+
"public Error(): string {",
|
|
4554
|
+
"return ($.pointerValue<wrappedError>(w).msg + \": \") + $.pointerValue<Exclude<$.GoError, null>>($.pointerValue<wrappedError>(w).cause).Error()",
|
|
4555
|
+
"return $.pointerValue<Exclude<$.GoError, null>>($.pointerValue<healthError>(h).cause).Error()",
|
|
4556
|
+
} {
|
|
4557
|
+
if !strings.Contains(text, want) {
|
|
4558
|
+
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
4559
|
+
}
|
|
4560
|
+
}
|
|
4561
|
+
for _, bad := range []string{
|
|
4562
|
+
"public async Error(): globalThis.Promise<string>",
|
|
4563
|
+
"await $.pointerValue<Exclude<$.GoError, null>>($.pointerValue<wrappedError>(w).cause).Error()",
|
|
4564
|
+
"await $.pointerValue<Exclude<$.GoError, null>>($.pointerValue<healthError>(h).cause).Error()",
|
|
4565
|
+
"await $.pointerValue<HealthError>(h).Error()",
|
|
4566
|
+
} {
|
|
4567
|
+
if strings.Contains(text, bad) {
|
|
4568
|
+
t.Fatalf("error stringification became async at %q:\n%s", bad, text)
|
|
4569
|
+
}
|
|
4570
|
+
}
|
|
4571
|
+
}
|
|
4572
|
+
|
|
4154
4573
|
func TestCompilePackagesScopesIfInitDeclarations(t *testing.T) {
|
|
4155
4574
|
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
4156
4575
|
"go.mod": "module example.test/ifinit\n\ngo 1.25.3\n",
|
|
@@ -4344,6 +4763,7 @@ func TestCompilePackagesQualifiesImportedTypesInSignaturesAndZeroValues(t *testi
|
|
|
4344
4763
|
"type Box struct {",
|
|
4345
4764
|
" Value int",
|
|
4346
4765
|
"}",
|
|
4766
|
+
"type Header map[string][]string",
|
|
4347
4767
|
"",
|
|
4348
4768
|
}, "\n"),
|
|
4349
4769
|
"main.go": strings.Join([]string{
|
|
@@ -4355,6 +4775,7 @@ func TestCompilePackagesQualifiesImportedTypesInSignaturesAndZeroValues(t *testi
|
|
|
4355
4775
|
"type Holder struct {",
|
|
4356
4776
|
" Box lib.Box",
|
|
4357
4777
|
" Boxes []lib.Box",
|
|
4778
|
+
" Header lib.Header",
|
|
4358
4779
|
" Fn func(lib.Box) (lib.Box, error)",
|
|
4359
4780
|
" Ptr atomic.Pointer[func()]",
|
|
4360
4781
|
"}",
|
|
@@ -4385,8 +4806,10 @@ func TestCompilePackagesQualifiesImportedTypesInSignaturesAndZeroValues(t *testi
|
|
|
4385
4806
|
for _, want := range []string{
|
|
4386
4807
|
"Box: $.VarRef<lib.Box>",
|
|
4387
4808
|
"Boxes: $.VarRef<$.Slice<lib.Box>>",
|
|
4809
|
+
"Header: $.VarRef<lib.Header>",
|
|
4388
4810
|
"Fn: $.VarRef<((_p0: lib.Box) => [lib.Box, $.GoError] | globalThis.Promise<[lib.Box, $.GoError]>) | null>",
|
|
4389
4811
|
"Ptr: $.VarRef<atomic.Pointer<(() => void) | null>>",
|
|
4812
|
+
"Header: $.varRef(init?.Header ?? (null as unknown as lib.Header))",
|
|
4390
4813
|
"$.markAsStructValue(new lib.Box())",
|
|
4391
4814
|
"$.markAsStructValue(new atomic.Pointer<(() => void) | null>())",
|
|
4392
4815
|
"export async function Use(fn: ((_p0: lib.Box) => [lib.Box, $.GoError] | globalThis.Promise<[lib.Box, $.GoError]>) | null, box: lib.Box): globalThis.Promise<[lib.Box, $.GoError]>",
|
|
@@ -4511,7 +4934,7 @@ func TestCompilePackagesNormalizesWideIntegerReturnTargets(t *testing.T) {
|
|
|
4511
4934
|
t.Fatal(err.Error())
|
|
4512
4935
|
}
|
|
4513
4936
|
text := string(content)
|
|
4514
|
-
if !strings.Contains(text, "return $.uint($.pointerValue<Exclude<hash.Hash64, null>>(h).Sum64(), 64)") {
|
|
4937
|
+
if !strings.Contains(text, "return $.uint(await $.pointerValue<Exclude<hash.Hash64, null>>(h).Sum64(), 64)") {
|
|
4515
4938
|
t.Fatalf("missing uint64 return normalization:\n%s", text)
|
|
4516
4939
|
}
|
|
4517
4940
|
}
|
|
@@ -4595,6 +5018,41 @@ func TestCompilePackagesUnwrapsOverridePointerMethodReceiver(t *testing.T) {
|
|
|
4595
5018
|
}
|
|
4596
5019
|
}
|
|
4597
5020
|
|
|
5021
|
+
func TestCompilePackagesUsesRuntimeValueForAbsentSelectedReceiverType(t *testing.T) {
|
|
5022
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
5023
|
+
"go.mod": "module example.test/selected-receiver-import\n\ngo 1.25.3\n",
|
|
5024
|
+
"main.go": strings.Join([]string{
|
|
5025
|
+
"package main",
|
|
5026
|
+
"import \"net/http\"",
|
|
5027
|
+
"func URLString(req *http.Request) string {",
|
|
5028
|
+
" return req.URL.String()",
|
|
5029
|
+
"}",
|
|
5030
|
+
"",
|
|
5031
|
+
}, "\n"),
|
|
5032
|
+
})
|
|
5033
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
5034
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
5035
|
+
if err != nil {
|
|
5036
|
+
t.Fatal(err.Error())
|
|
5037
|
+
}
|
|
5038
|
+
|
|
5039
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
5040
|
+
t.Fatal(err.Error())
|
|
5041
|
+
}
|
|
5042
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "selected-receiver-import", "main.gs.ts")
|
|
5043
|
+
content, err := os.ReadFile(outputFile)
|
|
5044
|
+
if err != nil {
|
|
5045
|
+
t.Fatal(err.Error())
|
|
5046
|
+
}
|
|
5047
|
+
text := string(content)
|
|
5048
|
+
if strings.Contains(text, "URL.prototype.String.call") {
|
|
5049
|
+
t.Fatalf("selected receiver method call used unqualified type:\n%s", text)
|
|
5050
|
+
}
|
|
5051
|
+
if !strings.Contains(text, "$.pointerValue<http.Request>(req).URL.String()") {
|
|
5052
|
+
t.Fatalf("selected receiver method call did not use runtime value method:\n%s", text)
|
|
5053
|
+
}
|
|
5054
|
+
}
|
|
5055
|
+
|
|
4598
5056
|
func TestCompilePackagesUnwrapsImportedArrayPackageVarReads(t *testing.T) {
|
|
4599
5057
|
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
4600
5058
|
"go.mod": "module example.test/imported-array-var\n\ngo 1.25.3\n",
|
|
@@ -456,7 +456,11 @@ func renderStruct(b *strings.Builder, structType *loweredStruct, runtimeOwner *R
|
|
|
456
456
|
b.WriteString("init?.")
|
|
457
457
|
b.WriteString(field.name)
|
|
458
458
|
b.WriteString(" ?? ")
|
|
459
|
+
b.WriteString("(")
|
|
459
460
|
b.WriteString(field.zero)
|
|
461
|
+
b.WriteString(" as unknown as ")
|
|
462
|
+
b.WriteString(field.typ)
|
|
463
|
+
b.WriteString(")")
|
|
460
464
|
}
|
|
461
465
|
b.WriteString(")")
|
|
462
466
|
if idx != len(structType.fields)-1 {
|
|
@@ -135,9 +135,7 @@ export function pointerValue(value) {
|
|
|
135
135
|
if (isVarRef(value)) {
|
|
136
136
|
return value.value;
|
|
137
137
|
}
|
|
138
|
-
const boxed = typeof value === 'object' &&
|
|
139
|
-
value !== null &&
|
|
140
|
-
'__goValue' in value ?
|
|
138
|
+
const boxed = typeof value === 'object' && value !== null && '__goValue' in value ?
|
|
141
139
|
value
|
|
142
140
|
: null;
|
|
143
141
|
if (boxed !== null &&
|
|
@@ -155,9 +153,7 @@ export function pointerValueOrNil(value) {
|
|
|
155
153
|
if (isVarRef(value)) {
|
|
156
154
|
return value.value;
|
|
157
155
|
}
|
|
158
|
-
const boxed = typeof value === 'object' &&
|
|
159
|
-
value !== null &&
|
|
160
|
-
'__goValue' in value ?
|
|
156
|
+
const boxed = typeof value === 'object' && value !== null && '__goValue' in value ?
|
|
161
157
|
value
|
|
162
158
|
: null;
|
|
163
159
|
if (boxed !== null &&
|
|
@@ -206,7 +202,9 @@ export function comparableEqual(a, b) {
|
|
|
206
202
|
return false;
|
|
207
203
|
}
|
|
208
204
|
if (hasGoValue(a) || hasGoValue(b)) {
|
|
209
|
-
return hasGoValue(a) &&
|
|
205
|
+
return (hasGoValue(a) &&
|
|
206
|
+
hasGoValue(b) &&
|
|
207
|
+
comparableEqual(a.__goValue, b.__goValue));
|
|
210
208
|
}
|
|
211
209
|
}
|
|
212
210
|
if (isStructValue(a) && isStructValue(b)) {
|
|
@@ -471,8 +469,8 @@ function int64Value(value) {
|
|
|
471
469
|
return BigInt.asIntN(64, BigInt(Math.trunc(value)));
|
|
472
470
|
}
|
|
473
471
|
function int64Result(value) {
|
|
474
|
-
const normalized = value >= -0x8000000000000000n && value <= 0x7fffffffffffffffn
|
|
475
|
-
|
|
472
|
+
const normalized = value >= -0x8000000000000000n && value <= 0x7fffffffffffffffn ?
|
|
473
|
+
value
|
|
476
474
|
: BigInt.asIntN(64, value);
|
|
477
475
|
return Number(normalized);
|
|
478
476
|
}
|