goscript 0.1.0 → 0.1.2

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 (495) hide show
  1. package/README.md +267 -255
  2. package/cmd/goscript/cmd-test.go +286 -0
  3. package/cmd/goscript/cmd-test_test.go +76 -0
  4. package/cmd/goscript/cmd_compile.go +9 -0
  5. package/cmd/goscript/main.go +1 -0
  6. package/compiler/build-flags.go +38 -0
  7. package/compiler/compile-request.go +33 -0
  8. package/compiler/compiler.go +1 -1
  9. package/compiler/compliance_test.go +0 -10
  10. package/compiler/config.go +2 -0
  11. package/compiler/gotest/owner.go +24 -0
  12. package/compiler/gotest/package-result.go +69 -0
  13. package/compiler/gotest/request.go +210 -0
  14. package/compiler/gotest/result.go +28 -0
  15. package/compiler/gotest/runner.go +1225 -0
  16. package/compiler/gotest/runner_test.go +1271 -0
  17. package/compiler/gotest/test.go +9 -0
  18. package/compiler/index.test.ts +1 -1
  19. package/compiler/lowered-program.go +80 -21
  20. package/compiler/lowering.go +6754 -602
  21. package/compiler/override-facts.go +357 -0
  22. package/compiler/override-registry.go +52 -190
  23. package/compiler/override-registry_test.go +182 -0
  24. package/compiler/package-graph.go +50 -27
  25. package/compiler/package-graph_test.go +99 -9
  26. package/compiler/package-test-function.go +9 -0
  27. package/compiler/package-test-graph-package.go +40 -0
  28. package/compiler/package-test-graph-variant.go +129 -0
  29. package/compiler/package-test-graph.go +112 -0
  30. package/compiler/package-test-graph_test.go +202 -0
  31. package/compiler/runtime-contract.go +229 -29
  32. package/compiler/runtime-contract_test.go +44 -30
  33. package/compiler/semantic-model-types.go +25 -6
  34. package/compiler/semantic-model.go +819 -74
  35. package/compiler/semantic-model_test.go +104 -0
  36. package/compiler/service.go +10 -4
  37. package/compiler/skeleton_test.go +2777 -524
  38. package/compiler/tsworkspace/owner-process-unix_test.go +72 -0
  39. package/compiler/tsworkspace/owner.go +342 -0
  40. package/compiler/tsworkspace/owner_test.go +93 -0
  41. package/compiler/tsworkspace/result.go +17 -0
  42. package/compiler/tsworkspace/tool-process-other.go +14 -0
  43. package/compiler/tsworkspace/tool-process-unix.go +19 -0
  44. package/compiler/typescript-emitter.go +576 -86
  45. package/compiler/wasm/compile.go +1 -1
  46. package/compiler/wasm/compile_test.go +61 -11
  47. package/compiler/wasm_api.go +172 -7
  48. package/dist/gs/builtin/builtin.d.ts +40 -3
  49. package/dist/gs/builtin/builtin.js +430 -22
  50. package/dist/gs/builtin/builtin.js.map +1 -1
  51. package/dist/gs/builtin/channel.d.ts +32 -10
  52. package/dist/gs/builtin/channel.js +119 -25
  53. package/dist/gs/builtin/channel.js.map +1 -1
  54. package/dist/gs/builtin/defer.d.ts +1 -0
  55. package/dist/gs/builtin/defer.js +12 -2
  56. package/dist/gs/builtin/defer.js.map +1 -1
  57. package/dist/gs/builtin/hostio.d.ts +9 -0
  58. package/dist/gs/builtin/hostio.js +25 -0
  59. package/dist/gs/builtin/hostio.js.map +1 -1
  60. package/dist/gs/builtin/map.js +40 -6
  61. package/dist/gs/builtin/map.js.map +1 -1
  62. package/dist/gs/builtin/print.js.map +1 -1
  63. package/dist/gs/builtin/slice.d.ts +64 -10
  64. package/dist/gs/builtin/slice.js +619 -244
  65. package/dist/gs/builtin/slice.js.map +1 -1
  66. package/dist/gs/builtin/type.d.ts +7 -2
  67. package/dist/gs/builtin/type.js +128 -29
  68. package/dist/gs/builtin/type.js.map +1 -1
  69. package/dist/gs/builtin/varRef.d.ts +7 -0
  70. package/dist/gs/builtin/varRef.js +23 -0
  71. package/dist/gs/builtin/varRef.js.map +1 -1
  72. package/dist/gs/bytes/buffer.gs.js +74 -70
  73. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  74. package/dist/gs/bytes/iter.gs.js +13 -13
  75. package/dist/gs/bytes/iter.gs.js.map +1 -1
  76. package/dist/gs/bytes/reader.gs.js +20 -18
  77. package/dist/gs/bytes/reader.gs.js.map +1 -1
  78. package/dist/gs/compress/zlib/index.d.ts +26 -0
  79. package/dist/gs/compress/zlib/index.js +168 -0
  80. package/dist/gs/compress/zlib/index.js.map +1 -0
  81. package/dist/gs/context/context.d.ts +6 -5
  82. package/dist/gs/context/context.js +17 -12
  83. package/dist/gs/context/context.js.map +1 -1
  84. package/dist/gs/crypto/ecdh/index.d.ts +52 -0
  85. package/dist/gs/crypto/ecdh/index.js +226 -0
  86. package/dist/gs/crypto/ecdh/index.js.map +1 -0
  87. package/dist/gs/crypto/ed25519/index.d.ts +34 -0
  88. package/dist/gs/crypto/ed25519/index.js +160 -0
  89. package/dist/gs/crypto/ed25519/index.js.map +1 -0
  90. package/dist/gs/crypto/internal/constanttime/index.d.ts +4 -0
  91. package/dist/gs/crypto/internal/constanttime/index.js +18 -0
  92. package/dist/gs/crypto/internal/constanttime/index.js.map +1 -0
  93. package/dist/gs/crypto/internal/fips140deps/byteorder/index.d.ts +1 -0
  94. package/dist/gs/crypto/internal/fips140deps/byteorder/index.js +2 -0
  95. package/dist/gs/crypto/internal/fips140deps/byteorder/index.js.map +1 -0
  96. package/dist/gs/crypto/internal/fips140deps/godebug/index.d.ts +1 -0
  97. package/dist/gs/crypto/internal/fips140deps/godebug/index.js +2 -0
  98. package/dist/gs/crypto/internal/fips140deps/godebug/index.js.map +1 -0
  99. package/dist/gs/crypto/rand/index.d.ts +2 -0
  100. package/dist/gs/crypto/rand/index.js +85 -0
  101. package/dist/gs/crypto/rand/index.js.map +1 -1
  102. package/dist/gs/crypto/sha256/index.d.ts +8 -0
  103. package/dist/gs/crypto/sha256/index.js +118 -0
  104. package/dist/gs/crypto/sha256/index.js.map +1 -0
  105. package/dist/gs/crypto/sha512/index.d.ts +14 -0
  106. package/dist/gs/crypto/sha512/index.js +129 -0
  107. package/dist/gs/crypto/sha512/index.js.map +1 -0
  108. package/dist/gs/embed/index.d.ts +7 -0
  109. package/dist/gs/embed/index.js +16 -0
  110. package/dist/gs/embed/index.js.map +1 -0
  111. package/dist/gs/encoding/json/index.d.ts +4 -0
  112. package/dist/gs/encoding/json/index.js +33 -0
  113. package/dist/gs/encoding/json/index.js.map +1 -1
  114. package/dist/gs/errors/errors.d.ts +4 -0
  115. package/dist/gs/errors/errors.js +108 -4
  116. package/dist/gs/errors/errors.js.map +1 -1
  117. package/dist/gs/fmt/fmt.d.ts +4 -4
  118. package/dist/gs/fmt/fmt.js +42 -11
  119. package/dist/gs/fmt/fmt.js.map +1 -1
  120. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +37 -2
  121. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +245 -1
  122. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  123. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.d.ts +189 -0
  124. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +861 -0
  125. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -0
  126. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +217 -0
  127. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +814 -0
  128. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -0
  129. package/dist/gs/github.com/aperturerobotics/util/conc/index.d.ts +20 -0
  130. package/dist/gs/github.com/aperturerobotics/util/conc/index.js +134 -0
  131. package/dist/gs/github.com/aperturerobotics/util/conc/index.js.map +1 -0
  132. package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
  133. package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.d.ts +3 -0
  134. package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js +50 -0
  135. package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js.map +1 -0
  136. package/dist/gs/github.com/klauspost/compress/internal/le/index.d.ts +9 -0
  137. package/dist/gs/github.com/klauspost/compress/internal/le/index.js +72 -0
  138. package/dist/gs/github.com/klauspost/compress/internal/le/index.js.map +1 -0
  139. package/dist/gs/github.com/mr-tron/base58/base58/index.d.ts +27 -0
  140. package/dist/gs/github.com/mr-tron/base58/base58/index.js +172 -0
  141. package/dist/gs/github.com/mr-tron/base58/base58/index.js.map +1 -0
  142. package/dist/gs/github.com/zeebo/blake3/internal/consts/index.d.ts +21 -0
  143. package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js +22 -0
  144. package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js.map +1 -0
  145. package/dist/gs/go/internal/scannerhooks/index.d.ts +3 -0
  146. package/dist/gs/go/internal/scannerhooks/index.js +5 -0
  147. package/dist/gs/go/internal/scannerhooks/index.js.map +1 -0
  148. package/dist/gs/go/scanner/index.d.ts +13 -0
  149. package/dist/gs/go/scanner/index.js +35 -0
  150. package/dist/gs/go/scanner/index.js.map +1 -1
  151. package/dist/gs/go/token/index.d.ts +156 -0
  152. package/dist/gs/go/token/index.js +507 -4
  153. package/dist/gs/go/token/index.js.map +1 -1
  154. package/dist/gs/hash/fnv/index.d.ts +57 -0
  155. package/dist/gs/hash/fnv/index.js +299 -0
  156. package/dist/gs/hash/fnv/index.js.map +1 -0
  157. package/dist/gs/hash/index.d.ts +17 -0
  158. package/dist/gs/hash/index.js +94 -0
  159. package/dist/gs/hash/index.js.map +1 -0
  160. package/dist/gs/internal/abi/index.d.ts +4 -0
  161. package/dist/gs/internal/abi/index.js +10 -0
  162. package/dist/gs/internal/abi/index.js.map +1 -1
  163. package/dist/gs/internal/bytealg/index.d.ts +2 -0
  164. package/dist/gs/internal/bytealg/index.js +14 -0
  165. package/dist/gs/internal/bytealg/index.js.map +1 -1
  166. package/dist/gs/internal/byteorder/index.d.ts +8 -2
  167. package/dist/gs/internal/byteorder/index.js +56 -25
  168. package/dist/gs/internal/byteorder/index.js.map +1 -1
  169. package/dist/gs/internal/godebug/index.d.ts +12 -0
  170. package/dist/gs/internal/godebug/index.js +30 -0
  171. package/dist/gs/internal/godebug/index.js.map +1 -0
  172. package/dist/gs/io/fs/index.d.ts +1 -0
  173. package/dist/gs/io/fs/index.js +1 -0
  174. package/dist/gs/io/fs/index.js.map +1 -1
  175. package/dist/gs/io/fs/readlink.d.ts +8 -0
  176. package/dist/gs/io/fs/readlink.js +60 -0
  177. package/dist/gs/io/fs/readlink.js.map +1 -0
  178. package/dist/gs/io/fs/walk.d.ts +3 -3
  179. package/dist/gs/io/fs/walk.js +7 -7
  180. package/dist/gs/io/fs/walk.js.map +1 -1
  181. package/dist/gs/io/io.d.ts +40 -6
  182. package/dist/gs/io/io.js +151 -26
  183. package/dist/gs/io/io.js.map +1 -1
  184. package/dist/gs/iter/iter.d.ts +3 -2
  185. package/dist/gs/iter/iter.js.map +1 -1
  186. package/dist/gs/maps/iter.d.ts +5 -5
  187. package/dist/gs/maps/iter.js +48 -21
  188. package/dist/gs/maps/iter.js.map +1 -1
  189. package/dist/gs/maps/maps.d.ts +6 -6
  190. package/dist/gs/maps/maps.js +1 -1
  191. package/dist/gs/maps/maps.js.map +1 -1
  192. package/dist/gs/math/bits/index.d.ts +13 -4
  193. package/dist/gs/math/bits/index.js +70 -48
  194. package/dist/gs/math/bits/index.js.map +1 -1
  195. package/dist/gs/math/const.gs.d.ts +5 -5
  196. package/dist/gs/math/const.gs.js +4 -4
  197. package/dist/gs/math/const.gs.js.map +1 -1
  198. package/dist/gs/mime/index.d.ts +1 -0
  199. package/dist/gs/mime/index.js +52 -0
  200. package/dist/gs/mime/index.js.map +1 -0
  201. package/dist/gs/net/http/httptest/index.d.ts +30 -0
  202. package/dist/gs/net/http/httptest/index.js +101 -0
  203. package/dist/gs/net/http/httptest/index.js.map +1 -0
  204. package/dist/gs/net/http/index.d.ts +131 -0
  205. package/dist/gs/net/http/index.js +307 -0
  206. package/dist/gs/net/http/index.js.map +1 -0
  207. package/dist/gs/net/http/pprof/index.d.ts +8 -0
  208. package/dist/gs/net/http/pprof/index.js +59 -0
  209. package/dist/gs/net/http/pprof/index.js.map +1 -0
  210. package/dist/gs/os/dir_unix.gs.js +2 -2
  211. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  212. package/dist/gs/os/error.gs.js +9 -7
  213. package/dist/gs/os/error.gs.js.map +1 -1
  214. package/dist/gs/os/types_js.gs.js +95 -15
  215. package/dist/gs/os/types_js.gs.js.map +1 -1
  216. package/dist/gs/path/filepath/match.js +165 -3
  217. package/dist/gs/path/filepath/match.js.map +1 -1
  218. package/dist/gs/path/filepath/path.d.ts +8 -4
  219. package/dist/gs/path/filepath/path.js +192 -8
  220. package/dist/gs/path/filepath/path.js.map +1 -1
  221. package/dist/gs/path/path.d.ts +4 -1
  222. package/dist/gs/path/path.js +16 -4
  223. package/dist/gs/path/path.js.map +1 -1
  224. package/dist/gs/reflect/index.d.ts +4 -3
  225. package/dist/gs/reflect/index.js +3 -2
  226. package/dist/gs/reflect/index.js.map +1 -1
  227. package/dist/gs/reflect/iter.js +2 -2
  228. package/dist/gs/reflect/iter.js.map +1 -1
  229. package/dist/gs/reflect/map.js +29 -0
  230. package/dist/gs/reflect/map.js.map +1 -1
  231. package/dist/gs/reflect/type.d.ts +31 -9
  232. package/dist/gs/reflect/type.js +536 -43
  233. package/dist/gs/reflect/type.js.map +1 -1
  234. package/dist/gs/reflect/types.d.ts +1 -0
  235. package/dist/gs/reflect/types.js +3 -1
  236. package/dist/gs/reflect/types.js.map +1 -1
  237. package/dist/gs/reflect/value.d.ts +4 -1
  238. package/dist/gs/reflect/value.js +39 -1
  239. package/dist/gs/reflect/value.js.map +1 -1
  240. package/dist/gs/reflect/visiblefields.js +1 -1
  241. package/dist/gs/reflect/visiblefields.js.map +1 -1
  242. package/dist/gs/runtime/debug/index.d.ts +41 -0
  243. package/dist/gs/runtime/debug/index.js +66 -0
  244. package/dist/gs/runtime/debug/index.js.map +1 -0
  245. package/dist/gs/runtime/pprof/index.d.ts +20 -0
  246. package/dist/gs/runtime/pprof/index.js +85 -0
  247. package/dist/gs/runtime/pprof/index.js.map +1 -0
  248. package/dist/gs/runtime/runtime.d.ts +35 -3
  249. package/dist/gs/runtime/runtime.js +72 -0
  250. package/dist/gs/runtime/runtime.js.map +1 -1
  251. package/dist/gs/runtime/trace/index.d.ts +19 -0
  252. package/dist/gs/runtime/trace/index.js +64 -0
  253. package/dist/gs/runtime/trace/index.js.map +1 -0
  254. package/dist/gs/slices/slices.d.ts +42 -8
  255. package/dist/gs/slices/slices.js +425 -11
  256. package/dist/gs/slices/slices.js.map +1 -1
  257. package/dist/gs/sort/slice.gs.d.ts +5 -3
  258. package/dist/gs/sort/slice.gs.js +60 -22
  259. package/dist/gs/sort/slice.gs.js.map +1 -1
  260. package/dist/gs/sort/sort.gs.d.ts +4 -4
  261. package/dist/gs/sort/sort.gs.js +11 -8
  262. package/dist/gs/sort/sort.gs.js.map +1 -1
  263. package/dist/gs/strings/builder.d.ts +1 -1
  264. package/dist/gs/strings/builder.js +29 -19
  265. package/dist/gs/strings/builder.js.map +1 -1
  266. package/dist/gs/strings/iter.js +140 -75
  267. package/dist/gs/strings/iter.js.map +1 -1
  268. package/dist/gs/strings/replace.js +2 -2
  269. package/dist/gs/strings/replace.js.map +1 -1
  270. package/dist/gs/strings/strings.js +52 -6
  271. package/dist/gs/strings/strings.js.map +1 -1
  272. package/dist/gs/sync/atomic/type.gs.d.ts +9 -8
  273. package/dist/gs/sync/atomic/type.gs.js +0 -2
  274. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  275. package/dist/gs/sync/sync.d.ts +8 -3
  276. package/dist/gs/sync/sync.js +66 -11
  277. package/dist/gs/sync/sync.js.map +1 -1
  278. package/dist/gs/syscall/constants.d.ts +36 -24
  279. package/dist/gs/syscall/constants.js +12 -0
  280. package/dist/gs/syscall/constants.js.map +1 -1
  281. package/dist/gs/syscall/errors.d.ts +117 -111
  282. package/dist/gs/syscall/errors.js +45 -0
  283. package/dist/gs/syscall/errors.js.map +1 -1
  284. package/dist/gs/syscall/fs.d.ts +37 -0
  285. package/dist/gs/syscall/fs.js +102 -0
  286. package/dist/gs/syscall/fs.js.map +1 -1
  287. package/dist/gs/syscall/js/index.d.ts +90 -0
  288. package/dist/gs/syscall/js/index.js +383 -0
  289. package/dist/gs/syscall/js/index.js.map +1 -0
  290. package/dist/gs/syscall/types.d.ts +26 -1
  291. package/dist/gs/syscall/types.js +45 -1
  292. package/dist/gs/syscall/types.js.map +1 -1
  293. package/dist/gs/testing/index.d.ts +1 -0
  294. package/dist/gs/testing/index.js +2 -0
  295. package/dist/gs/testing/index.js.map +1 -0
  296. package/dist/gs/testing/testing.d.ts +78 -0
  297. package/dist/gs/testing/testing.js +318 -0
  298. package/dist/gs/testing/testing.js.map +1 -0
  299. package/dist/gs/time/time.d.ts +41 -4
  300. package/dist/gs/time/time.js +227 -36
  301. package/dist/gs/time/time.js.map +1 -1
  302. package/dist/gs/unicode/unicode.d.ts +23 -1
  303. package/dist/gs/unicode/unicode.js +79 -10
  304. package/dist/gs/unicode/unicode.js.map +1 -1
  305. package/dist/gs/unicode/utf8/utf8.d.ts +4 -4
  306. package/dist/gs/unicode/utf8/utf8.js +24 -11
  307. package/dist/gs/unicode/utf8/utf8.js.map +1 -1
  308. package/dist/gs/unique/index.d.ts +11 -0
  309. package/dist/gs/unique/index.js +76 -0
  310. package/dist/gs/unique/index.js.map +1 -0
  311. package/go.mod +8 -8
  312. package/go.sum +14 -14
  313. package/gs/builtin/builtin.ts +585 -27
  314. package/gs/builtin/channel.ts +183 -29
  315. package/gs/builtin/defer.ts +13 -2
  316. package/gs/builtin/hostio.test.ts +1 -0
  317. package/gs/builtin/hostio.ts +38 -0
  318. package/gs/builtin/map.ts +46 -6
  319. package/gs/builtin/print.ts +12 -3
  320. package/gs/builtin/runtime-contract.test.ts +383 -10
  321. package/gs/builtin/slice.test.ts +70 -0
  322. package/gs/builtin/slice.ts +785 -265
  323. package/gs/builtin/type.ts +160 -41
  324. package/gs/builtin/varRef.ts +40 -1
  325. package/gs/bytes/buffer.gs.ts +74 -70
  326. package/gs/bytes/iter.gs.ts +13 -14
  327. package/gs/bytes/meta.json +8 -3
  328. package/gs/bytes/reader.gs.ts +20 -19
  329. package/gs/compress/zlib/index.test.ts +28 -0
  330. package/gs/compress/zlib/index.ts +200 -0
  331. package/gs/compress/zlib/meta.json +3 -0
  332. package/gs/context/context.test.ts +71 -0
  333. package/gs/context/context.ts +30 -29
  334. package/gs/crypto/ecdh/index.test.ts +43 -0
  335. package/gs/crypto/ecdh/index.ts +274 -0
  336. package/gs/crypto/ed25519/index.test.ts +41 -0
  337. package/gs/crypto/ed25519/index.ts +238 -0
  338. package/gs/crypto/ed25519/meta.json +13 -0
  339. package/gs/crypto/internal/constanttime/index.test.ts +25 -0
  340. package/gs/crypto/internal/constanttime/index.ts +22 -0
  341. package/gs/crypto/internal/fips140deps/byteorder/index.ts +1 -0
  342. package/gs/crypto/internal/fips140deps/godebug/index.ts +1 -0
  343. package/gs/crypto/rand/index.test.ts +89 -1
  344. package/gs/crypto/rand/index.ts +103 -1
  345. package/gs/crypto/rand/meta.json +4 -1
  346. package/gs/crypto/sha256/index.test.ts +78 -0
  347. package/gs/crypto/sha256/index.ts +150 -0
  348. package/gs/crypto/sha256/meta.json +9 -0
  349. package/gs/crypto/sha512/index.test.ts +31 -0
  350. package/gs/crypto/sha512/index.ts +161 -0
  351. package/gs/crypto/sha512/meta.json +11 -0
  352. package/gs/embed/index.ts +20 -0
  353. package/gs/embed/meta.json +5 -0
  354. package/gs/encoding/json/index.test.ts +39 -3
  355. package/gs/encoding/json/index.ts +45 -3
  356. package/gs/errors/errors.test.ts +85 -0
  357. package/gs/errors/errors.ts +132 -4
  358. package/gs/fmt/fmt.test.ts +3 -1
  359. package/gs/fmt/fmt.ts +55 -19
  360. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +128 -1
  361. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +342 -4
  362. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +180 -0
  363. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +1084 -0
  364. package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +31 -0
  365. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +1233 -0
  366. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +46 -0
  367. package/gs/github.com/aperturerobotics/util/conc/index.test.ts +30 -0
  368. package/gs/github.com/aperturerobotics/util/conc/index.ts +172 -0
  369. package/gs/github.com/aperturerobotics/util/conc/meta.json +9 -0
  370. package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.ts +1 -4
  371. package/gs/github.com/hack-pad/safejs/internal/catch/index.test.ts +35 -0
  372. package/gs/github.com/hack-pad/safejs/internal/catch/index.ts +65 -0
  373. package/gs/github.com/hack-pad/safejs/internal/catch/meta.json +9 -0
  374. package/gs/github.com/klauspost/compress/internal/le/index.test.ts +37 -0
  375. package/gs/github.com/klauspost/compress/internal/le/index.ts +115 -0
  376. package/gs/github.com/mr-tron/base58/base58/index.test.ts +70 -0
  377. package/gs/github.com/mr-tron/base58/base58/index.ts +231 -0
  378. package/gs/github.com/mr-tron/base58/base58/meta.json +3 -0
  379. package/gs/github.com/zeebo/blake3/internal/consts/index.test.ts +46 -0
  380. package/gs/github.com/zeebo/blake3/internal/consts/index.ts +26 -0
  381. package/gs/go/internal/scannerhooks/index.test.ts +14 -0
  382. package/gs/go/internal/scannerhooks/index.ts +9 -0
  383. package/gs/go/scanner/index.test.ts +22 -0
  384. package/gs/go/scanner/index.ts +47 -0
  385. package/gs/go/token/index.test.ts +47 -1
  386. package/gs/go/token/index.ts +583 -4
  387. package/gs/hash/fnv/index.test.ts +67 -0
  388. package/gs/hash/fnv/index.ts +351 -0
  389. package/gs/hash/fnv/meta.json +3 -0
  390. package/gs/hash/index.test.ts +37 -0
  391. package/gs/hash/index.ts +118 -0
  392. package/gs/hash/meta.json +5 -0
  393. package/gs/internal/abi/index.test.ts +18 -0
  394. package/gs/internal/abi/index.ts +14 -0
  395. package/gs/internal/bytealg/index.test.ts +18 -0
  396. package/gs/internal/bytealg/index.ts +16 -0
  397. package/gs/internal/byteorder/index.test.ts +39 -0
  398. package/gs/internal/byteorder/index.ts +100 -27
  399. package/gs/internal/godebug/index.test.ts +16 -0
  400. package/gs/internal/godebug/index.ts +35 -0
  401. package/gs/io/fs/index.ts +1 -0
  402. package/gs/io/fs/meta.json +5 -0
  403. package/gs/io/fs/readlink.test.ts +43 -0
  404. package/gs/io/fs/readlink.ts +69 -0
  405. package/gs/io/fs/walk.test.ts +61 -0
  406. package/gs/io/fs/walk.ts +17 -9
  407. package/gs/io/io.ts +177 -31
  408. package/gs/io/meta.json +10 -2
  409. package/gs/iter/iter.ts +8 -2
  410. package/gs/maps/iter.ts +75 -26
  411. package/gs/maps/maps.test.ts +23 -0
  412. package/gs/maps/maps.ts +13 -11
  413. package/gs/math/bits/index.test.ts +20 -0
  414. package/gs/math/bits/index.ts +107 -64
  415. package/gs/math/const.gs.test.ts +11 -5
  416. package/gs/math/const.gs.ts +5 -6
  417. package/gs/mime/index.ts +60 -0
  418. package/gs/net/http/httptest/index.test.ts +53 -0
  419. package/gs/net/http/httptest/index.ts +120 -0
  420. package/gs/net/http/index.test.ts +148 -0
  421. package/gs/net/http/index.ts +432 -0
  422. package/gs/net/http/meta.json +6 -0
  423. package/gs/net/http/pprof/index.test.ts +47 -0
  424. package/gs/net/http/pprof/index.ts +65 -0
  425. package/gs/os/dir_unix.gs.ts +2 -3
  426. package/gs/os/error.gs.ts +9 -10
  427. package/gs/os/error.test.ts +41 -0
  428. package/gs/os/file_unix_js.test.ts +55 -0
  429. package/gs/os/tempfile.gs.test.ts +37 -10
  430. package/gs/os/types_js.gs.ts +96 -17
  431. package/gs/path/filepath/match.test.ts +31 -12
  432. package/gs/path/filepath/match.ts +181 -3
  433. package/gs/path/filepath/meta.json +6 -0
  434. package/gs/path/filepath/path.test.ts +80 -0
  435. package/gs/path/filepath/path.ts +244 -11
  436. package/gs/path/path.ts +20 -5
  437. package/gs/reflect/field.test.ts +63 -0
  438. package/gs/reflect/index.ts +5 -1
  439. package/gs/reflect/iter.ts +2 -2
  440. package/gs/reflect/map.test.ts +42 -1
  441. package/gs/reflect/map.ts +39 -0
  442. package/gs/reflect/type.ts +728 -65
  443. package/gs/reflect/typefor.test.ts +100 -0
  444. package/gs/reflect/types.ts +3 -1
  445. package/gs/reflect/value.ts +50 -1
  446. package/gs/reflect/visiblefields.ts +1 -1
  447. package/gs/runtime/debug/index.test.ts +45 -0
  448. package/gs/runtime/debug/index.ts +96 -0
  449. package/gs/runtime/pprof/index.test.ts +36 -0
  450. package/gs/runtime/pprof/index.ts +104 -0
  451. package/gs/runtime/pprof/meta.json +6 -0
  452. package/gs/runtime/runtime.test.ts +19 -0
  453. package/gs/runtime/runtime.ts +98 -3
  454. package/gs/runtime/trace/index.test.ts +45 -0
  455. package/gs/runtime/trace/index.ts +97 -0
  456. package/gs/runtime/trace/meta.json +7 -0
  457. package/gs/slices/meta.json +2 -1
  458. package/gs/slices/slices.test.ts +180 -0
  459. package/gs/slices/slices.ts +502 -15
  460. package/gs/sort/meta.json +7 -0
  461. package/gs/sort/slice.gs.ts +85 -26
  462. package/gs/sort/slice.test.ts +40 -0
  463. package/gs/sort/sort.gs.ts +16 -13
  464. package/gs/strings/builder.test.ts +8 -0
  465. package/gs/strings/builder.ts +33 -20
  466. package/gs/strings/iter.test.ts +5 -7
  467. package/gs/strings/iter.ts +146 -71
  468. package/gs/strings/replace.test.ts +1 -4
  469. package/gs/strings/replace.ts +6 -6
  470. package/gs/strings/strings.test.ts +4 -0
  471. package/gs/strings/strings.ts +54 -6
  472. package/gs/sync/atomic/type.gs.ts +13 -14
  473. package/gs/sync/meta.json +3 -1
  474. package/gs/sync/sync.test.ts +69 -1
  475. package/gs/sync/sync.ts +72 -13
  476. package/gs/syscall/constants.ts +39 -24
  477. package/gs/syscall/errors.ts +165 -112
  478. package/gs/syscall/fs.ts +195 -0
  479. package/gs/syscall/js/index.ts +485 -0
  480. package/gs/syscall/js/meta.json +4 -0
  481. package/gs/syscall/net.test.ts +111 -0
  482. package/gs/syscall/types.ts +63 -2
  483. package/gs/testing/index.ts +1 -0
  484. package/gs/testing/meta.json +5 -0
  485. package/gs/testing/testing.test.ts +146 -0
  486. package/gs/testing/testing.ts +399 -0
  487. package/gs/time/meta.json +2 -2
  488. package/gs/time/time.test.ts +110 -0
  489. package/gs/time/time.ts +309 -57
  490. package/gs/unicode/unicode.test.ts +36 -0
  491. package/gs/unicode/unicode.ts +115 -9
  492. package/gs/unicode/utf8/utf8.test.ts +13 -0
  493. package/gs/unicode/utf8/utf8.ts +28 -16
  494. package/gs/unique/index.ts +98 -0
  495. package/package.json +3 -2
