goscript 0.0.26 → 0.0.29

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 (228) hide show
  1. package/README.md +4 -4
  2. package/cmd/goscript/cmd_compile.go +0 -3
  3. package/cmd/goscript/deps.go +11 -0
  4. package/compiler/analysis.go +298 -55
  5. package/compiler/assignment.go +2 -2
  6. package/compiler/builtin_test.go +1 -1
  7. package/compiler/compiler.go +200 -68
  8. package/compiler/compiler_test.go +17 -24
  9. package/compiler/composite-lit.go +32 -8
  10. package/compiler/decl.go +6 -6
  11. package/compiler/expr-call.go +170 -15
  12. package/compiler/expr-selector.go +100 -0
  13. package/compiler/expr.go +1 -1
  14. package/compiler/protobuf.go +557 -0
  15. package/compiler/spec-struct.go +4 -0
  16. package/compiler/spec-value.go +89 -10
  17. package/compiler/spec.go +254 -1
  18. package/compiler/stmt-assign.go +35 -0
  19. package/compiler/type-assert.go +87 -0
  20. package/compiler/type.go +4 -1
  21. package/dist/gs/builtin/builtin.d.ts +20 -1
  22. package/dist/gs/builtin/builtin.js +95 -4
  23. package/dist/gs/builtin/builtin.js.map +1 -1
  24. package/dist/gs/builtin/slice.d.ts +1 -1
  25. package/dist/gs/builtin/slice.js +21 -2
  26. package/dist/gs/builtin/slice.js.map +1 -1
  27. package/dist/gs/errors/errors.d.ts +5 -6
  28. package/dist/gs/errors/errors.js.map +1 -1
  29. package/dist/gs/internal/oserror/errors.d.ts +6 -0
  30. package/dist/gs/internal/oserror/errors.js +7 -0
  31. package/dist/gs/internal/oserror/errors.js.map +1 -0
  32. package/dist/gs/internal/oserror/index.d.ts +1 -0
  33. package/dist/gs/internal/oserror/index.js +2 -0
  34. package/dist/gs/internal/oserror/index.js.map +1 -0
  35. package/dist/gs/io/fs/format.d.ts +3 -0
  36. package/dist/gs/io/fs/format.js +56 -0
  37. package/dist/gs/io/fs/format.js.map +1 -0
  38. package/dist/gs/io/fs/fs.d.ts +79 -0
  39. package/dist/gs/io/fs/fs.js +200 -0
  40. package/dist/gs/io/fs/fs.js.map +1 -0
  41. package/dist/gs/io/fs/glob.d.ts +10 -0
  42. package/dist/gs/io/fs/glob.js +141 -0
  43. package/dist/gs/io/fs/glob.js.map +1 -0
  44. package/dist/gs/io/fs/index.d.ts +8 -0
  45. package/dist/gs/io/fs/index.js +9 -0
  46. package/dist/gs/io/fs/index.js.map +1 -0
  47. package/dist/gs/io/fs/readdir.d.ts +7 -0
  48. package/dist/gs/io/fs/readdir.js +152 -0
  49. package/dist/gs/io/fs/readdir.js.map +1 -0
  50. package/dist/gs/io/fs/readfile.d.ts +6 -0
  51. package/dist/gs/io/fs/readfile.js +118 -0
  52. package/dist/gs/io/fs/readfile.js.map +1 -0
  53. package/dist/gs/io/fs/stat.d.ts +6 -0
  54. package/dist/gs/io/fs/stat.js +87 -0
  55. package/dist/gs/io/fs/stat.js.map +1 -0
  56. package/dist/gs/io/fs/sub.d.ts +6 -0
  57. package/dist/gs/io/fs/sub.js +172 -0
  58. package/dist/gs/io/fs/sub.js.map +1 -0
  59. package/dist/gs/io/fs/walk.d.ts +7 -0
  60. package/dist/gs/io/fs/walk.js +76 -0
  61. package/dist/gs/io/fs/walk.js.map +1 -0
  62. package/dist/gs/io/index.d.ts +1 -0
  63. package/dist/gs/io/index.js +2 -0
  64. package/dist/gs/io/index.js.map +1 -0
  65. package/dist/gs/io/io.d.ts +107 -0
  66. package/dist/gs/io/io.js +385 -0
  67. package/dist/gs/io/io.js.map +1 -0
  68. package/dist/gs/path/index.d.ts +2 -0
  69. package/dist/gs/path/index.js +3 -0
  70. package/dist/gs/path/index.js.map +1 -0
  71. package/dist/gs/path/match.d.ts +6 -0
  72. package/dist/gs/path/match.js +281 -0
  73. package/dist/gs/path/match.js.map +1 -0
  74. package/dist/gs/path/path.d.ts +7 -0
  75. package/dist/gs/path/path.js +256 -0
  76. package/dist/gs/path/path.js.map +1 -0
  77. package/dist/gs/strings/builder.d.ts +18 -0
  78. package/dist/gs/strings/builder.js +205 -0
  79. package/dist/gs/strings/builder.js.map +1 -0
  80. package/dist/gs/strings/clone.d.ts +1 -0
  81. package/dist/gs/strings/clone.js +16 -0
  82. package/dist/gs/strings/clone.js.map +1 -0
  83. package/dist/gs/strings/compare.d.ts +1 -0
  84. package/dist/gs/strings/compare.js +14 -0
  85. package/dist/gs/strings/compare.js.map +1 -0
  86. package/dist/gs/strings/index.d.ts +2 -0
  87. package/dist/gs/strings/index.js +3 -0
  88. package/dist/gs/strings/index.js.map +1 -0
  89. package/dist/gs/strings/iter.d.ts +8 -0
  90. package/dist/gs/strings/iter.js +160 -0
  91. package/dist/gs/strings/iter.js.map +1 -0
  92. package/dist/gs/strings/reader.d.ts +34 -0
  93. package/dist/gs/strings/reader.js +418 -0
  94. package/dist/gs/strings/reader.js.map +1 -0
  95. package/dist/gs/strings/replace.d.ts +106 -0
  96. package/dist/gs/strings/replace.js +1136 -0
  97. package/dist/gs/strings/replace.js.map +1 -0
  98. package/dist/gs/strings/search.d.ts +24 -0
  99. package/dist/gs/strings/search.js +169 -0
  100. package/dist/gs/strings/search.js.map +1 -0
  101. package/dist/gs/strings/strings.d.ts +47 -0
  102. package/dist/gs/strings/strings.js +418 -0
  103. package/dist/gs/strings/strings.js.map +1 -0
  104. package/dist/gs/stringslite/index.d.ts +1 -0
  105. package/dist/gs/stringslite/index.js +2 -0
  106. package/dist/gs/stringslite/index.js.map +1 -0
  107. package/dist/gs/stringslite/strings.d.ts +11 -0
  108. package/dist/gs/stringslite/strings.js +67 -0
  109. package/dist/gs/stringslite/strings.js.map +1 -0
  110. package/dist/gs/sync/index.d.ts +1 -0
  111. package/dist/gs/sync/index.js +2 -0
  112. package/dist/gs/sync/index.js.map +1 -0
  113. package/dist/gs/sync/sync.d.ts +79 -0
  114. package/dist/gs/sync/sync.js +392 -0
  115. package/dist/gs/sync/sync.js.map +1 -0
  116. package/dist/gs/time/time.d.ts +11 -2
  117. package/dist/gs/time/time.js +337 -12
  118. package/dist/gs/time/time.js.map +1 -1
  119. package/dist/gs/unicode/index.d.ts +1 -0
  120. package/dist/gs/unicode/index.js +2 -0
  121. package/dist/gs/unicode/index.js.map +1 -0
  122. package/dist/gs/unicode/unicode.d.ts +105 -0
  123. package/dist/gs/unicode/unicode.js +332 -0
  124. package/dist/gs/unicode/unicode.js.map +1 -0
  125. package/dist/gs/unicode/utf8/index.d.ts +1 -0
  126. package/dist/gs/unicode/utf8/index.js +3 -0
  127. package/dist/gs/unicode/utf8/index.js.map +1 -0
  128. package/dist/gs/unicode/utf8/utf8.d.ts +20 -0
  129. package/dist/gs/unicode/utf8/utf8.js +196 -0
  130. package/dist/gs/unicode/utf8/utf8.js.map +1 -0
  131. package/dist/gs/unsafe/index.d.ts +1 -0
  132. package/dist/gs/unsafe/index.js +2 -0
  133. package/dist/gs/unsafe/index.js.map +1 -0
  134. package/dist/gs/unsafe/unsafe.d.ts +11 -0
  135. package/dist/gs/unsafe/unsafe.js +44 -0
  136. package/dist/gs/unsafe/unsafe.js.map +1 -0
  137. package/go.mod +2 -1
  138. package/go.sum +6 -2
  139. package/gs/README.md +6 -0
  140. package/gs/builtin/builtin.ts +171 -0
  141. package/gs/builtin/channel.ts +683 -0
  142. package/gs/builtin/defer.ts +58 -0
  143. package/gs/builtin/index.ts +1 -0
  144. package/gs/builtin/io.ts +22 -0
  145. package/gs/builtin/map.ts +50 -0
  146. package/gs/builtin/slice.ts +1030 -0
  147. package/gs/builtin/type.ts +1106 -0
  148. package/gs/builtin/varRef.ts +25 -0
  149. package/gs/cmp/godoc.txt +8 -0
  150. package/gs/cmp/index.ts +29 -0
  151. package/gs/context/context.ts +401 -0
  152. package/gs/context/godoc.txt +69 -0
  153. package/gs/context/index.ts +1 -0
  154. package/gs/errors/errors.ts +223 -0
  155. package/gs/errors/godoc.txt +63 -0
  156. package/gs/errors/index.ts +1 -0
  157. package/gs/internal/goarch/godoc.txt +39 -0
  158. package/gs/internal/goarch/index.ts +18 -0
  159. package/gs/internal/oserror/errors.ts +14 -0
  160. package/gs/internal/oserror/index.ts +1 -0
  161. package/gs/io/fs/format.ts +65 -0
  162. package/gs/io/fs/fs.ts +359 -0
  163. package/gs/io/fs/glob.ts +167 -0
  164. package/gs/io/fs/godoc.txt +35 -0
  165. package/gs/io/fs/index.ts +8 -0
  166. package/gs/io/fs/readdir.ts +126 -0
  167. package/gs/io/fs/readfile.ts +77 -0
  168. package/gs/io/fs/stat.ts +38 -0
  169. package/gs/io/fs/sub.ts +208 -0
  170. package/gs/io/fs/walk.ts +89 -0
  171. package/gs/io/godoc.txt +61 -0
  172. package/gs/io/index.ts +1 -0
  173. package/gs/io/io.go +75 -0
  174. package/gs/io/io.ts +546 -0
  175. package/gs/iter/godoc.txt +203 -0
  176. package/gs/iter/index.ts +1 -0
  177. package/gs/iter/iter.ts +117 -0
  178. package/gs/math/bits/index.ts +356 -0
  179. package/gs/math/godoc.txt +76 -0
  180. package/gs/path/index.ts +2 -0
  181. package/gs/path/match.ts +307 -0
  182. package/gs/path/path.ts +301 -0
  183. package/gs/runtime/godoc.txt +331 -0
  184. package/gs/runtime/index.ts +1 -0
  185. package/gs/runtime/runtime.ts +178 -0
  186. package/gs/slices/godoc.txt +44 -0
  187. package/gs/slices/index.ts +1 -0
  188. package/gs/slices/slices.ts +22 -0
  189. package/gs/strings/builder.test.ts +121 -0
  190. package/gs/strings/builder.ts +223 -0
  191. package/gs/strings/clone.test.ts +43 -0
  192. package/gs/strings/clone.ts +17 -0
  193. package/gs/strings/compare.test.ts +84 -0
  194. package/gs/strings/compare.ts +13 -0
  195. package/gs/strings/godoc.txt +66 -0
  196. package/gs/strings/index.ts +2 -0
  197. package/gs/strings/iter.test.ts +343 -0
  198. package/gs/strings/iter.ts +171 -0
  199. package/gs/strings/reader.test.ts +242 -0
  200. package/gs/strings/reader.ts +451 -0
  201. package/gs/strings/replace.test.ts +181 -0
  202. package/gs/strings/replace.ts +1310 -0
  203. package/gs/strings/search.test.ts +214 -0
  204. package/gs/strings/search.ts +213 -0
  205. package/gs/strings/strings.test.ts +477 -0
  206. package/gs/strings/strings.ts +510 -0
  207. package/gs/stringslite/godoc.txt +17 -0
  208. package/gs/stringslite/index.ts +1 -0
  209. package/gs/stringslite/strings.ts +82 -0
  210. package/gs/sync/godoc.txt +21 -0
  211. package/gs/sync/index.ts +1 -0
  212. package/gs/sync/sync.go +64 -0
  213. package/gs/sync/sync.ts +449 -0
  214. package/gs/time/godoc.txt +116 -0
  215. package/gs/time/index.ts +1 -0
  216. package/gs/time/time.ts +585 -0
  217. package/gs/unicode/godoc.txt +52 -0
  218. package/gs/unicode/index.ts +1 -0
  219. package/gs/unicode/unicode.go +38 -0
  220. package/gs/unicode/unicode.ts +418 -0
  221. package/gs/unicode/utf8/godoc.txt +22 -0
  222. package/gs/unicode/utf8/index.ts +2 -0
  223. package/gs/unicode/utf8/utf8.ts +227 -0
  224. package/gs/unsafe/godoc.txt +19 -0
  225. package/gs/unsafe/index.ts +1 -0
  226. package/gs/unsafe/unsafe.test.ts +68 -0
  227. package/gs/unsafe/unsafe.ts +77 -0
  228. package/package.json +4 -3
