goscript 0.1.4 → 0.2.1

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 (295) hide show
  1. package/README.md +5 -2
  2. package/cmd/go_js_wasm_exec/main.go +201 -0
  3. package/cmd/go_js_wasm_exec/main_test.go +83 -0
  4. package/cmd/goscript/{cmd_compile.go → cmd-compile.go} +7 -0
  5. package/cmd/goscript/cmd-test.go +14 -0
  6. package/cmd/goscript/cmd-test_test.go +1 -1
  7. package/cmd/goscript-wasm/main.go +38 -6
  8. package/compiler/compile-request.go +12 -9
  9. package/compiler/compliance_test.go +0 -1
  10. package/compiler/config.go +2 -0
  11. package/compiler/diagnostic.go +104 -12
  12. package/compiler/diagnostic_test.go +106 -0
  13. package/compiler/gotest/request.go +28 -0
  14. package/compiler/gotest/runner.go +354 -44
  15. package/compiler/gotest/runner_test.go +293 -1
  16. package/compiler/gotest/testdata/browserapi/browserapi_test.go +20 -0
  17. package/compiler/gotest/testdata/browserapi/go.mod +3 -0
  18. package/compiler/index.test.ts +23 -0
  19. package/compiler/lowered-program.go +33 -24
  20. package/compiler/lowering.go +746 -194
  21. package/compiler/lowering_bench_test.go +42 -27
  22. package/compiler/lowering_internal_test.go +18 -0
  23. package/compiler/override-facts.go +15 -0
  24. package/compiler/override-parity-verifier.go +450 -0
  25. package/compiler/override-parity.go +122 -0
  26. package/compiler/override-registry_test.go +559 -0
  27. package/compiler/protobuf-ts-binding.go +567 -0
  28. package/compiler/protobuf-ts-binding_test.go +402 -0
  29. package/compiler/runtime-contract.go +4 -0
  30. package/compiler/runtime-contract_test.go +2 -0
  31. package/compiler/semantic-model-types.go +9 -4
  32. package/compiler/semantic-model.go +282 -70
  33. package/compiler/semantic-model_test.go +82 -1
  34. package/compiler/service.go +21 -1
  35. package/compiler/skeleton_test.go +118 -10
  36. package/compiler/typescript-emitter.go +128 -13
  37. package/compiler/wasm/compile_test.go +37 -4
  38. package/compiler/{wasm_api.go → wasm-api.go} +57 -7
  39. package/dist/gs/builtin/hostio.js +5 -0
  40. package/dist/gs/builtin/hostio.js.map +1 -1
  41. package/dist/gs/builtin/slice.d.ts +13 -2
  42. package/dist/gs/builtin/slice.js +187 -6
  43. package/dist/gs/builtin/slice.js.map +1 -1
  44. package/dist/gs/builtin/type.d.ts +13 -5
  45. package/dist/gs/builtin/type.js +153 -60
  46. package/dist/gs/builtin/type.js.map +1 -1
  47. package/dist/gs/builtin/varRef.d.ts +11 -0
  48. package/dist/gs/builtin/varRef.js +57 -2
  49. package/dist/gs/builtin/varRef.js.map +1 -1
  50. package/dist/gs/bytes/buffer.gs.js +1 -1
  51. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  52. package/dist/gs/bytes/reader.gs.js +1 -1
  53. package/dist/gs/bytes/reader.gs.js.map +1 -1
  54. package/dist/gs/compress/zlib/index.d.ts +10 -3
  55. package/dist/gs/compress/zlib/index.js +50 -16
  56. package/dist/gs/compress/zlib/index.js.map +1 -1
  57. package/dist/gs/encoding/json/index.d.ts +114 -0
  58. package/dist/gs/encoding/json/index.js +544 -36
  59. package/dist/gs/encoding/json/index.js.map +1 -1
  60. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +101 -0
  61. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +589 -0
  62. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  63. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.d.ts +1 -0
  64. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +17 -11
  65. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -1
  66. package/dist/gs/github.com/pkg/errors/errors.js +54 -30
  67. package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
  68. package/dist/gs/go/scanner/index.d.ts +2 -0
  69. package/dist/gs/go/scanner/index.js +29 -5
  70. package/dist/gs/go/scanner/index.js.map +1 -1
  71. package/dist/gs/go/token/index.js +22 -6
  72. package/dist/gs/go/token/index.js.map +1 -1
  73. package/dist/gs/hash/index.d.ts +6 -0
  74. package/dist/gs/hash/index.js +20 -0
  75. package/dist/gs/hash/index.js.map +1 -1
  76. package/dist/gs/internal/byteorder/index.js +2 -2
  77. package/dist/gs/internal/byteorder/index.js.map +1 -1
  78. package/dist/gs/internal/goarch/index.d.ts +43 -3
  79. package/dist/gs/internal/goarch/index.js +42 -10
  80. package/dist/gs/internal/goarch/index.js.map +1 -1
  81. package/dist/gs/io/fs/fs.js +26 -14
  82. package/dist/gs/io/fs/fs.js.map +1 -1
  83. package/dist/gs/io/fs/readdir.js +4 -2
  84. package/dist/gs/io/fs/readdir.js.map +1 -1
  85. package/dist/gs/io/fs/sub.js +8 -1
  86. package/dist/gs/io/fs/sub.js.map +1 -1
  87. package/dist/gs/io/io.d.ts +2 -0
  88. package/dist/gs/io/io.js.map +1 -1
  89. package/dist/gs/math/bits/index.d.ts +5 -0
  90. package/dist/gs/math/bits/index.js +16 -4
  91. package/dist/gs/math/bits/index.js.map +1 -1
  92. package/dist/gs/mime/index.d.ts +16 -0
  93. package/dist/gs/mime/index.js +315 -6
  94. package/dist/gs/mime/index.js.map +1 -1
  95. package/dist/gs/net/http/httptest/index.d.ts +12 -0
  96. package/dist/gs/net/http/httptest/index.js +85 -6
  97. package/dist/gs/net/http/httptest/index.js.map +1 -1
  98. package/dist/gs/net/http/index.d.ts +300 -5
  99. package/dist/gs/net/http/index.js +1598 -58
  100. package/dist/gs/net/http/index.js.map +1 -1
  101. package/dist/gs/os/dir_unix.gs.js +1 -1
  102. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  103. package/dist/gs/os/error.gs.js +1 -1
  104. package/dist/gs/os/error.gs.js.map +1 -1
  105. package/dist/gs/os/exec.gs.d.ts +1 -0
  106. package/dist/gs/os/exec.gs.js +4 -8
  107. package/dist/gs/os/exec.gs.js.map +1 -1
  108. package/dist/gs/os/exec_posix.gs.js +1 -1
  109. package/dist/gs/os/exec_posix.gs.js.map +1 -1
  110. package/dist/gs/os/index.d.ts +1 -1
  111. package/dist/gs/os/index.js +1 -1
  112. package/dist/gs/os/index.js.map +1 -1
  113. package/dist/gs/os/proc.gs.d.ts +4 -0
  114. package/dist/gs/os/proc.gs.js +12 -6
  115. package/dist/gs/os/proc.gs.js.map +1 -1
  116. package/dist/gs/os/root_js.gs.js +1 -1
  117. package/dist/gs/os/root_js.gs.js.map +1 -1
  118. package/dist/gs/os/types.gs.js +1 -1
  119. package/dist/gs/os/types.gs.js.map +1 -1
  120. package/dist/gs/os/types_js.gs.js +1 -1
  121. package/dist/gs/os/types_js.gs.js.map +1 -1
  122. package/dist/gs/os/types_unix.gs.js +1 -1
  123. package/dist/gs/os/types_unix.gs.js.map +1 -1
  124. package/dist/gs/path/path.js +11 -7
  125. package/dist/gs/path/path.js.map +1 -1
  126. package/dist/gs/reflect/index.d.ts +5 -4
  127. package/dist/gs/reflect/index.js +4 -3
  128. package/dist/gs/reflect/index.js.map +1 -1
  129. package/dist/gs/reflect/map.js +15 -0
  130. package/dist/gs/reflect/map.js.map +1 -1
  131. package/dist/gs/reflect/type.d.ts +25 -6
  132. package/dist/gs/reflect/type.js +1475 -228
  133. package/dist/gs/reflect/type.js.map +1 -1
  134. package/dist/gs/reflect/types.d.ts +14 -6
  135. package/dist/gs/reflect/types.js +35 -1
  136. package/dist/gs/reflect/types.js.map +1 -1
  137. package/dist/gs/reflect/value.d.ts +1 -0
  138. package/dist/gs/reflect/value.js +83 -41
  139. package/dist/gs/reflect/value.js.map +1 -1
  140. package/dist/gs/reflect/visiblefields.js +4 -140
  141. package/dist/gs/reflect/visiblefields.js.map +1 -1
  142. package/dist/gs/runtime/pprof/index.d.ts +8 -2
  143. package/dist/gs/runtime/pprof/index.js +50 -30
  144. package/dist/gs/runtime/pprof/index.js.map +1 -1
  145. package/dist/gs/runtime/runtime.js +5 -4
  146. package/dist/gs/runtime/runtime.js.map +1 -1
  147. package/dist/gs/runtime/trace/index.js +5 -19
  148. package/dist/gs/runtime/trace/index.js.map +1 -1
  149. package/dist/gs/strconv/atoi.gs.js +1 -1
  150. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  151. package/dist/gs/strconv/complex.gs.d.ts +3 -0
  152. package/dist/gs/strconv/complex.gs.js +148 -0
  153. package/dist/gs/strconv/complex.gs.js.map +1 -0
  154. package/dist/gs/strconv/index.d.ts +1 -0
  155. package/dist/gs/strconv/index.js +1 -0
  156. package/dist/gs/strconv/index.js.map +1 -1
  157. package/dist/gs/strings/builder.js +1 -1
  158. package/dist/gs/strings/reader.js +9 -5
  159. package/dist/gs/strings/reader.js.map +1 -1
  160. package/dist/gs/strings/replace.js +15 -7
  161. package/dist/gs/strings/replace.js.map +1 -1
  162. package/dist/gs/strings/strings.d.ts +5 -0
  163. package/dist/gs/strings/strings.js +57 -5
  164. package/dist/gs/strings/strings.js.map +1 -1
  165. package/dist/gs/sync/atomic/doc_64.gs.js +7 -6
  166. package/dist/gs/sync/atomic/doc_64.gs.js.map +1 -1
  167. package/dist/gs/sync/atomic/type.gs.js +9 -9
  168. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  169. package/dist/gs/sync/atomic/value.gs.js +2 -2
  170. package/dist/gs/sync/atomic/value.gs.js.map +1 -1
  171. package/dist/gs/syscall/env.js +22 -14
  172. package/dist/gs/syscall/env.js.map +1 -1
  173. package/dist/gs/testing/testing.js +55 -13
  174. package/dist/gs/testing/testing.js.map +1 -1
  175. package/dist/gs/time/time.d.ts +24 -1
  176. package/dist/gs/time/time.js +43 -3
  177. package/dist/gs/time/time.js.map +1 -1
  178. package/dist/gs/unique/index.js +7 -1
  179. package/dist/gs/unique/index.js.map +1 -1
  180. package/go.mod +3 -3
  181. package/go.sum +16 -0
  182. package/gs/builtin/hostio.test.ts +16 -0
  183. package/gs/builtin/hostio.ts +7 -0
  184. package/gs/builtin/runtime-contract.test.ts +246 -21
  185. package/gs/builtin/slice.ts +269 -24
  186. package/gs/builtin/type.ts +226 -59
  187. package/gs/builtin/varRef.ts +85 -2
  188. package/gs/bytes/buffer.gs.ts +1 -1
  189. package/gs/bytes/reader.gs.ts +1 -1
  190. package/gs/compress/zlib/index.test.ts +62 -1
  191. package/gs/compress/zlib/index.ts +53 -16
  192. package/gs/compress/zlib/parity.json +51 -0
  193. package/gs/encoding/json/index.test.ts +360 -6
  194. package/gs/encoding/json/index.ts +679 -38
  195. package/gs/encoding/json/parity.json +81 -0
  196. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +373 -3
  197. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +893 -1
  198. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +18 -0
  199. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +17 -11
  200. package/gs/github.com/pkg/errors/errors.ts +54 -30
  201. package/gs/go/scanner/index.test.ts +39 -56
  202. package/gs/go/scanner/index.ts +33 -5
  203. package/gs/go/scanner/parity.json +27 -0
  204. package/gs/go/token/index.ts +22 -6
  205. package/gs/hash/index.test.ts +20 -33
  206. package/gs/hash/index.ts +28 -0
  207. package/gs/hash/parity.json +21 -0
  208. package/gs/internal/byteorder/index.test.ts +2 -2
  209. package/gs/internal/byteorder/index.ts +2 -2
  210. package/gs/internal/goarch/index.test.ts +32 -0
  211. package/gs/internal/goarch/index.ts +45 -13
  212. package/gs/internal/goarch/parity.json +144 -0
  213. package/gs/io/fs/fs.ts +26 -14
  214. package/gs/io/fs/readdir.ts +4 -4
  215. package/gs/io/fs/sub.ts +8 -1
  216. package/gs/io/io.ts +1 -0
  217. package/gs/io/parity.json +162 -0
  218. package/gs/math/bits/index.test.ts +14 -1
  219. package/gs/math/bits/index.ts +23 -4
  220. package/gs/math/bits/parity.json +156 -0
  221. package/gs/mime/index.test.ts +90 -0
  222. package/gs/mime/index.ts +369 -6
  223. package/gs/mime/parity.json +36 -0
  224. package/gs/net/http/httptest/index.test.ts +98 -2
  225. package/gs/net/http/httptest/index.ts +101 -6
  226. package/gs/net/http/httptest/parity.json +15 -0
  227. package/gs/net/http/index.test.ts +781 -12
  228. package/gs/net/http/index.ts +1860 -139
  229. package/gs/net/http/meta.json +16 -1
  230. package/gs/net/http/parity.json +193 -0
  231. package/gs/os/dir_unix.gs.ts +1 -1
  232. package/gs/os/error.gs.ts +1 -1
  233. package/gs/os/exec.gs.ts +4 -8
  234. package/gs/os/exec_posix.gs.ts +1 -1
  235. package/gs/os/index.test.ts +9 -0
  236. package/gs/os/index.ts +1 -0
  237. package/gs/os/parity.json +9 -0
  238. package/gs/os/proc.gs.ts +18 -5
  239. package/gs/os/proc.test.ts +26 -0
  240. package/gs/os/root_js.gs.ts +1 -1
  241. package/gs/os/types.gs.ts +1 -1
  242. package/gs/os/types_js.gs.ts +1 -1
  243. package/gs/os/types_unix.gs.ts +1 -1
  244. package/gs/path/path.ts +11 -7
  245. package/gs/reflect/field.test.ts +37 -15
  246. package/gs/reflect/function-types.test.ts +518 -22
  247. package/gs/reflect/index.ts +8 -6
  248. package/gs/reflect/map.ts +20 -0
  249. package/gs/reflect/meta.json +6 -4
  250. package/gs/reflect/parity.json +234 -0
  251. package/gs/reflect/sliceat.test.ts +156 -0
  252. package/gs/reflect/structof.test.ts +401 -0
  253. package/gs/reflect/type.ts +1961 -317
  254. package/gs/reflect/typefor.test.ts +530 -10
  255. package/gs/reflect/types.ts +43 -18
  256. package/gs/reflect/value.ts +105 -45
  257. package/gs/reflect/visiblefields.ts +5 -168
  258. package/gs/runtime/parity.json +24 -0
  259. package/gs/runtime/pprof/index.test.ts +29 -7
  260. package/gs/runtime/pprof/index.ts +56 -30
  261. package/gs/runtime/pprof/parity.json +27 -0
  262. package/gs/runtime/runtime.test.ts +3 -1
  263. package/gs/runtime/runtime.ts +4 -3
  264. package/gs/runtime/trace/index.test.ts +5 -3
  265. package/gs/runtime/trace/index.ts +8 -20
  266. package/gs/runtime/trace/parity.json +36 -0
  267. package/gs/strconv/atoi.gs.ts +1 -1
  268. package/gs/strconv/complex.gs.ts +174 -0
  269. package/gs/strconv/complex.test.ts +65 -0
  270. package/gs/strconv/index.ts +1 -0
  271. package/gs/strconv/parity.json +120 -0
  272. package/gs/strings/builder.ts +1 -1
  273. package/gs/strings/parity.json +186 -0
  274. package/gs/strings/reader.ts +9 -5
  275. package/gs/strings/replace.ts +15 -7
  276. package/gs/strings/strings.test.ts +22 -2
  277. package/gs/strings/strings.ts +64 -6
  278. package/gs/sync/atomic/doc_64.gs.ts +6 -7
  279. package/gs/sync/atomic/doc_64.test.ts +43 -0
  280. package/gs/sync/atomic/type.gs.ts +9 -9
  281. package/gs/sync/atomic/value.gs.ts +2 -2
  282. package/gs/syscall/env.ts +29 -14
  283. package/gs/testing/testing.test.ts +67 -0
  284. package/gs/testing/testing.ts +87 -19
  285. package/gs/time/parity.json +225 -0
  286. package/gs/time/time.test.ts +20 -2
  287. package/gs/time/time.ts +49 -7
  288. package/gs/unique/index.ts +7 -1
  289. package/package.json +4 -2
  290. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +0 -217
  291. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +0 -926
  292. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +0 -1
  293. package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +0 -38
  294. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +0 -1361
  295. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +0 -46
