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
package/gs/time/time.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import * as $ from '../builtin/index.js'
1
2
  import { makeChannel, ChannelRef, makeChannelRef } from '../builtin/channel.js'
2
3
 
3
4
  // Time represents a time instant with nanosecond precision
@@ -132,11 +133,40 @@ export class Time {
132
133
  return this._nsec
133
134
  }
134
135
 
136
+ public Date(): [number, Month, number] {
137
+ return [this.Year(), this.Month(), this.Day()]
138
+ }
139
+
140
+ public Clock(): [number, number, number] {
141
+ return [this.Hour(), this.Minute(), this.Second()]
142
+ }
143
+
144
+ public Zone(): [string, number] {
145
+ if (this._location.offsetSeconds !== undefined) {
146
+ return [this._location.name, this._location.offsetSeconds]
147
+ }
148
+ const offset = -this._date.getTimezoneOffset() * 60
149
+ return [this._location.name, offset]
150
+ }
151
+
135
152
  // Location returns the time zone information associated with t
136
153
  public Location(): Location {
137
154
  return this._location
138
155
  }
139
156
 
157
+ // UTC returns t with the location set to UTC.
158
+ public UTC(): Time {
159
+ return Time.create(this._date, this._nsec, undefined, UTC)
160
+ }
161
+
162
+ // In returns a copy of t representing the same instant in loc.
163
+ public In(loc: Location | $.VarRef<Location> | null): Time {
164
+ if (loc === null) {
165
+ throw new Error('time: missing Location in call to Time.In')
166
+ }
167
+ return Time.create(this._date, this._nsec, undefined, $.pointerValue(loc))
168
+ }
169
+
140
170
  // Format returns a textual representation of the time value formatted according to the layout