@@ -5,6 +5,7 @@ import (
5
5
  "go/ast"
6
6
  "go/token"
7
7
  "go/types"
8
+ "strings"
8
9
 
9
10
  "github.com/pkg/errors"
10
11
  )
@@ -38,6 +39,11 @@ import (
38
39
  func (c *GoToTSCompiler) WriteCallExpr(exp *ast.CallExpr) error {
39
40
  expFun := exp.Fun
40
41
 
42
+ // Handle protobuf method calls
43
+ if handled, err := c.writeProtobufMethodCall(exp); handled {
44
+ return err
45
+ }
46
+
41
47
  // Handle any type conversion with nil argument
42
48
  if len(exp.Args) == 1 {
43
49
  if nilIdent, isIdent := exp.Args[0].(*ast.Ident); isIdent && nilIdent.Name == "nil" {
@@ -325,6 +331,53 @@ func (c *GoToTSCompiler) WriteCallExpr(exp *ast.CallExpr) error {
325
331
  }
326
332
  }
327
333
  }
334
+ } else {
335
+ // Handle named types with slice underlying types: make(NamedSliceType, len, cap)
336
+ // This handles cases like: type appendSliceWriter []byte; make(appendSliceWriter, 0, len(s))
337
+ namedType := typeName.Type()
338
+ if sliceType, isSlice := namedType.Underlying().(*types.Slice); isSlice {
339
+ goElemType := sliceType.Elem()
340
+
341
+ // Check if it's a named type with []byte underlying type
342
+ if basicElem, isBasic := goElemType.(*types.Basic); isBasic && basicElem.Kind() == types.Uint8 {
343
+ c.tsw.WriteLiterally("new Uint8Array(")
344
+ if len(exp.Args) >= 2 {
345
+ if err := c.WriteValueExpr(exp.Args[1]); err != nil { // Length
346
+ return err
347
+ }
348
+ // Capacity argument for make([]byte, len, cap) is ignored for new Uint8Array(len)
349
+ } else {
350
+ // If no length is provided, default to 0
351
+ c.tsw.WriteLiterally("0")
352
+ }
353
+ c.tsw.WriteLiterally(")")
354
+ return nil // Handled make for named []byte type
355
+ }
356
+
357
+ // Handle other named slice types
358
+ c.tsw.WriteLiterally("$.makeSlice<")
359
+ c.WriteGoType(goElemType, GoTypeContextGeneral) // Write the element type
360
+ c.tsw.WriteLiterally(">(")
361
+
362
+ if len(exp.Args) >= 2 {
363
+ if err := c.WriteValueExpr(exp.Args[1]); err != nil { // Length
364
+ return err
365
+ }
366
+ if len(exp.Args) == 3 {
367
+ c.tsw.WriteLiterally(", ")
368
+ if err := c.WriteValueExpr(exp.Args[2]); err != nil { // Capacity
369
+ return err
370
+ }
371
+ } else if len(exp.Args) > 3 {
372
+ return errors.New("makeSlice expects 2 or 3 arguments")
373
+ }
374
+ } else {
375
+ // If no length is provided, default to 0
376
+ c.tsw.WriteLiterally("0")
377
+ }
378
+ c.tsw.WriteLiterally(")")
379
+ return nil // Handled make for named slice type
380
+ }
328
381
  }
329
382
  }
