goscript 0.1.3 → 0.1.4
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/cmd/goscript/cmd_compile.go +28 -8
- package/cmd/goscript/cmd_compile_test.go +105 -6
- package/compiler/build-flags.go +9 -10
- package/compiler/gotest/runner_test.go +127 -0
- package/compiler/lowering.go +596 -136
- package/compiler/lowering_bench_test.go +350 -0
- package/compiler/package-graph.go +61 -4
- package/compiler/package-graph_test.go +30 -0
- package/compiler/semantic-model-types.go +8 -0
- package/compiler/semantic-model.go +447 -22
- package/compiler/semantic-model_test.go +138 -0
- package/compiler/skeleton_test.go +948 -14
- package/compiler/typescript-emitter.go +19 -2
- package/dist/gs/builtin/builtin.d.ts +2 -2
- package/dist/gs/builtin/builtin.js +20 -0
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/slice.js +5 -0
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +1 -1
- package/dist/gs/builtin/type.js +72 -5
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/compress/zlib/index.d.ts +3 -3
- package/dist/gs/compress/zlib/index.js +88 -26
- package/dist/gs/compress/zlib/index.js.map +1 -1
- package/dist/gs/crypto/sha1/index.js +2 -5
- package/dist/gs/crypto/sha1/index.js.map +1 -1
- package/dist/gs/crypto/sha256/index.js +2 -5
- package/dist/gs/crypto/sha256/index.js.map +1 -1
- package/dist/gs/crypto/sha512/index.js +2 -5
- package/dist/gs/crypto/sha512/index.js.map +1 -1
- package/dist/gs/embed/index.d.ts +6 -0
- package/dist/gs/embed/index.js +210 -5
- package/dist/gs/embed/index.js.map +1 -1
- package/dist/gs/fmt/fmt.d.ts +3 -3
- package/dist/gs/fmt/fmt.js +29 -16
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +118 -6
- package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -1
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.d.ts +45 -0
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js +229 -0
- package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js.map +1 -0
- package/dist/gs/io/fs/readdir.js +5 -3
- package/dist/gs/io/fs/readdir.js.map +1 -1
- package/dist/gs/io/io.d.ts +10 -6
- package/dist/gs/io/io.js +87 -42
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/math/bits/index.d.ts +26 -5
- package/dist/gs/math/bits/index.js +13 -24
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +3 -1
- package/dist/gs/net/http/index.js +18 -1
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +6 -2
- package/dist/gs/os/types_js.gs.js +169 -8
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +1 -0
- package/dist/gs/reflect/type.js +80 -51
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/strings/reader.d.ts +1 -1
- package/dist/gs/strings/reader.js +2 -2
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +2 -1
- package/dist/gs/sync/sync.js +37 -16
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/syscall/js/index.js +9 -0
- package/dist/gs/syscall/js/index.js.map +1 -1
- package/dist/gs/testing/testing.js +8 -6
- package/dist/gs/testing/testing.js.map +1 -1
- package/gs/builtin/builtin.ts +25 -2
- package/gs/builtin/runtime-contract.test.ts +45 -0
- package/gs/builtin/slice.ts +7 -0
- package/gs/builtin/type.ts +85 -5
- package/gs/compress/zlib/index.test.ts +97 -0
- package/gs/compress/zlib/index.ts +117 -27
- package/gs/compress/zlib/meta.json +4 -1
- package/gs/crypto/sha1/index.test.ts +19 -2
- package/gs/crypto/sha1/index.ts +3 -6
- package/gs/crypto/sha256/index.test.ts +14 -2
- package/gs/crypto/sha256/index.ts +3 -6
- package/gs/crypto/sha512/index.test.ts +17 -2
- package/gs/crypto/sha512/index.ts +3 -6
- package/gs/embed/index.test.ts +87 -0
- package/gs/embed/index.ts +229 -5
- package/gs/fmt/fmt.test.ts +41 -3
- package/gs/fmt/fmt.ts +40 -17
- package/gs/fmt/meta.json +6 -1
- package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +8 -1
- package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +139 -11
- package/gs/github.com/go-git/go-billy/v6/osfs/index.test.ts +110 -0
- package/gs/github.com/go-git/go-billy/v6/osfs/index.ts +280 -0
- package/gs/github.com/go-git/go-billy/v6/osfs/meta.json +8 -0
- package/gs/io/fs/readdir.test.ts +38 -0
- package/gs/io/fs/readdir.ts +7 -3
- package/gs/io/io.test.ts +77 -6
- package/gs/io/io.ts +114 -52
- package/gs/io/meta.json +7 -1
- package/gs/math/bits/index.ts +52 -28
- package/gs/net/http/index.test.ts +16 -0
- package/gs/net/http/index.ts +19 -2
- package/gs/os/file_unix_js.test.ts +52 -0
- package/gs/os/meta.json +4 -0
- package/gs/os/readdir.test.ts +56 -0
- package/gs/os/types_js.gs.ts +169 -8
- package/gs/reflect/deepequal.test.ts +10 -1
- package/gs/reflect/type.ts +91 -56
- package/gs/reflect/typefor.test.ts +31 -1
- package/gs/strings/meta.json +5 -2
- package/gs/strings/reader.test.ts +2 -2
- package/gs/strings/reader.ts +2 -2
- package/gs/sync/meta.json +1 -0
- package/gs/sync/sync.test.ts +41 -1
- package/gs/sync/sync.ts +41 -16
- package/gs/syscall/js/index.test.ts +18 -0
- package/gs/syscall/js/index.ts +12 -0
- package/gs/testing/testing.test.ts +32 -3
- package/gs/testing/testing.ts +13 -10
- package/package.json +1 -1
|
@@ -132,7 +132,7 @@ func TestCompilePackagesEmitsSimplePackage(t *testing.T) {
|
|
|
132
132
|
"export async function main(): globalThis.Promise<void>",
|
|
133
133
|
"let size = 5",
|
|
134
134
|
"$.print(\"total:\", size)",
|
|
135
|
-
"$.println(
|
|
135
|
+
"$.println(\"Hello\", total)",
|
|
136
136
|
"$.panic(\"unreachable\")",
|
|
137
137
|
"await main()",
|
|
138
138
|
} {
|
|
@@ -215,9 +215,9 @@ func TestCompilePackagesLazilyInitializesCrossFilePackageVars(t *testing.T) {
|
|
|
215
215
|
}
|
|
216
216
|
text := string(content)
|
|
217
217
|
for _, want := range []string{
|
|
218
|
-
"export var two: holder
|
|
218
|
+
"export var two: holder",
|
|
219
219
|
"export function __goscript_get_two(): holder",
|
|
220
|
-
"export var remoteZero: __goscript_a.remote
|
|
220
|
+
"export var remoteZero: __goscript_a.remote",
|
|
221
221
|
"export function __goscript_get_remoteZero(): __goscript_a.remote",
|
|
222
222
|
"__goscript_a.__goscript_get_one()",
|
|
223
223
|
} {
|
|
@@ -263,7 +263,7 @@ func TestCompilePackagesLazilyInitializesSameFileLaterPackageVars(t *testing.T)
|
|
|
263
263
|
}
|
|
264
264
|
text := string(content)
|
|
265
265
|
for _, want := range []string{
|
|
266
|
-
"export var table: $.Slice<detail>
|
|
266
|
+
"export var table: $.Slice<detail>",
|
|
267
267
|
"export function __goscript_get_table(): $.Slice<detail>",
|
|
268
268
|
"export let later: detail = $.markAsStructValue(new detail({n: 7}))",
|
|
269
269
|
} {
|
|
@@ -305,7 +305,7 @@ func TestCompilePackagesLazilyInitializesFunctionBodyPackageVarDependencies(t *t
|
|
|
305
305
|
}
|
|
306
306
|
text := string(content)
|
|
307
307
|
for _, want := range []string{
|
|
308
|
-
"export var first: Point | $.VarRef<Point> | null
|
|
308
|
+
"export var first: Point | $.VarRef<Point> | null",
|
|
309
309
|
"export function __goscript_get_first(): Point | $.VarRef<Point> | null",
|
|
310
310
|
"function __goscript_get___goscriptTuple",
|
|
311
311
|
"export let later: number = 7",
|
|
@@ -355,7 +355,7 @@ func TestCompilePackagesLazilyInitializesEffectFreeTypeForFromCrossFileInit(t *t
|
|
|
355
355
|
}
|
|
356
356
|
aText := string(aContent)
|
|
357
357
|
for _, want := range []string{
|
|
358
|
-
"export var stringType: reflect.Type | null
|
|
358
|
+
"export var stringType: reflect.Type | null",
|
|
359
359
|
"export function __goscript_get_stringType(): reflect.Type | null",
|
|
360
360
|
"stringType = reflect.TypeFor",
|
|
361
361
|
} {
|
|
@@ -550,6 +550,204 @@ func TestCompilePackagesAliasesForInitShortDeclShadow(t *testing.T) {
|
|
|
550
550
|
}
|
|
551
551
|
}
|
|
552
552
|
|
|
553
|
+
func TestCompilePackagesDoesNotAliasPackageShadowWithoutRead(t *testing.T) {
|
|
554
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
555
|
+
"go.mod": "module example.test/packageshadow\n\ngo 1.25.3\n",
|
|
556
|
+
"main.go": strings.Join([]string{
|
|
557
|
+
"package main",
|
|
558
|
+
"var value = 1",
|
|
559
|
+
"func main() {",
|
|
560
|
+
" value := 2",
|
|
561
|
+
" var other = 3",
|
|
562
|
+
" println(value, other)",
|
|
563
|
+
"}",
|
|
564
|
+
"",
|
|
565
|
+
}, "\n"),
|
|
566
|
+
})
|
|
567
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
568
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
569
|
+
if err != nil {
|
|
570
|
+
t.Fatal(err.Error())
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
574
|
+
t.Fatal(err.Error())
|
|
575
|
+
}
|
|
576
|
+
content, err := os.ReadFile(filepath.Join(outputDir, "@goscript", "example.test", "packageshadow", "main.gs.ts"))
|
|
577
|
+
if err != nil {
|
|
578
|
+
t.Fatal(err.Error())
|
|
579
|
+
}
|
|
580
|
+
text := string(content)
|
|
581
|
+
if !strings.Contains(text, "let value = 2") {
|
|
582
|
+
t.Fatalf("local package shadow was not emitted with its source name:\n%s", text)
|
|
583
|
+
}
|
|
584
|
+
if strings.Contains(text, "__goscriptShadow") {
|
|
585
|
+
t.Fatalf("package shadow without initializer read should not allocate a shadow alias:\n%s", text)
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
func TestCompilePackagesAliasesPackageShadowInitializerReads(t *testing.T) {
|
|
590
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
591
|
+
"go.mod": "module example.test/packageshadowread\n\ngo 1.25.3\n",
|
|
592
|
+
"main.go": strings.Join([]string{
|
|
593
|
+
"package main",
|
|
594
|
+
"var value = 1",
|
|
595
|
+
"func helper() int { return 4 }",
|
|
596
|
+
"func main() {",
|
|
597
|
+
" println(helper())",
|
|
598
|
+
" helper := 5",
|
|
599
|
+
" println(helper)",
|
|
600
|
+
" first := value",
|
|
601
|
+
" value := value + 1",
|
|
602
|
+
" {",
|
|
603
|
+
" var first = first + value",
|
|
604
|
+
" println(first)",
|
|
605
|
+
" }",
|
|
606
|
+
" println(value)",
|
|
607
|
+
"}",
|
|
608
|
+
"",
|
|
609
|
+
}, "\n"),
|
|
610
|
+
})
|
|
611
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
612
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
613
|
+
if err != nil {
|
|
614
|
+
t.Fatal(err.Error())
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
618
|
+
t.Fatal(err.Error())
|
|
619
|
+
}
|
|
620
|
+
content, err := os.ReadFile(filepath.Join(outputDir, "@goscript", "example.test", "packageshadowread", "main.gs.ts"))
|
|
621
|
+
if err != nil {
|
|
622
|
+
t.Fatal(err.Error())
|
|
623
|
+
}
|
|
624
|
+
text := string(content)
|
|
625
|
+
if strings.Contains(text, "let value = value + 1") || strings.Contains(text, "let first: number = 0\n\t\tfirst = first + value") {
|
|
626
|
+
t.Fatalf("initializer read was emitted through a TDZ self-reference:\n%s", text)
|
|
627
|
+
}
|
|
628
|
+
if strings.Contains(text, "let helper = 5") {
|
|
629
|
+
t.Fatalf("same-file package function shadow was emitted with a TDZ-prone source name:\n%s", text)
|
|
630
|
+
}
|
|
631
|
+
if strings.Count(text, "__goscriptShadow") < 3 {
|
|
632
|
+
t.Fatalf("missing shadow aliases for initializer reads:\n%s", text)
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
func TestCompilePackagesLowersPackageConstBeforeLocalShadow(t *testing.T) {
|
|
637
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
638
|
+
"go.mod": "module example.test/constshadow\n\ngo 1.25.3\n",
|
|
639
|
+
"main.go": strings.Join([]string{
|
|
640
|
+
"package main",
|
|
641
|
+
"const headerLength = 4",
|
|
642
|
+
"func parse(buf []byte) int {",
|
|
643
|
+
" if len(buf) < headerLength {",
|
|
644
|
+
" return headerLength",
|
|
645
|
+
" }",
|
|
646
|
+
" n := len(buf)",
|
|
647
|
+
" headerLength := n",
|
|
648
|
+
" return headerLength",
|
|
649
|
+
"}",
|
|
650
|
+
"",
|
|
651
|
+
}, "\n"),
|
|
652
|
+
})
|
|
653
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
654
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
655
|
+
if err != nil {
|
|
656
|
+
t.Fatal(err.Error())
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
660
|
+
t.Fatal(err.Error())
|
|
661
|
+
}
|
|
662
|
+
content, err := os.ReadFile(filepath.Join(outputDir, "@goscript", "example.test", "constshadow", "main.gs.ts"))
|
|
663
|
+
if err != nil {
|
|
664
|
+
t.Fatal(err.Error())
|
|
665
|
+
}
|
|
666
|
+
text := string(content)
|
|
667
|
+
if strings.Contains(text, "$.len(buf) < headerLength") || strings.Contains(text, "return headerLength\n\t}") {
|
|
668
|
+
t.Fatalf("package const read was emitted through local TDZ shadow:\n%s", text)
|
|
669
|
+
}
|
|
670
|
+
if !strings.Contains(text, "$.len(buf) < 4") || !strings.Contains(text, "return 4") {
|
|
671
|
+
t.Fatalf("package const read was not lowered to a value before local shadow:\n%s", text)
|
|
672
|
+
}
|
|
673
|
+
if !strings.Contains(text, "let headerLength = n") {
|
|
674
|
+
t.Fatalf("local shadow was not preserved:\n%s", text)
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
func TestCompilePackagesPreservesNamedUint64InterfaceTypeInfo(t *testing.T) {
|
|
679
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
680
|
+
"go.mod": "module example.test/nameduint64\n\ngo 1.25.3\n",
|
|
681
|
+
"main.go": strings.Join([]string{
|
|
682
|
+
"package main",
|
|
683
|
+
"type Pol uint64",
|
|
684
|
+
"func (p Pol) String() string { return \"\" }",
|
|
685
|
+
"func box() any {",
|
|
686
|
+
" var p Pol",
|
|
687
|
+
" return &p",
|
|
688
|
+
"}",
|
|
689
|
+
"",
|
|
690
|
+
}, "\n"),
|
|
691
|
+
})
|
|
692
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
693
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
694
|
+
if err != nil {
|
|
695
|
+
t.Fatal(err.Error())
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
699
|
+
t.Fatal(err.Error())
|
|
700
|
+
}
|
|
701
|
+
content, err := os.ReadFile(filepath.Join(outputDir, "@goscript", "example.test", "nameduint64", "main.gs.ts"))
|
|
702
|
+
if err != nil {
|
|
703
|
+
t.Fatal(err.Error())
|
|
704
|
+
}
|
|
705
|
+
text := string(content)
|
|
706
|
+
want := `$.namedValueInterfaceValue<any>(p, "*main.Pol"`
|
|
707
|
+
if !strings.Contains(text, want) {
|
|
708
|
+
t.Fatalf("missing named interface box %q in generated output:\n%s", want, text)
|
|
709
|
+
}
|
|
710
|
+
want = `elemType: { kind: $.TypeKind.Basic, name: "uint64", typeName: "main.Pol" }`
|
|
711
|
+
if !strings.Contains(text, want) {
|
|
712
|
+
t.Fatalf("named uint64 pointer interface box lost type metadata:\n%s", text)
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
func TestCompilePackagesLowersWideIntegerConstantsForUint64Targets(t *testing.T) {
|
|
717
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
718
|
+
"go.mod": "module example.test/wideconst\n\ngo 1.25.3\n",
|
|
719
|
+
"main.go": strings.Join([]string{
|
|
720
|
+
"package main",
|
|
721
|
+
"type Pol uint64",
|
|
722
|
+
"func normalize(f Pol) Pol {",
|
|
723
|
+
" f &= Pol((1 << 54) - 1)",
|
|
724
|
+
" f |= (1 << 53) | 1",
|
|
725
|
+
" return f",
|
|
726
|
+
"}",
|
|
727
|
+
"",
|
|
728
|
+
}, "\n"),
|
|
729
|
+
})
|
|
730
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
731
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
732
|
+
if err != nil {
|
|
733
|
+
t.Fatal(err.Error())
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
737
|
+
t.Fatal(err.Error())
|
|
738
|
+
}
|
|
739
|
+
content, err := os.ReadFile(filepath.Join(outputDir, "@goscript", "example.test", "wideconst", "main.gs.ts"))
|
|
740
|
+
if err != nil {
|
|
741
|
+
t.Fatal(err.Error())
|
|
742
|
+
}
|
|
743
|
+
text := string(content)
|
|
744
|
+
for _, want := range []string{`$.uint("18014398509481983", 64)`, `$.uint("9007199254740993", 64)`} {
|
|
745
|
+
if !strings.Contains(text, want) {
|
|
746
|
+
t.Fatalf("missing wide integer constant %q in generated output:\n%s", want, text)
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
553
751
|
func TestCompilePackagesReadsShadowedVarRefStructFieldsOnce(t *testing.T) {
|
|
554
752
|
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
555
753
|
"go.mod": "module example.test/shadowvarreffield\n\ngo 1.25.3\n",
|
|
@@ -864,6 +1062,47 @@ func TestCompilePackagesUsesEmbedOverride(t *testing.T) {
|
|
|
864
1062
|
}
|
|
865
1063
|
}
|
|
866
1064
|
|
|
1065
|
+
func TestCompilePackagesEmbedsFS(t *testing.T) {
|
|
1066
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
1067
|
+
"go.mod": "module example.test/embedfs\n\ngo 1.25.3\n",
|
|
1068
|
+
"assets/config.json": `{"ok":true}`,
|
|
1069
|
+
"assets/nested.txt": "nested",
|
|
1070
|
+
"extra.txt": "extra",
|
|
1071
|
+
"main.go": strings.Join([]string{
|
|
1072
|
+
"package embedfs",
|
|
1073
|
+
"import \"embed\"",
|
|
1074
|
+
"//go:embed assets *.txt",
|
|
1075
|
+
"var StaticFS embed.FS",
|
|
1076
|
+
"",
|
|
1077
|
+
}, "\n"),
|
|
1078
|
+
})
|
|
1079
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
1080
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir, AllDependencies: true}, nil, nil)
|
|
1081
|
+
if err != nil {
|
|
1082
|
+
t.Fatal(err.Error())
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
1086
|
+
t.Fatal(err.Error())
|
|
1087
|
+
}
|
|
1088
|
+
content, err := os.ReadFile(filepath.Join(outputDir, "@goscript", "example.test", "embedfs", "main.gs.ts"))
|
|
1089
|
+
if err != nil {
|
|
1090
|
+
t.Fatal(err.Error())
|
|
1091
|
+
}
|
|
1092
|
+
if !strings.Contains(string(content), `export let StaticFS: embed.FS = $.markAsStructValue(new embed.FS`) {
|
|
1093
|
+
t.Fatalf("embedded FS was not emitted as embed.FS:\n%s", string(content))
|
|
1094
|
+
}
|
|
1095
|
+
if !strings.Contains(string(content), `["assets/config.json", new Uint8Array([123, 34, 111, 107, 34, 58, 116, 114, 117, 101, 125])]`) {
|
|
1096
|
+
t.Fatalf("embedded FS file content was not emitted:\n%s", string(content))
|
|
1097
|
+
}
|
|
1098
|
+
if !strings.Contains(string(content), `["assets/nested.txt", new Uint8Array([110, 101, 115, 116, 101, 100])]`) {
|
|
1099
|
+
t.Fatalf("embedded FS directory file content was not emitted:\n%s", string(content))
|
|
1100
|
+
}
|
|
1101
|
+
if !strings.Contains(string(content), `["extra.txt", new Uint8Array([101, 120, 116, 114, 97])]`) {
|
|
1102
|
+
t.Fatalf("embedded FS glob file content was not emitted:\n%s", string(content))
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
|
|
867
1106
|
func TestCompilePackagesEmitsPackageLocalImport(t *testing.T) {
|
|
868
1107
|
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
869
1108
|
"go.mod": "module example.test/imports\n\ngo 1.25.3\n",
|
|
@@ -950,6 +1189,51 @@ func TestCompilePackagesEmitsPackageLocalImport(t *testing.T) {
|
|
|
950
1189
|
}
|
|
951
1190
|
}
|
|
952
1191
|
|
|
1192
|
+
func TestCompilePackagesCallsCrossPackageUnexportedReceiverDynamically(t *testing.T) {
|
|
1193
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
1194
|
+
"go.mod": "module example.test/unexportedreceiver\n\ngo 1.25.3\n",
|
|
1195
|
+
"dep/dep.go": strings.Join([]string{
|
|
1196
|
+
"package dep",
|
|
1197
|
+
"type hidden struct{}",
|
|
1198
|
+
"func NewHidden() *hidden { return &hidden{} }",
|
|
1199
|
+
"func (h *hidden) Value() int { return 7 }",
|
|
1200
|
+
"",
|
|
1201
|
+
}, "\n"),
|
|
1202
|
+
"main.go": strings.Join([]string{
|
|
1203
|
+
"package main",
|
|
1204
|
+
"import \"example.test/unexportedreceiver/dep\"",
|
|
1205
|
+
"func main() {",
|
|
1206
|
+
" h := dep.NewHidden()",
|
|
1207
|
+
" println(h.Value())",
|
|
1208
|
+
"}",
|
|
1209
|
+
"",
|
|
1210
|
+
}, "\n"),
|
|
1211
|
+
})
|
|
1212
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
1213
|
+
comp, err := NewCompiler(&Config{
|
|
1214
|
+
Dir: moduleDir,
|
|
1215
|
+
OutputPath: outputDir,
|
|
1216
|
+
AllDependencies: true,
|
|
1217
|
+
}, nil, nil)
|
|
1218
|
+
if err != nil {
|
|
1219
|
+
t.Fatal(err.Error())
|
|
1220
|
+
}
|
|
1221
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
1222
|
+
t.Fatal(err.Error())
|
|
1223
|
+
}
|
|
1224
|
+
mainFile := filepath.Join(outputDir, "@goscript", "example.test", "unexportedreceiver", "main.gs.ts")
|
|
1225
|
+
mainContent, err := os.ReadFile(mainFile)
|
|
1226
|
+
if err != nil {
|
|
1227
|
+
t.Fatal(err.Error())
|
|
1228
|
+
}
|
|
1229
|
+
if !strings.Contains(string(mainContent), "$.pointerValue<any>(h).Value()") {
|
|
1230
|
+
t.Fatalf("cross-package unexported receiver method call was not dynamic:\n%s", string(mainContent))
|
|
1231
|
+
}
|
|
1232
|
+
if strings.Contains(string(mainContent), "dep.hidden.prototype.Value.call") {
|
|
1233
|
+
t.Fatalf("cross-package unexported receiver leaked through imported prototype:\n%s", string(mainContent))
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
|
|
953
1237
|
func TestCompilePackagesEmitsTypeOnlyLocalImports(t *testing.T) {
|
|
954
1238
|
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
955
1239
|
"go.mod": "module example.test/typeonlylocal\n\ngo 1.25.3\n",
|
|
@@ -1233,7 +1517,7 @@ func TestCompilePackagesEmitsStructMethodsAndPointerAssertions(t *testing.T) {
|
|
|
1233
1517
|
"Counter.prototype.Set.call(NewCounter(), 5)",
|
|
1234
1518
|
"let [, ok] = $.typeAssertTuple<Counter | $.VarRef<Counter> | null>(iface, { kind: $.TypeKind.Pointer, elemType: \"main.Counter\" })",
|
|
1235
1519
|
"\"Value\": { type: { kind: $.TypeKind.Basic, name: \"int\" }, tag: \"json:\\\"value\\\"\" }",
|
|
1236
|
-
"\"ID\": { kind: $.TypeKind.Basic, name: \"
|
|
1520
|
+
"\"ID\": { kind: $.TypeKind.Basic, name: \"int32\", typeName: \"main.ObjectID\" }",
|
|
1237
1521
|
} {
|
|
1238
1522
|
if !strings.Contains(text, want) {
|
|
1239
1523
|
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
@@ -1963,6 +2247,51 @@ func TestCompilePackagesLowersStringOrderingThroughRuntime(t *testing.T) {
|
|
|
1963
2247
|
}
|
|
1964
2248
|
}
|
|
1965
2249
|
|
|
2250
|
+
func TestCompilePackagesConvertsOverrideNamedStringToString(t *testing.T) {
|
|
2251
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
2252
|
+
"go.mod": "module example.test/reflecttag\n\ngo 1.25.3\n",
|
|
2253
|
+
"main.go": strings.Join([]string{
|
|
2254
|
+
"package main",
|
|
2255
|
+
"import (",
|
|
2256
|
+
" \"reflect\"",
|
|
2257
|
+
" \"strings\"",
|
|
2258
|
+
")",
|
|
2259
|
+
"func tagText(st reflect.Type) string {",
|
|
2260
|
+
" field := st.Field(0)",
|
|
2261
|
+
" tag := field.Tag.Get(\"yaml\")",
|
|
2262
|
+
" if tag == \"\" && strings.Index(string(field.Tag), \":\") < 0 {",
|
|
2263
|
+
" tag = string(field.Tag)",
|
|
2264
|
+
" }",
|
|
2265
|
+
" return tag",
|
|
2266
|
+
"}",
|
|
2267
|
+
"",
|
|
2268
|
+
}, "\n"),
|
|
2269
|
+
})
|
|
2270
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
2271
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
2272
|
+
if err != nil {
|
|
2273
|
+
t.Fatal(err.Error())
|
|
2274
|
+
}
|
|
2275
|
+
|
|
2276
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
2277
|
+
t.Fatal(err.Error())
|
|
2278
|
+
}
|
|
2279
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "reflecttag", "main.gs.ts")
|
|
2280
|
+
content, err := os.ReadFile(outputFile)
|
|
2281
|
+
if err != nil {
|
|
2282
|
+
t.Fatal(err.Error())
|
|
2283
|
+
}
|
|
2284
|
+
text := string(content)
|
|
2285
|
+
for _, want := range []string{
|
|
2286
|
+
`strings.Index(String(field.Tag), ":")`,
|
|
2287
|
+
`tag = String(field.Tag)`,
|
|
2288
|
+
} {
|
|
2289
|
+
if !strings.Contains(text, want) {
|
|
2290
|
+
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
|
|
1966
2295
|
func TestCompilePackagesEmitsInterfacesMethodValuesTypeSwitchesAndFunctionAssertions(t *testing.T) {
|
|
1967
2296
|
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
1968
2297
|
"go.mod": "module example.test/interfaces\n\ngo 1.25.3\n",
|
|
@@ -2293,6 +2622,63 @@ func TestCompilePackagesEmitsGenericMethodsAliasesAndDictionaries(t *testing.T)
|
|
|
2293
2622
|
}
|
|
2294
2623
|
}
|
|
2295
2624
|
|
|
2625
|
+
func TestCompilePackagesInfersGenericTypeArgsFromNamedArgument(t *testing.T) {
|
|
2626
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
2627
|
+
"go.mod": "module example.test/genericnamedarg\n\ngo 1.25.3\n",
|
|
2628
|
+
"main.go": strings.Join([]string{
|
|
2629
|
+
"package genericnamedarg",
|
|
2630
|
+
"type Source interface { Load() int }",
|
|
2631
|
+
"type auto struct{}",
|
|
2632
|
+
"func (a *auto) Load() int { return 7 }",
|
|
2633
|
+
"type key[T any] struct { name string }",
|
|
2634
|
+
"type entry struct { factory any }",
|
|
2635
|
+
"var entries = map[string]*entry{}",
|
|
2636
|
+
"func NewKey[T any](name string) key[T] {",
|
|
2637
|
+
" entries[name] = &entry{}",
|
|
2638
|
+
" return key[T]{name: name}",
|
|
2639
|
+
"}",
|
|
2640
|
+
"func Register[T any](key key[T], factory func() T) {",
|
|
2641
|
+
" entries[key.name].factory = factory",
|
|
2642
|
+
"}",
|
|
2643
|
+
"func Get[T any](key key[T]) T {",
|
|
2644
|
+
" f := entries[key.name].factory",
|
|
2645
|
+
" return f.(func() T)()",
|
|
2646
|
+
"}",
|
|
2647
|
+
"var loader = NewKey[Source](\"source\")",
|
|
2648
|
+
"func Use() int {",
|
|
2649
|
+
" Register(loader, func() Source { return &auto{} })",
|
|
2650
|
+
" src := Get(loader)",
|
|
2651
|
+
" return src.Load()",
|
|
2652
|
+
"}",
|
|
2653
|
+
"",
|
|
2654
|
+
}, "\n"),
|
|
2655
|
+
})
|
|
2656
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
2657
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
2658
|
+
if err != nil {
|
|
2659
|
+
t.Fatal(err.Error())
|
|
2660
|
+
}
|
|
2661
|
+
|
|
2662
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
2663
|
+
t.Fatal(err.Error())
|
|
2664
|
+
}
|
|
2665
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "genericnamedarg", "main.gs.ts")
|
|
2666
|
+
content, err := os.ReadFile(outputFile)
|
|
2667
|
+
if err != nil {
|
|
2668
|
+
t.Fatal(err.Error())
|
|
2669
|
+
}
|
|
2670
|
+
text := string(content)
|
|
2671
|
+
for _, want := range []string{
|
|
2672
|
+
"await Get({T: { type: \"genericnamedarg.Source\", zero: () => null, methods: {Load: (receiver: any, ...args: any[]) => receiver.Load(...args)} }}, $.markAsStructValue($.cloneStructValue(loader)))",
|
|
2673
|
+
"return await $.mustTypeAssert<(() => any | globalThis.Promise<any>) | null>(f, ({ kind: $.TypeKind.Function, params: [], results: [{ kind: $.TypeKind.Interface, methods: [] }] } as $.FunctionTypeInfo))!()",
|
|
2674
|
+
"return $.pointerValue<Exclude<Source, null>>(src).Load()",
|
|
2675
|
+
} {
|
|
2676
|
+
if !strings.Contains(text, want) {
|
|
2677
|
+
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
|
|
2296
2682
|
func TestCompilePackagesAttachesFunctionLiteralTypeInfo(t *testing.T) {
|
|
2297
2683
|
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
2298
2684
|
"go.mod": "module example.test/function-type-info\n\ngo 1.25.3\n",
|
|
@@ -2306,8 +2692,10 @@ func TestCompilePackagesAttachesFunctionLiteralTypeInfo(t *testing.T) {
|
|
|
2306
2692
|
" fn := func(value int) string {",
|
|
2307
2693
|
" return \"\"",
|
|
2308
2694
|
" }",
|
|
2695
|
+
" var zero Callback",
|
|
2309
2696
|
" var cb Callback = nil",
|
|
2310
2697
|
" _ = fn",
|
|
2698
|
+
" _ = zero",
|
|
2311
2699
|
" _ = cb",
|
|
2312
2700
|
" _ = call(fn)",
|
|
2313
2701
|
"}",
|
|
@@ -2332,6 +2720,8 @@ func TestCompilePackagesAttachesFunctionLiteralTypeInfo(t *testing.T) {
|
|
|
2332
2720
|
for _, want := range []string{
|
|
2333
2721
|
"export type Callback = ((value: number) => string | globalThis.Promise<string>) | null",
|
|
2334
2722
|
"export async function call(cb: ((value: number) => string | globalThis.Promise<string>) | null): globalThis.Promise<string> {\n\treturn await cb!(1)",
|
|
2723
|
+
"let zero: Callback | null = null as unknown as Callback | null",
|
|
2724
|
+
"let cb: Callback | null = (null as Callback | null)",
|
|
2335
2725
|
"$.functionValue((value: number): string => {",
|
|
2336
2726
|
"kind: $.TypeKind.Function",
|
|
2337
2727
|
"params: [{ kind: $.TypeKind.Basic, name: \"int\" }]",
|
|
@@ -2494,13 +2884,95 @@ func TestCompilePackagesPacksVariadicCallsInGeneratedSubpackage(t *testing.T) {
|
|
|
2494
2884
|
}
|
|
2495
2885
|
}
|
|
2496
2886
|
|
|
2497
|
-
func
|
|
2887
|
+
func TestCompilePackagesBoxesNumericVariadicInterfaceArgs(t *testing.T) {
|
|
2498
2888
|
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
2499
|
-
"go.mod": "module example.test/
|
|
2500
|
-
"
|
|
2501
|
-
"package
|
|
2502
|
-
"
|
|
2503
|
-
"",
|
|
2889
|
+
"go.mod": "module example.test/numeric-interface\n\ngo 1.25.3\n",
|
|
2890
|
+
"main.go": strings.Join([]string{
|
|
2891
|
+
"package numericinterface",
|
|
2892
|
+
"func collect(values ...any) {}",
|
|
2893
|
+
"func main() {",
|
|
2894
|
+
" var version int32 = 2",
|
|
2895
|
+
" collect(version, uint32(3))",
|
|
2896
|
+
"}",
|
|
2897
|
+
"",
|
|
2898
|
+
}, "\n"),
|
|
2899
|
+
})
|
|
2900
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
2901
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
2902
|
+
if err != nil {
|
|
2903
|
+
t.Fatal(err.Error())
|
|
2904
|
+
}
|
|
2905
|
+
|
|
2906
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
2907
|
+
t.Fatal(err.Error())
|
|
2908
|
+
}
|
|
2909
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "numeric-interface", "main.gs.ts")
|
|
2910
|
+
content, err := os.ReadFile(outputFile)
|
|
2911
|
+
if err != nil {
|
|
2912
|
+
t.Fatal(err.Error())
|
|
2913
|
+
}
|
|
2914
|
+
text := string(content)
|
|
2915
|
+
for _, want := range []string{
|
|
2916
|
+
"$.namedValueInterfaceValue<any>(version, \"int32\", {}, { kind: $.TypeKind.Basic, name: \"int32\" })",
|
|
2917
|
+
"$.namedValueInterfaceValue<any>($.uint(3, 32), \"uint32\", {}, { kind: $.TypeKind.Basic, name: \"uint32\" })",
|
|
2918
|
+
} {
|
|
2919
|
+
if !strings.Contains(text, want) {
|
|
2920
|
+
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
|
|
2925
|
+
func TestCompilePackagesAwaitsFmtWriterOverrides(t *testing.T) {
|
|
2926
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
2927
|
+
"go.mod": "module example.test/fmt-writer\n\ngo 1.25.3\n",
|
|
2928
|
+
"main.go": strings.Join([]string{
|
|
2929
|
+
"package fmtwriter",
|
|
2930
|
+
"import \"fmt\"",
|
|
2931
|
+
"type writer struct { buf []byte }",
|
|
2932
|
+
"func (w *writer) Write(p []byte) (int, error) {",
|
|
2933
|
+
" w.buf = append(w.buf, p...)",
|
|
2934
|
+
" return len(p), nil",
|
|
2935
|
+
"}",
|
|
2936
|
+
"func Use(w *writer) error {",
|
|
2937
|
+
" _, err := fmt.Fprintf(w, \"%s\", \"ok\")",
|
|
2938
|
+
" return err",
|
|
2939
|
+
"}",
|
|
2940
|
+
"",
|
|
2941
|
+
}, "\n"),
|
|
2942
|
+
})
|
|
2943
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
2944
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
2945
|
+
if err != nil {
|
|
2946
|
+
t.Fatal(err.Error())
|
|
2947
|
+
}
|
|
2948
|
+
|
|
2949
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
2950
|
+
t.Fatal(err.Error())
|
|
2951
|
+
}
|
|
2952
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "fmt-writer", "main.gs.ts")
|
|
2953
|
+
content, err := os.ReadFile(outputFile)
|
|
2954
|
+
if err != nil {
|
|
2955
|
+
t.Fatal(err.Error())
|
|
2956
|
+
}
|
|
2957
|
+
text := string(content)
|
|
2958
|
+
for _, want := range []string{
|
|
2959
|
+
"export async function Use",
|
|
2960
|
+
"await fmt.Fprintf(",
|
|
2961
|
+
"return err",
|
|
2962
|
+
} {
|
|
2963
|
+
if !strings.Contains(text, want) {
|
|
2964
|
+
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
2965
|
+
}
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
|
|
2969
|
+
func TestCompilePackagesImportsSelectedExternalFieldTypes(t *testing.T) {
|
|
2970
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
2971
|
+
"go.mod": "module example.test/selected-field-import\n\ngo 1.25.3\n",
|
|
2972
|
+
"dep/dep.go": strings.Join([]string{
|
|
2973
|
+
"package dep",
|
|
2974
|
+
"type URL struct { Path string }",
|
|
2975
|
+
"",
|
|
2504
2976
|
}, "\n"),
|
|
2505
2977
|
"api/api.go": strings.Join([]string{
|
|
2506
2978
|
"package api",
|
|
@@ -2887,6 +3359,468 @@ func TestCompilePackagesEmitsAsyncChannelsSelectAndDefer(t *testing.T) {
|
|
|
2887
3359
|
}
|
|
2888
3360
|
}
|
|
2889
3361
|
|
|
3362
|
+
func TestCompilePackagesPropagatesAsyncGenericInterfaceMethods(t *testing.T) {
|
|
3363
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
3364
|
+
"go.mod": "module example.test/genericasynciface\n\ngo 1.25.3\n",
|
|
3365
|
+
"main.go": strings.Join([]string{
|
|
3366
|
+
"package genericasynciface",
|
|
3367
|
+
"import \"context\"",
|
|
3368
|
+
"type Watchable[T comparable] interface {",
|
|
3369
|
+
" Get() T",
|
|
3370
|
+
" Wait(ctx context.Context, old T) T",
|
|
3371
|
+
"}",
|
|
3372
|
+
"type Box[T comparable] struct { ch chan T; val T }",
|
|
3373
|
+
"func (b *Box[T]) Get() T { return b.val }",
|
|
3374
|
+
"func (b *Box[T]) Wait(ctx context.Context, old T) T {",
|
|
3375
|
+
" select {",
|
|
3376
|
+
" case v := <-b.ch:",
|
|
3377
|
+
" return v",
|
|
3378
|
+
" case <-ctx.Done():",
|
|
3379
|
+
" return old",
|
|
3380
|
+
" }",
|
|
3381
|
+
"}",
|
|
3382
|
+
"func Use(ctx context.Context, w Watchable[int], old int) int {",
|
|
3383
|
+
" return w.Wait(ctx, old)",
|
|
3384
|
+
"}",
|
|
3385
|
+
"",
|
|
3386
|
+
}, "\n"),
|
|
3387
|
+
})
|
|
3388
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
3389
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
3390
|
+
if err != nil {
|
|
3391
|
+
t.Fatal(err.Error())
|
|
3392
|
+
}
|
|
3393
|
+
|
|
3394
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
3395
|
+
t.Fatal(err.Error())
|
|
3396
|
+
}
|
|
3397
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "genericasynciface", "main.gs.ts")
|
|
3398
|
+
content, err := os.ReadFile(outputFile)
|
|
3399
|
+
if err != nil {
|
|
3400
|
+
t.Fatal(err.Error())
|
|
3401
|
+
}
|
|
3402
|
+
text := string(content)
|
|
3403
|
+
for _, want := range []string{
|
|
3404
|
+
"Wait(ctx: context.Context | null, old: any): any | globalThis.Promise<any>",
|
|
3405
|
+
"public async Wait(ctx: context.Context | null, old: any): globalThis.Promise<any>",
|
|
3406
|
+
"return (await $.pointerValue<Exclude<Watchable, null>>(w).Wait(ctx, old) as number)",
|
|
3407
|
+
} {
|
|
3408
|
+
if !strings.Contains(text, want) {
|
|
3409
|
+
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
3410
|
+
}
|
|
3411
|
+
}
|
|
3412
|
+
}
|
|
3413
|
+
|
|
3414
|
+
func TestCompilePackagesPropagatesAsyncAnonymousInterfaceMethods(t *testing.T) {
|
|
3415
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
3416
|
+
"go.mod": "module example.test/anonymousasynciface\n\ngo 1.25.3\n",
|
|
3417
|
+
"main.go": strings.Join([]string{
|
|
3418
|
+
"package anonymousasynciface",
|
|
3419
|
+
"import \"context\"",
|
|
3420
|
+
"type Snapshot int",
|
|
3421
|
+
"type Watcher struct { ch chan Snapshot }",
|
|
3422
|
+
"func (w *Watcher) WaitValueChange(ctx context.Context, old Snapshot, errCh <-chan error) (Snapshot, error) {",
|
|
3423
|
+
" select {",
|
|
3424
|
+
" case v := <-w.ch:",
|
|
3425
|
+
" return v, nil",
|
|
3426
|
+
" case err := <-errCh:",
|
|
3427
|
+
" return old, err",
|
|
3428
|
+
" case <-ctx.Done():",
|
|
3429
|
+
" return old, ctx.Err()",
|
|
3430
|
+
" }",
|
|
3431
|
+
"}",
|
|
3432
|
+
"func Use(ctx context.Context, w interface {",
|
|
3433
|
+
" WaitValueChange(context.Context, Snapshot, <-chan error) (Snapshot, error)",
|
|
3434
|
+
"}, old Snapshot) (Snapshot, error) {",
|
|
3435
|
+
" return w.WaitValueChange(ctx, old, nil)",
|
|
3436
|
+
"}",
|
|
3437
|
+
"",
|
|
3438
|
+
}, "\n"),
|
|
3439
|
+
})
|
|
3440
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
3441
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
3442
|
+
if err != nil {
|
|
3443
|
+
t.Fatal(err.Error())
|
|
3444
|
+
}
|
|
3445
|
+
|
|
3446
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
3447
|
+
t.Fatal(err.Error())
|
|
3448
|
+
}
|
|
3449
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "anonymousasynciface", "main.gs.ts")
|
|
3450
|
+
content, err := os.ReadFile(outputFile)
|
|
3451
|
+
if err != nil {
|
|
3452
|
+
t.Fatal(err.Error())
|
|
3453
|
+
}
|
|
3454
|
+
text := string(content)
|
|
3455
|
+
for _, want := range []string{
|
|
3456
|
+
"export async function Use(ctx: context.Context | null, w: any, old: Snapshot): globalThis.Promise<[Snapshot, $.GoError]>",
|
|
3457
|
+
"return await $.pointerValue<any>(w).WaitValueChange(ctx, old, null)",
|
|
3458
|
+
} {
|
|
3459
|
+
if !strings.Contains(text, want) {
|
|
3460
|
+
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
3461
|
+
}
|
|
3462
|
+
}
|
|
3463
|
+
}
|
|
3464
|
+
|
|
3465
|
+
func TestCompilePackagesPropagatesAsyncThroughInstantiatedNamedInterface(t *testing.T) {
|
|
3466
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
3467
|
+
"go.mod": "module example.test/instantiatedasynciface\n\ngo 1.25.3\n",
|
|
3468
|
+
"main.go": strings.Join([]string{
|
|
3469
|
+
"package instantiatedasynciface",
|
|
3470
|
+
"import \"context\"",
|
|
3471
|
+
"type Snapshot int",
|
|
3472
|
+
"type Watchable[T any] interface {",
|
|
3473
|
+
" WaitValueChange(context.Context, T, <-chan error) (T, error)",
|
|
3474
|
+
"}",
|
|
3475
|
+
"type Container[T any] struct { ch chan T }",
|
|
3476
|
+
"func (c *Container[T]) WaitValueChange(ctx context.Context, old T, errCh <-chan error) (T, error) {",
|
|
3477
|
+
" select {",
|
|
3478
|
+
" case v := <-c.ch:",
|
|
3479
|
+
" return v, nil",
|
|
3480
|
+
" case err := <-errCh:",
|
|
3481
|
+
" return old, err",
|
|
3482
|
+
" case <-ctx.Done():",
|
|
3483
|
+
" return old, ctx.Err()",
|
|
3484
|
+
" }",
|
|
3485
|
+
"}",
|
|
3486
|
+
"func Bind(w Watchable[Snapshot]) {}",
|
|
3487
|
+
"func Use(ctx context.Context, w interface {",
|
|
3488
|
+
" WaitValueChange(context.Context, Snapshot, <-chan error) (Snapshot, error)",
|
|
3489
|
+
"}, old Snapshot) (Snapshot, error) {",
|
|
3490
|
+
" return w.WaitValueChange(ctx, old, nil)",
|
|
3491
|
+
"}",
|
|
3492
|
+
"",
|
|
3493
|
+
}, "\n"),
|
|
3494
|
+
})
|
|
3495
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
3496
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
3497
|
+
if err != nil {
|
|
3498
|
+
t.Fatal(err.Error())
|
|
3499
|
+
}
|
|
3500
|
+
|
|
3501
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
3502
|
+
t.Fatal(err.Error())
|
|
3503
|
+
}
|
|
3504
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "instantiatedasynciface", "main.gs.ts")
|
|
3505
|
+
content, err := os.ReadFile(outputFile)
|
|
3506
|
+
if err != nil {
|
|
3507
|
+
t.Fatal(err.Error())
|
|
3508
|
+
}
|
|
3509
|
+
text := string(content)
|
|
3510
|
+
for _, want := range []string{
|
|
3511
|
+
"export async function Use(ctx: context.Context | null, w: any, old: Snapshot): globalThis.Promise<[Snapshot, $.GoError]>",
|
|
3512
|
+
"return await $.pointerValue<any>(w).WaitValueChange(ctx, old, null)",
|
|
3513
|
+
} {
|
|
3514
|
+
if !strings.Contains(text, want) {
|
|
3515
|
+
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
3516
|
+
}
|
|
3517
|
+
}
|
|
3518
|
+
}
|
|
3519
|
+
|
|
3520
|
+
func TestCompilePackagesDoesNotAwaitUnmarkedAnonymousInterfaceMethod(t *testing.T) {
|
|
3521
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
3522
|
+
"go.mod": "module example.test/anonymousifaceawait\n\ngo 1.25.3\n",
|
|
3523
|
+
"main.go": strings.Join([]string{
|
|
3524
|
+
"package anonymousifaceawait",
|
|
3525
|
+
"import \"context\"",
|
|
3526
|
+
"type Snapshot int",
|
|
3527
|
+
"func Use(ctx context.Context, w interface {",
|
|
3528
|
+
" WaitValueChange(context.Context, Snapshot, <-chan error) (Snapshot, error)",
|
|
3529
|
+
"}, ch <-chan struct{}, old Snapshot) (Snapshot, error) {",
|
|
3530
|
+
" select {",
|
|
3531
|
+
" case <-ch:",
|
|
3532
|
+
" default:",
|
|
3533
|
+
" }",
|
|
3534
|
+
" return w.WaitValueChange(ctx, old, nil)",
|
|
3535
|
+
"}",
|
|
3536
|
+
"",
|
|
3537
|
+
}, "\n"),
|
|
3538
|
+
})
|
|
3539
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
3540
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
3541
|
+
if err != nil {
|
|
3542
|
+
t.Fatal(err.Error())
|
|
3543
|
+
}
|
|
3544
|
+
|
|
3545
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
3546
|
+
t.Fatal(err.Error())
|
|
3547
|
+
}
|
|
3548
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "anonymousifaceawait", "main.gs.ts")
|
|
3549
|
+
content, err := os.ReadFile(outputFile)
|
|
3550
|
+
if err != nil {
|
|
3551
|
+
t.Fatal(err.Error())
|
|
3552
|
+
}
|
|
3553
|
+
text := string(content)
|
|
3554
|
+
if strings.Contains(text, "return await $.pointerValue<any>(w).WaitValueChange(ctx, old, null)") {
|
|
3555
|
+
t.Fatalf("anonymous interface method call without an async implementation was awaited:\n%s", text)
|
|
3556
|
+
}
|
|
3557
|
+
}
|
|
3558
|
+
|
|
3559
|
+
func TestCompilePackagesDoesNotInheritAsyncIntoSyncFunctionLiteral(t *testing.T) {
|
|
3560
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
3561
|
+
"go.mod": "module example.test/syncfunclit\n\ngo 1.25.3\n",
|
|
3562
|
+
"main.go": strings.Join([]string{
|
|
3563
|
+
"package syncfunclit",
|
|
3564
|
+
"type Directive interface{ GetDirective() any }",
|
|
3565
|
+
"type Bridge struct{ keep func(Directive) (bool, error) }",
|
|
3566
|
+
"func NewBridge(keep func(Directive) (bool, error)) *Bridge { return &Bridge{keep: keep} }",
|
|
3567
|
+
"func Execute(ch <-chan struct{}) error {",
|
|
3568
|
+
" select {",
|
|
3569
|
+
" case <-ch:",
|
|
3570
|
+
" default:",
|
|
3571
|
+
" }",
|
|
3572
|
+
" _ = NewBridge(func(di Directive) (bool, error) {",
|
|
3573
|
+
" switch di.GetDirective().(type) {",
|
|
3574
|
+
" default:",
|
|
3575
|
+
" return true, nil",
|
|
3576
|
+
" }",
|
|
3577
|
+
" })",
|
|
3578
|
+
" return nil",
|
|
3579
|
+
"}",
|
|
3580
|
+
"",
|
|
3581
|
+
}, "\n"),
|
|
3582
|
+
})
|
|
3583
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
3584
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
3585
|
+
if err != nil {
|
|
3586
|
+
t.Fatal(err.Error())
|
|
3587
|
+
}
|
|
3588
|
+
|
|
3589
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
3590
|
+
t.Fatal(err.Error())
|
|
3591
|
+
}
|
|
3592
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "syncfunclit", "main.gs.ts")
|
|
3593
|
+
content, err := os.ReadFile(outputFile)
|
|
3594
|
+
if err != nil {
|
|
3595
|
+
t.Fatal(err.Error())
|
|
3596
|
+
}
|
|
3597
|
+
text := string(content)
|
|
3598
|
+
if strings.Contains(text, "await $.pointerValue<Exclude<Directive, null>>(di).GetDirective()") {
|
|
3599
|
+
t.Fatalf("sync function literal inherited async await:\n%s", text)
|
|
3600
|
+
}
|
|
3601
|
+
}
|
|
3602
|
+
|
|
3603
|
+
func TestCompilePackagesMarksRangeFuncAsyncWhenBodyAwaits(t *testing.T) {
|
|
3604
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
3605
|
+
"go.mod": "module example.test/rangefuncawaitbody\n\ngo 1.25.3\n",
|
|
3606
|
+
"main.go": strings.Join([]string{
|
|
3607
|
+
"package rangefuncawaitbody",
|
|
3608
|
+
"type Item struct{}",
|
|
3609
|
+
"func (i *Item) Release(ch <-chan struct{}) {",
|
|
3610
|
+
" select {",
|
|
3611
|
+
" case <-ch:",
|
|
3612
|
+
" default:",
|
|
3613
|
+
" }",
|
|
3614
|
+
"}",
|
|
3615
|
+
"func Back(items []Item) func(func(int, Item) bool) {",
|
|
3616
|
+
" return func(yield func(int, Item) bool) {",
|
|
3617
|
+
" for i := len(items)-1; i >= 0; i-- {",
|
|
3618
|
+
" if !yield(i, items[i]) { return }",
|
|
3619
|
+
" }",
|
|
3620
|
+
" }",
|
|
3621
|
+
"}",
|
|
3622
|
+
"func Use(ch <-chan struct{}, items []Item) {",
|
|
3623
|
+
" defer func() {",
|
|
3624
|
+
" for _, v := range Back(items) {",
|
|
3625
|
+
" v.Release(ch)",
|
|
3626
|
+
" }",
|
|
3627
|
+
" }()",
|
|
3628
|
+
"}",
|
|
3629
|
+
"",
|
|
3630
|
+
}, "\n"),
|
|
3631
|
+
})
|
|
3632
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
3633
|
+
comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
|
|
3634
|
+
if err != nil {
|
|
3635
|
+
t.Fatal(err.Error())
|
|
3636
|
+
}
|
|
3637
|
+
|
|
3638
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
3639
|
+
t.Fatal(err.Error())
|
|
3640
|
+
}
|
|
3641
|
+
outputFile := filepath.Join(outputDir, "@goscript", "example.test", "rangefuncawaitbody", "main.gs.ts")
|
|
3642
|
+
content, err := os.ReadFile(outputFile)
|
|
3643
|
+
if err != nil {
|
|
3644
|
+
t.Fatal(err.Error())
|
|
3645
|
+
}
|
|
3646
|
+
text := string(content)
|
|
3647
|
+
for _, want := range []string{
|
|
3648
|
+
";await (async () => {",
|
|
3649
|
+
"await v.value.Release(ch)",
|
|
3650
|
+
} {
|
|
3651
|
+
if !strings.Contains(text, want) {
|
|
3652
|
+
t.Fatalf("missing %q in generated output:\n%s", want, text)
|
|
3653
|
+
}
|
|
3654
|
+
}
|
|
3655
|
+
}
|
|
3656
|
+
|
|
3657
|
+
func TestCompilePackagesPropagatesImportedAsyncGenericInterfaceMethods(t *testing.T) {
|
|
3658
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
3659
|
+
"go.mod": "module example.test/importedgenericasynciface\n\ngo 1.25.3\n",
|
|
3660
|
+
"dep/dep.go": strings.Join([]string{
|
|
3661
|
+
"package dep",
|
|
3662
|
+
"import \"context\"",
|
|
3663
|
+
"type Watchable[T comparable] interface {",
|
|
3664
|
+
" Get() T",
|
|
3665
|
+
" Wait(ctx context.Context, old T) T",
|
|
3666
|
+
"}",
|
|
3667
|
+
"type Box[T comparable] struct { ch chan T; val T }",
|
|
3668
|
+
"func (b *Box[T]) Get() T { return b.val }",
|
|
3669
|
+
"func (b *Box[T]) Wait(ctx context.Context, old T) T {",
|
|
3670
|
+
" select {",
|
|
3671
|
+
" case v := <-b.ch:",
|
|
3672
|
+
" return v",
|
|
3673
|
+
" case <-ctx.Done():",
|
|
3674
|
+
" return old",
|
|
3675
|
+
" }",
|
|
3676
|
+
"}",
|
|
3677
|
+
"",
|
|
3678
|
+
}, "\n"),
|
|
3679
|
+
"main.go": strings.Join([]string{
|
|
3680
|
+
"package importedgenericasynciface",
|
|
3681
|
+
"import (",
|
|
3682
|
+
" \"context\"",
|
|
3683
|
+
" \"example.test/importedgenericasynciface/dep\"",
|
|
3684
|
+
")",
|
|
3685
|
+
"func Use(ctx context.Context, w dep.Watchable[int], old int) int {",
|
|
3686
|
+
" return w.Wait(ctx, old)",
|
|
3687
|
+
"}",
|
|
3688
|
+
"",
|
|
3689
|
+
}, "\n"),
|
|
3690
|
+
})
|
|
3691
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
3692
|
+
service := NewCompileService()
|
|
3693
|
+
_, err := service.Compile(context.Background(), &CompileRequest{
|
|
3694
|
+
Patterns: []string{".", "./dep"},
|
|
3695
|
+
Dir: moduleDir,
|
|
3696
|
+
OutputPath: outputDir,
|
|
3697
|
+
DependencyMode: DependencyModeAll,
|
|
3698
|
+
RuntimeEmissionMode: RuntimeEmissionModeEmit,
|
|
3699
|
+
})
|
|
3700
|
+
if err != nil {
|
|
3701
|
+
t.Fatal(err.Error())
|
|
3702
|
+
}
|
|
3703
|
+
depOutputFile := filepath.Join(outputDir, "@goscript", "example.test", "importedgenericasynciface", "dep", "dep.gs.ts")
|
|
3704
|
+
depContent, err := os.ReadFile(depOutputFile)
|
|
3705
|
+
if err != nil {
|
|
3706
|
+
t.Fatal(err.Error())
|
|
3707
|
+
}
|
|
3708
|
+
depText := string(depContent)
|
|
3709
|
+
for _, want := range []string{
|
|
3710
|
+
"Wait(ctx: context.Context | null, old: any): any | globalThis.Promise<any>",
|
|
3711
|
+
"public async Wait(ctx: context.Context | null, old: any): globalThis.Promise<any>",
|
|
3712
|
+
} {
|
|
3713
|
+
if !strings.Contains(depText, want) {
|
|
3714
|
+
t.Fatalf("missing %q in generated dep output:\n%s", want, depText)
|
|
3715
|
+
}
|
|
3716
|
+
}
|
|
3717
|
+
|
|
3718
|
+
mainOutputFile := filepath.Join(outputDir, "@goscript", "example.test", "importedgenericasynciface", "main.gs.ts")
|
|
3719
|
+
mainContent, err := os.ReadFile(mainOutputFile)
|
|
3720
|
+
if err != nil {
|
|
3721
|
+
t.Fatal(err.Error())
|
|
3722
|
+
}
|
|
3723
|
+
mainText := string(mainContent)
|
|
3724
|
+
if want := "return (await $.pointerValue<Exclude<dep.Watchable, null>>(w).Wait(ctx, old) as number)"; !strings.Contains(mainText, want) {
|
|
3725
|
+
t.Fatalf("missing %q in generated main output:\n%s", want, mainText)
|
|
3726
|
+
}
|
|
3727
|
+
}
|
|
3728
|
+
|
|
3729
|
+
func TestCompilePackagesPropagatesAsyncInterfaceMethodsFromTestImports(t *testing.T) {
|
|
3730
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
3731
|
+
"go.mod": "module example.test/testimportasynciface\n\ngo 1.25.3\n",
|
|
3732
|
+
"iface/provider.go": strings.Join([]string{
|
|
3733
|
+
"package iface",
|
|
3734
|
+
"import \"context\"",
|
|
3735
|
+
"type Provider interface {",
|
|
3736
|
+
" Create(context.Context) (string, error)",
|
|
3737
|
+
"}",
|
|
3738
|
+
"",
|
|
3739
|
+
}, "\n"),
|
|
3740
|
+
"impl/provider.go": strings.Join([]string{
|
|
3741
|
+
"package impl",
|
|
3742
|
+
"import (",
|
|
3743
|
+
" \"context\"",
|
|
3744
|
+
" \"example.test/testimportasynciface/iface\"",
|
|
3745
|
+
")",
|
|
3746
|
+
"type Provider struct { ch chan string }",
|
|
3747
|
+
"func NewProvider() iface.Provider {",
|
|
3748
|
+
" return &Provider{ch: make(chan string, 1)}",
|
|
3749
|
+
"}",
|
|
3750
|
+
"func (p *Provider) Create(ctx context.Context) (string, error) {",
|
|
3751
|
+
" select {",
|
|
3752
|
+
" case p.ch <- \"ok\":",
|
|
3753
|
+
" case <-ctx.Done():",
|
|
3754
|
+
" return \"\", ctx.Err()",
|
|
3755
|
+
" }",
|
|
3756
|
+
" return <-p.ch, nil",
|
|
3757
|
+
"}",
|
|
3758
|
+
"",
|
|
3759
|
+
}, "\n"),
|
|
3760
|
+
"use.go": strings.Join([]string{
|
|
3761
|
+
"package testimportasynciface",
|
|
3762
|
+
"import (",
|
|
3763
|
+
" \"context\"",
|
|
3764
|
+
" \"example.test/testimportasynciface/iface\"",
|
|
3765
|
+
")",
|
|
3766
|
+
"func Use(ctx context.Context, p iface.Provider) (string, error) {",
|
|
3767
|
+
" return p.Create(ctx)",
|
|
3768
|
+
"}",
|
|
3769
|
+
"",
|
|
3770
|
+
}, "\n"),
|
|
3771
|
+
"use_test.go": strings.Join([]string{
|
|
3772
|
+
"package testimportasynciface",
|
|
3773
|
+
"import (",
|
|
3774
|
+
" \"context\"",
|
|
3775
|
+
" \"testing\"",
|
|
3776
|
+
" \"example.test/testimportasynciface/impl\"",
|
|
3777
|
+
")",
|
|
3778
|
+
"func TestUse(t *testing.T) {",
|
|
3779
|
+
" p := impl.NewProvider()",
|
|
3780
|
+
" got, err := p.Create(context.Background())",
|
|
3781
|
+
" if err != nil || got != \"ok\" {",
|
|
3782
|
+
" t.Fatal(got, err)",
|
|
3783
|
+
" }",
|
|
3784
|
+
"}",
|
|
3785
|
+
"",
|
|
3786
|
+
}, "\n"),
|
|
3787
|
+
})
|
|
3788
|
+
outputDir := filepath.Join(t.TempDir(), "output")
|
|
3789
|
+
service := NewCompileService()
|
|
3790
|
+
_, err := service.Compile(context.Background(), &CompileRequest{
|
|
3791
|
+
Patterns: []string{"."},
|
|
3792
|
+
Dir: moduleDir,
|
|
3793
|
+
OutputPath: outputDir,
|
|
3794
|
+
DependencyMode: DependencyModeAll,
|
|
3795
|
+
RuntimeEmissionMode: RuntimeEmissionModeEmit,
|
|
3796
|
+
Tests: true,
|
|
3797
|
+
AllDependencies: true,
|
|
3798
|
+
})
|
|
3799
|
+
if err != nil {
|
|
3800
|
+
t.Fatal(err.Error())
|
|
3801
|
+
}
|
|
3802
|
+
|
|
3803
|
+
ifaceOutputFile := filepath.Join(outputDir, "@goscript", "example.test", "testimportasynciface", "iface", "provider.gs.ts")
|
|
3804
|
+
ifaceContent, err := os.ReadFile(ifaceOutputFile)
|
|
3805
|
+
if err != nil {
|
|
3806
|
+
t.Fatal(err.Error())
|
|
3807
|
+
}
|
|
3808
|
+
ifaceText := string(ifaceContent)
|
|
3809
|
+
if want := "Create(_p0: context.Context | null): [string, $.GoError] | globalThis.Promise<[string, $.GoError]>"; !strings.Contains(ifaceText, want) {
|
|
3810
|
+
t.Fatalf("test-import implementation did not color interface method async:\n%s", ifaceText)
|
|
3811
|
+
}
|
|
3812
|
+
|
|
3813
|
+
testOutputFile := filepath.Join(outputDir, "@goscript", "example.test", "testimportasynciface", "use_test.gs.ts")
|
|
3814
|
+
testContent, err := os.ReadFile(testOutputFile)
|
|
3815
|
+
if err != nil {
|
|
3816
|
+
t.Fatal(err.Error())
|
|
3817
|
+
}
|
|
3818
|
+
testText := string(testContent)
|
|
3819
|
+
if want := "let [got, err] = await $.pointerValue<Exclude<iface.Provider, null>>(p).Create(context.Background())"; !strings.Contains(testText, want) {
|
|
3820
|
+
t.Fatalf("test package call was not awaited:\n%s", testText)
|
|
3821
|
+
}
|
|
3822
|
+
}
|
|
3823
|
+
|
|
2890
3824
|
func TestCompilePackagesMarksSelectReturningIfElseCasesUnreachable(t *testing.T) {
|
|
2891
3825
|
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
2892
3826
|
"go.mod": "module example.test/select-if-else\n\ngo 1.25.3\n",
|
|
@@ -3389,7 +4323,7 @@ func TestCompilePackagesLowersUnaryBitwiseComplement(t *testing.T) {
|
|
|
3389
4323
|
}
|
|
3390
4324
|
text := string(content)
|
|
3391
4325
|
for _, want := range []string{
|
|
3392
|
-
"mask = mask & ~(3)",
|
|
4326
|
+
"mask = mask & ~((3))",
|
|
3393
4327
|
"$.println(~value, value & ~(3), mask, 0o700)",
|
|
3394
4328
|
} {
|
|
3395
4329
|
if !strings.Contains(text, want) {
|