goscript 0.1.1 → 0.1.3

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 (376) hide show
  1. package/cmd/goscript/cmd-test.go +104 -11
  2. package/cmd/goscript/cmd-test_test.go +1 -1
  3. package/cmd/goscript/cmd_compile.go +9 -0
  4. package/compiler/compile-request.go +31 -0
  5. package/compiler/compiler.go +1 -1
  6. package/compiler/compliance_test.go +0 -2
  7. package/compiler/config.go +2 -0
  8. package/compiler/gotest/package-result.go +2 -0
  9. package/compiler/gotest/request.go +85 -20
  10. package/compiler/gotest/runner.go +733 -96
  11. package/compiler/gotest/runner_test.go +647 -3
  12. package/compiler/lowered-program.go +10 -2
  13. package/compiler/lowering.go +2676 -349
  14. package/compiler/override-facts.go +77 -27
  15. package/compiler/override-registry.go +5 -4
  16. package/compiler/override-registry_test.go +178 -0
  17. package/compiler/package-graph_test.go +62 -7
  18. package/compiler/package-test-graph-variant.go +40 -16
  19. package/compiler/package-test-graph.go +0 -5
  20. package/compiler/package-test-graph_test.go +61 -3
  21. package/compiler/runtime-contract.go +40 -0
  22. package/compiler/semantic-model-types.go +16 -0
  23. package/compiler/semantic-model.go +336 -91
  24. package/compiler/semantic-model_test.go +50 -1
  25. package/compiler/service.go +9 -3
  26. package/compiler/skeleton_test.go +2371 -296
  27. package/compiler/tsworkspace/owner-process-unix_test.go +72 -0
  28. package/compiler/tsworkspace/owner.go +8 -0
  29. package/compiler/tsworkspace/tool-process-other.go +14 -0
  30. package/compiler/tsworkspace/tool-process-unix.go +19 -0
  31. package/compiler/typescript-emitter.go +149 -10
  32. package/dist/gs/builtin/builtin.d.ts +20 -1
  33. package/dist/gs/builtin/builtin.js +246 -26
  34. package/dist/gs/builtin/builtin.js.map +1 -1
  35. package/dist/gs/builtin/channel.d.ts +24 -10
  36. package/dist/gs/builtin/channel.js +143 -34
  37. package/dist/gs/builtin/channel.js.map +1 -1
  38. package/dist/gs/builtin/defer.d.ts +1 -0
  39. package/dist/gs/builtin/defer.js +12 -2
  40. package/dist/gs/builtin/defer.js.map +1 -1
  41. package/dist/gs/builtin/hostio.d.ts +9 -0
  42. package/dist/gs/builtin/hostio.js +25 -0
  43. package/dist/gs/builtin/hostio.js.map +1 -1
  44. package/dist/gs/builtin/map.js +40 -6
  45. package/dist/gs/builtin/map.js.map +1 -1
  46. package/dist/gs/builtin/print.js.map +1 -1
  47. package/dist/gs/builtin/slice.d.ts +43 -9
  48. package/dist/gs/builtin/slice.js +437 -234
  49. package/dist/gs/builtin/slice.js.map +1 -1
  50. package/dist/gs/builtin/type.d.ts +2 -0
  51. package/dist/gs/builtin/type.js +55 -10
  52. package/dist/gs/builtin/type.js.map +1 -1
  53. package/dist/gs/builtin/varRef.d.ts +2 -0
  54. package/dist/gs/builtin/varRef.js.map +1 -1
  55. package/dist/gs/bytes/buffer.gs.js +28 -28
  56. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  57. package/dist/gs/bytes/bytes.gs.d.ts +7 -5
  58. package/dist/gs/bytes/bytes.gs.js +10 -4
  59. package/dist/gs/bytes/bytes.gs.js.map +1 -1
  60. package/dist/gs/bytes/iter.gs.js +13 -13
  61. package/dist/gs/bytes/iter.gs.js.map +1 -1
  62. package/dist/gs/compress/zlib/index.d.ts +26 -0
  63. package/dist/gs/compress/zlib/index.js +168 -0
  64. package/dist/gs/compress/zlib/index.js.map +1 -0
  65. package/dist/gs/context/context.d.ts +1 -1
  66. package/dist/gs/context/context.js +8 -3
  67. package/dist/gs/context/context.js.map +1 -1
  68. package/dist/gs/crypto/ecdh/index.d.ts +52 -0
  69. package/dist/gs/crypto/ecdh/index.js +226 -0
  70. package/dist/gs/crypto/ecdh/index.js.map +1 -0
  71. package/dist/gs/crypto/ed25519/index.d.ts +34 -0
  72. package/dist/gs/crypto/ed25519/index.js +160 -0
  73. package/dist/gs/crypto/ed25519/index.js.map +1 -0
  74. package/dist/gs/crypto/internal/constanttime/index.d.ts +4 -0
  75. package/dist/gs/crypto/internal/constanttime/index.js +18 -0
  76. package/dist/gs/crypto/internal/constanttime/index.js.map +1 -0
  77. package/dist/gs/crypto/rand/index.d.ts +2 -0
  78. package/dist/gs/crypto/rand/index.js +85 -0
  79. package/dist/gs/crypto/rand/index.js.map +1 -1
  80. package/dist/gs/crypto/sha1/index.d.ts +5 -0
  81. package/dist/gs/crypto/sha1/index.js +106 -0
  82. package/dist/gs/crypto/sha1/index.js.map +1 -0
  83. package/dist/gs/crypto/sha256/index.d.ts +8 -0
  84. package/dist/gs/crypto/sha256/index.js +118 -0
  85. package/dist/gs/crypto/sha256/index.js.map +1 -0
  86. package/dist/gs/crypto/sha512/index.d.ts +14 -0
  87. package/dist/gs/crypto/sha512/index.js +129 -0
  88. package/dist/gs/crypto/sha512/index.js.map +1 -0
  89. package/dist/gs/encoding/json/index.d.ts +3 -0
  90. package/dist/gs/encoding/json/index.js +15 -0
  91. package/dist/gs/encoding/json/index.js.map +1 -1
  92. package/dist/gs/errors/errors.js +29 -6
  93. package/dist/gs/errors/errors.js.map +1 -1
  94. package/dist/gs/fmt/fmt.d.ts +1 -1
  95. package/dist/gs/fmt/fmt.js +64 -3
  96. package/dist/gs/fmt/fmt.js.map +1 -1
  97. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +7 -7
  98. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +52 -18
  99. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  100. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +56 -20
  101. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -1
  102. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +57 -3
  103. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +366 -1
  104. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -1
  105. package/dist/gs/github.com/aperturerobotics/util/conc/index.d.ts +20 -0
  106. package/dist/gs/github.com/aperturerobotics/util/conc/index.js +134 -0
  107. package/dist/gs/github.com/aperturerobotics/util/conc/index.js.map +1 -0
  108. package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
  109. package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.d.ts +3 -0
  110. package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js +50 -0
  111. package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js.map +1 -0
  112. package/dist/gs/github.com/klauspost/compress/internal/le/index.js +3 -2
  113. package/dist/gs/github.com/klauspost/compress/internal/le/index.js.map +1 -1
  114. package/dist/gs/github.com/mr-tron/base58/base58/index.d.ts +27 -0
  115. package/dist/gs/github.com/mr-tron/base58/base58/index.js +172 -0
  116. package/dist/gs/github.com/mr-tron/base58/base58/index.js.map +1 -0
  117. package/dist/gs/github.com/zeebo/blake3/internal/consts/index.d.ts +21 -0
  118. package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js +22 -0
  119. package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js.map +1 -0
  120. package/dist/gs/go/token/index.js +11 -4
  121. package/dist/gs/go/token/index.js.map +1 -1
  122. package/dist/gs/hash/fnv/index.d.ts +57 -0
  123. package/dist/gs/hash/fnv/index.js +299 -0
  124. package/dist/gs/hash/fnv/index.js.map +1 -0
  125. package/dist/gs/hash/index.d.ts +17 -0
  126. package/dist/gs/hash/index.js +94 -0
  127. package/dist/gs/hash/index.js.map +1 -0
  128. package/dist/gs/io/fs/readlink.js +2 -6
  129. package/dist/gs/io/fs/readlink.js.map +1 -1
  130. package/dist/gs/io/fs/walk.js.map +1 -1
  131. package/dist/gs/io/io.d.ts +8 -5
  132. package/dist/gs/io/io.js +20 -2
  133. package/dist/gs/io/io.js.map +1 -1
  134. package/dist/gs/iter/iter.d.ts +3 -2
  135. package/dist/gs/iter/iter.js.map +1 -1
  136. package/dist/gs/maps/iter.d.ts +5 -5
  137. package/dist/gs/maps/iter.js +48 -21
  138. package/dist/gs/maps/iter.js.map +1 -1
  139. package/dist/gs/maps/maps.d.ts +6 -6
  140. package/dist/gs/math/bits/index.js +14 -24
  141. package/dist/gs/math/bits/index.js.map +1 -1
  142. package/dist/gs/mime/index.js +3 -1
  143. package/dist/gs/mime/index.js.map +1 -1
  144. package/dist/gs/net/http/httptest/index.d.ts +20 -1
  145. package/dist/gs/net/http/httptest/index.js +85 -3
  146. package/dist/gs/net/http/httptest/index.js.map +1 -1
  147. package/dist/gs/net/http/index.d.ts +118 -6
  148. package/dist/gs/net/http/index.js +389 -14
  149. package/dist/gs/net/http/index.js.map +1 -1
  150. package/dist/gs/net/http/pprof/index.d.ts +8 -0
  151. package/dist/gs/net/http/pprof/index.js +59 -0
  152. package/dist/gs/net/http/pprof/index.js.map +1 -0
  153. package/dist/gs/os/error.gs.js +9 -7
  154. package/dist/gs/os/error.gs.js.map +1 -1
  155. package/dist/gs/os/types_js.gs.js +95 -15
  156. package/dist/gs/os/types_js.gs.js.map +1 -1
  157. package/dist/gs/os/zero_copy_posix.gs.js +1 -1
  158. package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
  159. package/dist/gs/path/filepath/match.js.map +1 -1
  160. package/dist/gs/path/filepath/path.d.ts +5 -3
  161. package/dist/gs/path/filepath/path.js +65 -10
  162. package/dist/gs/path/filepath/path.js.map +1 -1
  163. package/dist/gs/reflect/index.d.ts +3 -2
  164. package/dist/gs/reflect/index.js +2 -1
  165. package/dist/gs/reflect/index.js.map +1 -1
  166. package/dist/gs/reflect/iter.js +2 -2
  167. package/dist/gs/reflect/iter.js.map +1 -1
  168. package/dist/gs/reflect/map.js +26 -0
  169. package/dist/gs/reflect/map.js.map +1 -1
  170. package/dist/gs/reflect/type.d.ts +24 -5
  171. package/dist/gs/reflect/type.js +390 -38
  172. package/dist/gs/reflect/type.js.map +1 -1
  173. package/dist/gs/reflect/types.d.ts +1 -0
  174. package/dist/gs/reflect/types.js +3 -1
  175. package/dist/gs/reflect/types.js.map +1 -1
  176. package/dist/gs/reflect/value.d.ts +4 -1
  177. package/dist/gs/reflect/value.js +39 -1
  178. package/dist/gs/reflect/value.js.map +1 -1
  179. package/dist/gs/reflect/visiblefields.js +1 -1
  180. package/dist/gs/reflect/visiblefields.js.map +1 -1
  181. package/dist/gs/runtime/debug/index.d.ts +39 -0
  182. package/dist/gs/runtime/debug/index.js +58 -0
  183. package/dist/gs/runtime/debug/index.js.map +1 -1
  184. package/dist/gs/runtime/pprof/index.d.ts +20 -0
  185. package/dist/gs/runtime/pprof/index.js +85 -0
  186. package/dist/gs/runtime/pprof/index.js.map +1 -0
  187. package/dist/gs/runtime/trace/index.d.ts +19 -0
  188. package/dist/gs/runtime/trace/index.js +64 -0
  189. package/dist/gs/runtime/trace/index.js.map +1 -0
  190. package/dist/gs/slices/slices.d.ts +24 -9
  191. package/dist/gs/slices/slices.js +229 -24
  192. package/dist/gs/slices/slices.js.map +1 -1
  193. package/dist/gs/sort/slice.gs.d.ts +5 -3
  194. package/dist/gs/sort/slice.gs.js +55 -17
  195. package/dist/gs/sort/slice.gs.js.map +1 -1
  196. package/dist/gs/strings/builder.js +26 -17
  197. package/dist/gs/strings/builder.js.map +1 -1
  198. package/dist/gs/strings/iter.js +140 -75
  199. package/dist/gs/strings/iter.js.map +1 -1
  200. package/dist/gs/strings/replace.js +2 -2
  201. package/dist/gs/strings/replace.js.map +1 -1
  202. package/dist/gs/strings/strings.js +52 -6
  203. package/dist/gs/strings/strings.js.map +1 -1
  204. package/dist/gs/sync/sync.d.ts +6 -3
  205. package/dist/gs/sync/sync.js +39 -11
  206. package/dist/gs/sync/sync.js.map +1 -1
  207. package/dist/gs/syscall/errors.d.ts +116 -112
  208. package/dist/gs/syscall/errors.js +38 -1
  209. package/dist/gs/syscall/errors.js.map +1 -1
  210. package/dist/gs/syscall/fs.d.ts +2 -8
  211. package/dist/gs/syscall/fs.js.map +1 -1
  212. package/dist/gs/syscall/js/index.js +20 -12
  213. package/dist/gs/syscall/js/index.js.map +1 -1
  214. package/dist/gs/syscall/types.d.ts +4 -1
  215. package/dist/gs/syscall/types.js.map +1 -1
  216. package/dist/gs/testing/testing.d.ts +4 -3
  217. package/dist/gs/testing/testing.js +21 -4
  218. package/dist/gs/testing/testing.js.map +1 -1
  219. package/dist/gs/time/time.js +22 -0
  220. package/dist/gs/time/time.js.map +1 -1
  221. package/dist/gs/unicode/unicode.js.map +1 -1
  222. package/dist/gs/unique/index.js +7 -2
  223. package/dist/gs/unique/index.js.map +1 -1
  224. package/go.mod +8 -8
  225. package/go.sum +14 -23
  226. package/gs/builtin/builtin.ts +364 -37
  227. package/gs/builtin/channel.ts +208 -38
  228. package/gs/builtin/defer.ts +13 -2
  229. package/gs/builtin/hostio.test.ts +1 -0
  230. package/gs/builtin/hostio.ts +38 -0
  231. package/gs/builtin/map.ts +46 -6
  232. package/gs/builtin/print.ts +12 -3
  233. package/gs/builtin/runtime-contract.test.ts +290 -10
  234. package/gs/builtin/slice.test.ts +70 -0
  235. package/gs/builtin/slice.ts +566 -255
  236. package/gs/builtin/type.ts +63 -10
  237. package/gs/builtin/varRef.ts +2 -0
  238. package/gs/bytes/buffer.gs.ts +28 -28
  239. package/gs/bytes/bytes.gs.ts +19 -10
  240. package/gs/bytes/bytes.test.ts +17 -0
  241. package/gs/bytes/iter.gs.ts +13 -14
  242. package/gs/compress/zlib/index.test.ts +28 -0
  243. package/gs/compress/zlib/index.ts +200 -0
  244. package/gs/compress/zlib/meta.json +3 -0
  245. package/gs/context/context.test.ts +36 -2
  246. package/gs/context/context.ts +9 -4
  247. package/gs/crypto/ecdh/index.test.ts +43 -0
  248. package/gs/crypto/ecdh/index.ts +274 -0
  249. package/gs/crypto/ed25519/index.test.ts +41 -0
  250. package/gs/crypto/ed25519/index.ts +238 -0
  251. package/gs/crypto/ed25519/meta.json +13 -0
  252. package/gs/crypto/internal/constanttime/index.test.ts +25 -0
  253. package/gs/crypto/internal/constanttime/index.ts +22 -0
  254. package/gs/crypto/rand/index.test.ts +89 -1
  255. package/gs/crypto/rand/index.ts +103 -1
  256. package/gs/crypto/rand/meta.json +4 -1
  257. package/gs/crypto/sha1/index.test.ts +28 -0
  258. package/gs/crypto/sha1/index.ts +130 -0
  259. package/gs/crypto/sha1/meta.json +8 -0
  260. package/gs/crypto/sha256/index.test.ts +78 -0
  261. package/gs/crypto/sha256/index.ts +150 -0
  262. package/gs/crypto/sha256/meta.json +9 -0
  263. package/gs/crypto/sha512/index.test.ts +31 -0
  264. package/gs/crypto/sha512/index.ts +161 -0
  265. package/gs/crypto/sha512/meta.json +11 -0
  266. package/gs/encoding/json/index.test.ts +25 -3
  267. package/gs/encoding/json/index.ts +21 -3
  268. package/gs/errors/errors.test.ts +4 -1
  269. package/gs/errors/errors.ts +32 -8
  270. package/gs/fmt/fmt.test.ts +23 -1
  271. package/gs/fmt/fmt.ts +76 -10
  272. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +62 -7
  273. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +78 -36
  274. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +32 -11
  275. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +122 -43
  276. package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +31 -0
  277. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +518 -4
  278. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +6 -0
  279. package/gs/github.com/aperturerobotics/util/conc/index.test.ts +30 -0
  280. package/gs/github.com/aperturerobotics/util/conc/index.ts +172 -0
  281. package/gs/github.com/aperturerobotics/util/conc/meta.json +9 -0
  282. package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.ts +1 -4
  283. package/gs/github.com/hack-pad/safejs/internal/catch/index.test.ts +35 -0
  284. package/gs/github.com/hack-pad/safejs/internal/catch/index.ts +65 -0
  285. package/gs/github.com/hack-pad/safejs/internal/catch/meta.json +9 -0
  286. package/gs/github.com/klauspost/compress/internal/le/index.test.ts +2 -1
  287. package/gs/github.com/klauspost/compress/internal/le/index.ts +6 -5
  288. package/gs/github.com/mr-tron/base58/base58/index.test.ts +70 -0
  289. package/gs/github.com/mr-tron/base58/base58/index.ts +231 -0
  290. package/gs/github.com/mr-tron/base58/base58/meta.json +3 -0
  291. package/gs/github.com/zeebo/blake3/internal/consts/index.test.ts +46 -0
  292. package/gs/github.com/zeebo/blake3/internal/consts/index.ts +26 -0
  293. package/gs/go/token/index.ts +17 -4
  294. package/gs/hash/fnv/index.test.ts +67 -0
  295. package/gs/hash/fnv/index.ts +351 -0
  296. package/gs/hash/fnv/meta.json +3 -0
  297. package/gs/hash/index.test.ts +37 -0
  298. package/gs/hash/index.ts +118 -0
  299. package/gs/hash/meta.json +5 -0
  300. package/gs/internal/byteorder/index.test.ts +6 -6
  301. package/gs/io/fs/readlink.ts +40 -48
  302. package/gs/io/fs/walk.ts +10 -2
  303. package/gs/io/io.test.ts +64 -0
  304. package/gs/io/io.ts +34 -13
  305. package/gs/iter/iter.ts +8 -2
  306. package/gs/maps/iter.ts +69 -26
  307. package/gs/maps/maps.test.ts +23 -0
  308. package/gs/maps/maps.ts +6 -6
  309. package/gs/math/bits/index.test.ts +20 -0
  310. package/gs/math/bits/index.ts +15 -28
  311. package/gs/mime/index.ts +8 -2
  312. package/gs/net/http/httptest/index.test.ts +85 -0
  313. package/gs/net/http/httptest/index.ts +113 -3
  314. package/gs/net/http/index.test.ts +159 -1
  315. package/gs/net/http/index.ts +515 -15
  316. package/gs/net/http/meta.json +6 -0
  317. package/gs/net/http/pprof/index.test.ts +47 -0
  318. package/gs/net/http/pprof/index.ts +65 -0
  319. package/gs/os/error.gs.ts +9 -10
  320. package/gs/os/error.test.ts +41 -0
  321. package/gs/os/file_unix_js.test.ts +55 -0
  322. package/gs/os/tempfile.gs.test.ts +37 -10
  323. package/gs/os/types_js.gs.ts +94 -15
  324. package/gs/os/zero_copy_posix.gs.ts +1 -2
  325. package/gs/path/filepath/match.ts +4 -1
  326. package/gs/path/filepath/meta.json +6 -0
  327. package/gs/path/filepath/path.test.ts +57 -2
  328. package/gs/path/filepath/path.ts +91 -12
  329. package/gs/reflect/field.test.ts +63 -0
  330. package/gs/reflect/index.ts +4 -1
  331. package/gs/reflect/iter.ts +2 -2
  332. package/gs/reflect/map.test.ts +24 -2
  333. package/gs/reflect/map.ts +35 -0
  334. package/gs/reflect/type.ts +543 -60
  335. package/gs/reflect/typefor.test.ts +100 -0
  336. package/gs/reflect/types.ts +3 -1
  337. package/gs/reflect/value.ts +50 -1
  338. package/gs/reflect/visiblefields.ts +1 -1
  339. package/gs/runtime/debug/index.test.ts +22 -1
  340. package/gs/runtime/debug/index.ts +88 -0
  341. package/gs/runtime/pprof/index.test.ts +36 -0
  342. package/gs/runtime/pprof/index.ts +104 -0
  343. package/gs/runtime/pprof/meta.json +6 -0
  344. package/gs/runtime/trace/index.test.ts +45 -0
  345. package/gs/runtime/trace/index.ts +97 -0
  346. package/gs/runtime/trace/meta.json +7 -0
  347. package/gs/slices/meta.json +2 -1
  348. package/gs/slices/slices.test.ts +86 -0
  349. package/gs/slices/slices.ts +284 -37
  350. package/gs/sort/slice.gs.ts +73 -23
  351. package/gs/sort/slice.test.ts +40 -0
  352. package/gs/strings/builder.test.ts +8 -0
  353. package/gs/strings/builder.ts +29 -17
  354. package/gs/strings/iter.test.ts +5 -7
  355. package/gs/strings/iter.ts +146 -71
  356. package/gs/strings/replace.test.ts +1 -4
  357. package/gs/strings/replace.ts +6 -6
  358. package/gs/strings/strings.test.ts +4 -0
  359. package/gs/strings/strings.ts +54 -6
  360. package/gs/sync/meta.json +1 -0
  361. package/gs/sync/sync.test.ts +57 -1
  362. package/gs/sync/sync.ts +45 -13
  363. package/gs/syscall/errors.ts +158 -115
  364. package/gs/syscall/fs.ts +8 -8
  365. package/gs/syscall/js/index.ts +49 -22
  366. package/gs/syscall/net.test.ts +26 -0
  367. package/gs/syscall/types.ts +7 -2
  368. package/gs/testing/testing.test.ts +56 -0
  369. package/gs/testing/testing.ts +27 -10
  370. package/gs/time/meta.json +2 -2
  371. package/gs/time/time.test.ts +4 -0
  372. package/gs/time/time.ts +33 -2
  373. package/gs/unicode/unicode.test.ts +14 -3
  374. package/gs/unicode/unicode.ts +1 -5
  375. package/gs/unique/index.ts +9 -2
  376. package/package.json +3 -3
