goscript 0.2.5 → 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.
- package/cmd/goscript/cmd-compile.go +7 -0
- package/cmd/goscript/cmd_compile_test.go +83 -0
- package/compiler/compile-request.go +3 -0
- package/compiler/compiler-cache.go +828 -0
- package/compiler/compiler-cache_test.go +705 -0
- package/compiler/config.go +2 -0
- package/compiler/index.test.ts +26 -1
- package/compiler/index.ts +5 -0
- package/compiler/lowered-program.go +31 -20
- package/compiler/lowering.go +349 -93
- package/compiler/lowering_bench_test.go +1 -0
- package/compiler/override-facts.go +309 -8
- package/compiler/override-parity-verifier.go +45 -1
- package/compiler/override-parity-verifier_test.go +100 -0
- package/compiler/override-registry_test.go +1 -0
- package/compiler/package-graph.go +40 -12
- package/compiler/package-graph_test.go +29 -0
- package/compiler/runtime-contract.go +8 -0
- package/compiler/service.go +98 -11
- package/compiler/skeleton_test.go +110 -14
- package/compiler/typescript-emitter.go +120 -23
- package/dist/compiler/index.d.ts +2 -0
- package/dist/compiler/index.js +3 -0
- package/dist/compiler/index.js.map +1 -1
- package/dist/gs/builtin/builtin.d.ts +24 -33
- package/dist/gs/builtin/builtin.js +54 -61
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/hostio.d.ts +1 -0
- package/dist/gs/builtin/hostio.js +1 -1
- package/dist/gs/builtin/hostio.js.map +1 -1
- package/dist/gs/builtin/index.d.ts +1 -0
- package/dist/gs/builtin/index.js +1 -0
- package/dist/gs/builtin/index.js.map +1 -1
- package/dist/gs/builtin/panic.d.ts +18 -0
- package/dist/gs/builtin/panic.js +98 -0
- package/dist/gs/builtin/panic.js.map +1 -0
- package/dist/gs/builtin/slice.d.ts +10 -0
- package/dist/gs/builtin/slice.js +110 -53
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/builtin/type.js +15 -3
- package/dist/gs/builtin/type.js.map +1 -1
- package/dist/gs/builtin/varRef.d.ts +1 -1
- package/dist/gs/builtin/varRef.js +3 -2
- package/dist/gs/builtin/varRef.js.map +1 -1
- package/dist/gs/bytes/bytes.gs.js +51 -38
- package/dist/gs/bytes/bytes.gs.js.map +1 -1
- package/dist/gs/bytes/reader.gs.d.ts +1 -1
- package/dist/gs/bytes/reader.gs.js +6 -7
- package/dist/gs/bytes/reader.gs.js.map +1 -1
- package/dist/gs/cmp/index.d.ts +1 -1
- package/dist/gs/cmp/index.js +43 -10
- package/dist/gs/cmp/index.js.map +1 -1
- package/dist/gs/context/context.d.ts +2 -2
- package/dist/gs/context/context.js +1 -1
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/embed/index.js +1 -1
- package/dist/gs/embed/index.js.map +1 -1
- package/dist/gs/encoding/binary/index.js +201 -8
- package/dist/gs/encoding/binary/index.js.map +1 -1
- package/dist/gs/encoding/json/index.d.ts +5 -0
- package/dist/gs/encoding/json/index.js +388 -25
- package/dist/gs/encoding/json/index.js.map +1 -1
- package/dist/gs/errors/errors.js +17 -24
- package/dist/gs/errors/errors.js.map +1 -1
- package/dist/gs/fmt/fmt.js +129 -35
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/golang.org/x/crypto/cryptobyte/index.js +1 -1
- package/dist/gs/golang.org/x/crypto/cryptobyte/index.js.map +1 -1
- package/dist/gs/internal/bytealg/index.js +43 -8
- package/dist/gs/internal/bytealg/index.js.map +1 -1
- package/dist/gs/internal/byteorder/index.d.ts +2 -2
- package/dist/gs/internal/byteorder/index.js +2 -2
- package/dist/gs/internal/byteorder/index.js.map +1 -1
- package/dist/gs/io/fs/format.js +2 -2
- package/dist/gs/io/fs/format.js.map +1 -1
- package/dist/gs/io/fs/fs.d.ts +1 -1
- package/dist/gs/io/fs/fs.js +1 -1
- package/dist/gs/io/fs/fs.js.map +1 -1
- package/dist/gs/io/io.d.ts +21 -21
- package/dist/gs/io/io.js +49 -50
- package/dist/gs/io/io.js.map +1 -1
- package/dist/gs/math/bits/index.js +26 -8
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/math/copysign.gs.js +10 -17
- package/dist/gs/math/copysign.gs.js.map +1 -1
- package/dist/gs/math/pow.gs.js +5 -0
- package/dist/gs/math/pow.gs.js.map +1 -1
- package/dist/gs/math/signbit.gs.js +6 -2
- package/dist/gs/math/signbit.gs.js.map +1 -1
- package/dist/gs/mime/index.js +1 -0
- package/dist/gs/mime/index.js.map +1 -1
- package/dist/gs/net/http/index.d.ts +6 -6
- package/dist/gs/net/http/index.js +507 -43
- package/dist/gs/net/http/index.js.map +1 -1
- package/dist/gs/os/stat.gs.d.ts +2 -2
- package/dist/gs/os/types.gs.d.ts +1 -1
- package/dist/gs/os/types.gs.js +1 -1
- package/dist/gs/os/types.gs.js.map +1 -1
- package/dist/gs/os/types_js.gs.d.ts +1 -1
- package/dist/gs/os/types_js.gs.js +7 -7
- package/dist/gs/os/types_js.gs.js.map +1 -1
- package/dist/gs/os/types_unix.gs.d.ts +1 -1
- package/dist/gs/os/types_unix.gs.js +1 -1
- package/dist/gs/os/types_unix.gs.js.map +1 -1
- package/dist/gs/os/zero_copy_posix.gs.d.ts +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js +1 -1
- package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
- package/dist/gs/path/filepath/match.js +8 -4
- package/dist/gs/path/filepath/match.js.map +1 -1
- package/dist/gs/path/filepath/path.js +216 -42
- package/dist/gs/path/filepath/path.js.map +1 -1
- package/dist/gs/path/match.js +6 -3
- package/dist/gs/path/match.js.map +1 -1
- package/dist/gs/reflect/type.d.ts +5 -4
- package/dist/gs/reflect/type.js +29 -11
- package/dist/gs/reflect/type.js.map +1 -1
- package/dist/gs/slices/slices.js +11 -11
- package/dist/gs/slices/slices.js.map +1 -1
- package/dist/gs/strconv/atof.gs.js +156 -43
- package/dist/gs/strconv/atof.gs.js.map +1 -1
- package/dist/gs/strconv/atoi.gs.d.ts +3 -2
- package/dist/gs/strconv/atoi.gs.js +86 -67
- package/dist/gs/strconv/atoi.gs.js.map +1 -1
- package/dist/gs/strconv/ftoa.gs.js +73 -3
- package/dist/gs/strconv/ftoa.gs.js.map +1 -1
- package/dist/gs/strconv/itoa.gs.d.ts +4 -4
- package/dist/gs/strconv/itoa.gs.js +5 -4
- package/dist/gs/strconv/itoa.gs.js.map +1 -1
- package/dist/gs/strconv/quote.gs.d.ts +1 -1
- package/dist/gs/strconv/quote.gs.js +311 -103
- package/dist/gs/strconv/quote.gs.js.map +1 -1
- package/dist/gs/strings/reader.d.ts +1 -1
- package/dist/gs/strings/reader.js +8 -8
- package/dist/gs/strings/reader.js.map +1 -1
- package/dist/gs/strings/strings.js +87 -61
- package/dist/gs/strings/strings.js.map +1 -1
- package/dist/gs/sync/atomic/doc_64.gs.d.ts +14 -14
- package/dist/gs/sync/atomic/doc_64.gs.js +10 -10
- package/dist/gs/sync/atomic/doc_64.gs.js.map +1 -1
- package/dist/gs/sync/atomic/type.gs.d.ts +22 -22
- package/dist/gs/sync/atomic/type.gs.js +4 -4
- package/dist/gs/sync/atomic/type.gs.js.map +1 -1
- package/dist/gs/sync/sync.js +50 -12
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/syscall/fs.d.ts +6 -6
- package/dist/gs/syscall/fs.js +1 -1
- package/dist/gs/syscall/fs.js.map +1 -1
- package/dist/gs/time/time.d.ts +18 -18
- package/dist/gs/time/time.js +58 -55
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unicode/tables.d.ts +11 -0
- package/dist/gs/unicode/tables.js +635 -0
- package/dist/gs/unicode/tables.js.map +1 -0
- package/dist/gs/unicode/unicode.d.ts +58 -38
- package/dist/gs/unicode/unicode.js +362 -278
- package/dist/gs/unicode/unicode.js.map +1 -1
- package/go.sum +13 -0
- package/gs/builtin/builtin.ts +83 -93
- package/gs/builtin/hostio.ts +1 -1
- package/gs/builtin/index.ts +1 -0
- package/gs/builtin/panic.test.ts +189 -0
- package/gs/builtin/panic.ts +107 -0
- package/gs/builtin/runtime-contract.test.ts +5 -5
- package/gs/builtin/slice.test.ts +23 -0
- package/gs/builtin/slice.ts +133 -95
- package/gs/builtin/type.ts +16 -3
- package/gs/builtin/varRef.ts +4 -2
- package/gs/builtin/wide-int.test.ts +41 -0
- package/gs/bytes/bytes.gs.ts +54 -41
- package/gs/bytes/bytes.test.ts +18 -1
- package/gs/bytes/reader.gs.ts +7 -8
- package/gs/cmp/index.test.ts +55 -0
- package/gs/cmp/index.ts +45 -9
- package/gs/context/context.ts +3 -3
- package/gs/embed/index.ts +2 -2
- package/gs/encoding/binary/index.test.ts +104 -0
- package/gs/encoding/binary/index.ts +259 -11
- package/gs/encoding/json/index.test.ts +107 -0
- package/gs/encoding/json/index.ts +400 -29
- package/gs/errors/errors.test.ts +44 -1
- package/gs/errors/errors.ts +15 -31
- package/gs/fmt/fmt.test.ts +70 -2
- package/gs/fmt/fmt.ts +128 -34
- package/gs/golang.org/x/crypto/cryptobyte/index.ts +1 -1
- package/gs/internal/bytealg/index.test.ts +26 -1
- package/gs/internal/bytealg/index.ts +44 -8
- package/gs/internal/byteorder/index.ts +6 -4
- package/gs/io/fs/format.ts +2 -2
- package/gs/io/fs/fs.ts +2 -2
- package/gs/io/fs/stat.test.ts +2 -2
- package/gs/io/fs/sub.test.ts +2 -2
- package/gs/io/fs/walk.test.ts +2 -2
- package/gs/io/io.test.ts +47 -5
- package/gs/io/io.ts +73 -73
- package/gs/io/limit.test.ts +103 -0
- package/gs/math/bits/index.test.ts +128 -0
- package/gs/math/bits/index.ts +26 -8
- package/gs/math/copysign.gs.test.ts +3 -1
- package/gs/math/copysign.gs.ts +10 -22
- package/gs/math/pow.gs.test.ts +4 -5
- package/gs/math/pow.gs.ts +5 -0
- package/gs/math/signbit.gs.test.ts +2 -1
- package/gs/math/signbit.gs.ts +6 -3
- package/gs/mime/index.ts +1 -0
- package/gs/net/http/index.test.ts +683 -2
- package/gs/net/http/index.ts +598 -57
- package/gs/net/http/meta.json +3 -0
- package/gs/os/stat.gs.ts +2 -2
- package/gs/os/types.gs.ts +2 -2
- package/gs/os/types_js.gs.ts +9 -9
- package/gs/os/types_unix.gs.ts +2 -2
- package/gs/os/zero_copy_posix.gs.ts +2 -2
- package/gs/path/filepath/match.test.ts +16 -0
- package/gs/path/filepath/match.ts +8 -4
- package/gs/path/filepath/path.test.ts +91 -9
- package/gs/path/filepath/path.ts +223 -49
- package/gs/path/match.test.ts +32 -0
- package/gs/path/match.ts +6 -3
- package/gs/reflect/deepequal.test.ts +1 -1
- package/gs/reflect/field.test.ts +1 -1
- package/gs/reflect/function-types.test.ts +6 -6
- package/gs/reflect/sliceat.test.ts +13 -13
- package/gs/reflect/structof.test.ts +4 -4
- package/gs/reflect/type.ts +34 -14
- package/gs/reflect/typefor.test.ts +5 -5
- package/gs/runtime/pprof/index.test.ts +20 -0
- package/gs/runtime/trace/index.test.ts +3 -0
- package/gs/slices/slices.test.ts +31 -0
- package/gs/slices/slices.ts +11 -11
- package/gs/strconv/append.test.ts +99 -0
- package/gs/strconv/atof.gs.ts +156 -42
- package/gs/strconv/atof.test.ts +45 -0
- package/gs/strconv/atoi.gs.ts +87 -69
- package/gs/strconv/atoi.test.ts +49 -0
- package/gs/strconv/ftoa.gs.ts +85 -10
- package/gs/strconv/ftoa.test.ts +43 -0
- package/gs/strconv/itoa.gs.ts +10 -9
- package/gs/strconv/quote.gs.ts +335 -108
- package/gs/strconv/quote.test.ts +111 -0
- package/gs/strings/reader.test.ts +10 -10
- package/gs/strings/reader.ts +9 -9
- package/gs/strings/strings.test.ts +18 -5
- package/gs/strings/strings.ts +81 -68
- package/gs/sync/atomic/doc_64.gs.ts +24 -24
- package/gs/sync/atomic/doc_64.test.ts +5 -5
- package/gs/sync/atomic/type.gs.ts +28 -28
- package/gs/sync/sync.test.ts +109 -1
- package/gs/sync/sync.ts +46 -12
- package/gs/syscall/fs.ts +8 -8
- package/gs/syscall/net.test.ts +1 -1
- package/gs/time/parse.test.ts +45 -0
- package/gs/time/time.test.ts +46 -23
- package/gs/time/time.ts +69 -66
- package/gs/unicode/gen.go +198 -0
- package/gs/unicode/tables.ts +646 -0
- package/gs/unicode/unicode.test.ts +69 -0
- package/gs/unicode/unicode.ts +396 -312
- package/package.json +2 -2
- package/dist/gs/github.com/aperturerobotics/util/conc/index.d.ts +0 -20
- package/dist/gs/github.com/aperturerobotics/util/conc/index.js +0 -134
- package/dist/gs/github.com/aperturerobotics/util/conc/index.js.map +0 -1
- package/gs/github.com/aperturerobotics/util/conc/index.test.ts +0 -30
- package/gs/github.com/aperturerobotics/util/conc/index.ts +0 -172
- package/gs/github.com/aperturerobotics/util/conc/meta.json +0 -9
package/gs/sync/sync.test.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
//
|
|
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 (
|
|
517
|
-
|
|
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 (
|
|
529
|
-
|
|
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 (
|
|
543
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
131
|
+
_offset: bigint,
|
|
132
132
|
_whence: number,
|
|
133
|
-
): [
|
|
134
|
-
return [
|
|
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:
|
|
216
|
+
export function SetReadDeadline(_fd: number, _t: bigint): $.GoError {
|
|
217
217
|
return ENOSYS
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
-
export function SetWriteDeadline(_fd: number, _t:
|
|
220
|
+
export function SetWriteDeadline(_fd: number, _t: bigint): $.GoError {
|
|
221
221
|
return ENOSYS
|
|
222
222
|
}
|
|
223
223
|
|
package/gs/syscall/net.test.ts
CHANGED
|
@@ -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,
|
|
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
|
+
})
|
package/gs/time/time.test.ts
CHANGED
|
@@ -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(
|
|
47
|
-
expect(Duration_String(
|
|
48
|
-
expect(Duration_String(-
|
|
49
|
-
expect(Duration_String(
|
|
50
|
-
expect(Duration_String(
|
|
51
|
-
expect(Duration_String(
|
|
52
|
-
expect(Duration_String(
|
|
53
|
-
expect(Duration_String(
|
|
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(
|
|
60
|
-
expect(Duration_Microseconds(
|
|
61
|
-
expect(Duration_Milliseconds(
|
|
62
|
-
expect(Duration_Seconds(
|
|
63
|
-
expect(Duration_Minutes(
|
|
64
|
-
expect(Duration_Hours(
|
|
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(
|
|
69
|
-
expect(Duration_Truncate(-
|
|
70
|
-
expect(Duration_Round(
|
|
71
|
-
expect(Duration_Round(-
|
|
72
|
-
expect(Duration_Round(
|
|
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(
|
|
77
|
-
expect(Duration_Abs(-
|
|
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([
|
|
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([
|
|
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
|
})
|