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,8 +10,28 @@ import (
10
10
  "strings"
11
11
  "testing"
12
12
  "time"
13
+
14
+ "github.com/aperturerobotics/goscript/compiler"
13
15
  )
14
16
 
17
+ func TestDiagnosticsSummaryUsesCompilerFormatter(t *testing.T) {
18
+ got := diagnosticsSummary([]compiler.Diagnostic{{
19
+ Severity: compiler.DiagnosticSeverityError,
20
+ Code: "goscript/test",
21
+ Message: "failed",
22
+ Detail: "bad input",
23
+ Position: &compiler.DiagnosticPosition{
24
+ DisplayFile: "pkg/main.go",
25
+ Line: 4,
26
+ Column: 2,
27
+ },
28
+ }})
29
+ want := "pkg/main.go:4:2: goscript/test: failed (bad input)"
30
+ if got != want {
31
+ t.Fatalf("diagnosticsSummary() = %q, want %q", got, want)
32
+ }
33
+ }
34
+
15
35
  func TestRunnerRunsOrdinaryPackageTest(t *testing.T) {
16
36
  moduleDir := writeFixture(t, map[string]string{
17
37
  "go.mod": "module example.test/gotest\n\ngo 1.25.3\n",
@@ -1036,7 +1056,7 @@ func TestRunnerRunsCombinedRuntimeChunks(t *testing.T) {
1036
1056
  "case \"$runner\" in",
1037
1057
  "runner-all-*)",
1038
1058
  "\tsed -n 's/.*await __goscriptRunPackage(\"\\([^\"]*\\)\".*/\\1/p' \"$runner\" | while IFS= read -r pkg; do",
1039
- "\t\tprintf '" + combinedRuntimeResultPrefix + "{\"packagePath\":\"%s\",\"ok\":true,\"elapsedMs\":1,\"output\":\"\"}\\n' \"$pkg\"",
1059
+ "\t\tprintf '" + combinedRuntimeResultPrefix + "%s\\t1\\t1\\t\\n' \"$pkg\"",
1040
1060
  "\tdone",
1041
1061
  "\texit 0",
1042
1062
  "\t;;",
@@ -1072,6 +1092,157 @@ func TestRunnerRunsCombinedRuntimeChunks(t *testing.T) {
1072
1092
  }
1073
1093
  }
1074
1094
 
1095
+ func TestRunnerRunsBrowserRuntimeBackend(t *testing.T) {
1096
+ moduleDir := writeFixture(t, map[string]string{
1097
+ "go.mod": "module example.test/browser\n\ngo 1.25.3\n",
1098
+ "value_test.go": strings.Join([]string{
1099
+ "package browser",
1100
+ "",
1101
+ "import \"testing\"",
1102
+ "",
1103
+ "func TestBrowser(t *testing.T) {}",
1104
+ "",
1105
+ }, "\n"),
1106
+ })
1107
+ workDir := filepath.Join(moduleDir, ".tmp", "browser-runtime")
1108
+ writeExecutable(t, filepath.Join(moduleDir, "node_modules", ".bin", "vitest"), strings.Join([]string{
1109
+ "#!/bin/sh",
1110
+ "printf '" + combinedRuntimeResultPrefix + "example.test%%2Fbrowser\\t1\\t7\\tbrowser%%20ok\\n'",
1111
+ "exit 0",
1112
+ "",
1113
+ }, "\n"))
1114
+
1115
+ result, err := NewRunner().Run(context.Background(), &Request{
1116
+ Dir: moduleDir,
1117
+ Patterns: []string{"."},
1118
+ Timeout: 30 * time.Second,
1119
+ WorkDir: workDir,
1120
+ RuntimeBackend: RuntimeBackendBrowser,
1121
+ })
1122
+ if err != nil {
1123
+ t.Fatalf("run browser runtime fixture: %v", err)
1124
+ }
1125
+ if !result.Passed() {
1126
+ t.Fatalf("expected browser runtime fixture to pass: %#v", result.Packages)
1127
+ }
1128
+ if got := result.Packages[0].Output; got != "browser ok" {
1129
+ t.Fatalf("expected browser runtime output, got %q", got)
1130
+ }
1131
+ config, err := os.ReadFile(filepath.Join(workDir, "vitest-browser-0.config.mts"))
1132
+ if err != nil {
1133
+ t.Fatalf("read browser vitest config: %v", err)
1134
+ }
1135
+ if !strings.Contains(string(config), "browser: \"chromium\"") {
1136
+ t.Fatalf("expected Chromium browser config, got:\n%s", config)
1137
+ }
1138
+ }
1139
+
1140
+ func TestRunnerReportsBrowserRuntimeFailureRecord(t *testing.T) {
1141
+ moduleDir := writeFixture(t, map[string]string{
1142
+ "go.mod": "module example.test/browserfail\n\ngo 1.25.3\n",
1143
+ "value_test.go": strings.Join([]string{
1144
+ "package browserfail",
1145
+ "",
1146
+ "import \"testing\"",
1147
+ "",
1148
+ "func TestBrowser(t *testing.T) {}",
1149
+ "",
1150
+ }, "\n"),
1151
+ })
1152
+ writeExecutable(t, filepath.Join(moduleDir, "node_modules", ".bin", "tsgo"), "#!/bin/sh\nexit 0\n")
1153
+ writeExecutable(t, filepath.Join(moduleDir, "node_modules", ".bin", "vitest"), strings.Join([]string{
1154
+ "#!/bin/sh",
1155
+ "printf '" + combinedRuntimeResultPrefix + "example.test%%2Fbrowserfail\\t0\\t3\\tpage%%20exploded\\n'",
1156
+ "exit 1",
1157
+ "",
1158
+ }, "\n"))
1159
+
1160
+ result, err := NewRunner().Run(context.Background(), &Request{
1161
+ Dir: moduleDir,
1162
+ Patterns: []string{"."},
1163
+ Timeout: 30 * time.Second,
1164
+ RuntimeBackend: RuntimeBackendBrowser,
1165
+ })
1166
+ if err != nil {
1167
+ t.Fatalf("run browser failure fixture: %v", err)
1168
+ }
1169
+ if result.Passed() {
1170
+ t.Fatalf("expected browser runtime failure")
1171
+ }
1172
+ pkg := requirePackageResult(t, result, "example.test/browserfail")
1173
+ if pkg.Action != ActionFail || pkg.Phases.Runtime != PhaseStatusFail || pkg.Error != "page exploded" {
1174
+ t.Fatalf("unexpected browser failure result: %#v", pkg)
1175
+ }
1176
+ }
1177
+
1178
+ func TestParseCombinedRuntimeRecordsLineProtocol(t *testing.T) {
1179
+ records, ok := parseCombinedRuntimeRecords(strings.Join([]string{
1180
+ "ordinary output",
1181
+ combinedRuntimeResultPrefix + "example.test%2Fpkg\t1\t42\tline%201%0Aline%202%09tail",
1182
+ "",
1183
+ }, "\n"))
1184
+ if !ok {
1185
+ t.Fatal("expected combined runtime record")
1186
+ }
1187
+ if len(records) != 1 {
1188
+ t.Fatalf("expected one combined runtime record, got %#v", records)
1189
+ }
1190
+ record := records[0]
1191
+ if record.PackagePath != "example.test/pkg" {
1192
+ t.Fatalf("unexpected package path: %q", record.PackagePath)
1193
+ }
1194
+ if !record.OK {
1195
+ t.Fatal("expected passing runtime record")
1196
+ }
1197
+ if record.ElapsedMS != 42 {
1198
+ t.Fatalf("unexpected elapsed ms: %d", record.ElapsedMS)
1199
+ }
1200
+ if record.Output != "line 1\nline 2\ttail" {
1201
+ t.Fatalf("unexpected output: %q", record.Output)
1202
+ }
1203
+ }
1204
+
1205
+ func TestRunnerReportsBrowserRuntimeMissingResult(t *testing.T) {
1206
+ moduleDir := writeFixture(t, map[string]string{
1207
+ "go.mod": "module example.test/browsermissing\n\ngo 1.25.3\n",
1208
+ "value_test.go": strings.Join([]string{
1209
+ "package browsermissing",
1210
+ "",
1211
+ "import \"testing\"",
1212
+ "",
1213
+ "func TestBrowser(t *testing.T) {}",
1214
+ "",
1215
+ }, "\n"),
1216
+ })
1217
+ writeExecutable(t, filepath.Join(moduleDir, "node_modules", ".bin", "tsgo"), "#!/bin/sh\nexit 0\n")
1218
+ writeExecutable(t, filepath.Join(moduleDir, "node_modules", ".bin", "vitest"), strings.Join([]string{
1219
+ "#!/bin/sh",
1220
+ "printf 'page exploded before result\\n'",
1221
+ "exit 1",
1222
+ "",
1223
+ }, "\n"))
1224
+
1225
+ result, err := NewRunner().Run(context.Background(), &Request{
1226
+ Dir: moduleDir,
1227
+ Patterns: []string{"."},
1228
+ Timeout: 30 * time.Second,
1229
+ RuntimeBackend: RuntimeBackendBrowser,
1230
+ })
1231
+ if err != nil {
1232
+ t.Fatalf("run browser missing-result fixture: %v", err)
1233
+ }
1234
+ if result.Passed() {
1235
+ t.Fatalf("expected browser runtime failure")
1236
+ }
1237
+ pkg := requirePackageResult(t, result, "example.test/browsermissing")
1238
+ if pkg.Action != ActionFail || pkg.Phases.Runtime != PhaseStatusFail {
1239
+ t.Fatalf("unexpected browser missing-result status: %#v", pkg)
1240
+ }
1241
+ if !strings.Contains(pkg.Error, "page exploded before result") {
1242
+ t.Fatalf("expected browser process output in error, got %#v", pkg)
1243
+ }
1244
+ }
1245
+
1075
1246
  func TestRunnerFallsBackToPackageScopedTypeScriptProjects(t *testing.T) {
1076
1247
  moduleDir := writeFixture(t, map[string]string{
1077
1248
  "go.mod": "module example.test/packageprojects\n\ngo 1.25.3\n",
@@ -1195,6 +1366,34 @@ func TestNormalizeKeepsIncrementalTypeCheckExplicit(t *testing.T) {
1195
1366
  }
1196
1367
  }
1197
1368
 
1369
+ func TestNormalizeRuntimeBackend(t *testing.T) {
1370
+ norm, err := (&Request{Patterns: []string{"."}}).normalize()
1371
+ if err != nil {
1372
+ t.Fatalf("normalize default runtime backend: %v", err)
1373
+ }
1374
+ if norm.RuntimeBackend != RuntimeBackendBun {
1375
+ t.Fatalf("runtime backend = %q, want %q", norm.RuntimeBackend, RuntimeBackendBun)
1376
+ }
1377
+
1378
+ norm, err = (&Request{
1379
+ Patterns: []string{"."},
1380
+ RuntimeBackend: RuntimeBackendBrowser,
1381
+ }).normalize()
1382
+ if err != nil {
1383
+ t.Fatalf("normalize browser runtime backend: %v", err)
1384
+ }
1385
+ if norm.RuntimeBackend != RuntimeBackendBrowser {
1386
+ t.Fatalf("runtime backend = %q, want %q", norm.RuntimeBackend, RuntimeBackendBrowser)
1387
+ }
1388
+
1389
+ if _, err := (&Request{
1390
+ Patterns: []string{"."},
1391
+ RuntimeBackend: RuntimeBackend("deno"),
1392
+ }).normalize(); err == nil {
1393
+ t.Fatal("expected unsupported runtime backend to fail")
1394
+ }
1395
+ }
1396
+
1198
1397
  func TestPackageExecutionIndexesPrioritizesLargerTestPackages(t *testing.T) {
1199
1398
  result := &Result{Packages: []PackageResult{
1200
1399
  {
@@ -1251,6 +1450,76 @@ func TestRenderRunnerChangesToPackageSourceDir(t *testing.T) {
1251
1450
  }
1252
1451
  }
1253
1452
 
1453
+ func TestRenderBrowserRunnerAvoidsProcessAPIs(t *testing.T) {
1454
+ req := &normalizedRequest{
1455
+ RuntimeBackend: RuntimeBackendBrowser,
1456
+ }
1457
+ runner := renderPackageRunner(PackageResult{
1458
+ PackagePath: "example.test/pkg",
1459
+ SourceDir: "/workspace/pkg",
1460
+ Tests: []Test{{
1461
+ Name: "TestBrowser",
1462
+ PackagePath: "example.test/pkg",
1463
+ }},
1464
+ }, req)
1465
+
1466
+ if strings.Contains(runner, "process.") {
1467
+ t.Fatalf("browser runner should not use process APIs: %s", runner)
1468
+ }
1469
+ if !strings.Contains(runner, "import { test } from \"vitest\"") {
1470
+ t.Fatalf("expected browser runner to use Vitest: %s", runner)
1471
+ }
1472
+ if !strings.Contains(runner, "await runTests(\"example.test/pkg\"") {
1473
+ t.Fatalf("expected browser runner to execute package tests: %s", runner)
1474
+ }
1475
+ }
1476
+
1477
+ func TestRenderBrowserRunnerReportsProcessExit(t *testing.T) {
1478
+ req := &normalizedRequest{
1479
+ RuntimeBackend: RuntimeBackendBrowser,
1480
+ }
1481
+ runner := renderPackageRunner(PackageResult{
1482
+ PackagePath: "example.test/pkg",
1483
+ SourceDir: "/workspace/pkg",
1484
+ Tests: []Test{{
1485
+ Name: "TestBrowser",
1486
+ PackagePath: "example.test/pkg",
1487
+ }},
1488
+ }, req)
1489
+
1490
+ if !strings.Contains(runner, "__goscriptProcessExitCode") {
1491
+ t.Fatalf("expected browser runner to classify process exit: %s", runner)
1492
+ }
1493
+ if !strings.Contains(runner, "goscript process exited with code") {
1494
+ t.Fatalf("expected browser runner to report process exit code: %s", runner)
1495
+ }
1496
+ if !strings.Contains(runner, "__goscriptOK = exitCode === 0") {
1497
+ t.Fatalf("expected zero exit to pass and nonzero exit to fail: %s", runner)
1498
+ }
1499
+ }
1500
+
1501
+ func TestRenderBrowserRunnerHonorsPanicOnExitZero(t *testing.T) {
1502
+ req := &normalizedRequest{
1503
+ RuntimeBackend: RuntimeBackendBrowser,
1504
+ PanicOnExit0: true,
1505
+ }
1506
+ runner := renderPackageRunner(PackageResult{
1507
+ PackagePath: "example.test/pkg",
1508
+ SourceDir: "/workspace/pkg",
1509
+ Tests: []Test{{
1510
+ Name: "TestBrowser",
1511
+ PackagePath: "example.test/pkg",
1512
+ }},
1513
+ }, req)
1514
+
1515
+ if !strings.Contains(runner, "exitCode === 0 && true") {
1516
+ t.Fatalf("expected panic-on-exit-zero to reject os.Exit(0): %s", runner)
1517
+ }
1518
+ if !strings.Contains(runner, "unexpected os.Exit(0) during test") {
1519
+ t.Fatalf("expected panic-on-exit-zero error text: %s", runner)
1520
+ }
1521
+ }
1522
+
1254
1523
  func TestRenderCombinedRunnerChangesToEachPackageSourceDir(t *testing.T) {
1255
1524
  req := &normalizedRequest{}
1256
1525
  runner := renderCombinedRunner(&Result{Packages: []PackageResult{
@@ -1303,6 +1572,29 @@ func TestRenderTypeScriptProjectDisablesAmbientTypePackages(t *testing.T) {
1303
1572
  }
1304
1573
  }
1305
1574
 
1575
+ func TestRenderBrowserTypeScriptProjectsExcludeNodeAmbientDeclarations(t *testing.T) {
1576
+ req := &normalizedRequest{
1577
+ WorkDir: "/work",
1578
+ RuntimeBackend: RuntimeBackendBrowser,
1579
+ }
1580
+
1581
+ packageTSConfig := renderTypeScriptProject(req, "/work/output/package-0", "runner-0.ts", "tsconfig-0.json", false)
1582
+ if strings.Contains(packageTSConfig, "goscript-node.d.ts") {
1583
+ t.Fatalf("browser package tsconfig should not include node ambient declarations: %s", packageTSConfig)
1584
+ }
1585
+ if !strings.Contains(packageTSConfig, "goscript-browser.d.ts") {
1586
+ t.Fatalf("browser package tsconfig should include browser ambient declarations: %s", packageTSConfig)
1587
+ }
1588
+
1589
+ aggregateTSConfig := renderRuntimeTypeScriptProject(req, []string{"/work/output"}, false)
1590
+ if strings.Contains(aggregateTSConfig, "goscript-node.d.ts") {
1591
+ t.Fatalf("browser aggregate tsconfig should not include node ambient declarations: %s", aggregateTSConfig)
1592
+ }
1593
+ if !strings.Contains(aggregateTSConfig, "goscript-browser.d.ts") {
1594
+ t.Fatalf("browser aggregate tsconfig should include browser ambient declarations: %s", aggregateTSConfig)
1595
+ }
1596
+ }
1597
+
1306
1598
  func TestRenderTypeScriptProjectUsesNodeTypesWhenAvailable(t *testing.T) {
1307
1599
  req := &normalizedRequest{
1308
1600
  WorkDir: "/work",
@@ -0,0 +1,20 @@
1
+ //go:build js && wasm
2
+
3
+ package browserapi
4
+
5
+ import (
6
+ "syscall/js"
7
+ "testing"
8
+ )
9
+
10
+ func TestBrowserAPI(t *testing.T) {
11
+ document := js.Global().Get("document")
12
+ if document.IsUndefined() || document.IsNull() {
13
+ t.Fatal("missing browser document")
14
+ }
15
+ div := document.Call("createElement", "div")
16
+ div.Set("id", "goscript-browser-api")
17
+ if got := div.Get("id").String(); got != "goscript-browser-api" {
18
+ t.Fatalf("div id = %q", got)
19
+ }
20
+ }
@@ -0,0 +1,3 @@
1
+ module example.test/browserapi
2
+
3
+ go 1.25.3
@@ -28,4 +28,27 @@ describe('GoScript Compiler API', () => {
28
28
  expect(generated).toContain('export async function main(): globalThis.Promise<void>')
29
29
  expect(generated).toContain('$.println("api")')
30
30
  }, 30000)
31
+
32
+ it('inherits positioned compiler diagnostics on stderr', async () => {
33
+ const dir = await mkdtemp(join(tmpdir(), 'goscript-api-diagnostic-'))
34
+ const output = join(dir, 'output')
35
+ await mkdir(dir, { recursive: true })
36
+ await writeFile(join(dir, 'go.mod'), 'module example.test/apierr\n\ngo 1.25.3\n')
37
+ await writeFile(join(dir, 'main.go'), [
38
+ 'package apierr',
39
+ '',
40
+ 'func Make[T ~[]int]() T {',
41
+ ' return make(T, 1)',
42
+ '}',
43
+ '',
44
+ ].join('\n'))
45
+
46
+ await expect(compile({
47
+ pkg: '.',
48
+ output,
49
+ dir,
50
+ })).rejects.toMatchObject({
51
+ stderr: expect.stringContaining('main.go:4:'),
52
+ })
53
+ }, 30000)
31
54
  })
@@ -18,6 +18,7 @@ type loweredFile struct {
18
18
  decls []loweredDecl
19
19
  exports []string
20
20
  typeExports []string
21
+ exportAll bool
21
22
  sideEffect bool
22
23
  }
23
24
 
@@ -58,13 +59,14 @@ type loweredDecl struct {
58
59
  }
59
60
 
60
61
  type loweredStruct struct {
61
- exported bool
62
- indexExported bool
63
- name string
64
- typeName string
65
- cloneMethod string
66
- fields []loweredStructField
67
- methods []loweredFunction
62
+ exported bool
63
+ indexExported bool
64
+ protobufPreserveJSON bool
65
+ name string
66
+ typeName string
67
+ cloneMethod string
68
+ fields []loweredStructField
69
+ methods []loweredFunction
68
70
  }
69
71
 
70
72
  type loweredStructField struct {
@@ -75,28 +77,35 @@ type loweredStructField struct {
75
77
  runtimeType string
76
78
  doc string
77
79
  tag string
80
+ pkgPath string
81
+ index []int
82
+ offset int64
83
+ anonymous bool
84
+ exported bool
78
85
  structValue bool
79
86
  arrayValue bool
80
87
  }
81
88
 
82
89
  type loweredFunction struct {
83
- exported bool
84
- indexExported bool
85
- init bool
86
- async bool
87
- name string
88
- typeParams []string
89
- runtimeName string
90
- receiverAlias string
91
- receiverType string
92
- receiverValue string
93
- receiverMutable bool
94
- params []loweredParam
95
- paramBindings []loweredStmt
96
- namedResults []loweredNamedResult
97
- result string
98
- body []loweredStmt
99
- deferState *loweredDeferState
90
+ exported bool
91
+ indexExported bool
92
+ init bool
93
+ async bool
94
+ sourcePath string
95
+ name string
96
+ typeParams []string
97
+ runtimeName string
98
+ runtimeSignature string
99
+ receiverAlias string
100
+ receiverType string
101
+ receiverValue string
102
+ receiverMutable bool
103
+ params []loweredParam
104
+ paramBindings []loweredStmt
105
+ namedResults []loweredNamedResult
106
+ result string
107
+ body []loweredStmt
108
+ deferState *loweredDeferState
100
109
  }
101
110
 
102
111
  type loweredParam struct {