goscript 0.1.4 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/README.md +5 -2
  2. package/cmd/go_js_wasm_exec/main.go +201 -0
  3. package/cmd/go_js_wasm_exec/main_test.go +83 -0
  4. package/cmd/goscript/{cmd_compile.go → cmd-compile.go} +7 -0
  5. package/cmd/goscript/cmd-test.go +14 -0
  6. package/cmd/goscript/cmd-test_test.go +1 -1
  7. package/cmd/goscript-wasm/main.go +38 -6
  8. package/compiler/compile-request.go +12 -9
  9. package/compiler/compliance_test.go +0 -1
  10. package/compiler/config.go +2 -0
  11. package/compiler/diagnostic.go +104 -12
  12. package/compiler/diagnostic_test.go +106 -0
  13. package/compiler/gotest/request.go +28 -0
  14. package/compiler/gotest/runner.go +354 -44
  15. package/compiler/gotest/runner_test.go +293 -1
  16. package/compiler/gotest/testdata/browserapi/browserapi_test.go +20 -0
  17. package/compiler/gotest/testdata/browserapi/go.mod +3 -0
  18. package/compiler/index.test.ts +23 -0
  19. package/compiler/lowered-program.go +33 -24
  20. package/compiler/lowering.go +746 -194
  21. package/compiler/lowering_bench_test.go +42 -27
  22. package/compiler/lowering_internal_test.go +18 -0
  23. package/compiler/override-facts.go +15 -0
  24. package/compiler/override-parity-verifier.go +450 -0
  25. package/compiler/override-parity.go +122 -0
  26. package/compiler/override-registry_test.go +559 -0
  27. package/compiler/protobuf-ts-binding.go +567 -0
  28. package/compiler/protobuf-ts-binding_test.go +402 -0
  29. package/compiler/runtime-contract.go +4 -0
  30. package/compiler/runtime-contract_test.go +2 -0
  31. package/compiler/semantic-model-types.go +9 -4
  32. package/compiler/semantic-model.go +282 -70
  33. package/compiler/semantic-model_test.go +82 -1
  34. package/compiler/service.go +21 -1
  35. package/compiler/skeleton_test.go +118 -10
  36. package/compiler/typescript-emitter.go +128 -13
  37. package/compiler/wasm/compile_test.go +37 -4
  38. package/compiler/{wasm_api.go → wasm-api.go} +57 -7
  39. package/dist/gs/builtin/hostio.js +5 -0
  40. package/dist/gs/builtin/hostio.js.map +1 -1
  41. package/dist/gs/builtin/slice.d.ts +13 -2
  42. package/dist/gs/builtin/slice.js +187 -6
  43. package/dist/gs/builtin/slice.js.map +1 -1
  44. package/dist/gs/builtin/type.d.ts +13 -5
  45. package/dist/gs/builtin/type.js +153 -60
  46. package/dist/gs/builtin/type.js.map +1 -1
  47. package/dist/gs/builtin/varRef.d.ts +11 -0
  48. package/dist/gs/builtin/varRef.js +57 -2
  49. package/dist/gs/builtin/varRef.js.map +1 -1
  50. package/dist/gs/bytes/buffer.gs.js +1 -1
  51. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  52. package/dist/gs/bytes/reader.gs.js +1 -1
  53. package/dist/gs/bytes/reader.gs.js.map +1 -1
  54. package/dist/gs/compress/zlib/index.d.ts +10 -3
  55. package/dist/gs/compress/zlib/index.js +50 -16
  56. package/dist/gs/compress/zlib/index.js.map +1 -1
  57. package/dist/gs/encoding/json/index.d.ts +114 -0
  58. package/dist/gs/encoding/json/index.js +544 -36
  59. package/dist/gs/encoding/json/index.js.map +1 -1
  60. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +101 -0
  61. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +589 -0
  62. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  63. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.d.ts +1 -0
  64. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js +17 -11
  65. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.js.map +1 -1
  66. package/dist/gs/github.com/pkg/errors/errors.js +54 -30
  67. package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
  68. package/dist/gs/go/scanner/index.d.ts +2 -0
  69. package/dist/gs/go/scanner/index.js +29 -5
  70. package/dist/gs/go/scanner/index.js.map +1 -1
  71. package/dist/gs/go/token/index.js +22 -6
  72. package/dist/gs/go/token/index.js.map +1 -1
  73. package/dist/gs/hash/index.d.ts +6 -0
  74. package/dist/gs/hash/index.js +20 -0
  75. package/dist/gs/hash/index.js.map +1 -1
  76. package/dist/gs/internal/byteorder/index.js +2 -2
  77. package/dist/gs/internal/byteorder/index.js.map +1 -1
  78. package/dist/gs/internal/goarch/index.d.ts +43 -3
  79. package/dist/gs/internal/goarch/index.js +42 -10
  80. package/dist/gs/internal/goarch/index.js.map +1 -1
  81. package/dist/gs/io/fs/fs.js +26 -14
  82. package/dist/gs/io/fs/fs.js.map +1 -1
  83. package/dist/gs/io/fs/readdir.js +4 -2
  84. package/dist/gs/io/fs/readdir.js.map +1 -1
  85. package/dist/gs/io/fs/sub.js +8 -1
  86. package/dist/gs/io/fs/sub.js.map +1 -1
  87. package/dist/gs/io/io.d.ts +2 -0
  88. package/dist/gs/io/io.js.map +1 -1
  89. package/dist/gs/math/bits/index.d.ts +5 -0
  90. package/dist/gs/math/bits/index.js +16 -4
  91. package/dist/gs/math/bits/index.js.map +1 -1
  92. package/dist/gs/mime/index.d.ts +16 -0
  93. package/dist/gs/mime/index.js +315 -6
  94. package/dist/gs/mime/index.js.map +1 -1
  95. package/dist/gs/net/http/httptest/index.d.ts +12 -0
  96. package/dist/gs/net/http/httptest/index.js +85 -6
  97. package/dist/gs/net/http/httptest/index.js.map +1 -1
  98. package/dist/gs/net/http/index.d.ts +300 -5
  99. package/dist/gs/net/http/index.js +1598 -58
  100. package/dist/gs/net/http/index.js.map +1 -1
  101. package/dist/gs/os/dir_unix.gs.js +1 -1
  102. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  103. package/dist/gs/os/error.gs.js +1 -1
  104. package/dist/gs/os/error.gs.js.map +1 -1
  105. package/dist/gs/os/exec.gs.d.ts +1 -0
  106. package/dist/gs/os/exec.gs.js +4 -8
  107. package/dist/gs/os/exec.gs.js.map +1 -1
  108. package/dist/gs/os/exec_posix.gs.js +1 -1
  109. package/dist/gs/os/exec_posix.gs.js.map +1 -1
  110. package/dist/gs/os/index.d.ts +1 -1
  111. package/dist/gs/os/index.js +1 -1
  112. package/dist/gs/os/index.js.map +1 -1
  113. package/dist/gs/os/proc.gs.d.ts +4 -0
  114. package/dist/gs/os/proc.gs.js +12 -6
  115. package/dist/gs/os/proc.gs.js.map +1 -1
  116. package/dist/gs/os/root_js.gs.js +1 -1
  117. package/dist/gs/os/root_js.gs.js.map +1 -1
  118. package/dist/gs/os/types.gs.js +1 -1
  119. package/dist/gs/os/types.gs.js.map +1 -1
  120. package/dist/gs/os/types_js.gs.js +1 -1
  121. package/dist/gs/os/types_js.gs.js.map +1 -1
  122. package/dist/gs/os/types_unix.gs.js +1 -1
  123. package/dist/gs/os/types_unix.gs.js.map +1 -1
  124. package/dist/gs/path/path.js +11 -7
  125. package/dist/gs/path/path.js.map +1 -1
  126. package/dist/gs/reflect/index.d.ts +5 -4
  127. package/dist/gs/reflect/index.js +4 -3
  128. package/dist/gs/reflect/index.js.map +1 -1
  129. package/dist/gs/reflect/map.js +15 -0
  130. package/dist/gs/reflect/map.js.map +1 -1
  131. package/dist/gs/reflect/type.d.ts +25 -6
  132. package/dist/gs/reflect/type.js +1475 -228
  133. package/dist/gs/reflect/type.js.map +1 -1
  134. package/dist/gs/reflect/types.d.ts +14 -6
  135. package/dist/gs/reflect/types.js +35 -1
  136. package/dist/gs/reflect/types.js.map +1 -1
  137. package/dist/gs/reflect/value.d.ts +1 -0
  138. package/dist/gs/reflect/value.js +83 -41
  139. package/dist/gs/reflect/value.js.map +1 -1
  140. package/dist/gs/reflect/visiblefields.js +4 -140
  141. package/dist/gs/reflect/visiblefields.js.map +1 -1
  142. package/dist/gs/runtime/pprof/index.d.ts +8 -2
  143. package/dist/gs/runtime/pprof/index.js +50 -30
  144. package/dist/gs/runtime/pprof/index.js.map +1 -1
  145. package/dist/gs/runtime/runtime.js +5 -4
  146. package/dist/gs/runtime/runtime.js.map +1 -1
  147. package/dist/gs/runtime/trace/index.js +5 -19
  148. package/dist/gs/runtime/trace/index.js.map +1 -1
  149. package/dist/gs/strconv/atoi.gs.js +1 -1
  150. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  151. package/dist/gs/strconv/complex.gs.d.ts +3 -0
  152. package/dist/gs/strconv/complex.gs.js +148 -0
  153. package/dist/gs/strconv/complex.gs.js.map +1 -0
  154. package/dist/gs/strconv/index.d.ts +1 -0
  155. package/dist/gs/strconv/index.js +1 -0
  156. package/dist/gs/strconv/index.js.map +1 -1
  157. package/dist/gs/strings/builder.js +1 -1
  158. package/dist/gs/strings/reader.js +9 -5
  159. package/dist/gs/strings/reader.js.map +1 -1
  160. package/dist/gs/strings/replace.js +15 -7
  161. package/dist/gs/strings/replace.js.map +1 -1
  162. package/dist/gs/strings/strings.d.ts +5 -0
  163. package/dist/gs/strings/strings.js +57 -5
  164. package/dist/gs/strings/strings.js.map +1 -1
  165. package/dist/gs/sync/atomic/doc_64.gs.js +7 -6
  166. package/dist/gs/sync/atomic/doc_64.gs.js.map +1 -1
  167. package/dist/gs/sync/atomic/type.gs.js +9 -9
  168. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  169. package/dist/gs/sync/atomic/value.gs.js +2 -2
  170. package/dist/gs/sync/atomic/value.gs.js.map +1 -1
  171. package/dist/gs/syscall/env.js +22 -14
  172. package/dist/gs/syscall/env.js.map +1 -1
  173. package/dist/gs/testing/testing.js +55 -13
  174. package/dist/gs/testing/testing.js.map +1 -1
  175. package/dist/gs/time/time.d.ts +24 -1
  176. package/dist/gs/time/time.js +43 -3
  177. package/dist/gs/time/time.js.map +1 -1
  178. package/dist/gs/unique/index.js +7 -1
  179. package/dist/gs/unique/index.js.map +1 -1
  180. package/go.mod +3 -3
  181. package/go.sum +16 -0
  182. package/gs/builtin/hostio.test.ts +16 -0
  183. package/gs/builtin/hostio.ts +7 -0
  184. package/gs/builtin/runtime-contract.test.ts +246 -21
  185. package/gs/builtin/slice.ts +269 -24
  186. package/gs/builtin/type.ts +226 -59
  187. package/gs/builtin/varRef.ts +85 -2
  188. package/gs/bytes/buffer.gs.ts +1 -1
  189. package/gs/bytes/reader.gs.ts +1 -1
  190. package/gs/compress/zlib/index.test.ts +62 -1
  191. package/gs/compress/zlib/index.ts +53 -16
  192. package/gs/compress/zlib/parity.json +51 -0
  193. package/gs/encoding/json/index.test.ts +360 -6
  194. package/gs/encoding/json/index.ts +679 -38
  195. package/gs/encoding/json/parity.json +81 -0
  196. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +373 -3
  197. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +893 -1
  198. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.test.ts +18 -0
  199. package/gs/github.com/aperturerobotics/protobuf-go-lite/json/index.ts +17 -11
  200. package/gs/github.com/pkg/errors/errors.ts +54 -30
  201. package/gs/go/scanner/index.test.ts +39 -56
  202. package/gs/go/scanner/index.ts +33 -5
  203. package/gs/go/scanner/parity.json +27 -0
  204. package/gs/go/token/index.ts +22 -6
  205. package/gs/hash/index.test.ts +20 -33
  206. package/gs/hash/index.ts +28 -0
  207. package/gs/hash/parity.json +21 -0
  208. package/gs/internal/byteorder/index.test.ts +2 -2
  209. package/gs/internal/byteorder/index.ts +2 -2
  210. package/gs/internal/goarch/index.test.ts +32 -0
  211. package/gs/internal/goarch/index.ts +45 -13
  212. package/gs/internal/goarch/parity.json +144 -0
  213. package/gs/io/fs/fs.ts +26 -14
  214. package/gs/io/fs/readdir.ts +4 -4
  215. package/gs/io/fs/sub.ts +8 -1
  216. package/gs/io/io.ts +1 -0
  217. package/gs/io/parity.json +162 -0
  218. package/gs/math/bits/index.test.ts +14 -1
  219. package/gs/math/bits/index.ts +23 -4
  220. package/gs/math/bits/parity.json +156 -0
  221. package/gs/mime/index.test.ts +90 -0
  222. package/gs/mime/index.ts +369 -6
  223. package/gs/mime/parity.json +36 -0
  224. package/gs/net/http/httptest/index.test.ts +98 -2
  225. package/gs/net/http/httptest/index.ts +101 -6
  226. package/gs/net/http/httptest/parity.json +15 -0
  227. package/gs/net/http/index.test.ts +781 -12
  228. package/gs/net/http/index.ts +1860 -139
  229. package/gs/net/http/meta.json +16 -1
  230. package/gs/net/http/parity.json +193 -0
  231. package/gs/os/dir_unix.gs.ts +1 -1
  232. package/gs/os/error.gs.ts +1 -1
  233. package/gs/os/exec.gs.ts +4 -8
  234. package/gs/os/exec_posix.gs.ts +1 -1
  235. package/gs/os/index.test.ts +9 -0
  236. package/gs/os/index.ts +1 -0
  237. package/gs/os/parity.json +9 -0
  238. package/gs/os/proc.gs.ts +18 -5
  239. package/gs/os/proc.test.ts +26 -0
  240. package/gs/os/root_js.gs.ts +1 -1
  241. package/gs/os/types.gs.ts +1 -1
  242. package/gs/os/types_js.gs.ts +1 -1
  243. package/gs/os/types_unix.gs.ts +1 -1
  244. package/gs/path/path.ts +11 -7
  245. package/gs/reflect/field.test.ts +37 -15
  246. package/gs/reflect/function-types.test.ts +518 -22
  247. package/gs/reflect/index.ts +8 -6
  248. package/gs/reflect/map.ts +20 -0
  249. package/gs/reflect/meta.json +6 -4
  250. package/gs/reflect/parity.json +234 -0
  251. package/gs/reflect/sliceat.test.ts +156 -0
  252. package/gs/reflect/structof.test.ts +401 -0
  253. package/gs/reflect/type.ts +1961 -317
  254. package/gs/reflect/typefor.test.ts +530 -10
  255. package/gs/reflect/types.ts +43 -18
  256. package/gs/reflect/value.ts +105 -45
  257. package/gs/reflect/visiblefields.ts +5 -168
  258. package/gs/runtime/parity.json +24 -0
  259. package/gs/runtime/pprof/index.test.ts +29 -7
  260. package/gs/runtime/pprof/index.ts +56 -30
  261. package/gs/runtime/pprof/parity.json +27 -0
  262. package/gs/runtime/runtime.test.ts +3 -1
  263. package/gs/runtime/runtime.ts +4 -3
  264. package/gs/runtime/trace/index.test.ts +5 -3
  265. package/gs/runtime/trace/index.ts +8 -20
  266. package/gs/runtime/trace/parity.json +36 -0
  267. package/gs/strconv/atoi.gs.ts +1 -1
  268. package/gs/strconv/complex.gs.ts +174 -0
  269. package/gs/strconv/complex.test.ts +65 -0
  270. package/gs/strconv/index.ts +1 -0
  271. package/gs/strconv/parity.json +120 -0
  272. package/gs/strings/builder.ts +1 -1
  273. package/gs/strings/parity.json +186 -0
  274. package/gs/strings/reader.ts +9 -5
  275. package/gs/strings/replace.ts +15 -7
  276. package/gs/strings/strings.test.ts +22 -2
  277. package/gs/strings/strings.ts +64 -6
  278. package/gs/sync/atomic/doc_64.gs.ts +6 -7
  279. package/gs/sync/atomic/doc_64.test.ts +43 -0
  280. package/gs/sync/atomic/type.gs.ts +9 -9
  281. package/gs/sync/atomic/value.gs.ts +2 -2
  282. package/gs/syscall/env.ts +29 -14
  283. package/gs/testing/testing.test.ts +67 -0
  284. package/gs/testing/testing.ts +87 -19
  285. package/gs/time/parity.json +225 -0
  286. package/gs/time/time.test.ts +20 -2
  287. package/gs/time/time.ts +49 -7
  288. package/gs/unique/index.ts +7 -1
  289. package/package.json +4 -2
  290. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +0 -217
  291. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +0 -926
  292. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +0 -1
  293. package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +0 -38
  294. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +0 -1361
  295. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +0 -46
