goscript 0.1.0 → 0.1.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 (327) hide show
  1. package/README.md +267 -255
  2. package/cmd/goscript/cmd-test.go +193 -0
  3. package/cmd/goscript/cmd-test_test.go +76 -0
  4. package/cmd/goscript/main.go +1 -0
  5. package/compiler/build-flags.go +38 -0
  6. package/compiler/compile-request.go +2 -0
  7. package/compiler/compliance_test.go +0 -8
  8. package/compiler/gotest/owner.go +24 -0
  9. package/compiler/gotest/package-result.go +67 -0
  10. package/compiler/gotest/request.go +145 -0
  11. package/compiler/gotest/result.go +28 -0
  12. package/compiler/gotest/runner.go +588 -0
  13. package/compiler/gotest/runner_test.go +627 -0
  14. package/compiler/gotest/test.go +9 -0
  15. package/compiler/index.test.ts +1 -1
  16. package/compiler/lowered-program.go +71 -19
  17. package/compiler/lowering.go +5065 -569
  18. package/compiler/override-facts.go +307 -0
  19. package/compiler/override-registry.go +50 -189
  20. package/compiler/override-registry_test.go +47 -0
  21. package/compiler/package-graph.go +50 -27
  22. package/compiler/package-graph_test.go +37 -2
  23. package/compiler/package-test-function.go +9 -0
  24. package/compiler/package-test-graph-package.go +40 -0
  25. package/compiler/package-test-graph-variant.go +105 -0
  26. package/compiler/package-test-graph.go +117 -0
  27. package/compiler/package-test-graph_test.go +144 -0
  28. package/compiler/runtime-contract.go +189 -29
  29. package/compiler/runtime-contract_test.go +44 -30
  30. package/compiler/semantic-model-types.go +9 -6
  31. package/compiler/semantic-model.go +538 -38
  32. package/compiler/semantic-model_test.go +55 -0
  33. package/compiler/service.go +1 -1
  34. package/compiler/skeleton_test.go +679 -49
  35. package/compiler/tsworkspace/owner.go +334 -0
  36. package/compiler/tsworkspace/owner_test.go +93 -0
  37. package/compiler/tsworkspace/result.go +17 -0
  38. package/compiler/typescript-emitter.go +459 -82
  39. package/compiler/wasm/compile.go +1 -1
  40. package/compiler/wasm/compile_test.go +61 -11
  41. package/compiler/wasm_api.go +172 -7
  42. package/dist/gs/builtin/builtin.d.ts +20 -2
  43. package/dist/gs/builtin/builtin.js +194 -6
  44. package/dist/gs/builtin/builtin.js.map +1 -1
  45. package/dist/gs/builtin/channel.d.ts +8 -0
  46. package/dist/gs/builtin/channel.js +12 -0
  47. package/dist/gs/builtin/channel.js.map +1 -1
  48. package/dist/gs/builtin/slice.d.ts +22 -2
  49. package/dist/gs/builtin/slice.js +216 -44
  50. package/dist/gs/builtin/slice.js.map +1 -1
  51. package/dist/gs/builtin/type.d.ts +5 -2
  52. package/dist/gs/builtin/type.js +83 -24
  53. package/dist/gs/builtin/type.js.map +1 -1
  54. package/dist/gs/builtin/varRef.d.ts +5 -0
  55. package/dist/gs/builtin/varRef.js +23 -0
  56. package/dist/gs/builtin/varRef.js.map +1 -1
  57. package/dist/gs/bytes/buffer.gs.js +48 -44
  58. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  59. package/dist/gs/bytes/reader.gs.js +20 -18
  60. package/dist/gs/bytes/reader.gs.js.map +1 -1
  61. package/dist/gs/context/context.d.ts +5 -4
  62. package/dist/gs/context/context.js +10 -10
  63. package/dist/gs/context/context.js.map +1 -1
  64. package/dist/gs/crypto/internal/fips140deps/byteorder/index.d.ts +1 -0
  65. package/dist/gs/crypto/internal/fips140deps/byteorder/index.js +2 -0
  66. package/dist/gs/crypto/internal/fips140deps/byteorder/index.js.map +1 -0
  67. package/dist/gs/crypto/internal/fips140deps/godebug/index.d.ts +1 -0
  68. package/dist/gs/crypto/internal/fips140deps/godebug/index.js +2 -0
  69. package/dist/gs/crypto/internal/fips140deps/godebug/index.js.map +1 -0
  70. package/dist/gs/embed/index.d.ts +7 -0
  71. package/dist/gs/embed/index.js +16 -0
  72. package/dist/gs/embed/index.js.map +1 -0
  73. package/dist/gs/encoding/json/index.d.ts +1 -0
  74. package/dist/gs/encoding/json/index.js +18 -0
  75. package/dist/gs/encoding/json/index.js.map +1 -1
  76. package/dist/gs/errors/errors.d.ts +4 -0
  77. package/dist/gs/errors/errors.js +81 -0
  78. package/dist/gs/errors/errors.js.map +1 -1
  79. package/dist/gs/fmt/fmt.d.ts +4 -4
  80. package/dist/gs/fmt/fmt.js +42 -11
  81. package/dist/gs/fmt/fmt.js.map +1 -1
  82. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +35 -0
  83. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +211 -1
  84. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  85. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.d.ts +189 -0
  86. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +825 -0
  87. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -0
  88. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +163 -0
  89. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +449 -0
  90. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +1 -0
  91. package/dist/gs/github.com/klauspost/compress/internal/le/index.d.ts +9 -0
  92. package/dist/gs/github.com/klauspost/compress/internal/le/index.js +71 -0
  93. package/dist/gs/github.com/klauspost/compress/internal/le/index.js.map +1 -0
  94. package/dist/gs/go/internal/scannerhooks/index.d.ts +3 -0
  95. package/dist/gs/go/internal/scannerhooks/index.js +5 -0
  96. package/dist/gs/go/internal/scannerhooks/index.js.map +1 -0
  97. package/dist/gs/go/scanner/index.d.ts +13 -0
  98. package/dist/gs/go/scanner/index.js +35 -0
  99. package/dist/gs/go/scanner/index.js.map +1 -1
  100. package/dist/gs/go/token/index.d.ts +156 -0
  101. package/dist/gs/go/token/index.js +500 -4
  102. package/dist/gs/go/token/index.js.map +1 -1
  103. package/dist/gs/internal/abi/index.d.ts +4 -0
  104. package/dist/gs/internal/abi/index.js +10 -0
  105. package/dist/gs/internal/abi/index.js.map +1 -1
  106. package/dist/gs/internal/bytealg/index.d.ts +2 -0
  107. package/dist/gs/internal/bytealg/index.js +14 -0
  108. package/dist/gs/internal/bytealg/index.js.map +1 -1
  109. package/dist/gs/internal/byteorder/index.d.ts +8 -2
  110. package/dist/gs/internal/byteorder/index.js +56 -25
  111. package/dist/gs/internal/byteorder/index.js.map +1 -1
  112. package/dist/gs/internal/godebug/index.d.ts +12 -0
  113. package/dist/gs/internal/godebug/index.js +30 -0
  114. package/dist/gs/internal/godebug/index.js.map +1 -0
  115. package/dist/gs/io/fs/index.d.ts +1 -0
  116. package/dist/gs/io/fs/index.js +1 -0
  117. package/dist/gs/io/fs/index.js.map +1 -1
  118. package/dist/gs/io/fs/readlink.d.ts +8 -0
  119. package/dist/gs/io/fs/readlink.js +64 -0
  120. package/dist/gs/io/fs/readlink.js.map +1 -0
  121. package/dist/gs/io/fs/walk.d.ts +3 -3
  122. package/dist/gs/io/fs/walk.js +7 -7
  123. package/dist/gs/io/fs/walk.js.map +1 -1
  124. package/dist/gs/io/io.d.ts +40 -6
  125. package/dist/gs/io/io.js +151 -26
  126. package/dist/gs/io/io.js.map +1 -1
  127. package/dist/gs/maps/iter.d.ts +3 -3
  128. package/dist/gs/maps/iter.js +3 -3
  129. package/dist/gs/maps/iter.js.map +1 -1
  130. package/dist/gs/maps/maps.d.ts +2 -2
  131. package/dist/gs/maps/maps.js +1 -1
  132. package/dist/gs/maps/maps.js.map +1 -1
  133. package/dist/gs/math/bits/index.d.ts +13 -4
  134. package/dist/gs/math/bits/index.js +66 -34
  135. package/dist/gs/math/bits/index.js.map +1 -1
  136. package/dist/gs/math/const.gs.d.ts +5 -5
  137. package/dist/gs/math/const.gs.js +4 -4
  138. package/dist/gs/math/const.gs.js.map +1 -1
  139. package/dist/gs/mime/index.d.ts +1 -0
  140. package/dist/gs/mime/index.js +50 -0
  141. package/dist/gs/mime/index.js.map +1 -0
  142. package/dist/gs/net/http/httptest/index.d.ts +11 -0
  143. package/dist/gs/net/http/httptest/index.js +21 -0
  144. package/dist/gs/net/http/httptest/index.js.map +1 -0
  145. package/dist/gs/net/http/index.d.ts +27 -0
  146. package/dist/gs/net/http/index.js +61 -0
  147. package/dist/gs/net/http/index.js.map +1 -0
  148. package/dist/gs/os/dir_unix.gs.js +2 -2
  149. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  150. package/dist/gs/os/types_js.gs.js.map +1 -1
  151. package/dist/gs/path/filepath/match.js +165 -3
  152. package/dist/gs/path/filepath/match.js.map +1 -1
  153. package/dist/gs/path/filepath/path.d.ts +3 -1
  154. package/dist/gs/path/filepath/path.js +133 -4
  155. package/dist/gs/path/filepath/path.js.map +1 -1
  156. package/dist/gs/path/path.d.ts +4 -1
  157. package/dist/gs/path/path.js +16 -4
  158. package/dist/gs/path/path.js.map +1 -1
  159. package/dist/gs/reflect/index.d.ts +1 -1
  160. package/dist/gs/reflect/index.js +1 -1
  161. package/dist/gs/reflect/index.js.map +1 -1
  162. package/dist/gs/reflect/map.js +3 -0
  163. package/dist/gs/reflect/map.js.map +1 -1
  164. package/dist/gs/reflect/type.d.ts +7 -4
  165. package/dist/gs/reflect/type.js +148 -7
  166. package/dist/gs/reflect/type.js.map +1 -1
  167. package/dist/gs/runtime/debug/index.d.ts +2 -0
  168. package/dist/gs/runtime/debug/index.js +8 -0
  169. package/dist/gs/runtime/debug/index.js.map +1 -0
  170. package/dist/gs/runtime/runtime.d.ts +35 -3
  171. package/dist/gs/runtime/runtime.js +72 -0
  172. package/dist/gs/runtime/runtime.js.map +1 -1
  173. package/dist/gs/slices/slices.d.ts +24 -5
  174. package/dist/gs/slices/slices.js +214 -5
  175. package/dist/gs/slices/slices.js.map +1 -1
  176. package/dist/gs/sort/slice.gs.d.ts +3 -3
  177. package/dist/gs/sort/slice.gs.js +6 -6
  178. package/dist/gs/sort/slice.gs.js.map +1 -1
  179. package/dist/gs/sort/sort.gs.d.ts +4 -4
  180. package/dist/gs/sort/sort.gs.js +11 -8
  181. package/dist/gs/sort/sort.gs.js.map +1 -1
  182. package/dist/gs/strings/builder.d.ts +1 -1
  183. package/dist/gs/strings/builder.js +3 -2
  184. package/dist/gs/strings/builder.js.map +1 -1
  185. package/dist/gs/sync/atomic/type.gs.d.ts +9 -8
  186. package/dist/gs/sync/atomic/type.gs.js +0 -2
  187. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  188. package/dist/gs/sync/sync.d.ts +2 -0
  189. package/dist/gs/sync/sync.js +27 -0
  190. package/dist/gs/sync/sync.js.map +1 -1
  191. package/dist/gs/syscall/constants.d.ts +36 -24
  192. package/dist/gs/syscall/constants.js +12 -0
  193. package/dist/gs/syscall/constants.js.map +1 -1
  194. package/dist/gs/syscall/errors.d.ts +2 -0
  195. package/dist/gs/syscall/errors.js +8 -0
  196. package/dist/gs/syscall/errors.js.map +1 -1
  197. package/dist/gs/syscall/fs.d.ts +43 -0
  198. package/dist/gs/syscall/fs.js +102 -0
  199. package/dist/gs/syscall/fs.js.map +1 -1
  200. package/dist/gs/syscall/js/index.d.ts +90 -0
  201. package/dist/gs/syscall/js/index.js +375 -0
  202. package/dist/gs/syscall/js/index.js.map +1 -0
  203. package/dist/gs/syscall/types.d.ts +22 -0
  204. package/dist/gs/syscall/types.js +45 -1
  205. package/dist/gs/syscall/types.js.map +1 -1
  206. package/dist/gs/testing/index.d.ts +1 -0
  207. package/dist/gs/testing/index.js +2 -0
  208. package/dist/gs/testing/index.js.map +1 -0
  209. package/dist/gs/testing/testing.d.ts +77 -0
  210. package/dist/gs/testing/testing.js +301 -0
  211. package/dist/gs/testing/testing.js.map +1 -0
  212. package/dist/gs/time/time.d.ts +41 -4
  213. package/dist/gs/time/time.js +205 -36
  214. package/dist/gs/time/time.js.map +1 -1
  215. package/dist/gs/unicode/unicode.d.ts +23 -1
  216. package/dist/gs/unicode/unicode.js +79 -10
  217. package/dist/gs/unicode/unicode.js.map +1 -1
  218. package/dist/gs/unicode/utf8/utf8.d.ts +4 -4
  219. package/dist/gs/unicode/utf8/utf8.js +24 -11
  220. package/dist/gs/unicode/utf8/utf8.js.map +1 -1
  221. package/dist/gs/unique/index.d.ts +11 -0
  222. package/dist/gs/unique/index.js +71 -0
  223. package/dist/gs/unique/index.js.map +1 -0
  224. package/go.sum +9 -0
  225. package/gs/builtin/builtin.ts +239 -8
  226. package/gs/builtin/channel.ts +22 -0
  227. package/gs/builtin/runtime-contract.test.ts +126 -0
  228. package/gs/builtin/slice.ts +259 -50
  229. package/gs/builtin/type.ts +109 -34
  230. package/gs/builtin/varRef.ts +38 -1
  231. package/gs/bytes/buffer.gs.ts +48 -44
  232. package/gs/bytes/meta.json +8 -3
  233. package/gs/bytes/reader.gs.ts +20 -19
  234. package/gs/context/context.test.ts +41 -0
  235. package/gs/context/context.ts +22 -26
  236. package/gs/crypto/internal/fips140deps/byteorder/index.ts +1 -0
  237. package/gs/crypto/internal/fips140deps/godebug/index.ts +1 -0
  238. package/gs/embed/index.ts +20 -0
  239. package/gs/embed/meta.json +5 -0
  240. package/gs/encoding/json/index.test.ts +15 -1
  241. package/gs/encoding/json/index.ts +24 -0
  242. package/gs/errors/errors.test.ts +82 -0
  243. package/gs/errors/errors.ts +104 -0
  244. package/gs/fmt/fmt.ts +56 -16
  245. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +73 -1
  246. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +297 -1
  247. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +159 -0
  248. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +1005 -0
  249. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +719 -0
  250. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +40 -0
  251. package/gs/github.com/klauspost/compress/internal/le/index.test.ts +36 -0
  252. package/gs/github.com/klauspost/compress/internal/le/index.ts +114 -0
  253. package/gs/go/internal/scannerhooks/index.test.ts +14 -0
  254. package/gs/go/internal/scannerhooks/index.ts +9 -0
  255. package/gs/go/scanner/index.test.ts +22 -0
  256. package/gs/go/scanner/index.ts +47 -0
  257. package/gs/go/token/index.test.ts +47 -1
  258. package/gs/go/token/index.ts +570 -4
  259. package/gs/internal/abi/index.test.ts +18 -0
  260. package/gs/internal/abi/index.ts +14 -0
  261. package/gs/internal/bytealg/index.test.ts +18 -0
  262. package/gs/internal/bytealg/index.ts +16 -0
  263. package/gs/internal/byteorder/index.test.ts +39 -0
  264. package/gs/internal/byteorder/index.ts +100 -27
  265. package/gs/internal/godebug/index.test.ts +16 -0
  266. package/gs/internal/godebug/index.ts +35 -0
  267. package/gs/io/fs/index.ts +1 -0
  268. package/gs/io/fs/meta.json +5 -0
  269. package/gs/io/fs/readlink.test.ts +43 -0
  270. package/gs/io/fs/readlink.ts +77 -0
  271. package/gs/io/fs/walk.test.ts +61 -0
  272. package/gs/io/fs/walk.ts +9 -9
  273. package/gs/io/io.ts +174 -31
  274. package/gs/io/meta.json +10 -2
  275. package/gs/maps/iter.ts +12 -6
  276. package/gs/maps/maps.ts +8 -6
  277. package/gs/math/bits/index.ts +103 -47
  278. package/gs/math/const.gs.test.ts +11 -5
  279. package/gs/math/const.gs.ts +5 -6
  280. package/gs/mime/index.ts +54 -0
  281. package/gs/net/http/httptest/index.ts +25 -0
  282. package/gs/net/http/index.test.ts +20 -0
  283. package/gs/net/http/index.ts +81 -0
  284. package/gs/os/dir_unix.gs.ts +2 -3
  285. package/gs/os/types_js.gs.ts +2 -2
  286. package/gs/path/filepath/match.test.ts +31 -12
  287. package/gs/path/filepath/match.ts +178 -3
  288. package/gs/path/filepath/path.test.ts +25 -0
  289. package/gs/path/filepath/path.ts +159 -5
  290. package/gs/path/path.ts +20 -5
  291. package/gs/reflect/index.ts +1 -0
  292. package/gs/reflect/map.test.ts +19 -0
  293. package/gs/reflect/map.ts +4 -0
  294. package/gs/reflect/type.ts +197 -17
  295. package/gs/runtime/debug/index.test.ts +24 -0
  296. package/gs/runtime/debug/index.ts +8 -0
  297. package/gs/runtime/runtime.test.ts +19 -0
  298. package/gs/runtime/runtime.ts +98 -3
  299. package/gs/slices/slices.test.ts +94 -0
  300. package/gs/slices/slices.ts +245 -5
  301. package/gs/sort/meta.json +7 -0
  302. package/gs/sort/slice.gs.ts +16 -7
  303. package/gs/sort/sort.gs.ts +16 -13
  304. package/gs/strings/builder.ts +4 -3
  305. package/gs/sync/atomic/type.gs.ts +13 -14
  306. package/gs/sync/meta.json +3 -1
  307. package/gs/sync/sync.test.ts +13 -1
  308. package/gs/sync/sync.ts +27 -0
  309. package/gs/syscall/constants.ts +39 -24
  310. package/gs/syscall/errors.ts +10 -0
  311. package/gs/syscall/fs.ts +195 -0
  312. package/gs/syscall/js/index.ts +458 -0
  313. package/gs/syscall/js/meta.json +4 -0
  314. package/gs/syscall/net.test.ts +85 -0
  315. package/gs/syscall/types.ts +56 -0
  316. package/gs/testing/index.ts +1 -0
  317. package/gs/testing/meta.json +5 -0
  318. package/gs/testing/testing.test.ts +90 -0
  319. package/gs/testing/testing.ts +382 -0
  320. package/gs/time/time.test.ts +106 -0
  321. package/gs/time/time.ts +278 -57
  322. package/gs/unicode/unicode.test.ts +25 -0
  323. package/gs/unicode/unicode.ts +119 -9
  324. package/gs/unicode/utf8/utf8.test.ts +13 -0
  325. package/gs/unicode/utf8/utf8.ts +28 -16
  326. package/gs/unique/index.ts +91 -0
  327. package/package.json +2 -1