@@ -434,11 +434,15 @@ export class Reader {
434
434
  },
435
435
  ],
436
436
  Reader,
437
- {
438
- s: { kind: $.TypeKind.Basic, name: 'string' },
439
- i: { kind: $.TypeKind.Basic, name: 'number' },
440
- prevRune: { kind: $.TypeKind.Basic, name: 'number' },
441
- },
437
+ [
438
+ { name: 's', key: 's', type: { kind: $.TypeKind.Basic, name: 'string' } },
439
+ { name: 'i', key: 'i', type: { kind: $.TypeKind.Basic, name: 'number' } },
440
+ {
441
+ name: 'prevRune',
442
+ key: 'prevRune',
443
+ type: { kind: $.TypeKind.Basic, name: 'number' },
444
+ },
445
+ ],
442
446
  )
443
447
  }
444
448
 
@@ -205,14 +205,22 @@ export class Replacer {
205
205
  },
206
206
  ],
207
207
  Replacer,
208
- {
209
- built: { kind: $.TypeKind.Basic, name: 'boolean' },
210
- r: 'replacer',
211
- oldnew: {
212
- kind: $.TypeKind.Slice,
213
- elemType: { kind: $.TypeKind.Basic, name: 'string' },
208
+ [
209
+ {
210
+ name: 'built',
211
+ key: 'built',
212
+ type: { kind: $.TypeKind.Basic, name: 'boolean' },
214
213
  },
215
- },
214
+ { name: 'r', key: 'r', type: 'replacer' },
215
+ {
216
+ name: 'oldnew',
217
+ key: 'oldnew',
218
+ type: {
219
+ kind: $.TypeKind.Slice,
220
+ elemType: { kind: $.TypeKind.Basic, name: 'string' },
221
+ },
222
+ },
223
+ ],
216
224
  )
