goscript 0.2.6 → 0.2.7

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 (264) hide show
  1. package/cmd/goscript/cmd-compile.go +7 -0
  2. package/cmd/goscript/cmd_compile_test.go +83 -0
  3. package/compiler/compile-request.go +3 -0
  4. package/compiler/compiler-cache.go +828 -0
  5. package/compiler/compiler-cache_test.go +705 -0
  6. package/compiler/config.go +2 -0
  7. package/compiler/index.test.ts +26 -1
  8. package/compiler/index.ts +5 -0
  9. package/compiler/lowered-program.go +31 -20
  10. package/compiler/lowering.go +349 -93
  11. package/compiler/lowering_bench_test.go +1 -0
  12. package/compiler/override-facts.go +309 -8
  13. package/compiler/override-parity-verifier.go +45 -1
  14. package/compiler/override-parity-verifier_test.go +100 -0
  15. package/compiler/override-registry_test.go +1 -0
  16. package/compiler/package-graph.go +40 -12
  17. package/compiler/package-graph_test.go +29 -0
  18. package/compiler/runtime-contract.go +8 -0
  19. package/compiler/service.go +98 -11
  20. package/compiler/skeleton_test.go +110 -14
  21. package/compiler/typescript-emitter.go +120 -23
  22. package/dist/compiler/index.d.ts +2 -0
  23. package/dist/compiler/index.js +3 -0
  24. package/dist/compiler/index.js.map +1 -1
  25. package/dist/gs/builtin/builtin.d.ts +24 -33
  26. package/dist/gs/builtin/builtin.js +54 -61
  27. package/dist/gs/builtin/builtin.js.map +1 -1
  28. package/dist/gs/builtin/hostio.d.ts +1 -0
  29. package/dist/gs/builtin/hostio.js +1 -1
  30. package/dist/gs/builtin/hostio.js.map +1 -1
  31. package/dist/gs/builtin/index.d.ts +1 -0
  32. package/dist/gs/builtin/index.js +1 -0
  33. package/dist/gs/builtin/index.js.map +1 -1
  34. package/dist/gs/builtin/panic.d.ts +18 -0
  35. package/dist/gs/builtin/panic.js +98 -0
  36. package/dist/gs/builtin/panic.js.map +1 -0
  37. package/dist/gs/builtin/slice.d.ts +10 -0
  38. package/dist/gs/builtin/slice.js +110 -53
  39. package/dist/gs/builtin/slice.js.map +1 -1
  40. package/dist/gs/builtin/type.js +15 -3
  41. package/dist/gs/builtin/type.js.map +1 -1
  42. package/dist/gs/builtin/varRef.d.ts +1 -1
  43. package/dist/gs/builtin/varRef.js +3 -2
  44. package/dist/gs/builtin/varRef.js.map +1 -1
  45. package/dist/gs/bytes/bytes.gs.js +51 -38
  46. package/dist/gs/bytes/bytes.gs.js.map +1 -1
  47. package/dist/gs/bytes/reader.gs.d.ts +1 -1
  48. package/dist/gs/bytes/reader.gs.js +6 -7
  49. package/dist/gs/bytes/reader.gs.js.map +1 -1
  50. package/dist/gs/cmp/index.d.ts +1 -1
  51. package/dist/gs/cmp/index.js +43 -10
  52. package/dist/gs/cmp/index.js.map +1 -1
  53. package/dist/gs/context/context.d.ts +2 -2
  54. package/dist/gs/context/context.js +1 -1
  55. package/dist/gs/context/context.js.map +1 -1
  56. package/dist/gs/embed/index.js +1 -1
  57. package/dist/gs/embed/index.js.map +1 -1
  58. package/dist/gs/encoding/binary/index.js +201 -8
  59. package/dist/gs/encoding/binary/index.js.map +1 -1
  60. package/dist/gs/encoding/json/index.d.ts +5 -0
  61. package/dist/gs/encoding/json/index.js +388 -25
  62. package/dist/gs/encoding/json/index.js.map +1 -1
  63. package/dist/gs/errors/errors.js +17 -24
  64. package/dist/gs/errors/errors.js.map +1 -1
  65. package/dist/gs/fmt/fmt.js +129 -35
  66. package/dist/gs/fmt/fmt.js.map +1 -1
  67. package/dist/gs/golang.org/x/crypto/cryptobyte/index.js +1 -1
  68. package/dist/gs/golang.org/x/crypto/cryptobyte/index.js.map +1 -1
  69. package/dist/gs/internal/bytealg/index.js +43 -8
  70. package/dist/gs/internal/bytealg/index.js.map +1 -1
  71. package/dist/gs/internal/byteorder/index.d.ts +2 -2
  72. package/dist/gs/internal/byteorder/index.js +2 -2
  73. package/dist/gs/internal/byteorder/index.js.map +1 -1
  74. package/dist/gs/io/fs/format.js +2 -2
  75. package/dist/gs/io/fs/format.js.map +1 -1
  76. package/dist/gs/io/fs/fs.d.ts +1 -1
  77. package/dist/gs/io/fs/fs.js +1 -1
  78. package/dist/gs/io/fs/fs.js.map +1 -1
  79. package/dist/gs/io/io.d.ts +21 -21
  80. package/dist/gs/io/io.js +49 -50
  81. package/dist/gs/io/io.js.map +1 -1
  82. package/dist/gs/math/bits/index.js +26 -8
  83. package/dist/gs/math/bits/index.js.map +1 -1
  84. package/dist/gs/math/copysign.gs.js +10 -17
  85. package/dist/gs/math/copysign.gs.js.map +1 -1
  86. package/dist/gs/math/pow.gs.js +5 -0
  87. package/dist/gs/math/pow.gs.js.map +1 -1
  88. package/dist/gs/math/signbit.gs.js +6 -2
  89. package/dist/gs/math/signbit.gs.js.map +1 -1
  90. package/dist/gs/mime/index.js +1 -0
  91. package/dist/gs/mime/index.js.map +1 -1
  92. package/dist/gs/net/http/index.d.ts +6 -6
  93. package/dist/gs/net/http/index.js +507 -43
  94. package/dist/gs/net/http/index.js.map +1 -1
  95. package/dist/gs/os/stat.gs.d.ts +2 -2
  96. package/dist/gs/os/types.gs.d.ts +1 -1
  97. package/dist/gs/os/types.gs.js +1 -1
  98. package/dist/gs/os/types.gs.js.map +1 -1
  99. package/dist/gs/os/types_js.gs.d.ts +1 -1
  100. package/dist/gs/os/types_js.gs.js +7 -7
  101. package/dist/gs/os/types_js.gs.js.map +1 -1
  102. package/dist/gs/os/types_unix.gs.d.ts +1 -1
  103. package/dist/gs/os/types_unix.gs.js +1 -1
  104. package/dist/gs/os/types_unix.gs.js.map +1 -1
  105. package/dist/gs/os/zero_copy_posix.gs.d.ts +1 -1
  106. package/dist/gs/os/zero_copy_posix.gs.js +1 -1
  107. package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
  108. package/dist/gs/path/filepath/match.js +8 -4
  109. package/dist/gs/path/filepath/match.js.map +1 -1
  110. package/dist/gs/path/filepath/path.js +216 -42
  111. package/dist/gs/path/filepath/path.js.map +1 -1
  112. package/dist/gs/path/match.js +6 -3
  113. package/dist/gs/path/match.js.map +1 -1
  114. package/dist/gs/reflect/type.d.ts +5 -4
  115. package/dist/gs/reflect/type.js +29 -11
  116. package/dist/gs/reflect/type.js.map +1 -1
  117. package/dist/gs/slices/slices.js +11 -11
  118. package/dist/gs/slices/slices.js.map +1 -1
  119. package/dist/gs/strconv/atof.gs.js +156 -43
  120. package/dist/gs/strconv/atof.gs.js.map +1 -1
  121. package/dist/gs/strconv/atoi.gs.d.ts +3 -2
  122. package/dist/gs/strconv/atoi.gs.js +86 -67
  123. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  124. package/dist/gs/strconv/ftoa.gs.js +73 -3
  125. package/dist/gs/strconv/ftoa.gs.js.map +1 -1
  126. package/dist/gs/strconv/itoa.gs.d.ts +4 -4
  127. package/dist/gs/strconv/itoa.gs.js +5 -4
  128. package/dist/gs/strconv/itoa.gs.js.map +1 -1
  129. package/dist/gs/strconv/quote.gs.d.ts +1 -1
  130. package/dist/gs/strconv/quote.gs.js +311 -103
  131. package/dist/gs/strconv/quote.gs.js.map +1 -1
  132. package/dist/gs/strings/reader.d.ts +1 -1
  133. package/dist/gs/strings/reader.js +8 -8
  134. package/dist/gs/strings/reader.js.map +1 -1
  135. package/dist/gs/strings/strings.js +87 -61
  136. package/dist/gs/strings/strings.js.map +1 -1
  137. package/dist/gs/sync/atomic/doc_64.gs.d.ts +14 -14
  138. package/dist/gs/sync/atomic/doc_64.gs.js +10 -10
  139. package/dist/gs/sync/atomic/doc_64.gs.js.map +1 -1
  140. package/dist/gs/sync/atomic/type.gs.d.ts +22 -22
  141. package/dist/gs/sync/atomic/type.gs.js +4 -4
  142. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  143. package/dist/gs/sync/sync.js +50 -12
  144. package/dist/gs/sync/sync.js.map +1 -1
  145. package/dist/gs/syscall/fs.d.ts +6 -6
  146. package/dist/gs/syscall/fs.js +1 -1
  147. package/dist/gs/syscall/fs.js.map +1 -1
  148. package/dist/gs/time/time.d.ts +18 -18
  149. package/dist/gs/time/time.js +58 -55
  150. package/dist/gs/time/time.js.map +1 -1
  151. package/dist/gs/unicode/tables.d.ts +11 -0
  152. package/dist/gs/unicode/tables.js +635 -0
  153. package/dist/gs/unicode/tables.js.map +1 -0
  154. package/dist/gs/unicode/unicode.d.ts +58 -38
  155. package/dist/gs/unicode/unicode.js +362 -278
  156. package/dist/gs/unicode/unicode.js.map +1 -1
  157. package/go.sum +13 -0
  158. package/gs/builtin/builtin.ts +83 -93
  159. package/gs/builtin/hostio.ts +1 -1
  160. package/gs/builtin/index.ts +1 -0
  161. package/gs/builtin/panic.test.ts +189 -0
  162. package/gs/builtin/panic.ts +107 -0
  163. package/gs/builtin/runtime-contract.test.ts +5 -5
  164. package/gs/builtin/slice.test.ts +23 -0
  165. package/gs/builtin/slice.ts +133 -95
  166. package/gs/builtin/type.ts +16 -3
  167. package/gs/builtin/varRef.ts +4 -2
  168. package/gs/builtin/wide-int.test.ts +41 -0
  169. package/gs/bytes/bytes.gs.ts +54 -41
  170. package/gs/bytes/bytes.test.ts +18 -1
  171. package/gs/bytes/reader.gs.ts +7 -8
  172. package/gs/cmp/index.test.ts +55 -0
  173. package/gs/cmp/index.ts +45 -9
  174. package/gs/context/context.ts +3 -3
  175. package/gs/embed/index.ts +2 -2
  176. package/gs/encoding/binary/index.test.ts +104 -0
  177. package/gs/encoding/binary/index.ts +259 -11
  178. package/gs/encoding/json/index.test.ts +107 -0
  179. package/gs/encoding/json/index.ts +400 -29
  180. package/gs/errors/errors.test.ts +44 -1
  181. package/gs/errors/errors.ts +15 -31
  182. package/gs/fmt/fmt.test.ts +70 -2
  183. package/gs/fmt/fmt.ts +128 -34
  184. package/gs/golang.org/x/crypto/cryptobyte/index.ts +1 -1
  185. package/gs/internal/bytealg/index.test.ts +26 -1
  186. package/gs/internal/bytealg/index.ts +44 -8
  187. package/gs/internal/byteorder/index.ts +6 -4
  188. package/gs/io/fs/format.ts +2 -2
  189. package/gs/io/fs/fs.ts +2 -2
  190. package/gs/io/fs/stat.test.ts +2 -2
  191. package/gs/io/fs/sub.test.ts +2 -2
  192. package/gs/io/fs/walk.test.ts +2 -2
  193. package/gs/io/io.test.ts +47 -5
  194. package/gs/io/io.ts +73 -73
  195. package/gs/io/limit.test.ts +103 -0
  196. package/gs/math/bits/index.test.ts +128 -0
  197. package/gs/math/bits/index.ts +26 -8
  198. package/gs/math/copysign.gs.test.ts +3 -1
  199. package/gs/math/copysign.gs.ts +10 -22
  200. package/gs/math/pow.gs.test.ts +4 -5
  201. package/gs/math/pow.gs.ts +5 -0
  202. package/gs/math/signbit.gs.test.ts +2 -1
  203. package/gs/math/signbit.gs.ts +6 -3
  204. package/gs/mime/index.ts +1 -0
  205. package/gs/net/http/index.test.ts +683 -2
  206. package/gs/net/http/index.ts +598 -57
  207. package/gs/net/http/meta.json +3 -0
  208. package/gs/os/stat.gs.ts +2 -2
  209. package/gs/os/types.gs.ts +2 -2
  210. package/gs/os/types_js.gs.ts +9 -9
  211. package/gs/os/types_unix.gs.ts +2 -2
  212. package/gs/os/zero_copy_posix.gs.ts +2 -2
  213. package/gs/path/filepath/match.test.ts +16 -0
  214. package/gs/path/filepath/match.ts +8 -4
  215. package/gs/path/filepath/path.test.ts +91 -9
  216. package/gs/path/filepath/path.ts +223 -49
  217. package/gs/path/match.test.ts +32 -0
  218. package/gs/path/match.ts +6 -3
  219. package/gs/reflect/deepequal.test.ts +1 -1
  220. package/gs/reflect/field.test.ts +1 -1
  221. package/gs/reflect/function-types.test.ts +6 -6
  222. package/gs/reflect/sliceat.test.ts +13 -13
  223. package/gs/reflect/structof.test.ts +4 -4
  224. package/gs/reflect/type.ts +34 -14
  225. package/gs/reflect/typefor.test.ts +5 -5
  226. package/gs/runtime/pprof/index.test.ts +20 -0
  227. package/gs/runtime/trace/index.test.ts +3 -0
  228. package/gs/slices/slices.test.ts +31 -0
  229. package/gs/slices/slices.ts +11 -11
  230. package/gs/strconv/append.test.ts +99 -0
  231. package/gs/strconv/atof.gs.ts +156 -42
  232. package/gs/strconv/atof.test.ts +45 -0
  233. package/gs/strconv/atoi.gs.ts +87 -69
  234. package/gs/strconv/atoi.test.ts +49 -0
  235. package/gs/strconv/ftoa.gs.ts +85 -10
  236. package/gs/strconv/ftoa.test.ts +43 -0
  237. package/gs/strconv/itoa.gs.ts +10 -9
  238. package/gs/strconv/quote.gs.ts +335 -108
  239. package/gs/strconv/quote.test.ts +111 -0
  240. package/gs/strings/reader.test.ts +10 -10
  241. package/gs/strings/reader.ts +9 -9
  242. package/gs/strings/strings.test.ts +18 -5
  243. package/gs/strings/strings.ts +81 -68
  244. package/gs/sync/atomic/doc_64.gs.ts +24 -24
  245. package/gs/sync/atomic/doc_64.test.ts +5 -5
  246. package/gs/sync/atomic/type.gs.ts +28 -28
  247. package/gs/sync/sync.test.ts +109 -1
  248. package/gs/sync/sync.ts +46 -12
  249. package/gs/syscall/fs.ts +8 -8
  250. package/gs/syscall/net.test.ts +1 -1
  251. package/gs/time/parse.test.ts +45 -0
  252. package/gs/time/time.test.ts +46 -23
  253. package/gs/time/time.ts +69 -66
  254. package/gs/unicode/gen.go +198 -0
  255. package/gs/unicode/tables.ts +646 -0
  256. package/gs/unicode/unicode.test.ts +69 -0
  257. package/gs/unicode/unicode.ts +396 -312
  258. package/package.json +1 -1
  259. package/dist/gs/github.com/aperturerobotics/util/conc/index.d.ts +0 -20
  260. package/dist/gs/github.com/aperturerobotics/util/conc/index.js +0 -134
  261. package/dist/gs/github.com/aperturerobotics/util/conc/index.js.map +0 -1
  262. package/gs/github.com/aperturerobotics/util/conc/index.test.ts +0 -30
  263. package/gs/github.com/aperturerobotics/util/conc/index.ts +0 -172
  264. package/gs/github.com/aperturerobotics/util/conc/meta.json +0 -9
