goscript 0.0.24 → 0.0.25
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 +1 -1
- package/cmd/goscript/cmd_compile.go +17 -1
- package/compiler/analysis.go +1 -1
- package/compiler/builtin_test.go +2 -14
- package/compiler/compiler.go +231 -11
- package/compiler/decl.go +7 -1
- package/compiler/expr-call.go +212 -2
- package/compiler/expr.go +46 -2
- package/compiler/field.go +4 -4
- package/compiler/stmt-range.go +204 -1
- package/compiler/type.go +47 -4
- package/dist/gs/builtin/builtin.d.ts +9 -0
- package/dist/gs/builtin/builtin.js +9 -0
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/channel.d.ts +193 -0
- package/dist/gs/builtin/channel.js.map +1 -1
- package/dist/gs/builtin/defer.d.ts +38 -0
- package/dist/gs/builtin/defer.js.map +1 -1
- package/dist/gs/builtin/index.d.ts +1 -0
- package/dist/gs/builtin/index.js +2 -0
- package/dist/gs/builtin/index.js.map +1 -0
- package/dist/gs/builtin/io.d.ts +16 -0
- package/dist/gs/builtin/io.js.map +1 -1
- package/dist/gs/builtin/map.d.ts +33 -0
- package/dist/gs/builtin/map.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +173 -0
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.d.ts +203 -0
- package/dist/gs/builtin/type.js +1 -2
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/builtin/varRef.d.ts +14 -0
- package/dist/gs/builtin/varRef.js.map +1 -1
- package/dist/gs/cmp/index.d.ts +4 -0
- package/dist/gs/cmp/index.js +27 -0
- package/dist/gs/cmp/index.js.map +1 -0
- package/dist/gs/context/context.d.ts +26 -0
- package/dist/gs/context/context.js +287 -37
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/context/index.d.ts +1 -0
- package/dist/gs/internal/goarch/index.d.ts +6 -0
- package/dist/gs/internal/goarch/index.js +14 -0
- package/dist/gs/internal/goarch/index.js.map +1 -0
- package/dist/gs/iter/index.d.ts +1 -0
- package/dist/gs/iter/index.js +2 -0
- package/dist/gs/iter/index.js.map +1 -0
- package/dist/gs/iter/iter.d.ts +4 -0
- package/dist/gs/iter/iter.js +91 -0
- package/dist/gs/iter/iter.js.map +1 -0
- package/dist/gs/math/bits/index.d.ts +47 -0
- package/dist/gs/math/bits/index.js +298 -0
- package/dist/gs/math/bits/index.js.map +1 -0
- package/dist/gs/runtime/index.d.ts +1 -0
- package/dist/gs/runtime/runtime.d.ts +41 -0
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/slices/index.d.ts +1 -0
- package/dist/gs/slices/index.js +2 -0
- package/dist/gs/slices/index.js.map +1 -0
- package/dist/gs/slices/slices.d.ts +8 -0
- package/dist/gs/slices/slices.js +20 -0
- package/dist/gs/slices/slices.js.map +1 -0
- package/dist/gs/time/index.d.ts +1 -0
- package/dist/gs/time/time.d.ts +57 -0
- package/dist/gs/time/time.js +103 -10
- package/dist/gs/time/time.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -95,7 +95,7 @@ func main() {
|
|
|
95
95
|
|
|
96
96
|
// Compile the desired Go package(s)
|
|
97
97
|
// Replace "." with the specific Go import path of the package you want to compile
|
|
98
|
-
if err := comp.CompilePackages(context.Background(), "your/go/package/path"); err != nil {
|
|
98
|
+
if _, err := comp.CompilePackages(context.Background(), "your/go/package/path"); err != nil {
|
|
99
99
|
log.Fatalf("compilation failed: %v", err)
|
|
100
100
|
}
|
|
101
101
|
|
|
@@ -62,6 +62,21 @@ var CompileCommands = []*cli.Command{{
|
|
|
62
62
|
Destination: &cliCompilerBuildFlags,
|
|
63
63
|
EnvVars: []string{"GOSCRIPT_BUILD_FLAGS"},
|
|
64
64
|
},
|
|
65
|
+
&cli.BoolFlag{
|
|
66
|
+
Name: "disable-emit-builtin",
|
|
67
|
+
Usage: "disable emitting built-in packages that have handwritten equivalents",
|
|
68
|
+
Destination: &cliCompilerConfig.DisableEmitBuiltin,
|
|
69
|
+
Value: false,
|
|
70
|
+
EnvVars: []string{"GOSCRIPT_DISABLE_EMIT_BUILTIN"},
|
|
71
|
+
},
|
|
72
|
+
&cli.BoolFlag{
|
|
73
|
+
Name: "all-dependencies",
|
|
74
|
+
Usage: "compile all dependencies of the requested packages",
|
|
75
|
+
Aliases: []string{"all-deps", "deps"},
|
|
76
|
+
Destination: &cliCompilerConfig.AllDependencies,
|
|
77
|
+
Value: false,
|
|
78
|
+
EnvVars: []string{"GOSCRIPT_ALL_DEPENDENCIES"},
|
|
79
|
+
},
|
|
65
80
|
},
|
|
66
81
|
}}
|
|
67
82
|
|
|
@@ -75,5 +90,6 @@ func compilePackage(c *cli.Context) error {
|
|
|
75
90
|
// build flags
|
|
76
91
|
cliCompilerConfig.BuildFlags = slices.Clone(cliCompilerBuildFlags.Value())
|
|
77
92
|
|
|
78
|
-
|
|
93
|
+
_, err := cliCompiler.CompilePackages(context.Background(), pkgs...)
|
|
94
|
+
return err
|
|
79
95
|
}
|
package/compiler/analysis.go
CHANGED
|
@@ -553,7 +553,7 @@ func (v *analysisVisitor) Visit(node ast.Node) ast.Visitor {
|
|
|
553
553
|
// Standalone &x doesn't directly assign, but its usage in assignments
|
|
554
554
|
// or function calls determines varRefing. Assignments are handled below.
|
|
555
555
|
// Function calls like foo(&x) would require different tracking if needed.
|
|
556
|
-
//
|
|
556
|
+
// TODO: for now, we focus on assignments
|
|
557
557
|
return v
|
|
558
558
|
|
|
559
559
|
case *ast.CallExpr:
|
package/compiler/builtin_test.go
CHANGED
|
@@ -37,7 +37,7 @@ func TestEmitBuiltinOption(t *testing.T) {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
// Compile a package that depends on builtin (time)
|
|
40
|
-
err = compiler.CompilePackages(context.Background(), "time")
|
|
40
|
+
_, err = compiler.CompilePackages(context.Background(), "time")
|
|
41
41
|
if err != nil {
|
|
42
42
|
t.Fatalf("Compilation failed: %v", err)
|
|
43
43
|
}
|
|
@@ -76,23 +76,11 @@ func TestEmitBuiltinOption(t *testing.T) {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
// Compile a package that depends on builtin (time)
|
|
79
|
-
err = compiler.CompilePackages(context.Background(), "time")
|
|
79
|
+
_, err = compiler.CompilePackages(context.Background(), "time")
|
|
80
80
|
if err != nil {
|
|
81
81
|
t.Fatalf("Compilation failed: %v", err)
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
// Check that the unsafe package was copied to the output
|
|
85
|
-
unsafePath := filepath.Join(outputDir, "@goscript/unsafe")
|
|
86
|
-
if _, err := os.Stat(unsafePath); os.IsNotExist(err) {
|
|
87
|
-
t.Errorf("unsafe package was not emitted when DisableEmitBuiltin=false")
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Also check for runtime package
|
|
91
|
-
runtimePath := filepath.Join(outputDir, "@goscript/runtime")
|
|
92
|
-
if _, err := os.Stat(runtimePath); os.IsNotExist(err) {
|
|
93
|
-
t.Errorf("runtime package was not emitted when DisableEmitBuiltin=false")
|
|
94
|
-
}
|
|
95
|
-
|
|
96
84
|
// Time package should also have been emitted
|
|
97
85
|
timePath := filepath.Join(outputDir, "@goscript/time")
|
|
98
86
|
if _, err := os.Stat(timePath); os.IsNotExist(err) {
|
package/compiler/compiler.go
CHANGED
|
@@ -11,6 +11,8 @@ import (
|
|
|
11
11
|
"slices"
|
|
12
12
|
"strings"
|
|
13
13
|
|
|
14
|
+
"go/constant"
|
|
15
|
+
|
|
14
16
|
gs "github.com/aperturerobotics/goscript"
|
|
15
17
|
"github.com/sirupsen/logrus"
|
|
16
18
|
"golang.org/x/tools/go/packages"
|
|
@@ -72,6 +74,16 @@ func NewCompiler(conf *Config, le *logrus.Entry, opts *packages.Config) (*Compil
|
|
|
72
74
|
return &Compiler{config: *conf, le: le, opts: *opts}, nil
|
|
73
75
|
}
|
|
74
76
|
|
|
77
|
+
// CompilationResult contains information about what was compiled
|
|
78
|
+
type CompilationResult struct {
|
|
79
|
+
// CompiledPackages contains the package paths of all packages that were actually compiled to TypeScript
|
|
80
|
+
CompiledPackages []string
|
|
81
|
+
// CopiedPackages contains the package paths of all packages that were copied from handwritten sources
|
|
82
|
+
CopiedPackages []string
|
|
83
|
+
// OriginalPackages contains the package paths that were explicitly requested for compilation
|
|
84
|
+
OriginalPackages []string
|
|
85
|
+
}
|
|
86
|
+
|
|
75
87
|
// CompilePackages loads Go packages based on the provided patterns and
|
|
76
88
|
// then compiles each loaded package into TypeScript. It uses the context for
|
|
77
89
|
// cancellation and applies the compiler's configured options during package loading.
|
|
@@ -79,7 +91,8 @@ func NewCompiler(conf *Config, le *logrus.Entry, opts *packages.Config) (*Compil
|
|
|
79
91
|
// invokes its `Compile` method.
|
|
80
92
|
// If c.config.AllDependencies is true, it will also compile all dependencies
|
|
81
93
|
// of the requested packages, including standard library dependencies.
|
|
82
|
-
|
|
94
|
+
// Returns a CompilationResult with information about what was compiled.
|
|
95
|
+
func (c *Compiler) CompilePackages(ctx context.Context, patterns ...string) (*CompilationResult, error) {
|
|
83
96
|
opts := c.opts
|
|
84
97
|
opts.Context = ctx
|
|
85
98
|
|
|
@@ -87,7 +100,7 @@ func (c *Compiler) CompilePackages(ctx context.Context, patterns ...string) erro
|
|
|
87
100
|
opts.Mode |= packages.NeedImports
|
|
88
101
|
pkgs, err := packages.Load(&opts, patterns...)
|
|
89
102
|
if err != nil {
|
|
90
|
-
return fmt.Errorf("failed to load packages: %w", err)
|
|
103
|
+
return nil, fmt.Errorf("failed to load packages: %w", err)
|
|
91
104
|
}
|
|
92
105
|
|
|
93
106
|
// build a list of packages that patterns matched
|
|
@@ -96,12 +109,23 @@ func (c *Compiler) CompilePackages(ctx context.Context, patterns ...string) erro
|
|
|
96
109
|
patternPkgPaths = append(patternPkgPaths, pkg.PkgPath)
|
|
97
110
|
}
|
|
98
111
|
|
|
112
|
+
result := &CompilationResult{
|
|
113
|
+
OriginalPackages: patternPkgPaths,
|
|
114
|
+
}
|
|
115
|
+
|
|
99
116
|
// If AllDependencies is true, we need to collect all dependencies
|
|
100
117
|
if c.config.AllDependencies {
|
|
101
118
|
// Create a set to track processed packages by their ID
|
|
102
119
|
processed := make(map[string]bool)
|
|
103
120
|
var allPkgs []*packages.Package
|
|
104
121
|
|
|
122
|
+
// Helper function to check if a package has a handwritten equivalent
|
|
123
|
+
hasHandwrittenEquivalent := func(pkgPath string) bool {
|
|
124
|
+
gsSourcePath := "gs/" + pkgPath
|
|
125
|
+
_, gsErr := gs.GsOverrides.ReadDir(gsSourcePath)
|
|
126
|
+
return gsErr == nil
|
|
127
|
+
}
|
|
128
|
+
|
|
105
129
|
// Visit all packages and their dependencies
|
|
106
130
|
var visit func(pkg *packages.Package)
|
|
107
131
|
visit = func(pkg *packages.Package) {
|
|
@@ -109,8 +133,17 @@ func (c *Compiler) CompilePackages(ctx context.Context, patterns ...string) erro
|
|
|
109
133
|
return
|
|
110
134
|
}
|
|
111
135
|
processed[pkg.ID] = true
|
|
136
|
+
|
|
137
|
+
// Add this package to the list of all packages
|
|
112
138
|
allPkgs = append(allPkgs, pkg)
|
|
113
139
|
|
|
140
|
+
// Check if this package has a handwritten equivalent
|
|
141
|
+
if hasHandwrittenEquivalent(pkg.PkgPath) {
|
|
142
|
+
// Add this package but don't visit its dependencies
|
|
143
|
+
c.le.Debugf("Skipping dependencies of handwritten package: %s", pkg.PkgPath)
|
|
144
|
+
return
|
|
145
|
+
}
|
|
146
|
+
|
|
114
147
|
// Visit all imports, including standard library packages
|
|
115
148
|
for _, imp := range pkg.Imports {
|
|
116
149
|
visit(imp)
|
|
@@ -146,18 +179,31 @@ func (c *Compiler) CompilePackages(ctx context.Context, patterns ...string) erro
|
|
|
146
179
|
*/
|
|
147
180
|
}
|
|
148
181
|
|
|
182
|
+
// If DisableEmitBuiltin is false, we need to copy the builtin package to the output directory
|
|
183
|
+
if !c.config.DisableEmitBuiltin {
|
|
184
|
+
c.le.Infof("Copying builtin package to output directory")
|
|
185
|
+
builtinPath := "gs/builtin"
|
|
186
|
+
outputPath := ComputeModulePath(c.config.OutputPath, "builtin")
|
|
187
|
+
if err := c.copyEmbeddedPackage(builtinPath, outputPath); err != nil {
|
|
188
|
+
return nil, fmt.Errorf("failed to copy builtin package to output directory: %w", err)
|
|
189
|
+
}
|
|
190
|
+
result.CopiedPackages = append(result.CopiedPackages, "builtin")
|
|
191
|
+
}
|
|
192
|
+
|
|
149
193
|
// Compile all packages
|
|
150
194
|
for _, pkg := range pkgs {
|
|
151
195
|
// Check if the package has a handwritten equivalent
|
|
196
|
+
// If the package was explicitly requested, skip this logic
|
|
152
197
|
if !slices.Contains(patternPkgPaths, pkg.PkgPath) {
|
|
153
198
|
gsSourcePath := "gs/" + pkg.PkgPath
|
|
154
199
|
_, gsErr := gs.GsOverrides.ReadDir(gsSourcePath)
|
|
155
200
|
if gsErr != nil && !os.IsNotExist(gsErr) {
|
|
156
|
-
return gsErr
|
|
201
|
+
return nil, gsErr
|
|
157
202
|
}
|
|
158
203
|
if gsErr == nil {
|
|
159
204
|
if c.config.DisableEmitBuiltin {
|
|
160
205
|
c.le.Infof("Skipping compilation for overridden package %s", pkg.PkgPath)
|
|
206
|
+
result.CopiedPackages = append(result.CopiedPackages, pkg.PkgPath)
|
|
161
207
|
continue
|
|
162
208
|
} else {
|
|
163
209
|
// If DisableEmitBuiltin is false, we need to copy the handwritten package to the output directory
|
|
@@ -168,19 +214,20 @@ func (c *Compiler) CompilePackages(ctx context.Context, patterns ...string) erro
|
|
|
168
214
|
|
|
169
215
|
// Remove existing directory if it exists
|
|
170
216
|
if err := os.RemoveAll(outputPath); err != nil {
|
|
171
|
-
return fmt.Errorf("failed to remove existing output directory for %s: %w", pkg.PkgPath, err)
|
|
217
|
+
return nil, fmt.Errorf("failed to remove existing output directory for %s: %w", pkg.PkgPath, err)
|
|
172
218
|
}
|
|
173
219
|
|
|
174
220
|
// Create the output directory
|
|
175
221
|
if err := os.MkdirAll(outputPath, 0o755); err != nil {
|
|
176
|
-
return fmt.Errorf("failed to create output directory for %s: %w", pkg.PkgPath, err)
|
|
222
|
+
return nil, fmt.Errorf("failed to create output directory for %s: %w", pkg.PkgPath, err)
|
|
177
223
|
}
|
|
178
224
|
|
|
179
225
|
// Copy files from embedded FS to output directory
|
|
180
226
|
if err := c.copyEmbeddedPackage(gsSourcePath, outputPath); err != nil {
|
|
181
|
-
return fmt.Errorf("failed to copy embedded package %s: %w", pkg.PkgPath, err)
|
|
227
|
+
return nil, fmt.Errorf("failed to copy embedded package %s: %w", pkg.PkgPath, err)
|
|
182
228
|
}
|
|
183
229
|
|
|
230
|
+
result.CopiedPackages = append(result.CopiedPackages, pkg.PkgPath)
|
|
184
231
|
continue
|
|
185
232
|
}
|
|
186
233
|
}
|
|
@@ -192,17 +239,42 @@ func (c *Compiler) CompilePackages(ctx context.Context, patterns ...string) erro
|
|
|
192
239
|
continue
|
|
193
240
|
}
|
|
194
241
|
|
|
242
|
+
// Check if this is the unsafe package, which is not supported in GoScript
|
|
243
|
+
if pkg.PkgPath == "unsafe" {
|
|
244
|
+
// Find which package depends on unsafe by looking at the import graph
|
|
245
|
+
var dependentPackages []string
|
|
246
|
+
for _, otherPkg := range pkgs {
|
|
247
|
+
if otherPkg.PkgPath != "unsafe" {
|
|
248
|
+
for importPath := range otherPkg.Imports {
|
|
249
|
+
if importPath == "unsafe" {
|
|
250
|
+
dependentPackages = append(dependentPackages, otherPkg.PkgPath)
|
|
251
|
+
break
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
dependentList := "unknown package"
|
|
258
|
+
if len(dependentPackages) > 0 {
|
|
259
|
+
dependentList = strings.Join(dependentPackages, ", ")
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return nil, fmt.Errorf("cannot compile package 'unsafe': GoScript does not support the unsafe package due to its low-level memory operations that are incompatible with TypeScript/JavaScript. This package is required by: %s. Consider using alternative approaches that don't require unsafe operations", dependentList)
|
|
263
|
+
}
|
|
264
|
+
|
|
195
265
|
pkgCompiler, err := NewPackageCompiler(c.le, &c.config, pkg)
|
|
196
266
|
if err != nil {
|
|
197
|
-
return fmt.Errorf("failed to create package compiler for %s: %w", pkg.PkgPath, err)
|
|
267
|
+
return nil, fmt.Errorf("failed to create package compiler for %s: %w", pkg.PkgPath, err)
|
|
198
268
|
}
|
|
199
269
|
|
|
200
270
|
if err := pkgCompiler.Compile(ctx); err != nil {
|
|
201
|
-
return fmt.Errorf("failed to compile package %s: %w", pkg.PkgPath, err)
|
|
271
|
+
return nil, fmt.Errorf("failed to compile package %s: %w", pkg.PkgPath, err)
|
|
202
272
|
}
|
|
273
|
+
|
|
274
|
+
result.CompiledPackages = append(result.CompiledPackages, pkg.PkgPath)
|
|
203
275
|
}
|
|
204
276
|
|
|
205
|
-
return nil
|
|
277
|
+
return result, nil
|
|
206
278
|
}
|
|
207
279
|
|
|
208
280
|
// PackageCompiler is responsible for compiling an entire Go package into
|
|
@@ -433,6 +505,7 @@ func NewGoToTSCompiler(tsw *TSCodeWriter, pkg *packages.Package, analysis *Analy
|
|
|
433
505
|
// WriteIdent translates a Go identifier (`ast.Ident`) used as a value (e.g.,
|
|
434
506
|
// variable, function name) into its TypeScript equivalent.
|
|
435
507
|
// - If the identifier is `nil`, it writes `null`.
|
|
508
|
+
// - If the identifier refers to a constant, it writes the constant's evaluated value.
|
|
436
509
|
// - Otherwise, it writes the identifier's name.
|
|
437
510
|
// - If `accessVarRefedValue` is true and the analysis (`c.analysis.NeedsVarRefAccess`)
|
|
438
511
|
// indicates the variable is variable referenced, `.value` is appended to access the contained value.
|
|
@@ -452,8 +525,22 @@ func (c *GoToTSCompiler) WriteIdent(exp *ast.Ident, accessVarRefedValue bool) {
|
|
|
452
525
|
obj = c.pkg.TypesInfo.Defs[exp]
|
|
453
526
|
}
|
|
454
527
|
|
|
455
|
-
//
|
|
456
|
-
|
|
528
|
+
// Check if this identifier refers to a constant
|
|
529
|
+
if obj != nil {
|
|
530
|
+
if constObj, isConst := obj.(*types.Const); isConst {
|
|
531
|
+
// Only evaluate constants from the current package being compiled
|
|
532
|
+
// Don't evaluate constants from imported packages (they should use their exported names)
|
|
533
|
+
// Special case: predeclared constants like iota have a nil package, so we should evaluate them
|
|
534
|
+
if constObj.Pkg() == c.pkg.Types || constObj.Pkg() == nil {
|
|
535
|
+
// Write the constant's evaluated value instead of the identifier name
|
|
536
|
+
c.writeConstantValue(constObj)
|
|
537
|
+
return
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// Write the identifier name first, sanitizing if it's a reserved word
|
|
543
|
+
c.tsw.WriteLiterally(c.sanitizeIdentifier(exp.Name))
|
|
457
544
|
|
|
458
545
|
// Determine if we need to access .value based on analysis data
|
|
459
546
|
if obj != nil && accessVarRefedValue && c.analysis.NeedsVarRefAccess(obj) {
|
|
@@ -652,9 +739,142 @@ func (c *GoToTSCompiler) WriteDoc(doc *ast.CommentGroup) {
|
|
|
652
739
|
}
|
|
653
740
|
}
|
|
654
741
|
|
|
742
|
+
// sanitizeIdentifier checks if an identifier is a JavaScript/TypeScript reserved word
|
|
743
|
+
// and prefixes it with an underscore if it is. This prevents compilation errors
|
|
744
|
+
// when Go identifiers conflict with JS/TS keywords.
|
|
745
|
+
func (c *GoToTSCompiler) sanitizeIdentifier(name string) string {
|
|
746
|
+
// Don't sanitize boolean literals - they are valid in both Go and JS/TS
|
|
747
|
+
if name == "true" || name == "false" {
|
|
748
|
+
return name
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// List of JavaScript/TypeScript reserved words that could conflict
|
|
752
|
+
reservedWords := map[string]bool{
|
|
753
|
+
"abstract": true,
|
|
754
|
+
"any": true,
|
|
755
|
+
"as": true,
|
|
756
|
+
"asserts": true,
|
|
757
|
+
"async": true,
|
|
758
|
+
"await": true,
|
|
759
|
+
"boolean": true,
|
|
760
|
+
"break": true,
|
|
761
|
+
"case": true,
|
|
762
|
+
"catch": true,
|
|
763
|
+
"class": true,
|
|
764
|
+
"const": true,
|
|
765
|
+
"constructor": true,
|
|
766
|
+
"continue": true,
|
|
767
|
+
"debugger": true,
|
|
768
|
+
"declare": true,
|
|
769
|
+
"default": true,
|
|
770
|
+
"delete": true,
|
|
771
|
+
"do": true,
|
|
772
|
+
"else": true,
|
|
773
|
+
"enum": true,
|
|
774
|
+
"export": true,
|
|
775
|
+
"extends": true,
|
|
776
|
+
"finally": true,
|
|
777
|
+
"for": true,
|
|
778
|
+
"from": true,
|
|
779
|
+
"function": true,
|
|
780
|
+
"get": true,
|
|
781
|
+
"if": true,
|
|
782
|
+
"implements": true,
|
|
783
|
+
"import": true,
|
|
784
|
+
"in": true,
|
|
785
|
+
"instanceof": true,
|
|
786
|
+
"interface": true,
|
|
787
|
+
"is": true,
|
|
788
|
+
"keyof": true,
|
|
789
|
+
"let": true,
|
|
790
|
+
"module": true,
|
|
791
|
+
"namespace": true,
|
|
792
|
+
"never": true,
|
|
793
|
+
"new": true,
|
|
794
|
+
"null": true,
|
|
795
|
+
"number": true,
|
|
796
|
+
"object": true,
|
|
797
|
+
"of": true,
|
|
798
|
+
"package": true,
|
|
799
|
+
"private": true,
|
|
800
|
+
"protected": true,
|
|
801
|
+
"public": true,
|
|
802
|
+
"readonly": true,
|
|
803
|
+
"require": true,
|
|
804
|
+
"return": true,
|
|
805
|
+
"set": true,
|
|
806
|
+
"static": true,
|
|
807
|
+
"string": true,
|
|
808
|
+
"super": true,
|
|
809
|
+
"switch": true,
|
|
810
|
+
"symbol": true,
|
|
811
|
+
"this": true,
|
|
812
|
+
"throw": true,
|
|
813
|
+
"try": true,
|
|
814
|
+
"type": true,
|
|
815
|
+
"typeof": true,
|
|
816
|
+
"undefined": true,
|
|
817
|
+
"unique": true,
|
|
818
|
+
"unknown": true,
|
|
819
|
+
"var": true,
|
|
820
|
+
"void": true,
|
|
821
|
+
"while": true,
|
|
822
|
+
"with": true,
|
|
823
|
+
"yield": true,
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
if reservedWords[name] {
|
|
827
|
+
return "_" + name
|
|
828
|
+
}
|
|
829
|
+
return name
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
// writeConstantValue writes the evaluated value of a Go constant to TypeScript.
|
|
833
|
+
// It handles different constant types (integer, float, string, boolean, complex)
|
|
834
|
+
// and writes the appropriate TypeScript literal.
|
|
835
|
+
func (c *GoToTSCompiler) writeConstantValue(constObj *types.Const) {
|
|
836
|
+
val := constObj.Val()
|
|
837
|
+
|
|
838
|
+
switch val.Kind() {
|
|
839
|
+
case constant.Int:
|
|
840
|
+
// For integer constants, write the string representation
|
|
841
|
+
c.tsw.WriteLiterally(val.String())
|
|
842
|
+
case constant.Float:
|
|
843
|
+
// For float constants, write the string representation
|
|
844
|
+
c.tsw.WriteLiterally(val.String())
|
|
845
|
+
case constant.String:
|
|
846
|
+
// For string constants, write as a quoted string literal
|
|
847
|
+
c.tsw.WriteLiterally(val.String()) // val.String() already includes quotes
|
|
848
|
+
case constant.Bool:
|
|
849
|
+
// For boolean constants, write true/false
|
|
850
|
+
if constant.BoolVal(val) {
|
|
851
|
+
c.tsw.WriteLiterally("true")
|
|
852
|
+
} else {
|
|
853
|
+
c.tsw.WriteLiterally("false")
|
|
854
|
+
}
|
|
855
|
+
case constant.Complex:
|
|
856
|
+
// For complex constants, we need to handle them specially
|
|
857
|
+
// For now, write as a comment indicating unsupported
|
|
858
|
+
c.tsw.WriteLiterally("/* complex constant: " + val.String() + " */")
|
|
859
|
+
default:
|
|
860
|
+
// For unknown constant types, write as a comment
|
|
861
|
+
c.tsw.WriteLiterally("/* unknown constant: " + val.String() + " */")
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
655
865
|
// copyEmbeddedPackage recursively copies files from an embedded FS path to a filesystem directory.
|
|
656
866
|
// It handles both regular files and directories.
|
|
657
867
|
func (c *Compiler) copyEmbeddedPackage(embeddedPath string, outputPath string) error {
|
|
868
|
+
// Remove the output path if it exists
|
|
869
|
+
if err := os.RemoveAll(outputPath); err != nil {
|
|
870
|
+
return fmt.Errorf("failed to remove output directory %s: %w", outputPath, err)
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
// Create the output path
|
|
874
|
+
if err := os.MkdirAll(outputPath, 0o755); err != nil {
|
|
875
|
+
return fmt.Errorf("failed to create output directory %s: %w", outputPath, err)
|
|
876
|
+
}
|
|
877
|
+
|
|
658
878
|
// List the entries in the embedded path
|
|
659
879
|
entries, err := gs.GsOverrides.ReadDir(embeddedPath)
|
|
660
880
|
if err != nil {
|
package/compiler/decl.go
CHANGED
|
@@ -37,7 +37,7 @@ func (c *GoToTSCompiler) WriteDecls(decls []ast.Decl) error {
|
|
|
37
37
|
c.tsw.WriteLine("") // Add space after spec
|
|
38
38
|
}
|
|
39
39
|
default:
|
|
40
|
-
fmt.
|
|
40
|
+
return fmt.Errorf("unknown decl: %#v", decl)
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
return nil
|
|
@@ -79,6 +79,12 @@ func (c *GoToTSCompiler) WriteFuncDeclAsFunction(decl *ast.FuncDecl) error {
|
|
|
79
79
|
if obj := c.pkg.TypesInfo.Defs[decl.Name]; obj != nil {
|
|
80
80
|
isAsync = c.analysis.IsAsyncFunc(obj)
|
|
81
81
|
}
|
|
82
|
+
|
|
83
|
+
// Always make main function async (only in main package)
|
|
84
|
+
if decl.Name.Name == "main" && c.pkg.Name == "main" {
|
|
85
|
+
isAsync = true
|
|
86
|
+
}
|
|
87
|
+
|
|
82
88
|
if isAsync {
|
|
83
89
|
c.tsw.WriteLiterally("async ")
|
|
84
90
|
}
|