@ai-ecoverse/slicc-kernel 1.8.0 → 1.8.2
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 +111 -2
- package/dist/kernel-worker.js.map +2 -2
- package/dist/node-process-worker.js +45 -10
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +111 -2
- package/dist/node.js.map +2 -2
- package/dist/process-worker.js +45 -10
- package/dist/process-worker.js.map +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -109,7 +109,7 @@ A WASI program runs in a process worker of its own like an Emscripten one, again
|
|
|
109
109
|
|
|
110
110
|
### Program imports
|
|
111
111
|
|
|
112
|
-
A WASI command can name an ES module of its package that provides imports of its own, for host functions a program needs beyond WASI (`"imports": "host/pnpm-host.mjs"`). Each worker of the process (the process and every thread) loads it, with the same trust as Emscripten glue, and calls its `createImports(ctx)`, which returns import namespaces (`{ pnpm_host: { … } }`). It may not define `wasi_snapshot_preview1`, `wasix_32v1`, `wasi` or `env`; any other namespace the module imports is then accepted, and functions it does not provide answer `ENOSYS`. A WASI program (one that imports `wasi_snapshot_preview1` or `wasix_32v1`) needs no imports module for that: without one, its function imports from namespaces of its own all answer `ENOSYS`, so the same binary runs the commands that need no host functions anywhere. A module with no WASI imports, or a foreign import that is not a function, is still refused (126). `ctx` has:
|
|
112
|
+
A WASI command can name an ES module of its package that provides imports of its own, for host functions a program needs beyond WASI (`"imports": "host/pnpm-host.mjs"`). Each worker of the process (the process and every thread) loads it, with the same trust as Emscripten glue, and calls its `createImports(ctx)`, which returns import namespaces (`{ pnpm_host: { … } }`). It may not define `wasi_snapshot_preview1`, `wasix_32v1`, `wasi` or `env`; any other namespace the module imports is then accepted, and functions it does not provide answer `ENOSYS`. A WASI program (one that imports `wasi_snapshot_preview1` or `wasix_32v1`) needs no imports module for that: without one, its function imports from namespaces of its own all answer `ENOSYS`, so the same binary runs the commands that need no host functions anywhere. A stub answers in the import's own result type: 52 for `i32`, `f32` and `f64`, `52n` for `i64`, and nothing for a function without a result. An import whose result cannot carry an errno (several values, `v128`, a reference) is refused (126) unless the imports module provides it. A module with no WASI imports, or a foreign import that is not a function, is still refused (126). `ctx` has:
|
|
113
113
|
|
|
114
114
|
- `memory()`, `instance()` (after instantiation), `tid` (1 for the main thread), `argv`, `env`, `cwd()`;
|
|
115
115
|
- `fs`: the synchronous filesystem the WASI calls use (absolute paths);
|
|
@@ -208,6 +208,8 @@ Unit tests live in `test/unit/`, which stays out of git. They run real wasm bash
|
|
|
208
208
|
|
|
209
209
|
The Biome, TypeScript, lefthook, Renovate and CI configuration comes from [slicc-shared-web](https://github.com/ai-ecoverse/slicc-shared-web), which also provides the `slicc-lint-comments` (no comments anywhere), `slicc-no-unit-tests` (no unit tests in git) and `slicc-diff-cover` (100% coverage of changed lines) commands that `npm run lint` and the pre-commit hook use.
|
|
210
210
|
|
|
211
|
+
Releases are cut by semantic-release on every push to `main`. A failure after the version is tagged (a rejected push, a failed `npm publish`) doesn't strand that version: `tools/release-recover.mjs` runs next. For any version tagged at HEAD, it first pushes the tag if origin lacks it, then publishes the version if npm lacks it, with retries, and creates its GitHub release if that is missing too. Re-running the Release workflow completes such a version the same way.
|
|
212
|
+
|
|
211
213
|
## License
|
|
212
214
|
|
|
213
215
|
Apache-2.0
|
package/dist/kernel-worker.js
CHANGED
|
@@ -5544,6 +5544,109 @@ function importedMemory(bytes) {
|
|
|
5544
5544
|
}
|
|
5545
5545
|
return void 0;
|
|
5546
5546
|
}
|
|
5547
|
+
var RESERVED_NAMESPACES = /* @__PURE__ */ new Set([
|
|
5548
|
+
"wasi_snapshot_preview1",
|
|
5549
|
+
"wasix_32v1",
|
|
5550
|
+
"wasi",
|
|
5551
|
+
"env"
|
|
5552
|
+
]);
|
|
5553
|
+
var RESULTS = {
|
|
5554
|
+
127: "i32",
|
|
5555
|
+
126: "i64",
|
|
5556
|
+
125: "f32",
|
|
5557
|
+
124: "f64"
|
|
5558
|
+
};
|
|
5559
|
+
function resultOf(results) {
|
|
5560
|
+
if (results.length === 0) return "none";
|
|
5561
|
+
return results.length === 1 && RESULTS[results[0]] || "other";
|
|
5562
|
+
}
|
|
5563
|
+
var Reader = class {
|
|
5564
|
+
at = 8;
|
|
5565
|
+
bytes;
|
|
5566
|
+
constructor(bytes) {
|
|
5567
|
+
this.bytes = bytes;
|
|
5568
|
+
}
|
|
5569
|
+
byte() {
|
|
5570
|
+
return this.bytes[this.at++];
|
|
5571
|
+
}
|
|
5572
|
+
u32() {
|
|
5573
|
+
let result = 0;
|
|
5574
|
+
let shift = 0;
|
|
5575
|
+
for (; ; ) {
|
|
5576
|
+
const b = this.byte();
|
|
5577
|
+
result |= (b & 127) << shift;
|
|
5578
|
+
if (!(b & 128)) return result >>> 0;
|
|
5579
|
+
shift += 7;
|
|
5580
|
+
}
|
|
5581
|
+
}
|
|
5582
|
+
name() {
|
|
5583
|
+
const len = this.u32();
|
|
5584
|
+
const s = new TextDecoder().decode(this.bytes.subarray(this.at, this.at + len));
|
|
5585
|
+
this.at += len;
|
|
5586
|
+
return s;
|
|
5587
|
+
}
|
|
5588
|
+
valtype() {
|
|
5589
|
+
const code = this.byte();
|
|
5590
|
+
if (code === 99 || code === 100) this.u32();
|
|
5591
|
+
return code;
|
|
5592
|
+
}
|
|
5593
|
+
limits() {
|
|
5594
|
+
const flags = this.byte();
|
|
5595
|
+
this.u32();
|
|
5596
|
+
if (flags & 1) this.u32();
|
|
5597
|
+
}
|
|
5598
|
+
};
|
|
5599
|
+
function readTypes(r) {
|
|
5600
|
+
const types = [];
|
|
5601
|
+
for (let i = r.u32(); i > 0; i--) {
|
|
5602
|
+
if (r.byte() !== 96) return void 0;
|
|
5603
|
+
for (let n = r.u32(); n > 0; n--) r.valtype();
|
|
5604
|
+
const results = [];
|
|
5605
|
+
for (let n = r.u32(); n > 0; n--) results.push(r.valtype());
|
|
5606
|
+
types.push(resultOf(results));
|
|
5607
|
+
}
|
|
5608
|
+
return types;
|
|
5609
|
+
}
|
|
5610
|
+
function skipImport(r, kind) {
|
|
5611
|
+
if (kind === 1) {
|
|
5612
|
+
r.valtype();
|
|
5613
|
+
r.limits();
|
|
5614
|
+
} else if (kind === 2) r.limits();
|
|
5615
|
+
else if (kind === 3) {
|
|
5616
|
+
r.valtype();
|
|
5617
|
+
r.byte();
|
|
5618
|
+
} else {
|
|
5619
|
+
r.byte();
|
|
5620
|
+
r.u32();
|
|
5621
|
+
}
|
|
5622
|
+
}
|
|
5623
|
+
function readImports(r, types) {
|
|
5624
|
+
const foreign = {};
|
|
5625
|
+
for (let i = r.u32(); i > 0; i--) {
|
|
5626
|
+
const module = r.name();
|
|
5627
|
+
const field = r.name();
|
|
5628
|
+
const kind = r.byte();
|
|
5629
|
+
if (kind !== 0) skipImport(r, kind);
|
|
5630
|
+
else {
|
|
5631
|
+
const type = types[r.u32()] ?? "other";
|
|
5632
|
+
if (!RESERVED_NAMESPACES.has(module)) (foreign[module] ??= {})[field] = type;
|
|
5633
|
+
}
|
|
5634
|
+
}
|
|
5635
|
+
return foreign;
|
|
5636
|
+
}
|
|
5637
|
+
function foreignImports(bytes) {
|
|
5638
|
+
const r = new Reader(bytes);
|
|
5639
|
+
let types = [];
|
|
5640
|
+
while (r.at < bytes.length) {
|
|
5641
|
+
const id = r.byte();
|
|
5642
|
+
const end = r.u32() + r.at;
|
|
5643
|
+
if (id === 1) types = readTypes(r);
|
|
5644
|
+
if (!types) return void 0;
|
|
5645
|
+
if (id === 2) return readImports(r, types);
|
|
5646
|
+
r.at = end;
|
|
5647
|
+
}
|
|
5648
|
+
return {};
|
|
5649
|
+
}
|
|
5547
5650
|
|
|
5548
5651
|
// src/launcher.ts
|
|
5549
5652
|
var COMMAND2 = /^\/(?:usr\/)?bin\/([^/]+)$/;
|
|
@@ -5731,8 +5834,13 @@ var Launcher = class {
|
|
|
5731
5834
|
if (!module) {
|
|
5732
5835
|
module = this.base.readFileBuffer(path).then(async (bytes) => {
|
|
5733
5836
|
const memory = importedMemory(bytes);
|
|
5837
|
+
const foreign = foreignImports(bytes);
|
|
5734
5838
|
const compiled = await WebAssembly.compile(bytes);
|
|
5735
|
-
return {
|
|
5839
|
+
return {
|
|
5840
|
+
module: compiled,
|
|
5841
|
+
...memory ? { memory } : {},
|
|
5842
|
+
foreign
|
|
5843
|
+
};
|
|
5736
5844
|
});
|
|
5737
5845
|
this.compiled.set(key, module);
|
|
5738
5846
|
module.catch(() => this.compiled.delete(key));
|
|
@@ -5757,7 +5865,7 @@ var Launcher = class {
|
|
|
5757
5865
|
]);
|
|
5758
5866
|
return { glue, module: module2 };
|
|
5759
5867
|
}
|
|
5760
|
-
const { module, memory } = await this.module(target.wasm);
|
|
5868
|
+
const { module, memory, foreign } = await this.module(target.wasm);
|
|
5761
5869
|
const names = env.SLICC_WASM_BACKTRACE === "1" ? await this.names(target.wasm, module) : void 0;
|
|
5762
5870
|
const imports = target.imports ? await this.base.readFile(target.imports) : void 0;
|
|
5763
5871
|
return {
|
|
@@ -5765,6 +5873,7 @@ var Launcher = class {
|
|
|
5765
5873
|
glue: "",
|
|
5766
5874
|
module,
|
|
5767
5875
|
...memory ? { memory } : {},
|
|
5876
|
+
foreign,
|
|
5768
5877
|
...names ? { names } : {},
|
|
5769
5878
|
...imports !== void 0 ? { imports } : {}
|
|
5770
5879
|
};
|