goscript 0.1.2 → 0.1.4

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 (138) hide show
  1. package/cmd/goscript/cmd_compile.go +28 -8
  2. package/cmd/goscript/cmd_compile_test.go +105 -6
  3. package/compiler/build-flags.go +9 -10
  4. package/compiler/gotest/runner_test.go +127 -0
  5. package/compiler/lowered-program.go +1 -0
  6. package/compiler/lowering.go +1325 -194
  7. package/compiler/lowering_bench_test.go +350 -0
  8. package/compiler/override-registry_test.go +43 -0
  9. package/compiler/package-graph.go +61 -4
  10. package/compiler/package-graph_test.go +30 -0
  11. package/compiler/semantic-model-types.go +8 -0
  12. package/compiler/semantic-model.go +447 -22
  13. package/compiler/semantic-model_test.go +138 -0
  14. package/compiler/skeleton_test.go +1436 -50
  15. package/compiler/typescript-emitter.go +47 -4
  16. package/dist/gs/builtin/builtin.d.ts +2 -2
  17. package/dist/gs/builtin/builtin.js +20 -0
  18. package/dist/gs/builtin/builtin.js.map +1 -1
  19. package/dist/gs/builtin/channel.js +36 -9
  20. package/dist/gs/builtin/channel.js.map +1 -1
  21. package/dist/gs/builtin/slice.js +5 -0
  22. package/dist/gs/builtin/slice.js.map +1 -1
  23. package/dist/gs/builtin/type.d.ts +1 -1
  24. package/dist/gs/builtin/type.js +80 -8
  25. package/dist/gs/builtin/type.js.map +1 -1
  26. package/dist/gs/bytes/bytes.gs.d.ts +7 -5
  27. package/dist/gs/bytes/bytes.gs.js +10 -4
  28. package/dist/gs/bytes/bytes.gs.js.map +1 -1
  29. package/dist/gs/compress/zlib/index.d.ts +3 -3
  30. package/dist/gs/compress/zlib/index.js +88 -26
  31. package/dist/gs/compress/zlib/index.js.map +1 -1
  32. package/dist/gs/crypto/sha1/index.d.ts +5 -0
  33. package/dist/gs/crypto/sha1/index.js +103 -0
  34. package/dist/gs/crypto/sha1/index.js.map +1 -0
  35. package/dist/gs/crypto/sha256/index.js +2 -5
  36. package/dist/gs/crypto/sha256/index.js.map +1 -1
  37. package/dist/gs/crypto/sha512/index.js +2 -5
  38. package/dist/gs/crypto/sha512/index.js.map +1 -1
  39. package/dist/gs/embed/index.d.ts +6 -0
  40. package/dist/gs/embed/index.js +210 -5
  41. package/dist/gs/embed/index.js.map +1 -1
  42. package/dist/gs/fmt/fmt.d.ts +4 -4
  43. package/dist/gs/fmt/fmt.js +93 -19
  44. package/dist/gs/fmt/fmt.js.map +1 -1
  45. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +118 -6
  46. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -1
  47. package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.d.ts +45 -0
  48. package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js +229 -0
  49. package/dist/gs/github.com/go-git/go-billy/v6/osfs/index.js.map +1 -0
  50. package/dist/gs/io/fs/readdir.js +5 -3
  51. package/dist/gs/io/fs/readdir.js.map +1 -1
  52. package/dist/gs/io/io.d.ts +18 -11
  53. package/dist/gs/io/io.js +107 -44
  54. package/dist/gs/io/io.js.map +1 -1
  55. package/dist/gs/math/bits/index.d.ts +26 -5
  56. package/dist/gs/math/bits/index.js +13 -24
  57. package/dist/gs/math/bits/index.js.map +1 -1
  58. package/dist/gs/net/http/httptest/index.js +7 -5
  59. package/dist/gs/net/http/httptest/index.js.map +1 -1
  60. package/dist/gs/net/http/index.d.ts +11 -1
  61. package/dist/gs/net/http/index.js +157 -11
  62. package/dist/gs/net/http/index.js.map +1 -1
  63. package/dist/gs/os/types_js.gs.d.ts +6 -2
  64. package/dist/gs/os/types_js.gs.js +169 -8
  65. package/dist/gs/os/types_js.gs.js.map +1 -1
  66. package/dist/gs/os/zero_copy_posix.gs.js +1 -1
  67. package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
  68. package/dist/gs/reflect/type.d.ts +1 -0
  69. package/dist/gs/reflect/type.js +80 -51
  70. package/dist/gs/reflect/type.js.map +1 -1
  71. package/dist/gs/strings/reader.d.ts +1 -1
  72. package/dist/gs/strings/reader.js +2 -2
  73. package/dist/gs/strings/reader.js.map +1 -1
  74. package/dist/gs/sync/sync.d.ts +2 -1
  75. package/dist/gs/sync/sync.js +37 -16
  76. package/dist/gs/sync/sync.js.map +1 -1
  77. package/dist/gs/syscall/js/index.js +9 -0
  78. package/dist/gs/syscall/js/index.js.map +1 -1
  79. package/dist/gs/testing/testing.js +8 -6
  80. package/dist/gs/testing/testing.js.map +1 -1
  81. package/gs/builtin/builtin.ts +25 -2
  82. package/gs/builtin/channel.ts +47 -9
  83. package/gs/builtin/runtime-contract.test.ts +78 -0
  84. package/gs/builtin/slice.ts +7 -0
  85. package/gs/builtin/type.ts +97 -8
  86. package/gs/bytes/bytes.gs.ts +19 -10
  87. package/gs/bytes/bytes.test.ts +17 -0
  88. package/gs/compress/zlib/index.test.ts +97 -0
  89. package/gs/compress/zlib/index.ts +117 -27
  90. package/gs/compress/zlib/meta.json +4 -1
  91. package/gs/context/context.test.ts +5 -1
  92. package/gs/crypto/sha1/index.test.ts +45 -0
  93. package/gs/crypto/sha1/index.ts +127 -0
  94. package/gs/crypto/sha1/meta.json +8 -0
  95. package/gs/crypto/sha256/index.test.ts +14 -2
  96. package/gs/crypto/sha256/index.ts +3 -6
  97. package/gs/crypto/sha512/index.test.ts +17 -2
  98. package/gs/crypto/sha512/index.ts +3 -6
  99. package/gs/embed/index.test.ts +87 -0
  100. package/gs/embed/index.ts +229 -5
  101. package/gs/fmt/fmt.test.ts +61 -3
  102. package/gs/fmt/fmt.ts +115 -22
  103. package/gs/fmt/meta.json +6 -1
  104. package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +8 -1
  105. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +139 -11
  106. package/gs/github.com/aperturerobotics/util/conc/index.test.ts +1 -1
  107. package/gs/github.com/go-git/go-billy/v6/osfs/index.test.ts +110 -0
  108. package/gs/github.com/go-git/go-billy/v6/osfs/index.ts +280 -0
  109. package/gs/github.com/go-git/go-billy/v6/osfs/meta.json +8 -0
  110. package/gs/io/fs/readdir.test.ts +38 -0
  111. package/gs/io/fs/readdir.ts +7 -3
  112. package/gs/io/io.test.ts +135 -0
  113. package/gs/io/io.ts +143 -63
  114. package/gs/io/meta.json +7 -1
  115. package/gs/math/bits/index.ts +52 -28
  116. package/gs/net/http/httptest/index.test.ts +34 -2
  117. package/gs/net/http/httptest/index.ts +23 -8
  118. package/gs/net/http/index.test.ts +46 -0
  119. package/gs/net/http/index.ts +178 -12
  120. package/gs/os/file_unix_js.test.ts +52 -0
  121. package/gs/os/meta.json +4 -0
  122. package/gs/os/readdir.test.ts +56 -0
  123. package/gs/os/types_js.gs.ts +169 -8
  124. package/gs/os/zero_copy_posix.gs.ts +1 -2
  125. package/gs/reflect/deepequal.test.ts +10 -1
  126. package/gs/reflect/type.ts +91 -56
  127. package/gs/reflect/typefor.test.ts +31 -1
  128. package/gs/strings/meta.json +5 -2
  129. package/gs/strings/reader.test.ts +2 -2
  130. package/gs/strings/reader.ts +2 -2
  131. package/gs/sync/meta.json +2 -0
  132. package/gs/sync/sync.test.ts +41 -1
  133. package/gs/sync/sync.ts +41 -16
  134. package/gs/syscall/js/index.test.ts +18 -0
  135. package/gs/syscall/js/index.ts +12 -0
  136. package/gs/testing/testing.test.ts +32 -3
  137. package/gs/testing/testing.ts +13 -10
  138. package/package.json +1 -1
