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.
- package/README.md +4 -4
- package/cmd/goscript/cmd_compile.go +0 -3
- package/cmd/goscript/deps.go +11 -0
- package/compiler/analysis.go +298 -55
- package/compiler/assignment.go +2 -2
- package/compiler/builtin_test.go +1 -1
- package/compiler/compiler.go +200 -68
- package/compiler/compiler_test.go +17 -24
- package/compiler/composite-lit.go +32 -8
- package/compiler/decl.go +6 -6
- package/compiler/expr-call.go +170 -15
- package/compiler/expr-selector.go +100 -0
- package/compiler/expr.go +1 -1
- package/compiler/protobuf.go +557 -0
- package/compiler/spec-struct.go +4 -0
- package/compiler/spec-value.go +89 -10
- package/compiler/spec.go +254 -1
- package/compiler/stmt-assign.go +35 -0
- package/compiler/type-assert.go +87 -0
- package/compiler/type.go +4 -1
- package/dist/gs/builtin/builtin.d.ts +20 -1
- package/dist/gs/builtin/builtin.js +95 -4
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +1 -1
- package/dist/gs/builtin/slice.js +21 -2
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/errors/errors.d.ts +5 -6
- package/dist/gs/errors/errors.js.map +1 -1
- package/dist/gs/internal/oserror/errors.d.ts +6 -0
- package/dist/gs/internal/oserror/errors.js +7 -0
- package/dist/gs/internal/oserror/errors.js.map +1 -0
- package/dist/gs/internal/oserror/index.d.ts +1 -0
- package/dist/gs/internal/oserror/index.js +2 -0
- package/dist/gs/internal/oserror/index.js.map +1 -0
- package/dist/gs/io/fs/format.d.ts +3 -0
- package/dist/gs/io/fs/format.js +56 -0
- package/dist/gs/io/fs/format.js.map +1 -0
- package/dist/gs/io/fs/fs.d.ts +79 -0
- package/dist/gs/io/fs/fs.js +200 -0
- package/dist/gs/io/fs/fs.js.map +1 -0
- package/dist/gs/io/fs/glob.d.ts +10 -0
- package/dist/gs/io/fs/glob.js +141 -0
- package/dist/gs/io/fs/glob.js.map +1 -0
- package/dist/gs/io/fs/index.d.ts +8 -0
- package/dist/gs/io/fs/index.js +9 -0
- package/dist/gs/io/fs/index.js.map +1 -0
- package/dist/gs/io/fs/readdir.d.ts +7 -0
- package/dist/gs/io/fs/readdir.js +152 -0
- package/dist/gs/io/fs/readdir.js.map +1 -0
- package/dist/gs/io/fs/readfile.d.ts +6 -0
- package/dist/gs/io/fs/readfile.js +118 -0
- package/dist/gs/io/fs/readfile.js.map +1 -0
- package/dist/gs/io/fs/stat.d.ts +6 -0
- package/dist/gs/io/fs/stat.js +87 -0
- package/dist/gs/io/fs/stat.js.map +1 -0
- package/dist/gs/io/fs/sub.d.ts +6 -0
- package/dist/gs/io/fs/sub.js +172 -0
- package/dist/gs/io/fs/sub.js.map +1 -0
- package/dist/gs/io/fs/walk.d.ts +7 -0
- package/dist/gs/io/fs/walk.js +76 -0
- package/dist/gs/io/fs/walk.js.map +1 -0
- package/dist/gs/io/index.d.ts +1 -0
- package/dist/gs/io/index.js +2 -0
- package/dist/gs/io/index.js.map +1 -0
- package/dist/gs/io/io.d.ts +107 -0
- package/dist/gs/io/io.js +385 -0
- package/dist/gs/io/io.js.map +1 -0
- package/dist/gs/path/index.d.ts +2 -0
- package/dist/gs/path/index.js +3 -0
- package/dist/gs/path/index.js.map +1 -0
- package/dist/gs/path/match.d.ts +6 -0
- package/dist/gs/path/match.js +281 -0
- package/dist/gs/path/match.js.map +1 -0
- package/dist/gs/path/path.d.ts +7 -0
- package/dist/gs/path/path.js +256 -0
- package/dist/gs/path/path.js.map +1 -0
- package/dist/gs/strings/builder.d.ts +18 -0
- package/dist/gs/strings/builder.js +205 -0
- package/dist/gs/strings/builder.js.map +1 -0
- package/dist/gs/strings/clone.d.ts +1 -0
- package/dist/gs/strings/clone.js +16 -0
- package/dist/gs/strings/clone.js.map +1 -0
- package/dist/gs/strings/compare.d.ts +1 -0
- package/dist/gs/strings/compare.js +14 -0
- package/dist/gs/strings/compare.js.map +1 -0
- package/dist/gs/strings/index.d.ts +2 -0
- package/dist/gs/strings/index.js +3 -0
- package/dist/gs/strings/index.js.map +1 -0
- package/dist/gs/strings/iter.d.ts +8 -0
- package/dist/gs/strings/iter.js +160 -0
- package/dist/gs/strings/iter.js.map +1 -0
- package/dist/gs/strings/reader.d.ts +34 -0
- package/dist/gs/strings/reader.js +418 -0
- package/dist/gs/strings/reader.js.map +1 -0
- package/dist/gs/strings/replace.d.ts +106 -0
- package/dist/gs/strings/replace.js +1136 -0
- package/dist/gs/strings/replace.js.map +1 -0
- package/dist/gs/strings/search.d.ts +24 -0
- package/dist/gs/strings/search.js +169 -0
- package/dist/gs/strings/search.js.map +1 -0
- package/dist/gs/strings/strings.d.ts +47 -0
- package/dist/gs/strings/strings.js +418 -0
- package/dist/gs/strings/strings.js.map +1 -0
- package/dist/gs/stringslite/index.d.ts +1 -0
- package/dist/gs/stringslite/index.js +2 -0
- package/dist/gs/stringslite/index.js.map +1 -0
- package/dist/gs/stringslite/strings.d.ts +11 -0
- package/dist/gs/stringslite/strings.js +67 -0
- package/dist/gs/stringslite/strings.js.map +1 -0
- package/dist/gs/sync/index.d.ts +1 -0
- package/dist/gs/sync/index.js +2 -0
- package/dist/gs/sync/index.js.map +1 -0
- package/dist/gs/sync/sync.d.ts +79 -0
- package/dist/gs/sync/sync.js +392 -0
- package/dist/gs/sync/sync.js.map +1 -0
- package/dist/gs/time/time.d.ts +11 -2
- package/dist/gs/time/time.js +337 -12
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unicode/index.d.ts +1 -0
- package/dist/gs/unicode/index.js +2 -0
- package/dist/gs/unicode/index.js.map +1 -0
- package/dist/gs/unicode/unicode.d.ts +105 -0
- package/dist/gs/unicode/unicode.js +332 -0
- package/dist/gs/unicode/unicode.js.map +1 -0
- package/dist/gs/unicode/utf8/index.d.ts +1 -0
- package/dist/gs/unicode/utf8/index.js +3 -0
- package/dist/gs/unicode/utf8/index.js.map +1 -0
- package/dist/gs/unicode/utf8/utf8.d.ts +20 -0
- package/dist/gs/unicode/utf8/utf8.js +196 -0
- package/dist/gs/unicode/utf8/utf8.js.map +1 -0
- package/dist/gs/unsafe/index.d.ts +1 -0
- package/dist/gs/unsafe/index.js +2 -0
- package/dist/gs/unsafe/index.js.map +1 -0
- package/dist/gs/unsafe/unsafe.d.ts +11 -0
- package/dist/gs/unsafe/unsafe.js +44 -0
- package/dist/gs/unsafe/unsafe.js.map +1 -0
- package/go.mod +2 -1
- package/go.sum +6 -2
- package/gs/README.md +6 -0
- package/gs/builtin/builtin.ts +171 -0
- package/gs/builtin/channel.ts +683 -0
- package/gs/builtin/defer.ts +58 -0
- package/gs/builtin/index.ts +1 -0
- package/gs/builtin/io.ts +22 -0
- package/gs/builtin/map.ts +50 -0
- package/gs/builtin/slice.ts +1030 -0
- package/gs/builtin/type.ts +1106 -0
- package/gs/builtin/varRef.ts +25 -0
- package/gs/cmp/godoc.txt +8 -0
- package/gs/cmp/index.ts +29 -0
- package/gs/context/context.ts +401 -0
- package/gs/context/godoc.txt +69 -0
- package/gs/context/index.ts +1 -0
- package/gs/errors/errors.ts +223 -0
- package/gs/errors/godoc.txt +63 -0
- package/gs/errors/index.ts +1 -0
- package/gs/internal/goarch/godoc.txt +39 -0
- package/gs/internal/goarch/index.ts +18 -0
- package/gs/internal/oserror/errors.ts +14 -0
- package/gs/internal/oserror/index.ts +1 -0
- package/gs/io/fs/format.ts +65 -0
- package/gs/io/fs/fs.ts +359 -0
- package/gs/io/fs/glob.ts +167 -0
- package/gs/io/fs/godoc.txt +35 -0
- package/gs/io/fs/index.ts +8 -0
- package/gs/io/fs/readdir.ts +126 -0
- package/gs/io/fs/readfile.ts +77 -0
- package/gs/io/fs/stat.ts +38 -0
- package/gs/io/fs/sub.ts +208 -0
- package/gs/io/fs/walk.ts +89 -0
- package/gs/io/godoc.txt +61 -0
- package/gs/io/index.ts +1 -0
- package/gs/io/io.go +75 -0
- package/gs/io/io.ts +546 -0
- package/gs/iter/godoc.txt +203 -0
- package/gs/iter/index.ts +1 -0
- package/gs/iter/iter.ts +117 -0
- package/gs/math/bits/index.ts +356 -0
- package/gs/math/godoc.txt +76 -0
- package/gs/path/index.ts +2 -0
- package/gs/path/match.ts +307 -0
- package/gs/path/path.ts +301 -0
- package/gs/runtime/godoc.txt +331 -0
- package/gs/runtime/index.ts +1 -0
- package/gs/runtime/runtime.ts +178 -0
- package/gs/slices/godoc.txt +44 -0
- package/gs/slices/index.ts +1 -0
- package/gs/slices/slices.ts +22 -0
- package/gs/strings/builder.test.ts +121 -0
- package/gs/strings/builder.ts +223 -0
- package/gs/strings/clone.test.ts +43 -0
- package/gs/strings/clone.ts +17 -0
- package/gs/strings/compare.test.ts +84 -0
- package/gs/strings/compare.ts +13 -0
- package/gs/strings/godoc.txt +66 -0
- package/gs/strings/index.ts +2 -0
- package/gs/strings/iter.test.ts +343 -0
- package/gs/strings/iter.ts +171 -0
- package/gs/strings/reader.test.ts +242 -0
- package/gs/strings/reader.ts +451 -0
- package/gs/strings/replace.test.ts +181 -0
- package/gs/strings/replace.ts +1310 -0
- package/gs/strings/search.test.ts +214 -0
- package/gs/strings/search.ts +213 -0
- package/gs/strings/strings.test.ts +477 -0
- package/gs/strings/strings.ts +510 -0
- package/gs/stringslite/godoc.txt +17 -0
- package/gs/stringslite/index.ts +1 -0
- package/gs/stringslite/strings.ts +82 -0
- package/gs/sync/godoc.txt +21 -0
- package/gs/sync/index.ts +1 -0
- package/gs/sync/sync.go +64 -0
- package/gs/sync/sync.ts +449 -0
- package/gs/time/godoc.txt +116 -0
- package/gs/time/index.ts +1 -0
- package/gs/time/time.ts +585 -0
- package/gs/unicode/godoc.txt +52 -0
- package/gs/unicode/index.ts +1 -0
- package/gs/unicode/unicode.go +38 -0
- package/gs/unicode/unicode.ts +418 -0
- package/gs/unicode/utf8/godoc.txt +22 -0
- package/gs/unicode/utf8/index.ts +2 -0
- package/gs/unicode/utf8/utf8.ts +227 -0
- package/gs/unsafe/godoc.txt +19 -0
- package/gs/unsafe/index.ts +1 -0
- package/gs/unsafe/unsafe.test.ts +68 -0
- package/gs/unsafe/unsafe.ts +77 -0
- package/package.json +4 -3
package/compiler/expr-call.go
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
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
|
|
557
|
+
return nil // Handled int() conversion
|
|
471
558
|
}
|
|
472
|
-
|
|
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
|
-
//
|
|
496
|
-
c.
|
|
497
|
-
|
|
498
|
-
|
|
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
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
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
|
-
//
|
|
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" {
|