goscript 0.1.0 → 0.1.2

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 (495) hide show
  1. package/README.md +267 -255
  2. package/cmd/goscript/cmd-test.go +286 -0
  3. package/cmd/goscript/cmd-test_test.go +76 -0
  4. package/cmd/goscript/cmd_compile.go +9 -0
  5. package/cmd/goscript/main.go +1 -0
  6. package/compiler/build-flags.go +38 -0
  7. package/compiler/compile-request.go +33 -0
  8. package/compiler/compiler.go +1 -1
  9. package/compiler/compliance_test.go +0 -10
  10. package/compiler/config.go +2 -0
  11. package/compiler/gotest/owner.go +24 -0
  12. package/compiler/gotest/package-result.go +69 -0
  13. package/compiler/gotest/request.go +210 -0
  14. package/compiler/gotest/result.go +28 -0
  15. package/compiler/gotest/runner.go +1225 -0
  16. package/compiler/gotest/runner_test.go +1271 -0
  17. package/compiler/gotest/test.go +9 -0
  18. package/compiler/index.test.ts +1 -1
  19. package/compiler/lowered-program.go +80 -21
  20. package/compiler/lowering.go +6754 -602
  21. package/compiler/override-facts.go +357 -0
  22. package/compiler/override-registry.go +52 -190
  23. package/compiler/override-registry_test.go +182 -0
  24. package/compiler/package-graph.go +50 -27
  25. package/compiler/package-graph_test.go +99 -9
  26. package/compiler/package-test-function.go +9 -0
  27. package/compiler/package-test-graph-package.go +40 -0
  28. package/compiler/package-test-graph-variant.go +129 -0
  29. package/compiler/package-test-graph.go +112 -0
  30. package/compiler/package-test-graph_test.go +202 -0
  31. package/compiler/runtime-contract.go +229 -29
  32. package/compiler/runtime-contract_test.go +44 -30
  33. package/compiler/semantic-model-types.go +25 -6
  34. package/compiler/semantic-model.go +819 -74
  35. package/compiler/semantic-model_test.go +104 -0
  36. package/compiler/service.go +10 -4
  37. package/compiler/skeleton_test.go +2777 -524
  38. package/compiler/tsworkspace/owner-process-unix_test.go +72 -0
  39. package/compiler/tsworkspace/owner.go +342 -0
  40. package/compiler/tsworkspace/owner_test.go +93 -0
  41. package/compiler/tsworkspace/result.go +17 -0
  42. package/compiler/tsworkspace/tool-process-other.go +14 -0
  43. package/compiler/tsworkspace/tool-process-unix.go +19 -0
  44. package/compiler/typescript-emitter.go +576 -86
  45. package/compiler/wasm/compile.go +1 -1
  46. package/compiler/wasm/compile_test.go +61 -11
  47. package/compiler/wasm_api.go +172 -7
  48. package/dist/gs/builtin/builtin.d.ts +40 -3
  49. package/dist/gs/builtin/builtin.js +430 -22
  50. package/dist/gs/builtin/builtin.js.map +1 -1
  51. package/dist/gs/builtin/channel.d.ts +32 -10
  52. package/dist/gs/builtin/channel.js +119 -25
  53. package/dist/gs/builtin/channel.js.map +1 -1
  54. package/dist/gs/builtin/defer.d.ts +1 -0
  55. package/dist/gs/builtin/defer.js +12 -2
  56. package/dist/gs/builtin/defer.js.map +1 -1
  57. package/dist/gs/builtin/hostio.d.ts +9 -0
  58. package/dist/gs/builtin/hostio.js +25 -0
  59. package/dist/gs/builtin/hostio.js.map +1 -1
  60. package/dist/gs/builtin/map.js +40 -6
  61. package/dist/gs/builtin/map.js.map +1 -1
  62. package/dist/gs/builtin/print.js.map +1 -1
  63. package/dist/gs/builtin/slice.d.ts +64 -10
  64. package/dist/gs/builtin/slice.js +619 -244
  65. package/dist/gs/builtin/slice.js.map +1 -1
  66. package/dist/gs/builtin/type.d.ts +7 -2
  67. package/dist/gs/builtin/type.js +128 -29
  68. package/dist/gs/builtin/type.js.map +1 -1
  69. package/dist/gs/builtin/varRef.d.ts +7 -0
  70. package/dist/gs/builtin/varRef.js +23 -0
  71. package/dist/gs/builtin/varRef.js.map +1 -1
  72. package/dist/gs/bytes/buffer.gs.js +74 -70
  73. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  74. package/dist/gs/bytes/iter.gs.js +13 -13
  75. package/dist/gs/bytes/iter.gs.js.map +1 -1
  76. package/dist/gs/bytes/reader.gs.js +20 -18
  77. package/dist/gs/bytes/reader.gs.js.map +1 -1
  78. package/dist/gs/compress/zlib/index.d.ts +26 -0
  79. package/dist/gs/compress/zlib/index.js +168 -0
  80. package/dist/gs/compress/zlib/index.js.map +1 -0
  81. package/dist/gs/context/context.d.ts +6 -5
  82. package/dist/gs/context/context.js +17 -12
  83. package/dist/gs/context/context.js.map +1 -1
  84. package/dist/gs/crypto/ecdh/index.d.ts +52 -0
  85. package/dist/gs/crypto/ecdh/index.js +226 -0
  86. package/dist/gs/crypto/ecdh/index.js.map +1 -0
  87. package/dist/gs/crypto/ed25519/index.d.ts +34 -0
  88. package/dist/gs/crypto/ed25519/index.js +160 -0
  89. package/dist/gs/crypto/ed25519/index.js.map +1 -0
  90. package/dist/gs/crypto/internal/constanttime/index.d.ts +4 -0
  91. package/dist/gs/crypto/internal/constanttime/index.js +18 -0
  92. package/dist/gs/crypto/internal/constanttime/index.js.map +1 -0
  93. package/dist/gs/crypto/internal/fips140deps/byteorder/index.d.ts +1 -0
  94. package/dist/gs/crypto/internal/fips140deps/byteorder/index.js +2 -0
  95. package/dist/gs/crypto/internal/fips140deps/byteorder/index.js.map +1 -0
  96. package/dist/gs/crypto/internal/fips140deps/godebug/index.d.ts +1 -0
  97. package/dist/gs/crypto/internal/fips140deps/godebug/index.js +2 -0
  98. package/dist/gs/crypto/internal/fips140deps/godebug/index.js.map +1 -0
  99. package/dist/gs/crypto/rand/index.d.ts +2 -0
  100. package/dist/gs/crypto/rand/index.js +85 -0
  101. package/dist/gs/crypto/rand/index.js.map +1 -1
  102. package/dist/gs/crypto/sha256/index.d.ts +8 -0
  103. package/dist/gs/crypto/sha256/index.js +118 -0
  104. package/dist/gs/crypto/sha256/index.js.map +1 -0
  105. package/dist/gs/crypto/sha512/index.d.ts +14 -0
  106. package/dist/gs/crypto/sha512/index.js +129 -0
  107. package/dist/gs/crypto/sha512/index.js.map +1 -0
  108. package/dist/gs/embed/index.d.ts +7 -0
  109. package/dist/gs/embed/index.js +16 -0
  110. package/dist/gs/embed/index.js.map +1 -0
  111. package/dist/gs/encoding/json/index.d.ts +4 -0
  112. package/dist/gs/encoding/json/index.js +33 -0
  113. package/dist/gs/encoding/json/index.js.map +1 -1
  114. package/dist/gs/errors/errors.d.ts +4 -0
  115. package/dist/gs/errors/errors.js +108 -4
  116. package/dist/gs/errors/errors.js.map +1 -1
  117. package/dist/gs/fmt/fmt.d.ts +4 -4
  118. package/dist/gs/fmt/fmt.js +42 -11
  119. package/dist/gs/fmt/fmt.js.map +1 -1
  120. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +37 -2
  121. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +245 -1
  122. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  123. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.d.ts +189 -0
  124. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +861 -0
  125. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -0
  126. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +217 -0
  127. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +814 -0
  128. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -0
  129. package/dist/gs/github.com/aperturerobotics/util/conc/index.d.ts +20 -0
  130. package/dist/gs/github.com/aperturerobotics/util/conc/index.js +134 -0
  131. package/dist/gs/github.com/aperturerobotics/util/conc/index.js.map +1 -0
  132. package/dist/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.js.map +1 -1
  133. package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.d.ts +3 -0
  134. package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js +50 -0
  135. package/dist/gs/github.com/hack-pad/safejs/internal/catch/index.js.map +1 -0
  136. package/dist/gs/github.com/klauspost/compress/internal/le/index.d.ts +9 -0
  137. package/dist/gs/github.com/klauspost/compress/internal/le/index.js +72 -0
  138. package/dist/gs/github.com/klauspost/compress/internal/le/index.js.map +1 -0
  139. package/dist/gs/github.com/mr-tron/base58/base58/index.d.ts +27 -0
  140. package/dist/gs/github.com/mr-tron/base58/base58/index.js +172 -0
  141. package/dist/gs/github.com/mr-tron/base58/base58/index.js.map +1 -0
  142. package/dist/gs/github.com/zeebo/blake3/internal/consts/index.d.ts +21 -0
  143. package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js +22 -0
  144. package/dist/gs/github.com/zeebo/blake3/internal/consts/index.js.map +1 -0
  145. package/dist/gs/go/internal/scannerhooks/index.d.ts +3 -0
  146. package/dist/gs/go/internal/scannerhooks/index.js +5 -0
  147. package/dist/gs/go/internal/scannerhooks/index.js.map +1 -0
  148. package/dist/gs/go/scanner/index.d.ts +13 -0
  149. package/dist/gs/go/scanner/index.js +35 -0
  150. package/dist/gs/go/scanner/index.js.map +1 -1
  151. package/dist/gs/go/token/index.d.ts +156 -0
  152. package/dist/gs/go/token/index.js +507 -4
  153. package/dist/gs/go/token/index.js.map +1 -1
  154. package/dist/gs/hash/fnv/index.d.ts +57 -0
  155. package/dist/gs/hash/fnv/index.js +299 -0
  156. package/dist/gs/hash/fnv/index.js.map +1 -0
  157. package/dist/gs/hash/index.d.ts +17 -0
  158. package/dist/gs/hash/index.js +94 -0
  159. package/dist/gs/hash/index.js.map +1 -0
  160. package/dist/gs/internal/abi/index.d.ts +4 -0
  161. package/dist/gs/internal/abi/index.js +10 -0
  162. package/dist/gs/internal/abi/index.js.map +1 -1
  163. package/dist/gs/internal/bytealg/index.d.ts +2 -0
  164. package/dist/gs/internal/bytealg/index.js +14 -0
  165. package/dist/gs/internal/bytealg/index.js.map +1 -1
  166. package/dist/gs/internal/byteorder/index.d.ts +8 -2
  167. package/dist/gs/internal/byteorder/index.js +56 -25
  168. package/dist/gs/internal/byteorder/index.js.map +1 -1
  169. package/dist/gs/internal/godebug/index.d.ts +12 -0
  170. package/dist/gs/internal/godebug/index.js +30 -0
  171. package/dist/gs/internal/godebug/index.js.map +1 -0
  172. package/dist/gs/io/fs/index.d.ts +1 -0
  173. package/dist/gs/io/fs/index.js +1 -0
  174. package/dist/gs/io/fs/index.js.map +1 -1
  175. package/dist/gs/io/fs/readlink.d.ts +8 -0
  176. package/dist/gs/io/fs/readlink.js +60 -0
  177. package/dist/gs/io/fs/readlink.js.map +1 -0
  178. package/dist/gs/io/fs/walk.d.ts +3 -3
  179. package/dist/gs/io/fs/walk.js +7 -7
  180. package/dist/gs/io/fs/walk.js.map +1 -1
  181. package/dist/gs/io/io.d.ts +40 -6
  182. package/dist/gs/io/io.js +151 -26
  183. package/dist/gs/io/io.js.map +1 -1
  184. package/dist/gs/iter/iter.d.ts +3 -2
  185. package/dist/gs/iter/iter.js.map +1 -1
  186. package/dist/gs/maps/iter.d.ts +5 -5
  187. package/dist/gs/maps/iter.js +48 -21
  188. package/dist/gs/maps/iter.js.map +1 -1
  189. package/dist/gs/maps/maps.d.ts +6 -6
  190. package/dist/gs/maps/maps.js +1 -1
  191. package/dist/gs/maps/maps.js.map +1 -1
  192. package/dist/gs/math/bits/index.d.ts +13 -4
  193. package/dist/gs/math/bits/index.js +70 -48
  194. package/dist/gs/math/bits/index.js.map +1 -1
  195. package/dist/gs/math/const.gs.d.ts +5 -5
  196. package/dist/gs/math/const.gs.js +4 -4
  197. package/dist/gs/math/const.gs.js.map +1 -1
  198. package/dist/gs/mime/index.d.ts +1 -0
  199. package/dist/gs/mime/index.js +52 -0
  200. package/dist/gs/mime/index.js.map +1 -0
  201. package/dist/gs/net/http/httptest/index.d.ts +30 -0
  202. package/dist/gs/net/http/httptest/index.js +101 -0
  203. package/dist/gs/net/http/httptest/index.js.map +1 -0
  204. package/dist/gs/net/http/index.d.ts +131 -0
  205. package/dist/gs/net/http/index.js +307 -0
  206. package/dist/gs/net/http/index.js.map +1 -0
  207. package/dist/gs/net/http/pprof/index.d.ts +8 -0
  208. package/dist/gs/net/http/pprof/index.js +59 -0
  209. package/dist/gs/net/http/pprof/index.js.map +1 -0
  210. package/dist/gs/os/dir_unix.gs.js +2 -2
  211. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  212. package/dist/gs/os/error.gs.js +9 -7
  213. package/dist/gs/os/error.gs.js.map +1 -1
  214. package/dist/gs/os/types_js.gs.js +95 -15
  215. package/dist/gs/os/types_js.gs.js.map +1 -1
  216. package/dist/gs/path/filepath/match.js +165 -3
  217. package/dist/gs/path/filepath/match.js.map +1 -1
  218. package/dist/gs/path/filepath/path.d.ts +8 -4
  219. package/dist/gs/path/filepath/path.js +192 -8
  220. package/dist/gs/path/filepath/path.js.map +1 -1
  221. package/dist/gs/path/path.d.ts +4 -1
  222. package/dist/gs/path/path.js +16 -4
  223. package/dist/gs/path/path.js.map +1 -1
  224. package/dist/gs/reflect/index.d.ts +4 -3
  225. package/dist/gs/reflect/index.js +3 -2
  226. package/dist/gs/reflect/index.js.map +1 -1
  227. package/dist/gs/reflect/iter.js +2 -2
  228. package/dist/gs/reflect/iter.js.map +1 -1
  229. package/dist/gs/reflect/map.js +29 -0
  230. package/dist/gs/reflect/map.js.map +1 -1
  231. package/dist/gs/reflect/type.d.ts +31 -9
  232. package/dist/gs/reflect/type.js +536 -43
  233. package/dist/gs/reflect/type.js.map +1 -1
  234. package/dist/gs/reflect/types.d.ts +1 -0
  235. package/dist/gs/reflect/types.js +3 -1
  236. package/dist/gs/reflect/types.js.map +1 -1
  237. package/dist/gs/reflect/value.d.ts +4 -1
  238. package/dist/gs/reflect/value.js +39 -1
  239. package/dist/gs/reflect/value.js.map +1 -1
  240. package/dist/gs/reflect/visiblefields.js +1 -1
  241. package/dist/gs/reflect/visiblefields.js.map +1 -1
  242. package/dist/gs/runtime/debug/index.d.ts +41 -0
  243. package/dist/gs/runtime/debug/index.js +66 -0
  244. package/dist/gs/runtime/debug/index.js.map +1 -0
  245. package/dist/gs/runtime/pprof/index.d.ts +20 -0
  246. package/dist/gs/runtime/pprof/index.js +85 -0
  247. package/dist/gs/runtime/pprof/index.js.map +1 -0
  248. package/dist/gs/runtime/runtime.d.ts +35 -3
  249. package/dist/gs/runtime/runtime.js +72 -0
  250. package/dist/gs/runtime/runtime.js.map +1 -1
  251. package/dist/gs/runtime/trace/index.d.ts +19 -0
  252. package/dist/gs/runtime/trace/index.js +64 -0
  253. package/dist/gs/runtime/trace/index.js.map +1 -0
  254. package/dist/gs/slices/slices.d.ts +42 -8
  255. package/dist/gs/slices/slices.js +425 -11
  256. package/dist/gs/slices/slices.js.map +1 -1
  257. package/dist/gs/sort/slice.gs.d.ts +5 -3
  258. package/dist/gs/sort/slice.gs.js +60 -22
  259. package/dist/gs/sort/slice.gs.js.map +1 -1
  260. package/dist/gs/sort/sort.gs.d.ts +4 -4
  261. package/dist/gs/sort/sort.gs.js +11 -8
  262. package/dist/gs/sort/sort.gs.js.map +1 -1
  263. package/dist/gs/strings/builder.d.ts +1 -1
  264. package/dist/gs/strings/builder.js +29 -19
  265. package/dist/gs/strings/builder.js.map +1 -1
  266. package/dist/gs/strings/iter.js +140 -75
  267. package/dist/gs/strings/iter.js.map +1 -1
  268. package/dist/gs/strings/replace.js +2 -2
  269. package/dist/gs/strings/replace.js.map +1 -1
  270. package/dist/gs/strings/strings.js +52 -6
  271. package/dist/gs/strings/strings.js.map +1 -1
  272. package/dist/gs/sync/atomic/type.gs.d.ts +9 -8
  273. package/dist/gs/sync/atomic/type.gs.js +0 -2
  274. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  275. package/dist/gs/sync/sync.d.ts +8 -3
  276. package/dist/gs/sync/sync.js +66 -11
  277. package/dist/gs/sync/sync.js.map +1 -1
  278. package/dist/gs/syscall/constants.d.ts +36 -24
  279. package/dist/gs/syscall/constants.js +12 -0
  280. package/dist/gs/syscall/constants.js.map +1 -1
  281. package/dist/gs/syscall/errors.d.ts +117 -111
  282. package/dist/gs/syscall/errors.js +45 -0
  283. package/dist/gs/syscall/errors.js.map +1 -1
  284. package/dist/gs/syscall/fs.d.ts +37 -0
  285. package/dist/gs/syscall/fs.js +102 -0
  286. package/dist/gs/syscall/fs.js.map +1 -1
  287. package/dist/gs/syscall/js/index.d.ts +90 -0
  288. package/dist/gs/syscall/js/index.js +383 -0
  289. package/dist/gs/syscall/js/index.js.map +1 -0
  290. package/dist/gs/syscall/types.d.ts +26 -1
  291. package/dist/gs/syscall/types.js +45 -1
  292. package/dist/gs/syscall/types.js.map +1 -1
  293. package/dist/gs/testing/index.d.ts +1 -0
  294. package/dist/gs/testing/index.js +2 -0
  295. package/dist/gs/testing/index.js.map +1 -0
  296. package/dist/gs/testing/testing.d.ts +78 -0
  297. package/dist/gs/testing/testing.js +318 -0
  298. package/dist/gs/testing/testing.js.map +1 -0
  299. package/dist/gs/time/time.d.ts +41 -4
  300. package/dist/gs/time/time.js +227 -36
  301. package/dist/gs/time/time.js.map +1 -1
  302. package/dist/gs/unicode/unicode.d.ts +23 -1
  303. package/dist/gs/unicode/unicode.js +79 -10
  304. package/dist/gs/unicode/unicode.js.map +1 -1
  305. package/dist/gs/unicode/utf8/utf8.d.ts +4 -4
  306. package/dist/gs/unicode/utf8/utf8.js +24 -11
  307. package/dist/gs/unicode/utf8/utf8.js.map +1 -1
  308. package/dist/gs/unique/index.d.ts +11 -0
  309. package/dist/gs/unique/index.js +76 -0
  310. package/dist/gs/unique/index.js.map +1 -0
  311. package/go.mod +8 -8
  312. package/go.sum +14 -14
  313. package/gs/builtin/builtin.ts +585 -27
  314. package/gs/builtin/channel.ts +183 -29
  315. package/gs/builtin/defer.ts +13 -2
  316. package/gs/builtin/hostio.test.ts +1 -0
  317. package/gs/builtin/hostio.ts +38 -0
  318. package/gs/builtin/map.ts +46 -6
  319. package/gs/builtin/print.ts +12 -3
  320. package/gs/builtin/runtime-contract.test.ts +383 -10
  321. package/gs/builtin/slice.test.ts +70 -0
  322. package/gs/builtin/slice.ts +785 -265
  323. package/gs/builtin/type.ts +160 -41
  324. package/gs/builtin/varRef.ts +40 -1
  325. package/gs/bytes/buffer.gs.ts +74 -70
  326. package/gs/bytes/iter.gs.ts +13 -14
  327. package/gs/bytes/meta.json +8 -3
  328. package/gs/bytes/reader.gs.ts +20 -19
  329. package/gs/compress/zlib/index.test.ts +28 -0
  330. package/gs/compress/zlib/index.ts +200 -0
  331. package/gs/compress/zlib/meta.json +3 -0
  332. package/gs/context/context.test.ts +71 -0
  333. package/gs/context/context.ts +30 -29
  334. package/gs/crypto/ecdh/index.test.ts +43 -0
  335. package/gs/crypto/ecdh/index.ts +274 -0
  336. package/gs/crypto/ed25519/index.test.ts +41 -0
  337. package/gs/crypto/ed25519/index.ts +238 -0
  338. package/gs/crypto/ed25519/meta.json +13 -0
  339. package/gs/crypto/internal/constanttime/index.test.ts +25 -0
  340. package/gs/crypto/internal/constanttime/index.ts +22 -0
  341. package/gs/crypto/internal/fips140deps/byteorder/index.ts +1 -0
  342. package/gs/crypto/internal/fips140deps/godebug/index.ts +1 -0
  343. package/gs/crypto/rand/index.test.ts +89 -1
  344. package/gs/crypto/rand/index.ts +103 -1
  345. package/gs/crypto/rand/meta.json +4 -1
  346. package/gs/crypto/sha256/index.test.ts +78 -0
  347. package/gs/crypto/sha256/index.ts +150 -0
  348. package/gs/crypto/sha256/meta.json +9 -0
  349. package/gs/crypto/sha512/index.test.ts +31 -0
  350. package/gs/crypto/sha512/index.ts +161 -0
  351. package/gs/crypto/sha512/meta.json +11 -0
  352. package/gs/embed/index.ts +20 -0
  353. package/gs/embed/meta.json +5 -0
  354. package/gs/encoding/json/index.test.ts +39 -3
  355. package/gs/encoding/json/index.ts +45 -3
  356. package/gs/errors/errors.test.ts +85 -0
  357. package/gs/errors/errors.ts +132 -4
  358. package/gs/fmt/fmt.test.ts +3 -1
  359. package/gs/fmt/fmt.ts +55 -19
  360. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +128 -1
  361. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +342 -4
  362. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +180 -0
  363. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +1084 -0
  364. package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +31 -0
  365. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +1233 -0
  366. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +46 -0
  367. package/gs/github.com/aperturerobotics/util/conc/index.test.ts +30 -0
  368. package/gs/github.com/aperturerobotics/util/conc/index.ts +172 -0
  369. package/gs/github.com/aperturerobotics/util/conc/meta.json +9 -0
  370. package/gs/github.com/aperturerobotics/wasivm/wazero/kernel/runtime/browser/browser.ts +1 -4
  371. package/gs/github.com/hack-pad/safejs/internal/catch/index.test.ts +35 -0
  372. package/gs/github.com/hack-pad/safejs/internal/catch/index.ts +65 -0
  373. package/gs/github.com/hack-pad/safejs/internal/catch/meta.json +9 -0
  374. package/gs/github.com/klauspost/compress/internal/le/index.test.ts +37 -0
  375. package/gs/github.com/klauspost/compress/internal/le/index.ts +115 -0
  376. package/gs/github.com/mr-tron/base58/base58/index.test.ts +70 -0
  377. package/gs/github.com/mr-tron/base58/base58/index.ts +231 -0
  378. package/gs/github.com/mr-tron/base58/base58/meta.json +3 -0
  379. package/gs/github.com/zeebo/blake3/internal/consts/index.test.ts +46 -0
  380. package/gs/github.com/zeebo/blake3/internal/consts/index.ts +26 -0
  381. package/gs/go/internal/scannerhooks/index.test.ts +14 -0
  382. package/gs/go/internal/scannerhooks/index.ts +9 -0
  383. package/gs/go/scanner/index.test.ts +22 -0
  384. package/gs/go/scanner/index.ts +47 -0
  385. package/gs/go/token/index.test.ts +47 -1
  386. package/gs/go/token/index.ts +583 -4
  387. package/gs/hash/fnv/index.test.ts +67 -0
  388. package/gs/hash/fnv/index.ts +351 -0
  389. package/gs/hash/fnv/meta.json +3 -0
  390. package/gs/hash/index.test.ts +37 -0
  391. package/gs/hash/index.ts +118 -0
  392. package/gs/hash/meta.json +5 -0
  393. package/gs/internal/abi/index.test.ts +18 -0
  394. package/gs/internal/abi/index.ts +14 -0
  395. package/gs/internal/bytealg/index.test.ts +18 -0
  396. package/gs/internal/bytealg/index.ts +16 -0
  397. package/gs/internal/byteorder/index.test.ts +39 -0
  398. package/gs/internal/byteorder/index.ts +100 -27
  399. package/gs/internal/godebug/index.test.ts +16 -0
  400. package/gs/internal/godebug/index.ts +35 -0
  401. package/gs/io/fs/index.ts +1 -0
  402. package/gs/io/fs/meta.json +5 -0
  403. package/gs/io/fs/readlink.test.ts +43 -0
  404. package/gs/io/fs/readlink.ts +69 -0
  405. package/gs/io/fs/walk.test.ts +61 -0
  406. package/gs/io/fs/walk.ts +17 -9
  407. package/gs/io/io.ts +177 -31
  408. package/gs/io/meta.json +10 -2
  409. package/gs/iter/iter.ts +8 -2
  410. package/gs/maps/iter.ts +75 -26
  411. package/gs/maps/maps.test.ts +23 -0
  412. package/gs/maps/maps.ts +13 -11
  413. package/gs/math/bits/index.test.ts +20 -0
  414. package/gs/math/bits/index.ts +107 -64
  415. package/gs/math/const.gs.test.ts +11 -5
  416. package/gs/math/const.gs.ts +5 -6
  417. package/gs/mime/index.ts +60 -0
  418. package/gs/net/http/httptest/index.test.ts +53 -0
  419. package/gs/net/http/httptest/index.ts +120 -0
  420. package/gs/net/http/index.test.ts +148 -0
  421. package/gs/net/http/index.ts +432 -0
  422. package/gs/net/http/meta.json +6 -0
  423. package/gs/net/http/pprof/index.test.ts +47 -0
  424. package/gs/net/http/pprof/index.ts +65 -0
  425. package/gs/os/dir_unix.gs.ts +2 -3
  426. package/gs/os/error.gs.ts +9 -10
  427. package/gs/os/error.test.ts +41 -0
  428. package/gs/os/file_unix_js.test.ts +55 -0
  429. package/gs/os/tempfile.gs.test.ts +37 -10
  430. package/gs/os/types_js.gs.ts +96 -17
  431. package/gs/path/filepath/match.test.ts +31 -12
  432. package/gs/path/filepath/match.ts +181 -3
  433. package/gs/path/filepath/meta.json +6 -0
  434. package/gs/path/filepath/path.test.ts +80 -0
  435. package/gs/path/filepath/path.ts +244 -11
  436. package/gs/path/path.ts +20 -5
  437. package/gs/reflect/field.test.ts +63 -0
  438. package/gs/reflect/index.ts +5 -1
  439. package/gs/reflect/iter.ts +2 -2
  440. package/gs/reflect/map.test.ts +42 -1
  441. package/gs/reflect/map.ts +39 -0
  442. package/gs/reflect/type.ts +728 -65
  443. package/gs/reflect/typefor.test.ts +100 -0
  444. package/gs/reflect/types.ts +3 -1
  445. package/gs/reflect/value.ts +50 -1
  446. package/gs/reflect/visiblefields.ts +1 -1
  447. package/gs/runtime/debug/index.test.ts +45 -0
  448. package/gs/runtime/debug/index.ts +96 -0
  449. package/gs/runtime/pprof/index.test.ts +36 -0
  450. package/gs/runtime/pprof/index.ts +104 -0
  451. package/gs/runtime/pprof/meta.json +6 -0
  452. package/gs/runtime/runtime.test.ts +19 -0
  453. package/gs/runtime/runtime.ts +98 -3
  454. package/gs/runtime/trace/index.test.ts +45 -0
  455. package/gs/runtime/trace/index.ts +97 -0
  456. package/gs/runtime/trace/meta.json +7 -0
  457. package/gs/slices/meta.json +2 -1
  458. package/gs/slices/slices.test.ts +180 -0
  459. package/gs/slices/slices.ts +502 -15
  460. package/gs/sort/meta.json +7 -0
  461. package/gs/sort/slice.gs.ts +85 -26
  462. package/gs/sort/slice.test.ts +40 -0
  463. package/gs/sort/sort.gs.ts +16 -13
  464. package/gs/strings/builder.test.ts +8 -0
  465. package/gs/strings/builder.ts +33 -20
  466. package/gs/strings/iter.test.ts +5 -7
  467. package/gs/strings/iter.ts +146 -71
  468. package/gs/strings/replace.test.ts +1 -4
  469. package/gs/strings/replace.ts +6 -6
  470. package/gs/strings/strings.test.ts +4 -0
  471. package/gs/strings/strings.ts +54 -6
  472. package/gs/sync/atomic/type.gs.ts +13 -14
  473. package/gs/sync/meta.json +3 -1
  474. package/gs/sync/sync.test.ts +69 -1
  475. package/gs/sync/sync.ts +72 -13
  476. package/gs/syscall/constants.ts +39 -24
  477. package/gs/syscall/errors.ts +165 -112
  478. package/gs/syscall/fs.ts +195 -0
  479. package/gs/syscall/js/index.ts +485 -0
  480. package/gs/syscall/js/meta.json +4 -0
  481. package/gs/syscall/net.test.ts +111 -0
  482. package/gs/syscall/types.ts +63 -2
  483. package/gs/testing/index.ts +1 -0
  484. package/gs/testing/meta.json +5 -0
  485. package/gs/testing/testing.test.ts +146 -0
  486. package/gs/testing/testing.ts +399 -0
  487. package/gs/time/meta.json +2 -2
  488. package/gs/time/time.test.ts +110 -0
  489. package/gs/time/time.ts +309 -57
  490. package/gs/unicode/unicode.test.ts +36 -0
  491. package/gs/unicode/unicode.ts +115 -9
  492. package/gs/unicode/utf8/utf8.test.ts +13 -0
  493. package/gs/unicode/utf8/utf8.ts +28 -16
  494. package/gs/unique/index.ts +98 -0
  495. package/package.json +3 -2
