@amritk/nish-x86_64-linux 0.20.0 → 0.22.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 (74) hide show
  1. package/INSTALL.md +52 -10
  2. package/bin/nish +0 -0
  3. package/docs/AI.md +2777 -0
  4. package/package.json +2 -1
  5. package/runtime/browser.d.ts +6 -0
  6. package/runtime/browser.mjs +77 -0
  7. package/runtime/core/arrays.d.ts +36 -0
  8. package/runtime/core/arrays.mjs +153 -0
  9. package/runtime/core/checks.mjs +20 -0
  10. package/runtime/core/host.d.ts +80 -0
  11. package/runtime/core/host.mjs +325 -0
  12. package/runtime/core/numbers.d.ts +66 -0
  13. package/runtime/core/numbers.mjs +343 -0
  14. package/runtime/core/result.d.ts +45 -0
  15. package/runtime/core/result.mjs +140 -0
  16. package/runtime/core/strings.d.ts +14 -0
  17. package/runtime/core/strings.mjs +169 -0
  18. package/runtime/core.d.ts +9 -0
  19. package/runtime/core.mjs +55 -0
  20. package/runtime/host.d.ts +6 -0
  21. package/runtime/nish.d.ts +46 -2
  22. package/runtime/nish.h +75 -2
  23. package/runtime/nish.mjs +23 -3
  24. package/runtime/node.mjs +386 -0
  25. package/runtime/runtime-bytes.c +401 -0
  26. package/runtime/runtime-cross.c +1 -1
  27. package/runtime/runtime-host.c +1 -1
  28. package/runtime/runtime-net.c +12 -1
  29. package/runtime/runtime-os.c +1 -1
  30. package/runtime/runtime-parallel.c +1 -1
  31. package/runtime/runtime-simd.c +231 -7
  32. package/runtime/runtime-term.c +504 -0
  33. package/runtime/runtime-wasm.c +0 -11
  34. package/runtime/runtime.c +190 -6
  35. package/runtime/shim.mjs +6 -985
  36. package/runtime/sqlite/LICENSE.md +85 -0
  37. package/runtime/sqlite/README.md +45 -0
  38. package/runtime/sqlite/nish-sqlite.c +359 -0
  39. package/runtime/sqlite/sqlite3.c +271131 -0
  40. package/runtime/sqlite/sqlite3.h +14447 -0
  41. package/scripts/build.sh +311 -59
  42. package/std/LICENSE-fast-float +23 -0
  43. package/std/LICENSE-fdlibm +8 -0
  44. package/std/README.md +32 -12
  45. package/std/base64.ts +116 -0
  46. package/std/bytes.ts +256 -0
  47. package/std/cli.ts +344 -0
  48. package/std/collections.ts +6 -5
  49. package/std/crypto/LICENSE-crypt_blowfish +26 -0
  50. package/std/crypto/base64url.ts +125 -0
  51. package/std/crypto/bcrypt.ts +1557 -0
  52. package/std/crypto/hmac.ts +138 -2
  53. package/std/crypto/x509.ts +11 -122
  54. package/std/json-tokenizer.ts +2998 -57
  55. package/std/json-value.ts +22 -3
  56. package/std/json.ts +87 -8
  57. package/std/math.ts +608 -0
  58. package/std/net/http1-server.ts +282 -40
  59. package/std/net/http1.ts +40 -21
  60. package/std/net/http3-server.ts +50 -12
  61. package/std/net/postgres.ts +2294 -0
  62. package/std/net/prefork.ts +23 -3
  63. package/std/net/quic-listener.ts +20 -4
  64. package/std/random.ts +66 -4
  65. package/std/regex.ts +4274 -0
  66. package/std/sqlite.ts +391 -0
  67. package/std/term-io.ts +978 -0
  68. package/std/term-pixels.ts +874 -0
  69. package/std/term-probe.ts +459 -0
  70. package/std/term-rate.ts +993 -0
  71. package/std/term.ts +2453 -0
  72. package/std/text.ts +90 -7
  73. package/std/yaml-lines.ts +141 -0
  74. package/std/yaml.ts +4675 -0
@@ -84,6 +84,11 @@ export const PREFORK_STOPPED: i32 = -1
84
84
  * supervisor could not listen for SIGTERM and so starts none.
85
85
  */
86
86
  export const PREFORK_SPAWN_FAILED: i32 = -2
87
+ /**
88
+ * What `preforkWith` answers in the supervisor when `restart` is off and every
89
+ * worker has exited.
90
+ */
91
+ export const PREFORK_WORKERS_EXITED: i32 = -3
87
92
 