330
383
  }
@@ -460,16 +513,51 @@ func (c *GoToTSCompiler) WriteCallExpr(exp *ast.CallExpr) error {
460
513
  }
461
514
  return errors.New("unhandled append call with incorrect number of arguments")
462
515
  case "byte":
463
- // Translate byte(val) to $.byte(val)
516
+ // Translate byte(arg) to $.byte(arg)
517
+ if len(exp.Args) != 1 {
518
+ return errors.Errorf("unhandled byte call with incorrect number of arguments: %d != 1", len(exp.Args))
519
+ }
520
+ c.tsw.WriteLiterally("$.byte(")
521
+ if err := c.WriteValueExpr(exp.Args[0]); err != nil {
522
+ return fmt.Errorf("failed to write argument for byte() conversion: %w", err)
523
+ }
524
+ c.tsw.WriteLiterally(")")
525
+ return nil // Handled byte() conversion
526
+ case "int":
527
+ // Handle int() conversion
464
528
  if len(exp.Args) == 1 {
465
- c.tsw.WriteLiterally("$.byte(")
529
+ arg := exp.Args[0]
530
+
531
+ // Check if we're converting FROM a type with receiver methods TO int
532
+ if argType := c.pkg.TypesInfo.TypeOf(arg); argType != nil {
533
+ if namedArgType, isNamed := argType.(*types.Named); isNamed {
534
+ argTypeName := namedArgType.Obj().Name()
535
+ // Check if the argument type has receiver methods
536
+ if c.hasReceiverMethods(argTypeName) {
537
+ // Check if we're converting to int (the underlying type)
538
+ if types.Identical(types.Typ[types.Int], namedArgType.Underlying()) {
539
+ // This is a conversion from a type with methods to int
540
+ // Use valueOf() instead of $.int()
541
+ if err := c.WriteValueExpr(arg); err != nil {
542
+ return fmt.Errorf("failed to write argument for valueOf conversion: %w", err)
543
+ }
544
+ c.tsw.WriteLiterally(".valueOf()")
545
+ return nil // Handled conversion from type with methods to int
546
+ }
547
+ }
548
+ }
549
+ }
550
+
551
+ // Default case: Translate int(value) to $.int(value)
552
+ c.tsw.WriteLiterally("$.int(")
466
553
  if err := c.WriteValueExpr(exp.Args[0]); err != nil {
467
- return err
554
+ return fmt.Errorf("failed to write argument for int() conversion: %w", err)
468
555
  }
469
556
  c.tsw.WriteLiterally(")")
470
- return nil // Handled byte
557
+ return nil // Handled int() conversion
471
558
  }