@@ -0,0 +1,1225 @@
1
+ package gotest
2
+
3
+ import (
4
+ "context"
5
+ "encoding/json"
6
+ "os"
7
+ "path/filepath"
8
+ "regexp"
9
+ "slices"
10
+ "strconv"
11
+ "strings"
12
+ "sync"
13
+ "time"
14
+
15
+ "github.com/aperturerobotics/goscript/compiler"
16
+ "github.com/aperturerobotics/goscript/compiler/tsworkspace"
17
+ "github.com/pkg/errors"
18
+ )
19
+
20
+ const combinedRuntimeResultPrefix = "__GOSCRIPT_PACKAGE_RESULT__"
21
+
22
+ // Runner owns GoScript package-test loading, compilation, typecheck, and execution.
23
+ type Runner struct {
24
+ service *compiler.CompileService
25
+ }
26
+
27
+ // NewRunner creates a package-test runner.
28
+ func NewRunner() *Runner {
29
+ return &Runner{service: compiler.NewCompileService()}
30
+ }
31
+
32
+ // Run executes package tests through the GoScript compiler and TypeScript runtime.
33
+ func (r *Runner) Run(ctx context.Context, req *Request) (*Result, error) {
34
+ if r == nil {
35
+ r = NewRunner()
36
+ }
37
+ norm, err := req.normalize()
38
+ if err != nil {
39
+ return nil, err
40
+ }
41
+ r.service = compiler.NewCompileService(norm.OverrideDirs...)
42
+ if norm.Timeout != 0 {
43
+ var cancel context.CancelFunc
44
+ ctx, cancel = context.WithTimeout(ctx, norm.Timeout)
45
+ defer cancel()
46
+ }
47
+ if err := ctx.Err(); err != nil {
48
+ return nil, err
49
+ }
50
+ if norm.WorkDir == "" {
51
+ workRoot := filepath.Join(norm.Dir, ".tmp")
52
+ if err := os.MkdirAll(workRoot, 0o755); err != nil {
53
+ return nil, errors.Wrap(err, "create goscript test work root")
54
+ }
55
+ norm.WorkDir, err = os.MkdirTemp(workRoot, "goscript-test-")
56
+ if err != nil {
57
+ return nil, errors.Wrap(err, "create goscript test work directory")
58
+ }
59
+ }
60
+ if norm.OutputRoot == "" {
61
+ norm.OutputRoot = filepath.Join(norm.WorkDir, "output")
62
+ }
63
+
64
+ result := &Result{
65
+ WorkDir: norm.WorkDir,
66
+ OutputRoot: norm.OutputRoot,
67
+ }
68
+ workspace := tsworkspace.NewOwner(norm.WorkDir, norm.Dir)
69
+
70
+ runPattern, err := compileRunPattern(norm.Run)
71
+ if err != nil {
72
+ diag := compiler.Diagnostic{
73
+ Severity: compiler.DiagnosticSeverityError,
74
+ Code: "goscript/gotest:run-pattern",
75
+ Message: "invalid -run pattern",
76
+ Detail: err.Error(),
77
+ }
78
+ result.Diagnostics = append(result.Diagnostics, diag)
79
+ markAllFailures(result, OwnerPackageGraph, compiler.NewCompileError([]compiler.Diagnostic{diag}).Error())
80
+ return result, nil
81
+ }
82
+
83
+ testGraphReq := &compiler.CompileRequest{
84
+ Patterns: append([]string(nil), norm.Patterns...),
85
+ Dir: norm.Dir,
86
+ OutputPath: norm.OutputRoot,
87
+ BuildFlags: append([]string(nil), norm.BuildFlags...),
88
+ OverrideDirs: append([]string(nil), norm.OverrideDirs...),
89
+ DependencyMode: compiler.DependencyModeRequested,
90
+ RuntimeEmissionMode: compiler.RuntimeEmissionModeEmit,
91
+ Tests: true,
92
+ }
93
+ testGraph, loadDiagnostics := r.service.PackageGraphOwner().LoadTestGraph(ctx, testGraphReq)
94
+ result.Diagnostics = append(result.Diagnostics, loadDiagnostics...)
95
+ result.Packages = packageResults(testGraph, runPattern)
96
+ if diagnosticsHaveErrors(loadDiagnostics) && len(result.Packages) == 0 {
97
+ markAllFailures(result, OwnerPackageGraph, diagnosticsSummary(loadDiagnostics))
98
+ return result, nil
99
+ }
100
+
101
+ outputRoots := r.compilePackageOutputs(ctx, norm, result)
102
+
103
+ if phase := workspace.EnsurePackageJSON(); phase.Failed() {
104
+ markAllFailures(result, OwnerTestRunner, phase.Error)
105
+ return result, nil
106
+ }
107
+ nodeTypesAvailable := tsworkspace.NodeTypesPresent(norm.WorkDir, norm.Dir)
108
+ if phase := workspace.EnsureNodeAmbientTypes(); phase.Failed() {
109
+ markAllFailures(result, OwnerTestRunner, phase.Error)
110
+ return result, nil
111
+ }
112
+ if phase := workspace.WriteFile(tsworkspace.PhaseWorkspace, "tsconfig.json", renderRuntimeTypeScriptProject(norm, outputRoots, nodeTypesAvailable)); phase.Failed() {
113
+ markAllFailures(result, OwnerTestRunner, phase.Error)
114
+ return result, nil
115
+ }
116
+ r.runPackageTools(ctx, norm, workspace, result, outputRoots, nodeTypesAvailable)
117
+ return result, nil
118
+ }
119
+
120
+ func (r *Runner) runPackageTools(
121
+ ctx context.Context,
122
+ req *normalizedRequest,
123
+ workspace *tsworkspace.Owner,
124
+ result *Result,
125
+ outputRoots []string,
126
+ nodeTypesAvailable bool,
127
+ ) {
128
+ indexes := r.preparePackageWorkspaces(req, workspace, result, outputRoots, nodeTypesAvailable)
129
+ if len(indexes) == 0 {
130
+ return
131
+ }
132
+ if len(indexes) == 1 {
133
+ r.runPackageTypeCheckAndRuntime(ctx, req, workspace, result, indexes[0])
134
+ return
135
+ }
136
+ typecheck := workspace.RunTool(ctx, tsworkspace.PhaseTypeCheck, req.WorkDir, "tsgo", "--project", "tsconfig.json")
137
+ if typecheck.Failed() {
138
+ if owner, ok := aggregateTypeCheckFailureOwner(typecheck.Output); ok {
139
+ markTypeCheckFailures(result, owner, processErrorText(typecheck))
140
+ return
141
+ }
142
+ r.runPackageTypeChecksAndRuntimes(ctx, req, workspace, result, indexes)
143
+ return
144
+ }
145
+ for _, idx := range indexes {
146
+ result.Packages[idx].Phases.TypeCheck = PhaseStatusPass
147
+ }
148
+ r.runPackageRuntimes(ctx, req, workspace, result, indexes)
149
+ }
150
+
151
+ func (r *Runner) preparePackageWorkspaces(
152
+ req *normalizedRequest,
153
+ workspace *tsworkspace.Owner,
154
+ result *Result,
155
+ outputRoots []string,
156
+ nodeTypesAvailable bool,
157
+ ) []int {
158
+ var indexes []int
159
+ for idx := range result.Packages {
160
+ if !shouldCompilePackage(result.Packages[idx]) {
161
+ continue
162
+ }
163
+ if r.preparePackageWorkspace(req, workspace, result, outputRoots, nodeTypesAvailable, idx) {
164
+ indexes = append(indexes, idx)
165
+ }
166
+ }
167
+ return indexes
168
+ }
169
+
170
+ func (r *Runner) preparePackageWorkspace(
171
+ req *normalizedRequest,
172
+ workspace *tsworkspace.Owner,
173
+ result *Result,
174
+ outputRoots []string,
175
+ nodeTypesAvailable bool,
176
+ idx int,
177
+ ) bool {
178
+ result.Packages[idx].Phases.Workspace = PhaseStatusPass
179
+ outputRoot := outputRoots[idx]
180
+ runnerFile := packageRunnerFile(idx)
181
+ if phase := workspace.WriteFile(tsworkspace.PhaseWorkspace, runnerFile, renderRunner(result.Packages[idx], req)); phase.Failed() {
182
+ result.Packages[idx].Owner = OwnerTestRunner
183
+ result.Packages[idx].Phases.Workspace = PhaseStatusFail
184
+ result.Packages[idx].Error = phase.Error
185
+ return false
186
+ }
187
+ tsconfigFile := packageTSConfigFile(idx)
188
+ if phase := workspace.WriteFile(tsworkspace.PhaseWorkspace, tsconfigFile, renderTypeScriptProject(req, outputRoot, runnerFile, tsconfigFile, nodeTypesAvailable)); phase.Failed() {
189
+ result.Packages[idx].Owner = OwnerTestRunner
190
+ result.Packages[idx].Phases.Workspace = PhaseStatusFail
191
+ result.Packages[idx].Error = phase.Error
192
+ return false
193
+ }
194
+ return true
195
+ }
196
+
197
+ func (r *Runner) runPackageTypeChecksAndRuntimes(
198
+ ctx context.Context,
199
+ req *normalizedRequest,
200
+ workspace *tsworkspace.Owner,
201
+ result *Result,
202
+ indexes []int,
203
+ ) {
204
+ parallelism := max(req.Parallelism, 1)
205
+ sem := make(chan struct{}, parallelism)
206
+ var wg sync.WaitGroup
207
+ for _, idx := range packageExecutionIndexes(result, indexes) {
208
+ wg.Go(func() {
209
+ select {
210
+ case sem <- struct{}{}:
211
+ defer func() { <-sem }()
212
+ case <-ctx.Done():
213
+ result.Packages[idx].Owner = OwnerTestRunner
214
+ result.Packages[idx].Phases.TypeCheck = PhaseStatusFail
215
+ result.Packages[idx].Error = ctx.Err().Error()
216
+ return
217
+ }
218
+ r.runPackageTypeCheckAndRuntime(ctx, req, workspace, result, idx)
219
+ })
220
+ }
221
+ wg.Wait()
222
+ }
223
+
224
+ func (r *Runner) runPackageTypeCheckAndRuntime(
225
+ ctx context.Context,
226
+ req *normalizedRequest,
227
+ workspace *tsworkspace.Owner,
228
+ result *Result,
229
+ idx int,
230
+ ) {
231
+ if !r.runPackageTypeCheck(ctx, req, workspace, result, idx) {
232
+ return
233
+ }
234
+ r.runPackageRuntime(ctx, req, workspace, result, idx)
235
+ }
236
+
237
+ func (r *Runner) runPackageTypeCheck(
238
+ ctx context.Context,
239
+ req *normalizedRequest,
240
+ workspace *tsworkspace.Owner,
241
+ result *Result,
242
+ idx int,
243
+ ) bool {
244
+ typecheck := workspace.RunTool(ctx, tsworkspace.PhaseTypeCheck, req.WorkDir, "tsgo", "--project", packageTSConfigFile(idx))
245
+ if typecheck.Failed() {
246
+ result.Packages[idx].Owner = classifyProcessOutput(typecheck.Output)
247
+ result.Packages[idx].Phases.TypeCheck = PhaseStatusFail
248
+ result.Packages[idx].Error = processErrorText(typecheck)
249
+ return false
250
+ }
251
+ result.Packages[idx].Phases.TypeCheck = PhaseStatusPass
252
+ return true
253
+ }
254
+
255
+ func (r *Runner) runPackageRuntimes(
256
+ ctx context.Context,
257
+ req *normalizedRequest,
258
+ workspace *tsworkspace.Owner,
259
+ result *Result,
260
+ indexes []int,
261
+ ) {
262
+ if len(indexes) > 1 &&
263
+ (req.RuntimeGroups || req.Parallelism == 1) &&
264
+ r.runCombinedPackageRuntimes(ctx, req, workspace, result, indexes) {
265
+ return
266
+ }
267
+ r.runPackageRuntimesIndividually(ctx, req, workspace, result, indexes)
268
+ }
269
+
270
+ func (r *Runner) runPackageRuntimesIndividually(
271
+ ctx context.Context,
272
+ req *normalizedRequest,
273
+ workspace *tsworkspace.Owner,
274
+ result *Result,
275
+ indexes []int,
276
+ ) {
277
+ parallelism := max(req.Parallelism, 1)
278
+ sem := make(chan struct{}, parallelism)
279
+ var wg sync.WaitGroup
280
+ for _, idx := range packageExecutionIndexes(result, indexes) {
281
+ wg.Go(func() {
282
+ select {
283
+ case sem <- struct{}{}:
284
+ defer func() { <-sem }()
285
+ case <-ctx.Done():
286
+ result.Packages[idx].Owner = OwnerTestRunner
287
+ result.Packages[idx].Phases.Runtime = PhaseStatusFail
288
+ result.Packages[idx].Error = ctx.Err().Error()
289
+ return
290
+ }
291
+ r.runPackageRuntime(ctx, req, workspace, result, idx)
292
+ })
293
+ }
294
+ wg.Wait()
295
+ }
296
+
297
+ func (r *Runner) runCombinedPackageRuntimes(
298
+ ctx context.Context,
299
+ req *normalizedRequest,
300
+ workspace *tsworkspace.Owner,
301
+ result *Result,
302
+ indexes []int,
303
+ ) bool {
304
+ ordered := packageExecutionIndexes(result, indexes)
305
+ chunks := packageRuntimeChunks(ordered, max(req.Parallelism, 1))
306
+ if len(chunks) == 0 {
307
+ return true
308
+ }
309
+ if len(chunks) == 1 {
310
+ return r.runCombinedPackageRuntime(ctx, req, workspace, result, "runner-all.ts", chunks[0])
311
+ }
312
+
313
+ var mu sync.Mutex
314
+ ok := true
315
+ var wg sync.WaitGroup
316
+ for chunkIdx, chunk := range chunks {
317
+ runnerFile := "runner-all-" + strconv.Itoa(chunkIdx) + ".ts"
318
+ wg.Go(func() {
319
+ if r.runCombinedPackageRuntime(ctx, req, workspace, result, runnerFile, chunk) {
320
+ return
321
+ }
322
+ mu.Lock()
323
+ ok = false
324
+ mu.Unlock()
325
+ })
326
+ }
327
+ wg.Wait()
328
+ return ok
329
+ }
330
+
331
+ func packageRuntimeChunks(indexes []int, parallelism int) [][]int {
332
+ if len(indexes) == 0 {
333
+ return nil
334
+ }
335
+ if parallelism < 1 {
336
+ parallelism = 1
337
+ }
338
+ if parallelism > len(indexes) {
339
+ parallelism = len(indexes)
340
+ }
341
+ chunks := make([][]int, parallelism)
342
+ for idx, packageIdx := range indexes {
343
+ chunks[idx%parallelism] = append(chunks[idx%parallelism], packageIdx)
344
+ }
345
+ return chunks
346
+ }
347
+
348
+ func (r *Runner) runCombinedPackageRuntime(
349
+ ctx context.Context,
350
+ req *normalizedRequest,
351
+ workspace *tsworkspace.Owner,
352
+ result *Result,
353
+ runnerFile string,
354
+ indexes []int,
355
+ ) bool {
356
+ if phase := workspace.WriteFile(tsworkspace.PhaseWorkspace, runnerFile, renderCombinedRunner(result, indexes, req)); phase.Failed() {
357
+ return false
358
+ }
359
+ runtime := workspace.RunTool(ctx, tsworkspace.PhaseRuntime, req.WorkDir, "bun", runnerFile)
360
+ if runtime.Failed() {
361
+ return false
362
+ }
363
+ records, ok := parseCombinedRuntimeRecords(runtime.Output)
364
+ if !ok {
365
+ return false
366
+ }
367
+ byPath := make(map[string]combinedRuntimeRecord, len(records))
368
+ for _, record := range records {
369
+ byPath[record.PackagePath] = record
370
+ }
371
+ for _, idx := range indexes {
372
+ record, ok := byPath[result.Packages[idx].PackagePath]
373
+ if !ok {
374
+ return false
375
+ }
376
+ result.Packages[idx].Elapsed = time.Duration(record.ElapsedMS) * time.Millisecond
377
+ result.Packages[idx].Output = strings.TrimSpace(record.Output)
378
+ if record.OK {
379
+ result.Packages[idx].Phases.Runtime = PhaseStatusPass
380
+ result.Packages[idx].Action = ActionPass
381
+ continue
382
+ }
383
+ result.Packages[idx].Action = ActionFail
384
+ result.Packages[idx].Owner = classifyProcessOutput(record.Output)
385
+ result.Packages[idx].Phases.Runtime = PhaseStatusFail
386
+ result.Packages[idx].Error = strings.TrimSpace(record.Output)
387
+ if result.Packages[idx].Error == "" {
388
+ result.Packages[idx].Error = "goscript test failed"
389
+ }
390
+ }
391
+ return true
392
+ }
393
+
394
+ func (r *Runner) runPackageRuntime(
395
+ ctx context.Context,
396
+ req *normalizedRequest,
397
+ workspace *tsworkspace.Owner,
398
+ result *Result,
399
+ idx int,
400
+ ) {
401
+ runtime := workspace.RunTool(ctx, tsworkspace.PhaseRuntime, req.WorkDir, "bun", packageRunnerFile(idx))
402
+ result.Packages[idx].Elapsed = runtime.Elapsed
403
+ result.Packages[idx].Output = strings.TrimSpace(runtime.Output)
404
+ if runtime.Failed() {
405
+ result.Packages[idx].Action = ActionFail
406
+ result.Packages[idx].Owner = classifyProcessOutput(runtime.Output)
407
+ result.Packages[idx].Phases.Runtime = PhaseStatusFail
408
+ result.Packages[idx].Error = runtime.Error
409
+ return
410
+ }
411
+ result.Packages[idx].Phases.Runtime = PhaseStatusPass
412
+ result.Packages[idx].Action = ActionPass
413
+ }
414
+
415
+ func (r *Runner) compileTestImports(
416
+ ctx context.Context,
417
+ req *normalizedRequest,
418
+ outputRoot string,
419
+ pkg *PackageResult,
420
+ result *Result,
421
+ ) bool {
422
+ imports := append([]string(nil), pkg.TestImports...)
423
+ slices.Sort(imports)
424
+ imports = slices.Compact(imports)
425
+ for _, importPath := range imports {
426
+ if importPath == "" || importPath == pkg.PackagePath {
427
+ continue
428
+ }
429
+ compileReq := &compiler.CompileRequest{
430
+ Patterns: []string{importPath},
431
+ Dir: req.Dir,
432
+ OutputPath: outputRoot,
433
+ BuildFlags: append([]string(nil), req.BuildFlags...),
434
+ OverrideDirs: append([]string(nil), req.OverrideDirs...),
435
+ DependencyMode: compiler.DependencyModeAll,
436
+ RuntimeEmissionMode: compiler.RuntimeEmissionModeEmit,
437
+ Tests: false,
438
+ AllDependencies: true,
439
+ }
440
+ compileResult, compileErr := r.service.Compile(ctx, compileReq)
441
+ if compileResult != nil {
442
+ result.Diagnostics = append(result.Diagnostics, compileResult.Diagnostics...)
443
+ }
444
+ if compileErr != nil {
445
+ pkg.Action = ActionFail
446
+ if compileResult != nil {
447
+ pkg.Owner = classifyDiagnostics(compileResult.Diagnostics)
448
+ }
449
+ markCompilePhase(pkg, compileResult, false)
450
+ pkg.Error = compileErr.Error()
451
+ return false
452
+ }
453
+ markCompilePhase(pkg, compileResult, true)
454
+ }
455
+ return true
456
+ }
457
+
458
+ func (r *Runner) compilePackageOutputs(ctx context.Context, req *normalizedRequest, result *Result) []string {
459
+ outputRoots := make([]string, len(result.Packages))
460
+ if r.compilePackageBatch(ctx, req, result, outputRoots) {
461
+ return outputRoots
462
+ }
463
+ return r.compilePackageOutputsIndividually(ctx, req, result)
464
+ }
465
+
466
+ func (r *Runner) compilePackageBatch(ctx context.Context, req *normalizedRequest, result *Result, outputRoots []string) bool {
467
+ packagePaths := runnablePackagePaths(result.Packages)
468
+ if len(packagePaths) == 0 {
469
+ return true
470
+ }
471
+ testCompileReq := &compiler.CompileRequest{
472
+ Patterns: packagePaths,
473
+ Dir: req.Dir,
474
+ OutputPath: req.OutputRoot,
475
+ BuildFlags: append([]string(nil), req.BuildFlags...),
476
+ OverrideDirs: append([]string(nil), req.OverrideDirs...),
477
+ DependencyMode: compiler.DependencyModeAll,
478
+ RuntimeEmissionMode: compiler.RuntimeEmissionModeEmit,
479
+ Tests: true,
480
+ AllDependencies: true,
481
+ }
482
+ testCompileResult, testCompileErr := r.service.Compile(ctx, testCompileReq)
483
+ if testCompileErr != nil {
484
+ return false
485
+ }
486
+ if testCompileResult != nil {
487
+ result.Diagnostics = append(result.Diagnostics, testCompileResult.Diagnostics...)
488
+ }
489
+ for idx := range result.Packages {
490
+ if !shouldCompilePackage(result.Packages[idx]) {
491
+ continue
492
+ }
493
+ outputRoots[idx] = req.OutputRoot
494
+ markCompilePhase(&result.Packages[idx], testCompileResult, true)
495
+ }
496
+ return true
497
+ }
498
+
499
+ func (r *Runner) compilePackageOutputsIndividually(ctx context.Context, req *normalizedRequest, result *Result) []string {
500
+ outputRoots := make([]string, len(result.Packages))
501
+ for idx := range result.Packages {
502
+ if !shouldCompilePackage(result.Packages[idx]) {
503
+ continue
504
+ }
505
+ outputRoot := packageOutputRoot(req, idx)
506
+ outputRoots[idx] = outputRoot
507
+ compileReq := &compiler.CompileRequest{
508
+ Patterns: []string{result.Packages[idx].PackagePath},
509
+ Dir: req.Dir,
510
+ OutputPath: outputRoot,
511
+ BuildFlags: append([]string(nil), req.BuildFlags...),
512
+ OverrideDirs: append([]string(nil), req.OverrideDirs...),
513
+ DependencyMode: compiler.DependencyModeAll,
514
+ RuntimeEmissionMode: compiler.RuntimeEmissionModeEmit,
515
+ Tests: false,
516
+ AllDependencies: true,
517
+ }
518
+ if compileResult, compileErr := r.service.Compile(ctx, compileReq); compileErr != nil {
519
+ result.Packages[idx].Action = ActionFail
520
+ if compileResult != nil {
521
+ result.Diagnostics = append(result.Diagnostics, compileResult.Diagnostics...)
522
+ result.Packages[idx].Owner = classifyDiagnostics(compileResult.Diagnostics)
523
+ }
524
+ markCompilePhase(&result.Packages[idx], compileResult, false)
525
+ result.Packages[idx].Error = compileErr.Error()
526
+ continue
527
+ } else if compileResult != nil {
528
+ result.Diagnostics = append(result.Diagnostics, compileResult.Diagnostics...)
529
+ markCompilePhase(&result.Packages[idx], compileResult, true)
530
+ }
531
+ if !r.compileTestImports(ctx, req, outputRoot, &result.Packages[idx], result) {
532
+ continue
533
+ }
534
+ testCompileReq := &compiler.CompileRequest{
535
+ Patterns: []string{result.Packages[idx].PackagePath},
536
+ Dir: req.Dir,
537
+ OutputPath: outputRoot,
538
+ BuildFlags: append([]string(nil), req.BuildFlags...),
539
+ OverrideDirs: append([]string(nil), req.OverrideDirs...),
540
+ DependencyMode: compiler.DependencyModeAll,
541
+ RuntimeEmissionMode: compiler.RuntimeEmissionModeEmit,
542
+ Tests: true,
543
+ AllDependencies: true,
544
+ }
545
+ if compileResult, compileErr := r.service.Compile(ctx, testCompileReq); compileErr != nil {
546
+ result.Packages[idx].Action = ActionFail
547
+ if compileResult != nil {
548
+ result.Diagnostics = append(result.Diagnostics, compileResult.Diagnostics...)
549
+ result.Packages[idx].Owner = classifyDiagnostics(compileResult.Diagnostics)
550
+ }
551
+ markCompilePhase(&result.Packages[idx], compileResult, false)
552
+ result.Packages[idx].Error = compileErr.Error()
553
+ continue
554
+ } else if compileResult != nil {
555
+ result.Diagnostics = append(result.Diagnostics, compileResult.Diagnostics...)
556
+ markCompilePhase(&result.Packages[idx], compileResult, true)
557
+ }
558
+ }
559
+ return outputRoots
560
+ }
561
+
562
+ func compileRunPattern(pattern string) (*regexp.Regexp, error) {
563
+ pattern = strings.TrimSpace(pattern)
564
+ if pattern == "" {
565
+ return nil, nil
566
+ }
567
+ return regexp.Compile(pattern)
568
+ }
569
+
570
+ func packageResults(testGraph *compiler.PackageTestGraph, runPattern *regexp.Regexp) []PackageResult {
571
+ if testGraph == nil {
572
+ return nil
573
+ }
574
+ results := make([]PackageResult, 0, len(testGraph.Packages))
575
+ for _, pkg := range testGraph.Packages {
576
+ result := newSkippedPackageResult(pkg.PackagePath)
577
+ result.SourceDir = packageSourceDir(pkg)
578
+ result.Tests = append(result.Tests, packageVariantTests(pkg.SamePackageTests, runPattern)...)
579
+ result.Tests = append(result.Tests, packageVariantTests(pkg.ExternalPackageTests, runPattern)...)
580
+ result.TestImports = packageTestImports(pkg)
581
+ slices.SortFunc(result.Tests, func(a, b Test) int {
582
+ if a.Name == b.Name {
583
+ return strings.Compare(a.PackagePath, b.PackagePath)
584
+ }
585
+ return strings.Compare(a.Name, b.Name)
586
+ })
587
+ if len(result.Tests) != 0 {
588
+ result.TestPackagePath = result.Tests[0].PackagePath
589
+ result.Action = ActionFail
590
+ result.Phases = PackagePhases{}
591
+ }
592
+ if diagnosticsHaveErrors(pkg.Diagnostics) {
593
+ result.Action = ActionFail
594
+ result.Owner = OwnerPackageGraph
595
+ result.Error = diagnosticsSummary(pkg.Diagnostics)
596
+ result.Phases = failurePhases(OwnerPackageGraph)
597
+ }
598
+ results = append(results, result)
599
+ }
600
+ return results
601
+ }
602
+
603
+ func packageSourceDir(pkg *compiler.PackageTestGraphPackage) string {
604
+ if pkg == nil {
605
+ return ""
606
+ }
607
+ for _, files := range [][]string{
608
+ pkg.CompiledGoFiles,
609
+ pkg.GoFiles,
610
+ testVariantCompiledGoFiles(pkg.SamePackageTests),
611
+ testVariantGoFiles(pkg.SamePackageTests),
612
+ testVariantCompiledGoFiles(pkg.ExternalPackageTests),
613
+ testVariantGoFiles(pkg.ExternalPackageTests),
614
+ } {
615
+ if len(files) != 0 && files[0] != "" {
616
+ return filepath.Dir(files[0])
617
+ }
618
+ }
619
+ return ""
620
+ }
621
+
622
+ func testVariantCompiledGoFiles(variant *compiler.PackageTestGraphVariant) []string {
623
+ if variant == nil {
624
+ return nil
625
+ }
626
+ return variant.CompiledGoFiles
627
+ }
628
+
629
+ func testVariantGoFiles(variant *compiler.PackageTestGraphVariant) []string {
630
+ if variant == nil {
631
+ return nil
632
+ }
633
+ return variant.GoFiles
634
+ }
635
+
636
+ func newSkippedPackageResult(packagePath string) PackageResult {
637
+ return PackageResult{
638
+ PackagePath: packagePath,
639
+ Action: ActionSkip,
640
+ Phases: PackagePhases{
641
+ Workspace: PhaseStatusSkip,
642
+ Compile: PhaseStatusSkip,
643
+ Emit: PhaseStatusSkip,
644
+ TypeCheck: PhaseStatusSkip,
645
+ Runtime: PhaseStatusSkip,
646
+ },
647
+ }
648
+ }
649
+
650
+ func packageTestImports(pkg *compiler.PackageTestGraphPackage) []string {
651
+ importSet := make(map[string]bool)
652
+ for _, variant := range []*compiler.PackageTestGraphVariant{pkg.SamePackageTests, pkg.ExternalPackageTests} {
653
+ if variant == nil {
654
+ continue
655
+ }
656
+ for _, importPath := range variant.Imports {
657
+ importSet[importPath] = true
658
+ }
659
+ }
660
+ imports := make([]string, 0, len(importSet))
661
+ for importPath := range importSet {
662
+ imports = append(imports, importPath)
663
+ }
664
+ slices.Sort(imports)
665
+ return imports
666
+ }
667
+
668
+ func packageVariantTests(variant *compiler.PackageTestGraphVariant, runPattern *regexp.Regexp) []Test {
669
+ if variant == nil {
670
+ return nil
671
+ }
672
+ tests := make([]Test, 0, len(variant.Tests))
673
+ for _, test := range variant.Tests {
674
+ if runPattern != nil && !runPattern.MatchString(test.Name) {
675
+ continue
676
+ }
677
+ tests = append(tests, Test{
678
+ Name: test.Name,
679
+ PackagePath: test.PackagePath,
680
+ })
681
+ }
682
+ return tests
683
+ }
684
+
685
+ func shouldCompilePackage(result PackageResult) bool {
686
+ return result.Action != ActionSkip && result.Owner == "" && result.Error == ""
687
+ }
688
+
689
+ func runnablePackagePaths(results []PackageResult) []string {
690
+ seen := make(map[string]bool)
691
+ paths := make([]string, 0, len(results))
692
+ for _, result := range results {
693
+ if !shouldCompilePackage(result) {
694
+ continue
695
+ }
696
+ if result.PackagePath == "" || seen[result.PackagePath] {
697
+ continue
698
+ }
699
+ seen[result.PackagePath] = true
700
+ paths = append(paths, result.PackagePath)
701
+ }
702
+ slices.Sort(paths)
703
+ return paths
704
+ }
705
+
706
+ func packageExecutionIndexes(result *Result, indexes []int) []int {
707
+ ordered := append([]int(nil), indexes...)
708
+ slices.SortFunc(ordered, func(a, b int) int {
709
+ var aPkg, bPkg PackageResult
710
+ if result != nil {
711
+ if a >= 0 && a < len(result.Packages) {
712
+ aPkg = result.Packages[a]
713
+ }
714
+ if b >= 0 && b < len(result.Packages) {
715
+ bPkg = result.Packages[b]
716
+ }
717
+ }
718
+ if len(aPkg.Tests) != len(bPkg.Tests) {
719
+ return len(bPkg.Tests) - len(aPkg.Tests)
720
+ }
721
+ return strings.Compare(aPkg.PackagePath, bPkg.PackagePath)
722
+ })
723
+ return ordered
724
+ }
725
+
726
+ func markAllFailures(result *Result, owner Owner, message string) {
727
+ message = strings.TrimSpace(message)
728
+ if result == nil {
729
+ return
730
+ }
731
+ if len(result.Packages) == 0 {
732
+ result.Packages = append(result.Packages, PackageResult{
733
+ PackagePath: "package-patterns",
734
+ Action: ActionFail,
735
+ Owner: owner,
736
+ Error: message,
737
+ Phases: failurePhases(owner),
738
+ })
739
+ return
740
+ }
741
+ for idx := range result.Packages {
742
+ if result.Packages[idx].Action == ActionSkip {
743
+ continue
744
+ }
745
+ if result.Packages[idx].Action == ActionFail && (result.Packages[idx].Owner != "" || result.Packages[idx].Error != "") {
746
+ continue
747
+ }
748
+ result.Packages[idx].Action = ActionFail
749
+ result.Packages[idx].Owner = owner
750
+ result.Packages[idx].Error = message
751
+ result.Packages[idx].Phases = failurePhases(owner)
752
+ }
753
+ }
754
+
755
+ func markTypeCheckFailures(result *Result, owner Owner, message string) {
756
+ message = strings.TrimSpace(message)
757
+ if result == nil {
758
+ return
759
+ }
760
+ for idx := range result.Packages {
761
+ if !shouldCompilePackage(result.Packages[idx]) {
762
+ continue
763
+ }
764
+ result.Packages[idx].Action = ActionFail
765
+ result.Packages[idx].Owner = owner
766
+ result.Packages[idx].Error = message
767
+ result.Packages[idx].Phases.TypeCheck = PhaseStatusFail
768
+ result.Packages[idx].Phases.Runtime = PhaseStatusSkip
769
+ }
770
+ }
771
+
772
+ func failurePhases(owner Owner) PackagePhases {
773
+ if owner == OwnerPackageGraph {
774
+ return PackagePhases{
775
+ Workspace: PhaseStatusSkip,
776
+ Compile: PhaseStatusFail,
777
+ Emit: PhaseStatusSkip,
778
+ TypeCheck: PhaseStatusSkip,
779
+ Runtime: PhaseStatusSkip,
780
+ }
781
+ }
782
+ return PackagePhases{
783
+ Workspace: PhaseStatusFail,
784
+ Compile: PhaseStatusSkip,
785
+ Emit: PhaseStatusSkip,
786
+ TypeCheck: PhaseStatusSkip,
787
+ Runtime: PhaseStatusSkip,
788
+ }
789
+ }
790
+
791
+ func packageOutputRoot(req *normalizedRequest, idx int) string {
792
+ return filepath.Join(req.OutputRoot, "package-"+strconv.Itoa(idx))
793
+ }
794
+
795
+ func packageRunnerFile(idx int) string {
796
+ return "runner-" + strconv.Itoa(idx) + ".ts"
797
+ }
798
+
799
+ func packageTSConfigFile(idx int) string {
800
+ return "tsconfig-" + strconv.Itoa(idx) + ".json"
801
+ }
802
+
803
+ func renderRunner(result PackageResult, req *normalizedRequest) string {
804
+ var b strings.Builder
805
+ b.WriteString("import { runTests } from \"@goscript/testing/index.js\"\n")
806
+ imports := runnerImports(result.Tests)
807
+ for idx, packagePath := range imports {
808
+ b.WriteString("import * as pkg")
809
+ b.WriteString(strconv.Itoa(idx))
810
+ b.WriteString(" from ")
811
+ b.WriteString(strconv.Quote("@goscript/" + packagePath + "/index.js"))
812
+ b.WriteString("\n")
813
+ }
814
+ b.WriteString("\n")
815
+ writeProcessChdir(&b, result.SourceDir)
816
+ b.WriteString("const result = await runTests(")
817
+ b.WriteString(strconv.Quote(result.PackagePath))
818
+ b.WriteString(", [\n")
819
+ for idx, test := range result.Tests {
820
+ b.WriteString("\t{ name: ")
821
+ b.WriteString(strconv.Quote(test.Name))
822
+ b.WriteString(", fn: async (t) => await pkg")
823
+ b.WriteString(strconv.Itoa(slices.Index(imports, test.PackagePath)))
824
+ b.WriteString(".")
825
+ b.WriteString(test.Name)
826
+ b.WriteString("(t) }")
827
+ if idx != len(result.Tests)-1 {
828
+ b.WriteString(",")
829
+ }
830
+ b.WriteString("\n")
831
+ }
832
+ b.WriteString("], { verbose: ")
833
+ if req.Verbose {
834
+ b.WriteString("true")
835
+ } else {
836
+ b.WriteString("false")
837
+ }
838
+ b.WriteString(", count: ")
839
+ b.WriteString(strconv.Itoa(req.Count))
840
+ b.WriteString(", short: ")
841
+ if req.Short {
842
+ b.WriteString("true")
843
+ } else {
844
+ b.WriteString("false")
845
+ }
846
+ b.WriteString(" })\n")
847
+ b.WriteString("if (!result.ok) {\n\tthrow new Error(\"goscript test failed\")\n}\n")
848
+ b.WriteString("if (typeof process !== \"undefined\" && process.exit) {\n\tprocess.exit(0)\n}\n")
849
+ return b.String()
850
+ }
851
+
852
+ type combinedRuntimeRecord struct {
853
+ PackagePath string `json:"packagePath"`
854
+ OK bool `json:"ok"`
855
+ ElapsedMS int64 `json:"elapsedMs"`
856
+ Output string `json:"output"`
857
+ }
858
+
859
+ func parseCombinedRuntimeRecords(output string) ([]combinedRuntimeRecord, bool) {
860
+ var records []combinedRuntimeRecord
861
+ for line := range strings.SplitSeq(output, "\n") {
862
+ line = strings.TrimSpace(line)
863
+ if !strings.HasPrefix(line, combinedRuntimeResultPrefix) {
864
+ continue
865
+ }
866
+ var record combinedRuntimeRecord
867
+ if err := json.Unmarshal([]byte(strings.TrimPrefix(line, combinedRuntimeResultPrefix)), &record); err != nil {
868
+ return nil, false
869
+ }
870
+ if record.PackagePath == "" {
871
+ return nil, false
872
+ }
873
+ records = append(records, record)
874
+ }
875
+ return records, len(records) != 0
876
+ }
877
+
878
+ func renderCombinedRunner(result *Result, indexes []int, req *normalizedRequest) string {
879
+ aliases := runnerImportAliases(result, indexes)
880
+ var imports []string
881
+ for packagePath := range aliases {
882
+ imports = append(imports, packagePath)
883
+ }
884
+ slices.Sort(imports)
885
+
886
+ var b strings.Builder
887
+ b.WriteString("import { runTests } from \"@goscript/testing/index.js\"\n")
888
+ for _, packagePath := range imports {
889
+ b.WriteString("import * as ")
890
+ b.WriteString(aliases[packagePath])
891
+ b.WriteString(" from ")
892
+ b.WriteString(strconv.Quote("@goscript/" + packagePath + "/index.js"))
893
+ b.WriteString("\n")
894
+ }
895
+ b.WriteString("\n")
896
+ b.WriteString("const __goscriptResultPrefix = ")
897
+ b.WriteString(strconv.Quote(combinedRuntimeResultPrefix))
898
+ b.WriteString("\n")
899
+ b.WriteString("const __goscriptOriginalLog = console.log\n")
900
+ b.WriteString("async function __goscriptRunPackage(packagePath, packageDir, tests) {\n")
901
+ b.WriteString("\tif (packageDir && typeof process !== \"undefined\" && process.chdir) {\n")
902
+ b.WriteString("\t\tprocess.chdir(packageDir)\n")
903
+ b.WriteString("\t}\n")
904
+ b.WriteString("\tconst logs = []\n")
905
+ b.WriteString("\tconst startedAt = Date.now()\n")
906
+ b.WriteString("\tlet ok = false\n")
907
+ b.WriteString("\tconsole.log = (...args) => logs.push(args.map((arg) => String(arg)).join(' '))\n")
908
+ b.WriteString("\ttry {\n")
909
+ b.WriteString("\t\tconst result = await runTests(packagePath, tests, { verbose: ")
910
+ if req.Verbose {
911
+ b.WriteString("true")
912
+ } else {
913
+ b.WriteString("false")
914
+ }
915
+ b.WriteString(", count: ")
916
+ b.WriteString(strconv.Itoa(req.Count))
917
+ b.WriteString(", short: ")
918
+ if req.Short {
919
+ b.WriteString("true")
920
+ } else {
921
+ b.WriteString("false")
922
+ }
923
+ b.WriteString(" })\n")
924
+ b.WriteString("\t\tok = result.ok\n")
925
+ b.WriteString("\t} catch (err) {\n")
926
+ b.WriteString("\t\tok = false\n")
927
+ b.WriteString("\t\tlogs.push(err && err.stack ? String(err.stack) : String(err))\n")
928
+ b.WriteString("\t} finally {\n")
929
+ b.WriteString("\t\tconsole.log = __goscriptOriginalLog\n")
930
+ b.WriteString("\t}\n")
931
+ b.WriteString("\t__goscriptOriginalLog(__goscriptResultPrefix + JSON.stringify({ packagePath, ok, elapsedMs: Date.now() - startedAt, output: logs.join('\\n') }))\n")
932
+ b.WriteString("}\n\n")
933
+ for _, idx := range indexes {
934
+ pkg := result.Packages[idx]
935
+ b.WriteString("await __goscriptRunPackage(")
936
+ b.WriteString(strconv.Quote(pkg.PackagePath))
937
+ b.WriteString(", ")
938
+ b.WriteString(strconv.Quote(pkg.SourceDir))
939
+ b.WriteString(", [\n")
940
+ for testIdx, test := range pkg.Tests {
941
+ b.WriteString("\t{ name: ")
942
+ b.WriteString(strconv.Quote(test.Name))
943
+ b.WriteString(", fn: async (t) => await ")
944
+ b.WriteString(aliases[test.PackagePath])
945
+ b.WriteString(".")
946
+ b.WriteString(test.Name)
947
+ b.WriteString("(t) }")
948
+ if testIdx != len(pkg.Tests)-1 {
949
+ b.WriteString(",")
950
+ }
951
+ b.WriteString("\n")
952
+ }
953
+ b.WriteString("])\n")
954
+ }
955
+ b.WriteString("if (typeof process !== \"undefined\" && process.exit) {\n\tprocess.exit(0)\n}\n")
956
+ return b.String()
957
+ }
958
+
959
+ func writeProcessChdir(b *strings.Builder, dir string) {
960
+ if dir == "" {
961
+ return
962
+ }
963
+ b.WriteString("if (typeof process !== \"undefined\" && process.chdir) {\n")
964
+ b.WriteString("\tprocess.chdir(")
965
+ b.WriteString(strconv.Quote(dir))
966
+ b.WriteString(")\n")
967
+ b.WriteString("}\n")
968
+ }
969
+
970
+ func runnerImportAliases(result *Result, indexes []int) map[string]string {
971
+ seen := make(map[string]bool)
972
+ var imports []string
973
+ for _, idx := range indexes {
974
+ if result == nil || idx < 0 || idx >= len(result.Packages) {
975
+ continue
976
+ }
977
+ for _, packagePath := range runnerImports(result.Packages[idx].Tests) {
978
+ if seen[packagePath] {
979
+ continue
980
+ }
981
+ seen[packagePath] = true
982
+ imports = append(imports, packagePath)
983
+ }
984
+ }
985
+ slices.Sort(imports)
986
+ aliases := make(map[string]string, len(imports))
987
+ for idx, packagePath := range imports {
988
+ aliases[packagePath] = "pkg" + strconv.Itoa(idx)
989
+ }
990
+ return aliases
991
+ }
992
+
993
+ func runnerImports(tests []Test) []string {
994
+ seen := make(map[string]bool)
995
+ var imports []string
996
+ for _, test := range tests {
997
+ if test.PackagePath == "" || seen[test.PackagePath] {
998
+ continue
999
+ }
1000
+ seen[test.PackagePath] = true
1001
+ imports = append(imports, test.PackagePath)
1002
+ }
1003
+ slices.Sort(imports)
1004
+ return imports
1005
+ }
1006
+
1007
+ func processErrorText(result tsworkspace.Result) string {
1008
+ output := strings.TrimSpace(result.Output)
1009
+ if output != "" {
1010
+ return output
1011
+ }
1012
+ return result.Error
1013
+ }
1014
+
1015
+ func aggregateTypeCheckFailureOwner(output string) (Owner, bool) {
1016
+ owner := classifyProcessOutput(output)
1017
+ // Package-scoped fallback is worth paying for package-local emitted
1018
+ // TypeScript errors. Shared override package failures are independent of
1019
+ // the runner file, so rerunning tsgo per package only repeats the same
1020
+ // expensive project error.
1021
+ if owner == OwnerOverridePackage {
1022
+ return owner, true
1023
+ }
1024
+ return "", false
1025
+ }
1026
+
1027
+ func renderTypeScriptProject(req *normalizedRequest, outputRoot string, runnerFile string, projectFile string, nodeTypesAvailable bool) string {
1028
+ var b strings.Builder
1029
+ b.WriteString("{\n")
1030
+ b.WriteString(" \"compilerOptions\": {\n")
1031
+ b.WriteString(" \"target\": \"ES2022\",\n")
1032
+ b.WriteString(" \"module\": \"ESNext\",\n")
1033
+ b.WriteString(" \"moduleResolution\": \"Bundler\",\n")
1034
+ b.WriteString(" \"lib\": [\"ESNext\", \"DOM\"],\n")
1035
+ b.WriteString(" \"strict\": true,\n")
1036
+ b.WriteString(" \"allowImportingTsExtensions\": true,\n")
1037
+ if req.IncrementalTypeCheck {
1038
+ b.WriteString(" \"incremental\": true,\n")
1039
+ b.WriteString(" \"tsBuildInfoFile\": ")
1040
+ b.WriteString(strconv.Quote(typeScriptBuildInfoFile(projectFile)))
1041
+ b.WriteString(",\n")
1042
+ }
1043
+ b.WriteString(" \"noEmit\": true,\n")
1044
+ if nodeTypesAvailable {
1045
+ b.WriteString(" \"types\": [\"node\"],\n")
1046
+ } else {
1047
+ b.WriteString(" \"types\": [],\n")
1048
+ }
1049
+ b.WriteString(" \"paths\": {\n")
1050
+ b.WriteString(" \"*\": [\"./*\"],\n")
1051
+ b.WriteString(" \"@goscript/*\": [")
1052
+ b.WriteString(strconv.Quote("./" + typeScriptOutputAlias(req, outputRoot)))
1053
+ b.WriteString("]\n")
1054
+ b.WriteString(" }\n")
1055
+ b.WriteString(" },\n")
1056
+ b.WriteString(" \"include\": [")
1057
+ b.WriteString(strconv.Quote(runnerFile))
1058
+ b.WriteString(", ")
1059
+ b.WriteString(strconv.Quote(tsworkspace.NodeAmbientTypesFile))
1060
+ b.WriteString("]\n")
1061
+ b.WriteString("}\n")
1062
+ return b.String()
1063
+ }
1064
+
1065
+ func renderRuntimeTypeScriptProject(req *normalizedRequest, outputRoots []string, nodeTypesAvailable bool) string {
1066
+ var aliases []string
1067
+ seen := make(map[string]bool)
1068
+ for _, outputRoot := range outputRoots {
1069
+ if outputRoot == "" {
1070
+ continue
1071
+ }
1072
+ alias := "./" + typeScriptOutputAlias(req, outputRoot)
1073
+ if !seen[alias] {
1074
+ seen[alias] = true
1075
+ aliases = append(aliases, alias)
1076
+ }
1077
+ }
1078
+ if len(aliases) == 0 && req.OutputRoot != "" {
1079
+ aliases = append(aliases, "./"+typeScriptOutputAlias(req, req.OutputRoot))
1080
+ }
1081
+ var b strings.Builder
1082
+ b.WriteString("{\n")
1083
+ b.WriteString(" \"compilerOptions\": {\n")
1084
+ b.WriteString(" \"target\": \"ES2022\",\n")
1085
+ b.WriteString(" \"module\": \"ESNext\",\n")
1086
+ b.WriteString(" \"moduleResolution\": \"Bundler\",\n")
1087
+ b.WriteString(" \"lib\": [\"ESNext\", \"DOM\"],\n")
1088
+ b.WriteString(" \"strict\": true,\n")
1089
+ b.WriteString(" \"allowImportingTsExtensions\": true,\n")
1090
+ if req.IncrementalTypeCheck {
1091
+ b.WriteString(" \"incremental\": true,\n")
1092
+ b.WriteString(" \"tsBuildInfoFile\": ")
1093
+ b.WriteString(strconv.Quote(typeScriptBuildInfoFile("tsconfig.json")))
1094
+ b.WriteString(",\n")
1095
+ }
1096
+ b.WriteString(" \"noEmit\": true,\n")
1097
+ if nodeTypesAvailable {
1098
+ b.WriteString(" \"types\": [\"node\"],\n")
1099
+ } else {
1100
+ b.WriteString(" \"types\": [],\n")
1101
+ }
1102
+ b.WriteString(" \"paths\": {\n")
1103
+ b.WriteString(" \"*\": [\"./*\"],\n")
1104
+ b.WriteString(" \"@goscript/*\": [")
1105
+ for idx, alias := range aliases {
1106
+ if idx != 0 {
1107
+ b.WriteString(", ")
1108
+ }
1109
+ b.WriteString(strconv.Quote(alias))
1110
+ }
1111
+ b.WriteString("]\n")
1112
+ b.WriteString(" }\n")
1113
+ b.WriteString(" },\n")
1114
+ b.WriteString(" \"include\": [\"runner-*.ts\", ")
1115
+ b.WriteString(strconv.Quote(tsworkspace.NodeAmbientTypesFile))
1116
+ b.WriteString("]\n")
1117
+ b.WriteString("}\n")
1118
+ return b.String()
1119
+ }
1120
+
1121
+ func typeScriptBuildInfoFile(projectFile string) string {
1122
+ name := strings.TrimSuffix(projectFile, filepath.Ext(projectFile))
1123
+ if name == "" {
1124
+ name = "tsconfig"
1125
+ }
1126
+ return ".goscript/" + name + ".tsbuildinfo"
1127
+ }
1128
+
1129
+ func typeScriptOutputPattern(req *normalizedRequest, outputRoot string) string {
1130
+ if rel, err := filepath.Rel(req.WorkDir, outputRoot); err == nil {
1131
+ return filepath.ToSlash(rel)
1132
+ }
1133
+ return filepath.ToSlash(outputRoot)
1134
+ }
1135
+
1136
+ func typeScriptOutputAlias(req *normalizedRequest, outputRoot string) string {
1137
+ return filepath.ToSlash(filepath.Join(typeScriptOutputPattern(req, outputRoot), "@goscript", "*"))
1138
+ }
1139
+
1140
+ func markCompilePhase(pkg *PackageResult, result *compiler.CompilationResult, passed bool) {
1141
+ if pkg == nil {
1142
+ return
1143
+ }
1144
+ if passed {
1145
+ pkg.Phases.Compile = PhaseStatusPass
1146
+ pkg.Phases.Emit = PhaseStatusPass
1147
+ return
1148
+ }
1149
+ if classifyDiagnostics(resultDiagnostics(result)) == OwnerTypeScriptEmitter {
1150
+ pkg.Phases.Compile = PhaseStatusPass
1151
+ pkg.Phases.Emit = PhaseStatusFail
1152
+ return
1153
+ }
1154
+ pkg.Phases.Compile = PhaseStatusFail
1155
+ pkg.Phases.Emit = PhaseStatusSkip
1156
+ }
1157
+
1158
+ func resultDiagnostics(result *compiler.CompilationResult) []compiler.Diagnostic {
1159
+ if result == nil {
1160
+ return nil
1161
+ }
1162
+ return result.Diagnostics
1163
+ }
1164
+
1165
+ func classifyDiagnostics(diagnostics []compiler.Diagnostic) Owner {
1166
+ for _, diagnostic := range diagnostics {
1167
+ switch {
1168
+ case strings.HasPrefix(diagnostic.Code, "goscript/package-graph"):
1169
+ return OwnerPackageGraph
1170
+ case strings.HasPrefix(diagnostic.Code, "goscript/semantic"):
1171
+ return OwnerSemanticModel
1172
+ case strings.HasPrefix(diagnostic.Code, "goscript/lowering"):
1173
+ return OwnerLowering
1174
+ case strings.HasPrefix(diagnostic.Code, "goscript/emitter"):
1175
+ return OwnerTypeScriptEmitter
1176
+ case strings.HasPrefix(diagnostic.Code, "goscript/overrides"):
1177
+ return OwnerOverridePackage
1178
+ case strings.HasPrefix(diagnostic.Code, "goscript/runtime"):
1179
+ return OwnerRuntimePackage
1180
+ }
1181
+ }
1182
+ return OwnerTestRunner
1183
+ }
1184
+
1185
+ func classifyProcessOutput(output string) Owner {
1186
+ switch {
1187
+ case strings.Contains(output, "@goscript/testing") || strings.Contains(output, "@goscript/"):
1188
+ return OwnerOverridePackage
1189
+ case strings.Contains(output, "TypeScript") || strings.Contains(output, "TS"):
1190
+ return OwnerTypeScriptEmitter
1191
+ case strings.Contains(output, "panic") || strings.Contains(output, "runtime"):
1192
+ return OwnerRuntimePackage
1193
+ default:
1194
+ return OwnerTestRunner
1195
+ }
1196
+ }
1197
+
1198
+ func diagnosticsHaveErrors(diagnostics []compiler.Diagnostic) bool {
1199
+ for _, diagnostic := range diagnostics {
1200
+ if diagnostic.Severity == compiler.DiagnosticSeverityError {
1201
+ return true
1202
+ }
1203
+ }
1204
+ return false
1205
+ }
1206
+
1207
+ func diagnosticsSummary(diagnostics []compiler.Diagnostic) string {
1208
+ var b strings.Builder
1209
+ for idx, diagnostic := range diagnostics {
1210
+ if idx != 0 {
1211
+ b.WriteString("; ")
1212
+ }
1213
+ if diagnostic.Code != "" {
1214
+ b.WriteString(diagnostic.Code)
1215
+ b.WriteString(": ")
1216
+ }
1217
+ b.WriteString(diagnostic.Message)
1218
+ if diagnostic.Detail != "" {
1219
+ b.WriteString(" (")
1220
+ b.WriteString(diagnostic.Detail)
1221
+ b.WriteString(")")
1222
+ }
1223
+ }
1224
+ return b.String()
1225
+ }