@@ -0,0 +1,135 @@
1
+ import * as $ from '@goscript/builtin/index.js'
2
+ import { LimitedReader, MultiWriter, NopCloser, Pipe, TeeReader } from './index.js'
3
+ import { describe, expect, test } from 'vitest'
4
+
5
+ class sliceReader {
6
+ constructor(private data: Uint8Array) {}
7
+
8
+ Read(p: $.Bytes): [number, $.GoError] {
9
+ const n = Math.min($.len(p), this.data.length)
10
+ p!.set(this.data.subarray(0, n), 0)
11
+ this.data = this.data.subarray(n)
12
+ return [n, n === 0 ? (new Error('EOF') as $.GoError) : null]
13
+ }
14
+ }
15
+
16
+ class captureWriter {
17
+ public chunks: number[] = []
18
+
19
+ Write(p: $.Bytes): [number, $.GoError] {
20
+ this.chunks.push(...Array.from(p ?? []))
21
+ return [$.len(p), null]
22
+ }
23
+ }
24
+
25
+ describe('io override', () => {
26
+ test('LimitedReader accepts generated struct-literal construction', async () => {
27
+ const reader = new LimitedReader({
28
+ R: new sliceReader($.stringToBytes('abcdef')),
29
+ N: 3,
30
+ })
31
+ const buf = new Uint8Array(8)
32
+
33
+ const [n, err] = await reader.Read(buf)
34
+
35
+ expect(err).toBeNull()
36
+ expect(n).toBe(3)
37
+ expect(Buffer.from(buf.subarray(0, n)).toString('utf8')).toBe('abc')
38
+ })
39
+
40
+ test('TeeReader accepts nullable generated interface values', async () => {
41
+ const writer = new captureWriter()
42
+ const reader = TeeReader(new sliceReader($.stringToBytes('abc')), writer)
43
+ const buf = new Uint8Array(4)
44
+
45
+ const [n, err] = await reader.Read(buf)
46
+
47
+ expect(err).toBeNull()
48
+ expect(n).toBe(3)
49
+ expect(Buffer.from(writer.chunks).toString('utf8')).toBe('abc')
50
+ })
51
+
52
+ test('NopCloser accepts nullable generated interface values', () => {
53
+ const reader: sliceReader | null = new sliceReader($.stringToBytes('abc'))
54
+ const body = NopCloser(reader)
55
+ const buf = new Uint8Array(4)
56
+
57
+ const [n, err] = body.Read(buf)
58
+
59
+ expect(err).toBeNull()
60
+ expect(n).toBe(3)
61
+ expect(body.Close()).toBeNull()
62
+ })
63
+
64
+ test('TeeReader awaits async readers and writers', async () => {
65
+ const chunks: number[] = []
66
+ const reader = TeeReader(
67
+ {
68
+ async Read(p: $.Bytes): Promise<[number, $.GoError]> {
69
+ await Promise.resolve()
70
+ p!.set($.stringToBytes('abc'), 0)
71
+ return [3, null]
72
+ },
73
+ } as any,
74
+ {
75
+ async Write(p: $.Bytes): Promise<[number, $.GoError]> {
76
+ await Promise.resolve()
77
+ chunks.push(...Array.from(p ?? []))
78
+ return [$.len(p), null]
79
+ },
80
+ } as any,
81
+ )
82
+ const buf = new Uint8Array(4)
83
+
84
+ const [n, err] = await reader.Read(buf)
85
+
86
+ expect(err).toBeNull()
87
+ expect(n).toBe(3)
88
+ expect(Buffer.from(chunks).toString('utf8')).toBe('abc')
89
+ })
90
+
91
+ test('MultiWriter accepts nullable generated interface values', async () => {
92
+ const first = new captureWriter()
93
+ const second = new captureWriter()
94
+ const writer = MultiWriter(first, second)
95
+
96
+ const [n, err] = await writer.Write($.stringToBytes('abc'))
97
+
98
+ expect(err).toBeNull()
99
+ expect(n).toBe(3)
100
+ expect(Buffer.from(first.chunks).toString('utf8')).toBe('abc')
101
+ expect(Buffer.from(second.chunks).toString('utf8')).toBe('abc')
102
+ })
103
+
104
+ test('MultiWriter awaits async generated writers', async () => {
105
+ const chunks: number[] = []
106
+ const writer = MultiWriter({
107
+ async Write(p: $.Bytes): Promise<[number, $.GoError]> {
108
+ await Promise.resolve()
109
+ chunks.push(...Array.from(p ?? []))
110
+ return [$.len(p), null]
111
+ },
112
+ })
113
+
114
+ const [n, err] = await writer.Write($.stringToBytes('abc'))
115
+
116
+ expect(err).toBeNull()
117
+ expect(n).toBe(3)
118
+ expect(Buffer.from(chunks).toString('utf8')).toBe('abc')
119
+ })
120
+
121
+ test('PipeReader waits for a later write', async () => {
122
+ const [reader, writer] = Pipe()
123
+ const buf = new Uint8Array(5)
124
+
125
+ const read = reader.Read(buf)
126
+ const [written, writeErr] = await writer.Write($.stringToBytes('later'))
127
+ const [readBytes, readErr] = await read
128
+
129
+ expect(writeErr).toBeNull()
130
+ expect(written).toBe(5)
131
+ expect(readErr).toBeNull()
132
+ expect(readBytes).toBe(5)
133
+ expect(Buffer.from(buf).toString('utf8')).toBe('later')
134
+ })
135
+ })
package/gs/io/io.ts CHANGED
@@ -72,67 +72,111 @@ export interface WriteSeeker extends Writer, Seeker {}
72
72
  export interface ReadWriteSeeker extends Reader, Writer, Seeker {}
