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
@@ -1,3 +1,5 @@
1
+ import { varRef, type VarRef } from './varRef.js'
2
+
1
3
  /**
2
4
  * GoSliceObject contains metadata for complex slice views
3
5
  */
@@ -8,6 +10,10 @@ interface GoSliceObject<T> {
8
10
  capacity: number // Capacity of the slice
9
11
  }
10
12
 
13
+ const addressStride = 0x100000000
14
+ let nextAddressBase = 1
15
+ const addressBases = new WeakMap<object, number>()
16
+
11
17
  /**
12
18
  * SliceProxy is a proxy object for complex slices
13
19
  */
@@ -104,6 +110,44 @@ export function asArray<T>(slice: Slice<T>): T[] {
104
110
  return []
105
111
  }
106
112
 
113
+ export function sliceToArray<T>(
114
+ slice: Slice<T> | Uint8Array,
115
+ length: number,
116
+ typeHint?: string,
117
+ ): T[] | Uint8Array {
118
+ if (len(slice) < length) {
119
+ throw new Error(
120
+ `runtime error: cannot convert slice with length ${len(slice)} to array with length ${length}`,
121
+ )
122
+ }
123
+ if (typeHint === 'byte') {
124
+ return new Uint8Array(asArray(slice as Slice<T>).slice(0, length) as number[])
125
+ }
126
+ return asArray(slice as Slice<T>).slice(0, length)
127
+ }
128
+
129
+ export function sliceToArrayPointer<T>(
130
+ slice: Slice<T> | Uint8Array,
131
+ length: number,
132
+ typeHint?: string,
133
+ ): VarRef<T[] | Uint8Array> {
134
+ if (len(slice) < length) {
135
+ throw new Error(
136
+ `runtime error: cannot convert slice with length ${len(slice)} to array pointer with length ${length}`,
137
+ )
138
+ }
139
+ if (typeHint === 'byte') {
140
+ if (slice instanceof Uint8Array) {
141
+ return varRef(goSlice(slice, 0, length) as unknown as Uint8Array)
142
+ }
143
+ return varRef(goSlice(slice as Slice<T>, 0, length) as unknown as Uint8Array)
144
+ }
145
+ if (slice instanceof Uint8Array) {
146
+ return varRef(goSlice(slice, 0, length) as unknown as T[])
147
+ }
148
+ return varRef(goSlice(slice, 0, length) as T[])
149
+ }
150
+
107
151
  /**
108
152
  * isComplexSlice checks if a slice is a complex slice (has __meta__ property)
109
153
  */
@@ -117,6 +161,13 @@ function isComplexSlice<T>(slice: Slice<T>): slice is SliceProxy<T> {
117
161
  )
118
162
  }
119
163
 
