goscript 0.1.0 → 0.1.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 (327) hide show
  1. package/README.md +267 -255
  2. package/cmd/goscript/cmd-test.go +193 -0
  3. package/cmd/goscript/cmd-test_test.go +76 -0
  4. package/cmd/goscript/main.go +1 -0
  5. package/compiler/build-flags.go +38 -0
  6. package/compiler/compile-request.go +2 -0
  7. package/compiler/compliance_test.go +0 -8
  8. package/compiler/gotest/owner.go +24 -0
  9. package/compiler/gotest/package-result.go +67 -0
  10. package/compiler/gotest/request.go +145 -0
  11. package/compiler/gotest/result.go +28 -0
  12. package/compiler/gotest/runner.go +588 -0
  13. package/compiler/gotest/runner_test.go +627 -0
  14. package/compiler/gotest/test.go +9 -0
  15. package/compiler/index.test.ts +1 -1
  16. package/compiler/lowered-program.go +71 -19
  17. package/compiler/lowering.go +5065 -569
  18. package/compiler/override-facts.go +307 -0
  19. package/compiler/override-registry.go +50 -189
  20. package/compiler/override-registry_test.go +47 -0
  21. package/compiler/package-graph.go +50 -27
  22. package/compiler/package-graph_test.go +37 -2
  23. package/compiler/package-test-function.go +9 -0
  24. package/compiler/package-test-graph-package.go +40 -0
  25. package/compiler/package-test-graph-variant.go +105 -0
  26. package/compiler/package-test-graph.go +117 -0
  27. package/compiler/package-test-graph_test.go +144 -0
  28. package/compiler/runtime-contract.go +189 -29
  29. package/compiler/runtime-contract_test.go +44 -30
  30. package/compiler/semantic-model-types.go +9 -6
  31. package/compiler/semantic-model.go +538 -38
  32. package/compiler/semantic-model_test.go +55 -0
  33. package/compiler/service.go +1 -1
  34. package/compiler/skeleton_test.go +679 -49
  35. package/compiler/tsworkspace/owner.go +334 -0
  36. package/compiler/tsworkspace/owner_test.go +93 -0
  37. package/compiler/tsworkspace/result.go +17 -0
  38. package/compiler/typescript-emitter.go +459 -82
  39. package/compiler/wasm/compile.go +1 -1
  40. package/compiler/wasm/compile_test.go +61 -11
  41. package/compiler/wasm_api.go +172 -7
  42. package/dist/gs/builtin/builtin.d.ts +20 -2
  43. package/dist/gs/builtin/builtin.js +194 -6
  44. package/dist/gs/builtin/builtin.js.map +1 -1
  45. package/dist/gs/builtin/channel.d.ts +8 -0
  46. package/dist/gs/builtin/channel.js +12 -0
  47. package/dist/gs/builtin/channel.js.map +1 -1
  48. package/dist/gs/builtin/slice.d.ts +22 -2
  49. package/dist/gs/builtin/slice.js +216 -44
  50. package/dist/gs/builtin/slice.js.map +1 -1
  51. package/dist/gs/builtin/type.d.ts +5 -2
  52. package/dist/gs/builtin/type.js +83 -24
  53. package/dist/gs/builtin/type.js.map +1 -1
  54. package/dist/gs/builtin/varRef.d.ts +5 -0
  55. package/dist/gs/builtin/varRef.js +23 -0
  56. package/dist/gs/builtin/varRef.js.map +1 -1
  57. package/dist/gs/bytes/buffer.gs.js +48 -44
  58. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  59. package/dist/gs/bytes/reader.gs.js +20 -18
  60. package/dist/gs/bytes/reader.gs.js.map +1 -1
  61. package/dist/gs/context/context.d.ts +5 -4
  62. package/dist/gs/context/context.js +10 -10
  63. package/dist/gs/context/context.js.map +1 -1
  64. package/dist/gs/crypto/internal/fips140deps/byteorder/index.d.ts +1 -0
  65. package/dist/gs/crypto/internal/fips140deps/byteorder/index.js +2 -0
  66. package/dist/gs/crypto/internal/fips140deps/byteorder/index.js.map +1 -0
  67. package/dist/gs/crypto/internal/fips140deps/godebug/index.d.ts +1 -0
  68. package/dist/gs/crypto/internal/fips140deps/godebug/index.js +2 -0
  69. package/dist/gs/crypto/internal/fips140deps/godebug/index.js.map +1 -0
  70. package/dist/gs/embed/index.d.ts +7 -0
  71. package/dist/gs/embed/index.js +16 -0
  72. package/dist/gs/embed/index.js.map +1 -0
  73. package/dist/gs/encoding/json/index.d.ts +1 -0
  74. package/dist/gs/encoding/json/index.js +18 -0
  75. package/dist/gs/encoding/json/index.js.map +1 -1
  76. package/dist/gs/errors/errors.d.ts +4 -0
  77. package/dist/gs/errors/errors.js +81 -0
  78. package/dist/gs/errors/errors.js.map +1 -1
  79. package/dist/gs/fmt/fmt.d.ts +4 -4
  80. package/dist/gs/fmt/fmt.js +42 -11
  81. package/dist/gs/fmt/fmt.js.map +1 -1
  82. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +35 -0
  83. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +211 -1
  84. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  85. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.d.ts +189 -0
  86. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +825 -0
  87. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -0
  88. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +163 -0
  89. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +449 -0
  90. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -0
  91. package/dist/gs/github.com/klauspost/compress/internal/le/index.d.ts +9 -0
  92. package/dist/gs/github.com/klauspost/compress/internal/le/index.js +71 -0
  93. package/dist/gs/github.com/klauspost/compress/internal/le/index.js.map +1 -0
  94. package/dist/gs/go/internal/scannerhooks/index.d.ts +3 -0
  95. package/dist/gs/go/internal/scannerhooks/index.js +5 -0
  96. package/dist/gs/go/internal/scannerhooks/index.js.map +1 -0
  97. package/dist/gs/go/scanner/index.d.ts +13 -0
  98. package/dist/gs/go/scanner/index.js +35 -0
  99. package/dist/gs/go/scanner/index.js.map +1 -1
  100. package/dist/gs/go/token/index.d.ts +156 -0
  101. package/dist/gs/go/token/index.js +500 -4
  102. package/dist/gs/go/token/index.js.map +1 -1
  103. package/dist/gs/internal/abi/index.d.ts +4 -0
  104. package/dist/gs/internal/abi/index.js +10 -0
  105. package/dist/gs/internal/abi/index.js.map +1 -1
  106. package/dist/gs/internal/bytealg/index.d.ts +2 -0
  107. package/dist/gs/internal/bytealg/index.js +14 -0
  108. package/dist/gs/internal/bytealg/index.js.map +1 -1
  109. package/dist/gs/internal/byteorder/index.d.ts +8 -2
  110. package/dist/gs/internal/byteorder/index.js +56 -25
  111. package/dist/gs/internal/byteorder/index.js.map +1 -1
  112. package/dist/gs/internal/godebug/index.d.ts +12 -0
  113. package/dist/gs/internal/godebug/index.js +30 -0
  114. package/dist/gs/internal/godebug/index.js.map +1 -0
  115. package/dist/gs/io/fs/index.d.ts +1 -0
  116. package/dist/gs/io/fs/index.js +1 -0
  117. package/dist/gs/io/fs/index.js.map +1 -1
  118. package/dist/gs/io/fs/readlink.d.ts +8 -0
  119. package/dist/gs/io/fs/readlink.js +64 -0
  120. package/dist/gs/io/fs/readlink.js.map +1 -0
  121. package/dist/gs/io/fs/walk.d.ts +3 -3
  122. package/dist/gs/io/fs/walk.js +7 -7
  123. package/dist/gs/io/fs/walk.js.map +1 -1
  124. package/dist/gs/io/io.d.ts +40 -6
  125. package/dist/gs/io/io.js +151 -26
  126. package/dist/gs/io/io.js.map +1 -1
  127. package/dist/gs/maps/iter.d.ts +3 -3
  128. package/dist/gs/maps/iter.js +3 -3
  129. package/dist/gs/maps/iter.js.map +1 -1
  130. package/dist/gs/maps/maps.d.ts +2 -2
  131. package/dist/gs/maps/maps.js +1 -1
  132. package/dist/gs/maps/maps.js.map +1 -1
  133. package/dist/gs/math/bits/index.d.ts +13 -4
  134. package/dist/gs/math/bits/index.js +66 -34
  135. package/dist/gs/math/bits/index.js.map +1 -1
  136. package/dist/gs/math/const.gs.d.ts +5 -5
  137. package/dist/gs/math/const.gs.js +4 -4
  138. package/dist/gs/math/const.gs.js.map +1 -1
  139. package/dist/gs/mime/index.d.ts +1 -0
  140. package/dist/gs/mime/index.js +50 -0
  141. package/dist/gs/mime/index.js.map +1 -0
  142. package/dist/gs/net/http/httptest/index.d.ts +11 -0
  143. package/dist/gs/net/http/httptest/index.js +21 -0
  144. package/dist/gs/net/http/httptest/index.js.map +1 -0
  145. package/dist/gs/net/http/index.d.ts +27 -0
  146. package/dist/gs/net/http/index.js +61 -0
  147. package/dist/gs/net/http/index.js.map +1 -0
  148. package/dist/gs/os/dir_unix.gs.js +2 -2
  149. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  150. package/dist/gs/os/types_js.gs.js.map +1 -1
  151. package/dist/gs/path/filepath/match.js +165 -3
  152. package/dist/gs/path/filepath/match.js.map +1 -1
  153. package/dist/gs/path/filepath/path.d.ts +3 -1
  154. package/dist/gs/path/filepath/path.js +133 -4
  155. package/dist/gs/path/filepath/path.js.map +1 -1
  156. package/dist/gs/path/path.d.ts +4 -1
  157. package/dist/gs/path/path.js +16 -4
  158. package/dist/gs/path/path.js.map +1 -1
  159. package/dist/gs/reflect/index.d.ts +1 -1
  160. package/dist/gs/reflect/index.js +1 -1
  161. package/dist/gs/reflect/index.js.map +1 -1
  162. package/dist/gs/reflect/map.js +3 -0
  163. package/dist/gs/reflect/map.js.map +1 -1
  164. package/dist/gs/reflect/type.d.ts +7 -4
  165. package/dist/gs/reflect/type.js +148 -7
  166. package/dist/gs/reflect/type.js.map +1 -1
  167. package/dist/gs/runtime/debug/index.d.ts +2 -0
  168. package/dist/gs/runtime/debug/index.js +8 -0
  169. package/dist/gs/runtime/debug/index.js.map +1 -0
  170. package/dist/gs/runtime/runtime.d.ts +35 -3
  171. package/dist/gs/runtime/runtime.js +72 -0
  172. package/dist/gs/runtime/runtime.js.map +1 -1
  173. package/dist/gs/slices/slices.d.ts +24 -5
  174. package/dist/gs/slices/slices.js +214 -5
  175. package/dist/gs/slices/slices.js.map +1 -1
  176. package/dist/gs/sort/slice.gs.d.ts +3 -3
  177. package/dist/gs/sort/slice.gs.js +6 -6
  178. package/dist/gs/sort/slice.gs.js.map +1 -1
  179. package/dist/gs/sort/sort.gs.d.ts +4 -4
  180. package/dist/gs/sort/sort.gs.js +11 -8
  181. package/dist/gs/sort/sort.gs.js.map +1 -1
  182. package/dist/gs/strings/builder.d.ts +1 -1
  183. package/dist/gs/strings/builder.js +3 -2
  184. package/dist/gs/strings/builder.js.map +1 -1
  185. package/dist/gs/sync/atomic/type.gs.d.ts +9 -8
  186. package/dist/gs/sync/atomic/type.gs.js +0 -2
  187. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  188. package/dist/gs/sync/sync.d.ts +2 -0
  189. package/dist/gs/sync/sync.js +27 -0
  190. package/dist/gs/sync/sync.js.map +1 -1
  191. package/dist/gs/syscall/constants.d.ts +36 -24
  192. package/dist/gs/syscall/constants.js +12 -0
  193. package/dist/gs/syscall/constants.js.map +1 -1
  194. package/dist/gs/syscall/errors.d.ts +2 -0
  195. package/dist/gs/syscall/errors.js +8 -0
  196. package/dist/gs/syscall/errors.js.map +1 -1
  197. package/dist/gs/syscall/fs.d.ts +43 -0
  198. package/dist/gs/syscall/fs.js +102 -0
  199. package/dist/gs/syscall/fs.js.map +1 -1
  200. package/dist/gs/syscall/js/index.d.ts +90 -0
  201. package/dist/gs/syscall/js/index.js +375 -0
  202. package/dist/gs/syscall/js/index.js.map +1 -0
  203. package/dist/gs/syscall/types.d.ts +22 -0
  204. package/dist/gs/syscall/types.js +45 -1
  205. package/dist/gs/syscall/types.js.map +1 -1
  206. package/dist/gs/testing/index.d.ts +1 -0
  207. package/dist/gs/testing/index.js +2 -0
  208. package/dist/gs/testing/index.js.map +1 -0
  209. package/dist/gs/testing/testing.d.ts +77 -0
  210. package/dist/gs/testing/testing.js +301 -0
  211. package/dist/gs/testing/testing.js.map +1 -0
  212. package/dist/gs/time/time.d.ts +41 -4
  213. package/dist/gs/time/time.js +205 -36
  214. package/dist/gs/time/time.js.map +1 -1
  215. package/dist/gs/unicode/unicode.d.ts +23 -1
  216. package/dist/gs/unicode/unicode.js +79 -10
  217. package/dist/gs/unicode/unicode.js.map +1 -1
  218. package/dist/gs/unicode/utf8/utf8.d.ts +4 -4
  219. package/dist/gs/unicode/utf8/utf8.js +24 -11
  220. package/dist/gs/unicode/utf8/utf8.js.map +1 -1
  221. package/dist/gs/unique/index.d.ts +11 -0
  222. package/dist/gs/unique/index.js +71 -0
  223. package/dist/gs/unique/index.js.map +1 -0
  224. package/go.sum +9 -0
  225. package/gs/builtin/builtin.ts +239 -8
  226. package/gs/builtin/channel.ts +22 -0
  227. package/gs/builtin/runtime-contract.test.ts +126 -0
  228. package/gs/builtin/slice.ts +259 -50
  229. package/gs/builtin/type.ts +109 -34
  230. package/gs/builtin/varRef.ts +38 -1
  231. package/gs/bytes/buffer.gs.ts +48 -44
  232. package/gs/bytes/meta.json +8 -3
  233. package/gs/bytes/reader.gs.ts +20 -19
  234. package/gs/context/context.test.ts +41 -0
  235. package/gs/context/context.ts +22 -26
  236. package/gs/crypto/internal/fips140deps/byteorder/index.ts +1 -0
  237. package/gs/crypto/internal/fips140deps/godebug/index.ts +1 -0
  238. package/gs/embed/index.ts +20 -0
  239. package/gs/embed/meta.json +5 -0
  240. package/gs/encoding/json/index.test.ts +15 -1
  241. package/gs/encoding/json/index.ts +24 -0
  242. package/gs/errors/errors.test.ts +82 -0
  243. package/gs/errors/errors.ts +104 -0
  244. package/gs/fmt/fmt.ts +56 -16
  245. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +73 -1
  246. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +297 -1
  247. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +159 -0
  248. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +1005 -0
  249. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +719 -0
  250. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +40 -0
  251. package/gs/github.com/klauspost/compress/internal/le/index.test.ts +36 -0
  252. package/gs/github.com/klauspost/compress/internal/le/index.ts +114 -0
  253. package/gs/go/internal/scannerhooks/index.test.ts +14 -0
  254. package/gs/go/internal/scannerhooks/index.ts +9 -0
  255. package/gs/go/scanner/index.test.ts +22 -0
  256. package/gs/go/scanner/index.ts +47 -0
  257. package/gs/go/token/index.test.ts +47 -1
  258. package/gs/go/token/index.ts +570 -4
  259. package/gs/internal/abi/index.test.ts +18 -0
  260. package/gs/internal/abi/index.ts +14 -0
  261. package/gs/internal/bytealg/index.test.ts +18 -0
  262. package/gs/internal/bytealg/index.ts +16 -0
  263. package/gs/internal/byteorder/index.test.ts +39 -0
  264. package/gs/internal/byteorder/index.ts +100 -27
  265. package/gs/internal/godebug/index.test.ts +16 -0
  266. package/gs/internal/godebug/index.ts +35 -0
  267. package/gs/io/fs/index.ts +1 -0
  268. package/gs/io/fs/meta.json +5 -0
  269. package/gs/io/fs/readlink.test.ts +43 -0
  270. package/gs/io/fs/readlink.ts +77 -0
  271. package/gs/io/fs/walk.test.ts +61 -0
  272. package/gs/io/fs/walk.ts +9 -9
  273. package/gs/io/io.ts +174 -31
  274. package/gs/io/meta.json +10 -2
  275. package/gs/maps/iter.ts +12 -6
  276. package/gs/maps/maps.ts +8 -6
  277. package/gs/math/bits/index.ts +103 -47
  278. package/gs/math/const.gs.test.ts +11 -5
  279. package/gs/math/const.gs.ts +5 -6
  280. package/gs/mime/index.ts +54 -0
  281. package/gs/net/http/httptest/index.ts +25 -0
  282. package/gs/net/http/index.test.ts +20 -0
  283. package/gs/net/http/index.ts +81 -0
  284. package/gs/os/dir_unix.gs.ts +2 -3
  285. package/gs/os/types_js.gs.ts +2 -2
  286. package/gs/path/filepath/match.test.ts +31 -12
  287. package/gs/path/filepath/match.ts +178 -3
  288. package/gs/path/filepath/path.test.ts +25 -0
  289. package/gs/path/filepath/path.ts +159 -5
  290. package/gs/path/path.ts +20 -5
  291. package/gs/reflect/index.ts +1 -0
  292. package/gs/reflect/map.test.ts +19 -0
  293. package/gs/reflect/map.ts +4 -0
  294. package/gs/reflect/type.ts +197 -17
  295. package/gs/runtime/debug/index.test.ts +24 -0
  296. package/gs/runtime/debug/index.ts +8 -0
  297. package/gs/runtime/runtime.test.ts +19 -0
  298. package/gs/runtime/runtime.ts +98 -3
  299. package/gs/slices/slices.test.ts +94 -0
  300. package/gs/slices/slices.ts +245 -5
  301. package/gs/sort/meta.json +7 -0
  302. package/gs/sort/slice.gs.ts +16 -7
  303. package/gs/sort/sort.gs.ts +16 -13
  304. package/gs/strings/builder.ts +4 -3
  305. package/gs/sync/atomic/type.gs.ts +13 -14
  306. package/gs/sync/meta.json +3 -1
  307. package/gs/sync/sync.test.ts +13 -1
  308. package/gs/sync/sync.ts +27 -0
  309. package/gs/syscall/constants.ts +39 -24
  310. package/gs/syscall/errors.ts +10 -0
  311. package/gs/syscall/fs.ts +195 -0
  312. package/gs/syscall/js/index.ts +458 -0
  313. package/gs/syscall/js/meta.json +4 -0
  314. package/gs/syscall/net.test.ts +85 -0
  315. package/gs/syscall/types.ts +56 -0
  316. package/gs/testing/index.ts +1 -0
  317. package/gs/testing/meta.json +5 -0
  318. package/gs/testing/testing.test.ts +90 -0
  319. package/gs/testing/testing.ts +382 -0
  320. package/gs/time/time.test.ts +106 -0
  321. package/gs/time/time.ts +278 -57
  322. package/gs/unicode/unicode.test.ts +25 -0
  323. package/gs/unicode/unicode.ts +119 -9
  324. package/gs/unicode/utf8/utf8.test.ts +13 -0
  325. package/gs/unicode/utf8/utf8.ts +28 -16
  326. package/gs/unique/index.ts +91 -0
  327. package/package.json +2 -1