217
225
  }
218
226
 
@@ -1,5 +1,6 @@
1
1
  import { describe, it, expect } from 'vitest'
2
2
  import * as $ from '../builtin/index.js'
3
+ import * as unicode from '../unicode/unicode.js'
3
4
  import {
4
5
  Clone,
5
6
  Compare,
@@ -36,8 +37,12 @@ import {
36
37
  SplitN,
37
38
  Title,
38
39
  ToLower,
40
+ ToLowerSpecial,
39
41
  ToTitle,
42
+ ToTitleSpecial,
40
43
  ToUpper,
44
+ ToUpperSpecial,
45
+ ToValidUTF8,
41
46
  Trim,
42
47
  TrimFunc,
43
48
  TrimLeft,
@@ -390,8 +395,8 @@ describe('strings', () => {
390
395
 
391
396
  describe('ToTitle', () => {
392
397
  it('should convert to title case', () => {
393
- expect(ToTitle('hello world')).toBe('Hello World')
394
- expect(ToTitle('HELLO WORLD')).toBe('Hello World')
398
+ expect(ToTitle('hello world')).toBe('HELLO WORLD')
399
+ expect(ToTitle('HELLO WORLD')).toBe('HELLO WORLD')
395
400
  expect(ToTitle('')).toBe('')
396
401
  })
397
402
  })
@@ -404,6 +409,21 @@ describe('strings', () => {
404
409
  })
405
410
  })
406
411
 
412
+ describe('special casing and UTF-8 cleanup', () => {
413
+ it('should expose special-case string helpers', () => {
414
+ expect(ToUpperSpecial([], 'hello')).toBe('HELLO')
415
+ expect(ToLowerSpecial([], 'HELLO')).toBe('hello')
416
+ expect(ToTitleSpecial([], 'hello world')).toBe('HELLO WORLD')
417
+ expect(ToUpperSpecial(unicode.TurkishCase, 'iki')).toBe('İKİ')
418
+ expect(ToLowerSpecial(unicode.TurkishCase, 'Iİ')).toBe('ıi')
419
+ expect(ToTitleSpecial(unicode.TurkishCase, 'iki')).toBe('İKİ')
420
+ })
421
+
422
+ it('should preserve valid replacement runes', () => {
423
+ expect(ToValidUTF8('a\uFFFDb', '?')).toBe('a\uFFFDb')
424
+ })
425
+ })
426
+
407
427
  describe('Trim', () => {
408
428
  it('should trim cutset from both ends', () => {
409
429
  expect(Trim('!hello!', '!')).toBe('hello')
@@ -1,4 +1,5 @@
1
1
  import * as $ from '@goscript/builtin/index.js'
2
+ import * as unicode from '@goscript/unicode/index.js'
2
3
 
3
4
  // Count counts the number of non-overlapping instances of substr in s.
4
5
  // If substr is an empty string, Count returns 1 + the number of Unicode code points in s.
@@ -355,14 +356,76 @@ export function ToUpper(s: string): string {
355
356
  return s.toUpperCase()
356
357
  }
357
358
 
359
+ export function ToUpperSpecial(c: unicode.SpecialCase, s: string): string {
360
+ if (isTurkishCase(c)) {
361
+ return mapTurkishCase(s, 'upper')
362
+ }
363
+ return ToUpper(s)
364
+ }
365
+
358
366
  // ToLower returns s with all Unicode letters mapped to their lower case.
359
367
  export function ToLower(s: string): string {
360
368
  return s.toLowerCase()
361
369
  }
362
370
 
371
+ export function ToLowerSpecial(c: unicode.SpecialCase, s: string): string {
372
+ if (isTurkishCase(c)) {
373
+ return mapTurkishCase(s, 'lower')
374
+ }
375
+ return ToLower(s)
376
+ }
377
+
363
378
  // ToTitle returns a copy of the string s with all Unicode letters mapped to their Unicode title case.
364
379
  export function ToTitle(s: string): string {
365
- // JavaScript doesn't have a direct toTitleCase, so we'll use a simple approximation
380
+ return s.toUpperCase()
381
+ }
382
+
383
+ export function ToTitleSpecial(c: unicode.SpecialCase, s: string): string {
384
+ if (isTurkishCase(c)) {
385
+ return mapTurkishCase(s, 'upper')
386
+ }
387
+ return ToTitle(s)
388
+ }
389
+
390
+ function isTurkishCase(c: unicode.SpecialCase): boolean {
391
+ return c === unicode.TurkishCase || c === unicode.AzeriCase
392
+ }
393
+
394
+ function mapTurkishCase(s: string, mode: 'upper' | 'lower'): string {
395
+ let out = ''
396
+ for (const char of s) {
397
+ if (mode === 'upper') {
398
+ if (char === 'i') {
399
+ out += 'İ'
400
+ continue
401
+ }
402
+ if (char === 'ı') {
403
+ out += 'I'
404
+ continue
405
+ }
406
+ out += char.toUpperCase()
407
+ continue
408
+ }
409
+ if (char === 'I') {
410
+ out += 'ı'
411
+ continue
412
+ }
413
+ if (char === 'İ') {
414
+ out += 'i'
415
+ continue
416
+ }
417
+ out += char.toLowerCase()
418
+ }
419
+ return out
420
+ }
421
+
422
+ export function ToValidUTF8(s: string, replacement: string): string {
423
+ void replacement
424
+ return s
425
+ }
426
+
427
+ // Title returns a copy of the string s with all Unicode letters that begin words mapped to their Unicode title case.
428
+ export function Title(s: string): string {
366
429
  return s
367
430
  .split(' ')
368
431
  .map((word) =>
@@ -373,11 +436,6 @@ export function ToTitle(s: string): string {
373
436
  .join(' ')
374
437
  }
375
438
 
376
- // Title returns a copy of the string s with all Unicode letters that begin words mapped to their Unicode title case.
377
- export function Title(s: string): string {
378
- return ToTitle(s)
379
- }
380
-
381
439
  // TrimSpace returns a slice of the string s, with all leading and trailing white space removed.
382
440
  export function TrimSpace(s: string): string {
383
441
  return s.trim()
@@ -59,7 +59,7 @@ export function CompareAndSwapUint64(addr: $.VarRef<number> | null, old: number,
59
59
  //go:noescape
60
60
  export function AddInt64(addr: $.VarRef<number> | null, delta: number): number {
61
61
  if (!addr) return 0;
62
- addr.value = addr.value + delta;
62
+ addr.value = $.int64Add(addr.value, delta);
63
63
  return addr.value;
64
64
  }
65
65
 
@@ -72,7 +72,7 @@ export function AddInt64(addr: $.VarRef<number> | null, delta: number): number {
72
72
  //go:noescape
73
73
  export function AddUint64(addr: $.VarRef<number> | null, delta: number): number {
74
74
  if (!addr) return 0;
75
- addr.value = addr.value + delta;
75
+ addr.value = $.uint64Add(addr.value, delta);
76
76
  return addr.value;
77
77
  }
78
78
 
@@ -84,7 +84,7 @@ export function AddUint64(addr: $.VarRef<number> | null, delta: number): number
84
84
  export function AndInt64(addr: $.VarRef<number> | null, mask: number): number {
85
85
  if (!addr) return 0;
86
86
  let old = addr.value;
87
- addr.value = addr.value & mask;
87
+ addr.value = $.int64And(addr.value, mask);
88
88
  return old;
89
89
  }
90
90
 
@@ -96,7 +96,7 @@ export function AndInt64(addr: $.VarRef<number> | null, mask: number): number {
96
96
  export function AndUint64(addr: $.VarRef<number> | null, mask: number): number {
97
97
  if (!addr) return 0;
98
98
  let old = addr.value;
99
- addr.value = addr.value & mask;
99
+ addr.value = $.uint64And(addr.value, mask);
100
100
  return old;
101
101
  }
102
102
 
@@ -108,7 +108,7 @@ export function AndUint64(addr: $.VarRef<number> | null, mask: number): number {
108
108
  export function OrInt64(addr: $.VarRef<number> | null, mask: number): number {
109
109
  if (!addr) return 0;
110
110
  let old = addr.value;
111
- addr.value = addr.value | mask;
111
+ addr.value = $.int64Or(addr.value, mask);
112
112
  return old;
113
113
  }
114
114
 
@@ -120,7 +120,7 @@ export function OrInt64(addr: $.VarRef<number> | null, mask: number): number {
120
120
  export function OrUint64(addr: $.VarRef<number> | null, mask: number): number {
121
121
  if (!addr) return 0;
122
122
  let old = addr.value;
123
- addr.value = addr.value | mask;
123
+ addr.value = $.uint64Or(addr.value, mask);
124
124
  return old;
125
125
  }
126
126
 
@@ -165,4 +165,3 @@ export function StoreUint64(addr: $.VarRef<number> | null, val: number): void {
165
165
  addr.value = val;
166
166
  }
167
167
  }
168
-
@@ -0,0 +1,43 @@
1
+ import { describe, expect, test } from 'vitest'
2
+
3
+ import * as $ from '../../builtin/index.js'
4
+ import {
5
+ AddInt64,
6
+ AddUint64,
7
+ AndUint64,
8
+ OrUint64,
9
+ } from './doc_64.gs.js'
10
+
11
+ function asBigInt(value: number): bigint {
12
+ return typeof value === 'bigint' ? value : BigInt(value)
13
+ }
14
+
15
+ describe('sync/atomic 64-bit operations', () => {
16
+ test('adds uint64 values without mixing number and bigint arithmetic', () => {
17
+ const value = $.varRef($.uint('18446744073709551614', 64))
18
+
19
+ expect(AddUint64(value, $.uint(2, 64))).toBe(0)
20
+ expect(value.value).toBe(0)
21
+ })
22
+
23
+ test('preserves high uint64 bits for bitwise operations', () => {
24
+ const value = $.varRef($.uint('9223372036854775808', 64))
25
+
26
+ expect(asBigInt(OrUint64(value, $.uint(1, 64)))).toBe(
27
+ 9223372036854775808n,
28
+ )
29
+ expect(asBigInt(value.value)).toBe(9223372036854775809n)
30
+
31
+ expect(asBigInt(AndUint64(value, $.uint('18446744073709551614', 64)))).toBe(
32
+ 9223372036854775809n,
33
+ )
34
+ expect(asBigInt(value.value)).toBe(9223372036854775808n)
35
+ })
36
+
37
+ test('adds int64 values without number coercion', () => {
38
+ const value = $.varRef($.int('9223372036854775807', 64))
39
+
40
+ expect(AddInt64(value, 1)).toBe(-9223372036854775808)
41
+ expect(value.value).toBe(-9223372036854775808)
42
+ })
43
+ })
@@ -62,7 +62,7 @@ export class Bool {
62
62
  new Bool(),
63
63
  [{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Basic, name: "boolean" } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Basic, name: "boolean" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Basic, name: "boolean" } }, { name: "new", type: { kind: $.TypeKind.Basic, name: "boolean" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }],
64
64
  Bool,
65
- {"v": { kind: $.TypeKind.Basic, name: "number" }}
65
+ [{ name: "v", key: "v", type: { kind: $.TypeKind.Basic, name: "number" } }]
66
66
  );
67
67
  }
68
68
 
@@ -138,7 +138,7 @@ export class Pointer<T> {
138
138
  new Pointer(),
139
139
  [{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Pointer, elemType: { kind: $.TypeKind.Interface, methods: [] } } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Pointer, elemType: { kind: $.TypeKind.Interface, methods: [] } } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Pointer, elemType: { kind: $.TypeKind.Interface, methods: [] } } }], returns: [{ type: { kind: $.TypeKind.Pointer, elemType: { kind: $.TypeKind.Interface, methods: [] } } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Pointer, elemType: { kind: $.TypeKind.Interface, methods: [] } } }, { name: "new", type: { kind: $.TypeKind.Pointer, elemType: { kind: $.TypeKind.Interface, methods: [] } } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }],
140
140
  Pointer,
141
- {"v": { kind: $.TypeKind.Basic, name: "Pointer" }}
141
+ [{ name: "v", key: "v", type: { kind: $.TypeKind.Basic, name: "Pointer" } }]
142
142
  );
143
143
  }
144
144
 
@@ -218,7 +218,7 @@ export class Int32 {
218
218
  new Int32(),
219
219
  [{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Basic, name: "number" } }, { name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }, { name: "Add", args: [{ name: "delta", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "And", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Or", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }],
220
220
  Int32,
221
- {"v": { kind: $.TypeKind.Basic, name: "number" }}
221
+ [{ name: "v", key: "v", type: { kind: $.TypeKind.Basic, name: "number" } }]
222
222
  );
223
223
  }
224
224
 
@@ -298,7 +298,7 @@ export class Int64 {
298
298
  new Int64(),
299
299
  [{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Basic, name: "number" } }, { name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }, { name: "Add", args: [{ name: "delta", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "And", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Or", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }],
300
300
  Int64,
301
- {"v": { kind: $.TypeKind.Basic, name: "number" }}
301
+ [{ name: "v", key: "v", type: { kind: $.TypeKind.Basic, name: "number" } }]
302
302
  );
303
303
  }
304
304
 
@@ -378,7 +378,7 @@ export class Uint32 {
378
378
  new Uint32(),
379
379
  [{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Basic, name: "number" } }, { name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }, { name: "Add", args: [{ name: "delta", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "And", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Or", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }],
380
380
  Uint32,
381
- {"v": { kind: $.TypeKind.Basic, name: "number" }}
381
+ [{ name: "v", key: "v", type: { kind: $.TypeKind.Basic, name: "number" } }]
382
382
  );
383
383
  }
384
384
 
@@ -458,7 +458,7 @@ export class Uint64 {
458
458
  new Uint64(),
459
459
  [{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Basic, name: "number" } }, { name: "new", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }, { name: "Add", args: [{ name: "delta", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "And", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }, { name: "Or", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "number" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "number" } }] }],
460
460
  Uint64,
461
- {"v": { kind: $.TypeKind.Basic, name: "number" }}
461
+ [{ name: "v", key: "v", type: { kind: $.TypeKind.Basic, name: "number" } }]
462
462
  );
463
463
  }
464
464
 
@@ -538,7 +538,7 @@ export class Uintptr {
538
538
  new Uintptr(),
539
539
  [{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Basic, name: "uintptr" } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Basic, name: "uintptr" } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Basic, name: "uintptr" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "uintptr" } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Basic, name: "uintptr" } }, { name: "new", type: { kind: $.TypeKind.Basic, name: "uintptr" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }, { name: "Add", args: [{ name: "delta", type: { kind: $.TypeKind.Basic, name: "uintptr" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "uintptr" } }] }, { name: "And", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "uintptr" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "uintptr" } }] }, { name: "Or", args: [{ name: "mask", type: { kind: $.TypeKind.Basic, name: "uintptr" } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "uintptr" } }] }],
540
540
  Uintptr,
541
- {"v": { kind: $.TypeKind.Basic, name: "uintptr" }}
541
+ [{ name: "v", key: "v", type: { kind: $.TypeKind.Basic, name: "uintptr" } }]
542
542
  );
543
543
  }
544
544
 
@@ -570,7 +570,7 @@ class noCopy {
570
570
  new noCopy(),
571
571
  [{ name: "Lock", args: [], returns: [] }, { name: "Unlock", args: [], returns: [] }],
572
572
  noCopy,
573
- {}
573
+ []
574
574
  );
575
575
  }