164
+ function normalizeSliceIndex(value: number | undefined): number | undefined {
165
+ if (value === undefined) {
166
+ return undefined
167
+ }
168
+ return Number(value)
169
+ }
170
+
120
171
  /**
121
172
  * isSliceProxy checks if a slice is a SliceProxy (has __meta__ property)
122
173
  * This is an alias for isComplexSlice for better type hinting
@@ -135,6 +186,7 @@ export const makeSlice = <T>(
135
186
  length: number,
136
187
  capacity?: number,
137
188
  typeHint?: string,
189
+ zeroFactory?: () => T,
138
190
  ): Slice<T> => {
139
191
  if (typeHint === 'byte') {
140
192
  const actualCapacity = capacity === undefined ? length : capacity
@@ -176,25 +228,26 @@ export const makeSlice = <T>(
176
228
  )
177
229
  }
178
230
 
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
231
+ const zeroValue = (): T => {
232
+ if (zeroFactory !== undefined) {
233
+ return zeroFactory()
234
+ }
235
+ switch (typeHint) {
236
+ case 'number':
237
+ return 0 as T
238
+ case 'boolean':
239
+ return false as T
240
+ case 'string':
241
+ return '' as T
242
+ default:
243
+ return null as T // Default for objects, complex types, or unspecified
244
+ }
192
245
  }
193
246
 
194
247
  const backingArr = new Array<T>(actualCapacity)
195
248
  // Initialize the relevant part of the backing array
196
249
  for (let i = 0; i < length; i++) {
197
- backingArr[i] = zeroVal
250
+ backingArr[i] = zeroValue()
198
251
  }
199
252
  // The rest of backingArr (from length to actualCapacity-1) remains uninitialized (undefined),
200
253
  // representing available capacity.
@@ -208,7 +261,7 @@ export const makeSlice = <T>(
208
261
  // Its elements up to 'length' should reflect the initialized part of the slice.
209
262
  const proxyTargetArray = new Array<T>(length)
210
263
  for (let i = 0; i < length; i++) {
211
- proxyTargetArray[i] = backingArr[i] // Or simply zeroVal
264
+ proxyTargetArray[i] = backingArr[i]
212
265
  }
213
266
 
214
267
  const proxy = proxyTargetArray as SliceProxy<T>
@@ -296,6 +349,10 @@ export function goSlice<T>( // T can be number for Uint8Array case
296
349
  high?: number,
297
350
  max?: number,
298
351
  ): Slice<T> {
352
+ low = normalizeSliceIndex(low)
353
+ high = normalizeSliceIndex(high)
354
+ max = normalizeSliceIndex(max)
355
+
299
356
  const handler = {
300
357
  get(target: any, prop: string | symbol): any {
301
358
  if (typeof prop === 'string' && /^\d+$/.test(prop)) {
@@ -339,6 +396,7 @@ export function goSlice<T>( // T can be number for Uint8Array case
339
396
  const index = Number(prop)
340
397
  if (index >= 0 && index < target.__meta__.length) {
341
398
  target.__meta__.backing[target.__meta__.offset + index] = value
399
+ target[index] = value
342
400
  return true
343
401
  }
344
402
  if (
@@ -346,6 +404,7 @@ export function goSlice<T>( // T can be number for Uint8Array case
346
404
  target.__meta__.length < target.__meta__.capacity
347
405
  ) {
348
406
  target.__meta__.backing[target.__meta__.offset + index] = value
407
+ target[index] = value
349
408
  target.__meta__.length++
350
409
  return true
351
410
  }
@@ -372,7 +431,7 @@ export function goSlice<T>( // T can be number for Uint8Array case
372
431
  )
373
432
  }
374
433
 
375
- const subArrayView = s.subarray(actualLow, actualHigh) // This is Uint8Array
434
+ const newLength = actualHigh - actualLow
376
435
 
377
436
  if (max !== undefined) {
378
437
  if (max < actualHigh || max > s.length) {
@@ -382,35 +441,36 @@ export function goSlice<T>( // T can be number for Uint8Array case
382
441
  )
383
442
  }
384
443
 
385
- const newLength = subArrayView.length // actualHigh - actualLow
386
444
  const newCap = max - actualLow // Capacity of the new slice view
387
445
 
388
446
  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
- },
447
+ const proxyTarget = new Array<number>(newLength) as SliceProxy<number>
448
+ proxyTarget.__meta__ = {
449
+ backing: s as unknown as number[],
450
+ offset: actualLow,
451
+ length: newLength,
452
+ capacity: newCap,
400
453
  }
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>
454
+ return new Proxy(proxyTarget, handler) as unknown as Slice<T>
406
455
  } else {
407
456
  // newCap === newLength, standard Uint8Array is fine.
408
- return subArrayView as Slice<T> // T is number
457
+ return s.subarray(actualLow, actualHigh) as Slice<T> // T is number
409
458
  }
410
- } else {
411
- // max is not defined, return the Uint8Array subarray view directly.
412
- return subArrayView as Slice<T> // T is number
413
459
  }
460
+
461
+ if (actualHigh !== s.length) {
462
+ const proxyTarget = new Array<number>(newLength) as SliceProxy<number>
463
+ proxyTarget.__meta__ = {
464
+ backing: s as unknown as number[],
465
+ offset: actualLow,
466
+ length: newLength,
467
+ capacity: s.length - actualLow,
468
+ }
469
+ return new Proxy(proxyTarget, handler) as unknown as Slice<T>
470
+ }
471
+
472
+ // max is not defined and length equals capacity, return the Uint8Array view directly.
473
+ return s.subarray(actualLow, actualHigh) as Slice<T> // T is number
414
474
  }
415
475
 
416
476
  // Handle nil slices - in Go, slicing a nil slice with valid bounds returns nil
@@ -645,6 +705,7 @@ export const len = <T = unknown, V = unknown>(
645
705
  | Map<T, V>
646
706
  | Set<T>
647
707
  | Uint8Array
708
+ | { len(): number }
648
709
  | null
649
710
  | undefined,
650
711
  ): number => {
@@ -664,8 +725,12 @@ export const len = <T = unknown, V = unknown>(
664
725
  return obj.length
665
726
  }
666
727
 
667
- if (isComplexSlice(obj)) {
668
- return obj.__meta__.length
728
+ if (typeof (obj as any).len === 'function') {
729
+ return (obj as { len(): number }).len()
730
+ }
731
+
732
+ if (isComplexSlice(obj as any)) {
733
+ return (obj as SliceProxy<T>).__meta__.length
669
734
  }
670
735
 
671
736
  if (Array.isArray(obj)) {
@@ -719,18 +784,14 @@ export function append<T>(
719
784
  // 1. Flatten all elements from the varargs `...elements` into `varargsElements`.
720
785
  // Determine if the result should be a Uint8Array.
721
786
  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)
787
+ const produceUint8Array = inputIsUint8Array
727
788
 
728
789
  // If producing Uint8Array, all elements must be numbers and potentially flattened from other Uint8Arrays/number slices.
729
790
  if (produceUint8Array) {
730
791
  let combinedBytes: number[] = []
731
792
  // Add bytes from the original slice if it exists and is numeric.
732
793
  if (inputIsUint8Array) {
733
- combinedBytes.push(...Array.from(slice as Uint8Array))
794
+ appendBytes(combinedBytes, slice as Uint8Array)
734
795
  } else if (slice !== null && slice !== undefined) {
735
796
  // Original was Slice<number> or number[]
736
797
  const sliceLen = len(slice)
@@ -748,7 +809,7 @@ export function append<T>(
748
809
  // For Uint8Array, elements are always flattened if they are slices/Uint8Arrays.
749
810
  for (const item of elements) {
750
811
  if (item instanceof Uint8Array) {
751
- combinedBytes.push(...Array.from(item))
812
+ appendBytes(combinedBytes, item)
752
813
  } else if (isComplexSlice(item) || Array.isArray(item)) {
753
814
  const itemLen = len(item as Slice<any>)
754
815
  for (let i = 0; i < itemLen; i++) {
@@ -856,6 +917,12 @@ export function append<T>(
856
917
  return wrapSliceProxy(resultProxy) as any
857
918
  }
858
919
 
920
+ function appendBytes(dst: number[], src: Uint8Array): void {
921
+ for (let i = 0; i < src.length; i++) {
922
+ dst.push(src[i])
923
+ }
924
+ }
925
+
859
926
  /**
860
927
  * Copies elements from src to dst.
861
928
  * @param dst The destination slice.
@@ -1072,6 +1139,117 @@ export function index<T>(
1072
1139
  throw new Error('runtime error: index on unsupported type')
1073
1140
  }
1074
1141
 
1142
+ /**
1143
+ * indexRef returns an addressable reference to a slice or array element.
1144
+ */
1145
+ export function indexRef<T>(
1146
+ collection: Slice<T> | T[] | Uint8Array,
1147
+ index: number,
1148
+ ): VarRef<T> {
1149
+ if (collection === null || collection === undefined) {
1150
+ throw new Error('runtime error: index on nil or undefined collection')
1151
+ }
1152
+ if (collection instanceof Uint8Array) {
1153
+ if (index < 0 || index >= collection.length) {
1154
+ throw new Error(
1155
+ `runtime error: index out of range [${index}] with length ${collection.length}`,
1156
+ )
1157
+ }
1158
+ return {
1159
+ get value() {
1160
+ return collection[index] as T
1161
+ },
1162
+ set value(value: T) {
1163
+ collection[index] = value as number
1164
+ },
1165
+ __isVarRef: true,
1166
+ __goAddress: () => indexAddress(collection, index),
1167
+ }
1168
+ }
1169
+ if (isComplexSlice(collection)) {
1170
+ if (index < 0 || index >= collection.__meta__.length) {
1171
+ throw new Error(
1172
+ `runtime error: index out of range [${index}] with length ${collection.__meta__.length}`,
1173
+ )
1174
+ }
1175
+ const backingIndex = collection.__meta__.offset + index
1176
+ return {
1177
+ get value() {
1178
+ return collection.__meta__.backing[backingIndex]
1179
+ },
1180
+ set value(value: T) {
1181
+ collection[index] = value
1182
+ },
1183
+ __isVarRef: true,
1184
+ __goAddress: () => indexAddress(collection, index),
1185
+ }
1186
+ }
1187
+ if (Array.isArray(collection)) {
1188
+ if (index < 0 || index >= collection.length) {
1189
+ throw new Error(
1190
+ `runtime error: index out of range [${index}] with length ${collection.length}`,
1191
+ )
1192
+ }
1193
+ return {
1194
+ get value() {
1195
+ return collection[index]
1196
+ },
1197
+ set value(value: T) {
1198
+ collection[index] = value
1199
+ },
1200
+ __isVarRef: true,
1201
+ __goAddress: () => indexAddress(collection, index),
1202
+ }
1203
+ }
1204
+ throw new Error('runtime error: index on unsupported type')
1205
+ }
1206
+
1207
+ /**
1208
+ * indexAddress returns a stable synthetic address for an addressable slice or
1209
+ * array element.
1210
+ */
1211
+ export function indexAddress<T>(
1212
+ collection: Slice<T> | T[] | Uint8Array,
1213
+ index: number,
1214
+ ): number {
1215
+ if (collection === null || collection === undefined) {
1216
+ throw new Error('runtime error: index on nil or undefined collection')
1217
+ }
1218
+
1219
+ let backing: object
1220
+ let backingIndex: number
1221
+ let length: number
1222
+ if (collection instanceof Uint8Array) {
1223
+ backing = collection.buffer
1224
+ backingIndex = collection.byteOffset + index
1225
+ length = collection.length
1226
+ } else if (isComplexSlice(collection)) {
1227
+ backing = collection.__meta__.backing
1228
+ backingIndex = collection.__meta__.offset + index
1229
+ length = collection.__meta__.length
1230
+ } else if (Array.isArray(collection)) {
1231
+ backing = collection
1232
+ backingIndex = index
1233
+ length = collection.length
1234
+ } else {
1235
+ throw new Error('runtime error: index on unsupported type')
1236
+ }
1237
+
1238
+ if (index < 0 || index >= length) {
1239
+ throw new Error(
1240
+ `runtime error: index out of range [${index}] with length ${length}`,
1241
+ )
1242
+ }
1243
+
1244
+ let base = addressBases.get(backing)
1245
+ if (base === undefined) {
1246
+ base = nextAddressBase * addressStride
1247
+ nextAddressBase++
1248
+ addressBases.set(backing, base)
1249
+ }
1250
+ return base + backingIndex
1251
+ }
1252
+
1075
1253
  /**
1076
1254
  * Converts a string to an array of Unicode code points (runes).
1077
1255
  * @param str The input string.
@@ -1081,6 +1259,22 @@ export const stringToRunes = (str: string): number[] => {
1081
1259
  return Array.from(str).map((c) => c.codePointAt(0) || 0)
1082
1260
  }
1083
1261
 
1262
+ /**
1263
+ * Returns Go range pairs for a string: UTF-8 byte offset and rune value.
1264
+ * @param str The input string.
1265
+ * @returns Index/rune pairs matching Go's `for i, r := range str`.
1266
+ */
1267
+ export const rangeString = (str: string): Array<[number, number]> => {
1268
+ const encoder = new TextEncoder()
1269
+ const pairs: Array<[number, number]> = []
1270
+ let offset = 0
1271
+ for (const char of str) {
1272
+ pairs.push([offset, char.codePointAt(0) || 0])
1273
+ offset += encoder.encode(char).length
1274
+ }
1275
+ return pairs
1276
+ }
1277
+
1084
1278
  /**
1085
1279
  * Converts a single-character string to its Unicode code point (rune).
1086
1280
  * Used for readable rune constants like $.stringToRune('/') instead of 47.
@@ -1231,9 +1425,7 @@ export const bytesToString = (
1231
1425
  if (bytes === null) return ''
1232
1426
  // If it's already a string, just return it
1233
1427
  if (typeof bytes === 'string') return bytes
1234
- if (bytes instanceof Uint8Array) {
1235
- return new TextDecoder().decode(bytes)
1236
- }
1428
+ if (bytes instanceof Uint8Array) return decodeGoStringBytes(bytes)
1237
1429
  // Ensure we get a plain number[] for Uint8Array.from
1238
1430
  let byteArray: number[]
1239
1431
  if (isComplexSlice(bytes)) {
@@ -1246,7 +1438,24 @@ export const bytesToString = (
1246
1438
  // For simple T[] slices
1247
1439
  byteArray = bytes
1248
1440
  }
1249
- return new TextDecoder().decode(Uint8Array.from(byteArray))
1441
+ return decodeGoStringBytes(Uint8Array.from(byteArray))
1442
+ }
1443
+
1444
+ function decodeGoStringBytes(bytes: Uint8Array): string {
1445
+ try {
1446
+ return new TextDecoder('utf-8', { fatal: true }).decode(bytes)
1447
+ } catch {
1448
+ return bytesToBinaryString(bytes)
1449
+ }
1450
+ }
1451
+
1452
+ function bytesToBinaryString(bytes: Uint8Array): string {
1453
+ const chunkSize = 0x8000
1454
+ let out = ''
1455
+ for (let i = 0; i < bytes.length; i += chunkSize) {
1456
+ out += String.fromCharCode(...bytes.subarray(i, i + chunkSize))
1457
+ }
1458
+ return out
1250
1459
  }
1251
1460
 
1252
1461
  /**