73
73
 
74
74
  class pipeState {
75
- private chunks: Uint8Array[] = []
76
- private readOffset = 0
77
75
  private readerClosed = false
78
76
  private writerClosed = false
79
77
  private readerErr: $.GoError = null
80
78
  private writerErr: $.GoError = null
81
-
82
- Read(p: $.Bytes): [number, $.GoError] {
83
- if (this.readerClosed) {
84
- return [0, this.readerErr ?? ErrClosedPipe]
85
- }
86
- if ($.len(p) === 0) {
87
- return [0, null]
88
- }
89
- if (this.chunks.length === 0) {
79
+ private pendingReads: Array<{
80
+ data: $.Bytes
81
+ resolve: (result: [number, $.GoError]) => void
82
+ }> = []
83
+ private pendingWrites: Array<{
84
+ data: Uint8Array
85
+ offset: number
86
+ resolve: (result: [number, $.GoError]) => void
87
+ }> = []
88
+
89
+ Read(p: $.Bytes): Promise<[number, $.GoError]> {
90
+ return (async (): Promise<[number, $.GoError]> => {
91
+ if (this.readerClosed) {
92
+ return [0, this.readerErr ?? ErrClosedPipe]
93
+ }
94
+ if ($.len(p) === 0) {
95
+ return [0, null]
96
+ }
97
+ if (this.pendingWrites.length > 0) {
98
+ return this.consumeNextWrite(p)
99
+ }
90
100
  if (this.writerClosed) {
91
101
  return [0, this.writerErr ?? EOF]
92
102
  }
93
- return [0, EOF]
94
- }
95
-
96
- let copied = 0
97
- while (copied < $.len(p) && this.chunks.length > 0) {
98
- const chunk = this.chunks[0]
99
- const available = chunk.length - this.readOffset
100
- const want = Math.min($.len(p) - copied, available)
101
- const target = $.goSlice(p, copied, copied + want)
102
- $.copy(target, chunk.subarray(this.readOffset, this.readOffset + want))
103
- copied += want
104
- this.readOffset += want
105
- if (this.readOffset === chunk.length) {
106
- this.chunks.shift()
107
- this.readOffset = 0
108
- }
109
- }
110
- return [copied, null]
103
+ return await new Promise<[number, $.GoError]>((resolve) => {
104
+ this.pendingReads.push({ data: p, resolve })
105
+ })
106
+ })()
111
107
  }
112
108
 
113
- Write(p: $.Bytes): [number, $.GoError] {
114
- if (this.writerClosed || this.readerClosed) {
115
- return [0, this.readerErr ?? ErrClosedPipe]
116
- }
117
- const data = new Uint8Array($.len(p))
118
- $.copy(data, p)
119
- this.chunks.push(data)
120
- return [$.len(p), null]
109
+ Write(p: $.Bytes): Promise<[number, $.GoError]> {
110
+ return (async (): Promise<[number, $.GoError]> => {
111
+ if (this.writerClosed || this.readerClosed) {
112
+ return [0, this.readerErr ?? ErrClosedPipe]
113
+ }
114
+ if ($.len(p) === 0) {
115
+ return [0, null]
116
+ }
117
+ const data = new Uint8Array($.len(p))
118
+ $.copy(data, p)
119
+ return await new Promise<[number, $.GoError]>((resolve) => {
120
+ this.pendingWrites.push({ data, offset: 0, resolve })
121
+ this.drain()
122
+ })
123
+ })()
121
124
  }
122
125
 
123
126
  CloseReader(err: $.GoError): $.GoError {
124
127
  this.readerClosed = true
125
128
  this.readerErr = err
126
- this.chunks = []
127
- this.readOffset = 0
129
+ this.resolvePendingReads(ErrClosedPipe)
130
+ this.resolvePendingWrites(ErrClosedPipe)
128
131
  return null
129
132
  }
130
133
 
131
134
  CloseWriter(err: $.GoError): $.GoError {
132
135
  this.writerClosed = true
133
136
  this.writerErr = err
137
+ if (this.pendingWrites.length === 0) {
138
+ this.resolvePendingReads(err ?? EOF)
139
+ }
134
140
  return null
135
141
  }
142
+
143
+ private drain(): void {
144
+ while (this.pendingWrites.length > 0 && this.pendingReads.length > 0) {
145
+ if (this.readerClosed) {
146
+ this.resolvePendingWrites(this.readerErr ?? ErrClosedPipe)
147
+ return
148
+ }
149
+ const pending = this.pendingReads.shift()!
150
+ pending.resolve(this.consumeNextWrite(pending.data))
151
+ }
152
+ }
153
+
154
+ private consumeNextWrite(p: $.Bytes): [number, $.GoError] {
155
+ const pending = this.pendingWrites[0]
156
+ const n = Math.min($.len(p), pending.data.length - pending.offset)
157
+ $.copy(p, pending.data.subarray(pending.offset, pending.offset + n))
158
+ pending.offset += n
159
+ if (pending.offset === pending.data.length) {
160
+ this.pendingWrites.shift()
161
+ pending.resolve([pending.data.length, null])
162
+ if (this.writerClosed && this.pendingWrites.length === 0) {
163
+ this.resolvePendingReads(this.writerErr ?? EOF)
164
+ }
165
+ }
166
+ return [n, null]
167
+ }
168
+
169
+ private resolvePendingReads(err: $.GoError): void {
170
+ while (this.pendingReads.length > 0) {
171
+ this.pendingReads.shift()!.resolve([0, err])
172
+ }
173
+ }
174
+
175
+ private resolvePendingWrites(err: $.GoError): void {
176
+ while (this.pendingWrites.length > 0) {
177
+ this.pendingWrites.shift()!.resolve([0, err])
178
+ }
179
+ }
136
180
  }
137
181
 
138
182
  // PipeReader is the read half of a pipe.
@@ -140,7 +184,7 @@ export class PipeReader implements Reader, Closer {
140
184
  constructor(private pipe: pipeState) {}
141
185
 
142
186
  Read(data: $.Bytes): [number, $.GoError] {
143
- return this.pipe.Read(data)
187
+ return this.pipe.Read(data) as any
144
188
  }
145
189
 
146
190
  Close(): $.GoError {
@@ -157,7 +201,7 @@ export class PipeWriter implements Writer, Closer {
157
201
  constructor(private pipe: pipeState) {}
158
202
 
159
203
  Write(data: $.Bytes): [number, $.GoError] {
160
- return this.pipe.Write(data)
204
+ return this.pipe.Write(data) as any
161
205
  }
162
206
 
163
207
  Close(): $.GoError {
@@ -232,28 +276,40 @@ class DiscardWriter implements Writer {
232
276
  }
233
277
  }
234
278
 
235
- export const Discard: Writer = new DiscardWriter()
279
+ export const Discard: Writer | null = new DiscardWriter()
236
280
 
237
281
  // WriteString writes the contents of the string s to w, which accepts a slice of bytes
238
- export function WriteString(w: Writer, s: string): [number, $.GoError] {
282
+ export async function WriteString(
283
+ w: Writer,
284
+ s: string,
285
+ ): Promise<[number, $.GoError]> {
239
286
  // Check if w implements StringWriter interface
240
287
  if ('WriteString' in w && typeof (w as any).WriteString === 'function') {
241
- return (w as StringWriter).WriteString(s)
288
+ return await ((w as StringWriter).WriteString(s) as any)
242
289
  }
243
290
 
244
291
  // Convert string to bytes and write
245
292
  const bytes = new TextEncoder().encode(s)
246
- return w.Write(bytes)
293
+ return await (w.Write(bytes) as any)
247
294
  }
248
295
 
249
296
  // LimitedReader reads from R but limits the amount of data returned to just N bytes
250
297
  export class LimitedReader implements Reader {
251
- public R: Reader
298
+ public R: Reader | null
252
299
  public N: number
253
300
 
254
- constructor(r: Reader, n: number) {
255
- this.R = r
256
- this.N = n
301
+ constructor(
302
+ r?: Reader | { R?: Reader | null; N?: number } | null,
303
+ n?: number,
304
+ ) {
305
+ if (r != null && typeof (r as { Read?: unknown }).Read !== 'function') {
306
+ const init = r as { R?: Reader | null; N?: number }
307
+ this.R = init.R ?? null
308
+ this.N = init.N ?? 0
309
+ return
310
+ }
311
+ this.R = (r as Reader | null | undefined) ?? null
312
+ this.N = n ?? 0
257
313
  }
258
314
 
259
315
  Read(p: $.Bytes): [number, $.GoError] {
@@ -261,6 +317,9 @@ export class LimitedReader implements Reader {
261
317
  if (this.N <= 0) {
262
318
  return [0, EOF]
263
319
  }
320
+ if (this.R == null) {
321
+ throw new Error('io.LimitedReader: nil reader')
322
+ }
264
323
 
265
324
  let readBuf = p
266
325
  if ($.len(p) > this.N) {
@@ -596,7 +655,15 @@ export async function ReadAll(r: Reader): Promise<[$.Bytes, $.GoError]> {
596
655
  }
597
656
 
598
657
  // NopCloser returns a ReadCloser with a no-op Close method wrapping the provided Reader r
599
- export function NopCloser(r: Reader): ReadCloser {
658
+ export function NopCloser(r: Reader | null): ReadCloser {
659
+ if (r == null) {
660
+ return {
661
+ Read: () => {
662
+ throw new Error('nil Reader')
663
+ },
664
+ Close: () => null,
665
+ }
666
+ }
600
667
  return {
601
668
  Read: r.Read.bind(r),
602
669
  Close: () => null,
@@ -645,20 +712,23 @@ class multiReader implements Reader {
645
712
  }
646
713
 
647
714
  // MultiWriter creates a writer that duplicates its writes to all the provided writers
648
- export function MultiWriter(...writers: Writer[]): Writer {
649
- return new multiWriter(writers.slice())
715
+ export function MultiWriter(...writers: (Writer | null)[]): Writer {
716
+ return new multiWriter(writers.slice()) as any
650
717
  }
651
718
 
652
- class multiWriter implements Writer {
653
- private writers: Writer[]
719
+ class multiWriter {
720
+ private writers: (Writer | null)[]
654
721
 
655
- constructor(writers: Writer[]) {
722
+ constructor(writers: (Writer | null)[]) {
656
723
  this.writers = writers
657
724
  }
658
725
 
659
- Write(p: $.Bytes): [number, $.GoError] {
726
+ async Write(p: $.Bytes): Promise<[number, $.GoError]> {
660
727
  for (const w of this.writers) {
661
- const [n, err] = w.Write(p)
728
+ if (w == null) {
729
+ throw new Error('io.MultiWriter: nil writer')
730
+ }
731
+ const [n, err] = await w.Write(p)
662
732
  if (err !== null) {
663
733
  return [n, err]
664
734
  }
@@ -671,23 +741,33 @@ class multiWriter implements Writer {
671
741
  }
672
742
 
673
743
  // TeeReader returns a Reader that writes to w what it reads from r
674
- export function TeeReader(r: Reader, w: Writer): Reader {
744
+ export function TeeReader(r: Reader | null, w: Writer | null): Reader {
675
745
  return new teeReader(r, w)
676
746
  }
677
747
 
678
748
  class teeReader implements Reader {
679
- private r: Reader
680
- private w: Writer
749
+ private r: Reader | null
750
+ private w: Writer | null
681
751
 
682
- constructor(r: Reader, w: Writer) {
752
+ constructor(r: Reader | null, w: Writer | null) {
683
753
  this.r = r
684
754
  this.w = w
685
755
  }
686
756
 
687
757
  Read(p: $.Bytes): [number, $.GoError] {
688
- const [n, err] = this.r.Read(p)
758
+ return this.read(p) as any
759
+ }
760
+
761
+ private async read(p: $.Bytes): Promise<[number, $.GoError]> {
762
+ if (this.r == null) {
763
+ throw new Error('io.TeeReader: nil reader')
764
+ }
765
+ const [n, err] = await this.r.Read(p)
689
766
  if (n > 0) {
690
- const [nw, ew] = this.w.Write($.goSlice(p, 0, n))
767
+ if (this.w == null) {
768
+ throw new Error('io.TeeReader: nil writer')
769
+ }
770
+ const [nw, ew] = await this.w.Write($.goSlice(p, 0, n))
691
771
  if (ew !== null) {
692
772
  return [n, ew]
693
773
  }
package/gs/io/meta.json CHANGED
@@ -12,6 +12,12 @@
12
12
  "CopyN": true,
13
13
  "ReadAtLeast": true,
14
14
  "ReadFull": true,
15
- "ReadAll": true
15
+ "ReadAll": true,
16
+ "WriteString": true
17
+ },
18
+ "asyncMethods": {
19
+ "PipeReader.Read": true,
20
+ "PipeWriter.Write": true,
21
+ "TeeReader.Read": true
16
22
  }
17
23
  }
@@ -2,7 +2,7 @@
2
2
  // This replaces the auto-generated version that has TypeScript syntax errors
3
3
 
4
4
  // UintSize is the size of a uint in bits
5
- export const UintSize = 32 // Assuming 32-bit for JavaScript numbers
5
+ export const UintSize = 64
6
6
 
7
7
  type Word64 = number | bigint
8
8
 
@@ -23,8 +23,8 @@ function word64Result(value: bigint, useBigInt: boolean): Word64 {
23
23
  }
24
24
 
25
25
  // --- Leading zeros ---
26
- export function LeadingZeros(x: number): number {
27
- return Math.clz32(x >>> 0)
26
+ export function LeadingZeros(x: Word64): number {
27
+ return LeadingZeros64(x)
28
28
  }
29
29
 
30
30
  export function LeadingZeros8(x: number): number {
@@ -53,9 +53,8 @@ export function LeadingZeros64(x: Word64): number {
53
53
  }
54
54
 
55
55
  // --- Trailing zeros ---
56
- export function TrailingZeros(x: number): number {
57
- if (x === 0) return UintSize
58
- return TrailingZeros32(x)
56
+ export function TrailingZeros(x: Word64): number {
57
+ return TrailingZeros64(x)
59
58
  }
60
59
 
61
60
  export function TrailingZeros8(x: number): number {
@@ -90,8 +89,8 @@ export function TrailingZeros64(x: Word64): number {
90
89
  }
91
90
 
92
91
  // --- Ones count ---
93
- export function OnesCount(x: number): number {
94
- return OnesCount32(x)
92
+ export function OnesCount(x: Word64): number {
93
+ return OnesCount64(x)
95
94
  }
96
95
 
97
96
  export function OnesCount8(x: number): number {
@@ -124,8 +123,11 @@ export function OnesCount64(x: Word64): number {
124
123
  }
125
124
 
126
125
  // --- Rotate left ---
127
- export function RotateLeft(x: number, k: number): number {
128
- return RotateLeft32(x, k)
126
+ export function RotateLeft(x: number, k: number): number
127
+ export function RotateLeft(x: bigint, k: number): bigint
128
+ export function RotateLeft(x: Word64, k: number): number
129
+ export function RotateLeft(x: Word64, k: number): Word64 {
130
+ return RotateLeft64(x, k)
129
131
  }
130
132
 
131
133
  export function RotateLeft8(x: number, k: number): number {
@@ -151,6 +153,7 @@ export function RotateLeft32(x: number, k: number): number {
151
153
 
152
154
  export function RotateLeft64(x: number, k: number): number
153
155
  export function RotateLeft64(x: bigint, k: number): bigint
156
+ export function RotateLeft64(x: Word64, k: number): number
154
157
  export function RotateLeft64(x: Word64, k: number): Word64 {
155
158
  const n = 64
156
159
  k = k % n
@@ -163,8 +166,11 @@ export function RotateLeft64(x: Word64, k: number): Word64 {
163
166
  }
164
167
 
165
168
  // --- Reverse ---
166
- export function Reverse(x: number): number {
167
- return Reverse32(x)
169
+ export function Reverse(x: number): number
170
+ export function Reverse(x: bigint): bigint
171
+ export function Reverse(x: Word64): number
172
+ export function Reverse(x: Word64): Word64 {
173
+ return Reverse64(x)
168
174
  }
169
175
 
170
176
  export function Reverse8(x: number): number {
@@ -196,6 +202,7 @@ export function Reverse32(x: number): number {
196
202
 
197
203
  export function Reverse64(x: number): number
198
204
  export function Reverse64(x: bigint): bigint
205
+ export function Reverse64(x: Word64): number
199
206
  export function Reverse64(x: Word64): Word64 {
200
207
  // Implement 64-bit reverse using similar bit manipulation
201
208
  const useBigInt = useBigIntResult(x)
@@ -226,8 +233,11 @@ export function Reverse64(x: Word64): Word64 {
226
233
  }
227
234
 
228
235
  // --- ReverseBytes ---
229
- export function ReverseBytes(x: number): number {
230
- return ReverseBytes32(x)
236
+ export function ReverseBytes(x: number): number
237
+ export function ReverseBytes(x: bigint): bigint
238
+ export function ReverseBytes(x: Word64): number
239
+ export function ReverseBytes(x: Word64): Word64 {
240
+ return ReverseBytes64(x)
231
241
  }
232
242
 
233
243
  export function ReverseBytes16(x: number): number {
@@ -247,6 +257,7 @@ export function ReverseBytes32(x: number): number {
247
257
 
248
258
  export function ReverseBytes64(x: number): number
249
259
  export function ReverseBytes64(x: bigint): bigint
260
+ export function ReverseBytes64(x: Word64): number
250
261
  export function ReverseBytes64(x: Word64): Word64 {
251
262
  const useBigInt = useBigIntResult(x)
252
263
  const word = toUint64(x)
@@ -266,8 +277,8 @@ export function ReverseBytes64(x: Word64): Word64 {
266
277
  }
267
278
 
268
279
  // --- Len ---
269
- export function Len(x: number): number {
270
- return Len32(x)
280
+ export function Len(x: Word64): number {
281
+ return Len64(x)
271
282
  }
272
283
 
273
284
  export function Len8(x: number): number {
@@ -287,8 +298,11 @@ export function Len64(x: Word64): number {
287
298
  }
288
299
 
289
300
  // --- Multiplication functions ---
290
- export function Mul(x: number, y: number): [number, number] {
291
- return Mul32(x, y)
301
+ export function Mul(x: number, y: number): [number, number]
302
+ export function Mul(x: bigint, y: bigint): [bigint, bigint]
303
+ export function Mul(x: Word64, y: Word64): [number, number]
304
+ export function Mul(x: Word64, y: Word64): [Word64, Word64] {
305
+ return Mul64(x, y)
292
306
  }
293
307
 
294
308
  export function Mul32(x: number, y: number): [number, number] {
@@ -301,6 +315,7 @@ export function Mul32(x: number, y: number): [number, number] {
301
315
 
302
316
  export function Mul64(x: number, y: number): [number, number]
303
317
  export function Mul64(x: bigint, y: bigint): [bigint, bigint]
318
+ export function Mul64(x: Word64, y: Word64): [number, number]
304
319
  export function Mul64(x: Word64, y: Word64): [Word64, Word64] {
305
320
  const useBigInt = useBigIntResult(x, y)
306
321
  x = toUint64(x)
@@ -309,15 +324,15 @@ export function Mul64(x: Word64, y: Word64): [Word64, Word64] {
309
324
  const lo = product & uint64Mask
310
325
  const hi = product >> 64n
311
326
 
312
- return [
313
- word64Result(hi & uint64Mask, useBigInt),
314
- word64Result(lo, useBigInt),
315
- ]
327
+ return [word64Result(hi & uint64Mask, useBigInt), word64Result(lo, useBigInt)]
316
328
  }
317
329
 
318
330
  // --- Division functions ---
319
- export function Div(hi: number, lo: number, y: number): [number, number] {
320
- return Div32(hi, lo, y)
331
+ export function Div(hi: number, lo: number, y: number): [number, number]
332
+ export function Div(hi: bigint, lo: bigint, y: bigint): [bigint, bigint]
333
+ export function Div(hi: Word64, lo: Word64, y: Word64): [number, number]
334
+ export function Div(hi: Word64, lo: Word64, y: Word64): [Word64, Word64] {
335
+ return Div64(hi, lo, y)
321
336
  }
322
337
 
323
338
  export function Div32(hi: number, lo: number, y: number): [number, number] {
@@ -337,6 +352,7 @@ export function Div32(hi: number, lo: number, y: number): [number, number] {
337
352
 
338
353
  export function Div64(hi: number, lo: number, y: number): [number, number]
339
354
  export function Div64(hi: bigint, lo: bigint, y: bigint): [bigint, bigint]
355
+ export function Div64(hi: Word64, lo: Word64, y: Word64): [number, number]
340
356
  export function Div64(hi: Word64, lo: Word64, y: Word64): [Word64, Word64] {
341
357
  const useBigInt = useBigIntResult(hi, lo, y)
342
358
  hi = toUint64(hi)
@@ -356,8 +372,11 @@ export function Div64(hi: Word64, lo: Word64, y: Word64): [Word64, Word64] {
356
372
  }
357
373
 
358
374
  // --- Add and Sub with carry ---
359
- export function Add(x: number, y: number, carry: number): [number, number] {
360
- return Add32(x, y, carry)
375
+ export function Add(x: number, y: number, carry: number): [number, number]
376
+ export function Add(x: bigint, y: bigint, carry: bigint): [bigint, bigint]
377
+ export function Add(x: Word64, y: Word64, carry: Word64): [number, number]
378
+ export function Add(x: Word64, y: Word64, carry: Word64): [Word64, Word64] {
379
+ return Add64(x, y, carry)
361
380
  }
362
381
 
363
382
  export function Add32(x: number, y: number, carry: number): [number, number] {
@@ -369,6 +388,7 @@ export function Add32(x: number, y: number, carry: number): [number, number] {
369
388
 
370
389
  export function Add64(x: number, y: number, carry: number): [number, number]
371
390
  export function Add64(x: bigint, y: bigint, carry: bigint): [bigint, bigint]
391
+ export function Add64(x: Word64, y: Word64, carry: Word64): [number, number]
372
392
  export function Add64(x: Word64, y: Word64, carry: Word64): [Word64, Word64] {
373
393
  const useBigInt = useBigIntResult(x, y, carry)
374
394
  const sum = toUint64(x) + toUint64(y) + toUint64(carry)
@@ -377,8 +397,11 @@ export function Add64(x: Word64, y: Word64, carry: Word64): [Word64, Word64] {
377
397
  return [word64Result(result, useBigInt), word64Result(carryOut, useBigInt)]
378
398
  }
379
399
 
380
- export function Sub(x: number, y: number, borrow: number): [number, number] {
381
- return Sub32(x, y, borrow)
400
+ export function Sub(x: number, y: number, borrow: number): [number, number]
401
+ export function Sub(x: bigint, y: bigint, borrow: bigint): [bigint, bigint]
402
+ export function Sub(x: Word64, y: Word64, borrow: Word64): [number, number]
403
+ export function Sub(x: Word64, y: Word64, borrow: Word64): [Word64, Word64] {
404
+ return Sub64(x, y, borrow)
382
405
  }
383
406
 
384
407
  export function Sub32(x: number, y: number, borrow: number): [number, number] {
@@ -390,6 +413,7 @@ export function Sub32(x: number, y: number, borrow: number): [number, number] {
390
413
 
391
414
  export function Sub64(x: number, y: number, borrow: number): [number, number]
392
415
  export function Sub64(x: bigint, y: bigint, borrow: bigint): [bigint, bigint]
416
+ export function Sub64(x: Word64, y: Word64, borrow: Word64): [number, number]
393
417
  export function Sub64(x: Word64, y: Word64, borrow: Word64): [Word64, Word64] {
394
418
  const useBigInt = useBigIntResult(x, y, borrow)
395
419
  const diff = toUint64(x) - toUint64(y) - toUint64(borrow)