goscript 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. package/README.md +5 -2
  2. package/cmd/go_js_wasm_exec/main.go +201 -0
  3. package/cmd/go_js_wasm_exec/main_test.go +83 -0
  4. package/cmd/goscript/{cmd_compile.go → cmd-compile.go} +7 -0
  5. package/cmd/goscript/cmd-test.go +14 -0
  6. package/cmd/goscript/cmd-test_test.go +1 -1
  7. package/compiler/compile-request.go +12 -9
  8. package/compiler/compliance_test.go +0 -1
  9. package/compiler/config.go +2 -0
  10. package/compiler/gotest/request.go +28 -0
  11. package/compiler/gotest/runner.go +353 -27
  12. package/compiler/gotest/runner_test.go +273 -1
  13. package/compiler/gotest/testdata/browserapi/browserapi_test.go +20 -0
  14. package/compiler/gotest/testdata/browserapi/go.mod +3 -0
  15. package/compiler/lowered-program.go +24 -17
  16. package/compiler/lowering.go +392 -127
  17. package/compiler/lowering_bench_test.go +41 -27
  18. package/compiler/override-facts.go +15 -0
  19. package/compiler/override-parity-verifier.go +450 -0
  20. package/compiler/override-parity.go +122 -0
  21. package/compiler/override-registry_test.go +559 -0
  22. package/compiler/protobuf-ts-binding.go +514 -0
  23. package/compiler/protobuf-ts-binding_test.go +172 -0
  24. package/compiler/semantic-model-types.go +9 -4
  25. package/compiler/semantic-model.go +282 -70
  26. package/compiler/semantic-model_test.go +82 -1
  27. package/compiler/service.go +20 -1
  28. package/compiler/skeleton_test.go +62 -8
  29. package/compiler/typescript-emitter.go +128 -13
  30. package/dist/gs/builtin/slice.d.ts +2 -1
  31. package/dist/gs/builtin/slice.js +29 -4
  32. package/dist/gs/builtin/slice.js.map +1 -1
  33. package/dist/gs/builtin/type.d.ts +13 -5
  34. package/dist/gs/builtin/type.js +153 -60
  35. package/dist/gs/builtin/type.js.map +1 -1
  36. package/dist/gs/builtin/varRef.d.ts +11 -0
  37. package/dist/gs/builtin/varRef.js +57 -2
  38. package/dist/gs/builtin/varRef.js.map +1 -1
  39. package/dist/gs/bytes/buffer.gs.js +1 -1
  40. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  41. package/dist/gs/bytes/reader.gs.js +1 -1
  42. package/dist/gs/bytes/reader.gs.js.map +1 -1
  43. package/dist/gs/compress/zlib/index.d.ts +10 -3
  44. package/dist/gs/compress/zlib/index.js +50 -16
  45. package/dist/gs/compress/zlib/index.js.map +1 -1
  46. package/dist/gs/encoding/json/index.d.ts +114 -0
  47. package/dist/gs/encoding/json/index.js +544 -36
  48. package/dist/gs/encoding/json/index.js.map +1 -1
  49. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +100 -0
  50. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +564 -0
  51. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  52. package/dist/gs/github.com/pkg/errors/errors.js +54 -30
  53. package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
  54. package/dist/gs/go/scanner/index.d.ts +2 -0
  55. package/dist/gs/go/scanner/index.js +29 -5
  56. package/dist/gs/go/scanner/index.js.map +1 -1
  57. package/dist/gs/go/token/index.js +22 -6
  58. package/dist/gs/go/token/index.js.map +1 -1
  59. package/dist/gs/hash/index.d.ts +6 -0
  60. package/dist/gs/hash/index.js +20 -0
  61. package/dist/gs/hash/index.js.map +1 -1
  62. package/dist/gs/internal/goarch/index.d.ts +43 -3
  63. package/dist/gs/internal/goarch/index.js +42 -10
  64. package/dist/gs/internal/goarch/index.js.map +1 -1
  65. package/dist/gs/io/fs/fs.js +26 -14
  66. package/dist/gs/io/fs/fs.js.map +1 -1
  67. package/dist/gs/io/fs/readdir.js +4 -2
  68. package/dist/gs/io/fs/readdir.js.map +1 -1
  69. package/dist/gs/io/fs/sub.js +8 -1
  70. package/dist/gs/io/fs/sub.js.map +1 -1
  71. package/dist/gs/io/io.d.ts +2 -0
  72. package/dist/gs/io/io.js.map +1 -1
  73. package/dist/gs/math/bits/index.d.ts +5 -0
  74. package/dist/gs/math/bits/index.js +16 -4
  75. package/dist/gs/math/bits/index.js.map +1 -1
  76. package/dist/gs/mime/index.d.ts +16 -0
  77. package/dist/gs/mime/index.js +315 -6
  78. package/dist/gs/mime/index.js.map +1 -1
  79. package/dist/gs/net/http/httptest/index.d.ts +12 -0
  80. package/dist/gs/net/http/httptest/index.js +85 -6
  81. package/dist/gs/net/http/httptest/index.js.map +1 -1
  82. package/dist/gs/net/http/index.d.ts +300 -5
  83. package/dist/gs/net/http/index.js +1598 -58
  84. package/dist/gs/net/http/index.js.map +1 -1
  85. package/dist/gs/os/dir_unix.gs.js +1 -1
  86. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  87. package/dist/gs/os/error.gs.js +1 -1
  88. package/dist/gs/os/error.gs.js.map +1 -1
  89. package/dist/gs/os/exec.gs.d.ts +1 -0
  90. package/dist/gs/os/exec.gs.js +4 -8
  91. package/dist/gs/os/exec.gs.js.map +1 -1
  92. package/dist/gs/os/exec_posix.gs.js +1 -1
  93. package/dist/gs/os/exec_posix.gs.js.map +1 -1
  94. package/dist/gs/os/index.d.ts +1 -1
  95. package/dist/gs/os/index.js +1 -1
  96. package/dist/gs/os/index.js.map +1 -1
  97. package/dist/gs/os/proc.gs.d.ts +4 -0
  98. package/dist/gs/os/proc.gs.js +12 -6
  99. package/dist/gs/os/proc.gs.js.map +1 -1
  100. package/dist/gs/os/root_js.gs.js +1 -1
  101. package/dist/gs/os/root_js.gs.js.map +1 -1
  102. package/dist/gs/os/types.gs.js +1 -1
  103. package/dist/gs/os/types.gs.js.map +1 -1
  104. package/dist/gs/os/types_js.gs.js +1 -1
  105. package/dist/gs/os/types_js.gs.js.map +1 -1
  106. package/dist/gs/os/types_unix.gs.js +1 -1
  107. package/dist/gs/os/types_unix.gs.js.map +1 -1
  108. package/dist/gs/path/path.js +11 -7
  109. package/dist/gs/path/path.js.map +1 -1
  110. package/dist/gs/reflect/index.d.ts +5 -4
  111. package/dist/gs/reflect/index.js +4 -3
  112. package/dist/gs/reflect/index.js.map +1 -1
  113. package/dist/gs/reflect/map.js +15 -0
  114. package/dist/gs/reflect/map.js.map +1 -1
  115. package/dist/gs/reflect/type.d.ts +25 -6
  116. package/dist/gs/reflect/type.js +1418 -228
  117. package/dist/gs/reflect/type.js.map +1 -1
  118. package/dist/gs/reflect/types.d.ts +14 -6
  119. package/dist/gs/reflect/types.js +35 -1
  120. package/dist/gs/reflect/types.js.map +1 -1
  121. package/dist/gs/reflect/value.d.ts +1 -0
  122. package/dist/gs/reflect/value.js +83 -41
  123. package/dist/gs/reflect/value.js.map +1 -1
  124. package/dist/gs/reflect/visiblefields.js +4 -140
  125. package/dist/gs/reflect/visiblefields.js.map +1 -1
  126. package/dist/gs/runtime/pprof/index.d.ts +8 -2
  127. package/dist/gs/runtime/pprof/index.js +50 -30
  128. package/dist/gs/runtime/pprof/index.js.map +1 -1
  129. package/dist/gs/runtime/runtime.js +5 -4
  130. package/dist/gs/runtime/runtime.js.map +1 -1
  131. package/dist/gs/runtime/trace/index.js +5 -19
  132. package/dist/gs/runtime/trace/index.js.map +1 -1
  133. package/dist/gs/strconv/atoi.gs.js +1 -1
  134. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  135. package/dist/gs/strconv/complex.gs.d.ts +3 -0
  136. package/dist/gs/strconv/complex.gs.js +148 -0
  137. package/dist/gs/strconv/complex.gs.js.map +1 -0
  138. package/dist/gs/strconv/index.d.ts +1 -0
  139. package/dist/gs/strconv/index.js +1 -0
  140. package/dist/gs/strconv/index.js.map +1 -1
  141. package/dist/gs/strings/builder.js +1 -1
  142. package/dist/gs/strings/reader.js +9 -5
  143. package/dist/gs/strings/reader.js.map +1 -1
  144. package/dist/gs/strings/replace.js +15 -7
  145. package/dist/gs/strings/replace.js.map +1 -1
  146. package/dist/gs/strings/strings.d.ts +5 -0
  147. package/dist/gs/strings/strings.js +57 -5
  148. package/dist/gs/strings/strings.js.map +1 -1
  149. package/dist/gs/sync/atomic/type.gs.js +9 -9
  150. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  151. package/dist/gs/sync/atomic/value.gs.js +2 -2
  152. package/dist/gs/sync/atomic/value.gs.js.map +1 -1
  153. package/dist/gs/syscall/env.js +22 -14
  154. package/dist/gs/syscall/env.js.map +1 -1
  155. package/dist/gs/testing/testing.js +55 -13
  156. package/dist/gs/testing/testing.js.map +1 -1
  157. package/dist/gs/time/time.d.ts +24 -1
  158. package/dist/gs/time/time.js +43 -3
  159. package/dist/gs/time/time.js.map +1 -1
  160. package/dist/gs/unique/index.js +7 -1
  161. package/dist/gs/unique/index.js.map +1 -1
  162. package/go.mod +3 -3
  163. package/go.sum +16 -0
  164. package/gs/builtin/runtime-contract.test.ts +218 -21
  165. package/gs/builtin/slice.ts +44 -4
  166. package/gs/builtin/type.ts +226 -59
  167. package/gs/builtin/varRef.ts +85 -2
  168. package/gs/bytes/buffer.gs.ts +1 -1
  169. package/gs/bytes/reader.gs.ts +1 -1
  170. package/gs/compress/zlib/index.test.ts +62 -1
  171. package/gs/compress/zlib/index.ts +53 -16
  172. package/gs/compress/zlib/parity.json +51 -0
  173. package/gs/encoding/json/index.test.ts +360 -6
  174. package/gs/encoding/json/index.ts +679 -38
  175. package/gs/encoding/json/parity.json +81 -0
  176. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +211 -3
  177. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +857 -1
  178. package/gs/github.com/pkg/errors/errors.ts +54 -30
  179. package/gs/go/scanner/index.test.ts +39 -56
  180. package/gs/go/scanner/index.ts +33 -5
  181. package/gs/go/scanner/parity.json +27 -0
  182. package/gs/go/token/index.ts +22 -6
  183. package/gs/hash/index.test.ts +20 -33
  184. package/gs/hash/index.ts +28 -0
  185. package/gs/hash/parity.json +21 -0
  186. package/gs/internal/goarch/index.test.ts +32 -0
  187. package/gs/internal/goarch/index.ts +45 -13
  188. package/gs/internal/goarch/parity.json +144 -0
  189. package/gs/io/fs/fs.ts +26 -14
  190. package/gs/io/fs/readdir.ts +4 -4
  191. package/gs/io/fs/sub.ts +8 -1
  192. package/gs/io/io.ts +1 -0
  193. package/gs/io/parity.json +162 -0
  194. package/gs/math/bits/index.test.ts +14 -1
  195. package/gs/math/bits/index.ts +23 -4
  196. package/gs/math/bits/parity.json +156 -0
  197. package/gs/mime/index.test.ts +90 -0
  198. package/gs/mime/index.ts +369 -6
  199. package/gs/mime/parity.json +36 -0
  200. package/gs/net/http/httptest/index.test.ts +98 -2
  201. package/gs/net/http/httptest/index.ts +101 -6
  202. package/gs/net/http/httptest/parity.json +15 -0
  203. package/gs/net/http/index.test.ts +781 -12
  204. package/gs/net/http/index.ts +1860 -139
  205. package/gs/net/http/meta.json +16 -1
  206. package/gs/net/http/parity.json +193 -0
  207. package/gs/os/dir_unix.gs.ts +1 -1
  208. package/gs/os/error.gs.ts +1 -1
  209. package/gs/os/exec.gs.ts +4 -8
  210. package/gs/os/exec_posix.gs.ts +1 -1
  211. package/gs/os/index.test.ts +9 -0
  212. package/gs/os/index.ts +1 -0
  213. package/gs/os/parity.json +9 -0
  214. package/gs/os/proc.gs.ts +18 -5
  215. package/gs/os/proc.test.ts +26 -0
  216. package/gs/os/root_js.gs.ts +1 -1
  217. package/gs/os/types.gs.ts +1 -1
  218. package/gs/os/types_js.gs.ts +1 -1
  219. package/gs/os/types_unix.gs.ts +1 -1
  220. package/gs/path/path.ts +11 -7
  221. package/gs/reflect/field.test.ts +37 -15
  222. package/gs/reflect/function-types.test.ts +518 -22
  223. package/gs/reflect/index.ts +8 -6
  224. package/gs/reflect/map.ts +20 -0
  225. package/gs/reflect/meta.json +6 -4
  226. package/gs/reflect/parity.json +234 -0
  227. package/gs/reflect/sliceat.test.ts +156 -0
  228. package/gs/reflect/structof.test.ts +401 -0
  229. package/gs/reflect/type.ts +1897 -317
  230. package/gs/reflect/typefor.test.ts +510 -10
  231. package/gs/reflect/types.ts +43 -18
  232. package/gs/reflect/value.ts +105 -45
  233. package/gs/reflect/visiblefields.ts +5 -168
  234. package/gs/runtime/parity.json +24 -0
  235. package/gs/runtime/pprof/index.test.ts +29 -7
  236. package/gs/runtime/pprof/index.ts +56 -30
  237. package/gs/runtime/pprof/parity.json +27 -0
  238. package/gs/runtime/runtime.test.ts +3 -1
  239. package/gs/runtime/runtime.ts +4 -3
  240. package/gs/runtime/trace/index.test.ts +5 -3
  241. package/gs/runtime/trace/index.ts +8 -20
  242. package/gs/runtime/trace/parity.json +36 -0
  243. package/gs/strconv/atoi.gs.ts +1 -1
  244. package/gs/strconv/complex.gs.ts +174 -0
  245. package/gs/strconv/complex.test.ts +65 -0
  246. package/gs/strconv/index.ts +1 -0
  247. package/gs/strconv/parity.json +120 -0
  248. package/gs/strings/builder.ts +1 -1
  249. package/gs/strings/parity.json +186 -0
  250. package/gs/strings/reader.ts +9 -5
  251. package/gs/strings/replace.ts +15 -7
  252. package/gs/strings/strings.test.ts +22 -2
  253. package/gs/strings/strings.ts +64 -6
  254. package/gs/sync/atomic/type.gs.ts +9 -9
  255. package/gs/sync/atomic/value.gs.ts +2 -2
  256. package/gs/syscall/env.ts +29 -14
  257. package/gs/testing/testing.test.ts +67 -0
  258. package/gs/testing/testing.ts +87 -19
  259. package/gs/time/parity.json +225 -0
  260. package/gs/time/time.test.ts +20 -2
  261. package/gs/time/time.ts +49 -7
  262. package/gs/unique/index.ts +7 -1
  263. package/package.json +4 -2
  264. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +0 -217
  265. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +0 -926
  266. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +0 -1
  267. package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +0 -38
  268. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +0 -1361
  269. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +0 -46
  270. /package/compiler/{wasm_api.go → wasm-api.go} +0 -0
