@ai-ecoverse/slicc-kernel 1.26.0 → 1.26.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/README.md +2 -2
- package/dist/kernel-worker.js +18 -4
- package/dist/kernel-worker.js.map +2 -2
- package/dist/node-process-worker.js +2 -1
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +18 -4
- package/dist/node.js.map +2 -2
- package/dist/process-worker.js +2 -1
- package/dist/process-worker.js.map +2 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -144,7 +144,7 @@ A WASI program runs in a process worker of its own like an Emscripten one, again
|
|
|
144
144
|
|
|
145
145
|
- **Threads**: `wasi.thread-spawn` (wasm32-wasip1-threads) and WASIX `thread_spawn_v2` start a worker per thread on the process's shared memory, sized from the module's own import (a 2 GiB maximum when the engine cannot reserve more). The threads share one descriptor table; `exit` or a trap in any thread ends the process. At most 64 threads per process; `SLICC_WASM_THREADS` sets another cap, up to 256.
|
|
146
146
|
- **WASIX** (a module importing `wasix_32v1`): fork and setjmp/longjmp through Asyncify (the module is built with `wasm-opt --asyncify`), exec, `posix_spawn`, `waitpid`, pipes, `dup2`, signal handlers and interval timers, terminal modes, and dynamic linking: a position-independent main module loads side modules with `dlopen` from `LD_LIBRARY_PATH`, its runtime path, `/lib`, `/usr/lib` and `/usr/local/lib`.
|
|
147
|
-
- **Sockets**: the WASIX socket calls (`sock_open`, `bind`, `listen`, `connect`, `accept`, options, local and peer names) are the kernel's loopback sockets, and preview1's `sock_recv` / `sock_send` / `sock_shutdown` work on them and on inherited ones. HTTP and HTTPS leave through the realm proxy that `https_proxy` names, as for any other program; `resolve` answers loopback names and literal addresses.
|
|
147
|
+
- **Sockets**: the WASIX socket calls (`sock_open`, `bind`, `listen`, `connect`, `accept`, options, local and peer names) are the kernel's loopback sockets, and preview1's `sock_recv` / `sock_send` / `sock_shutdown` work on them and on inherited ones. Writing to a socket whose peer is gone fails with `EPIPE`, through `fd_write` as through `sock_send`, as if `MSG_NOSIGNAL` were set, since a WASI program cannot ignore `SIGPIPE`; a pipe or terminal whose reader is gone still ends the program with status 141. HTTP and HTTPS leave through the realm proxy that `https_proxy` names, as for any other program; `resolve` answers loopback names and literal addresses.
|
|
148
148
|
- **Diagnostics**: a trap ends the program with 134 and its message on stderr; with `SLICC_WASM_BACKTRACE=1` the wasm frames follow, named from the module's name section, or from a sidecar for a module shipped without one (`<module>.names` beside it, or the same path in a `<package>-names` package). `SLICC_WASI_STATS=1` makes a program print its calls, counted and timed, as it ends.
|
|
149
149
|
|
|
150
150
|
### Program imports
|
|
@@ -184,7 +184,7 @@ await kernel.run(['curl', '-sS', 'https://registry.npmjs.org/@ai-ecoverse/wasm-b
|
|
|
184
184
|
Programs drive a browser with the Chrome DevTools Protocol over a WebSocket, whichever host actually has the browser: slicc-extension's `chrome.debugger`, slicc-node's or slicc-swift's CDP proxy, or a test harness. The kernel relays; it does not launch a browser.
|
|
185
185
|
|
|
186
186
|
- **Programs** find the endpoint in `SLICC_CDP_URL`, `ws://127.0.0.1:9222/devtools/browser/<id>`, where `<id>` is random for each kernel boot. `http://127.0.0.1:9222/json/version` answers `{ "Browser", "Protocol-Version", "webSocketDebuggerUrl" }` with the same URL (carrying the request's query), and `/json/list` (or `/json`) lists the host's targets, without per-target sockets. Every other path is `404`. The listener starts on the first connection, on the kernel's loopback; a program that binds `9222` first keeps it.
|
|
187
|
-
- **Sessions** are Chrome's flattened ones: `Target.attachToTarget` with `flatten: true`, then commands with a top-level `sessionId`. Messages pass unchanged, as text frames up to 256 MiB (a larger one closes the socket with `1009`). Each program WebSocket gets a host connection of its own: closing the socket (or exiting) closes it, which detaches its sessions, and a host that closes is passed on as a close frame (`1011` with its reason). `terminate()` closes them all.
|
|
187
|
+
- **Sessions** are Chrome's flattened ones: `Target.attachToTarget` with `flatten: true`, then commands with a top-level `sessionId`. Messages pass unchanged, as text frames up to 256 MiB (a larger one closes the socket with `1009`). Each program WebSocket gets a host connection of its own: closing the socket (or exiting) closes it, which detaches its sessions, and a host that closes is passed on as a close frame (`1011` with its reason). The kernel then waits up to a second for the program's close frame before it hangs up, as RFC 6455 has it, so a program that answers the close can still report the code. `terminate()` closes them all.
|
|
188
188
|
- **Runtime**: a program adds `runtime=<name>` to the query of the URL it opens, and the kernel gives it to the host; the kernel does not interpret it.
|
|
189
189
|
- **No host**: `/json/*` and the WebSocket handshake answer `503` with `slicc-kernel: no CDP host is attached (createKernel({ cdp }) or client.serveCdp)`, and a host that refuses (an unknown runtime, say) gives `502` with its message.
|
|
190
190
|
- **Kernel-only**: port `9222` takes connections only from programs in the kernel. `kernel.dial`, a client's `dial` and `loopbackFetch` (and so `9222.kernel.localhost` and slicc-node's tunnel) are refused with `ECONNREFUSED`, since the facade drives the user's real browser.
|
package/dist/kernel-worker.js
CHANGED
|
@@ -3749,6 +3749,7 @@ Sec-WebSocket-Accept: ${accept2}\r
|
|
|
3749
3749
|
// src/cdp/facade.ts
|
|
3750
3750
|
var MAX_HEAD = 64 * 1024;
|
|
3751
3751
|
var LIST_TIMEOUT = 1e4;
|
|
3752
|
+
var CLOSE_WAIT_MS = 1e3;
|
|
3752
3753
|
function respond(status, body, type = "text/plain; charset=utf-8") {
|
|
3753
3754
|
const bytes = new TextEncoder().encode(body);
|
|
3754
3755
|
const head = latin1Bytes(
|
|
@@ -3894,7 +3895,11 @@ var CdpFacade = class {
|
|
|
3894
3895
|
async upgrade(conn, incoming, req, runtime) {
|
|
3895
3896
|
const accept2 = await acceptKey(req.headers);
|
|
3896
3897
|
const host = await this.host(runtime);
|
|
3897
|
-
|
|
3898
|
+
const limits = {
|
|
3899
|
+
max: this.options.maxMessage ?? MAX_MESSAGE,
|
|
3900
|
+
closeWaitMs: this.options.closeWaitMs ?? CLOSE_WAIT_MS
|
|
3901
|
+
};
|
|
3902
|
+
await new Relay(conn, incoming, host, limits, this.stop.signal).start(switchingHead(accept2)).finally(() => host.close());
|
|
3898
3903
|
}
|
|
3899
3904
|
};
|
|
3900
3905
|
var Relay = class {
|
|
@@ -3904,12 +3909,14 @@ var Relay = class {
|
|
|
3904
3909
|
incoming;
|
|
3905
3910
|
host;
|
|
3906
3911
|
max;
|
|
3912
|
+
closeWaitMs;
|
|
3907
3913
|
stop;
|
|
3908
|
-
constructor(conn, incoming, host,
|
|
3914
|
+
constructor(conn, incoming, host, limits, stop) {
|
|
3909
3915
|
this.conn = conn;
|
|
3910
3916
|
this.incoming = incoming;
|
|
3911
3917
|
this.host = host;
|
|
3912
|
-
this.max = max;
|
|
3918
|
+
this.max = limits.max;
|
|
3919
|
+
this.closeWaitMs = limits.closeWaitMs;
|
|
3913
3920
|
this.stop = stop;
|
|
3914
3921
|
}
|
|
3915
3922
|
send(bytes) {
|
|
@@ -3935,8 +3942,15 @@ var Relay = class {
|
|
|
3935
3942
|
void this.end(CLOSE.tooBig, `a message is over ${this.max} bytes`);
|
|
3936
3943
|
else void this.send(frame(OP_TEXT, bytes));
|
|
3937
3944
|
};
|
|
3938
|
-
|
|
3945
|
+
const pumping = this.pump();
|
|
3946
|
+
await Promise.race([pumping, hostGone]);
|
|
3939
3947
|
await this.writes;
|
|
3948
|
+
let timer;
|
|
3949
|
+
const waited = new Promise((resolve) => {
|
|
3950
|
+
timer = setTimeout(resolve, this.closeWaitMs);
|
|
3951
|
+
});
|
|
3952
|
+
await Promise.race([pumping, waited]);
|
|
3953
|
+
clearTimeout(timer);
|
|
3940
3954
|
}
|
|
3941
3955
|
async pump() {
|
|
3942
3956
|
const reader = new WsReader(this.incoming, this.max);
|