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
package/gs/io/io.ts CHANGED
@@ -59,7 +59,7 @@ export interface Closer {
59
59
 
60
60
  // Seeker is the interface that wraps the basic Seek method
61
61
  export interface Seeker {
62
- Seek(offset: number, whence: number): [number, $.GoError]
62
+ Seek(offset: bigint, whence: number): [bigint, $.GoError]
63
63
  }
64
64
 
65
65
  // Combined interfaces
@@ -222,12 +222,12 @@ export function Pipe(): [PipeReader, PipeWriter] {
222
222
 
223
223
  // ReaderAt is the interface that wraps the basic ReadAt method
224
224
  export interface ReaderAt {
225
- ReadAt(p: $.Bytes, off: number): [number, $.GoError]
225
+ ReadAt(p: $.Bytes, off: bigint): [number, $.GoError]
226
226
  }
227
227
 
228
228
  // WriterAt is the interface that wraps the basic WriteAt method
229
229
  export interface WriterAt {
230
- WriteAt(p: $.Bytes, off: number): [number, $.GoError]
230
+ WriteAt(p: $.Bytes, off: bigint): [number, $.GoError]
231
231
  }
232
232
 
233
233
  // ByteReader is the interface that wraps the ReadByte method
@@ -262,12 +262,12 @@ export interface StringWriter {
262
262
 
263
263
  // WriterTo is the interface that wraps the WriteTo method
264
264
  export interface WriterTo {
265
- WriteTo(w: Writer): [number, $.GoError]
265
+ WriteTo(w: Writer): [bigint, $.GoError]
266
266
  }
267
267
 
268
268
  // ReaderFrom is the interface that wraps the ReadFrom method
269
269
  export interface ReaderFrom {
270
- ReadFrom(r: Reader): [number, $.GoError]
270
+ ReadFrom(r: Reader): [bigint, $.GoError]
271
271
  }
272
272
 
273
273
  // Discard is a Writer on which all Write calls succeed without doing anything
@@ -297,25 +297,25 @@ export async function WriteString(
297
297
  // LimitedReader reads from R but limits the amount of data returned to just N bytes
298
298
  export class LimitedReader implements Reader {
299
299
  public R: Reader | null
300
- public N: number
300
+ public N: bigint
301
301
 
302
302
  constructor(
303
- r?: Reader | { R?: Reader | null; N?: number } | null,
304
- n?: number,
303
+ r?: Reader | { R?: Reader | null; N?: bigint } | null,
304
+ n?: bigint,
305
305
  ) {
306
306
  if (r != null && typeof (r as { Read?: unknown }).Read !== 'function') {
307
- const init = r as { R?: Reader | null; N?: number }
307
+ const init = r as { R?: Reader | null; N?: bigint }
308
308
  this.R = init.R ?? null
309
- this.N = init.N ?? 0
309
+ this.N = init.N ?? 0n
310
310
  return
311
311
  }
312
312
  this.R = (r as Reader | null | undefined) ?? null
313
- this.N = n ?? 0
313
+ this.N = n ?? 0n
314
314
  }
315
315
 
316
316
  Read(p: $.Bytes): [number, $.GoError] {
317
317
  return (async (): Promise<[number, $.GoError]> => {
318
- if (this.N <= 0) {
318
+ if (this.N <= 0n) {
319
319
  return [0, EOF]
320
320
  }
321
321
  if (this.R == null) {
@@ -323,19 +323,19 @@ export class LimitedReader implements Reader {
323
323
  }
324
324
 
325
325
  let readBuf = p
326
- if ($.len(p) > this.N) {
327
- readBuf = $.goSlice(p, 0, this.N)
326
+ if ($.len(p) > Number(this.N)) {
327
+ readBuf = $.goSlice(p, 0, Number(this.N))
328
328
  }
329
329
 
330
330
  const [n, err] = await (this.R.Read(readBuf) as any)
331
- this.N -= n
331
+ this.N -= BigInt(n)
332
332
  return [n, err]
333
333
  })() as any
334
334
  }
335
335
  }
336
336
 
337
337
  // LimitReader returns a Reader that reads from r but stops with EOF after n bytes
338
- export function LimitReader(r: Reader, n: number): Reader {
338
+ export function LimitReader(r: Reader, n: bigint): Reader {
339
339
  return new LimitedReader(r, n)
340
340
  }
341
341
 
@@ -346,11 +346,11 @@ export class SectionReader implements Reader, Seeker, ReaderAt {
346
346
  private off: number
347
347
  private limit: number
348
348
 
349
- constructor(r: ReaderAt, off: number, n: number) {
349
+ constructor(r: ReaderAt, off: bigint, n: bigint) {
350
350
  this.r = r
351
- this.base = off
352
- this.off = off
353
- this.limit = off + n
351
+ this.base = Number(off)
352
+ this.off = Number(off)
353
+ this.limit = Number(off) + Number(n)
354
354
  }
355
355
 
356
356
  Read(p: $.Bytes): [number, $.GoError] {
@@ -363,7 +363,7 @@ export class SectionReader implements Reader, Seeker, ReaderAt {
363
363
  p = $.goSlice(p, 0, max)
364
364
  }
365
365
 
366
- const res = this.r.ReadAt(p, this.off) as any
366
+ const res = this.r.ReadAt(p, BigInt(this.off)) as any
367
367
  if (res instanceof Promise) {
368
368
  return res.then(([n, err]: [number, $.GoError]) => {
369
369
  this.off += n
@@ -376,39 +376,41 @@ export class SectionReader implements Reader, Seeker, ReaderAt {
376
376
  return [n, err]
377
377
  }
378
378
 
379
- Seek(offset: number, whence: number): [number, $.GoError] {
379
+ Seek(offset: bigint, whence: number): [bigint, $.GoError] {
380
+ const offNum = Number(offset)
380
381
  let abs: number
381
382
  switch (whence) {
382
383
  case SeekStart:
383
- abs = this.base + offset
384
+ abs = this.base + offNum
384
385
  break
385
386
  case SeekCurrent:
386
- abs = this.off + offset
387
+ abs = this.off + offNum
387
388
  break
388
389
  case SeekEnd:
389
- abs = this.limit + offset
390
+ abs = this.limit + offNum
390
391
  break
391
392
  default:
392
- return [0, newError('io.SectionReader.Seek: invalid whence')]
393
+ return [0n, newError('io.SectionReader.Seek: invalid whence')]
393
394
  }
394
395
 
395
396
  if (abs < this.base) {
396
- return [0, newError('io.SectionReader.Seek: negative position')]
397
+ return [0n, newError('io.SectionReader.Seek: negative position')]
397
398
  }
398
399
 
399
400
  this.off = abs
400
- return [abs - this.base, null]
401
+ return [BigInt(abs - this.base), null]
401
402
  }
402
403
 
403
- ReadAt(p: $.Bytes, off: number): [number, $.GoError] {
404
- if (off < 0 || off >= this.limit - this.base) {
404
+ ReadAt(p: $.Bytes, off: bigint): [number, $.GoError] {
405
+ let offNum = Number(off)
406
+ if (offNum < 0 || offNum >= this.limit - this.base) {
405
407
  return [0, EOF]
406
408
  }
407
409
 
408
- off += this.base
409
- if (off + $.len(p) > this.limit) {
410
- p = $.goSlice(p, 0, this.limit - off)
411
- const res = this.r.ReadAt(p, off) as any
410
+ offNum += this.base
411
+ if (offNum + $.len(p) > this.limit) {
412
+ p = $.goSlice(p, 0, this.limit - offNum)
413
+ const res = this.r.ReadAt(p, BigInt(offNum)) as any
412
414
  if (res instanceof Promise) {
413
415
  return res.then(([n, err]: [number, $.GoError]) => {
414
416
  if (err === null) {
@@ -424,19 +426,19 @@ export class SectionReader implements Reader, Seeker, ReaderAt {
424
426
  return [n, err]
425
427
  }
426
428
 
427
- return this.r.ReadAt(p, off)
429
+ return this.r.ReadAt(p, BigInt(offNum))
428
430
  }
429
431
 
430
- Size(): number {
431
- return this.limit - this.base
432
+ Size(): bigint {
433
+ return BigInt(this.limit - this.base)
432
434
  }
433
435
  }
434
436
 
435
437
  // NewSectionReader returns a SectionReader that reads from r starting at offset off and stops with EOF after n bytes
436
438
  export function NewSectionReader(
437
439
  r: ReaderAt,
438
- off: number,
439
- n: number,
440
+ off: bigint,
441
+ n: bigint,
440
442
  ): SectionReader {
441
443
  return new SectionReader(r, off, n)
442
444
  }
@@ -447,49 +449,51 @@ export class OffsetWriter implements Writer, WriterAt {
447
449
  private base: number
448
450
  private off: number
449
451
 
450
- constructor(w: WriterAt, off: number) {
452
+ constructor(w: WriterAt, off: bigint) {
451
453
  this.w = w
452
- this.base = off
454
+ this.base = Number(off)
453
455
  this.off = 0
454
456
  }
455
457
 
456
458
  Write(p: $.Bytes): [number, $.GoError] {
457
- const [n, err] = this.w.WriteAt(p, this.base + this.off)
459
+ const [n, err] = this.w.WriteAt(p, BigInt(this.base + this.off))
458
460
  this.off += n
459
461
  return [n, err]
460
462
  }
461
463
 
462
- WriteAt(p: $.Bytes, off: number): [number, $.GoError] {
463
- if (off < 0) {
464
+ WriteAt(p: $.Bytes, off: bigint): [number, $.GoError] {
465
+ const offNum = Number(off)
466
+ if (offNum < 0) {
464
467
  return [0, newError('io.OffsetWriter.WriteAt: negative offset')]
465
468
  }
466
- return this.w.WriteAt(p, this.base + off)
469
+ return this.w.WriteAt(p, BigInt(this.base + offNum))
467
470
  }
468
471
 
469
- Seek(offset: number, whence: number): [number, $.GoError] {
472
+ Seek(offset: bigint, whence: number): [bigint, $.GoError] {
473
+ const offNum = Number(offset)
470
474
  let abs: number
471
475
  switch (whence) {
472
476
  case SeekStart:
473
- abs = offset
477
+ abs = offNum
474
478
  break
475
479
  case SeekCurrent:
476
- abs = this.off + offset
480
+ abs = this.off + offNum
477
481
  break
478
482
  default:
479
- return [0, newError('io.OffsetWriter.Seek: invalid whence')]
483
+ return [0n, newError('io.OffsetWriter.Seek: invalid whence')]
480
484
  }
481
485
 
482
486
  if (abs < 0) {
483
- return [0, newError('io.OffsetWriter.Seek: negative position')]
487
+ return [0n, newError('io.OffsetWriter.Seek: negative position')]
484
488
  }
485
489
 
486
490
  this.off = abs
487
- return [abs, null]
491
+ return [BigInt(abs), null]
488
492
  }
489
493
  }
490
494
 
491
495
  // NewOffsetWriter returns an OffsetWriter that writes to w starting at offset off
492
- export function NewOffsetWriter(w: WriterAt, off: number): OffsetWriter {
496
+ export function NewOffsetWriter(w: WriterAt, off: bigint): OffsetWriter {
493
497
  return new OffsetWriter(w, off)
494
498
  }
495
499
 
@@ -497,7 +501,7 @@ export function NewOffsetWriter(w: WriterAt, off: number): OffsetWriter {
497
501
  export async function Copy(
498
502
  dst: WriterLike,
499
503
  src: ReaderLike,
500
- ): Promise<[number, $.GoError]> {
504
+ ): Promise<[bigint, $.GoError]> {
501
505
  return await CopyBuffer(dst, src, null)
502
506
  }
503
507
 
@@ -506,11 +510,11 @@ export async function CopyBuffer(
506
510
  dst: WriterLike,
507
511
  src: ReaderLike,
508
512
  buf: $.Bytes | null,
509
- ): Promise<[number, $.GoError]> {
513
+ ): Promise<[bigint, $.GoError]> {
510
514
  dst = unwrapWriter(dst)
511
515
  src = unwrapReader(src)
512
516
  if (dst === null || src === null) {
513
- return [0, newError('io: copy with nil reader or writer')]
517
+ return [0n, newError('io: copy with nil reader or writer')]
514
518
  }
515
519
 
516
520
  // If src implements WriterTo, use it
@@ -527,7 +531,7 @@ export async function CopyBuffer(
527
531
  buf = $.makeSlice<number>(32 * 1024, undefined, 'byte') // 32KB default buffer
528
532
  }
529
533
 
530
- let written = 0
534
+ let written = 0n
531
535
  while (true) {
532
536
  const [nr, er] = await (src.Read(buf) as any)
533
537
  if (nr > 0) {
@@ -538,7 +542,7 @@ export async function CopyBuffer(
538
542
  }
539
543
  return [written, ew]
540
544
  }
541
- written += nw
545
+ written += BigInt(nw)
542
546
  if (ew !== null) {
543
547
  return [written, ew]
544
548
  }
@@ -580,8 +584,8 @@ function unwrapWriter(dst: WriterLike): Writer | null {
580
584
  export async function CopyN(
581
585
  dst: Writer,
582
586
  src: Reader,
583
- n: number,
584
- ): Promise<[number, $.GoError]> {
587
+ n: bigint,
588
+ ): Promise<[bigint, $.GoError]> {
585
589
  const [written, err] = await Copy(dst, LimitReader(src, n))
586
590
  if (written === n) {
587
591
  return [written, null]
@@ -636,6 +640,7 @@ export async function ReadAll(r: Reader): Promise<[$.Bytes, $.GoError]> {
636
640
  const chunks: $.Bytes[] = []
637
641
  let totalLength = 0
638
642
  const buf = $.makeSlice<number>(512, undefined, 'byte')
643
+ let readErr: $.GoError = null
639
644
 
640
645
  while (true) {
641
646
  const [n, err] = await (r.Read(buf) as any)
@@ -646,30 +651,25 @@ export async function ReadAll(r: Reader): Promise<[$.Bytes, $.GoError]> {
646
651
  totalLength += n
647
652
  }
648
653
  if (err !== null) {
649
- if (err === EOF) {
650
- break
654
+ // EOF is the normal terminator and is reported as a nil error. Any other
655
+ // error is returned together with the bytes already read, matching Go.
656
+ if (err !== EOF) {
657
+ readErr = err
651
658
  }
652
- return [$.makeSlice<number>(0, undefined, 'byte'), err]
659
+ break
653
660
  }
654
661
  }
655
662
 
656
- // Combine all chunks
663
+ // Combine all chunks.
657
664
  const result = $.makeSlice<number>(totalLength, undefined, 'byte')
658
665
  let offset = 0
659
666
  for (const chunk of chunks) {
660
- if (chunk instanceof Uint8Array) {
661
- // Handle Uint8Array chunks
662
- const resultSlice = $.goSlice(result, offset, offset + chunk.length)
663
- $.copy(resultSlice, chunk)
664
- } else {
665
- // Handle Slice<number> chunks
666
- const resultSlice = $.goSlice(result, offset, offset + $.len(chunk))
667
- $.copy(resultSlice, chunk)
668
- }
667
+ const resultSlice = $.goSlice(result, offset, offset + $.len(chunk))
668
+ $.copy(resultSlice, chunk)
669
669
  offset += $.len(chunk)
670
670
  }
671
671
 
672
- return [result, null]
672
+ return [result, readErr]
673
673
  }
674
674
 
675
675
  // NopCloser returns a ReadCloser with a no-op Close method wrapping the provided Reader r
@@ -0,0 +1,103 @@
1
+ import { describe, expect, test } from 'vitest'
2
+
3
+ import * as $ from '@goscript/builtin/index.js'
4
+
5
+ import {
6
+ EOF,
7
+ ErrShortBuffer,
8
+ ErrUnexpectedEOF,
9
+ LimitReader,
10
+ NewOffsetWriter,
11
+ ReadAtLeast,
12
+ } from './index.js'
13
+
14
+ // A Reader that hands out its data and returns the EOF sentinel once drained,
15
+ // matching Go's convention that a Read may return n>0 with a nil error.
16
+ class chunkReader {
17
+ constructor(private data: Uint8Array) {}
18
+
19
+ Read(p: $.Bytes): [number, $.GoError] {
20
+ if (this.data.length === 0) {
21
+ return [0, EOF]
22
+ }
23
+ const n = Math.min($.len(p), this.data.length)
24
+ p!.set(this.data.subarray(0, n), 0)
25
+ this.data = this.data.subarray(n)
26
+ return [n, null]
27
+ }
28
+ }
29
+
30
+ // A WriterAt that records bytes at their absolute offset.
31
+ class bufferWriterAt {
32
+ public buf: number[] = []
33
+
34
+ WriteAt(p: $.Bytes, off: bigint): [number, $.GoError] {
35
+ const base = Number(off)
36
+ const bytes = p ?? new Uint8Array(0)
37
+ for (let i = 0; i < bytes.length; i++) {
38
+ this.buf[base + i] = bytes[i]
39
+ }
40
+ return [$.len(p), null]
41
+ }
42
+ }
43
+
44
+ describe('io coverage (Go semantics)', () => {
45
+ test('LimitReader stops with EOF after n bytes', async () => {
46
+ const lr = LimitReader(new chunkReader($.stringToBytes('hello world')), 5n)
47
+ const buf = new Uint8Array(32)
48
+ const [n, err] = await (lr.Read(buf) as any)
49
+ expect(n).toBe(5)
50
+ expect(err).toBeNull()
51
+ expect($.bytesToString($.goSlice(buf, 0, n))).toBe('hello')
52
+ const [n2, err2] = await (lr.Read(buf) as any)
53
+ expect(n2).toBe(0)
54
+ expect(err2).toBe(EOF)
55
+ })
56
+
57
+ test('NewOffsetWriter writes at the base offset', () => {
58
+ const w = new bufferWriterAt()
59
+ const ow = NewOffsetWriter(w, 3n)
60
+ const [n, err] = ow.Write($.stringToBytes('abc'))
61
+ expect(n).toBe(3)
62
+ expect(err).toBeNull()
63
+ expect(String.fromCharCode(w.buf[3], w.buf[4], w.buf[5])).toBe('abc')
64
+ expect(w.buf[0]).toBeUndefined()
65
+ })
66
+
67
+ test('ReadAtLeast reads until min and reports short reads', async () => {
68
+ const buf4 = new Uint8Array(4)
69
+ const [n, err] = await ReadAtLeast(
70
+ new chunkReader($.stringToBytes('abcdef')),
71
+ buf4,
72
+ 4,
73
+ )
74
+ expect(n).toBe(4)
75
+ expect(err).toBeNull()
76
+ expect($.bytesToString(buf4)).toBe('abcd')
77
+
78
+ const buf5 = new Uint8Array(5)
79
+ const [n2, err2] = await ReadAtLeast(
80
+ new chunkReader($.stringToBytes('ab')),
81
+ buf5,
82
+ 4,
83
+ )
84
+ expect(n2).toBe(2)
85
+ expect(err2).toBe(ErrUnexpectedEOF)
86
+
87
+ const [n3, err3] = await ReadAtLeast(
88
+ new chunkReader(new Uint8Array(0)),
89
+ new Uint8Array(4),
90
+ 4,
91
+ )
92
+ expect(n3).toBe(0)
93
+ expect(err3).toBe(EOF)
94
+
95
+ const [n4, err4] = await ReadAtLeast(
96
+ new chunkReader($.stringToBytes('abcdef')),
97
+ new Uint8Array(3),
98
+ 5,
99
+ )
100
+ expect(n4).toBe(0)
101
+ expect(err4).toBe(ErrShortBuffer)
102
+ })
103
+ })
@@ -1,14 +1,53 @@
1
1
  import { describe, expect, it } from 'vitest'
2
2
 
3
3
  import {
4
+ Add,
5
+ Add32,
6
+ Add64,
7
+ Div,
8
+ Div32,
9
+ Div64,
10
+ LeadingZeros16,
11
+ LeadingZeros32,
12
+ LeadingZeros64,
13
+ LeadingZeros8,
14
+ Len16,
15
+ Len32,
16
+ Len64,
17
+ Len8,
18
+ Mul,
19
+ Mul32,
4
20
  Mul64,
21
+ OnesCount,
22
+ OnesCount16,
23
+ OnesCount32,
24
+ OnesCount64,
25
+ OnesCount8,
5
26
  Rem,
6
27
  Rem32,
7
28
  Rem64,
29
+ Reverse,
30
+ Reverse16,
31
+ Reverse32,
32
+ Reverse64,
33
+ Reverse8,
34
+ ReverseBytes,
35
+ ReverseBytes16,
36
+ ReverseBytes32,
37
+ ReverseBytes64,
38
+ RotateLeft,
8
39
  RotateLeft16,
9
40
  RotateLeft32,
10
41
  RotateLeft64,
11
42
  RotateLeft8,
43
+ Sub,
44
+ Sub32,
45
+ Sub64,
46
+ TrailingZeros,
47
+ TrailingZeros16,
48
+ TrailingZeros32,
49
+ TrailingZeros64,
50
+ TrailingZeros8,
12
51
  } from './index.js'
13
52
 
14
53
  describe('math/bits override', () => {
@@ -27,6 +66,20 @@ describe('math/bits override', () => {
27
66
  ])
28
67
  })
29
68
 
69
+ it('counts leading zeros over the 8/16-bit width, not 32', () => {
70
+ // Zero must yield the full width, and Len of zero is 0 (Go len8tab[0]).
71
+ expect(LeadingZeros8(0)).toBe(8)
72
+ expect(LeadingZeros16(0)).toBe(16)
73
+ expect(Len8(0)).toBe(0)
74
+ expect(Len16(0)).toBe(0)
75
+ // Non-zero values keep their width-relative counts.
76
+ expect(LeadingZeros8(1)).toBe(7)
77
+ expect(LeadingZeros8(0xff)).toBe(0)
78
+ expect(Len8(0xff)).toBe(8)
79
+ expect(LeadingZeros16(1)).toBe(15)
80
+ expect(Len16(0x8000)).toBe(16)
81
+ })
82
+
30
83
  it('returns remainders from double-word division helpers', () => {
31
84
  expect(Rem32(1, 0, 3)).toBe(1)
32
85
  expect(Rem(1n, 0n, 3n)).toBe(1n)
@@ -34,9 +87,84 @@ describe('math/bits override', () => {
34
87
  })
35
88
 
36
89
  it('rotates right for negative counts', () => {
90
+ expect(RotateLeft(1n, -1)).toBe(0x8000000000000000n)
37
91
  expect(RotateLeft8(1, -1)).toBe(0x80)
38
92
  expect(RotateLeft16(1, -1)).toBe(0x8000)
39
93
  expect(RotateLeft32(1, -1)).toBe(0x80000000)
40
94
  expect(RotateLeft64(1n, -1)).toBe(0x8000000000000000n)
41
95
  })
96
+
97
+ // Reference values below are produced by Go's math/bits for the same inputs.
98
+ it('Add carries out of the high bit (Go Add/Add32/Add64)', () => {
99
+ expect(Add32(0xffffffff, 2, 0)).toEqual([1, 1])
100
+ expect(Add64(0xffffffffffffffffn, 2n, 0n)).toEqual([1n, 1n])
101
+ // The width-agnostic dispatcher routes to the 64-bit path.
102
+ expect(Add(0xffffffffffffffffn, 2n, 0n)).toEqual([1n, 1n])
103
+ })
104
+
105
+ it('Sub borrows below zero (Go Sub/Sub32/Sub64)', () => {
106
+ expect(Sub32(0, 1, 0)).toEqual([4294967295, 1])
107
+ expect(Sub64(0n, 1n, 0n)).toEqual([18446744073709551615n, 1n])
108
+ expect(Sub(0n, 1n, 0n)).toEqual([18446744073709551615n, 1n])
109
+ })
110
+
111
+ it('Mul returns the full double-word product (Go Mul/Mul32/Mul64)', () => {
112
+ expect(Mul32(0xffffffff, 0xffffffff)).toEqual([4294967294, 1])
113
+ expect(Mul(0xffffffffffffffffn, 0xffffffffffffffffn)).toEqual([
114
+ 0xfffffffffffffffen,
115
+ 1n,
116
+ ])
117
+ })
118
+
119
+ it('Div splits a double-word dividend (Go Div/Div32/Div64)', () => {
120
+ expect(Div32(1, 0, 3)).toEqual([1431655765, 1])
121
+ expect(Div64(1n, 0n, 3n)).toEqual([6148914691236517205n, 1n])
122
+ expect(Div(1n, 0n, 3n)).toEqual([6148914691236517205n, 1n])
123
+ })
124
+
125
+ it('OnesCount counts set bits over each width (Go OnesCount*)', () => {
126
+ expect(OnesCount(0xff)).toBe(8)
127
+ expect(OnesCount8(0xff)).toBe(8)
128
+ expect(OnesCount16(0xf0f0)).toBe(8)
129
+ expect(OnesCount32(0xffffffff)).toBe(32)
130
+ expect(OnesCount64(0xffffffffffffffffn)).toBe(64)
131
+ })
132
+
133
+ it('TrailingZeros counts low zero bits, full width for zero (Go TrailingZeros*)', () => {
134
+ expect(TrailingZeros(8)).toBe(3)
135
+ expect(TrailingZeros8(0x80)).toBe(7)
136
+ expect(TrailingZeros16(0x8000)).toBe(15)
137
+ expect(TrailingZeros32(0x10)).toBe(4)
138
+ expect(TrailingZeros64(0x100000000n)).toBe(32)
139
+ expect(TrailingZeros8(0)).toBe(8)
140
+ expect(TrailingZeros16(0)).toBe(16)
141
+ expect(TrailingZeros32(0)).toBe(32)
142
+ expect(TrailingZeros64(0n)).toBe(64)
143
+ })
144
+
145
+ it('LeadingZeros32/64 and Len32/64 use the right width (Go)', () => {
146
+ expect(LeadingZeros32(1)).toBe(31)
147
+ expect(LeadingZeros32(0)).toBe(32)
148
+ expect(LeadingZeros64(1n)).toBe(63)
149
+ expect(LeadingZeros64(0n)).toBe(64)
150
+ expect(Len32(0x8000)).toBe(16)
151
+ expect(Len32(0)).toBe(0)
152
+ expect(Len64(0x100000000n)).toBe(33)
153
+ expect(Len64(0n)).toBe(0)
154
+ })
155
+
156
+ it('Reverse flips bit order over each width (Go Reverse*)', () => {
157
+ expect(Reverse8(1)).toBe(128)
158
+ expect(Reverse16(1)).toBe(32768)
159
+ expect(Reverse32(1)).toBe(2147483648)
160
+ expect(Reverse64(1n)).toBe(9223372036854775808n)
161
+ expect(Reverse(1n)).toBe(9223372036854775808n)
162
+ })
163
+
164
+ it('ReverseBytes flips byte order over each width (Go ReverseBytes*)', () => {
165
+ expect(ReverseBytes16(0x0102)).toBe(513)
166
+ expect(ReverseBytes32(0x01020304)).toBe(67305985)
167
+ expect(ReverseBytes64(0x0102030405060708n)).toBe(578437695752307201n)
168
+ expect(ReverseBytes(0x0102030405060708n)).toBe(578437695752307201n)
169
+ })
42
170
  })
@@ -31,12 +31,15 @@ export function LeadingZeros(x: Word64): number {
31
31
  return LeadingZeros64(x)
32
32
  }
33
33
 
34
+ // LeadingZeros8 derives from Len8 so that zero yields the full width (8), as in
35
+ // Go. Math.clz32 counts over 32 bits and returns 32 for zero, which would be
36
+ // wrong for the 8-bit width.
34
37
  export function LeadingZeros8(x: number): number {
35
- return Math.clz32((x & 0xff) << 24)
38
+ return 8 - Len8(x)
36
39
  }
37
40
 
38
41
  export function LeadingZeros16(x: number): number {
39
- return Math.clz32((x & 0xffff) << 16)
42
+ return 16 - Len16(x)
40
43
  }
41
44
 
42
45
  export function LeadingZeros32(x: number): number {
@@ -285,12 +288,26 @@ export function Len(x: Word64): number {
285
288
  return Len64(x)
286
289
  }
287
290
 
291
+ // Len8 is the bit-length primitive (Go uses a len8tab lookup): the minimum
292
+ // number of bits to represent the low 8 bits of x, and 0 for x == 0.
288
293
  export function Len8(x: number): number {
289
- return 8 - LeadingZeros8(x)
294
+ x &= 0xff
295
+ let n = 0
296
+ while (x > 0) {
297
+ x >>= 1
298
+ n++
299
+ }
300
+ return n
290
301
  }
291
302
 
292
303
  export function Len16(x: number): number {
293
- return 16 - LeadingZeros16(x)
304
+ x &= 0xffff
305
+ let n = 0
306
+ while (x > 0) {
307
+ x >>= 1
308
+ n++
309
+ }
310
+ return n
294
311
  }
295
312
 
296
313
  export function Len32(x: number): number {
@@ -310,10 +327,11 @@ export function Mul(x: Word64, y: Word64): [Word64, Word64] {
310
327
  }
311
328
 
312
329
  export function Mul32(x: number, y: number): [number, number] {
313
- // For 32-bit multiplication, we can use JavaScript's number precision
314
- const result = (x >>> 0) * (y >>> 0)
315
- const hi = Math.floor(result / 0x100000000) >>> 0
316
- const lo = result >>> 0
330
+ // The product of two uint32 needs 64 bits, beyond the 53-bit mantissa of a
331
+ // JS number, so multiply exactly via bigint before splitting hi/lo.
332
+ const product = BigInt(x >>> 0) * BigInt(y >>> 0)
333
+ const hi = Number((product >> 32n) & 0xffffffffn)
334
+ const lo = Number(product & 0xffffffffn)
317
335
  return [hi, lo]
318
336
  }
319
337
 
@@ -30,7 +30,9 @@ describe('Copysign', () => {
30
30
  it('should handle NaN values', () => {
31
31
  expect(Number.isNaN(Copysign(Number.NaN, 1))).toBe(true)
32
32
  expect(Number.isNaN(Copysign(Number.NaN, -1))).toBe(true)
33
- expect(Copysign(5, Number.NaN)).toBe(5) // NaN is positive
33
+ expect(Copysign(5, Number.NaN)).toBe(5) // quiet NaN sign bit is 0
34
+ // A negative NaN sign bit is honored, matching Go.
35
+ expect(Copysign(1, -Number.NaN)).toBe(-1)
34
36
  })
35
37
 
36
38
  it('should handle fractional values', () => {