141
171
  public Format(layout: string): string {
142
172
  // Implementation of Go's time formatting based on reference time:
@@ -498,7 +528,7 @@ export class Time {
498
528
  // Add adds the duration d to t, returning the sum
499
529
  // Preserves monotonic reading if present
500
530
  public Add(d: Duration): Time {
501
- const durationNs = d
531
+ const durationNs = durationNumber(d)
502
532
  const newDate = new globalThis.Date(
503
533
  this._date.getTime() + Math.floor(durationNs / 1000000),
504
534
  )
@@ -508,6 +538,33 @@ export class Time {
508
538
  return Time.create(newDate, newNsec, newMonotonic, this._location)
509
539
  }
510
540
 
541
+ public AddDate(years: number, months: number, days: number): Time {
542
+ if (this._location.offsetSeconds !== undefined) {
543
+ const offsetMs = this._location.offsetSeconds * 1000
544
+ const local = new globalThis.Date(this._date.getTime() + offsetMs)
545
+ const shifted = globalThis.Date.UTC(
546
+ local.getUTCFullYear() + years,
547
+ local.getUTCMonth() + months,
548
+ local.getUTCDate() + days,
549
+ local.getUTCHours(),
550
+ local.getUTCMinutes(),
551
+ local.getUTCSeconds(),
552
+ local.getUTCMilliseconds(),
553
+ )
554
+ return Time.create(
555
+ new globalThis.Date(shifted - offsetMs),
556
+ this._nsec,
557
+ undefined,
558
+ this._location,
559
+ )
560
+ }
561
+ const shifted = new globalThis.Date(this._date.getTime())
562
+ shifted.setFullYear(shifted.getFullYear() + years)
563
+ shifted.setMonth(shifted.getMonth() + months)
564
+ shifted.setDate(shifted.getDate() + days)
565
+ return Time.create(shifted, this._nsec, undefined, this._location)
566
+ }
567
+
511
568
  // Equal reports whether t and u represent the same time instant
512
569
  // Uses monotonic clock if both times have it
513
570
  public Equal(u: Time): boolean {
@@ -517,6 +574,10 @@ export class Time {
517
574
  return this._date.getTime() === u._date.getTime() && this._nsec === u._nsec
518
575
  }
519
576
 
577
+ public IsZero(): boolean {
578
+ return this.Equal(new Time())
579
+ }
580
+
520
581
  // Before reports whether the time instant t is before u
521
582
  // Uses monotonic clock if both times have it
522
583
  public Before(u: Time): boolean {
@@ -579,6 +640,25 @@ export class Time {
579
640
  // Duration represents a span of time (nanoseconds)
580
641
  export type Duration = number
581
642
 
643
+ const maxDuration = Number(9223372036854775807n)
644
+ const minDuration = Number(-9223372036854775808n)
645
+ const maxTimerDelayMilliseconds = 0x7fffffff
646
+
647
+ function durationNumber(d: Duration): number {
648
+ return Number(d)
649
+ }
650
+
651
+ function timeoutMilliseconds(d: Duration): number {
652
+ const ms = durationNumber(d) / 1000000
653
+ if (!Number.isFinite(ms) || ms > maxTimerDelayMilliseconds) {
654
+ return maxTimerDelayMilliseconds
655
+ }
656
+ if (ms <= 0) {
657
+ return 0
658
+ }
659
+ return ms
660
+ }
661
+
582
662
  // Duration comparison function
583
663
  export function Duration_lt(receiver: Duration, other: Duration): boolean {
584
664
  return receiver < other
@@ -589,7 +669,116 @@ export function Duration_multiply(
589
669
  receiver: Duration,
590
670
  multiplier: number,
591
671
  ): Duration {
592
- return receiver * multiplier
672
+ return durationNumber(receiver) * multiplier
673
+ }
674
+
675
+ export function Duration_Abs(receiver: Duration): Duration {
676
+ const value = durationNumber(receiver)
677
+ if (value >= 0) {
678
+ return value
679
+ }
680
+ if (value === minDuration) {
681
+ return maxDuration
682
+ }
683
+ return -value
684
+ }
685
+
686
+ export function Duration_Hours(receiver: Duration): number {
687
+ return durationNumber(receiver) / Hour
688
+ }
689
+
690
+ export function Duration_Microseconds(receiver: Duration): number {
691
+ return Math.trunc(durationNumber(receiver) / Microsecond)
692
+ }
693
+
694
+ export function Duration_Milliseconds(receiver: Duration): number {
695
+ return Math.trunc(durationNumber(receiver) / Millisecond)
696
+ }
697
+
698
+ export function Duration_Minutes(receiver: Duration): number {
699
+ return durationNumber(receiver) / Minute
700
+ }
701
+
702
+ export function Duration_Nanoseconds(receiver: Duration): number {
703
+ return durationNumber(receiver)
704
+ }
705
+
706
+ export function Duration_Round(receiver: Duration, multiple: Duration): Duration {
707
+ const value = durationNumber(receiver)
708
+ const unit = durationNumber(multiple)
709
+ if (unit <= 0) {
710
+ return value
711
+ }
712
+ const rounded =
713
+ value >= 0 ?
714
+ Math.floor(value / unit + 0.5) * unit
715
+ : Math.ceil(value / unit - 0.5) * unit
716
+ return Math.max(minDuration, Math.min(maxDuration, rounded))
717
+ }
718
+
719
+ // Duration_Seconds returns the duration as a floating point number of seconds.
720
+ export function Duration_Seconds(receiver: Duration): number {
721
+ return durationNumber(receiver) / Second
722
+ }
723
+
724
+ export function Duration_Truncate(
725
+ receiver: Duration,
726
+ multiple: Duration,
727
+ ): Duration {
728
+ const value = durationNumber(receiver)
729
+ const unit = durationNumber(multiple)
730
+ if (unit <= 0) {
731
+ return value
732
+ }
733
+ return value - (value % unit)
734
+ }
735
+
736
+ export function Duration_String(receiver: Duration): string {
737
+ const value = durationNumber(receiver)
738
+ if (value === 0) {
739
+ return '0s'
740
+ }
741
+ const sign = value < 0 ? '-' : ''
742
+ let remaining = Math.abs(value)
743
+ const hours = Math.floor(remaining / Hour)
744
+ remaining -= hours * Hour
745
+ const minutes = Math.floor(remaining / Minute)
746
+ remaining -= minutes * Minute
747
+ const seconds = Math.floor(remaining / Second)
748
+ remaining -= seconds * Second
749
+
750
+ let out = sign
751
+ if (hours !== 0) {
752
+ out += `${hours}h`
753
+ }
754
+ if (minutes !== 0) {
755
+ out += `${minutes}m`
756
+ }
757
+ if (seconds !== 0 || remaining !== 0) {
758
+ out += formatSeconds(seconds, remaining)
759
+ }
760
+ return out
761
+ }
762
+
763
+ export function Duration_format(
764
+ receiver: Duration,
765
+ buf: $.VarRef<number[]>,
766
+ ): number {
767
+ const text = Duration_String(receiver)
768
+ const bytes = Array.from(new TextEncoder().encode(text))
769
+ const start = Math.max(0, buf.value.length - bytes.length)
770
+ for (let idx = 0; idx < bytes.length && start + idx < buf.value.length; idx++) {
771
+ buf.value[start + idx] = bytes[idx]!
772
+ }
773
+ return start
774
+ }
775
+
776
+ function formatSeconds(seconds: number, nanos: number): string {
777
+ if (nanos === 0) {
778
+ return `${seconds}s`
779
+ }
780
+ const fraction = String(nanos).padStart(9, '0').replace(/0+$/, '')
781
+ return `${seconds}.${fraction}s`
593
782
  }
594
783
 
595
784
  // Location represents a time zone
@@ -692,17 +881,13 @@ export class Timer {
692
881
  private _timeout: NodeJS.Timeout | number
693
882
  private _duration: Duration
694
883
  private _callback?: () => void
884
+ private _channel = makeChannel(1, new Time(), 'both')
885
+ public C: ChannelRef<Time> = makeChannelRef(this._channel, 'receive')
695
886
 
696
887
  constructor(duration: Duration, callback?: () => void) {
697
888
  this._duration = duration
698
889
  this._callback = callback
699
- const ms = duration / 1000000 // Convert nanoseconds to milliseconds
700
-
701
- if (callback) {
702
- this._timeout = setTimeout(callback, ms)
703
- } else {
704
- this._timeout = setTimeout(() => {}, ms)
705
- }
890
+ this._timeout = this.start(duration)
706
891
  }
707
892
 
708
893
  // Stop prevents the Timer from firing
@@ -718,13 +903,19 @@ export class Timer {
718
903
  // Reset changes the timer to expire after duration d
719
904
  public Reset(d: Duration): boolean {
720
905
  this.Stop()
721
- const ms = d / 1000000
906
+ this._duration = d
907
+ this._timeout = this.start(d)
908
+ return true
909
+ }
910
+
911
+ private start(d: Duration): NodeJS.Timeout | number {
912
+ const ms = timeoutMilliseconds(d)
722
913
  if (this._callback) {
723
- this._timeout = setTimeout(this._callback, ms)
724
- } else {
725
- this._timeout = setTimeout(() => {}, ms)
914
+ return setTimeout(this._callback, ms)
726
915
  }
727
- return true
916
+ return setTimeout(() => {
917
+ this._channel.send(Now()).catch(() => {})
918
+ }, ms)
728
919
  }
729
920
  }
730
921
 
@@ -733,11 +924,12 @@ export class Ticker {
733
924
  private _interval: NodeJS.Timeout | number
734
925
  private _duration: Duration
735
926
  private _stopped: boolean = false
927
+ private _channel = makeChannel(1, new Time(), 'both')
928
+ public C: ChannelRef<Time> = makeChannelRef(this._channel, 'receive')
736
929
 
737
930
  constructor(duration: Duration) {
738
931
  this._duration = duration
739
- const ms = duration / 1000000 // Convert nanoseconds to milliseconds
740
- this._interval = setInterval(() => {}, ms)
932
+ this._interval = this.start(duration)
741
933
  }
742
934
 
743
935
  // Stop turns off a ticker
@@ -755,20 +947,22 @@ export class Ticker {
755
947
  this.Stop()
756
948
  this._stopped = false
757
949
  this._duration = d
758
- const ms = d / 1000000
759
- this._interval = setInterval(() => {}, ms)
950
+ this._interval = this.start(d)
760
951
  }
761
952
 
762
953
  // Channel returns an async iterator that yields time values
763
954
  public async *Channel(): AsyncIterableIterator<Time> {
764
- const ms = this._duration / 1000000
765
955
  while (!this._stopped) {
766
- await new Promise((resolve) => setTimeout(resolve, ms))
767
- if (!this._stopped) {
768
- yield Now()
769
- }
956
+ yield await this.C.receive()
770
957
  }
771
958
  }
959
+
960
+ private start(d: Duration): NodeJS.Timeout | number {
961
+ const ms = timeoutMilliseconds(d)
962
+ return setInterval(() => {
963
+ this._channel.send(Now()).catch(() => {})
964
+ }, ms)
965
+ }
772
966
  }
773
967
 
774
968
  // Now returns the current local time with monotonic clock reading
@@ -861,17 +1055,29 @@ export function Until(t: Time): Duration {
861
1055
 
862
1056
  // Sleep pauses the current execution for at least the duration d
863
1057
  export async function Sleep(d: Duration): Promise<void> {
864
- const ms = d / 1000000 // Convert nanoseconds to milliseconds
1058
+ const ms = timeoutMilliseconds(d)
865
1059
  return new Promise((resolve) => setTimeout(resolve, ms))
866
1060
  }
867
1061
 
868
1062
  // Export month constants
1063
+ export const January = Month.January
1064
+ export const February = Month.February
1065
+ export const March = Month.March
1066
+ export const April = Month.April
869
1067
  export const May = Month.May
1068
+ export const June = Month.June
1069
+ export const July = Month.July
1070
+ export const August = Month.August
1071
+ export const September = Month.September
1072
+ export const October = Month.October
1073
+ export const November = Month.November
1074
+ export const December = Month.December
870
1075
 
871
1076
  // Time layout constants (matching Go's time package)
872
1077
  export const DateTime = '2006-01-02 15:04:05'
873
1078
  export const Layout = "01/02 03:04:05PM '06 -0700"
874
1079
  export const RFC3339 = '2006-01-02T15:04:05Z07:00'
1080
+ export const RFC3339Nano = '2006-01-02T15:04:05.999999999Z07:00'
875
1081
  export const Kitchen = '3:04PM'
876
1082
 
877
1083
  // Unix returns the local Time corresponding to the given Unix time,
@@ -907,12 +1113,12 @@ export function UnixNano(nsec: number): Time {
907
1113
  // ParseDuration parses a duration string
908
1114
  // A duration string is a possibly signed sequence of decimal numbers,
909
1115
  // each with optional fraction and a unit suffix
910
- export function ParseDuration(s: string): Duration {
1116
+ export function ParseDuration(s: string): [Duration, $.GoError] {
911
1117
  const regex = /^([+-]?)(\d+(?:\.\d+)?)(ns|us|µs|ms|s|m|h)$/
912
1118
  const match = s.match(regex)
913
1119
 
914
1120
  if (!match) {
915
- throw new Error(`time: invalid duration "${s}"`)
1121
+ return [0, $.newError(`time: invalid duration "${s}"`)]
916
1122
  }
917
1123
 
918
1124
  const [, sign, valueStr, unit] = match
@@ -941,14 +1147,14 @@ export function ParseDuration(s: string): Duration {
941
1147
  nanoseconds = value * 3600000000000
942
1148
  break
943
1149
  default:
944
- throw new Error(`time: unknown unit "${unit}" in duration "${s}"`)
1150
+ return [0, $.newError(`time: unknown unit "${unit}" in duration "${s}"`)]
945
1151
  }
946
1152
 
947
- return nanoseconds
1153
+ return [nanoseconds, null]
948
1154
  }
949
1155
 
950
1156
  // Parse parses a formatted string and returns the time value it represents
951
- export function Parse(layout: string, value: string): Time {
1157
+ export function Parse(layout: string, value: string): [Time, $.GoError] {
952
1158
  return ParseInLocation(layout, value, UTC)
953
1159
  }
954
1160
 
@@ -957,7 +1163,7 @@ export function ParseInLocation(
957
1163
  layout: string,
958
1164
  value: string,
959
1165
  loc: Location,
960
- ): Time {
1166
+ ): [Time, $.GoError] {
961
1167
  // This is a simplified implementation
962
1168
  // A full implementation would need to parse according to the layout format
963
1169
 
@@ -965,48 +1171,63 @@ export function ParseInLocation(
965
1171
  if (layout === RFC3339 || layout === '2006-01-02T15:04:05Z07:00') {
966
1172
  const date = new globalThis.Date(value)
967
1173
  if (isNaN(date.getTime())) {
968
- throw new ParseError(
969
- layout,
970
- value,
971
- '',
972
- '',
973
- `parsing time "${value}" as "${layout}": cannot parse`,
974
- )
1174
+ return [
1175
+ new Time(),
1176
+ $.toGoError(
1177
+ new ParseError(
1178
+ layout,
1179
+ value,
1180
+ '',
1181
+ '',
1182
+ `parsing time "${value}" as "${layout}": cannot parse`,
1183
+ ),
1184
+ ),
1185
+ ]
975
1186
  }
976
- return Time.create(date, 0, undefined, loc)
1187
+ return [Time.create(date, 0, undefined, loc), null]
977
1188
  }
978
1189
 
979
1190
  if (layout === DateTime || layout === '2006-01-02 15:04:05') {
980
1191
  const date = new globalThis.Date(value)
981
1192
  if (isNaN(date.getTime())) {
982
- throw new ParseError(
983
- layout,
984
- value,
985
- '',
986
- '',
987
- `parsing time "${value}" as "${layout}": cannot parse`,
988
- )
1193
+ return [
1194
+ new Time(),
1195
+ $.toGoError(
1196
+ new ParseError(
1197
+ layout,
1198
+ value,
1199
+ '',
1200
+ '',
1201
+ `parsing time "${value}" as "${layout}": cannot parse`,
1202
+ ),
1203
+ ),
1204
+ ]
989
1205
  }
990
- return Time.create(date, 0, undefined, loc)
1206
+ return [Time.create(date, 0, undefined, loc), null]
991
1207
  }
992
1208
 
993
1209
  // Fallback to standard Date parsing
994
1210
  const date = new globalThis.Date(value)
995
1211
  if (isNaN(date.getTime())) {
996
- throw new ParseError(
997
- layout,
998
- value,
999
- '',
1000
- '',
1001
- `parsing time "${value}" as "${layout}": cannot parse`,
1002
- )
1212
+ return [
1213
+ new Time(),
1214
+ $.toGoError(
1215
+ new ParseError(
1216
+ layout,
1217
+ value,
1218
+ '',
1219
+ '',
1220
+ `parsing time "${value}" as "${layout}": cannot parse`,
1221
+ ),
1222
+ ),
1223
+ ]
1003
1224
  }
1004
- return Time.create(date, 0, undefined, loc)
1225
+ return [Time.create(date, 0, undefined, loc), null]
1005
1226
  }
1006
1227
 
1007
1228
  // After waits for the duration to elapse and then sends the current time on the returned channel
1008
1229
  export function After(d: Duration): ChannelRef<Time> {
1009
- const ms = d / 1000000 // Convert nanoseconds to milliseconds
1230
+ const ms = timeoutMilliseconds(d)
1010
1231
 
1011
1232
  // Create a buffered channel with capacity 1
1012
1233
  const channel = makeChannel(1, new Time(), 'both')
@@ -1035,8 +1256,8 @@ export function NewTicker(d: Duration): Ticker {
1035
1256
  }
1036
1257
 
1037
1258
  // Tick is a convenience wrapper for NewTicker providing access to the ticking channel only
1038
- export function Tick(d: Duration): AsyncIterableIterator<Time> {
1039
- return new Ticker(d).Channel()
1259
+ export function Tick(d: Duration): ChannelRef<Time> {
1260
+ return new Ticker(d).C
1040
1261
  }
1041
1262
 
1042
1263
  // LoadLocation returns the Location with the given name
@@ -0,0 +1,25 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import * as $ from '@goscript/builtin/index.js'
4
+
5
+ import { CategoryAliases, Cn, Is, Range16, Range32, RangeTable } from './unicode.js'
6
+
7
+ describe('unicode overrides', () => {
8
+ it('accepts generated struct-literal constructor shapes', () => {
9
+ const table = new RangeTable({
10
+ R16: $.arrayToSlice<Range16>([new Range16({ Lo: 0x41, Hi: 0x5a, Stride: 1 })]),
11
+ R32: $.arrayToSlice<Range32>([new Range32({ Lo: 0x10000, Hi: 0x10002, Stride: 1 })]),
12
+ LatinOffset: 1,
13
+ })
14
+
15
+ expect(table.LatinOffset).toBe(1)
16
+ expect(Is(table, 0x41)).toBe(true)
17
+ expect(Is(table, 0x10001)).toBe(true)
18
+ expect(Is(table, 0x61)).toBe(false)
19
+ })
20
+
21
+ it('exports category aliases used by regexp/syntax', () => {
22
+ expect(CategoryAliases.get('digit')).toBe('Nd')
23
+ expect(Cn).toBeInstanceOf(RangeTable)
24
+ })
25
+ })