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.
Files changed (117) hide show
  1. package/README.md +8 -8
  2. package/cmd/go_js_wasm_exec/main.go +1 -1
  3. package/cmd/go_js_wasm_exec/main_test.go +1 -1
  4. package/cmd/goscript/cmd-compile.go +9 -1
  5. package/cmd/goscript/cmd-test.go +1 -1
  6. package/cmd/goscript/cmd_compile_test.go +44 -0
  7. package/cmd/goscript/deps.go +1 -1
  8. package/cmd/goscript-wasm/main.go +2 -2
  9. package/compiler/compile-request.go +19 -0
  10. package/compiler/compile_bench_test.go +121 -0
  11. package/compiler/compliance_test.go +17 -1
  12. package/compiler/config.go +2 -0
  13. package/compiler/gotest/result.go +1 -1
  14. package/compiler/gotest/runner.go +2 -2
  15. package/compiler/gotest/runner_test.go +4 -7
  16. package/compiler/index.test.ts +28 -0
  17. package/compiler/index.ts +32 -16
  18. package/compiler/lowering.go +1238 -194
  19. package/compiler/lowering_bench_test.go +4 -0
  20. package/compiler/override-facts.go +1 -1
  21. package/compiler/package-graph.go +92 -0
  22. package/compiler/package-graph_test.go +113 -0
  23. package/compiler/runtime-contract.go +1 -1
  24. package/compiler/semantic-model.go +32 -0
  25. package/compiler/skeleton_test.go +241 -15
  26. package/compiler/wasm/compile.go +1 -1
  27. package/compiler/wasm/compile_test.go +1 -1
  28. package/dist/compiler/index.d.ts +4 -0
  29. package/dist/compiler/index.js +26 -15
  30. package/dist/compiler/index.js.map +1 -1
  31. package/dist/gs/database/sql/driver/index.d.ts +165 -0
  32. package/dist/gs/database/sql/driver/index.js +432 -0
  33. package/dist/gs/database/sql/driver/index.js.map +1 -0
  34. package/dist/gs/encoding/binary/index.d.ts +71 -0
  35. package/dist/gs/encoding/binary/index.js +778 -0
  36. package/dist/gs/encoding/binary/index.js.map +1 -0
  37. package/dist/gs/fmt/fmt.js +156 -57
  38. package/dist/gs/fmt/fmt.js.map +1 -1
  39. package/dist/gs/github.com/klauspost/cpuid/v2/index.d.ts +11 -0
  40. package/dist/gs/github.com/klauspost/cpuid/v2/index.js +28 -0
  41. package/dist/gs/github.com/klauspost/cpuid/v2/index.js.map +1 -0
  42. package/dist/gs/github.com/pkg/errors/errors.d.ts +0 -2
  43. package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
  44. package/dist/gs/github.com/pkg/errors/index.d.ts +2 -1
  45. package/dist/gs/github.com/pkg/errors/index.js +1 -1
  46. package/dist/gs/github.com/pkg/errors/index.js.map +1 -1
  47. package/dist/gs/github.com/pkg/errors/stack.d.ts +8 -19
  48. package/dist/gs/github.com/pkg/errors/stack.js +26 -61
  49. package/dist/gs/github.com/pkg/errors/stack.js.map +1 -1
  50. package/dist/gs/golang.org/x/crypto/cryptobyte/asn1/index.d.ts +19 -0
  51. package/dist/gs/golang.org/x/crypto/cryptobyte/asn1/index.js +25 -0
  52. package/dist/gs/golang.org/x/crypto/cryptobyte/asn1/index.js.map +1 -0
  53. package/dist/gs/golang.org/x/crypto/cryptobyte/index.d.ts +104 -0
  54. package/dist/gs/golang.org/x/crypto/cryptobyte/index.js +1107 -0
  55. package/dist/gs/golang.org/x/crypto/cryptobyte/index.js.map +1 -0
  56. package/dist/gs/golang.org/x/crypto/internal/alias/index.d.ts +3 -0
  57. package/dist/gs/golang.org/x/crypto/internal/alias/index.js +39 -0
  58. package/dist/gs/golang.org/x/crypto/internal/alias/index.js.map +1 -0
  59. package/dist/gs/runtime/runtime.d.ts +6 -1
  60. package/dist/gs/runtime/runtime.js +15 -8
  61. package/dist/gs/runtime/runtime.js.map +1 -1
  62. package/dist/gs/runtime/trace/index.d.ts +8 -5
  63. package/dist/gs/runtime/trace/index.js +324 -23
  64. package/dist/gs/runtime/trace/index.js.map +1 -1
  65. package/dist/gs/slices/slices.d.ts +2 -1
  66. package/dist/gs/slices/slices.js +9 -3
  67. package/dist/gs/slices/slices.js.map +1 -1
  68. package/dist/gs/sort/search.gs.d.ts +3 -1
  69. package/dist/gs/sort/search.gs.js +18 -53
  70. package/dist/gs/sort/search.gs.js.map +1 -1
  71. package/dist/gs/sync/sync.d.ts +1 -1
  72. package/dist/gs/sync/sync.js +3 -0
  73. package/dist/gs/sync/sync.js.map +1 -1
  74. package/dist/gs/time/time.d.ts +22 -29
  75. package/dist/gs/time/time.js +111 -32
  76. package/dist/gs/time/time.js.map +1 -1
  77. package/dist/gs/unsafe/unsafe.d.ts +3 -2
  78. package/dist/gs/unsafe/unsafe.js.map +1 -1
  79. package/go.mod +7 -5
  80. package/go.sum +12 -26
  81. package/gs/database/sql/driver/index.test.ts +88 -0
  82. package/gs/database/sql/driver/index.ts +675 -0
  83. package/gs/database/sql/driver/meta.json +3 -0
  84. package/gs/database/sql/driver/parity.json +144 -0
  85. package/gs/encoding/binary/index.test.ts +239 -0
  86. package/gs/encoding/binary/index.ts +999 -0
  87. package/gs/encoding/binary/meta.json +9 -0
  88. package/gs/encoding/binary/parity.json +72 -0
  89. package/gs/fmt/fmt.test.ts +28 -0
  90. package/gs/fmt/fmt.ts +198 -61
  91. package/gs/fmt/meta.json +2 -1
  92. package/gs/github.com/klauspost/cpuid/v2/index.ts +38 -0
  93. package/gs/github.com/klauspost/cpuid/v2/meta.json +3 -0
  94. package/gs/github.com/pkg/errors/errors.ts +1 -2
  95. package/gs/github.com/pkg/errors/index.ts +2 -1
  96. package/gs/github.com/pkg/errors/stack.ts +34 -62
  97. package/gs/golang.org/x/crypto/cryptobyte/asn1/index.test.ts +19 -0
  98. package/gs/golang.org/x/crypto/cryptobyte/asn1/index.ts +29 -0
  99. package/gs/golang.org/x/crypto/cryptobyte/index.test.ts +255 -0
  100. package/gs/golang.org/x/crypto/cryptobyte/index.ts +1441 -0
  101. package/gs/golang.org/x/crypto/cryptobyte/meta.json +3 -0
  102. package/gs/golang.org/x/crypto/internal/alias/index.test.ts +40 -0
  103. package/gs/golang.org/x/crypto/internal/alias/index.ts +40 -0
  104. package/gs/runtime/runtime.test.ts +16 -0
  105. package/gs/runtime/runtime.ts +17 -9
  106. package/gs/runtime/trace/index.test.ts +113 -14
  107. package/gs/runtime/trace/index.ts +384 -34
  108. package/gs/runtime/trace/meta.json +1 -0
  109. package/gs/slices/slices.test.ts +24 -1
  110. package/gs/slices/slices.ts +14 -4
  111. package/gs/sort/meta.json +1 -0
  112. package/gs/sort/search.gs.ts +20 -5
  113. package/gs/sync/sync.ts +4 -1
  114. package/gs/time/time.test.ts +79 -2
  115. package/gs/time/time.ts +133 -33
  116. package/gs/unsafe/unsafe.ts +4 -2
  117. package/package.json +2 -2
