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
@@ -44,6 +44,7 @@ export interface MethodSignature {
44
44
  */
45
45
  export interface StructFieldInfo {
46
46
  type: TypeInfo | string // The field's type
47
+ name?: string // The Go field name when it differs from the TypeScript key.
47
48
  tag?: string // The struct field tag (e.g., `json:"name,omitempty"`)
48
49
  }
49
50
 
@@ -233,6 +234,13 @@ export const registerStructType = (
233
234
  return typeInfo
234
235
  }
235
236
 
237
+ function resolveZeroValue<T>(zeroValue: any): T {
238
+ if (typeof zeroValue === 'function') {
239
+ return zeroValue() as T
240
+ }
241
+ return zeroValue as T
242
+ }
243
+
236
244
  /**
237
245
  * Registers an interface type with the runtime type system.
238
246
  *
@@ -500,13 +508,9 @@ function matchesStructType(value: any, info: TypeInfo): boolean {
500
508
 
501
509
  if (fieldsExist && sameFieldCount && allFieldsInStruct) {
502
510
  return Object.entries(info.fields).every(([fieldName, fieldType]) => {
503
- const fieldTypeInfo = isStructFieldInfo(fieldType)
504
- ? fieldType.type
505
- : fieldType
506
- return matchesType(
507
- value[fieldName],
508
- normalizeTypeInfo(fieldTypeInfo),
509
- )
511
+ const fieldTypeInfo =
512
+ isStructFieldInfo(fieldType) ? fieldType.type : fieldType
513
+ return matchesType(value[fieldName], normalizeTypeInfo(fieldTypeInfo))
510
514
  })
511
515
  }
512
516
 
@@ -667,9 +671,15 @@ function matchesMapType(value: any, info: TypeInfo): boolean {
667
671
  */
668
672
  function matchesArrayOrSliceType(value: any, info: TypeInfo): boolean {
669
673
  // For slices and arrays, check if the value is an array and sample element types
670
- if (!Array.isArray(value)) return false
671
674
  if (!isArrayTypeInfo(info) && !isSliceTypeInfo(info)) return false
672
675
 
676
+ if (value instanceof Uint8Array) {
677
+ if (isArrayTypeInfo(info) && value.length !== info.length) return false
678
+ return isNumberElementType(info.elemType)
679
+ }
680
+
681
+ if (!Array.isArray(value)) return false
682
+
673
683
  if (info.elemType) {
674
684
  const arr = value as any[]
675
685
  if (arr.length === 0) return true // Empty array matches any array type
@@ -690,6 +700,21 @@ function matchesArrayOrSliceType(value: any, info: TypeInfo): boolean {
690
700
  return true
691
701
  }
692
702
 
703
+ function isNumberElementType(typeInfo: string | TypeInfo | undefined): boolean {
704
+ if (typeInfo === undefined) return true
705
+ const info = normalizeTypeInfo(typeInfo)
706
+ return (
707
+ info.kind === TypeKind.Basic &&
708
+ (info.name === undefined ||
709
+ info.name === 'number' ||
710
+ info.name === 'int' ||
711
+ info.name === 'uint' ||
712
+ info.name === 'uint8' ||
713
+ info.name === 'byte' ||
714
+ info.name === 'float64')
715
+ )
716
+ }
717
+
693
718
  // Symbol used to mark struct instances that represent values (not pointers)
694
719
  const STRUCT_VALUE_MARKER = Symbol('structValue')
695
720
 
@@ -701,6 +726,20 @@ export function markAsStructValue<T>(value: T): T {
701
726
  return value
702
727
  }
703
728
 
729
+ export function cloneStructValue<T>(value: T): T {
730
+ const cloneable = value as T & {
731
+ __goscriptClone?: () => T
732
+ clone?: () => T
733
+ }
734
+ if (typeof cloneable.__goscriptClone === 'function') {
735
+ return cloneable.__goscriptClone()
736
+ }
737
+ if (typeof cloneable.clone === 'function') {
738
+ return cloneable.clone()
739
+ }
740
+ throw new Error('runtime error: value is not cloneable')
741
+ }
742
+
704
743
  // Check if a struct instance is marked as a value
705
744
  function isMarkedAsStructValue(value: any): boolean {
706
745
  return (
@@ -729,6 +768,10 @@ function matchesPointerType(value: any, info: TypeInfo): boolean {
729
768
 
730
769
  if (!isPointerTypeInfo(info)) return false
731
770
 
771
+ if (typeof value.__goType === 'string') {
772
+ return compareTypeStringWithTypeInfo(value.__goType, info)
773
+ }
774
+
732
775
  if (!info.elemType) return false
733
776
 
734
777
  let elem = info.elemType
@@ -854,6 +897,13 @@ function matchesType(value: any, info: TypeInfo): boolean {
854
897
  if (value === null || value === undefined) {
855
898
  return false
856
899
  }
900
+ if (
901
+ typeof value === 'object' &&
902
+ typeof value.__goType === 'string' &&
903
+ value.__goType === info.name
904
+ ) {
905
+ return true
906
+ }
857
907
 
858
908
  switch (info.kind) {
859
909
  case TypeKind.Basic:
@@ -1011,7 +1061,10 @@ export function typeAssert<T>(
1011
1061
 
1012
1062
  // Handle typed nil pointers (created by typedNil() for conversions like (*T)(nil))
1013
1063
  if (typeof value === 'object' && value !== null && value.__isTypedNil) {
1014
- if (isInterfaceTypeInfo(normalizedType) && matchesInterfaceType(value, normalizedType)) {
1064
+ if (
1065
+ isInterfaceTypeInfo(normalizedType) &&
1066
+ matchesInterfaceType(value, normalizedType)
1067
+ ) {
1015
1068
  return { value: value as T, ok: true }
1016
1069
  }
1017
1070
  // For typed nils, we need to compare the stored type with the expected type
@@ -1029,6 +1082,17 @@ export function typeAssert<T>(
1029
1082
  if (isPointerTypeInfo(normalizedType) && value === null) {
1030
1083
  return { value: null as unknown as T, ok: false }
1031
1084
  }
1085
+ if (
1086
+ typeof value === 'object' &&
1087
+ value !== null &&
1088
+ typeof value.__goType === 'string' &&
1089
+ value.__goType === normalizedType.name
1090
+ ) {
1091
+ if ('__goValue' in value) {
1092
+ return { value: value.__goValue as T, ok: true }
1093
+ }
1094
+ return { value: value as T, ok: true }
1095
+ }
1032
1096
 
1033
1097
  // Removed struct matching logic - struct types should use nominal matching
1034
1098
  // via matchesStructType in matchesType, not structural matching here
@@ -1040,9 +1104,9 @@ export function typeAssert<T>(
1040
1104
  ) {
1041
1105
  if (normalizedType.keyType || normalizedType.elemType) {
1042
1106
  const entries =
1043
- value instanceof Map
1044
- ? Array.from(value.entries())
1045
- : Object.entries(value)
1107
+ value instanceof Map ?
1108
+ Array.from(value.entries())
1109
+ : Object.entries(value)
1046
1110
 
1047
1111
  if (entries.length === 0) {
1048
1112
  return { value: value as T, ok: true }
@@ -1080,17 +1144,6 @@ export function typeAssert<T>(
1080
1144
 
1081
1145
  const matches = matchesType(value, normalizedType)
1082
1146
  if (matches) {
1083
- // Special handling for pointer type assertions:
1084
- // If the value is a VarRef and we're asserting to a pointer type,
1085
- // return the inner value (value.value), not the VarRef object itself
1086
- if (
1087
- isPointerTypeInfo(normalizedType) &&
1088
- typeof value === 'object' &&
1089
- value !== null &&
1090
- 'value' in value
1091
- ) {
1092
- return { value: value.value as T, ok: true }
1093
- }
1094
1147
  return { value: value as T, ok: true }
1095
1148
  }
1096
1149
 
@@ -1099,10 +1152,10 @@ export function typeAssert<T>(
1099
1152
  if (typeof typeInfo === 'string') {
1100
1153
  const registeredType = typeRegistry.get(typeInfo)
1101
1154
  if (registeredType && registeredType.zeroValue !== undefined) {
1102
- return { value: registeredType.zeroValue as T, ok: false }
1155
+ return { value: resolveZeroValue<T>(registeredType.zeroValue), ok: false }
1103
1156
  }
1104
1157
  } else if (normalizedType.zeroValue !== undefined) {
1105
- return { value: normalizedType.zeroValue as T, ok: false }
1158
+ return { value: resolveZeroValue<T>(normalizedType.zeroValue), ok: false }
1106
1159
  }
1107
1160
 
1108
1161
  return { value: null as unknown as T, ok: false }
@@ -1166,7 +1219,7 @@ export function is(value: any, typeInfo: string | TypeInfo): boolean {
1166
1219
  */
1167
1220
  export interface TypeSwitchCase {
1168
1221
  types: (string | TypeInfo)[] // Array of types for this case (e.g., case int, string:)
1169
- body: (value?: any) => void // Function representing the case body. 'value' is the asserted value if applicable.
1222
+ body: (value?: any) => any // Function representing the case body. 'value' is the asserted value if applicable.
1170
1223
  }
1171
1224
 
1172
1225
  /**
@@ -1180,16 +1233,15 @@ export interface TypeSwitchCase {
1180
1233
  export function typeSwitch(
1181
1234
  value: any,
1182
1235
  cases: TypeSwitchCase[],
1183
- defaultCase?: () => void,
1184
- ): void {
1236
+ defaultCase?: () => any,
1237
+ ): any {
1185
1238
  for (const caseObj of cases) {
1186
1239
  // For cases with multiple types (case T1, T2:), use $.is
1187
1240
  if (caseObj.types.length > 1) {
1188
1241
  const matchesAny = caseObj.types.some((typeInfo) => is(value, typeInfo))
1189
1242
  if (matchesAny) {
1190
1243
  // For multi-type cases, the case variable (if any) gets the original value
1191
- caseObj.body(value)
1192
- return // Found a match, exit switch
1244
+ return caseObj.body(value)
1193
1245
  }
1194
1246
  } else if (caseObj.types.length === 1) {
1195
1247
  // For single-type cases (case T:), use $.typeAssert to get the typed value and ok status
@@ -1197,9 +1249,7 @@ export function typeSwitch(
1197
1249
  const { value: assertedValue, ok } = typeAssert(value, typeInfo)
1198
1250
  if (ok) {
1199
1251
  // Pass the asserted value to the case body function
1200
- caseObj.body(assertedValue)
1201
-
1202
- return // Found a match, exit switch
1252
+ return caseObj.body(assertedValue)
1203
1253
  }
1204
1254
  }
1205
1255
  // Note: Cases with 0 types are not valid in Go type switches
@@ -1207,7 +1257,7 @@ export function typeSwitch(
1207
1257
 
1208
1258
  // If no case matched and a default case exists, execute it
1209
1259
  if (defaultCase) {
1210
- defaultCase()
1260
+ return defaultCase()
1211
1261
  }
1212
1262
  }
1213
1263
 
@@ -1228,6 +1278,13 @@ export function typedNil(typeName: string): any {
1228
1278
 
1229
1279
  export function interfaceValue<T>(value: unknown, typeName: string): T {
1230
1280
  if (value !== null && value !== undefined) {
1281
+ if (typeof value === 'object') {
1282
+ Object.defineProperty(value, '__goType', {
1283
+ value: typeName,
1284
+ writable: true,
1285
+ configurable: true,
1286
+ })
1287
+ }
1231
1288
  return value as T
1232
1289
  }
1233
1290
 
@@ -1255,6 +1312,24 @@ export function interfaceValue<T>(value: unknown, typeName: string): T {
1255
1312
  return nilValue as T
1256
1313
  }
1257
1314
 
1315
+ export function namedValueInterfaceValue<T>(
1316
+ value: unknown,
1317
+ typeName: string,
1318
+ methods: Record<string, (receiver: any, ...args: any[]) => any>,
1319
+ ): T {
1320
+ const boxed: any = {
1321
+ __goType: typeName,
1322
+ __goValue: value,
1323
+ valueOf: () => value,
1324
+ toString: () => String(value),
1325
+ [Symbol.toPrimitive]: () => value as any,
1326
+ }
1327
+ for (const [name, method] of Object.entries(methods)) {
1328
+ boxed[name] = (...args: any[]) => method(value, ...args)
1329
+ }
1330
+ return boxed as T
1331
+ }
1332
+
1258
1333
  export function namedFunction<T>(fn: T, typeName: string): T {
1259
1334
  if (typeof fn !== 'function') {
1260
1335
  return fn
@@ -5,7 +5,12 @@
5
5
  * var myVariable int // variable referenced
6
6
  * myOtherVar := &myVariable
7
7
  */
8
- export type VarRef<T> = { value: T; __isVarRef?: true }
8
+ export type VarRef<T> = {
9
+ value: T
10
+ __isVarRef?: true
11
+ __goType?: string
12
+ __goAddress?: () => number
13
+ }
9
14
 
10
15
  /** Wrap a non-null T in a variable reference. */
11
16
  export function varRef<T>(v: T): VarRef<T> {
@@ -15,6 +20,22 @@ export function varRef<T>(v: T): VarRef<T> {
15
20
  return { value: v, __isVarRef: true }
16
21
  }
17
22
 
23
+ /** Create a variable reference to an object field. */
24
+ export function fieldRef<T extends object, K extends keyof T>(
25
+ target: T,
26
+ key: K,
27
+ ): VarRef<T[K]> {
28
+ return {
29
+ get value(): T[K] {
30
+ return target[key]
31
+ },
32
+ set value(value: T[K]) {
33
+ target[key] = value
34
+ },
35
+ __isVarRef: true,
36
+ }
37
+ }
38
+
18
39
  /** Check if a value is a VarRef (pointer) */
19
40
  export function isVarRef(v: unknown): v is VarRef<unknown> {
20
41
  return v !== null && typeof v === 'object' && (v as any).__isVarRef === true
@@ -29,3 +50,19 @@ export function unref<T>(b: VarRef<T>): T {
29
50
  }
30
51
  return b.value
31
52
  }
53
+
54
+ export function unsupportedPointerRef<T>(_value: unknown): VarRef<T> {
55
+ return {
56
+ get value(): T {
57
+ throw new Error(
58
+ 'unsafe pointer dereference is not supported in JavaScript/TypeScript',
59
+ )
60
+ },
61
+ set value(_value: T) {
62
+ throw new Error(
63
+ 'unsafe pointer dereference is not supported in JavaScript/TypeScript',
64
+ )
65
+ },
66
+ __isVarRef: true,
67
+ }
68
+ }
@@ -269,28 +269,30 @@ export class Buffer {
269
269
  // error except io.EOF encountered during the read is also returned. If the
270
270
  // buffer becomes too large, ReadFrom will panic with [ErrTooLarge].
271
271
  public ReadFrom(r: io.Reader): [number, $.GoError] {
272
- const b = this
273
- b.lastRead = 0
274
- let n = 0
275
- for (; ; ) {
276
- let i = b.grow(512)
277
- b.buf = $.goSlice(b.buf, undefined, i)
278
- let [m, e] = r!.Read($.bytesToUint8Array($.goSlice(b.buf, i, $.cap(b.buf))))
279
- if (m < 0) {
280
- $.panic(errNegativeRead)
281
- }
272
+ return (async (): Promise<[number, $.GoError]> => {
273
+ const b = this
274
+ b.lastRead = 0
275
+ let n = 0
276
+ for (; ; ) {
277
+ let i = b.grow(512)
278
+ b.buf = $.goSlice(b.buf, undefined, i)
279
+ let [m, e] = await (r!.Read($.bytesToUint8Array($.goSlice(b.buf, i, $.cap(b.buf)))) as any)
280
+ if (m < 0) {
281
+ $.panic(errNegativeRead)
282
+ }
282
283
 
283
- b.buf = $.goSlice(b.buf, undefined, i + m)
284
- n += (m as number)
284
+ b.buf = $.goSlice(b.buf, undefined, i + m)
285
+ n += (m as number)
285
286
 
286
- // e is EOF, so return nil explicitly
287
- if (e == io.EOF) {
288
- return [n, null]
289
- }
290
- if (e != null) {
291
- return [n, e]
287
+ // e is EOF, so return nil explicitly
288
+ if (e == io.EOF) {
289
+ return [n, null]
290
+ }
291
+ if (e != null) {
292
+ return [n, e]
293
+ }
292
294
  }
293
- }
295
+ })() as any
294
296
  }
295
297
 
296
298
  // WriteTo writes data to w until the buffer is drained or an error occurs.
@@ -298,30 +300,32 @@ export class Buffer {
298
300
  // int, but it is int64 to match the [io.WriterTo] interface. Any error
299
301
  // encountered during the write is also returned.
300
302
  public WriteTo(w: io.Writer): [number, $.GoError] {
301
- const b = this
302
- b.lastRead = 0
303
- let n = 0
304
- {
305
- let nBytes = b.Len()
306
- if (nBytes > 0) {
307
- let [m, e] = w!.Write($.bytesToUint8Array($.goSlice(b.buf, b.off, undefined)))
308
- if (m > nBytes) {
309
- $.panic("bytes.Buffer.WriteTo: invalid Write count")
310
- }
311
- b.off += m
312
- n = (m as number)
313
- if (e != null) {
314
- return [n, e]
315
- }
316
- // all bytes should have been written, by definition of
317
- // Write method in io.Writer
318
- if (m != nBytes) {
319
- return [n, io.ErrShortWrite]
303
+ return (async (): Promise<[number, $.GoError]> => {
304
+ const b = this
305
+ b.lastRead = 0
306
+ let n = 0
307
+ {
308
+ let nBytes = b.Len()
309
+ if (nBytes > 0) {
310
+ let [m, e] = await (w!.Write($.bytesToUint8Array($.goSlice(b.buf, b.off, undefined))) as any)
311
+ if (m > nBytes) {
312
+ $.panic("bytes.Buffer.WriteTo: invalid Write count")
313
+ }
314
+ b.off += m
315
+ n = (m as number)
316
+ if (e != null) {
317
+ return [n, e]
318
+ }
319
+ // all bytes should have been written, by definition of
320
+ // Write method in io.Writer
321
+ if (m != nBytes) {
322
+ return [n, io.ErrShortWrite]
323
+ }
320
324
  }
321
325
  }
322
- }
323
- b.Reset()
324
- return [n, null]
326
+ b.Reset()
327
+ return [n, null]
328
+ })() as any
325
329
  }
326
330
 
327
331
  // WriteByte appends the byte c to the buffer, growing the buffer as needed.
@@ -373,7 +377,7 @@ export class Buffer {
373
377
  }
374
378
  return [0, io.EOF]
375
379
  }
376
- const n = $.copy($.bytesToUint8Array(p), $.bytesToUint8Array($.goSlice(b.buf, b.off, undefined)))
380
+ const n = $.copy(p, $.goSlice(b.buf, b.off, undefined))
377
381
  b.off += n
378
382
  if (n > 0) {
379
383
  b.lastRead = -1
@@ -603,8 +607,8 @@ export function growSlice(b: $.Bytes, n: number): $.Bytes {
603
607
  // we could rely purely on append to determine the growth rate.
604
608
  c = 2 * $.cap(b)
605
609
  }
606
- let b2 = $.append<number>(null, new Uint8Array(c))
607
- let i = $.copy($.bytesToUint8Array(b2), $.bytesToUint8Array(b))
610
+ let b2 = $.makeSlice<number>(c, c, 'byte')
611
+ let i = $.copy(b2, b)
608
612
  return $.goSlice(b2, undefined, i)
609
613
  }
610
614
 
@@ -1,10 +1,15 @@
1
1
  {
2
2
  "dependencies": [
3
3
  "errors",
4
- "io",
4
+ "io",
5
5
  "iter",
6
6
  "unicode",
7
7
  "unicode/utf8",
8
8
  "unsafe"
9
- ]
10
- }
9
+ ],
10
+ "asyncMethods": {
11
+ "Buffer.ReadFrom": true,
12
+ "Buffer.WriteTo": true,
13
+ "Reader.WriteTo": true
14
+ }
15
+ }
@@ -80,7 +80,7 @@ export class Reader {
80
80
  return [0, io.EOF]
81
81
  }
82
82
  r.prevRune = -1
83
- const n = $.copy($.bytesToUint8Array(b), $.bytesToUint8Array($.goSlice(r.s, r.i, undefined)))
83
+ const n = $.copy(b, $.goSlice(r.s, r.i, undefined))
84
84
  r.i += (n as number)
85
85
  return [n, null]
86
86
  }
@@ -94,7 +94,7 @@ export class Reader {
94
94
  if (off >= ($.len(r.s) as number)) {
95
95
  return [0, io.EOF]
96
96
  }
97
- const n = $.copy($.bytesToUint8Array(b), $.bytesToUint8Array($.goSlice(r.s, off, undefined)))
97
+ const n = $.copy(b, $.goSlice(r.s, off, undefined))
98
98
  let err: $.GoError = null
99
99
  if (n < $.len(b)) {
100
100
  err = io.EOF
@@ -187,22 +187,24 @@ export class Reader {
187
187
 
188
188
  // WriteTo implements the [io.WriterTo] interface.
189
189
  public WriteTo(w: io.Writer): [number, $.GoError] {
190
- const r = this
191
- r.prevRune = -1
192
- if (r.i >= ($.len(r.s) as number)) {
193
- return [0, null]
194
- }
195
- const b = $.goSlice(r.s, r.i, undefined)
196
- const [m, err] = w!.Write($.bytesToUint8Array(b))
197
- if (m > $.len(b)) {
198
- $.panic("bytes.Reader.WriteTo: invalid Write count")
199
- }
200
- r.i += (m as number)
201
- const n = (m as number)
202
- if (m != $.len(b) && err == null) {
203
- return [n, io.ErrShortWrite]
204
- }
205
- return [n, err]
190
+ return (async (): Promise<[number, $.GoError]> => {
191
+ const r = this
192
+ r.prevRune = -1
193
+ if (r.i >= ($.len(r.s) as number)) {
194
+ return [0, null]
195
+ }
196
+ const b = $.goSlice(r.s, r.i, undefined)
197
+ const [m, err] = await (w!.Write($.bytesToUint8Array(b)) as any)
198
+ if (m > $.len(b)) {
199
+ $.panic("bytes.Reader.WriteTo: invalid Write count")
200
+ }
201
+ r.i += (m as number)
202
+ const n = (m as number)
203
+ if (m != $.len(b) && err == null) {
204
+ return [n, io.ErrShortWrite]
205
+ }
206
+ return [n, err]
207
+ })() as any
206
208
  }
207
209
 
208
210
  // Reset resets the [Reader] to be reading from b.
@@ -227,4 +229,3 @@ export class Reader {
227
229
  export function NewReader(b: $.Bytes): Reader {
228
230
  return new Reader({s: $.normalizeBytes(b), i: 0, prevRune: -1})
229
231
  }
230
-
@@ -0,0 +1,41 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { AfterFunc, WithCancel, Background } from './index.js'
4
+
5
+ async function nextMicrotask(): Promise<void> {
6
+ await new Promise<void>((resolve) => queueMicrotask(resolve))
7
+ }
8
+
9
+ describe('context override', () => {
10
+ it('runs AfterFunc after cancellation', async () => {
11
+ const [ctx, cancel] = WithCancel(Background())
12
+ let called = false
13
+
14
+ const stop = AfterFunc(ctx, () => {
15
+ called = true
16
+ })
17
+
18
+ cancel?.()
19
+ await nextMicrotask()
20
+ await nextMicrotask()
21
+
22
+ expect(called).toBe(true)
23
+ expect(stop()).toBe(false)
24
+ })
25
+
26
+ it('stops AfterFunc before cancellation', async () => {
27
+ const [ctx, cancel] = WithCancel(Background())
28
+ let called = false
29
+
30
+ const stop = AfterFunc(ctx, () => {
31
+ called = true
32
+ })
33
+
34
+ expect(stop()).toBe(true)
35
+ cancel?.()
36
+ await nextMicrotask()
37
+ await nextMicrotask()
38
+
39
+ expect(called).toBe(false)
40
+ })
41
+ })