@@ -10,6 +10,7 @@ import {
10
10
  cloneStructValue,
11
11
  callGenericMethod,
12
12
  chanRecvWithOk,
13
+ fieldRef,
13
14
  functionValue,
14
15
  genericZero,
15
16
  goSlice,
@@ -28,6 +29,9 @@ import {
28
29
  namedFunction,
29
30
  namedValueInterfaceValue,
30
31
  newError,
32
+ ownedPointerAddress,
33
+ ownedPointerFromRef,
34
+ ownedPointerRef,
31
35
  pointerValue,
32
36
  print,
33
37
  println,
@@ -36,6 +40,7 @@ import {
36
40
  registerStructType,
37
41
  resetHostRuntimeForTests,
38
42
  selectStatement,
43
+ sliceFromOwnedPointer,
39
44
  sliceToArray,
40
45
  sliceHeaderRef,
41
46
  stringHeaderRef,
@@ -139,9 +144,12 @@ describe('builtin runtime contract helpers', () => {
139
144
  expect(uint(uint64And(0xf0n, 0x3cn), 32)).toBe(0x30)
140
145
  expect(uint(uint64Or(0xf0n, 0x0fn), 32)).toBe(0xff)
141
146
  expect(uint(uint64Xor(0xf0n, 0xffn), 32)).toBe(0x0f)
142
- expect(uint64And(uint('18446744073709551615', 64), uint('18014398509481983', 64))).toBe(
143
- 18014398509481983n,
144
- )
147
+ expect(
148
+ uint64And(
149
+ uint('18446744073709551615', 64),
150
+ uint('18014398509481983', 64),
151
+ ),
152
+ ).toBe(18014398509481983n)
145
153
  expect(uintShr(0x80000000, 31, 32)).toBe(1)
146
154
  expect(uintShr(0x80000000, 32, 32)).toBe(0)
147
155
  expect(uintShr(0xff, 4, 8)).toBe(15)
@@ -187,9 +195,9 @@ describe('builtin runtime contract helpers', () => {
187
195
  expect(bytesToUint8Array(pointerValue(namedPointerMethodBox))).toEqual(
188
196
  new Uint8Array([1, 2, 3]),
189
197
  )
190
- expect(bytesToUint8Array(goSlice(pointerValue(namedPointerMethodBox), 1))).toEqual(
191
- new Uint8Array([2, 3]),
192
- )
198
+ expect(
199
+ bytesToUint8Array(goSlice(pointerValue(namedPointerMethodBox), 1)),
200
+ ).toEqual(new Uint8Array([2, 3]))
193
201
  const namedStringBox = namedValueInterfaceValue('id', 'main.Name', {
194
202
  String: (receiver: string) => `name:${receiver}`,
195
203
  })
@@ -233,6 +241,31 @@ describe('builtin runtime contract helpers', () => {
233
241
  ])
234
242
  })
235
243
 
244
+ it('attaches owned pointer handles to variable and field refs', () => {
245
+ const local = varRef(1)
246
+ const localPointer = ownedPointerFromRef(local)
247
+ expect(localPointer).toBeDefined()
248
+ expect(ownedPointerRef(localPointer!)).toBe(local)
249
+ expect(ownedPointerAddress(localPointer!)).toBe(local.__goAddress!())
250
+ ownedPointerRef(localPointer!).value = 3
251
+ expect(local.value).toBe(3)
252
+ expect(() => sliceFromOwnedPointer(localPointer!, 1)).toThrow(
253
+ 'reflect.SliceAt requires a GoScript-owned pointer',
254
+ )
255
+
256
+ const target = { count: 2 }
257
+ const count = fieldRef(target, 'count')
258
+ const countPointer = ownedPointerFromRef(count)
259
+ expect(countPointer).toBeDefined()
260
+ ownedPointerRef(countPointer!).value = 4
261
+ expect(target.count).toBe(4)
262
+
263
+ const sameField = fieldRef(target, 'count')
264
+ expect(ownedPointerAddress(ownedPointerFromRef(sameField)!)).toBe(
265
+ ownedPointerAddress(countPointer!),
266
+ )
267
+ })
268
+
236
269
  it('matches struct map keys by Go comparable value', () => {
237
270
  class Key {
238
271
  public _fields: {
@@ -307,19 +340,16 @@ describe('builtin runtime contract helpers', () => {
307
340
  returns: [],
308
341
  },
309
342
  ])
310
- registerStructType(
311
- 'collision.Hash',
312
- new HashMessage(),
313
- [],
314
- HashMessage,
315
- {},
316
- )
343
+ registerStructType('collision.Hash', new HashMessage(), [], HashMessage, [])
317
344
 
318
345
  expect(typeAssertTuple(new HashInterfaceImpl(), 'collision.Hash')[1]).toBe(
319
346
  true,
320
347
  )
321
348
  expect(
322
- typeAssertTuple(markAsStructValue(new HashMessage()), 'collision.Hash')[1],
349
+ typeAssertTuple(
350
+ markAsStructValue(new HashMessage()),
351
+ 'collision.Hash',
352
+ )[1],
323
353
  ).toBe(true)
324
354
  })
325
355
 
@@ -426,7 +456,9 @@ describe('builtin runtime contract helpers', () => {
426
456
  sh.Data = strh.Data
427
457
  sh.Len = strh.Len
428
458
  sh.Cap = strh.Len
429
- expect(bytesToUint8Array(headerBytes.value)).toEqual(new Uint8Array([97, 98, 99]))
459
+ expect(bytesToUint8Array(headerBytes.value)).toEqual(
460
+ new Uint8Array([97, 98, 99]),
461
+ )
430
462
  })
431
463
 
432
464
  it('exposes stable synthetic slice index addresses', () => {
@@ -441,6 +473,27 @@ describe('builtin runtime contract helpers', () => {
441
473
  expect(indexAddress(other, 0)).not.toBe(indexAddress(left, 0))
442
474
  })
443
475
 
476
+ it('exposes owned pointer handles for addressable collection elements', () => {
477
+ const values = [1, 2, 3, 4]
478
+ const second = indexRef(values, 1)
479
+ const pointer = ownedPointerFromRef(second)
480
+
481
+ expect(pointer).toBeDefined()
482
+ expect(ownedPointerAddress(pointer!)).toBe(indexAddress(values, 1))
483
+ ownedPointerRef(pointer!).value = 8
484
+ expect(values).toEqual([1, 8, 3, 4])
485
+
486
+ const view = sliceFromOwnedPointer(pointer!, 2) as number[]
487
+ view[1] = 12
488
+ expect(values).toEqual([1, 8, 12, 4])
489
+
490
+ const bytes = new Uint8Array([5, 6, 7])
491
+ const bytePointer = ownedPointerFromRef(indexRef<number>(bytes, 1))
492
+ const byteView = sliceFromOwnedPointer(bytePointer!, 2) as Uint8Array
493
+ byteView[0] = 9
494
+ expect(Array.from(bytes)).toEqual([5, 9, 7])
495
+ })
496
+
444
497
  it('copies slices into fixed arrays with Go length checks', () => {
445
498
  const source = goSlice([1, 2, 3], 1, 3)
446
499
  const array = sliceToArray<number>(source, 2)
@@ -485,7 +538,11 @@ describe('builtin runtime contract helpers', () => {
485
538
  expect(typeAssert<Runner>(new Runner(), runnerInterface).ok).toBe(true)
486
539
  expect(typeAssert<Runner>(null, runnerInterface).ok).toBe(false)
487
540
 
488
- const emptyInterface = registerInterfaceType('phase5.EmptyInterface', null, [])
541
+ const emptyInterface = registerInterfaceType(
542
+ 'phase5.EmptyInterface',
543
+ null,
544
+ [],
545
+ )
489
546
  const fn = functionValue(() => 'ok', {
490
547
  kind: TypeKind.Function,
491
548
  params: [],
@@ -564,28 +621,40 @@ describe('builtin runtime contract helpers', () => {
564
621
  expect(bytesOk).toBe(true)
565
622
  expect(pointerValue(assertedBytesRef)).toBe(bytesRef.value)
566
623
 
624
+ const greetInfo = {
625
+ kind: TypeKind.Function,
626
+ name: 'phase5.Greet',
627
+ params: [{ kind: TypeKind.Basic, name: 'string' }],
628
+ results: [{ kind: TypeKind.Basic, name: 'string' }],
629
+ }
567
630
  const greet = namedFunction(
568
631
  (name: string) => `hello ${name}`,
569
632
  'phase5.Greet',
633
+ greetInfo,
570
634
  )
635
+ expect(typeAssert<typeof greet>(greet, greetInfo).ok).toBe(true)
571
636
  expect(
572
637
  typeAssert<typeof greet>(greet, {
573
638
  kind: TypeKind.Function,
574
639
  name: 'phase5.Greet',
640
+ params: [{ kind: TypeKind.Basic, name: 'int' }],
641
+ results: [{ kind: TypeKind.Basic, name: 'string' }],
575
642
  }).ok,
576
- ).toBe(true)
643
+ ).toBe(false)
577
644
  expect(
578
645
  typeAssert<{ Name: string }>(
579
646
  { Name: 'Alice' },
580
647
  {
581
648
  kind: TypeKind.Struct,
582
649
  methods: [],
583
- fields: {
584
- Name: {
650
+ fields: [
651
+ {
652
+ name: 'Name',
653
+ key: 'Name',
585
654
  type: { kind: TypeKind.Basic, name: 'string' },
586
655
  tag: 'json:"name"',
587
656
  },
588
- },
657
+ ],
589
658
  },
590
659
  ).ok,
591
660
  ).toBe(true)
@@ -596,6 +665,20 @@ describe('builtin runtime contract helpers', () => {
596
665
  })
597
666
  expect(literal(7)).toBe('7')
598
667
  expect(literal).toHaveProperty('__typeInfo')
668
+ expect(
669
+ typeAssert<typeof literal>(literal, {
670
+ kind: TypeKind.Function,
671
+ params: [{ kind: TypeKind.Basic, name: 'int' }],
672
+ results: [{ kind: TypeKind.Basic, name: 'string' }],
673
+ }).ok,
674
+ ).toBe(true)
675
+ expect(
676
+ typeAssert<(...args: unknown[]) => unknown>(() => undefined, {
677
+ kind: TypeKind.Function,
678
+ params: [],
679
+ results: [],
680
+ }).ok,
681
+ ).toBe(false)
599
682
 
600
683
  const genericArgs = {
601
684
  T: {
@@ -609,6 +692,118 @@ describe('builtin runtime contract helpers', () => {
609
692
  expect(callGenericMethod(genericArgs, 'T', 'String', 12)).toBe('12')
610
693
  })
611
694
 
695
+ it('compares anonymous descriptors inside function assertions', () => {
696
+ const acceptsAny = functionValue((value: unknown) => String(value), {
697
+ kind: TypeKind.Function,
698
+ name: 'main.AcceptsAny',
699
+ params: [{ kind: TypeKind.Interface, methods: [] }],
700
+ results: [{ kind: TypeKind.Basic, name: 'string' }],
701
+ })
702
+
703
+ expect(
704
+ typeAssert<typeof acceptsAny>(acceptsAny, {
705
+ kind: TypeKind.Function,
706
+ name: 'main.AcceptsAny',
707
+ params: [{ kind: TypeKind.Interface, methods: [] }],
708
+ results: [{ kind: TypeKind.Basic, name: 'string' }],
709
+ }).ok,
710
+ ).toBe(true)
711
+
712
+ const acceptsStruct = functionValue(
713
+ (value: { Name: string }) => value.Name,
714
+ {
715
+ kind: TypeKind.Function,
716
+ name: 'main.AcceptsStruct',
717
+ params: [
718
+ {
719
+ kind: TypeKind.Struct,
720
+ methods: [],
721
+ fields: [
722
+ {
723
+ name: 'Name',
724
+ type: { kind: TypeKind.Basic, name: 'string' },
725
+ tag: 'json:"name"',
726
+ },
727
+ ],
728
+ },
729
+ ],
730
+ results: [{ kind: TypeKind.Basic, name: 'string' }],
731
+ },
732
+ )
733
+
734
+ expect(
735
+ typeAssert<typeof acceptsStruct>(acceptsStruct, {
736
+ kind: TypeKind.Function,
737
+ name: 'main.AcceptsStruct',
738
+ params: [
739
+ {
740
+ kind: TypeKind.Struct,
741
+ methods: [],
742
+ fields: [
743
+ {
744
+ name: 'Name',
745
+ type: { kind: TypeKind.Basic, name: 'string' },
746
+ tag: 'json:"name"',
747
+ },
748
+ ],
749
+ },
750
+ ],
751
+ results: [{ kind: TypeKind.Basic, name: 'string' }],
752
+ }).ok,
753
+ ).toBe(true)
754
+ expect(
755
+ typeAssert<typeof acceptsStruct>(acceptsStruct, {
756
+ kind: TypeKind.Function,
757
+ name: 'main.AcceptsStruct',
758
+ params: [
759
+ {
760
+ kind: TypeKind.Struct,
761
+ methods: [],
762
+ fields: [
763
+ {
764
+ name: 'Name',
765
+ type: { kind: TypeKind.Basic, name: 'string' },
766
+ tag: 'json:"other"',
767
+ },
768
+ ],
769
+ },
770
+ ],
771
+ results: [{ kind: TypeKind.Basic, name: 'string' }],
772
+ }).ok,
773
+ ).toBe(false)
774
+
775
+ const acceptsAlias = functionValue((value: number) => value, {
776
+ kind: TypeKind.Function,
777
+ name: 'main.AcceptsAlias',
778
+ params: [{ kind: TypeKind.Basic, name: 'int', typeName: 'main.A' }],
779
+ results: [{ kind: TypeKind.Basic, name: 'int' }],
780
+ })
781
+ expect(
782
+ typeAssert<typeof acceptsAlias>(acceptsAlias, {
783
+ kind: TypeKind.Function,
784
+ name: 'main.AcceptsAlias',
785
+ params: [{ kind: TypeKind.Basic, name: 'int', typeName: 'main.A' }],
786
+ results: [{ kind: TypeKind.Basic, name: 'int' }],
787
+ }).ok,
788
+ ).toBe(true)
789
+ expect(
790
+ typeAssert<typeof acceptsAlias>(acceptsAlias, {
791
+ kind: TypeKind.Function,
792
+ name: 'main.AcceptsAlias',
793
+ params: [{ kind: TypeKind.Basic, name: 'int', typeName: 'main.B' }],
794
+ results: [{ kind: TypeKind.Basic, name: 'int' }],
795
+ }).ok,
796
+ ).toBe(false)
797
+ expect(
798
+ typeAssert<typeof acceptsAlias>(acceptsAlias, {
799
+ kind: TypeKind.Function,
800
+ name: 'main.AcceptsAlias',
801
+ params: [{ kind: TypeKind.Basic, name: 'int' }],
802
+ results: [{ kind: TypeKind.Basic, name: 'int' }],
803
+ }).ok,
804
+ ).toBe(false)
805
+ })
806
+
612
807
  it('exposes channel helpers used by future lowering', async () => {
613
808
  const channel = makeChannel<number>(1, 0, 'both')
614
809
  expect(cap(channel)).toBe(1)
@@ -674,7 +869,9 @@ describe('builtin runtime contract helpers', () => {
674
869
  await signal.send('value')
675
870
  const received = await Promise.race([
676
871
  signal.receive(),
677
- new Promise<string>((resolve) => setTimeout(() => resolve('timeout'), 20)),
872
+ new Promise<string>((resolve) =>
873
+ setTimeout(() => resolve('timeout'), 20),
874
+ ),
678
875
  ])
679
876
  expect(received).toBe('value')
680
877
  })
@@ -1,4 +1,10 @@
1
- import { isVarRef, varRef, type VarRef } from './varRef.js'
1
+ import {
2
+ isOwnedPointerHandle,
3
+ isVarRef,
4
+ varRef,
5
+ type OwnedPointerHandle,
6
+ type VarRef,
7
+ } from './varRef.js'
2
8
 
3
9
  export class GoBinaryString extends String {
4
10
  readonly bytes: Uint8Array
@@ -1291,7 +1297,7 @@ export function indexRef<T>(
1291
1297
  `runtime error: index out of range [${index}] with length ${collection.length}`,
1292
1298
  )
1293
1299
  }
1294
- return {
1300
+ const ref: VarRef<T> = {
1295
1301
  get value() {
1296
1302
  return collection[index] as T
1297
1303
  },
@@ -1303,6 +1309,8 @@ export function indexRef<T>(
1303
1309
  __goCollection: collection,
1304
1310
  __goIndex: index,
1305
1311
  }
1312
+ ref.__goPointer = collectionPointer(ref, collection, index)
1313
+ return ref
1306
1314
  }
1307
1315
  if (isComplexSlice(collection)) {
1308
1316
  if (index < 0 || index >= collection.__meta__.length) {
@@ -1311,7 +1319,7 @@ export function indexRef<T>(
1311
1319
  )
1312
1320
  }
1313
1321
  const backingIndex = collection.__meta__.offset + index
1314
- return {
1322
+ const ref: VarRef<T> = {
1315
1323
  get value() {
1316
1324
  return collection.__meta__.backing[backingIndex]
1317
1325
  },
@@ -1323,6 +1331,8 @@ export function indexRef<T>(
1323
1331
  __goCollection: collection,
1324
1332
  __goIndex: index,
1325
1333
  }
1334
+ ref.__goPointer = collectionPointer(ref, collection, index)
1335
+ return ref
1326
1336
  }
1327
1337
  if (Array.isArray(collection)) {
1328
1338
  if (index < 0 || index >= collection.length) {
@@ -1330,7 +1340,7 @@ export function indexRef<T>(
1330
1340
  `runtime error: index out of range [${index}] with length ${collection.length}`,
1331
1341
  )
1332
1342
  }
1333
- return {
1343
+ const ref: VarRef<T> = {
1334
1344
  get value() {
1335
1345
  return collection[index]
1336
1346
  },
@@ -1342,10 +1352,40 @@ export function indexRef<T>(
1342
1352
  __goCollection: collection,
1343
1353
  __goIndex: index,
1344
1354
  }
1355
+ ref.__goPointer = collectionPointer(ref, collection, index)
1356
+ return ref
1345
1357
  }
1346
1358
  throw new Error('runtime error: index on unsupported type')
1347
1359
  }
1348
1360
 
1361
+ function collectionPointer<T>(
1362
+ ref: VarRef<T>,
1363
+ collection: Slice<T> | T[] | Uint8Array,
1364
+ index: number,
1365
+ ): OwnedPointerHandle<T> {
1366
+ return {
1367
+ __goOwnedPointer: true,
1368
+ __goAddress: () => indexAddress(collection, index),
1369
+ __goRef: () => ref,
1370
+ __goSlice: (length: number) => {
1371
+ if (length < 0) {
1372
+ throw new Error('runtime error: unsafe slice length out of range')
1373
+ }
1374
+ return goSlice(collection as any, index, index + length, index + length)
1375
+ },
1376
+ }
1377
+ }
1378
+
1379
+ export function sliceFromOwnedPointer<T>(
1380
+ pointer: OwnedPointerHandle<T>,
1381
+ length: number,
1382
+ ): Slice<T> | Uint8Array {
1383
+ if (!isOwnedPointerHandle(pointer) || pointer.__goSlice === undefined) {
1384
+ throw new Error('reflect.SliceAt requires a GoScript-owned pointer')
1385
+ }
1386
+ return pointer.__goSlice(length) as Slice<T> | Uint8Array
1387
+ }
1388
+
1349
1389
  /**
1350
1390
  * arrayPointerFromIndexRef turns &slice[i] into a pointer to an N-element array
1351
1391
  * view. This models unsafe conversions such as (*[64]byte)(unsafe.Pointer(&b[0]))