goscript 0.1.4 → 0.2.0

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 (270) hide show
  1. package/README.md +5 -2
  2. package/cmd/go_js_wasm_exec/main.go +201 -0
  3. package/cmd/go_js_wasm_exec/main_test.go +83 -0
  4. package/cmd/goscript/{cmd_compile.go → cmd-compile.go} +7 -0
  5. package/cmd/goscript/cmd-test.go +14 -0
  6. package/cmd/goscript/cmd-test_test.go +1 -1
  7. package/compiler/compile-request.go +12 -9
  8. package/compiler/compliance_test.go +0 -1
  9. package/compiler/config.go +2 -0
  10. package/compiler/gotest/request.go +28 -0
  11. package/compiler/gotest/runner.go +353 -27
  12. package/compiler/gotest/runner_test.go +273 -1
  13. package/compiler/gotest/testdata/browserapi/browserapi_test.go +20 -0
  14. package/compiler/gotest/testdata/browserapi/go.mod +3 -0
  15. package/compiler/lowered-program.go +24 -17
  16. package/compiler/lowering.go +392 -127
  17. package/compiler/lowering_bench_test.go +41 -27
  18. package/compiler/override-facts.go +15 -0
  19. package/compiler/override-parity-verifier.go +450 -0
  20. package/compiler/override-parity.go +122 -0
  21. package/compiler/override-registry_test.go +559 -0
  22. package/compiler/protobuf-ts-binding.go +514 -0
  23. package/compiler/protobuf-ts-binding_test.go +172 -0
  24. package/compiler/semantic-model-types.go +9 -4
  25. package/compiler/semantic-model.go +282 -70
  26. package/compiler/semantic-model_test.go +82 -1
  27. package/compiler/service.go +20 -1
  28. package/compiler/skeleton_test.go +62 -8
  29. package/compiler/typescript-emitter.go +128 -13
  30. package/dist/gs/builtin/slice.d.ts +2 -1
  31. package/dist/gs/builtin/slice.js +29 -4
  32. package/dist/gs/builtin/slice.js.map +1 -1
  33. package/dist/gs/builtin/type.d.ts +13 -5
  34. package/dist/gs/builtin/type.js +153 -60
  35. package/dist/gs/builtin/type.js.map +1 -1
  36. package/dist/gs/builtin/varRef.d.ts +11 -0
  37. package/dist/gs/builtin/varRef.js +57 -2
  38. package/dist/gs/builtin/varRef.js.map +1 -1
  39. package/dist/gs/bytes/buffer.gs.js +1 -1
  40. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  41. package/dist/gs/bytes/reader.gs.js +1 -1
  42. package/dist/gs/bytes/reader.gs.js.map +1 -1
  43. package/dist/gs/compress/zlib/index.d.ts +10 -3
  44. package/dist/gs/compress/zlib/index.js +50 -16
  45. package/dist/gs/compress/zlib/index.js.map +1 -1
  46. package/dist/gs/encoding/json/index.d.ts +114 -0
  47. package/dist/gs/encoding/json/index.js +544 -36
  48. package/dist/gs/encoding/json/index.js.map +1 -1
  49. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +100 -0
  50. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +564 -0
  51. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  52. package/dist/gs/github.com/pkg/errors/errors.js +54 -30
  53. package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
  54. package/dist/gs/go/scanner/index.d.ts +2 -0
  55. package/dist/gs/go/scanner/index.js +29 -5
  56. package/dist/gs/go/scanner/index.js.map +1 -1
  57. package/dist/gs/go/token/index.js +22 -6
  58. package/dist/gs/go/token/index.js.map +1 -1
  59. package/dist/gs/hash/index.d.ts +6 -0
  60. package/dist/gs/hash/index.js +20 -0
  61. package/dist/gs/hash/index.js.map +1 -1
  62. package/dist/gs/internal/goarch/index.d.ts +43 -3
  63. package/dist/gs/internal/goarch/index.js +42 -10
  64. package/dist/gs/internal/goarch/index.js.map +1 -1
  65. package/dist/gs/io/fs/fs.js +26 -14
  66. package/dist/gs/io/fs/fs.js.map +1 -1
  67. package/dist/gs/io/fs/readdir.js +4 -2
  68. package/dist/gs/io/fs/readdir.js.map +1 -1
  69. package/dist/gs/io/fs/sub.js +8 -1
  70. package/dist/gs/io/fs/sub.js.map +1 -1
  71. package/dist/gs/io/io.d.ts +2 -0
  72. package/dist/gs/io/io.js.map +1 -1
  73. package/dist/gs/math/bits/index.d.ts +5 -0
  74. package/dist/gs/math/bits/index.js +16 -4
  75. package/dist/gs/math/bits/index.js.map +1 -1
  76. package/dist/gs/mime/index.d.ts +16 -0
  77. package/dist/gs/mime/index.js +315 -6
  78. package/dist/gs/mime/index.js.map +1 -1
  79. package/dist/gs/net/http/httptest/index.d.ts +12 -0
  80. package/dist/gs/net/http/httptest/index.js +85 -6
  81. package/dist/gs/net/http/httptest/index.js.map +1 -1
  82. package/dist/gs/net/http/index.d.ts +300 -5
  83. package/dist/gs/net/http/index.js +1598 -58
  84. package/dist/gs/net/http/index.js.map +1 -1
  85. package/dist/gs/os/dir_unix.gs.js +1 -1
  86. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  87. package/dist/gs/os/error.gs.js +1 -1
  88. package/dist/gs/os/error.gs.js.map +1 -1
  89. package/dist/gs/os/exec.gs.d.ts +1 -0
  90. package/dist/gs/os/exec.gs.js +4 -8
  91. package/dist/gs/os/exec.gs.js.map +1 -1
  92. package/dist/gs/os/exec_posix.gs.js +1 -1
  93. package/dist/gs/os/exec_posix.gs.js.map +1 -1
  94. package/dist/gs/os/index.d.ts +1 -1
  95. package/dist/gs/os/index.js +1 -1
  96. package/dist/gs/os/index.js.map +1 -1
  97. package/dist/gs/os/proc.gs.d.ts +4 -0
  98. package/dist/gs/os/proc.gs.js +12 -6
  99. package/dist/gs/os/proc.gs.js.map +1 -1
  100. package/dist/gs/os/root_js.gs.js +1 -1
  101. package/dist/gs/os/root_js.gs.js.map +1 -1
  102. package/dist/gs/os/types.gs.js +1 -1
  103. package/dist/gs/os/types.gs.js.map +1 -1
  104. package/dist/gs/os/types_js.gs.js +1 -1
  105. package/dist/gs/os/types_js.gs.js.map +1 -1
  106. package/dist/gs/os/types_unix.gs.js +1 -1
  107. package/dist/gs/os/types_unix.gs.js.map +1 -1
  108. package/dist/gs/path/path.js +11 -7
  109. package/dist/gs/path/path.js.map +1 -1
  110. package/dist/gs/reflect/index.d.ts +5 -4
  111. package/dist/gs/reflect/index.js +4 -3
  112. package/dist/gs/reflect/index.js.map +1 -1
  113. package/dist/gs/reflect/map.js +15 -0
  114. package/dist/gs/reflect/map.js.map +1 -1
  115. package/dist/gs/reflect/type.d.ts +25 -6
  116. package/dist/gs/reflect/type.js +1418 -228
  117. package/dist/gs/reflect/type.js.map +1 -1
  118. package/dist/gs/reflect/types.d.ts +14 -6
  119. package/dist/gs/reflect/types.js +35 -1
  120. package/dist/gs/reflect/types.js.map +1 -1
  121. package/dist/gs/reflect/value.d.ts +1 -0
  122. package/dist/gs/reflect/value.js +83 -41
  123. package/dist/gs/reflect/value.js.map +1 -1
  124. package/dist/gs/reflect/visiblefields.js +4 -140
  125. package/dist/gs/reflect/visiblefields.js.map +1 -1
  126. package/dist/gs/runtime/pprof/index.d.ts +8 -2
  127. package/dist/gs/runtime/pprof/index.js +50 -30
  128. package/dist/gs/runtime/pprof/index.js.map +1 -1
  129. package/dist/gs/runtime/runtime.js +5 -4
  130. package/dist/gs/runtime/runtime.js.map +1 -1
  131. package/dist/gs/runtime/trace/index.js +5 -19
  132. package/dist/gs/runtime/trace/index.js.map +1 -1
  133. package/dist/gs/strconv/atoi.gs.js +1 -1
  134. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  135. package/dist/gs/strconv/complex.gs.d.ts +3 -0
  136. package/dist/gs/strconv/complex.gs.js +148 -0
  137. package/dist/gs/strconv/complex.gs.js.map +1 -0
  138. package/dist/gs/strconv/index.d.ts +1 -0
  139. package/dist/gs/strconv/index.js +1 -0
  140. package/dist/gs/strconv/index.js.map +1 -1
  141. package/dist/gs/strings/builder.js +1 -1
  142. package/dist/gs/strings/reader.js +9 -5
  143. package/dist/gs/strings/reader.js.map +1 -1
  144. package/dist/gs/strings/replace.js +15 -7
  145. package/dist/gs/strings/replace.js.map +1 -1
  146. package/dist/gs/strings/strings.d.ts +5 -0
  147. package/dist/gs/strings/strings.js +57 -5
  148. package/dist/gs/strings/strings.js.map +1 -1
  149. package/dist/gs/sync/atomic/type.gs.js +9 -9
  150. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  151. package/dist/gs/sync/atomic/value.gs.js +2 -2
  152. package/dist/gs/sync/atomic/value.gs.js.map +1 -1
  153. package/dist/gs/syscall/env.js +22 -14
  154. package/dist/gs/syscall/env.js.map +1 -1
  155. package/dist/gs/testing/testing.js +55 -13
  156. package/dist/gs/testing/testing.js.map +1 -1
  157. package/dist/gs/time/time.d.ts +24 -1
  158. package/dist/gs/time/time.js +43 -3
  159. package/dist/gs/time/time.js.map +1 -1
  160. package/dist/gs/unique/index.js +7 -1
  161. package/dist/gs/unique/index.js.map +1 -1
  162. package/go.mod +3 -3
  163. package/go.sum +16 -0
  164. package/gs/builtin/runtime-contract.test.ts +218 -21
  165. package/gs/builtin/slice.ts +44 -4
  166. package/gs/builtin/type.ts +226 -59
  167. package/gs/builtin/varRef.ts +85 -2
  168. package/gs/bytes/buffer.gs.ts +1 -1
  169. package/gs/bytes/reader.gs.ts +1 -1
  170. package/gs/compress/zlib/index.test.ts +62 -1
  171. package/gs/compress/zlib/index.ts +53 -16
  172. package/gs/compress/zlib/parity.json +51 -0
  173. package/gs/encoding/json/index.test.ts +360 -6
  174. package/gs/encoding/json/index.ts +679 -38
  175. package/gs/encoding/json/parity.json +81 -0
  176. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +211 -3
  177. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +857 -1
  178. package/gs/github.com/pkg/errors/errors.ts +54 -30
  179. package/gs/go/scanner/index.test.ts +39 -56
  180. package/gs/go/scanner/index.ts +33 -5
  181. package/gs/go/scanner/parity.json +27 -0
  182. package/gs/go/token/index.ts +22 -6
  183. package/gs/hash/index.test.ts +20 -33
  184. package/gs/hash/index.ts +28 -0
  185. package/gs/hash/parity.json +21 -0
  186. package/gs/internal/goarch/index.test.ts +32 -0
  187. package/gs/internal/goarch/index.ts +45 -13
  188. package/gs/internal/goarch/parity.json +144 -0
  189. package/gs/io/fs/fs.ts +26 -14
  190. package/gs/io/fs/readdir.ts +4 -4
  191. package/gs/io/fs/sub.ts +8 -1
  192. package/gs/io/io.ts +1 -0
  193. package/gs/io/parity.json +162 -0
  194. package/gs/math/bits/index.test.ts +14 -1
  195. package/gs/math/bits/index.ts +23 -4
  196. package/gs/math/bits/parity.json +156 -0
  197. package/gs/mime/index.test.ts +90 -0
  198. package/gs/mime/index.ts +369 -6
  199. package/gs/mime/parity.json +36 -0
  200. package/gs/net/http/httptest/index.test.ts +98 -2
  201. package/gs/net/http/httptest/index.ts +101 -6
  202. package/gs/net/http/httptest/parity.json +15 -0
  203. package/gs/net/http/index.test.ts +781 -12
  204. package/gs/net/http/index.ts +1860 -139
  205. package/gs/net/http/meta.json +16 -1
  206. package/gs/net/http/parity.json +193 -0
  207. package/gs/os/dir_unix.gs.ts +1 -1
  208. package/gs/os/error.gs.ts +1 -1
  209. package/gs/os/exec.gs.ts +4 -8
  210. package/gs/os/exec_posix.gs.ts +1 -1
  211. package/gs/os/index.test.ts +9 -0
  212. package/gs/os/index.ts +1 -0
  213. package/gs/os/parity.json +9 -0
  214. package/gs/os/proc.gs.ts +18 -5
  215. package/gs/os/proc.test.ts +26 -0
  216. package/gs/os/root_js.gs.ts +1 -1
  217. package/gs/os/types.gs.ts +1 -1
  218. package/gs/os/types_js.gs.ts +1 -1
  219. package/gs/os/types_unix.gs.ts +1 -1
  220. package/gs/path/path.ts +11 -7
  221. package/gs/reflect/field.test.ts +37 -15
  222. package/gs/reflect/function-types.test.ts +518 -22
  223. package/gs/reflect/index.ts +8 -6
  224. package/gs/reflect/map.ts +20 -0
  225. package/gs/reflect/meta.json +6 -4
  226. package/gs/reflect/parity.json +234 -0
  227. package/gs/reflect/sliceat.test.ts +156 -0
  228. package/gs/reflect/structof.test.ts +401 -0
  229. package/gs/reflect/type.ts +1897 -317
  230. package/gs/reflect/typefor.test.ts +510 -10
  231. package/gs/reflect/types.ts +43 -18
  232. package/gs/reflect/value.ts +105 -45
  233. package/gs/reflect/visiblefields.ts +5 -168
  234. package/gs/runtime/parity.json +24 -0
  235. package/gs/runtime/pprof/index.test.ts +29 -7
  236. package/gs/runtime/pprof/index.ts +56 -30
  237. package/gs/runtime/pprof/parity.json +27 -0
  238. package/gs/runtime/runtime.test.ts +3 -1
  239. package/gs/runtime/runtime.ts +4 -3
  240. package/gs/runtime/trace/index.test.ts +5 -3
  241. package/gs/runtime/trace/index.ts +8 -20
  242. package/gs/runtime/trace/parity.json +36 -0
  243. package/gs/strconv/atoi.gs.ts +1 -1
  244. package/gs/strconv/complex.gs.ts +174 -0
  245. package/gs/strconv/complex.test.ts +65 -0
  246. package/gs/strconv/index.ts +1 -0
  247. package/gs/strconv/parity.json +120 -0
  248. package/gs/strings/builder.ts +1 -1
  249. package/gs/strings/parity.json +186 -0
  250. package/gs/strings/reader.ts +9 -5
  251. package/gs/strings/replace.ts +15 -7
  252. package/gs/strings/strings.test.ts +22 -2
  253. package/gs/strings/strings.ts +64 -6
  254. package/gs/sync/atomic/type.gs.ts +9 -9
  255. package/gs/sync/atomic/value.gs.ts +2 -2
  256. package/gs/syscall/env.ts +29 -14
  257. package/gs/testing/testing.test.ts +67 -0
  258. package/gs/testing/testing.ts +87 -19
  259. package/gs/time/parity.json +225 -0
  260. package/gs/time/time.test.ts +20 -2
  261. package/gs/time/time.ts +49 -7
  262. package/gs/unique/index.ts +7 -1
  263. package/package.json +4 -2
  264. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +0 -217
  265. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +0 -926
  266. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +0 -1
  267. package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +0 -38
  268. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +0 -1361
  269. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +0 -46
  270. /package/compiler/{wasm_api.go → wasm-api.go} +0 -0