88
93
  /** The supervisor's numbers; every one is checked by `preforkWith`. */
89
94
  export class PreforkConfig {
@@ -99,6 +104,11 @@ export class PreforkConfig {
99
104
  quickExitMs: i32 = 1000
100
105
  /** How long the workers get to exit after SIGTERM before SIGKILL. */
101
106
  graceMs: i32 = 5000
107
+ /**
108
+ * Start a worker that exited again. Off, a worker that exits stays gone,
109
+ * and the supervisor returns once none is left.
110
+ */
111
+ restart: boolean = true
102
112
  }
103
113
 
104
114
  /** True when `s` is one or more ASCII digits and nothing else. */
@@ -177,6 +187,8 @@ class PreforkSlot {
177
187
  pid: i32 = 0
178
188
  /** The wait before the last restart, 0 after a worker that ran long. */
179
189
  delay: i32 = 0
190
+ /** The worker exited with `restart` off, and is never started again. */
191
+ gone: boolean = false
180
192
  }
181
193
 
182
194
  /** The supervisor's state while it runs. */
@@ -269,7 +281,9 @@ class PreforkSupervisor {
269
281
  const slot: PreforkSlot = this.slots[index]
270
282
  this.running = this.running - 1
271
283
  slot.pid = 0
272
- if (!stopping) {
284
+ if (!this.config.restart) {
285
+ slot.gone = true
286
+ } else if (!stopping) {
273
287
  this.backoff(slot, preforkNowMs(), false)
274
288
  }
275
289
  }
@@ -285,7 +299,7 @@ class PreforkSupervisor {
285
299
  const now: i64 = preforkNowMs()
286
300
  for (let i: i32 = 0; i < toI32(this.slots.length); i++) {
287
301
  const slot: PreforkSlot = this.slots[i]
288
- if (slot.pid === 0 && slot.at <= now && !this.start(i)) {
302
+ if (slot.pid === 0 && !slot.gone && slot.at <= now && !this.start(i)) {
289
303
  if (first) {
290
304
  return false
291
305
  }
@@ -355,7 +369,9 @@ const preforkInvalid = (config: PreforkConfig): string => {
355
369
 
356
370
  /**
357
371
  * In a worker, its index. In the supervisor, run the workers until SIGTERM or
358
- * SIGINT and answer `PREFORK_STOPPED`, or `PREFORK_SPAWN_FAILED` when a worker's
372
+ * SIGINT and answer `PREFORK_STOPPED`; with `restart` off, also until every
373
+ * worker has exited, answering `PREFORK_WORKERS_EXITED`; or
374
+ * `PREFORK_SPAWN_FAILED` when a worker's
359
375
  * first start failed (those already started are stopped first) or no signal
360
376
  * listener could be made (no worker is started). Panics on a config
361
377
  * `preforkInvalid` names a field of.
@@ -399,6 +415,10 @@ export const preforkWith = (args: string[], config: PreforkConfig): i32 => {
399
415
  running = false
400
416
  } else {
401
417
  supervisor.reap(false)
418
+ if (!config.restart && supervisor.running === 0) {
419
+ result = PREFORK_WORKERS_EXITED
420
+ running = false
421
+ }
402
422
  supervisor.restart(false)
403
423
  }
404
424
  }
@@ -68,7 +68,7 @@
68
68
  * of in one burst that overruns a queue on the path.
69
69
  *
70
70
  * let out: u8[] | null = quicListenerTakePaced(conn, now);
71
- * while (out !== null) { … send it … ; out = quicListenerTakePaced(conn, now); }
71
+ * while (out !== null) { … send it with conn.datagramEcn … ; out = quicListenerTakePaced(conn, now); }
72
72
  * … and wake at the earlier of conn.deadline() and quicListenerPaceTime(conn, now)
73
73
  *
74
74
  * A carrier that sends whole flights with `quicListenerTakeFlight`, below,
@@ -90,9 +90,16 @@
90
90
  * side, `quicListenerReceiveSegments` hands a connection the datagrams of
91
91
  * one GRO receive, segment by segment, in place.
92
92
  *
93
+ * **ECN** (RFC 9000 §13.4). A carrier whose platform sends the ECN bits it
94
+ * is given sets the connection's `ecnMarking` and sends each datagram with
95
+ * the codepoint the connection marked it with: `conn.datagramEcn` after a
96
+ * `takeDatagramInto` or `quicListenerTakePaced`, `flight.ecn` for a flight.
97
+ * One send carries one codepoint, so a flight ends before a datagram the
98
+ * connection would mark otherwise. The listener's own answers go unmarked.
99
+ *
93
100
  * const flight = new QuicFlight();
94
101
  * const n: i32 = quicListenerTakeFlight(conn, now, buf, 0, toI32(buf.length), flight);
95
- * if (n > 0) { udpSendTo(fd, buf, 0, n, peer, flight.count > 1 ? flight.segment : 0, 0); }
102
+ * if (n > 0) { udpSendTo(fd, buf, 0, n, peer, flight.count > 1 ? flight.segment : 0, flight.ecn); }
96
103
  *
97
104
  * **Sans-IO and deterministic.** The caller gives the time, the client's
98
105
  * address and, once, `QUIC_LISTENER_ENTROPY_SIZE` random bytes: every
@@ -928,6 +935,8 @@ export class QuicFlight {
928
935
  count: i32 = 0
929
936
  /** Every datagram's size but the last's, which may be shorter: the `UDP_SEGMENT` to send with. */
930
937
  segment: i32 = 0
938
+ /** The ECN codepoint every datagram of the flight was marked with: the one to send with. */
939
+ ecn: i32 = 0
931
940
  }
932
941
 
933
942
  /**
@@ -941,8 +950,8 @@ export class QuicFlight {
941
950
  * `quicListenerTakePaced` does, so the flight is the pacer's whole credit
942
951
  * and no more. It stops at the first datagram shorter than
943
952
  * `QUIC_CONN_DATAGRAM_SIZE`, which can only be the last of a segmented send,
944
- * at `QUIC_LISTENER_FLIGHT_MAX` datagrams, and when `cap` has no room for
945
- * another.
953
+ * at `QUIC_LISTENER_FLIGHT_MAX` datagrams, when `cap` has no room for
954
+ * another, and before a datagram whose ECN codepoint would not be the first's.
946
955
  */
947
956
  export const quicListenerTakeFlight = (
948
957
  conn: QuicConnection,
@@ -954,6 +963,7 @@ export const quicListenerTakeFlight = (
954
963
  ): i32 => {
955
964
  flight.count = 0
956
965
  flight.segment = 0
966
+ flight.ecn = 0
957
967
  let length: i32 = 0
958
968
  if (conn.recovery.pacerDelay(now, quicListenerQuantum(conn)) > 0) {
959
969
  return length
@@ -963,6 +973,11 @@ export const quicListenerTakeFlight = (
963
973
  length + QUIC_CONN_DATAGRAM_SIZE <= cap &&
964
974
  conn.recovery.pacerDelay(now, QUIC_CONN_DATAGRAM_SIZE) <= 0
965
975
  ) {
976
+ // The codepoint `takeDatagramInto` would mark the next datagram with: one send carries one.
977
+ const next: i32 = conn.ecnMarking ? conn.recovery.ecnCodepoint() : 0
978
+ if (flight.count > 0 && next !== flight.ecn) {
979
+ return length
980
+ }
966
981
  const n: i32 = conn.takeDatagramInto(buf, at + length, now)
967
982
  if (n <= 0) {
968
983
  return length
@@ -970,6 +985,7 @@ export const quicListenerTakeFlight = (
970
985
  conn.recovery.onPaced(now, n)
971
986
  if (flight.count === 0) {
972
987
  flight.segment = n
988
+ flight.ecn = conn.datagramEcn
973
989
  }
974
990
  flight.count = flight.count + 1
975
991
  length = length + n
package/std/random.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * import { Rng } from "nish/random";
6
6
  *
7
7
  * const r = new Rng(42);
8
- * const die: i32 = 1 + (r.nextI32() >>> 1) % 6;
8
+ * const die: i32 = r.nextInt(1, 6); // 1 to 6, each with equal chance
9
9
  * const u: f64 = r.nextF64(); // in [0, 1)
10
10
  *
11
11
  * The state is one 32-bit integer. Each step adds the odd constant
@@ -24,8 +24,11 @@
24
24
  * two's-complement wrap natively and answer `(a + b) | 0` and `Math.imul(a, b)`
25
25
  * under Node (docs/LANGUAGE.md, "nish:unsafe"); every shift has a constant
26
26
  * count, and `^` and `>>> 16` answer the same 32 bits in JavaScript as in the
27
- * compiled program. `nextF64` builds its double from integers below 2^53, so
28
- * its products and sums are exact both ways. The program a test prints under
27
+ * compiled program. `nextInt` reads its span and its draws as unsigned
28
+ * counts with no `u32` (whose conversions saturate under Node): the sign bit
29
+ * flipped orders them under a signed compare, and the remainder is taken in
30
+ * pieces that stay below 2^31. `nextF64` builds its double from integers
31
+ * below 2^53, so its products and sums are exact both ways. The program a test prints under
29
32
  * Node is the one it prints compiled (docs/RUN_UNDER_NODE.md).
30
33
  *
31
34
  * It is not for cryptography: a key or a nonce comes from
@@ -37,7 +40,7 @@
37
40
  * would be a write their caller can see, and is refused as any such write is;
38
41
  * give each task its own, seeded from its index.
39
42
  */
40
- import { wrappingAdd, wrappingMul } from "nish:unsafe"
43
+ import { wrappingAdd, wrappingMul, wrappingSub } from "nish:unsafe"
41
44
 
42
45
  /** 0x9E3779B9 as an `i32`: the Weyl increment, odd, so the walk visits every state. */
43
46
  const GOLDEN: i32 = -1640531527
@@ -54,6 +57,35 @@ const TWO_26: f64 = 67108864.0
54
57
  /** 2^53, which scales a 53-bit integer into [0, 1). */
55
58
  const TWO_53: f64 = 9007199254740992.0
56
59
 
60
+ /** The sign bit: `x ^ SIGN` orders the bits of `x` as an unsigned count under a signed compare. */
61
+ const SIGN: i32 = -2147483648
62
+
63
+ /** 2^31 - 1, the `i32` just below 2^31, from which `remainder` finds 2^31 mod m. */
64
+ const MAX: i32 = 2147483647
65
+
66
+ /** Whether `a < b` when both are read as unsigned 32-bit counts. */
67
+ const below = (a: i32, b: i32): boolean => (a ^ SIGN) < (b ^ SIGN)
68
+
69
+ /**
70
+ * `a mod m` with both read as unsigned 32-bit counts and `m` not 0. A count
71
+ * of 2^31 or more is a negative `i32`, so it is taken apart into pieces a
72
+ * signed `%` answers the same in JavaScript, and every sum stays below 2^31.
73
+ */
74
+ const remainder = (a: i32, m: i32): i32 => {
75
+ if (m < 0) {
76
+ // m is 2^31 or more, so a is less than 2m: at most one m comes off.
77
+ return below(a, m) ? a : wrappingSub(a, m)
78
+ }
79
+ if (a >= 0) {
80
+ return a % m
81
+ }
82
+ // a is 2^31 + low, so a mod m is low plus 2^31 mod m, added mod m.
83
+ const low: i32 = (a ^ SIGN) % m
84
+ const high: i32 = wrappingAdd(MAX % m, 1) % m
85
+ const room: i32 = wrappingSub(m, high)
86
+ return low >= room ? wrappingSub(low, room) : wrappingAdd(low, high)
87
+ }
88
+
57
89
  /** MurmurHash3's `fmix32`: every bit of `h` into every bit of the answer, a bijection on 32 bits. */
58
90
  const mix = (h: i32): i32 => {
59
91
  let x: i32 = h
@@ -91,4 +123,34 @@ export class Rng {
91
123
  const lo: i32 = this.nextI32() >>> 6
92
124
  return (toF64(hi) * TWO_26 + toF64(lo)) / TWO_53
93
125
  }
126
+
127
+ /**
128
+ * An integer in [lo, hi], both ends included, each with equal chance;
129
+ * `nextInt(1, 6)` is a die. It panics when `lo` is greater than `hi`, and
130
+ * the whole `i32` range, `nextInt(-2147483648, 2147483647)`, is one
131
+ * `nextI32()`.
132
+ *
133
+ * There is no modulo bias: where the span `hi - lo + 1`, an unsigned count
134
+ * up to 2^32, does not divide 2^32 evenly, a draw among the lowest
135
+ * 2^32 mod span is refused and drawn again, and what is left holds every
136
+ * answer equally often. Fewer than half the draws are ever refused, so an
137
+ * answer takes one `nextI32()` step usually and fewer than two on average,
138
+ * and a sequence is still the seed's.
139
+ */
140
+ nextInt(lo: i32, hi: i32): i32 {
141
+ if (lo > hi) {
142
+ panic("Rng.nextInt: lo is greater than hi")
143
+ }
144
+ const span: i32 = wrappingAdd(wrappingSub(hi, lo), 1)
145
+ if (span === 0) {
146
+ return this.nextI32()
147
+ }
148
+ // 2^32 mod span, as (2^32 - span) mod span.
149
+ const refused: i32 = remainder(wrappingSub(0, span), span)
150
+ let draw: i32 = this.nextI32()
151
+ while (below(draw, refused)) {
152
+ draw = this.nextI32()
153
+ }
154
+ return wrappingAdd(lo, remainder(draw, span))
155
+ }
94
156
  }