goscript 0.1.4 → 0.2.1

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 (295) 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/cmd/goscript-wasm/main.go +38 -6
  8. package/compiler/compile-request.go +12 -9
  9. package/compiler/compliance_test.go +0 -1
  10. package/compiler/config.go +2 -0
  11. package/compiler/diagnostic.go +104 -12
  12. package/compiler/diagnostic_test.go +106 -0
  13. package/compiler/gotest/request.go +28 -0
  14. package/compiler/gotest/runner.go +354 -44
  15. package/compiler/gotest/runner_test.go +293 -1
  16. package/compiler/gotest/testdata/browserapi/browserapi_test.go +20 -0
  17. package/compiler/gotest/testdata/browserapi/go.mod +3 -0
  18. package/compiler/index.test.ts +23 -0
  19. package/compiler/lowered-program.go +33 -24
  20. package/compiler/lowering.go +746 -194
  21. package/compiler/lowering_bench_test.go +42 -27
  22. package/compiler/lowering_internal_test.go +18 -0
  23. package/compiler/override-facts.go +15 -0
  24. package/compiler/override-parity-verifier.go +450 -0
  25. package/compiler/override-parity.go +122 -0
  26. package/compiler/override-registry_test.go +559 -0
  27. package/compiler/protobuf-ts-binding.go +567 -0
  28. package/compiler/protobuf-ts-binding_test.go +402 -0
  29. package/compiler/runtime-contract.go +4 -0
  30. package/compiler/runtime-contract_test.go +2 -0
  31. package/compiler/semantic-model-types.go +9 -4
  32. package/compiler/semantic-model.go +282 -70
  33. package/compiler/semantic-model_test.go +82 -1
  34. package/compiler/service.go +21 -1
  35. package/compiler/skeleton_test.go +118 -10
  36. package/compiler/typescript-emitter.go +128 -13
  37. package/compiler/wasm/compile_test.go +37 -4
  38. package/compiler/{wasm_api.go → wasm-api.go} +57 -7
  39. package/dist/gs/builtin/hostio.js +5 -0
  40. package/dist/gs/builtin/hostio.js.map +1 -1
  41. package/dist/gs/builtin/slice.d.ts +13 -2
  42. package/dist/gs/builtin/slice.js +187 -6
  43. package/dist/gs/builtin/slice.js.map +1 -1
  44. package/dist/gs/builtin/type.d.ts +13 -5
  45. package/dist/gs/builtin/type.js +153 -60
  46. package/dist/gs/builtin/type.js.map +1 -1
  47. package/dist/gs/builtin/varRef.d.ts +11 -0
  48. package/dist/gs/builtin/varRef.js +57 -2
  49. package/dist/gs/builtin/varRef.js.map +1 -1
  50. package/dist/gs/bytes/buffer.gs.js +1 -1
  51. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  52. package/dist/gs/bytes/reader.gs.js +1 -1
  53. package/dist/gs/bytes/reader.gs.js.map +1 -1
  54. package/dist/gs/compress/zlib/index.d.ts +10 -3
  55. package/dist/gs/compress/zlib/index.js +50 -16
  56. package/dist/gs/compress/zlib/index.js.map +1 -1
  57. package/dist/gs/encoding/json/index.d.ts +114 -0
  58. package/dist/gs/encoding/json/index.js +544 -36
  59. package/dist/gs/encoding/json/index.js.map +1 -1
  60. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +101 -0
  61. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +589 -0
  62. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  63. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.d.ts +1 -0
  64. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +17 -11
  65. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -1
  66. package/dist/gs/github.com/pkg/errors/errors.js +54 -30
  67. package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
  68. package/dist/gs/go/scanner/index.d.ts +2 -0
  69. package/dist/gs/go/scanner/index.js +29 -5
  70. package/dist/gs/go/scanner/index.js.map +1 -1
  71. package/dist/gs/go/token/index.js +22 -6
  72. package/dist/gs/go/token/index.js.map +1 -1
  73. package/dist/gs/hash/index.d.ts +6 -0
  74. package/dist/gs/hash/index.js +20 -0
  75. package/dist/gs/hash/index.js.map +1 -1
  76. package/dist/gs/internal/byteorder/index.js +2 -2
  77. package/dist/gs/internal/byteorder/index.js.map +1 -1
  78. package/dist/gs/internal/goarch/index.d.ts +43 -3
  79. package/dist/gs/internal/goarch/index.js +42 -10
  80. package/dist/gs/internal/goarch/index.js.map +1 -1
  81. package/dist/gs/io/fs/fs.js +26 -14
  82. package/dist/gs/io/fs/fs.js.map +1 -1
  83. package/dist/gs/io/fs/readdir.js +4 -2
  84. package/dist/gs/io/fs/readdir.js.map +1 -1
  85. package/dist/gs/io/fs/sub.js +8 -1
  86. package/dist/gs/io/fs/sub.js.map +1 -1
  87. package/dist/gs/io/io.d.ts +2 -0
  88. package/dist/gs/io/io.js.map +1 -1
  89. package/dist/gs/math/bits/index.d.ts +5 -0
  90. package/dist/gs/math/bits/index.js +16 -4
  91. package/dist/gs/math/bits/index.js.map +1 -1
  92. package/dist/gs/mime/index.d.ts +16 -0
  93. package/dist/gs/mime/index.js +315 -6
  94. package/dist/gs/mime/index.js.map +1 -1
  95. package/dist/gs/net/http/httptest/index.d.ts +12 -0
  96. package/dist/gs/net/http/httptest/index.js +85 -6
  97. package/dist/gs/net/http/httptest/index.js.map +1 -1
  98. package/dist/gs/net/http/index.d.ts +300 -5
  99. package/dist/gs/net/http/index.js +1598 -58
  100. package/dist/gs/net/http/index.js.map +1 -1
  101. package/dist/gs/os/dir_unix.gs.js +1 -1
  102. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  103. package/dist/gs/os/error.gs.js +1 -1
  104. package/dist/gs/os/error.gs.js.map +1 -1
  105. package/dist/gs/os/exec.gs.d.ts +1 -0
  106. package/dist/gs/os/exec.gs.js +4 -8
  107. package/dist/gs/os/exec.gs.js.map +1 -1
  108. package/dist/gs/os/exec_posix.gs.js +1 -1
  109. package/dist/gs/os/exec_posix.gs.js.map +1 -1
  110. package/dist/gs/os/index.d.ts +1 -1
  111. package/dist/gs/os/index.js +1 -1
  112. package/dist/gs/os/index.js.map +1 -1
  113. package/dist/gs/os/proc.gs.d.ts +4 -0
  114. package/dist/gs/os/proc.gs.js +12 -6
  115. package/dist/gs/os/proc.gs.js.map +1 -1
  116. package/dist/gs/os/root_js.gs.js +1 -1
  117. package/dist/gs/os/root_js.gs.js.map +1 -1
  118. package/dist/gs/os/types.gs.js +1 -1
  119. package/dist/gs/os/types.gs.js.map +1 -1
  120. package/dist/gs/os/types_js.gs.js +1 -1
  121. package/dist/gs/os/types_js.gs.js.map +1 -1
  122. package/dist/gs/os/types_unix.gs.js +1 -1
  123. package/dist/gs/os/types_unix.gs.js.map +1 -1
  124. package/dist/gs/path/path.js +11 -7
  125. package/dist/gs/path/path.js.map +1 -1
  126. package/dist/gs/reflect/index.d.ts +5 -4
  127. package/dist/gs/reflect/index.js +4 -3
  128. package/dist/gs/reflect/index.js.map +1 -1
  129. package/dist/gs/reflect/map.js +15 -0
  130. package/dist/gs/reflect/map.js.map +1 -1
  131. package/dist/gs/reflect/type.d.ts +25 -6
  132. package/dist/gs/reflect/type.js +1475 -228
  133. package/dist/gs/reflect/type.js.map +1 -1
  134. package/dist/gs/reflect/types.d.ts +14 -6
  135. package/dist/gs/reflect/types.js +35 -1
  136. package/dist/gs/reflect/types.js.map +1 -1
  137. package/dist/gs/reflect/value.d.ts +1 -0
  138. package/dist/gs/reflect/value.js +83 -41
  139. package/dist/gs/reflect/value.js.map +1 -1
  140. package/dist/gs/reflect/visiblefields.js +4 -140
  141. package/dist/gs/reflect/visiblefields.js.map +1 -1
  142. package/dist/gs/runtime/pprof/index.d.ts +8 -2
  143. package/dist/gs/runtime/pprof/index.js +50 -30
  144. package/dist/gs/runtime/pprof/index.js.map +1 -1
  145. package/dist/gs/runtime/runtime.js +5 -4
  146. package/dist/gs/runtime/runtime.js.map +1 -1
  147. package/dist/gs/runtime/trace/index.js +5 -19
  148. package/dist/gs/runtime/trace/index.js.map +1 -1
  149. package/dist/gs/strconv/atoi.gs.js +1 -1
  150. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  151. package/dist/gs/strconv/complex.gs.d.ts +3 -0
  152. package/dist/gs/strconv/complex.gs.js +148 -0
  153. package/dist/gs/strconv/complex.gs.js.map +1 -0
  154. package/dist/gs/strconv/index.d.ts +1 -0
  155. package/dist/gs/strconv/index.js +1 -0
  156. package/dist/gs/strconv/index.js.map +1 -1
  157. package/dist/gs/strings/builder.js +1 -1
  158. package/dist/gs/strings/reader.js +9 -5
  159. package/dist/gs/strings/reader.js.map +1 -1
  160. package/dist/gs/strings/replace.js +15 -7
  161. package/dist/gs/strings/replace.js.map +1 -1
  162. package/dist/gs/strings/strings.d.ts +5 -0
  163. package/dist/gs/strings/strings.js +57 -5
  164. package/dist/gs/strings/strings.js.map +1 -1
  165. package/dist/gs/sync/atomic/doc_64.gs.js +7 -6
  166. package/dist/gs/sync/atomic/doc_64.gs.js.map +1 -1
  167. package/dist/gs/sync/atomic/type.gs.js +9 -9
  168. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  169. package/dist/gs/sync/atomic/value.gs.js +2 -2
  170. package/dist/gs/sync/atomic/value.gs.js.map +1 -1
  171. package/dist/gs/syscall/env.js +22 -14
  172. package/dist/gs/syscall/env.js.map +1 -1
  173. package/dist/gs/testing/testing.js +55 -13
  174. package/dist/gs/testing/testing.js.map +1 -1
  175. package/dist/gs/time/time.d.ts +24 -1
  176. package/dist/gs/time/time.js +43 -3
  177. package/dist/gs/time/time.js.map +1 -1
  178. package/dist/gs/unique/index.js +7 -1
  179. package/dist/gs/unique/index.js.map +1 -1
  180. package/go.mod +3 -3
  181. package/go.sum +16 -0
  182. package/gs/builtin/hostio.test.ts +16 -0
  183. package/gs/builtin/hostio.ts +7 -0
  184. package/gs/builtin/runtime-contract.test.ts +246 -21
  185. package/gs/builtin/slice.ts +269 -24
  186. package/gs/builtin/type.ts +226 -59
  187. package/gs/builtin/varRef.ts +85 -2
  188. package/gs/bytes/buffer.gs.ts +1 -1
  189. package/gs/bytes/reader.gs.ts +1 -1
  190. package/gs/compress/zlib/index.test.ts +62 -1
  191. package/gs/compress/zlib/index.ts +53 -16
  192. package/gs/compress/zlib/parity.json +51 -0
  193. package/gs/encoding/json/index.test.ts +360 -6
  194. package/gs/encoding/json/index.ts +679 -38
  195. package/gs/encoding/json/parity.json +81 -0
  196. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +373 -3
  197. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +893 -1
  198. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +18 -0
  199. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +17 -11
  200. package/gs/github.com/pkg/errors/errors.ts +54 -30
  201. package/gs/go/scanner/index.test.ts +39 -56
  202. package/gs/go/scanner/index.ts +33 -5
  203. package/gs/go/scanner/parity.json +27 -0
  204. package/gs/go/token/index.ts +22 -6
  205. package/gs/hash/index.test.ts +20 -33
  206. package/gs/hash/index.ts +28 -0
  207. package/gs/hash/parity.json +21 -0
  208. package/gs/internal/byteorder/index.test.ts +2 -2
  209. package/gs/internal/byteorder/index.ts +2 -2
  210. package/gs/internal/goarch/index.test.ts +32 -0
  211. package/gs/internal/goarch/index.ts +45 -13
  212. package/gs/internal/goarch/parity.json +144 -0
  213. package/gs/io/fs/fs.ts +26 -14
  214. package/gs/io/fs/readdir.ts +4 -4
  215. package/gs/io/fs/sub.ts +8 -1
  216. package/gs/io/io.ts +1 -0
  217. package/gs/io/parity.json +162 -0
  218. package/gs/math/bits/index.test.ts +14 -1
  219. package/gs/math/bits/index.ts +23 -4
  220. package/gs/math/bits/parity.json +156 -0
  221. package/gs/mime/index.test.ts +90 -0
  222. package/gs/mime/index.ts +369 -6
  223. package/gs/mime/parity.json +36 -0
  224. package/gs/net/http/httptest/index.test.ts +98 -2
  225. package/gs/net/http/httptest/index.ts +101 -6
  226. package/gs/net/http/httptest/parity.json +15 -0
  227. package/gs/net/http/index.test.ts +781 -12
  228. package/gs/net/http/index.ts +1860 -139
  229. package/gs/net/http/meta.json +16 -1
  230. package/gs/net/http/parity.json +193 -0
  231. package/gs/os/dir_unix.gs.ts +1 -1
  232. package/gs/os/error.gs.ts +1 -1
  233. package/gs/os/exec.gs.ts +4 -8
  234. package/gs/os/exec_posix.gs.ts +1 -1
  235. package/gs/os/index.test.ts +9 -0
  236. package/gs/os/index.ts +1 -0
  237. package/gs/os/parity.json +9 -0
  238. package/gs/os/proc.gs.ts +18 -5
  239. package/gs/os/proc.test.ts +26 -0
  240. package/gs/os/root_js.gs.ts +1 -1
  241. package/gs/os/types.gs.ts +1 -1
  242. package/gs/os/types_js.gs.ts +1 -1
  243. package/gs/os/types_unix.gs.ts +1 -1
  244. package/gs/path/path.ts +11 -7
  245. package/gs/reflect/field.test.ts +37 -15
  246. package/gs/reflect/function-types.test.ts +518 -22
  247. package/gs/reflect/index.ts +8 -6
  248. package/gs/reflect/map.ts +20 -0
  249. package/gs/reflect/meta.json +6 -4
  250. package/gs/reflect/parity.json +234 -0
  251. package/gs/reflect/sliceat.test.ts +156 -0
  252. package/gs/reflect/structof.test.ts +401 -0
  253. package/gs/reflect/type.ts +1961 -317
  254. package/gs/reflect/typefor.test.ts +530 -10
  255. package/gs/reflect/types.ts +43 -18
  256. package/gs/reflect/value.ts +105 -45
  257. package/gs/reflect/visiblefields.ts +5 -168
  258. package/gs/runtime/parity.json +24 -0
  259. package/gs/runtime/pprof/index.test.ts +29 -7
  260. package/gs/runtime/pprof/index.ts +56 -30
  261. package/gs/runtime/pprof/parity.json +27 -0
  262. package/gs/runtime/runtime.test.ts +3 -1
  263. package/gs/runtime/runtime.ts +4 -3
  264. package/gs/runtime/trace/index.test.ts +5 -3
  265. package/gs/runtime/trace/index.ts +8 -20
  266. package/gs/runtime/trace/parity.json +36 -0
  267. package/gs/strconv/atoi.gs.ts +1 -1
  268. package/gs/strconv/complex.gs.ts +174 -0
  269. package/gs/strconv/complex.test.ts +65 -0
  270. package/gs/strconv/index.ts +1 -0
  271. package/gs/strconv/parity.json +120 -0
  272. package/gs/strings/builder.ts +1 -1
  273. package/gs/strings/parity.json +186 -0
  274. package/gs/strings/reader.ts +9 -5
  275. package/gs/strings/replace.ts +15 -7
  276. package/gs/strings/strings.test.ts +22 -2
  277. package/gs/strings/strings.ts +64 -6
  278. package/gs/sync/atomic/doc_64.gs.ts +6 -7
  279. package/gs/sync/atomic/doc_64.test.ts +43 -0
  280. package/gs/sync/atomic/type.gs.ts +9 -9
  281. package/gs/sync/atomic/value.gs.ts +2 -2
  282. package/gs/syscall/env.ts +29 -14
  283. package/gs/testing/testing.test.ts +67 -0
  284. package/gs/testing/testing.ts +87 -19
  285. package/gs/time/parity.json +225 -0
  286. package/gs/time/time.test.ts +20 -2
  287. package/gs/time/time.ts +49 -7
  288. package/gs/unique/index.ts +7 -1
  289. package/package.json +4 -2
  290. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +0 -217
  291. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +0 -926
  292. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +0 -1
  293. package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +0 -38
  294. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +0 -1361
  295. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +0 -46
