@amritk/nish-x86_64-linux 0.27.2 → 0.29.0
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 +16 -8
- package/bin/nish +0 -0
- package/docs/AI.md +118 -26
- package/package.json +1 -1
- package/runtime/core/host.d.ts +2 -1
- package/runtime/core/host.mjs +4 -0
- package/runtime/core.d.ts +47 -0
- package/runtime/core.mjs +67 -0
- package/runtime/nish.d.ts +176 -0
- package/runtime/nish.h +120 -6
- package/runtime/nish.mjs +24 -4
- package/runtime/runtime-checksum.c +270 -0
- package/runtime/runtime-net.c +386 -5
- package/runtime/runtime-os.c +59 -8
- package/runtime/runtime-parallel.c +81 -5
- package/runtime/runtime-sandbox.c +479 -0
- package/runtime/runtime-sha256.c +239 -0
- package/runtime/runtime-shm.c +541 -0
- package/runtime/runtime.c +827 -791
- package/scripts/build.sh +79 -28
- package/std/README.md +25 -13
- package/std/collections.ts +5 -5
- package/std/compress/checksum.ts +88 -75
- package/std/compress/deflate.ts +224 -0
- package/std/compress/gzip.ts +52 -0
- package/std/crypto/bcrypt.ts +816 -280
- package/std/crypto/hmac.ts +305 -2
- package/std/crypto/jwt.ts +1661 -0
- package/std/json-equal.ts +335 -0
- package/std/json-format.ts +1070 -0
- package/std/json-number.ts +428 -0
- package/std/json-pointer.ts +245 -0
- package/std/json-typed.ts +34 -0
- package/std/json-value.ts +510 -17
- package/std/json.ts +35 -6
- package/std/net/handler.ts +1348 -0
- package/std/net/http-client.ts +97 -16
- package/std/net/http-compress.ts +301 -16
- package/std/net/http1-client.ts +104 -19
- package/std/net/http1-server.ts +127 -24
- package/std/net/http1.ts +24 -4
- package/std/net/outbound.ts +409 -0
- package/std/net/postgres.ts +405 -0
- package/std/net/prefork.ts +344 -20
- package/std/net/websocket.ts +295 -14
- package/std/regex.ts +613 -52
- package/std/secret.ts +1 -1
- package/std/sync/ring.ts +587 -0
- package/std/sync/shm.ts +284 -0
- package/std/term-io.ts +35 -8
- package/std/term-rate.ts +13 -1
- package/std/threads.ts +35 -3
- package/std/yaml-json.ts +841 -0
- /package/runtime/{LICENSE-ryu → LICENSE-zmij} +0 -0
package/INSTALL.md
CHANGED
|
@@ -254,7 +254,9 @@ routes are
|
|
|
254
254
|
# on the musl host, with its own clang and the runtime from this repository
|
|
255
255
|
clang app.ll runtime/runtime.c runtime/runtime-os.c runtime/runtime-parallel.c \
|
|
256
256
|
runtime/runtime-cross.c runtime/runtime-host.c runtime/runtime-net.c \
|
|
257
|
-
runtime/runtime-simd.c runtime/runtime-aes.c runtime/runtime-
|
|
257
|
+
runtime/runtime-simd.c runtime/runtime-aes.c runtime/runtime-sha256.c runtime/runtime-term.c \
|
|
258
|
+
runtime/runtime-bytes.c runtime/runtime-checksum.c runtime/runtime-sandbox.c \
|
|
259
|
+
runtime/runtime-shm.c -lm -o app
|
|
258
260
|
```
|
|
259
261
|
|
|
260
262
|
`--link`ing inside the container is the mistake to avoid: it shells out to the
|
|
@@ -390,7 +392,7 @@ it into `build/seed/`; `NISH_BOOTSTRAP=<path>` names one you already have and
|
|
|
390
392
|
skips the download. §2a has what the build does with it.
|
|
391
393
|
|
|
392
394
|
The published package ships `bin/` (the `nish` command, which is a launcher),
|
|
393
|
-
`runtime/` (the C runtime —
|
|
395
|
+
`runtime/` (the C runtime — fourteen translation units, the wasm subset and their
|
|
394
396
|
header — and `runtime/sqlite/`, SQLite's vendored source),
|
|
395
397
|
`scripts/build.sh` (the link pipeline), `std/` (the standard library) and
|
|
396
398
|
`docs/AI.md` (the rules card). The
|
|
@@ -403,12 +405,14 @@ working directory — and the binary runs from inside its own platform package
|
|
|
403
405
|
for exactly that reason.
|
|
404
406
|
|
|
405
407
|
Building the IR yourself rather than through `--link` means naming the runtime
|
|
406
|
-
on the `clang` line, and it is
|
|
408
|
+
on the `clang` line, and it is fourteen files:
|
|
407
409
|
|
|
408
410
|
```bash
|
|
409
411
|
clang app.ll runtime/runtime.c runtime/runtime-os.c runtime/runtime-parallel.c \
|
|
410
412
|
runtime/runtime-cross.c runtime/runtime-host.c runtime/runtime-net.c \
|
|
411
|
-
runtime/runtime-simd.c runtime/runtime-aes.c runtime/runtime-
|
|
413
|
+
runtime/runtime-simd.c runtime/runtime-aes.c runtime/runtime-sha256.c runtime/runtime-term.c \
|
|
414
|
+
runtime/runtime-bytes.c runtime/runtime-checksum.c runtime/runtime-sandbox.c \
|
|
415
|
+
runtime/runtime-shm.c -lm -o app
|
|
412
416
|
```
|
|
413
417
|
|
|
414
418
|
`runtime.c` is the part every program touches — the arena, strings, arrays,
|
|
@@ -421,14 +425,18 @@ the strings and arrays a task answers, a channel sends or a `Mutex` keeps out
|
|
|
421
425
|
of the arena they were made in, `runtime-host.c` holds the wall clock,
|
|
422
426
|
entropy, file times and signals, `runtime-net.c` the sockets of `nish:net`,
|
|
423
427
|
`runtime-simd.c` and `runtime-aes.c` the vector text search and AES-GCM,
|
|
424
|
-
`runtime-
|
|
428
|
+
`runtime-sha256.c` the SHA-256 block kernel `nish/crypto/sha256` hands its
|
|
429
|
+
blocks to on a CPU with the SHA instructions (`NISH_SHA256=soft` keeps the
|
|
430
|
+
portable path), `runtime-term.c` the stdin reads and terminal calls of `nish:term`,
|
|
425
431
|
`runtime-bytes.c` the byte-class runs of `nish/bytes`, which `nish/json` steps
|
|
426
|
-
over.
|
|
432
|
+
over, `runtime-checksum.c` the CRC-32 kernels of `nish/compress/checksum`,
|
|
433
|
+
`runtime-sandbox.c` the confinement a `--sandbox` build applies, and
|
|
434
|
+
`runtime-shm.c` the shared-memory regions of `nish/sync/shm`.
|
|
427
435
|
They are separate so that each carries its own measured size ceiling
|
|
428
436
|
([docs/wp7-runtime.md](wp7-runtime.md)); nothing in the core calls into the
|
|
429
437
|
others, so a line that names only `runtime.c` and `runtime-os.c` still links a
|
|
430
|
-
program that uses none of the other
|
|
431
|
-
|
|
438
|
+
program that uses none of the other nine. `scripts/build.sh` compiles the other
|
|
439
|
+
nine beside any
|
|
432
440
|
`runtime.c` it is handed, so a build that goes through it — every `--link`,
|
|
433
441
|
and every `--profile` recipe in these documents — needs to name only the one.
|
|
434
442
|
|
package/bin/nish
CHANGED
|
Binary file
|
package/docs/AI.md
CHANGED
|
@@ -180,7 +180,7 @@ rejects. This table is the highest-value part of the page.
|
|
|
180
180
|
| `keyof T`, `<T = i32>` (a default type argument) | `` Unsupported type `keyof T` (Phase 1 supports …) `` / `a default type argument … is not supported` | name the type; a type argument is always inferred |
|
|
181
181
|
| `class B extends A` | `` `extends` is not supported: Nish has no inheritance `` | repeat the fields and `implements` an interface |
|
|
182
182
|
| `static` members, `get x()` / `set x(v)` | `` … `static` members are not supported `` / `` Getters and setters are not supported in class `C` (use a method) `` | module `const`s and plain methods |
|
|
183
|
-
| `const [a, b] = xs`, `({ x }: Point) =>`, `(n
|
|
183
|
+
| `const [a, b] = xs`, `({ x }: Point) =>`, `(n?: i32)`, `(n = 1)`, `f(...xs)` | `Destructuring is not supported` / `Destructured parameters are not supported` / `Optional parameters are not supported` / `` Parameter `n` has a default and no type annotation `` / `Spread arguments are not supported` | one name per binding; `n: i32 = 1` (a constant or an earlier parameter) for a default; `...ns: i32[]` as the last parameter, or pass the array itself |
|
|
184
184
|
| `function f(): void;` (an overload), `export default function ()` | `Functions must have a body` / `Functions must be named` | one named function, with its body |
|
|
185
185
|
| a method in an `interface` | `` Interface `I` cannot declare methods (interfaces describe layout only) `` | fields only; a top-level function over the interface |
|
|
186
186
|
| `abstract class`, `declare class`, `constructor(public x: i32)`, `interface B extends A`, `[k: string]: T` | `Abstract classes are not supported` / `` `declare class` is not supported `` / `Parameter properties … are not supported; declare the field and assign it` / ``Interface inheritance (`extends`) is not supported; list every field`` / `Index signatures are not supported …` | a plain class with its fields declared and assigned in the constructor; every field listed; a `Map` for a keyed table |
|
|
@@ -845,10 +845,14 @@ export const main = (): i32 => {
|
|
|
845
845
|
- **Call it, or pass it on to another function parameter. Nothing else**:
|
|
846
846
|
`const g = f`, `return f` and `[f]` are
|
|
847
847
|
`` `f` is a function parameter and can only be called or passed on as a function argument ``.
|
|
848
|
-
- **An arrow
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
848
|
+
- **An arrow may read the `const` locals and parameters of the function it is
|
|
849
|
+
written in**, and write through a captured reference
|
|
850
|
+
(`(x) => { if (x > limit) { hits.push(x) } }`); each capture becomes one more
|
|
851
|
+
argument of the direct call. It may not assign to one, read a `let`
|
|
852
|
+
(`` The arrow reads `k`, a `let` of the function it is written in: ... bind the value to a `const` before the call ``),
|
|
853
|
+
read `this` (bind `const self = this`), or read a function parameter of its
|
|
854
|
+
function. An arrow inside another arrow, or given to a method, a
|
|
855
|
+
constructor, `expose` or `exposeWith`, captures nothing.
|
|
852
856
|
- **The argument's type must match exactly**: `(x: i32) => i64` for a
|
|
853
857
|
`(x: i32) => i32` parameter is refused. A generic function cannot be passed
|
|
854
858
|
by name — write `(x) => identity(x)`.
|
|
@@ -858,12 +862,13 @@ export const main = (): i32 => {
|
|
|
858
862
|
- **Only a top-level function** may have one: not a method, a constructor, a
|
|
859
863
|
field, a local, a return type or an alias.
|
|
860
864
|
|
|
861
|
-
```ts nish:err
|
|
865
|
+
```ts nish:err NL2585
|
|
862
866
|
const apply = (f: (x: i32) => i32, x: i32): i32 => f(x);
|
|
863
867
|
|
|
864
868
|
export const main = (): i32 => {
|
|
865
|
-
|
|
866
|
-
|
|
869
|
+
let k = 3;
|
|
870
|
+
k = k + 1;
|
|
871
|
+
return apply((x) => x + k, 1); // reads the `let` `k`: bind `const kNow = k` before the call
|
|
867
872
|
};
|
|
868
873
|
```
|
|
869
874
|
|
|
@@ -976,6 +981,11 @@ export const main = (): i32 => {
|
|
|
976
981
|
(NL2388): `using s = scope()`.
|
|
977
982
|
The scope is only ever the receiver of a `spawn` statement: never pass it,
|
|
978
983
|
store it or return it.
|
|
984
|
+
- **A task that recurses deeply gets a bigger stack from `scopeWithStack`.**
|
|
985
|
+
`using s = scopeWithStack(64 * 1024 * 1024)` is a scope whose tasks each run
|
|
986
|
+
on a new thread with a 64 MiB stack; a thread's default is 8 MiB. Ask for at
|
|
987
|
+
least 131072 bytes: a number below it is refused (NL2584). Under Node the size
|
|
988
|
+
is ignored, so run Node with `--stack-size` too.
|
|
979
989
|
- **The task is a top-level function named in the `spawn`, or an arrow written
|
|
980
990
|
there.** `s.spawn(entry, arg)` with no destination runs an entry that
|
|
981
991
|
answers `void`; `s.spawn(() => work(a, b))` runs an arrow that reads the
|
|
@@ -1893,32 +1903,52 @@ export const main = (): i32 => {
|
|
|
1893
1903
|
`push` inside the body extends the loop. `for...in`, `for await` and
|
|
1894
1904
|
`for (x of xs)` over an existing `x` are each refused by name.
|
|
1895
1905
|
- `switch` takes an **integer or enum** discriminant; every `case` label is an
|
|
1896
|
-
integer constant expression of that type.
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
declare a variable directly; wrap its body in a block.
|
|
1901
|
-
-
|
|
1906
|
+
integer constant expression of that type. A clause that does not end in
|
|
1907
|
+
`break`, `return`, `continue` or `process.exit` **falls through** into the
|
|
1908
|
+
next, as in TypeScript; an *empty* clause is how `case 1: case 2:` shares a
|
|
1909
|
+
body. A clause reached by falling into it is not narrowed by its label. A
|
|
1910
|
+
clause cannot declare a variable directly; wrap its body in a block.
|
|
1911
|
+
- **Labels** go on a loop, a block or a `switch`: `break outer` leaves the
|
|
1912
|
+
statement named `outer` from any depth, `continue outer` starts the next
|
|
1913
|
+
turn of the loop named `outer`. A label on any other statement is refused,
|
|
1914
|
+
and a jump cannot leave an arrow for a label outside it.
|
|
1902
1915
|
- `process.exit(code)` and `panic(msg)` **terminate control flow**, so a
|
|
1903
1916
|
non-`void` function may end with either.
|
|
1904
1917
|
- **Unreachable code is an error**, not a warning: anything after a `return`,
|
|
1905
1918
|
`break`, `continue`, `process.exit`, an `if` whose branches all return, or an
|
|
1906
1919
|
infinite loop.
|
|
1907
1920
|
|
|
1908
|
-
```ts nish:
|
|
1909
|
-
const
|
|
1921
|
+
```ts nish:ok
|
|
1922
|
+
const firstPair = (limit: i32, target: i32): i32 => {
|
|
1923
|
+
outer: for (let i: i32 = 0; i < limit; i++) {
|
|
1924
|
+
for (let j: i32 = 0; j < limit; j++) {
|
|
1925
|
+
if (i * j === target) {
|
|
1926
|
+
return i * 100 + j;
|
|
1927
|
+
}
|
|
1928
|
+
if (j > i) {
|
|
1929
|
+
continue outer; // the next `i`
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
return -1;
|
|
1934
|
+
};
|
|
1935
|
+
|
|
1936
|
+
const classify = (n: i32): i32 => {
|
|
1937
|
+
let score: i32 = 0;
|
|
1910
1938
|
switch (n) {
|
|
1911
1939
|
case 0:
|
|
1912
|
-
|
|
1940
|
+
score += 10; // no `break`: falls into `case 1`
|
|
1913
1941
|
case 1:
|
|
1914
|
-
|
|
1942
|
+
score += 1;
|
|
1943
|
+
break;
|
|
1915
1944
|
default:
|
|
1916
|
-
|
|
1945
|
+
score = -1;
|
|
1917
1946
|
}
|
|
1947
|
+
return score;
|
|
1918
1948
|
};
|
|
1919
1949
|
|
|
1920
1950
|
export const main = (): i32 => {
|
|
1921
|
-
console.log(classify(0));
|
|
1951
|
+
console.log(`${firstPair(10, 12)} ${classify(0)} ${classify(1)}`); // 304 11 1
|
|
1922
1952
|
return 0;
|
|
1923
1953
|
};
|
|
1924
1954
|
```
|
|
@@ -2181,6 +2211,10 @@ also watches the signal fd. None of `spawn`, `kill`, `waitPid` may be called in
|
|
|
2181
2211
|
a task or a parallel body; the two host facts may. `availableParallelism()` (`i32`, at least 1, no `--threads` needed) and
|
|
2182
2212
|
`totalMemory()` (`i64` bytes, or `-1`) size a program to the machine. None of
|
|
2183
2213
|
the five exists on a wasm target, and `spawn` and `waitPid` throw under Node.
|
|
2214
|
+
`spawnWithFds(argv, fds)` is `spawn` that hands the child `fds[i]` as
|
|
2215
|
+
descriptor `3 + i` (systemd's `LISTEN_FDS` numbering); every other descriptor
|
|
2216
|
+
still closes at exec. More than 64, or a negative one, is `-22`; it needs
|
|
2217
|
+
`process.spawn` under `--sandbox`, refuses a wasm target and throws under Node.
|
|
2184
2218
|
`setNice(n)` sets the nice value, and it is lower-only even as root: `n` takes
|
|
2185
2219
|
0..19 (`-22` outside it) and a value below the current one is `-13`, with no
|
|
2186
2220
|
system call either way. `setIdlePriority()` moves the program to Linux's `SCHED_IDLE`
|
|
@@ -2230,8 +2264,42 @@ unread is reported again. Add `signalFd()` to the loop to wake on SIGTERM.
|
|
|
2230
2264
|
`NET_SO_KEEPALIVE`, `NET_SO_SNDBUF` and `NET_SO_RCVBUF`, `i32` ids exported
|
|
2231
2265
|
beside it; any other id is `-22`. Linux drops quick-ACK mode on its own, so set
|
|
2232
2266
|
it again after each response. The ids are not module constants: pass them
|
|
2233
|
-
directly.
|
|
2234
|
-
|
|
2267
|
+
directly. `netMss(fd)` answers a connected TCP socket's send MSS, the payload
|
|
2268
|
+
bytes one segment carries, and `-1` for anything else (never an errno), so size
|
|
2269
|
+
writes by it with a fallback. None but `netMss` exists on a wasm target (there
|
|
2270
|
+
it is always `-1`), and under Node each throws.
|
|
2271
|
+
|
|
2272
|
+
Unix-domain stream sockets: `unixListen(path, backlog, flags)` listens on a
|
|
2273
|
+
socket file left at 0600 (`unixListenMode(path, backlog, flags, mode)` for
|
|
2274
|
+
another mode), `unixConnect(path)` and `unixAccept(fd)` answer descriptors
|
|
2275
|
+
that `netRead`, `netWrite`, `netShutdown`, `netClose` and the loop take as
|
|
2276
|
+
they are, and `unixSocketPair(NET_UNIX_STREAM, fds)` fills `fds: i32[]` with
|
|
2277
|
+
two connected ends (`NET_UNIX_SEQPACKET` keeps message boundaries; Linux
|
|
2278
|
+
only, `-95` on Darwin). A path starting with `@` is Linux's abstract
|
|
2279
|
+
namespace and makes no file (`-95` on Darwin); write `./@name` for a socket
|
|
2280
|
+
file so named. A path that exists is `-98`; flag `NET_UNIX_UNLINK_STALE`
|
|
2281
|
+
first removes a socket file nobody listens on (Linux; on Darwin it is `-95`
|
|
2282
|
+
at a socket file, since a full backlog and a dead file both refuse there).
|
|
2283
|
+
`NET_UNIX_UNLINK_STALE`, `NET_UNIX_STREAM` and `NET_TCP_NODELAY` are all `1`,
|
|
2284
|
+
so pass the constant each call names. A path as written is at most 107
|
|
2285
|
+
bytes (103 on Darwin) and an abstract name at most 107 after its `@`; longer
|
|
2286
|
+
is `-36`. A full backlog makes `unixConnect`
|
|
2287
|
+
`-11` on Linux and `-111` on Darwin. Under `--sandbox`, a listener on a path
|
|
2288
|
+
also needs `fs.write` (`-13` without it); an abstract name does not, and a
|
|
2289
|
+
connect to a path is not confined. `sendFd(sock, fd, buf, off, len)` sends
|
|
2290
|
+
`buf[off, off + len)` with descriptor `fd` attached (`len` 0 is `-22`) and
|
|
2291
|
+
answers the bytes sent, which on a stream socket can be short: the descriptor
|
|
2292
|
+
went with the first bytes, so send the rest with `netWrite`; `recvFd(sock, buf, off, len, fd)` reads into the
|
|
2293
|
+
range and sets `fd[0]` to the descriptor that came with it, or `-1`; the
|
|
2294
|
+
descriptor arrives close-on-exec, its status flags (`O_NONBLOCK` among them)
|
|
2295
|
+
the open file's, which the sender shares, any beyond the first are closed,
|
|
2296
|
+
and `fd` shorter than 1 is `-22`. `peerCredentials(sock, out)` writes
|
|
2297
|
+
`[pid, uid, gid]` of the process that made the connection, as it was at
|
|
2298
|
+
connect time, into an `out` of length 3 or more (`-22` shorter, `-107` for a
|
|
2299
|
+
listener or a socket never connected); on Darwin the
|
|
2300
|
+
pid can be `-1`. All three answer `-88` or `-95` for a socket that is not
|
|
2301
|
+
Unix-domain. The Unix calls are refused on a wasm target, and under Node each
|
|
2302
|
+
throws.
|
|
2235
2303
|
|
|
2236
2304
|
**Arena.** `Arena.mark()`, `Arena.used()` and `using a = arena()` — see below.
|
|
2237
2305
|
`Arena.release(m)` and `Arena.reset()` were removed before 1.0: write
|
|
@@ -2261,6 +2329,10 @@ console.log(`${seen.size} ${counts.size} ${seen.has("b")}`);
|
|
|
2261
2329
|
- A key is a string, any number type, a `boolean`, an enum or a class instance
|
|
2262
2330
|
(by identity). An interface, an array, a nullable type or a `Result` is not a
|
|
2263
2331
|
key; a value is anything but `void` or an interface.
|
|
2332
|
+
- A pair of `i32`s is one `i64` key, not a string: `(toI64(a) << toI64(32)) |
|
|
2333
|
+
toI64(toU32(b))`. Every operand is an `i64` so it also runs
|
|
2334
|
+
under Node, where `i64` is a `BigInt`; it is exact for every pair. A `+` in
|
|
2335
|
+
place of `|` overflows at `a = -2^31` with a negative `b`.
|
|
2264
2336
|
- A module that declares its own `Map` or `Set` keeps it, but then no other
|
|
2265
2337
|
module of the program may name the global one.
|
|
2266
2338
|
|
|
@@ -2619,7 +2691,8 @@ negative `DEFLATE_ERR_*` / `GZIP_ERR_*` code for any malformed stream, so test
|
|
|
2619
2691
|
it before reading `out`. `GzipWriter` and `GzipReader` stream. On HTTP/1.1,
|
|
2620
2692
|
`conn.respondEncoded(status, names, values, body, off, len, enc,
|
|
2621
2693
|
conn.acceptEncoding())` with an `HttpCompressor` from `nish/net/http-compress`
|
|
2622
|
-
negotiates, compresses
|
|
2694
|
+
negotiates, compresses when it pays (`minLength`, `minSavingPercent`,
|
|
2695
|
+
`segmentMode`; `enc.decision` says why not) and sets the fields. Do not compress a secret beside
|
|
2623
2696
|
text the client chose (BREACH). (No block, as for `nish/text`;
|
|
2624
2697
|
`tests/link/std_compress` is its program, and the user guide's
|
|
2625
2698
|
[compression page](guide/using-nish/compression.md) its walk-through.)
|
|
@@ -2665,7 +2738,7 @@ or `PG_LOST` to `fail(run)` (on a spent handle these do nothing and count in
|
|
|
2665
2738
|
`stray`), and after each call `next(run)` until
|
|
2666
2739
|
`PG_BATCH_NONE`: `PG_BATCH_ROW` (the connection's row answers request `tag`),
|
|
2667
2740
|
then one of `PG_BATCH_DONE`, `PG_BATCH_MISSING` or `PG_BATCH_FAILED` per
|
|
2668
|
-
request. It reads no clock: when to take is the loop's choice. (No block;
|
|
2741
|
+
request. It reads no clock: when to take is the loop's choice, or a `PgBatchClock`'s (`PgBatchClockConfig`: `minCount`, `factor` × the moving average of batch sizes, `maxWaitUs`, the idle bypass `lightCount`; defaults are a fixed window), which `takeDue(conn, clock, nowUs, pool.inFlight())` consults after `clock.arrived(nowUs)` per add; `PgBatchTurns` wakes one collecting connection only when its batch is due. (No block;
|
|
2669
2742
|
`tests/postgres/live`'s `batch` scenario runs it against a server, and the user
|
|
2670
2743
|
guide's [PostgreSQL page](guide/using-nish/postgres.md#batching-keyed-reads)
|
|
2671
2744
|
its walk-through.)
|
|
@@ -2709,8 +2782,11 @@ export const main = (): i32 => {
|
|
|
2709
2782
|
};
|
|
2710
2783
|
```
|
|
2711
2784
|
|
|
2712
|
-
**Optional parameters** —
|
|
2713
|
-
|
|
2785
|
+
**Optional parameters** — write a default instead: `(n: i32 = 1)`. A default
|
|
2786
|
+
is a literal, an enum member or an earlier parameter, and the call site fills
|
|
2787
|
+
it in. `x?: T` is refused. A variable count of one type is a rest parameter,
|
|
2788
|
+
`(...ns: i32[])`, last in the list; a call never spreads (`f(...xs)`), it passes
|
|
2789
|
+
`xs` to an array parameter.
|
|
2714
2790
|
|
|
2715
2791
|
**A calendar, regex, JSON, threads of your own** — not in the language (the
|
|
2716
2792
|
wall clock is `Date.now()`, and that is all of `Date`). Say so rather than
|
|
@@ -2822,6 +2898,22 @@ const settings = (): string => readFileSync("settings.txt");
|
|
|
2822
2898
|
export const main = (): i32 => settings().length;
|
|
2823
2899
|
```
|
|
2824
2900
|
|
|
2901
|
+
The policy judges the source; `--sandbox` (Linux, `--link` and `nish run`)
|
|
2902
|
+
makes the kernel hold the running binary to the same set. Before any C
|
|
2903
|
+
constructor runs, it withholds every file, process and socket operation `main`
|
|
2904
|
+
does not reach, C code it links included. A file operation it refuses fails
|
|
2905
|
+
like a missing permission; a refused process or socket call ends the program
|
|
2906
|
+
with `SIGSYS` (status 159); a kernel that cannot apply it exits 126 before
|
|
2907
|
+
`main` unless built with `--sandbox=best-effort`. A darwin target, a library
|
|
2908
|
+
with no `main` and `--emit-napi` refuse the flag
|
|
2909
|
+
([LANGUAGE.md](LANGUAGE.md#the-sandbox)). Only under `--sandbox` may an
|
|
2910
|
+
`--allow` list scope `fs.read` or `fs.write` to a directory
|
|
2911
|
+
(`--allow fs.read=/srv/data`): the directory must exist at build time, and
|
|
2912
|
+
the kernel grants the capability beneath it alone — except that a `main`
|
|
2913
|
+
reaching `process.spawn` can still read every file beneath `/`, so that
|
|
2914
|
+
`exec` can load a program. Any other scope, a scope
|
|
2915
|
+
in `--deny` and a scope without `--sandbox` are usage errors, exit 2.
|
|
2916
|
+
|
|
2825
2917
|
## Before you say it compiles
|
|
2826
2918
|
|
|
2827
2919
|
Run it. `nish file.ts --json` is one command and it is the only proof.
|
package/package.json
CHANGED
package/runtime/core/host.d.ts
CHANGED
|
@@ -73,8 +73,9 @@ export declare function isTerminal(fd: i32): boolean;
|
|
|
73
73
|
export declare function terminalSize(): i32[];
|
|
74
74
|
/** `crypto.getRandomValues(bytes)` for a `u8[]`; a typed array goes straight through. */
|
|
75
75
|
export declare function getRandomValues<T extends u8[] | Uint8Array>(bytes: T): T;
|
|
76
|
-
/** These
|
|
76
|
+
/** These five have no synchronous reading: each throws, naming itself, and is typed as `runtime/nish.d.ts` types it. */
|
|
77
77
|
export declare function spawn(argv: string[]): i32;
|
|
78
|
+
export declare function spawnWithFds(argv: string[], fds: readonly i32[]): i32;
|
|
78
79
|
export declare function waitPid(pid: i32, flags: i32): i32[];
|
|
79
80
|
export declare function signalFd(): i32;
|
|
80
81
|
export declare function readSignal(fd: i32): i32;
|
package/runtime/core/host.mjs
CHANGED
package/runtime/core.d.ts
CHANGED
|
@@ -7,3 +7,50 @@ export * from "./core/host.js";
|
|
|
7
7
|
export * from "./core/numbers.js";
|
|
8
8
|
export * from "./core/result.js";
|
|
9
9
|
export * from "./core/strings.js";
|
|
10
|
+
|
|
11
|
+
// `nish:simd`: what `--emit-ts` writes for a program's `import ... from "nish:simd"`.
|
|
12
|
+
import type { f32, f64, i32, u16, u32, u8 } from "./core/numbers.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A sixteen-byte vector of lanes. Opaque: TypeScript refuses `+` on one, as
|
|
16
|
+
* `nish` does, but lets `===` and `<` through, which `nish` refuses. Under
|
|
17
|
+
* Node it is a typed array made once and never written after.
|
|
18
|
+
*/
|
|
19
|
+
export interface u8x16 { readonly __nishSimd: "u8x16"; readonly __lane: u8 }
|
|
20
|
+
export interface u16x8 { readonly __nishSimd: "u16x8"; readonly __lane: u16 }
|
|
21
|
+
export interface i32x4 { readonly __nishSimd: "i32x4"; readonly __lane: i32 }
|
|
22
|
+
export interface u32x4 { readonly __nishSimd: "u32x4"; readonly __lane: u32 }
|
|
23
|
+
export interface f32x4 { readonly __nishSimd: "f32x4"; readonly __lane: f32 }
|
|
24
|
+
export interface f64x2 { readonly __nishSimd: "f64x2"; readonly __lane: f64 }
|
|
25
|
+
/** Any of the six. */
|
|
26
|
+
export type SimdVector = u8x16 | u16x8 | i32x4 | u32x4 | f32x4 | f64x2;
|
|
27
|
+
/** One value per lane, lane 0 first. */
|
|
28
|
+
export declare function u8x16(
|
|
29
|
+
a0: u8, a1: u8, a2: u8, a3: u8, a4: u8, a5: u8, a6: u8, a7: u8,
|
|
30
|
+
a8: u8, a9: u8, a10: u8, a11: u8, a12: u8, a13: u8, a14: u8, a15: u8
|
|
31
|
+
): u8x16;
|
|
32
|
+
export declare function u16x8(a0: u16, a1: u16, a2: u16, a3: u16, a4: u16, a5: u16, a6: u16, a7: u16): u16x8;
|
|
33
|
+
export declare function i32x4(a0: i32, a1: i32, a2: i32, a3: i32): i32x4;
|
|
34
|
+
export declare function u32x4(a0: u32, a1: u32, a2: u32, a3: u32): u32x4;
|
|
35
|
+
export declare function f32x4(a0: f32, a1: f32, a2: f32, a3: f32): f32x4;
|
|
36
|
+
export declare function f64x2(a0: f64, a1: f64): f64x2;
|
|
37
|
+
/** `x` in every lane. */
|
|
38
|
+
export declare function splatU8x16(x: u8): u8x16;
|
|
39
|
+
export declare function splatU16x8(x: u16): u16x8;
|
|
40
|
+
export declare function splatI32x4(x: i32): i32x4;
|
|
41
|
+
export declare function splatU32x4(x: u32): u32x4;
|
|
42
|
+
export declare function splatF32x4(x: f32): f32x4;
|
|
43
|
+
export declare function splatF64x2(x: f64): f64x2;
|
|
44
|
+
/** `xs[i]` to `xs[i + N - 1]`, bounds-checked once for the whole vector. */
|
|
45
|
+
export declare function loadU8x16(xs: readonly u8[], i: i32): u8x16;
|
|
46
|
+
export declare function loadU16x8(xs: readonly u16[], i: i32): u16x8;
|
|
47
|
+
export declare function loadI32x4(xs: readonly i32[], i: i32): i32x4;
|
|
48
|
+
export declare function loadU32x4(xs: readonly u32[], i: i32): u32x4;
|
|
49
|
+
export declare function loadF32x4(xs: readonly f32[], i: i32): f32x4;
|
|
50
|
+
export declare function loadF64x2(xs: readonly f64[], i: i32): f64x2;
|
|
51
|
+
/** The lanes of `v` into `xs[i]` to `xs[i + N - 1]`, checked once. */
|
|
52
|
+
export declare function store<V extends SimdVector>(v: V, xs: V["__lane"][], i: i32): void;
|
|
53
|
+
/** Lane `k`, an integer literal in range. */
|
|
54
|
+
export declare function extract<V extends SimdVector>(v: V, k: i32): V["__lane"];
|
|
55
|
+
/** A new vector: `v` with lane `k` set to `x`. */
|
|
56
|
+
export declare function replace<V extends SimdVector>(v: V, k: i32, x: V["__lane"]): V;
|
package/runtime/core.mjs
CHANGED
|
@@ -48,8 +48,75 @@
|
|
|
48
48
|
*
|
|
49
49
|
* The rewrite rules that call these helpers are listed in docs/wp13-differential.md.
|
|
50
50
|
*/
|
|
51
|
+
import { panicIndex, toIndex } from "./core/checks.mjs";
|
|
52
|
+
|
|
51
53
|
export * from "./core/arrays.mjs";
|
|
52
54
|
export * from "./core/host.mjs";
|
|
53
55
|
export * from "./core/numbers.mjs";
|
|
54
56
|
export * from "./core/result.mjs";
|
|
55
57
|
export * from "./core/strings.mjs";
|
|
58
|
+
|
|
59
|
+
// ---- `nish:simd` ------------------------------------------------------------
|
|
60
|
+
// A vector is a fresh typed array of its lanes, made once and never written
|
|
61
|
+
// after: `replace` copies, so a vector held in two places stays one value, as
|
|
62
|
+
// the native `<N x T>` register is. The array type does the lane arithmetic a
|
|
63
|
+
// native lane does: a `u8` lane wraps through `Uint8Array`, an `f32` lane rounds
|
|
64
|
+
// through `Float32Array`. `load…` and `store` check the whole vector once, and
|
|
65
|
+
// panic with the native words: the first index, and the array's length.
|
|
66
|
+
|
|
67
|
+
const simdMake = (Lanes) => (...lanes) => new Lanes(lanes);
|
|
68
|
+
const simdSplat = (Lanes) => (x) => new Lanes(16 / Lanes.BYTES_PER_ELEMENT).fill(x);
|
|
69
|
+
// The first index of `count` lanes at `i` in `xs`, or the native panic naming
|
|
70
|
+
// a lane that is out of range: the first when it is, else the last. A negative
|
|
71
|
+
// index prints as the unsigned 64-bit number the native compare saw.
|
|
72
|
+
const simdAt = (xs, i, count) => {
|
|
73
|
+
const k = toIndex(i);
|
|
74
|
+
if (k < 0) panicIndex(BigInt.asUintN(64, BigInt(k)), xs.length);
|
|
75
|
+
if (k >= xs.length) panicIndex(k, xs.length);
|
|
76
|
+
if (k + count > xs.length) panicIndex(k + count - 1, xs.length);
|
|
77
|
+
return k;
|
|
78
|
+
};
|
|
79
|
+
const simdLoad = (Lanes) => (xs, i) => {
|
|
80
|
+
const count = 16 / Lanes.BYTES_PER_ELEMENT;
|
|
81
|
+
const k = simdAt(xs, i, count);
|
|
82
|
+
const out = new Lanes(count);
|
|
83
|
+
for (let j = 0; j < count; j++) out[j] = xs[k + j];
|
|
84
|
+
return out;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const u8x16 = simdMake(Uint8Array);
|
|
88
|
+
export const u16x8 = simdMake(Uint16Array);
|
|
89
|
+
export const i32x4 = simdMake(Int32Array);
|
|
90
|
+
export const u32x4 = simdMake(Uint32Array);
|
|
91
|
+
export const f32x4 = simdMake(Float32Array);
|
|
92
|
+
export const f64x2 = simdMake(Float64Array);
|
|
93
|
+
export const splatU8x16 = simdSplat(Uint8Array);
|
|
94
|
+
export const splatU16x8 = simdSplat(Uint16Array);
|
|
95
|
+
export const splatI32x4 = simdSplat(Int32Array);
|
|
96
|
+
export const splatU32x4 = simdSplat(Uint32Array);
|
|
97
|
+
export const splatF32x4 = simdSplat(Float32Array);
|
|
98
|
+
export const splatF64x2 = simdSplat(Float64Array);
|
|
99
|
+
export const loadU8x16 = simdLoad(Uint8Array);
|
|
100
|
+
export const loadU16x8 = simdLoad(Uint16Array);
|
|
101
|
+
export const loadI32x4 = simdLoad(Int32Array);
|
|
102
|
+
export const loadU32x4 = simdLoad(Uint32Array);
|
|
103
|
+
export const loadF32x4 = simdLoad(Float32Array);
|
|
104
|
+
export const loadF64x2 = simdLoad(Float64Array);
|
|
105
|
+
|
|
106
|
+
/** `store(v, xs, i)`: the lanes into `xs[i]` to `xs[i + N - 1]`, checked once. */
|
|
107
|
+
export function store(v, xs, i) {
|
|
108
|
+
const k = simdAt(xs, i, v.length);
|
|
109
|
+
for (let j = 0; j < v.length; j++) xs[k + j] = v[j];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** `extract(v, k)`: lane `k`, a constant the checker held in range. */
|
|
113
|
+
export function extract(v, k) {
|
|
114
|
+
return v[k];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** `replace(v, k, x)`: a new vector, `v` with lane `k` set to `x`. */
|
|
118
|
+
export function replace(v, k, x) {
|
|
119
|
+
const out = v.slice();
|
|
120
|
+
out[k] = x;
|
|
121
|
+
return out;
|
|
122
|
+
}
|