@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/runtime/nish.d.ts
CHANGED
|
@@ -333,6 +333,14 @@ declare function spawnSyncTo(argv: string[], stdoutPath: string, stderrPath: str
|
|
|
333
333
|
* the child is then killed and each array keeps at most the first 16 MiB.
|
|
334
334
|
*/
|
|
335
335
|
declare function spawnPiped(argv: string[], stdin: readonly u8[], stdout: u8[], stderr: u8[]): i32;
|
|
336
|
+
/**
|
|
337
|
+
* `spawn` with the child holding `fds[i]` as descriptor `3 + i`, inherited
|
|
338
|
+
* across the exec; every other descriptor stays close-on-exec. The child's pid,
|
|
339
|
+
* or a negative errno: -22 more than 64 descriptors or a negative one, -9 one
|
|
340
|
+
* that is not open, -24 (or -22 above the descriptor limit) a scratch
|
|
341
|
+
* descriptor the system cannot give. No reading under Node, which throws.
|
|
342
|
+
*/
|
|
343
|
+
declare function spawnWithFds(argv: string[], fds: readonly i32[]): i32;
|
|
336
344
|
/**
|
|
337
345
|
* Start `argv[0]` through `PATH` without waiting: the child's pid, or a
|
|
338
346
|
* negative errno. The child is the program's until `waitPid` reaps it. No
|
|
@@ -460,6 +468,11 @@ declare function pollWait(loop: i32, ready: i32[], timeoutMs: i32): i32;
|
|
|
460
468
|
* a negative errno (-9 a closed descriptor, -88 not a socket).
|
|
461
469
|
*/
|
|
462
470
|
declare function netSetOption(fd: i32, option: i32, value: i32): i32;
|
|
471
|
+
/**
|
|
472
|
+
* A connected TCP socket's send MSS, the payload bytes one segment carries;
|
|
473
|
+
* -1, never an errno, for anything else, and always on wasm.
|
|
474
|
+
*/
|
|
475
|
+
declare function netMss(fd: i32): i32;
|
|
463
476
|
/** `TCP_NODELAY`: `value` 1 sends a small write at once, 0 lets Nagle batch it. */
|
|
464
477
|
declare const NET_TCP_NODELAY: i32;
|
|
465
478
|
/**
|
|
@@ -474,6 +487,57 @@ declare const NET_SO_KEEPALIVE: i32;
|
|
|
474
487
|
declare const NET_SO_SNDBUF: i32;
|
|
475
488
|
/** `SO_RCVBUF`: the receive buffer, `value` in bytes; Linux doubles the value it stores. */
|
|
476
489
|
declare const NET_SO_RCVBUF: i32;
|
|
490
|
+
/**
|
|
491
|
+
* A listening Unix stream socket at `path` (`@name`: Linux's abstract
|
|
492
|
+
* namespace), its file mode 0600. A path that exists is -98, unless `flags`
|
|
493
|
+
* holds `NET_UNIX_UNLINK_STALE`; -36 a path too long, -22 an empty one.
|
|
494
|
+
*/
|
|
495
|
+
declare function unixListen(path: string, backlog: i32, flags: i32): i32;
|
|
496
|
+
/** `unixListen` with the socket file's mode chosen (0 to 0o777); -22 for an `@name`. */
|
|
497
|
+
declare function unixListenMode(path: string, backlog: i32, flags: i32, mode: i32): i32;
|
|
498
|
+
/** A non-blocking socket connected to the listener at `path`; -11 a full backlog on Linux (-111 on Darwin), -111 nothing listening. */
|
|
499
|
+
declare function unixConnect(path: string): i32;
|
|
500
|
+
/** The next connection on a Unix listener, non-blocking; -11 when none is waiting. */
|
|
501
|
+
declare function unixAccept(fd: i32): i32;
|
|
502
|
+
/**
|
|
503
|
+
* Two connected sockets into `fds[0]` and `fds[1]`, and 0: `kind` is
|
|
504
|
+
* `NET_UNIX_STREAM` or `NET_UNIX_SEQPACKET` (-95 on Darwin); -22 another kind
|
|
505
|
+
* or an `fds` shorter than 2.
|
|
506
|
+
*/
|
|
507
|
+
declare function unixSocketPair(kind: i32, fds: i32[]): i32;
|
|
508
|
+
/**
|
|
509
|
+
* Send `buf[off..off+len)` over the Unix socket `sock` with a copy of the
|
|
510
|
+
* descriptor `fd` (`SCM_RIGHTS`): the bytes sent, or a negative errno; -22 a
|
|
511
|
+
* zero `len` or a negative `fd`, -9 a closed `sock` or `fd`, -88 a `sock`
|
|
512
|
+
* that is not a socket, -95 one that is not Unix. A stream socket can send
|
|
513
|
+
* short: the descriptor travels with the first bytes, so send the rest with
|
|
514
|
+
* `netWrite`.
|
|
515
|
+
*/
|
|
516
|
+
declare function sendFd(sock: i32, fd: i32, buf: readonly u8[], off: i32, len: i32): i32;
|
|
517
|
+
/**
|
|
518
|
+
* Read at most `len` bytes into `buf[off..]` from the Unix socket `sock`, and
|
|
519
|
+
* the first descriptor that came with them into `fd[0]`, or -1: the bytes read,
|
|
520
|
+
* or a negative errno. Every other descriptor in the message is closed; the
|
|
521
|
+
* one kept is close-on-exec and keeps the sender's blocking mode. -22 a zero
|
|
522
|
+
* `len` or an empty `fd`, -9 a closed `sock`, -88 not a socket, -95 not
|
|
523
|
+
* Unix.
|
|
524
|
+
*/
|
|
525
|
+
declare function recvFd(sock: i32, buf: u8[], off: i32, len: i32, fd: i32[]): i32;
|
|
526
|
+
/**
|
|
527
|
+
* The peer of the Unix socket `fd` as of its connect: `out` gets its pid, uid
|
|
528
|
+
* and gid, and the answer is 0; the pid is -1 where Darwin has no
|
|
529
|
+
* `LOCAL_PEERPID`. A uid or gid of 2^31 or above wraps (-2 is uid
|
|
530
|
+
* 4294967294). -22 an `out` shorter than 3, -9 a closed `fd`, -88 not a
|
|
531
|
+
* socket, -95 not Unix, -107 a socket with no peer (a listener, or one never
|
|
532
|
+
* connected).
|
|
533
|
+
*/
|
|
534
|
+
declare function peerCredentials(fd: i32, out: i32[]): i32;
|
|
535
|
+
/** `unixListen` flag: unlink a socket file nothing listens on, then bind. */
|
|
536
|
+
declare const NET_UNIX_UNLINK_STALE: i32;
|
|
537
|
+
/** `unixSocketPair` kind: a byte stream. */
|
|
538
|
+
declare const NET_UNIX_STREAM: i32;
|
|
539
|
+
/** `unixSocketPair` kind: each write one message (`SOCK_SEQPACKET`). */
|
|
540
|
+
declare const NET_UNIX_SEQPACKET: i32;
|
|
477
541
|
|
|
478
542
|
// ---- `nish:term` ------------------------------------------------------------------
|
|
479
543
|
//
|
|
@@ -580,6 +644,13 @@ declare module "nish:process" {
|
|
|
580
644
|
export function spawnPiped(argv: string[], stdin: readonly u8[], stdout: u8[], stderr: u8[]): i32;
|
|
581
645
|
/** Start a child without waiting: its pid, or a negative errno. */
|
|
582
646
|
export function spawn(argv: string[]): i32;
|
|
647
|
+
/**
|
|
648
|
+
* `spawn` with the child holding `fds[i]` as descriptor `3 + i`: its pid, or
|
|
649
|
+
* a negative errno; -22 more than 64 descriptors or a negative one, -9 one
|
|
650
|
+
* that is not open, -24 (or -22 above the descriptor limit) a scratch
|
|
651
|
+
* descriptor the system cannot give.
|
|
652
|
+
*/
|
|
653
|
+
export function spawnWithFds(argv: string[], fds: readonly i32[]): i32;
|
|
583
654
|
/** Send 0, 2, 9 or 15 to `pid`: 0, or a negative errno; any other signal is -22. */
|
|
584
655
|
export function kill(pid: i32, sig: i32): i32;
|
|
585
656
|
/** `[pid, status]` for a child that exited, `[0, 0]` under WNOHANG (flag 1) with none, or `[-errno, 0]`. */
|
|
@@ -667,6 +738,11 @@ declare module "nish:net" {
|
|
|
667
738
|
* a negative errno (-9 a closed descriptor, -88 not a socket).
|
|
668
739
|
*/
|
|
669
740
|
export function netSetOption(fd: i32, option: i32, value: i32): i32;
|
|
741
|
+
/**
|
|
742
|
+
* A connected TCP socket's send MSS, the payload bytes one segment carries;
|
|
743
|
+
* -1, never an errno, for anything else, and always on wasm.
|
|
744
|
+
*/
|
|
745
|
+
export function netMss(fd: i32): i32;
|
|
670
746
|
/** `TCP_NODELAY`: `value` 1 sends a small write at once, 0 lets Nagle batch it. */
|
|
671
747
|
export const NET_TCP_NODELAY: i32;
|
|
672
748
|
/**
|
|
@@ -681,6 +757,57 @@ declare module "nish:net" {
|
|
|
681
757
|
export const NET_SO_SNDBUF: i32;
|
|
682
758
|
/** `SO_RCVBUF`: the receive buffer, `value` in bytes; Linux doubles the value it stores. */
|
|
683
759
|
export const NET_SO_RCVBUF: i32;
|
|
760
|
+
/**
|
|
761
|
+
* A listening Unix stream socket at `path` (`@name`: Linux's abstract
|
|
762
|
+
* namespace), its file mode 0600. A path that exists is -98, unless `flags`
|
|
763
|
+
* holds `NET_UNIX_UNLINK_STALE`; -36 a path too long, -22 an empty one.
|
|
764
|
+
*/
|
|
765
|
+
export function unixListen(path: string, backlog: i32, flags: i32): i32;
|
|
766
|
+
/** `unixListen` with the socket file's mode chosen (0 to 0o777); -22 for an `@name`. */
|
|
767
|
+
export function unixListenMode(path: string, backlog: i32, flags: i32, mode: i32): i32;
|
|
768
|
+
/** A non-blocking socket connected to the listener at `path`; -11 a full backlog on Linux (-111 on Darwin), -111 nothing listening. */
|
|
769
|
+
export function unixConnect(path: string): i32;
|
|
770
|
+
/** The next connection on a Unix listener, non-blocking; -11 when none is waiting. */
|
|
771
|
+
export function unixAccept(fd: i32): i32;
|
|
772
|
+
/**
|
|
773
|
+
* Two connected sockets into `fds[0]` and `fds[1]`, and 0: `kind` is
|
|
774
|
+
* `NET_UNIX_STREAM` or `NET_UNIX_SEQPACKET` (-95 on Darwin); -22 another kind
|
|
775
|
+
* or an `fds` shorter than 2.
|
|
776
|
+
*/
|
|
777
|
+
export function unixSocketPair(kind: i32, fds: i32[]): i32;
|
|
778
|
+
/**
|
|
779
|
+
* Send `buf[off..off+len)` over the Unix socket `sock` with a copy of the
|
|
780
|
+
* descriptor `fd` (`SCM_RIGHTS`): the bytes sent, or a negative errno; -22 a
|
|
781
|
+
* zero `len` or a negative `fd`, -9 a closed `sock` or `fd`, -88 a `sock`
|
|
782
|
+
* that is not a socket, -95 one that is not Unix. A stream socket can send
|
|
783
|
+
* short: the descriptor travels with the first bytes, so send the rest with
|
|
784
|
+
* `netWrite`.
|
|
785
|
+
*/
|
|
786
|
+
export function sendFd(sock: i32, fd: i32, buf: readonly u8[], off: i32, len: i32): i32;
|
|
787
|
+
/**
|
|
788
|
+
* Read at most `len` bytes into `buf[off..]` from the Unix socket `sock`, and
|
|
789
|
+
* the first descriptor that came with them into `fd[0]`, or -1: the bytes read,
|
|
790
|
+
* or a negative errno. Every other descriptor in the message is closed; the
|
|
791
|
+
* one kept is close-on-exec and keeps the sender's blocking mode. -22 a zero
|
|
792
|
+
* `len` or an empty `fd`, -9 a closed `sock`, -88 not a socket, -95 not
|
|
793
|
+
* Unix.
|
|
794
|
+
*/
|
|
795
|
+
export function recvFd(sock: i32, buf: u8[], off: i32, len: i32, fd: i32[]): i32;
|
|
796
|
+
/**
|
|
797
|
+
* The peer of the Unix socket `fd` as of its connect: `out` gets its pid, uid
|
|
798
|
+
* and gid, and the answer is 0; the pid is -1 where Darwin has no
|
|
799
|
+
* `LOCAL_PEERPID`. A uid or gid of 2^31 or above wraps (-2 is uid
|
|
800
|
+
* 4294967294). -22 an `out` shorter than 3, -9 a closed `fd`, -88 not a
|
|
801
|
+
* socket, -95 not Unix, -107 a socket with no peer (a listener, or one never
|
|
802
|
+
* connected).
|
|
803
|
+
*/
|
|
804
|
+
export function peerCredentials(fd: i32, out: i32[]): i32;
|
|
805
|
+
/** `unixListen` flag: unlink a socket file nothing listens on, then bind. */
|
|
806
|
+
export const NET_UNIX_UNLINK_STALE: i32;
|
|
807
|
+
/** `unixSocketPair` kind: a byte stream. */
|
|
808
|
+
export const NET_UNIX_STREAM: i32;
|
|
809
|
+
/** `unixSocketPair` kind: each write one message (`SOCK_SEQPACKET`). */
|
|
810
|
+
export const NET_UNIX_SEQPACKET: i32;
|
|
684
811
|
}
|
|
685
812
|
|
|
686
813
|
declare module "nish:unsafe" {
|
|
@@ -698,6 +825,55 @@ declare module "nish:unsafe" {
|
|
|
698
825
|
export function readCString(p: CPtr): string;
|
|
699
826
|
}
|
|
700
827
|
|
|
828
|
+
// `nish:simd` (docs/LANGUAGE.md -> Vectors): the six sixteen-byte vector
|
|
829
|
+
// types and the calls that make, load, store and take one apart. Under Node,
|
|
830
|
+
// `runtime/nish.mjs` answers the import with `runtime/core.mjs`'s names.
|
|
831
|
+
declare module "nish:simd" {
|
|
832
|
+
/**
|
|
833
|
+
* A sixteen-byte vector of lanes. Opaque: TypeScript refuses `+` on one, as
|
|
834
|
+
* `nish` does, but lets `===` and `<` through, which `nish` refuses. Under
|
|
835
|
+
* Node it is a typed array made once and never written after.
|
|
836
|
+
*/
|
|
837
|
+
export interface u8x16 { readonly __nishSimd: "u8x16"; readonly __lane: u8 }
|
|
838
|
+
export interface u16x8 { readonly __nishSimd: "u16x8"; readonly __lane: u16 }
|
|
839
|
+
export interface i32x4 { readonly __nishSimd: "i32x4"; readonly __lane: i32 }
|
|
840
|
+
export interface u32x4 { readonly __nishSimd: "u32x4"; readonly __lane: u32 }
|
|
841
|
+
export interface f32x4 { readonly __nishSimd: "f32x4"; readonly __lane: f32 }
|
|
842
|
+
export interface f64x2 { readonly __nishSimd: "f64x2"; readonly __lane: f64 }
|
|
843
|
+
/** Any of the six. */
|
|
844
|
+
export type SimdVector = u8x16 | u16x8 | i32x4 | u32x4 | f32x4 | f64x2;
|
|
845
|
+
/** One value per lane, lane 0 first. */
|
|
846
|
+
export function u8x16(
|
|
847
|
+
a0: u8, a1: u8, a2: u8, a3: u8, a4: u8, a5: u8, a6: u8, a7: u8,
|
|
848
|
+
a8: u8, a9: u8, a10: u8, a11: u8, a12: u8, a13: u8, a14: u8, a15: u8
|
|
849
|
+
): u8x16;
|
|
850
|
+
export function u16x8(a0: u16, a1: u16, a2: u16, a3: u16, a4: u16, a5: u16, a6: u16, a7: u16): u16x8;
|
|
851
|
+
export function i32x4(a0: i32, a1: i32, a2: i32, a3: i32): i32x4;
|
|
852
|
+
export function u32x4(a0: u32, a1: u32, a2: u32, a3: u32): u32x4;
|
|
853
|
+
export function f32x4(a0: f32, a1: f32, a2: f32, a3: f32): f32x4;
|
|
854
|
+
export function f64x2(a0: f64, a1: f64): f64x2;
|
|
855
|
+
/** `x` in every lane. */
|
|
856
|
+
export function splatU8x16(x: u8): u8x16;
|
|
857
|
+
export function splatU16x8(x: u16): u16x8;
|
|
858
|
+
export function splatI32x4(x: i32): i32x4;
|
|
859
|
+
export function splatU32x4(x: u32): u32x4;
|
|
860
|
+
export function splatF32x4(x: f32): f32x4;
|
|
861
|
+
export function splatF64x2(x: f64): f64x2;
|
|
862
|
+
/** `xs[i]` to `xs[i + N - 1]`, bounds-checked once for the whole vector. */
|
|
863
|
+
export function loadU8x16(xs: readonly u8[], i: i32): u8x16;
|
|
864
|
+
export function loadU16x8(xs: readonly u16[], i: i32): u16x8;
|
|
865
|
+
export function loadI32x4(xs: readonly i32[], i: i32): i32x4;
|
|
866
|
+
export function loadU32x4(xs: readonly u32[], i: i32): u32x4;
|
|
867
|
+
export function loadF32x4(xs: readonly f32[], i: i32): f32x4;
|
|
868
|
+
export function loadF64x2(xs: readonly f64[], i: i32): f64x2;
|
|
869
|
+
/** The lanes of `v` into `xs[i]` to `xs[i + N - 1]`, checked once. */
|
|
870
|
+
export function store<V extends SimdVector>(v: V, xs: V["__lane"][], i: i32): void;
|
|
871
|
+
/** Lane `k`, an integer literal in range. */
|
|
872
|
+
export function extract<V extends SimdVector>(v: V, k: i32): V["__lane"];
|
|
873
|
+
/** A new vector: `v` with lane `k` set to `x`. */
|
|
874
|
+
export function replace<V extends SimdVector>(v: V, k: i32, x: V["__lane"]): V;
|
|
875
|
+
}
|
|
876
|
+
|
|
701
877
|
declare module "nish:io" {
|
|
702
878
|
/** `s` to stdout with no trailing newline and no conversion. */
|
|
703
879
|
export function write(s: string): void;
|
package/runtime/nish.h
CHANGED
|
@@ -9,14 +9,17 @@
|
|
|
9
9
|
* functions, the directory and subprocess calls, `nish_getenv`, the monotonic
|
|
10
10
|
* clock, `nish_platform` / `nish_arch` — and runtime-parallel.c, runtime-host.c,
|
|
11
11
|
* runtime-net.c, runtime-simd.c (the byte searches that read a vector at a
|
|
12
|
-
* time), runtime-aes.c (AES-GCM on the CPU's AES instructions)
|
|
13
|
-
* runtime-
|
|
12
|
+
* time), runtime-aes.c (AES-GCM on the CPU's AES instructions),
|
|
13
|
+
* runtime-sha256.c (SHA-256 on the CPU's SHA instructions), runtime-checksum.c
|
|
14
|
+
* (CRC-32 on its carry-less multiply or CRC instructions) and runtime-term.c
|
|
15
|
+
* (stdin and the terminal, `nish:term`) split off
|
|
14
16
|
* the same way since. They are separate so that each carries its own measured
|
|
15
17
|
* code-size ceiling (docs/wp7-runtime.md, "Runtime additions and budget"); a
|
|
16
18
|
* host links all of them, which `scripts/build.sh` does for you when handed
|
|
17
|
-
* runtime.c, runtime-aes.c included: the
|
|
18
|
-
* std/crypto/aes.ts,
|
|
19
|
-
*
|
|
19
|
+
* runtime.c, runtime-aes.c, runtime-sha256.c and runtime-checksum.c included: the
|
|
20
|
+
* compiler calls their kernels from std/crypto/aes.ts, std/crypto/sha256.ts and
|
|
21
|
+
* std/compress/checksum.ts, so `scripts/build.sh` pairs each of them with
|
|
22
|
+
* runtime.c and `src/run-cache.ts` caches them like the others. `tests/run.js` checks that every runtime function
|
|
20
23
|
* declared in runtime.ts has a prototype in this file.
|
|
21
24
|
*
|
|
22
25
|
* Headers generated by `nish --emit-header` include this one, so keep
|
|
@@ -197,6 +200,16 @@ extern void (*nish_fatal_hook)(void);
|
|
|
197
200
|
/* Number to string, as `${n}` does: decimal for integers, shortest round-trip (JS Number#toString) for f64. */
|
|
198
201
|
nish_str *nish_str_from_i32(int32_t v);
|
|
199
202
|
nish_str *nish_str_from_f64(double v);
|
|
203
|
+
/* The bytes `nish_str_from_f64` would hold, written into `out` with no NUL;
|
|
204
|
+
returns the length. 32 bytes is room to spare: the longest spelling,
|
|
205
|
+
-0.0000012345678901234567, is 25 (runtime.c says why, and runtime-test.c
|
|
206
|
+
pins it). For a caller that writes numbers into its own buffer. */
|
|
207
|
+
#define NISH_F64_MAX 32
|
|
208
|
+
int nish_f64_format(double v, char out[NISH_F64_MAX]);
|
|
209
|
+
/* `nish_f64_format`'s bytes into `buf[at]` (std/json.ts's JsonWriter): the new
|
|
210
|
+
end, or -1, with nothing written, when `at < 0` or they do not fit before
|
|
211
|
+
`len`. `buf` may be null only when nothing fits. */
|
|
212
|
+
int32_t nish_json_put_f64(uint8_t *buf, int32_t len, int32_t at, double v);
|
|
200
213
|
nish_str *nish_str_from_i64(int64_t v);
|
|
201
214
|
/* Unsigned decimal (WP15). u8/u16/u32 are zero-extended by the caller, so one
|
|
202
215
|
symbol serves every unsigned width. */
|
|
@@ -348,6 +361,40 @@ void nish_aes_ctr(const nish_array *rk, int32_t rounds, const nish_array *j0, co
|
|
|
348
361
|
`rk` instead, and they are the same H. 0 <= length <= data.len. */
|
|
349
362
|
void nish_aes_ghash(nish_array *y, uint64_t hHi, uint64_t hLo, const nish_array *rk, const nish_array *data,
|
|
350
363
|
int32_t length);
|
|
364
|
+
/* ---- SHA-256 on the CPU's SHA instructions --------------------------------
|
|
365
|
+
* runtime/runtime-sha256.c: SHA-NI on x86-64, the ARMv8 SHA-256 instructions
|
|
366
|
+
* on AArch64. The compiler calls the kernel in place of std/crypto/sha256.ts's
|
|
367
|
+
* private `sha256Compress`, behind `nish_sha256_hw`, and calls the Nish
|
|
368
|
+
* function itself when either answers 0. Constant time in the state and the
|
|
369
|
+
* block. */
|
|
370
|
+
/* 1 when this process runs the kernel, 0 when it runs the Nish code. Resolved
|
|
371
|
+
on the first call and fixed from then on: `NISH_SHA256=soft` pins 0; unset,
|
|
372
|
+
`hw` or any other value is the best this machine has, read on that call from
|
|
373
|
+
CPUID (leaf 7's SHA, leaf 1's SSE4.1 and SSSE3), AArch64 Linux's AT_HWCAP
|
|
374
|
+
(SHA2) or macOS's `hw.optional.arm.FEAT_SHA256`. Always 0 on other targets,
|
|
375
|
+
wasm32 among them. */
|
|
376
|
+
int32_t nish_sha256_hw(void);
|
|
377
|
+
/* FIPS 180-4 §6.2.2 on the 64 bytes at src[at..at + 64) (u8[]), into the hash
|
|
378
|
+
value h[0..8) (u32[]); 1 when it ran. Answers 0 and writes nothing unless
|
|
379
|
+
h.len >= 8, w.len >= 64 and 0 <= at <= src.len - 64, `sha256Compress`'s
|
|
380
|
+
guard, so the caller's fallback panics as the Nish function does. `w` (u32[],
|
|
381
|
+
the message schedule the Nish code fills) is neither read nor written. */
|
|
382
|
+
int32_t nish_sha256_compress(nish_array *h, const nish_array *w, const nish_array *src, int32_t at);
|
|
383
|
+
/* ---- CRC-32 on the CPU's carry-less multiply or CRC instructions ---------
|
|
384
|
+
* runtime/runtime-checksum.c: PCLMULQDQ folding on x86-64, the ARMv8 CRC32
|
|
385
|
+
* instructions on AArch64. The compiler calls the kernel in
|
|
386
|
+
* place of std/compress/checksum.ts's private `crc32Walk`, behind
|
|
387
|
+
* `nish_crc32_hw`, and calls the Nish walker itself when that answers 0. */
|
|
388
|
+
/* 1 when this process runs the kernel, 0 when it runs the Nish tables.
|
|
389
|
+
Resolved on the first call and fixed from then on: `NISH_CRC32=soft` pins 0;
|
|
390
|
+
unset or any other value is the best this machine has, read on that call
|
|
391
|
+
from CPUID leaf 1 (PCLMULQDQ, SSE4.1), AArch64's AT_HWCAP (CRC32) or
|
|
392
|
+
Darwin's hw.optional sysctls. Always 0 on other targets, wasm32 among them. */
|
|
393
|
+
int32_t nish_crc32_hw(void);
|
|
394
|
+
/* The CRC-32 (ISO 3309, RFC 1952) `crc` extended over buf[off..off+len)
|
|
395
|
+
(u8[]), conditioned as zlib's crc32(): 0 starts a message, and the answer
|
|
396
|
+
continues one. The caller has checked 0 <= off <= off + len <= buf.len. */
|
|
397
|
+
uint32_t nish_crc32_update(uint32_t crc, const nish_array *buf, int32_t off, int32_t len);
|
|
351
398
|
|
|
352
399
|
/* `secureZero(bytes)` (#385): sets every byte of `bytes` to zero through
|
|
353
400
|
* `volatile` stores, out of line, so that neither `-O2` nor `-flto` can drop
|
|
@@ -477,6 +524,14 @@ int32_t nish_spawn_child(const nish_array *argv);
|
|
|
477
524
|
* copied; SIGPIPE is blocked on the calling thread for the call, a SIGPIPE the
|
|
478
525
|
* call raised is consumed, and the thread's mask is restored after it. */
|
|
479
526
|
int32_t nish_spawn_piped(const nish_array *argv, const nish_array *in, nish_array *out, nish_array *err);
|
|
527
|
+
/* `spawnWithFds(argv, fds)`: `nish_spawn_child` with the child holding
|
|
528
|
+
* `fds[i]` (element type `int32_t`) as descriptor `3 + i`, close-on-exec
|
|
529
|
+
* cleared there. More than 64 descriptors or a negative one is -EINVAL before
|
|
530
|
+
* anything starts, a source that is not open is -EBADF, and a scratch
|
|
531
|
+
* descriptor the system cannot give is -EMFILE (-EINVAL above the descriptor
|
|
532
|
+
* limit); -ENOSYS under
|
|
533
|
+
* WASI. This process's descriptors are left as they were. */
|
|
534
|
+
int32_t nish_spawn_with_fds(const nish_array *argv, const nish_array *fds);
|
|
480
535
|
/* `kill(pid, sig)`: send `sig` to `pid` and answer 0, or a negative errno. Only
|
|
481
536
|
* 0, 2 (SIGINT), 9 (SIGKILL) and 15 (SIGTERM) are sent; any other signal, and
|
|
482
537
|
* a pid of 0 or below, is -EINVAL. -ESRCH when no process has the pid, -EPERM
|
|
@@ -614,6 +669,9 @@ bool nish_is_executable(const nish_str *path);
|
|
|
614
669
|
* whitelist, by the runtime's own id (1 `TCP_NODELAY`, 2 `TCP_QUICKACK`, 3
|
|
615
670
|
* `SO_KEEPALIVE`, 4 `SO_SNDBUF`, 5 `SO_RCVBUF`); any other id is -22, and
|
|
616
671
|
* `TCP_QUICKACK` off Linux is -95.
|
|
672
|
+
* `nish_net_mss(fd)`: a connected TCP socket's send MSS, from `TCP_INFO`'s
|
|
673
|
+
* `tcpi_snd_mss` or else `TCP_MAXSEG`; a plain -1, never an errno, for
|
|
674
|
+
* anything else (a closed descriptor, an unconnected or non-TCP socket).
|
|
617
675
|
* `nish_tcp_connect(addr)`: a new socket connecting to `addr`, answered at
|
|
618
676
|
* once; its `EINPROGRESS` is not a failure, and any other closes it.
|
|
619
677
|
* `nish_connect_result(fd)`: `SO_ERROR` once the socket is writable, 0 when
|
|
@@ -638,7 +696,36 @@ bool nish_is_executable(const nish_str *path);
|
|
|
638
696
|
* into `ready` (element type `int32_t`) a token and its events, 4 added for a
|
|
639
697
|
* hang-up or an error, per ready descriptor: at most `ready->len / 2` pairs
|
|
640
698
|
* and at most 64 in one call. It answers the count, 0 on a timeout or an
|
|
641
|
-
* interrupting signal, and -22 for a `ready` shorter than 2.
|
|
699
|
+
* interrupting signal, and -22 for a `ready` shorter than 2.
|
|
700
|
+
*
|
|
701
|
+
* Unix-domain sockets. A `path` names a socket file, or with a leading `@`
|
|
702
|
+
* Linux's abstract namespace (-95 on Darwin); empty, holding a NUL, or a bare
|
|
703
|
+
* `@` is -22, and one too long for `sun_path` with its NUL is -36, before any
|
|
704
|
+
* socket exists. `nish_unix_listen(path, backlog, flags)` is a listening
|
|
705
|
+
* stream socket whose file has mode 0600; a path that exists is -98, unless
|
|
706
|
+
* flag 1 (`NET_UNIX_UNLINK_STALE`) unlinks a socket file nothing listens on
|
|
707
|
+
* (anything but a socket is -17, a live listener -98). `nish_unix_listen_mode`
|
|
708
|
+
* takes the mode (0..0o777, -22 for an abstract name). `nish_unix_connect(path)`
|
|
709
|
+
* connects, -11 for a full backlog on Linux (-111 on Darwin). `nish_unix_accept(fd)` takes the next
|
|
710
|
+
* connection, -11 when none waits. `nish_unix_socket_pair(kind, fds)` writes
|
|
711
|
+
* two connected sockets into `fds` (element type `int32_t`, at least 2): kind
|
|
712
|
+
* 1 a stream, kind 2 `SOCK_SEQPACKET` (-95 on Darwin). Every descriptor is
|
|
713
|
+
* non-blocking and close-on-exec.
|
|
714
|
+
*
|
|
715
|
+
* Descriptors over a Unix socket: each of the three refuses a descriptor that
|
|
716
|
+
* is closed with -9, one that is not a socket with -88 and a socket of another
|
|
717
|
+
* family with -95.
|
|
718
|
+
* `nish_send_fd(sock, fd, buf, off, len)` sends `len` bytes (at least 1, else
|
|
719
|
+
* -22, as is a negative `fd`) carrying one `SCM_RIGHTS` copy of `fd`; a
|
|
720
|
+
* stream socket can send short, the descriptor gone with the first bytes. `nish_recv_fd(sock, buf, off,
|
|
721
|
+
* len, fd)` reads at most `len` bytes (at least 1, and `fd` at least one
|
|
722
|
+
* `int32_t` long, else -22) and writes the first descriptor received, or -1,
|
|
723
|
+
* into `fd[0]`, closing every other; the one kept is close-on-exec and its
|
|
724
|
+
* status flags are left as the sender's. `nish_peer_credentials(fd, out)`
|
|
725
|
+
* writes the peer's pid, uid and gid as of the connect into `out` (at least
|
|
726
|
+
* 3, else -22), wrapping a uid or gid of 2^31 or above into `int32_t`; a
|
|
727
|
+
* socket with no peer is -ENOTCONN (-107) on both platforms, and Darwin's pid
|
|
728
|
+
* is -1 where `LOCAL_PEERPID` is missing. */
|
|
642
729
|
int32_t nish_net_address(nish_array *out, const nish_str *host, int32_t port);
|
|
643
730
|
int32_t nish_net_local_port(int32_t fd);
|
|
644
731
|
int32_t nish_tcp_listen(const nish_str *host, int32_t port, int32_t backlog);
|
|
@@ -649,6 +736,7 @@ int32_t nish_net_write(int32_t fd, const nish_array *buf, int64_t off, int64_t l
|
|
|
649
736
|
int32_t nish_net_shutdown(int32_t fd, int32_t how);
|
|
650
737
|
int32_t nish_net_close(int32_t fd);
|
|
651
738
|
int32_t nish_net_set_option(int32_t fd, int32_t option, int32_t value);
|
|
739
|
+
int32_t nish_net_mss(int32_t fd);
|
|
652
740
|
int32_t nish_tcp_connect(const nish_array *addr);
|
|
653
741
|
int32_t nish_connect_result(int32_t fd);
|
|
654
742
|
int32_t nish_udp_bind(const nish_str *host, int32_t port, int32_t flags);
|
|
@@ -661,6 +749,14 @@ int32_t nish_poll_add(int32_t loop, int32_t fd, int32_t events, int32_t token);
|
|
|
661
749
|
int32_t nish_poll_modify(int32_t loop, int32_t fd, int32_t events, int32_t token);
|
|
662
750
|
int32_t nish_poll_remove(int32_t loop, int32_t fd);
|
|
663
751
|
int32_t nish_poll_wait(int32_t loop, nish_array *ready, int32_t timeout_ms);
|
|
752
|
+
int32_t nish_unix_listen(const nish_str *path, int32_t backlog, int32_t flags);
|
|
753
|
+
int32_t nish_unix_listen_mode(const nish_str *path, int32_t backlog, int32_t flags, int32_t mode);
|
|
754
|
+
int32_t nish_unix_connect(const nish_str *path);
|
|
755
|
+
int32_t nish_unix_accept(int32_t fd);
|
|
756
|
+
int32_t nish_unix_socket_pair(int32_t kind, nish_array *fds);
|
|
757
|
+
int32_t nish_send_fd(int32_t sock, int32_t fd, const nish_array *buf, int64_t off, int64_t len);
|
|
758
|
+
int32_t nish_recv_fd(int32_t sock, nish_array *buf, int64_t off, int64_t len, nish_array *fd);
|
|
759
|
+
int32_t nish_peer_credentials(int32_t fd, nish_array *out);
|
|
664
760
|
|
|
665
761
|
/* ---- The terminal, runtime/runtime-term.c, `nish:term` -------------------
|
|
666
762
|
*
|
|
@@ -741,6 +837,17 @@ int64_t nish_cpu_count(void);
|
|
|
741
837
|
* rounded up, and `NISH_NUM_THREADS` when it is set to a positive number. At
|
|
742
838
|
* least 1; 1 under WASI. Read each call (runtime-os.c). */
|
|
743
839
|
int64_t nish_cpu_online(void);
|
|
840
|
+
/* WP37 `--sandbox` (runtime-sandbox.c): `nish_sandbox` confines the process to
|
|
841
|
+
the capability mask `caps` from `.preinit_array`, `mode` 1 strict and 2
|
|
842
|
+
best-effort, and `nish_sandbox_check` refuses to run at the top of `main`
|
|
843
|
+
when it never ran. `read_dirs` and `write_dirs` are the directories
|
|
844
|
+
Landlock scopes `fs.read` and `fs.write` to, `exec_paths` the programs
|
|
845
|
+
`process.spawn` may execute, each a run of NUL-terminated paths ended by an
|
|
846
|
+
empty one; null leaves the capability whole.
|
|
847
|
+
`nish_cpu_prime` caches the pool's CPU count while /sys is still readable. */
|
|
848
|
+
void nish_sandbox(int32_t caps, int32_t mode, const char *read_dirs, const char *write_dirs, const char *exec_paths);
|
|
849
|
+
void nish_sandbox_check(void);
|
|
850
|
+
void nish_cpu_prime(void);
|
|
744
851
|
void nish_parallel_range(nish_par_body body, void *ctx, int64_t len, int64_t grain);
|
|
745
852
|
/* Keeps every later region and join on threads created and joined per call,
|
|
746
853
|
* as before the pool existed, so no parked worker outlives the code it would
|
|
@@ -766,6 +873,13 @@ __attribute__((constructor)) static void nish_napi_unpooled(void) { nish_pool_di
|
|
|
766
873
|
* calling thread, so running short of threads costs speed and never an
|
|
767
874
|
* answer.
|
|
768
875
|
*
|
|
876
|
+
* `scope` points at a `ThreadScope` (std/threads.ts), whose first `int32_t` is
|
|
877
|
+
* the stack `scopeWithStack` asked for, or 0. A nonzero one runs every task on
|
|
878
|
+
* a new thread of its own started with that stack, rounded up to the page,
|
|
879
|
+
* plus a guard page, none on the calling thread; if one cannot be started the
|
|
880
|
+
* program ends, saying whether the system was out of threads or memory or
|
|
881
|
+
* refused the size (`nish_stack_fail`). Without threads the word is ignored.
|
|
882
|
+
*
|
|
769
883
|
* The preconditions are the language's (docs/LANGUAGE.md, "Scoped tasks"):
|
|
770
884
|
* `run` writes nothing another task or the caller can see, its result is a
|
|
771
885
|
* scalar it writes into its own payload, and only `finish`, on the calling
|
package/runtime/nish.mjs
CHANGED
|
@@ -104,9 +104,11 @@ provide("realpathSync", shim.realpathSync);
|
|
|
104
104
|
provide("spawnSync", shim.spawnSync);
|
|
105
105
|
provide("spawnSyncTo", shim.spawnSyncTo);
|
|
106
106
|
provide("spawnPiped", shim.spawnPiped);
|
|
107
|
-
// WP34 N12. `spawn` and `waitPid` throw, naming themselves: a
|
|
108
|
-
// by Node's event loop. `kill`, `availableParallelism` and
|
|
107
|
+
// WP34 N12. `spawn`, `spawnWithFds` and `waitPid` throw, naming themselves: a
|
|
108
|
+
// child is reaped by Node's event loop. `kill`, `availableParallelism` and
|
|
109
|
+
// `totalMemory` answer.
|
|
109
110
|
provide("spawn", shim.spawn);
|
|
111
|
+
provide("spawnWithFds", shim.spawnWithFds);
|
|
110
112
|
provide("kill", shim.kill);
|
|
111
113
|
provide("waitPid", shim.waitPid);
|
|
112
114
|
provide("availableParallelism", shim.availableParallelism);
|
|
@@ -147,16 +149,28 @@ for (const name of [
|
|
|
147
149
|
"pollRemove",
|
|
148
150
|
"pollWait",
|
|
149
151
|
"netSetOption",
|
|
152
|
+
"netMss",
|
|
153
|
+
"unixListen",
|
|
154
|
+
"unixListenMode",
|
|
155
|
+
"unixConnect",
|
|
156
|
+
"unixAccept",
|
|
157
|
+
"unixSocketPair",
|
|
158
|
+
"sendFd",
|
|
159
|
+
"recvFd",
|
|
160
|
+
"peerCredentials",
|
|
150
161
|
]) {
|
|
151
162
|
provide(name, () => shim.noNetReading(name));
|
|
152
163
|
}
|
|
153
|
-
// `netSetOption`'s option ids
|
|
154
|
-
// as natively: only
|
|
164
|
+
// `netSetOption`'s option ids and the `NET_UNIX_` flag and kinds are plain
|
|
165
|
+
// numbers, so they read the same here as natively: only a call throws.
|
|
155
166
|
provide("NET_TCP_NODELAY", 1);
|
|
156
167
|
provide("NET_TCP_QUICKACK", 2);
|
|
157
168
|
provide("NET_SO_KEEPALIVE", 3);
|
|
158
169
|
provide("NET_SO_SNDBUF", 4);
|
|
159
170
|
provide("NET_SO_RCVBUF", 5);
|
|
171
|
+
provide("NET_UNIX_UNLINK_STALE", 1);
|
|
172
|
+
provide("NET_UNIX_STREAM", 1);
|
|
173
|
+
provide("NET_UNIX_SEQPACKET", 2);
|
|
160
174
|
|
|
161
175
|
// `nish:term`. Whether a descriptor is a terminal and how big stdout's is have
|
|
162
176
|
// Node's answers; reading stdin, waiting for it and raw mode throw, each naming
|
|
@@ -314,6 +328,9 @@ provide("arena", shim.arena);
|
|
|
314
328
|
// zero-fills it. `nish:unsafe` and `nish:term` are each answered by a module
|
|
315
329
|
// that hands back the globals installed above: its functions are globals of this module either
|
|
316
330
|
// way, and the import is what the compiler requires a program to write.
|
|
331
|
+
// `nish:simd` is `runtime/core.mjs`, whose vectors are typed arrays made once
|
|
332
|
+
// and never written after, so `--emit-ts` output and a program run as it was
|
|
333
|
+
// written share one implementation.
|
|
317
334
|
const UNSAFE_EXPORTS = ["uncheckedGet", "uncheckedSet", "wrappingAdd", "wrappingSub", "wrappingMul"];
|
|
318
335
|
const unsafeSource = UNSAFE_EXPORTS.map((name) => `export const ${name} = globalThis.${name};`).join("\n");
|
|
319
336
|
const TERM_EXPORTS = ["readStdin", "waitStdin", "isTerminal", "terminalSize", "setRawMode", "setTerminalRestore"];
|
|
@@ -326,6 +343,9 @@ registerHooks({
|
|
|
326
343
|
if (specifier === "nish:unsafe") {
|
|
327
344
|
return { url: `data:text/javascript,${encodeURIComponent(unsafeSource)}`, shortCircuit: true };
|
|
328
345
|
}
|
|
346
|
+
if (specifier === "nish:simd") {
|
|
347
|
+
return next(new URL("./core.mjs", import.meta.url).href, context);
|
|
348
|
+
}
|
|
329
349
|
if (specifier === "nish:term") {
|
|
330
350
|
return { url: `data:text/javascript,${encodeURIComponent(termSource)}`, shortCircuit: true };
|
|
331
351
|
}
|