@@ -3,10 +3,24 @@ import { describe, expect, it } from 'vitest'
3
3
  import * as $ from '@goscript/builtin/index.js'
4
4
 
5
5
  import {
6
+ All,
6
7
  Backward,
8
+ BinarySearch,
9
+ Clip,
10
+ Compact,
11
+ CompactFunc,
12
+ CompareFunc,
13
+ Concat,
14
+ DeleteFunc,
15
+ EqualFunc,
16
+ IndexFunc,
7
17
  IsSorted,
8
18
  IsSortedFunc,
9
19
  Max,
20
+ MaxFunc,
21
+ Min,
22
+ MinFunc,
23
+ Replace,
10
24
  Sorted,
11
25
  SortStableFunc,
12
26
  } from './slices.js'
@@ -26,6 +40,63 @@ describe('slices.SortStableFunc', () => {
26
40
  })
27
41
  })
28
42
 
43
+ describe('slices compatibility helpers', () => {
44
+ it('implements comparison, min/max, compact, replace, clip, and search helpers', () => {
45
+ expect(
46
+ CompareFunc($.arrayToSlice(['a', 'c']), $.arrayToSlice(['a', 'b']), (a, b) =>
47
+ a.localeCompare(b),
48
+ ),
49
+ ).toBeGreaterThan(0)
50
+ expect(Min($.arrayToSlice([3, 1, 2]))).toBe(1)
51
+ expect(MaxFunc($.arrayToSlice([{ v: 1 }, { v: 4 }]), (a, b) => a.v - b.v).v).toBe(4)
52
+ expect(MinFunc($.arrayToSlice([{ v: 3 }, { v: 2 }]), (a, b) => a.v - b.v).v).toBe(2)
53
+ expect(Array.from(Compact($.arrayToSlice([1, 1, 2, 2, 3])) ?? [])).toEqual([1, 2, 3])
54
+ expect(
55
+ Array.from(
56
+ CompactFunc(
57
+ $.arrayToSlice(['a', 'A', 'b']),
58
+ (a, b) => a.toLowerCase() === b.toLowerCase(),
59
+ ) ?? [],
60
+ ),
61
+ ).toEqual(['a', 'b'])
62
+ expect(Array.from(Replace($.arrayToSlice([1, 2, 3, 4]), 1, 3, 9, 8)) ?? []).toEqual([
63
+ 1, 9, 8, 4,
64
+ ])
65
+ expect(Array.from(Clip($.arrayToSlice([1, 2])) ?? [])).toEqual([1, 2])
66
+ expect(BinarySearch($.arrayToSlice([1, 3, 5]), 3)).toEqual([1, true])
67
+ })
68
+
69
+ it('concatenates slices and preserves empty concat nilness', () => {
70
+ expect(Concat()).toBeNull()
71
+ expect(Concat($.arrayToSlice<number>([]))).toBeNull()
72
+ expect(Array.from(Concat($.arrayToSlice([1]), null, $.arrayToSlice([2, 3])) ?? [])).toEqual([
73
+ 1, 2, 3,
74
+ ])
75
+ expect(Array.from(Concat(new Uint8Array([1, 2]), new Uint8Array([3])) ?? [])).toEqual([
76
+ 1, 2, 3,
77
+ ])
78
+ })
79
+
80
+ it('accepts generated possibly-async callback types for sync helpers', () => {
81
+ const compare: (a: number, b: number) => number | Promise<number> = (a, b) => a - b
82
+ const keepOdd: (v: number) => boolean | Promise<boolean> = (v) => v % 2 === 0
83
+ const equal: (a: string, b: string) => boolean | Promise<boolean> = (a, b) => a === b
84
+
85
+ expect(CompareFunc($.arrayToSlice([1]), $.arrayToSlice([2]), compare)).toBeLessThan(0)
86
+ expect(Array.from(DeleteFunc($.arrayToSlice([1, 2, 3]), keepOdd) ?? [])).toEqual([1, 3])
87
+ expect(EqualFunc($.arrayToSlice(['a']), $.arrayToSlice(['a']), equal)).toBe(true)
88
+ expect(IndexFunc($.arrayToSlice([1, 2, 3]), keepOdd)).toBe(1)
89
+ expect(IsSortedFunc($.arrayToSlice([1, 2, 3]), compare)).toBe(true)
90
+ expect(BinarySearch($.arrayToSlice([1, 2, 3]), 2)).toEqual([1, true])
91
+ })
92
+
93
+ it('rejects actual async callback results in sync helpers', () => {
94
+ expect(() =>
95
+ CompareFunc($.arrayToSlice([1]), $.arrayToSlice([2]), async (a, b) => a - b),
96
+ ).toThrow('slices: asynchronous callback result is not supported')
97
+ })
98
+ })
99
+
29
100
  describe('slices.Sorted', () => {
30
101
  it('collects and sorts iterator values', () => {
31
102
  const values = Sorted<string>((yieldValue) => {
@@ -67,6 +138,21 @@ describe('slices.Backward', () => {
67
138
  })
68
139
  })
69
140
 
141
+ describe('slices.All', () => {
142
+ it('accepts async yield callbacks', async () => {
143
+ const visited: Array<[number, string]> = []
144
+ await All($.arrayToSlice(['a', 'b', 'c']))(async (index, value) => {
145
+ visited.push([index, value])
146
+ return index < 1
147
+ })
148
+
149
+ expect(visited).toEqual([
150
+ [0, 'a'],
151
+ [1, 'b'],
152
+ ])
153
+ })
154
+ })
155
+
70
156
  describe('slices.IsSorted', () => {
71
157
  it('reports ordered and unordered slices', () => {
72
158
  expect(IsSorted($.arrayToSlice([1, 2, 3]))).toBe(true)
@@ -3,6 +3,11 @@ import * as $ from '@goscript/builtin/index.js'
3
3
  import * as cmp from '../cmp/index.js'
4
4
  import * as iter from '../iter/index.js'
5
5
 
6
+ type SyncCallbackResult<T> = T | globalThis.Promise<T>
7
+ type CompareCallback<T, U = T> = ((v1: T, v2: U) => SyncCallbackResult<number>) | null
8
+ type PredicateCallback<T> = ((value: T) => SyncCallbackResult<boolean>) | null
9
+ type EqualCallback<T, U = T> = ((v1: T, v2: U) => SyncCallbackResult<boolean>) | null
10
+
6
11
  /**
7
12
  * Compare compares the elements of s1 and s2 using cmp.Compare.
8
13
  * The elements are compared sequentially, starting at index 0,
@@ -42,6 +47,34 @@ export function Compare<T extends string | number>(
42
47
  return 0
43
48
  }
44
49
 
50
+ export function CompareFunc<T, U>(
51
+ s1: $.Slice<T>,
52
+ s2: $.Slice<U>,
53
+ compare: CompareCallback<T, U>,
54
+ ): number {
55
+ if (compare == null) {
56
+ throw new Error('slices.CompareFunc: nil comparison function')
57
+ }
58
+ const len1 = $.len(s1)
59
+ const len2 = $.len(s2)
60
+ const minLen = len1 < len2 ? len1 : len2
61
+ for (let i = 0; i < minLen; i++) {
62
+ const result = syncNumber(
63
+ compare((s1 as any)[i] as T, (s2 as any)[i] as U),
64
+ )
65
+ if (result !== 0) {
66
+ return result
67
+ }
68
+ }
69
+ if (len1 < len2) {
70
+ return -1
71
+ }
72
+ if (len1 > len2) {
73
+ return 1
74
+ }
75
+ return 0
76
+ }
77
+
45
78
  /**
46
79
  * Clone returns a shallow copy of s while preserving nilness.
47
80
  * @param s The slice to clone
@@ -58,6 +91,38 @@ export function Clone<T>(s: $.Slice<T>): $.Slice<T> {
58
91
  return out
59
92
  }
60
93
 
94
+ export function Concat<T>(...slices: $.Slice<T>[]): $.Slice<T> {
95
+ let size = 0
96
+ let byteSlice = false
97
+ for (const slice of slices) {
98
+ size += $.len(slice)
99
+ byteSlice = byteSlice || slice instanceof Uint8Array
100
+ }
101
+ if (size === 0) {
102
+ return null
103
+ }
104
+ if (byteSlice) {
105
+ const out = new Uint8Array(size)
106
+ let pos = 0
107
+ for (const slice of slices) {
108
+ const length = $.len(slice)
109
+ for (let i = 0; i < length; i++) {
110
+ out[pos++] = (slice as any)[i] as number
111
+ }
112
+ }
113
+ return out as $.Slice<T>
114
+ }
115
+ const out = $.makeSlice<T>(size)
116
+ let pos = 0
117
+ for (const slice of slices) {
118
+ const length = $.len(slice)
119
+ for (let i = 0; i < length; i++) {
120
+ ;(out as any)[pos++] = (slice as any)[i] as T
121
+ }
122
+ }
123
+ return out
124
+ }
125
+
61
126
  /**
62
127
  * All returns an iterator over index-value pairs in the slice.
63
128
  * This is equivalent to Go's slices.All function.
@@ -66,22 +131,35 @@ export function Clone<T>(s: $.Slice<T>): $.Slice<T> {
66
131
  */
67
132
  export function All<T>(
68
133
  s: $.Slice<T>,
69
- ): (yieldFunc: (index: number, value: T) => boolean) => void {
70
- return function (_yield: (index: number, value: T) => boolean): void {
134
+ ): (yieldFunc: (index: number, value: T) => iter.YieldResult) => void | globalThis.Promise<void> {
135
+ return function (
136
+ _yield: (index: number, value: T) => iter.YieldResult,
137
+ ): void | globalThis.Promise<void> {
71
138
  const length = $.len(s)
72
- for (let i = 0; i < length; i++) {
73
- const value = (s as any)[i] as T // Use proper indexing to avoid type issues
74
- if (!_yield(i, value)) {
75
- break
139
+ const walk = (i: number): void | globalThis.Promise<void> => {
140
+ for (; i < length; i++) {
141
+ const value = (s as any)[i] as T // Use proper indexing to avoid type issues
142
+ const keepGoing = _yield(i, value)
143
+ if (keepGoing instanceof Promise) {
144
+ return keepGoing.then((next) => {
145
+ if (next) {
146
+ return walk(i + 1)
147
+ }
148
+ })
149
+ }
150
+ if (!keepGoing) {
151
+ return
152
+ }
76
153
  }
77
154
  }
155
+ return walk(0)
78
156
  }
79
157
  }
80
158
 
81
159
  export function Backward<T>(
82
160
  s: $.Slice<T>,
83
161
  ): (
84
- _yield: (index: number, value: T) => boolean | globalThis.Promise<boolean>
162
+ _yield: (index: number, value: T) => boolean | globalThis.Promise<boolean>,
85
163
  ) => void | globalThis.Promise<void> {
86
164
  return function (
87
165
  _yield: (index: number, value: T) => boolean | globalThis.Promise<boolean>,
@@ -136,17 +214,73 @@ export function Max<T extends cmp.Ordered>(x: $.Slice<T>): T {
136
214
  return max
137
215
  }
138
216
 
217
+ export function Min<T extends cmp.Ordered>(x: $.Slice<T>): T {
218
+ if ($.len(x) === 0) {
219
+ throw new Error('slices.Min: empty list')
220
+ }
221
+ let min = (x as any)[0] as T
222
+ for (let i = 1; i < $.len(x); i++) {
223
+ const value = (x as any)[i] as T
224
+ if (cmp.Compare(value, min) < 0) {
225
+ min = value
226
+ }
227
+ }
228
+ return min
229
+ }
230
+
231
+ export function MaxFunc<T>(
232
+ x: $.Slice<T>,
233
+ compare: CompareCallback<T>,
234
+ ): T {
235
+ if (compare == null) {
236
+ throw new Error('slices.MaxFunc: nil comparison function')
237
+ }
238
+ if ($.len(x) === 0) {
239
+ throw new Error('slices.MaxFunc: empty list')
240
+ }
241
+ let max = (x as any)[0] as T
242
+ for (let i = 1; i < $.len(x); i++) {
243
+ const value = (x as any)[i] as T
244
+ if (syncNumber(compare(max, value)) < 0) {
245
+ max = value
246
+ }
247
+ }
248
+ return max
249
+ }
250
+
251
+ export function MinFunc<T>(
252
+ x: $.Slice<T>,
253
+ compare: CompareCallback<T>,
254
+ ): T {
255
+ if (compare == null) {
256
+ throw new Error('slices.MinFunc: nil comparison function')
257
+ }
258
+ if ($.len(x) === 0) {
259
+ throw new Error('slices.MinFunc: empty list')
260
+ }
261
+ let min = (x as any)[0] as T
262
+ for (let i = 1; i < $.len(x); i++) {
263
+ const value = (x as any)[i] as T
264
+ if (syncNumber(compare(value, min)) < 0) {
265
+ min = value
266
+ }
267
+ }
268
+ return min
269
+ }
270
+
139
271
  export function Collect<T>(seq: iter.Seq<T>): $.Slice<T> {
140
272
  const out: T[] = []
141
- seq((value) => {
273
+ seq((value: T) => {
142
274
  out.push(value)
143
275
  return true
144
276
  })
145
277
  return out.length === 0 ? null : out
146
278
  }
147
279
 
148
- export function Sorted<T extends string | number>(seq: iter.Seq<T>): $.Slice<T> {
149
- const out = Collect(seq)
280
+ export function Sorted<T extends string | number>(
281
+ seq: iter.Seq<T>,
282
+ ): $.Slice<T> {
283
+ const out = Collect<T>(seq)
150
284
  Sort(out)
151
285
  return out
152
286
  }
@@ -185,15 +319,18 @@ export function Delete<T>(s: $.Slice<T>, i: number, j: number): $.Slice<T> {
185
319
 
186
320
  export function DeleteFunc<T>(
187
321
  s: $.Slice<T>,
188
- del: (value: T) => boolean,
322
+ del: PredicateCallback<T>,
189
323
  ): $.Slice<T> {
324
+ if (del == null) {
325
+ throw new Error('slices.DeleteFunc: nil delete function')
326
+ }
190
327
  if (s === null || s === undefined) {
191
328
  return s
192
329
  }
193
330
  let w = 0
194
331
  for (let i = 0; i < s.length; i++) {
195
332
  const value = s[i] as T
196
- if (!del(value)) {
333
+ if (!syncBoolean(del(value))) {
197
334
  ;(s as any)[w] = value
198
335
  w++
199
336
  }
@@ -204,6 +341,83 @@ export function DeleteFunc<T>(
204
341
  return $.goSlice(s, 0, w) as $.Slice<T>
205
342
  }
206
343
 
344
+ export function Replace<T>(
345
+ s: $.Slice<T>,
346
+ i: number,
347
+ j: number,
348
+ ...v: T[]
349
+ ): $.Slice<T> {
350
+ const length = $.len(s)
351
+ if (i < 0 || j < i || j > length) {
352
+ throw new Error(
353
+ `slice bounds out of range [${i}:${j}] with length ${length}`,
354
+ )
355
+ }
356
+ const out = $.makeSlice<T>(length - (j - i) + v.length)
357
+ let pos = 0
358
+ for (let idx = 0; idx < i; idx++) {
359
+ ;(out as any)[pos++] = (s as any)[idx]
360
+ }
361
+ for (const value of v) {
362
+ ;(out as any)[pos++] = value
363
+ }
364
+ for (let idx = j; idx < length; idx++) {
365
+ ;(out as any)[pos++] = (s as any)[idx]
366
+ }
367
+ return out
368
+ }
369
+
370
+ export function Compact<T>(s: $.Slice<T>): $.Slice<T> {
371
+ if (s === null || s === undefined || $.len(s) < 2) {
372
+ return s
373
+ }
374
+ let w = 1
375
+ for (let i = 1; i < $.len(s); i++) {
376
+ if ((s as any)[i] !== (s as any)[i - 1]) {
377
+ ;(s as any)[w] = (s as any)[i]
378
+ w++
379
+ }
380
+ }
381
+ for (let i = w; i < $.len(s); i++) {
382
+ ;(s as any)[i] = clearValue(s)
383
+ }
384
+ return $.goSlice(s, 0, w) as $.Slice<T>
385
+ }
386
+
387
+ export function CompactFunc<T>(
388
+ s: $.Slice<T>,
389
+ eq: EqualCallback<T>,
390
+ ): $.Slice<T> {
391
+ if (eq == null) {
392
+ throw new Error('slices.CompactFunc: nil equality function')
393
+ }
394
+ if (s === null || s === undefined || $.len(s) < 2) {
395
+ return s
396
+ }
397
+ let w = 1
398
+ for (let i = 1; i < $.len(s); i++) {
399
+ if (!syncBoolean(eq((s as any)[i - 1] as T, (s as any)[i] as T))) {
400
+ ;(s as any)[w] = (s as any)[i]
401
+ w++
402
+ }
403
+ }
404
+ for (let i = w; i < $.len(s); i++) {
405
+ ;(s as any)[i] = clearValue(s)
406
+ }
407
+ return $.goSlice(s, 0, w) as $.Slice<T>
408
+ }
409
+
410
+ export function Clip<T>(s: $.Slice<T>): $.Slice<T> {
411
+ if (s == null) {
412
+ return null
413
+ }
414
+ const out = $.makeSlice<T>($.len(s), $.len(s))
415
+ for (let i = 0; i < $.len(s); i++) {
416
+ ;(out as any)[i] = (s as any)[i]
417
+ }
418
+ return out
419
+ }
420
+
207
421
  export function Equal<T>(s1: $.Slice<T>, s2: $.Slice<T>): boolean {
208
422
  const len1 = $.len(s1)
209
423
  if (len1 !== $.len(s2)) {
@@ -220,14 +434,17 @@ export function Equal<T>(s1: $.Slice<T>, s2: $.Slice<T>): boolean {
220
434
  export function EqualFunc<T, U>(
221
435
  s1: $.Slice<T>,
222
436
  s2: $.Slice<U>,
223
- eq: (v1: T, v2: U) => boolean,
437
+ eq: EqualCallback<T, U>,
224
438
  ): boolean {
439
+ if (eq == null) {
440
+ throw new Error('slices.EqualFunc: nil equality function')
441
+ }
225
442
  const len1 = $.len(s1)
226
443
  if (len1 !== $.len(s2)) {
227
444
  return false
228
445
  }
229
446
  for (let i = 0; i < len1; i++) {
230
- if (!eq((s1 as any)[i] as T, (s2 as any)[i] as U)) {
447
+ if (!syncBoolean(eq((s1 as any)[i] as T, (s2 as any)[i] as U))) {
231
448
  return false
232
449
  }
233
450
  }
@@ -243,9 +460,12 @@ export function Index<T>(s: $.Slice<T>, v: T): number {
243
460
  return -1
244
461
  }
245
462
 
246
- export function IndexFunc<T>(s: $.Slice<T>, f: (v: T) => boolean): number {
463
+ export function IndexFunc<T>(s: $.Slice<T>, f: PredicateCallback<T>): number {
464
+ if (f == null) {
465
+ throw new Error('slices.IndexFunc: nil predicate function')
466
+ }
247
467
  for (let i = 0; i < $.len(s); i++) {
248
- if (f((s as any)[i] as T)) {
468
+ if (syncBoolean(f((s as any)[i] as T))) {
249
469
  return i
250
470
  }
251
471
  }
@@ -256,14 +476,16 @@ export function Contains<T>(s: $.Slice<T>, v: T): boolean {
256
476
  return Index(s, v) >= 0
257
477
  }
258
478
 
259
- export function ContainsFunc<T>(s: $.Slice<T>, f: (v: T) => boolean): boolean {
479
+ export function ContainsFunc<T>(s: $.Slice<T>, f: PredicateCallback<T>): boolean {
260
480
  return IndexFunc(s, f) >= 0
261
481
  }
262
482
 
263
483
  export function Insert<T>(s: $.Slice<T>, i: number, ...v: T[]): $.Slice<T> {
264
484
  const length = $.len(s)
265
485
  if (i < 0 || i > length) {
266
- throw new Error(`slice bounds out of range [${i}:${i}] with length ${length}`)
486
+ throw new Error(
487
+ `slice bounds out of range [${i}:${i}] with length ${length}`,
488
+ )
267
489
  }
268
490
  if (v.length === 0) {
269
491
  return s
@@ -333,20 +555,29 @@ export function Grow<T>(s: $.Slice<T>, n: number): $.Slice<T> {
333
555
  * @param s The slice to sort in place
334
556
  * @param cmp Comparison function
335
557
  */
336
- export function SortFunc<T>(s: $.Slice<T>, cmp: (a: T, b: T) => number): void {
558
+ export function SortFunc<T>(
559
+ s: $.Slice<T>,
560
+ cmp: CompareCallback<T>,
561
+ ): void {
562
+ if (cmp == null) {
563
+ throw new Error('slices.SortFunc: nil comparison function')
564
+ }
337
565
  if (s === null || s === undefined) {
338
566
  return
339
567
  }
340
568
  const arr = s as any as T[]
341
- arr.sort(cmp)
569
+ arr.sort((a, b) => syncNumber(cmp(a, b)))
342
570
  }
343
571
 
344
572
  export function IsSortedFunc<T>(
345
573
  x: $.Slice<T>,
346
- cmp: (a: T, b: T) => number,
574
+ cmp: CompareCallback<T>,
347
575
  ): boolean {
576
+ if (cmp == null) {
577
+ throw new Error('slices.IsSortedFunc: nil comparison function')
578
+ }
348
579
  for (let i = $.len(x) - 1; i > 0; i--) {
349
- if (cmp((x as any)[i] as T, (x as any)[i - 1] as T) < 0) {
580
+ if (syncNumber(cmp((x as any)[i] as T, (x as any)[i - 1] as T)) < 0) {
350
581
  return false
351
582
  }
352
583
  }
@@ -355,23 +586,15 @@ export function IsSortedFunc<T>(
355
586
 
356
587
  export function SortStableFunc<T>(
357
588
  s: $.Slice<T>,
358
- cmp: (a: T, b: T) => number,
589
+ cmp: CompareCallback<T>,
359
590
  ): void {
591
+ if (cmp == null) {
592
+ throw new Error('slices.SortStableFunc: nil comparison function')
593
+ }
360
594
  if (s === null || s === undefined) {
361
595
  return
362
596
  }
363
- const sorted = (s as any as T[])
364
- .map((value, index) => ({ value, index }))
365
- .sort((a, b) => {
366
- const result = cmp(a.value, b.value)
367
- if (result !== 0) {
368
- return result
369
- }
370
- return a.index - b.index
371
- })
372
- for (let i = 0; i < sorted.length; i++) {
373
- ;(s as any)[i] = sorted[i].value
374
- }
597
+ ;(s as any as T[]).sort((a, b) => syncNumber(cmp(a, b)))
375
598
  }
376
599
 
377
600
  function clearValue<T>(s: $.Slice<T>): T | null {
@@ -409,14 +632,17 @@ function clearValue<T>(s: $.Slice<T>): T | null {
409
632
  export function BinarySearchFunc<E, T>(
410
633
  x: $.Slice<E>,
411
634
  target: T,
412
- cmp: (a: E, b: T) => number,
635
+ cmp: CompareCallback<E, T>,
413
636
  ): [number, boolean] {
637
+ if (cmp == null) {
638
+ throw new Error('slices.BinarySearchFunc: nil comparison function')
639
+ }
414
640
  let left = 0
415
641
  let right = $.len(x)
416
642
 
417
643
  while (left < right) {
418
644
  const mid = Math.floor((left + right) / 2)
419
- const result = cmp((x as any)[mid] as E, target)
645
+ const result = syncNumber(cmp((x as any)[mid] as E, target))
420
646
 
421
647
  if (result < 0) {
422
648
  left = mid + 1
@@ -429,3 +655,24 @@ export function BinarySearchFunc<E, T>(
429
655
 
430
656
  return [left, false]
431
657
  }
658
+
659
+ function syncNumber(value: SyncCallbackResult<number>): number {
660
+ if (value instanceof Promise) {
661
+ throw new Error('slices: asynchronous callback result is not supported')
662
+ }
663
+ return value
664
+ }
665
+
666
+ function syncBoolean(value: SyncCallbackResult<boolean>): boolean {
667
+ if (value instanceof Promise) {
668
+ throw new Error('slices: asynchronous callback result is not supported')
669
+ }
670
+ return value
671
+ }
672
+
673
+ export function BinarySearch<T extends cmp.Ordered>(
674
+ x: $.Slice<T>,
675
+ target: T,
676
+ ): [number, boolean] {
677
+ return BinarySearchFunc(x, target, cmp.Compare)
678
+ }
@@ -8,47 +8,98 @@ interface SliceMetadata<T> {
8
8
  capacity: number
9
9
  }
10
10
 
11
- // Helper function to swap elements in a slice
12
- function swapInSlice<T>(slice: $.Slice<T>, i: number, j: number): void {
11
+ type LessFunc = (
12
+ i: number,
13
+ j: number,
14
+ ) => boolean | globalThis.Promise<boolean>
15
+
16
+ function setInSlice<T>(slice: $.Slice<T>, i: number, value: T): void {
13
17
  if (!slice) return
14
-
15
- const temp = $.index(slice, i)
16
- if (Array.isArray(slice)) {
17
- const val_j = $.index(slice, j)
18
- const val_i = temp
19
- slice[i] = val_j as T
20
- slice[j] = val_i as T
18
+
19
+ if (Array.isArray(slice) || slice instanceof Uint8Array) {
20
+ ;(slice as any)[i] = value
21
21
  } else if (typeof slice === 'object' && '__meta__' in slice) {
22
22
  const meta = (slice as any).__meta__ as SliceMetadata<T>
23
- const backing = meta.backing
24
- backing[meta.offset + i] = $.index(slice, j) as T
25
- backing[meta.offset + j] = temp as T
23
+ meta.backing[meta.offset + i] = value
24
+ }
25
+ }
26
+
27
+ async function sortedIndices(n: number, less: LessFunc): Promise<number[]> {
28
+ const indices = Array.from({ length: n }, (_, i) => i)
29
+ await sortIndexRange(indices, 0, indices.length, less)
30
+ return indices
31
+ }
32
+
33
+ async function sortIndexRange(
34
+ indices: number[],
35
+ lo: number,
36
+ hi: number,
37
+ less: LessFunc,
38
+ ): Promise<void> {
39
+ if (hi - lo <= 16) {
40
+ for (let i = lo + 1; i < hi; i++) {
41
+ const value = indices[i]
42
+ let j = i
43
+ while (j > lo && (await less(value, indices[j - 1]))) {
44
+ indices[j] = indices[j - 1]
45
+ j--
46
+ }
47
+ indices[j] = value
48
+ }
49
+ return
50
+ }
51
+
52
+ const mid = lo + Math.floor((hi - lo) / 2)
53
+ await sortIndexRange(indices, lo, mid, less)
54
+ await sortIndexRange(indices, mid, hi, less)
55
+
56
+ const merged: number[] = []
57
+ let left = lo
58
+ let right = mid
59
+ while (left < mid && right < hi) {
60
+ if (await less(indices[right], indices[left])) {
61
+ merged.push(indices[right])
62
+ right++
63
+ } else {
64
+ merged.push(indices[left])
65
+ left++
66
+ }
67
+ }
68
+ while (left < mid) {
69
+ merged.push(indices[left])
70
+ left++
71
+ }
72
+ while (right < hi) {
73
+ merged.push(indices[right])
74
+ right++
75
+ }
76
+ for (let i = 0; i < merged.length; i++) {
77
+ indices[lo + i] = merged[i]
26
78
  }
27
79
  }
28
80
 
29
81
  // Slice sorts the slice x given the provided less function
30
82
  export async function Slice(
31
83
  x: $.Slice<any>,
32
- less: (i: number, j: number) => boolean | globalThis.Promise<boolean>
84
+ less: LessFunc,
33
85
  ): globalThis.Promise<void> {
34
86
  if (!x) return
35
-
36
- // Simple insertion sort using the provided less function
87
+
37
88
  const n = $.len(x)
38
- for (let i = 1; i < n; i++) {
39
- for (let j = i; j > 0 && await less(j, j - 1); j--) {
40
- swapInSlice(x, j, j - 1)
41
- }
89
+ const indices = await sortedIndices(n, less)
90
+ const sorted = indices.map((index) => $.index(x, index))
91
+ for (let i = 0; i < sorted.length; i++) {
92
+ setInSlice(x, i, sorted[i])
42
93
  }
43
94
  }
44
95
 
45
96
  // SliceIsSorted reports whether the slice x is sorted according to the provided less function
46
97
  export async function SliceIsSorted(
47
98
  x: $.Slice<any>,
48
- less: (i: number, j: number) => boolean | globalThis.Promise<boolean>
99
+ less: LessFunc,
49
100
  ): globalThis.Promise<boolean> {
50
101
  if (!x) return true
51
-
102
+
52
103
  const n = $.len(x)
53
104
  for (let i = n - 1; i > 0; i--) {
54
105
  if (await less(i, i - 1)) {
@@ -61,8 +112,7 @@ export async function SliceIsSorted(
61
112
  // SliceStable sorts the slice x while keeping the original order of equal elements
62
113
  export async function SliceStable(
63
114
  x: $.Slice<any>,
64
- less: (i: number, j: number) => boolean | globalThis.Promise<boolean>
115
+ less: LessFunc,
65
116
  ): globalThis.Promise<void> {
66
- // For simplicity, use the same sort - can be improved later
67
117
  await Slice(x, less)
68
118
  }