goscript 0.2.2 → 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/testdata/browserapi/browserapi_test.go +36 -0
- package/compiler/lowering.go +223 -9
- package/compiler/override-registry_test.go +50 -0
- package/compiler/protobuf-ts-binding.go +154 -6
- package/compiler/protobuf-ts-binding_test.go +7 -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 +473 -15
- 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/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/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/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/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/gs/builtin/builtin.ts +11 -14
- package/gs/builtin/defer.ts +2 -2
- package/gs/builtin/hostio.ts +5 -5
- 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/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/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/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/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 +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
|
+
}
|
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,
|
|
@@ -6799,7 +6851,7 @@ func (o *LoweringOwner) lowerFuncLit(ctx lowerFileContext, lit *ast.FuncLit) (st
|
|
|
6799
6851
|
deferState := &loweredDeferState{}
|
|
6800
6852
|
bodyCtx := ctx.withSignature(signature).withAsyncFunction(false).withDeferState(deferState).withoutRangeBranch()
|
|
6801
6853
|
asyncCompatibleParams := funcLiteralNeedsAsyncFunctionParamCalls(signature)
|
|
6802
|
-
if asyncCompatibleParams ||
|
|
6854
|
+
if asyncCompatibleParams || funcLiteralUsesAwaitableCall(ctx, lit) {
|
|
6803
6855
|
bodyCtx = bodyCtx.withAsyncFunction(true)
|
|
6804
6856
|
}
|
|
6805
6857
|
var params []loweredParam
|
|
@@ -6816,7 +6868,7 @@ func (o *LoweringOwner) lowerFuncLit(ctx lowerFileContext, lit *ast.FuncLit) (st
|
|
|
6816
6868
|
renderNamedResults(&rendered, o.lowerNamedResults(ctx, signature), 1)
|
|
6817
6869
|
renderDeferStack(&rendered, deferState, 1)
|
|
6818
6870
|
renderStmts(&rendered, body, 1)
|
|
6819
|
-
async := stmtsContainAwait(body) || deferState.async
|
|
6871
|
+
async := bodyCtx.asyncFunction || stmtsContainAwait(body) || deferState.async
|
|
6820
6872
|
prefix := ""
|
|
6821
6873
|
if async {
|
|
6822
6874
|
prefix = "async "
|
|
@@ -6839,7 +6891,7 @@ func renderLoweredParams(params []loweredParam) string {
|
|
|
6839
6891
|
return strings.Join(rendered, ", ")
|
|
6840
6892
|
}
|
|
6841
6893
|
|
|
6842
|
-
func
|
|
6894
|
+
func funcLiteralUsesAwaitableCall(ctx lowerFileContext, lit *ast.FuncLit) bool {
|
|
6843
6895
|
if lit == nil || lit.Body == nil || ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
6844
6896
|
return false
|
|
6845
6897
|
}
|
|
@@ -6855,7 +6907,8 @@ func funcLiteralUsesFunctionIdentifierCall(ctx lowerFileContext, lit *ast.FuncLi
|
|
|
6855
6907
|
if !ok {
|
|
6856
6908
|
return true
|
|
6857
6909
|
}
|
|
6858
|
-
uses = callUsesFunctionIdentifier(ctx.semPkg.source, call.Fun)
|
|
6910
|
+
uses = callUsesFunctionIdentifier(ctx.semPkg.source, call.Fun) ||
|
|
6911
|
+
callUsesInterfaceMethod(ctx.semPkg.source, call.Fun)
|
|
6859
6912
|
return !uses
|
|
6860
6913
|
})
|
|
6861
6914
|
return uses
|
|
@@ -7057,15 +7110,16 @@ func (o *LoweringOwner) lowerCallExpr(ctx lowerFileContext, expr *ast.CallExpr)
|
|
|
7057
7110
|
}
|
|
7058
7111
|
}
|
|
7059
7112
|
}
|
|
7113
|
+
appendHelper := o.runtimeOwner.QualifiedHelper(RuntimeHelperAppend)
|
|
7060
7114
|
if expr.Ellipsis != token.NoPos && len(args) > 1 {
|
|
7061
7115
|
last := len(args) - 1
|
|
7062
7116
|
spread := args[last]
|
|
7063
7117
|
if isStringType(ctx.semPkg.source.TypesInfo.TypeOf(expr.Args[len(expr.Args)-1])) {
|
|
7064
7118
|
spread = o.runtimeOwner.QualifiedHelper(RuntimeHelperStringToBytes) + "(" + spread + ")"
|
|
7065
7119
|
}
|
|
7066
|
-
args[last] =
|
|
7120
|
+
args[last] = spread
|
|
7121
|
+
appendHelper = o.runtimeOwner.QualifiedHelper(RuntimeHelperAppendSlice)
|
|
7067
7122
|
}
|
|
7068
|
-
appendHelper := o.runtimeOwner.QualifiedHelper(RuntimeHelperAppend)
|
|
7069
7123
|
if len(args) > 0 && args[0] == "null" {
|
|
7070
7124
|
if slice, ok := types.Unalias(ctx.semPkg.source.TypesInfo.TypeOf(expr)).Underlying().(*types.Slice); ok {
|
|
7071
7125
|
appendHelper += "<" + o.tsTypeFor(ctx, slice.Elem()) + ">"
|
|
@@ -7975,6 +8029,13 @@ func (o *LoweringOwner) lowerPointerReceiverMethodCall(
|
|
|
7975
8029
|
methodMemberName(selector.Sel.Name) + "(" + strings.Join(args, ", ") + ")"
|
|
7976
8030
|
return call, diagnostics, true
|
|
7977
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
|
+
}
|
|
7978
8039
|
if crossPackageUnexportedNamedType(ctx, receiver) {
|
|
7979
8040
|
call := o.runtimeOwner.QualifiedHelper(RuntimeHelperPointerValue) +
|
|
7980
8041
|
"<any>(" + receiverExpr + ")." + methodMemberName(selector.Sel.Name) +
|
|
@@ -9786,12 +9847,61 @@ func (o *LoweringOwner) runtimeTypeInfoExpr(typ types.Type) string {
|
|
|
9786
9847
|
}
|
|
9787
9848
|
|
|
9788
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 {
|
|
9789
9854
|
typeParam, ok := types.Unalias(typ).(*types.TypeParam)
|
|
9790
|
-
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:
|
|
9791
9903
|
return o.runtimeTypeInfoExpr(typ)
|
|
9792
9904
|
}
|
|
9793
|
-
return "__typeArgs?.[" + strconv.Quote(typeParam.Obj().Name()) + "]?.type ?? " +
|
|
9794
|
-
o.runtimeTypeInfoExpr(typ)
|
|
9795
9905
|
}
|
|
9796
9906
|
|
|
9797
9907
|
func (o *LoweringOwner) runtimeTypeInfoExprWithSeen(typ types.Type, seen map[types.Type]bool) string {
|
|
@@ -9919,6 +10029,40 @@ func (o *LoweringOwner) runtimeStructFieldsExpr(structType *types.Struct, seen m
|
|
|
9919
10029
|
return "[" + strings.Join(fields, ", ") + "]"
|
|
9920
10030
|
}
|
|
9921
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
|
+
|
|
9922
10066
|
func runtimeStructFieldInfoExpr(
|
|
9923
10067
|
runtimeType string,
|
|
9924
10068
|
storageKey string,
|
|
@@ -9983,6 +10127,26 @@ func (o *LoweringOwner) runtimeFunctionTypeInfoWithSeen(signature *types.Signatu
|
|
|
9983
10127
|
return "({ " + strings.Join(parts, ", ") + " } as " + runtimePackage + ".FunctionTypeInfo)"
|
|
9984
10128
|
}
|
|
9985
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
|
+
|
|
9986
10150
|
func (o *LoweringOwner) runtimeSignatureTypes(tuple *types.Tuple, seen map[types.Type]bool) string {
|
|
9987
10151
|
if tuple == nil || tuple.Len() == 0 {
|
|
9988
10152
|
return "[]"
|
|
@@ -9994,6 +10158,17 @@ func (o *LoweringOwner) runtimeSignatureTypes(tuple *types.Tuple, seen map[types
|
|
|
9994
10158
|
return "[" + strings.Join(types, ", ") + "]"
|
|
9995
10159
|
}
|
|
9996
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
|
+
|
|
9997
10172
|
func tsStructFieldName(name string, idx int) string {
|
|
9998
10173
|
if name == "_" {
|
|
9999
10174
|
return "_blank" + strconv.Itoa(idx)
|
|
@@ -10945,6 +11120,7 @@ func (o *LoweringOwner) callNeedsAwait(ctx lowerFileContext, fun ast.Expr) bool
|
|
|
10945
11120
|
return o.functionAsync(ctx, calledFunction(ctx.semPkg.source, fun)) ||
|
|
10946
11121
|
o.overrideCallNeedsAwait(ctx, fun) ||
|
|
10947
11122
|
callUsesFunctionValue(ctx.semPkg.source, fun) ||
|
|
11123
|
+
(ctx.asyncFunction && callUsesInterfaceMethod(ctx.semPkg.source, fun)) ||
|
|
10948
11124
|
(ctx.asyncFunction && callUsesFunctionIdentifier(ctx.semPkg.source, fun))
|
|
10949
11125
|
}
|
|
10950
11126
|
if ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
@@ -10953,10 +11129,48 @@ func (o *LoweringOwner) callNeedsAwait(ctx lowerFileContext, fun ast.Expr) bool
|
|
|
10953
11129
|
return o.functionAsync(ctx, calledFunction(ctx.semPkg.source, fun)) ||
|
|
10954
11130
|
o.overrideCallNeedsAwait(ctx, fun) ||
|
|
10955
11131
|
callUsesFunctionValue(ctx.semPkg.source, fun) ||
|
|
11132
|
+
(ctx.asyncFunction && callUsesInterfaceMethod(ctx.semPkg.source, fun)) ||
|
|
10956
11133
|
(ctx.asyncFunction && callUsesFunctionIdentifier(ctx.semPkg.source, fun))
|
|
10957
11134
|
}
|
|
10958
11135
|
}
|
|
10959
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
|
+
|
|
10960
11174
|
func (o *LoweringOwner) overrideCallNeedsAwait(ctx lowerFileContext, fun ast.Expr) bool {
|
|
10961
11175
|
if o.overrideOwner == nil || ctx.semPkg == nil || ctx.semPkg.source == nil {
|
|
10962
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",
|
|
@@ -5,6 +5,7 @@ import (
|
|
|
5
5
|
"go/ast"
|
|
6
6
|
"os"
|
|
7
7
|
"path/filepath"
|
|
8
|
+
"slices"
|
|
8
9
|
"strings"
|
|
9
10
|
)
|
|
10
11
|
|
|
@@ -16,6 +17,13 @@ type protobufTypeScriptBinding struct {
|
|
|
16
17
|
hasOneof bool
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
type protobufTypeScriptBindingOneofCase struct {
|
|
21
|
+
groupLocalName string
|
|
22
|
+
caseLocalName string
|
|
23
|
+
branchCtor string
|
|
24
|
+
valueCtor string
|
|
25
|
+
}
|
|
26
|
+
|
|
19
27
|
func protobufTypeScriptBindings(semPkg *semanticPackage, options LoweringOptions) (map[string]protobufTypeScriptBinding, []Diagnostic) {
|
|
20
28
|
if semPkg == nil || semPkg.source == nil || !options.ProtobufTypeScriptBinding {
|
|
21
29
|
return nil, nil
|
|
@@ -291,6 +299,7 @@ func rewriteProtobufTypeScriptBindingFile(file *loweredFile, binding protobufTyp
|
|
|
291
299
|
source: binding.importSource,
|
|
292
300
|
sideEffect: true,
|
|
293
301
|
})
|
|
302
|
+
oneofCases := protobufTypeScriptBindingOneofCases(file)
|
|
294
303
|
var setupDecls []loweredDecl
|
|
295
304
|
for _, decl := range file.decls {
|
|
296
305
|
if decl.structType == nil {
|
|
@@ -306,7 +315,7 @@ func rewriteProtobufTypeScriptBindingFile(file *loweredFile, binding protobufTyp
|
|
|
306
315
|
if !ok {
|
|
307
316
|
continue
|
|
308
317
|
}
|
|
309
|
-
setup := protobufTypeScriptBindingStructSetupDecl(decl.structType, importAlias, messageName)
|
|
318
|
+
setup := protobufTypeScriptBindingStructSetupDecl(decl.structType, importAlias, messageName, oneofCases[decl.structType.name])
|
|
310
319
|
if setup.code != "" {
|
|
311
320
|
setupDecls = append(setupDecls, setup)
|
|
312
321
|
}
|
|
@@ -314,6 +323,102 @@ func rewriteProtobufTypeScriptBindingFile(file *loweredFile, binding protobufTyp
|
|
|
314
323
|
file.decls = append(file.decls, setupDecls...)
|
|
315
324
|
}
|
|
316
325
|
|
|
326
|
+
func protobufTypeScriptBindingOneofCases(file *loweredFile) map[string][]protobufTypeScriptBindingOneofCase {
|
|
327
|
+
parentByName := make(map[string]*loweredStruct)
|
|
328
|
+
for _, decl := range file.decls {
|
|
329
|
+
if decl.structType != nil {
|
|
330
|
+
parentByName[decl.structType.name] = decl.structType
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
out := make(map[string][]protobufTypeScriptBindingOneofCase)
|
|
334
|
+
for _, decl := range file.decls {
|
|
335
|
+
branch := decl.structType
|
|
336
|
+
if branch == nil || !strings.Contains(branch.name, "_") {
|
|
337
|
+
continue
|
|
338
|
+
}
|
|
339
|
+
parent := protobufTypeScriptBindingOneofParent(branch.name, parentByName)
|
|
340
|
+
if parent == nil {
|
|
341
|
+
continue
|
|
342
|
+
}
|
|
343
|
+
groups := protobufTypeScriptBindingOneofGroups(parent)
|
|
344
|
+
if len(groups) == 0 {
|
|
345
|
+
continue
|
|
346
|
+
}
|
|
347
|
+
groupLocalName := protobufTypeScriptBindingOneofCaseGroup(branch, parent, groups)
|
|
348
|
+
if groupLocalName == "" {
|
|
349
|
+
continue
|
|
350
|
+
}
|
|
351
|
+
for _, field := range branch.fields {
|
|
352
|
+
if !strings.Contains(field.tag, "oneof") {
|
|
353
|
+
continue
|
|
354
|
+
}
|
|
355
|
+
out[parent.name] = append(out[parent.name], protobufTypeScriptBindingOneofCase{
|
|
356
|
+
groupLocalName: groupLocalName,
|
|
357
|
+
caseLocalName: protobufTypeScriptBindingFieldLocalName(field),
|
|
358
|
+
branchCtor: branch.name,
|
|
359
|
+
valueCtor: protobufTypeScriptBindingFieldCtor(field),
|
|
360
|
+
})
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
for parentName := range out {
|
|
364
|
+
slices.SortFunc(out[parentName], func(left, right protobufTypeScriptBindingOneofCase) int {
|
|
365
|
+
if left.groupLocalName != right.groupLocalName {
|
|
366
|
+
return strings.Compare(left.groupLocalName, right.groupLocalName)
|
|
367
|
+
}
|
|
368
|
+
return strings.Compare(left.caseLocalName, right.caseLocalName)
|
|
369
|
+
})
|
|
370
|
+
}
|
|
371
|
+
return out
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
func protobufTypeScriptBindingOneofParent(branchName string, parents map[string]*loweredStruct) *loweredStruct {
|
|
375
|
+
var parent *loweredStruct
|
|
376
|
+
for name, candidate := range parents {
|
|
377
|
+
if name == branchName || !strings.HasPrefix(branchName, name+"_") {
|
|
378
|
+
continue
|
|
379
|
+
}
|
|
380
|
+
if parent == nil || len(name) > len(parent.name) {
|
|
381
|
+
parent = candidate
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return parent
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
func protobufTypeScriptBindingOneofGroups(parent *loweredStruct) map[string]string {
|
|
388
|
+
groups := make(map[string]string)
|
|
389
|
+
for _, field := range parent.fields {
|
|
390
|
+
if !strings.Contains(field.tag, "protobuf_oneof") {
|
|
391
|
+
continue
|
|
392
|
+
}
|
|
393
|
+
localName := protobufTypeScriptBindingTagValue(field.tag, "protobuf_oneof:\"")
|
|
394
|
+
if localName == "" {
|
|
395
|
+
groups[field.name] = protobufTypeScriptBindingFieldLocalName(field)
|
|
396
|
+
continue
|
|
397
|
+
}
|
|
398
|
+
groups[field.name] = protobufTypeScriptBindingProtoCamel(localName)
|
|
399
|
+
}
|
|
400
|
+
return groups
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
func protobufTypeScriptBindingOneofCaseGroup(branch, parent *loweredStruct, groups map[string]string) string {
|
|
404
|
+
if len(groups) == 1 {
|
|
405
|
+
for _, localName := range groups {
|
|
406
|
+
return localName
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
prefix := "is" + parent.name + "_"
|
|
410
|
+
for _, method := range branch.methods {
|
|
411
|
+
groupName, ok := strings.CutPrefix(method.name, prefix)
|
|
412
|
+
if !ok {
|
|
413
|
+
continue
|
|
414
|
+
}
|
|
415
|
+
if localName := groups[groupName]; localName != "" {
|
|
416
|
+
return localName
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return ""
|
|
420
|
+
}
|
|
421
|
+
|
|
317
422
|
func protobufTypeScriptBindingSyntheticMapEntry(name string) bool {
|
|
318
423
|
return strings.Contains(name, "_") && strings.HasSuffix(name, "Entry")
|
|
319
424
|
}
|
|
@@ -466,23 +571,66 @@ func protobufBindingParam(method *loweredFunction, idx int, fallback string) str
|
|
|
466
571
|
return method.params[idx].name
|
|
467
572
|
}
|
|
468
573
|
|
|
469
|
-
func protobufTypeScriptBindingStructSetupDecl(structType *loweredStruct, importAlias, messageName string) loweredDecl {
|
|
574
|
+
func protobufTypeScriptBindingStructSetupDecl(structType *loweredStruct, importAlias, messageName string, oneofCases []protobufTypeScriptBindingOneofCase) loweredDecl {
|
|
470
575
|
if structType == nil {
|
|
471
576
|
return loweredDecl{}
|
|
472
577
|
}
|
|
473
578
|
if messageName == "" {
|
|
474
579
|
messageName = structType.name
|
|
475
580
|
}
|
|
476
|
-
|
|
581
|
+
fieldEntries := make(map[string]string)
|
|
477
582
|
for _, field := range structType.fields {
|
|
478
583
|
ctor := protobufTypeScriptBindingFieldCtor(field)
|
|
479
584
|
if ctor == "" {
|
|
480
585
|
continue
|
|
481
586
|
}
|
|
482
|
-
|
|
587
|
+
fieldEntries[protobufTypeScriptBindingFieldLocalName(field)] = ctor
|
|
588
|
+
}
|
|
589
|
+
for _, oneofCase := range oneofCases {
|
|
590
|
+
if oneofCase.valueCtor != "" {
|
|
591
|
+
fieldEntries[oneofCase.caseLocalName] = oneofCase.valueCtor
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
fieldNames := make([]string, 0, len(fieldEntries))
|
|
595
|
+
for name := range fieldEntries {
|
|
596
|
+
fieldNames = append(fieldNames, name)
|
|
597
|
+
}
|
|
598
|
+
slices.Sort(fieldNames)
|
|
599
|
+
entries := make([]string, 0, len(fieldNames))
|
|
600
|
+
for _, name := range fieldNames {
|
|
601
|
+
entries = append(entries, strconvQuote(name)+": "+fieldEntries[name])
|
|
602
|
+
}
|
|
603
|
+
code := "(" + structType.name + " as any).__protobufTypeScriptMessage = " + importAlias + "." + messageName + ";\n" +
|
|
604
|
+
"(" + structType.name + " as any).__protobufTypeScriptFields = {" + strings.Join(entries, ", ") + "};"
|
|
605
|
+
if len(oneofCases) != 0 {
|
|
606
|
+
code += "\n(" + structType.name + " as any).__protobufTypeScriptOneofFields = " + protobufTypeScriptBindingOneofFieldsLiteral(oneofCases) + ";"
|
|
607
|
+
}
|
|
608
|
+
return loweredDecl{code: code}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
func protobufTypeScriptBindingOneofFieldsLiteral(oneofCases []protobufTypeScriptBindingOneofCase) string {
|
|
612
|
+
groups := make(map[string][]protobufTypeScriptBindingOneofCase)
|
|
613
|
+
for _, oneofCase := range oneofCases {
|
|
614
|
+
groups[oneofCase.groupLocalName] = append(groups[oneofCase.groupLocalName], oneofCase)
|
|
615
|
+
}
|
|
616
|
+
groupNames := make([]string, 0, len(groups))
|
|
617
|
+
for name := range groups {
|
|
618
|
+
groupNames = append(groupNames, name)
|
|
619
|
+
}
|
|
620
|
+
slices.Sort(groupNames)
|
|
621
|
+
entries := make([]string, 0, len(groupNames))
|
|
622
|
+
for _, groupName := range groupNames {
|
|
623
|
+
cases := groups[groupName]
|
|
624
|
+
slices.SortFunc(cases, func(left, right protobufTypeScriptBindingOneofCase) int {
|
|
625
|
+
return strings.Compare(left.caseLocalName, right.caseLocalName)
|
|
626
|
+
})
|
|
627
|
+
caseEntries := make([]string, 0, len(cases))
|
|
628
|
+
for _, oneofCase := range cases {
|
|
629
|
+
caseEntries = append(caseEntries, strconvQuote(oneofCase.caseLocalName)+": "+oneofCase.branchCtor)
|
|
630
|
+
}
|
|
631
|
+
entries = append(entries, strconvQuote(groupName)+": {"+strings.Join(caseEntries, ", ")+"}")
|
|
483
632
|
}
|
|
484
|
-
return
|
|
485
|
-
"(" + structType.name + " as any).__protobufTypeScriptFields = {" + strings.Join(entries, ", ") + "};"}
|
|
633
|
+
return "{" + strings.Join(entries, ", ") + "}"
|
|
486
634
|
}
|
|
487
635
|
|
|
488
636
|
func protobufTypeScriptBindingFieldLocalName(field loweredStructField) string {
|