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,307 @@
1
+ package compiler
2
+
3
+ import (
4
+ "bytes"
5
+ "context"
6
+ "errors"
7
+ "io"
8
+ "io/fs"
9
+ "maps"
10
+ "path"
11
+ "slices"
12
+ "strings"
13
+
14
+ gs "github.com/aperturerobotics/goscript"
15
+ jsoniter "github.com/aperturerobotics/json-iterator-lite"
16
+ )
17
+
18
+ // OverrideFacts is the immutable compiler-visible view of GoScript overrides.
19
+ type OverrideFacts struct {
20
+ packages map[string]overridePackageFacts
21
+ }
22
+
23
+ type overridePackageFacts struct {
24
+ metadata OverrideMetadata
25
+ copyPackage overrideCopyPackage
26
+ dependencies []string
27
+ }
28
+
29
+ // HasPackage returns true when pkgPath has a GoScript override package.
30
+ func (f *OverrideFacts) HasPackage(pkgPath string) bool {
31
+ if f == nil || pkgPath == "" {
32
+ return false
33
+ }
34
+ _, ok := f.packages[pkgPath]
35
+ return ok
36
+ }
37
+
38
+ // Metadata returns compiler-visible override metadata for a package path.
39
+ func (f *OverrideFacts) Metadata(pkgPath string) OverrideMetadata {
40
+ if f == nil {
41
+ return newOverrideMetadata()
42
+ }
43
+ pkg := f.packages[pkgPath]
44
+ return cloneOverrideMetadata(pkg.metadata)
45
+ }
46
+
47
+ // IsMethodAsync returns true when override metadata marks a method async.
48
+ func (f *OverrideFacts) IsMethodAsync(pkgPath, method string) bool {
49
+ if f == nil {
50
+ return false
51
+ }
52
+ pkg := f.packages[pkgPath]
53
+ return pkg.metadata.AsyncMethods[method]
54
+ }
55
+
56
+ // IsFunctionAsync returns true when override metadata marks a package-level function async.
57
+ func (f *OverrideFacts) IsFunctionAsync(pkgPath, function string) bool {
58
+ if f == nil {
59
+ return false
60
+ }
61
+ pkg := f.packages[pkgPath]
62
+ return pkg.metadata.AsyncFunctions[function]
63
+ }
64
+
65
+ func (f *OverrideFacts) copyPackage(pkgPath string) (overrideCopyPackage, []string, bool) {
66
+ if f == nil {
67
+ return overrideCopyPackage{}, nil, false
68
+ }
69
+ pkg, ok := f.packages[pkgPath]
70
+ if !ok {
71
+ return overrideCopyPackage{}, nil, false
72
+ }
73
+ return cloneOverrideCopyPackage(pkg.copyPackage), slices.Clone(pkg.dependencies), true
74
+ }
75
+
76
+ func (f *OverrideFacts) importPackageRoot(importPath string) (string, bool) {
77
+ if f == nil {
78
+ return "", false
79
+ }
80
+ importPath = strings.TrimPrefix(importPath, "@goscript/")
81
+ importPath = strings.TrimSuffix(importPath, ".js")
82
+ importPath = strings.TrimSuffix(importPath, ".ts")
83
+ if before, ok := strings.CutSuffix(importPath, "/index"); ok {
84
+ importPath = before
85
+ }
86
+ parts := strings.Split(importPath, "/")
87
+ for idx := len(parts); idx > 0; idx-- {
88
+ candidate := strings.Join(parts[:idx], "/")
89
+ if f.HasPackage(candidate) {
90
+ return candidate, true
91
+ }
92
+ }
93
+ return "", false
94
+ }
95
+
96
+ func buildOverrideFacts(ctx context.Context) (*OverrideFacts, []Diagnostic) {
97
+ roots, err := discoverOverridePackageRoots()
98
+ if err != nil {
99
+ return nil, []Diagnostic{overrideError("discover override packages", "", err)}
100
+ }
101
+ paths := make([]string, 0, len(roots))
102
+ for pkgPath := range roots {
103
+ paths = append(paths, pkgPath)
104
+ }
105
+ slices.Sort(paths)
106
+
107
+ facts := &OverrideFacts{packages: make(map[string]overridePackageFacts, len(paths))}
108
+ var diagnostics []Diagnostic
109
+ for _, pkgPath := range paths {
110
+ if err := ctx.Err(); err != nil {
111
+ return facts, []Diagnostic{contextCanceledDiagnostic(err)}
112
+ }
113
+ metadata, err := loadOverrideMetadata(pkgPath)
114
+ if err != nil {
115
+ diagnostics = append(diagnostics, overrideError("read override metadata", pkgPath, err))
116
+ continue
117
+ }
118
+ copyPackage, dependencies, packageDiagnostics := loadOverrideCopyPackage(pkgPath, roots, metadata)
119
+ diagnostics = append(diagnostics, packageDiagnostics...)
120
+ if diagnosticsHaveErrors(packageDiagnostics) {
121
+ continue
122
+ }
123
+ facts.packages[pkgPath] = overridePackageFacts{
124
+ metadata: cloneOverrideMetadata(metadata),
125
+ copyPackage: copyPackage,
126
+ dependencies: dependencies,
127
+ }
128
+ }
129
+ if diagnosticsHaveErrors(diagnostics) {
130
+ return facts, diagnostics
131
+ }
132
+ return facts, diagnostics
133
+ }
134
+
135
+ func discoverOverridePackageRoots() (map[string]bool, error) {
136
+ roots := make(map[string]bool)
137
+ if err := fs.WalkDir(gs.GsOverrides, "gs", func(filePath string, entry fs.DirEntry, err error) error {
138
+ if err != nil {
139
+ return err
140
+ }
141
+ if entry.IsDir() || path.Base(filePath) != "index.ts" {
142
+ return nil
143
+ }
144
+ pkgPath := strings.TrimPrefix(path.Dir(filePath), "gs/")
145
+ if pkgPath != "." && pkgPath != "" {
146
+ roots[pkgPath] = true
147
+ }
148
+ return nil
149
+ }); err != nil {
150
+ return nil, err
151
+ }
152
+ return roots, nil
153
+ }
154
+
155
+ func loadOverrideMetadata(pkgPath string) (OverrideMetadata, error) {
156
+ metadata := newOverrideMetadata()
157
+ data, err := gs.GsOverrides.ReadFile("gs/" + pkgPath + "/meta.json")
158
+ if err != nil {
159
+ if errors.Is(err, fs.ErrNotExist) {
160
+ return metadata, nil
161
+ }
162
+ return OverrideMetadata{}, err
163
+ }
164
+
165
+ iter := jsoniter.ParseBytes(data)
166
+ for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
167
+ switch field {
168
+ case "dependencies":
169
+ for iter.ReadArray() {
170
+ metadata.Dependencies = append(metadata.Dependencies, iter.ReadString())
171
+ }
172
+ case "asyncMethods":
173
+ for method := iter.ReadObject(); method != ""; method = iter.ReadObject() {
174
+ metadata.AsyncMethods[method] = iter.ReadBool()
175
+ }
176
+ case "asyncFunctions":
177
+ for function := iter.ReadObject(); function != ""; function = iter.ReadObject() {
178
+ metadata.AsyncFunctions[function] = iter.ReadBool()
179
+ }
180
+ default:
181
+ iter.Skip()
182
+ }
183
+ }
184
+ if iter.Error != nil && !errors.Is(iter.Error, io.EOF) {
185
+ return OverrideMetadata{}, iter.Error
186
+ }
187
+ return metadata, nil
188
+ }
189
+
190
+ func loadOverrideCopyPackage(
191
+ pkgPath string,
192
+ roots map[string]bool,
193
+ metadata OverrideMetadata,
194
+ ) (overrideCopyPackage, []string, []Diagnostic) {
195
+ if !roots[pkgPath] {
196
+ return overrideCopyPackage{}, nil, []Diagnostic{{
197
+ Severity: DiagnosticSeverityError,
198
+ Code: "goscript/overrides:missing-package",
199
+ Message: "override package does not exist",
200
+ Detail: pkgPath,
201
+ }}
202
+ }
203
+
204
+ facts := &OverrideFacts{packages: make(map[string]overridePackageFacts, len(roots))}
205
+ for root := range roots {
206
+ facts.packages[root] = overridePackageFacts{}
207
+ }
208
+
209
+ copyPackage := overrideCopyPackage{path: pkgPath}
210
+ dependencySet := make(map[string]bool)
211
+ for _, dependency := range metadata.Dependencies {
212
+ dependency = strings.TrimSpace(dependency)
213
+ if dependency != "" && dependency != pkgPath {
214
+ dependencySet[dependency] = true
215
+ }
216
+ }
217
+
218
+ root := "gs/" + pkgPath
219
+ err := fs.WalkDir(gs.GsOverrides, root, func(filePath string, entry fs.DirEntry, walkErr error) error {
220
+ if walkErr != nil {
221
+ return walkErr
222
+ }
223
+ if entry.IsDir() {
224
+ nestedPkg := strings.TrimPrefix(filePath, "gs/")
225
+ if nestedPkg != pkgPath && roots[nestedPkg] {
226
+ return fs.SkipDir
227
+ }
228
+ return nil
229
+ }
230
+ if !isOverrideSourceFile(filePath) {
231
+ return nil
232
+ }
233
+ data, readErr := gs.GsOverrides.ReadFile(filePath)
234
+ if readErr != nil {
235
+ return readErr
236
+ }
237
+ rel := strings.TrimPrefix(filePath, "gs/")
238
+ copyPackage.files = append(copyPackage.files, overrideCopyFile{
239
+ path: rel,
240
+ data: data,
241
+ })
242
+ for _, imported := range scanOverrideImports(string(data)) {
243
+ dependency, ok := facts.importPackageRoot(imported)
244
+ if ok && dependency != "builtin" && dependency != pkgPath {
245
+ dependencySet[dependency] = true
246
+ }
247
+ }
248
+ return nil
249
+ })
250
+ if err != nil {
251
+ return overrideCopyPackage{}, nil, []Diagnostic{overrideError("read override package", pkgPath, err)}
252
+ }
253
+
254
+ if len(copyPackage.files) == 0 {
255
+ return overrideCopyPackage{}, nil, []Diagnostic{{
256
+ Severity: DiagnosticSeverityError,
257
+ Code: "goscript/overrides:empty-package",
258
+ Message: "override package does not contain TypeScript source files",
259
+ Detail: pkgPath,
260
+ }}
261
+ }
262
+ slices.SortFunc(copyPackage.files, func(a, b overrideCopyFile) int {
263
+ return strings.Compare(a.path, b.path)
264
+ })
265
+
266
+ dependencies := make([]string, 0, len(dependencySet))
267
+ for dependency := range dependencySet {
268
+ dependencies = append(dependencies, dependency)
269
+ }
270
+ slices.Sort(dependencies)
271
+ return copyPackage, dependencies, nil
272
+ }
273
+
274
+ func newOverrideMetadata() OverrideMetadata {
275
+ return OverrideMetadata{
276
+ AsyncFunctions: make(map[string]bool),
277
+ AsyncMethods: make(map[string]bool),
278
+ }
279
+ }
280
+
281
+ func cloneOverrideMetadata(metadata OverrideMetadata) OverrideMetadata {
282
+ return OverrideMetadata{
283
+ Dependencies: slices.Clone(metadata.Dependencies),
284
+ AsyncFunctions: cloneBoolMap(metadata.AsyncFunctions),
285
+ AsyncMethods: cloneBoolMap(metadata.AsyncMethods),
286
+ }
287
+ }
288
+
289
+ func cloneBoolMap(values map[string]bool) map[string]bool {
290
+ cloned := make(map[string]bool, len(values))
291
+ maps.Copy(cloned, values)
292
+ return cloned
293
+ }
294
+
295
+ func cloneOverrideCopyPackage(pkg overrideCopyPackage) overrideCopyPackage {
296
+ cloned := overrideCopyPackage{
297
+ path: pkg.path,
298
+ files: make([]overrideCopyFile, 0, len(pkg.files)),
299
+ }
300
+ for _, file := range pkg.files {
301
+ cloned.files = append(cloned.files, overrideCopyFile{
302
+ path: file.path,
303
+ data: bytes.Clone(file.data),
304
+ })
305
+ }
306
+ return cloned
307
+ }
@@ -2,82 +2,56 @@ package compiler
2
2
 
