goscript 0.2.5 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/cmd/goscript/cmd-compile.go +7 -0
  2. package/cmd/goscript/cmd_compile_test.go +83 -0
  3. package/compiler/compile-request.go +3 -0
  4. package/compiler/compiler-cache.go +828 -0
  5. package/compiler/compiler-cache_test.go +705 -0
  6. package/compiler/config.go +2 -0
  7. package/compiler/index.test.ts +26 -1
  8. package/compiler/index.ts +5 -0
  9. package/compiler/lowered-program.go +31 -20
  10. package/compiler/lowering.go +349 -93
  11. package/compiler/lowering_bench_test.go +1 -0
  12. package/compiler/override-facts.go +309 -8
  13. package/compiler/override-parity-verifier.go +45 -1
  14. package/compiler/override-parity-verifier_test.go +100 -0
  15. package/compiler/override-registry_test.go +1 -0
  16. package/compiler/package-graph.go +40 -12
  17. package/compiler/package-graph_test.go +29 -0
  18. package/compiler/runtime-contract.go +8 -0
  19. package/compiler/service.go +98 -11
  20. package/compiler/skeleton_test.go +110 -14
  21. package/compiler/typescript-emitter.go +120 -23
  22. package/dist/compiler/index.d.ts +2 -0
  23. package/dist/compiler/index.js +3 -0
  24. package/dist/compiler/index.js.map +1 -1
  25. package/dist/gs/builtin/builtin.d.ts +24 -33
  26. package/dist/gs/builtin/builtin.js +54 -61
  27. package/dist/gs/builtin/builtin.js.map +1 -1
  28. package/dist/gs/builtin/hostio.d.ts +1 -0
  29. package/dist/gs/builtin/hostio.js +1 -1
  30. package/dist/gs/builtin/hostio.js.map +1 -1
  31. package/dist/gs/builtin/index.d.ts +1 -0
  32. package/dist/gs/builtin/index.js +1 -0
  33. package/dist/gs/builtin/index.js.map +1 -1
  34. package/dist/gs/builtin/panic.d.ts +18 -0
  35. package/dist/gs/builtin/panic.js +98 -0
  36. package/dist/gs/builtin/panic.js.map +1 -0
  37. package/dist/gs/builtin/slice.d.ts +10 -0
  38. package/dist/gs/builtin/slice.js +110 -53
  39. package/dist/gs/builtin/slice.js.map +1 -1
  40. package/dist/gs/builtin/type.js +15 -3
  41. package/dist/gs/builtin/type.js.map +1 -1
  42. package/dist/gs/builtin/varRef.d.ts +1 -1
  43. package/dist/gs/builtin/varRef.js +3 -2
  44. package/dist/gs/builtin/varRef.js.map +1 -1
  45. package/dist/gs/bytes/bytes.gs.js +51 -38
  46. package/dist/gs/bytes/bytes.gs.js.map +1 -1
  47. package/dist/gs/bytes/reader.gs.d.ts +1 -1
  48. package/dist/gs/bytes/reader.gs.js +6 -7
  49. package/dist/gs/bytes/reader.gs.js.map +1 -1
  50. package/dist/gs/cmp/index.d.ts +1 -1
  51. package/dist/gs/cmp/index.js +43 -10
  52. package/dist/gs/cmp/index.js.map +1 -1
  53. package/dist/gs/context/context.d.ts +2 -2
  54. package/dist/gs/context/context.js +1 -1
  55. package/dist/gs/context/context.js.map +1 -1
  56. package/dist/gs/embed/index.js +1 -1
  57. package/dist/gs/embed/index.js.map +1 -1
  58. package/dist/gs/encoding/binary/index.js +201 -8
  59. package/dist/gs/encoding/binary/index.js.map +1 -1
  60. package/dist/gs/encoding/json/index.d.ts +5 -0
  61. package/dist/gs/encoding/json/index.js +388 -25
  62. package/dist/gs/encoding/json/index.js.map +1 -1
  63. package/dist/gs/errors/errors.js +17 -24
  64. package/dist/gs/errors/errors.js.map +1 -1
  65. package/dist/gs/fmt/fmt.js +129 -35
  66. package/dist/gs/fmt/fmt.js.map +1 -1
  67. package/dist/gs/golang.org/x/crypto/cryptobyte/index.js +1 -1
  68. package/dist/gs/golang.org/x/crypto/cryptobyte/index.js.map +1 -1
  69. package/dist/gs/internal/bytealg/index.js +43 -8
  70. package/dist/gs/internal/bytealg/index.js.map +1 -1
  71. package/dist/gs/internal/byteorder/index.d.ts +2 -2
  72. package/dist/gs/internal/byteorder/index.js +2 -2
  73. package/dist/gs/internal/byteorder/index.js.map +1 -1
  74. package/dist/gs/io/fs/format.js +2 -2
  75. package/dist/gs/io/fs/format.js.map +1 -1
  76. package/dist/gs/io/fs/fs.d.ts +1 -1
  77. package/dist/gs/io/fs/fs.js +1 -1
  78. package/dist/gs/io/fs/fs.js.map +1 -1
  79. package/dist/gs/io/io.d.ts +21 -21
  80. package/dist/gs/io/io.js +49 -50
  81. package/dist/gs/io/io.js.map +1 -1
  82. package/dist/gs/math/bits/index.js +26 -8
  83. package/dist/gs/math/bits/index.js.map +1 -1
  84. package/dist/gs/math/copysign.gs.js +10 -17
  85. package/dist/gs/math/copysign.gs.js.map +1 -1
  86. package/dist/gs/math/pow.gs.js +5 -0
  87. package/dist/gs/math/pow.gs.js.map +1 -1
  88. package/dist/gs/math/signbit.gs.js +6 -2
  89. package/dist/gs/math/signbit.gs.js.map +1 -1
  90. package/dist/gs/mime/index.js +1 -0
  91. package/dist/gs/mime/index.js.map +1 -1
  92. package/dist/gs/net/http/index.d.ts +6 -6
  93. package/dist/gs/net/http/index.js +507 -43
  94. package/dist/gs/net/http/index.js.map +1 -1
  95. package/dist/gs/os/stat.gs.d.ts +2 -2
  96. package/dist/gs/os/types.gs.d.ts +1 -1
  97. package/dist/gs/os/types.gs.js +1 -1
  98. package/dist/gs/os/types.gs.js.map +1 -1
  99. package/dist/gs/os/types_js.gs.d.ts +1 -1
  100. package/dist/gs/os/types_js.gs.js +7 -7
  101. package/dist/gs/os/types_js.gs.js.map +1 -1
  102. package/dist/gs/os/types_unix.gs.d.ts +1 -1
  103. package/dist/gs/os/types_unix.gs.js +1 -1
  104. package/dist/gs/os/types_unix.gs.js.map +1 -1
  105. package/dist/gs/os/zero_copy_posix.gs.d.ts +1 -1
  106. package/dist/gs/os/zero_copy_posix.gs.js +1 -1
  107. package/dist/gs/os/zero_copy_posix.gs.js.map +1 -1
  108. package/dist/gs/path/filepath/match.js +8 -4
  109. package/dist/gs/path/filepath/match.js.map +1 -1
  110. package/dist/gs/path/filepath/path.js +216 -42
  111. package/dist/gs/path/filepath/path.js.map +1 -1
  112. package/dist/gs/path/match.js +6 -3
  113. package/dist/gs/path/match.js.map +1 -1
  114. package/dist/gs/reflect/type.d.ts +5 -4
  115. package/dist/gs/reflect/type.js +29 -11
  116. package/dist/gs/reflect/type.js.map +1 -1
  117. package/dist/gs/slices/slices.js +11 -11
  118. package/dist/gs/slices/slices.js.map +1 -1
  119. package/dist/gs/strconv/atof.gs.js +156 -43
  120. package/dist/gs/strconv/atof.gs.js.map +1 -1
  121. package/dist/gs/strconv/atoi.gs.d.ts +3 -2
  122. package/dist/gs/strconv/atoi.gs.js +86 -67
  123. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  124. package/dist/gs/strconv/ftoa.gs.js +73 -3
  125. package/dist/gs/strconv/ftoa.gs.js.map +1 -1
  126. package/dist/gs/strconv/itoa.gs.d.ts +4 -4
  127. package/dist/gs/strconv/itoa.gs.js +5 -4
  128. package/dist/gs/strconv/itoa.gs.js.map +1 -1
  129. package/dist/gs/strconv/quote.gs.d.ts +1 -1
  130. package/dist/gs/strconv/quote.gs.js +311 -103
  131. package/dist/gs/strconv/quote.gs.js.map +1 -1
  132. package/dist/gs/strings/reader.d.ts +1 -1
  133. package/dist/gs/strings/reader.js +8 -8
  134. package/dist/gs/strings/reader.js.map +1 -1
  135. package/dist/gs/strings/strings.js +87 -61
  136. package/dist/gs/strings/strings.js.map +1 -1
  137. package/dist/gs/sync/atomic/doc_64.gs.d.ts +14 -14
  138. package/dist/gs/sync/atomic/doc_64.gs.js +10 -10
  139. package/dist/gs/sync/atomic/doc_64.gs.js.map +1 -1
  140. package/dist/gs/sync/atomic/type.gs.d.ts +22 -22
  141. package/dist/gs/sync/atomic/type.gs.js +4 -4
  142. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  143. package/dist/gs/sync/sync.js +50 -12
  144. package/dist/gs/sync/sync.js.map +1 -1
  145. package/dist/gs/syscall/fs.d.ts +6 -6
  146. package/dist/gs/syscall/fs.js +1 -1
  147. package/dist/gs/syscall/fs.js.map +1 -1
  148. package/dist/gs/time/time.d.ts +18 -18
  149. package/dist/gs/time/time.js +58 -55
  150. package/dist/gs/time/time.js.map +1 -1
  151. package/dist/gs/unicode/tables.d.ts +11 -0
  152. package/dist/gs/unicode/tables.js +635 -0
  153. package/dist/gs/unicode/tables.js.map +1 -0
  154. package/dist/gs/unicode/unicode.d.ts +58 -38
  155. package/dist/gs/unicode/unicode.js +362 -278
  156. package/dist/gs/unicode/unicode.js.map +1 -1
  157. package/go.sum +13 -0
  158. package/gs/builtin/builtin.ts +83 -93
  159. package/gs/builtin/hostio.ts +1 -1
  160. package/gs/builtin/index.ts +1 -0
  161. package/gs/builtin/panic.test.ts +189 -0
  162. package/gs/builtin/panic.ts +107 -0
  163. package/gs/builtin/runtime-contract.test.ts +5 -5
  164. package/gs/builtin/slice.test.ts +23 -0
  165. package/gs/builtin/slice.ts +133 -95
  166. package/gs/builtin/type.ts +16 -3
  167. package/gs/builtin/varRef.ts +4 -2
  168. package/gs/builtin/wide-int.test.ts +41 -0
  169. package/gs/bytes/bytes.gs.ts +54 -41
  170. package/gs/bytes/bytes.test.ts +18 -1
  171. package/gs/bytes/reader.gs.ts +7 -8
  172. package/gs/cmp/index.test.ts +55 -0
  173. package/gs/cmp/index.ts +45 -9
  174. package/gs/context/context.ts +3 -3
  175. package/gs/embed/index.ts +2 -2
  176. package/gs/encoding/binary/index.test.ts +104 -0
  177. package/gs/encoding/binary/index.ts +259 -11
  178. package/gs/encoding/json/index.test.ts +107 -0
  179. package/gs/encoding/json/index.ts +400 -29
  180. package/gs/errors/errors.test.ts +44 -1
  181. package/gs/errors/errors.ts +15 -31
  182. package/gs/fmt/fmt.test.ts +70 -2
  183. package/gs/fmt/fmt.ts +128 -34
  184. package/gs/golang.org/x/crypto/cryptobyte/index.ts +1 -1
  185. package/gs/internal/bytealg/index.test.ts +26 -1
  186. package/gs/internal/bytealg/index.ts +44 -8
  187. package/gs/internal/byteorder/index.ts +6 -4
  188. package/gs/io/fs/format.ts +2 -2
  189. package/gs/io/fs/fs.ts +2 -2
  190. package/gs/io/fs/stat.test.ts +2 -2
  191. package/gs/io/fs/sub.test.ts +2 -2
  192. package/gs/io/fs/walk.test.ts +2 -2
  193. package/gs/io/io.test.ts +47 -5
  194. package/gs/io/io.ts +73 -73
  195. package/gs/io/limit.test.ts +103 -0
  196. package/gs/math/bits/index.test.ts +128 -0
  197. package/gs/math/bits/index.ts +26 -8
  198. package/gs/math/copysign.gs.test.ts +3 -1
  199. package/gs/math/copysign.gs.ts +10 -22
  200. package/gs/math/pow.gs.test.ts +4 -5
  201. package/gs/math/pow.gs.ts +5 -0
  202. package/gs/math/signbit.gs.test.ts +2 -1
  203. package/gs/math/signbit.gs.ts +6 -3
  204. package/gs/mime/index.ts +1 -0
  205. package/gs/net/http/index.test.ts +683 -2
  206. package/gs/net/http/index.ts +598 -57
  207. package/gs/net/http/meta.json +3 -0
  208. package/gs/os/stat.gs.ts +2 -2
  209. package/gs/os/types.gs.ts +2 -2
  210. package/gs/os/types_js.gs.ts +9 -9
  211. package/gs/os/types_unix.gs.ts +2 -2
  212. package/gs/os/zero_copy_posix.gs.ts +2 -2
  213. package/gs/path/filepath/match.test.ts +16 -0
  214. package/gs/path/filepath/match.ts +8 -4
  215. package/gs/path/filepath/path.test.ts +91 -9
  216. package/gs/path/filepath/path.ts +223 -49
  217. package/gs/path/match.test.ts +32 -0
  218. package/gs/path/match.ts +6 -3
  219. package/gs/reflect/deepequal.test.ts +1 -1
  220. package/gs/reflect/field.test.ts +1 -1
  221. package/gs/reflect/function-types.test.ts +6 -6
  222. package/gs/reflect/sliceat.test.ts +13 -13
  223. package/gs/reflect/structof.test.ts +4 -4
  224. package/gs/reflect/type.ts +34 -14
  225. package/gs/reflect/typefor.test.ts +5 -5
  226. package/gs/runtime/pprof/index.test.ts +20 -0
  227. package/gs/runtime/trace/index.test.ts +3 -0
  228. package/gs/slices/slices.test.ts +31 -0
  229. package/gs/slices/slices.ts +11 -11
  230. package/gs/strconv/append.test.ts +99 -0
  231. package/gs/strconv/atof.gs.ts +156 -42
  232. package/gs/strconv/atof.test.ts +45 -0
  233. package/gs/strconv/atoi.gs.ts +87 -69
  234. package/gs/strconv/atoi.test.ts +49 -0
  235. package/gs/strconv/ftoa.gs.ts +85 -10
  236. package/gs/strconv/ftoa.test.ts +43 -0
  237. package/gs/strconv/itoa.gs.ts +10 -9
  238. package/gs/strconv/quote.gs.ts +335 -108
  239. package/gs/strconv/quote.test.ts +111 -0
  240. package/gs/strings/reader.test.ts +10 -10
  241. package/gs/strings/reader.ts +9 -9
  242. package/gs/strings/strings.test.ts +18 -5
  243. package/gs/strings/strings.ts +81 -68
  244. package/gs/sync/atomic/doc_64.gs.ts +24 -24
  245. package/gs/sync/atomic/doc_64.test.ts +5 -5
  246. package/gs/sync/atomic/type.gs.ts +28 -28
  247. package/gs/sync/sync.test.ts +109 -1
  248. package/gs/sync/sync.ts +46 -12
  249. package/gs/syscall/fs.ts +8 -8
  250. package/gs/syscall/net.test.ts +1 -1
  251. package/gs/time/parse.test.ts +45 -0
  252. package/gs/time/time.test.ts +46 -23
  253. package/gs/time/time.ts +69 -66
  254. package/gs/unicode/gen.go +198 -0
  255. package/gs/unicode/tables.ts +646 -0
  256. package/gs/unicode/unicode.test.ts +69 -0
  257. package/gs/unicode/unicode.ts +396 -312
  258. package/package.json +2 -2
  259. package/dist/gs/github.com/aperturerobotics/util/conc/index.d.ts +0 -20
  260. package/dist/gs/github.com/aperturerobotics/util/conc/index.js +0 -134
  261. package/dist/gs/github.com/aperturerobotics/util/conc/index.js.map +0 -1
  262. package/gs/github.com/aperturerobotics/util/conc/index.test.ts +0 -30
  263. package/gs/github.com/aperturerobotics/util/conc/index.ts +0 -172
  264. package/gs/github.com/aperturerobotics/util/conc/meta.json +0 -9
