@ai-ecoverse/slicc-kernel 1.142.2 → 1.142.3
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 +3 -1
- package/dist/kernel-worker.js +1 -1
- package/dist/node-process-worker.js +1 -1
- package/dist/node.js +69 -5
- package/dist/node.js.map +3 -3
- package/dist/process-worker.js +1 -1
- package/dist/types/node.d.ts +8 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -202,10 +202,12 @@ const { status, stdout } = await kernel.run(['bash', '-c', 'echo hi'], { cwd: '/
|
|
|
202
202
|
kernel.terminate();
|
|
203
203
|
```
|
|
204
204
|
|
|
205
|
-
`createNodeKernel({ root, modules, commands, env, network, worker, facades, processMounts, fstabRetries, cdp, hostfs, hostfsOrigin, hostfsFetch, users, onDenial, approve, compileCache })` takes the options of `createKernel` except `metadata`, and `fstabRetries`, the delays in ms between tries of a failing `/etc/fstab` line (default `[1000, 4000, 16000]`). `root` is an in-memory directory by default (`memoryRoot()` makes another), which keeps each file in 1 MiB chunks, and POSIX metadata stays in memory. Processes and threads run on `worker_threads`. The kernel has `run`, `openTerminal`, `users`, `setRoutes`, `updateTransportTraits` and `terminate` as above, plus `integrity.revoke(path?)`, `root`, `writeFile(path, data, { mode }?)` (creating the parent directories; `mode` sets the permission bits, `0` to `0o7777`, before the data is written), `chmod(path, mode)` and `readFile(path)` to put files in place and read results; like the `fs` of an attached client, they go through the mounts, as the processes see them. `nodeTransport()` is `fetchTransport()` with Node's `fetch`, which no CORS binds (`crossOrigin: 'any'`). `connect({ user })` and `attachKernel` work as in the browser: the port is a `worker_threads` `MessagePort`, which a worker thread can attach with, and `terminate()` ends every attached client.
|
|
205
|
+
`createNodeKernel({ root, modules, commands, env, network, worker, facades, processMounts, fstabRetries, cdp, hostfs, hostfsOrigin, hostfsFetch, users, onDenial, approve, compileCache, warmWorker })` takes the options of `createKernel` except `metadata`, and `fstabRetries`, the delays in ms between tries of a failing `/etc/fstab` line (default `[1000, 4000, 16000]`). `root` is an in-memory directory by default (`memoryRoot()` makes another), which keeps each file in 1 MiB chunks, and POSIX metadata stays in memory. Processes and threads run on `worker_threads`. The kernel has `run`, `openTerminal`, `users`, `setRoutes`, `updateTransportTraits` and `terminate` as above, plus `integrity.revoke(path?)`, `root`, `writeFile(path, data, { mode }?)` (creating the parent directories; `mode` sets the permission bits, `0` to `0o7777`, before the data is written), `chmod(path, mode)` and `readFile(path)` to put files in place and read results; like the `fs` of an attached client, they go through the mounts, as the processes see them. `nodeTransport()` is `fetchTransport()` with Node's `fetch`, which no CORS binds (`crossOrigin: 'any'`). `connect({ user })` and `attachKernel` work as in the browser: the port is a `worker_threads` `MessagePort`, which a worker thread can attach with, and `terminate()` ends every attached client.
|
|
206
206
|
|
|
207
207
|
`compileCache` (opt-in, off by default; #1285, slicc-jsh#566) is an absolute host directory where each process worker keeps the compiled code of the JS programs it imports (`module.enableCompileCache`), so the next spawn of the same program skips V8's compile. It stores V8's code cache, keyed and checksummed by the module's source, one file per program (about 7 MB for a 2.4 MB bundle), shared by every kernel given the same directory; programs can't reach or write it (the worker hands it to Node before the lockdown, and `node:worker_threads` stays refused). Measured on a 2.4 MB bundle, a spawn went from about 54 to 39 ms; a trivial program costs about 1 ms more. **The directory must be private to the embedder:** V8's code cache is trusted bytecode that Node only checksums, so whoever can write it can plant code that runs inside a process worker past the lockdown. Never make it reachable from inside the kernel (no `hostfs` mount of it or of a parent), and don't share one between kernels of different trust. A host's own `NODE_COMPILE_CACHE` is never handed to the process workers, with or without the option, so programs never land in a host-wide cache. If a host preload (`--import` or `--require`) has already enabled another compile cache in the workers, a kernel given `compileCache` refuses to run programs there instead of caching them in the host's directory.
|
|
208
208
|
|
|
209
|
+
`warmWorker` (on by default; `false` turns it off; #1341, slicc-jsh#566) keeps one process worker booted ahead of the next spawn, fork or thread on the Node entry, so the spawn skips the worker's boot: it has loaded the process worker module and nothing else, no pid, credentials, environment, cwd, descriptors, lockdown or program, all of which arrive with its init message, and every worker still serves exactly one process or thread and is then terminated. Its own `process.env` is a snapshot taken when the spare is created rather than at the spawn, but a program never sees it (`process` is withheld, and a program's environment is the one its spawn gives it). The spare never keeps the host alive, is replaced after each spawn off the critical path, is dropped if it errors or exits while idle, and is released after 30 s without a spawn; `terminate()` ends it. It costs about 11 MB of host RSS while it waits.
|
|
210
|
+
|
|
209
211
|
By default `nodeTransport()` refuses destinations on the host itself, because Node can reach them and a page can't: local DevTools on 9222–9229, dev servers, local admin APIs, and the cloud metadata address.
|
|
210
212
|
- **What it refuses:** loopback (`127.0.0.0/8`, `::1`, and their IPv4-mapped forms), unspecified addresses (`0.0.0.0/8`, `::`), `localhost` and `*.localhost`, and link-local addresses (`169.254.0.0/16`, `fe80::/10`), plus AWS's IPv6 metadata address `fd00:ec2::254`.
|
|
211
213
|
- **How it checks:** it matches on the addresses the name resolves to, so a public name that resolves to `127.0.0.1` is refused too. It checks every request and WebSocket open, `host.slicc.internal` and each redirect hop included.
|
package/dist/kernel-worker.js
CHANGED
|
@@ -7595,7 +7595,7 @@ function satisfies(version, range2) {
|
|
|
7595
7595
|
}
|
|
7596
7596
|
|
|
7597
7597
|
// src/version.ts
|
|
7598
|
-
var KERNEL_VERSION = true ? "1.142.
|
|
7598
|
+
var KERNEL_VERSION = true ? "1.142.3" : "0.0.0-dev";
|
|
7599
7599
|
var OS_RELEASE = "6.0.0-slicc";
|
|
7600
7600
|
function procVersion() {
|
|
7601
7601
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -6725,7 +6725,7 @@ var KERNEL_VERSION, OS_RELEASE;
|
|
|
6725
6725
|
var init_version = __esm({
|
|
6726
6726
|
"src/version.ts"() {
|
|
6727
6727
|
"use strict";
|
|
6728
|
-
KERNEL_VERSION = true ? "1.142.
|
|
6728
|
+
KERNEL_VERSION = true ? "1.142.3" : "0.0.0-dev";
|
|
6729
6729
|
OS_RELEASE = "6.0.0-slicc";
|
|
6730
6730
|
}
|
|
6731
6731
|
});
|
package/dist/node.js
CHANGED
|
@@ -7979,7 +7979,7 @@ function satisfies(version, range2) {
|
|
|
7979
7979
|
}
|
|
7980
7980
|
|
|
7981
7981
|
// src/version.ts
|
|
7982
|
-
var KERNEL_VERSION = true ? "1.142.
|
|
7982
|
+
var KERNEL_VERSION = true ? "1.142.3" : "0.0.0-dev";
|
|
7983
7983
|
var OS_RELEASE = "6.0.0-slicc";
|
|
7984
7984
|
function procVersion() {
|
|
7985
7985
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -32110,7 +32110,66 @@ function nodeTransport(options = {}) {
|
|
|
32110
32110
|
}
|
|
32111
32111
|
var TERMINATED = "the kernel is terminated";
|
|
32112
32112
|
var EXIT_GRACE_MS = 50;
|
|
32113
|
-
|
|
32113
|
+
var WARM_IDLE_MS = 3e4;
|
|
32114
|
+
function warmPool(make, live, idleMs = WARM_IDLE_MS) {
|
|
32115
|
+
let spare;
|
|
32116
|
+
let idle2;
|
|
32117
|
+
let closed = false;
|
|
32118
|
+
const drop = (worker) => {
|
|
32119
|
+
if (spare !== worker) return;
|
|
32120
|
+
spare = void 0;
|
|
32121
|
+
clearTimeout(idle2);
|
|
32122
|
+
live.delete(kill);
|
|
32123
|
+
};
|
|
32124
|
+
const kill = () => {
|
|
32125
|
+
const worker = spare;
|
|
32126
|
+
if (!worker) return;
|
|
32127
|
+
drop(worker);
|
|
32128
|
+
void worker.terminate();
|
|
32129
|
+
};
|
|
32130
|
+
const fill2 = () => {
|
|
32131
|
+
if (closed || spare) return;
|
|
32132
|
+
let worker;
|
|
32133
|
+
try {
|
|
32134
|
+
worker = make();
|
|
32135
|
+
} catch {
|
|
32136
|
+
closed = true;
|
|
32137
|
+
return;
|
|
32138
|
+
}
|
|
32139
|
+
worker.unref();
|
|
32140
|
+
worker.once("error", () => drop(worker));
|
|
32141
|
+
worker.once("exit", () => drop(worker));
|
|
32142
|
+
spare = worker;
|
|
32143
|
+
live.add(kill);
|
|
32144
|
+
idle2 = setTimeout(kill, idleMs);
|
|
32145
|
+
idle2.unref?.();
|
|
32146
|
+
};
|
|
32147
|
+
return {
|
|
32148
|
+
take() {
|
|
32149
|
+
const worker = spare;
|
|
32150
|
+
if (worker) {
|
|
32151
|
+
drop(worker);
|
|
32152
|
+
worker.removeAllListeners("error");
|
|
32153
|
+
worker.removeAllListeners("exit");
|
|
32154
|
+
worker.ref();
|
|
32155
|
+
}
|
|
32156
|
+
setImmediate(fill2);
|
|
32157
|
+
return worker ?? make();
|
|
32158
|
+
},
|
|
32159
|
+
close() {
|
|
32160
|
+
closed = true;
|
|
32161
|
+
kill();
|
|
32162
|
+
}
|
|
32163
|
+
};
|
|
32164
|
+
}
|
|
32165
|
+
function processWorker(file, workerData) {
|
|
32166
|
+
return new Worker(file, { env: workerEnv(), ...workerData ? { workerData } : {} });
|
|
32167
|
+
}
|
|
32168
|
+
function warmPoolOf(options, file, workerData, live) {
|
|
32169
|
+
if (options.warmWorker === false) return void 0;
|
|
32170
|
+
return warmPool(() => processWorker(file, workerData), live);
|
|
32171
|
+
}
|
|
32172
|
+
function nodeWorker(file, live, closed, workerData, take) {
|
|
32114
32173
|
const errors = /* @__PURE__ */ new Set();
|
|
32115
32174
|
const messages = /* @__PURE__ */ new Map();
|
|
32116
32175
|
const fail3 = (message3) => {
|
|
@@ -32119,7 +32178,7 @@ function nodeWorker(file, live, closed, workerData) {
|
|
|
32119
32178
|
} });
|
|
32120
32179
|
}
|
|
32121
32180
|
};
|
|
32122
|
-
const worker = closed ? void 0 :
|
|
32181
|
+
const worker = closed ? void 0 : take?.() ?? processWorker(file, workerData);
|
|
32123
32182
|
let ending = false;
|
|
32124
32183
|
if (worker) {
|
|
32125
32184
|
const kill = () => {
|
|
@@ -32192,11 +32251,13 @@ async function createNodeKernel(options = {}) {
|
|
|
32192
32251
|
let terminated = false;
|
|
32193
32252
|
const file = options.worker ?? new URL("./node-process-worker.js", import.meta.url);
|
|
32194
32253
|
const compileCache = cacheDirOf(options.compileCache);
|
|
32254
|
+
const workerData = compileCache ? { compileCache } : void 0;
|
|
32255
|
+
const warm = warmPoolOf(options, file, workerData, live);
|
|
32195
32256
|
const transport = options.network?.transport;
|
|
32196
32257
|
const launcher = new Launcher({
|
|
32197
32258
|
fs,
|
|
32198
32259
|
unlinkOwner: pidOwner(process),
|
|
32199
|
-
createWorker: () => nodeWorker(file, live, terminated,
|
|
32260
|
+
createWorker: () => nodeWorker(file, live, terminated, workerData, warm ? () => warm.take() : void 0),
|
|
32200
32261
|
createDriverWorker: () => nodeWorker(
|
|
32201
32262
|
options.driverWorker ?? new URL("./node-driver-worker.js", import.meta.url),
|
|
32202
32263
|
live,
|
|
@@ -32329,6 +32390,7 @@ async function createNodeKernel(options = {}) {
|
|
|
32329
32390
|
},
|
|
32330
32391
|
terminate() {
|
|
32331
32392
|
terminated = true;
|
|
32393
|
+
warm?.close();
|
|
32332
32394
|
for (const client of [...clients]) client.detach();
|
|
32333
32395
|
for (const reject of [...pending]) reject(new Error(TERMINATED));
|
|
32334
32396
|
for (const kill of [...live]) kill();
|
|
@@ -32340,11 +32402,13 @@ async function createNodeKernel(options = {}) {
|
|
|
32340
32402
|
export {
|
|
32341
32403
|
KernelCallError,
|
|
32342
32404
|
KernelGoneError,
|
|
32405
|
+
WARM_IDLE_MS,
|
|
32343
32406
|
attachKernel,
|
|
32344
32407
|
createNodeKernel,
|
|
32345
32408
|
fetchTransport,
|
|
32346
32409
|
memoryRoot,
|
|
32347
32410
|
nodeTransport,
|
|
32348
|
-
serveHostfsPort
|
|
32411
|
+
serveHostfsPort,
|
|
32412
|
+
warmPool
|
|
32349
32413
|
};
|
|
32350
32414
|
//# sourceMappingURL=node.js.map
|