@@ -638,22 +638,19 @@ export function ToTitle(s: $.Bytes): $.Bytes {
638
638
  // ToUpperSpecial treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their
639
639
  // upper case, giving priority to the special casing rules.
640
640
  export function ToUpperSpecial(c: unicode.SpecialCase, s: $.Bytes): $.Bytes {
641
- // For now, ignore special case and fall back to regular ToUpper
642
- return ToUpper(s)
641
+ return Map((r) => c.ToUpper(r), s)
643
642
  }
644
643
 
645
644
  // ToLowerSpecial treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their
646
645
  // lower case, giving priority to the special casing rules.
647
646
  export function ToLowerSpecial(c: unicode.SpecialCase, s: $.Bytes): $.Bytes {
648
- // For now, ignore special case and fall back to regular ToLower
649
- return ToLower(s)
647
+ return Map((r) => c.ToLower(r), s)
650
648
  }
651
649
 
652
650
  // ToTitleSpecial treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their
653
651
  // title case, giving priority to the special casing rules.
654
652
  export function ToTitleSpecial(c: unicode.SpecialCase, s: $.Bytes): $.Bytes {
655
- // For now, ignore special case and fall back to regular ToTitle
656
- return ToTitle(s)
653
+ return Map((r) => c.ToTitle(r), s)
657
654
  }
658
655
 
659
656
  // ToValidUTF8 treats s as UTF-8-encoded bytes and returns a copy with each run of bytes
@@ -1124,38 +1121,40 @@ export function Replace(s: $.Bytes, old: $.Bytes, _new: $.Bytes, n: number): $.B
1124
1121
  return new Uint8Array($.bytesToArray(s))
1125
1122
  }
