goscript 0.2.2 → 0.2.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.
Files changed (160) hide show
  1. package/compiler/gotest/testdata/browserapi/browserapi_test.go +36 -0
  2. package/compiler/lowering.go +279 -16
  3. package/compiler/override-registry_test.go +175 -0
  4. package/compiler/protobuf-ts-binding.go +154 -6
  5. package/compiler/protobuf-ts-binding_test.go +7 -2
  6. package/compiler/runtime-contract.go +2 -0
  7. package/compiler/runtime-contract_test.go +1 -0
  8. package/compiler/semantic-model.go +16 -0
  9. package/compiler/semantic-model_test.go +38 -0
  10. package/compiler/skeleton_test.go +522 -17
  11. package/compiler/typescript-emitter.go +4 -0
  12. package/dist/gs/builtin/builtin.js +7 -9
  13. package/dist/gs/builtin/builtin.js.map +1 -1
  14. package/dist/gs/builtin/defer.js +2 -2
  15. package/dist/gs/builtin/hostio.js +5 -5
  16. package/dist/gs/builtin/hostio.js.map +1 -1
  17. package/dist/gs/builtin/map.js +2 -1
  18. package/dist/gs/builtin/map.js.map +1 -1
  19. package/dist/gs/builtin/slice.d.ts +3 -0
  20. package/dist/gs/builtin/slice.js +39 -0
  21. package/dist/gs/builtin/slice.js.map +1 -1
  22. package/dist/gs/builtin/type.js +49 -0
  23. package/dist/gs/builtin/type.js.map +1 -1
  24. package/dist/gs/compress/gzip/index.d.ts +41 -0
  25. package/dist/gs/compress/gzip/index.js +235 -0
  26. package/dist/gs/compress/gzip/index.js.map +1 -0
  27. package/dist/gs/compress/zlib/index.js +5 -2
  28. package/dist/gs/compress/zlib/index.js.map +1 -1
  29. package/dist/gs/crypto/ecdh/index.js +27 -8
  30. package/dist/gs/crypto/ecdh/index.js.map +1 -1
  31. package/dist/gs/crypto/ed25519/index.js +3 -3
  32. package/dist/gs/crypto/ed25519/index.js.map +1 -1
  33. package/dist/gs/crypto/rand/index.js +6 -3
  34. package/dist/gs/crypto/rand/index.js.map +1 -1
  35. package/dist/gs/embed/index.js +9 -3
  36. package/dist/gs/embed/index.js.map +1 -1
  37. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +1 -0
  38. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +33 -0
  39. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  40. package/dist/gs/github.com/mr-tron/base58/base58/index.js +4 -1
  41. package/dist/gs/github.com/mr-tron/base58/base58/index.js.map +1 -1
  42. package/dist/gs/golang.org/x/crypto/scrypt/index.d.ts +2 -0
  43. package/dist/gs/golang.org/x/crypto/scrypt/index.js +39 -0
  44. package/dist/gs/golang.org/x/crypto/scrypt/index.js.map +1 -0
  45. package/dist/gs/hash/fnv/index.js +13 -5
  46. package/dist/gs/hash/fnv/index.js.map +1 -1
  47. package/dist/gs/io/fs/glob.d.ts +3 -3
  48. package/dist/gs/io/fs/glob.js +9 -9
  49. package/dist/gs/io/fs/glob.js.map +1 -1
  50. package/dist/gs/io/fs/readdir.d.ts +2 -2
  51. package/dist/gs/io/fs/readdir.js +13 -74
  52. package/dist/gs/io/fs/readdir.js.map +1 -1
  53. package/dist/gs/io/fs/readlink.d.ts +1 -1
  54. package/dist/gs/io/fs/readlink.js +2 -2
  55. package/dist/gs/io/fs/readlink.js.map +1 -1
  56. package/dist/gs/io/fs/stat.d.ts +4 -2
  57. package/dist/gs/io/fs/stat.js +12 -73
  58. package/dist/gs/io/fs/stat.js.map +1 -1
  59. package/dist/gs/io/fs/sub.d.ts +2 -2
  60. package/dist/gs/io/fs/sub.js +11 -11
  61. package/dist/gs/io/fs/sub.js.map +1 -1
  62. package/dist/gs/io/fs/walk.js +2 -2
  63. package/dist/gs/io/fs/walk.js.map +1 -1
  64. package/dist/gs/maps/iter.js.map +1 -1
  65. package/dist/gs/maps/maps.js.map +1 -1
  66. package/dist/gs/mime/index.js +5 -2
  67. package/dist/gs/mime/index.js.map +1 -1
  68. package/dist/gs/net/http/httptest/index.js +6 -3
  69. package/dist/gs/net/http/httptest/index.js.map +1 -1
  70. package/dist/gs/net/http/index.d.ts +34 -18
  71. package/dist/gs/net/http/index.js +280 -63
  72. package/dist/gs/net/http/index.js.map +1 -1
  73. package/dist/gs/net/http/pprof/index.d.ts +5 -5
  74. package/dist/gs/net/http/pprof/index.js +21 -21
  75. package/dist/gs/net/http/pprof/index.js.map +1 -1
  76. package/dist/gs/reflect/iter.js +1 -1
  77. package/dist/gs/reflect/iter.js.map +1 -1
  78. package/dist/gs/reflect/type.d.ts +2 -0
  79. package/dist/gs/reflect/type.js +53 -21
  80. package/dist/gs/reflect/type.js.map +1 -1
  81. package/dist/gs/runtime/pprof/index.js.map +1 -1
  82. package/dist/gs/runtime/runtime.js +2 -2
  83. package/dist/gs/runtime/runtime.js.map +1 -1
  84. package/dist/gs/runtime/trace/index.js.map +1 -1
  85. package/dist/gs/slices/slices.d.ts +1 -1
  86. package/dist/gs/slices/slices.js +37 -4
  87. package/dist/gs/slices/slices.js.map +1 -1
  88. package/gs/builtin/builtin.ts +11 -14
  89. package/gs/builtin/defer.ts +2 -2
  90. package/gs/builtin/hostio.ts +5 -5
  91. package/gs/builtin/map.ts +4 -1
  92. package/gs/builtin/runtime-contract.test.ts +25 -0
  93. package/gs/builtin/slice.test.ts +14 -0
  94. package/gs/builtin/slice.ts +64 -0
  95. package/gs/builtin/type.ts +72 -0
  96. package/gs/bytes/bytes.test.ts +14 -13
  97. package/gs/compress/gzip/index.test.ts +86 -0
  98. package/gs/compress/gzip/index.ts +297 -0
  99. package/gs/compress/gzip/meta.json +6 -0
  100. package/gs/compress/gzip/parity.json +45 -0
  101. package/gs/compress/zlib/index.test.ts +19 -5
  102. package/gs/compress/zlib/index.ts +16 -7
  103. package/gs/context/context.test.ts +3 -1
  104. package/gs/crypto/ecdh/index.test.ts +6 -2
  105. package/gs/crypto/ecdh/index.ts +49 -12
  106. package/gs/crypto/ed25519/index.ts +20 -7
  107. package/gs/crypto/rand/index.ts +6 -3
  108. package/gs/embed/index.test.ts +4 -4
  109. package/gs/embed/index.ts +9 -3
  110. package/gs/fmt/fmt.test.ts +29 -4
  111. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +126 -0
  112. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +46 -0
  113. package/gs/github.com/mr-tron/base58/base58/index.ts +9 -3
  114. package/gs/github.com/zeebo/blake3/internal/consts/index.test.ts +2 -8
  115. package/gs/golang.org/x/crypto/scrypt/index.test.ts +81 -0
  116. package/gs/golang.org/x/crypto/scrypt/index.ts +54 -0
  117. package/gs/golang.org/x/crypto/scrypt/meta.json +5 -0
  118. package/gs/hash/fnv/index.test.ts +1 -8
  119. package/gs/hash/fnv/index.ts +27 -10
  120. package/gs/io/fs/glob.ts +14 -11
  121. package/gs/io/fs/meta.json +5 -0
  122. package/gs/io/fs/readdir.test.ts +63 -2
  123. package/gs/io/fs/readdir.ts +33 -30
  124. package/gs/io/fs/readlink.test.ts +2 -2
  125. package/gs/io/fs/readlink.ts +5 -2
  126. package/gs/io/fs/stat.test.ts +79 -0
  127. package/gs/io/fs/stat.ts +24 -10
  128. package/gs/io/fs/sub.test.ts +93 -0
  129. package/gs/io/fs/sub.ts +13 -13
  130. package/gs/io/fs/walk.ts +2 -2
  131. package/gs/maps/iter.ts +9 -9
  132. package/gs/maps/maps.ts +4 -4
  133. package/gs/math/bits/index.test.ts +10 -1
  134. package/gs/mime/index.test.ts +33 -15
  135. package/gs/mime/index.ts +9 -2
  136. package/gs/net/http/httptest/index.test.ts +17 -3
  137. package/gs/net/http/httptest/index.ts +8 -3
  138. package/gs/net/http/index.test.ts +851 -124
  139. package/gs/net/http/index.ts +612 -146
  140. package/gs/net/http/meta.json +3 -1
  141. package/gs/net/http/pprof/index.test.ts +4 -4
  142. package/gs/net/http/pprof/index.ts +43 -22
  143. package/gs/os/file_unix_js.test.ts +22 -0
  144. package/gs/reflect/iter.ts +4 -2
  145. package/gs/reflect/map.test.ts +56 -1
  146. package/gs/reflect/type.ts +76 -37
  147. package/gs/runtime/pprof/index.test.ts +7 -1
  148. package/gs/runtime/pprof/index.ts +5 -1
  149. package/gs/runtime/runtime.test.ts +7 -0
  150. package/gs/runtime/runtime.ts +2 -4
  151. package/gs/runtime/trace/index.test.ts +9 -1
  152. package/gs/runtime/trace/index.ts +5 -1
  153. package/gs/slices/meta.json +3 -0
  154. package/gs/slices/slices.test.ts +59 -21
  155. package/gs/slices/slices.ts +61 -20
  156. package/gs/strconv/complex.test.ts +17 -3
  157. package/gs/sync/atomic/doc_64.test.ts +2 -9
  158. package/gs/sync/sync.test.ts +18 -8
  159. package/gs/syscall/js/index.test.ts +9 -4
  160. package/package.json +5 -4