@@ -10,12 +10,13 @@ import (
10
10
  )
11
11
 
12
12
  type loweringBenchFixture struct {
13
- model *SemanticModel
14
- owner *LoweringOwner
15
- semPkg *semanticPackage
16
- file loweringBenchFile
17
- genDecls []loweringBenchGenDecl
18
- stmtLists []loweringBenchStmtList
13
+ model *SemanticModel
14
+ owner *LoweringOwner
15
+ semPkg *semanticPackage
16
+ lazyPackageVarsByPkg map[string]map[types.Object]bool
17
+ file loweringBenchFile
18
+ genDecls []loweringBenchGenDecl
19
+ stmtLists []loweringBenchStmtList
19
20
  }
20
21
 
21
22
  type loweringBenchFile struct {
@@ -42,7 +43,13 @@ func BenchmarkLoweringPackage(b *testing.B) {
42
43
  b.ReportAllocs()
43
44
  b.ResetTimer()
44
45
  for i := 0; i < b.N; i++ {
45
- if _, diagnostics := fixture.owner.lowerPackage(fixture.model, fixture.semPkg); diagnosticsHaveErrors(diagnostics) {
46
+ if _, diagnostics := fixture.owner.lowerPackage(
47
+ fixture.model,
48
+ fixture.semPkg,
49
+ make(map[string]map[types.Object]bool),
50
+ make(runtimeMethodSetCache),
51
+ LoweringOptions{},
52
+ ); diagnosticsHaveErrors(diagnostics) {
46
53
  b.Fatal(diagnostics)
47
54
  }
48
55
  }
@@ -60,6 +67,7 @@ func BenchmarkLoweringAnalyzeLocalFileReferences(b *testing.B) {
60
67
  fixture.file.associated,
61
68
  fixture.file.declFiles,
62
69
  fixture.file.outputNames,
70
+ make(runtimeMethodSetCache),
63
71
  )
64
72
  }
65
73
  }
@@ -77,6 +85,10 @@ func BenchmarkLoweringFile(b *testing.B) {
77
85
  fixture.file.declFiles,
78
86
  fixture.file.outputNames,
79
87
  fixture.file.lazyPackageVars,
88
+ fixture.lazyPackageVarsByPkg,
89
+ make(runtimeMethodSetCache),
90
+ false,
91
+ "",
80
92
  ); diagnosticsHaveErrors(diagnostics) {
81
93
  b.Fatal(diagnostics)
82
94
  }
@@ -160,7 +172,8 @@ func newLoweringBenchFixture(tb testing.TB) *loweringBenchFixture {
160
172
  owner := service.LoweringOwner()
161
173
  declFiles := packageDeclFiles(semPkg)
162
174
  outputNames := packageOutputNames(semPkg)
163
- lazyPackageVars := owner.lazyPackageVars(semPkg, declFiles)
175
+ lazyPackageVarsByPkg := make(map[string]map[types.Object]bool)
176
+ lazyPackageVars := owner.packageLazyVars(semPkg, lazyPackageVarsByPkg, declFiles)
164
177
 
165
178
  var benchFile loweringBenchFile
166
179
  var genDecls []loweringBenchGenDecl
@@ -168,20 +181,21 @@ func newLoweringBenchFixture(tb testing.TB) *loweringBenchFixture {
168
181
  for idx, file := range semPkg.source.Syntax {
169
182
  sourcePath := sourceFilePath(semPkg, idx, file)
170
183
  associated := owner.methodDeclsForFileTypes(semPkg, file)
171
- localRefs := owner.analyzeLocalFileReferences(semPkg, file, sourcePath, associated, declFiles, outputNames)
184
+ localRefs := owner.analyzeLocalFileReferences(semPkg, file, sourcePath, associated, declFiles, outputNames, make(runtimeMethodSetCache))
172
185
  ctx := lowerFileContext{
173
- model: model,
174
- semPkg: semPkg,
175
- file: file,
176
- importAliases: make(map[string]string),
177
- importPaths: make(map[string]string),
178
- importNames: make(map[string]string),
179
- importObjects: make(map[*types.PkgName]string),
180
- sourcePath: sourcePath,
181
- localAliases: localRefs.aliases,
182
- lazyPackageVars: lazyPackageVars,
183
- tempNames: newTempNameOwner(),
184
- topLevel: true,
186
+ model: model,
187
+ semPkg: semPkg,
188
+ file: file,
189
+ importAliases: make(map[string]string),
190
+ importPaths: make(map[string]string),
191
+ importNames: make(map[string]string),
192
+ importObjects: make(map[*types.PkgName]string),
193
+ sourcePath: sourcePath,
194
+ localAliases: localRefs.aliases,
195
+ lazyPackageVars: lazyPackageVars,
196
+ lazyPackageVarsByPkg: lazyPackageVarsByPkg,
197
+ tempNames: newTempNameOwner(),
198
+ topLevel: true,
185
199
  }
186
200
  if filepath.Base(sourcePath) == "bench.go" {
187
201
  benchFile = loweringBenchFile{
@@ -214,12 +228,13 @@ func newLoweringBenchFixture(tb testing.TB) *loweringBenchFixture {
214
228
  tb.Fatalf("incomplete lowering benchmark fixture: genDecls=%d stmtLists=%d", len(genDecls), len(stmtLists))
215
229
  }
216
230
  return &loweringBenchFixture{
217
- model: model,
218
- owner: owner,
219
- semPkg: semPkg,
220
- file: benchFile,
221
- genDecls: genDecls,
222
- stmtLists: stmtLists,
231
+ model: model,
232
+ owner: owner,
233
+ semPkg: semPkg,
234
+ lazyPackageVarsByPkg: lazyPackageVarsByPkg,
235
+ file: benchFile,
236
+ genDecls: genDecls,
237
+ stmtLists: stmtLists,
223
238
  }
224
239
  }
225
240
 
@@ -0,0 +1,18 @@
1
+ package compiler
2
+
3
+ import "testing"
4
+
5
+ func TestIntegerBitHelpersHandleNilTypes(t *testing.T) {
6
+ if bits, ok := unsignedIntegerBits(nil); ok || bits != 0 {
7
+ t.Fatalf("unsignedIntegerBits(nil) = %d, %v; want 0, false", bits, ok)
8
+ }
9
+ if bits, ok := signedIntegerBits(nil); ok || bits != 0 {
10
+ t.Fatalf("signedIntegerBits(nil) = %d, %v; want 0, false", bits, ok)
11
+ }
12
+ if bits, ok := integerBits(nil); ok || bits != 0 {
13
+ t.Fatalf("integerBits(nil) = %d, %v; want 0, false", bits, ok)
14
+ }
15
+ if isRuntimeWideIntegerType(nil) {
16
+ t.Fatalf("isRuntimeWideIntegerType(nil) = true; want false")
17
+ }
18
+ }
@@ -24,6 +24,7 @@ type OverrideFacts struct {
24
24
 
25
25
  type overridePackageFacts struct {
26
26
  metadata OverrideMetadata
27
+ parity overrideParityLedger
27
28
  copyPackage overrideCopyPackage
28
29
  dependencies []string
29
30
  }
@@ -52,6 +53,14 @@ func (f *OverrideFacts) Metadata(pkgPath string) OverrideMetadata {
52
53
  return cloneOverrideMetadata(pkg.metadata)
53
54
  }
54
55
 
56
+ func (f *OverrideFacts) parityLedger(pkgPath string) overrideParityLedger {
57
+ if f == nil {
58
+ return newOverrideParityLedger()
59
+ }
60
+ pkg := f.packages[pkgPath]
61
+ return cloneOverrideParityLedger(pkg.parity)
62
+ }
63
+
55
64
  // IsMethodAsync returns true when override metadata marks a method async.
56
65
  func (f *OverrideFacts) IsMethodAsync(pkgPath, method string) bool {
57
66
  if f == nil {
@@ -122,6 +131,11 @@ func buildOverrideFacts(ctx context.Context, overrideDirs []string) (*OverrideFa
122
131
  diagnostics = append(diagnostics, overrideError("read override metadata", pkgPath, err))
123
132
  continue
124
133
  }
134
+ parity, err := loadOverrideParityLedger(roots[pkgPath])
135
+ if err != nil {
136
+ diagnostics = append(diagnostics, overrideError("read override parity ledger", pkgPath, err))
137
+ continue
138
+ }
125
139
  copyPackage, dependencies, packageDiagnostics := loadOverrideCopyPackage(roots[pkgPath], roots, metadata)
126
140
  diagnostics = append(diagnostics, packageDiagnostics...)
127
141
  if diagnosticsHaveErrors(packageDiagnostics) {
@@ -129,6 +143,7 @@ func buildOverrideFacts(ctx context.Context, overrideDirs []string) (*OverrideFa
129
143
  }
130
144
  facts.packages[pkgPath] = overridePackageFacts{
131
145
  metadata: cloneOverrideMetadata(metadata),
146
+ parity: cloneOverrideParityLedger(parity),
132
147
  copyPackage: copyPackage,
133
148
  dependencies: dependencies,
134
149
  }
@@ -0,0 +1,450 @@
1
+ package compiler
2
+
3
+ import (
4
+ "context"
5
+ "go/ast"
6
+ "go/types"
7
+ "path"
8
+ "regexp"
9
+ "slices"
10
+ "strings"
11
+
12
+ "github.com/pkg/errors"
13
+ )
14
+
15
+ var (
16
+ overrideExportDeclarationPattern = regexp.MustCompile(`(?m)^\s*export\s+(?:async\s+)?(const|let|var|function|class|interface|type|enum)\s+([A-Za-z_$][A-Za-z0-9_$]*)`)
17
+ overrideLocalDeclarationPattern = regexp.MustCompile(`(?m)^\s*(?:export\s+)?(?:async\s+)?(const|let|var|function|class|interface|type|enum)\s+([A-Za-z_$][A-Za-z0-9_$]*)`)
18
+ overrideImportNamedPattern = regexp.MustCompile(`(?s)import\s+(type\s+)?\{([^}]*)\}\s+from\s+['"][^'"]+['"]`)
19
+ overrideExportNamedPattern = regexp.MustCompile(`(?s)export\s+(type\s+)?\{([^}]*)\}\s*(?:from\s+['"]([^'"]+)['"])?`)
20
+ overrideExportAllPattern = regexp.MustCompile(`(?m)^\s*export\s+\*\s+from\s+['"]([^'"]+)['"]`)
21
+ )
22
+
23
+ type goPackageExport struct {
24
+ name string
25
+ requiresValue bool
26
+ }
27
+
28
+ type typeScriptExport struct {
29
+ value bool
30
+ typ bool
31
+ }
32
+
33
+ type namedTypeScriptExport struct {
34
+ source string
35
+ target string
36
+ typeOnly bool
37
+ }
38
+
39
+ // OverrideParityVerifier owns compiler-side parity checks for ledgered overrides.
40
+ type OverrideParityVerifier struct{}
41
+
42
+ // NewOverrideParityVerifier creates the override parity verifier.
43
+ func NewOverrideParityVerifier() *OverrideParityVerifier {
44
+ return &OverrideParityVerifier{}
45
+ }
46
+
47
+ // Verify checks ledgered override packages against JS/WASM Go exports and
48
+ // effective TypeScript package exports.
49
+ func (v *OverrideParityVerifier) Verify(
50
+ ctx context.Context,
51
+ graph *PackageGraph,
52
+ facts *OverrideFacts,
53
+ ) []Diagnostic {
54
+ if err := ctx.Err(); err != nil {
55
+ return []Diagnostic{contextCanceledDiagnostic(err)}
56
+ }
57
+ if graph == nil || facts == nil {
58
+ return nil
59
+ }
60
+
61
+ var diagnostics []Diagnostic
62
+ for _, node := range graph.Nodes {
63
+ if err := ctx.Err(); err != nil {
64
+ return append(diagnostics, contextCanceledDiagnostic(err))
65
+ }
66
+ if node == nil || !node.OverrideCandidate {
67
+ continue
68
+ }
69
+ ledger := facts.parityLedger(node.PkgPath)
70
+ if !ledger.Strict && len(ledger.Symbols) == 0 {
71
+ continue
72
+ }
73
+ pkg := graph.packagesByPath[node.PkgPath]
74
+ if pkg == nil || pkg.Types == nil {
75
+ diagnostics = append(diagnostics, Diagnostic{
76
+ Severity: DiagnosticSeverityError,
77
+ Code: "goscript/overrides:parity-no-package",
78
+ Message: "override parity verification requires typed Go package facts",
79
+ Detail: node.PkgPath,
80
+ })
81
+ continue
82
+ }
83
+ exports, err := facts.effectiveTypeScriptExports(node.PkgPath)
84
+ if err != nil {
85
+ diagnostics = append(diagnostics, Diagnostic{
86
+ Severity: DiagnosticSeverityError,
87
+ Code: "goscript/overrides:parity-export-scan",
88
+ Message: "override parity verification failed to scan TypeScript exports",
89
+ Detail: node.PkgPath + ": " + err.Error(),
90
+ })
91
+ continue
92
+ }
93
+ diagnostics = append(diagnostics, verifyOverrideParityPackage(node.PkgPath, pkg.Types, ledger, exports)...)
94
+ }
95
+ diagnostics = append(diagnostics, verifyBlockedOverrideUses(graph, facts)...)
96
+ return diagnostics
97
+ }
98
+
99
+ // VerifyNoDeferred reports transient parity entries that remain in packages
100
+ // whose parity surface is expected to be closed.
101
+ func (v *OverrideParityVerifier) VerifyNoDeferred(facts *OverrideFacts, pkgPaths ...string) []Diagnostic {
102
+ if facts == nil {
103
+ return nil
104
+ }
105
+ var diagnostics []Diagnostic
106
+ for _, pkgPath := range pkgPaths {
107
+ ledger := facts.parityLedger(pkgPath)
108
+ symbols := make([]string, 0, len(ledger.Symbols))
109
+ for symbol := range ledger.Symbols {
110
+ symbols = append(symbols, symbol)
111
+ }
112
+ slices.Sort(symbols)
113
+ for _, symbol := range symbols {
114
+ entry := ledger.Symbols[symbol]
115
+ if entry.Status != overrideParityStatusDeferred {
116
+ continue
117
+ }
118
+ diagnostics = append(diagnostics, Diagnostic{
119
+ Severity: DiagnosticSeverityError,
120
+ Code: "goscript/overrides:parity-deferred",
121
+ Message: "override parity ledger still contains a transient deferred symbol",
122
+ Detail: pkgPath + "." + symbol,
123
+ })
124
+ }
125
+ }
126
+ return diagnostics
127
+ }
128
+
129
+ func verifyOverrideParityPackage(
130
+ pkgPath string,
131
+ goPkg *types.Package,
132
+ ledger overrideParityLedger,
133
+ tsExports map[string]typeScriptExport,
134
+ ) []Diagnostic {
135
+ goExports := exportedPackageSymbols(goPkg)
136
+ goExportSet := make(map[string]bool, len(goExports))
137
+ var diagnostics []Diagnostic
138
+ for _, symbol := range goExports {
139
+ goExportSet[symbol.name] = true
140
+ entry, ok := ledger.Symbols[symbol.name]
141
+ if ledger.Strict && !ok {
142
+ diagnostics = append(diagnostics, Diagnostic{
143
+ Severity: DiagnosticSeverityError,
144
+ Code: "goscript/overrides:parity-unclassified",
145
+ Message: "Go export is missing from override parity ledger",
146
+ Detail: pkgPath + "." + symbol.name,
147
+ })
148
+ continue
149
+ }
150
+ if !ok {
151
+ continue
152
+ }
153
+ if entry.Status.requiresExport() && !symbol.satisfiedBy(tsExports[symbol.name]) {
154
+ diagnostics = append(diagnostics, Diagnostic{
155
+ Severity: DiagnosticSeverityError,
156
+ Code: "goscript/overrides:parity-missing-export",
157
+ Message: "override parity ledger requires a TypeScript export that is missing",
158
+ Detail: pkgPath + "." + symbol.name + " is classified as " + string(entry.Status),
159
+ })
160
+ }
161
+ if entry.Status.forbidsExport() && tsExports[symbol.name].present() {
162
+ diagnostics = append(diagnostics, Diagnostic{
163
+ Severity: DiagnosticSeverityError,
164
+ Code: "goscript/overrides:parity-unexpected-export",
165
+ Message: "override parity ledger marks a Go export blocked, but TypeScript exports it",
166
+ Detail: pkgPath + "." + symbol.name + " is classified as " + string(entry.Status),
167
+ })
168
+ }
169
+ }
170
+ for symbol := range ledger.Symbols {
171
+ if !goExportSet[symbol] {
172
+ diagnostics = append(diagnostics, Diagnostic{
173
+ Severity: DiagnosticSeverityError,
174
+ Code: "goscript/overrides:parity-unknown-symbol",
175
+ Message: "override parity ledger references a symbol not exported by the Go package",
176
+ Detail: pkgPath + "." + symbol,
177
+ })
178
+ }
179
+ }
180
+ return diagnostics
181
+ }
182
+
183
+ func (symbol goPackageExport) satisfiedBy(export typeScriptExport) bool {
184
+ if symbol.requiresValue {
185
+ return export.value
186
+ }
187
+ return export.typ
188
+ }
189
+
190
+ func (export typeScriptExport) present() bool {
191
+ return export.value || export.typ
192
+ }
193
+
194
+ func exportedPackageSymbols(goPkg *types.Package) []goPackageExport {
195
+ if goPkg == nil || goPkg.Scope() == nil {
196
+ return nil
197
+ }
198
+ names := goPkg.Scope().Names()
199
+ symbols := make([]goPackageExport, 0, len(names))
200
+ for _, name := range names {
201
+ if !ast.IsExported(name) {
202
+ continue
203
+ }
204
+ obj := goPkg.Scope().Lookup(name)
205
+ typeName, isTypeName := obj.(*types.TypeName)
206
+ symbols = append(symbols, goPackageExport{
207
+ name: name,
208
+ requiresValue: !isTypeName || typeNameRequiresValue(typeName),
209
+ })
210
+ }
211
+ slices.SortFunc(symbols, func(a, b goPackageExport) int {
212
+ return strings.Compare(a.name, b.name)
213
+ })
214
+ return symbols
215
+ }
216
+
217
+ func typeNameRequiresValue(typeName *types.TypeName) bool {
218
+ if typeName == nil || typeName.Type() == nil {
219
+ return false
220
+ }
221
+ _, ok := types.Unalias(typeName.Type()).Underlying().(*types.Struct)
222
+ return ok
223
+ }
224
+
225
+ func verifyBlockedOverrideUses(graph *PackageGraph, facts *OverrideFacts) []Diagnostic {
226
+ if graph == nil || facts == nil {
227
+ return nil
228
+ }
229
+ seen := make(map[string]bool)
230
+ var diagnostics []Diagnostic
231
+ for _, node := range graph.Nodes {
232
+ if node == nil || node.OverrideCandidate {
233
+ continue
234
+ }
235
+ pkg := graph.packagesByPath[node.PkgPath]
236
+ if pkg == nil || pkg.TypesInfo == nil {
237
+ continue
238
+ }
239
+ sourcePkgPath := packagePath(pkg)
240
+ for ident, obj := range pkg.TypesInfo.Uses {
241
+ if ident == nil || obj == nil || obj.Pkg() == nil {
242
+ continue
243
+ }
244
+ if sourcePkgPath == obj.Pkg().Path() {
245
+ continue
246
+ }
247
+ ledger := facts.parityLedger(obj.Pkg().Path())
248
+ entry, ok := ledger.Symbols[obj.Name()]
249
+ if !ok || entry.Status != overrideParityStatusBlocked {
250
+ continue
251
+ }
252
+ key := sourcePkgPath + "->" + obj.Pkg().Path() + "." + obj.Name()
253
+ if seen[key] {
254
+ continue
255
+ }
256
+ seen[key] = true
257
+ diagnostics = append(diagnostics, Diagnostic{
258
+ Severity: DiagnosticSeverityError,
259
+ Code: "goscript/overrides:parity-blocked-use",
260
+ Message: "Go code uses an override symbol classified as blocked",
261
+ Detail: obj.Pkg().Path() + "." + obj.Name() + ": " + entry.Reason,
262
+ })
263
+ }
264
+ }
265
+ return diagnostics
266
+ }
267
+
268
+ func (f *OverrideFacts) effectiveTypeScriptExports(pkgPath string) (map[string]typeScriptExport, error) {
269
+ pkg, _, ok := f.copyPackage(pkgPath)
270
+ if !ok {
271
+ return nil, errors.Errorf("override package %q is missing", pkgPath)
272
+ }
273
+ files := make(map[string]string, len(pkg.files))
274
+ for _, file := range pkg.files {
275
+ files[path.Clean(file.path)] = string(file.data)
276
+ }
277
+ exports := make(map[string]typeScriptExport)
278
+ visited := make(map[string]bool)
279
+ if err := collectTypeScriptExports(path.Join(pkgPath, "index.ts"), files, exports, visited); err != nil {
280
+ return nil, err
281
+ }
282
+ return exports, nil
283
+ }
284
+
285
+ func collectTypeScriptExports(
286
+ filePath string,
287
+ files map[string]string,
288
+ exports map[string]typeScriptExport,
289
+ visited map[string]bool,
290
+ ) error {
291
+ filePath = path.Clean(filePath)
292
+ if visited[filePath] {
293
+ return nil
294
+ }
295
+ visited[filePath] = true
296
+ data, ok := files[filePath]
297
+ if !ok {
298
+ return errors.Errorf("missing %s", filePath)
299
+ }
300
+ localBindings := localTypeScriptBindings(data)
301
+ for _, match := range overrideExportDeclarationPattern.FindAllStringSubmatch(data, -1) {
302
+ addTypeScriptExport(exports, match[2], typeScriptExportForDeclaration(match[1]))
303
+ }
304
+ for _, match := range overrideExportNamedPattern.FindAllStringSubmatch(data, -1) {
305
+ namedExports := parseNamedTypeScriptExports(match[2], match[1] != "")
306
+ if match[3] == "" {
307
+ if err := addLocalNamedTypeScriptExports(filePath, exports, localBindings, namedExports); err != nil {
308
+ return err
309
+ }
310
+ continue
311
+ }
312
+ target, ok := resolveOverrideExportPath(filePath, match[3])
313
+ if !ok {
314
+ continue
315
+ }
316
+ targetExports := make(map[string]typeScriptExport)
317
+ if err := collectTypeScriptExports(target, files, targetExports, make(map[string]bool)); err != nil {
318
+ return err
319
+ }
320
+ for _, namedExport := range namedExports {
321
+ sourceExport := targetExports[namedExport.source]
322
+ if !sourceExport.present() {
323
+ return errors.Errorf("%s re-exports missing symbol %s from %s", filePath, namedExport.source, target)
324
+ }
325
+ exportShape := sourceExport
326
+ if namedExport.typeOnly {
327
+ if !sourceExport.typ {
328
+ return errors.Errorf("%s re-exports missing type symbol %s from %s", filePath, namedExport.source, target)
329
+ }
330
+ exportShape = typeScriptExport{typ: true}
331
+ } else if !sourceExport.value {
332
+ return errors.Errorf("%s re-exports missing value symbol %s from %s", filePath, namedExport.source, target)
333
+ }
334
+ addTypeScriptExport(exports, namedExport.target, exportShape)
335
+ }
336
+ }
337
+ for _, match := range overrideExportAllPattern.FindAllStringSubmatch(data, -1) {
338
+ target, ok := resolveOverrideExportPath(filePath, match[1])
339
+ if ok {
340
+ if err := collectTypeScriptExports(target, files, exports, visited); err != nil {
341
+ return err
342
+ }
343
+ }
344
+ }
345
+ return nil
346
+ }
347
+
348
+ func typeScriptExportForDeclaration(kind string) typeScriptExport {
349
+ switch kind {
350
+ case "const", "let", "var", "function":
351
+ return typeScriptExport{value: true}
352
+ case "class", "enum":
353
+ return typeScriptExport{value: true, typ: true}
354
+ case "interface", "type":
355
+ return typeScriptExport{typ: true}
356
+ default:
357
+ return typeScriptExport{}
358
+ }
359
+ }
360
+
361
+ func addTypeScriptExport(exports map[string]typeScriptExport, name string, export typeScriptExport) {
362
+ if name == "" {
363
+ return
364
+ }
365
+ current := exports[name]
366
+ current.value = current.value || export.value
367
+ current.typ = current.typ || export.typ
368
+ exports[name] = current
369
+ }
370
+
371
+ func localTypeScriptBindings(data string) map[string]typeScriptExport {
372
+ bindings := make(map[string]typeScriptExport)
373
+ for _, match := range overrideLocalDeclarationPattern.FindAllStringSubmatch(data, -1) {
374
+ addTypeScriptExport(bindings, match[2], typeScriptExportForDeclaration(match[1]))
375
+ }
376
+ for _, match := range overrideImportNamedPattern.FindAllStringSubmatch(data, -1) {
377
+ for _, namedImport := range parseNamedTypeScriptExports(match[2], match[1] != "") {
378
+ exportShape := typeScriptExport{value: true, typ: true}
379
+ if namedImport.typeOnly {
380
+ exportShape = typeScriptExport{typ: true}
381
+ }
382
+ addTypeScriptExport(bindings, namedImport.target, exportShape)
383
+ }
384
+ }
385
+ return bindings
386
+ }
387
+
388
+ func addLocalNamedTypeScriptExports(
389
+ filePath string,
390
+ exports map[string]typeScriptExport,
391
+ localBindings map[string]typeScriptExport,
392
+ namedExports []namedTypeScriptExport,
393
+ ) error {
394
+ for _, namedExport := range namedExports {
395
+ exportShape := localBindings[namedExport.source]
396
+ if namedExport.typeOnly {
397
+ if !exportShape.typ {
398
+ return errors.Errorf("%s exports missing local type symbol %s", filePath, namedExport.source)
399
+ }
400
+ exportShape = typeScriptExport{typ: true}
401
+ } else if !exportShape.value {
402
+ return errors.Errorf("%s exports missing local value symbol %s", filePath, namedExport.source)
403
+ }
404
+ addTypeScriptExport(exports, namedExport.target, exportShape)
405
+ }
406
+ return nil
407
+ }
408
+
409
+ func parseNamedTypeScriptExports(list string, statementTypeOnly bool) []namedTypeScriptExport {
410
+ var exports []namedTypeScriptExport
411
+ for item := range strings.SplitSeq(list, ",") {
412
+ item = strings.TrimSpace(item)
413
+ if item == "" {
414
+ continue
415
+ }
416
+ typeOnly := statementTypeOnly
417
+ if strings.HasPrefix(item, "type ") {
418
+ typeOnly = true
419
+ item = strings.TrimSpace(strings.TrimPrefix(item, "type "))
420
+ }
421
+ parts := strings.Fields(item)
422
+ if len(parts) == 0 {
423
+ continue
424
+ }
425
+ namedExport := namedTypeScriptExport{
426
+ source: parts[0],
427
+ target: parts[0],
428
+ typeOnly: typeOnly,
429
+ }
430
+ if len(parts) >= 3 && parts[len(parts)-2] == "as" {
431
+ namedExport.target = parts[len(parts)-1]
432
+ }
433
+ exports = append(exports, namedExport)
434
+ }
435
+ return exports
436
+ }
437
+
438
+ func resolveOverrideExportPath(currentFile, spec string) (string, bool) {
439
+ if !strings.HasPrefix(spec, ".") {
440
+ return "", false
441
+ }
442
+ target := path.Clean(path.Join(path.Dir(currentFile), spec))
443
+ switch path.Ext(target) {
444
+ case ".js", ".ts":
445
+ target = strings.TrimSuffix(target, path.Ext(target)) + ".ts"
446
+ case "":
447
+ target = path.Join(target, "index.ts")
448
+ }
449
+ return target, true
450
+ }