@@ -0,0 +1,32 @@
1
+ import { ErrBadPattern, Match } from './index.js'
2
+ import { describe, expect, test } from 'vitest'
3
+
4
+ describe('path.Match', () => {
5
+ test('star consumes the run up to but not including a slash', () => {
6
+ // Go: path.Match("*/c", "a/c") => (true, nil). The star matches "a" and
7
+ // the literal "/c" matches the remainder.
8
+ expect(Match('*/c', 'a/c')).toEqual([true, null])
9
+ // Go: a star still cannot cross a slash.
10
+ expect(Match('*c', 'a/c')).toEqual([false, null])
11
+ // Go: path.Match("a*b", "axxb") => (true, nil).
12
+ expect(Match('a*b', 'axxb')).toEqual([true, null])
13
+ })
14
+
15
+ test('unterminated character class reports ErrBadPattern', () => {
16
+ // Go: an escape that consumes the last rune of the class returns
17
+ // ErrBadPattern rather than indexing past the end of the chunk.
18
+ const [ok, err] = Match('[a', 'x')
19
+ expect(ok).toBe(false)
20
+ expect(err).toBe(ErrBadPattern)
21
+
22
+ const [ok2, err2] = Match('[', 'a')
23
+ expect(ok2).toBe(false)
24
+ expect(err2).toBe(ErrBadPattern)
25
+ })
26
+
27
+ test('well-formed character class still matches', () => {
28
+ // Go: path.Match("[a-c]", "b") => (true, nil).
29
+ expect(Match('[a-c]', 'b')).toEqual([true, null])
30
+ expect(Match('[^a-c]', 'b')).toEqual([false, null])
31
+ })
32
+ })
package/gs/path/match.ts CHANGED
@@ -78,7 +78,7 @@ export function Match(pattern: string, name: string): [boolean, $.GoError] {
78
78
  for (let i = 0; i < $.len(name) && $.indexString(name, i) != 47; i++) {
79
79
  let [t, ok, err] = matchChunk(
80
80
  chunk,
81
- $.sliceString(name, i, undefined),
81
+ $.sliceString(name, i + 1, undefined),
82
82
  )
83
83
 
84
84
  // if we're the last chunk, make sure we exhausted the name
@@ -300,8 +300,11 @@ export function getEsc(chunk: string): [number, string, $.GoError] {
300
300
  return [0, '', ErrBadPattern]
301
301
  }
302
302
  chunk = $.sliceString(chunk, n, undefined)
303
- if ($.len(chunk) == 0 || $.indexString(chunk, 0) != 45 || $.len(chunk) == 1) {
304
- return [r, chunk, null]
303
+ // An escape that consumes the last rune of the class leaves no terminator,
304
+ // so the pattern is malformed (Go reports ErrBadPattern instead of indexing
305
+ // past the end of the chunk).
306
+ if ($.len(chunk) == 0) {
307
+ return [r, chunk, ErrBadPattern]
305
308
  }
306
309
  return [r, chunk, null]
307
310
  }
@@ -45,6 +45,6 @@ describe('DeepEqual', () => {
45
45
  new BasicType(Uint32, 'uint32'),
46
46
  )
47
47
 
48
- expect(v.Uint()).toBe(7)
48
+ expect(v.Uint()).toBe(7n)
49
49
  })
50
50
  })
