goscript 0.1.3 → 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 (330) 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} +35 -8
  5. package/cmd/goscript/cmd-test.go +14 -0
  6. package/cmd/goscript/cmd-test_test.go +1 -1
  7. package/cmd/goscript/cmd_compile_test.go +105 -6
  8. package/compiler/build-flags.go +9 -10
  9. package/compiler/compile-request.go +12 -9
  10. package/compiler/compliance_test.go +0 -1
  11. package/compiler/config.go +2 -0
  12. package/compiler/gotest/request.go +28 -0
  13. package/compiler/gotest/runner.go +353 -27
  14. package/compiler/gotest/runner_test.go +400 -1
  15. package/compiler/gotest/testdata/browserapi/browserapi_test.go +20 -0
  16. package/compiler/gotest/testdata/browserapi/go.mod +3 -0
  17. package/compiler/lowered-program.go +24 -17
  18. package/compiler/lowering.go +988 -263
  19. package/compiler/lowering_bench_test.go +364 -0
  20. package/compiler/override-facts.go +15 -0
  21. package/compiler/override-parity-verifier.go +450 -0
  22. package/compiler/override-parity.go +122 -0
  23. package/compiler/override-registry_test.go +559 -0
  24. package/compiler/package-graph.go +61 -4
  25. package/compiler/package-graph_test.go +30 -0
  26. package/compiler/protobuf-ts-binding.go +514 -0
  27. package/compiler/protobuf-ts-binding_test.go +172 -0
  28. package/compiler/semantic-model-types.go +17 -4
  29. package/compiler/semantic-model.go +709 -72
  30. package/compiler/semantic-model_test.go +219 -0
  31. package/compiler/service.go +20 -1
  32. package/compiler/skeleton_test.go +1008 -20
  33. package/compiler/typescript-emitter.go +147 -15
  34. package/dist/gs/builtin/builtin.d.ts +2 -2
  35. package/dist/gs/builtin/builtin.js +20 -0
  36. package/dist/gs/builtin/builtin.js.map +1 -1
  37. package/dist/gs/builtin/slice.d.ts +2 -1
  38. package/dist/gs/builtin/slice.js +34 -4
  39. package/dist/gs/builtin/slice.js.map +1 -1
  40. package/dist/gs/builtin/type.d.ts +14 -6
  41. package/dist/gs/builtin/type.js +224 -64
  42. package/dist/gs/builtin/type.js.map +1 -1
  43. package/dist/gs/builtin/varRef.d.ts +11 -0
  44. package/dist/gs/builtin/varRef.js +57 -2
  45. package/dist/gs/builtin/varRef.js.map +1 -1
  46. package/dist/gs/bytes/buffer.gs.js +1 -1
  47. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  48. package/dist/gs/bytes/reader.gs.js +1 -1
  49. package/dist/gs/bytes/reader.gs.js.map +1 -1
  50. package/dist/gs/compress/zlib/index.d.ts +13 -6
  51. package/dist/gs/compress/zlib/index.js +131 -35
  52. package/dist/gs/compress/zlib/index.js.map +1 -1
  53. package/dist/gs/crypto/sha1/index.js +2 -5
  54. package/dist/gs/crypto/sha1/index.js.map +1 -1
  55. package/dist/gs/crypto/sha256/index.js +2 -5
  56. package/dist/gs/crypto/sha256/index.js.map +1 -1
  57. package/dist/gs/crypto/sha512/index.js +2 -5
  58. package/dist/gs/crypto/sha512/index.js.map +1 -1
  59. package/dist/gs/embed/index.d.ts +6 -0
  60. package/dist/gs/embed/index.js +210 -5
  61. package/dist/gs/embed/index.js.map +1 -1
  62. package/dist/gs/encoding/json/index.d.ts +114 -0
  63. package/dist/gs/encoding/json/index.js +544 -36
  64. package/dist/gs/encoding/json/index.js.map +1 -1
  65. package/dist/gs/fmt/fmt.d.ts +3 -3
  66. package/dist/gs/fmt/fmt.js +29 -16
  67. package/dist/gs/fmt/fmt.js.map +1 -1
  68. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +100 -0
  69. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +564 -0
  70. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  71. package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.d.ts +45 -0
  72. package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js +229 -0
  73. package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js.map +1 -0
  74. package/dist/gs/github.com/pkg/errors/errors.js +54 -30
  75. package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
  76. package/dist/gs/go/scanner/index.d.ts +2 -0
  77. package/dist/gs/go/scanner/index.js +29 -5
  78. package/dist/gs/go/scanner/index.js.map +1 -1
  79. package/dist/gs/go/token/index.js +22 -6
  80. package/dist/gs/go/token/index.js.map +1 -1
  81. package/dist/gs/hash/index.d.ts +6 -0
  82. package/dist/gs/hash/index.js +20 -0
  83. package/dist/gs/hash/index.js.map +1 -1
  84. package/dist/gs/internal/goarch/index.d.ts +43 -3
  85. package/dist/gs/internal/goarch/index.js +42 -10
  86. package/dist/gs/internal/goarch/index.js.map +1 -1
  87. package/dist/gs/io/fs/fs.js +26 -14
  88. package/dist/gs/io/fs/fs.js.map +1 -1
  89. package/dist/gs/io/fs/readdir.js +8 -4
  90. package/dist/gs/io/fs/readdir.js.map +1 -1
  91. package/dist/gs/io/fs/sub.js +8 -1
  92. package/dist/gs/io/fs/sub.js.map +1 -1
  93. package/dist/gs/io/io.d.ts +12 -6
  94. package/dist/gs/io/io.js +87 -42
  95. package/dist/gs/io/io.js.map +1 -1
  96. package/dist/gs/math/bits/index.d.ts +31 -5
  97. package/dist/gs/math/bits/index.js +29 -28
  98. package/dist/gs/math/bits/index.js.map +1 -1
  99. package/dist/gs/mime/index.d.ts +16 -0
  100. package/dist/gs/mime/index.js +315 -6
  101. package/dist/gs/mime/index.js.map +1 -1
  102. package/dist/gs/net/http/httptest/index.d.ts +12 -0
  103. package/dist/gs/net/http/httptest/index.js +85 -6
  104. package/dist/gs/net/http/httptest/index.js.map +1 -1
  105. package/dist/gs/net/http/index.d.ts +303 -6
  106. package/dist/gs/net/http/index.js +1615 -58
  107. package/dist/gs/net/http/index.js.map +1 -1
  108. package/dist/gs/os/dir_unix.gs.js +1 -1
  109. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  110. package/dist/gs/os/error.gs.js +1 -1
  111. package/dist/gs/os/error.gs.js.map +1 -1
  112. package/dist/gs/os/exec.gs.d.ts +1 -0
  113. package/dist/gs/os/exec.gs.js +4 -8
  114. package/dist/gs/os/exec.gs.js.map +1 -1
  115. package/dist/gs/os/exec_posix.gs.js +1 -1
  116. package/dist/gs/os/exec_posix.gs.js.map +1 -1
  117. package/dist/gs/os/index.d.ts +1 -1
  118. package/dist/gs/os/index.js +1 -1
  119. package/dist/gs/os/index.js.map +1 -1
  120. package/dist/gs/os/proc.gs.d.ts +4 -0
  121. package/dist/gs/os/proc.gs.js +12 -6
  122. package/dist/gs/os/proc.gs.js.map +1 -1
  123. package/dist/gs/os/root_js.gs.js +1 -1
  124. package/dist/gs/os/root_js.gs.js.map +1 -1
  125. package/dist/gs/os/types.gs.js +1 -1
  126. package/dist/gs/os/types.gs.js.map +1 -1
  127. package/dist/gs/os/types_js.gs.d.ts +6 -2
  128. package/dist/gs/os/types_js.gs.js +170 -9
  129. package/dist/gs/os/types_js.gs.js.map +1 -1
  130. package/dist/gs/os/types_unix.gs.js +1 -1
  131. package/dist/gs/os/types_unix.gs.js.map +1 -1
  132. package/dist/gs/path/path.js +11 -7
  133. package/dist/gs/path/path.js.map +1 -1
  134. package/dist/gs/reflect/index.d.ts +5 -4
  135. package/dist/gs/reflect/index.js +4 -3
  136. package/dist/gs/reflect/index.js.map +1 -1
  137. package/dist/gs/reflect/map.js +15 -0
  138. package/dist/gs/reflect/map.js.map +1 -1
  139. package/dist/gs/reflect/type.d.ts +26 -6
  140. package/dist/gs/reflect/type.js +1498 -279
  141. package/dist/gs/reflect/type.js.map +1 -1
  142. package/dist/gs/reflect/types.d.ts +14 -6
  143. package/dist/gs/reflect/types.js +35 -1
  144. package/dist/gs/reflect/types.js.map +1 -1
  145. package/dist/gs/reflect/value.d.ts +1 -0
  146. package/dist/gs/reflect/value.js +83 -41
  147. package/dist/gs/reflect/value.js.map +1 -1
  148. package/dist/gs/reflect/visiblefields.js +4 -140
  149. package/dist/gs/reflect/visiblefields.js.map +1 -1
  150. package/dist/gs/runtime/pprof/index.d.ts +8 -2
  151. package/dist/gs/runtime/pprof/index.js +50 -30
  152. package/dist/gs/runtime/pprof/index.js.map +1 -1
  153. package/dist/gs/runtime/runtime.js +5 -4
  154. package/dist/gs/runtime/runtime.js.map +1 -1
  155. package/dist/gs/runtime/trace/index.js +5 -19
  156. package/dist/gs/runtime/trace/index.js.map +1 -1
  157. package/dist/gs/strconv/atoi.gs.js +1 -1
  158. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  159. package/dist/gs/strconv/complex.gs.d.ts +3 -0
  160. package/dist/gs/strconv/complex.gs.js +148 -0
  161. package/dist/gs/strconv/complex.gs.js.map +1 -0
  162. package/dist/gs/strconv/index.d.ts +1 -0
  163. package/dist/gs/strconv/index.js +1 -0
  164. package/dist/gs/strconv/index.js.map +1 -1
  165. package/dist/gs/strings/builder.js +1 -1
  166. package/dist/gs/strings/reader.d.ts +1 -1
  167. package/dist/gs/strings/reader.js +11 -7
  168. package/dist/gs/strings/reader.js.map +1 -1
  169. package/dist/gs/strings/replace.js +15 -7
  170. package/dist/gs/strings/replace.js.map +1 -1
  171. package/dist/gs/strings/strings.d.ts +5 -0
  172. package/dist/gs/strings/strings.js +57 -5
  173. package/dist/gs/strings/strings.js.map +1 -1
  174. package/dist/gs/sync/atomic/type.gs.js +9 -9
  175. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  176. package/dist/gs/sync/atomic/value.gs.js +2 -2
  177. package/dist/gs/sync/atomic/value.gs.js.map +1 -1
  178. package/dist/gs/sync/sync.d.ts +2 -1
  179. package/dist/gs/sync/sync.js +37 -16
  180. package/dist/gs/sync/sync.js.map +1 -1
  181. package/dist/gs/syscall/env.js +22 -14
  182. package/dist/gs/syscall/env.js.map +1 -1
  183. package/dist/gs/syscall/js/index.js +9 -0
  184. package/dist/gs/syscall/js/index.js.map +1 -1
  185. package/dist/gs/testing/testing.js +59 -15
  186. package/dist/gs/testing/testing.js.map +1 -1
  187. package/dist/gs/time/time.d.ts +24 -1
  188. package/dist/gs/time/time.js +43 -3
  189. package/dist/gs/time/time.js.map +1 -1
  190. package/dist/gs/unique/index.js +7 -1
  191. package/dist/gs/unique/index.js.map +1 -1
  192. package/go.mod +3 -3
  193. package/go.sum +16 -0
  194. package/gs/builtin/builtin.ts +25 -2
  195. package/gs/builtin/runtime-contract.test.ts +260 -18
  196. package/gs/builtin/slice.ts +51 -4
  197. package/gs/builtin/type.ts +310 -63
  198. package/gs/builtin/varRef.ts +85 -2
  199. package/gs/bytes/buffer.gs.ts +1 -1
  200. package/gs/bytes/reader.gs.ts +1 -1
  201. package/gs/compress/zlib/index.test.ts +159 -1
  202. package/gs/compress/zlib/index.ts +164 -37
  203. package/gs/compress/zlib/meta.json +4 -1
  204. package/gs/compress/zlib/parity.json +51 -0
  205. package/gs/crypto/sha1/index.test.ts +19 -2
  206. package/gs/crypto/sha1/index.ts +3 -6
  207. package/gs/crypto/sha256/index.test.ts +14 -2
  208. package/gs/crypto/sha256/index.ts +3 -6
  209. package/gs/crypto/sha512/index.test.ts +17 -2
  210. package/gs/crypto/sha512/index.ts +3 -6
  211. package/gs/embed/index.test.ts +87 -0
  212. package/gs/embed/index.ts +229 -5
  213. package/gs/encoding/json/index.test.ts +360 -6
  214. package/gs/encoding/json/index.ts +679 -38
  215. package/gs/encoding/json/parity.json +81 -0
  216. package/gs/fmt/fmt.test.ts +41 -3
  217. package/gs/fmt/fmt.ts +40 -17
  218. package/gs/fmt/meta.json +6 -1
  219. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +211 -3
  220. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +857 -1
  221. package/gs/github.com/go-git/go-billy/v6/osfs/index.test.ts +110 -0
  222. package/gs/github.com/go-git/go-billy/v6/osfs/index.ts +280 -0
  223. package/gs/github.com/go-git/go-billy/v6/osfs/meta.json +8 -0
  224. package/gs/github.com/pkg/errors/errors.ts +54 -30
  225. package/gs/go/scanner/index.test.ts +39 -56
  226. package/gs/go/scanner/index.ts +33 -5
  227. package/gs/go/scanner/parity.json +27 -0
  228. package/gs/go/token/index.ts +22 -6
  229. package/gs/hash/index.test.ts +20 -33
  230. package/gs/hash/index.ts +28 -0
  231. package/gs/hash/parity.json +21 -0
  232. package/gs/internal/goarch/index.test.ts +32 -0
  233. package/gs/internal/goarch/index.ts +45 -13
  234. package/gs/internal/goarch/parity.json +144 -0
  235. package/gs/io/fs/fs.ts +26 -14
  236. package/gs/io/fs/readdir.test.ts +38 -0
  237. package/gs/io/fs/readdir.ts +8 -4
  238. package/gs/io/fs/sub.ts +8 -1
  239. package/gs/io/io.test.ts +77 -6
  240. package/gs/io/io.ts +115 -52
  241. package/gs/io/meta.json +7 -1
  242. package/gs/io/parity.json +162 -0
  243. package/gs/math/bits/index.test.ts +14 -1
  244. package/gs/math/bits/index.ts +75 -32
  245. package/gs/math/bits/parity.json +156 -0
  246. package/gs/mime/index.test.ts +90 -0
  247. package/gs/mime/index.ts +369 -6
  248. package/gs/mime/parity.json +36 -0
  249. package/gs/net/http/httptest/index.test.ts +98 -2
  250. package/gs/net/http/httptest/index.ts +101 -6
  251. package/gs/net/http/httptest/parity.json +15 -0
  252. package/gs/net/http/index.test.ts +797 -12
  253. package/gs/net/http/index.ts +1874 -136
  254. package/gs/net/http/meta.json +16 -1
  255. package/gs/net/http/parity.json +193 -0
  256. package/gs/os/dir_unix.gs.ts +1 -1
  257. package/gs/os/error.gs.ts +1 -1
  258. package/gs/os/exec.gs.ts +4 -8
  259. package/gs/os/exec_posix.gs.ts +1 -1
  260. package/gs/os/file_unix_js.test.ts +52 -0
  261. package/gs/os/index.test.ts +9 -0
  262. package/gs/os/index.ts +1 -0
  263. package/gs/os/meta.json +4 -0
  264. package/gs/os/parity.json +9 -0
  265. package/gs/os/proc.gs.ts +18 -5
  266. package/gs/os/proc.test.ts +26 -0
  267. package/gs/os/readdir.test.ts +56 -0
  268. package/gs/os/root_js.gs.ts +1 -1
  269. package/gs/os/types.gs.ts +1 -1
  270. package/gs/os/types_js.gs.ts +170 -9
  271. package/gs/os/types_unix.gs.ts +1 -1
  272. package/gs/path/path.ts +11 -7
  273. package/gs/reflect/deepequal.test.ts +10 -1
  274. package/gs/reflect/field.test.ts +37 -15
  275. package/gs/reflect/function-types.test.ts +518 -22
  276. package/gs/reflect/index.ts +8 -6
  277. package/gs/reflect/map.ts +20 -0
  278. package/gs/reflect/meta.json +6 -4
  279. package/gs/reflect/parity.json +234 -0
  280. package/gs/reflect/sliceat.test.ts +156 -0
  281. package/gs/reflect/structof.test.ts +401 -0
  282. package/gs/reflect/type.ts +1980 -365
  283. package/gs/reflect/typefor.test.ts +540 -10
  284. package/gs/reflect/types.ts +43 -18
  285. package/gs/reflect/value.ts +105 -45
  286. package/gs/reflect/visiblefields.ts +5 -168
  287. package/gs/runtime/parity.json +24 -0
  288. package/gs/runtime/pprof/index.test.ts +29 -7
  289. package/gs/runtime/pprof/index.ts +56 -30
  290. package/gs/runtime/pprof/parity.json +27 -0
  291. package/gs/runtime/runtime.test.ts +3 -1
  292. package/gs/runtime/runtime.ts +4 -3
  293. package/gs/runtime/trace/index.test.ts +5 -3
  294. package/gs/runtime/trace/index.ts +8 -20
  295. package/gs/runtime/trace/parity.json +36 -0
  296. package/gs/strconv/atoi.gs.ts +1 -1
  297. package/gs/strconv/complex.gs.ts +174 -0
  298. package/gs/strconv/complex.test.ts +65 -0
  299. package/gs/strconv/index.ts +1 -0
  300. package/gs/strconv/parity.json +120 -0
  301. package/gs/strings/builder.ts +1 -1
  302. package/gs/strings/meta.json +5 -2
  303. package/gs/strings/parity.json +186 -0
  304. package/gs/strings/reader.test.ts +2 -2
  305. package/gs/strings/reader.ts +11 -7
  306. package/gs/strings/replace.ts +15 -7
  307. package/gs/strings/strings.test.ts +22 -2
  308. package/gs/strings/strings.ts +64 -6
  309. package/gs/sync/atomic/type.gs.ts +9 -9
  310. package/gs/sync/atomic/value.gs.ts +2 -2
  311. package/gs/sync/meta.json +1 -0
  312. package/gs/sync/sync.test.ts +41 -1
  313. package/gs/sync/sync.ts +41 -16
  314. package/gs/syscall/env.ts +29 -14
  315. package/gs/syscall/js/index.test.ts +18 -0
  316. package/gs/syscall/js/index.ts +12 -0
  317. package/gs/testing/testing.test.ts +99 -3
  318. package/gs/testing/testing.ts +95 -24
  319. package/gs/time/parity.json +225 -0
  320. package/gs/time/time.test.ts +20 -2
  321. package/gs/time/time.ts +49 -7
  322. package/gs/unique/index.ts +7 -1
  323. package/package.json +4 -2
  324. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +0 -217
  325. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +0 -814
  326. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +0 -1
  327. package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +0 -31
  328. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +0 -1233
  329. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +0 -46
  330. /package/compiler/{wasm_api.go → wasm-api.go} +0 -0