@@ -0,0 +1,9 @@
1
+ {
2
+ "dependencies": ["io"],
3
+ "asyncFunctions": {
4
+ "Read": true,
5
+ "ReadUvarint": true,
6
+ "ReadVarint": true,
7
+ "Write": true
8
+ }
9
+ }
@@ -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
+ }
@@ -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 '[' + value.map(defaultFormat).join(' ') + ']'
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 defaultFormat((value as { __goValue: unknown }).__goValue)
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: string[] = []
180
+ const parts: MaybeString[] = []
142
181
  for (const [k, v] of (value as Map<any, any>).entries()) {
143
- parts.push(`${defaultFormat(k)}:${defaultFormat(v)}`)
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 `{${parts.join(' ')}}`
194
+ return joinMaybe(parts, ' ', '{', '}')
146
195
  }
147
196
  if (value instanceof Set) {
148
- const parts: string[] = []
197
+ const parts: MaybeString[] = []
149
198
  for (const v of (value as Set<any>).values()) {
150
- parts.push(defaultFormat(v))
199
+ parts.push(defaultFormatMaybe(v))
151
200
  }
152
- return '[' + parts.join(' ') + ']'
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
- return `{${Object.entries(value as Record<string, any>)
160
- .map(([k, v]) => `${k}:${defaultFormat(v)}`)
161
- .join(' ')}}`
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
- let result = ''
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
- result += '%'
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 = formatWithState(arg, verb, flags, width, precision)
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 = formatValue(arg, verb)
222
- }
223
-
224
- // Apply width and precision formatting
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
- result += formatted
358
+ parts.push(
359
+ applyFormatOptions(formatted, arg, verb, flags, width, precision),
360
+ )
260
361
  argIndex++