@@ -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
+ }
@@ -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,
@@ -6795,11 +6847,32 @@ func isLegacyOctalLiteral(value string) bool {
6795
6847
  }
6796
6848
 
6797
6849
  func (o *LoweringOwner) lowerFuncLit(ctx lowerFileContext, lit *ast.FuncLit) (string, bool, []Diagnostic) {
6850
+ return o.lowerFuncLitWithAsyncCalls(ctx, lit, true)
6851
+ }
6852
+
6853
+ func (o *LoweringOwner) lowerFuncLitForTarget(
6854
+ ctx lowerFileContext,
6855
+ lit *ast.FuncLit,
6856
+ targetType types.Type,
6857
+ allowAsyncOverrideCallback bool,
6858
+ ) (string, bool, []Diagnostic) {
6859
+ allowAsyncCalls := true
6860
+ if !allowAsyncOverrideCallback && signatureForType(targetType) != nil {
6861
+ allowAsyncCalls = false
6862
+ }
6863
+ return o.lowerFuncLitWithAsyncCalls(ctx, lit, allowAsyncCalls)
6864
+ }
6865
+
6866
+ func (o *LoweringOwner) lowerFuncLitWithAsyncCalls(
6867
+ ctx lowerFileContext,
6868
+ lit *ast.FuncLit,
6869
+ allowAsyncCalls bool,
6870
+ ) (string, bool, []Diagnostic) {
6798
6871
  signature, _ := ctx.semPkg.source.TypesInfo.TypeOf(lit).(*types.Signature)
6799
6872
  deferState := &loweredDeferState{}
6800
6873
  bodyCtx := ctx.withSignature(signature).withAsyncFunction(false).withDeferState(deferState).withoutRangeBranch()
6801
6874
  asyncCompatibleParams := funcLiteralNeedsAsyncFunctionParamCalls(signature)
6802
- if asyncCompatibleParams || funcLiteralUsesFunctionIdentifierCall(ctx, lit) {
6875
+ if allowAsyncCalls && (asyncCompatibleParams || funcLiteralUsesAwaitableCall(ctx, lit)) {
6803
6876
  bodyCtx = bodyCtx.withAsyncFunction(true)
6804
6877
  }
6805
6878
  var params []loweredParam
@@ -6816,7 +6889,7 @@ func (o *LoweringOwner) lowerFuncLit(ctx lowerFileContext, lit *ast.FuncLit) (st
6816
6889
  renderNamedResults(&rendered, o.lowerNamedResults(ctx, signature), 1)
6817
6890
  renderDeferStack(&rendered, deferState, 1)
6818
6891
  renderStmts(&rendered, body, 1)
6819
- async := stmtsContainAwait(body) || deferState.async
6892
+ async := bodyCtx.asyncFunction || stmtsContainAwait(body) || deferState.async
6820
6893
  prefix := ""
6821
6894
  if async {
6822
6895
  prefix = "async "
@@ -6839,7 +6912,7 @@ func renderLoweredParams(params []loweredParam) string {
6839
6912
  return strings.Join(rendered, ", ")
6840
6913
  }
6841
6914
 
6842
- func funcLiteralUsesFunctionIdentifierCall(ctx lowerFileContext, lit *ast.FuncLit) bool {
6915
+ func funcLiteralUsesAwaitableCall(ctx lowerFileContext, lit *ast.FuncLit) bool {
6843
6916
  if lit == nil || lit.Body == nil || ctx.semPkg == nil || ctx.semPkg.source == nil {
6844
6917
  return false
6845
6918
  }
@@ -6855,7 +6928,8 @@ func funcLiteralUsesFunctionIdentifierCall(ctx lowerFileContext, lit *ast.FuncLi
6855
6928
  if !ok {
6856
6929
  return true
6857
6930
  }
6858
- uses = callUsesFunctionIdentifier(ctx.semPkg.source, call.Fun)
6931
+ uses = callUsesFunctionIdentifier(ctx.semPkg.source, call.Fun) ||
6932
+ callUsesInterfaceMethod(ctx.semPkg.source, call.Fun)
6859
6933
  return !uses
6860
6934
  })
6861
6935
  return uses
@@ -7057,15 +7131,16 @@ func (o *LoweringOwner) lowerCallExpr(ctx lowerFileContext, expr *ast.CallExpr)
7057
7131
  }
7058
7132
  }
7059
7133
  }
7134
+ appendHelper := o.runtimeOwner.QualifiedHelper(RuntimeHelperAppend)
7060
7135
  if expr.Ellipsis != token.NoPos && len(args) > 1 {
7061
7136
  last := len(args) - 1
7062
7137
  spread := args[last]
7063
7138
  if isStringType(ctx.semPkg.source.TypesInfo.TypeOf(expr.Args[len(expr.Args)-1])) {
7064
7139
  spread = o.runtimeOwner.QualifiedHelper(RuntimeHelperStringToBytes) + "(" + spread + ")"
7065
7140
  }
7066
- args[last] = "...(" + spread + " ?? [])"
7141
+ args[last] = spread
7142
+ appendHelper = o.runtimeOwner.QualifiedHelper(RuntimeHelperAppendSlice)
7067
7143
  }
7068
- appendHelper := o.runtimeOwner.QualifiedHelper(RuntimeHelperAppend)
7069
7144
  if len(args) > 0 && args[0] == "null" {
7070
7145
  if slice, ok := types.Unalias(ctx.semPkg.source.TypesInfo.TypeOf(expr)).Underlying().(*types.Slice); ok {
7071
7146
  appendHelper += "<" + o.tsTypeFor(ctx, slice.Elem()) + ">"
@@ -7222,13 +7297,14 @@ func (o *LoweringOwner) lowerCallArgs(
7222
7297
  signature *types.Signature,
7223
7298
  ) ([]string, []Diagnostic) {
7224
7299
  overrideCall := o.callUsesOverridePackage(ctx, expr.Fun)
7300
+ allowAsyncOverrideCallback := !overrideCall || o.overrideCallNeedsAwait(ctx, expr.Fun)
7225
7301
  if args, diagnostics, ok := o.lowerTupleCallArgs(ctx, expr, signature, overrideCall); ok {
7226
7302
  return args, diagnostics
7227
7303
  }
7228
7304
  if signature != nil && signature.Variadic() && overrideCall && !isBuiltinCallTarget(ctx, expr.Fun) {
7229
7305
  params := signature.Params()
7230
7306
  if params == nil || params.Len() == 0 {
7231
- return o.lowerFixedCallArgs(ctx, expr.Args, signature, overrideCall)
7307
+ return o.lowerFixedCallArgs(ctx, expr.Args, signature, overrideCall, allowAsyncOverrideCallback)
7232
7308
  }
7233
7309
  fixedCount := params.Len() - 1
7234
7310
  targetType := params.At(fixedCount).Type()
@@ -7238,7 +7314,7 @@ func (o *LoweringOwner) lowerCallArgs(
7238
7314
  args := make([]string, 0, len(expr.Args))
7239
7315
  var diagnostics []Diagnostic
7240
7316
  for idx, arg := range expr.Args {
7241
- lowered, argDiagnostics := o.lowerExpr(ctx, arg)
7317
+ lowered, argDiagnostics := o.lowerCallArgExpr(ctx, arg, params.At(min(idx, fixedCount)).Type(), allowAsyncOverrideCallback)
7242
7318
  diagnostics = append(diagnostics, argDiagnostics...)
7243
7319
  if idx < fixedCount {
7244
7320
  lowered = o.lowerCallArgForTarget(ctx, arg, params.At(idx).Type(), lowered, overrideCall)
@@ -7255,11 +7331,11 @@ func (o *LoweringOwner) lowerCallArgs(
7255
7331
  if signature == nil || !signature.Variadic() ||
7256
7332
  isBuiltinCallTarget(ctx, expr.Fun) ||
7257
7333
  overrideCall {
7258
- return o.lowerFixedCallArgs(ctx, expr.Args, signature, overrideCall)
7334
+ return o.lowerFixedCallArgs(ctx, expr.Args, signature, overrideCall, allowAsyncOverrideCallback)
7259
7335
  }
7260
7336
  params := signature.Params()
7261
7337
  if params == nil || params.Len() == 0 {
7262
- return o.lowerFixedCallArgs(ctx, expr.Args, signature, overrideCall)
7338
+ return o.lowerFixedCallArgs(ctx, expr.Args, signature, overrideCall, allowAsyncOverrideCallback)
7263
7339
  }
7264
7340
 
7265
7341
  fixedCount := params.Len() - 1
@@ -7267,7 +7343,11 @@ func (o *LoweringOwner) lowerCallArgs(
7267
7343
  var variadicArgs []string
7268
7344
  var diagnostics []Diagnostic
7269
7345
  for idx, arg := range expr.Args {
7270
- lowered, argDiagnostics := o.lowerExpr(ctx, arg)
7346
+ targetType := params.At(fixedCount).Type()
7347
+ if idx < fixedCount {
7348
+ targetType = params.At(idx).Type()
7349
+ }
7350
+ lowered, argDiagnostics := o.lowerCallArgExpr(ctx, arg, targetType, allowAsyncOverrideCallback)
7271
7351
  diagnostics = append(diagnostics, argDiagnostics...)
7272
7352
  if idx < fixedCount {
7273
7353
  lowered = o.lowerCallArgForTarget(ctx, arg, params.At(idx).Type(), lowered, overrideCall)
@@ -7368,6 +7448,7 @@ func (o *LoweringOwner) lowerFixedCallArgs(
7368
7448
  exprs []ast.Expr,
7369
7449
  signature *types.Signature,
7370
7450
  overrideCall bool,
7451
+ allowAsyncOverrideCallback bool,
7371
7452
  ) ([]string, []Diagnostic) {
7372
7453
  var params *types.Tuple
7373
7454
  if signature != nil {
@@ -7376,7 +7457,11 @@ func (o *LoweringOwner) lowerFixedCallArgs(
7376
7457
  args := make([]string, 0, len(exprs))
7377
7458
  var diagnostics []Diagnostic
7378
7459
  for idx, expr := range exprs {
7379
- lowered, exprDiagnostics := o.lowerExpr(ctx, expr)
7460
+ var targetType types.Type
7461
+ if params != nil && idx < params.Len() {
7462
+ targetType = params.At(idx).Type()
7463
+ }
7464
+ lowered, exprDiagnostics := o.lowerCallArgExpr(ctx, expr, targetType, allowAsyncOverrideCallback)
7380
7465
  diagnostics = append(diagnostics, exprDiagnostics...)
7381
7466
  if params != nil && idx < params.Len() {
7382
7467
  lowered = o.lowerCallArgForTarget(ctx, expr, params.At(idx).Type(), lowered, overrideCall)
@@ -7386,6 +7471,19 @@ func (o *LoweringOwner) lowerFixedCallArgs(
7386
7471
  return args, diagnostics
7387
7472
  }
7388
7473
 
7474
+ func (o *LoweringOwner) lowerCallArgExpr(
7475
+ ctx lowerFileContext,
7476
+ expr ast.Expr,
7477
+ targetType types.Type,
7478
+ overrideCall bool,
7479
+ ) (string, []Diagnostic) {
7480
+ if lit, ok := ast.Unparen(expr).(*ast.FuncLit); ok && targetType != nil {
7481
+ value, _, diagnostics := o.lowerFuncLitForTarget(ctx, lit, targetType, overrideCall)
7482
+ return value, diagnostics
7483
+ }
7484
+ return o.lowerExpr(ctx, expr)
7485
+ }
7486
+
7389
7487
  func (o *LoweringOwner) lowerCallArgForTarget(
7390
7488
  ctx lowerFileContext,
7391
7489
  expr ast.Expr,
@@ -7975,6 +8073,13 @@ func (o *LoweringOwner) lowerPointerReceiverMethodCall(
7975
8073
  methodMemberName(selector.Sel.Name) + "(" + strings.Join(args, ", ") + ")"
7976
8074
  return call, diagnostics, true
7977
8075
  }
8076
+ if receiver != nil && receiver.Obj() != nil && receiver.Obj().Pkg() != nil {
8077
+ pkgPath := receiver.Obj().Pkg().Path()
8078
+ if ctx.importPaths[pkgPath] == "" && !o.hasGeneratedImportPackage(ctx.model, pkgPath) {
8079
+ call := receiverExpr + "." + methodMemberName(selector.Sel.Name) + "(" + strings.Join(args, ", ") + ")"
8080
+ return call, diagnostics, true
8081
+ }
8082
+ }
7978
8083
  if crossPackageUnexportedNamedType(ctx, receiver) {
7979
8084
  call := o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) +
7980
8085
  "<any>(" + receiverExpr + ")." + methodMemberName(selector.Sel.Name) +
@@ -8329,7 +8434,12 @@ func (o *LoweringOwner) lowerMethodValueClosure(
8329
8434
  if includeReceiver {
8330
8435
  args = append([]string{"__receiver"}, args...)
8331
8436
  }
8332
- return "((__receiver) => (" + strings.Join(params, ", ") + ") => " + callee + "(" + strings.Join(args, ", ") + "))(" + receiver + ")"
8437
+ closure := "((__receiver) => (" + strings.Join(params, ", ") + ") => " + callee + "(" + strings.Join(args, ", ") + "))(" + receiver + ")"
8438
+ if signature == nil {
8439
+ return closure
8440
+ }
8441
+ return o.runtimeOwner.QualifiedHelper(RuntimeHelperFunctionValue) +
8442
+ "(" + closure + ", " + o.runtimeFunctionTypeInfo(signature, "") + ")"
8333
8443
  }
8334
8444
 
8335
8445
  func (o *LoweringOwner) lowerMethodExpressionClosure(ctx lowerFileContext, selection *types.Selection) string {
@@ -9786,12 +9896,61 @@ func (o *LoweringOwner) runtimeTypeInfoExpr(typ types.Type) string {
9786
9896
  }
9787
9897
 
9788
9898
  func (o *LoweringOwner) runtimeTypeAssertInfoExpr(ctx lowerFileContext, typ types.Type) string {
9899
+ return o.runtimeTypeAssertInfoExprWithSeen(ctx, typ, make(map[types.Type]bool))
9900
+ }
9901
+
9902
+ func (o *LoweringOwner) runtimeTypeAssertInfoExprWithSeen(ctx lowerFileContext, typ types.Type, seen map[types.Type]bool) string {
9789
9903
  typeParam, ok := types.Unalias(typ).(*types.TypeParam)
9790
- if !ok || !typeParamInScope(ctx, typeParam) {
9904
+ if ok && typeParamInScope(ctx, typeParam) {
9905
+ return "__typeArgs?.[" + strconv.Quote(typeParam.Obj().Name()) + "]?.type ?? " +
9906
+ o.runtimeTypeInfoExpr(typ)
9907
+ }
9908
+
9909
+ typeKind := o.runtimeOwner.QualifiedHelper(RuntimeHelperTypeKind)
9910
+ if typ == nil {
9911
+ return "{ kind: " + typeKind + ".Basic, name: \"unknown\" }"
9912
+ }
9913
+ typeKey := types.Unalias(typ)
9914
+ if typeKey != nil {
9915
+ if seen[typeKey] {
9916
+ return o.shallowRuntimeTypeInfoExpr(typ)
9917
+ }
9918
+ seen[typeKey] = true
9919
+ defer delete(seen, typeKey)
9920
+ }
9921
+ if named := namedFunctionType(typ); named != nil {
9922
+ return o.runtimeFunctionTypeAssertInfoWithSeen(ctx, named.Underlying().(*types.Signature), runtimeNamedTypeName(named), seen)
9923
+ }
9924
+ if named := namedStructType(typ); named != nil {
9925
+ return strconv.Quote(runtimeNamedTypeName(named))
9926
+ }
9927
+ if named := namedNonStructType(typ); named != nil {
9928
+ if basic, ok := types.Unalias(named.Underlying()).(*types.Basic); ok {
9929
+ return runtimeBasicTypeInfoExpr(typeKind, basic, runtimeNamedTypeName(named))
9930
+ }
9931
+ return strconv.Quote(runtimeNamedTypeName(named))
9932
+ }
9933
+ switch typed := types.Unalias(typ).Underlying().(type) {
9934
+ case *types.Pointer:
9935
+ return "{ kind: " + typeKind + ".Pointer, elemType: " + o.runtimeTypeAssertInfoExprWithSeen(ctx, typed.Elem(), seen) + " }"
9936
+ case *types.Struct:
9937
+ return "{ kind: " + typeKind + ".Struct, methods: [], fields: " + o.runtimeStructAssertFieldsExpr(ctx, typed, seen) + " }"
9938
+ case *types.Slice:
9939
+ return "{ kind: " + typeKind + ".Slice, elemType: " + o.runtimeTypeAssertInfoExprWithSeen(ctx, typed.Elem(), seen) + " }"
9940
+ case *types.Array:
9941
+ return "{ kind: " + typeKind + ".Array, elemType: " + o.runtimeTypeAssertInfoExprWithSeen(ctx, typed.Elem(), seen) + ", length: " + strconv.FormatInt(typed.Len(), 10) + " }"
9942
+ case *types.Map:
9943
+ return "{ kind: " + typeKind + ".Map, keyType: " + o.runtimeTypeAssertInfoExprWithSeen(ctx, typed.Key(), seen) + ", elemType: " + o.runtimeTypeAssertInfoExprWithSeen(ctx, typed.Elem(), seen) + " }"
9944
+ case *types.Chan:
9945
+ return "{ kind: " + typeKind + ".Channel, direction: " + strconv.Quote(channelDirectionString(typed.Dir())) + ", elemType: " + o.runtimeTypeAssertInfoExprWithSeen(ctx, typed.Elem(), seen) + " }"
9946
+ case *types.Interface:
9947
+ typed.Complete()
9948
+ return "{ kind: " + typeKind + ".Interface, methods: " + o.runtimeMethodAssertSignaturesWithSeen(ctx, typed, seen) + " }"
9949
+ case *types.Signature:
9950
+ return o.runtimeFunctionTypeAssertInfoWithSeen(ctx, typed, "", seen)
9951
+ default:
9791
9952
  return o.runtimeTypeInfoExpr(typ)
9792
9953
  }
9793
- return "__typeArgs?.[" + strconv.Quote(typeParam.Obj().Name()) + "]?.type ?? " +
9794
- o.runtimeTypeInfoExpr(typ)
9795
9954
  }
9796
9955
 
9797
9956
  func (o *LoweringOwner) runtimeTypeInfoExprWithSeen(typ types.Type, seen map[types.Type]bool) string {
@@ -9919,6 +10078,40 @@ func (o *LoweringOwner) runtimeStructFieldsExpr(structType *types.Struct, seen m
9919
10078
  return "[" + strings.Join(fields, ", ") + "]"
9920
10079
  }
9921
10080
 
10081
+ func (o *LoweringOwner) runtimeStructAssertFieldsExpr(ctx lowerFileContext, structType *types.Struct, seen map[types.Type]bool) string {
10082
+ fields := make([]string, 0, structType.NumFields())
10083
+ var vars []*types.Var
10084
+ for field := range structType.Fields() {
10085
+ vars = append(vars, field)
10086
+ }
10087
+ offsets := structFieldOffsets(goScriptTypeSizes(), vars)
10088
+ for idx := range structType.NumFields() {
10089
+ field := structType.Field(idx)
10090
+ fieldName := tsStructFieldName(field.Name(), idx)
10091
+ runtimeName := ""
10092
+ if fieldName != field.Name() {
10093
+ runtimeName = field.Name()
10094
+ }
10095
+ pkgPath := ""
10096
+ if !field.Exported() && field.Pkg() != nil {
10097
+ pkgPath = field.Pkg().Path()
10098
+ }
10099
+ fieldInfo := runtimeStructFieldInfoExpr(
10100
+ o.runtimeTypeAssertInfoExprWithSeen(ctx, field.Type(), seen),
10101
+ fieldName,
10102
+ runtimeName,
10103
+ structType.Tag(idx),
10104
+ pkgPath,
10105
+ field.Embedded(),
10106
+ []int{idx},
10107
+ offsets[idx],
10108
+ field.Exported(),
10109
+ )
10110
+ fields = append(fields, fieldInfo)
10111
+ }
10112
+ return "[" + strings.Join(fields, ", ") + "]"
10113
+ }
10114
+
9922
10115
  func runtimeStructFieldInfoExpr(
9923
10116
  runtimeType string,
9924
10117
  storageKey string,
@@ -9983,6 +10176,26 @@ func (o *LoweringOwner) runtimeFunctionTypeInfoWithSeen(signature *types.Signatu
9983
10176
  return "({ " + strings.Join(parts, ", ") + " } as " + runtimePackage + ".FunctionTypeInfo)"
9984
10177
  }
9985
10178
 
10179
+ func (o *LoweringOwner) runtimeFunctionTypeAssertInfoWithSeen(
10180
+ ctx lowerFileContext,
10181
+ signature *types.Signature,
10182
+ name string,
10183
+ seen map[types.Type]bool,
10184
+ ) string {
10185
+ typeKind := o.runtimeOwner.QualifiedHelper(RuntimeHelperTypeKind)
10186
+ parts := []string{"kind: " + typeKind + ".Function"}
10187
+ if name != "" {
10188
+ parts = append(parts, "name: "+strconv.Quote(name))
10189
+ }
10190
+ parts = append(parts, "params: "+o.runtimeTypeAssertSignatureTypes(ctx, signature.Params(), seen))
10191
+ parts = append(parts, "results: "+o.runtimeTypeAssertSignatureTypes(ctx, signature.Results(), seen))
10192
+ if signature.Variadic() {
10193
+ parts = append(parts, "isVariadic: true")
10194
+ }
10195
+ runtimePackage := strings.TrimSuffix(typeKind, ".TypeKind")
10196
+ return "({ " + strings.Join(parts, ", ") + " } as " + runtimePackage + ".FunctionTypeInfo)"
10197
+ }
10198
+
9986
10199
  func (o *LoweringOwner) runtimeSignatureTypes(tuple *types.Tuple, seen map[types.Type]bool) string {
9987
10200
  if tuple == nil || tuple.Len() == 0 {
9988
10201
  return "[]"
@@ -9994,6 +10207,17 @@ func (o *LoweringOwner) runtimeSignatureTypes(tuple *types.Tuple, seen map[types
9994
10207
  return "[" + strings.Join(types, ", ") + "]"
9995
10208
  }
9996
10209
 
10210
+ func (o *LoweringOwner) runtimeTypeAssertSignatureTypes(ctx lowerFileContext, tuple *types.Tuple, seen map[types.Type]bool) string {
10211
+ if tuple == nil || tuple.Len() == 0 {
10212
+ return "[]"
10213
+ }
10214
+ types := make([]string, 0, tuple.Len())
10215
+ for v := range tuple.Variables() {
10216
+ types = append(types, o.runtimeTypeAssertInfoExprWithSeen(ctx, v.Type(), seen))
10217
+ }
10218
+ return "[" + strings.Join(types, ", ") + "]"
10219
+ }
10220
+
9997
10221
  func tsStructFieldName(name string, idx int) string {
9998
10222
  if name == "_" {
9999
10223
  return "_blank" + strconv.Itoa(idx)
@@ -10945,6 +11169,7 @@ func (o *LoweringOwner) callNeedsAwait(ctx lowerFileContext, fun ast.Expr) bool
10945
11169
  return o.functionAsync(ctx, calledFunction(ctx.semPkg.source, fun)) ||
10946
11170
  o.overrideCallNeedsAwait(ctx, fun) ||
10947
11171
  callUsesFunctionValue(ctx.semPkg.source, fun) ||
11172
+ (ctx.asyncFunction && callUsesInterfaceMethod(ctx.semPkg.source, fun)) ||
10948
11173
  (ctx.asyncFunction && callUsesFunctionIdentifier(ctx.semPkg.source, fun))
10949
11174
  }
10950
11175
  if ctx.semPkg == nil || ctx.semPkg.source == nil {
@@ -10953,10 +11178,48 @@ func (o *LoweringOwner) callNeedsAwait(ctx lowerFileContext, fun ast.Expr) bool
10953
11178
  return o.functionAsync(ctx, calledFunction(ctx.semPkg.source, fun)) ||
10954
11179
  o.overrideCallNeedsAwait(ctx, fun) ||
10955
11180
  callUsesFunctionValue(ctx.semPkg.source, fun) ||
11181
+ (ctx.asyncFunction && callUsesInterfaceMethod(ctx.semPkg.source, fun)) ||
10956
11182
  (ctx.asyncFunction && callUsesFunctionIdentifier(ctx.semPkg.source, fun))
10957
11183
  }
10958
11184
  }
10959
11185
 
11186
+ func callUsesInterfaceMethod(pkg *packages.Package, fun ast.Expr) bool {
11187
+ if pkg == nil {
11188
+ return false
11189
+ }
11190
+ selector, ok := fun.(*ast.SelectorExpr)
11191
+ if !ok {
11192
+ return false
11193
+ }
11194
+ selection := pkg.TypesInfo.Selections[selector]
11195
+ if selection == nil || selection.Kind() != types.MethodVal {
11196
+ return false
11197
+ }
11198
+ if selectionUsesSyncErrorMethod(selection) {
11199
+ return false
11200
+ }
11201
+ return isInterfaceType(selection.Recv())
11202
+ }
11203
+
11204
+ func selectionUsesSyncErrorMethod(selection *types.Selection) bool {
11205
+ if selection == nil || selection.Kind() != types.MethodVal {
11206
+ return false
11207
+ }
11208
+ method, _ := selection.Obj().(*types.Func)
11209
+ return isSyncErrorMethodFunc(method)
11210
+ }
11211
+
11212
+ func isSyncErrorMethodFunc(fn *types.Func) bool {
11213
+ if fn == nil || fn.Name() != "Error" {
11214
+ return false
11215
+ }
11216
+ signature, _ := fn.Type().(*types.Signature)
11217
+ if signature == nil || signature.Params().Len() != 0 || signature.Results().Len() != 1 {
11218
+ return false
11219
+ }
11220
+ return types.Identical(signature.Results().At(0).Type(), types.Typ[types.String])
11221
+ }
11222
+
10960
11223
  func (o *LoweringOwner) overrideCallNeedsAwait(ctx lowerFileContext, fun ast.Expr) bool {
10961
11224
  if o.overrideOwner == nil || ctx.semPkg == nil || ctx.semPkg.source == nil {
10962
11225
  return false