@@ -1,3 +1,61 @@
1
+ import { isVarRef, varRef, type VarRef } from './varRef.js'
2
+
3
+ export class GoBinaryString extends String {
4
+ readonly bytes: Uint8Array
5
+
6
+ constructor(bytes: Uint8Array) {
7
+ super(bytesToBinaryString(bytes))
8
+ this.bytes = bytes.slice()
9
+ }
10
+
11
+ toString(): string {
12
+ return bytesToBinaryString(this.bytes)
13
+ }
14
+
15
+ valueOf(): string {
16
+ return this.toString()
17
+ }
18
+
19
+ [Symbol.toPrimitive](): string {
20
+ return this.toString()
21
+ }
22
+ }
23
+
24
+ type GoStringValue = string | GoBinaryString
25
+ type GoStringBytes = GoStringValue | Slice<number> | Uint8Array
26
+
27
+ function isGoStringValue(value: unknown): value is GoStringValue {
28
+ return typeof value === 'string' || value instanceof GoBinaryString
29
+ }
30
+
31
+ function goStringBytes(str: GoStringValue): Uint8Array {
32
+ if (str instanceof GoBinaryString) {
33
+ return str.bytes.slice()
34
+ }
35
+ return new TextEncoder().encode(str)
36
+ }
37
+
38
+ function goStringComparableBytes(value: GoStringBytes): Uint8Array {
39
+ if (isGoStringValue(value)) {
40
+ return goStringBytes(value)
41
+ }
42
+ if (value instanceof Uint8Array) {
43
+ return value
44
+ }
45
+ if (value === null || value === undefined) {
46
+ return new Uint8Array(0)
47
+ }
48
+ return Uint8Array.from(asArray(value))
49
+ }
50
+
51
+ function goStringFromBytes(bytes: Uint8Array): string {
52
+ try {
53
+ return new TextDecoder('utf-8', { fatal: true }).decode(bytes)
54
+ } catch {
55
+ return new GoBinaryString(bytes) as unknown as string
56
+ }
57
+ }
58
+
1
59
  /**
2
60
  * GoSliceObject contains metadata for complex slice views
3
61
  */
