@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.
- package/INSTALL.md +52 -10
- package/bin/nish +0 -0
- package/docs/AI.md +2777 -0
- package/package.json +2 -1
- package/runtime/browser.d.ts +6 -0
- package/runtime/browser.mjs +77 -0
- package/runtime/core/arrays.d.ts +36 -0
- package/runtime/core/arrays.mjs +153 -0
- package/runtime/core/checks.mjs +20 -0
- package/runtime/core/host.d.ts +80 -0
- package/runtime/core/host.mjs +325 -0
- package/runtime/core/numbers.d.ts +66 -0
- package/runtime/core/numbers.mjs +343 -0
- package/runtime/core/result.d.ts +45 -0
- package/runtime/core/result.mjs +140 -0
- package/runtime/core/strings.d.ts +14 -0
- package/runtime/core/strings.mjs +169 -0
- package/runtime/core.d.ts +9 -0
- package/runtime/core.mjs +55 -0
- package/runtime/host.d.ts +6 -0
- package/runtime/nish.d.ts +46 -2
- package/runtime/nish.h +75 -2
- package/runtime/nish.mjs +23 -3
- package/runtime/node.mjs +386 -0
- package/runtime/runtime-bytes.c +401 -0
- package/runtime/runtime-cross.c +1 -1
- package/runtime/runtime-host.c +1 -1
- package/runtime/runtime-net.c +12 -1
- package/runtime/runtime-os.c +1 -1
- package/runtime/runtime-parallel.c +1 -1
- package/runtime/runtime-simd.c +231 -7
- package/runtime/runtime-term.c +504 -0
- package/runtime/runtime-wasm.c +0 -11
- package/runtime/runtime.c +190 -6
- package/runtime/shim.mjs +6 -985
- package/runtime/sqlite/LICENSE.md +85 -0
- package/runtime/sqlite/README.md +45 -0
- package/runtime/sqlite/nish-sqlite.c +359 -0
- package/runtime/sqlite/sqlite3.c +271131 -0
- package/runtime/sqlite/sqlite3.h +14447 -0
- package/scripts/build.sh +311 -59
- package/std/LICENSE-fast-float +23 -0
- package/std/LICENSE-fdlibm +8 -0
- package/std/README.md +32 -12
- package/std/base64.ts +116 -0
- package/std/bytes.ts +256 -0
- package/std/cli.ts +344 -0
- package/std/collections.ts +6 -5
- package/std/crypto/LICENSE-crypt_blowfish +26 -0
- package/std/crypto/base64url.ts +125 -0
- package/std/crypto/bcrypt.ts +1557 -0
- package/std/crypto/hmac.ts +138 -2
- package/std/crypto/x509.ts +11 -122
- package/std/json-tokenizer.ts +2998 -57
- package/std/json-value.ts +22 -3
- package/std/json.ts +87 -8
- package/std/math.ts +608 -0
- package/std/net/http1-server.ts +282 -40
- package/std/net/http1.ts +40 -21
- package/std/net/http3-server.ts +50 -12
- package/std/net/postgres.ts +2294 -0
- package/std/net/prefork.ts +23 -3
- package/std/net/quic-listener.ts +20 -4
- package/std/random.ts +66 -4
- package/std/regex.ts +4274 -0
- package/std/sqlite.ts +391 -0
- package/std/term-io.ts +978 -0
- package/std/term-pixels.ts +874 -0
- package/std/term-probe.ts +459 -0
- package/std/term-rate.ts +993 -0
- package/std/term.ts +2453 -0
- package/std/text.ts +90 -7
- package/std/yaml-lines.ts +141 -0
- package/std/yaml.ts +4675 -0
package/std/net/prefork.ts
CHANGED
|
@@ -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 (!
|
|
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
|
|
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
|
}
|
package/std/net/quic-listener.ts
CHANGED
|
@@ -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,
|
|
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,
|
|
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 =
|
|
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. `
|
|
28
|
-
*
|
|
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
|
}
|