goscript 0.0.48 → 0.0.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/cmd/goscript/deps.go +1 -4
  2. package/compiler/analysis.go +1120 -513
  3. package/compiler/analysis_test.go +113 -4
  4. package/compiler/compiler.go +88 -124
  5. package/compiler/decl.go +22 -0
  6. package/compiler/expr-call-async.go +46 -52
  7. package/compiler/expr-call-type-conversion.go +144 -59
  8. package/compiler/expr-call.go +235 -12
  9. package/compiler/expr.go +5 -82
  10. package/compiler/gs_dependencies_test.go +60 -1
  11. package/compiler/spec-value.go +73 -51
  12. package/compiler/spec.go +337 -151
  13. package/compiler/stmt-assign.go +7 -4
  14. package/compiler/stmt.go +250 -81
  15. package/compiler/type.go +13 -0
  16. package/dist/gs/builtin/builtin.d.ts +1 -5
  17. package/dist/gs/builtin/builtin.js +1 -34
  18. package/dist/gs/builtin/builtin.js.map +1 -1
  19. package/dist/gs/builtin/slice.js.map +1 -1
  20. package/dist/gs/context/context.d.ts +16 -18
  21. package/dist/gs/context/context.js +23 -13
  22. package/dist/gs/context/context.js.map +1 -1
  23. package/dist/gs/fmt/fmt.js +22 -4
  24. package/dist/gs/fmt/fmt.js.map +1 -1
  25. package/dist/gs/io/fs/fs.d.ts +6 -12
  26. package/dist/gs/io/fs/fs.js +52 -67
  27. package/dist/gs/io/fs/fs.js.map +1 -1
  28. package/dist/gs/os/index.d.ts +2 -1
  29. package/dist/gs/os/index.js +1 -1
  30. package/dist/gs/os/index.js.map +1 -1
  31. package/dist/gs/os/types_js.gs.d.ts +7 -1
  32. package/dist/gs/os/types_js.gs.js +16 -1
  33. package/dist/gs/os/types_js.gs.js.map +1 -1
  34. package/dist/gs/os/types_unix.gs.js +2 -2
  35. package/dist/gs/os/types_unix.gs.js.map +1 -1
  36. package/dist/gs/reflect/index.d.ts +3 -3
  37. package/dist/gs/reflect/index.js +2 -2
  38. package/dist/gs/reflect/index.js.map +1 -1
  39. package/dist/gs/reflect/map.js +2 -2
  40. package/dist/gs/reflect/map.js.map +1 -1
  41. package/dist/gs/reflect/type.d.ts +8 -9
  42. package/dist/gs/reflect/type.js +98 -103
  43. package/dist/gs/reflect/type.js.map +1 -1
  44. package/dist/gs/reflect/types.d.ts +1 -10
  45. package/dist/gs/reflect/types.js +3 -26
  46. package/dist/gs/reflect/types.js.map +1 -1
  47. package/dist/gs/reflect/value.js +23 -23
  48. package/dist/gs/reflect/value.js.map +1 -1
  49. package/dist/gs/reflect/visiblefields.js +3 -3
  50. package/dist/gs/reflect/visiblefields.js.map +1 -1
  51. package/dist/gs/time/time.d.ts +13 -23
  52. package/dist/gs/time/time.js +57 -75
  53. package/dist/gs/time/time.js.map +1 -1
  54. package/gs/builtin/builtin.ts +3 -47
  55. package/gs/builtin/slice.ts +1 -1
  56. package/gs/bytes/meta.json +10 -0
  57. package/gs/context/context.ts +63 -45
  58. package/gs/fmt/fmt.ts +22 -4
  59. package/gs/fmt/meta.json +5 -0
  60. package/gs/internal/meta.json +5 -0
  61. package/gs/io/fs/fs.ts +58 -73
  62. package/gs/io/meta.json +9 -0
  63. package/gs/maps/meta.json +6 -0
  64. package/gs/math/meta.json +5 -0
  65. package/gs/os/index.ts +8 -1
  66. package/gs/os/meta.json +15 -0
  67. package/gs/os/types_js.gs.ts +22 -1
  68. package/gs/os/types_unix.gs.ts +2 -2
  69. package/gs/path/meta.json +6 -0
  70. package/gs/reflect/function-types.test.ts +10 -10
  71. package/gs/reflect/index.ts +6 -6
  72. package/gs/reflect/map.ts +2 -2
  73. package/gs/reflect/meta.json +5 -0
  74. package/gs/reflect/type.ts +105 -105
  75. package/gs/reflect/types.ts +2 -28
  76. package/gs/reflect/value.ts +23 -23
  77. package/gs/reflect/visiblefields.ts +3 -3
  78. package/gs/strconv/meta.json +5 -0
  79. package/gs/strings/meta.json +9 -0
  80. package/gs/sync/meta.json +19 -0
  81. package/gs/time/time.ts +65 -84
  82. package/package.json +2 -2
  83. package/dist/gs/builtin/io.d.ts +0 -16
  84. package/dist/gs/builtin/io.js +0 -15
  85. package/dist/gs/builtin/io.js.map +0 -1
  86. package/dist/gs/internal/testlog/index.d.ts +0 -1
  87. package/dist/gs/internal/testlog/index.js +0 -5
  88. package/dist/gs/internal/testlog/index.js.map +0 -1
  89. package/dist/gs/maps/iter.gs.d.ts +0 -7
  90. package/dist/gs/maps/iter.gs.js +0 -65
  91. package/dist/gs/maps/iter.gs.js.map +0 -1
  92. package/dist/gs/maps/maps.gs.d.ts +0 -7
  93. package/dist/gs/maps/maps.gs.js +0 -79
  94. package/dist/gs/maps/maps.gs.js.map +0 -1
  95. package/dist/gs/reflect/abi.d.ts +0 -59
  96. package/dist/gs/reflect/abi.gs.d.ts +0 -59
  97. package/dist/gs/reflect/abi.gs.js +0 -79
  98. package/dist/gs/reflect/abi.gs.js.map +0 -1
  99. package/dist/gs/reflect/abi.js +0 -79
  100. package/dist/gs/reflect/abi.js.map +0 -1
  101. package/dist/gs/reflect/badlinkname.d.ts +0 -52
  102. package/dist/gs/reflect/badlinkname.gs.d.ts +0 -52
  103. package/dist/gs/reflect/badlinkname.gs.js +0 -72
  104. package/dist/gs/reflect/badlinkname.gs.js.map +0 -1
  105. package/dist/gs/reflect/badlinkname.js +0 -72
  106. package/dist/gs/reflect/badlinkname.js.map +0 -1
  107. package/dist/gs/reflect/deepequal.gs.d.ts +0 -25
  108. package/dist/gs/reflect/deepequal.gs.js +0 -308
  109. package/dist/gs/reflect/deepequal.gs.js.map +0 -1
  110. package/dist/gs/reflect/float32reg_generic.gs.d.ts +0 -2
  111. package/dist/gs/reflect/float32reg_generic.gs.js +0 -10
  112. package/dist/gs/reflect/float32reg_generic.gs.js.map +0 -1
  113. package/dist/gs/reflect/index.gs.d.ts +0 -1
  114. package/dist/gs/reflect/index.gs.js +0 -3
  115. package/dist/gs/reflect/index.gs.js.map +0 -1
  116. package/dist/gs/reflect/iter.gs.d.ts +0 -3
  117. package/dist/gs/reflect/iter.gs.js +0 -24
  118. package/dist/gs/reflect/iter.gs.js.map +0 -1
  119. package/dist/gs/reflect/makefunc.gs.d.ts +0 -34
  120. package/dist/gs/reflect/makefunc.gs.js +0 -288
  121. package/dist/gs/reflect/makefunc.gs.js.map +0 -1
  122. package/dist/gs/reflect/map_swiss.gs.d.ts +0 -14
  123. package/dist/gs/reflect/map_swiss.gs.js +0 -70
  124. package/dist/gs/reflect/map_swiss.gs.js.map +0 -1
  125. package/dist/gs/reflect/reflect.gs.d.ts +0 -132
  126. package/dist/gs/reflect/reflect.gs.js +0 -437
  127. package/dist/gs/reflect/reflect.gs.js.map +0 -1
  128. package/dist/gs/reflect/swapper.gs.d.ts +0 -1
  129. package/dist/gs/reflect/swapper.gs.js +0 -32
  130. package/dist/gs/reflect/swapper.gs.js.map +0 -1
  131. package/dist/gs/reflect/type.gs.d.ts +0 -4
  132. package/dist/gs/reflect/type.gs.js +0 -21
  133. package/dist/gs/reflect/type.gs.js.map +0 -1
  134. package/dist/gs/reflect/value.gs.d.ts +0 -4
  135. package/dist/gs/reflect/value.gs.js +0 -12
  136. package/dist/gs/reflect/value.gs.js.map +0 -1
  137. package/dist/gs/reflect/visiblefields.gs.d.ts +0 -3
  138. package/dist/gs/reflect/visiblefields.gs.js +0 -123
  139. package/dist/gs/reflect/visiblefields.gs.js.map +0 -1
  140. package/dist/gs/stringslite/index.d.ts +0 -1
  141. package/dist/gs/stringslite/index.js +0 -2
  142. package/dist/gs/stringslite/index.js.map +0 -1
  143. package/dist/gs/stringslite/strings.d.ts +0 -11
  144. package/dist/gs/stringslite/strings.js +0 -67
  145. package/dist/gs/stringslite/strings.js.map +0 -1
  146. package/gs/bytes/metadata.go +0 -12
  147. package/gs/fmt/metadata.go +0 -7
  148. package/gs/internal/metadata.go +0 -7
  149. package/gs/io/io.go +0 -75
  150. package/gs/io/metadata.go +0 -11
  151. package/gs/maps/metadata.go +0 -8
  152. package/gs/math/metadata.go +0 -7
  153. package/gs/os/metadata.go +0 -17
  154. package/gs/path/metadata.go +0 -8
  155. package/gs/reflect/metadata.go +0 -7
  156. package/gs/strconv/metadata.go +0 -7
  157. package/gs/strings/metadata.go +0 -11
  158. package/gs/sync/metadata.go +0 -7
  159. package/gs/sync/sync.go +0 -64
