goscript 0.2.1 → 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/runner.go +98 -0
- package/compiler/gotest/runner_test.go +45 -0
- package/compiler/gotest/testdata/browserapi/browserapi_test.go +36 -0
- package/compiler/lowering.go +227 -11
- package/compiler/override-registry_test.go +50 -0
- package/compiler/protobuf-ts-binding.go +155 -7
- package/compiler/protobuf-ts-binding_test.go +116 -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 +477 -16
- 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/aes/index.d.ts +15 -0
- package/dist/gs/crypto/aes/index.js +57 -0
- package/dist/gs/crypto/aes/index.js.map +1 -0
- package/dist/gs/crypto/cipher/index.d.ts +41 -0
- package/dist/gs/crypto/cipher/index.js +255 -0
- package/dist/gs/crypto/cipher/index.js.map +1 -0
- 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/chacha20poly1305/index.d.ts +31 -0
- package/dist/gs/golang.org/x/crypto/chacha20poly1305/index.js +117 -0
- package/dist/gs/golang.org/x/crypto/chacha20poly1305/index.js.map +1 -0
- 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/io/io.js +18 -2
- package/dist/gs/io/io.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/debug/index.js +2 -1
- package/dist/gs/runtime/debug/index.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/go.mod +2 -2
- package/go.sum +2 -0
- package/gs/builtin/builtin.ts +11 -14
- package/gs/builtin/defer.ts +2 -2
- package/gs/builtin/hostio.test.ts +8 -3
- package/gs/builtin/hostio.ts +5 -7
- 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/aes/index.test.ts +120 -0
- package/gs/crypto/aes/index.ts +76 -0
- package/gs/crypto/cipher/index.ts +345 -0
- package/gs/crypto/cipher/meta.json +6 -0
- 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/chacha20poly1305/index.test.ts +91 -0
- package/gs/golang.org/x/crypto/chacha20poly1305/index.ts +245 -0
- 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/io/io.test.ts +56 -1
- package/gs/io/io.ts +19 -2
- 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/debug/index.test.ts +32 -4
- package/gs/runtime/debug/index.ts +5 -2
- 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 +13 -5
|
@@ -141,6 +141,10 @@ func (r *Runner) runPackageTools(
|
|
|
141
141
|
if len(indexes) == 0 {
|
|
142
142
|
return
|
|
143
143
|
}
|
|
144
|
+
if phase := materializeRuntimeModuleShims(req, outputRoots); phase.Failed() {
|
|
145
|
+
markRuntimeFailures(result, indexes, OwnerTestRunner, phase.Error)
|
|
146
|
+
return
|
|
147
|
+
}
|
|
144
148
|
if len(indexes) == 1 {
|
|
145
149
|
r.runPackageTypeCheckAndRuntime(ctx, req, workspace, result, outputRoots, indexes[0])
|
|
146
150
|
return
|
|
@@ -286,6 +290,100 @@ func (r *Runner) runPackageRuntimes(
|
|
|
286
290
|
r.runPackageRuntimesIndividually(ctx, req, workspace, result, outputRoots, indexes)
|
|
287
291
|
}
|
|
288
292
|
|
|
293
|
+
func materializeRuntimeModuleShims(req *normalizedRequest, outputRoots []string) tsworkspace.Result {
|
|
294
|
+
if req.RuntimeBackend != RuntimeBackendBun {
|
|
295
|
+
return tsworkspace.Result{Phase: tsworkspace.PhaseWorkspace}
|
|
296
|
+
}
|
|
297
|
+
seen := make(map[string]bool)
|
|
298
|
+
shimRoots := runtimeModuleShimRoots(req, outputRoots)
|
|
299
|
+
for _, outputRoot := range outputRoots {
|
|
300
|
+
if outputRoot == "" {
|
|
301
|
+
continue
|
|
302
|
+
}
|
|
303
|
+
root := filepath.Join(outputRoot, "@goscript")
|
|
304
|
+
if _, err := os.Stat(root); err != nil {
|
|
305
|
+
if os.IsNotExist(err) {
|
|
306
|
+
continue
|
|
307
|
+
}
|
|
308
|
+
return tsworkspace.Result{Phase: tsworkspace.PhaseWorkspace, Error: errors.Wrap(err, "stat GoScript runtime output root").Error()}
|
|
309
|
+
}
|
|
310
|
+
err := filepath.WalkDir(root, func(path string, entry os.DirEntry, err error) error {
|
|
311
|
+
if err != nil {
|
|
312
|
+
return err
|
|
313
|
+
}
|
|
314
|
+
if entry.IsDir() || filepath.Ext(path) != ".ts" {
|
|
315
|
+
return nil
|
|
316
|
+
}
|
|
317
|
+
rel, err := filepath.Rel(root, path)
|
|
318
|
+
if err != nil {
|
|
319
|
+
return err
|
|
320
|
+
}
|
|
321
|
+
shimRel := filepath.Join("node_modules", "@goscript", strings.TrimSuffix(rel, ".ts")+".js")
|
|
322
|
+
for _, shimRoot := range shimRoots {
|
|
323
|
+
shimPath := filepath.Join(shimRoot, shimRel)
|
|
324
|
+
seenKey := shimPath
|
|
325
|
+
if seen[seenKey] {
|
|
326
|
+
continue
|
|
327
|
+
}
|
|
328
|
+
seen[seenKey] = true
|
|
329
|
+
shimDir := filepath.Dir(shimPath)
|
|
330
|
+
importPath, err := filepath.Rel(shimDir, path)
|
|
331
|
+
if err != nil {
|
|
332
|
+
return err
|
|
333
|
+
}
|
|
334
|
+
importPath = filepath.ToSlash(importPath)
|
|
335
|
+
if !strings.HasPrefix(importPath, ".") {
|
|
336
|
+
importPath = "./" + importPath
|
|
337
|
+
}
|
|
338
|
+
if err := writeRuntimeModuleShim(shimPath, "export * from "+strconv.Quote(importPath)+"\n"); err != nil {
|
|
339
|
+
return err
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return nil
|
|
343
|
+
})
|
|
344
|
+
if err != nil {
|
|
345
|
+
return tsworkspace.Result{Phase: tsworkspace.PhaseWorkspace, Error: errors.Wrap(err, "materialize GoScript runtime module shims").Error()}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return tsworkspace.Result{Phase: tsworkspace.PhaseWorkspace}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
func runtimeModuleShimRoots(req *normalizedRequest, outputRoots []string) []string {
|
|
352
|
+
seen := make(map[string]bool)
|
|
353
|
+
var roots []string
|
|
354
|
+
for _, root := range append([]string{req.WorkDir}, outputRoots...) {
|
|
355
|
+
if root == "" {
|
|
356
|
+
continue
|
|
357
|
+
}
|
|
358
|
+
clean := filepath.Clean(root)
|
|
359
|
+
if seen[clean] {
|
|
360
|
+
continue
|
|
361
|
+
}
|
|
362
|
+
seen[clean] = true
|
|
363
|
+
roots = append(roots, clean)
|
|
364
|
+
}
|
|
365
|
+
return roots
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
func writeRuntimeModuleShim(path string, data string) error {
|
|
369
|
+
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
370
|
+
return err
|
|
371
|
+
}
|
|
372
|
+
return os.WriteFile(path, []byte(data), 0o644)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
func markRuntimeFailures(result *Result, indexes []int, owner Owner, message string) {
|
|
376
|
+
for _, idx := range indexes {
|
|
377
|
+
if idx < 0 || idx >= len(result.Packages) {
|
|
378
|
+
continue
|
|
379
|
+
}
|
|
380
|
+
result.Packages[idx].Action = ActionFail
|
|
381
|
+
result.Packages[idx].Owner = owner
|
|
382
|
+
result.Packages[idx].Phases.Runtime = PhaseStatusFail
|
|
383
|
+
result.Packages[idx].Error = message
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
289
387
|
func (r *Runner) runPackageRuntimesIndividually(
|
|
290
388
|
ctx context.Context,
|
|
291
389
|
req *normalizedRequest,
|
|
@@ -1629,6 +1629,51 @@ func TestRenderRuntimeTypeScriptProjectDisablesEmit(t *testing.T) {
|
|
|
1629
1629
|
}
|
|
1630
1630
|
}
|
|
1631
1631
|
|
|
1632
|
+
func TestMaterializeRuntimeModuleShimsReexportsGeneratedTypeScript(t *testing.T) {
|
|
1633
|
+
workDir := t.TempDir()
|
|
1634
|
+
outputRoot := filepath.Join(workDir, "output")
|
|
1635
|
+
for _, name := range []string{
|
|
1636
|
+
"errors/index.ts",
|
|
1637
|
+
"github.com/s4wave/spacewave/core/plugin/space/config.gs.ts",
|
|
1638
|
+
} {
|
|
1639
|
+
path := filepath.Join(outputRoot, "@goscript", filepath.FromSlash(name))
|
|
1640
|
+
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
1641
|
+
t.Fatalf("create output parent: %v", err)
|
|
1642
|
+
}
|
|
1643
|
+
if err := os.WriteFile(path, []byte("export const value = 1\n"), 0o644); err != nil {
|
|
1644
|
+
t.Fatalf("write output file: %v", err)
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
req := &normalizedRequest{
|
|
1649
|
+
WorkDir: workDir,
|
|
1650
|
+
RuntimeBackend: RuntimeBackendBun,
|
|
1651
|
+
}
|
|
1652
|
+
phase := materializeRuntimeModuleShims(req, []string{outputRoot})
|
|
1653
|
+
if phase.Failed() {
|
|
1654
|
+
t.Fatalf("materialize shims: %s", phase.Error)
|
|
1655
|
+
}
|
|
1656
|
+
for _, root := range []string{workDir, outputRoot} {
|
|
1657
|
+
for _, name := range []string{
|
|
1658
|
+
"errors/index.js",
|
|
1659
|
+
"github.com/s4wave/spacewave/core/plugin/space/config.gs.js",
|
|
1660
|
+
} {
|
|
1661
|
+
path := filepath.Join(root, "node_modules", "@goscript", filepath.FromSlash(name))
|
|
1662
|
+
data, err := os.ReadFile(path)
|
|
1663
|
+
if err != nil {
|
|
1664
|
+
t.Fatalf("read shim %s: %v", name, err)
|
|
1665
|
+
}
|
|
1666
|
+
text := string(data)
|
|
1667
|
+
if !strings.Contains(text, ".ts\"") {
|
|
1668
|
+
t.Fatalf("shim should re-export generated TypeScript: %s", text)
|
|
1669
|
+
}
|
|
1670
|
+
if strings.Contains(text, workDir) {
|
|
1671
|
+
t.Fatalf("shim should use a portable relative import, got: %s", text)
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1632
1677
|
func TestRenderTypeScriptProjectsCanUseIncrementalBuildInfo(t *testing.T) {
|
|
1633
1678
|
req := &normalizedRequest{
|
|
1634
1679
|
WorkDir: "/work",
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
package browserapi
|
|
4
4
|
|
|
5
5
|
import (
|
|
6
|
+
"fmt"
|
|
7
|
+
"os"
|
|
6
8
|
"syscall/js"
|
|
7
9
|
"testing"
|
|
8
10
|
)
|
|
@@ -18,3 +20,37 @@ func TestBrowserAPI(t *testing.T) {
|
|
|
18
20
|
t.Fatalf("div id = %q", got)
|
|
19
21
|
}
|
|
20
22
|
}
|
|
23
|
+
|
|
24
|
+
func TestBrowserStderrUsesConsoleLog(t *testing.T) {
|
|
25
|
+
console := js.Global().Get("console")
|
|
26
|
+
if console.IsUndefined() || console.IsNull() {
|
|
27
|
+
t.Fatal("missing browser console")
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
originalLog := console.Get("log")
|
|
31
|
+
originalError := console.Get("error")
|
|
32
|
+
calls := make([]string, 0, 1)
|
|
33
|
+
logFn := js.FuncOf(func(this js.Value, args []js.Value) any {
|
|
34
|
+
calls = append(calls, "log:"+args[0].String())
|
|
35
|
+
return nil
|
|
36
|
+
})
|
|
37
|
+
errorFn := js.FuncOf(func(this js.Value, args []js.Value) any {
|
|
38
|
+
calls = append(calls, "error:"+args[0].String())
|
|
39
|
+
return nil
|
|
40
|
+
})
|
|
41
|
+
defer logFn.Release()
|
|
42
|
+
defer errorFn.Release()
|
|
43
|
+
defer console.Set("log", originalLog)
|
|
44
|
+
defer console.Set("error", originalError)
|
|
45
|
+
|
|
46
|
+
console.Set("log", logFn)
|
|
47
|
+
console.Set("error", errorFn)
|
|
48
|
+
|
|
49
|
+
if _, err := fmt.Fprintln(os.Stderr, "goscript stderr proof"); err != nil {
|
|
50
|
+
t.Fatal(err)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if len(calls) != 1 || calls[0] != "log:goscript stderr proof" {
|
|
54
|
+
t.Fatalf("stderr console calls = %#v, want console.log", calls)
|
|
55
|
+
}
|
|
56
|
+
}
|
package/compiler/lowering.go
CHANGED
|
@@ -16,6 +16,8 @@ import (
|
|
|
16
16
|
"strconv"
|
|
17
17
|
"strings"
|
|
18
18
|
"unicode/utf8"
|
|
19
|
+
|
|
20
|
+
"golang.org/x/tools/go/packages"
|
|
19
21
|
)
|
|
20
22
|
|
|
21
23
|
// LoweringOwner owns conversion from the semantic model to compiler IR.
|
|
@@ -2506,6 +2508,14 @@ func (o *LoweringOwner) runtimeMethodSignaturesWithSeen(iface *types.Interface,
|
|
|
2506
2508
|
return "[" + strings.Join(methods, ", ") + "]"
|
|
2507
2509
|
}
|
|
2508
2510
|
|
|
2511
|
+
func (o *LoweringOwner) runtimeMethodAssertSignaturesWithSeen(ctx lowerFileContext, iface *types.Interface, seen map[types.Type]bool) string {
|
|
2512
|
+
methods := make([]string, 0, iface.NumMethods())
|
|
2513
|
+
for method := range iface.Methods() {
|
|
2514
|
+
methods = append(methods, o.runtimeMethodAssertSignature(ctx, method, seen))
|
|
2515
|
+
}
|
|
2516
|
+
return "[" + strings.Join(methods, ", ") + "]"
|
|
2517
|
+
}
|
|
2518
|
+
|
|
2509
2519
|
func (o *LoweringOwner) runtimeMethodSignature(method *types.Func, seen map[types.Type]bool) string {
|
|
2510
2520
|
signature, _ := method.Type().(*types.Signature)
|
|
2511
2521
|
if signature == nil {
|
|
@@ -2516,6 +2526,16 @@ func (o *LoweringOwner) runtimeMethodSignature(method *types.Func, seen map[type
|
|
|
2516
2526
|
", returns: " + o.runtimeMethodReturns(signature.Results(), seen) + " }"
|
|
2517
2527
|
}
|
|
2518
2528
|
|
|
2529
|
+
func (o *LoweringOwner) runtimeMethodAssertSignature(ctx lowerFileContext, method *types.Func, seen map[types.Type]bool) string {
|
|
2530
|
+
signature, _ := method.Type().(*types.Signature)
|
|
2531
|
+
if signature == nil {
|
|
2532
|
+
return "{ name: " + strconv.Quote(method.Name()) + ", args: [], returns: [] }"
|
|
2533
|
+
}
|
|
2534
|
+
return "{ name: " + strconv.Quote(method.Name()) +
|
|
2535
|
+
", args: " + o.runtimeMethodAssertArgs(ctx, signature.Params(), seen) +
|
|
2536
|
+
", returns: " + o.runtimeMethodAssertReturns(ctx, signature.Results(), seen) + " }"
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2519
2539
|
func (o *LoweringOwner) runtimeMethodArgs(tuple *types.Tuple, seen map[types.Type]bool) string {
|
|
2520
2540
|
if tuple == nil || tuple.Len() == 0 {
|
|
2521
2541
|
return "[]"
|
|
@@ -2532,6 +2552,22 @@ func (o *LoweringOwner) runtimeMethodArgs(tuple *types.Tuple, seen map[types.Typ
|
|
|
2532
2552
|
return "[" + strings.Join(args, ", ") + "]"
|
|
2533
2553
|
}
|
|
2534
2554
|
|
|
2555
|
+
func (o *LoweringOwner) runtimeMethodAssertArgs(ctx lowerFileContext, tuple *types.Tuple, seen map[types.Type]bool) string {
|
|
2556
|
+
if tuple == nil || tuple.Len() == 0 {
|
|
2557
|
+
return "[]"
|
|
2558
|
+
}
|
|
2559
|
+
args := make([]string, 0, tuple.Len())
|
|
2560
|
+
for idx := range tuple.Len() {
|
|
2561
|
+
param := tuple.At(idx)
|
|
2562
|
+
name := param.Name()
|
|
2563
|
+
if name == "" {
|
|
2564
|
+
name = "_p" + strconv.Itoa(idx)
|
|
2565
|
+
}
|
|
2566
|
+
args = append(args, "{ name: "+strconv.Quote(name)+", type: "+o.runtimeTypeAssertInfoExprWithSeen(ctx, param.Type(), seen)+" }")
|
|
2567
|
+
}
|
|
2568
|
+
return "[" + strings.Join(args, ", ") + "]"
|
|
2569
|
+
}
|
|
2570
|
+
|
|
2535
2571
|
func (o *LoweringOwner) runtimeMethodReturns(tuple *types.Tuple, seen map[types.Type]bool) string {
|
|
2536
2572
|
if tuple == nil || tuple.Len() == 0 {
|
|
2537
2573
|
return "[]"
|
|
@@ -2548,6 +2584,22 @@ func (o *LoweringOwner) runtimeMethodReturns(tuple *types.Tuple, seen map[types.
|
|
|
2548
2584
|
return "[" + strings.Join(results, ", ") + "]"
|
|
2549
2585
|
}
|
|
2550
2586
|
|
|
2587
|
+
func (o *LoweringOwner) runtimeMethodAssertReturns(ctx lowerFileContext, tuple *types.Tuple, seen map[types.Type]bool) string {
|
|
2588
|
+
if tuple == nil || tuple.Len() == 0 {
|
|
2589
|
+
return "[]"
|
|
2590
|
+
}
|
|
2591
|
+
results := make([]string, 0, tuple.Len())
|
|
2592
|
+
for idx := range tuple.Len() {
|
|
2593
|
+
result := tuple.At(idx)
|
|
2594
|
+
name := result.Name()
|
|
2595
|
+
if name == "" {
|
|
2596
|
+
name = "_r" + strconv.Itoa(idx)
|
|
2597
|
+
}
|
|
2598
|
+
results = append(results, "{ name: "+strconv.Quote(name)+", type: "+o.runtimeTypeAssertInfoExprWithSeen(ctx, result.Type(), seen)+" }")
|
|
2599
|
+
}
|
|
2600
|
+
return "[" + strings.Join(results, ", ") + "]"
|
|
2601
|
+
}
|
|
2602
|
+
|
|
2551
2603
|
func (o *LoweringOwner) lowerStructType(ctx lowerFileContext, semType *semanticType) (*loweredStruct, []Diagnostic) {
|
|
2552
2604
|
lowered := &loweredStruct{
|
|
2553
2605
|
exported: ctx.topLevel,
|
|
@@ -4554,6 +4606,8 @@ func shortDeclNeedsTypeAnnotation(typ types.Type) bool {
|
|
|
4554
4606
|
return true
|
|
4555
4607
|
case *types.Slice:
|
|
4556
4608
|
return true
|
|
4609
|
+
case *types.Chan:
|
|
4610
|
+
return true
|
|
4557
4611
|
default:
|
|
4558
4612
|
return false
|
|
4559
4613
|
}
|
|
@@ -6797,7 +6851,7 @@ func (o *LoweringOwner) lowerFuncLit(ctx lowerFileContext, lit *ast.FuncLit) (st
|
|
|
6797
6851
|
deferState := &loweredDeferState{}
|
|
6798
6852
|
bodyCtx := ctx.withSignature(signature).withAsyncFunction(false).withDeferState(deferState).withoutRangeBranch()
|
|
6799
6853
|
asyncCompatibleParams := funcLiteralNeedsAsyncFunctionParamCalls(signature)
|
|
6800
|
-
if asyncCompatibleParams ||
|
|
6854
|
+
if asyncCompatibleParams || funcLiteralUsesAwaitableCall(ctx, lit) {
|
|
6801
6855
|
bodyCtx = bodyCtx.withAsyncFunction(true)
|
|
6802
6856
|
}
|
|
6803
6857
|
var params []loweredParam
|
|
@@ -6814,7 +6868,7 @@ func (o *LoweringOwner) lowerFuncLit(ctx lowerFileContext, lit *ast.FuncLit) (st
|
|
|
6814
6868
|
renderNamedResults(&rendered, o.lowerNamedResults(ctx, signature), 1)
|
|
6815
6869
|
renderDeferStack(&rendered, deferState, 1)
|
|
6816
6870
|
renderStmts(&rendered, body, 1)
|
|
6817
|
-
async := stmtsContainAwait(body) || deferState.async
|
|
6871
|
+
async := bodyCtx.asyncFunction || stmtsContainAwait(body) || deferState.async
|
|
6818
6872
|
prefix := ""
|
|
6819
6873
|
if async {
|
|
6820
6874
|
prefix = "async "
|
|
@@ -6837,7 +6891,7 @@ func renderLoweredParams(params []loweredParam) string {
|
|
|
6837
6891
|
return strings.Join(rendered, ", ")
|
|
6838
6892
|
}
|
|
6839
6893
|
|
|
6840
|
-
func
|
|
6894
|
+
func funcLiteralUsesAwaitableCall(ctx lowerFileContext, lit *ast.FuncLit) bool {
|
|
6841
6895
|
if lit == nil || lit.Body == nil || ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
6842
6896
|
return false
|
|
6843
6897
|
}
|
|
@@ -6853,7 +6907,8 @@ func funcLiteralUsesFunctionIdentifierCall(ctx lowerFileContext, lit *ast.FuncLi
|
|
|
6853
6907
|
if !ok {
|
|
6854
6908
|
return true
|
|
6855
6909
|
}
|
|
6856
|
-
uses = callUsesFunctionIdentifier(ctx.semPkg.source, call.Fun)
|
|
6910
|
+
uses = callUsesFunctionIdentifier(ctx.semPkg.source, call.Fun) ||
|
|
6911
|
+
callUsesInterfaceMethod(ctx.semPkg.source, call.Fun)
|
|
6857
6912
|
return !uses
|
|
6858
6913
|
})
|
|
6859
6914
|
return uses
|
|
@@ -7055,15 +7110,16 @@ func (o *LoweringOwner) lowerCallExpr(ctx lowerFileContext, expr *ast.CallExpr)
|
|
|
7055
7110
|
}
|
|
7056
7111
|
}
|
|
7057
7112
|
}
|
|
7113
|
+
appendHelper := o.runtimeOwner.QualifiedHelper(RuntimeHelperAppend)
|
|
7058
7114
|
if expr.Ellipsis != token.NoPos && len(args) > 1 {
|
|
7059
7115
|
last := len(args) - 1
|
|
7060
7116
|
spread := args[last]
|
|
7061
7117
|
if isStringType(ctx.semPkg.source.TypesInfo.TypeOf(expr.Args[len(expr.Args)-1])) {
|
|
7062
7118
|
spread = o.runtimeOwner.QualifiedHelper(RuntimeHelperStringToBytes) + "(" + spread + ")"
|
|
7063
7119
|
}
|
|
7064
|
-
args[last] =
|
|
7120
|
+
args[last] = spread
|
|
7121
|
+
appendHelper = o.runtimeOwner.QualifiedHelper(RuntimeHelperAppendSlice)
|
|
7065
7122
|
}
|
|
7066
|
-
appendHelper := o.runtimeOwner.QualifiedHelper(RuntimeHelperAppend)
|
|
7067
7123
|
if len(args) > 0 && args[0] == "null" {
|
|
7068
7124
|
if slice, ok := types.Unalias(ctx.semPkg.source.TypesInfo.TypeOf(expr)).Underlying().(*types.Slice); ok {
|
|
7069
7125
|
appendHelper += "<" + o.tsTypeFor(ctx, slice.Elem()) + ">"
|
|
@@ -7973,6 +8029,13 @@ func (o *LoweringOwner) lowerPointerReceiverMethodCall(
|
|
|
7973
8029
|
methodMemberName(selector.Sel.Name) + "(" + strings.Join(args, ", ") + ")"
|
|
7974
8030
|
return call, diagnostics, true
|
|
7975
8031
|
}
|
|
8032
|
+
if receiver != nil && receiver.Obj() != nil && receiver.Obj().Pkg() != nil {
|
|
8033
|
+
pkgPath := receiver.Obj().Pkg().Path()
|
|
8034
|
+
if ctx.importPaths[pkgPath] == "" && !o.hasGeneratedImportPackage(ctx.model, pkgPath) {
|
|
8035
|
+
call := receiverExpr + "." + methodMemberName(selector.Sel.Name) + "(" + strings.Join(args, ", ") + ")"
|
|
8036
|
+
return call, diagnostics, true
|
|
8037
|
+
}
|
|
8038
|
+
}
|
|
7976
8039
|
if crossPackageUnexportedNamedType(ctx, receiver) {
|
|
7977
8040
|
call := o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) +
|
|
7978
8041
|
"<any>(" + receiverExpr + ")." + methodMemberName(selector.Sel.Name) +
|
|
@@ -8688,7 +8751,7 @@ func (o *LoweringOwner) lowerPointerValueExpr(ctx lowerFileContext, expr ast.Exp
|
|
|
8688
8751
|
return value, diagnostics
|
|
8689
8752
|
}
|
|
8690
8753
|
if ref, diagnostics, ok := o.lowerUnsafeArrayPointerRefExpr(ctx, expr); ok {
|
|
8691
|
-
return ref + "
|
|
8754
|
+
return ref + "!.value", diagnostics
|
|
8692
8755
|
}
|
|
8693
8756
|
if ref, diagnostics, ok := o.lowerUnsafePointerRefExpr(ctx, expr); ok {
|
|
8694
8757
|
return ref + ".value", diagnostics
|
|
@@ -8925,7 +8988,7 @@ func sameLoweredSourceExpr(ctx lowerFileContext, left ast.Expr, right ast.Expr)
|
|
|
8925
8988
|
|
|
8926
8989
|
func (o *LoweringOwner) lowerPointerStorageExpr(ctx lowerFileContext, expr ast.Expr) (string, []Diagnostic) {
|
|
8927
8990
|
if ref, diagnostics, ok := o.lowerUnsafeArrayPointerRefExpr(ctx, expr); ok {
|
|
8928
|
-
return ref + "
|
|
8991
|
+
return ref + "!.value", diagnostics
|
|
8929
8992
|
}
|
|
8930
8993
|
if ref, diagnostics, ok := o.lowerUnsafePointerRefExpr(ctx, expr); ok {
|
|
8931
8994
|
return ref + ".value", diagnostics
|
|
@@ -9784,12 +9847,61 @@ func (o *LoweringOwner) runtimeTypeInfoExpr(typ types.Type) string {
|
|
|
9784
9847
|
}
|
|
9785
9848
|
|
|
9786
9849
|
func (o *LoweringOwner) runtimeTypeAssertInfoExpr(ctx lowerFileContext, typ types.Type) string {
|
|
9850
|
+
return o.runtimeTypeAssertInfoExprWithSeen(ctx, typ, make(map[types.Type]bool))
|
|
9851
|
+
}
|
|
9852
|
+
|
|
9853
|
+
func (o *LoweringOwner) runtimeTypeAssertInfoExprWithSeen(ctx lowerFileContext, typ types.Type, seen map[types.Type]bool) string {
|
|
9787
9854
|
typeParam, ok := types.Unalias(typ).(*types.TypeParam)
|
|
9788
|
-
if
|
|
9855
|
+
if ok && typeParamInScope(ctx, typeParam) {
|
|
9856
|
+
return "__typeArgs?.[" + strconv.Quote(typeParam.Obj().Name()) + "]?.type ?? " +
|
|
9857
|
+
o.runtimeTypeInfoExpr(typ)
|
|
9858
|
+
}
|
|
9859
|
+
|
|
9860
|
+
typeKind := o.runtimeOwner.QualifiedHelper(RuntimeHelperTypeKind)
|
|
9861
|
+
if typ == nil {
|
|
9862
|
+
return "{ kind: " + typeKind + ".Basic, name: \"unknown\" }"
|
|
9863
|
+
}
|
|
9864
|
+
typeKey := types.Unalias(typ)
|
|
9865
|
+
if typeKey != nil {
|
|
9866
|
+
if seen[typeKey] {
|
|
9867
|
+
return o.shallowRuntimeTypeInfoExpr(typ)
|
|
9868
|
+
}
|
|
9869
|
+
seen[typeKey] = true
|
|
9870
|
+
defer delete(seen, typeKey)
|
|
9871
|
+
}
|
|
9872
|
+
if named := namedFunctionType(typ); named != nil {
|
|
9873
|
+
return o.runtimeFunctionTypeAssertInfoWithSeen(ctx, named.Underlying().(*types.Signature), runtimeNamedTypeName(named), seen)
|
|
9874
|
+
}
|
|
9875
|
+
if named := namedStructType(typ); named != nil {
|
|
9876
|
+
return strconv.Quote(runtimeNamedTypeName(named))
|
|
9877
|
+
}
|
|
9878
|
+
if named := namedNonStructType(typ); named != nil {
|
|
9879
|
+
if basic, ok := types.Unalias(named.Underlying()).(*types.Basic); ok {
|
|
9880
|
+
return runtimeBasicTypeInfoExpr(typeKind, basic, runtimeNamedTypeName(named))
|
|
9881
|
+
}
|
|
9882
|
+
return strconv.Quote(runtimeNamedTypeName(named))
|
|
9883
|
+
}
|
|
9884
|
+
switch typed := types.Unalias(typ).Underlying().(type) {
|
|
9885
|
+
case *types.Pointer:
|
|
9886
|
+
return "{ kind: " + typeKind + ".Pointer, elemType: " + o.runtimeTypeAssertInfoExprWithSeen(ctx, typed.Elem(), seen) + " }"
|
|
9887
|
+
case *types.Struct:
|
|
9888
|
+
return "{ kind: " + typeKind + ".Struct, methods: [], fields: " + o.runtimeStructAssertFieldsExpr(ctx, typed, seen) + " }"
|
|
9889
|
+
case *types.Slice:
|
|
9890
|
+
return "{ kind: " + typeKind + ".Slice, elemType: " + o.runtimeTypeAssertInfoExprWithSeen(ctx, typed.Elem(), seen) + " }"
|
|
9891
|
+
case *types.Array:
|
|
9892
|
+
return "{ kind: " + typeKind + ".Array, elemType: " + o.runtimeTypeAssertInfoExprWithSeen(ctx, typed.Elem(), seen) + ", length: " + strconv.FormatInt(typed.Len(), 10) + " }"
|
|
9893
|
+
case *types.Map:
|
|
9894
|
+
return "{ kind: " + typeKind + ".Map, keyType: " + o.runtimeTypeAssertInfoExprWithSeen(ctx, typed.Key(), seen) + ", elemType: " + o.runtimeTypeAssertInfoExprWithSeen(ctx, typed.Elem(), seen) + " }"
|
|
9895
|
+
case *types.Chan:
|
|
9896
|
+
return "{ kind: " + typeKind + ".Channel, direction: " + strconv.Quote(channelDirectionString(typed.Dir())) + ", elemType: " + o.runtimeTypeAssertInfoExprWithSeen(ctx, typed.Elem(), seen) + " }"
|
|
9897
|
+
case *types.Interface:
|
|
9898
|
+
typed.Complete()
|
|
9899
|
+
return "{ kind: " + typeKind + ".Interface, methods: " + o.runtimeMethodAssertSignaturesWithSeen(ctx, typed, seen) + " }"
|
|
9900
|
+
case *types.Signature:
|
|
9901
|
+
return o.runtimeFunctionTypeAssertInfoWithSeen(ctx, typed, "", seen)
|
|
9902
|
+
default:
|
|
9789
9903
|
return o.runtimeTypeInfoExpr(typ)
|
|
9790
9904
|
}
|
|
9791
|
-
return "__typeArgs?.[" + strconv.Quote(typeParam.Obj().Name()) + "]?.type ?? " +
|
|
9792
|
-
o.runtimeTypeInfoExpr(typ)
|
|
9793
9905
|
}
|
|
9794
9906
|
|
|
9795
9907
|
func (o *LoweringOwner) runtimeTypeInfoExprWithSeen(typ types.Type, seen map[types.Type]bool) string {
|
|
@@ -9917,6 +10029,40 @@ func (o *LoweringOwner) runtimeStructFieldsExpr(structType *types.Struct, seen m
|
|
|
9917
10029
|
return "[" + strings.Join(fields, ", ") + "]"
|
|
9918
10030
|
}
|
|
9919
10031
|
|
|
10032
|
+
func (o *LoweringOwner) runtimeStructAssertFieldsExpr(ctx lowerFileContext, structType *types.Struct, seen map[types.Type]bool) string {
|
|
10033
|
+
fields := make([]string, 0, structType.NumFields())
|
|
10034
|
+
var vars []*types.Var
|
|
10035
|
+
for field := range structType.Fields() {
|
|
10036
|
+
vars = append(vars, field)
|
|
10037
|
+
}
|
|
10038
|
+
offsets := structFieldOffsets(goScriptTypeSizes(), vars)
|
|
10039
|
+
for idx := range structType.NumFields() {
|
|
10040
|
+
field := structType.Field(idx)
|
|
10041
|
+
fieldName := tsStructFieldName(field.Name(), idx)
|
|
10042
|
+
runtimeName := ""
|
|
10043
|
+
if fieldName != field.Name() {
|
|
10044
|
+
runtimeName = field.Name()
|
|
10045
|
+
}
|
|
10046
|
+
pkgPath := ""
|
|
10047
|
+
if !field.Exported() && field.Pkg() != nil {
|
|
10048
|
+
pkgPath = field.Pkg().Path()
|
|
10049
|
+
}
|
|
10050
|
+
fieldInfo := runtimeStructFieldInfoExpr(
|
|
10051
|
+
o.runtimeTypeAssertInfoExprWithSeen(ctx, field.Type(), seen),
|
|
10052
|
+
fieldName,
|
|
10053
|
+
runtimeName,
|
|
10054
|
+
structType.Tag(idx),
|
|
10055
|
+
pkgPath,
|
|
10056
|
+
field.Embedded(),
|
|
10057
|
+
[]int{idx},
|
|
10058
|
+
offsets[idx],
|
|
10059
|
+
field.Exported(),
|
|
10060
|
+
)
|
|
10061
|
+
fields = append(fields, fieldInfo)
|
|
10062
|
+
}
|
|
10063
|
+
return "[" + strings.Join(fields, ", ") + "]"
|
|
10064
|
+
}
|
|
10065
|
+
|
|
9920
10066
|
func runtimeStructFieldInfoExpr(
|
|
9921
10067
|
runtimeType string,
|
|
9922
10068
|
storageKey string,
|
|
@@ -9981,6 +10127,26 @@ func (o *LoweringOwner) runtimeFunctionTypeInfoWithSeen(signature *types.Signatu
|
|
|
9981
10127
|
return "({ " + strings.Join(parts, ", ") + " } as " + runtimePackage + ".FunctionTypeInfo)"
|
|
9982
10128
|
}
|
|
9983
10129
|
|
|
10130
|
+
func (o *LoweringOwner) runtimeFunctionTypeAssertInfoWithSeen(
|
|
10131
|
+
ctx lowerFileContext,
|
|
10132
|
+
signature *types.Signature,
|
|
10133
|
+
name string,
|
|
10134
|
+
seen map[types.Type]bool,
|
|
10135
|
+
) string {
|
|
10136
|
+
typeKind := o.runtimeOwner.QualifiedHelper(RuntimeHelperTypeKind)
|
|
10137
|
+
parts := []string{"kind: " + typeKind + ".Function"}
|
|
10138
|
+
if name != "" {
|
|
10139
|
+
parts = append(parts, "name: "+strconv.Quote(name))
|
|
10140
|
+
}
|
|
10141
|
+
parts = append(parts, "params: "+o.runtimeTypeAssertSignatureTypes(ctx, signature.Params(), seen))
|
|
10142
|
+
parts = append(parts, "results: "+o.runtimeTypeAssertSignatureTypes(ctx, signature.Results(), seen))
|
|
10143
|
+
if signature.Variadic() {
|
|
10144
|
+
parts = append(parts, "isVariadic: true")
|
|
10145
|
+
}
|
|
10146
|
+
runtimePackage := strings.TrimSuffix(typeKind, ".TypeKind")
|
|
10147
|
+
return "({ " + strings.Join(parts, ", ") + " } as " + runtimePackage + ".FunctionTypeInfo)"
|
|
10148
|
+
}
|
|
10149
|
+
|
|
9984
10150
|
func (o *LoweringOwner) runtimeSignatureTypes(tuple *types.Tuple, seen map[types.Type]bool) string {
|
|
9985
10151
|
if tuple == nil || tuple.Len() == 0 {
|
|
9986
10152
|
return "[]"
|
|
@@ -9992,6 +10158,17 @@ func (o *LoweringOwner) runtimeSignatureTypes(tuple *types.Tuple, seen map[types
|
|
|
9992
10158
|
return "[" + strings.Join(types, ", ") + "]"
|
|
9993
10159
|
}
|
|
9994
10160
|
|
|
10161
|
+
func (o *LoweringOwner) runtimeTypeAssertSignatureTypes(ctx lowerFileContext, tuple *types.Tuple, seen map[types.Type]bool) string {
|
|
10162
|
+
if tuple == nil || tuple.Len() == 0 {
|
|
10163
|
+
return "[]"
|
|
10164
|
+
}
|
|
10165
|
+
types := make([]string, 0, tuple.Len())
|
|
10166
|
+
for v := range tuple.Variables() {
|
|
10167
|
+
types = append(types, o.runtimeTypeAssertInfoExprWithSeen(ctx, v.Type(), seen))
|
|
10168
|
+
}
|
|
10169
|
+
return "[" + strings.Join(types, ", ") + "]"
|
|
10170
|
+
}
|
|
10171
|
+
|
|
9995
10172
|
func tsStructFieldName(name string, idx int) string {
|
|
9996
10173
|
if name == "_" {
|
|
9997
10174
|
return "_blank" + strconv.Itoa(idx)
|
|
@@ -10943,6 +11120,7 @@ func (o *LoweringOwner) callNeedsAwait(ctx lowerFileContext, fun ast.Expr) bool
|
|
|
10943
11120
|
return o.functionAsync(ctx, calledFunction(ctx.semPkg.source, fun)) ||
|
|
10944
11121
|
o.overrideCallNeedsAwait(ctx, fun) ||
|
|
10945
11122
|
callUsesFunctionValue(ctx.semPkg.source, fun) ||
|
|
11123
|
+
(ctx.asyncFunction && callUsesInterfaceMethod(ctx.semPkg.source, fun)) ||
|
|
10946
11124
|
(ctx.asyncFunction && callUsesFunctionIdentifier(ctx.semPkg.source, fun))
|
|
10947
11125
|
}
|
|
10948
11126
|
if ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
@@ -10951,10 +11129,48 @@ func (o *LoweringOwner) callNeedsAwait(ctx lowerFileContext, fun ast.Expr) bool
|
|
|
10951
11129
|
return o.functionAsync(ctx, calledFunction(ctx.semPkg.source, fun)) ||
|
|
10952
11130
|
o.overrideCallNeedsAwait(ctx, fun) ||
|
|
10953
11131
|
callUsesFunctionValue(ctx.semPkg.source, fun) ||
|
|
11132
|
+
(ctx.asyncFunction && callUsesInterfaceMethod(ctx.semPkg.source, fun)) ||
|
|
10954
11133
|
(ctx.asyncFunction && callUsesFunctionIdentifier(ctx.semPkg.source, fun))
|
|
10955
11134
|
}
|
|
10956
11135
|
}
|
|
10957
11136
|
|
|
11137
|
+
func callUsesInterfaceMethod(pkg *packages.Package, fun ast.Expr) bool {
|
|
11138
|
+
if pkg == nil {
|
|
11139
|
+
return false
|
|
11140
|
+
}
|
|
11141
|
+
selector, ok := fun.(*ast.SelectorExpr)
|
|
11142
|
+
if !ok {
|
|
11143
|
+
return false
|
|
11144
|
+
}
|
|
11145
|
+
selection := pkg.TypesInfo.Selections[selector]
|
|
11146
|
+
if selection == nil || selection.Kind() != types.MethodVal {
|
|
11147
|
+
return false
|
|
11148
|
+
}
|
|
11149
|
+
if selectionUsesSyncErrorMethod(selection) {
|
|
11150
|
+
return false
|
|
11151
|
+
}
|
|
11152
|
+
return isInterfaceType(selection.Recv())
|
|
11153
|
+
}
|
|
11154
|
+
|
|
11155
|
+
func selectionUsesSyncErrorMethod(selection *types.Selection) bool {
|
|
11156
|
+
if selection == nil || selection.Kind() != types.MethodVal {
|
|
11157
|
+
return false
|
|
11158
|
+
}
|
|
11159
|
+
method, _ := selection.Obj().(*types.Func)
|
|
11160
|
+
return isSyncErrorMethodFunc(method)
|
|
11161
|
+
}
|
|
11162
|
+
|
|
11163
|
+
func isSyncErrorMethodFunc(fn *types.Func) bool {
|
|
11164
|
+
if fn == nil || fn.Name() != "Error" {
|
|
11165
|
+
return false
|
|
11166
|
+
}
|
|
11167
|
+
signature, _ := fn.Type().(*types.Signature)
|
|
11168
|
+
if signature == nil || signature.Params().Len() != 0 || signature.Results().Len() != 1 {
|
|
11169
|
+
return false
|
|
11170
|
+
}
|
|
11171
|
+
return types.Identical(signature.Results().At(0).Type(), types.Typ[types.String])
|
|
11172
|
+
}
|
|
11173
|
+
|
|
10958
11174
|
func (o *LoweringOwner) overrideCallNeedsAwait(ctx lowerFileContext, fun ast.Expr) bool {
|
|
10959
11175
|
if o.overrideOwner == nil || ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
10960
11176
|
return false
|
|
@@ -488,6 +488,56 @@ func TestCompilePackagesAwaitsOverrideAsyncFunctions(t *testing.T) {
|
|
|
488
488
|
}
|
|
489
489
|
}
|
|
490
490
|
|
|
491
|
+
func TestCompilePackagesAwaitsAsyncSlicesSortFuncComparator(t *testing.T) {
|
|
492
|
+
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
493
|
+
"go.mod": "module example.test/slicesasyncsort\n\ngo 1.25.3\n",
|
|
494
|
+
"main.go": strings.Join([]string{
|
|
495
|
+
"package main",
|
|
496
|
+
"import \"slices\"",
|
|
497
|
+
"type Comparator interface { Less(a, b int) bool }",
|
|
498
|
+
"func Use(c Comparator, values []int) {",
|
|
499
|
+
" slices.SortFunc(values, func(a, b int) int {",
|
|
500
|
+
" if c.Less(a, b) {",
|
|
501
|
+
" return -1",
|
|
502
|
+
" }",
|
|
503
|
+
" if c.Less(b, a) {",
|
|
504
|
+
" return 1",
|
|
505
|
+
" }",
|
|
506
|
+
" return 0",
|
|
507
|
+
" })",
|
|
508
|
+
"}",
|
|
509
|
+
"",
|
|
510
|
+
}, "\n"),
|
|
511
|
+
})
|
|
512
|
+
out := filepath.Join(t.TempDir(), "out")
|
|
513
|
+
comp, err := NewCompiler(&Config{
|
|
514
|
+
Dir: moduleDir,
|
|
515
|
+
OutputPath: out,
|
|
516
|
+
AllDependencies: true,
|
|
517
|
+
}, nil, nil)
|
|
518
|
+
if err != nil {
|
|
519
|
+
t.Fatal(err.Error())
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
|
|
523
|
+
t.Fatal(err.Error())
|
|
524
|
+
}
|
|
525
|
+
content, err := os.ReadFile(filepath.Join(out, "@goscript", "example.test", "slicesasyncsort", "main.gs.ts"))
|
|
526
|
+
if err != nil {
|
|
527
|
+
t.Fatal(err.Error())
|
|
528
|
+
}
|
|
529
|
+
text := string(content)
|
|
530
|
+
if !strings.Contains(text, "export async function Use") {
|
|
531
|
+
t.Fatalf("caller was not marked async for slices.SortFunc:\n%s", text)
|
|
532
|
+
}
|
|
533
|
+
if !strings.Contains(text, "await slices.SortFunc") {
|
|
534
|
+
t.Fatalf("slices.SortFunc call was not awaited:\n%s", text)
|
|
535
|
+
}
|
|
536
|
+
if !strings.Contains(text, "$.functionValue(async") {
|
|
537
|
+
t.Fatalf("SortFunc comparator was not lowered as async:\n%s", text)
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
491
541
|
func TestCompilePackagesAwaitsReflectValueCall(t *testing.T) {
|
|
492
542
|
moduleDir := writePackageGraphFixture(t, map[string]string{
|
|
493
543
|
"go.mod": "module example.test/reflectcallasync\n\ngo 1.25.3\n",
|