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
@@ -15,6 +15,38 @@ export interface SelectResult<T> {
15
15
  id: number
16
16
  }
17
17
 
18
+ function scheduleClosedChannelWake(wake: () => void): void {
19
+ // Closed-channel wakeups represent goroutine scheduling, not an immediate
20
+ // Promise continuation. Keep them on a task boundary so goroutine work queued
21
+ // around the close can observe state published before the blocked receiver
22
+ // resumes.
23
+ setTimeout(wake, 0)
24
+ }
25
+
26
+ function completeUnbufferedReceive<T>(
27
+ resolveReceive: (value: T) => void,
28
+ value: T,
29
+ ): Promise<void> {
30
+ return new Promise<void>((resolve) => {
31
+ queueMicrotask(() => {
32
+ resolveReceive(value)
33
+ queueMicrotask(resolve)
34
+ })
35
+ })
36
+ }
37
+
38
+ function completeUnbufferedReceiveWithOk<T>(
39
+ resolveReceive: (result: ChannelReceiveResult<T>) => void,
40
+ result: ChannelReceiveResult<T>,
41
+ ): Promise<void> {
42
+ return new Promise<void>((resolve) => {
43
+ queueMicrotask(() => {
44
+ resolveReceive(result)
45
+ queueMicrotask(resolve)
46
+ })
47
+ })
48
+ }
49
+
18
50
  /**
19
51
  * Represents a Go channel in TypeScript.
20
52
  * Supports asynchronous sending and receiving of values.
@@ -56,7 +88,7 @@ export interface Channel<T> {
56
88
  * @param id An identifier for this case in the select statement
57
89
  * @returns Promise that resolves when this case is selected
58
90
  */
59
- selectReceive(id: number): Promise<SelectResult<T>>
91
+ selectReceive(id: number, signal?: AbortSignal): Promise<SelectResult<T>>
60
92
 
61
93
  /**
62
94
  * Used in select statements to create a send operation promise.
@@ -64,7 +96,11 @@ export interface Channel<T> {
64
96
  * @param id An identifier for this case in the select statement
65
97
  * @returns Promise that resolves when this case is selected
66
98
  */
67
- selectSend(value: T, id: number): Promise<SelectResult<boolean>>
99
+ selectSend(
100
+ value: T,
101
+ id: number,
102
+ signal?: AbortSignal,
103
+ ): Promise<SelectResult<boolean>>
68
104
 
69
105
  /**
70
106
  * Checks if the channel has data ready to be received without blocking.
@@ -82,6 +118,11 @@ export interface Channel<T> {
82
118
  * Reports the number of buffered values currently queued in the channel.
83
119
  */
84
120
  len(): number
121
+
122
+ /**
123
+ * Reports the channel buffer capacity.
124
+ */
125
+ cap(): number
85
126
  }
86
127
 
