goscript 0.0.23 → 0.0.24
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 +1 -1
- package/compiler/analysis.go +73 -131
- package/compiler/analysis_test.go +220 -0
- package/compiler/assignment.go +37 -43
- package/compiler/builtin_test.go +102 -0
- package/compiler/compiler.go +79 -14
- package/compiler/composite-lit.go +108 -43
- package/compiler/config.go +7 -3
- package/compiler/config_test.go +6 -33
- package/compiler/expr-selector.go +66 -41
- package/compiler/expr-star.go +57 -65
- package/compiler/expr-type.go +1 -1
- package/compiler/expr-value.go +1 -1
- package/compiler/expr.go +79 -18
- package/compiler/primitive.go +11 -10
- package/compiler/spec-struct.go +3 -3
- package/compiler/spec-value.go +75 -29
- package/compiler/spec.go +9 -3
- package/compiler/stmt-assign.go +36 -2
- package/compiler/stmt-for.go +11 -0
- package/compiler/stmt-range.go +110 -0
- package/compiler/stmt.go +52 -0
- package/compiler/type.go +36 -11
- package/dist/gs/builtin/builtin.js +37 -0
- package/dist/gs/builtin/builtin.js.map +1 -0
- package/dist/gs/builtin/channel.js +471 -0
- package/dist/gs/builtin/channel.js.map +1 -0
- package/dist/gs/builtin/defer.js +54 -0
- package/dist/gs/builtin/defer.js.map +1 -0
- package/dist/gs/builtin/io.js +15 -0
- package/dist/gs/builtin/io.js.map +1 -0
- package/dist/gs/builtin/map.js +44 -0
- package/dist/gs/builtin/map.js.map +1 -0
- package/dist/gs/builtin/slice.js +799 -0
- package/dist/gs/builtin/slice.js.map +1 -0
- package/dist/gs/builtin/type.js +745 -0
- package/dist/gs/builtin/type.js.map +1 -0
- package/dist/gs/builtin/varRef.js +14 -0
- package/dist/gs/builtin/varRef.js.map +1 -0
- package/dist/gs/context/context.js +55 -0
- package/dist/gs/context/context.js.map +1 -0
- package/dist/gs/context/index.js +2 -0
- package/dist/gs/context/index.js.map +1 -0
- package/dist/gs/runtime/index.js +2 -0
- package/dist/gs/runtime/index.js.map +1 -0
- package/dist/gs/runtime/runtime.js +158 -0
- package/dist/gs/runtime/runtime.js.map +1 -0
- package/dist/gs/time/index.js +2 -0
- package/dist/gs/time/index.js.map +1 -0
- package/dist/gs/time/time.js +115 -0
- package/dist/gs/time/time.js.map +1 -0
- package/package.json +3 -2
package/compiler/assignment.go
CHANGED
|
@@ -21,7 +21,7 @@ import (
|
|
|
21
21
|
// to `$.mapSet(myMap_ts, key_ts, value_ts)`.
|
|
22
22
|
// - Other single-variable assignments (`variable = value`):
|
|
23
23
|
// - The LHS expression is written (caller typically ensures `.value` is appended
|
|
24
|
-
// if assigning to a
|
|
24
|
+
// if assigning to a VarRefed variable's content).
|
|
25
25
|
// - The Go assignment token (`tok`, e.g., `=`, `+=`) is translated to its
|
|
26
26
|
// TypeScript equivalent using `TokenToTs`.
|
|
27
27
|
// - The RHS expression(s) are written. If `shouldApplyClone` indicates the RHS
|
|
@@ -68,10 +68,10 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
68
68
|
return nil
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
// Special handling for
|
|
71
|
+
// Special handling for variable referenced variables in declarations
|
|
72
72
|
if addDeclaration && tok == token.DEFINE {
|
|
73
|
-
// Determine if LHS is
|
|
74
|
-
|
|
73
|
+
// Determine if LHS is variable referenced
|
|
74
|
+
isLHSVarRefed := false
|
|
75
75
|
var lhsIdent *ast.Ident
|
|
76
76
|
var lhsObj types.Object
|
|
77
77
|
|
|
@@ -84,30 +84,22 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
84
84
|
lhsObj = def
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
// Check if this variable needs to be
|
|
88
|
-
if lhsObj != nil && c.analysis.
|
|
89
|
-
|
|
87
|
+
// Check if this variable needs to be variable referenced
|
|
88
|
+
if lhsObj != nil && c.analysis.NeedsVarRef(lhsObj) {
|
|
89
|
+
isLHSVarRefed = true
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
// Special handling for short declaration of
|
|
94
|
-
if
|
|
93
|
+
// Special handling for short declaration of variable referenced variables
|
|
94
|
+
if isLHSVarRefed && lhsIdent != nil {
|
|
95
95
|
c.tsw.WriteLiterally("let ")
|
|
96
96
|
// Just write the identifier name without .value
|
|
97
97
|
c.tsw.WriteLiterally(lhsIdent.Name)
|
|
98
|
-
|
|
99
|
-
// Add type annotation for boxed variables in declarations
|
|
100
|
-
if lhsObj != nil {
|
|
101
|
-
c.tsw.WriteLiterally(": ")
|
|
102
|
-
c.tsw.WriteLiterally("$.Box<")
|
|
103
|
-
c.WriteGoType(lhsObj.Type(), GoTypeContextGeneral)
|
|
104
|
-
c.tsw.WriteLiterally(">")
|
|
105
|
-
}
|
|
106
|
-
|
|
98
|
+
// No type annotation, allow TypeScript to infer it from varRef.
|
|
107
99
|
c.tsw.WriteLiterally(" = ")
|
|
108
100
|
|
|
109
|
-
//
|
|
110
|
-
c.tsw.WriteLiterally("$.
|
|
101
|
+
// Create the variable reference for the initializer
|
|
102
|
+
c.tsw.WriteLiterally("$.varRef(")
|
|
111
103
|
if err := c.WriteValueExpr(rhs[0]); err != nil {
|
|
112
104
|
return err
|
|
113
105
|
}
|
|
@@ -226,12 +218,12 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
226
218
|
}
|
|
227
219
|
|
|
228
220
|
if !currentIsMapIndex {
|
|
229
|
-
// For single assignments, handle
|
|
221
|
+
// For single assignments, handle variable referenced variables specially
|
|
230
222
|
if len(lhs) == 1 && len(rhs) == 1 {
|
|
231
223
|
lhsExprIdent, lhsExprIsIdent := l.(*ast.Ident)
|
|
232
224
|
if lhsExprIsIdent {
|
|
233
|
-
// Determine if LHS is
|
|
234
|
-
|
|
225
|
+
// Determine if LHS is variable referenced
|
|
226
|
+
isLHSVarRefed := false
|
|
235
227
|
var lhsObj types.Object
|
|
236
228
|
|
|
237
229
|
// Get the types.Object from the identifier
|
|
@@ -241,13 +233,13 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
241
233
|
lhsObj = def
|
|
242
234
|
}
|
|
243
235
|
|
|
244
|
-
// Check if this variable needs to be
|
|
245
|
-
if lhsObj != nil && c.analysis.
|
|
246
|
-
|
|
236
|
+
// Check if this variable needs to be variable referenced
|
|
237
|
+
if lhsObj != nil && c.analysis.NeedsVarRef(lhsObj) {
|
|
238
|
+
isLHSVarRefed = true
|
|
247
239
|
}
|
|
248
240
|
|
|
249
|
-
// prevent writing .value unless lhs is
|
|
250
|
-
c.WriteIdent(lhsExprIdent,
|
|
241
|
+
// prevent writing .value unless lhs is variable referenced
|
|
242
|
+
c.WriteIdent(lhsExprIdent, isLHSVarRefed)
|
|
251
243
|
continue
|
|
252
244
|
}
|
|
253
245
|
}
|
|
@@ -279,15 +271,16 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
279
271
|
if i != 0 {
|
|
280
272
|
c.tsw.WriteLiterally(", ")
|
|
281
273
|
}
|
|
282
|
-
|
|
274
|
+
|
|
275
|
+
// Check if we need to access a variable referenced source value and apply clone
|
|
283
276
|
// For struct value assignments, we need to handle:
|
|
284
|
-
// 1.
|
|
285
|
-
// 2.
|
|
286
|
-
// 3.
|
|
287
|
-
// 4.
|
|
277
|
+
// 1. UnVarRefed source, unVarRefed target: source.clone()
|
|
278
|
+
// 2. Variable referenced source, unVarRefed target: source.value.clone()
|
|
279
|
+
// 3. UnVarRefed source, variable referenced target: $.varRef(source)
|
|
280
|
+
// 4. Variable referenced source, variable referenced target: source (straight assignment of the variable reference)
|
|
288
281
|
|
|
289
|
-
// Determine if RHS is a
|
|
290
|
-
|
|
282
|
+
// Determine if RHS is a variable referenced variable (could be a struct or other variable)
|
|
283
|
+
needsVarRefedAccessRHS := false
|
|
291
284
|
var rhsObj types.Object
|
|
292
285
|
|
|
293
286
|
// Check if RHS is an identifier (variable name)
|
|
@@ -298,17 +291,17 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
298
291
|
rhsObj = c.pkg.TypesInfo.Defs[rhsIdent]
|
|
299
292
|
}
|
|
300
293
|
|
|
301
|
-
// Important: For struct copying, we need to check if the variable itself is
|
|
302
|
-
// Important: For struct copying, we need to check if the variable needs
|
|
303
|
-
// This is more comprehensive than just checking if it's
|
|
294
|
+
// Important: For struct copying, we need to check if the variable itself is variable referenced
|
|
295
|
+
// Important: For struct copying, we need to check if the variable needs variable referenced access
|
|
296
|
+
// This is more comprehensive than just checking if it's variable referenced
|
|
304
297
|
if rhsObj != nil {
|
|
305
|
-
|
|
298
|
+
needsVarRefedAccessRHS = c.analysis.NeedsVarRefAccess(rhsObj)
|
|
306
299
|
}
|
|
307
300
|
}
|
|
308
301
|
|
|
309
302
|
// Handle different cases for struct cloning
|
|
310
303
|
if shouldApplyClone(c.pkg, r) {
|
|
311
|
-
// For other expressions, we need to handle
|
|
304
|
+
// For other expressions, we need to handle variable referenced access differently
|
|
312
305
|
if _, isIdent := r.(*ast.Ident); isIdent {
|
|
313
306
|
// For identifiers, WriteValueExpr already adds .value if needed
|
|
314
307
|
if err := c.WriteValueExpr(r); err != nil {
|
|
@@ -319,14 +312,15 @@ func (c *GoToTSCompiler) writeAssignmentCore(lhs, rhs []ast.Expr, tok token.Toke
|
|
|
319
312
|
if err := c.WriteValueExpr(r); err != nil {
|
|
320
313
|
return err
|
|
321
314
|
}
|
|
322
|
-
// Only add .value for non-identifiers that need
|
|
323
|
-
if
|
|
324
|
-
c.tsw.WriteLiterally(".value") // Access the
|
|
315
|
+
// Only add .value for non-identifiers that need variable referenced access
|
|
316
|
+
if needsVarRefedAccessRHS {
|
|
317
|
+
c.tsw.WriteLiterally(".value") // Access the variable referenced value
|
|
325
318
|
}
|
|
326
319
|
}
|
|
327
320
|
|
|
328
321
|
c.tsw.WriteLiterally(".clone()") // Always add clone for struct values
|
|
329
322
|
} else {
|
|
323
|
+
// Non-struct case: write RHS normally
|
|
330
324
|
if err := c.WriteValueExpr(r); err != nil { // RHS is a non-struct value
|
|
331
325
|
return err
|
|
332
326
|
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
package compiler
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"os"
|
|
6
|
+
"path/filepath"
|
|
7
|
+
"testing"
|
|
8
|
+
|
|
9
|
+
"github.com/sirupsen/logrus"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
func TestEmitBuiltinOption(t *testing.T) {
|
|
13
|
+
// Create a temporary directory for the test output
|
|
14
|
+
tempDir, err := os.MkdirTemp("", "goscript-test-emit-builtin")
|
|
15
|
+
if err != nil {
|
|
16
|
+
t.Fatalf("Failed to create temp dir: %v", err)
|
|
17
|
+
}
|
|
18
|
+
defer os.RemoveAll(tempDir)
|
|
19
|
+
|
|
20
|
+
// Setup logger
|
|
21
|
+
log := logrus.New()
|
|
22
|
+
log.SetLevel(logrus.DebugLevel)
|
|
23
|
+
le := logrus.NewEntry(log)
|
|
24
|
+
|
|
25
|
+
// Case 1: DisableEmitBuiltin = true (default behavior in compliance tests)
|
|
26
|
+
t.Run("DisableEmitBuiltin=true", func(t *testing.T) {
|
|
27
|
+
outputDir := filepath.Join(tempDir, "disabled")
|
|
28
|
+
config := &Config{
|
|
29
|
+
OutputPath: outputDir,
|
|
30
|
+
AllDependencies: true,
|
|
31
|
+
DisableEmitBuiltin: true,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
compiler, err := NewCompiler(config, le, nil)
|
|
35
|
+
if err != nil {
|
|
36
|
+
t.Fatalf("Failed to create compiler: %v", err)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Compile a package that depends on builtin (time)
|
|
40
|
+
err = compiler.CompilePackages(context.Background(), "time")
|
|
41
|
+
if err != nil {
|
|
42
|
+
t.Fatalf("Compilation failed: %v", err)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Check that the unsafe package wasn't emitted (we know it's handwritten)
|
|
46
|
+
unsafePath := filepath.Join(outputDir, "@goscript/unsafe")
|
|
47
|
+
if _, err := os.Stat(unsafePath); !os.IsNotExist(err) {
|
|
48
|
+
t.Errorf("unsafe package was emitted when DisableEmitBuiltin=true")
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Also check for runtime package
|
|
52
|
+
runtimePath := filepath.Join(outputDir, "@goscript/runtime")
|
|
53
|
+
if _, err := os.Stat(runtimePath); !os.IsNotExist(err) {
|
|
54
|
+
t.Errorf("runtime package was emitted when DisableEmitBuiltin=true")
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// But time package should have been emitted
|
|
58
|
+
timePath := filepath.Join(outputDir, "@goscript/time")
|
|
59
|
+
if _, err := os.Stat(timePath); os.IsNotExist(err) {
|
|
60
|
+
t.Errorf("time package was not emitted")
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
// Case 2: DisableEmitBuiltin = false (new behavior for third-party projects)
|
|
65
|
+
t.Run("DisableEmitBuiltin=false", func(t *testing.T) {
|
|
66
|
+
outputDir := filepath.Join(tempDir, "enabled")
|
|
67
|
+
config := &Config{
|
|
68
|
+
OutputPath: outputDir,
|
|
69
|
+
AllDependencies: true,
|
|
70
|
+
DisableEmitBuiltin: false,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
compiler, err := NewCompiler(config, le, nil)
|
|
74
|
+
if err != nil {
|
|
75
|
+
t.Fatalf("Failed to create compiler: %v", err)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Compile a package that depends on builtin (time)
|
|
79
|
+
err = compiler.CompilePackages(context.Background(), "time")
|
|
80
|
+
if err != nil {
|
|
81
|
+
t.Fatalf("Compilation failed: %v", err)
|
|
82
|
+
}
|
|
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
|
+
// Time package should also have been emitted
|
|
97
|
+
timePath := filepath.Join(outputDir, "@goscript/time")
|
|
98
|
+
if _, err := os.Stat(timePath); os.IsNotExist(err) {
|
|
99
|
+
t.Errorf("time package was not emitted")
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
}
|
package/compiler/compiler.go
CHANGED
|
@@ -150,13 +150,39 @@ func (c *Compiler) CompilePackages(ctx context.Context, patterns ...string) erro
|
|
|
150
150
|
for _, pkg := range pkgs {
|
|
151
151
|
// Check if the package has a handwritten equivalent
|
|
152
152
|
if !slices.Contains(patternPkgPaths, pkg.PkgPath) {
|
|
153
|
-
|
|
153
|
+
gsSourcePath := "gs/" + pkg.PkgPath
|
|
154
|
+
_, gsErr := gs.GsOverrides.ReadDir(gsSourcePath)
|
|
154
155
|
if gsErr != nil && !os.IsNotExist(gsErr) {
|
|
155
156
|
return gsErr
|
|
156
157
|
}
|
|
157
158
|
if gsErr == nil {
|
|
158
|
-
c.
|
|
159
|
-
|
|
159
|
+
if c.config.DisableEmitBuiltin {
|
|
160
|
+
c.le.Infof("Skipping compilation for overridden package %s", pkg.PkgPath)
|
|
161
|
+
continue
|
|
162
|
+
} else {
|
|
163
|
+
// If DisableEmitBuiltin is false, we need to copy the handwritten package to the output directory
|
|
164
|
+
c.le.Infof("Copying handwritten package %s to output directory", pkg.PkgPath)
|
|
165
|
+
|
|
166
|
+
// Compute output path for this package
|
|
167
|
+
outputPath := ComputeModulePath(c.config.OutputPath, pkg.PkgPath)
|
|
168
|
+
|
|
169
|
+
// Remove existing directory if it exists
|
|
170
|
+
if err := os.RemoveAll(outputPath); err != nil {
|
|
171
|
+
return fmt.Errorf("failed to remove existing output directory for %s: %w", pkg.PkgPath, err)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Create the output directory
|
|
175
|
+
if err := os.MkdirAll(outputPath, 0o755); err != nil {
|
|
176
|
+
return fmt.Errorf("failed to create output directory for %s: %w", pkg.PkgPath, err)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Copy files from embedded FS to output directory
|
|
180
|
+
if err := c.copyEmbeddedPackage(gsSourcePath, outputPath); err != nil {
|
|
181
|
+
return fmt.Errorf("failed to copy embedded package %s: %w", pkg.PkgPath, err)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
continue
|
|
185
|
+
}
|
|
160
186
|
}
|
|
161
187
|
}
|
|
162
188
|
|
|
@@ -202,7 +228,7 @@ func NewPackageCompiler(
|
|
|
202
228
|
le: le,
|
|
203
229
|
pkg: pkg,
|
|
204
230
|
compilerConf: compilerConf,
|
|
205
|
-
outputPath: ComputeModulePath(compilerConf.
|
|
231
|
+
outputPath: ComputeModulePath(compilerConf.OutputPath, pkg.PkgPath),
|
|
206
232
|
}
|
|
207
233
|
|
|
208
234
|
return res, nil
|
|
@@ -287,7 +313,7 @@ func (c *PackageCompiler) generateIndexFile(compiledFiles []string) error {
|
|
|
287
313
|
// CompileFile handles the compilation of a single Go source file to TypeScript.
|
|
288
314
|
// It first performs a pre-compilation analysis of the file using `AnalyzeFile`
|
|
289
315
|
// to gather information necessary for accurate TypeScript generation (e.g.,
|
|
290
|
-
// about
|
|
316
|
+
// about varRefing, async functions, defer statements).
|
|
291
317
|
// Then, it creates a `FileCompiler` instance for the file and invokes its
|
|
292
318
|
// `Compile` method to generate the TypeScript code.
|
|
293
319
|
func (p *PackageCompiler) CompileFile(ctx context.Context, name string, syntax *ast.File) error {
|
|
@@ -351,7 +377,7 @@ func (c *FileCompiler) Compile(ctx context.Context) error {
|
|
|
351
377
|
pkgPath := c.pkg.PkgPath
|
|
352
378
|
|
|
353
379
|
outputFilePath := TranslateGoFilePathToTypescriptFilePath(pkgPath, filepath.Base(c.fullPath))
|
|
354
|
-
outputFilePathAbs := filepath.Join(c.compilerConfig.
|
|
380
|
+
outputFilePathAbs := filepath.Join(c.compilerConfig.OutputPath, outputFilePath)
|
|
355
381
|
|
|
356
382
|
if err := os.MkdirAll(filepath.Dir(outputFilePathAbs), 0o755); err != nil {
|
|
357
383
|
return err
|
|
@@ -382,7 +408,7 @@ func (c *FileCompiler) Compile(ctx context.Context) error {
|
|
|
382
408
|
// GoToTSCompiler is the core component responsible for translating Go AST nodes
|
|
383
409
|
// and type information into TypeScript code. It uses a `TSCodeWriter` to output
|
|
384
410
|
// the generated TypeScript and relies on `Analysis` data to make informed
|
|
385
|
-
// decisions about code generation (e.g.,
|
|
411
|
+
// decisions about code generation (e.g., varRefing, async behavior).
|
|
386
412
|
type GoToTSCompiler struct {
|
|
387
413
|
tsw *TSCodeWriter
|
|
388
414
|
|
|
@@ -408,14 +434,12 @@ func NewGoToTSCompiler(tsw *TSCodeWriter, pkg *packages.Package, analysis *Analy
|
|
|
408
434
|
// variable, function name) into its TypeScript equivalent.
|
|
409
435
|
// - If the identifier is `nil`, it writes `null`.
|
|
410
436
|
// - Otherwise, it writes the identifier's name.
|
|
411
|
-
// - If `
|
|
412
|
-
// indicates
|
|
413
|
-
// in a box (due to its address being taken or other boxing requirements),
|
|
414
|
-
// it appends `.value` to access the actual value from the box.
|
|
437
|
+
// - If `accessVarRefedValue` is true and the analysis (`c.analysis.NeedsVarRefAccess`)
|
|
438
|
+
// indicates the variable is variable referenced, `.value` is appended to access the contained value.
|
|
415
439
|
//
|
|
416
440
|
// This function relies on `go/types` (`TypesInfo.Uses` or `Defs`) to resolve
|
|
417
|
-
// the identifier and the `Analysis` data to determine
|
|
418
|
-
func (c *GoToTSCompiler) WriteIdent(exp *ast.Ident,
|
|
441
|
+
// the identifier and the `Analysis` data to determine varRefing needs.
|
|
442
|
+
func (c *GoToTSCompiler) WriteIdent(exp *ast.Ident, accessVarRefedValue bool) {
|
|
419
443
|
if exp.Name == "nil" {
|
|
420
444
|
c.tsw.WriteLiterally("null")
|
|
421
445
|
return
|
|
@@ -432,7 +456,7 @@ func (c *GoToTSCompiler) WriteIdent(exp *ast.Ident, accessBoxedValue bool) {
|
|
|
432
456
|
c.tsw.WriteLiterally(exp.Name)
|
|
433
457
|
|
|
434
458
|
// Determine if we need to access .value based on analysis data
|
|
435
|
-
if obj != nil &&
|
|
459
|
+
if obj != nil && accessVarRefedValue && c.analysis.NeedsVarRefAccess(obj) {
|
|
436
460
|
c.tsw.WriteLiterally("!.value")
|
|
437
461
|
}
|
|
438
462
|
}
|
|
@@ -627,3 +651,44 @@ func (c *GoToTSCompiler) WriteDoc(doc *ast.CommentGroup) {
|
|
|
627
651
|
}
|
|
628
652
|
}
|
|
629
653
|
}
|
|
654
|
+
|
|
655
|
+
// copyEmbeddedPackage recursively copies files from an embedded FS path to a filesystem directory.
|
|
656
|
+
// It handles both regular files and directories.
|
|
657
|
+
func (c *Compiler) copyEmbeddedPackage(embeddedPath string, outputPath string) error {
|
|
658
|
+
// List the entries in the embedded path
|
|
659
|
+
entries, err := gs.GsOverrides.ReadDir(embeddedPath)
|
|
660
|
+
if err != nil {
|
|
661
|
+
return fmt.Errorf("failed to read embedded directory %s: %w", embeddedPath, err)
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// Process each entry
|
|
665
|
+
for _, entry := range entries {
|
|
666
|
+
entryPath := filepath.Join(embeddedPath, entry.Name())
|
|
667
|
+
outputEntryPath := filepath.Join(outputPath, entry.Name())
|
|
668
|
+
|
|
669
|
+
if entry.IsDir() {
|
|
670
|
+
// Create the output directory
|
|
671
|
+
if err := os.MkdirAll(outputEntryPath, 0o755); err != nil {
|
|
672
|
+
return fmt.Errorf("failed to create output directory %s: %w", outputEntryPath, err)
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// Recursively copy the directory contents
|
|
676
|
+
if err := c.copyEmbeddedPackage(entryPath, outputEntryPath); err != nil {
|
|
677
|
+
return err
|
|
678
|
+
}
|
|
679
|
+
} else {
|
|
680
|
+
// Read the file content from the embedded FS
|
|
681
|
+
content, err := gs.GsOverrides.ReadFile(entryPath)
|
|
682
|
+
if err != nil {
|
|
683
|
+
return fmt.Errorf("failed to read embedded file %s: %w", entryPath, err)
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// Write the content to the output file
|
|
687
|
+
if err := os.WriteFile(outputEntryPath, content, 0o644); err != nil {
|
|
688
|
+
return fmt.Errorf("failed to write file %s: %w", outputEntryPath, err)
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
return nil
|
|
694
|
+
}
|