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
@@ -2,7 +2,18 @@ import { describe, expect, it } from 'vitest'
2
2
 
3
3
  import * as $ from '@goscript/builtin/index.js'
4
4
 
5
- import { Cond, Map, Mutex, Pool, RWMutex, WaitGroup } from './sync.js'
5
+ import {
6
+ Cond,
7
+ Map,
8
+ Mutex,
9
+ Once,
10
+ OnceFunc,
11
+ OnceValue,
12
+ OnceValues,
13
+ Pool,
14
+ RWMutex,
15
+ WaitGroup,
16
+ } from './sync.js'
6
17
 
7
18
  describe('sync.WaitGroup', () => {
8
19
  it('Go tracks scheduled work and unblocks Wait after completion', async () => {
@@ -44,6 +55,103 @@ describe('sync.RWMutex', () => {
44
55
  await locker.Lock()
45
56
  locker.Unlock()
46
57
  })
58
+
59
+ it('blocks new readers while a writer is waiting', async () => {
60
+ const rw = new RWMutex()
61
+ const events: string[] = []
62
+
63
+ await rw.RLock()
64
+ const writer = rw.Lock().then(() => {
65
+ events.push('writer')
66
+ })
67
+ const reader = rw.RLock().then(() => {
68
+ events.push('reader')
69
+ })
70
+ await Promise.resolve()
71
+
72
+ expect(events).toEqual([])
73
+ expect(rw.TryRLock()).toBe(false)
74
+
75
+ rw.RUnlock()
76
+ await writer
77
+ expect(events).toEqual(['writer'])
78
+
79
+ rw.Unlock()
80
+ await reader
81
+ expect(events).toEqual(['writer', 'reader'])
82
+ rw.RUnlock()
83
+ })
84
+ })
85
+
86
+ describe('sync.Once', () => {
87
+ it('marks Do complete even when f panics', async () => {
88
+ const once = new Once()
89
+ let calls = 0
90
+
91
+ await expect(
92
+ once.Do(() => {
93
+ calls++
94
+ throw new Error('boom')
95
+ }),
96
+ ).rejects.toThrow('boom')
97
+ await once.Do(() => {
98
+ calls++
99
+ })
100
+
101
+ expect(calls).toBe(1)
102
+ })
103
+
104
+ it('OnceFunc and OnceValue helpers replay the first panic', () => {
105
+ let funcCalls = 0
106
+ const fn = OnceFunc(() => {
107
+ funcCalls++
108
+ throw new Error('func panic')
109
+ })
110
+
111
+ expect(fn).toThrow('func panic')
112
+ expect(fn).toThrow('func panic')
113
+ expect(funcCalls).toBe(1)
114
+
115
+ let valueCalls = 0
116
+ const value = OnceValue(() => {
117
+ valueCalls++
118
+ throw new Error('value panic')
119
+ })
120
+
121
+ expect(value).toThrow('value panic')
122
+ expect(value).toThrow('value panic')
123
+ expect(valueCalls).toBe(1)
124
+
125
+ let valuesCalls = 0
126
+ const values = OnceValues(() => {
127
+ valuesCalls++
128
+ throw new Error('values panic')
129
+ })
130
+
131
+ expect(values).toThrow('values panic')
132
+ expect(values).toThrow('values panic')
133
+ expect(valuesCalls).toBe(1)
134
+ })
135
+
136
+ it('OnceValue helpers return the first successful result', () => {
137
+ let valueCalls = 0
138
+ const value = OnceValue(() => {
139
+ valueCalls++
140
+ return 'first'
141
+ })
142
+ let valuesCalls = 0
143
+ const values = OnceValues(() => {
144
+ valuesCalls++
145
+ return ['left', 'right'] as [string, string]
146
+ })
147
+
148
+ expect(value()).toBe('first')
149
+ expect(value()).toBe('first')
150
+ expect(valueCalls).toBe(1)
151
+ expect(values()).toEqual(['left', 'right'])
152
+ expect(values()).toEqual(['left', 'right'])
153
+ expect(valuesCalls).toBe(1)
154
+ })
47
155
  })
48
156
 
49
157
  describe('sync.Map', () => {
package/gs/sync/sync.ts CHANGED
@@ -28,8 +28,7 @@ export class Mutex implements Locker {
28
28
  return
29
29
  }
30
30
 
31
- // In a real implementation, this would block the goroutine
32
- // Use Promise to simulate blocking behavior like channels
31
+ // GoScript lowers goroutine blocking to async suspension.
33
32
  return new Promise<void>((resolve) => {
34
33
  this._waitQueue.push(resolve)
35
34
  })
@@ -56,7 +55,6 @@ export class Mutex implements Locker {
56
55
  if (this._waitQueue.length > 0) {
57
56
  const next = this._waitQueue.shift()!
58
57
  this._locked = true
59
- // Use queueMicrotask to simulate goroutine scheduling
60
58
  queueMicrotask(() => next())
61
59
  }
62
60
  }
@@ -111,7 +109,7 @@ export class RWMutex {
111
109
 
112
110
  // RLock locks rw for reading
113
111
  public async RLock(): Promise<void> {
114
- if (!this._writer) {
112
+ if (!this._writer && this._writerWaitQueue.length === 0) {
115
113
  this._readers++
116
114
  return
117
115
  }
@@ -126,7 +124,7 @@ export class RWMutex {
126
124
 
127
125
  // TryRLock tries to lock rw for reading and reports whether it succeeded
128
126
  public TryRLock(): boolean {
129
- if (!this._writer) {
127
+ if (!this._writer && this._writerWaitQueue.length === 0) {
130
128
  this._readers++
131
129
  return true
132
130
  }
@@ -254,8 +252,8 @@ export class Once {
254
252
  await this._m.Lock()
255
253
  try {
256
254
  if (!this._done) {
257
- await f()
258
255
  this._done = true
256
+ await f()
259
257
  }
260
258
  } finally {
261
259
  this._m.Unlock()
@@ -512,10 +510,22 @@ export class Pool {
512
510
  // OnceFunc returns a function that invokes f only once
513
511
  export function OnceFunc(f: () => void): () => void {
514
512
  let called = false
513
+ let panicked = false
514
+ let panicValue: unknown
515
515
  return () => {
516
- if (!called) {
517
- called = true
516
+ if (called) {
517
+ if (panicked) {
518
+ throw panicValue
519
+ }
520
+ return
521
+ }
522
+ called = true
523
+ try {
518
524
  f()
525
+ } catch (err) {
526
+ panicked = true
527
+ panicValue = err
528
+ throw err
519
529
  }
520
530
  }
521
531
  }
@@ -524,10 +534,22 @@ export function OnceFunc(f: () => void): () => void {
524
534
  export function OnceValue<T>(f: () => T): () => T {
525
535
  let value: T
526
536
  let called = false
537
+ let panicked = false
538
+ let panicValue: unknown
527
539
  return () => {
528
- if (!called) {
529
- called = true
540
+ if (called) {
541
+ if (panicked) {
542
+ throw panicValue
543
+ }
544
+ return value
545
+ }
546
+ called = true
547
+ try {
530
548
  value = f()
549
+ } catch (err) {
550
+ panicked = true
551
+ panicValue = err
552
+ throw err
531
553
  }
532
554
  return value
533
555
  }
@@ -538,10 +560,22 @@ export function OnceValues<T1, T2>(f: () => [T1, T2]): () => [T1, T2] {
538
560
  let value1: T1
539
561
  let value2: T2
540
562
  let called = false
563
+ let panicked = false
564
+ let panicValue: unknown
541
565
  return () => {
542
- if (!called) {
543
- called = true
566
+ if (called) {
567
+ if (panicked) {
568
+ throw panicValue
569
+ }
570
+ return [value1, value2]
571
+ }
572
+ called = true
573
+ try {
544
574
  ;[value1, value2] = f()
575
+ } catch (err) {
576
+ panicked = true
577
+ panicValue = err
578
+ throw err
545
579
  }
546
580
  return [value1, value2]
547
581
  }
package/gs/syscall/fs.ts CHANGED
@@ -95,7 +95,7 @@ export function Fsync(_fd: number): $.GoError {
95
95
  return ENOSYS
96
96
  }
97
97
 
98
- export function Ftruncate(_fd: number, _length: number): $.GoError {
98
+ export function Ftruncate(_fd: number, _length: bigint): $.GoError {
99
99
  return ENOSYS
100
100
  }
101
101
 
@@ -113,7 +113,7 @@ export function ReadDirent(
113
113
  export function Pread(
114
114
  _fd: number,
115
115
  _b: $.Bytes | null,
116
- _offset: number,
116
+ _offset: bigint,
117
117
  ): [number, $.GoError] {
118
118
  return [0, ENOSYS]
119
119
  }
@@ -121,17 +121,17 @@ export function Pread(
121
121
  export function Pwrite(
122
122
  _fd: number,
123
123
  _b: $.Bytes | null,
124
- _offset: number,
124
+ _offset: bigint,
125
125
  ): [number, $.GoError] {
126
126
  return [0, ENOSYS]
127
127
  }
128
128
 
129
129
  export function Seek(
130
130
  _fd: number,
131
- _offset: number,
131
+ _offset: bigint,
132
132
  _whence: number,
133
- ): [number, $.GoError] {
134
- return [0, ENOSYS]
133
+ ): [bigint, $.GoError] {
134
+ return [0n, ENOSYS]
135
135
  }
136
136
 
137
137
  export function Write(_fd: number, _b: $.Bytes | null): [number, $.GoError] {
@@ -213,11 +213,11 @@ export function SendmsgN(
213
213
  return [0, ENOSYS]
214
214
  }
215
215
 
216
- export function SetReadDeadline(_fd: number, _t: number): $.GoError {
216
+ export function SetReadDeadline(_fd: number, _t: bigint): $.GoError {
217
217
  return ENOSYS
218
218
  }
219
219
 
220
- export function SetWriteDeadline(_fd: number, _t: number): $.GoError {
220
+ export function SetWriteDeadline(_fd: number, _t: bigint): $.GoError {
221
221
  return ENOSYS
222
222
  }
223
223
 
@@ -102,7 +102,7 @@ describe('syscall network stubs', () => {
102
102
  expect(ReadDirent(-1, null)).toEqual([0, ENOSYS])
103
103
  expect(Pread(-1, null, 0)).toEqual([0, ENOSYS])
104
104
  expect(Pwrite(-1, null, 0)).toEqual([0, ENOSYS])
105
- expect(Seek(-1, 0, 0)).toEqual([0, ENOSYS])
105
+ expect(Seek(-1, 0n, 0)).toEqual([0n, ENOSYS])
106
106
  expect(Write(-1, null)).toEqual([0, ENOSYS])
107
107
  expect(Dup(-1)).toEqual([0, ENOSYS])
108
108
  expect(readv(-1, [new Iovec()])).toEqual([0, ENOSYS])
@@ -0,0 +1,45 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import {
4
+ FixedZone,
5
+ Hour,
6
+ Now,
7
+ Parse,
8
+ ParseInLocation,
9
+ RFC3339,
10
+ Since,
11
+ Until,
12
+ } from './index.js'
13
+
14
+ // Reference Unix seconds are produced by Go's time package for the same input.
15
+ describe('time parse/since/until (Go semantics)', () => {
16
+ it('Parse reads an RFC3339 timestamp as UTC', () => {
17
+ const [t, err] = Parse(RFC3339, '2026-06-22T15:04:05Z')
18
+ expect(err).toBeNull()
19
+ expect(t.Unix()).toBe(1782140645n)
20
+ })
21
+
22
+ it('ParseInLocation honors the zone offset', () => {
23
+ const [t, err] = ParseInLocation(
24
+ RFC3339,
25
+ '2026-06-22T15:04:05+01:00',
26
+ FixedZone('X', 3600),
27
+ )
28
+ expect(err).toBeNull()
29
+ expect(t.Unix()).toBe(1782137045n)
30
+ })
31
+
32
+ it('Since measures elapsed time as a positive delta', () => {
33
+ const past = Now().Add(-Hour)
34
+ const elapsed = Since(past)
35
+ expect(elapsed >= Hour).toBe(true)
36
+ expect(elapsed < Hour + 5n * 1000000000n).toBe(true)
37
+ })
38
+
39
+ it('Until measures remaining time toward a future instant', () => {
40
+ const future = Now().Add(Hour)
41
+ const remaining = Until(future)
42
+ expect(remaining <= Hour).toBe(true)
43
+ expect(remaining > Hour - 5n * 1000000000n).toBe(true)
44
+ })
45
+ })
@@ -37,44 +37,47 @@ import {
37
37
  Sunday,
38
38
  May,
39
39
  Time,
40
+ Tick,
40
41
  UTC,
42
+ UnixMicro,
43
+ UnixMilli,
41
44
  } from './time.js'
42
45
  import type { Month } from './time.js'
43
46
 
44
47
  describe('time.Duration_String', () => {
45
48
  it('formats common durations', () => {
46
- expect(Duration_String(0)).toBe('0s')
47
- expect(Duration_String(1500 * Millisecond)).toBe('1.5s')
48
- expect(Duration_String(-1500 * Millisecond)).toBe('-1.5s')
49
- expect(Duration_String(2 * Second)).toBe('2s')
50
- expect(Duration_String(9 * Millisecond)).toBe('9ms')
51
- expect(Duration_String(1500 * Microsecond)).toBe('1.5ms')
52
- expect(Duration_String(1500)).toBe('1.5\u00b5s')
53
- expect(Duration_String(12)).toBe('12ns')
49
+ expect(Duration_String(0n)).toBe('0s')
50
+ expect(Duration_String(1500n * Millisecond)).toBe('1.5s')
51
+ expect(Duration_String(-1500n * Millisecond)).toBe('-1.5s')
52
+ expect(Duration_String(2n * Second)).toBe('2s')
53
+ expect(Duration_String(9n * Millisecond)).toBe('9ms')
54
+ expect(Duration_String(1500n * Microsecond)).toBe('1.5ms')
55
+ expect(Duration_String(1500n)).toBe('1.5\u00b5s')
56
+ expect(Duration_String(12n)).toBe('12ns')
54
57
  })
55
58
  })
56
59
 
57
60
  describe('time.Duration methods', () => {
58
61
  it('converts to integer and fractional units', () => {
59
- expect(Duration_Nanoseconds(1500 * Microsecond)).toBe(1500000)
60
- expect(Duration_Microseconds(1500 * Microsecond)).toBe(1500)
61
- expect(Duration_Milliseconds(1500 * Microsecond)).toBe(1)
62
- expect(Duration_Seconds(1500 * Millisecond)).toBe(1.5)
63
- expect(Duration_Minutes(90 * Second)).toBe(1.5)
64
- expect(Duration_Hours(90 * Minute)).toBe(1.5)
62
+ expect(Duration_Nanoseconds(1500n * Microsecond)).toBe(1500000n)
63
+ expect(Duration_Microseconds(1500n * Microsecond)).toBe(1500n)
64
+ expect(Duration_Milliseconds(1500n * Microsecond)).toBe(1n)
65
+ expect(Duration_Seconds(1500n * Millisecond)).toBe(1.5)
66
+ expect(Duration_Minutes(90n * Second)).toBe(1.5)
67
+ expect(Duration_Hours(90n * Minute)).toBe(1.5)
65
68
  })
66
69
 
67
70
  it('rounds and truncates with Go duration semantics', () => {
68
- expect(Duration_Truncate(1500 * Millisecond, Second)).toBe(Second)
69
- expect(Duration_Truncate(-1500 * Millisecond, Second)).toBe(-Second)
70
- expect(Duration_Round(1500 * Millisecond, Second)).toBe(2 * Second)
71
- expect(Duration_Round(-1500 * Millisecond, Second)).toBe(-2 * Second)
72
- expect(Duration_Round(1500 * Millisecond, 0)).toBe(1500 * Millisecond)
71
+ expect(Duration_Truncate(1500n * Millisecond, Second)).toBe(Second)
72
+ expect(Duration_Truncate(-1500n * Millisecond, Second)).toBe(-Second)
73
+ expect(Duration_Round(1500n * Millisecond, Second)).toBe(2n * Second)
74
+ expect(Duration_Round(-1500n * Millisecond, Second)).toBe(-2n * Second)
75
+ expect(Duration_Round(1500n * Millisecond, 0n)).toBe(1500n * Millisecond)
73
76
  })
74
77
 
75
78
  it('returns absolute values', () => {
76
- expect(Duration_Abs(2 * Second)).toBe(2 * Second)
77
- expect(Duration_Abs(-2 * Second)).toBe(2 * Second)
79
+ expect(Duration_Abs(2n * Second)).toBe(2n * Second)
80
+ expect(Duration_Abs(-2n * Second)).toBe(2n * Second)
78
81
  })
79
82
  })
80
83
 
@@ -113,6 +116,12 @@ describe('time constants and timers', () => {
113
116
 
114
117
  expect(value.Unix()).toBeGreaterThan(0)
115
118
  })
119
+
120
+ it('delivers Tick values on C', async () => {
121
+ const value = await Tick(0).receive()
122
+
123
+ expect(value.Unix()).toBeGreaterThan(0)
124
+ })
116
125
  })
117
126
 
118
127
  describe('time.Time.In', () => {
@@ -134,6 +143,16 @@ describe('time.Time.In', () => {
134
143
  })
135
144
 
136
145
  describe('time.Time calendar and binary helpers', () => {
146
+ it('round-trips Unix millisecond and microsecond constructors', () => {
147
+ const millis = UnixMilli(1234567890123n)
148
+ const micros = UnixMicro(1234567890123456n)
149
+
150
+ expect(millis.UnixMilli()).toBe(1234567890123n)
151
+ expect(millis.Unix()).toBe(1234567890n)
152
+ expect(micros.UnixMicro()).toBe(1234567890123456n)
153
+ expect(micros.Unix()).toBe(1234567890n)
154
+ })
155
+
137
156
  it('appends formatted text to byte slices', () => {
138
157
  const t = Date(2025, May, 15, 1, 10, 42, 0, UTC)
139
158
  const out = t.AppendFormat($.stringToBytes('ts='), RFC3339)
@@ -175,11 +194,15 @@ describe('time.Time calendar and binary helpers', () => {
175
194
  )
176
195
 
177
196
  expect(utc.MarshalBinary()).toEqual([
178
- new Uint8Array([1, 0, 0, 0, 14, 223, 183, 54, 18, 7, 91, 205, 21, 255, 255]),
197
+ new Uint8Array([
198
+ 1, 0, 0, 0, 14, 223, 183, 54, 18, 7, 91, 205, 21, 255, 255,
199
+ ]),
179
200
  null,
180
201
  ])
181
202
  expect(pdt.MarshalBinary()).toEqual([
182
- new Uint8Array([1, 0, 0, 0, 14, 223, 183, 54, 18, 7, 91, 205, 21, 254, 92]),
203
+ new Uint8Array([
204
+ 1, 0, 0, 0, 14, 223, 183, 54, 18, 7, 91, 205, 21, 254, 92,
205
+ ]),
183
206
  null,
184
207
  ])
185
208
  })