87
128
  /**
@@ -96,6 +137,27 @@ export interface SelectCase<T> {
96
137
  onSelected?: (result: SelectResult<T>) => Promise<any>
97
138
  }
98
139
 
140
+ const selectVoidReturnMarker = '__goscriptSelectVoidReturn'
141
+
142
+ export interface SelectVoidReturn {
143
+ readonly [selectVoidReturnMarker]: true
144
+ }
145
+
146
+ export function selectVoidReturn(): SelectVoidReturn {
147
+ return { [selectVoidReturnMarker]: true }
148
+ }
149
+
150
+ function selectHandlerResult<V>(handlerResult: any): [boolean, V] {
151
+ if (
152
+ handlerResult &&
153
+ typeof handlerResult === 'object' &&
154
+ handlerResult[selectVoidReturnMarker] === true
155
+ ) {
156
+ return [true, undefined as V]
157
+ }
158
+ return [handlerResult !== undefined, handlerResult as V]
159
+ }
160
+
99
161
  /**
100
162
  * Helper for 'select' statements. Takes an array of select cases
101
163
  * and resolves when one of them completes, following Go's select rules.
@@ -151,13 +213,13 @@ export async function selectStatement<T, V = void>(
151
213
  const handlerResult = await selectedCase.onSelected(
152
214
  result as SelectResult<T>,
153
215
  )
154
- return [handlerResult !== undefined, handlerResult as V]
216
+ return selectHandlerResult<V>(handlerResult)
155
217
  }
156
218
  } else {
157
219
  const result = await selectedCase.channel.selectReceive(selectedCase.id)
158
220
  if (selectedCase.onSelected) {
159
221
  const handlerResult = await selectedCase.onSelected(result)
160
- return [handlerResult !== undefined, handlerResult as V]
222
+ return selectHandlerResult<V>(handlerResult)
161
223
  }
162
224
  }
163
225
  } else {
@@ -178,22 +240,27 @@ export async function selectStatement<T, V = void>(
178
240
  ok: false,
179
241
  id: -1,
180
242
  } as SelectResult<T>)
181
- return [handlerResult !== undefined, handlerResult as V]
243
+ return selectHandlerResult<V>(handlerResult)
182
244
  }
183
245
  return [false, undefined as V] // Return after executing the default case
184
246
  }
185
247
 
186
248
  // 3. If no operations are ready and no default case, block until one is ready
187
249
  // Use Promise.race on the blocking promises
250
+ const abort = new AbortController()
188
251
  const blockingPromises = cases
189
252
  .filter((c) => c.id !== -1) // Exclude default case
190
253
  .filter((c) => c.channel !== null) // Exclude nil channels (they would block forever)
191
254
  .map((caseObj) => {
192
255
  // At this point caseObj.channel is guaranteed to be non-null
193
256
  if (caseObj.isSend) {
194
- return caseObj.channel!.selectSend(caseObj.value, caseObj.id)
257
+ return caseObj.channel!.selectSend(
258
+ caseObj.value,
259
+ caseObj.id,
260
+ abort.signal,
261
+ )
195
262
  } else {
196
- return caseObj.channel!.selectReceive(caseObj.id)
263
+ return caseObj.channel!.selectReceive(caseObj.id, abort.signal)
197
264
  }
198
265
  })
199
266
 
@@ -204,11 +271,12 @@ export async function selectStatement<T, V = void>(
204
271
  }
205
272
 
206
273
  const result = await Promise.race(blockingPromises)
274
+ abort.abort()
207
275
  // Execute onSelected handler for the selected case
208
276
  const selectedCase = cases.find((c) => c.id === result.id)
209
277
  if (selectedCase && selectedCase.onSelected) {
210
278
  const handlerResult = await selectedCase.onSelected(result)
211
- return [handlerResult !== undefined, handlerResult as V]
279
+ return selectHandlerResult<V>(handlerResult)
212
280
  }
213
281
 
214
282
  // No explicit return needed here, as the function will implicitly return after the await
@@ -344,13 +412,14 @@ class BufferedChannel<T> implements Channel<T> {
344
412
  // Attempt to hand off to a waiting receiver (rendezvous)
345
413
  if (this.receivers.length > 0) {
346
414
  const receiverTask = this.receivers.shift()!
347
- queueMicrotask(() => receiverTask.resolveReceive(value))
348
- return
415
+ return completeUnbufferedReceive(receiverTask.resolveReceive, value)
349
416
  }
350
417
  if (this.receiversWithOk.length > 0) {
351
418
  const receiverTask = this.receiversWithOk.shift()!
352
- queueMicrotask(() => receiverTask.resolveReceive({ value, ok: true }))
353
- return
419
+ return completeUnbufferedReceiveWithOk(receiverTask.resolveReceive, {
420
+ value,
421
+ ok: true,
422
+ })
354
423
  }
355
424
 
356
425
  // If no waiting receivers, try to buffer if space is available
@@ -430,7 +499,10 @@ class BufferedChannel<T> implements Channel<T> {
430
499
  })
431
500
  }
432
501
 
433
- async selectReceive(id: number): Promise<SelectResult<T>> {
502
+ async selectReceive(
503
+ id: number,
504
+ signal?: AbortSignal,
505
+ ): Promise<SelectResult<T>> {
434
506
  if (this.buffer.length > 0) {
435
507
  const value = this.buffer.shift()!
436
508
  if (this.senders.length > 0) {
@@ -452,15 +524,43 @@ class BufferedChannel<T> implements Channel<T> {
452
524
  }
453
525
 
454
526
  return new Promise<SelectResult<T>>((resolve) => {
455
- this.receiversWithOk.push({
527
+ const state = { done: false }
528
+ const receiversWithOk = this.receiversWithOk
529
+ const task = {
456
530
  resolveReceive: (result: ChannelReceiveResult<T>) => {
457
- resolve({ ...result, id })
531
+ if (!state.done) {
532
+ state.done = true
533
+ cleanup()
534
+ resolve({ ...result, id })
535
+ }
458
536
  },
459
- })
537
+ }
538
+ function cleanup() {
539
+ signal?.removeEventListener('abort', onAbort)
540
+ const idx = receiversWithOk.indexOf(task)
541
+ if (idx >= 0) {
542
+ receiversWithOk.splice(idx, 1)
543
+ }
544
+ }
545
+ function onAbort() {
546
+ if (!state.done) {
547
+ state.done = true
548
+ cleanup()
549
+ }
550
+ }
551
+ if (signal?.aborted) {
552
+ return
553
+ }
554
+ signal?.addEventListener('abort', onAbort, { once: true })
555
+ this.receiversWithOk.push(task)
460
556
  })
461
557
  }
462
558
 
463
- async selectSend(value: T, id: number): Promise<SelectResult<boolean>> {
559
+ async selectSend(
560
+ value: T,
561
+ id: number,
562
+ signal?: AbortSignal,
563
+ ): Promise<SelectResult<boolean>> {
464
564
  if (this.closed) {
465
565
  // A select case sending on a closed channel panics in Go.
466
566
  // This will cause Promise.race in selectStatement to reject.
@@ -469,12 +569,15 @@ class BufferedChannel<T> implements Channel<T> {
469
569
 
470
570
  if (this.receivers.length > 0) {
471
571
  const receiverTask = this.receivers.shift()!
472
- queueMicrotask(() => receiverTask.resolveReceive(value))
572
+ await completeUnbufferedReceive(receiverTask.resolveReceive, value)
473
573
  return { value: true, ok: true, id }
474
574
  }
475
575
  if (this.receiversWithOk.length > 0) {
476
576
  const receiverTask = this.receiversWithOk.shift()!
477
- queueMicrotask(() => receiverTask.resolveReceive({ value, ok: true }))
577
+ await completeUnbufferedReceiveWithOk(receiverTask.resolveReceive, {
578
+ value,
579
+ ok: true,
580
+ })
478
581
  return { value: true, ok: true, id }
479
582
  }
480
583
 
@@ -484,11 +587,43 @@ class BufferedChannel<T> implements Channel<T> {
484
587
  }
485
588
 
486
589
  return new Promise<SelectResult<boolean>>((resolve, reject) => {
487
- this.senders.push({
590
+ const state = { done: false }
591
+ const senders = this.senders
592
+ const task = {
488
593
  value,
489
- resolveSend: () => resolve({ value: true, ok: true, id }),
490
- rejectSend: (e) => reject(e), // Propagate error if channel closes
491
- })
594
+ resolveSend: () => {
595
+ if (!state.done) {
596
+ state.done = true
597
+ cleanup()
598
+ resolve({ value: true, ok: true, id })
599
+ }
600
+ },
601
+ rejectSend: (e: Error) => {
602
+ if (!state.done) {
603
+ state.done = true
604
+ cleanup()
605
+ reject(e)
606
+ }
607
+ },
608
+ }
609
+ function cleanup() {
610
+ signal?.removeEventListener('abort', onAbort)
611
+ const idx = senders.indexOf(task)
612
+ if (idx >= 0) {
613
+ senders.splice(idx, 1)
614
+ }
615
+ }
616
+ function onAbort() {
617
+ if (!state.done) {
618
+ state.done = true
619
+ cleanup()
620
+ }
621
+ }
622
+ if (signal?.aborted) {
623
+ return
624
+ }
625
+ signal?.addEventListener('abort', onAbort, { once: true })
626
+ this.senders.push(task)
492
627
  })
493
628
  }
494
629
 
@@ -501,7 +636,7 @@ class BufferedChannel<T> implements Channel<T> {
501
636
  const sendersToNotify = [...this.senders] // Shallow copy for iteration
502
637
  this.senders = []
503
638
  for (const senderTask of sendersToNotify) {
504
- queueMicrotask(() =>
639
+ scheduleClosedChannelWake(() =>
505
640
  senderTask.rejectSend(new Error('send on closed channel')),
506
641
  )
507
642
  }
@@ -509,13 +644,15 @@ class BufferedChannel<T> implements Channel<T> {
509
644
  const receiversToNotify = [...this.receivers]
510
645
  this.receivers = []
511
646
  for (const receiverTask of receiversToNotify) {
512
- queueMicrotask(() => receiverTask.resolveReceive(this.zeroValue))
647
+ scheduleClosedChannelWake(() =>
648
+ receiverTask.resolveReceive(this.zeroValue),
649
+ )
513
650
  }
514
651
 
515
652
  const receiversWithOkToNotify = [...this.receiversWithOk]
516
653
  this.receiversWithOk = []
517
654
  for (const receiverTask of receiversWithOkToNotify) {
518
- queueMicrotask(() =>
655
+ scheduleClosedChannelWake(() =>
519
656
  receiverTask.resolveReceive({ value: this.zeroValue, ok: false }),
520
657
  )
521
658
  }
@@ -539,6 +676,10 @@ class BufferedChannel<T> implements Channel<T> {
539
676
  len(): number {
540
677
  return this.buffer.length
541
678
  }
679
+
680
+ cap(): number {
681
+ return this.capacity
682
+ }
542
683
  }
543
684
 
544
685
  /**
@@ -562,9 +703,14 @@ export interface ChannelRef<T> {
562
703
  close(): void
563
704
  canSendNonBlocking(): boolean
564
705
  canReceiveNonBlocking(): boolean
565
- selectSend(value: T, id: number): Promise<SelectResult<boolean>>
566
- selectReceive(id: number): Promise<SelectResult<T>>
706
+ selectSend(
707
+ value: T,
708
+ id: number,
709
+ signal?: AbortSignal,
710
+ ): Promise<SelectResult<boolean>>
711
+ selectReceive(id: number, signal?: AbortSignal): Promise<SelectResult<T>>
567
712
  len(): number
713
+ cap(): number
568
714
  }
569
715
 
570
716
  /**
@@ -600,17 +746,25 @@ export class BidirectionalChannelRef<T> implements ChannelRef<T> {
600
746
  return this.channel.canReceiveNonBlocking()
601
747
  }
602
748
 
603
- selectSend(value: T, id: number): Promise<SelectResult<boolean>> {
604
- return this.channel.selectSend(value, id)
749
+ selectSend(
750
+ value: T,
751
+ id: number,
752
+ signal?: AbortSignal,
753
+ ): Promise<SelectResult<boolean>> {
754
+ return this.channel.selectSend(value, id, signal)
605
755
  }
606
756
 
607
- selectReceive(id: number): Promise<SelectResult<T>> {
608
- return this.channel.selectReceive(id)
757
+ selectReceive(id: number, signal?: AbortSignal): Promise<SelectResult<T>> {
758
+ return this.channel.selectReceive(id, signal)
609
759
  }
610
760
 
611
761
  len(): number {
612
762
  return this.channel.len()
613
763
  }
764
+
765
+ cap(): number {
766
+ return this.channel.cap()
767
+ }
614
768
  }
615
769
 
616
770
  /**
@@ -635,8 +789,12 @@ export class SendOnlyChannelRef<T> implements ChannelRef<T> {
635
789
  return this.channel.canSendNonBlocking()
636
790
  }
637
791
 
638
- selectSend(value: T, id: number): Promise<SelectResult<boolean>> {
639
- return this.channel.selectSend(value, id)
792
+ selectSend(
793
+ value: T,
794
+ id: number,
795
+ signal?: AbortSignal,
796
+ ): Promise<SelectResult<boolean>> {
797
+ return this.channel.selectSend(value, id, signal)
640
798
  }
641
799
 
642
800
  // Disallow receive operations
@@ -652,13 +810,17 @@ export class SendOnlyChannelRef<T> implements ChannelRef<T> {
652
810
  return false
653
811
  }
654
812
 
655
- selectReceive(_id: number): Promise<SelectResult<T>> {
813
+ selectReceive(_id: number, _signal?: AbortSignal): Promise<SelectResult<T>> {
656
814
  throw new Error('Cannot receive from send-only channel')
657
815
  }
658
816
 
659
817
  len(): number {
660
818
  return this.channel.len()
661
819
  }
820
+
821
+ cap(): number {
822
+ return this.channel.cap()
823
+ }
662
824
  }
663
825
 
664
826
  /**
@@ -682,8 +844,8 @@ export class ReceiveOnlyChannelRef<T> implements ChannelRef<T> {
682
844
  return this.channel.canReceiveNonBlocking()
683
845
  }
684
846
 
685
- selectReceive(id: number): Promise<SelectResult<T>> {
686
- return this.channel.selectReceive(id)
847
+ selectReceive(id: number, signal?: AbortSignal): Promise<SelectResult<T>> {
848
+ return this.channel.selectReceive(id, signal)
687
849
  }
688
850
 
689
851
  // Disallow send operations
@@ -700,13 +862,21 @@ export class ReceiveOnlyChannelRef<T> implements ChannelRef<T> {
700
862
  return false
701
863
  }
702
864
 
703
- selectSend(_value: T, _id: number): Promise<SelectResult<boolean>> {
865
+ selectSend(
866
+ _value: T,
867
+ _id: number,
868
+ _signal?: AbortSignal,
869
+ ): Promise<SelectResult<boolean>> {
704
870
  throw new Error('Cannot send to receive-only channel')
705
871
  }
706
872
 
707
873
  len(): number {
708
874
  return this.channel.len()
709
875
  }
876
+
877
+ cap(): number {
878
+ return this.channel.cap()
879
+ }
710
880
  }
711
881
 
712
882
  /**
@@ -51,8 +51,19 @@ export class AsyncDisposableStack implements AsyncDisposable {
51
51
  */