@@ -6,8 +64,13 @@ interface GoSliceObject<T> {
6
64
  offset: number // Offset into the backing array
7
65
  length: number // Length of the slice
8
66
  capacity: number // Capacity of the slice
67
+ target?: T[] // Materialized proxy target for JS array operations
9
68
  }
10
69
 
70
+ const addressStride = 0x100000000
71
+ let nextAddressBase = 1
72
+ const addressBases = new WeakMap<object, number>()
73
+
11
74
  /**
12
75
  * SliceProxy is a proxy object for complex slices
13
76
  */
@@ -15,6 +78,25 @@ export type SliceProxy<T> = T[] & {
15
78
  __meta__: GoSliceObject<T>
16
79
  }
17
80
 
81
+ type ByteSlice = Uint8Array & {
82
+ __meta__?: GoSliceObject<number>
83
+ }
84
+
85
+ function sliceIndexProperty(prop: string | symbol): number {
86
+ if (typeof prop !== 'string' || prop.length === 0) {
87
+ return -1
88
+ }
89
+ let index = 0
90
+ for (let i = 0; i < prop.length; i++) {
91
+ const digit = prop.charCodeAt(i) - 48
92
+ if (digit < 0 || digit > 9) {
93
+ return -1
94
+ }
95
+ index = index * 10 + digit
96
+ }
97
+ return index
98
+ }
99
+
18
100
  /**
19
101
  * Slice<T> is a union type that is either a plain array or a proxy
20
102
  * null represents the nil state.
@@ -32,39 +114,41 @@ export type Slice<T> =
32
114
  * and route it through the backing array.
33
115
  */
