@ai-ecoverse/slicc-kernel 1.146.6 → 1.147.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/README.md +2 -0
- package/dist/kernel-worker.js +66 -10
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node-process-worker.js +1 -1
- package/dist/node.js +66 -10
- package/dist/node.js.map +3 -3
- package/dist/process-worker.js +1 -1
- package/dist/types/fs/opfs.d.ts +1 -0
- package/dist/types/launcher.d.ts +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -239,6 +239,8 @@ A command's name is any single path component without whitespace or control char
|
|
|
239
239
|
|
|
240
240
|
**Variants by environment** ([homescoop#357](https://github.com/ai-ecoverse/homescoop/issues/357)): one package can carry more than one build of a wasm command and choose between them by the environment. `"variants": [{ "env": { "PYTHON_FORK": "true" }, "wasm": "bin/python-fork.wasm" }]` on a command entry (Emscripten or WASI) is matched in order against the environment the new process gets, at spawn and at exec. Every key must equal its value exactly, and the first match runs its `wasm`; no match runs the command's own `wasm`. This holds however the kernel reaches the entry: by name, by its path (`/usr/bin/python3`, as `sys.executable` gives it to `subprocess` and `multiprocessing`), or through a symlink to that path (a venv's `bin/python`). So `PYTHON_FORK=true python3`, `PYTHON_FORK=true exec /usr/bin/python3` and a child that inherits `PYTHON_FORK=true` all get the variant, and `PYTHON_FORK=1` doesn't. Commands of one package that share a build (`python`, `python3`, `pip`, `pip3`) each carry the same `variants`. A variant replaces only the module: the `abi`, the glue, `env`, `argv0`, `argv0Path` and the `/usr/bin` entry stay the command's. For an Emscripten command that means a variant swaps only the `.wasm` and keeps the command's JS glue, so it must be built against that same glue; a WASI or WASIX command has no glue, so there's no such constraint. Only the chosen module is read, checked and compiled, and compiled modules are cached by its path. A read or `stat` of `/usr/bin/<name>` still shows the default `wasm`. A `variants` that isn't an array, or has an entry without an `env` object of strings and a `wasm` inside the package, is ignored as a whole, with one warning per command, and the command runs its `wasm`. An older kernel ignores the field.
|
|
241
241
|
|
|
242
|
+
**A pnpm bin of a kernel command** ([#1453](https://github.com/ai-ecoverse/slicc-kernel/issues/1453)): a `#!/usr/bin/env node` (or `#!/usr/bin/node`) script run by its path, whose package lists the same name in `slicc.commands`, runs that kernel command, even when a `node` command exists. This is the bin shim `pnpm add -g` writes into `$PNPM_HOME/bin`, which names its target in a `// pnpm-wasm-shim={"target":…}` line; a script without that line is run as a script, so a same-named file in a package that differs from its glue still doesn't run as the command (#899). The shim's target, with its links resolved, must lie in a package installed directly under one of the command roots, and the name must be the catalog's command from that same package, so a shim only ever runs a command the caller could run by name, with the same checks; with `integrity` on, the shim itself is verified as a source. So `pnpm add -g <pkg> && <cmd>` works in one line.
|
|
243
|
+
|
|
242
244
|
A package can also name a command that runs files by their suffix, as `binfmt_misc` does: `"slicc": { "binfmt": { ".jsh": "jsh" } }`. Executing a file that has no `#!` line and is not a wasm module, whose name ends in a mapped suffix, runs that command with the file's path as invoked and the arguments after it, as a `#!` line naming the command would; a `#!` line still wins. The longest matching suffix wins, the whole name is never a suffix (`.jsh` alone is not one), and of two packages that map one suffix, the one whose name sorts first wins, as for commands; the kernel warns once (`console.warn`) when another package maps that suffix to a different command. A suffix starts with a dot and the command must be a name the catalog resolves when the file runs.
|
|
243
245
|
|
|
244
246
|
### WASI programs
|
package/dist/kernel-worker.js
CHANGED
|
@@ -3221,13 +3221,7 @@ var OpfsFs = class {
|
|
|
3221
3221
|
}
|
|
3222
3222
|
}
|
|
3223
3223
|
async place(handle, dir, name2, copies) {
|
|
3224
|
-
|
|
3225
|
-
if (move) this.others++;
|
|
3226
|
-
const moved2 = await move?.call(handle, dir, name2).then(
|
|
3227
|
-
() => true,
|
|
3228
|
-
() => false
|
|
3229
|
-
);
|
|
3230
|
-
if (moved2) return true;
|
|
3224
|
+
if (await this.moved(handle, dir, name2)) return true;
|
|
3231
3225
|
const before = this.fileMoves;
|
|
3232
3226
|
try {
|
|
3233
3227
|
await this.copy(handle, dir, name2, copies);
|
|
@@ -3240,6 +3234,23 @@ var OpfsFs = class {
|
|
|
3240
3234
|
return false;
|
|
3241
3235
|
}
|
|
3242
3236
|
fileMoves = 0;
|
|
3237
|
+
async moved(handle, dir, name2) {
|
|
3238
|
+
const move = handle.move;
|
|
3239
|
+
if (!move) return false;
|
|
3240
|
+
for (let attempt = 0; ; attempt++) {
|
|
3241
|
+
this.others++;
|
|
3242
|
+
const failed3 = await move.call(handle, dir, name2).then(
|
|
3243
|
+
() => void 0,
|
|
3244
|
+
(err) => ({ err })
|
|
3245
|
+
);
|
|
3246
|
+
if (!failed3) return true;
|
|
3247
|
+
const error = failed3.err?.name;
|
|
3248
|
+
if (handle.kind !== "file" || !LOCKED.has(error)) return false;
|
|
3249
|
+
const delay = SYNC_BACKOFF_MS[attempt];
|
|
3250
|
+
if (delay === void 0) throw fsError("EBUSY", name2);
|
|
3251
|
+
await new Promise((resolve2) => setTimeout(resolve2, delay));
|
|
3252
|
+
}
|
|
3253
|
+
}
|
|
3243
3254
|
async copy(handle, dir, name2, copies, rest2 = "") {
|
|
3244
3255
|
if (handle.kind === "file" && movable(handle)) {
|
|
3245
3256
|
this.others++;
|
|
@@ -7774,7 +7785,7 @@ function satisfies(version, range2) {
|
|
|
7774
7785
|
}
|
|
7775
7786
|
|
|
7776
7787
|
// src/version.ts
|
|
7777
|
-
var KERNEL_VERSION = true ? "1.
|
|
7788
|
+
var KERNEL_VERSION = true ? "1.147.0" : "0.0.0-dev";
|
|
7778
7789
|
var OS_RELEASE = "6.0.0-slicc";
|
|
7779
7790
|
function procVersion() {
|
|
7780
7791
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -28848,6 +28859,8 @@ function linksOf2(req) {
|
|
|
28848
28859
|
return req.links === void 0 ? {} : { links: req.links };
|
|
28849
28860
|
}
|
|
28850
28861
|
var COMMAND2 = /^\/(?:usr\/)?bin\/([^/]+)$/;
|
|
28862
|
+
var SHIM_MARKER = /^\/\/ pnpm-wasm-shim=(\{.*\})$/gm;
|
|
28863
|
+
var SHIM_MAX = 64 * 1024;
|
|
28851
28864
|
var PACKAGE_ROOT = /^(.*\/node_modules\/(?:@[^/]+\/)?[^/]+)\//;
|
|
28852
28865
|
var ENV_REFERENCE = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
28853
28866
|
var WASM_MAGIC = [0, 97, 115, 109];
|
|
@@ -29539,7 +29552,10 @@ var Launcher = class {
|
|
|
29539
29552
|
return { abi: "emscripten", glue, wasm, argv0: baseName2(argv0 || file), ...asked };
|
|
29540
29553
|
}
|
|
29541
29554
|
const owner = await this.glueOwner(glue, baseName2(file), scope);
|
|
29542
|
-
if (!owner)
|
|
29555
|
+
if (!owner) {
|
|
29556
|
+
const shim = await this.shimOwner(glue, baseName2(file), scope);
|
|
29557
|
+
return shim && { ...targetOf(shim), ...asked, shim: glue };
|
|
29558
|
+
}
|
|
29543
29559
|
return { ...targetOf(owner), ...asked, ...owner.glue === glue ? {} : { copy: glue } };
|
|
29544
29560
|
}
|
|
29545
29561
|
async ownOrRefused(path, name2, scope) {
|
|
@@ -29575,6 +29591,43 @@ var Launcher = class {
|
|
|
29575
29591
|
}
|
|
29576
29592
|
return void 0;
|
|
29577
29593
|
}
|
|
29594
|
+
async shimOwner(script, name2, scope) {
|
|
29595
|
+
const command = (await this.commands(scope)).get(name2);
|
|
29596
|
+
if (!command || command.script || command.origin?.script) return void 0;
|
|
29597
|
+
const target = await this.shimTarget(script);
|
|
29598
|
+
if (target === void 0) return void 0;
|
|
29599
|
+
const pkg = await this.installedPackage(await physicalPathAsync(this.base, target), scope);
|
|
29600
|
+
if (!pkg) return void 0;
|
|
29601
|
+
const glue = command.origin?.glue ?? command.glue;
|
|
29602
|
+
const own = await physicalPathAsync(this.base, glue).catch(() => void 0);
|
|
29603
|
+
return own?.startsWith(`${pkg}/`) ? command : void 0;
|
|
29604
|
+
}
|
|
29605
|
+
async shimTarget(script) {
|
|
29606
|
+
const st = await this.base.stat(script).catch(() => void 0);
|
|
29607
|
+
if (!st?.isFile || st.size > SHIM_MAX) return void 0;
|
|
29608
|
+
const text = await this.base.readFile(script).catch(() => "");
|
|
29609
|
+
const marker = [...text.matchAll(SHIM_MARKER)].at(-1)?.[1];
|
|
29610
|
+
if (marker === void 0) return void 0;
|
|
29611
|
+
let target;
|
|
29612
|
+
try {
|
|
29613
|
+
target = JSON.parse(marker).target;
|
|
29614
|
+
} catch {
|
|
29615
|
+
return void 0;
|
|
29616
|
+
}
|
|
29617
|
+
if (typeof target !== "string" || target === "") return void 0;
|
|
29618
|
+
const dir = await physicalPathAsync(this.base, script.slice(0, script.lastIndexOf("/")) || "/");
|
|
29619
|
+
return this.fs.resolvePath(dir, target);
|
|
29620
|
+
}
|
|
29621
|
+
async installedPackage(real, scope) {
|
|
29622
|
+
for (const root of await this.roots(scope)) {
|
|
29623
|
+
const top = await physicalPathAsync(this.base, root).catch(() => void 0);
|
|
29624
|
+
if (!top || !real.startsWith(`${top}/`)) continue;
|
|
29625
|
+
const [first = "", second] = real.slice(top.length + 1).split("/");
|
|
29626
|
+
const pkg = first.startsWith("@") && second ? `${top}/${first}/${second}` : `${top}/${first}`;
|
|
29627
|
+
if (pkg !== real && await this.base.exists(`${pkg}/package.json`)) return pkg;
|
|
29628
|
+
}
|
|
29629
|
+
return void 0;
|
|
29630
|
+
}
|
|
29578
29631
|
async glueOwner(glue, name2, scope) {
|
|
29579
29632
|
const commands = [...(await this.commands(scope)).values()];
|
|
29580
29633
|
const owners = commands.filter((c) => c.abi === "emscripten" && !c.script && c.glue === glue);
|
|
@@ -29670,7 +29723,10 @@ var Launcher = class {
|
|
|
29670
29723
|
const found = await this.resolve(file, argv[0] ?? file, cwd, scope);
|
|
29671
29724
|
const named = typeof argv0 === "string" && found && !found.fixed;
|
|
29672
29725
|
const direct = named ? { ...found, argv0 } : found;
|
|
29673
|
-
if (direct)
|
|
29726
|
+
if (direct) {
|
|
29727
|
+
const shim = direct.shim ? { sources: [direct.shim], asked: direct.asked ? { [direct.shim]: direct.asked } : {} } : {};
|
|
29728
|
+
return { target: direct, args: [...direct.prefix ?? [], ...argv.slice(1)], ...shim };
|
|
29729
|
+
}
|
|
29674
29730
|
if (catalogOnly && !await this.scriptCommand(file, cwd, scope)) return void 0;
|
|
29675
29731
|
const script = await this.interpreted(file, argv, cwd, scope);
|
|
29676
29732
|
return script && { ...script, script: true };
|