@@ -63,7 +63,7 @@ describe('reflect struct field access', () => {
63
63
  ValueOf(person)
64
64
  .FieldByIndex(arrayToSlice([1]))
65
65
  .Int(),
66
- ).toBe(3)
66
+ ).toBe(3n)
67
67
  expect(ValueOf(person).FieldByName('Missing').IsValid()).toBe(false)
68
68
 
69
69
  const stringMethod = ValueOf(person).MethodByName('String')
@@ -358,7 +358,7 @@ describe('Function Type Detection', () => {
358
358
  })
359
359
  const tupleResult = asArray(await ValueOf(tupleFunc).Call(arrayToSlice([])))
360
360
  expect(tupleResult).toHaveLength(2)
361
- expect(tupleResult[0].Int()).toBe(1)
361
+ expect(tupleResult[0].Int()).toBe(1n)
362
362
  expect(tupleResult[1].String()).toBe('ok')
363
363
 
364
364
  const sliceFunc = functionValue(() => [1, 2], {
@@ -384,7 +384,7 @@ describe('Function Type Detection', () => {
384
384
  await ValueOf(namedResultFunc).Call(arrayToSlice([])),
385
385
  )
386
386
  expect(namedResult[0].Type().String()).toBe('main.MyInt')
387
- expect(namedResult[0].Int()).toBe(7)
387
+ expect(namedResult[0].Int()).toBe(7n)
388
388
 
389
389
  const badTupleFunc = functionValue(() => [1], {
390
390
  kind: TypeKind.Function,
@@ -459,7 +459,7 @@ describe('Function Type Detection', () => {
459
459
  )()
460
460
  expect(tuple).toEqual([3, true])
461
461
  const reflectedTuple = asArray(await tupleValue.Call(arrayToSlice([])))
462
- expect(reflectedTuple[0].Int()).toBe(3)
462
+ expect(reflectedTuple[0].Int()).toBe(3n)
463
463
  expect(reflectedTuple[1].Bool()).toBe(true)
464
464
 
465
465
  const zeroType = FuncOf(arrayToSlice([]), arrayToSlice([]), false)
@@ -481,7 +481,7 @@ describe('Function Type Detection', () => {
481
481
  const variadicValue = MakeFunc(variadicType, (args) => {
482
482
  const values = asArray(args)
483
483
  expect(values).toHaveLength(2)
484
- return arrayToSlice([ValueOf(values[0].Int() + values[1].Len())])
484
+ return arrayToSlice([ValueOf(Number(values[0].Int()) + values[1].Len())])
485
485
  })
486
486
  const variadic = variadicValue.Interface() as (
487
487
  prefix: number,
@@ -493,13 +493,13 @@ describe('Function Type Detection', () => {
493
493
  arrayToSlice([ValueOf(10), ValueOf('a'), ValueOf('b')]),
494
494
  ),
495
495
  )
496
- expect(reflectedVariadic[0].Int()).toBe(12)
496
+ expect(reflectedVariadic[0].Int()).toBe(12n)
497
497
  const reflectedSliceCall = asArray(
498
498
  await variadicValue.CallSlice(
499
499
  arrayToSlice([ValueOf(10), ValueOf(arrayToSlice(['a', 'b', 'c']))]),
500
500
  ),
501
501
  )
502
- expect(reflectedSliceCall[0].Int()).toBe(13)
502
+ expect(reflectedSliceCall[0].Int()).toBe(13n)
503
503
 
504
504
  const badResult = MakeFunc(unaryType, () => arrayToSlice([]))
505
505
  await expect(
@@ -19,18 +19,18 @@ describe('reflect owned pointer handles', () => {
19
19
  const values = [1, 2, 3]
20
20
  const element = ValueOf(values).Index(1)
21
21
 
22
- element.SetInt(8)
22
+ element.SetInt(8n)
23
23
  expect(values).toEqual([1, 8, 3])
24
24
 
25
25
  const address = element.UnsafeAddr()
26
26
  expect($.isOwnedPointerHandle(address)).toBe(true)
27
27
 
28
28
  const pointer = NewAt(element.Type(), address as any)
29
- pointer.Elem().SetInt(11)
29
+ pointer.Elem().SetInt(11n)
30
30
  expect(values).toEqual([1, 11, 3])
31
31
 
32
32
  const refPointer = NewAt(element.Type(), $.indexRef(values, 1) as any)
33
- refPointer.Elem().SetInt(14)
33
+ refPointer.Elem().SetInt(14n)
34
34
  expect(values).toEqual([1, 14, 3])
35
35
  })
36
36
 
@@ -38,14 +38,14 @@ describe('reflect owned pointer handles', () => {
38
38
  const bytes = new Uint8Array([4, 5, 6])
39
39
  const element = ValueOf(bytes).Index(1)
40
40
 
41
- element.SetUint(9)
41
+ element.SetUint(9n)
42
42
  expect(Array.from(bytes)).toEqual([4, 9, 6])
43
43
 
44
44
  const address = element.UnsafeAddr()
45
45
  expect($.isOwnedPointerHandle(address)).toBe(true)
46
46
 
47
47
  const pointer = NewAt(element.Type(), address as any)
48
- pointer.Elem().SetUint(12)
48
+ pointer.Elem().SetUint(12n)
49
49
  expect(Array.from(bytes)).toEqual([4, 12, 6])
50
50
  })
51
51
 
@@ -54,14 +54,14 @@ describe('reflect owned pointer handles', () => {
54
54
  const arrayValue = new Value(values, ArrayOf(2, TypeOf(0)))
55
55
  const element = arrayValue.Index(0)
56
56
 
57
- element.SetInt(7)
57
+ element.SetInt(7n)
58
58
  expect(values).toEqual([7, 2])
59
59
 
60
60
  const address = element.UnsafeAddr()
61
61
  expect($.isOwnedPointerHandle(address)).toBe(true)
62
62
 
63
63
  const pointer = NewAt(element.Type(), address as any)
64
- pointer.Elem().SetInt(13)
64
+ pointer.Elem().SetInt(13n)
65
65
  expect(values).toEqual([13, 2])
66
66
  })
67
67
 
@@ -71,13 +71,13 @@ describe('reflect owned pointer handles', () => {
71
71
 
72
72
  NewAt(intType, local as any)
73
73
  .Elem()
74
- .SetInt(4)
74
+ .SetInt(4n)
75
75
  expect(local.value).toBe(4)
76
76
 
77
77
  const target = { count: 2 }
78
78
  NewAt(intType, $.fieldRef(target, 'count') as any)
79
79
  .Elem()
80
- .SetInt(5)
80
+ .SetInt(5n)
81
81
  expect(target.count).toBe(5)
82
82
 
83
83
  expect(() => SliceAt(intType, local as any, 1)).toThrow(
@@ -107,8 +107,8 @@ describe('reflect owned pointer handles', () => {
107
107
  expect(slice.Cap()).toBe(2)
108
108
  expect(slice.Pointer()).toBe($.indexAddress(values, 1))
109
109
 
110
- slice.Index(0).SetInt(21)
111
- slice.Index(1).SetInt(31)
110
+ slice.Index(0).SetInt(21n)
111
+ slice.Index(1).SetInt(31n)
112
112
  expect(values).toEqual([10, 21, 31, 40])
113
113
  })
114
114
 
@@ -123,8 +123,8 @@ describe('reflect owned pointer handles', () => {
123
123
  expect(slice.Cap()).toBe(2)
124
124
  expect(slice.Pointer()).toBe($.indexAddress(bytes, 1))
125
125
 
126
- slice.Index(0).SetUint(7)
127
- slice.Index(1).SetUint(8)
126
+ slice.Index(0).SetUint(7n)
127
+ slice.Index(1).SetUint(8n)
128
128
  expect(Array.from(bytes)).toEqual([1, 7, 8, 4])
129
129
  })
130
130
 
@@ -41,7 +41,7 @@ describe('StructOf', () => {
41
41
 
42
42
  const value = New(typ).Elem()
43
43
  value.Field(0).SetString('Ada')
44
- value.FieldByName('Count').SetInt(3)
44
+ value.FieldByName('Count').SetInt(3n)
45
45
 
46
46
  const [data, err] = Marshal(value.Interface())
47
47
  expect(err).toBeNull()
@@ -51,7 +51,7 @@ describe('StructOf', () => {
51
51
  expect(TypeOf(clone).String()).toBe(typ.String())
52
52
  expect(clone.Name).toBe('Ada')
53
53
  expect(clone.Count).toBe(3)
54
- value.FieldByName('Count').SetInt(4)
54
+ value.FieldByName('Count').SetInt(4n)
55
55
  expect(clone.Count).toBe(3)
56
56
  })
57
57
 
@@ -348,9 +348,9 @@ describe('StructOf', () => {
348
348
  ])
349
349
 
350
350
  const value = New(outer).Elem()
351
- value.FieldByIndex($.arrayToSlice([0, 0])).SetInt(7)
351
+ value.FieldByIndex($.arrayToSlice([0, 0])).SetInt(7n)
352
352
  value.FieldByName('Label').SetString('seven')
353
- expect(value.FieldByName('ID').Int()).toBe(7)
353
+ expect(value.FieldByName('ID').Int()).toBe(7n)
354
354
  expect(value.FieldByIndex($.arrayToSlice([0, 1])).String()).toBe('seven')
355
355
  })
356
356
 
@@ -587,9 +587,24 @@ export class Value {
587
587
  }
588
588
 
589
589
  // Methods required by godoc.txt and used throughout the codebase
590
- public Int(): number {
590
+
591
+ // integerValue reads the underlying value as a bigint regardless of whether it
592
+ // is stored as a number (int8..int32/uint8..uint32) or a bigint (int64/uint64).
593
+ private integerValue(): bigint | null {
594
+ if (typeof this._value === 'bigint') {
595
+ return this._value
596
+ }
591
597
  const value = this.numericValue()
592
598
  if (value !== null && Number.isInteger(value)) {
599
+ return BigInt(value)
600
+ }
601
+ return null
602
+ }
603
+
604
+ // Int returns v's underlying value as an int64, matching reflect.Value.Int.
605
+ public Int(): bigint {
606
+ const value = this.integerValue()
607
+ if (value !== null) {
593
608
  return value
594
609
  }
595
610
  throw new Error(
@@ -599,9 +614,10 @@ export class Value {
599
614
  )
600
615
  }
601
616
 
602
- public Uint(): number {
603
- const value = this.numericValue()
604
- if (value !== null && value >= 0) {
617
+ // Uint returns v's underlying value as a uint64, matching reflect.Value.Uint.
618
+ public Uint(): bigint {
619
+ const value = this.integerValue()
620
+ if (value !== null && value >= 0n) {
605
621
  return value
606
622
  }
607
623
  throw new Error(
@@ -1159,8 +1175,9 @@ export class Value {
1159
1175
  }
1160
1176
  }
1161
1177
 
1162
- // SetInt sets v's underlying value to x
1163
- public SetInt(x: number): void {
1178
+ // SetInt sets v's underlying value to x. x is an int64 (bigint); the stored
1179
+ // value uses the field's representation: bigint for Int64, number otherwise.
1180
+ public SetInt(x: bigint): void {
1164
1181
  if (!this.CanSet()) {
1165
1182
  throw new Error(
1166
1183
  'reflect: call of reflect.Value.SetInt on unaddressable value',
@@ -1172,17 +1189,19 @@ export class Value {
1172
1189
  'reflect: call of reflect.Value.SetInt on ' + k + ' Value',
1173
1190
  )
1174
1191
  }
1175
- this._value = x
1192
+ const stored: number | bigint = k === Int64 ? x : Number(x)
1193
+ this._value = stored
1176
1194
  if (this._parentVarRef) {
1177
- this._parentVarRef.value = x
1195
+ this._parentVarRef.value = stored
1178
1196
  }
1179
1197
  if (this._parentStruct && this._fieldName) {
1180
- this._parentStruct[this._fieldName] = x
1198
+ this._parentStruct[this._fieldName] = stored
1181
1199
  }
1182
1200
  }
1183
1201
 
1184
- // SetUint sets v's underlying value to x
1185
- public SetUint(x: number): void {
1202
+ // SetUint sets v's underlying value to x. x is a uint64 (bigint); the stored
1203
+ // value uses the field's representation: bigint for Uint64, number otherwise.
1204
+ public SetUint(x: bigint): void {
1186
1205
  if (!this.CanSet()) {
1187
1206
  throw new Error(
1188
1207
  'reflect: call of reflect.Value.SetUint on unaddressable value',
@@ -1201,12 +1220,13 @@ export class Value {
1201
1220
  'reflect: call of reflect.Value.SetUint on ' + k + ' Value',
1202
1221
  )
1203
1222
  }
1204
- this._value = x
1223
+ const stored: number | bigint = k === Uint64 ? x : Number(x)
1224
+ this._value = stored
1205
1225
  if (this._parentVarRef) {
1206
- this._parentVarRef.value = x
1226
+ this._parentVarRef.value = stored
1207
1227
  }
1208
1228
  if (this._parentStruct && this._fieldName) {
1209
- this._parentStruct[this._fieldName] = x
1229
+ this._parentStruct[this._fieldName] = stored
1210
1230
  }
1211
1231
  }
1212
1232
 
@@ -184,8 +184,8 @@ describe('TypeFor', () => {
184
184
 
185
185
  const elem = ValueOf(boxed).Elem()
186
186
  expect(elem.Kind()).toBe(Uint64)
187
- elem.SetUint(15)
188
- expect(target.value).toBe(15)
187
+ elem.SetUint(15n)
188
+ expect(target.value).toBe(15n)
189
189
  })
190
190
 
191
191
  it('preserves channel type metadata on interface boxes', () => {
@@ -680,9 +680,9 @@ describe('TypeFor', () => {
680
680
  const pointer = New(TypeOf(0))
681
681
  const value = Indirect(pointer)
682
682
 
683
- expect(value.Int()).toBe(0)
684
- value.SetInt(7)
685
- expect(pointer.Elem().Int()).toBe(7)
683
+ expect(value.Int()).toBe(0n)
684
+ value.SetInt(7n)
685
+ expect(pointer.Elem().Int()).toBe(7n)
686
686
  })
687
687
 
688
688
  it('interns runtime type descriptors for reflect.Type map keys', () => {
@@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest'
3
3
  import {
4
4
  Lookup,
5
5
  NewProfile,
6
+ Profiles,
6
7
  StartCPUProfile,
7
8
  StopCPUProfile,
8
9
  WriteHeapProfile,
@@ -61,4 +62,23 @@ describe('runtime/pprof override', () => {
61
62
  'pprof: NewProfile name already in use: goscript.test',
62
63
  )
63
64
  })
65
+
66
+ it('lists built-in and custom profiles', () => {
67
+ const custom =
68
+ Lookup('goscript.profiles') ?? NewProfile('goscript.profiles')
69
+ const profiles = Array.from(Profiles() ?? [])
70
+ const names = profiles.map((profile) => profile?.Name())
71
+
72
+ expect(names).toEqual(
73
+ expect.arrayContaining([
74
+ 'allocs',
75
+ 'block',
76
+ 'goroutine',
77
+ 'heap',
78
+ 'mutex',
79
+ 'threadcreate',
80
+ custom.Name(),
81
+ ]),
82
+ )
83
+ })
64
84
  })
@@ -5,6 +5,7 @@ import * as context from '@goscript/context/index.js'
5
5
  import {
6
6
  IsEnabled,
7
7
  Log,
8
+ Logf,
8
9
  NewTask,
9
10
  Start,
10
11
  StartRegion,
@@ -109,6 +110,7 @@ describe('runtime/trace override', () => {
109
110
  const [ctx, task] = NewTask(context.Background(), 'proof-task')
110
111
  WithRegion(ctx, 'proof-region', () => {
111
112
  Log(ctx, 'proof-key', 'proof-value')
113
+ Logf(ctx, 'proof-format', 'value=%s count=%d', 'ok', 3)
112
114
  })
113
115
  task.End()
114
116
 
@@ -126,6 +128,7 @@ describe('runtime/trace override', () => {
126
128
  expect(text).toContain('proof-task')
127
129
  expect(text).toContain('proof-region')
128
130
  expect(text).toContain('proof-value')
131
+ expect(text).toContain('value=ok count=3')
129
132
  })
130
133
 
131
134
  it('splits a large capture into batches under the size limit', () => {
@@ -13,7 +13,9 @@ import {
13
13
  CompareFunc,
14
14
  Concat,
15
15
  DeleteFunc,
16
+ Equal,
16
17
  EqualFunc,
18
+ Index,
17
19
  IndexFunc,
18
20
  IsSorted,
19
21
  IsSortedFunc,
@@ -27,6 +29,35 @@ import {
27
29
  SortStableFunc,
28
30
  } from './slices.js'
29
31
 
32
+ describe('slices Go comparable equality and lower-bound search', () => {
33
+ // Go compares comparable elements (arrays/structs) by value with ==, and
34
+ // BinarySearch returns the earliest index for duplicate targets.
35
+ it('Compact removes adjacent equal-by-value array elements', () => {
36
+ expect(Array.from(Compact($.arrayToSlice([[1], [1], [2]])) ?? [])).toEqual([
37
+ [1],
38
+ [2],
39
+ ])
40
+ })
41
+
42
+ it('Equal compares array elements by value', () => {
43
+ expect(Equal($.arrayToSlice([[1, 2]]), $.arrayToSlice([[1, 2]]))).toBe(true)
44
+ expect(Equal($.arrayToSlice([[1, 2]]), $.arrayToSlice([[1, 3]]))).toBe(
45
+ false,
46
+ )
47
+ })
48
+
49
+ it('Index finds an equal-by-value array element', () => {
50
+ expect(Index($.arrayToSlice([[1], [2], [3]]), [2])).toBe(1)
51
+ expect(Index($.arrayToSlice([[1], [2]]), [9])).toBe(-1)
52
+ })
53
+
54
+ it('BinarySearch returns the first index of a duplicate target', () => {
55
+ expect(BinarySearch($.arrayToSlice([1, 2, 2, 2, 3]), 2)).toEqual([1, true])
56
+ expect(BinarySearch($.arrayToSlice([1, 2, 2, 2, 3]), 4)).toEqual([5, false])
57
+ expect(BinarySearch($.arrayToSlice([1, 3, 5]), 0)).toEqual([0, false])
58
+ })
59
+ })
60
+
30
61
  describe('slices.SortFunc', () => {
31
62
  it('awaits async comparison callbacks', async () => {
32
63
  const values = $.arrayToSlice([3, 1, 2])
@@ -381,7 +381,7 @@ export function Compact<T>(s: $.Slice<T>): $.Slice<T> {
381
381
  }
382
382
  let w = 1
383
383
  for (let i = 1; i < $.len(s); i++) {
384
- if ((s as any)[i] !== (s as any)[i - 1]) {
384
+ if (!$.comparableEqual((s as any)[i], (s as any)[i - 1])) {
385
385
  ;(s as any)[w] = (s as any)[i]
386
386
  w++
387
387
  }
@@ -432,7 +432,7 @@ export function Equal<T>(s1: $.Slice<T>, s2: $.Slice<T>): boolean {
432
432
  return false
433
433
  }
434
434
  for (let i = 0; i < len1; i++) {
435
- if ((s1 as any)[i] !== (s2 as any)[i]) {
435
+ if (!$.comparableEqual((s1 as any)[i], (s2 as any)[i])) {
436
436
  return false
437
437
  }
438
438
  }
@@ -461,7 +461,7 @@ export function EqualFunc<T, U>(
461
461
 
462
462
  export function Index<T>(s: $.Slice<T>, v: T): number {
463
463
  for (let i = 0; i < $.len(s); i++) {
464
- if ((s as any)[i] === v) {
464
+ if ($.comparableEqual((s as any)[i], v)) {
465
465
  return i
466
466
  }
467
467
  }
@@ -688,23 +688,23 @@ export function BinarySearchFunc<E, T>(
688
688
  if (cmp == null) {
689
689
  throw new Error('slices.BinarySearchFunc: nil comparison function')
690
690
  }
691
+ const n = $.len(x)
691
692
  let left = 0
692
- let right = $.len(x)
693
+ let right = n
693
694
 
695
+ // Lower-bound search: narrow to the earliest index not less than target so
696
+ // duplicate targets return the first match, matching Go's BinarySearchFunc.
694
697
  while (left < right) {
695
698
  const mid = Math.floor((left + right) / 2)
696
- const result = syncNumber(cmp((x as any)[mid] as E, target))
697
-
698
- if (result < 0) {
699
+ if (syncNumber(cmp((x as any)[mid] as E, target)) < 0) {
699
700
  left = mid + 1
700
- } else if (result > 0) {
701
- right = mid
702
701
  } else {
703
- return [mid, true]
702
+ right = mid
704
703
  }
705
704
  }
706
705
 
707
- return [left, false]
706
+ const found = left < n && syncNumber(cmp((x as any)[left] as E, target)) === 0
707
+ return [left, found]
708
708
  }
709
709
 
710
710
  function syncNumber(value: SyncCallbackResult<number>): number {
@@ -0,0 +1,99 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import * as $ from '@goscript/builtin/index.js'
4
+
5
+ import { AppendBool } from './atob.gs.js'
6
+ import { AppendFloat } from './ftoa.gs.js'
7
+ import { AppendInt, AppendUint, FormatUint } from './itoa.gs.js'
8
+ import {
9
+ AppendQuote,
10
+ AppendQuoteRune,
11
+ AppendQuoteRuneToASCII,
12
+ AppendQuoteRuneToGraphic,
13
+ AppendQuoteToASCII,
14
+ AppendQuoteToGraphic,
15
+ IsGraphic,
16
+ IsPrint,
17
+ QuoteRuneToASCII,
18
+ QuoteRuneToGraphic,
19
+ QuotedPrefix,
20
+ QuoteToGraphic,
21
+ } from './quote.gs.js'
22
+
23
+ // Expected outputs are the literal results Go's strconv produces (go1.26.4).
24
+ function appended(dst: $.Bytes): string {
25
+ return $.bytesToString(dst)
26
+ }
27
+
28
+ function prefix(s: string): $.Bytes {
29
+ return $.stringToBytes(s)
30
+ }
31
+
32
+ describe('strconv append/format coverage (Go semantics)', () => {
33
+ it('FormatUint renders in the requested base', () => {
34
+ expect(FormatUint(255, 16)).toBe('ff')
35
+ expect(FormatUint(10, 2)).toBe('1010')
36
+ })
37
+
38
+ it('AppendInt/AppendUint extend the destination buffer', () => {
39
+ expect(appended(AppendInt(prefix('x='), -42, 10))).toBe('x=-42')
40
+ expect(appended(AppendUint(prefix('x='), 255, 16))).toBe('x=ff')
41
+ })
42
+
43
+ it('AppendBool appends true/false', () => {
44
+ expect(appended(AppendBool(prefix('b='), true))).toBe('b=true')
45
+ expect(appended(AppendBool(prefix('b='), false))).toBe('b=false')
46
+ })
47
+
48
+ it('AppendFloat formats with the given verb and precision', () => {
49
+ expect(appended(AppendFloat(prefix('f='), 3.14159, 0x66, 2, 64))).toBe(
50
+ 'f=3.14',
51
+ )
52
+ })
53
+
54
+ it('AppendQuote escapes like Quote', () => {
55
+ expect(appended(AppendQuote(prefix('q='), 'a\tb'))).toBe('q="a\\tb"')
56
+ })
57
+
58
+ it('AppendQuoteToASCII escapes non-ASCII to \\u', () => {
59
+ expect(appended(AppendQuoteToASCII(prefix(''), 'héllo'))).toBe(
60
+ '"h\\u00e9llo"',
61
+ )
62
+ })
63
+
64
+ it('AppendQuoteToGraphic keeps graphic Unicode in place', () => {
65
+ expect(appended(AppendQuoteToGraphic(prefix(''), '背'))).toBe('"背"')
66
+ })
67
+
68
+ it('AppendQuoteRune* quote a single rune', () => {
69
+ expect(appended(AppendQuoteRune(prefix(''), 0x41))).toBe("'A'")
70
+ expect(appended(AppendQuoteRuneToASCII(prefix(''), 0x4e16))).toBe(
71
+ "'\\u4e16'",
72
+ )
73
+ expect(appended(AppendQuoteRuneToGraphic(prefix(''), 0x4e16))).toBe("'世'")
74
+ })
75
+
76
+ it('QuoteToGraphic and QuoteRune variants match Go', () => {
77
+ expect(QuoteToGraphic('背\t')).toBe('"背\\t"')
78
+ expect(QuoteRuneToASCII(0x4e16)).toBe("'\\u4e16'")
79
+ expect(QuoteRuneToGraphic(0x4e16)).toBe("'世'")
80
+ })
81
+
82
+ it('IsPrint and IsGraphic match Go predicates', () => {
83
+ expect(IsPrint(0x41)).toBe(true)
84
+ expect(IsPrint(0x09)).toBe(false)
85
+ expect(IsPrint(0x07)).toBe(false)
86
+ expect(IsGraphic(0x41)).toBe(true)
87
+ expect(IsGraphic(0x20)).toBe(true)
88
+ expect(IsGraphic(0x09)).toBe(false)
89
+ })
90
+
91
+ it('QuotedPrefix returns the leading quoted literal or a syntax error', () => {
92
+ const [p, err] = QuotedPrefix('"abc" tail')
93
+ expect(p).toBe('"abc"')
94
+ expect(err).toBeNull()
95
+ const [p2, err2] = QuotedPrefix('nope')
96
+ expect(p2).toBe('')
97
+ expect(err2).not.toBeNull()
98
+ })
99
+ })