34
116
  function wrapSliceProxy<T>(proxy: SliceProxy<T>): SliceProxy<T> {
117
+ const meta = proxy.__meta__
118
+ meta.target = proxy
35
119
  const handler = {
36
120
  get(target: any, prop: string | symbol): any {
37
- if (typeof prop === 'string' && /^\d+$/.test(prop)) {
38
- const index = Number(prop)
39
- if (index >= 0 && index < target.__meta__.length) {
40
- return target.__meta__.backing[target.__meta__.offset + index]
121
+ const index = sliceIndexProperty(prop)
122
+ if (index >= 0) {
123
+ if (index < meta.length) {
124
+ return meta.backing[meta.offset + index]
41
125
  }
42
126
  throw new Error(
43
- `Slice index out of range: ${index} >= ${target.__meta__.length}`,
127
+ `Slice index out of range: ${index} >= ${meta.length}`,
44
128
  )
45
129
  }
46
130
 
47
131
  if (prop === 'length') {
48
- return target.__meta__.length
132
+ return meta.length
49
133
  }
50
134
 
51
135
  if (prop === '__meta__') {
52
- return target.__meta__
136
+ return meta
53
137
  }
54
138
 
55
139
  return Reflect.get(target, prop)
56
140
  },
57
141
 
58
142
  set(target: any, prop: string | symbol, value: any): boolean {
59
- if (typeof prop === 'string' && /^\d+$/.test(prop)) {
60
- const index = Number(prop)
61
- if (index >= 0 && index < target.__meta__.length) {
62
- target.__meta__.backing[target.__meta__.offset + index] = value
143
+ const index = sliceIndexProperty(prop)
144
+ if (index >= 0) {
145
+ if (index < meta.length) {
146
+ meta.backing[meta.offset + index] = value
63
147
  target[index] = value // Also update the proxy target for consistency
64
148
  return true
65
149
  }
66
150
  throw new Error(
67
- `Slice index out of range: ${index} >= ${target.__meta__.length}`,
151
+ `Slice index out of range: ${index} >= ${meta.length}`,
68
152
  )
69
153
  }
70
154
 
@@ -79,6 +163,24 @@ function wrapSliceProxy<T>(proxy: SliceProxy<T>): SliceProxy<T> {
79
163
  return new Proxy(proxy, handler) as SliceProxy<T>
80
164
  }
81
165
 
166
+ function sliceProxyFromBacking<T>(
167
+ backing: T[],
168
+ offset: number,
169
+ length: number,
170
+ capacity: number,
171
+ target?: T[],
172
+ ): SliceProxy<T> {
173
+ const proxyTargetArray = (target ?? new Array<T>(length)) as SliceProxy<T>
174
+ proxyTargetArray.length = length
175
+ if (target === undefined) {
176
+ for (let i = 0; i < length; i++) {
177
+ proxyTargetArray[i] = backing[offset + i]
178
+ }
179
+ }
180
+ proxyTargetArray.__meta__ = { backing, offset, length, capacity }
181
+ return wrapSliceProxy(proxyTargetArray)
182
+ }
183
+
82
184
  // asArray converts a slice to a JavaScript array.
83
185
  export function asArray<T>(slice: Slice<T>): T[] {
84
186
  if (slice === null || slice === undefined) {
@@ -104,6 +206,48 @@ export function asArray<T>(slice: Slice<T>): T[] {
104
206
  return []
105
207
  }
106
208
 
209
+ export function sliceToArray<T>(
210
+ slice: Slice<T> | Uint8Array,
211
+ length: number,
212
+ typeHint?: string,
213
+ ): T[] | Uint8Array {
214
+ if (len(slice) < length) {
215
+ throw new Error(
216
+ `runtime error: cannot convert slice with length ${len(slice)} to array with length ${length}`,
217
+ )
218
+ }
219
+ if (typeHint === 'byte') {
220
+ return new Uint8Array(
221
+ asArray(slice as Slice<T>).slice(0, length) as number[],
222
+ )
223
+ }
224
+ return asArray(slice as Slice<T>).slice(0, length)
225
+ }
226
+
227
+ export function sliceToArrayPointer<T>(
228
+ slice: Slice<T> | Uint8Array,
229
+ length: number,
230
+ typeHint?: string,
231
+ ): VarRef<T[] | Uint8Array> {
232
+ if (len(slice) < length) {
233
+ throw new Error(
234
+ `runtime error: cannot convert slice with length ${len(slice)} to array pointer with length ${length}`,
235
+ )
236
+ }
237
+ if (typeHint === 'byte') {
238
+ if (slice instanceof Uint8Array) {
239
+ return varRef(goSlice(slice, 0, length) as unknown as Uint8Array)
240
+ }
241
+ return varRef(
242
+ goSlice(slice as Slice<T>, 0, length) as unknown as Uint8Array,
243
+ )
244
+ }
245
+ if (slice instanceof Uint8Array) {
246
+ return varRef(goSlice(slice, 0, length) as unknown as T[])
247
+ }
248
+ return varRef(goSlice(slice, 0, length) as T[])
249
+ }
250
+
107
251
  /**
108
252
  * isComplexSlice checks if a slice is a complex slice (has __meta__ property)
109
253
  */
@@ -117,6 +261,35 @@ function isComplexSlice<T>(slice: Slice<T>): slice is SliceProxy<T> {
117
261
  )
118
262
  }
119
263
 
264
+ function normalizeSliceIndex(value: number | undefined): number | undefined {
265
+ if (value === undefined) {
266
+ return undefined
267
+ }
268
+ return Number(value)
269
+ }
270
+
271
+ function byteSliceMeta(slice: Uint8Array): GoSliceObject<number> | undefined {
272
+ return (slice as ByteSlice).__meta__
273
+ }
274
+
275
+ function byteSliceView(
276
+ backing: Uint8Array,
277
+ offset: number,
278
+ length: number,
279
+ capacity: number,
280
+ ): Uint8Array {
281
+ const view = backing.subarray(offset, offset + length) as ByteSlice
282
+ if (capacity !== length) {
283
+ view.__meta__ = {
284
+ backing: backing as unknown as number[],
285
+ offset,
286
+ length,
287
+ capacity,
288
+ }
289
+ }
290
+ return view
291
+ }
292
+
120
293
  /**
121
294
  * isSliceProxy checks if a slice is a SliceProxy (has __meta__ property)
122
295
  * This is an alias for isComplexSlice for better type hinting
@@ -135,6 +308,7 @@ export const makeSlice = <T>(
135
308
  length: number,
136
309
  capacity?: number,
137
310
  typeHint?: string,
311
+ zeroFactory?: () => T,
138
312
  ): Slice<T> => {
139
313
  if (typeHint === 'byte') {
140
314
  const actualCapacity = capacity === undefined ? length : capacity
@@ -149,24 +323,7 @@ export const makeSlice = <T>(
149
323
  return new Uint8Array(length) as Slice<T>
150
324
  }
151
325
 
152
- // If capacity > length, create a SliceProxy backed by a Uint8Array
153
- const backingUint8 = new Uint8Array(actualCapacity)
154
- const backingNumbers = Array.from(backingUint8) as T[] // Convert to number[] for backing
155
-
156
- const proxyTargetArray = new Array<T>(length)
157
- for (let i = 0; i < length; i++) {
158
- proxyTargetArray[i] = 0 as T // Initialize with zeros
159
- }
160
-
161
- const proxy = proxyTargetArray as SliceProxy<T>
162
- proxy.__meta__ = {
163
- backing: backingNumbers,
164
- offset: 0,
165
- length: length,
166
- capacity: actualCapacity,
167
- }
168
-
169
- return wrapSliceProxy(proxy) as Slice<T>
326
+ return byteSliceView(new Uint8Array(actualCapacity), 0, length, actualCapacity) as Slice<T>
170
327
  }
171
328
 
172
329
  const actualCapacity = capacity === undefined ? length : capacity
@@ -176,28 +333,28 @@ export const makeSlice = <T>(
176
333
  )
177
334
  }
178
335
 
179
- let zeroVal: any
180
- switch (typeHint) {
181
- case 'number':
182
- zeroVal = 0
183
- break
184
- case 'boolean':
185
- zeroVal = false
186
- break
187
- case 'string':
188
- zeroVal = ''
189
- break
190
- default:
191
- zeroVal = null // Default for objects, complex types, or unspecified
336
+ const zeroValue = (): T => {
337
+ if (zeroFactory !== undefined) {
338
+ return zeroFactory()
339
+ }
340
+ switch (typeHint) {
341
+ case 'number':
342
+ return 0 as T
343
+ case 'boolean':
344
+ return false as T
345
+ case 'string':
346
+ return '' as T
347
+ default:
348
+ return null as T // Default for objects, complex types, or unspecified
349
+ }
192
350
  }
193
351
 
194
352
  const backingArr = new Array<T>(actualCapacity)
195
- // Initialize the relevant part of the backing array
196
- for (let i = 0; i < length; i++) {
197
- backingArr[i] = zeroVal
353
+ // Go zero-initializes the whole backing array. Elements beyond len become
354
+ // observable when a slice is resliced up to cap.
355
+ for (let i = 0; i < actualCapacity; i++) {
356
+ backingArr[i] = zeroValue()
198
357
  }
199
- // The rest of backingArr (from length to actualCapacity-1) remains uninitialized (undefined),
200
- // representing available capacity.
201
358
 
202
359
  // OPTIMIZATION: If length equals capacity, return backing array directly
203
360
  if (length === actualCapacity) {
@@ -208,7 +365,7 @@ export const makeSlice = <T>(
208
365
  // Its elements up to 'length' should reflect the initialized part of the slice.
209
366
  const proxyTargetArray = new Array<T>(length)
210
367
  for (let i = 0; i < length; i++) {
211
- proxyTargetArray[i] = backingArr[i] // Or simply zeroVal
368
+ proxyTargetArray[i] = backingArr[i]
212
369
  }
213
370
 
214
371
  const proxy = proxyTargetArray as SliceProxy<T>
@@ -222,9 +379,9 @@ export const makeSlice = <T>(
222
379
  // Create a proper Proxy with the handler for SliceProxy behavior
223
380
  const handler = {
224
381
  get(target: any, prop: string | symbol): any {
225
- if (typeof prop === 'string' && /^\d+$/.test(prop)) {
226
- const index = Number(prop)
227
- if (index >= 0 && index < target.__meta__.length) {
382
+ const index = sliceIndexProperty(prop)
383
+ if (index >= 0) {
384
+ if (index < target.__meta__.length) {
228
385
  return target.__meta__.backing[target.__meta__.offset + index]
229
386
  }
230
387
  throw new Error(
@@ -244,9 +401,9 @@ export const makeSlice = <T>(
244
401
  },
245
402
 
246
403
  set(target: any, prop: string | symbol, value: any): boolean {
247
- if (typeof prop === 'string' && /^\d+$/.test(prop)) {
248
- const index = Number(prop)
249
- if (index >= 0 && index < target.__meta__.length) {
404
+ const index = sliceIndexProperty(prop)
405
+ if (index >= 0) {
406
+ if (index < target.__meta__.length) {
250
407
  target.__meta__.backing[target.__meta__.offset + index] = value
251
408
  target[index] = value // Also update the proxy target for consistency
252
409
  return true
@@ -296,11 +453,16 @@ export function goSlice<T>( // T can be number for Uint8Array case
296
453
  high?: number,
297
454
  max?: number,
298
455
  ): Slice<T> {
456
+ s = collectionValue(s) as Slice<T> | Uint8Array
457
+ low = normalizeSliceIndex(low)
458
+ high = normalizeSliceIndex(high)
459
+ max = normalizeSliceIndex(max)
460
+
299
461
  const handler = {
300
462
  get(target: any, prop: string | symbol): any {
301
- if (typeof prop === 'string' && /^\d+$/.test(prop)) {
302
- const index = Number(prop)
303
- if (index >= 0 && index < target.__meta__.length) {
463
+ const index = sliceIndexProperty(prop)
464
+ if (index >= 0) {
465
+ if (index < target.__meta__.length) {
304
466
  return target.__meta__.backing[target.__meta__.offset + index]
305
467
  }
306
468
  throw new Error(
@@ -335,10 +497,11 @@ export function goSlice<T>( // T can be number for Uint8Array case
335
497
  },
336
498
 
337
499
  set(target: any, prop: string | symbol, value: any): boolean {
338
- if (typeof prop === 'string' && /^\d+$/.test(prop)) {
339
- const index = Number(prop)
340
- if (index >= 0 && index < target.__meta__.length) {
500
+ const index = sliceIndexProperty(prop)
501
+ if (index >= 0) {
502
+ if (index < target.__meta__.length) {
341
503
  target.__meta__.backing[target.__meta__.offset + index] = value
504
+ target[index] = value
342
505
  return true
343
506
  }
344
507
  if (
@@ -346,6 +509,7 @@ export function goSlice<T>( // T can be number for Uint8Array case
346
509
  target.__meta__.length < target.__meta__.capacity
347
510
  ) {
348
511
  target.__meta__.backing[target.__meta__.offset + index] = value
512
+ target[index] = value
349
513
  target.__meta__.length++
350
514
  return true
351
515
  }
@@ -363,54 +527,51 @@ export function goSlice<T>( // T can be number for Uint8Array case
363
527
  }
364
528
 
365
529
  if (s instanceof Uint8Array) {
530
+ const meta = byteSliceMeta(s)
531
+ const metaBacking = meta?.backing as unknown
532
+ const backing =
533
+ metaBacking instanceof Uint8Array ? metaBacking : s
534
+ const baseOffset = meta?.offset ?? 0
535
+ const baseCapacity = meta?.capacity ?? s.length
366
536
  const actualLow = low ?? 0
367
537
  const actualHigh = high ?? s.length
368
538
 
369
- if (actualLow < 0 || actualHigh < actualLow || actualHigh > s.length) {
539
+ if (
540
+ actualLow < 0 ||
541
+ actualHigh < actualLow ||
542
+ actualLow > baseCapacity ||
543
+ actualHigh > baseCapacity
544
+ ) {
370
545
  throw new Error(
371
- `Invalid slice indices: low ${actualLow}, high ${actualHigh} for Uint8Array of length ${s.length}`,
546
+ `Invalid slice indices: low ${actualLow}, high ${actualHigh} for Uint8Array with capacity ${baseCapacity}`,
372
547
  )
373
548
  }
374
549
 
375
- const subArrayView = s.subarray(actualLow, actualHigh) // This is Uint8Array
550
+ const newLength = actualHigh - actualLow
376
551
 
377
552
  if (max !== undefined) {
378
- if (max < actualHigh || max > s.length) {
553
+ if (max < actualHigh || max > baseCapacity) {
379
554
  // max is relative to the original s.length (capacity)
380
555
  throw new Error(
381
- `Invalid max index: ${max}. Constraints: low ${actualLow} <= high ${actualHigh} <= max <= original_length ${s.length}`,
556
+ `Invalid max index: ${max}. Constraints: low ${actualLow} <= high ${actualHigh} <= max <= capacity ${baseCapacity}`,
382
557
  )
383
558
  }
384
559
 
385
- const newLength = subArrayView.length // actualHigh - actualLow
386
560
  const newCap = max - actualLow // Capacity of the new slice view
387
-
388
- if (newCap !== newLength) {
389
- // Capacity is different from length, so return SliceProxy<number>
390
- // The original s was Uint8Array, so T is effectively 'number' for this path.
391
- const backingNumbers = Array.from(subArrayView) // Convert Uint8Array data to number[]
392
-
393
- const proxyTarget = {
394
- __meta__: {
395
- backing: backingNumbers, // number[]
396
- offset: 0, // Offset is 0 because backingNumbers is a direct copy
397
- length: newLength,
398
- capacity: newCap,
399
- },
400
- }
401
- // Explicitly cast to Slice<T> after ensuring T is number for this branch.
402
- return new Proxy(
403
- proxyTarget,
404
- handler,
405
- ) as unknown as SliceProxy<number> as Slice<T>
406
- } else {
407
- // newCap === newLength, standard Uint8Array is fine.
408
- return subArrayView as Slice<T> // T is number
409
- }
410
- } else {
411
- // max is not defined, return the Uint8Array subarray view directly.
412
- return subArrayView as Slice<T> // T is number
561
+ return byteSliceView(
562
+ backing,
563
+ baseOffset + actualLow,
564
+ newLength,
565
+ newCap,
566
+ ) as Slice<T>
413
567
  }
568
+
569
+ return byteSliceView(
570
+ backing,
571
+ baseOffset + actualLow,
572
+ newLength,
573
+ baseCapacity - actualLow,
574
+ ) as Slice<T>
414
575
  }
415
576
 
416
577
  // Handle nil slices - in Go, slicing a nil slice with valid bounds returns nil
@@ -501,7 +662,7 @@ export function goSlice<T>( // T can be number for Uint8Array case
501
662
  const newOffset = oldOffset + low
502
663
 
503
664
  // OPTIMIZATION: If the result would have offset=0 and length=capacity, return backing directly
504
- if (newOffset === 0 && newLength === newCap) {
665
+ if (newOffset === 0 && newLength === newCap && backing.length === newLength) {
505
666
  return backing as Slice<T>
506
667
  }
507
668
 
@@ -555,9 +716,9 @@ export const arrayToSlice = <T>(
555
716
 
556
717
  const handler = {
557
718
  get(target: any, prop: string | symbol): any {
558
- if (typeof prop === 'string' && /^\d+$/.test(prop)) {
559
- const index = Number(prop)
560
- if (index >= 0 && index < target.__meta__.length) {
719
+ const index = sliceIndexProperty(prop)
720
+ if (index >= 0) {
721
+ if (index < target.__meta__.length) {
561
722
  return target.__meta__.backing[target.__meta__.offset + index]
562
723
  }
563
724
  throw new Error(
@@ -592,9 +753,9 @@ export const arrayToSlice = <T>(
592
753
  },
593
754
 
594
755
  set(target: any, prop: string | symbol, value: any): boolean {
595
- if (typeof prop === 'string' && /^\d+$/.test(prop)) {
596
- const index = Number(prop)
597
- if (index >= 0 && index < target.__meta__.length) {
756
+ const index = sliceIndexProperty(prop)
757
+ if (index >= 0) {
758
+ if (index < target.__meta__.length) {
598
759
  target.__meta__.backing[target.__meta__.offset + index] = value
599
760
  return true
600
761
  }
@@ -639,37 +800,51 @@ export const arrayToSlice = <T>(
639
800
  */
640
801
  export const len = <T = unknown, V = unknown>(
641
802
  obj:
642
- | string
803
+ | GoStringValue
643
804
  | Array<T>
644
805
  | Slice<T>
645
806
  | Map<T, V>
646
807
  | Set<T>
647
808
  | Uint8Array
809
+ | { len(): number }
648
810
  | null
649
811
  | undefined,
650
812
  ): number => {
813
+ obj = collectionValue(obj) as typeof obj
651
814
  if (obj === null || obj === undefined) {
652
815
  return 0
653
816
  }
654
817
 
655
818
  if (typeof obj === 'string') {
656
- return stringLen(obj) // Call new stringLen for strings
819
+ return stringLen(obj)
820
+ }
821
+
822
+ if (obj instanceof Uint8Array) {
823
+ return obj.length
824
+ }
825
+
826
+ if (Array.isArray(obj)) {
827
+ const meta = (obj as unknown as SliceProxy<T>).__meta__
828
+ if (meta !== undefined) {
829
+ return meta.length
830
+ }
831
+ return obj.length
657
832
  }
658
833
 
659
834
  if (obj instanceof Map || obj instanceof Set) {
660
835
  return obj.size
661
836
  }
662
837
 
663
- if (obj instanceof Uint8Array) {
664
- return obj.length
838
+ if (obj instanceof GoBinaryString) {
839
+ return stringLen(obj)
665
840
  }
666
841
 
667
- if (isComplexSlice(obj)) {
668
- return obj.__meta__.length
842
+ if (isComplexSlice(obj as any)) {
843
+ return (obj as unknown as SliceProxy<T>).__meta__.length
669
844
  }
670
845
 
671
- if (Array.isArray(obj)) {
672
- return obj.length
846
+ if (typeof (obj as any).len === 'function') {
847
+ return (obj as { len(): number }).len()
673
848
  }
674
849
 
675
850
  throw new Error('cannot determine len of this type')
@@ -680,23 +855,30 @@ export const len = <T = unknown, V = unknown>(
680
855
  * @param obj The slice.
681
856
  * @returns The capacity of the slice.
682
857
  */
683
- export const cap = <T>(obj: Slice<T> | Uint8Array): number => {
858
+ export const cap = <T>(
859
+ obj: Slice<T> | Uint8Array | { cap(): number } | null | undefined,
860
+ ): number => {
861
+ obj = collectionValue(obj) as typeof obj
684
862
  if (obj === null || obj === undefined) {
685
863
  return 0
686
864
  }
687
865
 
688
- if (obj instanceof Uint8Array) {
689
- return obj.length // Uint8Array capacity is its length
866
+ if (isComplexSlice(obj as any)) {
867
+ return (obj as SliceProxy<T>).__meta__.capacity
690
868
  }
691
869
 
692
- if (isComplexSlice(obj)) {
693
- return obj.__meta__.capacity
870
+ if (obj instanceof Uint8Array) {
871
+ return obj.length // Uint8Array capacity is its length
694
872
  }
695
873
 
696
874
  if (Array.isArray(obj)) {
697
875
  return obj.length
698
876
  }
699
877
 
878
+ if (typeof (obj as any).cap === 'function') {
879
+ return (obj as { cap(): number }).cap()
880
+ }
881
+
700
882
  return 0
701
883
  }
702
884
 
@@ -711,6 +893,7 @@ export const cap = <T>(obj: Slice<T> | Uint8Array): number => {
711
893
  export function append(slice: Uint8Array, ...elements: any[]): Uint8Array
712
894
  // Overload for null slice with number elements - returns number slice (Bytes compatible)
713
895
  export function append(slice: null, ...elements: number[]): Slice<number>
896
+ export function append<T>(slice: null, ...elements: T[]): Slice<T>
714
897
  export function append<T>(slice: Slice<T>, ...elements: any[]): Slice<T>
715
898
  export function append<T>(
716
899
  slice: Slice<T> | Uint8Array | null,
@@ -719,59 +902,11 @@ export function append<T>(
719
902
  // 1. Flatten all elements from the varargs `...elements` into `varargsElements`.
720
903
  // Determine if the result should be a Uint8Array.
721
904
  const inputIsUint8Array = slice instanceof Uint8Array
722
- const appendingUint8Array = elements.some((el) => el instanceof Uint8Array)
723
- const produceUint8Array =
724
- inputIsUint8Array ||
725
- appendingUint8Array ||
726
- (slice === null && appendingUint8Array)
905
+ const produceUint8Array = inputIsUint8Array
727
906
 
728
907
  // If producing Uint8Array, all elements must be numbers and potentially flattened from other Uint8Arrays/number slices.
729
908
  if (produceUint8Array) {
730
- let combinedBytes: number[] = []
731
- // Add bytes from the original slice if it exists and is numeric.
732
- if (inputIsUint8Array) {
733
- combinedBytes.push(...Array.from(slice as Uint8Array))
734
- } else if (slice !== null && slice !== undefined) {
735
- // Original was Slice<number> or number[]
736
- const sliceLen = len(slice)
737
- for (let i = 0; i < sliceLen; i++) {
738
- const val = (slice as any)[i]
739
- if (typeof val !== 'number') {
740
- throw new Error(
741
- 'Cannot produce Uint8Array: original slice contains non-number elements.',
742
- )
743
- }
744
- combinedBytes.push(val)
745
- }
746
- }
747
- // Add bytes from the varargs elements.
748
- // For Uint8Array, elements are always flattened if they are slices/Uint8Arrays.
749
- for (const item of elements) {
750
- if (item instanceof Uint8Array) {
751
- combinedBytes.push(...Array.from(item))
752
- } else if (isComplexSlice(item) || Array.isArray(item)) {
753
- const itemLen = len(item as Slice<any>)
754
- for (let i = 0; i < itemLen; i++) {
755
- const val = (item as any)[i]
756
- if (typeof val !== 'number') {
757
- throw new Error(
758
- 'Cannot produce Uint8Array: appended elements contain non-numbers.',
759
- )
760
- }
761
- combinedBytes.push(val)
762
- }
763
- } else {
764
- if (typeof item !== 'number') {
765
- throw new Error(
766
- 'Cannot produce Uint8Array: appended elements contain non-numbers.',
767
- )
768
- }
769
- combinedBytes.push(item)
770
- }
771
- }
772
- const newArr = new Uint8Array(combinedBytes.length)
773
- newArr.set(combinedBytes)
774
- return newArr as any
909
+ return appendByteSlice(slice as Uint8Array, elements) as any
775
910
  }
776
911
 
777
912
  // Handle generic Slice<T> (non-Uint8Array result).
@@ -783,28 +918,30 @@ export function append<T>(
783
918
  return slice as any
784
919
  }
785
920
 
786
- let originalElements: T[] = []
921
+ let originalElements: T[] | undefined
922
+ let oldLength = 0
787
923
  let oldCapacity: number
788
924
  let isOriginalComplex = false
789
925
  let originalBacking: T[] | undefined = undefined
926
+ let originalTarget: T[] | undefined = undefined
790
927
  let originalOffset = 0
791
928
 
792
929
  if (slice === null || slice === undefined) {
793
930
  oldCapacity = 0
794
931
  } else if (isComplexSlice(slice)) {
795
932
  const meta = slice.__meta__
796
- for (let i = 0; i < meta.length; i++)
797
- originalElements.push(meta.backing[meta.offset + i])
933
+ oldLength = meta.length
798
934
  oldCapacity = meta.capacity
799
935
  isOriginalComplex = true
800
936
  originalBacking = meta.backing
937
+ originalTarget = meta.target
801
938
  originalOffset = meta.offset
802
939
  } else {
803
940
  // Simple T[] array
804
941
  originalElements = (slice as T[]).slice()
805
- oldCapacity = (slice as T[]).length
942
+ oldLength = originalElements.length
943
+ oldCapacity = oldLength
806
944
  }
807
- const oldLength = originalElements.length
808
945
  const newLength = oldLength + numAdded
809
946
 
810
947
  // Case 1: Modify in-place if original was SliceProxy and has enough capacity.
@@ -812,16 +949,19 @@ export function append<T>(
812
949
  for (let i = 0; i < numAdded; i++) {
813
950
  originalBacking[originalOffset + oldLength + i] = elements[i] as T
814
951
  }
815
- const resultProxy = new Array(newLength) as SliceProxy<T>
816
- for (let i = 0; i < newLength; i++)
817
- resultProxy[i] = originalBacking[originalOffset + i]
818
- resultProxy.__meta__ = {
819
- backing: originalBacking,
820
- offset: originalOffset,
821
- length: newLength,
822
- capacity: oldCapacity,
952
+ const target = originalTarget
953
+ if (target !== undefined) {
954
+ for (let i = 0; i < numAdded; i++) {
955
+ target[oldLength + i] = elements[i] as T
956
+ }
823
957
  }
824
- return wrapSliceProxy(resultProxy) as any
958
+ return sliceProxyFromBacking(
959
+ originalBacking,
960
+ originalOffset,
961
+ newLength,
962
+ oldCapacity,
963
+ target,
964
+ ) as any
825
965
  }
826
966
 
827
967
  // Case 2: Reallocation is needed.
@@ -838,22 +978,87 @@ export function append<T>(
838
978
  }
839
979
 
840
980
  const newBacking = new Array<T>(newCapacity)
841
- for (let i = 0; i < oldLength; i++) {
842
- newBacking[i] = originalElements[i]
981
+ if (isOriginalComplex && originalBacking) {
982
+ for (let i = 0; i < oldLength; i++) {
983
+ newBacking[i] = originalBacking[originalOffset + i]
984
+ }
985
+ } else if (originalElements !== undefined) {
986
+ for (let i = 0; i < oldLength; i++) {
987
+ newBacking[i] = originalElements[i]
988
+ }
843
989
  }
844
990
  for (let i = 0; i < numAdded; i++) {
845
991
  newBacking[oldLength + i] = elements[i] as T
846
992
  }
847
993
 
848
- const resultProxy = new Array(newLength) as SliceProxy<T>
849
- for (let i = 0; i < newLength; i++) resultProxy[i] = newBacking[i]
850
- resultProxy.__meta__ = {
851
- backing: newBacking,
852
- offset: 0,
853
- length: newLength,
854
- capacity: newCapacity,
994
+ return sliceProxyFromBacking(newBacking, 0, newLength, newCapacity) as any
995
+ }
996
+
997
+ function appendByteSlice(slice: Uint8Array, elements: any[]): Uint8Array {
998
+ const meta = byteSliceMeta(slice)
999
+ const metaBacking = meta?.backing as unknown
1000
+ const backing =
1001
+ metaBacking instanceof Uint8Array ? metaBacking : slice
1002
+ const offset = meta?.offset ?? 0
1003
+ const oldLength = slice.length
1004
+ const oldCapacity = meta?.capacity ?? oldLength
1005
+ let added = 0
1006
+ for (const item of elements) {
1007
+ added += byteElementLength(item)
1008
+ }
1009
+ const newLength = oldLength + added
1010
+ if (newLength <= oldCapacity) {
1011
+ const view = byteSliceView(backing, offset, newLength, oldCapacity)
1012
+ writeByteElements(view, oldLength, elements)
1013
+ return view
1014
+ }
1015
+ const next = new Uint8Array(newLength)
1016
+ next.set(slice)
1017
+ writeByteElements(next, oldLength, elements)
1018
+ return next
1019
+ }
1020
+
1021
+ function byteElementLength(item: any): number {
1022
+ if (item instanceof Uint8Array) {
1023
+ return item.length
1024
+ }
1025
+ if (isComplexSlice(item) || Array.isArray(item)) {
1026
+ return len(item as Slice<any>)
1027
+ }
1028
+ if (typeof item !== 'number') {
1029
+ throw new Error('Cannot produce Uint8Array: appended elements contain non-numbers.')
1030
+ }
1031
+ return 1
1032
+ }
1033
+
1034
+ function writeByteElements(dst: Uint8Array, offset: number, elements: any[]): void {
1035
+ let cursor = offset
1036
+ for (const item of elements) {
1037
+ if (item instanceof Uint8Array) {
1038
+ dst.set(item, cursor)
1039
+ cursor += item.length
1040
+ continue
1041
+ }
1042
+ if (isComplexSlice(item) || Array.isArray(item)) {
1043
+ const itemLen = len(item as Slice<any>)
1044
+ for (let i = 0; i < itemLen; i++) {
1045
+ const value = (item as any)[i]
1046
+ if (typeof value !== 'number') {
1047
+ throw new Error(
1048
+ 'Cannot produce Uint8Array: appended elements contain non-numbers.',
1049
+ )
1050
+ }
1051
+ dst[cursor] = value
1052
+ cursor++
1053
+ }
1054
+ continue
1055
+ }
1056
+ if (typeof item !== 'number') {
1057
+ throw new Error('Cannot produce Uint8Array: appended elements contain non-numbers.')
1058
+ }
1059
+ dst[cursor] = item
1060
+ cursor++
855
1061
  }
856
- return wrapSliceProxy(resultProxy) as any
857
1062
  }
858
1063
 
859
1064
  /**
@@ -868,14 +1073,14 @@ export function copy<T>(dst: Slice<T>, src: Slice<T>): number
868
1073
  export function copy<T>(dst: Slice<T>, src: string): number
869
1074
  export function copy<T>(
870
1075
  dst: Slice<T> | Uint8Array,
871
- src: Slice<T> | Uint8Array | string,
1076
+ src: Slice<T> | Uint8Array | GoStringValue,
872
1077
  ): number {
873
1078
  if (dst === null) {
874
1079
  return 0
875
1080
  }
876
1081
 
877
1082
  // Handle string source first
878
- if (typeof src === 'string') {
1083
+ if (isGoStringValue(src)) {
879
1084
  return copyFromString(dst, src)
880
1085
  }
881
1086
 
@@ -916,9 +1121,13 @@ export function copy<T>(
916
1121
  /**
917
1122
  * Helper: Copy from string to any destination type
918
1123
  */
919
- function copyFromString<T>(dst: Slice<T> | Uint8Array, src: string): number {
1124
+ function copyFromString<T>(
1125
+ dst: Slice<T> | Uint8Array,
1126
+ src: GoStringValue,
1127
+ ): number {
920
1128
  const dstLen = dst instanceof Uint8Array ? dst.length : len(dst)
921
- const count = Math.min(dstLen, src.length)
1129
+ const bytes = goStringBytes(src)
1130
+ const count = Math.min(dstLen, bytes.length)
922
1131
 
923
1132
  if (count === 0) {
924
1133
  return 0
@@ -926,18 +1135,18 @@ function copyFromString<T>(dst: Slice<T> | Uint8Array, src: string): number {
926
1135
 
927
1136
  if (dst instanceof Uint8Array) {
928
1137
  for (let i = 0; i < count; i++) {
929
- dst[i] = src.charCodeAt(i)
1138
+ dst[i] = bytes[i]
930
1139
  }
931
1140
  } else if (isComplexSlice(dst)) {
932
1141
  const dstMeta = dst.__meta__
933
1142
  for (let i = 0; i < count; i++) {
934
- const byteVal = src.charCodeAt(i)
1143
+ const byteVal = bytes[i]
935
1144
  dstMeta.backing[dstMeta.offset + i] = byteVal as unknown as T
936
1145
  ;(dst as any)[i] = byteVal
937
1146
  }
938
1147
  } else if (Array.isArray(dst)) {
939
1148
  for (let i = 0; i < count; i++) {
940
- dst[i] = src.charCodeAt(i) as unknown as T
1149
+ dst[i] = bytes[i] as unknown as T
941
1150
  }
942
1151
  }
943
1152
 
@@ -952,15 +1161,9 @@ function copyToUint8Array(
952
1161
  src: Slice<number>,
953
1162
  count: number,
954
1163
  ): number {
955
- if (isComplexSlice(src)) {
956
- const srcMeta = src.__meta__
957
- for (let i = 0; i < count; i++) {
958
- dst[i] = srcMeta.backing[srcMeta.offset + i]
959
- }
960
- } else if (Array.isArray(src)) {
961
- for (let i = 0; i < count; i++) {
962
- dst[i] = src[i]
963
- }
1164
+ const values = copySliceValues(src, count)
1165
+ for (let i = 0; i < count; i++) {
1166
+ dst[i] = values[i]
964
1167
  }
965
1168
  return count
966
1169
  }
@@ -973,15 +1176,16 @@ function copyFromUint8Array<T>(
973
1176
  src: Uint8Array,
974
1177
  count: number,
975
1178
  ): number {
1179
+ const values = Array.from(src.subarray(0, count))
976
1180
  if (isComplexSlice(dst)) {
977
1181
  const dstMeta = dst.__meta__
978
1182
  for (let i = 0; i < count; i++) {
979
- dstMeta.backing[dstMeta.offset + i] = src[i] as unknown as T
980
- ;(dst as any)[i] = src[i]
1183
+ dstMeta.backing[dstMeta.offset + i] = values[i] as unknown as T
1184
+ ;(dst as any)[i] = values[i]
981
1185
  }
982
1186
  } else if (Array.isArray(dst)) {
983
1187
  for (let i = 0; i < count; i++) {
984
- dst[i] = src[i] as unknown as T
1188
+ dst[i] = values[i] as unknown as T
985
1189
  }
986
1190
  }
987
1191
  return count
@@ -995,37 +1199,36 @@ function copyBetweenSlices<T>(
995
1199
  src: Slice<T>,
996
1200
  count: number,
997
1201
  ): number {
1202
+ const values = copySliceValues(src, count)
998
1203
  if (isComplexSlice(dst)) {
999
1204
  const dstMeta = dst.__meta__
1000
-
1001
- if (isComplexSlice(src)) {
1002
- const srcMeta = src.__meta__
1003
- for (let i = 0; i < count; i++) {
1004
- dstMeta.backing[dstMeta.offset + i] =
1005
- srcMeta.backing[srcMeta.offset + i]
1006
- ;(dst as any)[i] = srcMeta.backing[srcMeta.offset + i]
1007
- }
1008
- } else if (Array.isArray(src)) {
1009
- for (let i = 0; i < count; i++) {
1010
- dstMeta.backing[dstMeta.offset + i] = src[i]
1011
- ;(dst as any)[i] = src[i]
1012
- }
1205
+ for (let i = 0; i < count; i++) {
1206
+ dstMeta.backing[dstMeta.offset + i] = values[i]
1207
+ ;(dst as any)[i] = values[i]
1013
1208
  }
1014
1209
  } else if (Array.isArray(dst)) {
1015
- if (isComplexSlice(src)) {
1016
- const srcMeta = src.__meta__
1017
- for (let i = 0; i < count; i++) {
1018
- dst[i] = srcMeta.backing[srcMeta.offset + i]
1019
- }
1020
- } else if (Array.isArray(src)) {
1021
- for (let i = 0; i < count; i++) {
1022
- dst[i] = src[i]
1023
- }
1210
+ for (let i = 0; i < count; i++) {
1211
+ dst[i] = values[i]
1024
1212
  }
1025
1213
  }
1026
1214
  return count
1027
1215
  }
1028
1216
 
1217
+ function copySliceValues<T>(src: Slice<T>, count: number): T[] {
1218
+ const values = new Array<T>(count)
1219
+ if (isComplexSlice(src)) {
1220
+ const srcMeta = src.__meta__
1221
+ for (let i = 0; i < count; i++) {
1222
+ values[i] = srcMeta.backing[srcMeta.offset + i]
1223
+ }
1224
+ } else if (Array.isArray(src)) {
1225
+ for (let i = 0; i < count; i++) {
1226
+ values[i] = src[i]
1227
+ }
1228
+ }
1229
+ return values
1230
+ }
1231
+
1029
1232
  /**
1030
1233
  * Accesses an element at a specific index for various Go-like types (string, slice, array).
1031
1234
  * Mimics Go's indexing behavior: `myCollection[index]`
@@ -1038,14 +1241,14 @@ function copyBetweenSlices<T>(
1038
1241
  * @throws Error if index is out of bounds or type is unsupported.
1039
1242
  */
1040
1243
  export function index<T>(
1041
- collection: string | Slice<T> | T[],
1244
+ collection: GoStringValue | Slice<T> | T[],
1042
1245
  index: number,
1043
1246
  ): T | number {
1044
1247
  if (collection === null || collection === undefined) {
1045
1248
  throw new Error('runtime error: index on nil or undefined collection')
1046
1249
  }
1047
1250
 
1048
- if (typeof collection === 'string') {
1251
+ if (isGoStringValue(collection)) {
1049
1252
  return indexString(collection, index) // Use the existing indexString for byte access
1050
1253
  } else if (collection instanceof Uint8Array) {
1051
1254
  if (index < 0 || index >= collection.length) {
@@ -1072,6 +1275,151 @@ export function index<T>(
1072
1275
  throw new Error('runtime error: index on unsupported type')
1073
1276
  }
1074
1277
 
1278
+ /**
1279
+ * indexRef returns an addressable reference to a slice or array element.
1280
+ */
1281
+ export function indexRef<T>(
1282
+ collection: Slice<T> | T[] | Uint8Array,
1283
+ index: number,
1284
+ ): VarRef<T> {
1285
+ if (collection === null || collection === undefined) {
1286
+ throw new Error('runtime error: index on nil or undefined collection')
1287
+ }
1288
+ if (collection instanceof Uint8Array) {
1289
+ if (index < 0 || index >= collection.length) {
1290
+ throw new Error(
1291
+ `runtime error: index out of range [${index}] with length ${collection.length}`,
1292
+ )
1293
+ }
1294
+ return {
1295
+ get value() {
1296
+ return collection[index] as T
1297
+ },
1298
+ set value(value: T) {
1299
+ collection[index] = value as number
1300
+ },
1301
+ __isVarRef: true,
1302
+ __goAddress: () => indexAddress(collection, index),
1303
+ __goCollection: collection,
1304
+ __goIndex: index,
1305
+ }
1306
+ }
1307
+ if (isComplexSlice(collection)) {
1308
+ if (index < 0 || index >= collection.__meta__.length) {
1309
+ throw new Error(
1310
+ `runtime error: index out of range [${index}] with length ${collection.__meta__.length}`,
1311
+ )
1312
+ }
1313
+ const backingIndex = collection.__meta__.offset + index
1314
+ return {
1315
+ get value() {
1316
+ return collection.__meta__.backing[backingIndex]
1317
+ },
1318
+ set value(value: T) {
1319
+ collection[index] = value
1320
+ },
1321
+ __isVarRef: true,
1322
+ __goAddress: () => indexAddress(collection, index),
1323
+ __goCollection: collection,
1324
+ __goIndex: index,
1325
+ }
1326
+ }
1327
+ if (Array.isArray(collection)) {
1328
+ if (index < 0 || index >= collection.length) {
1329
+ throw new Error(
1330
+ `runtime error: index out of range [${index}] with length ${collection.length}`,
1331
+ )
1332
+ }
1333
+ return {
1334
+ get value() {
1335
+ return collection[index]
1336
+ },
1337
+ set value(value: T) {
1338
+ collection[index] = value
1339
+ },
1340
+ __isVarRef: true,
1341
+ __goAddress: () => indexAddress(collection, index),
1342
+ __goCollection: collection,
1343
+ __goIndex: index,
1344
+ }
1345
+ }
1346
+ throw new Error('runtime error: index on unsupported type')
1347
+ }
1348
+
1349
+ /**
1350
+ * arrayPointerFromIndexRef turns &slice[i] into a pointer to an N-element array
1351
+ * view. This models unsafe conversions such as (*[64]byte)(unsafe.Pointer(&b[0]))
1352
+ * for packages that immediately slice or index the resulting array pointer.
1353
+ */
1354
+ export function arrayPointerFromIndexRef<T>(
1355
+ ref: VarRef<T>,
1356
+ length: number,
1357
+ ): VarRef<Slice<T> | T[] | Uint8Array> {
1358
+ const collection = ref.__goCollection as
1359
+ | Slice<T>
1360
+ | T[]
1361
+ | Uint8Array
1362
+ | undefined
1363
+ if (collection === undefined) {
1364
+ throw new Error(
1365
+ 'unsafe array pointer requires an indexed collection reference',
1366
+ )
1367
+ }
1368
+ const index = ref.__goIndex ?? 0
1369
+ return varRef(
1370
+ goSlice(collection as any, index, index + length) as
1371
+ | Slice<T>
1372
+ | T[]
1373
+ | Uint8Array,
1374
+ )
1375
+ }
1376
+
1377
+ /**
1378
+ * indexAddress returns a stable synthetic address for an addressable slice or
1379
+ * array element.
1380
+ */
1381
+ export function indexAddress<T>(
1382
+ collection: Slice<T> | T[] | Uint8Array,
1383
+ index: number,
1384
+ ): number {
1385
+ if (collection === null || collection === undefined) {
1386
+ throw new Error('runtime error: index on nil or undefined collection')
1387
+ }
1388
+
1389
+ let backing: object
1390
+ let backingIndex: number
1391
+ let length: number
1392
+ if (collection instanceof Uint8Array) {
1393
+ backing = collection.buffer
1394
+ backingIndex = collection.byteOffset + index
1395
+ length = collection.length
1396
+ } else if (isComplexSlice(collection)) {
1397
+ backing = collection.__meta__.backing
1398
+ backingIndex = collection.__meta__.offset + index
1399
+ length = collection.__meta__.length
1400
+ } else if (Array.isArray(collection)) {
1401
+ backing = collection
1402
+ backingIndex = index
1403
+ length = collection.length
1404
+ } else {
1405
+ throw new Error('runtime error: index on unsupported type')
1406
+ }
1407
+
1408
+ if (index < 0 || index >= length) {
1409
+ throw new Error(
1410
+ `runtime error: index out of range [${index}] with length ${length}`,
1411
+ )
1412
+ }
1413
+
1414
+ let base = addressBases.get(backing)
1415
+ if (base === undefined) {
1416
+ base = nextAddressBase * addressStride
1417
+ nextAddressBase++
1418
+ addressBases.set(backing, base)
1419
+ }
1420
+ return base + backingIndex
1421
+ }
1422
+
1075
1423
  /**
1076
1424
  * Converts a string to an array of Unicode code points (runes).
1077
1425
  * @param str The input string.
@@ -1081,6 +1429,22 @@ export const stringToRunes = (str: string): number[] => {
1081
1429
  return Array.from(str).map((c) => c.codePointAt(0) || 0)
1082
1430
  }
1083
1431
 
1432
+ /**
1433
+ * Returns Go range pairs for a string: UTF-8 byte offset and rune value.
1434
+ * @param str The input string.
1435
+ * @returns Index/rune pairs matching Go's `for i, r := range str`.
1436
+ */
1437
+ export const rangeString = (str: string): Array<[number, number]> => {
1438
+ const encoder = new TextEncoder()
1439
+ const pairs: Array<[number, number]> = []
1440
+ let offset = 0
1441
+ for (const char of str) {
1442
+ pairs.push([offset, char.codePointAt(0) || 0])
1443
+ offset += encoder.encode(char).length
1444
+ }
1445
+ return pairs
1446
+ }
1447
+
1084
1448
  /**
1085
1449
  * Converts a single-character string to its Unicode code point (rune).
1086
1450
  * Used for readable rune constants like $.stringToRune('/') instead of 47.
@@ -1122,10 +1486,10 @@ export const byte = (n: number): number => {
1122
1486
  * @throws Error if index is out of bounds.
1123
1487
  */
1124
1488
  export const indexString = (
1125
- str: string | import('./builtin.js').Bytes,
1489
+ str: GoStringValue | import('./builtin.js').Bytes,
1126
1490
  index: number,
1127
1491
  ): number => {
1128
- if (typeof str !== 'string') {
1492
+ if (!isGoStringValue(str)) {
1129
1493
  // Bytes - access directly
1130
1494
  if (str instanceof Uint8Array) {
1131
1495
  if (index < 0 || index >= str.length) {
@@ -1148,7 +1512,7 @@ export const indexString = (
1148
1512
  }
1149
1513
  return str[index]
1150
1514
  }
1151
- const bytes = new TextEncoder().encode(str)
1515
+ const bytes = goStringBytes(str)
1152
1516
  if (index < 0 || index >= bytes.length) {
1153
1517
  throw new Error(
1154
1518
  `runtime error: index out of range [${index}] with length ${bytes.length}`,
@@ -1163,8 +1527,8 @@ export const indexString = (
1163
1527
  * @param str The string.
1164
1528
  * @returns The number of bytes in the UTF-8 representation of the string.
1165
1529
  */
1166
- export const stringLen = (str: string): number => {
1167
- return new TextEncoder().encode(str).length
1530
+ export const stringLen = (str: GoStringValue): number => {
1531
+ return goStringBytes(str).length
1168
1532
  }
1169
1533
 
1170
1534
  /**
@@ -1177,11 +1541,11 @@ export const stringLen = (str: string): number => {
1177
1541
  * @throws Error if the slice would create invalid UTF-8.
1178
1542
  */
1179
1543
  export const sliceString = (
1180
- str: string,
1544
+ str: GoStringValue,
1181
1545
  low?: number,
1182
1546
  high?: number,
1183
1547
  ): string => {
1184
- const bytes = new TextEncoder().encode(str)
1548
+ const bytes = goStringBytes(str)
1185
1549
  const actualLow = low === undefined ? 0 : low
1186
1550
  const actualHigh = high === undefined ? bytes.length : high
1187
1551
 
@@ -1203,21 +1567,7 @@ export const sliceString = (
1203
1567
  )
1204
1568
  }
1205
1569
 
1206
- const slicedBytes = bytes.subarray(actualLow, actualHigh)
1207
-
1208
- try {
1209
- // Attempt to decode with strict UTF-8 validation
1210
- const result = new TextDecoder('utf-8', { fatal: true }).decode(slicedBytes)
1211
- return result
1212
- } catch (e: unknown) {
1213
- // If we get here, the slice would create invalid UTF-8
1214
- // This is a fundamental limitation of JavaScript string handling
1215
- throw new Error(
1216
- `Cannot slice string at byte indices [${actualLow}:${actualHigh}] because it would create invalid UTF-8. ` +
1217
- `This is a limitation of JavaScript's string handling.`,
1218
- { cause: e },
1219
- )
1220
- }
1570
+ return goStringFromBytes(bytes.subarray(actualLow, actualHigh))
1221
1571
  }
1222
1572
 
1223
1573
  /**
@@ -1231,9 +1581,7 @@ export const bytesToString = (
1231
1581
  if (bytes === null) return ''
1232
1582
  // If it's already a string, just return it
1233
1583
  if (typeof bytes === 'string') return bytes
1234
- if (bytes instanceof Uint8Array) {
1235
- return new TextDecoder().decode(bytes)
1236
- }
1584
+ if (bytes instanceof Uint8Array) return goStringFromBytes(bytes)
1237
1585
  // Ensure we get a plain number[] for Uint8Array.from
1238
1586
  let byteArray: number[]
1239
1587
  if (isComplexSlice(bytes)) {
@@ -1246,7 +1594,114 @@ export const bytesToString = (
1246
1594
  // For simple T[] slices
1247
1595
  byteArray = bytes
1248
1596
  }
1249
- return new TextDecoder().decode(Uint8Array.from(byteArray))
1597
+ return goStringFromBytes(Uint8Array.from(byteArray)) as string
1598
+ }
1599
+
1600
+ export function stringEqual(
1601
+ left: GoStringBytes,
1602
+ right: GoStringBytes,
1603
+ ): boolean {
1604
+ const leftBytes = goStringComparableBytes(left)
1605
+ const rightBytes = goStringComparableBytes(right)
1606
+ if (leftBytes.length !== rightBytes.length) {
1607
+ return false
1608
+ }
1609
+ for (let i = 0; i < leftBytes.length; i++) {
1610
+ if (leftBytes[i] !== rightBytes[i]) {
1611
+ return false
1612
+ }
1613
+ }
1614
+ return true
1615
+ }
1616
+
1617
+ export function stringCompare(
1618
+ left: GoStringBytes,
1619
+ right: GoStringBytes,
1620
+ ): number {
1621
+ if (!isGoStringValue(left) && !isGoStringValue(right)) {
1622
+ const leftBytes = byteStringView(left)
1623
+ const rightBytes = byteStringView(right)
1624
+ const leftLen = leftBytes.length
1625
+ const rightLen = rightBytes.length
1626
+ const sharedLen = Math.min(leftLen, rightLen)
1627
+ for (let i = 0; i < sharedLen; i++) {
1628
+ const diff =
1629
+ (leftBytes.backing[leftBytes.offset + i] ?? 0) -
1630
+ (rightBytes.backing[rightBytes.offset + i] ?? 0)
1631
+ if (diff !== 0) {
1632
+ return diff
1633
+ }
1634
+ }
1635
+ return leftLen - rightLen
1636
+ }
1637
+
1638
+ const leftBytes = goStringComparableBytes(left)
1639
+ const rightBytes = goStringComparableBytes(right)
1640
+ const sharedLen = Math.min(leftBytes.length, rightBytes.length)
1641
+ for (let i = 0; i < sharedLen; i++) {
1642
+ const diff = leftBytes[i] - rightBytes[i]
1643
+ if (diff !== 0) {
1644
+ return diff
1645
+ }
1646
+ }
1647
+ return leftBytes.length - rightBytes.length
1648
+ }
1649
+
1650
+ type ByteStringView = {
1651
+ backing: ArrayLike<number>
1652
+ offset: number
1653
+ length: number
1654
+ }
1655
+
1656
+ function byteStringView(value: GoStringBytes): ByteStringView {
1657
+ value = collectionValue(value) as GoStringBytes
1658
+ if (value === null || value === undefined) {
1659
+ return { backing: [], offset: 0, length: 0 }
1660
+ }
1661
+ if (value instanceof Uint8Array) {
1662
+ return { backing: value, offset: 0, length: value.length }
1663
+ }
1664
+ if (Array.isArray(value)) {
1665
+ const meta = (value as unknown as SliceProxy<number>).__meta__
1666
+ if (meta !== undefined) {
1667
+ return {
1668
+ backing: meta.backing,
1669
+ offset: meta.offset,
1670
+ length: meta.length,
1671
+ }
1672
+ }
1673
+ return { backing: value, offset: 0, length: value.length }
1674
+ }
1675
+ const meta = (value as unknown as SliceProxy<number>).__meta__
1676
+ return {
1677
+ backing: meta.backing,
1678
+ offset: meta.offset,
1679
+ length: meta.length,
1680
+ }
1681
+ }
1682
+
1683
+ function collectionValue(value: unknown): unknown {
1684
+ if (isVarRef(value)) {
1685
+ return collectionValue(value.value)
1686
+ }
1687
+ if (
1688
+ typeof value === 'object' &&
1689
+ value !== null &&
1690
+ typeof (value as { __goType?: unknown }).__goType === 'string' &&
1691
+ '__goValue' in value
1692
+ ) {
1693
+ return collectionValue((value as { __goValue: unknown }).__goValue)
1694
+ }
1695
+ return value
1696
+ }
1697
+
1698
+ function bytesToBinaryString(bytes: Uint8Array): string {
1699
+ const chunkSize = 0x8000
1700
+ let out = ''
1701
+ for (let i = 0; i < bytes.length; i += chunkSize) {
1702
+ out += String.fromCharCode(...bytes.subarray(i, i + chunkSize))
1703
+ }
1704
+ return out
1250
1705
  }
1251
1706
 
1252
1707
  /**
@@ -1255,10 +1710,10 @@ export const bytesToString = (
1255
1710
  * @returns A Uint8Array representing the UTF-8 bytes of the string.
1256
1711
  */
1257
1712
  export function stringToBytes(
1258
- s: string | import('./builtin.js').Bytes,
1713
+ s: GoStringValue | import('./builtin.js').Bytes,
1259
1714
  ): Uint8Array {
1260
- if (typeof s === 'string') {
1261
- return new TextEncoder().encode(s)
1715
+ if (isGoStringValue(s)) {
1716
+ return goStringBytes(s)
1262
1717
  }
1263
1718
  // Already bytes - normalize to Uint8Array
1264
1719
  if (s instanceof Uint8Array) {
@@ -1271,6 +1726,71 @@ export function stringToBytes(
1271
1726
  return new Uint8Array(Array.isArray(s) ? s : [])
1272
1727
  }
1273
1728
 
1729
+ type StringHeaderData = {
1730
+ kind: 'string'
1731
+ value: string
1732
+ }
1733
+
1734
+ export function stringHeaderRef(s: VarRef<string>): VarRef<{
1735
+ Data: StringHeaderData
1736
+ Len: number
1737
+ }> {
1738
+ return varRef({
1739
+ get Data(): StringHeaderData {
1740
+ return { kind: 'string', value: s.value }
1741
+ },
1742
+ set Data(_value: StringHeaderData) {},
1743
+ get Len(): number {
1744
+ return stringToBytes(s.value).length
1745
+ },
1746
+ set Len(_value: number) {},
1747
+ })
1748
+ }
1749
+
1750
+ export function sliceHeaderRef(b: VarRef<Slice<number>>): VarRef<{
1751
+ Data: StringHeaderData | null
1752
+ Len: number
1753
+ Cap: number
1754
+ }> {
1755
+ let data: StringHeaderData | null = null
1756
+ let length = 0
1757
+ let capacity = 0
1758
+ const refresh = () => {
1759
+ if (data === null) {
1760
+ return
1761
+ }
1762
+ const bytes = stringToBytes(data.value)
1763
+ const out = makeSlice<number>(length, Math.max(capacity, length), 'byte')
1764
+ if (out !== null) {
1765
+ copy(out, goSlice(bytes, 0, Math.min(length, bytes.length)))
1766
+ }
1767
+ b.value = out
1768
+ }
1769
+ return varRef({
1770
+ get Data(): StringHeaderData | null {
1771
+ return data
1772
+ },
1773
+ set Data(value: StringHeaderData | null) {
1774
+ data = value
1775
+ refresh()
1776
+ },
1777
+ get Len(): number {
1778
+ return length
1779
+ },
1780
+ set Len(value: number) {
1781
+ length = value
1782
+ refresh()
1783
+ },
1784
+ get Cap(): number {
1785
+ return capacity
1786
+ },
1787
+ set Cap(value: number) {
1788
+ capacity = value
1789
+ refresh()
1790
+ },
1791
+ })
1792
+ }
1793
+
1274
1794
  /**
1275
1795
  * Handles string() conversion for values that could be either string or []byte.
1276
1796
  * Used for generic type parameters with constraint []byte|string.
@@ -1283,8 +1803,8 @@ export function genericBytesOrStringToString(
1283
1803
  if (value === null || value === undefined) {
1284
1804
  return ''
1285
1805
  }
1286
- if (typeof value === 'string') {
1287
- return value
1806
+ if (isGoStringValue(value)) {
1807
+ return value as string
1288
1808
  }
1289
1809
  return bytesToString(value)
1290
1810
  }
@@ -1298,10 +1818,10 @@ export function genericBytesOrStringToString(
1298
1818
  * @returns The byte value at the specified index
1299
1819
  */
1300
1820
  export function indexStringOrBytes(
1301
- value: string | import('./builtin.js').Bytes,
1821
+ value: GoStringValue | import('./builtin.js').Bytes,
1302
1822
  index: number,
1303
1823
  ): number {
1304
- if (typeof value === 'string') {
1824
+ if (isGoStringValue(value)) {
1305
1825
  return indexString(value, index)
1306
1826
  } else if (value instanceof Uint8Array) {
1307
1827
  // For Uint8Array, direct access returns the byte value
@@ -1337,9 +1857,9 @@ export function indexStringOrBytes(
1337
1857
  * @returns The sliced value of the same type as input
1338
1858
  */
1339
1859
  export function sliceStringOrBytes<
1340
- T extends string | import('./builtin.js').Bytes,
1860
+ T extends GoStringValue | import('./builtin.js').Bytes,
1341
1861
  >(value: T, low?: number, high?: number, max?: number): T {
1342
- if (typeof value === 'string') {
1862
+ if (isGoStringValue(value)) {
1343
1863
  // For strings, use sliceString and ignore max parameter
1344
1864
  return sliceString(value, low, high) as T
1345
1865
  } else {