472
- return errors.New("unhandled byte call with incorrect number of arguments")
559
+ // Return error for incorrect number of arguments
560
+ return fmt.Errorf("unhandled int conversion with incorrect number of arguments: %d != 1", len(exp.Args))
473
561
  default:
474
562
  // Check if this is a type conversion to a function type
475
563
  if funIdent != nil {
@@ -478,6 +566,30 @@ func (c *GoToTSCompiler) WriteCallExpr(exp *ast.CallExpr) error {
478
566
  if typeName, isType := obj.(*types.TypeName); isType {
479
567
  // Make sure we have exactly one argument
480
568
  if len(exp.Args) == 1 {
569
+ arg := exp.Args[0]
570
+
571
+ // Check if we're converting FROM a type with receiver methods TO its underlying type
572
+ if argType := c.pkg.TypesInfo.TypeOf(arg); argType != nil {
573
+ if namedArgType, isNamed := argType.(*types.Named); isNamed {
574
+ argTypeName := namedArgType.Obj().Name()
575
+ // Check if the argument type has receiver methods
576
+ if c.hasReceiverMethods(argTypeName) {
577
+ // Check if we're converting to the underlying type
578
+ targetType := typeName.Type()
579
+ underlyingType := namedArgType.Underlying()
580
+ if types.Identical(targetType, underlyingType) {
581
+ // This is a conversion from a type with methods to its underlying type
582
+ // Use valueOf() instead of TypeScript cast
583
+ if err := c.WriteValueExpr(arg); err != nil {
584
+ return fmt.Errorf("failed to write argument for valueOf conversion: %w", err)
585
+ }
586
+ c.tsw.WriteLiterally(".valueOf()")
587
+ return nil // Handled conversion from type with methods to underlying type
588
+ }
589
+ }
590
+ }
591
+ }
592
+
481
593
  // Check if this is a function type
482
594
  if _, isFuncType := typeName.Type().Underlying().(*types.Signature); isFuncType {
483
595
  // For function types, we need to add a __goTypeName property
@@ -492,17 +604,30 @@ func (c *GoToTSCompiler) WriteCallExpr(exp *ast.CallExpr) error {
492
604
  c.tsw.WriteLiterallyf(", { __goTypeName: '%s' })", funIdent.String())
493
605
  return nil // Handled function type cast
494
606
  } else {
495
- // For non-function types, use the TypeScript "as" operator
496
- c.tsw.WriteLiterally("(")
497
- if err := c.WriteValueExpr(exp.Args[0]); err != nil {
498
- return fmt.Errorf("failed to write argument for type cast: %w", err)
499
- }
607
+ // Check if this type has receiver methods
608
+ if c.hasReceiverMethods(funIdent.String()) {
609
+ // For types with methods, use class constructor
610
+ c.tsw.WriteLiterally("new ")
611
+ c.tsw.WriteLiterally(funIdent.String())
612
+ c.tsw.WriteLiterally("(")
613
+ if err := c.WriteValueExpr(exp.Args[0]); err != nil {
614
+ return fmt.Errorf("failed to write argument for type constructor: %w", err)
615
+ }
616
+ c.tsw.WriteLiterally(")")
617
+ return nil // Handled type with methods conversion
618
+ } else {
619
+ // For non-function types without methods, use the TypeScript "as" operator
620
+ c.tsw.WriteLiterally("(")
621
+ if err := c.WriteValueExpr(exp.Args[0]); err != nil {
622
+ return fmt.Errorf("failed to write argument for type cast: %w", err)
623
+ }
500
624
 
501
- // Then use the TypeScript "as" operator with the mapped type name
502
- c.tsw.WriteLiterally(" as ")
503
- c.WriteGoType(typeName.Type(), GoTypeContextGeneral)
504
- c.tsw.WriteLiterally(")")
505
- return nil // Handled non-function type cast
625
+ // Then use the TypeScript "as" operator with the mapped type name
626
+ c.tsw.WriteLiterally(" as ")
627
+ c.WriteGoType(typeName.Type(), GoTypeContextGeneral)
628
+ c.tsw.WriteLiterally(")")
629
+ return nil // Handled non-function type cast
630
+ }
506
631
  }
507
632
  }
508
633
  }
@@ -554,6 +679,36 @@ func (c *GoToTSCompiler) WriteCallExpr(exp *ast.CallExpr) error {
554
679
  return nil // Handled regular function call
555
680
  }
556
681
  } else {
682
+ // Check if this is an async method call (e.g., mu.Lock())
683
+ if selExpr, ok := expFun.(*ast.SelectorExpr); ok {
684
+ // Check if this is a method call on a variable (e.g., mu.Lock())
685
+ if ident, ok := selExpr.X.(*ast.Ident); ok {
686
+ // Get the type of the receiver
687
+ if obj := c.pkg.TypesInfo.Uses[ident]; obj != nil {
688
+ if varObj, ok := obj.(*types.Var); ok {
689
+ // Get the type name and package
690
+ if namedType, ok := varObj.Type().(*types.Named); ok {
691
+ typeName := namedType.Obj().Name()
692
+ methodName := selExpr.Sel.Name
693
+
694
+ // Check if the type is from an imported package
695
+ if typePkg := namedType.Obj().Pkg(); typePkg != nil && typePkg != c.pkg.Types {
696
+ pkgPath := typePkg.Path()
697
+ // Extract package name from path (e.g., "sync" from "github.com/.../gs/sync")
698
+ parts := strings.Split(pkgPath, "/")
699
+ pkgName := parts[len(parts)-1]
700
+
701
+ // Check if this method is async based on metadata
702
+ if c.analysis.IsMethodAsync(pkgName, typeName, methodName) {
703
+ c.tsw.WriteLiterally("await ")
704
+ }
705
+ }
706
+ }
707
+ }
708
+ }
709
+ }
710
+ }
711
+
557
712
  // If expFun is a function literal, it needs to be wrapped in parentheses for IIFE syntax
558
713
  if _, isFuncLit := expFun.(*ast.FuncLit); isFuncLit {
559
714
  c.tsw.WriteLiterally("(")
@@ -38,6 +38,14 @@ func (c *GoToTSCompiler) WriteSelectorExpr(exp *ast.SelectorExpr) error {
38
38
  }
39
39
  }
40
40
 
41
+ // Check if this is a method value (method being used as a value, not called immediately)
42
+ if c.analysis.IsMethodValue(exp) {
43
+ // This is a method value - we need to bind it properly
44
+ if selection := c.pkg.TypesInfo.Selections[exp]; selection != nil {
45
+ return c.writeMethodValue(exp, selection)
46
+ }
47
+ }
48
+
41
49
  // --- Special case for dereferenced pointer to struct with field access: (*p).field or (**p).field etc ---
42
50
  var baseExpr ast.Expr = exp.X
43
51
  // Look inside parentheses if present
@@ -148,3 +156,95 @@ func (c *GoToTSCompiler) WriteSelectorExpr(exp *ast.SelectorExpr) error {
148
156
  c.WriteIdent(exp.Sel, false)
149
157
  return nil
150
158
  }
159
+
160
+ // writeMethodValue handles method values (methods used as values, not called immediately)
161
+ // and generates proper binding code to maintain the 'this' context.
162
+ func (c *GoToTSCompiler) writeMethodValue(exp *ast.SelectorExpr, selection *types.Selection) error {
163
+ // Get the method signature to understand the receiver type
164
+ methodObj := selection.Obj().(*types.Func)
165
+ sig := methodObj.Type().(*types.Signature)
166
+ recv := sig.Recv()
167
+
168
+ if recv == nil {
169
+ // This shouldn't happen for method values, but handle gracefully
170
+ return fmt.Errorf("method value has no receiver: %s", methodObj.Name())
171
+ }
172
+
173
+ // Determine if this is a pointer receiver or value receiver
174
+ recvType := recv.Type()
175
+ isPointerReceiver := false
176
+ if _, ok := recvType.(*types.Pointer); ok {
177
+ isPointerReceiver = true
178
+ }
179
+
180
+ // Get the base expression type to understand what we're working with
181
+ baseType := c.pkg.TypesInfo.TypeOf(exp.X)
182
+ baseIsPointer := false
183
+ if _, ok := baseType.(*types.Pointer); ok {
184
+ baseIsPointer = true
185
+ }
186
+
187
+ // Write the receiver expression
188
+ if err := c.WriteValueExpr(exp.X); err != nil {
189
+ return fmt.Errorf("failed to write method value receiver: %w", err)
190
+ }
191
+
192
+ // Add null assertion if needed
193
+ if baseIsPointer {
194
+ c.tsw.WriteLiterally("!")
195
+ }
196
+
197
+ // Handle different receiver type combinations according to Go semantics
198
+ if isPointerReceiver && !baseIsPointer {
199
+ // Pointer receiver method on value type: t.Mp equivalent to (&t).Mp
200
+ // The receiver should be the address of the value
201
+ c.tsw.WriteLiterally(".")
202
+ c.WriteIdent(exp.Sel, false)
203
+ c.tsw.WriteLiterally(".bind(")
204
+ if err := c.WriteValueExpr(exp.X); err != nil {
205
+ return fmt.Errorf("failed to write method value receiver for binding: %w", err)
206
+ }
207
+ if baseIsPointer {
208
+ c.tsw.WriteLiterally("!")
209
+ }
210
+ c.tsw.WriteLiterally(")")
211
+ } else if !isPointerReceiver && baseIsPointer {
212
+ // Value receiver method on pointer type: pt.Mv equivalent to (*pt).Mv
213
+ // The receiver should be a copy of the dereferenced value
214
+ c.tsw.WriteLiterally(".value.")
215
+ c.WriteIdent(exp.Sel, false)
216
+ c.tsw.WriteLiterally(".bind(")
217
+ if err := c.WriteValueExpr(exp.X); err != nil {
218
+ return fmt.Errorf("failed to write method value receiver for binding: %w", err)
219
+ }
220
+ c.tsw.WriteLiterally("!.value.clone())")
221
+ } else if !isPointerReceiver && !baseIsPointer {
222
+ // Value receiver method on value type: t.Mv
223
+ // The receiver should be a copy of the value
224
+ c.tsw.WriteLiterally(".")
225
+ c.WriteIdent(exp.Sel, false)
226
+ c.tsw.WriteLiterally(".bind(")
227
+ if err := c.WriteValueExpr(exp.X); err != nil {
228
+ return fmt.Errorf("failed to write method value receiver for binding: %w", err)
229
+ }
230
+ if baseIsPointer {
231
+ c.tsw.WriteLiterally("!")
232
+ }
233
+ c.tsw.WriteLiterally(".clone())")
234
+ } else {
235
+ // Pointer receiver method on pointer type: pt.Mp
236
+ // The receiver should be the pointer itself
237
+ c.tsw.WriteLiterally(".")
238
+ c.WriteIdent(exp.Sel, false)
239
+ c.tsw.WriteLiterally(".bind(")
240
+ if err := c.WriteValueExpr(exp.X); err != nil {
241
+ return fmt.Errorf("failed to write method value receiver for binding: %w", err)
242
+ }
243
+ if baseIsPointer {
244
+ c.tsw.WriteLiterally("!")
245
+ }
246
+ c.tsw.WriteLiterally(")")
247
+ }
248
+
249
+ return nil
250
+ }
package/compiler/expr.go CHANGED
@@ -388,7 +388,7 @@ func (c *GoToTSCompiler) WriteBinaryExpr(exp *ast.BinaryExpr) error {
388
388
  isBitwise = true
389
389
  }
390
390
 
391
- // Special handling for large bit shift expressions that would overflow in JavaScript
391
+ // Handle large bit shift expressions that would overflow in JavaScript
392
392
  if exp.Op == token.SHL {
393
393
  // Check if this is 1 << 63 pattern
394
394
  if leftLit, leftIsLit := exp.X.(*ast.BasicLit); leftIsLit && leftLit.Value == "1" {