goscript 0.0.25 → 0.0.28
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/README.md +4 -4
- package/cmd/goscript/cmd_compile.go +0 -3
- package/cmd/goscript/deps.go +11 -0
- package/compiler/analysis.go +259 -55
- package/compiler/assignment.go +2 -2
- package/compiler/builtin_test.go +1 -1
- package/compiler/compiler.go +201 -49
- package/compiler/compiler_test.go +53 -0
- package/compiler/composite-lit.go +32 -8
- package/compiler/decl.go +6 -6
- package/compiler/expr-call.go +83 -0
- package/compiler/expr.go +1 -1
- package/compiler/protobuf.go +557 -0
- package/compiler/spec-struct.go +4 -0
- package/compiler/spec-value.go +11 -3
- package/compiler/spec.go +18 -1
- package/compiler/stmt-assign.go +35 -0
- package/compiler/type-assert.go +87 -0
- package/compiler/type.go +5 -2
- package/dist/gs/builtin/builtin.d.ts +19 -1
- package/dist/gs/builtin/builtin.js +85 -5
- package/dist/gs/builtin/builtin.js.map +1 -1
- package/dist/gs/builtin/channel.js.map +1 -1
- package/dist/gs/builtin/slice.d.ts +1 -1
- package/dist/gs/builtin/slice.js +59 -26
- package/dist/gs/builtin/slice.js.map +1 -1
- package/dist/gs/cmp/index.js.map +1 -1
- package/dist/gs/context/context.d.ts +1 -1
- package/dist/gs/context/context.js +20 -11
- package/dist/gs/context/context.js.map +1 -1
- package/dist/gs/errors/errors.d.ts +7 -0
- package/dist/gs/errors/errors.js +190 -0
- package/dist/gs/errors/errors.js.map +1 -0
- package/dist/gs/errors/index.d.ts +1 -0
- package/dist/gs/errors/index.js +2 -0
- package/dist/gs/errors/index.js.map +1 -0
- package/dist/gs/internal/goarch/index.js +1 -1
- package/dist/gs/internal/goarch/index.js.map +1 -1
- package/dist/gs/io/index.d.ts +1 -0
- package/dist/gs/io/index.js +2 -0
- package/dist/gs/io/index.js.map +1 -0
- package/dist/gs/io/io.d.ts +107 -0
- package/dist/gs/io/io.js +385 -0
- package/dist/gs/io/io.js.map +1 -0
- package/dist/gs/iter/iter.js.map +1 -1
- package/dist/gs/math/bits/index.js +34 -32
- package/dist/gs/math/bits/index.js.map +1 -1
- package/dist/gs/runtime/runtime.d.ts +1 -0
- package/dist/gs/runtime/runtime.js +15 -18
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/slices/slices.d.ts +1 -1
- package/dist/gs/slices/slices.js +1 -1
- package/dist/gs/slices/slices.js.map +1 -1
- package/dist/gs/strings/builder.d.ts +18 -0
- package/dist/gs/strings/builder.js +205 -0
- package/dist/gs/strings/builder.js.map +1 -0
- package/dist/gs/strings/clone.d.ts +1 -0
- package/dist/gs/strings/clone.js +16 -0
- package/dist/gs/strings/clone.js.map +1 -0
- package/dist/gs/strings/compare.d.ts +1 -0
- package/dist/gs/strings/compare.js +14 -0
- package/dist/gs/strings/compare.js.map +1 -0
- package/dist/gs/strings/index.d.ts +2 -0
- package/dist/gs/strings/index.js +3 -0
- package/dist/gs/strings/index.js.map +1 -0
- package/dist/gs/strings/iter.d.ts +8 -0
- package/dist/gs/strings/iter.js +160 -0
- package/dist/gs/strings/iter.js.map +1 -0
- package/dist/gs/strings/reader.d.ts +34 -0
- package/dist/gs/strings/reader.js +418 -0
- package/dist/gs/strings/reader.js.map +1 -0
- package/dist/gs/strings/replace.d.ts +106 -0
- package/dist/gs/strings/replace.js +1136 -0
- package/dist/gs/strings/replace.js.map +1 -0
- package/dist/gs/strings/search.d.ts +24 -0
- package/dist/gs/strings/search.js +169 -0
- package/dist/gs/strings/search.js.map +1 -0
- package/dist/gs/strings/strings.d.ts +47 -0
- package/dist/gs/strings/strings.js +418 -0
- package/dist/gs/strings/strings.js.map +1 -0
- package/dist/gs/stringslite/index.d.ts +1 -0
- package/dist/gs/stringslite/index.js +2 -0
- package/dist/gs/stringslite/index.js.map +1 -0
- package/dist/gs/stringslite/strings.d.ts +11 -0
- package/dist/gs/stringslite/strings.js +67 -0
- package/dist/gs/stringslite/strings.js.map +1 -0
- package/dist/gs/sync/index.d.ts +1 -0
- package/dist/gs/sync/index.js +2 -0
- package/dist/gs/sync/index.js.map +1 -0
- package/dist/gs/sync/sync.d.ts +79 -0
- package/dist/gs/sync/sync.js +392 -0
- package/dist/gs/sync/sync.js.map +1 -0
- package/dist/gs/time/time.js +7 -7
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unicode/index.d.ts +1 -0
- package/dist/gs/unicode/index.js +2 -0
- package/dist/gs/unicode/index.js.map +1 -0
- package/dist/gs/unicode/unicode.d.ts +105 -0
- package/dist/gs/unicode/unicode.js +332 -0
- package/dist/gs/unicode/unicode.js.map +1 -0
- package/dist/gs/unicode/utf8/index.d.ts +1 -0
- package/dist/gs/unicode/utf8/index.js +3 -0
- package/dist/gs/unicode/utf8/index.js.map +1 -0
- package/dist/gs/unicode/utf8/utf8.d.ts +20 -0
- package/dist/gs/unicode/utf8/utf8.js +196 -0
- package/dist/gs/unicode/utf8/utf8.js.map +1 -0
- package/dist/gs/unsafe/index.d.ts +1 -0
- package/dist/gs/unsafe/index.js +2 -0
- package/dist/gs/unsafe/index.js.map +1 -0
- package/dist/gs/unsafe/unsafe.d.ts +11 -0
- package/dist/gs/unsafe/unsafe.js +44 -0
- package/dist/gs/unsafe/unsafe.js.map +1 -0
- package/go.mod +2 -1
- package/go.sum +6 -2
- package/gs/README.md +6 -0
- package/gs/builtin/builtin.ts +158 -0
- package/gs/builtin/channel.ts +683 -0
- package/gs/builtin/defer.ts +58 -0
- package/gs/builtin/index.ts +1 -0
- package/gs/builtin/io.ts +22 -0
- package/gs/builtin/map.ts +50 -0
- package/gs/builtin/slice.ts +1030 -0
- package/gs/builtin/type.ts +1106 -0
- package/gs/builtin/varRef.ts +25 -0
- package/gs/cmp/godoc.txt +8 -0
- package/gs/cmp/index.ts +29 -0
- package/gs/context/context.ts +401 -0
- package/gs/context/godoc.txt +69 -0
- package/gs/context/index.ts +1 -0
- package/gs/errors/errors.ts +223 -0
- package/gs/errors/godoc.txt +63 -0
- package/gs/errors/index.ts +1 -0
- package/gs/internal/goarch/godoc.txt +39 -0
- package/gs/internal/goarch/index.ts +18 -0
- package/gs/io/godoc.txt +61 -0
- package/gs/io/index.ts +1 -0
- package/gs/io/io.go +75 -0
- package/gs/io/io.ts +546 -0
- package/gs/iter/godoc.txt +203 -0
- package/gs/iter/index.ts +1 -0
- package/gs/iter/iter.ts +117 -0
- package/gs/math/bits/index.ts +356 -0
- package/gs/math/godoc.txt +76 -0
- package/gs/runtime/godoc.txt +331 -0
- package/gs/runtime/index.ts +1 -0
- package/gs/runtime/runtime.ts +178 -0
- package/gs/slices/godoc.txt +44 -0
- package/gs/slices/index.ts +1 -0
- package/gs/slices/slices.ts +22 -0
- package/gs/strings/builder.test.ts +121 -0
- package/gs/strings/builder.ts +223 -0
- package/gs/strings/clone.test.ts +43 -0
- package/gs/strings/clone.ts +17 -0
- package/gs/strings/compare.test.ts +84 -0
- package/gs/strings/compare.ts +13 -0
- package/gs/strings/godoc.txt +66 -0
- package/gs/strings/index.ts +2 -0
- package/gs/strings/iter.test.ts +343 -0
- package/gs/strings/iter.ts +171 -0
- package/gs/strings/reader.test.ts +243 -0
- package/gs/strings/reader.ts +451 -0
- package/gs/strings/replace.test.ts +181 -0
- package/gs/strings/replace.ts +1310 -0
- package/gs/strings/search.test.ts +214 -0
- package/gs/strings/search.ts +213 -0
- package/gs/strings/strings.test.ts +477 -0
- package/gs/strings/strings.ts +510 -0
- package/gs/stringslite/godoc.txt +17 -0
- package/gs/stringslite/index.ts +1 -0
- package/gs/stringslite/strings.ts +82 -0
- package/gs/sync/godoc.txt +21 -0
- package/gs/sync/index.ts +1 -0
- package/gs/sync/sync.go +64 -0
- package/gs/sync/sync.ts +449 -0
- package/gs/time/godoc.md +116 -0
- package/gs/time/godoc.txt +116 -0
- package/gs/time/index.ts +1 -0
- package/gs/time/time.ts +272 -0
- package/gs/unicode/godoc.txt +52 -0
- package/gs/unicode/index.ts +1 -0
- package/gs/unicode/unicode.go +38 -0
- package/gs/unicode/unicode.ts +418 -0
- package/gs/unicode/utf8/godoc.txt +22 -0
- package/gs/unicode/utf8/index.ts +2 -0
- package/gs/unicode/utf8/utf8.ts +227 -0
- package/gs/unsafe/godoc.txt +19 -0
- package/gs/unsafe/index.ts +1 -0
- package/gs/unsafe/unsafe.test.ts +68 -0
- package/gs/unsafe/unsafe.ts +77 -0
- package/package.json +6 -4
package/gs/sync/sync.ts
ADDED
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
// Package sync provides basic synchronization primitives such as mutual exclusion
|
|
2
|
+
// locks. Other than the Once and WaitGroup types, most are intended for use by
|
|
3
|
+
// low-level library routines. Higher-level synchronization is better done via
|
|
4
|
+
// channels and communication.
|
|
5
|
+
|
|
6
|
+
// Locker represents an object that can be locked and unlocked
|
|
7
|
+
export interface Locker {
|
|
8
|
+
Lock(): Promise<void>
|
|
9
|
+
Unlock(): void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Mutex is a mutual exclusion lock
|
|
13
|
+
export class Mutex implements Locker {
|
|
14
|
+
private _locked: boolean = false
|
|
15
|
+
private _waitQueue: Array<() => void> = []
|
|
16
|
+
|
|
17
|
+
constructor(init?: Partial<{}>) {
|
|
18
|
+
// Mutex has no public fields to initialize
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Lock locks m
|
|
22
|
+
// If the lock is already in use, the calling goroutine blocks until the mutex is available
|
|
23
|
+
public async Lock(): Promise<void> {
|
|
24
|
+
if (!this._locked) {
|
|
25
|
+
this._locked = true
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// In a real implementation, this would block the goroutine
|
|
30
|
+
// Use Promise to simulate blocking behavior like channels
|
|
31
|
+
return new Promise<void>((resolve) => {
|
|
32
|
+
this._waitQueue.push(resolve)
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// TryLock tries to lock m and reports whether it succeeded
|
|
37
|
+
public TryLock(): boolean {
|
|
38
|
+
if (!this._locked) {
|
|
39
|
+
this._locked = true
|
|
40
|
+
return true
|
|
41
|
+
}
|
|
42
|
+
return false
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Unlock unlocks m
|
|
46
|
+
public Unlock(): void {
|
|
47
|
+
if (!this._locked) {
|
|
48
|
+
throw new Error('sync: unlock of unlocked mutex')
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this._locked = false
|
|
52
|
+
|
|
53
|
+
// Wake up the next waiting goroutine
|
|
54
|
+
if (this._waitQueue.length > 0) {
|
|
55
|
+
const next = this._waitQueue.shift()!
|
|
56
|
+
this._locked = true
|
|
57
|
+
// Use queueMicrotask to simulate goroutine scheduling
|
|
58
|
+
queueMicrotask(() => next())
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// clone returns a copy of this Mutex instance
|
|
63
|
+
public clone(): Mutex {
|
|
64
|
+
return new Mutex()
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// RWMutex is a reader/writer mutual exclusion lock
|
|
69
|
+
export class RWMutex {
|
|
70
|
+
private _readers: number = 0
|
|
71
|
+
private _writer: boolean = false
|
|
72
|
+
private _readerWaitQueue: Array<() => void> = []
|
|
73
|
+
private _writerWaitQueue: Array<() => void> = []
|
|
74
|
+
|
|
75
|
+
constructor(init?: Partial<{}>) {
|
|
76
|
+
// RWMutex has no public fields to initialize
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Lock locks rw for writing
|
|
80
|
+
public async Lock(): Promise<void> {
|
|
81
|
+
if (!this._writer && this._readers === 0) {
|
|
82
|
+
this._writer = true
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return new Promise<void>((resolve) => {
|
|
87
|
+
this._writerWaitQueue.push(resolve)
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// TryLock tries to lock rw for writing and reports whether it succeeded
|
|
92
|
+
public TryLock(): boolean {
|
|
93
|
+
if (!this._writer && this._readers === 0) {
|
|
94
|
+
this._writer = true
|
|
95
|
+
return true
|
|
96
|
+
}
|
|
97
|
+
return false
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Unlock unlocks rw for writing
|
|
101
|
+
public Unlock(): void {
|
|
102
|
+
if (!this._writer) {
|
|
103
|
+
throw new Error('sync: unlock of unlocked RWMutex')
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
this._writer = false
|
|
107
|
+
this._wakeUpWaiters()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// RLock locks rw for reading
|
|
111
|
+
public async RLock(): Promise<void> {
|
|
112
|
+
if (!this._writer) {
|
|
113
|
+
this._readers++
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return new Promise<void>((resolve) => {
|
|
118
|
+
this._readerWaitQueue.push(() => {
|
|
119
|
+
this._readers++
|
|
120
|
+
resolve()
|
|
121
|
+
})
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// TryRLock tries to lock rw for reading and reports whether it succeeded
|
|
126
|
+
public TryRLock(): boolean {
|
|
127
|
+
if (!this._writer) {
|
|
128
|
+
this._readers++
|
|
129
|
+
return true
|
|
130
|
+
}
|
|
131
|
+
return false
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// RUnlock undoes a single RLock call
|
|
135
|
+
public RUnlock(): void {
|
|
136
|
+
if (this._readers === 0) {
|
|
137
|
+
throw new Error('sync: RUnlock of unlocked RWMutex')
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
this._readers--
|
|
141
|
+
if (this._readers === 0) {
|
|
142
|
+
this._wakeUpWaiters()
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private _wakeUpWaiters(): void {
|
|
147
|
+
// Prioritize writers
|
|
148
|
+
if (this._writerWaitQueue.length > 0 && this._readers === 0) {
|
|
149
|
+
const next = this._writerWaitQueue.shift()!
|
|
150
|
+
this._writer = true
|
|
151
|
+
queueMicrotask(() => next())
|
|
152
|
+
} else if (this._readerWaitQueue.length > 0 && !this._writer) {
|
|
153
|
+
// Wake up all waiting readers
|
|
154
|
+
const readers = this._readerWaitQueue.splice(0)
|
|
155
|
+
queueMicrotask(() => {
|
|
156
|
+
readers.forEach((reader) => reader())
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// clone returns a copy of this RWMutex instance
|
|
162
|
+
public clone(): RWMutex {
|
|
163
|
+
return new RWMutex()
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// WaitGroup waits for a collection of goroutines to finish
|
|
168
|
+
export class WaitGroup {
|
|
169
|
+
private _counter: number = 0
|
|
170
|
+
private _waiters: Array<() => void> = []
|
|
171
|
+
|
|
172
|
+
constructor(init?: Partial<{}>) {
|
|
173
|
+
// WaitGroup has no public fields to initialize
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Add adds delta, which may be negative, to the WaitGroup counter
|
|
177
|
+
public Add(delta: number): void {
|
|
178
|
+
this._counter += delta
|
|
179
|
+
if (this._counter < 0) {
|
|
180
|
+
throw new Error('sync: negative WaitGroup counter')
|
|
181
|
+
}
|
|
182
|
+
if (this._counter === 0) {
|
|
183
|
+
// Wake up all waiters
|
|
184
|
+
const waiters = this._waiters.splice(0)
|
|
185
|
+
queueMicrotask(() => {
|
|
186
|
+
waiters.forEach((waiter) => waiter())
|
|
187
|
+
})
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Done decrements the WaitGroup counter by one
|
|
192
|
+
public Done(): void {
|
|
193
|
+
this.Add(-1)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Wait blocks until the WaitGroup counter is zero
|
|
197
|
+
public async Wait(): Promise<void> {
|
|
198
|
+
if (this._counter === 0) {
|
|
199
|
+
return
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return new Promise<void>((resolve) => {
|
|
203
|
+
this._waiters.push(resolve)
|
|
204
|
+
})
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// clone returns a copy of this WaitGroup instance
|
|
208
|
+
public clone(): WaitGroup {
|
|
209
|
+
return new WaitGroup()
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Once is an object that will perform exactly one action
|
|
214
|
+
export class Once {
|
|
215
|
+
private _done: boolean = false
|
|
216
|
+
private _m: Mutex = new Mutex()
|
|
217
|
+
|
|
218
|
+
constructor(init?: Partial<{}>) {
|
|
219
|
+
// Once has no public fields to initialize
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Do calls the function f if and only if Do is being called for the first time for this instance of Once
|
|
223
|
+
public async Do(f: () => void): Promise<void> {
|
|
224
|
+
if (this._done) {
|
|
225
|
+
return
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
await this._m.Lock()
|
|
229
|
+
try {
|
|
230
|
+
if (!this._done) {
|
|
231
|
+
f()
|
|
232
|
+
this._done = true
|
|
233
|
+
}
|
|
234
|
+
} finally {
|
|
235
|
+
this._m.Unlock()
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// clone returns a copy of this Once instance
|
|
240
|
+
public clone(): Once {
|
|
241
|
+
return new Once()
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Cond implements a condition variable, a rendezvous point for goroutines waiting for or announcing the occurrence of an event
|
|
246
|
+
export class Cond {
|
|
247
|
+
private _l: Locker
|
|
248
|
+
private _waiters: Array<() => void> = []
|
|
249
|
+
|
|
250
|
+
constructor(l: Locker) {
|
|
251
|
+
this._l = l
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Broadcast wakes all goroutines waiting on c
|
|
255
|
+
public Broadcast(): void {
|
|
256
|
+
const waiters = this._waiters.splice(0)
|
|
257
|
+
queueMicrotask(() => {
|
|
258
|
+
waiters.forEach((waiter) => waiter())
|
|
259
|
+
})
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Signal wakes one goroutine waiting on c, if there is any
|
|
263
|
+
public Signal(): void {
|
|
264
|
+
if (this._waiters.length > 0) {
|
|
265
|
+
const waiter = this._waiters.shift()!
|
|
266
|
+
queueMicrotask(() => waiter())
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Wait atomically unlocks c.L and suspends execution of the calling goroutine
|
|
271
|
+
public async Wait(): Promise<void> {
|
|
272
|
+
this._l.Unlock()
|
|
273
|
+
|
|
274
|
+
return new Promise<void>((resolve) => {
|
|
275
|
+
this._waiters.push(async () => {
|
|
276
|
+
await this._l.Lock()
|
|
277
|
+
resolve()
|
|
278
|
+
})
|
|
279
|
+
})
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// clone returns a copy of this Cond instance
|
|
283
|
+
public clone(): Cond {
|
|
284
|
+
return new Cond(this._l)
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// NewCond returns a new Cond with Locker l
|
|
289
|
+
export function NewCond(l: Locker): Cond {
|
|
290
|
+
return new Cond(l)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Map is like a Go map[interface{}]interface{} but is safe for concurrent use by multiple goroutines
|
|
294
|
+
export class Map {
|
|
295
|
+
private _m: RWMutex = new RWMutex()
|
|
296
|
+
private _data: globalThis.Map<any, any> = new globalThis.Map()
|
|
297
|
+
|
|
298
|
+
constructor(init?: Partial<{}>) {
|
|
299
|
+
// Map has no public fields to initialize
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Delete deletes the value for a key
|
|
303
|
+
public async Delete(key: any): Promise<void> {
|
|
304
|
+
await this._m.Lock()
|
|
305
|
+
try {
|
|
306
|
+
this._data.delete(key)
|
|
307
|
+
} finally {
|
|
308
|
+
this._m.Unlock()
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Load returns the value stored in the map for a key, or nil if no value is present
|
|
313
|
+
public async Load(key: any): Promise<[any, boolean]> {
|
|
314
|
+
await this._m.RLock()
|
|
315
|
+
try {
|
|
316
|
+
const value = this._data.get(key)
|
|
317
|
+
return [value, this._data.has(key)]
|
|
318
|
+
} finally {
|
|
319
|
+
this._m.RUnlock()
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// LoadAndDelete deletes the value for a key, returning the previous value if any
|
|
324
|
+
public async LoadAndDelete(key: any): Promise<[any, boolean]> {
|
|
325
|
+
await this._m.Lock()
|
|
326
|
+
try {
|
|
327
|
+
const value = this._data.get(key)
|
|
328
|
+
const loaded = this._data.has(key)
|
|
329
|
+
this._data.delete(key)
|
|
330
|
+
return [value, loaded]
|
|
331
|
+
} finally {
|
|
332
|
+
this._m.Unlock()
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// LoadOrStore returns the existing value for the key if present
|
|
337
|
+
public async LoadOrStore(key: any, value: any): Promise<[any, boolean]> {
|
|
338
|
+
await this._m.Lock()
|
|
339
|
+
try {
|
|
340
|
+
if (this._data.has(key)) {
|
|
341
|
+
return [this._data.get(key), true]
|
|
342
|
+
}
|
|
343
|
+
this._data.set(key, value)
|
|
344
|
+
return [value, false]
|
|
345
|
+
} finally {
|
|
346
|
+
this._m.Unlock()
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Range calls f sequentially for each key and value present in the map
|
|
351
|
+
public async Range(f: (key: any, value: any) => boolean): Promise<void> {
|
|
352
|
+
await this._m.RLock()
|
|
353
|
+
try {
|
|
354
|
+
for (const [key, value] of this._data) {
|
|
355
|
+
if (!f(key, value)) {
|
|
356
|
+
break
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
} finally {
|
|
360
|
+
this._m.RUnlock()
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Store sets the value for a key
|
|
365
|
+
public async Store(key: any, value: any): Promise<void> {
|
|
366
|
+
await this._m.Lock()
|
|
367
|
+
try {
|
|
368
|
+
this._data.set(key, value)
|
|
369
|
+
} finally {
|
|
370
|
+
this._m.Unlock()
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// clone returns a copy of this Map instance
|
|
375
|
+
public clone(): Map {
|
|
376
|
+
return new Map()
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Pool is a set of temporary objects that may be individually saved and retrieved
|
|
381
|
+
export class Pool {
|
|
382
|
+
public New?: () => any
|
|
383
|
+
private _pool: any[] = []
|
|
384
|
+
|
|
385
|
+
constructor(init?: Partial<{ New?: () => any }>) {
|
|
386
|
+
this.New = init?.New
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Get selects an arbitrary item from the Pool, removes it from the Pool, and returns it to the caller
|
|
390
|
+
public Get(): any {
|
|
391
|
+
if (this._pool.length > 0) {
|
|
392
|
+
return this._pool.pop()
|
|
393
|
+
}
|
|
394
|
+
if (this.New) {
|
|
395
|
+
return this.New()
|
|
396
|
+
}
|
|
397
|
+
return null
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Put adds x to the pool
|
|
401
|
+
public Put(x: any): void {
|
|
402
|
+
if (x !== null && x !== undefined) {
|
|
403
|
+
this._pool.push(x)
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// clone returns a copy of this Pool instance
|
|
408
|
+
public clone(): Pool {
|
|
409
|
+
return new Pool({ New: this.New })
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// OnceFunc returns a function that invokes f only once
|
|
414
|
+
export function OnceFunc(f: () => void): () => void {
|
|
415
|
+
let called = false
|
|
416
|
+
return () => {
|
|
417
|
+
if (!called) {
|
|
418
|
+
called = true
|
|
419
|
+
f()
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// OnceValue returns a function that invokes f only once and returns the value returned by f
|
|
425
|
+
export function OnceValue<T>(f: () => T): () => T {
|
|
426
|
+
let value: T
|
|
427
|
+
let called = false
|
|
428
|
+
return () => {
|
|
429
|
+
if (!called) {
|
|
430
|
+
called = true
|
|
431
|
+
value = f()
|
|
432
|
+
}
|
|
433
|
+
return value
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// OnceValues returns a function that invokes f only once and returns the values returned by f
|
|
438
|
+
export function OnceValues<T1, T2>(f: () => [T1, T2]): () => [T1, T2] {
|
|
439
|
+
let value1: T1
|
|
440
|
+
let value2: T2
|
|
441
|
+
let called = false
|
|
442
|
+
return () => {
|
|
443
|
+
if (!called) {
|
|
444
|
+
called = true
|
|
445
|
+
;[value1, value2] = f()
|
|
446
|
+
}
|
|
447
|
+
return [value1, value2]
|
|
448
|
+
}
|
|
449
|
+
}
|
package/gs/time/godoc.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
package time // import "time"
|
|
2
|
+
|
|
3
|
+
Package time provides functionality for measuring and displaying time.
|
|
4
|
+
|
|
5
|
+
The calendrical calculations always assume a Gregorian calendar, with no leap
|
|
6
|
+
seconds.
|
|
7
|
+
|
|
8
|
+
# Monotonic Clocks
|
|
9
|
+
|
|
10
|
+
Operating systems provide both a “wall clock,” which is subject to changes
|
|
11
|
+
for clock synchronization, and a “monotonic clock,” which is not. The general
|
|
12
|
+
rule is that the wall clock is for telling time and the monotonic clock is for
|
|
13
|
+
measuring time. Rather than split the API, in this package the Time returned by
|
|
14
|
+
time.Now contains both a wall clock reading and a monotonic clock reading; later
|
|
15
|
+
time-telling operations use the wall clock reading, but later time-measuring
|
|
16
|
+
operations, specifically comparisons and subtractions, use the monotonic clock
|
|
17
|
+
reading.
|
|
18
|
+
|
|
19
|
+
For example, this code always computes a positive elapsed time of approximately
|
|
20
|
+
20 milliseconds, even if the wall clock is changed during the operation being
|
|
21
|
+
timed:
|
|
22
|
+
|
|
23
|
+
start := time.Now()
|
|
24
|
+
... operation that takes 20 milliseconds ...
|
|
25
|
+
t := time.Now()
|
|
26
|
+
elapsed := t.Sub(start)
|
|
27
|
+
|
|
28
|
+
Other idioms, such as time.Since(start), time.Until(deadline), and
|
|
29
|
+
time.Now().Before(deadline), are similarly robust against wall clock resets.
|
|
30
|
+
|
|
31
|
+
The rest of this section gives the precise details of how operations use
|
|
32
|
+
monotonic clocks, but understanding those details is not required to use this
|
|
33
|
+
package.
|
|
34
|
+
|
|
35
|
+
The Time returned by time.Now contains a monotonic clock reading. If Time t
|
|
36
|
+
has a monotonic clock reading, t.Add adds the same duration to both the wall
|
|
37
|
+
clock and monotonic clock readings to compute the result. Because t.AddDate(y,
|
|
38
|
+
m, d), t.Round(d), and t.Truncate(d) are wall time computations, they always
|
|
39
|
+
strip any monotonic clock reading from their results. Because t.In, t.Local,
|
|
40
|
+
and t.UTC are used for their effect on the interpretation of the wall time,
|
|
41
|
+
they also strip any monotonic clock reading from their results. The canonical
|
|
42
|
+
way to strip a monotonic clock reading is to use t = t.Round(0).
|
|
43
|
+
|
|
44
|
+
If Times t and u both contain monotonic clock readings, the operations
|
|
45
|
+
t.After(u), t.Before(u), t.Equal(u), t.Compare(u), and t.Sub(u) are carried out
|
|
46
|
+
using the monotonic clock readings alone, ignoring the wall clock readings.
|
|
47
|
+
If either t or u contains no monotonic clock reading, these operations fall back
|
|
48
|
+
to using the wall clock readings.
|
|
49
|
+
|
|
50
|
+
On some systems the monotonic clock will stop if the computer goes to sleep.
|
|
51
|
+
On such a system, t.Sub(u) may not accurately reflect the actual time that
|
|
52
|
+
passed between t and u. The same applies to other functions and methods that
|
|
53
|
+
subtract times, such as Since, Until, Time.Before, Time.After, Time.Add,
|
|
54
|
+
Time.Equal and Time.Compare. In some cases, you may need to strip the monotonic
|
|
55
|
+
clock to get accurate results.
|
|
56
|
+
|
|
57
|
+
Because the monotonic clock reading has no meaning outside the current process,
|
|
58
|
+
the serialized forms generated by t.GobEncode, t.MarshalBinary, t.MarshalJSON,
|
|
59
|
+
and t.MarshalText omit the monotonic clock reading, and t.Format provides
|
|
60
|
+
no format for it. Similarly, the constructors time.Date, time.Parse,
|
|
61
|
+
time.ParseInLocation, and time.Unix, as well as the unmarshalers t.GobDecode,
|
|
62
|
+
t.UnmarshalBinary. t.UnmarshalJSON, and t.UnmarshalText always create times with
|
|
63
|
+
no monotonic clock reading.
|
|
64
|
+
|
|
65
|
+
The monotonic clock reading exists only in Time values. It is not a part of
|
|
66
|
+
Duration values or the Unix times returned by t.Unix and friends.
|
|
67
|
+
|
|
68
|
+
Note that the Go == operator compares not just the time instant but also the
|
|
69
|
+
Location and the monotonic clock reading. See the documentation for the Time
|
|
70
|
+
type for a discussion of equality testing for Time values.
|
|
71
|
+
|
|
72
|
+
For debugging, the result of t.String does include the monotonic clock
|
|
73
|
+
reading if present. If t != u because of different monotonic clock readings,
|
|
74
|
+
that difference will be visible when printing t.String() and u.String().
|
|
75
|
+
|
|
76
|
+
# Timer Resolution
|
|
77
|
+
|
|
78
|
+
Timer resolution varies depending on the Go runtime, the operating system
|
|
79
|
+
and the underlying hardware. On Unix, the resolution is ~1ms. On Windows
|
|
80
|
+
version 1803 and newer, the resolution is ~0.5ms. On older Windows versions,
|
|
81
|
+
the default resolution is ~16ms, but a higher resolution may be requested using
|
|
82
|
+
golang.org/x/sys/windows.TimeBeginPeriod.
|
|
83
|
+
|
|
84
|
+
const Layout = "01/02 03:04:05PM '06 -0700" ...
|
|
85
|
+
const Nanosecond Duration = 1 ...
|
|
86
|
+
func After(d Duration) <-chan Time
|
|
87
|
+
func Sleep(d Duration)
|
|
88
|
+
func Tick(d Duration) <-chan Time
|
|
89
|
+
type Duration int64
|
|
90
|
+
func ParseDuration(s string) (Duration, error)
|
|
91
|
+
func Since(t Time) Duration
|
|
92
|
+
func Until(t Time) Duration
|
|
93
|
+
type Location struct{ ... }
|
|
94
|
+
var Local *Location = &localLoc
|
|
95
|
+
var UTC *Location = &utcLoc
|
|
96
|
+
func FixedZone(name string, offset int) *Location
|
|
97
|
+
func LoadLocation(name string) (*Location, error)
|
|
98
|
+
func LoadLocationFromTZData(name string, data []byte) (*Location, error)
|
|
99
|
+
type Month int
|
|
100
|
+
const January Month = 1 + iota ...
|
|
101
|
+
type ParseError struct{ ... }
|
|
102
|
+
type Ticker struct{ ... }
|
|
103
|
+
func NewTicker(d Duration) *Ticker
|
|
104
|
+
type Time struct{ ... }
|
|
105
|
+
func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time
|
|
106
|
+
func Now() Time
|
|
107
|
+
func Parse(layout, value string) (Time, error)
|
|
108
|
+
func ParseInLocation(layout, value string, loc *Location) (Time, error)
|
|
109
|
+
func Unix(sec int64, nsec int64) Time
|
|
110
|
+
func UnixMicro(usec int64) Time
|
|
111
|
+
func UnixMilli(msec int64) Time
|
|
112
|
+
type Timer struct{ ... }
|
|
113
|
+
func AfterFunc(d Duration, f func()) *Timer
|
|
114
|
+
func NewTimer(d Duration) *Timer
|
|
115
|
+
type Weekday int
|
|
116
|
+
const Sunday Weekday = iota ...
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
package time // import "time"
|
|
2
|
+
|
|
3
|
+
Package time provides functionality for measuring and displaying time.
|
|
4
|
+
|
|
5
|
+
The calendrical calculations always assume a Gregorian calendar, with no leap
|
|
6
|
+
seconds.
|
|
7
|
+
|
|
8
|
+
# Monotonic Clocks
|
|
9
|
+
|
|
10
|
+
Operating systems provide both a “wall clock,” which is subject to changes
|
|
11
|
+
for clock synchronization, and a “monotonic clock,” which is not. The general
|
|
12
|
+
rule is that the wall clock is for telling time and the monotonic clock is for
|
|
13
|
+
measuring time. Rather than split the API, in this package the Time returned by
|
|
14
|
+
time.Now contains both a wall clock reading and a monotonic clock reading; later
|
|
15
|
+
time-telling operations use the wall clock reading, but later time-measuring
|
|
16
|
+
operations, specifically comparisons and subtractions, use the monotonic clock
|
|
17
|
+
reading.
|
|
18
|
+
|
|
19
|
+
For example, this code always computes a positive elapsed time of approximately
|
|
20
|
+
20 milliseconds, even if the wall clock is changed during the operation being
|
|
21
|
+
timed:
|
|
22
|
+
|
|
23
|
+
start := time.Now()
|
|
24
|
+
... operation that takes 20 milliseconds ...
|
|
25
|
+
t := time.Now()
|
|
26
|
+
elapsed := t.Sub(start)
|
|
27
|
+
|
|
28
|
+
Other idioms, such as time.Since(start), time.Until(deadline), and
|
|
29
|
+
time.Now().Before(deadline), are similarly robust against wall clock resets.
|
|
30
|
+
|
|
31
|
+
The rest of this section gives the precise details of how operations use
|
|
32
|
+
monotonic clocks, but understanding those details is not required to use this
|
|
33
|
+
package.
|
|
34
|
+
|
|
35
|
+
The Time returned by time.Now contains a monotonic clock reading. If Time t
|
|
36
|
+
has a monotonic clock reading, t.Add adds the same duration to both the wall
|
|
37
|
+
clock and monotonic clock readings to compute the result. Because t.AddDate(y,
|
|
38
|
+
m, d), t.Round(d), and t.Truncate(d) are wall time computations, they always
|
|
39
|
+
strip any monotonic clock reading from their results. Because t.In, t.Local,
|
|
40
|
+
and t.UTC are used for their effect on the interpretation of the wall time,
|
|
41
|
+
they also strip any monotonic clock reading from their results. The canonical
|
|
42
|
+
way to strip a monotonic clock reading is to use t = t.Round(0).
|
|
43
|
+
|
|
44
|
+
If Times t and u both contain monotonic clock readings, the operations
|
|
45
|
+
t.After(u), t.Before(u), t.Equal(u), t.Compare(u), and t.Sub(u) are carried out
|
|
46
|
+
using the monotonic clock readings alone, ignoring the wall clock readings.
|
|
47
|
+
If either t or u contains no monotonic clock reading, these operations fall back
|
|
48
|
+
to using the wall clock readings.
|
|
49
|
+
|
|
50
|
+
On some systems the monotonic clock will stop if the computer goes to sleep.
|
|
51
|
+
On such a system, t.Sub(u) may not accurately reflect the actual time that
|
|
52
|
+
passed between t and u. The same applies to other functions and methods that
|
|
53
|
+
subtract times, such as Since, Until, Time.Before, Time.After, Time.Add,
|
|
54
|
+
Time.Equal and Time.Compare. In some cases, you may need to strip the monotonic
|
|
55
|
+
clock to get accurate results.
|
|
56
|
+
|
|
57
|
+
Because the monotonic clock reading has no meaning outside the current process,
|
|
58
|
+
the serialized forms generated by t.GobEncode, t.MarshalBinary, t.MarshalJSON,
|
|
59
|
+
and t.MarshalText omit the monotonic clock reading, and t.Format provides
|
|
60
|
+
no format for it. Similarly, the constructors time.Date, time.Parse,
|
|
61
|
+
time.ParseInLocation, and time.Unix, as well as the unmarshalers t.GobDecode,
|
|
62
|
+
t.UnmarshalBinary. t.UnmarshalJSON, and t.UnmarshalText always create times with
|
|
63
|
+
no monotonic clock reading.
|
|
64
|
+
|
|
65
|
+
The monotonic clock reading exists only in Time values. It is not a part of
|
|
66
|
+
Duration values or the Unix times returned by t.Unix and friends.
|
|
67
|
+
|
|
68
|
+
Note that the Go == operator compares not just the time instant but also the
|
|
69
|
+
Location and the monotonic clock reading. See the documentation for the Time
|
|
70
|
+
type for a discussion of equality testing for Time values.
|
|
71
|
+
|
|
72
|
+
For debugging, the result of t.String does include the monotonic clock
|
|
73
|
+
reading if present. If t != u because of different monotonic clock readings,
|
|
74
|
+
that difference will be visible when printing t.String() and u.String().
|
|
75
|
+
|
|
76
|
+
# Timer Resolution
|
|
77
|
+
|
|
78
|
+
Timer resolution varies depending on the Go runtime, the operating system
|
|
79
|
+
and the underlying hardware. On Unix, the resolution is ~1ms. On Windows
|
|
80
|
+
version 1803 and newer, the resolution is ~0.5ms. On older Windows versions,
|
|
81
|
+
the default resolution is ~16ms, but a higher resolution may be requested using
|
|
82
|
+
golang.org/x/sys/windows.TimeBeginPeriod.
|
|
83
|
+
|
|
84
|
+
const Layout = "01/02 03:04:05PM '06 -0700" ...
|
|
85
|
+
const Nanosecond Duration = 1 ...
|
|
86
|
+
func After(d Duration) <-chan Time
|
|
87
|
+
func Sleep(d Duration)
|
|
88
|
+
func Tick(d Duration) <-chan Time
|
|
89
|
+
type Duration int64
|
|
90
|
+
func ParseDuration(s string) (Duration, error)
|
|
91
|
+
func Since(t Time) Duration
|
|
92
|
+
func Until(t Time) Duration
|
|
93
|
+
type Location struct{ ... }
|
|
94
|
+
var Local *Location = &localLoc
|
|
95
|
+
var UTC *Location = &utcLoc
|
|
96
|
+
func FixedZone(name string, offset int) *Location
|
|
97
|
+
func LoadLocation(name string) (*Location, error)
|
|
98
|
+
func LoadLocationFromTZData(name string, data []byte) (*Location, error)
|
|
99
|
+
type Month int
|
|
100
|
+
const January Month = 1 + iota ...
|
|
101
|
+
type ParseError struct{ ... }
|
|
102
|
+
type Ticker struct{ ... }
|
|
103
|
+
func NewTicker(d Duration) *Ticker
|
|
104
|
+
type Time struct{ ... }
|
|
105
|
+
func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time
|
|
106
|
+
func Now() Time
|
|
107
|
+
func Parse(layout, value string) (Time, error)
|
|
108
|
+
func ParseInLocation(layout, value string, loc *Location) (Time, error)
|
|
109
|
+
func Unix(sec int64, nsec int64) Time
|
|
110
|
+
func UnixMicro(usec int64) Time
|
|
111
|
+
func UnixMilli(msec int64) Time
|
|
112
|
+
type Timer struct{ ... }
|
|
113
|
+
func AfterFunc(d Duration, f func()) *Timer
|
|
114
|
+
func NewTimer(d Duration) *Timer
|
|
115
|
+
type Weekday int
|
|
116
|
+
const Sunday Weekday = iota ...
|
package/gs/time/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './time.js'
|