@@ -0,0 +1,588 @@
1
+ package gotest
2
+
3
+ import (
4
+ "context"
5
+ "os"
6
+ "path/filepath"
7
+ "regexp"
8
+ "slices"
9
+ "strconv"
10
+ "strings"
11
+
12
+ "github.com/aperturerobotics/goscript/compiler"
13
+ "github.com/aperturerobotics/goscript/compiler/tsworkspace"
14
+ "github.com/pkg/errors"
15
+ )
16
+
17
+ // Runner owns GoScript package-test loading, compilation, typecheck, and execution.
18
+ type Runner struct {
19
+ service *compiler.CompileService
20
+ }
21
+
22
+ // NewRunner creates a package-test runner.
23
+ func NewRunner() *Runner {
24
+ return &Runner{service: compiler.NewCompileService()}
25
+ }
26
+
27
+ // Run executes package tests through the GoScript compiler and TypeScript runtime.
28
+ func (r *Runner) Run(ctx context.Context, req *Request) (*Result, error) {
29
+ if r == nil {
30
+ r = NewRunner()
31
+ }
32
+ norm, err := req.normalize()
33
+ if err != nil {
34
+ return nil, err
35
+ }
36
+ if norm.Timeout != 0 {
37
+ var cancel context.CancelFunc
38
+ ctx, cancel = context.WithTimeout(ctx, norm.Timeout)
39
+ defer cancel()
40
+ }
41
+ if err := ctx.Err(); err != nil {
42
+ return nil, err
43
+ }
44
+ if norm.WorkDir == "" {
45
+ workRoot := filepath.Join(norm.Dir, ".tmp")
46
+ if err := os.MkdirAll(workRoot, 0o755); err != nil {
47
+ return nil, errors.Wrap(err, "create goscript test work root")
48
+ }
49
+ norm.WorkDir, err = os.MkdirTemp(workRoot, "goscript-test-")
50
+ if err != nil {
51
+ return nil, errors.Wrap(err, "create goscript test work directory")
52
+ }
53
+ }
54
+ if norm.OutputRoot == "" {
55
+ norm.OutputRoot = filepath.Join(norm.WorkDir, "output")
56
+ }
57
+
58
+ result := &Result{
59
+ WorkDir: norm.WorkDir,
60
+ OutputRoot: norm.OutputRoot,
61
+ }
62
+ workspace := tsworkspace.NewOwner(norm.WorkDir, norm.Dir)
63
+
64
+ runPattern, err := compileRunPattern(norm.Run)
65
+ if err != nil {
66
+ diag := compiler.Diagnostic{
67
+ Severity: compiler.DiagnosticSeverityError,
68
+ Code: "goscript/gotest:run-pattern",
69
+ Message: "invalid -run pattern",
70
+ Detail: err.Error(),
71
+ }
72
+ result.Diagnostics = append(result.Diagnostics, diag)
73
+ markAllFailures(result, OwnerPackageGraph, compiler.NewCompileError([]compiler.Diagnostic{diag}).Error())
74
+ return result, nil
75
+ }
76
+
77
+ testGraphReq := &compiler.CompileRequest{
78
+ Patterns: append([]string(nil), norm.Patterns...),
79
+ Dir: norm.Dir,
80
+ OutputPath: norm.OutputRoot,
81
+ BuildFlags: append([]string(nil), norm.BuildFlags...),
82
+ DependencyMode: compiler.DependencyModeRequested,
83
+ RuntimeEmissionMode: compiler.RuntimeEmissionModeEmit,
84
+ Tests: true,
85
+ }
86
+ testGraph, loadDiagnostics := r.service.PackageGraphOwner().LoadTestGraph(ctx, testGraphReq)
87
+ result.Diagnostics = append(result.Diagnostics, loadDiagnostics...)
88
+ result.Packages = packageResults(testGraph, runPattern)
89
+ if diagnosticsHaveErrors(loadDiagnostics) && len(result.Packages) == 0 {
90
+ markAllFailures(result, OwnerPackageGraph, diagnosticsSummary(loadDiagnostics))
91
+ return result, nil
92
+ }
93
+
94
+ for idx := range result.Packages {
95
+ if !shouldCompilePackage(result.Packages[idx]) {
96
+ continue
97
+ }
98
+ outputRoot := packageOutputRoot(norm, idx)
99
+ compileReq := &compiler.CompileRequest{
100
+ Patterns: []string{result.Packages[idx].PackagePath},
101
+ Dir: norm.Dir,
102
+ OutputPath: outputRoot,
103
+ BuildFlags: append([]string(nil), norm.BuildFlags...),
104
+ DependencyMode: compiler.DependencyModeAll,
105
+ RuntimeEmissionMode: compiler.RuntimeEmissionModeEmit,
106
+ Tests: false,
107
+ AllDependencies: true,
108
+ }
109
+ if compileResult, compileErr := r.service.Compile(ctx, compileReq); compileErr != nil {
110
+ result.Packages[idx].Action = ActionFail
111
+ if compileResult != nil {
112
+ result.Diagnostics = append(result.Diagnostics, compileResult.Diagnostics...)
113
+ result.Packages[idx].Owner = classifyDiagnostics(compileResult.Diagnostics)
114
+ }
115
+ markCompilePhase(&result.Packages[idx], compileResult, false)
116
+ result.Packages[idx].Error = compileErr.Error()
117
+ continue
118
+ } else if compileResult != nil {
119
+ result.Diagnostics = append(result.Diagnostics, compileResult.Diagnostics...)
120
+ markCompilePhase(&result.Packages[idx], compileResult, true)
121
+ }
122
+ if !r.compileTestImports(ctx, norm, outputRoot, &result.Packages[idx], result) {
123
+ continue
124
+ }
125
+ testCompileReq := &compiler.CompileRequest{
126
+ Patterns: []string{result.Packages[idx].PackagePath},
127
+ Dir: norm.Dir,
128
+ OutputPath: outputRoot,
129
+ BuildFlags: append([]string(nil), norm.BuildFlags...),
130
+ DependencyMode: compiler.DependencyModeAll,
131
+ RuntimeEmissionMode: compiler.RuntimeEmissionModeEmit,
132
+ Tests: true,
133
+ AllDependencies: true,
134
+ }
135
+ if compileResult, compileErr := r.service.Compile(ctx, testCompileReq); compileErr != nil {
136
+ result.Packages[idx].Action = ActionFail
137
+ if compileResult != nil {
138
+ result.Diagnostics = append(result.Diagnostics, compileResult.Diagnostics...)
139
+ result.Packages[idx].Owner = classifyDiagnostics(compileResult.Diagnostics)
140
+ }
141
+ markCompilePhase(&result.Packages[idx], compileResult, false)
142
+ result.Packages[idx].Error = compileErr.Error()
143
+ continue
144
+ } else if compileResult != nil {
145
+ result.Diagnostics = append(result.Diagnostics, compileResult.Diagnostics...)
146
+ markCompilePhase(&result.Packages[idx], compileResult, true)
147
+ }
148
+ }
149
+
150
+ if phase := workspace.EnsurePackageJSON(); phase.Failed() {
151
+ markAllFailures(result, OwnerTestRunner, phase.Error)
152
+ return result, nil
153
+ }
154
+ nodeTypesAvailable := tsworkspace.NodeTypesPresent(norm.WorkDir, norm.Dir)
155
+ if phase := workspace.EnsureNodeAmbientTypes(); phase.Failed() {
156
+ markAllFailures(result, OwnerTestRunner, phase.Error)
157
+ return result, nil
158
+ }
159
+ for idx := range result.Packages {
160
+ if !shouldCompilePackage(result.Packages[idx]) {
161
+ continue
162
+ }
163
+ result.Packages[idx].Phases.Workspace = PhaseStatusPass
164
+ outputRoot := packageOutputRoot(norm, idx)
165
+ runnerFile := packageRunnerFile(idx)
166
+ if phase := workspace.WriteFile(tsworkspace.PhaseWorkspace, runnerFile, renderRunner(result.Packages[idx], norm)); phase.Failed() {
167
+ result.Packages[idx].Owner = OwnerTestRunner
168
+ result.Packages[idx].Phases.Workspace = PhaseStatusFail
169
+ result.Packages[idx].Error = phase.Error
170
+ continue
171
+ }
172
+ tsconfigFile := "tsconfig.json"
173
+ if phase := workspace.WriteFile(tsworkspace.PhaseWorkspace, tsconfigFile, renderTypeScriptProject(norm, outputRoot, runnerFile, nodeTypesAvailable)); phase.Failed() {
174
+ result.Packages[idx].Owner = OwnerTestRunner
175
+ result.Packages[idx].Phases.Workspace = PhaseStatusFail
176
+ result.Packages[idx].Error = phase.Error
177
+ continue
178
+ }
179
+ typecheck := workspace.RunTool(ctx, tsworkspace.PhaseTypeCheck, norm.WorkDir, "tsgo", "--project", tsconfigFile)
180
+ if typecheck.Failed() {
181
+ result.Packages[idx].Owner = classifyProcessOutput(typecheck.Output)
182
+ result.Packages[idx].Phases.TypeCheck = PhaseStatusFail
183
+ result.Packages[idx].Error = processErrorText(typecheck)
184
+ continue
185
+ }
186
+ result.Packages[idx].Phases.TypeCheck = PhaseStatusPass
187
+ runtime := workspace.RunTool(ctx, tsworkspace.PhaseRuntime, norm.WorkDir, "bun", runnerFile)
188
+ result.Packages[idx].Elapsed = runtime.Elapsed
189
+ result.Packages[idx].Output = strings.TrimSpace(runtime.Output)
190
+ if runtime.Failed() {
191
+ result.Packages[idx].Action = ActionFail
192
+ result.Packages[idx].Owner = classifyProcessOutput(runtime.Output)
193
+ result.Packages[idx].Phases.Runtime = PhaseStatusFail
194
+ result.Packages[idx].Error = runtime.Error
195
+ continue
196
+ }
197
+ result.Packages[idx].Phases.Runtime = PhaseStatusPass
198
+ result.Packages[idx].Action = ActionPass
199
+ }
200
+ return result, nil
201
+ }
202
+
203
+ func (r *Runner) compileTestImports(
204
+ ctx context.Context,
205
+ req *normalizedRequest,
206
+ outputRoot string,
207
+ pkg *PackageResult,
208
+ result *Result,
209
+ ) bool {
210
+ imports := append([]string(nil), pkg.TestImports...)
211
+ slices.Sort(imports)
212
+ imports = slices.Compact(imports)
213
+ for _, importPath := range imports {
214
+ if importPath == "" || importPath == pkg.PackagePath {
215
+ continue
216
+ }
217
+ compileReq := &compiler.CompileRequest{
218
+ Patterns: []string{importPath},
219
+ Dir: req.Dir,
220
+ OutputPath: outputRoot,
221
+ BuildFlags: append([]string(nil), req.BuildFlags...),
222
+ DependencyMode: compiler.DependencyModeAll,
223
+ RuntimeEmissionMode: compiler.RuntimeEmissionModeEmit,
224
+ Tests: false,
225
+ AllDependencies: true,
226
+ }
227
+ compileResult, compileErr := r.service.Compile(ctx, compileReq)
228
+ if compileResult != nil {
229
+ result.Diagnostics = append(result.Diagnostics, compileResult.Diagnostics...)
230
+ }
231
+ if compileErr != nil {
232
+ pkg.Action = ActionFail
233
+ if compileResult != nil {
234
+ pkg.Owner = classifyDiagnostics(compileResult.Diagnostics)
235
+ }
236
+ markCompilePhase(pkg, compileResult, false)
237
+ pkg.Error = compileErr.Error()
238
+ return false
239
+ }
240
+ markCompilePhase(pkg, compileResult, true)
241
+ }
242
+ return true
243
+ }
244
+
245
+ func compileRunPattern(pattern string) (*regexp.Regexp, error) {
246
+ pattern = strings.TrimSpace(pattern)
247
+ if pattern == "" {
248
+ return nil, nil
249
+ }
250
+ return regexp.Compile(pattern)
251
+ }
252
+
253
+ func packageResults(testGraph *compiler.PackageTestGraph, runPattern *regexp.Regexp) []PackageResult {
254
+ if testGraph == nil {
255
+ return nil
256
+ }
257
+ results := make([]PackageResult, 0, len(testGraph.Packages))
258
+ for _, pkg := range testGraph.Packages {
259
+ result := newSkippedPackageResult(pkg.PackagePath)
260
+ result.Tests = append(result.Tests, packageVariantTests(pkg.SamePackageTests, runPattern)...)
261
+ result.Tests = append(result.Tests, packageVariantTests(pkg.ExternalPackageTests, runPattern)...)
262
+ result.TestImports = packageTestImports(pkg)
263
+ slices.SortFunc(result.Tests, func(a, b Test) int {
264
+ if a.Name == b.Name {
265
+ return strings.Compare(a.PackagePath, b.PackagePath)
266
+ }
267
+ return strings.Compare(a.Name, b.Name)
268
+ })
269
+ if len(result.Tests) != 0 {
270
+ result.TestPackagePath = result.Tests[0].PackagePath
271
+ result.Action = ActionFail
272
+ result.Phases = PackagePhases{}
273
+ }
274
+ if diagnosticsHaveErrors(pkg.Diagnostics) {
275
+ result.Action = ActionFail
276
+ result.Owner = OwnerPackageGraph
277
+ result.Error = diagnosticsSummary(pkg.Diagnostics)
278
+ result.Phases = failurePhases(OwnerPackageGraph)
279
+ }
280
+ results = append(results, result)
281
+ }
282
+ return results
283
+ }
284
+
285
+ func newSkippedPackageResult(packagePath string) PackageResult {
286
+ return PackageResult{
287
+ PackagePath: packagePath,
288
+ Action: ActionSkip,
289
+ Phases: PackagePhases{
290
+ Workspace: PhaseStatusSkip,
291
+ Compile: PhaseStatusSkip,
292
+ Emit: PhaseStatusSkip,
293
+ TypeCheck: PhaseStatusSkip,
294
+ Runtime: PhaseStatusSkip,
295
+ },
296
+ }
297
+ }
298
+
299
+ func packageTestImports(pkg *compiler.PackageTestGraphPackage) []string {
300
+ importSet := make(map[string]bool)
301
+ for _, variant := range []*compiler.PackageTestGraphVariant{pkg.SamePackageTests, pkg.ExternalPackageTests} {
302
+ if variant == nil {
303
+ continue
304
+ }
305
+ for _, importPath := range variant.Imports {
306
+ importSet[importPath] = true
307
+ }
308
+ }
309
+ imports := make([]string, 0, len(importSet))
310
+ for importPath := range importSet {
311
+ imports = append(imports, importPath)
312
+ }
313
+ slices.Sort(imports)
314
+ return imports
315
+ }
316
+
317
+ func packageVariantTests(variant *compiler.PackageTestGraphVariant, runPattern *regexp.Regexp) []Test {
318
+ if variant == nil {
319
+ return nil
320
+ }
321
+ tests := make([]Test, 0, len(variant.Tests))
322
+ for _, test := range variant.Tests {
323
+ if runPattern != nil && !runPattern.MatchString(test.Name) {
324
+ continue
325
+ }
326
+ tests = append(tests, Test{
327
+ Name: test.Name,
328
+ PackagePath: test.PackagePath,
329
+ })
330
+ }
331
+ return tests
332
+ }
333
+
334
+ func shouldCompilePackage(result PackageResult) bool {
335
+ return result.Action != ActionSkip && result.Owner == "" && result.Error == ""
336
+ }
337
+
338
+ func markAllFailures(result *Result, owner Owner, message string) {
339
+ message = strings.TrimSpace(message)
340
+ if result == nil {
341
+ return
342
+ }
343
+ if len(result.Packages) == 0 {
344
+ result.Packages = append(result.Packages, PackageResult{
345
+ PackagePath: "package-patterns",
346
+ Action: ActionFail,
347
+ Owner: owner,
348
+ Error: message,
349
+ Phases: failurePhases(owner),
350
+ })
351
+ return
352
+ }
353
+ for idx := range result.Packages {
354
+ if result.Packages[idx].Action == ActionSkip {
355
+ continue
356
+ }
357
+ if result.Packages[idx].Action == ActionFail && (result.Packages[idx].Owner != "" || result.Packages[idx].Error != "") {
358
+ continue
359
+ }
360
+ result.Packages[idx].Action = ActionFail
361
+ result.Packages[idx].Owner = owner
362
+ result.Packages[idx].Error = message
363
+ result.Packages[idx].Phases = failurePhases(owner)
364
+ }
365
+ }
366
+
367
+ func failurePhases(owner Owner) PackagePhases {
368
+ if owner == OwnerPackageGraph {
369
+ return PackagePhases{
370
+ Workspace: PhaseStatusSkip,
371
+ Compile: PhaseStatusFail,
372
+ Emit: PhaseStatusSkip,
373
+ TypeCheck: PhaseStatusSkip,
374
+ Runtime: PhaseStatusSkip,
375
+ }
376
+ }
377
+ return PackagePhases{
378
+ Workspace: PhaseStatusFail,
379
+ Compile: PhaseStatusSkip,
380
+ Emit: PhaseStatusSkip,
381
+ TypeCheck: PhaseStatusSkip,
382
+ Runtime: PhaseStatusSkip,
383
+ }
384
+ }
385
+
386
+ func packageOutputRoot(req *normalizedRequest, idx int) string {
387
+ return filepath.Join(req.OutputRoot, "package-"+strconv.Itoa(idx))
388
+ }
389
+
390
+ func packageRunnerFile(idx int) string {
391
+ return "runner-" + strconv.Itoa(idx) + ".ts"
392
+ }
393
+
394
+ func renderRunner(result PackageResult, req *normalizedRequest) string {
395
+ var b strings.Builder
396
+ b.WriteString("import { runTests } from \"@goscript/testing/index.js\"\n")
397
+ imports := runnerImports(result.Tests)
398
+ for idx, packagePath := range imports {
399
+ b.WriteString("import * as pkg")
400
+ b.WriteString(strconv.Itoa(idx))
401
+ b.WriteString(" from ")
402
+ b.WriteString(strconv.Quote("@goscript/" + packagePath + "/index.js"))
403
+ b.WriteString("\n")
404
+ }
405
+ b.WriteString("\n")
406
+ b.WriteString("const result = await runTests(")
407
+ b.WriteString(strconv.Quote(result.PackagePath))
408
+ b.WriteString(", [\n")
409
+ for idx, test := range result.Tests {
410
+ b.WriteString("\t{ name: ")
411
+ b.WriteString(strconv.Quote(test.Name))
412
+ b.WriteString(", fn: async (t) => await pkg")
413
+ b.WriteString(strconv.Itoa(slices.Index(imports, test.PackagePath)))
414
+ b.WriteString(".")
415
+ b.WriteString(test.Name)
416
+ b.WriteString("(t) }")
417
+ if idx != len(result.Tests)-1 {
418
+ b.WriteString(",")
419
+ }
420
+ b.WriteString("\n")
421
+ }
422
+ b.WriteString("], { verbose: ")
423
+ if req.Verbose {
424
+ b.WriteString("true")
425
+ } else {
426
+ b.WriteString("false")
427
+ }
428
+ b.WriteString(", count: ")
429
+ b.WriteString(strconv.Itoa(req.Count))
430
+ b.WriteString(", short: ")
431
+ if req.Short {
432
+ b.WriteString("true")
433
+ } else {
434
+ b.WriteString("false")
435
+ }
436
+ b.WriteString(" })\n")
437
+ b.WriteString("if (!result.ok) {\n\tthrow new Error(\"goscript test failed\")\n}\n")
438
+ return b.String()
439
+ }
440
+
441
+ func runnerImports(tests []Test) []string {
442
+ seen := make(map[string]bool)
443
+ var imports []string
444
+ for _, test := range tests {
445
+ if test.PackagePath == "" || seen[test.PackagePath] {
446
+ continue
447
+ }
448
+ seen[test.PackagePath] = true
449
+ imports = append(imports, test.PackagePath)
450
+ }
451
+ slices.Sort(imports)
452
+ return imports
453
+ }
454
+
455
+ func processErrorText(result tsworkspace.Result) string {
456
+ output := strings.TrimSpace(result.Output)
457
+ if output != "" {
458
+ return output
459
+ }
460
+ return result.Error
461
+ }
462
+
463
+ func renderTypeScriptProject(req *normalizedRequest, outputRoot string, runnerFile string, nodeTypesAvailable bool) string {
464
+ outputPattern := filepath.ToSlash(outputRoot)
465
+ outputAlias := filepath.ToSlash(filepath.Join(outputRoot, "@goscript", "*"))
466
+ if rel, err := filepath.Rel(req.WorkDir, outputRoot); err == nil {
467
+ outputPattern = filepath.ToSlash(rel)
468
+ outputAlias = filepath.ToSlash(filepath.Join(rel, "@goscript", "*"))
469
+ }
470
+ var b strings.Builder
471
+ b.WriteString("{\n")
472
+ b.WriteString(" \"compilerOptions\": {\n")
473
+ b.WriteString(" \"target\": \"ES2022\",\n")
474
+ b.WriteString(" \"module\": \"ESNext\",\n")
475
+ b.WriteString(" \"moduleResolution\": \"Bundler\",\n")
476
+ b.WriteString(" \"lib\": [\"ESNext\", \"DOM\"],\n")
477
+ b.WriteString(" \"strict\": true,\n")
478
+ b.WriteString(" \"allowImportingTsExtensions\": true,\n")
479
+ b.WriteString(" \"noEmit\": true,\n")
480
+ if nodeTypesAvailable {
481
+ b.WriteString(" \"types\": [\"node\"],\n")
482
+ } else {
483
+ b.WriteString(" \"types\": [],\n")
484
+ }
485
+ b.WriteString(" \"paths\": {\n")
486
+ b.WriteString(" \"*\": [\"./*\"],\n")
487
+ b.WriteString(" \"@goscript/*\": [")
488
+ b.WriteString(strconv.Quote("./" + outputAlias))
489
+ b.WriteString("]\n")
490
+ b.WriteString(" }\n")
491
+ b.WriteString(" },\n")
492
+ b.WriteString(" \"include\": [")
493
+ b.WriteString(strconv.Quote(outputPattern + "/**/*.ts"))
494
+ b.WriteString(", ")
495
+ b.WriteString(strconv.Quote(runnerFile))
496
+ b.WriteString(", ")
497
+ b.WriteString(strconv.Quote(tsworkspace.NodeAmbientTypesFile))
498
+ b.WriteString("]\n")
499
+ b.WriteString("}\n")
500
+ return b.String()
501
+ }
502
+
503
+ func markCompilePhase(pkg *PackageResult, result *compiler.CompilationResult, passed bool) {
504
+ if pkg == nil {
505
+ return
506
+ }
507
+ if passed {
508
+ pkg.Phases.Compile = PhaseStatusPass
509
+ pkg.Phases.Emit = PhaseStatusPass
510
+ return
511
+ }
512
+ if classifyDiagnostics(resultDiagnostics(result)) == OwnerTypeScriptEmitter {
513
+ pkg.Phases.Compile = PhaseStatusPass
514
+ pkg.Phases.Emit = PhaseStatusFail
515
+ return
516
+ }
517
+ pkg.Phases.Compile = PhaseStatusFail
518
+ pkg.Phases.Emit = PhaseStatusSkip
519
+ }
520
+
521
+ func resultDiagnostics(result *compiler.CompilationResult) []compiler.Diagnostic {
522
+ if result == nil {
523
+ return nil
524
+ }
525
+ return result.Diagnostics
526
+ }
527
+
528
+ func classifyDiagnostics(diagnostics []compiler.Diagnostic) Owner {
529
+ for _, diagnostic := range diagnostics {
530
+ switch {
531
+ case strings.HasPrefix(diagnostic.Code, "goscript/package-graph"):
532
+ return OwnerPackageGraph
533
+ case strings.HasPrefix(diagnostic.Code, "goscript/semantic"):
534
+ return OwnerSemanticModel
535
+ case strings.HasPrefix(diagnostic.Code, "goscript/lowering"):
536
+ return OwnerLowering
537
+ case strings.HasPrefix(diagnostic.Code, "goscript/emitter"):
538
+ return OwnerTypeScriptEmitter
539
+ case strings.HasPrefix(diagnostic.Code, "goscript/overrides"):
540
+ return OwnerOverridePackage
541
+ case strings.HasPrefix(diagnostic.Code, "goscript/runtime"):
542
+ return OwnerRuntimePackage
543
+ }
544
+ }
545
+ return OwnerTestRunner
546
+ }
547
+
548
+ func classifyProcessOutput(output string) Owner {
549
+ switch {
550
+ case strings.Contains(output, "@goscript/testing") || strings.Contains(output, "@goscript/"):
551
+ return OwnerOverridePackage
552
+ case strings.Contains(output, "TypeScript") || strings.Contains(output, "TS"):
553
+ return OwnerTypeScriptEmitter
554
+ case strings.Contains(output, "panic") || strings.Contains(output, "runtime"):
555
+ return OwnerRuntimePackage
556
+ default:
557
+ return OwnerTestRunner
558
+ }
559
+ }
560
+
561
+ func diagnosticsHaveErrors(diagnostics []compiler.Diagnostic) bool {
562
+ for _, diagnostic := range diagnostics {
563
+ if diagnostic.Severity == compiler.DiagnosticSeverityError {
564
+ return true
565
+ }
566
+ }
567
+ return false
568
+ }
569
+
570
+ func diagnosticsSummary(diagnostics []compiler.Diagnostic) string {
571
+ var b strings.Builder
572
+ for idx, diagnostic := range diagnostics {
573
+ if idx != 0 {
574
+ b.WriteString("; ")
575
+ }
576
+ if diagnostic.Code != "" {
577
+ b.WriteString(diagnostic.Code)
578
+ b.WriteString(": ")
579
+ }
580
+ b.WriteString(diagnostic.Message)
581
+ if diagnostic.Detail != "" {
582
+ b.WriteString(" (")
583
+ b.WriteString(diagnostic.Detail)
584
+ b.WriteString(")")
585
+ }
586
+ }
587
+ return b.String()
588
+ }