3
3
  import (
4
4
  "context"
5
- "errors"
6
- "io"
7
- "io/fs"
8
5
  "os"
9
- "path"
10
6
  "path/filepath"
11
7
  "slices"
12
8
  "strings"
13
-
14
- gs "github.com/aperturerobotics/goscript"
15
- jsoniter "github.com/aperturerobotics/json-iterator-lite"
16
9
  )
17
10
 
18
11
  // OverrideMetadata describes compiler-visible facts from a package override.
19
12
  type OverrideMetadata struct {
20
13
  // Dependencies are override package dependencies.
21
14
  Dependencies []string
15
+ // AsyncFunctions maps package-level function names to async status.
16
+ AsyncFunctions map[string]bool
22
17
  // AsyncMethods maps Type.Method keys to async status.
23
18
  AsyncMethods map[string]bool
24
19
  }
25
20
 
26
21
  // OverrideRegistryOwner owns GoScript override package metadata and copy plans.
27
22
  type OverrideRegistryOwner struct {
28
- metadata map[string]*OverrideMetadata
29
- packageRootCache map[string]bool
23
+ facts *OverrideFacts
30
24
  }
31
25
 
32
26
  // NewOverrideRegistryOwner creates the override registry owner.
33
27
  func NewOverrideRegistryOwner() *OverrideRegistryOwner {
34
- return &OverrideRegistryOwner{
35
- metadata: make(map[string]*OverrideMetadata),
36
- }
28
+ return &OverrideRegistryOwner{}
37
29
  }
