goscript 0.2.4 → 0.2.5
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 +8 -8
- package/cmd/go_js_wasm_exec/main.go +1 -1
- package/cmd/go_js_wasm_exec/main_test.go +1 -1
- package/cmd/goscript/cmd-compile.go +9 -1
- package/cmd/goscript/cmd-test.go +1 -1
- package/cmd/goscript/cmd_compile_test.go +44 -0
- package/cmd/goscript/deps.go +1 -1
- package/cmd/goscript-wasm/main.go +2 -2
- package/compiler/compile-request.go +19 -0
- package/compiler/compile_bench_test.go +121 -0
- package/compiler/compliance_test.go +17 -1
- package/compiler/config.go +2 -0
- package/compiler/gotest/result.go +1 -1
- package/compiler/gotest/runner.go +2 -2
- package/compiler/gotest/runner_test.go +4 -7
- package/compiler/index.test.ts +28 -0
- package/compiler/index.ts +32 -16
- package/compiler/lowering.go +1238 -194
- package/compiler/lowering_bench_test.go +4 -0
- package/compiler/override-facts.go +1 -1
- package/compiler/package-graph.go +92 -0
- package/compiler/package-graph_test.go +113 -0
- package/compiler/runtime-contract.go +1 -1
- package/compiler/semantic-model.go +32 -0
- package/compiler/skeleton_test.go +241 -15
- package/compiler/wasm/compile.go +1 -1
- package/compiler/wasm/compile_test.go +1 -1
- package/dist/compiler/index.d.ts +4 -0
- package/dist/compiler/index.js +26 -15
- package/dist/compiler/index.js.map +1 -1
- package/dist/gs/database/sql/driver/index.d.ts +165 -0
- package/dist/gs/database/sql/driver/index.js +432 -0
- package/dist/gs/database/sql/driver/index.js.map +1 -0
- package/dist/gs/encoding/binary/index.d.ts +71 -0
- package/dist/gs/encoding/binary/index.js +778 -0
- package/dist/gs/encoding/binary/index.js.map +1 -0
- package/dist/gs/fmt/fmt.js +156 -57
- package/dist/gs/fmt/fmt.js.map +1 -1
- package/dist/gs/github.com/klauspost/cpuid/v2/index.d.ts +11 -0
- package/dist/gs/github.com/klauspost/cpuid/v2/index.js +28 -0
- package/dist/gs/github.com/klauspost/cpuid/v2/index.js.map +1 -0
- package/dist/gs/github.com/pkg/errors/errors.d.ts +0 -2
- package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/index.d.ts +2 -1
- package/dist/gs/github.com/pkg/errors/index.js +1 -1
- package/dist/gs/github.com/pkg/errors/index.js.map +1 -1
- package/dist/gs/github.com/pkg/errors/stack.d.ts +8 -19
- package/dist/gs/github.com/pkg/errors/stack.js +26 -61
- package/dist/gs/github.com/pkg/errors/stack.js.map +1 -1
- package/dist/gs/golang.org/x/crypto/cryptobyte/asn1/index.d.ts +19 -0
- package/dist/gs/golang.org/x/crypto/cryptobyte/asn1/index.js +25 -0
- package/dist/gs/golang.org/x/crypto/cryptobyte/asn1/index.js.map +1 -0
- package/dist/gs/golang.org/x/crypto/cryptobyte/index.d.ts +104 -0
- package/dist/gs/golang.org/x/crypto/cryptobyte/index.js +1107 -0
- package/dist/gs/golang.org/x/crypto/cryptobyte/index.js.map +1 -0
- package/dist/gs/golang.org/x/crypto/internal/alias/index.d.ts +3 -0
- package/dist/gs/golang.org/x/crypto/internal/alias/index.js +39 -0
- package/dist/gs/golang.org/x/crypto/internal/alias/index.js.map +1 -0
- package/dist/gs/runtime/runtime.d.ts +6 -1
- package/dist/gs/runtime/runtime.js +15 -8
- package/dist/gs/runtime/runtime.js.map +1 -1
- package/dist/gs/runtime/trace/index.d.ts +8 -5
- package/dist/gs/runtime/trace/index.js +324 -23
- package/dist/gs/runtime/trace/index.js.map +1 -1
- package/dist/gs/slices/slices.d.ts +2 -1
- package/dist/gs/slices/slices.js +9 -3
- package/dist/gs/slices/slices.js.map +1 -1
- package/dist/gs/sort/search.gs.d.ts +3 -1
- package/dist/gs/sort/search.gs.js +18 -53
- package/dist/gs/sort/search.gs.js.map +1 -1
- package/dist/gs/sync/sync.d.ts +1 -1
- package/dist/gs/sync/sync.js +3 -0
- package/dist/gs/sync/sync.js.map +1 -1
- package/dist/gs/time/time.d.ts +22 -29
- package/dist/gs/time/time.js +111 -32
- package/dist/gs/time/time.js.map +1 -1
- package/dist/gs/unsafe/unsafe.d.ts +3 -2
- package/dist/gs/unsafe/unsafe.js.map +1 -1
- package/go.mod +7 -5
- package/go.sum +12 -26
- package/gs/database/sql/driver/index.test.ts +88 -0
- package/gs/database/sql/driver/index.ts +675 -0
- package/gs/database/sql/driver/meta.json +3 -0
- package/gs/database/sql/driver/parity.json +144 -0
- package/gs/encoding/binary/index.test.ts +239 -0
- package/gs/encoding/binary/index.ts +999 -0
- package/gs/encoding/binary/meta.json +9 -0
- package/gs/encoding/binary/parity.json +72 -0
- package/gs/fmt/fmt.test.ts +28 -0
- package/gs/fmt/fmt.ts +198 -61
- package/gs/fmt/meta.json +2 -1
- package/gs/github.com/klauspost/cpuid/v2/index.ts +38 -0
- package/gs/github.com/klauspost/cpuid/v2/meta.json +3 -0
- package/gs/github.com/pkg/errors/errors.ts +1 -2
- package/gs/github.com/pkg/errors/index.ts +2 -1
- package/gs/github.com/pkg/errors/stack.ts +34 -62
- package/gs/golang.org/x/crypto/cryptobyte/asn1/index.test.ts +19 -0
- package/gs/golang.org/x/crypto/cryptobyte/asn1/index.ts +29 -0
- package/gs/golang.org/x/crypto/cryptobyte/index.test.ts +255 -0
- package/gs/golang.org/x/crypto/cryptobyte/index.ts +1441 -0
- package/gs/golang.org/x/crypto/cryptobyte/meta.json +3 -0
- package/gs/golang.org/x/crypto/internal/alias/index.test.ts +40 -0
- package/gs/golang.org/x/crypto/internal/alias/index.ts +40 -0
- package/gs/runtime/runtime.test.ts +16 -0
- package/gs/runtime/runtime.ts +17 -9
- package/gs/runtime/trace/index.test.ts +113 -14
- package/gs/runtime/trace/index.ts +384 -34
- package/gs/runtime/trace/meta.json +1 -0
- package/gs/slices/slices.test.ts +24 -1
- package/gs/slices/slices.ts +14 -4
- package/gs/sort/meta.json +1 -0
- package/gs/sort/search.gs.ts +20 -5
- package/gs/sync/sync.ts +4 -1
- package/gs/time/time.test.ts +79 -2
- package/gs/time/time.ts +133 -33
- package/gs/unsafe/unsafe.ts +4 -2
- package/package.json +2 -2
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"strict": true,
|
|
4
|
+
"symbols": {
|
|
5
|
+
"Append": {
|
|
6
|
+
"status": "real"
|
|
7
|
+
},
|
|
8
|
+
"AppendByteOrder": {
|
|
9
|
+
"status": "real"
|
|
10
|
+
},
|
|
11
|
+
"AppendUvarint": {
|
|
12
|
+
"status": "real"
|
|
13
|
+
},
|
|
14
|
+
"AppendVarint": {
|
|
15
|
+
"status": "real"
|
|
16
|
+
},
|
|
17
|
+
"BigEndian": {
|
|
18
|
+
"status": "real"
|
|
19
|
+
},
|
|
20
|
+
"ByteOrder": {
|
|
21
|
+
"status": "real"
|
|
22
|
+
},
|
|
23
|
+
"Decode": {
|
|
24
|
+
"status": "real"
|
|
25
|
+
},
|
|
26
|
+
"Encode": {
|
|
27
|
+
"status": "real"
|
|
28
|
+
},
|
|
29
|
+
"LittleEndian": {
|
|
30
|
+
"status": "real"
|
|
31
|
+
},
|
|
32
|
+
"MaxVarintLen16": {
|
|
33
|
+
"status": "real"
|
|
34
|
+
},
|
|
35
|
+
"MaxVarintLen32": {
|
|
36
|
+
"status": "real"
|
|
37
|
+
},
|
|
38
|
+
"MaxVarintLen64": {
|
|
39
|
+
"status": "real"
|
|
40
|
+
},
|
|
41
|
+
"NativeEndian": {
|
|
42
|
+
"status": "real"
|
|
43
|
+
},
|
|
44
|
+
"PutUvarint": {
|
|
45
|
+
"status": "real"
|
|
46
|
+
},
|
|
47
|
+
"PutVarint": {
|
|
48
|
+
"status": "real"
|
|
49
|
+
},
|
|
50
|
+
"Read": {
|
|
51
|
+
"status": "real"
|
|
52
|
+
},
|
|
53
|
+
"ReadUvarint": {
|
|
54
|
+
"status": "real"
|
|
55
|
+
},
|
|
56
|
+
"ReadVarint": {
|
|
57
|
+
"status": "real"
|
|
58
|
+
},
|
|
59
|
+
"Size": {
|
|
60
|
+
"status": "real"
|
|
61
|
+
},
|
|
62
|
+
"Uvarint": {
|
|
63
|
+
"status": "real"
|
|
64
|
+
},
|
|
65
|
+
"Varint": {
|
|
66
|
+
"status": "real"
|
|
67
|
+
},
|
|
68
|
+
"Write": {
|
|
69
|
+
"status": "real"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
package/gs/fmt/fmt.test.ts
CHANGED
|
@@ -144,6 +144,34 @@ describe('fmt basic value formatting', () => {
|
|
|
144
144
|
}
|
|
145
145
|
expect(fmt.Sprintf('value=%s', stringer)).toBe('value=string-value')
|
|
146
146
|
})
|
|
147
|
+
|
|
148
|
+
it('uses only fmt.Formatter-shaped Format methods', () => {
|
|
149
|
+
const formatter = {
|
|
150
|
+
Format(state: fmt.State, verb: number) {
|
|
151
|
+
state.Write($.stringToBytes(`${String.fromCharCode(verb)}:ok`))
|
|
152
|
+
},
|
|
153
|
+
}
|
|
154
|
+
expect(fmt.Sprintf('%s', formatter)).toBe('s:ok')
|
|
155
|
+
|
|
156
|
+
const nodeLike = {
|
|
157
|
+
Format(_buf: unknown) {
|
|
158
|
+
throw new Error('domain Format should not be called by fmt')
|
|
159
|
+
},
|
|
160
|
+
String() {
|
|
161
|
+
return 'node-string'
|
|
162
|
+
},
|
|
163
|
+
}
|
|
164
|
+
expect(fmt.Sprintf('%s', nodeLike)).toBe('node-string')
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
it('allows Sprintf callers to await async stringers', async () => {
|
|
168
|
+
const stringer = {
|
|
169
|
+
async String() {
|
|
170
|
+
return 'async-string'
|
|
171
|
+
},
|
|
172
|
+
}
|
|
173
|
+
expect(await fmt.Sprintf('value=%s', stringer)).toBe('value=async-string')
|
|
174
|
+
})
|
|
147
175
|
})
|
|
148
176
|
|
|
149
177
|
describe('fmt spacing rules', () => {
|
package/gs/fmt/fmt.ts
CHANGED
|
@@ -98,13 +98,52 @@ function hasGoTypeName(value: unknown): value is { __goType: string } {
|
|
|
98
98
|
)
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
type MaybeString = string | PromiseLike<string>
|
|
102
|
+
|
|
103
|
+
function isPromiseLike<T = unknown>(value: unknown): value is PromiseLike<T> {
|
|
104
|
+
return (
|
|
105
|
+
value !== null &&
|
|
106
|
+
(typeof value === 'object' || typeof value === 'function') &&
|
|
107
|
+
typeof (value as { then?: unknown }).then === 'function'
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function toMaybeString(value: unknown): MaybeString {
|
|
112
|
+
if (isPromiseLike(value)) {
|
|
113
|
+
return value.then((resolved) => String(resolved))
|
|
114
|
+
}
|
|
115
|
+
return String(value)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function joinMaybe(
|
|
119
|
+
parts: MaybeString[],
|
|
120
|
+
separator: string,
|
|
121
|
+
prefix = '',
|
|
122
|
+
suffix = '',
|
|
123
|
+
): MaybeString {
|
|
124
|
+
if (parts.some(isPromiseLike)) {
|
|
125
|
+
return Promise.all(parts.map((part) => Promise.resolve(part))).then(
|
|
126
|
+
(resolved) => `${prefix}${resolved.join(separator)}${suffix}`,
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
return `${prefix}${(parts as string[]).join(separator)}${suffix}`
|
|
130
|
+
}
|
|
131
|
+
|
|
101
132
|
function defaultFormat(value: any): string {
|
|
133
|
+
const formatted = defaultFormatMaybe(value)
|
|
134
|
+
if (isPromiseLike(formatted)) {
|
|
135
|
+
return String(formatted)
|
|
136
|
+
}
|
|
137
|
+
return formatted
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function defaultFormatMaybe(value: any): MaybeString {
|
|
102
141
|
if (value === null || value === undefined) return '<nil>'
|
|
103
142
|
if (typeof value === 'boolean') return value ? 'true' : 'false'
|
|
104
143
|
if (typeof value === 'number') return value.toString()
|
|
105
144
|
if (typeof value === 'string') return value
|
|
106
145
|
if (Array.isArray(value))
|
|
107
|
-
return
|
|
146
|
+
return joinMaybe(value.map(defaultFormatMaybe), ' ', '[', ']')
|
|
108
147
|
if (typeof value === 'object') {
|
|
109
148
|
// Prefer GoStringer if present
|
|
110
149
|
if (
|
|
@@ -112,7 +151,7 @@ function defaultFormat(value: any): string {
|
|
|
112
151
|
typeof (value as any).GoString === 'function'
|
|
113
152
|
) {
|
|
114
153
|
try {
|
|
115
|
-
return (value as any).GoString()
|
|
154
|
+
return toMaybeString((value as any).GoString())
|
|
116
155
|
} catch {
|
|
117
156
|
// Ignore error by continuing to next case.
|
|
118
157
|
}
|
|
@@ -120,7 +159,7 @@ function defaultFormat(value: any): string {
|
|
|
120
159
|
// Prefer error interface if present
|
|
121
160
|
if ((value as any).Error && typeof (value as any).Error === 'function') {
|
|
122
161
|
try {
|
|
123
|
-
return (value as any).Error()
|
|
162
|
+
return toMaybeString((value as any).Error())
|
|
124
163
|
} catch {
|
|
125
164
|
// Ignore error by continuing to next case.
|
|
126
165
|
}
|
|
@@ -128,37 +167,54 @@ function defaultFormat(value: any): string {
|
|
|
128
167
|
// Check for Stringer interface
|
|
129
168
|
if ((value as any).String && typeof (value as any).String === 'function') {
|
|
130
169
|
try {
|
|
131
|
-
return (value as any).String()
|
|
170
|
+
return toMaybeString((value as any).String())
|
|
132
171
|
} catch {
|
|
133
172
|
// Ignore error by continuing to next case.
|
|
134
173
|
}
|
|
135
174
|
}
|
|
136
175
|
if ('__goValue' in value) {
|
|
137
|
-
return
|
|
176
|
+
return defaultFormatMaybe((value as { __goValue: unknown }).__goValue)
|
|
138
177
|
}
|
|
139
178
|
// Basic Map/Set rendering
|
|
140
179
|
if (value instanceof Map) {
|
|
141
|
-
const parts:
|
|
180
|
+
const parts: MaybeString[] = []
|
|
142
181
|
for (const [k, v] of (value as Map<any, any>).entries()) {
|
|
143
|
-
|
|
182
|
+
const key = defaultFormatMaybe(k)
|
|
183
|
+
const elem = defaultFormatMaybe(v)
|
|
184
|
+
if (isPromiseLike(key) || isPromiseLike(elem)) {
|
|
185
|
+
parts.push(
|
|
186
|
+
Promise.all([Promise.resolve(key), Promise.resolve(elem)]).then(
|
|
187
|
+
([resolvedKey, resolvedElem]) => `${resolvedKey}:${resolvedElem}`,
|
|
188
|
+
),
|
|
189
|
+
)
|
|
190
|
+
} else {
|
|
191
|
+
parts.push(`${key}:${elem}`)
|
|
192
|
+
}
|
|
144
193
|
}
|
|
145
|
-
return
|
|
194
|
+
return joinMaybe(parts, ' ', '{', '}')
|
|
146
195
|
}
|
|
147
196
|
if (value instanceof Set) {
|
|
148
|
-
const parts:
|
|
197
|
+
const parts: MaybeString[] = []
|
|
149
198
|
for (const v of (value as Set<any>).values()) {
|
|
150
|
-
parts.push(
|
|
199
|
+
parts.push(defaultFormatMaybe(v))
|
|
151
200
|
}
|
|
152
|
-
return '
|
|
201
|
+
return joinMaybe(parts, ' ', '[', ']')
|
|
153
202
|
}
|
|
154
203
|
// Default object representation
|
|
155
204
|
if (
|
|
156
205
|
(value as any).constructor?.name &&
|
|
157
206
|
(value as any).constructor.name !== 'Object'
|
|
158
207
|
) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
208
|
+
const parts = Object.entries(value as Record<string, any>).map(
|
|
209
|
+
([k, v]) => {
|
|
210
|
+
const formatted = defaultFormatMaybe(v)
|
|
211
|
+
if (isPromiseLike(formatted)) {
|
|
212
|
+
return formatted.then((resolved) => `${k}:${resolved}`)
|
|
213
|
+
}
|
|
214
|
+
return `${k}:${formatted}`
|
|
215
|
+
},
|
|
216
|
+
)
|
|
217
|
+
return joinMaybe(parts, ' ', '{', '}')
|
|
162
218
|
}
|
|
163
219
|
try {
|
|
164
220
|
return JSON.stringify(value)
|
|
@@ -170,7 +226,79 @@ function defaultFormat(value: any): string {
|
|
|
170
226
|
}
|
|
171
227
|
|
|
172
228
|
function parseFormat(format: string, args: any[]): string {
|
|
173
|
-
|
|
229
|
+
const formatted = parseFormatMaybe(format, args, false)
|
|
230
|
+
if (isPromiseLike(formatted)) {
|
|
231
|
+
return String(formatted)
|
|
232
|
+
}
|
|
233
|
+
return formatted
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function formatValueMaybe(value: any, verb: string): MaybeString {
|
|
237
|
+
switch (verb) {
|
|
238
|
+
case 'v':
|
|
239
|
+
case 'w':
|
|
240
|
+
case 's':
|
|
241
|
+
if (verb === 's') {
|
|
242
|
+
if (typeof value === 'string') return value
|
|
243
|
+
if (value instanceof Uint8Array) return $.bytesToString(value)
|
|
244
|
+
}
|
|
245
|
+
return defaultFormatMaybe(value)
|
|
246
|
+
default:
|
|
247
|
+
return formatValue(value, verb)
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function applyFormatOptions(
|
|
252
|
+
formatted: MaybeString,
|
|
253
|
+
arg: any,
|
|
254
|
+
verb: string,
|
|
255
|
+
flags: string,
|
|
256
|
+
width: string,
|
|
257
|
+
precision: string,
|
|
258
|
+
): MaybeString {
|
|
259
|
+
const apply = (text: string): string => {
|
|
260
|
+
let result = text
|
|
261
|
+
if (width && !precision) {
|
|
262
|
+
const w = parseInt(width)
|
|
263
|
+
if (flags.includes('-')) {
|
|
264
|
+
result = result.padEnd(w)
|
|
265
|
+
} else {
|
|
266
|
+
result = result.padStart(w, flags.includes('0') ? '0' : ' ')
|
|
267
|
+
}
|
|
268
|
+
} else if (precision && (verb === 'f' || verb === 'e' || verb === 'g')) {
|
|
269
|
+
const p = parseInt(precision)
|
|
270
|
+
const num = Number(arg)
|
|
271
|
+
if (verb === 'f') {
|
|
272
|
+
result = num.toFixed(p)
|
|
273
|
+
} else if (verb === 'e') {
|
|
274
|
+
result = num.toExponential(p)
|
|
275
|
+
} else if (verb === 'g') {
|
|
276
|
+
result = num.toPrecision(p)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (width) {
|
|
280
|
+
const w = parseInt(width)
|
|
281
|
+
if (flags.includes('-')) {
|
|
282
|
+
result = result.padEnd(w)
|
|
283
|
+
} else {
|
|
284
|
+
result = result.padStart(w)
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return result
|
|
289
|
+
}
|
|
290
|
+
if (isPromiseLike(formatted)) {
|
|
291
|
+
return formatted.then(apply)
|
|
292
|
+
}
|
|
293
|
+
return apply(formatted)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function parseFormatMaybe(
|
|
297
|
+
format: string,
|
|
298
|
+
args: any[],
|
|
299
|
+
allowAsync = true,
|
|
300
|
+
): MaybeString {
|
|
301
|
+
const parts: MaybeString[] = []
|
|
174
302
|
let argIndex = 0
|
|
175
303
|
|
|
176
304
|
for (let i = 0; i < format.length; i++) {
|
|
@@ -178,7 +306,7 @@ function parseFormat(format: string, args: any[]): string {
|
|
|
178
306
|
if (i + 1 < format.length) {
|
|
179
307
|
const nextChar = format[i + 1]
|
|
180
308
|
if (nextChar === '%') {
|
|
181
|
-
|
|
309
|
+
parts.push('%')
|
|
182
310
|
i++ // skip the next %
|
|
183
311
|
continue
|
|
184
312
|
}
|
|
@@ -216,65 +344,38 @@ function parseFormat(format: string, args: any[]): string {
|
|
|
216
344
|
|
|
217
345
|
if (argIndex < args.length) {
|
|
218
346
|
const arg = args[argIndex]
|
|
219
|
-
let formatted
|
|
347
|
+
let formatted: MaybeString | null =
|
|
348
|
+
allowAsync ?
|
|
349
|
+
formatWithStateMaybe(arg, verb, flags, width, precision)
|
|
350
|
+
: formatWithState(arg, verb, flags, width, precision)
|
|
220
351
|
if (formatted === null) {
|
|
221
|
-
formatted =
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
if (width && !precision) {
|
|
226
|
-
const w = parseInt(width)
|
|
227
|
-
if (flags.includes('-')) {
|
|
228
|
-
formatted = formatted.padEnd(w)
|
|
229
|
-
} else {
|
|
230
|
-
formatted = formatted.padStart(
|
|
231
|
-
w,
|
|
232
|
-
flags.includes('0') ? '0' : ' ',
|
|
233
|
-
)
|
|
234
|
-
}
|
|
235
|
-
} else if (
|
|
236
|
-
precision &&
|
|
237
|
-
(verb === 'f' || verb === 'e' || verb === 'g')
|
|
238
|
-
) {
|
|
239
|
-
const p = parseInt(precision)
|
|
240
|
-
const num = Number(arg)
|
|
241
|
-
if (verb === 'f') {
|
|
242
|
-
formatted = num.toFixed(p)
|
|
243
|
-
} else if (verb === 'e') {
|
|
244
|
-
formatted = num.toExponential(p)
|
|
245
|
-
} else if (verb === 'g') {
|
|
246
|
-
formatted = num.toPrecision(p)
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
if (width) {
|
|
250
|
-
const w = parseInt(width)
|
|
251
|
-
if (flags.includes('-')) {
|
|
252
|
-
formatted = formatted.padEnd(w)
|
|
253
|
-
} else {
|
|
254
|
-
formatted = formatted.padStart(w)
|
|
255
|
-
}
|
|
256
|
-
}
|
|
352
|
+
formatted =
|
|
353
|
+
allowAsync ?
|
|
354
|
+
formatValueMaybe(arg, verb)
|
|
355
|
+
: formatValue(arg, verb)
|
|
257
356
|
}
|
|
258
357
|
|
|
259
|
-
|
|
358
|
+
parts.push(
|
|
359
|
+
applyFormatOptions(formatted, arg, verb, flags, width, precision),
|
|
360
|
+
)
|
|
260
361
|
argIndex++
|
|
261
362
|
} else {
|
|
262
|
-
|
|
363
|
+
parts.push(`%!${verb}(MISSING)`)
|
|
263
364
|
}
|
|
264
365
|
|
|
265
366
|
i = j
|
|
266
367
|
} else {
|
|
267
|
-
|
|
368
|
+
parts.push(format[i])
|
|
268
369
|
}
|
|
269
370
|
} else {
|
|
270
|
-
|
|
371
|
+
parts.push(format[i])
|
|
271
372
|
}
|
|
272
373
|
} else {
|
|
273
|
-
|
|
374
|
+
parts.push(format[i])
|
|
274
375
|
}
|
|
275
376
|
}
|
|
276
377
|
|
|
277
|
-
return
|
|
378
|
+
return joinMaybe(parts, '')
|
|
278
379
|
}
|
|
279
380
|
|
|
280
381
|
function formatWithState(
|
|
@@ -284,7 +385,7 @@ function formatWithState(
|
|
|
284
385
|
width: string,
|
|
285
386
|
precision: string,
|
|
286
387
|
): string | null {
|
|
287
|
-
if (!value || typeof value.Format !== 'function') {
|
|
388
|
+
if (!value || typeof value.Format !== 'function' || value.Format.length < 2) {
|
|
288
389
|
return null
|
|
289
390
|
}
|
|
290
391
|
|
|
@@ -310,6 +411,42 @@ function formatWithState(
|
|
|
310
411
|
return out
|
|
311
412
|
}
|
|
312
413
|
|
|
414
|
+
function formatWithStateMaybe(
|
|
415
|
+
value: any,
|
|
416
|
+
verb: string,
|
|
417
|
+
flags: string,
|
|
418
|
+
width: string,
|
|
419
|
+
precision: string,
|
|
420
|
+
): MaybeString | null {
|
|
421
|
+
if (!value || typeof value.Format !== 'function' || value.Format.length < 2) {
|
|
422
|
+
return null
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
let out = ''
|
|
426
|
+
const state: State = {
|
|
427
|
+
Flag(c: number): boolean {
|
|
428
|
+
return flags.includes(String.fromCharCode(c))
|
|
429
|
+
},
|
|
430
|
+
Precision(): [number, boolean] {
|
|
431
|
+
return precision === '' ? [0, false] : [parseInt(precision), true]
|
|
432
|
+
},
|
|
433
|
+
Width(): [number, boolean] {
|
|
434
|
+
return width === '' ? [0, false] : [parseInt(width), true]
|
|
435
|
+
},
|
|
436
|
+
Write(b: $.Bytes): [number, $.GoError | null] {
|
|
437
|
+
const text = $.bytesToString(b)
|
|
438
|
+
out += text
|
|
439
|
+
return [text.length, null]
|
|
440
|
+
},
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const result = value.Format(state, verb.codePointAt(0) ?? 0)
|
|
444
|
+
if (isPromiseLike(result)) {
|
|
445
|
+
return result.then(() => out)
|
|
446
|
+
}
|
|
447
|
+
return out
|
|
448
|
+
}
|
|
449
|
+
|
|
313
450
|
// Global stdout simulation for Print functions
|
|
314
451
|
let stdout = {
|
|
315
452
|
write: (data: string) => {
|
|
@@ -366,7 +503,7 @@ export function Sprint(...a: any[]): string {
|
|
|
366
503
|
}
|
|
367
504
|
|
|
368
505
|
export function Sprintf(format: string, ...a: any[]): string {
|
|
369
|
-
return
|
|
506
|
+
return parseFormatMaybe(format, a) as string
|
|
370
507
|
}
|
|
371
508
|
|
|
372
509
|
export function Sprintln(...a: any[]): string {
|
package/gs/fmt/meta.json
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as $ from '@goscript/builtin/index.js'
|
|
2
|
+
|
|
3
|
+
// FeatureID is the identifier for a single CPU feature.
|
|
4
|
+
export type FeatureID = number
|
|
5
|
+
|
|
6
|
+
// UNKNOWN is the sentinel for an unrecognized feature.
|
|
7
|
+
export const UNKNOWN: FeatureID = -1
|
|
8
|
+
|
|
9
|
+
// AVX2 identifies AVX2 SIMD support. Matches the upstream iota value.
|
|
10
|
+
export const AVX2: FeatureID = 19
|
|
11
|
+
|
|
12
|
+
// AVX512F identifies AVX-512 Foundation support. Matches the upstream iota value.
|
|
13
|
+
export const AVX512F: FeatureID = 26
|
|
14
|
+
|
|
15
|
+
// CPUInfo reports detected CPU capabilities. The browser/wasm target has no
|
|
16
|
+
// SIMD instruction set to detect, so this override reports no features and
|
|
17
|
+
// callers fall back to portable Go implementations.
|
|
18
|
+
export class CPUInfo {
|
|
19
|
+
constructor(_init?: Partial<{}>) {}
|
|
20
|
+
|
|
21
|
+
public clone(): CPUInfo {
|
|
22
|
+
return $.markAsStructValue(new CPUInfo())
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Supports reports whether all listed features are available. The wasm
|
|
26
|
+
// target never exposes native SIMD features, so this always reports false.
|
|
27
|
+
public Supports(..._ids: FeatureID[]): boolean {
|
|
28
|
+
return false
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// CPU holds the detected capabilities of the current CPU. On wasm there is no
|
|
33
|
+
// native CPU feature set, so it reports nothing.
|
|
34
|
+
export let CPU: CPUInfo = $.markAsStructValue(new CPUInfo())
|
|
35
|
+
|
|
36
|
+
export function __goscript_set_CPU(value: CPUInfo): void {
|
|
37
|
+
CPU = value
|
|
38
|
+
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import * as $ from '@goscript/builtin/index.js'
|
|
2
2
|
import { callers } from './stack.js'
|
|
3
|
+
import type { StackTrace } from './stack.js'
|
|
3
4
|
|
|
4
5
|
// Type definitions
|
|
5
|
-
export type Frame = any // Simplified frame type
|
|
6
|
-
export type StackTrace = Frame[] | null
|
|
7
6
|
export type stack = any // Simplified stack type
|
|
8
7
|
export type uintptr = number
|
|
9
8
|
|
|
@@ -2,72 +2,44 @@ import * as $ from '@goscript/builtin/index.js'
|
|
|
2
2
|
|
|
3
3
|
// Type definitions
|
|
4
4
|
export type uintptr = number
|
|
5
|
+
export type Frame = uintptr
|
|
6
|
+
export type StackTrace = $.Slice<Frame>
|
|
5
7
|
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
valueOf(): uintptr {
|
|
10
|
-
return this._value
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
toString(): string {
|
|
14
|
-
return String(this._value)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
static from(value: uintptr): Frame {
|
|
18
|
-
return new Frame(value)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// pc returns the program counter for this frame;
|
|
22
|
-
// multiple frames may have the same PC value.
|
|
23
|
-
public pc(): uintptr {
|
|
24
|
-
return this._value - 1
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// file returns the full path to the file that contains the
|
|
28
|
-
// function for this Frame's pc.
|
|
29
|
-
public file(): string {
|
|
30
|
-
return 'unknown'
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// line returns the line number of source code of the
|
|
34
|
-
// function for this Frame's pc.
|
|
35
|
-
public line(): number {
|
|
36
|
-
return 0
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// name returns the name of this function, if known.
|
|
40
|
-
public name(): string {
|
|
41
|
-
return 'unknown'
|
|
42
|
-
}
|
|
8
|
+
export function Frame_pc(receiver: Frame): uintptr {
|
|
9
|
+
return receiver - 1
|
|
10
|
+
}
|
|
43
11
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const name = this.name()
|
|
47
|
-
if (name == 'unknown') {
|
|
48
|
-
return [new TextEncoder().encode(name), null]
|
|
49
|
-
}
|
|
50
|
-
return [
|
|
51
|
-
new TextEncoder().encode(`${name} ${this.file()}:${this.line()}`),
|
|
52
|
-
null,
|
|
53
|
-
]
|
|
54
|
-
}
|
|
12
|
+
export function Frame_file(_receiver: Frame): string {
|
|
13
|
+
return 'unknown'
|
|
55
14
|
}
|
|
56
15
|
|
|
57
|
-
export
|
|
58
|
-
|
|
16
|
+
export function Frame_line(_receiver: Frame): number {
|
|
17
|
+
return 0
|
|
18
|
+
}
|
|
59
19
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
20
|
+
export function Frame_name(_receiver: Frame): string {
|
|
21
|
+
return 'unknown'
|
|
22
|
+
}
|
|
63
23
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
24
|
+
export function Frame_MarshalText(receiver: Frame): [$.Bytes, $.GoError] {
|
|
25
|
+
const name = Frame_name(receiver)
|
|
26
|
+
if (name == 'unknown') {
|
|
27
|
+
return [new TextEncoder().encode(name), null]
|
|
28
|
+
}
|
|
29
|
+
return [
|
|
30
|
+
new TextEncoder().encode(
|
|
31
|
+
`${name} ${Frame_file(receiver)}:${Frame_line(receiver)}`,
|
|
32
|
+
),
|
|
33
|
+
null,
|
|
34
|
+
]
|
|
35
|
+
}
|
|
67
36
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
37
|
+
export function StackTrace_Format(
|
|
38
|
+
_receiver: StackTrace,
|
|
39
|
+
_state: any,
|
|
40
|
+
_verb: number,
|
|
41
|
+
): void {
|
|
42
|
+
// Stack frame formatting is informational in the JavaScript target.
|
|
71
43
|
}
|
|
72
44
|
|
|
73
45
|
class stack {
|
|
@@ -88,14 +60,14 @@ class stack {
|
|
|
88
60
|
public StackTrace(): StackTrace {
|
|
89
61
|
const s = this._value
|
|
90
62
|
if (!s || s.length === 0) {
|
|
91
|
-
return
|
|
63
|
+
return null
|
|
92
64
|
}
|
|
93
65
|
|
|
94
66
|
const frames: Frame[] = []
|
|
95
67
|
for (let i = 0; i < s.length; i++) {
|
|
96
|
-
frames.push(
|
|
68
|
+
frames.push(s[i])
|
|
97
69
|
}
|
|
98
|
-
return
|
|
70
|
+
return $.arrayToSlice(frames)
|
|
99
71
|
}
|
|
100
72
|
}
|
|
101
73
|
|