576
576
 
@@ -595,6 +595,6 @@ class align64 {
595
595
  new align64(),
596
596
  [],
597
597
  align64,
598
- {}
598
+ []
599
599
  );
600
600
  }
@@ -96,7 +96,7 @@ export class Value {
96
96
  new Value(),
97
97
  [{ name: "Load", args: [], returns: [{ type: { kind: $.TypeKind.Interface, methods: [] } }] }, { name: "Store", args: [{ name: "val", type: { kind: $.TypeKind.Interface, methods: [] } }], returns: [] }, { name: "Swap", args: [{ name: "new", type: { kind: $.TypeKind.Interface, methods: [] } }], returns: [{ type: { kind: $.TypeKind.Interface, methods: [] } }] }, { name: "CompareAndSwap", args: [{ name: "old", type: { kind: $.TypeKind.Interface, methods: [] } }, { name: "new", type: { kind: $.TypeKind.Interface, methods: [] } }], returns: [{ type: { kind: $.TypeKind.Basic, name: "boolean" } }] }],
98
98
  Value,
99
- {"v": { kind: $.TypeKind.Interface, methods: [] }}
99
+ [{ name: "v", key: "v", type: { kind: $.TypeKind.Interface, methods: [] } }]
100
100
  );
101
101
  }
102
102
 