38
30
 
39
- // Metadata returns compiler-visible override metadata for a package path.
40
- func (o *OverrideRegistryOwner) Metadata(pkgPath string) (*OverrideMetadata, error) {
31
+ // Facts returns the immutable compiler-visible override facts.
32
+ func (o *OverrideRegistryOwner) Facts(ctx context.Context) (*OverrideFacts, []Diagnostic) {
41
33
  if o == nil {
42
34
  o = NewOverrideRegistryOwner()
43
35
  }
44
- if metadata := o.metadata[pkgPath]; metadata != nil {
45
- return metadata, nil
46
- }
47
-
48
- metadata := &OverrideMetadata{
49
- AsyncMethods: make(map[string]bool),
36
+ if o.facts != nil {
37
+ return o.facts, nil
50
38
  }
51
- data, err := gs.GsOverrides.ReadFile("gs/" + pkgPath + "/meta.json")
52
- if err != nil {
53
- if errors.Is(err, fs.ErrNotExist) {
54
- o.metadata[pkgPath] = metadata
55
- return metadata, nil
56
- }
57
- return nil, err
39
+ facts, diagnostics := buildOverrideFacts(ctx)
40
+ if diagnosticsHaveErrors(diagnostics) {
41
+ return facts, diagnostics
58
42
  }
43
+ o.facts = facts
44
+ return facts, diagnostics
45
+ }
59
46
 
60
- iter := jsoniter.ParseBytes(data)
61
- for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
62
- switch field {
63
- case "dependencies":
64
- for iter.ReadArray() {
65
- metadata.Dependencies = append(metadata.Dependencies, iter.ReadString())
66
- }
67
- case "asyncMethods":
68
- for method := iter.ReadObject(); method != ""; method = iter.ReadObject() {
69
- metadata.AsyncMethods[method] = iter.ReadBool()
70
- }
71
- default:
72
- iter.Skip()
73
- }
74
- }
75
- if iter.Error != nil && !errors.Is(iter.Error, io.EOF) {
76
- return nil, iter.Error
47
+ // Metadata returns compiler-visible override metadata for a package path.
48
+ func (o *OverrideRegistryOwner) Metadata(pkgPath string) (*OverrideMetadata, error) {
49
+ facts, diagnostics := o.Facts(context.Background())
50
+ if diagnosticsHaveErrors(diagnostics) {
51
+ return nil, NewCompileError(diagnostics)
77
52
  }
78
-
79
- o.metadata[pkgPath] = metadata
80
- return metadata, nil
53
+ metadata := facts.Metadata(pkgPath)
54
+ return &metadata, nil
81
55
  }
82
56
 
83
57
  // CopyPlan builds the ordered override package copy plan for a request.
@@ -107,17 +81,17 @@ func (o *OverrideRegistryOwner) CopyPlan(
107
81
  Message: "override copy planning requires a package graph",
108
82
  }}
109
83
  }
110
- if _, err := o.packageRoots(); err != nil {
111
- return nil, []Diagnostic{overrideError("discover override packages", "", err)}
84
+ facts, diagnostics := o.Facts(ctx)
85
+ if diagnosticsHaveErrors(diagnostics) {
86
+ return nil, diagnostics
112
87
  }
113
88
 
114
- var diagnostics []Diagnostic
115
89
  visiting := make(map[string]bool)
116
90
  visited := make(map[string]bool)
117
- diagnostics = append(diagnostics, o.addPackageToPlan(ctx, plan, "builtin", visiting, visited)...)
91
+ diagnostics = append(diagnostics, o.addPackageToPlan(ctx, facts, plan, "builtin", visiting, visited)...)
118
92
  for _, node := range graph.Nodes {
119
93
  if node.OverrideCandidate {
120
- diagnostics = append(diagnostics, o.addPackageToPlan(ctx, plan, node.PkgPath, visiting, visited)...)
94
+ diagnostics = append(diagnostics, o.addPackageToPlan(ctx, facts, plan, node.PkgPath, visiting, visited)...)
121
95
  }
122
96
  }
123
97
  if diagnosticsHaveErrors(diagnostics) {
@@ -181,11 +155,20 @@ func (o *OverrideRegistryOwner) CopyPackages(
181
155
 
182
156
  // IsMethodAsync returns true when override metadata marks a method async.
183
157
  func (o *OverrideRegistryOwner) IsMethodAsync(pkgPath, method string) (bool, error) {
184
- metadata, err := o.Metadata(pkgPath)
185
- if err != nil {
186
- return false, err
158
+ facts, diagnostics := o.Facts(context.Background())
159
+ if diagnosticsHaveErrors(diagnostics) {
160
+ return false, NewCompileError(diagnostics)
161
+ }
162
+ return facts.IsMethodAsync(pkgPath, method), nil
163
+ }
164
+
165
+ // IsFunctionAsync returns true when override metadata marks a package-level function async.
166
+ func (o *OverrideRegistryOwner) IsFunctionAsync(pkgPath, function string) (bool, error) {
167
+ facts, diagnostics := o.Facts(context.Background())
168
+ if diagnosticsHaveErrors(diagnostics) {
169
+ return false, NewCompileError(diagnostics)
187
170
  }
188
- return metadata.AsyncMethods[method], nil
171
+ return facts.IsFunctionAsync(pkgPath, function), nil
189
172
  }
190
173
 
191
174
  type overrideCopyPlan struct {
@@ -204,6 +187,7 @@ type overrideCopyFile struct {
204
187
 
205
188
  func (o *OverrideRegistryOwner) addPackageToPlan(
206
189
  ctx context.Context,
190
+ facts *OverrideFacts,
207
191
  plan *overrideCopyPlan,
208
192
  pkgPath string,
209
193
  visiting map[string]bool,
@@ -228,13 +212,19 @@ func (o *OverrideRegistryOwner) addPackageToPlan(
228
212
  }}
229
213
  }
230
214
 
231
- pkg, dependencies, diagnostics := o.loadCopyPackage(pkgPath)
232
- if diagnosticsHaveErrors(diagnostics) {
233
- return diagnostics
215
+ pkg, dependencies, ok := facts.copyPackage(pkgPath)
216
+ if !ok {
217
+ return []Diagnostic{{
218
+ Severity: DiagnosticSeverityError,
219
+ Code: "goscript/overrides:missing-package",
220
+ Message: "override package does not exist",
221
+ Detail: pkgPath,
222
+ }}
234
223
  }
235
224
  visiting[pkgPath] = true
225
+ var diagnostics []Diagnostic
236
226
  for _, dependency := range dependencies {
237
- diagnostics = append(diagnostics, o.addPackageToPlan(ctx, plan, dependency, visiting, visited)...)
227
+ diagnostics = append(diagnostics, o.addPackageToPlan(ctx, facts, plan, dependency, visiting, visited)...)
238
228
  }
239
229
  delete(visiting, pkgPath)
240
230
  if diagnosticsHaveErrors(diagnostics) {
@@ -246,135 +236,6 @@ func (o *OverrideRegistryOwner) addPackageToPlan(
246
236
  return diagnostics
247
237
  }
248
238
 
249
- func (o *OverrideRegistryOwner) loadCopyPackage(pkgPath string) (overrideCopyPackage, []string, []Diagnostic) {
250
- roots, err := o.packageRoots()
251
- if err != nil {
252
- return overrideCopyPackage{}, nil, []Diagnostic{overrideError("discover override packages", "", err)}
253
- }
254
- if !roots[pkgPath] {
255
- return overrideCopyPackage{}, nil, []Diagnostic{{
256
- Severity: DiagnosticSeverityError,
257
- Code: "goscript/overrides:missing-package",
258
- Message: "override package does not exist",
259
- Detail: pkgPath,
260
- }}
261
- }
262
-
263
- metadata, err := o.Metadata(pkgPath)
264
- if err != nil {
265
- return overrideCopyPackage{}, nil, []Diagnostic{overrideError("read override metadata", pkgPath, err)}
266
- }
267
-
268
- copyPackage := overrideCopyPackage{path: pkgPath}
269
- dependencySet := make(map[string]bool)
270
- for _, dependency := range metadata.Dependencies {
271
- dependency = strings.TrimSpace(dependency)
272
- if dependency != "" && dependency != pkgPath {
273
- dependencySet[dependency] = true
274
- }
275
- }
276
-
277
- root := "gs/" + pkgPath
278
- err = fs.WalkDir(gs.GsOverrides, root, func(filePath string, entry fs.DirEntry, walkErr error) error {
279
- if walkErr != nil {
280
- return walkErr
281
- }
282
- if entry.IsDir() {
283
- nestedPkg := strings.TrimPrefix(filePath, "gs/")
284
- if nestedPkg != pkgPath && roots[nestedPkg] {
285
- return fs.SkipDir
286
- }
287
- return nil
288
- }
289
- if !isOverrideSourceFile(filePath) {
290
- return nil
291
- }
292
- data, readErr := gs.GsOverrides.ReadFile(filePath)
293
- if readErr != nil {
294
- return readErr
295
- }
296
- rel := strings.TrimPrefix(filePath, "gs/")
297
- copyPackage.files = append(copyPackage.files, overrideCopyFile{
298
- path: rel,
299
- data: data,
300
- })
301
- for _, imported := range scanOverrideImports(string(data)) {
302
- dependency, ok := o.importPackageRoot(imported)
303
- if ok && dependency != "builtin" && dependency != pkgPath {
304
- dependencySet[dependency] = true
305
- }
306
- }
307
- return nil
308
- })
309
- if err != nil {
310
- return overrideCopyPackage{}, nil, []Diagnostic{overrideError("read override package", pkgPath, err)}
311
- }
312
-
313
- if len(copyPackage.files) == 0 {
314
- return overrideCopyPackage{}, nil, []Diagnostic{{
315
- Severity: DiagnosticSeverityError,
316
- Code: "goscript/overrides:empty-package",
317
- Message: "override package does not contain TypeScript source files",
318
- Detail: pkgPath,
319
- }}
320
- }
321
- slices.SortFunc(copyPackage.files, func(a, b overrideCopyFile) int {
322
- return strings.Compare(a.path, b.path)
323
- })
324
-
325
- dependencies := make([]string, 0, len(dependencySet))
326
- for dependency := range dependencySet {
327
- dependencies = append(dependencies, dependency)
328
- }
329
- slices.Sort(dependencies)
330
- return copyPackage, dependencies, nil
331
- }
332
-
333
- func (o *OverrideRegistryOwner) packageRoots() (map[string]bool, error) {
334
- if o.packageRootCache != nil {
335
- return o.packageRootCache, nil
336
- }
337
- roots := make(map[string]bool)
338
- if err := fs.WalkDir(gs.GsOverrides, "gs", func(filePath string, entry fs.DirEntry, err error) error {
339
- if err != nil {
340
- return err
341
- }
342
- if entry.IsDir() || path.Base(filePath) != "index.ts" {
343
- return nil
344
- }
345
- pkgPath := strings.TrimPrefix(path.Dir(filePath), "gs/")
346
- if pkgPath != "." && pkgPath != "" {
347
- roots[pkgPath] = true
348
- }
349
- return nil
350
- }); err != nil {
351
- return nil, err
352
- }
353
- o.packageRootCache = roots
354
- return roots, nil
355
- }
356
-
357
- func (o *OverrideRegistryOwner) importPackageRoot(importPath string) (string, bool) {
358
- roots, err := o.packageRoots()
359
- if err != nil {
360
- return "", false
361
- }
362
- importPath = strings.TrimPrefix(importPath, "@goscript/")
363
- importPath = strings.TrimSuffix(importPath, ".js")
364
- importPath = strings.TrimSuffix(importPath, ".ts")
365
- if before, ok := strings.CutSuffix(importPath, "/index"); ok {
366
- importPath = before
367
- }
368
- parts := strings.Split(importPath, "/")
369
- for idx := len(parts); idx > 0; idx-- {
370
- candidate := strings.Join(parts[:idx], "/")
371
- if roots[candidate] {
372
- return candidate, true
373
- }
374
- }
375
- return "", false
376
- }
377
-
378
239
  func isOverrideSourceFile(filePath string) bool {
379
240
  return strings.HasSuffix(filePath, ".ts") && !strings.HasSuffix(filePath, ".test.ts")
380
241
  }
@@ -35,6 +35,53 @@ func TestOverrideRegistryPlansRuntimeAndOverrideDependencies(t *testing.T) {
35
35
  }
36
36
  }
37
37
 
38
+ func TestOverrideRegistryFactsAreImmutable(t *testing.T) {
39
+ owner := NewOverrideRegistryOwner()
40
+ facts, diagnostics := owner.Facts(context.Background())
41
+ if diagnosticsHaveErrors(diagnostics) {
42
+ t.Fatalf("override facts failed: %#v", diagnostics)
43
+ }
44
+
45
+ metadata := facts.Metadata("sync")
46
+ if !metadata.AsyncMethods["Map.Load"] {
47
+ t.Fatalf("expected sync Map.Load async metadata")
48
+ }
49
+ metadata.AsyncMethods["Map.Load"] = false
50
+ metadata.Dependencies = append(metadata.Dependencies, "mutated")
51
+
52
+ metadata = facts.Metadata("sync")
53
+ if !metadata.AsyncMethods["Map.Load"] {
54
+ t.Fatalf("override metadata mutation leaked back into facts")
55
+ }
56
+ if slices.Contains(metadata.Dependencies, "mutated") {
57
+ t.Fatalf("override dependency mutation leaked back into facts: %v", metadata.Dependencies)
58
+ }
59
+
60
+ pkg, dependencies, ok := facts.copyPackage("fmt")
61
+ if !ok {
62
+ t.Fatalf("missing fmt copy package facts")
63
+ }
64
+ if !slices.Contains(dependencies, "errors") {
65
+ t.Fatalf("expected fmt dependency on errors, got %v", dependencies)
66
+ }
67
+ dependencies = append(dependencies, "mutated")
68
+ if len(pkg.files) == 0 {
69
+ t.Fatalf("expected fmt copy files")
70
+ }
71
+ pkg.files[0].data[0] = '!'
72
+
73
+ pkg, dependencies, ok = facts.copyPackage("fmt")
74
+ if !ok {
75
+ t.Fatalf("missing fmt copy package facts after mutation")
76
+ }
77
+ if slices.Contains(dependencies, "mutated") {
78
+ t.Fatalf("copy dependency mutation leaked back into facts: %v", dependencies)
79
+ }
80
+ if len(pkg.files) == 0 || pkg.files[0].data[0] == '!' {
81
+ t.Fatalf("copy file mutation leaked back into facts")
82
+ }
83
+ }
84
+
38
85
  func TestOverrideRegistryCopiesRuntimeAndOverrides(t *testing.T) {
39
86
  owner := NewOverrideRegistryOwner()
40
87
  req := &CompileRequest{