@@ -242,6 +242,87 @@ func TestSemanticModelRecordsInterfaceAssertionAndNilFacts(t *testing.T) {
242
242
  }
243
243
  }
244
244
 
245
+ func TestSemanticModelRejectsInterfaceMethodSignatureMismatch(t *testing.T) {
246
+ moduleDir := writePackageGraphFixture(t, map[string]string{
247
+ "go.mod": "module example.test/signaturemismatch\n\ngo 1.25.3\n",
248
+ "main.go": strings.Join([]string{
249
+ "package signaturemismatch",
250
+ "type Reader interface { Read() int }",
251
+ "type Impl struct{}",
252
+ "func (Impl) Read() string { return \"bad\" }",
253
+ "",
254
+ }, "\n"),
255
+ })
256
+ graph := loadPackageGraph(t, &CompileRequest{
257
+ Patterns: []string{"."},
258
+ Dir: moduleDir,
259
+ OutputPath: filepath.Join(t.TempDir(), "out"),
260
+ DependencyMode: DependencyModeRequested,
261
+ RuntimeEmissionMode: RuntimeEmissionModeEmit,
262
+ })
263
+ model := buildSemanticModel(t, graph)
264
+
265
+ if hasInterfaceImplementation(model, "Impl", "Reader", false) {
266
+ t.Fatalf("unexpected Impl -> Reader implementation: %#v", model.interfaceImplementations)
267
+ }
268
+ }
269
+
270
+ func TestSemanticModelAcceptsPromotedInterfaceMethods(t *testing.T) {
271
+ moduleDir := writePackageGraphFixture(t, map[string]string{
272
+ "go.mod": "module example.test/promoted\n\ngo 1.25.3\n",
273
+ "main.go": strings.Join([]string{
274
+ "package promoted",
275
+ "type Reader interface { Read() int }",
276
+ "type Base struct{}",
277
+ "func (Base) Read() int { return 1 }",
278
+ "type Impl struct { Base }",
279
+ "",
280
+ }, "\n"),
281
+ })
282
+ graph := loadPackageGraph(t, &CompileRequest{
283
+ Patterns: []string{"."},
284
+ Dir: moduleDir,
285
+ OutputPath: filepath.Join(t.TempDir(), "out"),
286
+ DependencyMode: DependencyModeRequested,
287
+ RuntimeEmissionMode: RuntimeEmissionModeEmit,
288
+ })
289
+ model := buildSemanticModel(t, graph)
290
+
291
+ if !hasInterfaceImplementation(model, "Impl", "Reader", false) {
292
+ t.Fatalf("missing promoted Impl -> Reader implementation: %#v", model.interfaceImplementations)
293
+ }
294
+ }
295
+
296
+ func TestSemanticModelKeepsUnexportedInterfaceMethodsPackageScoped(t *testing.T) {
297
+ moduleDir := writePackageGraphFixture(t, map[string]string{
298
+ "go.mod": "module example.test/unexportediface\n\ngo 1.25.3\n",
299
+ "dep/dep.go": strings.Join([]string{
300
+ "package dep",
301
+ "type private interface { read() int }",
302
+ "",
303
+ }, "\n"),
304
+ "main.go": strings.Join([]string{
305
+ "package unexportediface",
306
+ "import _ \"example.test/unexportediface/dep\"",
307
+ "type Impl struct{}",
308
+ "func (Impl) read() int { return 1 }",
309
+ "",
310
+ }, "\n"),
311
+ })
312
+ graph := loadPackageGraph(t, &CompileRequest{
313
+ Patterns: []string{"."},
314
+ Dir: moduleDir,
315
+ OutputPath: filepath.Join(t.TempDir(), "out"),
316
+ DependencyMode: DependencyModeAll,
317
+ RuntimeEmissionMode: RuntimeEmissionModeEmit,
318
+ })
319
+ model := buildSemanticModel(t, graph)
320
+
321
+ if hasInterfaceImplementation(model, "Impl", "private", false) {
322
+ t.Fatalf("unexpected cross-package unexported implementation: %#v", model.interfaceImplementations)
323
+ }
324
+ }
325
+
245
326
  func TestSemanticModelColorsAsyncFunctionsAndOverrides(t *testing.T) {
246
327
  moduleDir := writePackageGraphFixture(t, map[string]string{
247
328
  "go.mod": "module example.test/async\n\ngo 1.25.3\n",
@@ -356,7 +437,7 @@ func TestSemanticModelPropagatesAsyncToOverrideInterfaceMethods(t *testing.T) {
356
437
  if implementation.typ != nil && implementation.typ.Obj().Name() == "asyncWriter" &&
357
438
  implementation.iface != nil && implementation.iface.Obj().Pkg().Path() == "io" &&
358
439
  implementation.iface.Obj().Name() == "Writer" &&
359
- implementation.pointer && implementation.asyncMethods["Write"] {
440
+ implementation.pointer {
360
441
  found = true
361
442
  break
362
443
  }
@@ -14,6 +14,7 @@ type CompileService struct {
14
14
  emitterOwner *TypeScriptEmitOwner
15
15
  runtimeOwner *RuntimeContractOwner
16
16
  overrideOwner *OverrideRegistryOwner
17
+ parityOwner *OverrideParityVerifier
17
18
  }
18
19
 
19
20
  // NewCompileService creates a compile service with every pipeline owner.
@@ -28,6 +29,7 @@ func NewCompileService(overrideDirs ...string) *CompileService {
28
29
  emitterOwner: NewTypeScriptEmitOwner(runtimeOwner),
29
30
  runtimeOwner: runtimeOwner,
30
31
  overrideOwner: overrideOwner,
32
+ parityOwner: NewOverrideParityVerifier(),
31
33
  }
32
34
  }
33
35
 
@@ -96,6 +98,19 @@ func (s *CompileService) Compile(ctx context.Context, req *CompileRequest) (*Com
96
98
  return result, NewCompileError(diagnostics)
97
99
  }
98
100
 
101
+ overrideFacts, factsDiagnostics := s.overrideOwner.Facts(ctx)
102
+ diagnostics = append(diagnostics, factsDiagnostics...)
103
+ if diagnosticsHaveErrors(diagnostics) {
104
+ result.Diagnostics = diagnostics
105
+ return result, NewCompileError(diagnostics)
106
+ }
107
+ parityDiagnostics := s.parityOwner.Verify(ctx, graph, overrideFacts)
108
+ diagnostics = append(diagnostics, parityDiagnostics...)
109
+ if diagnosticsHaveErrors(diagnostics) {
110
+ result.Diagnostics = diagnostics
111
+ return result, NewCompileError(diagnostics)
112
+ }
113
+
99
114
  semanticModel, semanticDiagnostics := s.semanticOwner.Build(ctx, graph)
100
115
  diagnostics = append(diagnostics, semanticDiagnostics...)
101
116
  if diagnosticsHaveErrors(diagnostics) {
@@ -110,7 +125,11 @@ func (s *CompileService) Compile(ctx context.Context, req *CompileRequest) (*Com
110
125
  return result, NewCompileError(diagnostics)
111
126
  }
112
127
 
113
- loweredProgram, loweringDiagnostics := s.loweringOwner.Build(ctx, semanticModel)
128
+ loweredProgram, loweringDiagnostics := s.loweringOwner.Build(ctx, semanticModel, LoweringOptions{
129
+ SourceRoot: protobufTypeScriptBindingRoot(req.Dir),
130
+ OutputPath: req.OutputPath,
131
+ ProtobufTypeScriptBinding: req.ProtobufTypeScriptBinding,
132
+ })
114
133
  diagnostics = append(diagnostics, loweringDiagnostics...)
115
134
  if diagnosticsHaveErrors(diagnostics) {
116
135
  result.Diagnostics = diagnostics
@@ -911,6 +911,49 @@ func TestCompilePackagesAnnotatesNewPointerShortDecls(t *testing.T) {
911
911
  }
912
912
  }
913
913
 
914
+ func TestCompilePackagesAnnotatesNewArrayPointerShortDecls(t *testing.T) {
915
+ moduleDir := writePackageGraphFixture(t, map[string]string{
916
+ "go.mod": "module example.test/newarrayptrdecl\n\ngo 1.25.3\n",
917
+ "main.go": strings.Join([]string{
918
+ "package main",
919
+ "func use(*[32]byte) {}",
920
+ "func main() {",
921
+ " buf := new([32]byte)",
922
+ " use(buf)",
923
+ " if true {",
924
+ " buf = nil",
925
+ " }",
926
+ " use(buf)",
927
+ "}",
928
+ "",
929
+ }, "\n"),
930
+ })
931
+ outputDir := filepath.Join(t.TempDir(), "output")
932
+ comp, err := NewCompiler(&Config{Dir: moduleDir, OutputPath: outputDir}, nil, nil)
933
+ if err != nil {
934
+ t.Fatal(err.Error())
935
+ }
936
+
937
+ if _, err := comp.CompilePackages(context.Background(), "."); err != nil {
938
+ t.Fatal(err.Error())
939
+ }
940
+ outputFile := filepath.Join(outputDir, "@goscript", "example.test", "newarrayptrdecl", "main.gs.ts")
941
+ content, err := os.ReadFile(outputFile)
942
+ if err != nil {
943
+ t.Fatal(err.Error())
944
+ }
945
+ text := string(content)
946
+ for _, want := range []string{
947
+ "let buf: $.VarRef<Uint8Array> | null = $.varRef<Uint8Array>(new Uint8Array(32))",
948
+ "buf = null",
949
+ "use(buf)",
950
+ } {
951
+ if !strings.Contains(text, want) {
952
+ t.Fatalf("missing %q in generated output:\n%s", want, text)
953
+ }
954
+ }
955
+ }
956
+
914
957
  func TestCompilePackagesEmitsShadowedBuiltinCalls(t *testing.T) {
915
958
  moduleDir := writePackageGraphFixture(t, map[string]string{
916
959
  "go.mod": "module example.test/shadowbuiltin\n\ngo 1.25.3\n",
@@ -1516,8 +1559,8 @@ func TestCompilePackagesEmitsStructMethodsAndPointerAssertions(t *testing.T) {
1516
1559
  "Counter.prototype.Set.call(pointer, 2)",
1517
1560
  "Counter.prototype.Set.call(NewCounter(), 5)",
1518
1561
  "let [, ok] = $.typeAssertTuple<Counter | $.VarRef<Counter> | null>(iface, { kind: $.TypeKind.Pointer, elemType: \"main.Counter\" })",
1519
- "\"Value\": { type: { kind: $.TypeKind.Basic, name: \"int\" }, tag: \"json:\\\"value\\\"\" }",
1520
- "\"ID\": { kind: $.TypeKind.Basic, name: \"int32\", typeName: \"main.ObjectID\" }",
1562
+ "{ name: \"Value\", key: \"Value\", type: { kind: $.TypeKind.Basic, name: \"int\" }, tag: \"json:\\\"value\\\"\", index: [0], offset: 0, exported: true }",
1563
+ "{ name: \"ID\", key: \"ID\", type: { kind: $.TypeKind.Basic, name: \"int32\", typeName: \"main.ObjectID\" }, index: [1], offset: 8, exported: true }",
1521
1564
  } {
1522
1565
  if !strings.Contains(text, want) {
1523
1566
  t.Fatalf("missing %q in generated output:\n%s", want, text)
@@ -2346,9 +2389,11 @@ func TestCompilePackagesEmitsInterfacesMethodValuesTypeSwitchesAndFunctionAssert
2346
2389
  "Close(): string",
2347
2390
  "$.registerInterfaceType(\n\t\"main.ReadCloser\"",
2348
2391
  "((__receiver) => () => __receiver.Inc())($.pointerValue<Counter>(counter))",
2349
- "$.namedFunction(greet, \"main.Greeter\")",
2392
+ "$.namedFunction(greet, \"main.Greeter\", ({ kind: $.TypeKind.Function, name: \"main.Greeter\"",
2393
+ "params: [{ kind: $.TypeKind.Basic, name: \"string\" }]",
2394
+ "results: [{ kind: $.TypeKind.Basic, name: \"string\" }]",
2350
2395
  "$.interfaceValue<any>(null, \"*struct{Name string}\")",
2351
- "elemType: { kind: $.TypeKind.Struct, methods: [], fields: {\"Name\": { kind: $.TypeKind.Basic, name: \"string\" }} }",
2396
+ "elemType: { kind: $.TypeKind.Struct, methods: [], fields: [{ name: \"Name\", key: \"Name\", type: { kind: $.TypeKind.Basic, name: \"string\" }",
2352
2397
  "let fn = __goscriptTuple",
2353
2398
  "switch (true)",
2354
2399
  "case $.typeAssert<Exclude<ReadCloser, null>>(__goscriptTypeSwitchValue, \"main.ReadCloser\").ok",
@@ -2612,9 +2657,9 @@ func TestCompilePackagesEmitsGenericMethodsAliasesAndDictionaries(t *testing.T)
2612
2657
  "$.mapSet(seen, 1, {})",
2613
2658
  "$.genericZero(__typeArgs, \"T\", null)",
2614
2659
  "$.callGenericMethod(__typeArgs, \"T\", \"String\", v)",
2615
- "ZeroValue({T: { type: { kind: $.TypeKind.Basic, name: \"int\", typeName: \"main.MyInt\" }, zero: () => 0, methods: {String: (receiver: any, ...args: any[]) => (MyInt_String as any)(($.isVarRef(receiver) ? receiver.value : receiver), ...args)} }})",
2616
- "CallString({T: { type: { kind: $.TypeKind.Basic, name: \"int\", typeName: \"main.MyInt\" }, zero: () => 0, methods: {String: (receiver: any, ...args: any[]) => (MyInt_String as any)(($.isVarRef(receiver) ? receiver.value : receiver), ...args)} }}, zero)",
2617
- "Sum({T: { type: { kind: $.TypeKind.Basic, name: \"int\", typeName: \"main.MyInt\" }, zero: () => 0, methods: {String: (receiver: any, ...args: any[]) => (MyInt_String as any)(($.isVarRef(receiver) ? receiver.value : receiver), ...args)} }}, null)",
2660
+ "ZeroValue({T: { type: { kind: $.TypeKind.Basic, name: \"int\", typeName: \"main.MyInt\" }, zero: () => 0, methods: {String: (receiver: any, ...args: any[]) => (MyInt_String as any)(($.isVarRef(receiver) ? receiver.value : receiver), ...args)}, methodSignatures: [{ name: \"String\", args: [], returns: [{ name: \"_r0\", type: { kind: $.TypeKind.Basic, name: \"string\" } }] }] }})",
2661
+ "CallString({T: { type: { kind: $.TypeKind.Basic, name: \"int\", typeName: \"main.MyInt\" }, zero: () => 0, methods: {String: (receiver: any, ...args: any[]) => (MyInt_String as any)(($.isVarRef(receiver) ? receiver.value : receiver), ...args)}, methodSignatures: [{ name: \"String\", args: [], returns: [{ name: \"_r0\", type: { kind: $.TypeKind.Basic, name: \"string\" } }] }] }}, zero)",
2662
+ "Sum({T: { type: { kind: $.TypeKind.Basic, name: \"int\", typeName: \"main.MyInt\" }, zero: () => 0, methods: {String: (receiver: any, ...args: any[]) => (MyInt_String as any)(($.isVarRef(receiver) ? receiver.value : receiver), ...args)}, methodSignatures: [{ name: \"String\", args: [], returns: [{ name: \"_r0\", type: { kind: $.TypeKind.Basic, name: \"string\" } }] }] }}, null)",
2618
2663
  } {
2619
2664
  if !strings.Contains(text, want) {
2620
2665
  t.Fatalf("missing %q in generated output:\n%s", want, text)
@@ -2761,7 +2806,7 @@ func TestCompilePackagesEmitsRecursiveFunctionTypeInfo(t *testing.T) {
2761
2806
  text := string(content)
2762
2807
  for _, want := range []string{
2763
2808
  "export type Handler = ((_p0: ((_p0: Handler | null) => Handler | null | globalThis.Promise<Handler | null>) | null) => Handler | null | globalThis.Promise<Handler | null>) | null",
2764
- "\"Next\": ({ kind: $.TypeKind.Function, name: \"main.Handler\"",
2809
+ "{ name: \"Next\", key: \"Next\", type: ({ kind: $.TypeKind.Function, name: \"main.Handler\"",
2765
2810
  "params: [{ kind: $.TypeKind.Function, params: [], results: [] }]",
2766
2811
  "results: [{ kind: $.TypeKind.Function, params: [], results: [] }]",
2767
2812
  } {
@@ -4127,6 +4172,12 @@ func TestCompilePackagesLowersSwitchesAndFunctionValueCalls(t *testing.T) {
4127
4172
  " if value > 0 {",
4128
4173
  " goto Again",
4129
4174
  " }",
4175
+ "Drive:",
4176
+ " window := value + 1",
4177
+ " if window < 0 {",
4178
+ " goto Drive",
4179
+ " }",
4180
+ " println(window)",
4130
4181
  " release := func() { println(\"release\") }",
4131
4182
  " rel := &release",
4132
4183
  " (*rel)()",
@@ -4163,6 +4214,9 @@ func TestCompilePackagesLowersSwitchesAndFunctionValueCalls(t *testing.T) {
4163
4214
  "break Block",
4164
4215
  "Again: while (true)",
4165
4216
  "continue Again",
4217
+ "Drive: while (true)",
4218
+ "var window = value + 1",
4219
+ "$.println(window)",
4166
4220
  "($.pointerValue<(() => void) | null>(rel))!()",
4167
4221
  "$.functionValue((): void => {\n\t\tusing __defer = new $.DisposableStack()",
4168
4222
  "__defer.defer(() => { $.println(\"wrapped deferred\") })",
@@ -134,6 +134,7 @@ func (o *TypeScriptEmitOwner) EmitToMemory(
134
134
 
135
135
  func (o *TypeScriptEmitOwner) renderLoweredFile(pkg *loweredPackage, file *loweredFile) string {
136
136
  var b strings.Builder
137
+ b.Grow(estimateLoweredFileSize(file))
137
138
  if file.sourcePath != "" {
138
139
  b.WriteString("// Generated file based on ")
139
140
  b.WriteString(filepath.Base(file.sourcePath))
@@ -219,6 +220,104 @@ func (o *TypeScriptEmitOwner) renderLoweredFile(pkg *loweredPackage, file *lower
219
220
  return b.String()
220
221
  }
221
222
 
223
+ func estimateLoweredFileSize(file *loweredFile) int {
224
+ if file == nil {
225
+ return 0
226
+ }
227
+ size := 128 + len(file.imports)*96 + len(file.decls)*32
228
+ for _, imp := range file.imports {
229
+ size += len(imp.alias) + len(imp.source)
230
+ }
231
+ for _, decl := range file.decls {
232
+ size += len(decl.code)
233
+ if decl.function != nil {
234
+ size += estimateLoweredFunctionSize(decl.function)
235
+ }
236
+ if decl.structType != nil {
237
+ size += estimateLoweredStructSize(decl.structType)
238
+ }
239
+ }
240
+ return size
241
+ }
242
+
243
+ func estimateLoweredStructSize(structType *loweredStruct) int {
244
+ if structType == nil {
245
+ return 0
246
+ }
247
+ size := 256 + len(structType.name) + len(structType.typeName) + len(structType.fields)*128
248
+ for _, field := range structType.fields {
249
+ size += len(field.name) + len(field.runtimeName) + len(field.typ) + len(field.zero) + len(field.runtimeType) +
250
+ len(field.doc) + len(field.tag)
251
+ }
252
+ for idx := range structType.methods {
253
+ size += estimateLoweredFunctionSize(&structType.methods[idx])
254
+ }
255
+ return size
256
+ }
257
+
258
+ func estimateLoweredFunctionSize(fn *loweredFunction) int {
259
+ if fn == nil {
260
+ return 0
261
+ }
262
+ size := 192 + len(fn.name) + len(fn.result) + len(fn.receiverAlias) + len(fn.receiverType) + len(fn.receiverValue)
263
+ for _, typeParam := range fn.typeParams {
264
+ size += len(typeParam) + 2
265
+ }
266
+ for _, param := range fn.params {
267
+ size += len(param.name) + len(param.typ) + 4
268
+ }
269
+ for _, result := range fn.namedResults {
270
+ size += len(result.name) + len(result.typ) + len(result.zero) + len(result.returnExpr) + 16
271
+ }
272
+ size += estimateLoweredStmtsSize(fn.paramBindings)
273
+ size += estimateLoweredStmtsSize(fn.body)
274
+ return size
275
+ }
276
+
277
+ func estimateLoweredStmtsSize(stmts []loweredStmt) int {
278
+ size := len(stmts) * 24
279
+ for _, stmt := range stmts {
280
+ size += len(stmt.text) + len(stmt.leading)*16
281
+ for _, line := range stmt.leading {
282
+ size += len(line)
283
+ }
284
+ size += estimateLoweredStmtsSize(stmt.children)
285
+ size += estimateLoweredStmtsSize(stmt.elseBody)
286
+ if stmt.rangeFunc != nil {
287
+ size += len(stmt.rangeFunc.value) + len(stmt.rangeFunc.params)*16 + estimateLoweredStmtsSize(stmt.rangeFunc.body)
288
+ }
289
+ if stmt.switchStmt != nil {
290
+ size += len(stmt.switchStmt.value)
291
+ for _, switchCase := range stmt.switchStmt.cases {
292
+ size += len(switchCase.values)*16 + estimateLoweredStmtsSize(switchCase.body)
293
+ for _, value := range switchCase.values {
294
+ size += len(value)
295
+ }
296
+ }
297
+ }
298
+ if stmt.selectStmt != nil {
299
+ size += len(stmt.selectStmt.hasReturn) + len(stmt.selectStmt.value) + len(stmt.selectStmt.result) + len(stmt.selectStmt.resultType)
300
+ for _, selectCase := range stmt.selectStmt.cases {
301
+ size += len(selectCase.channel) + len(selectCase.value) + estimateLoweredStmtsSize(selectCase.prelude) +
302
+ estimateLoweredStmtsSize(selectCase.body)
303
+ }
304
+ }
305
+ if stmt.typeSwitch != nil {
306
+ size += len(stmt.typeSwitch.value) + len(stmt.typeSwitch.varName) + estimateLoweredStmtsSize(stmt.typeSwitch.defaultBody)
307
+ for _, switchCase := range stmt.typeSwitch.cases {
308
+ for _, typ := range switchCase.types {
309
+ size += len(typ)
310
+ }
311
+ for _, typ := range switchCase.tsTypes {
312
+ size += len(typ)
313
+ }
314
+ size += estimateLoweredStmtsSize(switchCase.body)
315
+ }
316
+ }
317
+ }
318
+ return size
319
+ }
320
+
222
321
  func sortedStructDecls(decls []loweredDecl) []loweredDecl {
223
322
  structs := make([]loweredDecl, 0)
224
323
  names := make(map[string]bool)
@@ -421,29 +520,42 @@ func renderStruct(b *strings.Builder, structType *loweredStruct, runtimeOwner *R
421
520
  if idx != 0 {
422
521
  b.WriteString(", ")
423
522
  }
424
- methodName := method.name
425
- if method.runtimeName != "" {
426
- methodName = method.runtimeName
427
- }
428
- b.WriteString("{ name: ")
429
- b.WriteString(strconvQuote(methodName))
430
- b.WriteString(", args: [], returns: [] }")
523
+ b.WriteString(runtimeMethodSignatureExpr(method))
431
524
  }
432
525
  b.WriteString("],\n\t\t")
433
526
  b.WriteString(structType.name)
434
- b.WriteString(",\n\t\t{")
527
+ b.WriteString(",\n\t\t[")
435
528
  for idx, field := range structType.fields {
436
529
  if idx != 0 {
437
530
  b.WriteString(", ")
438
531
  }
439
- b.WriteString(strconvQuote(field.name))
440
- b.WriteString(": ")
441
- b.WriteString(runtimeStructFieldInfoExpr(field.runtimeType, field.runtimeName, field.tag))
442
- }
443
- b.WriteString("}\n\t)\n")
532
+ b.WriteString(runtimeStructFieldInfoExpr(
533
+ field.runtimeType,
534
+ field.name,
535
+ field.runtimeName,
536
+ field.tag,
537
+ field.pkgPath,
538
+ field.anonymous,
539
+ field.index,
540
+ field.offset,
541
+ field.exported,
542
+ ))
543
+ }
544
+ b.WriteString("]\n\t)\n")
444
545
  b.WriteString("}\n")
445
546
  }
446
547
 
548
+ func runtimeMethodSignatureExpr(method loweredFunction) string {
549
+ if method.runtimeSignature != "" {
550
+ return method.runtimeSignature
551
+ }
552
+ methodName := method.name
553
+ if method.runtimeName != "" {
554
+ methodName = method.runtimeName
555
+ }
556
+ return "{ name: " + strconvQuote(methodName) + ", args: [], returns: [] }"
557
+ }
558
+
447
559
  func writeLineComment(b *strings.Builder, indent string, comment string) {
448
560
  comment = strings.TrimSpace(comment)
449
561
  if comment == "" {
@@ -1158,6 +1270,9 @@ func renderIndex(pkg *loweredPackage) string {
1158
1270
  if file.sideEffect {
1159
1271
  lines = append(lines, "import \"./"+file.outputName+"\"")
1160
1272
  }
1273
+ if file.exportAll {
1274
+ lines = append(lines, "export * from \"./"+file.outputName+"\"")
1275
+ }
1161
1276
  exports := slices.Clone(file.exports)
1162
1277
  slices.Sort(exports)
1163
1278
  if len(exports) != 0 {
@@ -1,4 +1,4 @@
1
- import { type VarRef } from './varRef.js';
1
+ import { type OwnedPointerHandle, type VarRef } from './varRef.js';
2
2
  export declare class GoBinaryString extends String {
3
3
  readonly bytes: Uint8Array;
4
4
  constructor(bytes: Uint8Array);
@@ -119,6 +119,7 @@ export declare function index<T>(collection: GoStringValue | Slice<T> | T[], ind
119
119
  * indexRef returns an addressable reference to a slice or array element.
120
120
  */
121
121
  export declare function indexRef<T>(collection: Slice<T> | T[] | Uint8Array, index: number): VarRef<T>;
122
+ export declare function sliceFromOwnedPointer<T>(pointer: OwnedPointerHandle<T>, length: number): Slice<T> | Uint8Array;
122
123
  /**
123
124
  * arrayPointerFromIndexRef turns &slice[i] into a pointer to an N-element array
124
125
  * view. This models unsafe conversions such as (*[64]byte)(unsafe.Pointer(&b[0]))
@@ -1,4 +1,4 @@
1
- import { isVarRef, varRef } from './varRef.js';
1
+ import { isOwnedPointerHandle, isVarRef, varRef, } from './varRef.js';
2
2
  export class GoBinaryString extends String {
3
3
  bytes;
4
4
  constructor(bytes) {
@@ -926,7 +926,7 @@ export function indexRef(collection, index) {
926
926
  if (index < 0 || index >= collection.length) {
927
927
  throw new Error(`runtime error: index out of range [${index}] with length ${collection.length}`);
928
928
  }
929
- return {
929
+ const ref = {
930
930
  get value() {
931
931
  return collection[index];
932
932
  },
@@ -938,13 +938,15 @@ export function indexRef(collection, index) {
938
938
  __goCollection: collection,
939
939
  __goIndex: index,
940
940
  };
941
+ ref.__goPointer = collectionPointer(ref, collection, index);
942
+ return ref;
941
943
  }
942
944
  if (isComplexSlice(collection)) {
943
945
  if (index < 0 || index >= collection.__meta__.length) {
944
946
  throw new Error(`runtime error: index out of range [${index}] with length ${collection.__meta__.length}`);
945
947
  }
946
948
  const backingIndex = collection.__meta__.offset + index;
947
- return {
949
+ const ref = {
948
950
  get value() {
949
951
  return collection.__meta__.backing[backingIndex];
950
952
  },
@@ -956,12 +958,14 @@ export function indexRef(collection, index) {
956
958
  __goCollection: collection,
957
959
  __goIndex: index,
958
960
  };
961
+ ref.__goPointer = collectionPointer(ref, collection, index);
962
+ return ref;
959
963
  }
960
964
  if (Array.isArray(collection)) {
961
965
  if (index < 0 || index >= collection.length) {
962
966
  throw new Error(`runtime error: index out of range [${index}] with length ${collection.length}`);
963
967
  }
964
- return {
968
+ const ref = {
965
969
  get value() {
966
970
  return collection[index];
967
971
  },
@@ -973,9 +977,30 @@ export function indexRef(collection, index) {
973
977
  __goCollection: collection,
974
978
  __goIndex: index,
975
979
  };
980
+ ref.__goPointer = collectionPointer(ref, collection, index);
981
+ return ref;
976
982
  }
977
983
  throw new Error('runtime error: index on unsupported type');
978
984
  }
985
+ function collectionPointer(ref, collection, index) {
986
+ return {
987
+ __goOwnedPointer: true,
988
+ __goAddress: () => indexAddress(collection, index),
989
+ __goRef: () => ref,
990
+ __goSlice: (length) => {
991
+ if (length < 0) {
992
+ throw new Error('runtime error: unsafe slice length out of range');
993
+ }
994
+ return goSlice(collection, index, index + length, index + length);
995
+ },
996
+ };
997
+ }
998
+ export function sliceFromOwnedPointer(pointer, length) {
999
+ if (!isOwnedPointerHandle(pointer) || pointer.__goSlice === undefined) {
1000
+ throw new Error('reflect.SliceAt requires a GoScript-owned pointer');
1001
+ }
1002
+ return pointer.__goSlice(length);
1003
+ }
979
1004
  /**
980
1005
  * arrayPointerFromIndexRef turns &slice[i] into a pointer to an N-element array
981
1006
  * view. This models unsafe conversions such as (*[64]byte)(unsafe.Pointer(&b[0]))