@ai-ecoverse/slicc-kernel 1.163.1 → 1.164.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 +5 -1
- package/dist/kernel-worker.js +9 -2
- package/dist/kernel-worker.js.map +2 -2
- package/dist/node-driver-worker.js +40 -3
- package/dist/node-driver-worker.js.map +3 -3
- package/dist/node-process-worker.js +86 -20
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +9 -2
- package/dist/node.js.map +2 -2
- package/dist/process-worker.js +5 -2
- package/dist/process-worker.js.map +2 -2
- package/dist/types/kernel/socket.d.ts +1 -0
- package/dist/types/process/js/js-context.d.ts +7 -0
- package/dist/types/process/js/js-sync.d.ts +6 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -427,6 +427,10 @@ The module's default export (or its `main` export) is called with a context and
|
|
|
427
427
|
- **What `fn` gets:** a fresh array of V8 CallSites holding only the program's own frames (its modules, `data:` imports, `sync.runScript` scripts and code they `eval`), `node:` frames and native frames. Kernel frames are dropped by script identity, so a script named like a kernel file doesn't let them through, and so are host files. A program's strict frames give `getFunction()` and `getThis()` as `undefined`.
|
|
428
428
|
- **Fallback:** if `fn` throws or returns a non-string, or an error is formatted while `fn` runs, the default stack is used.
|
|
429
429
|
- **How it works:** process workers start with `--expose-internals`, so the worker can install the formatter before the lockdown. Host flags a worker refuses are dropped. If the worker still can't start with the flag, the method is absent. Every `internal/*` and `node:internal/*` module stays refused to programs, as do `node:module` and `node:worker_threads`.
|
|
430
|
+
- `sync.errorSource(error)` (#1610, slicc-jsh#1082) is Node only, so check it with `typeof ctx.sync.errorSource === 'function'`. It gives `{ sourceLine, lineNumber, startColumn }` (null-prototype and frozen), the source line Node prints over an uncaught error, for an error V8 raised in the program's own code. That includes a direct `eval` of a value that isn't a string literal (`const s = 'null.d'; eval(s)` gives `null.d` and line 1) and a `sync.runScript` script.
|
|
431
|
+
- **Only the program's own code:** it answers only when the error's top frame is a program frame and the position V8 kept is in that same script and line.
|
|
432
|
+
- **`undefined` cases:** kernel-made errors; values that aren't native errors; an error V8 kept no position for (a `new Error()` the program constructs); a script that borrows the kernel worker's name; and an error an own `Error.prepareStackTrace` formats.
|
|
433
|
+
- **How it works:** it reads V8's message through Node's internal errors binding, which the worker loads at start-up through the same `--expose-internals` as `setStackFormatter`. It prints no warning and needs no inspector.
|
|
430
434
|
- **Kernel frames in a program's stacks** (#1583): on the Node entry, the process worker's bundle names itself `slicc-kernel:/node-process-worker.js` (a `sourceURL`), so the kernel's own frames in an error a program sees (its own errors, a failed `ctx` call, `runScript`) show that name and not the host directory the kernel is installed in. The same holds in `CallSite.toString()` and `getScriptNameOrSourceURL()`, which a program's own `Error.prepareStackTrace` gets; `getFileName()` still returns the bundle's file URL. Line and column numbers are unchanged, so they still point into `dist/node-process-worker.js`. Don't run an embedder with `--enable-source-maps` if program-visible paths matter: Node then maps the kernel's frames back to the absolute paths of its sources. In a browser the frames keep the bundle's URL, because Chrome ignores `sourceURL` in a module worker loaded by URL.
|
|
431
435
|
- `module` (#1598, slicc-jsh#566) is a frozen `{ path }` with the command module's own path in the kernel's file system (e.g. `/usr/lib/node_modules/jsh/dist/jsh.mjs`), so a program can read its package's other files through `ctx.fs` on first use. It's the path the kernel found the package under, with symlinks left as they are (a pnpm-style `node_modules/<name>` link stays in it), and reads the same files through `ctx.fs`. It's a kernel path, never a host one, and a thread gets the same. It's absent for the kernel's built-in programs (`sudo`, `crontab`) and for a program run from inline source with no file.
|
|
432
436
|
- `memory()`, synchronous and without a kernel call, measures the calling isolate: each `thread` answers for its own (#1240, slicc-jsh#397). It returns a fresh plain object of numbers in bytes, each field only where it's measured: `heapUsed`, `heapTotal`, `heapLimit` (V8's heap size limit), `external`, `arrayBuffers` and `rss`. On the Node entry they come from V8's heap statistics and Node's memory usage, through functions the worker captured before its lockdown, so nothing reachable from the program leads back to `process` or `v8`. `rss` is the host process's resident set size, as a Node worker thread reports it in `process.memoryUsage().rss`: it isn't per process, but shared by every process and thread of the kernel, and by any other kernel in that host process (#1563, slicc-jsh#539). In a browser `memory()` answers `{}` for now, with no `rss`.
|
|
@@ -534,7 +538,7 @@ The module's default export (or its `main` export) is called with a context and
|
|
|
534
538
|
- A connection's `tls` is `{ path: 'kernel', protocol, cipher ({ name, standardName, version }, as a client's; [#1500](https://github.com/ai-ecoverse/slicc-kernel/issues/1500)), alpnProtocol, servername (the SNI the client sent, or ''), authorized (whether a client certificate verified), authorizationError?, peerCertificates (the client's chain) }`.
|
|
535
539
|
- On a `listen({ tls })` listener, the kernel handshakes accepted connections concurrently, from the first `accept` on, and `accept` (and `for await`) yields each as its handshake finishes, so a client that connects and stays silent doesn't hold up the next. It holds at most `backlog` (up to 64) connections in a handshake or handshaken but not yet taken; beyond that it stops accepting, leaving the rest in the kernel's backlog, until one finishes or is taken. A connection whose handshake fails is closed and never yielded. `secure()` rejects instead.
|
|
536
540
|
- `handshakeTimeout` (milliseconds, 120000 by default, as Node's) ends a handshake that hasn't finished with `ERR_TLS_HANDSHAKE_TIMEOUT`. A listener closes that connection. After `secure()` rejects, the connection stays open and is the program's to answer or close, as with Node's `tlsClientError` ([#1504](https://github.com/ai-ecoverse/slicc-kernel/issues/1504)).
|
|
537
|
-
- A client that sends a plain HTTP request instead of a ClientHello fails the handshake with `ERR_SSL_HTTP_REQUEST`, as in Node. A client that resets during the handshake fails it with `ECONNRESET` and `read ECONNRESET`, as Node's server reports it, and one that closes with `ECONNRESET` and `the client closed the connection during the TLS handshake` ([#1578](https://github.com/ai-ecoverse/slicc-kernel/issues/1578)). A loopback TLS client whose server resets before
|
|
541
|
+
- A client that sends a plain HTTP request instead of a ClientHello fails the handshake with `ERR_SSL_HTTP_REQUEST`, as in Node. A client that resets during the handshake fails it with `ECONNRESET` and `read ECONNRESET`, as Node's server reports it, and one that closes with `ECONNRESET` and `the client closed the connection during the TLS handshake` ([#1578](https://github.com/ai-ecoverse/slicc-kernel/issues/1578)). A loopback TLS client whose server resets before its ClientHello goes out fails with `ECONNRESET` and `connect ECONNRESET <host>:<port>` (only while nothing has been read from the server), and one reset on or after its ClientHello with `read ECONNRESET`, as Node 22 tells them apart, not `EPIPE` ([#1611](https://github.com/ai-ecoverse/slicc-kernel/issues/1611), [#1624](https://github.com/ai-ecoverse/slicc-kernel/issues/1624)). A handshake, server or loopback client, waits without holding the program's other calls, and an aborted `accept({ signal })` or `connect({ signal })` ends it. A signal delivered to the program doesn't interrupt a handshake, as with `SA_RESTART`.
|
|
538
542
|
- **Choosing per connection** ([#1501](https://github.com/ai-ecoverse/slicc-kernel/issues/1501), [#1502](https://github.com/ai-ecoverse/slicc-kernel/issues/1502), tls-engine 4.2.0-9's `TLS_SERVER_SELECT`), for Node's `SNICallback`, `addContext` and `ALPNCallback`: `tls.select({ servername, protocols })` on `listen` or `secure` is called once the client's ClientHello is in, with the SNI (or `''`) and the protocols the client offers. It returns (or resolves with) `{ context, alpn }` or `{ refuse }`:
|
|
539
543
|
- `context` is a certificate from `net.tlsContext({ cert, key, passphrase })` (or its `fd`); without it the listener's own `cert` serves, and with `select` that one is optional. `alpn` is one of `protocols`, or none; another is `EINVAL` and refuses the handshake. `select` and a fixed `alpn` list together are `EINVAL` (`ERR_TLS_ALPN_CALLBACK_WITH_PROTOCOLS`), as in Node.
|
|
540
544
|
- `refuse` sends a fatal alert and ends the handshake: `'unrecognized_name'` (112), `'no_application_protocol'` (120), `'handshake_failure'` (40), `'access_denied'` (49) or `'internal_error'` (80), or the number. A `select` that throws refuses with 40, and one that doesn't answer within `handshakeTimeout` times the handshake out. On a listener the connection is dropped and the listener keeps accepting; `secure()` rejects with the error.
|
package/dist/kernel-worker.js
CHANGED
|
@@ -6458,6 +6458,10 @@ var KernelSocket = class _KernelSocket {
|
|
|
6458
6458
|
if (bytes.length === 0 && this.reset) throw this.reset;
|
|
6459
6459
|
return bytes;
|
|
6460
6460
|
}
|
|
6461
|
+
connectReset() {
|
|
6462
|
+
const at = this.peer?.family === "inet" ? ` ${this.peer.host}:${this.peer.port}` : "";
|
|
6463
|
+
return `connect ECONNRESET${at}`;
|
|
6464
|
+
}
|
|
6461
6465
|
drained(rx) {
|
|
6462
6466
|
if (this.refused && rx.buffered === 0) throw this.refused;
|
|
6463
6467
|
}
|
|
@@ -6641,6 +6645,7 @@ var KernelSocket = class _KernelSocket {
|
|
|
6641
6645
|
signal.throwIfAborted();
|
|
6642
6646
|
this.served = true;
|
|
6643
6647
|
let handshaking = true;
|
|
6648
|
+
let heard = false;
|
|
6644
6649
|
const view2 = {
|
|
6645
6650
|
localAddr: "",
|
|
6646
6651
|
remoteAddr: "",
|
|
@@ -6648,10 +6653,12 @@ var KernelSocket = class _KernelSocket {
|
|
|
6648
6653
|
const bytes = await raw2.rx.read(SERVE_CHUNK, handshaking ? signal : void 0).catch(() => EMPTY);
|
|
6649
6654
|
if (bytes.length === 0 && this.refused)
|
|
6650
6655
|
throw new KernelError("ECONNRESET", "read ECONNRESET");
|
|
6656
|
+
heard ||= bytes.length > 0;
|
|
6651
6657
|
return bytes.length > 0 ? bytes : null;
|
|
6652
6658
|
},
|
|
6653
6659
|
write: (bytes) => raw2.tx.write(bytes).catch((err) => {
|
|
6654
|
-
|
|
6660
|
+
if (!this.refused) throw err;
|
|
6661
|
+
throw new KernelError("ECONNRESET", heard ? "read ECONNRESET" : this.connectReset());
|
|
6655
6662
|
}),
|
|
6656
6663
|
closeWrite: () => raw2.tx.closeWrite(),
|
|
6657
6664
|
close: () => {
|
|
@@ -8437,7 +8444,7 @@ function satisfies(version, range2) {
|
|
|
8437
8444
|
}
|
|
8438
8445
|
|
|
8439
8446
|
// src/version.ts
|
|
8440
|
-
var KERNEL_VERSION = true ? "1.
|
|
8447
|
+
var KERNEL_VERSION = true ? "1.164.1" : "0.0.0-dev";
|
|
8441
8448
|
var OS_RELEASE = "6.0.0-slicc";
|
|
8442
8449
|
function procVersion() {
|
|
8443
8450
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|