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
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VarRef represents a Go variable which can be referred to by other variables.
|
|
3
|
+
*
|
|
4
|
+
* For example:
|
|
5
|
+
* var myVariable int // variable referenced
|
|
6
|
+
* myOtherVar := &myVariable
|
|
7
|
+
*/
|
|
8
|
+
export type VarRef<T> = { value: T }
|
|
9
|
+
|
|
10
|
+
/** Wrap a non-null T in a variable reference. */
|
|
11
|
+
export function varRef<T>(v: T): VarRef<T> {
|
|
12
|
+
// We create a new object wrapper for every varRef call to ensure
|
|
13
|
+
// distinct pointer identity, crucial for pointer comparisons (p1 == p2).
|
|
14
|
+
return { value: v }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Dereference a variable reference, throws on null → simulates Go panic. */
|
|
18
|
+
export function unref<T>(b: VarRef<T>): T {
|
|
19
|
+
if (b === null) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
'runtime error: invalid memory address or nil pointer dereference',
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
return b.value
|
|
25
|
+
}
|
package/gs/cmp/godoc.txt
ADDED
package/gs/cmp/index.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Minimal stub for cmp package
|
|
2
|
+
// This provides the Ordered type and comparison functions needed by slices
|
|
3
|
+
|
|
4
|
+
// Ordered represents types that can be ordered (comparable)
|
|
5
|
+
export type Ordered = number | string | boolean | bigint
|
|
6
|
+
|
|
7
|
+
// Compare compares two values and returns:
|
|
8
|
+
// -1 if a < b
|
|
9
|
+
// 0 if a == b
|
|
10
|
+
// 1 if a > b
|
|
11
|
+
export function Compare<T extends Ordered>(a: T, b: T): number {
|
|
12
|
+
if (a < b) return -1
|
|
13
|
+
if (a > b) return 1
|
|
14
|
+
return 0
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Less reports whether a < b
|
|
18
|
+
export function Less<T extends Ordered>(a: T, b: T): boolean {
|
|
19
|
+
return a < b
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Or returns the first non-zero result from the comparison functions,
|
|
23
|
+
// or zero if all comparisons return zero
|
|
24
|
+
export function Or(...comparisons: number[]): number {
|
|
25
|
+
for (const cmp of comparisons) {
|
|
26
|
+
if (cmp !== 0) return cmp
|
|
27
|
+
}
|
|
28
|
+
return 0
|
|
29
|
+
}
|
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
import * as $ from '@goscript/builtin/builtin.js'
|
|
2
|
+
|
|
3
|
+
export const Canceled = new Error('context canceled')
|
|
4
|
+
Canceled.name = 'CanceledError'
|
|
5
|
+
|
|
6
|
+
export class DeadlineExceededError extends Error {
|
|
7
|
+
constructor() {
|
|
8
|
+
super('context deadline exceeded')
|
|
9
|
+
this.name = 'DeadlineExceededError'
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export const DeadlineExceeded = new DeadlineExceededError()
|
|
13
|
+
|
|
14
|
+
// Function types
|
|
15
|
+
export type CancelFunc = () => void
|
|
16
|
+
export type CancelCauseFunc = (cause: Error | null) => void
|
|
17
|
+
|
|
18
|
+
// Context interface matching Go's context.Context
|
|
19
|
+
export interface Context {
|
|
20
|
+
// Deadline returns the time when work done on behalf of this context should be canceled
|
|
21
|
+
Deadline(): [Date | null, boolean]
|
|
22
|
+
|
|
23
|
+
// Done returns a channel that's closed when work done on behalf of this context should be canceled
|
|
24
|
+
Done(): $.Channel<{}>
|
|
25
|
+
|
|
26
|
+
// Err returns a non-nil error value after Done is closed
|
|
27
|
+
Err(): Error | null
|
|
28
|
+
|
|
29
|
+
// Value returns the value associated with this context for key, or null
|
|
30
|
+
Value(key: any): any
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Base implementation for all contexts
|
|
34
|
+
abstract class baseContext implements Context {
|
|
35
|
+
abstract Deadline(): [Date | null, boolean]
|
|
36
|
+
abstract Done(): $.Channel<{}>
|
|
37
|
+
abstract Err(): Error | null
|
|
38
|
+
abstract Value(key: any): any
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Background/TODO context that is never canceled
|
|
42
|
+
class backgroundContext extends baseContext {
|
|
43
|
+
private static readonly neverClosedChannel = $.makeChannel<{}>(0, {}, 'both')
|
|
44
|
+
|
|
45
|
+
static getNeverClosedChannel(): $.Channel<{}> {
|
|
46
|
+
return backgroundContext.neverClosedChannel
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
Deadline(): [Date | null, boolean] {
|
|
50
|
+
return [null, false]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
Done(): $.Channel<{}> {
|
|
54
|
+
return backgroundContext.neverClosedChannel
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
Err(): Error | null {
|
|
58
|
+
return null
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
Value(key: any): any {
|
|
62
|
+
return null
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Value context wraps a parent and adds a key-value pair
|
|
67
|
+
class valueContext extends baseContext {
|
|
68
|
+
constructor(
|
|
69
|
+
private parent: Context,
|
|
70
|
+
private key: any,
|
|
71
|
+
private val: any,
|
|
72
|
+
) {
|
|
73
|
+
super()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getParent(): Context {
|
|
77
|
+
return this.parent
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
Deadline(): [Date | null, boolean] {
|
|
81
|
+
return this.parent.Deadline()
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
Done(): $.Channel<{}> {
|
|
85
|
+
return this.parent.Done()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
Err(): Error | null {
|
|
89
|
+
return this.parent.Err()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
Value(key: any): any {
|
|
93
|
+
if (this.key === key) {
|
|
94
|
+
return this.val
|
|
95
|
+
}
|
|
96
|
+
return this.parent.Value(key)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Cancel context that can be canceled
|
|
101
|
+
class cancelContext extends baseContext {
|
|
102
|
+
protected doneChannel: $.Channel<{}>
|
|
103
|
+
protected err: Error | null = null
|
|
104
|
+
protected cause: Error | null = null
|
|
105
|
+
protected children: Set<cancelContext> = new Set()
|
|
106
|
+
protected parent: Context
|
|
107
|
+
protected parentCancelCtx: cancelContext | null = null
|
|
108
|
+
protected removeFromParent: (() => void) | null = null
|
|
109
|
+
|
|
110
|
+
constructor(parent: Context) {
|
|
111
|
+
super()
|
|
112
|
+
this.parent = parent
|
|
113
|
+
this.doneChannel = $.makeChannel<{}>(0, {}, 'both')
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
Deadline(): [Date | null, boolean] {
|
|
117
|
+
return this.parent.Deadline()
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
Done(): $.Channel<{}> {
|
|
121
|
+
return this.doneChannel
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
Err(): Error | null {
|
|
125
|
+
return this.err
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
Value(key: any): any {
|
|
129
|
+
return this.parent.Value(key)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
getCause(): Error | null {
|
|
133
|
+
if (this.cause !== null) {
|
|
134
|
+
return this.cause
|
|
135
|
+
}
|
|
136
|
+
return this.err
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
cancel(removeFromParent: boolean, err: Error, cause: Error | null): void {
|
|
140
|
+
if (this.err !== null) {
|
|
141
|
+
return // Already canceled
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
this.err = err
|
|
145
|
+
this.cause = cause
|
|
146
|
+
this.doneChannel.close()
|
|
147
|
+
|
|
148
|
+
// Cancel all children
|
|
149
|
+
for (const child of this.children) {
|
|
150
|
+
child.cancel(false, err, cause)
|
|
151
|
+
}
|
|
152
|
+
this.children.clear()
|
|
153
|
+
|
|
154
|
+
// Remove from parent's children if requested
|
|
155
|
+
if (removeFromParent && this.removeFromParent) {
|
|
156
|
+
this.removeFromParent()
|
|
157
|
+
this.removeFromParent = null
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
propagateCancel(): void {
|
|
162
|
+
// Find parent cancelContext if any
|
|
163
|
+
let parent = this.parent
|
|
164
|
+
while (parent instanceof valueContext) {
|
|
165
|
+
parent = (parent as valueContext).getParent()
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (parent instanceof cancelContext) {
|
|
169
|
+
// Parent is a cancel context, register as child
|
|
170
|
+
this.parentCancelCtx = parent
|
|
171
|
+
if (parent.err !== null) {
|
|
172
|
+
// Parent already canceled
|
|
173
|
+
this.cancel(false, parent.err, parent.cause)
|
|
174
|
+
} else {
|
|
175
|
+
parent.children.add(this)
|
|
176
|
+
this.removeFromParent = () => {
|
|
177
|
+
parent.children.delete(this)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
// Watch parent's Done channel
|
|
182
|
+
this.watchParentDone()
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private watchParentDone(): void {
|
|
187
|
+
const parentDone = this.parent.Done()
|
|
188
|
+
;(async () => {
|
|
189
|
+
try {
|
|
190
|
+
await parentDone.receive()
|
|
191
|
+
} catch {
|
|
192
|
+
// Channel closed
|
|
193
|
+
}
|
|
194
|
+
// Parent is done, cancel this context
|
|
195
|
+
const parentErr = this.parent.Err()
|
|
196
|
+
if (parentErr && this.err === null) {
|
|
197
|
+
this.cancel(false, parentErr, null)
|
|
198
|
+
}
|
|
199
|
+
})()
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Timer context with deadline
|
|
204
|
+
class timerContext extends cancelContext {
|
|
205
|
+
private deadline: Date
|
|
206
|
+
private timer: any
|
|
207
|
+
|
|
208
|
+
constructor(parent: Context, deadline: Date) {
|
|
209
|
+
super(parent)
|
|
210
|
+
this.deadline = deadline
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
Deadline(): [Date | null, boolean] {
|
|
214
|
+
return [this.deadline, true]
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
startTimer(): void {
|
|
218
|
+
const now = Date.now()
|
|
219
|
+
const duration = this.deadline.getTime() - now
|
|
220
|
+
|
|
221
|
+
if (duration <= 0) {
|
|
222
|
+
// Already expired
|
|
223
|
+
this.cancel(true, DeadlineExceeded, null)
|
|
224
|
+
return
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
this.timer = setTimeout(() => {
|
|
228
|
+
this.cancel(true, DeadlineExceeded, null)
|
|
229
|
+
}, duration)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
cancel(removeFromParent: boolean, err: Error, cause: Error | null): void {
|
|
233
|
+
super.cancel(removeFromParent, err, cause)
|
|
234
|
+
if (this.timer) {
|
|
235
|
+
clearTimeout(this.timer)
|
|
236
|
+
this.timer = null
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Without cancel context - inherits values but not cancellation
|
|
242
|
+
class withoutCancelContext extends baseContext {
|
|
243
|
+
constructor(private parent: Context) {
|
|
244
|
+
super()
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
Deadline(): [Date | null, boolean] {
|
|
248
|
+
return [null, false]
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
Done(): $.Channel<{}> {
|
|
252
|
+
return backgroundContext.getNeverClosedChannel()
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
Err(): Error | null {
|
|
256
|
+
return null
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
Value(key: any): any {
|
|
260
|
+
return this.parent.Value(key)
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Singleton contexts
|
|
265
|
+
const background = new backgroundContext()
|
|
266
|
+
const todo = new backgroundContext()
|
|
267
|
+
|
|
268
|
+
// Background returns a non-nil, empty Context that is never canceled
|
|
269
|
+
export function Background(): Context {
|
|
270
|
+
return background
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// TODO returns a non-nil, empty Context
|
|
274
|
+
export function TODO(): Context {
|
|
275
|
+
return todo
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// WithCancel returns a copy of parent with a new Done channel
|
|
279
|
+
export function WithCancel(parent: Context): [Context, CancelFunc] {
|
|
280
|
+
const ctx = new cancelContext(parent)
|
|
281
|
+
ctx.propagateCancel()
|
|
282
|
+
|
|
283
|
+
return [
|
|
284
|
+
ctx,
|
|
285
|
+
() => {
|
|
286
|
+
ctx.cancel(true, Canceled, null)
|
|
287
|
+
},
|
|
288
|
+
]
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// WithCancelCause returns a copy of parent with a new Done channel and cause recording
|
|
292
|
+
export function WithCancelCause(parent: Context): [Context, CancelCauseFunc] {
|
|
293
|
+
const ctx = new cancelContext(parent)
|
|
294
|
+
ctx.propagateCancel()
|
|
295
|
+
|
|
296
|
+
return [
|
|
297
|
+
ctx,
|
|
298
|
+
(cause: Error | null) => {
|
|
299
|
+
ctx.cancel(true, Canceled, cause)
|
|
300
|
+
},
|
|
301
|
+
]
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// WithDeadline returns a copy of parent with the deadline adjusted to be no later than d
|
|
305
|
+
export function WithDeadline(parent: Context, d: Date): [Context, CancelFunc] {
|
|
306
|
+
return WithDeadlineCause(parent, d, null)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// WithDeadlineCause is like WithDeadline but also sets the cause
|
|
310
|
+
export function WithDeadlineCause(
|
|
311
|
+
parent: Context,
|
|
312
|
+
d: Date,
|
|
313
|
+
cause: Error | null,
|
|
314
|
+
): [Context, CancelFunc] {
|
|
315
|
+
// Check if parent deadline is already earlier
|
|
316
|
+
const [parentDeadline, ok] = parent.Deadline()
|
|
317
|
+
if (ok && parentDeadline && parentDeadline <= d) {
|
|
318
|
+
// Parent deadline is already sooner
|
|
319
|
+
return WithCancel(parent)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const ctx = new timerContext(parent, d)
|
|
323
|
+
ctx.propagateCancel()
|
|
324
|
+
ctx.startTimer()
|
|
325
|
+
|
|
326
|
+
return [
|
|
327
|
+
ctx,
|
|
328
|
+
() => {
|
|
329
|
+
ctx.cancel(true, Canceled, cause)
|
|
330
|
+
},
|
|
331
|
+
]
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// WithTimeout returns WithDeadline(parent, Date.now() + timeout)
|
|
335
|
+
export function WithTimeout(
|
|
336
|
+
parent: Context,
|
|
337
|
+
timeout: number,
|
|
338
|
+
): [Context, CancelFunc] {
|
|
339
|
+
return WithDeadline(parent, new Date(Date.now() + timeout))
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// WithTimeoutCause is like WithTimeout but also sets the cause
|
|
343
|
+
export function WithTimeoutCause(
|
|
344
|
+
parent: Context,
|
|
345
|
+
timeout: number,
|
|
346
|
+
cause: Error | null,
|
|
347
|
+
): [Context, CancelFunc] {
|
|
348
|
+
return WithDeadlineCause(parent, new Date(Date.now() + timeout), cause)
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// WithValue returns a copy of parent with the value associated with key
|
|
352
|
+
export function WithValue(parent: Context, key: any, val: any): Context {
|
|
353
|
+
return new valueContext(parent, key, val)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// WithoutCancel returns a context that inherits values but not cancellation
|
|
357
|
+
export function WithoutCancel(parent: Context): Context {
|
|
358
|
+
return new withoutCancelContext(parent)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Cause returns the underlying cause of the context's cancellation
|
|
362
|
+
export function Cause(ctx: Context): Error | null {
|
|
363
|
+
let c = ctx
|
|
364
|
+
// Unwrap value contexts
|
|
365
|
+
while (c instanceof valueContext) {
|
|
366
|
+
c = (c as valueContext).getParent()
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
if (c instanceof cancelContext) {
|
|
370
|
+
return c.getCause()
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return c.Err()
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// AfterFunc runs f in a separate goroutine after ctx is done
|
|
377
|
+
export function AfterFunc(ctx: Context, f: () => void): () => boolean {
|
|
378
|
+
let stopped = false
|
|
379
|
+
let done = false
|
|
380
|
+
|
|
381
|
+
const promise = (async () => {
|
|
382
|
+
try {
|
|
383
|
+
await ctx.Done().receive()
|
|
384
|
+
} catch {
|
|
385
|
+
// Channel closed
|
|
386
|
+
}
|
|
387
|
+
if (!stopped) {
|
|
388
|
+
done = true
|
|
389
|
+
// Run in next tick to simulate goroutine
|
|
390
|
+
setImmediate(f)
|
|
391
|
+
}
|
|
392
|
+
})()
|
|
393
|
+
|
|
394
|
+
return () => {
|
|
395
|
+
if (!done) {
|
|
396
|
+
stopped = true
|
|
397
|
+
return true
|
|
398
|
+
}
|
|
399
|
+
return false
|
|
400
|
+
}
|
|
401
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
package context // import "context"
|
|
2
|
+
|
|
3
|
+
Package context defines the Context type, which carries deadlines, cancellation
|
|
4
|
+
signals, and other request-scoped values across API boundaries and between
|
|
5
|
+
processes.
|
|
6
|
+
|
|
7
|
+
Incoming requests to a server should create a Context, and outgoing calls to
|
|
8
|
+
servers should accept a Context. The chain of function calls between them must
|
|
9
|
+
propagate the Context, optionally replacing it with a derived Context created
|
|
10
|
+
using WithCancel, WithDeadline, WithTimeout, or WithValue.
|
|
11
|
+
|
|
12
|
+
A Context may be canceled to indicate that work done on its behalf should stop.
|
|
13
|
+
A Context with a deadline is canceled after the deadline passes. When a Context
|
|
14
|
+
is canceled, all Contexts derived from it are also canceled.
|
|
15
|
+
|
|
16
|
+
The WithCancel, WithDeadline, and WithTimeout functions take a Context (the
|
|
17
|
+
parent) and return a derived Context (the child) and a CancelFunc. Calling the
|
|
18
|
+
CancelFunc directly cancels the child and its children, removes the parent's
|
|
19
|
+
reference to the child, and stops any associated timers. Failing to call the
|
|
20
|
+
CancelFunc leaks the child and its children until the parent is canceled.
|
|
21
|
+
The go vet tool checks that CancelFuncs are used on all control-flow paths.
|
|
22
|
+
|
|
23
|
+
The WithCancelCause, WithDeadlineCause, and WithTimeoutCause functions return a
|
|
24
|
+
CancelCauseFunc, which takes an error and records it as the cancellation cause.
|
|
25
|
+
Calling Cause on the canceled context or any of its children retrieves the
|
|
26
|
+
cause. If no cause is specified, Cause(ctx) returns the same value as ctx.Err().
|
|
27
|
+
|
|
28
|
+
Programs that use Contexts should follow these rules to keep interfaces
|
|
29
|
+
consistent across packages and enable static analysis tools to check context
|
|
30
|
+
propagation:
|
|
31
|
+
|
|
32
|
+
Do not store Contexts inside a struct type; instead, pass a Context
|
|
33
|
+
explicitly to each function that needs it. This is discussed further in
|
|
34
|
+
https://go.dev/blog/context-and-structs. The Context should be the first
|
|
35
|
+
parameter, typically named ctx:
|
|
36
|
+
|
|
37
|
+
func DoSomething(ctx context.Context, arg Arg) error {
|
|
38
|
+
// ... use ctx ...
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
Do not pass a nil Context, even if a function permits it. Pass context.TODO if
|
|
42
|
+
you are unsure about which Context to use.
|
|
43
|
+
|
|
44
|
+
Use context Values only for request-scoped data that transits processes and
|
|
45
|
+
APIs, not for passing optional parameters to functions.
|
|
46
|
+
|
|
47
|
+
The same Context may be passed to functions running in different goroutines;
|
|
48
|
+
Contexts are safe for simultaneous use by multiple goroutines.
|
|
49
|
+
|
|
50
|
+
See https://go.dev/blog/context for example code for a server that uses
|
|
51
|
+
Contexts.
|
|
52
|
+
|
|
53
|
+
var Canceled = errors.New("context canceled")
|
|
54
|
+
var DeadlineExceeded error = deadlineExceededError{}
|
|
55
|
+
func AfterFunc(ctx Context, f func()) (stop func() bool)
|
|
56
|
+
func Cause(c Context) error
|
|
57
|
+
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
|
|
58
|
+
func WithCancelCause(parent Context) (ctx Context, cancel CancelCauseFunc)
|
|
59
|
+
func WithDeadline(parent Context, d time.Time) (Context, CancelFunc)
|
|
60
|
+
func WithDeadlineCause(parent Context, d time.Time, cause error) (Context, CancelFunc)
|
|
61
|
+
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
|
|
62
|
+
func WithTimeoutCause(parent Context, timeout time.Duration, cause error) (Context, CancelFunc)
|
|
63
|
+
type CancelCauseFunc func(cause error)
|
|
64
|
+
type CancelFunc func()
|
|
65
|
+
type Context interface{ ... }
|
|
66
|
+
func Background() Context
|
|
67
|
+
func TODO() Context
|
|
68
|
+
func WithValue(parent Context, key, val any) Context
|
|
69
|
+
func WithoutCancel(parent Context) Context
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './context.js'
|