52
52
  async [Symbol.asyncDispose](): Promise<void> {
53
53
  // Execute in LIFO order, awaiting each potentially async function
54
- for (let i = this.stack.length - 1; i >= 0; --i) {
55
- await this.stack[i]()
54
+ while (this.stack.length) {
55
+ const fn = this.stack.pop()!
56
+ await fn()
57
+ }
58
+ }
59
+
60
+ [Symbol.dispose](): void {
61
+ while (this.stack.length) {
62
+ const fn = this.stack.pop()!
63
+ const result = fn()
64
+ if (result && typeof (result as Promise<void>).then === "function") {
65
+ throw new Error("async deferred function disposed synchronously")
66
+ }
56
67
  }
57
68
  }
58
69
  }
@@ -36,6 +36,7 @@ function runtimeFixture(platform: string): HostRuntime {
36
36
  deno: null,
37
37
  getEnv: () => '',
38
38
  getStdioHandle: () => null,
39
+ nodeCrypto: null,
39
40
  nodeFS: null,
40
41
  platform,
41
42
  processObj: null,
@@ -54,6 +54,16 @@ export type NodeFSModule = {
54
54
  ): void
55
55
  }
56
56
 
57
+ export type NodeCryptoHash = {
58
+ copy?(): NodeCryptoHash
59
+ update(data: Uint8Array): NodeCryptoHash
60
+ digest(): Uint8Array
61
+ }
62
+
63
+ export type NodeCryptoModule = {
64
+ createHash(algorithm: string): NodeCryptoHash
65
+ }
66
+
57
67
  export type DenoStream = {
58
68
  readSync?(buffer: Uint8Array): number | null
59
69
  writeSync?(buffer: Uint8Array): number
@@ -74,6 +84,7 @@ type HostTextWrite = (data: string) => void
74
84
 
75
85
  export type HostRuntime = {
76
86
  deno: any | null
87
+ nodeCrypto: NodeCryptoModule | null
77
88
  nodeFS: NodeFSModule | null
78
89
  platform: string
79
90
  processObj: any | null
@@ -166,6 +177,31 @@ function detectNodeFS(processObj: any | null): NodeFSModule | null {
166
177
  return null
167
178
  }
168
179
 
180
+ function detectNodeCrypto(processObj: any | null): NodeCryptoModule | null {
181
+ if (processObj && typeof processObj.getBuiltinModule === 'function') {
182
+ const module = processObj.getBuiltinModule('crypto')
183
+ if (module && typeof module.createHash === 'function') {
184
+ return module as NodeCryptoModule
185
+ }
186
+ }
187
+
188
+ const requireFn = getDynamicRequire()
189
+ if (requireFn) {
190
+ for (const specifier of ['node:crypto', 'crypto']) {
191
+ try {
192
+ const module = requireFn(specifier) as NodeCryptoModule | null
193
+ if (module && typeof module.createHash === 'function') {
194
+ return module
195
+ }
196
+ } catch {
197
+ // Try the next fallback.
198
+ }
199
+ }
200
+ }
201
+
202
+ return null
203
+ }
204
+
169
205
  function hasURLScheme(path: string): boolean {
170
206
  return /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(path)
171
207
  }
@@ -247,6 +283,7 @@ function detectHostRuntime(): HostRuntime {
247
283
  const deno = globalObj.Deno ?? null
248
284
  const processObj = globalObj.process ?? null
249
285
  const nodeFS = detectNodeFS(processObj)
286
+ const nodeCrypto = detectNodeCrypto(processObj)
250
287
 
251
288
  const getStdioHandle = (fd: number): DenoFileLike | null => {
252
289
  if (!deno) {
@@ -344,6 +381,7 @@ function detectHostRuntime(): HostRuntime {
344
381
  deno,
345
382
  getEnv,
346
383
  getStdioHandle,
384
+ nodeCrypto,
347
385
  nodeFS,
348
386
  platform,
349
387
  processObj,
package/gs/builtin/map.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import { comparableEqual } from './builtin.js'
2
+ import { GoBinaryString, stringEqual } from './slice.js'
3
+
1
4
  /**
2
5
  * Creates a new map (TypeScript Map).
3
6
  * @returns A new TypeScript Map.
@@ -18,9 +21,9 @@ export function mapGet<K, V, D>(
18
21
  key: K,
19
22
  defaultValue: D,
20
23
  ): [V, true] | [D, false] {
21
- const exists = map?.has(key)
22
- if (exists) {
23
- return [map!.get(key)!, true]
24
+ const entry = findMapEntry(map, key)
25
+ if (entry.found) {
26
+ return [entry.value, true]
24
27
  } else {
25
28
  return [defaultValue, false]
26
29
  }
@@ -36,7 +39,8 @@ export const mapSet = <K, V>(map: Map<K, V> | null, key: K, value: V): void => {
36
39
  if (!map) {
37
40
  throw new Error('assign to nil map')
38
41
  }
39
- map.set(key, value)
42
+ const entry = findMapEntry(map, key)
43
+ map.set(entry.found ? entry.key : key, value)
40
44
  }
41
45
 
42
46
  /**
@@ -45,7 +49,10 @@ export const mapSet = <K, V>(map: Map<K, V> | null, key: K, value: V): void => {
45
49
  * @param key The key to delete.
46
50
  */
47
51
  export const deleteMapEntry = <K, V>(map: Map<K, V> | null, key: K): void => {
48
- map?.delete(key)
52
+ const entry = findMapEntry(map, key)
53
+ if (entry.found) {
54
+ map!.delete(entry.key)
55
+ }
49
56
  }
50
57
 
51
58
  /**
@@ -55,5 +62,38 @@ export const deleteMapEntry = <K, V>(map: Map<K, V> | null, key: K): void => {
55
62
  * @returns True if the key exists, false otherwise.
56
63
  */
57
64
  export const mapHas = <K, V>(map: Map<K, V> | null, key: K): boolean => {
58
- return map?.has(key) ?? false
65
+ return findMapEntry(map, key).found
66
+ }
67
+
68
+ function findMapEntry<K, V>(
69
+ map: Map<K, V> | null,
70
+ key: K,
71
+ ): { found: false } | { found: true; key: K; value: V } {
72
+ if (!map) {
73
+ return { found: false }
74
+ }
75
+ if (map.has(key)) {
76
+ return { found: true, key, value: map.get(key)! }
77
+ }
78
+ if (isGoStringKey(key)) {
79
+ for (const [candidate, value] of map.entries()) {
80
+ if (isGoStringKey(candidate) && stringEqual(candidate as string, key as string)) {
81
+ return { found: true, key: candidate, value }
82
+ }
83
+ }
84
+ return { found: false }
85
+ }
86
+ if (key === null || (typeof key !== 'object' && typeof key !== 'function')) {
87
+ return { found: false }
88
+ }
89
+ for (const [candidate, value] of map.entries()) {
90
+ if (candidate !== key && comparableEqual(candidate, key)) {
91
+ return { found: true, key: candidate, value }
92
+ }
93
+ }
94
+ return { found: false }
95
+ }
96
+
97
+ function isGoStringKey(value: unknown): value is string | GoBinaryString {
98
+ return typeof value === 'string' || value instanceof GoBinaryString
59
99
  }
@@ -68,7 +68,10 @@ function formatValue(
68
68
  try {
69
69
  if (value instanceof Map) {
70
70
  return formatArray(
71
- Array.from(value.entries()).map(([k, v]) => `${formatValue(k, depth + 1, true, seen)} => ${formatValue(v, depth + 1, true, seen)}`),
71
+ Array.from(value.entries()).map(
72
+ ([k, v]) =>
73
+ `${formatValue(k, depth + 1, true, seen)} => ${formatValue(v, depth + 1, true, seen)}`,
74
+ ),
72
75
  depth,
73
76
  seen,
74
77
  )
@@ -113,7 +116,11 @@ function formatUint8Array(value: Uint8Array): string {
113
116
  return `Uint8Array(${value.length}) [ ${Array.from(value).join(', ')} ]`
114
117
  }
115
118
 
116
- function formatArray(value: readonly any[], depth: number, seen: WeakSet<object>): string {
119
+ function formatArray(
120
+ value: readonly any[],
121
+ depth: number,
122
+ seen: WeakSet<object>,
123
+ ): string {
117
124
  if (value.length === 0) {
118
125
  return '[]'
119
126
  }
@@ -150,5 +157,7 @@ function getObjectEntries(value: Record<string, any>): [string, any][] {
150
157
  })
151
158
  }
152
159
 
153
- return Object.entries(value).filter(([, entry]) => typeof entry !== 'function')
160
+ return Object.entries(value).filter(
161
+ ([, entry]) => typeof entry !== 'function',
162
+ )
154
163
  }