@@ -1,7 +1,7 @@
1
1
  import { StructField, StructTag, ValueError, } from './types.js';
2
2
  export { StructField };
3
3
  import { MapIter } from './map.js';
4
- import { getTypeByName as builtinGetTypeByName, TypeKind, isStructTypeInfo, isInterfaceTypeInfo, isStructFieldInfo, } from '../builtin/type.js';
4
+ import { getTypeByName as builtinGetTypeByName, isStructTypeInfo, isInterfaceTypeInfo, structFieldRuntimeKey, } from '../builtin/type.js';
5
5
  import { Zero } from './value.js';
6
6
  import { DeepEqual } from './deepequal.js';
7
7
  import * as $ from '../builtin/index.js';
@@ -153,8 +153,10 @@ export const Struct = 25;
153
153
  export const UnsafePointer = 26;
154
154
  const pointerAddressStride = 0x100000000;
155
155
  const pointerAddresses = new WeakMap();
156
+ const fieldPointerAddresses = new WeakMap();
156
157
  let nextPointerAddress = 1;
157
158
  const canonicalTypes = new globalThis.Map();
159
+ const constructingRegisteredTypes = new globalThis.Map();
158
160
  function pointerAddress(value) {
159
161
  let address = pointerAddresses.get(value);
160
162
  if (address === undefined) {
@@ -164,15 +166,121 @@ function pointerAddress(value) {
164
166
  }
165
167
  return address;
166
168
  }
169
+ function fieldPointerAddress(target, key) {
170
+ let addresses = fieldPointerAddresses.get(target);
171
+ if (addresses === undefined) {
172
+ addresses = new globalThis.Map();
173
+ fieldPointerAddresses.set(target, addresses);
174
+ }
175
+ let address = addresses.get(key);
176
+ if (address === undefined) {
177
+ address = nextPointerAddress * pointerAddressStride;
178
+ nextPointerAddress++;
179
+ addresses.set(key, address);
180
+ }
181
+ return address;
182
+ }
167
183
  function internType(t) {
168
- const key = `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}`;
184
+ const key = typeIdentityKey(t);
169
185
  const existing = canonicalTypes.get(key);
170
186
  if (existing) {
187
+ mergeTypeMetadata(existing, t);
171
188
  return existing;
172
189
  }
173
190
  canonicalTypes.set(key, t);
174
191
  return t;
175
192
  }
193
+ function mergeTypeMetadata(target, source) {
194
+ if (target instanceof BasicType && source instanceof BasicType) {
195
+ target.mergeMethodSignatures(source.methodSignatures());
196
+ return;
197
+ }
198
+ if (target instanceof PointerType && source instanceof PointerType) {
199
+ target.mergeMethodSignatures(source.methodSignatures());
200
+ return;
201
+ }
202
+ if (target instanceof FunctionType && source instanceof FunctionType) {
203
+ target.mergeSignature(source);
204
+ target.mergeMethodSignatures(source.methodSignatures());
205
+ }
206
+ }
207
+ function typeIdentityKey(t, seen = new Set()) {
208
+ if (seen.has(t)) {
209
+ return `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}`;
210
+ }
211
+ seen.add(t);
212
+ if (t instanceof StructType) {
213
+ return t.identityKey(seen);
214
+ }
215
+ switch (t.Kind()) {
216
+ case Array:
217
+ return `${t.Kind()}:${t.Len()}:${typeIdentityKey(t.Elem(), seen)}`;
218
+ case Chan:
219
+ case Ptr:
220
+ case Slice:
221
+ return `${t.Kind()}:${t.String()}:${typeIdentityKey(t.Elem(), seen)}`;
222
+ case Map:
223
+ return `${t.Kind()}:${typeIdentityKey(t.Key(), seen)}:${typeIdentityKey(t.Elem(), seen)}`;
224
+ case Func: {
225
+ if (t.Name() !== '') {
226
+ return `${t.Kind()}:named:${t.PkgPath()}:${t.Name()}`;
227
+ }
228
+ const params = globalThis.Array.from({ length: t.NumIn() }, (_unused, idx) => typeIdentityKey(t.In(idx), seen));
229
+ const results = globalThis.Array.from({ length: t.NumOut() }, (_unused, idx) => typeIdentityKey(t.Out(idx), seen));
230
+ return `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}:${t.IsVariadic()}:${params.join(',')}:${results.join(',')}`;
231
+ }
232
+ default:
233
+ return `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}`;
234
+ }
235
+ }
236
+ function typeUnderlyingIdentityKey(t, seen = new Set()) {
237
+ if (seen.has(t)) {
238
+ return `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}`;
239
+ }
240
+ seen.add(t);
241
+ if (t instanceof BasicType) {
242
+ return `basic:${t.underlyingName()}`;
243
+ }
244
+ if (t instanceof StructType) {
245
+ return t.underlyingIdentityKey(seen);
246
+ }
247
+ switch (t.Kind()) {
248
+ case Array:
249
+ return `array:${t.Len()}:${typeIdentityKey(t.Elem(), seen)}`;
250
+ case Chan:
251
+ return `chan:${t.String()}:${typeIdentityKey(t.Elem(), seen)}`;
252
+ case Ptr:
253
+ return `ptr:${typeIdentityKey(t.Elem(), seen)}`;
254
+ case Slice:
255
+ return `slice:${typeIdentityKey(t.Elem(), seen)}`;
256
+ case Map:
257
+ return `map:${typeIdentityKey(t.Key(), seen)}:${typeIdentityKey(t.Elem(), seen)}`;
258
+ case Func: {
259
+ const params = globalThis.Array.from({ length: t.NumIn() }, (_unused, idx) => typeIdentityKey(t.In(idx), seen));
260
+ const results = globalThis.Array.from({ length: t.NumOut() }, (_unused, idx) => typeIdentityKey(t.Out(idx), seen));
261
+ return `func:${t.IsVariadic()}:${params.join(',')}:${results.join(',')}`;
262
+ }
263
+ case Interface:
264
+ return `interface:${typeMethods(t).map(methodSignatureIdentityKey).join('|')}`;
265
+ default:
266
+ return `${t.Kind()}:${t.PkgPath()}:${t.Name()}:${t.String()}`;
267
+ }
268
+ }
269
+ function typeIsNamed(t) {
270
+ if (t.Kind() === Interface) {
271
+ return t.String() !== 'interface{}' && !t.String().startsWith('interface {');
272
+ }
273
+ if (t.Kind() === Struct || t.Kind() === Func) {
274
+ return t.Name() !== '';
275
+ }
276
+ if (t instanceof BasicType) {
277
+ return t.Kind() !== Invalid && t.Name() !== '';
278
+ }
279
+ return t.Name() !== '';
280
+ }
281
+ function nonFunctionTypePanic(method, t) {
282
+ throw new Error(`reflect: ${method} of non-func type ${t.String()}`);
283
+ }
176
284
  // InvalidTypeInstance is a singleton type for invalid/zero reflect.Value
177
285
  class InvalidTypeClass {
178
286
  Kind() {
@@ -202,6 +310,21 @@ class InvalidTypeClass {
202
310
  NumField() {
203
311
  return 0;
204
312
  }
313
+ NumIn() {
314
+ return nonFunctionTypePanic('NumIn', this);
315
+ }
316
+ In(_i) {
317
+ return nonFunctionTypePanic('In', this);
318
+ }
319
+ NumOut() {
320
+ return nonFunctionTypePanic('NumOut', this);
321
+ }
322
+ Out(_i) {
323
+ return nonFunctionTypePanic('Out', this);
324
+ }
325
+ IsVariadic() {
326
+ return nonFunctionTypePanic('IsVariadic', this);
327
+ }
205
328
  Field(_i) {
206
329
  throw new Error('reflect: Field of invalid type');
207
330
  }
@@ -335,6 +458,9 @@ export class Value {
335
458
  return this._type.String();
336
459
  }
337
460
  Len() {
461
+ if (this.Kind() === Slice || this.Kind() === Array) {
462
+ return $.len(this._value);
463
+ }
338
464
  // Check for slice objects created by $.arrayToSlice
339
465
  if (this._value &&
340
466
  typeof this._value === 'object' &&
@@ -383,8 +509,9 @@ export class Value {
383
509
  return this._value === null || this._value === undefined;
384
510
  }
385
511
  Index(i) {
386
- if (globalThis.Array.isArray(this._value)) {
387
- return new Value(this._value[i], getTypeOf(this._value[i]));
512
+ if (this.Kind() === Slice || this.Kind() === Array) {
513
+ const ref = $.indexRef(this._value, i);
514
+ return new Value(ref.value, this._type.Elem(), ref);
388
515
  }
389
516
  throw new Error('reflect: call of reflect.Value.Index on ' +
390
517
  Kind_String(this._type.Kind()) +
@@ -446,16 +573,17 @@ export class Value {
446
573
  throw new ValueError({ Kind: this.Kind(), Method: 'Field' });
447
574
  }
448
575
  const field = this.Type().Field(i);
576
+ const fieldKey = structFieldStorageKey(this.Type(), i);
449
577
  if (!field) {
450
578
  throw new Error('reflect: struct field index out of range');
451
579
  }
452
580
  const parentObj = this._value;
453
- let fieldVal = parentObj[field.Name];
581
+ let fieldVal = parentObj[fieldKey];
454
582
  if (fieldVal === undefined) {
455
583
  fieldVal = null;
456
584
  }
457
585
  // Pass parent struct and field name so Set() can update the struct
458
- return new Value(fieldVal, field.Type, undefined, parentObj, field.Name);
586
+ return new Value(fieldVal, field.Type, undefined, parentObj, fieldKey);
459
587
  }
460
588
  FieldByIndex(index) {
461
589
  let current = this;
@@ -488,6 +616,9 @@ export class Value {
488
616
  if (this._value === null || this._value === undefined) {
489
617
  return 0;
490
618
  }
619
+ if ($.isOwnedPointerHandle(this._value)) {
620
+ return $.ownedPointerAddress(this._value);
621
+ }
491
622
  if ($.isVarRef(this._value)) {
492
623
  const address = this._value.__goAddress?.();
493
624
  if (address !== undefined) {
@@ -517,7 +648,18 @@ export class Value {
517
648
  throw new ValueError({ Kind: this.Kind(), Method: 'UnsafeAddr' });
518
649
  }
519
650
  if (this._parentStruct && this._fieldName) {
520
- return { value: this };
651
+ const target = this._parentStruct;
652
+ const key = this._fieldName;
653
+ const ref = $.fieldRef(target, key);
654
+ return {
655
+ __goOwnedPointer: true,
656
+ __goAddress: () => fieldPointerAddress(target, key),
657
+ __goRef: () => ref,
658
+ };
659
+ }
660
+ if (this._parentVarRef?.__goPointer) {
661
+ return this._parentVarRef
662
+ .__goPointer;
521
663
  }
522
664
  return this.Pointer();
523
665
  }
@@ -547,6 +689,9 @@ export class Value {
547
689
  if (this._parentStruct && this._fieldName) {
548
690
  return new Value($.fieldRef(this._parentStruct, this._fieldName), ptrType);
549
691
  }
692
+ if (this._parentVarRef) {
693
+ return new Value(this._parentVarRef, ptrType);
694
+ }
550
695
  return new Value($.varRef(this._value), ptrType);
551
696
  }
552
697
  CanSet() {
@@ -558,23 +703,9 @@ export class Value {
558
703
  if (!this.CanSet()) {
559
704
  throw new Error('reflect: assign to invalid value');
560
705
  }
561
- // Interface types can accept any value
562
- if (this.Kind() === Interface) {
563
- this._value = x.value;
564
- // Also update the parent VarRef if we were dereferenced from one
565
- if (this._parentVarRef) {
566
- this._parentVarRef.value = x.value;
567
- }
568
- // Also update the parent struct field if this is a struct field
569
- if (this._parentStruct && this._fieldName) {
570
- this._parentStruct[this._fieldName] = x.value;
571
- }
572
- return;
573
- }
574
- // For other types, check if types are compatible (simplified check)
575
706
  const thisType = this.Type();
576
707
  const xType = x.Type();
577
- if (thisType.Kind() !== xType.Kind()) {
708
+ if (!xType.AssignableTo(thisType)) {
578
709
  throw new Error('reflect: assign to wrong type');
579
710
  }
580
711
  this._value = x.value;
@@ -605,21 +736,23 @@ export class Value {
605
736
  if (typeof method !== 'function') {
606
737
  return new Value();
607
738
  }
608
- return new Value(method.bind(receiver), new FunctionType('func'));
739
+ const [signature] = methodSignatureByName(this.Type(), name);
740
+ const methodType = signature ?
741
+ methodTypeFromSignature(signature, this.Type(), false)
742
+ : new FunctionType('func');
743
+ return new Value(method.bind(receiver), methodType);
609
744
  }
610
- Call(inArgs) {
745
+ async Call(inArgs) {
611
746
  if (this.Kind() !== Func || typeof this._value !== 'function') {
612
747
  throw new ValueError({ Kind: this.Kind(), Method: 'Call' });
613
748
  }
614
- const args = $.asArray(inArgs).map((arg) => arg.Interface());
615
- const result = this._value(...args);
616
- if (globalThis.Array.isArray(result)) {
617
- return $.arrayToSlice(result.map((value) => ValueOf(value)));
618
- }
619
- if (result === undefined) {
620
- return $.makeSlice(0);
749
+ return await callReflectFunction(this._value, this._type, inArgs, 'Call');
750
+ }
751
+ async CallSlice(inArgs) {
752
+ if (this.Kind() !== Func || typeof this._value !== 'function') {
753
+ throw new ValueError({ Kind: this.Kind(), Method: 'CallSlice' });
621
754
  }
622
- return $.arrayToSlice([ValueOf(result)]);
755
+ return await callReflectFunction(this._value, this._type, inArgs, 'CallSlice');
623
756
  }
624
757
  IsZero() {
625
758
  const zeroVal = Zero(this.Type()).value;
@@ -886,10 +1019,7 @@ export class Value {
886
1019
  Cap() {
887
1020
  const k = this.Kind();
888
1021
  if (k === Slice || k === Array) {
889
- if (globalThis.Array.isArray(this._value)) {
890
- return this._value.length;
891
- }
892
- return 0;
1022
+ return $.cap(this._value);
893
1023
  }
894
1024
  if (k === Chan) {
895
1025
  return 0; // Simplified
@@ -962,11 +1092,13 @@ export class BasicType {
962
1092
  _name;
963
1093
  _size;
964
1094
  _typeName;
965
- constructor(_kind, _name, _size = 8, _typeName = '') {
1095
+ _methods;
1096
+ constructor(_kind, _name, _size = 8, _typeName = '', _methods = []) {
966
1097
  this._kind = _kind;
967
1098
  this._name = _name;
968
1099
  this._size = _size;
969
1100
  this._typeName = _typeName;
1101
+ this._methods = _methods;
970
1102
  }
971
1103
  String() {
972
1104
  return this._typeName || this._name;
@@ -974,6 +1106,9 @@ export class BasicType {
974
1106
  Kind() {
975
1107
  return this._kind;
976
1108
  }
1109
+ underlyingName() {
1110
+ return Kind_String(this._kind);
1111
+ }
977
1112
  Comparable() {
978
1113
  return this._kind !== Func && this._kind !== Map && this._kind !== Slice;
979
1114
  }
@@ -986,6 +1121,21 @@ export class BasicType {
986
1121
  NumField() {
987
1122
  return 0;
988
1123
  }
1124
+ NumIn() {
1125
+ return nonFunctionTypePanic('NumIn', this);
1126
+ }
1127
+ In(_i) {
1128
+ return nonFunctionTypePanic('In', this);
1129
+ }
1130
+ NumOut() {
1131
+ return nonFunctionTypePanic('NumOut', this);
1132
+ }
1133
+ Out(_i) {
1134
+ return nonFunctionTypePanic('Out', this);
1135
+ }
1136
+ IsVariadic() {
1137
+ return nonFunctionTypePanic('IsVariadic', this);
1138
+ }
989
1139
  PkgPath() {
990
1140
  if (this._typeName) {
991
1141
  const dotIndex = this._typeName.lastIndexOf('.');
@@ -1025,7 +1175,7 @@ export class BasicType {
1025
1175
  if (u.Kind() !== Interface) {
1026
1176
  throw new Error('reflect: non-interface type passed to Type.Implements');
1027
1177
  }
1028
- return false;
1178
+ return typeImplementsInterface(this, u);
1029
1179
  }
1030
1180
  AssignableTo(u) {
1031
1181
  return typeAssignableTo(this, u);
@@ -1084,10 +1234,16 @@ export class BasicType {
1084
1234
  ' Type');
1085
1235
  }
1086
1236
  NumMethod() {
1087
- return 0;
1237
+ return typeMethods(this).length;
1088
1238
  }
1089
- MethodByName(_name) {
1090
- return [zeroMethod(), false];
1239
+ MethodByName(name) {
1240
+ return typeMethodByName(this, name);
1241
+ }
1242
+ methodSignatures() {
1243
+ return this._methods;
1244
+ }
1245
+ mergeMethodSignatures(methods) {
1246
+ this._methods = mergeMethodSignatureList(this._methods, methods);
1091
1247
  }
1092
1248
  Len() {
1093
1249
  throw new Error('reflect: call of reflect.Type.Len on ' +
@@ -1150,6 +1306,21 @@ class SliceType {
1150
1306
  NumField() {
1151
1307
  return 0;
1152
1308
  }
1309
+ NumIn() {
1310
+ return nonFunctionTypePanic('NumIn', this);
1311
+ }
1312
+ In(_i) {
1313
+ return nonFunctionTypePanic('In', this);
1314
+ }
1315
+ NumOut() {
1316
+ return nonFunctionTypePanic('NumOut', this);
1317
+ }
1318
+ Out(_i) {
1319
+ return nonFunctionTypePanic('Out', this);
1320
+ }
1321
+ IsVariadic() {
1322
+ return nonFunctionTypePanic('IsVariadic', this);
1323
+ }
1153
1324
  PkgPath() {
1154
1325
  return '';
1155
1326
  }
@@ -1176,7 +1347,7 @@ class SliceType {
1176
1347
  if (u.Kind() !== Interface) {
1177
1348
  throw new Error('reflect: non-interface type passed to Type.Implements');
1178
1349
  }
1179
- return false;
1350
+ return typeImplementsInterface(this, u);
1180
1351
  }
1181
1352
  AssignableTo(u) {
1182
1353
  return typeAssignableTo(this, u);
@@ -1229,6 +1400,21 @@ class ArrayType {
1229
1400
  NumField() {
1230
1401
  return 0;
1231
1402
  }
1403
+ NumIn() {
1404
+ return nonFunctionTypePanic('NumIn', this);
1405
+ }
1406
+ In(_i) {
1407
+ return nonFunctionTypePanic('In', this);
1408
+ }
1409
+ NumOut() {
1410
+ return nonFunctionTypePanic('NumOut', this);
1411
+ }
1412
+ Out(_i) {
1413
+ return nonFunctionTypePanic('Out', this);
1414
+ }
1415
+ IsVariadic() {
1416
+ return nonFunctionTypePanic('IsVariadic', this);
1417
+ }
1232
1418
  Len() {
1233
1419
  return this._len;
1234
1420
  }
@@ -1258,7 +1444,7 @@ class ArrayType {
1258
1444
  if (u.Kind() !== Interface) {
1259
1445
  throw new Error('reflect: non-interface type passed to Type.Implements');
1260
1446
  }
1261
- return false;
1447
+ return typeImplementsInterface(this, u);
1262
1448
  }
1263
1449
  AssignableTo(u) {
1264
1450
  return typeAssignableTo(this, u);
@@ -1288,8 +1474,10 @@ class ArrayType {
1288
1474
  // Pointer type implementation
1289
1475
  class PointerType {
1290
1476
  _elemType;
1291
- constructor(_elemType) {
1477
+ _methods;
1478
+ constructor(_elemType, _methods = []) {
1292
1479
  this._elemType = _elemType;
1480
+ this._methods = _methods;
1293
1481
  }
1294
1482
  String() {
1295
1483
  return '*' + this._elemType.String();
@@ -1309,6 +1497,21 @@ class PointerType {
1309
1497
  NumField() {
1310
1498
  return 0;
1311
1499
  }
1500
+ NumIn() {
1501
+ return nonFunctionTypePanic('NumIn', this);
1502
+ }
1503
+ In(_i) {
1504
+ return nonFunctionTypePanic('In', this);
1505
+ }
1506
+ NumOut() {
1507
+ return nonFunctionTypePanic('NumOut', this);
1508
+ }
1509
+ Out(_i) {
1510
+ return nonFunctionTypePanic('Out', this);
1511
+ }
1512
+ IsVariadic() {
1513
+ return nonFunctionTypePanic('IsVariadic', this);
1514
+ }
1312
1515
  PkgPath() {
1313
1516
  return '';
1314
1517
  }
@@ -1335,9 +1538,7 @@ class PointerType {
1335
1538
  if (u.Kind() !== Interface) {
1336
1539
  throw new Error('reflect: non-interface type passed to Type.Implements');
1337
1540
  }
1338
- // For pointer types, check if the element type implements the interface
1339
- const elemTypeName = this._elemType.String();
1340
- return typeImplementsInterface(elemTypeName, u);
1541
+ return typeImplementsInterface(this, u);
1341
1542
  }
1342
1543
  AssignableTo(u) {
1343
1544
  return typeAssignableTo(this, u);
@@ -1355,10 +1556,16 @@ class PointerType {
1355
1556
  throw new Error('reflect: call of reflect.Type.OverflowFloat on pointer Type');
1356
1557
  }
1357
1558
  NumMethod() {
1358
- return 0;
1559
+ return typeMethods(this).length;
1359
1560
  }
1360
1561
  MethodByName(name) {
1361
- return typeMethodByName(this._elemType, name);
1562
+ return typeMethodByName(this, name);
1563
+ }
1564
+ methodSignatures() {
1565
+ return this._methods;
1566
+ }
1567
+ mergeMethodSignatures(methods) {
1568
+ this._methods = mergeMethodSignatureList(this._methods, methods);
1362
1569
  }
1363
1570
  Len() {
1364
1571
  throw new Error('reflect: call of reflect.Type.Len on pointer Type');
@@ -1367,13 +1574,42 @@ class PointerType {
1367
1574
  throw new Error('reflect: call of reflect.Type.Bits on pointer Type');
1368
1575
  }
1369
1576
  }
1370
- // Function type implementation
1371
1577
  class FunctionType {
1578
+ _name;
1372
1579
  _signature;
1373
- constructor(_signature) {
1374
- this._signature = _signature;
1580
+ _params;
1581
+ _results;
1582
+ _variadic;
1583
+ _hasSignature;
1584
+ _methods;
1585
+ constructor(signatureOrDescriptor) {
1586
+ if (typeof signatureOrDescriptor === 'string') {
1587
+ this._name = '';
1588
+ this._signature = signatureOrDescriptor;
1589
+ this._params = [];
1590
+ this._results = [];
1591
+ this._variadic = false;
1592
+ this._hasSignature = false;
1593
+ this._methods = [];
1594
+ return;
1595
+ }
1596
+ this._name = signatureOrDescriptor.name ?? '';
1597
+ this._params = signatureOrDescriptor.params ?? [];
1598
+ this._results = signatureOrDescriptor.results ?? [];
1599
+ this._variadic = signatureOrDescriptor.variadic ?? false;
1600
+ this._hasSignature =
1601
+ signatureOrDescriptor.signature !== undefined ||
1602
+ signatureOrDescriptor.params !== undefined ||
1603
+ signatureOrDescriptor.results !== undefined;
1604
+ this._methods = signatureOrDescriptor.methods ?? [];
1605
+ this._signature =
1606
+ signatureOrDescriptor.signature ??
1607
+ formatFunctionSignature(this._params, this._results, this._variadic);
1375
1608
  }
1376
1609
  String() {
1610
+ if (this._name !== '') {
1611
+ return this._name;
1612
+ }
1377
1613
  return this._signature;
1378
1614
  }
1379
1615
  Kind() {
@@ -1391,11 +1627,44 @@ class FunctionType {
1391
1627
  NumField() {
1392
1628
  return 0;
1393
1629
  }
1630
+ NumIn() {
1631
+ return this._params.length;
1632
+ }
1633
+ In(i) {
1634
+ if (i < 0 || i >= this._params.length) {
1635
+ throw new Error(`reflect: In index out of range [${i}] with length ${this._params.length}`);
1636
+ }
1637
+ return this._params[i];
1638
+ }
1639
+ NumOut() {
1640
+ return this._results.length;
1641
+ }
1642
+ Out(i) {
1643
+ if (i < 0 || i >= this._results.length) {
1644
+ throw new Error(`reflect: Out index out of range [${i}] with length ${this._results.length}`);
1645
+ }
1646
+ return this._results[i];
1647
+ }
1648
+ IsVariadic() {
1649
+ return this._variadic;
1650
+ }
1394
1651
  PkgPath() {
1652
+ if (this._name !== '') {
1653
+ const dotIndex = this._name.lastIndexOf('.');
1654
+ if (dotIndex > 0) {
1655
+ return this._name.substring(0, dotIndex);
1656
+ }
1657
+ }
1395
1658
  return '';
1396
1659
  }
1397
1660
  Name() {
1398
- // Function types are unnamed composite types
1661
+ if (this._name !== '') {
1662
+ const dotIndex = this._name.lastIndexOf('.');
1663
+ if (dotIndex >= 0) {
1664
+ return this._name.substring(dotIndex + 1);
1665
+ }
1666
+ return this._name;
1667
+ }
1399
1668
  return '';
1400
1669
  }
1401
1670
  Field(_i) {
@@ -1417,7 +1686,7 @@ class FunctionType {
1417
1686
  if (u.Kind() !== Interface) {
1418
1687
  throw new Error('reflect: non-interface type passed to Type.Implements');
1419
1688
  }
1420
- return false;
1689
+ return typeImplementsInterface(this, u);
1421
1690
  }
1422
1691
  AssignableTo(u) {
1423
1692
  return typeAssignableTo(this, u);
@@ -1435,10 +1704,26 @@ class FunctionType {
1435
1704
  throw new Error('reflect: call of reflect.Type.OverflowFloat on func Type');
1436
1705
  }
1437
1706
  NumMethod() {
1438
- return 0;
1707
+ return typeMethods(this).length;
1439
1708
  }
1440
- MethodByName(_name) {
1441
- return [zeroMethod(), false];
1709
+ MethodByName(name) {
1710
+ return typeMethodByName(this, name);
1711
+ }
1712
+ methodSignatures() {
1713
+ return this._methods;
1714
+ }
1715
+ mergeMethodSignatures(methods) {
1716
+ this._methods = mergeMethodSignatureList(this._methods, methods);
1717
+ }
1718
+ mergeSignature(source) {
1719
+ if (!source._hasSignature || this._hasSignature) {
1720
+ return;
1721
+ }
1722
+ this._params = source._params;
1723
+ this._results = source._results;
1724
+ this._variadic = source._variadic;
1725
+ this._signature = source._signature;
1726
+ this._hasSignature = true;
1442
1727
  }
1443
1728
  Len() {
1444
1729
  throw new Error('reflect: call of reflect.Type.Len on func Type');
@@ -1447,6 +1732,174 @@ class FunctionType {
1447
1732
  throw new Error('reflect: call of reflect.Type.Bits on func Type');
1448
1733
  }
1449
1734
  }
1735
+ function formatFunctionSignature(params, results, variadic) {
1736
+ const paramStrings = params.map((param, index) => {
1737
+ const typeName = param.String();
1738
+ if (!variadic || index !== params.length - 1) {
1739
+ return typeName;
1740
+ }
1741
+ if (typeName.startsWith('[]')) {
1742
+ return '...' + typeName.slice(2);
1743
+ }
1744
+ return '...' + typeName;
1745
+ });
1746
+ let signature = `func(${paramStrings.join(', ')})`;
1747
+ if (results.length === 1) {
1748
+ signature += ` ${results[0].String()}`;
1749
+ }
1750
+ else if (results.length > 1) {
1751
+ signature += ` (${results.map((result) => result.String()).join(', ')})`;
1752
+ }
1753
+ return signature;
1754
+ }
1755
+ async function callReflectFunction(fn, fnType, inArgs, op) {
1756
+ const args = $.asArray(inArgs);
1757
+ const rawArgs = reflectCallRawArgs(fnType, args, op);
1758
+ const result = await fn(...rawArgs);
1759
+ return normalizeReflectCallResults(fnType, result);
1760
+ }
1761
+ function reflectCallRawArgs(fnType, args, op) {
1762
+ if (op === 'CallSlice') {
1763
+ return reflectCallSliceRawArgs(fnType, args);
1764
+ }
1765
+ if (!fnType.IsVariadic()) {
1766
+ validateReflectCallInputCount(fnType, args.length);
1767
+ return args.map((arg, index) => reflectCallValueInterface(op, arg, fnType.In(index), index));
1768
+ }
1769
+ const fixedCount = fnType.NumIn() - 1;
1770
+ if (args.length < fixedCount) {
1771
+ throw new Error('reflect: Call with too few input arguments');
1772
+ }
1773
+ const rawArgs = [];
1774
+ for (let i = 0; i < fixedCount; i++) {
1775
+ rawArgs.push(reflectCallValueInterface(op, args[i], fnType.In(i), i));
1776
+ }
1777
+ const variadicElemType = fnType.In(fixedCount).Elem();
1778
+ const variadicValues = args.slice(fixedCount);
1779
+ for (let i = 0; i < variadicValues.length; i++) {
1780
+ const value = variadicValues[i];
1781
+ if (!value.IsValid()) {
1782
+ throw new Error(`reflect: ${op} using zero Value argument`);
1783
+ }
1784
+ if (!value.Type().AssignableTo(variadicElemType)) {
1785
+ throw new Error(`reflect: cannot use ${value.Type().String()} as type ${variadicElemType.String()} in ${op}`);
1786
+ }
1787
+ }
1788
+ rawArgs.push($.arrayToSlice(variadicValues.map((value) => value.Interface())));
1789
+ return rawArgs;
1790
+ }
1791
+ function reflectCallSliceRawArgs(fnType, args) {
1792
+ if (!fnType.IsVariadic()) {
1793
+ throw new Error('reflect: CallSlice of non-variadic function');
1794
+ }
1795
+ const expected = fnType.NumIn();
1796
+ if (args.length < expected) {
1797
+ throw new Error('reflect: CallSlice with too few input arguments');
1798
+ }
1799
+ if (args.length > expected) {
1800
+ throw new Error('reflect: CallSlice with too many input arguments');
1801
+ }
1802
+ return args.map((arg, index) => reflectCallValueInterface('CallSlice', arg, fnType.In(index), index));
1803
+ }
1804
+ function reflectCallValueInterface(op, value, target, _index) {
1805
+ if (!value.IsValid()) {
1806
+ throw new Error(`reflect: ${op} using zero Value argument`);
1807
+ }
1808
+ if (!value.Type().AssignableTo(target)) {
1809
+ throw new Error(`reflect: ${op} using ${value.Type().String()} as type ${target.String()}`);
1810
+ }
1811
+ return value.Interface();
1812
+ }
1813
+ function validateReflectCallInputCount(fnType, actual) {
1814
+ const expected = fnType.NumIn();
1815
+ if (actual !== expected) {
1816
+ throw new Error(`reflect: Call with ${actual} input arguments for function with ${expected} inputs`);
1817
+ }
1818
+ }
1819
+ function normalizeReflectCallResults(fnType, result) {
1820
+ const expected = fnType.NumOut();
1821
+ if (expected === 0) {
1822
+ if (result !== undefined) {
1823
+ throw new Error('reflect: Call returned 1 results for function with 0 outputs');
1824
+ }
1825
+ return $.makeSlice(0);
1826
+ }
1827
+ if (expected === 1) {
1828
+ return $.arrayToSlice([new Value(result, fnType.Out(0))]);
1829
+ }
1830
+ if (!globalThis.Array.isArray(result)) {
1831
+ throw new Error(`reflect: Call returned 1 results for function with ${expected} outputs`);
1832
+ }
1833
+ if (result.length !== expected) {
1834
+ throw new Error(`reflect: Call returned ${result.length} results for function with ${expected} outputs`);
1835
+ }
1836
+ return $.arrayToSlice(result.map((value, index) => new Value(value, fnType.Out(index))));
1837
+ }
1838
+ export function MakeFunc(typ, fn) {
1839
+ if (!typ || typ.Kind() !== Func) {
1840
+ throw new Error('reflect: call of MakeFunc with non-Func type');
1841
+ }
1842
+ if (typeof fn !== 'function') {
1843
+ throw new Error('reflect.MakeFunc: nil implementation');
1844
+ }
1845
+ const typeInfo = functionTypeInfoFromType(typ);
1846
+ const wrapper = $.functionValue(async (...rawArgs) => {
1847
+ const args = makeFuncArgs(typ, rawArgs);
1848
+ const resultValues = $.asArray(await fn($.arrayToSlice(args)));
1849
+ validateMakeFuncResults(typ, resultValues);
1850
+ if (typ.NumOut() === 0) {
1851
+ return undefined;
1852
+ }
1853
+ if (typ.NumOut() === 1) {
1854
+ return makeFuncReturnInterface(resultValues[0], typ.Out(0));
1855
+ }
1856
+ return resultValues.map((value, index) => makeFuncReturnInterface(value, typ.Out(index)));
1857
+ }, typeInfo);
1858
+ return new Value(wrapper, typ);
1859
+ }
1860
+ function makeFuncArgs(typ, rawArgs) {
1861
+ validateReflectCallInputCount(typ, rawArgs.length);
1862
+ return rawArgs.map((arg, index) => {
1863
+ const value = ValueOf(arg);
1864
+ const target = typ.In(index);
1865
+ if (!value.Type().AssignableTo(target)) {
1866
+ throw new Error(`reflect.MakeFunc: cannot use ${value.Type().String()} as type ${target.String()} in argument ${index}`);
1867
+ }
1868
+ return value;
1869
+ });
1870
+ }
1871
+ function validateMakeFuncResults(typ, resultValues) {
1872
+ const expected = typ.NumOut();
1873
+ if (resultValues.length !== expected) {
1874
+ throw new Error(`reflect.MakeFunc: returned ${resultValues.length} results for function with ${expected} outputs`);
1875
+ }
1876
+ for (let i = 0; i < resultValues.length; i++) {
1877
+ const result = resultValues[i];
1878
+ if (!result.IsValid()) {
1879
+ throw new Error(`reflect.MakeFunc: returned zero Value for result ${i}`);
1880
+ }
1881
+ const target = typ.Out(i);
1882
+ if (!result.Type().AssignableTo(target)) {
1883
+ throw new Error(`reflect.MakeFunc: cannot use ${result.Type().String()} as type ${target.String()} in result ${i}`);
1884
+ }
1885
+ }
1886
+ }
1887
+ function makeFuncReturnInterface(value, target) {
1888
+ const raw = value.Interface();
1889
+ if (target.Kind() === Interface) {
1890
+ return raw;
1891
+ }
1892
+ return unwrapGoInterfaceBox(raw);
1893
+ }
1894
+ function unwrapGoInterfaceBox(value) {
1895
+ if (value !== null &&
1896
+ value !== undefined &&
1897
+ typeof value === 'object' &&
1898
+ '__goValue' in value) {
1899
+ return value.__goValue;
1900
+ }
1901
+ return value;
1902
+ }
1450
1903
  // Map type implementation
1451
1904
  class MapType {
1452
1905
  _keyType;
@@ -1473,6 +1926,21 @@ class MapType {
1473
1926
  NumField() {
1474
1927
  return 0;
1475
1928
  }
1929
+ NumIn() {
1930
+ return nonFunctionTypePanic('NumIn', this);
1931
+ }
1932
+ In(_i) {
1933
+ return nonFunctionTypePanic('In', this);
1934
+ }
1935
+ NumOut() {
1936
+ return nonFunctionTypePanic('NumOut', this);
1937
+ }
1938
+ Out(_i) {
1939
+ return nonFunctionTypePanic('Out', this);
1940
+ }
1941
+ IsVariadic() {
1942
+ return nonFunctionTypePanic('IsVariadic', this);
1943
+ }
1476
1944
  Key() {
1477
1945
  return this._keyType;
1478
1946
  }
@@ -1499,7 +1967,7 @@ class MapType {
1499
1967
  if (u.Kind() !== Interface) {
1500
1968
  throw new Error('reflect: non-interface type passed to Type.Implements');
1501
1969
  }
1502
- return false;
1970
+ return typeImplementsInterface(this, u);
1503
1971
  }
1504
1972
  AssignableTo(u) {
1505
1973
  return typeAssignableTo(this, u);
@@ -1530,47 +1998,122 @@ class MapType {
1530
1998
  }
1531
1999
  }
1532
2000
  // Struct type implementation
1533
- /**
1534
- * Helper function to check if a type's method set contains all methods
1535
- * required by an interface.
1536
- *
1537
- * @param typeName The name of the type to check (e.g., "main.MyType")
1538
- * @param interfaceType The interface type that must be implemented
1539
- * @returns True if the type implements the interface, false otherwise
1540
- */
1541
- function typeImplementsInterface(typeName, interfaceType) {
1542
- // Get the interface name and look it up in the type registry
1543
- const interfaceName = interfaceType instanceof InterfaceType ?
1544
- interfaceType.registeredName() || interfaceType.String()
1545
- : interfaceType.String();
1546
- const interfaceTypeInfo = builtinGetTypeByName(interfaceName);
1547
- if (!interfaceTypeInfo || !isInterfaceTypeInfo(interfaceTypeInfo)) {
1548
- return false;
2001
+ function typeImplementsInterface(t, interfaceType) {
2002
+ if (interfaceType.Kind() !== Interface) {
2003
+ throw new Error('reflect: non-interface type passed to Type.Implements');
2004
+ }
2005
+ const requiredMethods = typeMethods(interfaceType);
2006
+ if (requiredMethods.length === 0) {
2007
+ return true;
1549
2008
  }
1550
- // Get the type info for the struct/type
1551
- const typeInfo = builtinGetTypeByName(typeName);
1552
- if (!typeInfo || !isStructTypeInfo(typeInfo)) {
2009
+ const methods = typeMethods(t);
2010
+ return requiredMethods.every((requiredMethod) => {
2011
+ const method = methods.find((candidate) => candidate.name === requiredMethod.name);
2012
+ return (method !== undefined && methodSignatureIdentical(method, requiredMethod));
2013
+ });
2014
+ }
2015
+ function methodSignatureIdentical(actual, required) {
2016
+ return (methodArgListIdentical(actual.args, required.args) &&
2017
+ methodArgListIdentical(actual.returns, required.returns));
2018
+ }
2019
+ function methodArgListIdentical(actual, required) {
2020
+ if (actual.length !== required.length) {
1553
2021
  return false;
1554
2022
  }
1555
- // Check if the type has all required methods
1556
- const requiredMethods = interfaceTypeInfo.methods || [];
1557
- const typeMethods = typeInfo.methods || [];
1558
- // For each required method, check if the type has a matching method
1559
- for (const requiredMethod of requiredMethods) {
1560
- const typeMethod = typeMethods.find((m) => m.name === requiredMethod.name);
1561
- if (!typeMethod) {
1562
- return false;
2023
+ return actual.every((arg, index) => methodArgIdentityKey(arg) === methodArgIdentityKey(required[index]));
2024
+ }
2025
+ function methodArgIdentityKey(arg) {
2026
+ return typeInfoIdentityKey(arg.type, new Set());
2027
+ }
2028
+ function methodSignatureIdentityKey(method) {
2029
+ const args = method.args.map(methodArgIdentityKey).join(',');
2030
+ const returns = method.returns.map(methodArgIdentityKey).join(',');
2031
+ return `${method.name}(${args})(${returns})`;
2032
+ }
2033
+ function mergeMethodSignatureList(existing, incoming) {
2034
+ if (incoming.length === 0) {
2035
+ return existing;
2036
+ }
2037
+ const merged = [...existing];
2038
+ for (const method of incoming) {
2039
+ const existingIndex = merged.findIndex((candidate) => candidate.name === method.name);
2040
+ if (existingIndex === -1) {
2041
+ merged.push(method);
2042
+ continue;
1563
2043
  }
1564
- // Check if method signatures match (simplified - just check counts)
1565
- if (typeMethod.args.length !== requiredMethod.args.length) {
1566
- return false;
2044
+ if (methodSignatureIdentityKey(merged[existingIndex]) !==
2045
+ methodSignatureIdentityKey(method)) {
2046
+ merged[existingIndex] = method;
1567
2047
  }
1568
- if (typeMethod.returns.length !== requiredMethod.returns.length) {
1569
- return false;
2048
+ }
2049
+ return merged.sort((left, right) => left.name.localeCompare(right.name));
2050
+ }
2051
+ function typeInfoIdentityKey(info, seen) {
2052
+ if (typeof info === 'string') {
2053
+ const registered = builtinGetTypeByName(info);
2054
+ if (!registered) {
2055
+ return `named:${info}`;
2056
+ }
2057
+ const registeredName = registered.name ?? info;
2058
+ if (registeredName !== '') {
2059
+ return `named:${registeredName}`;
2060
+ }
2061
+ if (seen.has(info)) {
2062
+ return `named:${info}`;
1570
2063
  }
1571
- // Could add deeper type checking here, but for now this is sufficient
2064
+ seen.add(info);
2065
+ const key = typeInfoIdentityKey(registered, seen);
2066
+ seen.delete(info);
2067
+ return key;
2068
+ }
2069
+ switch (info.kind) {
2070
+ case $.TypeKind.Basic:
2071
+ if (info.typeName) {
2072
+ return `named:${info.typeName}`;
2073
+ }
2074
+ return `basic:${info.name ?? 'unknown'}`;
2075
+ case $.TypeKind.Interface:
2076
+ if (info.name) {
2077
+ return `named:${info.name}`;
2078
+ }
2079
+ return `interface:${(info.methods ?? [])
2080
+ .map(methodSignatureIdentityKey)
2081
+ .join('|')}`;
2082
+ case $.TypeKind.Struct:
2083
+ if (info.name) {
2084
+ return `named:${info.name}`;
2085
+ }
2086
+ return `struct:${(info.fields ?? [])
2087
+ .map((field) => [
2088
+ field.name,
2089
+ field.pkgPath ?? '',
2090
+ field.tag ?? '',
2091
+ field.anonymous === true ? 'anonymous' : 'named',
2092
+ typeInfoIdentityKey(field.type, seen),
2093
+ ].join('\u0000'))
2094
+ .join('\u0001')}`;
2095
+ case $.TypeKind.Pointer:
2096
+ return `ptr:${typeInfoIdentityKey(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
2097
+ case $.TypeKind.Slice:
2098
+ return `slice:${typeInfoIdentityKey(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
2099
+ case $.TypeKind.Array:
2100
+ return `array:${info.length}:${typeInfoIdentityKey(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
2101
+ case $.TypeKind.Map:
2102
+ return `map:${typeInfoIdentityKey(info.keyType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}:${typeInfoIdentityKey(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
2103
+ case $.TypeKind.Function:
2104
+ if (info.name) {
2105
+ return `named:${info.name}`;
2106
+ }
2107
+ return `func:${info.isVariadic === true}:${(info.params ?? [])
2108
+ .map((param) => typeInfoIdentityKey(param, seen))
2109
+ .join(',')}:${(info.results ?? [])
2110
+ .map((result) => typeInfoIdentityKey(result, seen))
2111
+ .join(',')}`;
2112
+ case $.TypeKind.Channel:
2113
+ return `chan:${info.direction ?? 'both'}:${typeInfoIdentityKey(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
2114
+ default:
2115
+ return 'unknown';
1572
2116
  }
1573
- return true;
1574
2117
  }
1575
2118
  function typeFieldByName(t, name) {
1576
2119
  return typeFieldByNameFunc(t, (fieldName) => fieldName === name);
@@ -1579,14 +2122,62 @@ function typeFieldByNameFunc(t, match) {
1579
2122
  if (t.Kind() !== Struct) {
1580
2123
  throw new Error('reflect: FieldByName of non-struct type');
1581
2124
  }
1582
- for (let i = 0; i < t.NumField(); i++) {
1583
- const field = t.Field(i);
2125
+ for (const field of visibleStructFields(t)) {
1584
2126
  if (match(field.Name)) {
1585
2127
  return [field, true];
1586
2128
  }
1587
2129
  }
1588
2130
  return [new StructField(), false];
1589
2131
  }
2132
+ export function visibleStructFields(t) {
2133
+ const fields = [];
2134
+ const byName = new globalThis.Map();
2135
+ const visiting = new Set();
2136
+ const index = [];
2137
+ const walk = (typ) => {
2138
+ if (visiting.has(typ)) {
2139
+ return;
2140
+ }
2141
+ visiting.add(typ);
2142
+ for (let i = 0; i < typ.NumField(); i++) {
2143
+ const field = typ.Field(i).clone();
2144
+ index.push(i);
2145
+ let add = true;
2146
+ const oldIndex = byName.get(field.Name);
2147
+ if (oldIndex !== undefined) {
2148
+ const old = fields[oldIndex];
2149
+ if (index.length === old.Index.length) {
2150
+ old.Name = '';
2151
+ add = false;
2152
+ }
2153
+ else if (index.length < old.Index.length) {
2154
+ old.Name = '';
2155
+ }
2156
+ else {
2157
+ add = false;
2158
+ }
2159
+ }
2160
+ if (add) {
2161
+ field.Index = [...index];
2162
+ byName.set(field.Name, fields.length);
2163
+ fields.push(field);
2164
+ }
2165
+ if (field.Anonymous) {
2166
+ let fieldType = field.Type;
2167
+ if (fieldType.Kind() === Ptr) {
2168
+ fieldType = fieldType.Elem();
2169
+ }
2170
+ if (fieldType.Kind() === Struct) {
2171
+ walk(fieldType);
2172
+ }
2173
+ }
2174
+ index.pop();
2175
+ }
2176
+ visiting.delete(typ);
2177
+ };
2178
+ walk(t);
2179
+ return fields.filter((field) => field.Name !== '');
2180
+ }
1590
2181
  function zeroMethod() {
1591
2182
  return {
1592
2183
  Name: '',
@@ -1595,16 +2186,50 @@ function zeroMethod() {
1595
2186
  Index: 0,
1596
2187
  };
1597
2188
  }
1598
- function methodFromSignature(signature, index) {
2189
+ function methodFromSignature(signature, index, receiver) {
1599
2190
  return {
1600
2191
  Name: signature.name,
1601
- Type: new FunctionType('func'),
2192
+ Type: methodTypeFromSignature(signature, receiver, receiver.Kind() !== Interface),
1602
2193
  Func: () => undefined,
1603
2194
  Index: index,
1604
2195
  };
1605
2196
  }
2197
+ function methodTypeFromSignature(signature, receiver, includeReceiver) {
2198
+ const params = signature.args.map(methodArgType);
2199
+ if (includeReceiver) {
2200
+ params.unshift(receiver);
2201
+ }
2202
+ return new FunctionType({
2203
+ params,
2204
+ results: signature.returns.map(methodArgType),
2205
+ });
2206
+ }
2207
+ function methodArgType(arg) {
2208
+ return typeFromTypeInfoWithSeen(arg.type, new Set());
2209
+ }
1606
2210
  function typeMethods(t) {
1607
- const typeInfo = builtinGetTypeByName(t.String());
2211
+ let typeInfo = builtinGetTypeByName(t.String());
2212
+ if (!typeInfo && t.Kind() === Ptr) {
2213
+ typeInfo = builtinGetTypeByName(t.Elem().String());
2214
+ }
2215
+ if (!typeInfo && t instanceof InterfaceType) {
2216
+ const registeredName = t.registeredName();
2217
+ if (registeredName) {
2218
+ typeInfo = builtinGetTypeByName(registeredName);
2219
+ }
2220
+ }
2221
+ if (!typeInfo && t instanceof InterfaceType) {
2222
+ return t.methodSignatures();
2223
+ }
2224
+ if (!typeInfo && t instanceof PointerType) {
2225
+ return mergeMethodSignatureList(typeMethods(t.Elem()), t.methodSignatures());
2226
+ }
2227
+ if (!typeInfo && t instanceof BasicType) {
2228
+ return t.methodSignatures();
2229
+ }
2230
+ if (!typeInfo && t instanceof FunctionType) {
2231
+ return t.methodSignatures();
2232
+ }
1608
2233
  if (!typeInfo) {
1609
2234
  return [];
1610
2235
  }
@@ -1613,29 +2238,98 @@ function typeMethods(t) {
1613
2238
  }
1614
2239
  return [];
1615
2240
  }
1616
- function typeMethodByName(t, name) {
2241
+ function methodSignatureByName(t, name) {
1617
2242
  const methods = typeMethods(t);
1618
2243
  const index = methods.findIndex((method) => method.name === name);
1619
2244
  if (index === -1) {
2245
+ return [undefined, -1];
2246
+ }
2247
+ return [methods[index], index];
2248
+ }
2249
+ function typeMethodByName(t, name) {
2250
+ const [signature, index] = methodSignatureByName(t, name);
2251
+ if (!signature) {
1620
2252
  return [zeroMethod(), false];
1621
2253
  }
1622
- return [methodFromSignature(methods[index], index), true];
2254
+ return [methodFromSignature(signature, index, t), true];
1623
2255
  }
1624
2256
  function typeAssignableTo(t, u) {
1625
2257
  if (u === null) {
1626
2258
  return false;
1627
2259
  }
1628
- return t.String() === u.String() || t.Implements(u);
2260
+ if (typeIdentityKey(t) === typeIdentityKey(u)) {
2261
+ return true;
2262
+ }
2263
+ if ((!typeIsNamed(t) || !typeIsNamed(u)) &&
2264
+ typeUnderlyingIdentityKey(t) === typeUnderlyingIdentityKey(u)) {
2265
+ return true;
2266
+ }
2267
+ if (u.Kind() !== Interface) {
2268
+ return false;
2269
+ }
2270
+ return t.Implements(u);
2271
+ }
2272
+ export function structFieldStorageKey(t, i) {
2273
+ if (t instanceof StructType) {
2274
+ return t.fieldKey(i);
2275
+ }
2276
+ return t.Field(i).Name;
2277
+ }
2278
+ function typeAlignment(typ) {
2279
+ switch (typ.Kind()) {
2280
+ case Bool:
2281
+ case Int8:
2282
+ case Uint8:
2283
+ return 1;
2284
+ case Int16:
2285
+ case Uint16:
2286
+ return 2;
2287
+ case Int32:
2288
+ case Uint32:
2289
+ case Float32:
2290
+ case Complex64:
2291
+ return 4;
2292
+ case Array:
2293
+ return typeAlignment(typ.Elem());
2294
+ case Struct: {
2295
+ let align = 1;
2296
+ for (let i = 0; i < typ.NumField(); i++) {
2297
+ align = Math.max(align, typeAlignment(typ.Field(i).Type));
2298
+ }
2299
+ return align;
2300
+ }
2301
+ default:
2302
+ return 8;
2303
+ }
2304
+ }
2305
+ function alignOffset(offset, alignment) {
2306
+ if (alignment <= 1) {
2307
+ return offset;
2308
+ }
2309
+ return Math.ceil(offset / alignment) * alignment;
2310
+ }
2311
+ function structDescriptorSize(fields) {
2312
+ let size = 0;
2313
+ let alignment = 1;
2314
+ for (const field of fields) {
2315
+ alignment = Math.max(alignment, typeAlignment(field.type));
2316
+ size = Math.max(size, field.offset + field.type.Size());
2317
+ }
2318
+ return alignOffset(size, alignment);
1629
2319
  }
1630
2320
  class StructType {
1631
2321
  _name;
1632
2322
  _fields;
1633
- constructor(_name, _fields = []) {
2323
+ _pkgPath;
2324
+ _string;
2325
+ constructor(_name, _fields = [], _pkgPath = '', _string = _name) {
1634
2326
  this._name = _name;
1635
2327
  this._fields = _fields;
2328
+ this._pkgPath = _pkgPath;
2329
+ this._string = _string;
1636
2330
  }
1637
2331
  String() {
1638
- return this._name;
2332
+ return this._string;
1639
2333
  }
1640
2334
  Kind() {
1641
2335
  return Struct;
@@ -1644,8 +2338,7 @@ class StructType {
1644
2338
  return this._fields.every((field) => field.type.Comparable());
1645
2339
  }
1646
2340
  Size() {
1647
- // Struct size is implementation-defined, we'll use a reasonable default
1648
- return this._fields.reduce((sum, field) => sum + field.type.Size(), 0);
2341
+ return structDescriptorSize(this._fields);
1649
2342
  }
1650
2343
  Elem() {
1651
2344
  throw new Error('reflect: Elem of invalid type');
@@ -1653,7 +2346,28 @@ class StructType {
1653
2346
  NumField() {
1654
2347
  return this._fields.length;
1655
2348
  }
2349
+ NumIn() {
2350
+ return nonFunctionTypePanic('NumIn', this);
2351
+ }
2352
+ In(_i) {
2353
+ return nonFunctionTypePanic('In', this);
2354
+ }
2355
+ NumOut() {
2356
+ return nonFunctionTypePanic('NumOut', this);
2357
+ }
2358
+ Out(_i) {
2359
+ return nonFunctionTypePanic('Out', this);
2360
+ }
2361
+ IsVariadic() {
2362
+ return nonFunctionTypePanic('IsVariadic', this);
2363
+ }
1656
2364
  PkgPath() {
2365
+ if (this._pkgPath !== '') {
2366
+ return this._pkgPath;
2367
+ }
2368
+ if (this._name === '') {
2369
+ return '';
2370
+ }
1657
2371
  // Extract package path from full type name (e.g., "main.Person" -> "main")
1658
2372
  const dotIndex = this._name.lastIndexOf('.');
1659
2373
  if (dotIndex > 0) {
@@ -1662,6 +2376,9 @@ class StructType {
1662
2376
  return '';
1663
2377
  }
1664
2378
  Name() {
2379
+ if (this._name === '') {
2380
+ return '';
2381
+ }
1665
2382
  // Extract type name from full type name (e.g., "main.Person" -> "Person")
1666
2383
  const dotIndex = this._name.lastIndexOf('.');
1667
2384
  if (dotIndex >= 0) {
@@ -1676,12 +2393,56 @@ class StructType {
1676
2393
  const f = this._fields[i];
1677
2394
  return new StructField({
1678
2395
  Name: f.name,
1679
- PkgPath: '',
2396
+ PkgPath: f.pkgPath,
1680
2397
  Type: f.type,
1681
2398
  Tag: f.tag ? new StructTag(f.tag) : undefined,
1682
- Index: [i],
2399
+ Offset: f.offset,
2400
+ Index: [...f.index],
2401
+ Anonymous: f.anonymous,
1683
2402
  });
1684
2403
  }
2404
+ fieldKey(i) {
2405
+ if (i < 0 || i >= this.NumField()) {
2406
+ throw new Error(`reflect: Field index out of range [${i}] with length ${this.NumField()}`);
2407
+ }
2408
+ return this._fields[i].key;
2409
+ }
2410
+ descriptors() {
2411
+ return this._fields.map((field) => ({
2412
+ ...field,
2413
+ index: [...field.index],
2414
+ }));
2415
+ }
2416
+ replaceDescriptors(fields) {
2417
+ this._fields = fields;
2418
+ }
2419
+ identityKey(seen) {
2420
+ if (this._name !== '') {
2421
+ return `struct:${this._name}`;
2422
+ }
2423
+ const fields = this._fields
2424
+ .map((field) => [
2425
+ field.name,
2426
+ field.pkgPath,
2427
+ field.tag ?? '',
2428
+ field.anonymous ? 'anonymous' : 'named',
2429
+ typeIdentityKey(field.type, seen),
2430
+ ].join('\u0000'))
2431
+ .join('\u0001');
2432
+ return `struct:${this._pkgPath}:${this._name}:${fields}`;
2433
+ }
2434
+ underlyingIdentityKey(seen) {
2435
+ const fields = this._fields
2436
+ .map((field) => [
2437
+ field.name,
2438
+ field.pkgPath,
2439
+ field.tag ?? '',
2440
+ field.anonymous ? 'anonymous' : 'named',
2441
+ typeIdentityKey(field.type, seen),
2442
+ ].join('\u0000'))
2443
+ .join('\u0001');
2444
+ return `struct:${fields}`;
2445
+ }
1685
2446
  FieldByName(name) {
1686
2447
  return typeFieldByName(this, name);
1687
2448
  }
@@ -1698,7 +2459,7 @@ class StructType {
1698
2459
  if (u.Kind() !== Interface) {
1699
2460
  throw new Error('reflect: non-interface type passed to Type.Implements');
1700
2461
  }
1701
- return typeImplementsInterface(this._name, u);
2462
+ return typeImplementsInterface(this, u);
1702
2463
  }
1703
2464
  AssignableTo(u) {
1704
2465
  return typeAssignableTo(this, u);
@@ -1727,7 +2488,7 @@ class StructType {
1727
2488
  Bits() {
1728
2489
  throw new Error('reflect: call of reflect.Type.Bits on struct Type');
1729
2490
  }
1730
- static createTypeFromFieldInfo(ti) {
2491
+ static createTypeFromFieldInfo(ti, seen = new Set()) {
1731
2492
  if (typeof ti === 'string') {
1732
2493
  return basicTypeFromName(ti === 'number' ? 'int' : ti);
1733
2494
  }
@@ -1740,18 +2501,21 @@ class StructType {
1740
2501
  return basicTypeFromName(name === 'number' ? 'int' : name, typeName);
1741
2502
  case 'slice':
1742
2503
  if (ti.elemType) {
1743
- return new SliceType(StructType.createTypeFromFieldInfo(ti.elemType));
2504
+ return new SliceType(StructType.createTypeFromFieldInfo(ti.elemType, seen));
1744
2505
  }
1745
2506
  return new SliceType(new BasicType(Invalid, 'unknown', 8));
1746
2507
  case 'pointer':
1747
2508
  if (ti.elemType) {
1748
- return new PointerType(StructType.createTypeFromFieldInfo(ti.elemType));
2509
+ return new PointerType(StructType.createTypeFromFieldInfo(ti.elemType, seen));
1749
2510
  }
1750
2511
  return new PointerType(new BasicType(Invalid, 'unknown', 8));
1751
2512
  case 'interface':
1752
- return new InterfaceType(name);
1753
- case 'struct':
1754
- return new StructType(name, structFieldsFromTypeInfo(ti));
2513
+ return interfaceTypeFromInfo(ti, seen);
2514
+ case 'struct': {
2515
+ const structName = ti.name ?? '';
2516
+ const fields = structFieldsFromTypeInfo(ti, seen);
2517
+ return new StructType(structName, fields, '', structName === '' ? structTypeString(fields) : structName);
2518
+ }
1755
2519
  default:
1756
2520
  return new BasicType(Invalid, name, 8);
1757
2521
  }
@@ -1801,18 +2565,66 @@ function basicTypeFromName(name, typeName = '') {
1801
2565
  return new BasicType(Invalid, name, 8, typeName);
1802
2566
  }
1803
2567
  }
1804
- function structFieldsFromTypeInfo(ti) {
1805
- return Object.entries(ti.fields || {}).map(([name, fieldInfo]) => {
1806
- if (isStructFieldInfo(fieldInfo)) {
1807
- return {
1808
- name: fieldInfo.name ?? name,
1809
- type: typeFromTypeInfo(fieldInfo.type),
1810
- tag: fieldInfo.tag,
1811
- };
1812
- }
2568
+ function typeFromGoTypeName(typeName) {
2569
+ const trimmed = typeName.trim();
2570
+ if (trimmed === '')
2571
+ return null;
2572
+ if (trimmed.startsWith('<-chan ')) {
2573
+ return new ChannelType(typeFromGoTypeName(trimmed.slice(7)) ?? anyType(), RecvDir);
2574
+ }
2575
+ if (trimmed.startsWith('chan<- ')) {
2576
+ return new ChannelType(typeFromGoTypeName(trimmed.slice(7)) ?? anyType(), SendDir);
2577
+ }
2578
+ if (trimmed.startsWith('chan ')) {
2579
+ return new ChannelType(typeFromGoTypeName(trimmed.slice(5)) ?? anyType(), BothDir);
2580
+ }
2581
+ if (trimmed.startsWith('[]')) {
2582
+ return new SliceType(typeFromGoTypeName(trimmed.slice(2)) ?? anyType());
2583
+ }
2584
+ if (trimmed.startsWith('*')) {
2585
+ return new PointerType(typeFromGoTypeName(trimmed.slice(1)) ?? anyType());
2586
+ }
2587
+ if (trimmed === 'struct{}' || trimmed === 'struct {}') {
2588
+ return new StructType('', [], '', 'struct {}');
2589
+ }
2590
+ if (trimmed === 'interface{}' || trimmed === 'any') {
2591
+ return anyType();
2592
+ }
2593
+ if (trimmed === 'error') {
2594
+ return new InterfaceType('error', 'error');
2595
+ }
2596
+ const registered = builtinGetTypeByName(trimmed);
2597
+ if (registered) {
2598
+ return typeFromTypeInfo(registered);
2599
+ }
2600
+ const basic = basicTypeFromName(trimmed);
2601
+ if (basic.Kind() !== Invalid) {
2602
+ return basic;
2603
+ }
2604
+ return null;
2605
+ }
2606
+ function channelTypeFromGoTypeName(typeName) {
2607
+ const typ = typeFromGoTypeName(typeName);
2608
+ if (typ?.Kind() === Chan) {
2609
+ return typ;
2610
+ }
2611
+ return null;
2612
+ }
2613
+ function anyType() {
2614
+ return new BasicType(Interface, 'interface{}', 16);
2615
+ }
2616
+ function structFieldsFromTypeInfo(ti, seen = new Set()) {
2617
+ return (ti.fields || []).map((fieldInfo, index) => {
1813
2618
  return {
1814
- name,
1815
- type: typeFromTypeInfo(fieldInfo),
2619
+ name: fieldInfo.name,
2620
+ key: structFieldRuntimeKey(fieldInfo),
2621
+ type: typeFromTypeInfoWithSeen(fieldInfo.type, seen),
2622
+ tag: fieldInfo.tag,
2623
+ pkgPath: fieldInfo.pkgPath ?? '',
2624
+ anonymous: fieldInfo.anonymous ?? false,
2625
+ index: fieldInfo.index ? [...fieldInfo.index] : [index],
2626
+ offset: fieldInfo.offset ?? index * 8,
2627
+ exported: fieldInfo.exported ?? (fieldInfo.pkgPath ?? '') === '',
1816
2628
  };
1817
2629
  });
1818
2630
  }
@@ -1852,6 +2664,21 @@ class ChannelType {
1852
2664
  NumField() {
1853
2665
  return 0;
1854
2666
  }
2667
+ NumIn() {
2668
+ return nonFunctionTypePanic('NumIn', this);
2669
+ }
2670
+ In(_i) {
2671
+ return nonFunctionTypePanic('In', this);
2672
+ }
2673
+ NumOut() {
2674
+ return nonFunctionTypePanic('NumOut', this);
2675
+ }
2676
+ Out(_i) {
2677
+ return nonFunctionTypePanic('Out', this);
2678
+ }
2679
+ IsVariadic() {
2680
+ return nonFunctionTypePanic('IsVariadic', this);
2681
+ }
1855
2682
  PkgPath() {
1856
2683
  return '';
1857
2684
  }
@@ -1878,7 +2705,7 @@ class ChannelType {
1878
2705
  if (u.Kind() !== Interface) {
1879
2706
  throw new Error('reflect: non-interface type passed to Type.Implements');
1880
2707
  }
1881
- return false;
2708
+ return typeImplementsInterface(this, u);
1882
2709
  }
1883
2710
  AssignableTo(u) {
1884
2711
  return typeAssignableTo(this, u);
@@ -1915,9 +2742,11 @@ class ChannelType {
1915
2742
  class InterfaceType {
1916
2743
  _name;
1917
2744
  _registeredName;
1918
- constructor(_name = 'interface{}', _registeredName) {
2745
+ _methods;
2746
+ constructor(_name = 'interface{}', _registeredName, _methods = []) {
1919
2747
  this._name = _name;
1920
2748
  this._registeredName = _registeredName;
2749
+ this._methods = _methods;
1921
2750
  }
1922
2751
  String() {
1923
2752
  return this._name;
@@ -1937,6 +2766,21 @@ class InterfaceType {
1937
2766
  NumField() {
1938
2767
  return 0;
1939
2768
  }
2769
+ NumIn() {
2770
+ return nonFunctionTypePanic('NumIn', this);
2771
+ }
2772
+ In(_i) {
2773
+ return nonFunctionTypePanic('In', this);
2774
+ }
2775
+ NumOut() {
2776
+ return nonFunctionTypePanic('NumOut', this);
2777
+ }
2778
+ Out(_i) {
2779
+ return nonFunctionTypePanic('Out', this);
2780
+ }
2781
+ IsVariadic() {
2782
+ return nonFunctionTypePanic('IsVariadic', this);
2783
+ }
1940
2784
  PkgPath() {
1941
2785
  if (this._name === 'interface{}' || this._name.startsWith('interface {')) {
1942
2786
  return '';
@@ -1969,8 +2813,14 @@ class InterfaceType {
1969
2813
  Key() {
1970
2814
  throw new Error('reflect: Key of non-map type');
1971
2815
  }
1972
- Implements(_u) {
1973
- return false;
2816
+ Implements(u) {
2817
+ if (!u) {
2818
+ return false;
2819
+ }
2820
+ if (u.Kind() !== Interface) {
2821
+ throw new Error('reflect: non-interface type passed to Type.Implements');
2822
+ }
2823
+ return typeImplementsInterface(this, u);
1974
2824
  }
1975
2825
  AssignableTo(u) {
1976
2826
  return typeAssignableTo(this, u);
@@ -2002,6 +2852,9 @@ class InterfaceType {
2002
2852
  registeredName() {
2003
2853
  return this._registeredName;
2004
2854
  }
2855
+ methodSignatures() {
2856
+ return this._methods;
2857
+ }
2005
2858
  }
2006
2859
  function getTypeOf(value) {
2007
2860
  // Check for typed nil before checking for plain null
@@ -2043,22 +2896,19 @@ function getTypeOf(value) {
2043
2896
  if ((typeInfo.kind === 'function' || typeInfo.kind === 'Function') &&
2044
2897
  typeInfo.params &&
2045
2898
  typeInfo.results) {
2899
+ if (funcWithMeta.__goTypeName && !typeInfo.name) {
2900
+ return functionTypeFromInfo({
2901
+ ...typeInfo,
2902
+ name: funcWithMeta.__goTypeName,
2903
+ });
2904
+ }
2046
2905
  return functionTypeFromInfo(typeInfo);
2047
2906
  }
2048
2907
  }
2049
2908
  // Then check for __goTypeName which indicates a typed function
2050
2909
  if (funcWithMeta.__goTypeName) {
2051
- // This is a typed Go function - try to reconstruct the signature
2052
2910
  const typeName = funcWithMeta.__goTypeName;
2053
- // For known Go function types, construct proper signatures
2054
- if (typeName === 'Greeter') {
2055
- return new FunctionType('func(string) string');
2056
- }
2057
- else if (typeName === 'Adder') {
2058
- return new FunctionType('func(int, int) int');
2059
- }
2060
- // Generic fallback for typed functions
2061
- return new FunctionType(`func`); // Could be enhanced with parameter parsing
2911
+ return new FunctionType({ name: typeName });
2062
2912
  }
2063
2913
  // For untyped functions, try to parse the signature
2064
2914
  const funcStr = value.toString();
@@ -2098,6 +2948,15 @@ function getTypeOf(value) {
2098
2948
  value.__goTypeInfo) {
2099
2949
  return typeFromTypeInfo(value.__goTypeInfo);
2100
2950
  }
2951
+ if ('__goType' in value) {
2952
+ const goType = value.__goType;
2953
+ if (typeof goType === 'string') {
2954
+ const channelType = channelTypeFromGoTypeName(goType);
2955
+ if (channelType) {
2956
+ return channelType;
2957
+ }
2958
+ }
2959
+ }
2101
2960
  if ('real' in value &&
2102
2961
  'imag' in value &&
2103
2962
  typeof value.real === 'number' &&
@@ -2165,34 +3024,31 @@ function getTypeOf(value) {
2165
3024
  }
2166
3025
  }
2167
3026
  // Check if it has a constructor with __typeInfo for proper struct names
3027
+ if (value &&
3028
+ typeof value === 'object' &&
3029
+ value.constructor &&
3030
+ '__reflectType' in value.constructor) {
3031
+ const reflectType = value.constructor
3032
+ .__reflectType;
3033
+ if (reflectType) {
3034
+ return reflectType;
3035
+ }
3036
+ }
2168
3037
  if (value &&
2169
3038
  typeof value === 'object' &&
2170
3039
  value.constructor &&
2171
3040
  '__typeInfo' in value.constructor) {
2172
3041
  const typeInfo = value.constructor.__typeInfo;
2173
- if (typeInfo && typeInfo.name) {
2174
- const typeName = typeInfo.name.includes('.') ?
2175
- typeInfo.name
2176
- : `main.${typeInfo.name}`;
2177
- const regTypeInfo = builtinGetTypeByName(typeName);
2178
- let fields = [];
2179
- if (regTypeInfo && isStructTypeInfo(regTypeInfo)) {
2180
- fields = Object.entries(regTypeInfo.fields || {}).map(([name, fieldInfo]) => {
2181
- // Check if fieldInfo is a StructFieldInfo with type and tag
2182
- if (isStructFieldInfo(fieldInfo)) {
2183
- return {
2184
- name: fieldInfo.name ?? name,
2185
- type: StructType.createTypeFromFieldInfo(fieldInfo.type),
2186
- tag: fieldInfo.tag,
2187
- };
2188
- }
2189
- // Otherwise it's just the type info directly (backwards compatible)
2190
- return {
2191
- name,
2192
- type: StructType.createTypeFromFieldInfo(fieldInfo),
2193
- };
2194
- });
3042
+ if (typeInfo && isStructTypeInfo(typeInfo)) {
3043
+ const name = typeInfo.name ?? '';
3044
+ if (name === '') {
3045
+ return new StructType('', structFieldsFromTypeInfo(typeInfo));
2195
3046
  }
3047
+ const typeName = name.includes('.') ? name : `main.${name}`;
3048
+ const regTypeInfo = builtinGetTypeByName(typeName);
3049
+ const fields = regTypeInfo && isStructTypeInfo(regTypeInfo) ?
3050
+ structFieldsFromTypeInfo(regTypeInfo)
3051
+ : structFieldsFromTypeInfo(typeInfo);
2196
3052
  return new StructType(typeName, fields);
2197
3053
  }
2198
3054
  }
@@ -2242,86 +3098,497 @@ export function MapOf(key, elem) {
2242
3098
  export function ChanOf(dir, t) {
2243
3099
  return internType(new ChannelType(t, dir));
2244
3100
  }
3101
+ export function StructOf(fields) {
3102
+ const inputFields = $.asArray(fields);
3103
+ const descriptors = [];
3104
+ const names = new Set();
3105
+ let pkgPath = '';
3106
+ let offset = 0;
3107
+ for (const [idx, field] of inputFields.entries()) {
3108
+ validateStructOfField(field, idx);
3109
+ if (field.PkgPath !== '') {
3110
+ if (pkgPath === '') {
3111
+ pkgPath = field.PkgPath;
3112
+ }
3113
+ else if (pkgPath !== field.PkgPath) {
3114
+ throw new Error(`reflect.Struct: fields with different PkgPath ${pkgPath} and ${field.PkgPath}`);
3115
+ }
3116
+ }
3117
+ if (names.has(field.Name) && field.Name !== '_') {
3118
+ throw new Error(`reflect.StructOf: duplicate field ${field.Name}`);
3119
+ }
3120
+ names.add(field.Name);
3121
+ const fieldOffset = alignOffset(offset, typeAlignment(field.Type));
3122
+ const tag = field.Tag?.toString();
3123
+ const descriptor = {
3124
+ name: field.Name,
3125
+ key: field.Name === '_' ? `_${idx}` : field.Name,
3126
+ type: field.Type,
3127
+ ...(tag ? { tag } : {}),
3128
+ pkgPath: field.PkgPath,
3129
+ anonymous: field.Anonymous,
3130
+ index: [idx],
3131
+ offset: fieldOffset,
3132
+ exported: field.IsExported(),
3133
+ };
3134
+ descriptors.push(descriptor);
3135
+ offset = fieldOffset + field.Type.Size();
3136
+ }
3137
+ return internType(new StructType('', descriptors, '', structTypeString(descriptors)));
3138
+ }
3139
+ function validateStructOfField(field, idx) {
3140
+ if (field.Name === '') {
3141
+ throw new Error(`reflect.StructOf: field ${idx} has no name`);
3142
+ }
3143
+ if (!isValidStructFieldName(field.Name)) {
3144
+ throw new Error(`reflect.StructOf: field ${idx} has invalid name`);
3145
+ }
3146
+ if (!field.Type) {
3147
+ throw new Error(`reflect.StructOf: field ${idx} has no type`);
3148
+ }
3149
+ if (field.Anonymous && field.PkgPath !== '') {
3150
+ throw new Error(`reflect.StructOf: field "${field.Name}" is anonymous but has PkgPath set`);
3151
+ }
3152
+ if (field.IsExported() && isUnexportedStructFieldName(field.Name)) {
3153
+ throw new Error(`reflect.StructOf: field "${field.Name}" is unexported but missing PkgPath`);
3154
+ }
3155
+ validateAnonymousStructOfField(field);
3156
+ }
3157
+ function isValidStructFieldName(name) {
3158
+ return /^[\p{L}_][\p{L}\p{N}_]*$/u.test(name);
3159
+ }
3160
+ function isUnexportedStructFieldName(name) {
3161
+ const first = name.charCodeAt(0);
3162
+ return name[0] === '_' || (first >= 97 && first <= 122);
3163
+ }
3164
+ function validateAnonymousStructOfField(field) {
3165
+ if (!field.Anonymous) {
3166
+ return;
3167
+ }
3168
+ const typ = field.Type;
3169
+ if (typ.Kind() === Ptr) {
3170
+ const elem = typ.Elem();
3171
+ if (elem.Kind() === Ptr || elem.Kind() === Interface) {
3172
+ throw new Error(`reflect.StructOf: illegal embedded field type ${typ.String()}`);
3173
+ }
3174
+ if (embeddedMethodCount(typ) > 0) {
3175
+ throw new Error('reflect: embedded type with methods not implemented');
3176
+ }
3177
+ return;
3178
+ }
3179
+ if (embeddedMethodCount(typ) > 0) {
3180
+ throw new Error('reflect: embedded type with methods not implemented');
3181
+ }
3182
+ }
3183
+ function embeddedMethodCount(typ) {
3184
+ if (typ.Kind() === Ptr) {
3185
+ return Math.max(typ.NumMethod(), typ.Elem().NumMethod());
3186
+ }
3187
+ return typ.NumMethod();
3188
+ }
3189
+ function structTypeString(fields) {
3190
+ if (fields.length === 0) {
3191
+ return 'struct {}';
3192
+ }
3193
+ return `struct { ${fields.map(structFieldString).join('; ')} }`;
3194
+ }
3195
+ function structFieldString(field) {
3196
+ const tag = field.tag ? ` ${JSON.stringify(field.tag)}` : '';
3197
+ const prefix = field.anonymous ? '' : `${field.name} `;
3198
+ return `${prefix}${field.type.String()}${tag}`;
3199
+ }
3200
+ export function FuncOf(inTypes, outTypes, variadic) {
3201
+ const params = $.asArray(inTypes).map(funcOfType);
3202
+ const results = $.asArray(outTypes).map(funcOfType);
3203
+ if (variadic &&
3204
+ (params.length === 0 || params[params.length - 1].Kind() !== Slice)) {
3205
+ throw new Error('reflect.FuncOf: last arg of variadic func must be slice');
3206
+ }
3207
+ if (params.length + results.length > 128) {
3208
+ throw new Error('reflect.FuncOf: too many arguments');
3209
+ }
3210
+ return internType(new FunctionType({ params, results, variadic }));
3211
+ }
3212
+ function funcOfType(typ) {
3213
+ if (!typ) {
3214
+ throw new Error('reflect.FuncOf: nil Type');
3215
+ }
3216
+ return typ;
3217
+ }
2245
3218
  export function TypeFor(typeArgs) {
2246
3219
  const descriptor = typeArgs?.T;
3220
+ const methodSignatures = genericMethodSignatures(descriptor);
2247
3221
  if (descriptor?.type) {
2248
- return internType(typeFromTypeInfo(descriptor.type));
3222
+ return internType(typeWithMethodSignatures(typeFromTypeInfo(descriptor.type), methodSignatures));
2249
3223
  }
2250
- if (descriptor?.methods) {
2251
- const methods = Object.keys(descriptor.methods);
2252
- if (methods.length !== 0) {
2253
- return internType(new InterfaceType(`interface { ${methods.map((method) => method + '()').join('; ')} }`));
2254
- }
3224
+ if (methodSignatures.length !== 0) {
3225
+ return internType(new InterfaceType(interfaceTypeString(methodSignatures), undefined, methodSignatures));
2255
3226
  }
2256
3227
  if (descriptor?.zero) {
2257
3228
  return internType(getTypeOf(descriptor.zero()));
2258
3229
  }
2259
3230
  return internType(new InterfaceType('interface{}'));
2260
3231
  }
3232
+ function genericMethodSignatures(descriptor) {
3233
+ if (!descriptor) {
3234
+ return [];
3235
+ }
3236
+ if (descriptor.methodSignatures && descriptor.methodSignatures.length !== 0) {
3237
+ return descriptor.methodSignatures;
3238
+ }
3239
+ if (!descriptor.methods) {
3240
+ return [];
3241
+ }
3242
+ return Object.keys(descriptor.methods).map((method) => ({
3243
+ name: method,
3244
+ args: [],
3245
+ returns: [],
3246
+ }));
3247
+ }
3248
+ function typeWithMethodSignatures(typ, methods) {
3249
+ if (methods.length === 0) {
3250
+ return typ;
3251
+ }
3252
+ if (typ instanceof BasicType) {
3253
+ typ.mergeMethodSignatures(methods);
3254
+ return typ;
3255
+ }
3256
+ if (typ instanceof PointerType) {
3257
+ typ.mergeMethodSignatures(methods);
3258
+ return typ;
3259
+ }
3260
+ if (typ instanceof FunctionType) {
3261
+ typ.mergeMethodSignatures(methods);
3262
+ return typ;
3263
+ }
3264
+ return typ;
3265
+ }
2261
3266
  function typeFromTypeInfo(info) {
3267
+ return typeFromTypeInfoWithSeen(info, new Set());
3268
+ }
3269
+ function typeFromTypeInfoWithSeen(info, seen) {
2262
3270
  if (typeof info === 'string') {
2263
3271
  const registered = builtinGetTypeByName(info);
2264
3272
  if (registered) {
2265
- return internType(typeFromTypeInfo(registered));
3273
+ const typ = typeFromTypeInfoWithSeen(registered, seen);
3274
+ return internType(typ);
3275
+ }
3276
+ return internType(StructType.createTypeFromFieldInfo(info, seen));
3277
+ }
3278
+ const recursiveName = recursiveTypeInfoName(info);
3279
+ if (recursiveName !== '') {
3280
+ const constructing = constructingRegisteredTypes.get(recursiveName);
3281
+ if (constructing) {
3282
+ return constructing;
3283
+ }
3284
+ if (seen.has(recursiveName)) {
3285
+ return internType(shallowTypeFromRegisteredInfo(recursiveName, info));
3286
+ }
3287
+ if (info.kind === $.TypeKind.Struct) {
3288
+ const typ = new StructType(recursiveName, []);
3289
+ constructingRegisteredTypes.set(recursiveName, typ);
3290
+ seen.add(recursiveName);
3291
+ try {
3292
+ typ.replaceDescriptors(structFieldsFromTypeInfo(info, seen));
3293
+ return internType(typ);
3294
+ }
3295
+ finally {
3296
+ seen.delete(recursiveName);
3297
+ constructingRegisteredTypes.delete(recursiveName);
3298
+ }
2266
3299
  }
2267
- return internType(StructType.createTypeFromFieldInfo(info));
3300
+ seen.add(recursiveName);
3301
+ const typ = typeFromStructuredTypeInfoWithSeen(info, seen);
3302
+ seen.delete(recursiveName);
3303
+ return internType(typ);
2268
3304
  }
3305
+ return internType(typeFromStructuredTypeInfoWithSeen(info, seen));
3306
+ }
3307
+ function recursiveTypeInfoName(info) {
3308
+ if (info.kind === $.TypeKind.Basic) {
3309
+ return info.typeName ?? '';
3310
+ }
3311
+ return info.name ?? '';
3312
+ }
3313
+ function typeFromStructuredTypeInfoWithSeen(info, seen) {
2269
3314
  switch (info.kind) {
2270
3315
  case $.TypeKind.Array:
2271
- return internType(new ArrayType(typeFromTypeInfo(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }), info.length));
3316
+ return new ArrayType(typeFromTypeInfoWithSeen(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen), info.length);
2272
3317
  case $.TypeKind.Basic:
2273
- return internType(StructType.createTypeFromFieldInfo(info));
3318
+ return StructType.createTypeFromFieldInfo(info, seen);
2274
3319
  case $.TypeKind.Channel:
2275
- return internType(new ChannelType(typeFromTypeInfo(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }), chanDirFromTypeInfo(info.direction)));
3320
+ return new ChannelType(typeFromTypeInfoWithSeen(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen), chanDirFromTypeInfo(info.direction));
2276
3321
  case $.TypeKind.Function:
2277
- return internType(functionTypeFromInfo(info));
3322
+ return functionTypeFromInfo(info, seen);
2278
3323
  case $.TypeKind.Interface:
2279
- return internType(interfaceTypeFromInfo(info));
3324
+ return interfaceTypeFromInfo(info, seen);
2280
3325
  case $.TypeKind.Map:
2281
- return internType(new MapType(typeFromTypeInfo(info.keyType ?? { kind: $.TypeKind.Basic, name: 'unknown' }), typeFromTypeInfo(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' })));
3326
+ return new MapType(typeFromTypeInfoWithSeen(info.keyType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen), typeFromTypeInfoWithSeen(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen));
2282
3327
  case $.TypeKind.Slice:
2283
- return internType(new SliceType(typeFromTypeInfo(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' })));
3328
+ return new SliceType(typeFromTypeInfoWithSeen(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen));
2284
3329
  case $.TypeKind.Struct:
2285
- return internType(StructType.createTypeFromFieldInfo(info));
3330
+ return StructType.createTypeFromFieldInfo(info, seen);
2286
3331
  case $.TypeKind.Pointer:
2287
- return internType(new PointerType(typeFromTypeInfo(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' })));
3332
+ return new PointerType(typeFromTypeInfoWithSeen(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen));
2288
3333
  default:
2289
- return internType(StructType.createTypeFromFieldInfo(info));
3334
+ return StructType.createTypeFromFieldInfo(info, seen);
2290
3335
  }
2291
3336
  }
2292
- function functionTypeFromInfo(info) {
2293
- if (info.name) {
2294
- return new FunctionType(info.name);
3337
+ function shallowTypeFromRegisteredInfo(name, info) {
3338
+ switch (info.kind) {
3339
+ case $.TypeKind.Interface:
3340
+ return new InterfaceType(name, name, info.methods ?? []);
3341
+ case $.TypeKind.Struct:
3342
+ return new StructType(name, []);
3343
+ case $.TypeKind.Function:
3344
+ return new FunctionType({ name });
3345
+ case $.TypeKind.Basic:
3346
+ return StructType.createTypeFromFieldInfo({
3347
+ kind: $.TypeKind.Basic,
3348
+ name: info.name ?? 'unknown',
3349
+ typeName: info.typeName ?? name,
3350
+ });
3351
+ default:
3352
+ return StructType.createTypeFromFieldInfo(name);
2295
3353
  }
2296
- const params = info.params ?? [];
2297
- const paramTypes = params.map((param, index) => {
2298
- const typeName = functionSignatureTypeName(param);
2299
- if (!info.isVariadic || index !== params.length - 1) {
2300
- return typeName;
2301
- }
2302
- if (typeName.startsWith('[]')) {
2303
- return '...' + typeName.slice(2);
2304
- }
2305
- return '...' + typeName;
3354
+ }
3355
+ function functionTypeFromInfo(info, seen = new Set()) {
3356
+ const params = (info.params ?? []).map((param) => typeFromTypeInfoWithSeen(param, seen));
3357
+ const results = (info.results ?? []).map((result) => typeFromTypeInfoWithSeen(result, seen));
3358
+ return new FunctionType({
3359
+ name: info.name,
3360
+ params,
3361
+ results,
3362
+ variadic: info.isVariadic ?? false,
2306
3363
  });
2307
- const resultTypes = (info.results ?? []).map(functionSignatureTypeName);
2308
- let signature = `func(${paramTypes.join(', ')})`;
2309
- if (resultTypes.length === 1) {
2310
- signature += ` ${resultTypes[0]}`;
3364
+ }
3365
+ function functionTypeInfoFromType(typ) {
3366
+ const params = [];
3367
+ for (let i = 0; i < typ.NumIn(); i++) {
3368
+ params.push(typeInfoFromReflectType(typ.In(i)));
3369
+ }
3370
+ const results = [];
3371
+ for (let i = 0; i < typ.NumOut(); i++) {
3372
+ results.push(typeInfoFromReflectType(typ.Out(i)));
3373
+ }
3374
+ const info = {
3375
+ kind: $.TypeKind.Function,
3376
+ params,
3377
+ results,
3378
+ };
3379
+ if (typ.Name() !== '') {
3380
+ info.name = typ.String();
3381
+ }
3382
+ if (typ.IsVariadic()) {
3383
+ info.isVariadic = true;
3384
+ }
3385
+ return info;
3386
+ }
3387
+ export function typeInfoFromReflectType(typ) {
3388
+ if (typ.PkgPath() !== '' && typ.Name() !== '') {
3389
+ return typ.String();
3390
+ }
3391
+ switch (typ.Kind()) {
3392
+ case Bool:
3393
+ case Int:
3394
+ case Int8:
3395
+ case Int16:
3396
+ case Int32:
3397
+ case Int64:
3398
+ case Uint:
3399
+ case Uint8:
3400
+ case Uint16:
3401
+ case Uint32:
3402
+ case Uint64:
3403
+ case Uintptr:
3404
+ case Float32:
3405
+ case Float64:
3406
+ case Complex64:
3407
+ case Complex128:
3408
+ case String:
3409
+ case UnsafePointer:
3410
+ return { kind: $.TypeKind.Basic, name: typ.String() };
3411
+ case Interface:
3412
+ return {
3413
+ kind: $.TypeKind.Interface,
3414
+ methods: typeMethods(typ).map((method) => ({
3415
+ name: method.name,
3416
+ args: method.args,
3417
+ returns: method.returns,
3418
+ })),
3419
+ };
3420
+ case Slice:
3421
+ return {
3422
+ kind: $.TypeKind.Slice,
3423
+ elemType: typeInfoFromReflectType(typ.Elem()),
3424
+ };
3425
+ case Array:
3426
+ return {
3427
+ kind: $.TypeKind.Array,
3428
+ elemType: typeInfoFromReflectType(typ.Elem()),
3429
+ length: typ.Len(),
3430
+ };
3431
+ case Ptr:
3432
+ return {
3433
+ kind: $.TypeKind.Pointer,
3434
+ elemType: typeInfoFromReflectType(typ.Elem()),
3435
+ };
3436
+ case Map:
3437
+ return {
3438
+ kind: $.TypeKind.Map,
3439
+ keyType: typeInfoFromReflectType(typ.Key()),
3440
+ elemType: typeInfoFromReflectType(typ.Elem()),
3441
+ };
3442
+ case Chan:
3443
+ return {
3444
+ kind: $.TypeKind.Channel,
3445
+ elemType: typeInfoFromReflectType(typ.Elem()),
3446
+ direction: channelDirectionFromString(typ.String()),
3447
+ };
3448
+ case Func:
3449
+ return functionTypeInfoFromType(typ);
3450
+ case Struct: {
3451
+ const fields = typ instanceof StructType ?
3452
+ typ.descriptors()
3453
+ : globalThis.Array.from({ length: typ.NumField() }, (_unused, idx) => {
3454
+ const field = typ.Field(idx);
3455
+ return {
3456
+ name: field.Name,
3457
+ key: structFieldStorageKey(typ, idx),
3458
+ type: field.Type,
3459
+ tag: field.Tag?.toString(),
3460
+ pkgPath: field.PkgPath,
3461
+ anonymous: field.Anonymous,
3462
+ index: [...field.Index],
3463
+ offset: field.Offset,
3464
+ exported: field.IsExported(),
3465
+ };
3466
+ });
3467
+ return {
3468
+ kind: $.TypeKind.Struct,
3469
+ name: typ.Name() === '' ? '' : typ.String(),
3470
+ methods: [],
3471
+ fields: fields.map((field) => ({
3472
+ name: field.name,
3473
+ key: field.key,
3474
+ type: typeInfoFromReflectType(field.type),
3475
+ ...(field.tag ? { tag: field.tag } : {}),
3476
+ ...(field.pkgPath ? { pkgPath: field.pkgPath } : {}),
3477
+ ...(field.anonymous ? { anonymous: true } : {}),
3478
+ index: [...field.index],
3479
+ offset: field.offset,
3480
+ exported: field.exported,
3481
+ })),
3482
+ };
3483
+ }
3484
+ default:
3485
+ return typ.String();
2311
3486
  }
2312
- if (resultTypes.length > 1) {
2313
- signature += ` (${resultTypes.join(', ')})`;
3487
+ }
3488
+ function channelDirectionFromString(typeName) {
3489
+ if (typeName.startsWith('<-chan ')) {
3490
+ return 'receive';
3491
+ }
3492
+ if (typeName.startsWith('chan<- ')) {
3493
+ return 'send';
3494
+ }
3495
+ return 'both';
3496
+ }
3497
+ function interfaceTypeFromInfo(info, seen = new Set()) {
3498
+ const methods = info.methods ?? [];
3499
+ if (methods.length === 0) {
3500
+ return new InterfaceType('interface{}', info.name, methods);
2314
3501
  }
2315
- return new FunctionType(signature);
3502
+ return new InterfaceType(interfaceTypeString(methods, seen), info.name, methods);
2316
3503
  }
2317
- function functionSignatureTypeName(info) {
2318
- return typeFromTypeInfo(info).String();
3504
+ function interfaceTypeString(methods, seen = new Set()) {
3505
+ return `interface { ${methods
3506
+ .map((method) => interfaceMethodString(method, seen))
3507
+ .join('; ')} }`;
2319
3508
  }
2320
- function interfaceTypeFromInfo(info) {
2321
- if (info.methods.length === 0) {
2322
- return new InterfaceType('interface{}', info.name);
3509
+ function interfaceMethodString(method, seen) {
3510
+ const args = method.args.map((arg) => methodArgString(arg, seen)).join(', ');
3511
+ const returns = method.returns.map((arg) => methodArgString(arg, seen));
3512
+ if (returns.length === 0) {
3513
+ return `${method.name}(${args})`;
3514
+ }
3515
+ if (returns.length === 1) {
3516
+ return `${method.name}(${args}) ${returns[0]}`;
3517
+ }
3518
+ return `${method.name}(${args}) (${returns.join(', ')})`;
3519
+ }
3520
+ function structTypeInfoString(info, seen) {
3521
+ if (info.name) {
3522
+ return info.name;
3523
+ }
3524
+ const fields = info.fields ?? [];
3525
+ if (fields.length === 0) {
3526
+ return 'struct {}';
3527
+ }
3528
+ return `struct { ${fields
3529
+ .map((field) => structFieldInfoString(field, seen))
3530
+ .join('; ')} }`;
3531
+ }
3532
+ function structFieldInfoString(field, seen) {
3533
+ const tag = field.tag ? ` ${JSON.stringify(field.tag)}` : '';
3534
+ const prefix = field.anonymous ? '' : `${field.name} `;
3535
+ return `${prefix}${typeInfoString(field.type, seen)}${tag}`;
3536
+ }
3537
+ function methodArgString(arg, seen) {
3538
+ return typeInfoString(arg.type, seen);
3539
+ }
3540
+ function typeInfoString(info, seen) {
3541
+ if (typeof info === 'string') {
3542
+ return info;
3543
+ }
3544
+ switch (info.kind) {
3545
+ case $.TypeKind.Basic:
3546
+ return info.typeName ?? info.name ?? 'unknown';
3547
+ case $.TypeKind.Interface: {
3548
+ const name = info.name ?? '';
3549
+ if (name !== '' && seen.has(name)) {
3550
+ return name;
3551
+ }
3552
+ if (info.methods.length === 0) {
3553
+ return 'interface{}';
3554
+ }
3555
+ if (name !== '') {
3556
+ seen.add(name);
3557
+ }
3558
+ const text = interfaceTypeString(info.methods, seen);
3559
+ if (name !== '') {
3560
+ seen.delete(name);
3561
+ }
3562
+ return text;
3563
+ }
3564
+ case $.TypeKind.Struct:
3565
+ return structTypeInfoString(info, seen);
3566
+ case $.TypeKind.Pointer:
3567
+ return `*${typeInfoString(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
3568
+ case $.TypeKind.Slice:
3569
+ return `[]${typeInfoString(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
3570
+ case $.TypeKind.Array:
3571
+ return `[${info.length}]${typeInfoString(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
3572
+ case $.TypeKind.Map:
3573
+ return `map[${typeInfoString(info.keyType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}]${typeInfoString(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
3574
+ case $.TypeKind.Function: {
3575
+ const params = (info.params ?? [])
3576
+ .map((param) => typeInfoString(param, seen))
3577
+ .join(', ');
3578
+ const results = (info.results ?? []).map((result) => typeInfoString(result, seen));
3579
+ if (results.length === 0) {
3580
+ return `func(${params})`;
3581
+ }
3582
+ if (results.length === 1) {
3583
+ return `func(${params}) ${results[0]}`;
3584
+ }
3585
+ return `func(${params}) (${results.join(', ')})`;
3586
+ }
3587
+ case $.TypeKind.Channel:
3588
+ return `chan ${typeInfoString(info.elemType ?? { kind: $.TypeKind.Basic, name: 'unknown' }, seen)}`;
3589
+ default:
3590
+ return 'unknown';
2323
3591
  }
2324
- return new InterfaceType(`interface { ${info.methods.map((method) => method.name + '()').join('; ')} }`, info.name);
2325
3592
  }
2326
3593
  function chanDirFromTypeInfo(direction) {
2327
3594
  switch (direction) {
@@ -2339,35 +3606,15 @@ function chanDirFromTypeInfo(direction) {
2339
3606
  */
2340
3607
  export function getInterfaceTypeByName(name) {
2341
3608
  const typeInfo = builtinGetTypeByName(name);
2342
- if (typeInfo && typeInfo.kind === TypeKind.Interface) {
2343
- return new InterfaceType(name, name);
3609
+ if (typeInfo && isInterfaceTypeInfo(typeInfo)) {
3610
+ return new InterfaceType(name, name, typeInfo.methods ?? []);
2344
3611
  }
2345
3612
  return new InterfaceType('interface{}');
2346
3613
  }
2347
3614
  export function getInterfaceLiteralTypeByName(name) {
2348
3615
  const typeInfo = builtinGetTypeByName(name);
2349
- if (typeInfo && typeInfo.kind === TypeKind.Interface) {
2350
- const methods = typeInfo.methods || [];
2351
- if (methods.length === 0) {
2352
- return new InterfaceType('interface{}', name);
2353
- }
2354
- const methodSigs = methods
2355
- .map((m) => {
2356
- const args = m.args
2357
- ?.map((a) => (typeof a === 'string' ? a : 'any'))
2358
- .join(', ') || '';
2359
- const returns = m.returns?.map((r) => typeof r === 'string' ? r : 'any');
2360
- let returnSig = '';
2361
- if (returns && returns.length === 1) {
2362
- returnSig = ` ${returns[0]}`;
2363
- }
2364
- else if (returns && returns.length > 1) {
2365
- returnSig = ` (${returns.join(', ')})`;
2366
- }
2367
- return `${m.name}(${args})${returnSig}`;
2368
- })
2369
- .join('; ');
2370
- return new InterfaceType(`interface { ${methodSigs} }`, name);
3616
+ if (typeInfo && isInterfaceTypeInfo(typeInfo)) {
3617
+ return interfaceTypeFromInfo(typeInfo);
2371
3618
  }
2372
3619
  return new InterfaceType('interface{}');
2373
3620
  }