261
362
  } else {
262
- result += `%!${verb}(MISSING)`
363
+ parts.push(`%!${verb}(MISSING)`)
263
364
  }
264
365
 
265
366
  i = j
266
367
  } else {
267
- result += format[i]
368
+ parts.push(format[i])
268
369
  }
269
370
  } else {
270
- result += format[i]
371
+ parts.push(format[i])
271
372
  }
272
373
  } else {
273
- result += format[i]
374
+ parts.push(format[i])
274
375
  }
275
376
  }
276
377
 
277
- return result
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 parseFormat(format, a)
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
@@ -2,7 +2,8 @@
2
2
  "asyncFunctions": {
3
3
  "Fprint": true,
4
4
  "Fprintf": true,
5
- "Fprintln": true
5
+ "Fprintln": true,
6
+ "Sprintf": true
6
7
  },
7
8
  "dependencies": [
8
9
  "errors"
@@ -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
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "dependencies": []
3
+ }
@@ -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
 
@@ -9,4 +9,5 @@ export {
9
9
  Wrapf,
10
10
  } from './errors.js'
11
11
  export { As, Is, Unwrap } from './go113.js'
12
- export { Frame, StackTrace } from './stack.js'
12
+ export type { Frame, StackTrace } from './stack.js'
13
+ export { Frame_MarshalText, StackTrace_Format } from './stack.js'
@@ -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 class Frame {
7
- constructor(private _value: uintptr) {}
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
- // MarshalText formats a stacktrace Frame as a text string.
45
- public MarshalText(): [$.Bytes, $.GoError] {
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 class StackTrace {
58
- constructor(private _value: Frame[] | null) {}
16
+ export function Frame_line(_receiver: Frame): number {
17
+ return 0
18
+ }
59
19
 
60
- valueOf(): Frame[] | null {
61
- return this._value
62
- }
20
+ export function Frame_name(_receiver: Frame): string {
21
+ return 'unknown'
22
+ }
63
23
 
64
- toString(): string {
65
- return String(this._value)
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
- static from(value: Frame[] | null): StackTrace {
69
- return new StackTrace(value)
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 new StackTrace(null)
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(new Frame(s[i]))
68
+ frames.push(s[i])
97
69
  }
98
- return new StackTrace(frames)
70
+ return $.arrayToSlice(frames)
99
71
  }
100
72
  }
101
73