@@ -143,7 +143,7 @@ class efaceWords {
143
143
  new efaceWords(),
144
144
  [],
145
145
  efaceWords,
146
- {"data": { kind: $.TypeKind.Basic, name: "Pointer" }, "typ": { kind: $.TypeKind.Basic, name: "Pointer" }}
146
+ [{ name: "data", key: "data", type: { kind: $.TypeKind.Basic, name: "Pointer" } }, { name: "typ", key: "typ", type: { kind: $.TypeKind.Basic, name: "Pointer" } }]
147
147
  );
148
148
  }
149
149
 
package/gs/syscall/env.ts CHANGED
@@ -1,47 +1,62 @@
1
1
  import * as $ from '@goscript/builtin/index.js'
2
2
 
3
+ type ProcessEnv = Record<string, string | undefined>
4
+
5
+ interface ProcessLike {
6
+ env?: ProcessEnv
7
+ }
8
+
9
+ function hostEnv(): ProcessEnv | undefined {
10
+ return (globalThis as { process?: ProcessLike }).process?.env
11
+ }
12
+
3
13
  // Environment variable functions using Node.js/browser APIs
4
14
  export function Getenv(key: string): [string, boolean] {
5
- if (typeof process !== 'undefined' && process.env) {
6
- const value = process.env[key]
15
+ const env = hostEnv()
16
+ if (env !== undefined) {
17
+ const value = env[key]
7
18
  return value !== undefined ? [value, true] : ['', false]
8
19
  }
9
20
  return ['', false]
10
21
  }
11
22
 
12
23
  export function Setenv(key: string, value: string): $.GoError {
13
- if (typeof process !== 'undefined' && process.env) {
14
- process.env[key] = value
24
+ const env = hostEnv()
25
+ if (env !== undefined) {
26
+ env[key] = value
15
27
  return null
16
28
  }
17
29
  return { Error: () => 'setenv not supported' }
18
30
  }
19
31
 
20
32
  export function Unsetenv(key: string): $.GoError {
21
- if (typeof process !== 'undefined' && process.env) {
22
- delete process.env[key]
33
+ const env = hostEnv()
34
+ if (env !== undefined) {
35
+ delete env[key]
23
36
  return null
24
37
  }
25
38
  return { Error: () => 'unsetenv not supported' }
26
39
  }
27
40
 
28
41
  export function Clearenv(): void {
29
- if (typeof process !== 'undefined' && process.env) {
30
- for (const key in process.env) {
31
- delete process.env[key]
42
+ const env = hostEnv()
43
+ if (env !== undefined) {
44
+ for (const key in env) {
45
+ delete env[key]
32
46
  }
33
47
  }
34
48
  }
35
49
 
36
50
  export function Environ(): $.Slice<string> {
37
- if (typeof process !== 'undefined' && process.env) {
38
- const env: string[] = []
39
- for (const [key, value] of Object.entries(process.env)) {
51
+ const host = hostEnv()
52
+ if (host !== undefined) {
53
+ const values: string[] = []
54
+ for (const [key, value] of Object.entries(host)) {
40
55
  if (value !== undefined) {
41
- env.push(`${key}=${value}`)
56
+ values.push(`${key}=${value}`)
42
57
  }
43
58
  }
44
- return $.arrayToSlice(env)
59
+ return $.arrayToSlice(values)
45
60
  }
46
61
  return $.arrayToSlice([])
47
62
  }
@@ -108,6 +108,73 @@ describe('testing.T', () => {
108
108
  )
109
109
  })
110
110
 
111
+ it('propagates process exits out of subtests without cleanup', async () => {
112
+ const t = new T('root')
113
+ const exit = { __goscriptExitCode: 7 }
114
+ let cleaned = false
115
+
116
+ await expect(
117
+ t.Run('child', (child) => {
118
+ child.Cleanup(() => {
119
+ cleaned = true
120
+ })
121
+ throw exit
122
+ }),
123
+ ).rejects.toBe(exit)
124
+ expect(cleaned).toBe(false)
125
+ })
126
+
127
+ it('propagates process exits out of subtest cleanups', async () => {
128
+ const t = new T('root')
129
+ const exit = { __goscriptExitCode: 8 }
130
+
131
+ await expect(
132
+ t.Run('child', (child) => {
133
+ child.Cleanup(() => {
134
+ throw exit
135
+ })
136
+ }),
137
+ ).rejects.toBe(exit)
138
+ expect(t.Failed()).toBe(false)
139
+ })
140
+
141
+ it('propagates process exits out of package tests without cleanup', async () => {
142
+ const exit = { __goscriptExitCode: 9 }
143
+ let cleaned = false
144
+
145
+ await expect(
146
+ runTests('example.test/exit', [
147
+ {
148
+ name: 'TestExit',
149
+ fn: (t) => {
150
+ t.Cleanup(() => {
151
+ cleaned = true
152
+ })
153
+ throw exit
154
+ },
155
+ },
156
+ ]),
157
+ ).rejects.toBe(exit)
158
+ expect(cleaned).toBe(false)
159
+ })
160
+
161
+ it('propagates process exits out of package test cleanups', async () => {
162
+ const exit = { __goscriptExitCode: 10 }
163
+
164
+ await expect(
165
+ runTests('example.test/exit-cleanup', [
166
+ {
167
+ name: 'TestExitCleanup',
168
+ fn: (t) => {
169
+ t.Cleanup(() => {
170
+ throw exit
171
+ })
172
+ },
173
+ },
174
+ ]),
175
+ ).rejects.toBe(exit)
176
+ })
177
+
111
178
  it('returns a non-nil context', () => {
112
179
  const t = new T('root')
113
180