@@ -3,12 +3,25 @@ import {
3
3
  makeMap,
4
4
  mapGet,
5
5
  mapSet,
6
+ markAsStructValue,
7
+ namedValueInterfaceValue,
6
8
  TypeKind,
7
9
  registerInterfaceType,
8
10
  registerStructType,
11
+ varRef,
9
12
  } from '../builtin/index.js'
10
13
  import { StructField } from './types.js'
11
- import { Int, Struct, TypeFor } from './type.js'
14
+ import {
15
+ Int,
16
+ Ptr,
17
+ Struct,
18
+ StructOf,
19
+ TypeFor,
20
+ TypeOf,
21
+ Uint64,
22
+ ValueOf,
23
+ } from './type.js'
24
+ import { Indirect, New, Zero } from './value.js'
12
25
 
13
26
  describe('TypeFor', () => {
14
27
  it('exposes StructField PkgPath and exported semantics', () => {
@@ -48,6 +61,129 @@ describe('TypeFor', () => {
48
61
  expect(namedIntType.Kind()).toBe(Int)
49
62
  })
50
63
 
64
+ it('preserves generic method signatures for named basic types', () => {
65
+ const stringResult = { kind: TypeKind.Basic, name: 'string' } as const
66
+ const namedIntDescriptor = {
67
+ kind: TypeKind.Basic,
68
+ name: 'int',
69
+ typeName: 'main.MyInt',
70
+ } as const
71
+ const methodSignatures = [
72
+ {
73
+ name: 'String',
74
+ args: [],
75
+ returns: [{ type: stringResult }],
76
+ },
77
+ ]
78
+ const preexisting = TypeFor({
79
+ T: {
80
+ type: namedIntDescriptor,
81
+ zero: () => 0,
82
+ },
83
+ })
84
+
85
+ const namedIntType = TypeFor({
86
+ T: {
87
+ type: namedIntDescriptor,
88
+ zero: () => 0,
89
+ methods: { String: (receiver: number) => String(receiver) },
90
+ methodSignatures,
91
+ },
92
+ })
93
+ const stringerType = TypeFor({
94
+ T: {
95
+ type: {
96
+ kind: TypeKind.Interface,
97
+ methods: methodSignatures,
98
+ },
99
+ zero: () => null,
100
+ },
101
+ })
102
+
103
+ expect(namedIntType).toBe(preexisting)
104
+ expect(namedIntType.NumMethod()).toBe(1)
105
+ const [method, ok] = namedIntType.MethodByName('String')
106
+ expect(ok).toBe(true)
107
+ expect(method.Type.NumIn()).toBe(1)
108
+ expect(method.Type.NumOut()).toBe(1)
109
+ expect(method.Type.Out(0).String()).toBe('string')
110
+ expect(namedIntType.Implements(stringerType)).toBe(true)
111
+ })
112
+
113
+ it('preserves generic method signatures for pointers to named basic types', () => {
114
+ const stringResult = { kind: TypeKind.Basic, name: 'string' } as const
115
+ const methodSignatures = [
116
+ {
117
+ name: 'String',
118
+ args: [],
119
+ returns: [{ type: stringResult }],
120
+ },
121
+ ]
122
+ const pointerType = TypeFor({
123
+ T: {
124
+ type: {
125
+ kind: TypeKind.Pointer,
126
+ elemType: {
127
+ kind: TypeKind.Basic,
128
+ name: 'bool',
129
+ typeName: 'main.MyBool',
130
+ },
131
+ },
132
+ zero: () => null,
133
+ methods: { String: () => 'true' },
134
+ methodSignatures,
135
+ },
136
+ })
137
+ const stringerType = TypeFor({
138
+ T: {
139
+ type: {
140
+ kind: TypeKind.Interface,
141
+ methods: methodSignatures,
142
+ },
143
+ zero: () => null,
144
+ },
145
+ })
146
+
147
+ expect(pointerType.Kind()).toBe(Ptr)
148
+ expect(pointerType.String()).toBe('*main.MyBool')
149
+ expect(pointerType.NumMethod()).toBe(1)
150
+ const [method, ok] = pointerType.MethodByName('String')
151
+ expect(ok).toBe(true)
152
+ expect(method.Type.NumIn()).toBe(1)
153
+ expect(method.Type.In(0)).toBe(pointerType)
154
+ expect(method.Type.NumOut()).toBe(1)
155
+ expect(method.Type.Out(0).String()).toBe('string')
156
+ expect(pointerType.Implements(stringerType)).toBe(true)
157
+ })
158
+
159
+ it('preserves named pointer type metadata on interface boxes', () => {
160
+ const target = varRef(0)
161
+ const boxed = namedValueInterfaceValue(
162
+ target,
163
+ '*chunker.Pol',
164
+ {},
165
+ {
166
+ kind: TypeKind.Pointer,
167
+ elemType: {
168
+ kind: TypeKind.Basic,
169
+ name: 'uint64',
170
+ typeName: 'chunker.Pol',
171
+ },
172
+ },
173
+ )
174
+
175
+ const typ = TypeOf(boxed)
176
+ expect(typ.String()).toBe('*chunker.Pol')
177
+ expect(typ.Kind()).toBe(Ptr)
178
+ expect(typ.Elem().Kind()).toBe(Uint64)
179
+ expect(typ.Elem().Name()).toBe('Pol')
180
+
181
+ const elem = ValueOf(boxed).Elem()
182
+ expect(elem.Kind()).toBe(Uint64)
183
+ elem.SetUint(15)
184
+ expect(target.value).toBe(15)
185
+ })
186
+
51
187
  it('formats literal interface methods from type metadata', () => {
52
188
  const ifaceType = TypeFor({
53
189
  T: {
@@ -62,6 +198,130 @@ describe('TypeFor', () => {
62
198
  expect(ifaceType.String()).toBe('interface { SomeMethod() }')
63
199
  })
64
200
 
201
+ it('handles recursive interface method metadata', () => {
202
+ const recursiveMethod = {
203
+ name: 'Visit',
204
+ args: [{ name: 'next', type: 'main.RecursiveInterface' }],
205
+ returns: [{ name: '_r0', type: 'main.RecursiveInterface' }],
206
+ }
207
+ registerInterfaceType('main.RecursiveInterface', null, [recursiveMethod])
208
+
209
+ class RecursiveImpl {
210
+ public Visit(next: unknown): unknown {
211
+ return next
212
+ }
213
+ }
214
+
215
+ const typeInfo = registerStructType(
216
+ 'main.RecursiveImpl',
217
+ new RecursiveImpl(),
218
+ [recursiveMethod],
219
+ RecursiveImpl,
220
+ [],
221
+ )
222
+ ;(RecursiveImpl as any).__typeInfo = typeInfo
223
+
224
+ const ifaceType = TypeFor({
225
+ T: { type: 'main.RecursiveInterface', zero: () => null },
226
+ })
227
+
228
+ expect(ifaceType.String()).toBe(
229
+ 'interface { Visit(main.RecursiveInterface) main.RecursiveInterface }',
230
+ )
231
+ expect(ifaceType.AssignableTo(ifaceType)).toBe(true)
232
+ expect(TypeOf(new RecursiveImpl()).AssignableTo(ifaceType)).toBe(true)
233
+ })
234
+
235
+ it('handles recursive struct field metadata', () => {
236
+ class RecursiveNode {
237
+ public Next: RecursiveNode | null = null
238
+ }
239
+
240
+ const typeInfo = registerStructType(
241
+ 'main.RecursiveNode',
242
+ new RecursiveNode(),
243
+ [],
244
+ RecursiveNode,
245
+ [
246
+ {
247
+ name: 'Next',
248
+ key: 'Next',
249
+ type: {
250
+ kind: TypeKind.Pointer,
251
+ elemType: 'main.RecursiveNode',
252
+ },
253
+ },
254
+ ],
255
+ )
256
+ Object.assign(RecursiveNode, { __typeInfo: typeInfo })
257
+
258
+ const nodeType = TypeFor({
259
+ T: { type: 'main.RecursiveNode', zero: () => new RecursiveNode() },
260
+ })
261
+
262
+ expect(nodeType.Kind()).toBe(Struct)
263
+ expect(nodeType.Field(0).Name).toBe('Next')
264
+ expect(nodeType.Field(0).Type.String()).toBe('*main.RecursiveNode')
265
+ expect(nodeType.Field(0).Type.Elem().NumField()).toBe(1)
266
+ expect(nodeType.Field(0).Type.Elem().Field(0).Type.String()).toBe(
267
+ '*main.RecursiveNode',
268
+ )
269
+ expect(TypeOf(new RecursiveNode()).Field(0).Type.String()).toBe(
270
+ '*main.RecursiveNode',
271
+ )
272
+ expect(TypeOf(new RecursiveNode()).Field(0).Type.Elem().NumField()).toBe(1)
273
+ })
274
+
275
+ it('keeps mutually recursive registered struct identity canonical', () => {
276
+ class RecursiveA {
277
+ public B: RecursiveB | null = null
278
+ }
279
+ class RecursiveB {
280
+ public A: RecursiveA | null = null
281
+ }
282
+
283
+ const aInfo = registerStructType(
284
+ 'main.RecursiveA',
285
+ new RecursiveA(),
286
+ [],
287
+ RecursiveA,
288
+ [
289
+ {
290
+ name: 'B',
291
+ key: 'B',
292
+ type: { kind: TypeKind.Pointer, elemType: 'main.RecursiveB' },
293
+ },
294
+ ],
295
+ )
296
+ const bInfo = registerStructType(
297
+ 'main.RecursiveB',
298
+ new RecursiveB(),
299
+ [],
300
+ RecursiveB,
301
+ [
302
+ {
303
+ name: 'A',
304
+ key: 'A',
305
+ type: { kind: TypeKind.Pointer, elemType: 'main.RecursiveA' },
306
+ },
307
+ ],
308
+ )
309
+ Object.assign(RecursiveA, { __typeInfo: aInfo })
310
+ Object.assign(RecursiveB, { __typeInfo: bInfo })
311
+
312
+ const aType = TypeFor({
313
+ T: { type: 'main.RecursiveA', zero: () => new RecursiveA() },
314
+ })
315
+ const bType = TypeFor({
316
+ T: { type: 'main.RecursiveB', zero: () => new RecursiveB() },
317
+ })
318
+ const bFromA = aType.Field(0).Type.Elem()
319
+
320
+ expect(bFromA.NumField()).toBe(1)
321
+ expect(bFromA).toBe(bType)
322
+ expect(bType.Field(0).Type.Elem()).toBe(aType)
323
+ })
324
+
65
325
  it('formats unnamed function signatures from type metadata', () => {
66
326
  const fnType = TypeFor({
67
327
  T: {
@@ -75,6 +335,194 @@ describe('TypeFor', () => {
75
335
  })
76
336
 
77
337
  expect(fnType.String()).toBe('func(int) string')
338
+ expect(fnType.NumIn()).toBe(1)
339
+ expect(fnType.In(0).String()).toBe('int')
340
+ expect(fnType.NumOut()).toBe(1)
341
+ expect(fnType.Out(0).String()).toBe('string')
342
+ expect(fnType.IsVariadic()).toBe(false)
343
+ })
344
+
345
+ it('preserves named and variadic function descriptors', () => {
346
+ const namedFnType = TypeFor({
347
+ T: {
348
+ type: {
349
+ kind: TypeKind.Function,
350
+ name: 'example.test.Callback',
351
+ params: [{ kind: TypeKind.Basic, name: 'int' }],
352
+ results: [{ kind: TypeKind.Basic, name: 'string' }],
353
+ },
354
+ zero: () => null,
355
+ },
356
+ })
357
+
358
+ expect(namedFnType.String()).toBe('example.test.Callback')
359
+ expect(namedFnType.PkgPath()).toBe('example.test')
360
+ expect(namedFnType.Name()).toBe('Callback')
361
+ expect(namedFnType.NumIn()).toBe(1)
362
+ expect(namedFnType.In(0).String()).toBe('int')
363
+ expect(namedFnType.NumOut()).toBe(1)
364
+ expect(namedFnType.Out(0).String()).toBe('string')
365
+
366
+ const variadicFnType = TypeFor({
367
+ T: {
368
+ type: {
369
+ kind: TypeKind.Function,
370
+ params: [
371
+ {
372
+ kind: TypeKind.Slice,
373
+ elemType: { kind: TypeKind.Basic, name: 'string' },
374
+ },
375
+ ],
376
+ results: [{ kind: TypeKind.Basic, name: 'int' }],
377
+ isVariadic: true,
378
+ },
379
+ zero: () => null,
380
+ },
381
+ })
382
+
383
+ expect(variadicFnType.String()).toBe('func(...string) int')
384
+ expect(variadicFnType.NumIn()).toBe(1)
385
+ expect(variadicFnType.In(0).String()).toBe('[]string')
386
+ expect(variadicFnType.NumOut()).toBe(1)
387
+ expect(variadicFnType.Out(0).String()).toBe('int')
388
+ expect(variadicFnType.IsVariadic()).toBe(true)
389
+ })
390
+
391
+ it('rehydrates anonymous struct descriptors as unnamed struct types', () => {
392
+ const intType = TypeOf(0)
393
+ const descriptor = {
394
+ kind: TypeKind.Struct,
395
+ methods: [],
396
+ fields: [
397
+ {
398
+ name: 'X',
399
+ key: 'X',
400
+ type: { kind: TypeKind.Basic, name: 'int' },
401
+ tag: 'json:"x"',
402
+ index: [0],
403
+ offset: 0,
404
+ exported: true,
405
+ },
406
+ ],
407
+ } as const
408
+
409
+ const typ = TypeFor({
410
+ T: {
411
+ type: descriptor,
412
+ zero: () => ({ X: 0 }),
413
+ },
414
+ })
415
+ const dynamic = StructOf([
416
+ new StructField({
417
+ Name: 'X',
418
+ Type: intType,
419
+ Tag: 'json:"x"',
420
+ }),
421
+ ])
422
+
423
+ expect(typ.String()).toBe('struct { X int "json:\\"x\\"" }')
424
+ expect(typ.Name()).toBe('')
425
+ expect(typ.PkgPath()).toBe('')
426
+ expect(typ.NumField()).toBe(1)
427
+ expect(typ.Field(0).Name).toBe('X')
428
+ expect(typ.Field(0).Tag.Get('json')).toBe('x')
429
+ expect(typ.AssignableTo(dynamic)).toBe(true)
430
+ expect(dynamic.AssignableTo(typ)).toBe(true)
431
+ })
432
+
433
+ it('uses full anonymous struct identity in method signatures', () => {
434
+ const baseField = {
435
+ name: 'X',
436
+ key: 'X',
437
+ type: { kind: TypeKind.Basic, name: 'int' },
438
+ index: [0],
439
+ offset: 0,
440
+ exported: true,
441
+ } as const
442
+ const taggedParam = {
443
+ kind: TypeKind.Struct,
444
+ methods: [],
445
+ fields: [{ ...baseField, tag: 'json:"a"' }],
446
+ } as const
447
+ const methodSignatures = [
448
+ {
449
+ name: 'Accept',
450
+ args: [{ type: taggedParam }],
451
+ returns: [],
452
+ },
453
+ ]
454
+ const receiverType = TypeFor({
455
+ T: {
456
+ type: { kind: TypeKind.Basic, name: 'int', typeName: 'main.Receiver' },
457
+ zero: () => 0,
458
+ methodSignatures,
459
+ },
460
+ })
461
+ const sameInterface = TypeFor({
462
+ T: {
463
+ type: {
464
+ kind: TypeKind.Interface,
465
+ methods: methodSignatures,
466
+ },
467
+ zero: () => null,
468
+ },
469
+ })
470
+ const differentTagInterface = TypeFor({
471
+ T: {
472
+ type: {
473
+ kind: TypeKind.Interface,
474
+ methods: [
475
+ {
476
+ name: 'Accept',
477
+ args: [
478
+ {
479
+ type: {
480
+ kind: TypeKind.Struct,
481
+ methods: [],
482
+ fields: [{ ...baseField, tag: 'json:"b"' }],
483
+ },
484
+ },
485
+ ],
486
+ returns: [],
487
+ },
488
+ ],
489
+ },
490
+ zero: () => null,
491
+ },
492
+ })
493
+ const differentEmbeddingInterface = TypeFor({
494
+ T: {
495
+ type: {
496
+ kind: TypeKind.Interface,
497
+ methods: [
498
+ {
499
+ name: 'Accept',
500
+ args: [
501
+ {
502
+ type: {
503
+ kind: TypeKind.Struct,
504
+ methods: [],
505
+ fields: [
506
+ {
507
+ ...baseField,
508
+ tag: 'json:"a"',
509
+ anonymous: true,
510
+ },
511
+ ],
512
+ },
513
+ },
514
+ ],
515
+ returns: [],
516
+ },
517
+ ],
518
+ },
519
+ zero: () => null,
520
+ },
521
+ })
522
+
523
+ expect(receiverType.Implements(sameInterface)).toBe(true)
524
+ expect(receiverType.Implements(differentTagInterface)).toBe(false)
525
+ expect(receiverType.Implements(differentEmbeddingInterface)).toBe(false)
78
526
  })
79
527
 
80
528
  it('resolves registered type names from descriptors', () => {
@@ -85,25 +533,39 @@ describe('TypeFor', () => {
85
533
  new RegisteredStruct(),
86
534
  [],
87
535
  RegisteredStruct,
88
- {},
536
+ [],
89
537
  )
90
538
  registerStructType(
91
539
  'main.RegisteredWithFields',
92
540
  new RegisteredWithFields(),
93
541
  [],
94
542
  RegisteredWithFields,
95
- {
96
- Name: { kind: TypeKind.Basic, name: 'string' },
97
- Count: {
543
+ [
544
+ {
545
+ name: 'Name',
546
+ key: 'Name',
547
+ type: { kind: TypeKind.Basic, name: 'string' },
548
+ },
549
+ {
550
+ key: 'Count',
98
551
  name: 'Total',
99
552
  type: { kind: TypeKind.Basic, name: 'int' },
100
553
  tag: 'json:"total"',
554
+ pkgPath: 'main',
555
+ anonymous: true,
556
+ index: [3],
557
+ offset: 24,
558
+ exported: false,
101
559
  },
102
- Items: {
103
- kind: TypeKind.Slice,
104
- elemType: 'main.RegisteredStruct',
560
+ {
561
+ name: 'Items',
562
+ key: 'Items',
563
+ type: {
564
+ kind: TypeKind.Slice,
565
+ elemType: 'main.RegisteredStruct',
566
+ },
105
567
  },
106
- },
568
+ ],
107
569
  )
108
570
  registerInterfaceType('main.RegisteredInterface', null, [
109
571
  { name: 'SomeMethod', args: [], returns: [] },
@@ -130,9 +592,77 @@ describe('TypeFor', () => {
130
592
  expect(fieldsType.Field(0).Name).toBe('Name')
131
593
  expect(fieldsType.Field(0).Type.String()).toBe('string')
132
594
  expect(fieldsType.Field(1).Name).toBe('Total')
595
+ expect(fieldsType.Field(1).PkgPath).toBe('main')
596
+ expect(fieldsType.Field(1).IsExported()).toBe(false)
597
+ expect(fieldsType.Field(1).Anonymous).toBe(true)
598
+ expect(fieldsType.Field(1).Index).toEqual([3])
599
+ expect(fieldsType.Field(1).Offset).toBe(24)
133
600
  expect(fieldsType.Field(1).Tag.Get('json')).toBe('total')
134
601
  expect(fieldsType.Field(2).Type.String()).toBe('[]main.RegisteredStruct')
135
- expect(fieldsType.Field(2).Type.Elem().String()).toBe('main.RegisteredStruct')
602
+ expect(fieldsType.Field(2).Type.Elem().String()).toBe(
603
+ 'main.RegisteredStruct',
604
+ )
605
+ })
606
+
607
+ it('allocates registered struct zero values through the named constructor', () => {
608
+ class RegisteredZero {
609
+ public get Name(): string {
610
+ return this._fields.Name.value
611
+ }
612
+ public set Name(value: string) {
613
+ this._fields.Name.value = value
614
+ }
615
+
616
+ public _fields: {
617
+ Name: ReturnType<typeof varRef<string>>
618
+ }
619
+
620
+ constructor(init?: Partial<{ Name?: string }>) {
621
+ this._fields = {
622
+ Name: varRef(init?.Name ?? ''),
623
+ }
624
+ }
625
+
626
+ public clone(): RegisteredZero {
627
+ return markAsStructValue(new RegisteredZero({ Name: this.Name }))
628
+ }
629
+ }
630
+
631
+ const typeInfo = registerStructType(
632
+ 'main.RegisteredZero',
633
+ () => new RegisteredZero(),
634
+ [],
635
+ RegisteredZero,
636
+ [
637
+ {
638
+ name: 'Name',
639
+ key: 'Name',
640
+ type: { kind: TypeKind.Basic, name: 'string' },
641
+ index: [0],
642
+ offset: 0,
643
+ exported: true,
644
+ },
645
+ ],
646
+ )
647
+ ;(RegisteredZero as any).__typeInfo = typeInfo
648
+
649
+ const typ = TypeOf(new RegisteredZero())
650
+ expect(Zero(typ).Interface()).toBeInstanceOf(RegisteredZero)
651
+ expect(TypeOf(Zero(typ).Interface()).String()).toBe('main.RegisteredZero')
652
+
653
+ const ptr = New(typ)
654
+ expect(ptr.Elem().Interface()).toBeInstanceOf(RegisteredZero)
655
+ ptr.Elem().FieldByName('Name').SetString('Ada')
656
+ expect((ptr.Elem().Interface() as RegisteredZero).Name).toBe('Ada')
657
+ })
658
+
659
+ it('unwraps New pointers through Indirect', () => {
660
+ const pointer = New(TypeOf(0))
661
+ const value = Indirect(pointer)
662
+
663
+ expect(value.Int()).toBe(0)
664
+ value.SetInt(7)
665
+ expect(pointer.Elem().Int()).toBe(7)
136
666
  })
137
667
 
138
668
  it('interns runtime type descriptors for reflect.Type map keys', () => {
@@ -11,6 +11,8 @@ export interface UnsafePointer {
11
11
 
12
12
  export type Pointer = UnsafePointer | null
13
13
 
14
+ export type ReflectFunc = (...args: unknown[]) => unknown
15
+
14
16
  // Define the possible JavaScript values that can be reflected
15
17
  export type ReflectValue =
16
18
  | null
@@ -20,7 +22,7 @@ export type ReflectValue =
20
22
  | bigint
21
23
  | string
22
24
  | symbol
23
- | Function //eslint-disable-line @typescript-eslint/no-unsafe-function-type
25
+ | ReflectFunc
24
26
  | object
25
27
  | unknown[]
26
28
  | Map<unknown, unknown>
@@ -37,6 +39,10 @@ export type ReflectValue =
37
39
  // Import Type and Kind from the main type module
38
40
  import { Type, Kind, Value, Kind_String, ChanDir } from './type.js'
39
41
 
42
+ type StructFieldInit = Omit<Partial<StructField>, 'Tag'> & {
43
+ Tag?: StructTag | string
44
+ }
45
+
40
46
  // Struct field representation
41
47
  export class StructField {
42
48
  public Name: string = ''
@@ -47,9 +53,13 @@ export class StructField {
47
53
  public Index: number[] = []
48
54
  public Anonymous: boolean = false
49
55
 
50
- constructor(init?: Partial<StructField>) {
56
+ constructor(init?: StructFieldInit) {
51
57
  if (init) {
52
- Object.assign(this, init)
58
+ const { Tag, ...rest } = init
59
+ Object.assign(this, rest)
60
+ if (Tag !== undefined) {
61
+ this.Tag = typeof Tag === 'string' ? new StructTag(Tag) : Tag
62
+ }
53
63
  }
54
64
  }
55
65
 
@@ -102,12 +112,17 @@ export function StructTag_Get(tag: StructTag | undefined, key: string): string {
102
112
  return tag.Get(key)
103
113
  }
104
114
 
105
- // Method representation
106
- export interface Method {
107
- Name: string
108
- Type: Type
109
- Func: Function //eslint-disable-line @typescript-eslint/no-unsafe-function-type
110
- Index: number
115
+ export class Method {
116
+ public Name = ''
117
+ public Type!: Type
118
+ public Func!: ReflectFunc
119
+ public Index = 0
120
+
121
+ constructor(init?: Partial<Method>) {
122
+ if (init) {
123
+ Object.assign(this, init)
124
+ }
125
+ }
111
126
  }
112
127
 
113
128
  // Channel type for reflection
@@ -139,17 +154,27 @@ export const SelectSend: SelectDir = 1
139
154
  export const SelectRecv: SelectDir = 2
140
155
  export const SelectDefault: SelectDir = 3
141
156
 
142
- // Slice header (internal representation)
143
- export interface SliceHeader {
144
- Data: uintptr
145
- Len: number
146
- Cap: number
157
+ export class SliceHeader {
158
+ public Data: uintptr = 0
159
+ public Len = 0
160
+ public Cap = 0
161
+
162
+ constructor(init?: Partial<SliceHeader>) {
163
+ if (init) {
164
+ Object.assign(this, init)
165
+ }
166
+ }
147
167
  }
148
168
 
149
- // String header (internal representation)
150
- export interface StringHeader {
151
- Data: uintptr
152
- Len: number
169
+ export class StringHeader {
170
+ public Data: uintptr = 0
171
+ public Len = 0
172
+
173
+ constructor(init?: Partial<StringHeader>) {
174
+ if (init) {
175
+ Object.assign(this, init)
176
+ }
177
+ }
153
178
  }
154
179
 
155
180
  // Map iterator with proper typing