@@ -35,7 +35,7 @@ export function panic(...args: any[]): never {
35
35
  * For maps, it deletes all entries.
36
36
  * @param v The slice or map to clear
37
37
  */
38
- export function clear<T>(v: T[] | Map<unknown, unknown> | null): void {
38
+ export function clear<T>(v: Slice<T> | Map<unknown, unknown> | null): void {
39
39
  if (v === null || v === undefined) {
40
40
  return
41
41
  }
@@ -43,12 +43,40 @@ export function clear<T>(v: T[] | Map<unknown, unknown> | null): void {
43
43
  v.clear()
44
44
  return
45
45
  }
46
+ if (v instanceof Uint8Array) {
47
+ v.fill(0)
48
+ return
49
+ }
50
+ if (isSliceProxy(v)) {
51
+ const zero = clearZeroValue(v)
52
+ for (let i = 0; i < v.length; i++) {
53
+ v[i] = zero
54
+ }
55
+ return
56
+ }
46
57
  if (Array.isArray(v)) {
47
- v.fill(null as T)
58
+ v.fill(clearZeroValue(v))
48
59
  return
49
60
  }
50
61
  }
51
62
 
63
+ function clearZeroValue<T>(v: T[]): T {
64
+ for (const item of v) {
65
+ if (item !== null && item !== undefined) {
66
+ switch (typeof item) {
67
+ case 'number':
68
+ return 0 as T
69
+ case 'string':
70
+ return '' as T
71
+ case 'boolean':
72
+ return false as T
73
+ }
74
+ break
75
+ }
76
+ }
77
+ return null as T
78
+ }
79
+
52
80
  /**
53
81
  * assignStruct copies all field values from source struct to target struct.
54
82
  * Used for pointer dereference assignment: *p = value
@@ -96,13 +124,137 @@ export function pointerValue<T>(value: T | VarRef<T> | null | undefined): T {
96
124
  return value
97
125
  }
98
126
 
127
+ export function arrayEqual(a: unknown, b: unknown): boolean {
128
+ return comparableEqual(a, b)
129
+ }
130
+
131
+ function comparableEqual(a: unknown, b: unknown): boolean {
132
+ if (a === b) {
133
+ return true
134
+ }
135
+ if (a === null || a === undefined || b === null || b === undefined) {
136
+ return false
137
+ }
138
+ if (isArrayLike(a) && isArrayLike(b)) {
139
+ if (a.length !== b.length) {
140
+ return false
141
+ }
142
+ for (let i = 0; i < a.length; i++) {
143
+ if (!comparableEqual(a[i], b[i])) {
144
+ return false
145
+ }
146
+ }
147
+ return true
148
+ }
149
+ if (hasGoType(a) || hasGoType(b)) {
150
+ if (!hasGoType(a) || !hasGoType(b) || a.__goType !== b.__goType) {
151
+ return false
152
+ }
153
+ if (a.__isTypedNil || b.__isTypedNil) {
154
+ return a.__isTypedNil === true && b.__isTypedNil === true
155
+ }
156
+ }
157
+ if (isStructValue(a) && isStructValue(b)) {
158
+ return fieldsEqual(a._fields, b._fields)
159
+ }
160
+ return false
161
+ }
162
+
163
+ function isArrayLike(value: unknown): value is ArrayLike<unknown> {
164
+ return Array.isArray(value) || value instanceof Uint8Array
165
+ }
166
+
167
+ function hasGoType(value: unknown): value is {
168
+ __goType: string
169
+ __isTypedNil?: boolean
170
+ } {
171
+ return (
172
+ typeof value === 'object' &&
173
+ value !== null &&
174
+ typeof (value as { __goType?: unknown }).__goType === 'string'
175
+ )
176
+ }
177
+
178
+ function isStructValue(value: unknown): value is {
179
+ _fields: Record<string, VarRef<unknown>>
180
+ } {
181
+ return (
182
+ typeof value === 'object' &&
183
+ value !== null &&
184
+ typeof (value as { _fields?: unknown })._fields === 'object' &&
185
+ (value as { _fields?: unknown })._fields !== null
186
+ )
187
+ }
188
+
189
+ function fieldsEqual(
190
+ a: Record<string, VarRef<unknown>>,
191
+ b: Record<string, VarRef<unknown>>,
192
+ ): boolean {
193
+ const aKeys = Object.keys(a)
194
+ const bKeys = Object.keys(b)
195
+ if (aKeys.length !== bKeys.length) {
196
+ return false
197
+ }
198
+ for (const key of aKeys) {
199
+ if (!(key in b) || !comparableEqual(a[key].value, b[key].value)) {
200
+ return false
201
+ }
202
+ }
203
+ return true
204
+ }
205
+
206
+ export interface Complex {
207
+ real: number
208
+ imag: number
209
+ }
210
+
211
+ export function complex(real: number, imag: number): Complex {
212
+ return { real, imag }
213
+ }
214
+
215
+ export function real(value: number | Complex | null | undefined): number {
216
+ if (typeof value === 'number') {
217
+ return value
218
+ }
219
+ return value?.real ?? 0
220
+ }
221
+
222
+ export function imag(value: number | Complex | null | undefined): number {
223
+ if (typeof value === 'number') {
224
+ return 0
225
+ }
226
+ return value?.imag ?? 0
227
+ }
228
+
99
229
  // Bytes represents all valid []byte representations in TypeScript
100
230
  // This includes Uint8Array (the preferred representation) and $.Slice<number> (which includes null)
101
231
  export type Bytes = Uint8Array | Slice<number>
102
232
 
103
233
  // int converts a value to a Go int type, handling proper signed integer conversion
104
234
  // This ensures that values like 2147483648 (2^31) are properly handled according to Go semantics
105
- export function int(value: number): number {
235
+ export function int(value: number | bigint, bits = 0): number {
236
+ if (typeof value === 'bigint') {
237
+ if (bits > 0 && bits <= 64) {
238
+ return Number(BigInt.asIntN(bits, value))
239
+ }
240
+ return Number(value)
241
+ }
242
+ if (bits > 0 && bits < 64) {
243
+ const modulo = 2 ** bits
244
+ const sign = 2 ** (bits - 1)
245
+ let truncated = Math.trunc(value)
246
+ if (!Number.isFinite(truncated)) {
247
+ return truncated
248
+ }
249
+ truncated %= modulo
250
+ if (truncated < 0) {
251
+ truncated += modulo
252
+ }
253
+ if (truncated >= sign) {
254
+ truncated -= modulo
255
+ }
256
+ return truncated
257
+ }
106
258
  // In Go, int is typically 64-bit on 64-bit systems, but for compatibility with JavaScript
107
259
  // we need to handle the conversion properly. The issue is that JavaScript's number type
108
260
  // can represent values larger than 32-bit signed integers, but when cast in certain contexts
@@ -115,6 +267,86 @@ export function int(value: number): number {
115
267
  return Math.trunc(value)
116
268
  }
117
269
 
270
+ // uint converts a value to an unsigned Go integer width.
271
+ export function uint(value: number | bigint, bits = 64): number {
272
+ if (typeof value === 'bigint') {
273
+ const normalized = BigInt.asUintN(Math.min(bits, 64), value)
274
+ if (bits >= 64) {
275
+ return normalized as unknown as number
276
+ }
277
+ return Number(normalized)
278
+ }
279
+ const modulo = bits >= 64 ? 2 ** 64 : 2 ** bits
280
+ let truncated = Math.trunc(value)
281
+ if (!Number.isFinite(truncated)) {
282
+ return truncated
283
+ }
284
+ truncated %= modulo
285
+ if (truncated < 0) {
286
+ truncated += modulo
287
+ }
288
+ return truncated
289
+ }
290
+
291
+ export function uint64Shl(value: number | bigint, shift: number | bigint): number {
292
+ return uint64Result(uint64Value(value) << BigInt(Math.trunc(Number(shift))))
293
+ }
294
+
295
+ export function uint64Shr(value: number | bigint, shift: number | bigint): number {
296
+ return uint64Result(uint64Value(value) >> BigInt(Math.trunc(Number(shift))))
297
+ }
298
+
299
+ export function uintShr(
300
+ value: number | bigint,
301
+ shift: number | bigint,
302
+ bits = 32,
303
+ ): number {
304
+ const width = Math.min(bits, 32)
305
+ const amount = Math.trunc(Number(shift))
306
+ if (amount < 0) {
307
+ throw new Error('runtime error: negative shift amount')
308
+ }
309
+ if (amount >= width) {
310
+ return 0
311
+ }
312
+ return uint(value, width) >>> amount
313
+ }
314
+
315
+ export function uint64Mul(left: number | bigint, right: number | bigint): number {
316
+ return uint64Result(uint64Value(left) * uint64Value(right))
317
+ }
318
+
319
+ export function uint64Add(left: number | bigint, right: number | bigint): number {
320
+ return uint64Result(uint64Value(left) + uint64Value(right))
321
+ }
322
+
323
+ export function uint64Sub(left: number | bigint, right: number | bigint): number {
324
+ return uint64Result(uint64Value(left) - uint64Value(right))
325
+ }
326
+
327
+ export function uint64And(left: number | bigint, right: number | bigint): number {
328
+ return uint64Result(uint64Value(left) & uint64Value(right))
329
+ }
330
+
331
+ export function uint64Or(left: number | bigint, right: number | bigint): number {
332
+ return uint64Result(uint64Value(left) | uint64Value(right))
333
+ }
334
+
335
+ export function uint64Xor(left: number | bigint, right: number | bigint): number {
336
+ return uint64Result(uint64Value(left) ^ uint64Value(right))
337
+ }
338
+
339
+ function uint64Value(value: number | bigint): bigint {
340
+ if (typeof value === 'bigint') {
341
+ return BigInt.asUintN(64, value)
342
+ }
343
+ return BigInt.asUintN(64, BigInt(Math.trunc(value)))
344
+ }
345
+
346
+ function uint64Result(value: bigint): number {
347
+ return BigInt.asUintN(64, value) as unknown as number
348
+ }
349
+
118
350
  /**
119
351
  * Normalizes various byte representations into a `Uint8Array` for protobuf compatibility.
120
352
  *
@@ -248,17 +480,16 @@ export function bytesToArray(bytes: Bytes | null): number[] {
248
480
  return Array.from(bytes)
249
481
  }
250
482
 
251
- if (Array.isArray(bytes)) {
252
- return bytes
253
- }
254
-
255
- // Handle SliceProxy
256
483
  if (isSliceProxy(bytes)) {
257
484
  const proxy = bytes as SliceProxy<number>
258
485
  const meta = proxy.__meta__
259
486
  return meta.backing.slice(meta.offset, meta.offset + meta.length)
260
487
  }
261
488
 
489
+ if (Array.isArray(bytes)) {
490
+ return bytes
491
+ }
492
+
262
493
  throw new Error(`Cannot convert bytes of type ${typeof bytes} to array`)
263
494
  }
264
495
 
@@ -77,6 +77,11 @@ export interface Channel<T> {
77
77
  * Used for non-blocking select operations.
78
78
  */
79
79
  canSendNonBlocking(): boolean
80
+
81
+ /**
82
+ * Reports the number of buffered values currently queued in the channel.
83
+ */
84
+ len(): number
80
85
  }
81
86
 
82
87
  /**
@@ -530,6 +535,10 @@ class BufferedChannel<T> implements Channel<T> {
530
535
  this.receiversWithOk.length > 0
531
536
  )
532
537
  }
538
+
539
+ len(): number {
540
+ return this.buffer.length
541
+ }
533
542
  }
534
543
 
535
544
  /**
@@ -555,6 +564,7 @@ export interface ChannelRef<T> {
555
564
  canReceiveNonBlocking(): boolean
556
565
  selectSend(value: T, id: number): Promise<SelectResult<boolean>>
557
566
  selectReceive(id: number): Promise<SelectResult<T>>
567
+ len(): number
558
568
  }
559
569
 
560
570
  /**
@@ -597,6 +607,10 @@ export class BidirectionalChannelRef<T> implements ChannelRef<T> {
597
607
  selectReceive(id: number): Promise<SelectResult<T>> {
598
608
  return this.channel.selectReceive(id)
599
609
  }
610
+
611
+ len(): number {
612
+ return this.channel.len()
613
+ }
600
614
  }
601
615
 
602
616
  /**
@@ -641,6 +655,10 @@ export class SendOnlyChannelRef<T> implements ChannelRef<T> {
641
655
  selectReceive(_id: number): Promise<SelectResult<T>> {
642
656
  throw new Error('Cannot receive from send-only channel')
643
657
  }
658
+
659
+ len(): number {
660
+ return this.channel.len()
661
+ }
644
662
  }
645
663
 
646
664
  /**
@@ -685,6 +703,10 @@ export class ReceiveOnlyChannelRef<T> implements ChannelRef<T> {
685
703
  selectSend(_value: T, _id: number): Promise<SelectResult<boolean>> {
686
704
  throw new Error('Cannot send to receive-only channel')
687
705
  }
706
+
707
+ len(): number {
708
+ return this.channel.len()
709
+ }
688
710
  }
689
711
 
690
712
  /**
@@ -1,13 +1,21 @@
1
1
  import { afterEach, describe, expect, it, vi } from 'vitest'
2
2
 
3
3
  import {
4
+ bytesToUint8Array,
4
5
  byte,
6
+ cap,
7
+ cloneStructValue,
5
8
  callGenericMethod,
6
9
  chanRecvWithOk,
7
10
  functionValue,
8
11
  genericZero,
12
+ goSlice,
9
13
  int,
14
+ indexAddress,
15
+ indexRef,
10
16
  interfaceValue,
17
+ len,
18
+ makeSlice,
11
19
  makeChannel,
12
20
  makeMap,
13
21
  mapGet,
@@ -18,13 +26,26 @@ import {
18
26
  pointerValue,
19
27
  print,
20
28
  println,
29
+ rangeString,
21
30
  registerInterfaceType,
22
31
  registerStructType,
23
32
  resetHostRuntimeForTests,
33
+ sliceToArray,
24
34
  TypeKind,
25
35
  typeAssert,
26
36
  typedNil,
37
+ uint,
38
+ uint64Add,
39
+ uint64And,
40
+ uint64Mul,
41
+ uint64Or,
42
+ uint64Shl,
43
+ uint64Shr,
44
+ uint64Sub,
45
+ uint64Xor,
46
+ uintShr,
27
47
  unref,
48
+ unsupportedPointerRef,
28
49
  varRef,
29
50
  } from './index.js'
30
51
 
@@ -90,14 +111,54 @@ describe('builtin runtime contract helpers', () => {
90
111
 
91
112
  it('exposes numeric, varref, map, and error helpers', () => {
92
113
  expect(int(1.9)).toBe(1)
114
+ expect(int(3n)).toBe(3)
115
+ expect(uint(-1n, 8)).toBe(255)
93
116
  expect(byte(257)).toBe(1)
117
+ expect(uint(uint64Shl(1n, 63), 32)).toBe(0)
118
+ expect(uint(uint64Shr(uint64Shl(1n, 63), 60), 32)).toBe(8)
119
+ expect(uint(uint64Mul(0xffffffffffffffffn, 3), 32)).toBe(0xfffffffd)
120
+ expect(uint(uint64Add(0xffffffffffffffffn, 2), 32)).toBe(1)
121
+ expect(uint(uint64Sub(1n, 2), 32)).toBe(0xffffffff)
122
+ expect(uint(uint64And(0xf0n, 0x3cn), 32)).toBe(0x30)
123
+ expect(uint(uint64Or(0xf0n, 0x0fn), 32)).toBe(0xff)
124
+ expect(uint(uint64Xor(0xf0n, 0xffn), 32)).toBe(0x0f)
125
+ expect(uintShr(0x80000000, 31, 32)).toBe(1)
126
+ expect(uintShr(0x80000000, 32, 32)).toBe(0)
127
+ expect(uintShr(0xff, 4, 8)).toBe(15)
94
128
 
95
129
  const value = varRef(4)
96
130
  value.value = 8
97
131
  expect(unref(value)).toBe(8)
98
132
  expect(pointerValue(value)).toBe(8)
133
+ const pointerAssert = typeAssert<typeof value>(value, {
134
+ kind: TypeKind.Pointer,
135
+ elemType: { kind: TypeKind.Basic, name: 'int' },
136
+ })
137
+ expect(pointerAssert).toEqual({ value, ok: true })
138
+ const nilNamedSlice = varRef(null)
139
+ const nilNamedSliceIface = interfaceValue(
140
+ nilNamedSlice,
141
+ '*main.ObjectIdentifier',
142
+ )
143
+ expect(
144
+ typeAssert<typeof nilNamedSlice>(nilNamedSliceIface, {
145
+ kind: TypeKind.Pointer,
146
+ elemType: 'main.ObjectIdentifier',
147
+ }),
148
+ ).toEqual({ value: nilNamedSlice, ok: true })
99
149
  expect(pointerValue({ ok: true })).toEqual({ ok: true })
150
+ expect(cloneStructValue({ clone: () => ({ ok: true }) })).toEqual({
151
+ ok: true,
152
+ })
153
+ expect(
154
+ cloneStructValue({ __goscriptClone: () => ({ internal: true }) }),
155
+ ).toEqual({ internal: true })
100
156
  expect(() => pointerValue(null)).toThrow('nil pointer dereference')
157
+ const unsupported = unsupportedPointerRef<number>(0)
158
+ expect(() => unsupported.value).toThrow('unsafe pointer dereference')
159
+ expect(() => {
160
+ unsupported.value = 1
161
+ }).toThrow('unsafe pointer dereference')
101
162
 
102
163
  const m = makeMap<string, number>()
103
164
  mapSet(m, 'answer', 42)
@@ -105,6 +166,69 @@ describe('builtin runtime contract helpers', () => {
105
166
  expect(mapGet(m, 'missing', 0)).toEqual([0, false])
106
167
 
107
168
  expect(newError('bad')?.Error()).toBe('bad')
169
+ expect(rangeString('a¢€')).toEqual([
170
+ [0, 97],
171
+ [1, 162],
172
+ [3, 8364],
173
+ ])
174
+ })
175
+
176
+ it('exposes addressable slice and array index references', () => {
177
+ const values = [1, 2, 3]
178
+ const second = indexRef(values, 1)
179
+ second.value = 8
180
+ expect(values).toEqual([1, 8, 3])
181
+ expect(pointerValue(second)).toBe(8)
182
+
183
+ const view = goSlice(values, 1, 3)
184
+ const firstInView = indexRef(view, 0)
185
+ firstInView.value = 11
186
+ expect(values).toEqual([1, 11, 3])
187
+ expect(Object.getOwnPropertyDescriptor(view, '0')?.value).toBe(11)
188
+
189
+ const bytes = new Uint8Array([4, 5])
190
+ const firstByte = indexRef<number>(bytes, 0)
191
+ firstByte.value = 9
192
+ expect(Array.from(bytes)).toEqual([9, 5])
193
+
194
+ const byteBacking = makeSlice<number>(8, undefined, 'byte')
195
+ const shortBytes = goSlice(byteBacking as Uint8Array, 0, 2)
196
+ expect(len(shortBytes)).toBe(2)
197
+ expect(cap(shortBytes)).toBe(8)
198
+ const fullBytes = goSlice(shortBytes, 0, 8)
199
+ fullBytes![7] = 12
200
+ expect((byteBacking as Uint8Array)[7]).toBe(12)
201
+
202
+ shortBytes![0] = 14
203
+ expect(bytesToUint8Array(shortBytes)).toEqual(new Uint8Array([14, 0]))
204
+ })
205
+
206
+ it('exposes stable synthetic slice index addresses', () => {
207
+ const values = [1, 2, 3, 4]
208
+ const left = goSlice(values, 1, 3)
209
+ const right = goSlice(values, 2, 4)
210
+ const other = [8, 9]
211
+
212
+ expect(indexAddress(left, 0)).toBe(indexAddress(values, 1))
213
+ expect(indexAddress(left, 1)).toBe(indexAddress(right, 0))
214
+ expect(indexAddress(left, 1)).toBeGreaterThan(indexAddress(left, 0))
215
+ expect(indexAddress(other, 0)).not.toBe(indexAddress(left, 0))
216
+ })
217
+
218
+ it('copies slices into fixed arrays with Go length checks', () => {
219
+ const source = goSlice([1, 2, 3], 1, 3)
220
+ const array = sliceToArray<number>(source, 2)
221
+ array[0] = 9
222
+
223
+ expect(array).toEqual([9, 3])
224
+ expect(source![0]).toBe(2)
225
+ expect(() => sliceToArray<number>(source, 3)).toThrow(
226
+ 'cannot convert slice with length 2 to array with length 3',
227
+ )
228
+
229
+ expect(sliceToArray<number>(new Uint8Array([4, 5, 6]), 2, 'byte')).toEqual(
230
+ new Uint8Array([4, 5]),
231
+ )
108
232
  })
109
233
 
110
234
  it('exposes value and type descriptor helpers', () => {
@@ -223,7 +347,9 @@ describe('builtin runtime contract helpers', () => {
223
347
  it('exposes channel helpers used by future lowering', async () => {
224
348
  const channel = makeChannel<number>(1, 0, 'both')
225
349
  await channel.send(7)
350
+ expect(len(channel)).toBe(1)
226
351
  expect(await chanRecvWithOk(channel)).toEqual({ value: 7, ok: true })
352
+ expect(len(channel)).toBe(0)
227
353
  channel.close()
228
354
  expect(await chanRecvWithOk(channel)).toEqual({ value: 0, ok: false })
229
355
  })