1126
1123
 
1127
- // Handle empty old pattern - replace at beginning and after each UTF-8 sequence
1124
+ // Handle empty old pattern - matches at the start and after each UTF-8
1125
+ // sequence, yielding up to runeCount+1 insertions. After the insertion
1126
+ // limit is reached the untouched remainder of s is appended, as in Go.
1128
1127
  if (old === null || $.len(old) === 0) {
1129
1128
  const result: number[] = []
1130
1129
  const newBytes = _new === null ? [] : $.bytesToArray(_new)
1131
-
1132
- // Add replacement at beginning
1133
- if (n !== 0) {
1134
- result.push(...newBytes)
1135
- if (n > 0) n--
1136
- }
1137
-
1138
- // Add replacement after each UTF-8 sequence
1139
- for (let i = 0; i < $.len(s) && n !== 0; ) {
1130
+
1131
+ // Count runes to bound n the way Go's Count does for an empty pattern.
1132
+ let runeCount = 0
1133
+ for (let i = 0; i < $.len(s); ) {
1140
1134
  const [, size] = utf8.DecodeRune($.goSlice(s, i, undefined))
1141
- if (size <= 0) {
1142
- result.push(s![i])
1143
- i++
1144
- } else {
1145
- // Add the rune bytes
1146
- for (let j = 0; j < size; j++) {
1147
- result.push(s![i + j])
1135
+ i += size > 0 ? size : 1
1136
+ runeCount++
1137
+ }
1138
+ const limit = n < 0 ? runeCount + 1 : Math.min(n, runeCount + 1)
1139
+
1140
+ let start = 0
1141
+ for (let ins = 0; ins < limit; ins++) {
1142
+ if (ins > 0) {
1143
+ const [, size] = utf8.DecodeRune($.goSlice(s, start, undefined))
1144
+ const wid = size > 0 ? size : 1
1145
+ for (let j = 0; j < wid; j++) {
1146
+ result.push(s![start + j])
1148
1147
  }
1149
- i += size
1150
- }
1151
-
1152
- // Add replacement after this rune
1153
- if (n !== 0) {
1154
- result.push(...newBytes)
1155
- if (n > 0) n--
1148
+ start += wid
1156
1149
  }
1150
+ result.push(...newBytes)
1157
1151
  }
1158
-
1152
+
1153
+ // Append the untouched remainder after the last insertion.
1154
+ for (let j = start; j < $.len(s); j++) {
1155
+ result.push(s![j])
1156
+ }
1157
+
1159
1158
  return new Uint8Array(result)
1160
1159
  }
1161
1160
 
@@ -1226,18 +1225,32 @@ export function EqualFold(s: $.Bytes, t: $.Bytes): boolean {
1226
1225
  if (s![si] !== t![ti]) return false
1227
1226
  si++
1228
1227
  ti++
1229
- } else {
1230
- // Convert both to lowercase for comparison
1231
- const sLower = unicode.ToLower(sr)
1232
- const tLower = unicode.ToLower(tr)
1233
-
1234
- if (sLower !== tLower) return false
1235
-
1236
- si += ssize
1237
- ti += tsize
1228
+ continue
1229
+ }
1230
+ si += ssize
1231
+ ti += tsize
1232
+ let a = sr
1233
+ let b = tr
1234
+ if (a === b) continue
1235
+ if (b < a) {
1236
+ const tmp = a
1237
+ a = b
1238
+ b = tmp
1238
1239
  }
1240
+ if (b < 0x80) {
1241
+ // ASCII: a and b match only as the same letter in opposite case.
1242
+ if (a >= 0x41 && a <= 0x5a && b === a + 0x20) continue
1243
+ return false
1244
+ }
1245
+ // Walk the simple-fold orbit of the smaller rune toward the larger.
1246
+ let r = unicode.SimpleFold(a)
1247
+ while (r !== a && r < b) {
1248
+ r = unicode.SimpleFold(r)
1249
+ }
1250
+ if (r === b) continue
1251
+ return false
1239
1252
  }
1240
-
1253
+
1241
1254
  return si === $.len(s) && ti === $.len(t)
1242
1255
  }
1243
1256
 
@@ -1,8 +1,25 @@
1
1
  import * as $ from '@goscript/builtin/index.js'
2
- import { IndexFunc } from './index.js'
2
+ import { IndexFunc, Replace } from './index.js'
3
3
  import { describe, expect, test } from 'vitest'
4
4
 
5
+ const rep = (s: string, old: string, n: string, count: number): string =>
6
+ $.bytesToString(
7
+ Replace(
8
+ $.stringToBytes(s),
9
+ $.stringToBytes(old),
10
+ $.stringToBytes(n),
11
+ count,
12
+ ),
13
+ )
14
+
5
15
  describe('bytes', () => {
16
+ test('Replace with empty old appends the untouched remainder', () => {
17
+ // Go: bytes.Replace([]byte("abc"), []byte(""), []byte("-"), 2) => "-a-bc".
18
+ expect(rep('abc', '', '-', 2)).toBe('-a-bc')
19
+ expect(rep('abc', '', '-', -1)).toBe('-a-b-c-')
20
+ expect(rep('aaa', 'a', 'b', -1)).toBe('bbb')
21
+ })
22
+
6
23
  test('IndexFunc accepts generated async-shaped callbacks', () => {
7
24
  const predicate: (r: number) => boolean | Promise<boolean> = (r) =>
8
25
  r === 0x62
@@ -160,29 +160,28 @@ export class Reader {
160
160
  }
161
161
 
162
162
  // Seek implements the [io.Seeker] interface.
163
- public Seek(offset: number, whence: number): [number, $.GoError] {
163
+ public Seek(offset: bigint, whence: number): [bigint, $.GoError] {
164
164
  const r = this
165
165
  r.prevRune = -1
166
166
  let abs: number = 0
167
167
  switch (whence) {
168
168
  case io.SeekStart:
169
- abs = offset
169
+ abs = Number(offset)
170
170
  break
171
171
  case io.SeekCurrent:
172
- abs = r.i + offset
172
+ abs = r.i + Number(offset)
173
173
  break
174
174
  case io.SeekEnd:
175
- abs = ($.len(r.s) as number) + offset
175
+ abs = ($.len(r.s) as number) + Number(offset)
176
176
  break
177
177
  default:
178
- return [0, errors.New("bytes.Reader.Seek: invalid whence")]
179
- break
178
+ return [0n, errors.New("bytes.Reader.Seek: invalid whence")]
180
179
  }
181
180
  if (abs < 0) {
182
- return [0, errors.New("bytes.Reader.Seek: negative position")]
181
+ return [0n, errors.New("bytes.Reader.Seek: negative position")]
183
182
  }
184
183
  r.i = abs
185
- return [abs, null]
184
+ return [BigInt(abs), null]
186
185
  }
187
186
 
188
187
  // WriteTo implements the [io.WriterTo] interface.
@@ -0,0 +1,55 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { Compare, Less, Or } from './index.js'
4
+
5
+ describe('cmp.Compare', () => {
6
+ it('orders ordinary values', () => {
7
+ expect(Compare(1, 2)).toBe(-1)
8
+ expect(Compare(2, 1)).toBe(1)
9
+ expect(Compare(2, 2)).toBe(0)
10
+ expect(Compare('a', 'b')).toBe(-1)
11
+ })
12
+
13
+ it('orders NaN below every non-NaN value (Go cmp.Compare)', () => {
14
+ expect(Compare(Number.NaN, 1)).toBe(-1)
15
+ expect(Compare(1, Number.NaN)).toBe(1)
16
+ expect(Compare(Number.NaN, Number.NEGATIVE_INFINITY)).toBe(-1)
17
+ })
18
+
19
+ it('treats two NaNs as equal', () => {
20
+ expect(Compare(Number.NaN, Number.NaN)).toBe(0)
21
+ })
22
+
23
+ it('treats -0 and 0 as equal', () => {
24
+ expect(Compare(-0, 0)).toBe(0)
25
+ })
26
+ })
27
+
28
+ describe('cmp.Less', () => {
29
+ it('reports NaN as less than any non-NaN value', () => {
30
+ expect(Less(Number.NaN, 1)).toBe(true)
31
+ expect(Less(1, Number.NaN)).toBe(false)
32
+ expect(Less(Number.NaN, Number.NaN)).toBe(false)
33
+ })
34
+
35
+ it('reports ordinary ordering', () => {
36
+ expect(Less(1, 2)).toBe(true)
37
+ expect(Less(2, 1)).toBe(false)
38
+ })
39
+ })
40
+
41
+ describe('cmp.Or', () => {
42
+ it('returns the first non-zero comparison', () => {
43
+ expect(Or(0, 0, -1, 1)).toBe(-1)
44
+ expect(Or(0, 0)).toBe(0)
45
+ })
46
+
47
+ it('returns the first non-zero value for any comparable type', () => {
48
+ expect(Or('', 'default')).toBe('default')
49
+ expect(Or('first', 'second')).toBe('first')
50
+ expect(Or(false, true)).toBe(true)
51
+ expect(Or(0n, 5n)).toBe(5n)
52
+ expect(Or('', '')).toBe('')
53
+ expect(Or(false, false)).toBe(false)
54
+ })
55
+ })
package/gs/cmp/index.ts CHANGED
@@ -8,22 +8,58 @@ export type Ordered = number | string | boolean | bigint
8
8
  // -1 if a < b
9
9
  // 0 if a == b
10
10
  // 1 if a > b
11
+ // Floating-point NaN orders below every non-NaN value and equals itself, as in
12
+ // Go's cmp.Compare; raw JS < / > would report two incomparable NaNs as equal.
11
13
  export function Compare<T extends Ordered>(a: T, b: T): number {
12
- if (a < b) return -1
13
- if (a > b) return 1
14
+ const aNaN = Number.isNaN(a as unknown as number)
15
+ const bNaN = Number.isNaN(b as unknown as number)
16
+ if (aNaN && bNaN) return 0
17
+ if (aNaN || a < b) return -1
18
+ if (bNaN || a > b) return 1
14
19
  return 0
15
20
  }
16
21
 
17
- // Less reports whether a < b
22
+ // Less reports whether a < b, treating NaN as less than any non-NaN value to
23
+ // match Go's cmp.Less.
18
24
  export function Less<T extends Ordered>(a: T, b: T): boolean {
19
- return a < b
25
+ return (
26
+ (Number.isNaN(a as unknown as number) &&
27
+ !Number.isNaN(b as unknown as number)) ||
28
+ a < b
29
+ )
20
30
  }
21
31
 
22
32
  // Or returns the first non-zero result from the comparison functions,
23
- // or zero if all comparisons return zero
24
- export function Or(...comparisons: number[]): number {
25
- for (const cmp of comparisons) {
26
- if (cmp !== 0) return cmp
33
+ // isZeroValue reports whether v equals the zero value for its comparable kind,
34
+ // matching Go's `val != zero` test in cmp.Or. Scalars compare against their
35
+ // typed zero; pointers, interfaces, maps, slices, channels, and funcs are zero
36
+ // only when nil.
37
+ function isZeroValue(v: unknown): boolean {
38
+ switch (typeof v) {
39
+ case 'number':
40
+ return v === 0
41
+ case 'bigint':
42
+ return v === 0n
43
+ case 'string':
44
+ return v === ''
45
+ case 'boolean':
46
+ return v === false
47
+ case 'undefined':
48
+ return true
49
+ default:
50
+ return v === null
27
51
  }
28
- return 0
52
+ }
53
+
54
+ // Or returns the first of its arguments that is not equal to that comparable
55
+ // type's zero value, or the zero value if every argument is zero, as in Go's
56
+ // cmp.Or. The earlier number-only implementation treated the empty string,
57
+ // false, and 0n as non-zero.
58
+ export function Or<T>(...vals: T[]): T {
59
+ for (const v of vals) {
60
+ if (!isZeroValue(v)) {
61
+ return v
62
+ }
63
+ }
64
+ return vals.length > 0 ? vals[vals.length - 1] : (undefined as T)
29
65
  }
@@ -209,7 +209,7 @@ class timerContext extends cancelContext {
209
209
  }
210
210
 
211
211
  startTimer(): void {
212
- const duration = this.deadline.Sub(time.Now()) / 1000000
212
+ const duration = Number(this.deadline.Sub(time.Now())) / 1000000
213
213
 
214
214
  if (duration <= 0) {
215
215
  // Already expired
@@ -341,7 +341,7 @@ export function WithDeadlineCause(
341
341
  // WithTimeout returns WithDeadline(parent, Date.now() + timeout)
342
342
  export function WithTimeout(
343
343
  parent: Context,
344
- timeout: number,
344
+ timeout: time.Duration,
345
345
  ): [ContextNonNil, CancelFunc] {
346
346
  return WithDeadline(parent, time.Now().Add(timeout))
347
347
  }
@@ -349,7 +349,7 @@ export function WithTimeout(
349
349
  // WithTimeoutCause is like WithTimeout but also sets the cause
350
350
  export function WithTimeoutCause(
351
351
  parent: Context,
352
- timeout: number,
352
+ timeout: time.Duration,
353
353
  cause: $.GoError,
354
354
  ): [ContextNonNil, CancelFunc] {
355
355
  return WithDeadlineCause(parent, time.Now().Add(timeout), cause)
package/gs/embed/index.ts CHANGED
@@ -201,8 +201,8 @@ class embedFileInfo {
201
201
  return this.name
202
202
  }
203
203
 
204
- Size(): number {
205
- return this.size
204
+ Size(): bigint {
205
+ return BigInt(this.size)
206
206
  }
207
207
 
208
208
  Sys(): null {
@@ -236,4 +236,108 @@ describe('encoding/binary override', () => {
236
236
  BigEndian.PutUint32($.makeSlice<number>(1, undefined, 'byte'), 1),
237
237
  ).toThrow('runtime error: index out of range [3] with length 1')
238
238
  })
239
+
240
+ it('sizes, appends, and decodes complex64 and complex128', () => {
241
+ const c128 = $.namedValueInterfaceValue<unknown>(
242
+ { real: 1.5, imag: 2.5 },
243
+ 'complex128',
244
+ {},
245
+ { kind: $.TypeKind.Basic, name: 'complex128' },
246
+ )
247
+ expect(Size(c128)).toBe(16)
248
+ const [enc128, err128] = Append(null, BigEndian, c128)
249
+ expect(err128).toBeNull()
250
+ expect(Array.from($.bytesToUint8Array(enc128))).toEqual([
251
+ 0x3f, 0xf8, 0, 0, 0, 0, 0, 0, 0x40, 0x04, 0, 0, 0, 0, 0, 0,
252
+ ])
253
+
254
+ const ref128 = $.varRef<unknown>({ real: 0, imag: 0 })
255
+ const target128 = $.namedValueInterfaceValue<unknown>(
256
+ ref128,
257
+ '*complex128',
258
+ {},
259
+ {
260
+ kind: $.TypeKind.Pointer,
261
+ elemType: { kind: $.TypeKind.Basic, name: 'complex128' },
262
+ },
263
+ )
264
+ expect(Decode(enc128, BigEndian, target128)).toEqual([16, null])
265
+ expect(ref128.value).toEqual({ real: 1.5, imag: 2.5 })
266
+
267
+ const c64 = $.namedValueInterfaceValue<unknown>(
268
+ { real: 1, imag: -1 },
269
+ 'complex64',
270
+ {},
271
+ { kind: $.TypeKind.Basic, name: 'complex64' },
272
+ )
273
+ expect(Size(c64)).toBe(8)
274
+ })
275
+
276
+ it('sizes, appends, and decodes fixed-size structs field by field', () => {
277
+ const structInfo: $.TypeInfo = {
278
+ kind: $.TypeKind.Struct,
279
+ name: 'Sample',
280
+ methods: [],
281
+ fields: [
282
+ {
283
+ name: 'A',
284
+ key: 'A',
285
+ type: { kind: $.TypeKind.Basic, name: 'int32' },
286
+ },
287
+ {
288
+ name: 'B',
289
+ key: 'B',
290
+ type: { kind: $.TypeKind.Basic, name: 'uint16' },
291
+ },
292
+ {
293
+ name: 'C',
294
+ key: 'C',
295
+ type: {
296
+ kind: $.TypeKind.Array,
297
+ length: 2,
298
+ elemType: { kind: $.TypeKind.Basic, name: 'uint8' },
299
+ },
300
+ },
301
+ ],
302
+ }
303
+
304
+ const instance = {
305
+ _fields: {
306
+ A: $.varRef(0x01020304),
307
+ B: $.varRef(0x0506),
308
+ C: $.varRef([0xaa, 0xbb]),
309
+ },
310
+ }
311
+ const value = $.namedValueInterfaceValue<unknown>(
312
+ instance,
313
+ 'Sample',
314
+ {},
315
+ structInfo,
316
+ )
317
+
318
+ expect(Size(value)).toBe(8)
319
+ const [encoded, err] = Append(null, BigEndian, value)
320
+ expect(err).toBeNull()
321
+ expect(Array.from($.bytesToUint8Array(encoded))).toEqual([
322
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xaa, 0xbb,
323
+ ])
324
+
325
+ const decodedInstance = {
326
+ _fields: {
327
+ A: $.varRef(0),
328
+ B: $.varRef(0),
329
+ C: $.varRef([0, 0]),
330
+ },
331
+ }
332
+ const target = $.namedValueInterfaceValue<unknown>(
333
+ $.varRef(decodedInstance),
334
+ '*Sample',
335
+ {},
336
+ { kind: $.TypeKind.Pointer, elemType: structInfo },
337
+ )
338
+ expect(Decode(encoded, BigEndian, target)).toEqual([8, null])
339
+ expect(decodedInstance._fields.A.value).toBe(0x01020304)
340
+ expect(decodedInstance._fields.B.value).toBe(0x0506)
341
+ expect(decodedInstance._fields.C.value).toEqual([0xaa, 0xbb])
342
+ })
239
343
  })