package/compiler/spec.go CHANGED
@@ -92,123 +92,240 @@ func (c *GoToTSCompiler) writeVarRefedFieldInitializer(fieldName string, fieldTy
92
92
  c.tsw.WriteLiterally(": $.varRef(")
93
93
 
94
94
  if isEmbedded {
95
- _, isPtr := fieldType.(*types.Pointer)
96
- _, isInterface := fieldType.Underlying().(*types.Interface)
97
- if isPtr || isInterface {
98
- c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
99
- } else {
100
- // Check if the embedded type is an interface
101
- embeddedTypeUnderlying := fieldType
102
- if named, isNamed := embeddedTypeUnderlying.(*types.Named); isNamed {
103
- embeddedTypeUnderlying = named.Underlying()
104
- }
105
- if _, isInterface := embeddedTypeUnderlying.(*types.Interface); isInterface {
106
- // For interfaces, use the provided value or null instead of trying to instantiate
107
- c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
108
- } else {
109
- // For structs, instantiate with provided fields
110
- typeForNew := fieldName
111
- c.tsw.WriteLiterallyf("new %s(init?.%s)", typeForNew, fieldName)
112
- }
113
- }
95
+ c.writeEmbeddedFieldInitializer(fieldName, fieldType)
114
96
  } else {
115
- isStructValueType := false
116
- var structTypeNameForClone string
97
+ c.writeRegularFieldInitializer(fieldName, fieldType, astType)
98
+ }
99
+
100
+ c.tsw.WriteLiterally(")")
101
+ }
102
+
103
+ func (c *GoToTSCompiler) writeEmbeddedFieldInitializer(fieldName string, fieldType types.Type) {
104
+ _, isPtr := fieldType.(*types.Pointer)
105
+ _, isInterface := fieldType.Underlying().(*types.Interface)
106
+
107
+ if isPtr || isInterface {
108
+ c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
109
+ return
110
+ }
111
+
112
+ // Check if the embedded type is an interface
113
+ embeddedTypeUnderlying := fieldType
114
+ if named, isNamed := embeddedTypeUnderlying.(*types.Named); isNamed {
115
+ embeddedTypeUnderlying = named.Underlying()
116
+ }
117
+
118
+ if _, isInterface := embeddedTypeUnderlying.(*types.Interface); isInterface {
119
+ // For interfaces, use the provided value or null instead of trying to instantiate
120
+ c.tsw.WriteLiterallyf("init?.%s ?? null", fieldName)
121
+ return
122
+ }
123
+
124
+ // For structs, instantiate with provided fields
125
+ typeForNew := fieldName
126
+ c.tsw.WriteLiterallyf("new %s(init?.%s)", typeForNew, fieldName)
127
+ }
128
+
129
+ func (c *GoToTSCompiler) writeRegularFieldInitializer(fieldName string, fieldType types.Type, astType ast.Expr) {
130
+ // Check if this is a struct value type that needs cloning
131
+ if c.isStructValueType(fieldType) {
132
+ structTypeNameForClone := c.getTypeString(fieldType)
133
+ c.tsw.WriteLiterallyf("init?.%s?.clone() ?? new %s()", fieldName, structTypeNameForClone)
134
+ return
135
+ }
136
+
137
+ c.tsw.WriteLiterallyf("init?.%s ?? ", fieldName)
138
+
139
+ // Debug for Mode field specifically
140
+ if fieldName == "Mode" {
141
+ fmt.Printf("DEBUG Mode field: Type=%T, String=%s\n", fieldType, fieldType.String())
142
+ }
143
+
144
+ // Priority 1: Check if this is a wrapper type
145
+ if c.analysis.IsNamedBasicType(fieldType) {
146
+ // For wrapper types, use the zero value of the underlying type with type casting
117
147
  if named, ok := fieldType.(*types.Named); ok {
118
- if _, isStruct := named.Underlying().(*types.Struct); isStruct {
119
- isStructValueType = true
120
- structTypeNameForClone = c.getTypeString(fieldType)
121
- }
148
+ c.WriteZeroValueForType(named.Underlying())
149
+ c.tsw.WriteLiterally(" as ")
150
+ c.WriteGoType(fieldType, GoTypeContextGeneral)
151
+ } else if alias, ok := fieldType.(*types.Alias); ok {
152
+ c.WriteZeroValueForType(alias.Underlying())
153
+ c.tsw.WriteLiterally(" as ")
154
+ c.WriteGoType(fieldType, GoTypeContextGeneral)
155
+ } else {
156
+ // Fallback to original behavior
157
+ c.WriteZeroValueForType(fieldType)
122
158
  }
159
+ return
160
+ }
123
161
 
124
- if isStructValueType {
125
- c.tsw.WriteLiterallyf("init?.%s?.clone() ?? new %s()", fieldName, structTypeNameForClone)
126
- } else {
127
- c.tsw.WriteLiterallyf("init?.%s ?? ", fieldName)
128
- // Check if this is a named type or type alias and use constructor instead of null
129
- if named, isNamed := fieldType.(*types.Named); isNamed {
130
- // This is a named type
131
- // Check if underlying type is an interface
132
- if _, isInterface := named.Underlying().(*types.Interface); isInterface {
133
- // For interfaces, use null as the zero value
134
- c.tsw.WriteLiterally("null")
135
- } else if _, isStruct := named.Underlying().(*types.Struct); !isStruct {
136
- // For non-struct, non-interface named types, use constructor
137
- c.tsw.WriteLiterally("new ")
138
- c.WriteNamedType(named)
139
- c.tsw.WriteLiterally("(")
140
- c.WriteZeroValueForType(named.Underlying())
141
- c.tsw.WriteLiterally(")")
142
- } else {
143
- c.WriteZeroValueForType(fieldType)
144
- }
145
- } else if alias, isAlias := fieldType.(*types.Alias); isAlias {
146
- // This is a type alias (like os.FileMode)
147
- // Check if underlying type is an interface
148
- if _, isInterface := alias.Underlying().(*types.Interface); isInterface {
149
- // For interface type aliases, use null as the zero value
150
- c.tsw.WriteLiterally("null")
151
- } else if _, isStruct := alias.Underlying().(*types.Struct); !isStruct {
152
- // For non-struct, non-interface type aliases, use constructor
153
- c.tsw.WriteLiterally("new ")
154
- // Use AST type information if available to preserve qualified names
155
- if astType != nil {
156
- c.WriteTypeExpr(astType)
157
- } else {
158
- c.WriteGoType(fieldType, GoTypeContextGeneral)
159
- }
160
- c.tsw.WriteLiterally("(")
161
- c.WriteZeroValueForType(alias.Underlying())
162
- c.tsw.WriteLiterally(")")
163
- } else {
164
- c.WriteZeroValueForType(fieldType)
165
- }
166
- } else {
167
- c.WriteZeroValueForType(fieldType)
168
- }
162
+ // Priority 2: Handle imported types with basic underlying types (like os.FileMode)
163
+ if c.isImportedBasicType(fieldType) {
164
+ if fieldName == "Mode" {
165
+ fmt.Printf("DEBUG Mode field: Using imported basic type zero value\n")
169
166
  }
167
+ c.writeImportedBasicTypeZeroValue(fieldType)
168
+ return
170
169
  }
171
170
 
172
- c.tsw.WriteLiterally(")")
171
+ // Priority 3: Handle named types
172
+ if named, isNamed := fieldType.(*types.Named); isNamed {
173
+ if fieldName == "Mode" {
174
+ fmt.Printf("DEBUG Mode field: Using named type zero value\n")
175
+ }
176
+ c.writeNamedTypeZeroValue(named)
177
+ return
178
+ }
179
+
180
+ // Priority 4: Handle type aliases
181
+ if alias, isAlias := fieldType.(*types.Alias); isAlias {
182
+ if fieldName == "Mode" {
183
+ fmt.Printf("DEBUG Mode field: Using type alias zero value\n")
184
+ }
185
+ c.writeTypeAliasZeroValue(alias, astType)
186
+ return
187
+ }
188
+
189
+ // Default: use WriteZeroValueForType
190
+ if fieldName == "Mode" {
191
+ fmt.Printf("DEBUG Mode field: Using default WriteZeroValueForType\n")
192
+ }
193
+ c.WriteZeroValueForType(fieldType)
173
194
  }
174
195
 
175
- func (c *GoToTSCompiler) writeClonedFieldInitializer(fieldName string, fieldType types.Type, isEmbedded bool) {
176
- c.tsw.WriteLiterally(fieldName)
177
- c.tsw.WriteLiterally(": $.varRef(")
196
+ func (c *GoToTSCompiler) isStructValueType(fieldType types.Type) bool {
197
+ if named, ok := fieldType.(*types.Named); ok {
198
+ if _, isStruct := named.Underlying().(*types.Struct); isStruct {
199
+ return true
200
+ }
201
+ }
202
+ return false
203
+ }
178
204
 
179
- if isEmbedded {
180
- isPointerToStruct := false
181
- trueType := fieldType
182
- if ptr, isPtr := trueType.(*types.Pointer); isPtr {
183
- trueType = ptr.Elem()
184
- isPointerToStruct = true
205
+ func (c *GoToTSCompiler) isImportedBasicType(fieldType types.Type) bool {
206
+ // Handle named types
207
+ if named, isNamed := fieldType.(*types.Named); isNamed {
208
+ obj := named.Obj()
209
+ if obj == nil || obj.Pkg() == nil || obj.Pkg() == c.pkg.Types {
210
+ return false // Not imported or is local
185
211
  }
186
212
 
187
- if named, isNamed := trueType.(*types.Named); isNamed {
188
- _, isUnderlyingStruct := named.Underlying().(*types.Struct)
189
- if isUnderlyingStruct && !isPointerToStruct { // Is a value struct
190
- c.tsw.WriteLiterallyf("this._fields.%s.value.clone()", fieldName)
191
- } else { // Is a pointer to a struct, or not a struct
192
- c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
193
- }
194
- } else {
195
- c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
213
+ underlying := named.Underlying()
214
+ if underlying == nil {
215
+ return false
196
216
  }
197
- } else {
198
- isValueTypeStruct := false
199
- if named, ok := fieldType.(*types.Named); ok {
200
- if _, isStruct := named.Underlying().(*types.Struct); isStruct {
201
- isValueTypeStruct = true
202
- }
217
+
218
+ _, isBasic := underlying.(*types.Basic)
219
+ return isBasic
220
+ }
221
+
222
+ // Handle type aliases (like os.FileMode = fs.FileMode)
223
+ if alias, isAlias := fieldType.(*types.Alias); isAlias {
224
+ obj := alias.Obj()
225
+ if obj == nil || obj.Pkg() == nil || obj.Pkg() == c.pkg.Types {
226
+ return false // Not imported or is local
203
227
  }
204
228
 
205
- if isValueTypeStruct {
206
- c.tsw.WriteLiterallyf("this._fields.%s.value?.clone() ?? null", fieldName)
207
- } else {
208
- c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
229
+ underlying := alias.Underlying()
230
+ if underlying == nil {
231
+ return false
209
232
  }
233
+
234
+ _, isBasic := underlying.(*types.Basic)
235
+ return isBasic
236
+ }
237
+
238
+ return false
239
+ }
240
+
241
+ func (c *GoToTSCompiler) writeImportedBasicTypeZeroValue(fieldType types.Type) {
242
+ if named, ok := fieldType.(*types.Named); ok {
243
+ underlying := named.Underlying()
244
+ fmt.Printf("DEBUG writeImportedBasicTypeZeroValue: Named type, underlying=%T\n", underlying)
245
+ // Write zero value of underlying type with type casting
246
+ c.WriteZeroValueForType(underlying)
247
+ c.tsw.WriteLiterally(" as ")
248
+ c.WriteGoType(fieldType, GoTypeContextGeneral)
249
+ return
250
+ }
251
+
252
+ if alias, ok := fieldType.(*types.Alias); ok {
253
+ underlying := alias.Underlying()
254
+ fmt.Printf("DEBUG writeImportedBasicTypeZeroValue: Alias type, underlying=%T\n", underlying)
255
+ // Write zero value of underlying type with type casting
256
+ c.WriteZeroValueForType(underlying)
257
+ c.tsw.WriteLiterally(" as ")
258
+ c.WriteGoType(fieldType, GoTypeContextGeneral)
259
+ return
260
+ }
261
+
262
+ // Fallback (should not happen if isImportedBasicType was correct)
263
+ fmt.Printf("DEBUG writeImportedBasicTypeZeroValue: Fallback path\n")
264
+ c.WriteZeroValueForType(fieldType)
265
+ }
266
+
267
+ func (c *GoToTSCompiler) writeNamedTypeZeroValue(named *types.Named) {
268
+ // Check if this is a wrapper type first
269
+ if c.analysis.IsNamedBasicType(named) {
270
+ // For wrapper types, use the zero value of the underlying type with type casting
271
+ c.WriteZeroValueForType(named.Underlying())
272
+ c.tsw.WriteLiterally(" as ")
273
+ c.WriteGoType(named, GoTypeContextGeneral)
274
+ return
275
+ }
276
+
277
+ // Check if underlying type is an interface
278
+ if _, isInterface := named.Underlying().(*types.Interface); isInterface {
279
+ c.tsw.WriteLiterally("null")
280
+ return
281
+ }
282
+
283
+ // Check if underlying type is a struct
284
+ if _, isStruct := named.Underlying().(*types.Struct); isStruct {
285
+ c.WriteZeroValueForType(named)
286
+ return
287
+ }
288
+
289
+ // For non-struct, non-interface named types, use constructor
290
+ c.tsw.WriteLiterally("new ")
291
+ c.WriteNamedType(named)
292
+ c.tsw.WriteLiterally("(")
293
+ c.WriteZeroValueForType(named.Underlying())
294
+ c.tsw.WriteLiterally(")")
295
+ }
296
+
297
+ func (c *GoToTSCompiler) writeTypeAliasZeroValue(alias *types.Alias, astType ast.Expr) {
298
+ // Check if this is a wrapper type first
299
+ if c.analysis.IsNamedBasicType(alias) {
300
+ // For wrapper types, use the zero value of the underlying type with type casting
301
+ c.WriteZeroValueForType(alias.Underlying())
302
+ c.tsw.WriteLiterally(" as ")
303
+ c.WriteGoType(alias, GoTypeContextGeneral)
304
+ return
305
+ }
306
+
307
+ // Check if underlying type is an interface
308
+ if _, isInterface := alias.Underlying().(*types.Interface); isInterface {
309
+ c.tsw.WriteLiterally("null")
310
+ return
210
311
  }
211
312
 
313
+ // Check if underlying type is a struct
314
+ if _, isStruct := alias.Underlying().(*types.Struct); isStruct {
315
+ c.WriteZeroValueForType(alias)
316
+ return
317
+ }
318
+
319
+ // For non-struct, non-interface type aliases, use constructor
320
+ c.tsw.WriteLiterally("new ")
321
+ // Use AST type information if available to preserve qualified names
322
+ if astType != nil {
323
+ c.WriteTypeExpr(astType)
324
+ } else {
325
+ c.WriteGoType(alias, GoTypeContextGeneral)
326
+ }
327
+ c.tsw.WriteLiterally("(")
328
+ c.WriteZeroValueForType(alias.Underlying())
212
329
  c.tsw.WriteLiterally(")")
213
330
  }
214
331
 
@@ -244,7 +361,11 @@ func (c *GoToTSCompiler) hasReceiverMethods(typeName string) bool {
244
361
  return false
245
362
  }
246
363
 
247
- // WriteNamedTypeWithMethods generates a TypeScript class for a Go named type that has receiver methods
364
+ // WriteNamedTypeWithMethods generates TypeScript code for Go named types that have methods.
365
+ // Instead of generating a class, it now generates:
366
+ // 1. A type alias for the underlying type
367
+ // 2. Function declarations for each method (TypeName_MethodName)
368
+ // 3. Function implementations for each method
248
369
  func (c *GoToTSCompiler) WriteNamedTypeWithMethods(a *ast.TypeSpec) error {
249
370
  className := a.Name.Name
250
371
 
@@ -258,49 +379,16 @@ func (c *GoToTSCompiler) WriteNamedTypeWithMethods(a *ast.TypeSpec) error {
258
379
  c.tsw.WriteLiterally("export ")
259
380
  }
260
381
 
261
- c.tsw.WriteLiterallyf("class %s {", className)
262
- c.tsw.WriteLine("")
263
- c.tsw.Indent(1)
264
-
265
- // Constructor that takes the underlying type value
266
- c.tsw.WriteLiterally("constructor(private _value: ")
267
- // Use AST-based type writing to preserve qualified names like os.FileInfo
268
- c.WriteTypeExpr(a.Type)
269
- c.tsw.WriteLine(") {}")
270
- c.tsw.WriteLine("")
271
-
272
- // valueOf method to get the underlying value (for type conversions and operations)
273
- c.tsw.WriteLiterally("valueOf(): ")
274
- // Use AST-based type writing to preserve qualified names like os.FileInfo
275
- c.WriteTypeExpr(a.Type)
276
- c.tsw.WriteLine(" {")
277
- c.tsw.Indent(1)
278
- c.tsw.WriteLine("return this._value")
279
- c.tsw.Indent(-1)
280
- c.tsw.WriteLine("}")
281
- c.tsw.WriteLine("")
282
-
283
- // toString method for string conversion
284
- c.tsw.WriteLine("toString(): string {")
285
- c.tsw.Indent(1)
286
- c.tsw.WriteLine("return String(this._value)")
287
- c.tsw.Indent(-1)
288
- c.tsw.WriteLine("}")
289
- c.tsw.WriteLine("")
290
-
291
- // Static from method for type conversion
292
- c.tsw.WriteLiterallyf("static from(value: ")
382
+ // Generate type alias instead of class
383
+ c.tsw.WriteLiterally("type ")
384
+ c.tsw.WriteLiterally(className)
385
+ c.tsw.WriteLiterally(" = ")
293
386
  // Use AST-based type writing to preserve qualified names like os.FileInfo
294
387
  c.WriteTypeExpr(a.Type)
295
- c.tsw.WriteLiterallyf("): %s {", className)
296
- c.tsw.WriteLine("")
297
- c.tsw.Indent(1)
298
- c.tsw.WriteLiterallyf("return new %s(value)", className)
388
+ c.tsw.WriteLine(";")
299
389
  c.tsw.WriteLine("")
300
- c.tsw.Indent(-1)
301
- c.tsw.WriteLine("}")
302
390
 
303
- // Add receiver methods for this type
391
+ // Generate function declarations and implementations for each method
304
392
  for _, fileSyntax := range c.pkg.Syntax {
305
393
  for _, decl := range fileSyntax.Decls {
306
394
  funcDecl, isFunc := decl.(*ast.FuncDecl)
@@ -324,28 +412,86 @@ func (c *GoToTSCompiler) WriteNamedTypeWithMethods(a *ast.TypeSpec) error {
324
412
  }
325
413
 
326
414
  if recvTypeName == className {
327
- c.tsw.WriteLine("")
328
- if err := c.writeNamedTypeMethod(funcDecl); err != nil {
415
+ if !isInsideFunction {
416
+ c.tsw.WriteLiterally("export ")
417
+ }
418
+
419
+ // Generate function signature: export function TypeName_MethodName(receiver: TypeName, ...args): ReturnType
420
+ c.tsw.WriteLiterally("function ")
421
+ c.tsw.WriteLiterally(className)
422
+ c.tsw.WriteLiterally("_")
423
+ c.tsw.WriteLiterally(funcDecl.Name.Name)
424
+ c.tsw.WriteLiterally("(")
425
+
426
+ // First parameter is the receiver - use the original receiver parameter name
427
+ var receiverParamName string = "receiver" // default fallback
428
+ if funcDecl.Recv != nil && len(funcDecl.Recv.List) > 0 {
429
+ if len(funcDecl.Recv.List[0].Names) > 0 {
430
+ if name := funcDecl.Recv.List[0].Names[0]; name != nil && name.Name != "_" {
431
+ receiverParamName = name.Name
432
+ }
433
+ }
434
+ }
435
+ c.tsw.WriteLiterally(receiverParamName)
436
+ c.tsw.WriteLiterally(": ")
437
+ c.tsw.WriteLiterally(className)
438
+
439
+ // Add other parameters
440
+ if funcDecl.Type.Params != nil && len(funcDecl.Type.Params.List) > 0 {
441
+ c.tsw.WriteLiterally(", ")
442
+ c.WriteFieldList(funcDecl.Type.Params, true) // true = arguments
443
+ }
444
+
445
+ c.tsw.WriteLiterally(")")
446
+
447
+ // Add return type
448
+ if funcDecl.Type.Results != nil && len(funcDecl.Type.Results.List) > 0 {
449
+ c.tsw.WriteLiterally(": ")
450
+ if len(funcDecl.Type.Results.List) == 1 {
451
+ c.WriteTypeExpr(funcDecl.Type.Results.List[0].Type)
452
+ } else {
453
+ c.tsw.WriteLiterally("[")
454
+ for i, field := range funcDecl.Type.Results.List {
455
+ if i > 0 {
456
+ c.tsw.WriteLiterally(", ")
457
+ }
458
+ c.WriteTypeExpr(field.Type)
459
+ }
460
+ c.tsw.WriteLiterally("]")
461
+ }
462
+ } else {
463
+ c.tsw.WriteLiterally(": void")
464
+ }
465
+
466
+ c.tsw.WriteLine(" {")
467
+ c.tsw.Indent(1)
468
+
469
+ // Write method body with receiver as first parameter
470
+ if err := c.writeWrapperFunctionBody(funcDecl, className); err != nil {
329
471
  return err
330
472
  }
473
+
474
+ c.tsw.Indent(-1)
475
+ c.tsw.WriteLine("}")
476
+ c.tsw.WriteLine("")
331
477
  }
332
478
  }
333
479
  }
334
480
 
335
- c.tsw.Indent(-1)
336
- c.tsw.WriteLine("}")
337
-
338
481
  return nil
339
482
  }
340
483
 
341
- // writeNamedTypeMethod writes a method for a named type, handling receiver binding properly
342
- func (c *GoToTSCompiler) writeNamedTypeMethod(decl *ast.FuncDecl) error {
343
- _, err := c.writeMethodSignature(decl)
344
- if err != nil {
345
- return err
484
+ // writeWrapperFunctionBody writes the body of a wrapper function, treating the receiver as the first parameter
485
+ func (c *GoToTSCompiler) writeWrapperFunctionBody(decl *ast.FuncDecl, typeName string) error {
486
+ // Write function body statements directly - identifier mapping is handled by pre-computed analysis
487
+ if decl.Body != nil {
488
+ for _, stmt := range decl.Body.List {
489
+ if err := c.WriteStmt(stmt); err != nil {
490
+ return err
491
+ }
492
+ }
346
493
  }
347
-
348
- return c.writeMethodBodyWithReceiverBinding(decl, "this._value")
494
+ return nil
349
495
  }
350
496
 
351
497
  // WriteTypeSpec writes the type specification to the output.
@@ -515,3 +661,43 @@ func (c *GoToTSCompiler) WriteImportSpec(a *ast.ImportSpec) {
515
661
 
516
662
  c.tsw.WriteImport(impName, tsImportPath+"/index.js")
517
663
  }
664
+
665
+ func (c *GoToTSCompiler) writeClonedFieldInitializer(fieldName string, fieldType types.Type, isEmbedded bool) {
666
+ c.tsw.WriteLiterally(fieldName)
667
+ c.tsw.WriteLiterally(": $.varRef(")
668
+
669
+ if isEmbedded {
670
+ isPointerToStruct := false
671
+ trueType := fieldType
672
+ if ptr, isPtr := trueType.(*types.Pointer); isPtr {
673
+ trueType = ptr.Elem()
674
+ isPointerToStruct = true
675
+ }
676
+
677
+ if named, isNamed := trueType.(*types.Named); isNamed {
678
+ _, isUnderlyingStruct := named.Underlying().(*types.Struct)
679
+ if isUnderlyingStruct && !isPointerToStruct { // Is a value struct
680
+ c.tsw.WriteLiterallyf("this._fields.%s.value.clone()", fieldName)
681
+ } else { // Is a pointer to a struct, or not a struct
682
+ c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
683
+ }
684
+ } else {
685
+ c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
686
+ }
687
+ } else {
688
+ isValueTypeStruct := false
689
+ if named, ok := fieldType.(*types.Named); ok {
690
+ if _, isStruct := named.Underlying().(*types.Struct); isStruct {
691
+ isValueTypeStruct = true
692
+ }
693
+ }
694
+
695
+ if isValueTypeStruct {
696
+ c.tsw.WriteLiterallyf("this._fields.%s.value?.clone() ?? null", fieldName)
697
+ } else {
698
+ c.tsw.WriteLiterallyf("this._fields.%s.value", fieldName)
699
+ }
700
+ }
701
+
702
+ c.tsw.WriteLiterally(")")
703
+ }
@@ -117,6 +117,8 @@ func (c *GoToTSCompiler) WriteStmtAssign(exp *ast.AssignStmt) error {
117
117
  }
118
118
  }
119
119
  c.tsw.WriteLiterally("] = ")
120
+ // Add await if the call is async
121
+ c.writeAsyncCallIfNeeded(callExpr)
120
122
  c.WriteValueExpr(callExpr)
121
123
  c.tsw.WriteLine("")
122
124
  return nil
@@ -165,6 +167,8 @@ func (c *GoToTSCompiler) WriteStmtAssign(exp *ast.AssignStmt) error {
165
167
 
166
168
  // Write a temporary variable to hold the function call result
167
169
  c.tsw.WriteLiterally(" const _tmp = ")
170
+ // Add await if the call is async
171
+ c.writeAsyncCallIfNeeded(callExpr)
168
172
  if err := c.WriteValueExpr(callExpr); err != nil {
169
173
  return fmt.Errorf("failed to write RHS call expression in assignment: %w", err)
170
174
  }
@@ -287,10 +291,9 @@ func (c *GoToTSCompiler) WriteStmtAssign(exp *ast.AssignStmt) error {
287
291
  }
288
292
  c.tsw.WriteLiterally("] = ")
289
293
 
290
- // Write the right-hand side (the function call)
291
- if err := c.WriteValueExpr(callExpr); err != nil {
292
- return fmt.Errorf("failed to write RHS call expression in assignment: %w", err)
293
- }
294
+ // Add await if the call is async
295
+ c.writeAsyncCallIfNeeded(callExpr)
296
+ c.WriteValueExpr(callExpr)
294
297
 
295
298
  c.tsw.WriteLine("")
296
299
  return nil