@ai-ecoverse/slicc-kernel 1.83.0 → 1.84.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 +10 -3
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +85 -38
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node-process-worker.js +27 -5
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +215 -62
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +27 -5
- package/dist/process-worker.js.map +3 -3
- package/package.json +1 -1
package/dist/kernel-worker.js
CHANGED
|
@@ -7487,9 +7487,13 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
|
|
|
7487
7487
|
// src/fs/fresh-modules.ts
|
|
7488
7488
|
var MAGIC = [0, 97, 115, 109];
|
|
7489
7489
|
var MAX_FRESH = 65536;
|
|
7490
|
+
var DEFAULT_UMASK = 18;
|
|
7490
7491
|
function isModule(bytes) {
|
|
7491
7492
|
return MAGIC.every((b, i) => bytes[i] === b);
|
|
7492
7493
|
}
|
|
7494
|
+
function within4(path, dir) {
|
|
7495
|
+
return path.startsWith(dir === "/" ? "/" : `${dir}/`);
|
|
7496
|
+
}
|
|
7493
7497
|
var FreshModules = class {
|
|
7494
7498
|
fresh = /* @__PURE__ */ new Map();
|
|
7495
7499
|
add(path, umask, pid) {
|
|
@@ -7497,17 +7501,40 @@ var FreshModules = class {
|
|
|
7497
7501
|
this.fresh.delete(key);
|
|
7498
7502
|
const oldest = this.fresh.size >= MAX_FRESH ? this.fresh.keys().next().value : void 0;
|
|
7499
7503
|
if (oldest !== void 0) this.fresh.delete(oldest);
|
|
7500
|
-
|
|
7504
|
+
const mask = umask & 511;
|
|
7505
|
+
this.fresh.set(key, { umask: mask, pid, added: 0, setup: mask !== DEFAULT_UMASK });
|
|
7501
7506
|
}
|
|
7502
7507
|
forget(pid) {
|
|
7503
7508
|
for (const [path, fresh2] of this.fresh) if (fresh2.pid === pid) this.fresh.delete(path);
|
|
7504
7509
|
}
|
|
7510
|
+
drop(fresh2) {
|
|
7511
|
+
for (const [key, note] of [...this.fresh]) if (note === fresh2) this.fresh.delete(key);
|
|
7512
|
+
}
|
|
7513
|
+
moved(from, to) {
|
|
7514
|
+
const source = normalizePath(from);
|
|
7515
|
+
const target = normalizePath(to);
|
|
7516
|
+
if (source === target) return;
|
|
7517
|
+
for (const key of [...this.fresh.keys()]) {
|
|
7518
|
+
if (key === target || within4(key, target)) this.fresh.delete(key);
|
|
7519
|
+
}
|
|
7520
|
+
for (const [key, fresh2] of [...this.fresh]) {
|
|
7521
|
+
if (key !== source && !within4(key, source)) continue;
|
|
7522
|
+
this.fresh.delete(key);
|
|
7523
|
+
this.fresh.set(target + key.slice(source.length), fresh2);
|
|
7524
|
+
}
|
|
7525
|
+
}
|
|
7505
7526
|
wrap(fs) {
|
|
7506
|
-
const
|
|
7527
|
+
const head = async (path) => {
|
|
7528
|
+
if (fs.pread) return fs.pread(path, 0, MAGIC.length);
|
|
7529
|
+
return (await fs.readFileBuffer(path)).subarray(0, MAGIC.length);
|
|
7530
|
+
};
|
|
7531
|
+
const decide = async (given, known) => {
|
|
7507
7532
|
const path = normalizePath(given);
|
|
7508
7533
|
const fresh2 = this.fresh.get(path);
|
|
7509
|
-
if (!fresh2
|
|
7534
|
+
if (!fresh2) return;
|
|
7535
|
+
const bytes = known && known.length >= MAGIC.length ? known : await head(path);
|
|
7510
7536
|
const want = isModule(bytes) ? 73 & ~fresh2.umask : 0;
|
|
7537
|
+
fresh2.setup = false;
|
|
7511
7538
|
if (want === fresh2.added) return;
|
|
7512
7539
|
const mode = (await fs.stat(path)).mode & 4095;
|
|
7513
7540
|
await fs.chmod(path, mode & ~fresh2.added | want);
|
|
@@ -7516,32 +7543,47 @@ var FreshModules = class {
|
|
|
7516
7543
|
const overrides = {
|
|
7517
7544
|
writeFile: async (path, content, owner) => {
|
|
7518
7545
|
await fs.writeFile(path, content, owner);
|
|
7519
|
-
|
|
7546
|
+
if (this.fresh.has(normalizePath(path))) {
|
|
7547
|
+
await decide(
|
|
7548
|
+
path,
|
|
7549
|
+
typeof content === "string" ? new TextEncoder().encode(content) : content
|
|
7550
|
+
);
|
|
7551
|
+
}
|
|
7520
7552
|
},
|
|
7521
7553
|
chmod: async (path, mode) => {
|
|
7522
7554
|
const fresh2 = this.fresh.get(normalizePath(path));
|
|
7523
|
-
|
|
7524
|
-
if (
|
|
7555
|
+
if (fresh2?.setup && (mode & 4095) === (438 & ~fresh2.umask)) fresh2.setup = false;
|
|
7556
|
+
else if (fresh2) this.drop(fresh2);
|
|
7525
7557
|
await fs.chmod(path, mode);
|
|
7526
7558
|
},
|
|
7527
7559
|
rm: async (path, options) => {
|
|
7528
|
-
this.fresh.delete(normalizePath(path));
|
|
7529
7560
|
await fs.rm(path, options);
|
|
7561
|
+
const at = normalizePath(path);
|
|
7562
|
+
for (const key of [...this.fresh.keys()]) {
|
|
7563
|
+
if (key === at || within4(key, at)) this.fresh.delete(key);
|
|
7564
|
+
}
|
|
7530
7565
|
},
|
|
7531
7566
|
rename: async (from, to) => {
|
|
7532
7567
|
await fs.rename(from, to);
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
|
|
7568
|
+
this.moved(from, to);
|
|
7569
|
+
},
|
|
7570
|
+
link: async (from, to, follow2) => {
|
|
7571
|
+
await fs.link(from, to, follow2);
|
|
7572
|
+
const source = follow2 && fs.realpath ? await fs.realpath(from, true) : from;
|
|
7573
|
+
const fresh2 = this.fresh.get(normalizePath(source));
|
|
7536
7574
|
if (fresh2) this.fresh.set(normalizePath(to), fresh2);
|
|
7537
7575
|
}
|
|
7538
7576
|
};
|
|
7539
7577
|
const ranged2 = rangedOps(fs);
|
|
7540
7578
|
if (ranged2) {
|
|
7541
7579
|
overrides.pwrite = async (path, at, bytes, transfer) => {
|
|
7542
|
-
const
|
|
7580
|
+
const touches2 = at < MAGIC.length && this.fresh.has(normalizePath(path));
|
|
7543
7581
|
await ranged2.pwrite(path, at, bytes, transfer);
|
|
7544
|
-
if (
|
|
7582
|
+
if (touches2) await decide(path);
|
|
7583
|
+
};
|
|
7584
|
+
overrides.truncate = async (path, size) => {
|
|
7585
|
+
await ranged2.truncate(path, size);
|
|
7586
|
+
if (size < MAGIC.length && this.fresh.has(normalizePath(path))) await decide(path);
|
|
7545
7587
|
};
|
|
7546
7588
|
}
|
|
7547
7589
|
const bound2 = /* @__PURE__ */ new WeakMap();
|
|
@@ -7613,7 +7655,7 @@ var UNLINKED_DIR = ".slicc-unlinked";
|
|
|
7613
7655
|
function webLocks() {
|
|
7614
7656
|
return globalThis.navigator?.locks;
|
|
7615
7657
|
}
|
|
7616
|
-
var
|
|
7658
|
+
var within5 = (path, target) => path === target || target === "/" || path.startsWith(`${target}/`);
|
|
7617
7659
|
var parentOf5 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
7618
7660
|
var lockName = (instance) => `slicc-unlinked:${instance}`;
|
|
7619
7661
|
var dirOf = (root) => root === "/" ? `/${UNLINKED_DIR}` : `${root}/${UNLINKED_DIR}`;
|
|
@@ -7713,7 +7755,7 @@ var UnlinkedKeeper = class {
|
|
|
7713
7755
|
for (const holder of this.holders) {
|
|
7714
7756
|
if (holder.owns(target)) continue;
|
|
7715
7757
|
for (const path of holder.held()) {
|
|
7716
|
-
if (!
|
|
7758
|
+
if (!within5(path, target) || holder.isKept(path)) continue;
|
|
7717
7759
|
held.set(path, [...held.get(path) ?? [], holder]);
|
|
7718
7760
|
}
|
|
7719
7761
|
}
|
|
@@ -8336,7 +8378,7 @@ function parseSize(text) {
|
|
|
8336
8378
|
if (!match) throw errnoError("EINVAL", `not a size: ${text}`);
|
|
8337
8379
|
return Math.floor(Number(match[1]) * UNITS[match[2].toLowerCase()]);
|
|
8338
8380
|
}
|
|
8339
|
-
var
|
|
8381
|
+
var within6 = (path, target) => path === target || target === "/" || path.startsWith(`${target}/`);
|
|
8340
8382
|
var HeldSet = class extends Set {
|
|
8341
8383
|
idle;
|
|
8342
8384
|
constructor(idle) {
|
|
@@ -8355,7 +8397,7 @@ var HeldSet = class extends Set {
|
|
|
8355
8397
|
}
|
|
8356
8398
|
};
|
|
8357
8399
|
function heldUnder(held, target) {
|
|
8358
|
-
for (const paths of held) for (const path of paths.keys()) if (
|
|
8400
|
+
for (const paths of held) for (const path of paths.keys()) if (within6(path, target)) return true;
|
|
8359
8401
|
return false;
|
|
8360
8402
|
}
|
|
8361
8403
|
var HeldPaths = class extends Map {
|
|
@@ -8471,24 +8513,24 @@ var HeldPaths = class extends Map {
|
|
|
8471
8513
|
return this.owning === path;
|
|
8472
8514
|
}
|
|
8473
8515
|
revoke(prefix) {
|
|
8474
|
-
for (const path of this.keys()) if (
|
|
8516
|
+
for (const path of this.keys()) if (within6(path, prefix)) this.revoked.add(path);
|
|
8475
8517
|
}
|
|
8476
8518
|
renamed(from, to) {
|
|
8477
8519
|
for (const [path, count2] of [...this]) {
|
|
8478
|
-
if (!
|
|
8520
|
+
if (!within6(path, from)) continue;
|
|
8479
8521
|
const moved2 = to + path.slice(from.length);
|
|
8480
8522
|
this.delete(path);
|
|
8481
8523
|
this.set(moved2, (this.get(moved2) ?? 0) + count2);
|
|
8482
8524
|
if (this.revoked.delete(path)) this.revoked.add(moved2);
|
|
8483
8525
|
}
|
|
8484
8526
|
for (const [path, count2] of [...this.opens]) {
|
|
8485
|
-
if (!
|
|
8527
|
+
if (!within6(path, from)) continue;
|
|
8486
8528
|
const moved2 = to + path.slice(from.length);
|
|
8487
8529
|
this.opens.delete(path);
|
|
8488
8530
|
this.opens.set(moved2, (this.opens.get(moved2) ?? 0) + count2);
|
|
8489
8531
|
}
|
|
8490
8532
|
for (const [id2, key] of this.handles) {
|
|
8491
|
-
if (
|
|
8533
|
+
if (within6(key, from)) this.handles.set(id2, to + key.slice(from.length));
|
|
8492
8534
|
}
|
|
8493
8535
|
}
|
|
8494
8536
|
isRevoked(path) {
|
|
@@ -8595,7 +8637,7 @@ var MountTable = class {
|
|
|
8595
8637
|
locate(path) {
|
|
8596
8638
|
let best;
|
|
8597
8639
|
for (const mount of this.mounts.values()) {
|
|
8598
|
-
if (
|
|
8640
|
+
if (within6(path, mount.target) && (!best || mount.target.length > best.target.length))
|
|
8599
8641
|
best = mount;
|
|
8600
8642
|
}
|
|
8601
8643
|
if (!best) return void 0;
|
|
@@ -8738,7 +8780,7 @@ var MountTable = class {
|
|
|
8738
8780
|
async commitUnder(prefix) {
|
|
8739
8781
|
const at = normalizePath(prefix);
|
|
8740
8782
|
await Promise.all(
|
|
8741
|
-
[...this.sessions.keys()].filter((p) =>
|
|
8783
|
+
[...this.sessions.keys()].filter((p) => within6(p, at)).map((p) => this.commit(p))
|
|
8742
8784
|
);
|
|
8743
8785
|
}
|
|
8744
8786
|
async commitOverlapping(real, offset, length2) {
|
|
@@ -8773,10 +8815,10 @@ var MountTable = class {
|
|
|
8773
8815
|
}
|
|
8774
8816
|
forget(mount, path) {
|
|
8775
8817
|
mount.epoch++;
|
|
8776
|
-
for (const key of [...mount.attrs.keys()]) if (
|
|
8818
|
+
for (const key of [...mount.attrs.keys()]) if (within6(key, path)) mount.attrs.delete(key);
|
|
8777
8819
|
mount.lists.delete(path);
|
|
8778
8820
|
mount.lists.delete(parentOf7(path));
|
|
8779
|
-
for (const key of [...mount.lists.keys()]) if (
|
|
8821
|
+
for (const key of [...mount.lists.keys()]) if (within6(key, path)) mount.lists.delete(key);
|
|
8780
8822
|
}
|
|
8781
8823
|
async getattr(mount, path, rel2, settled = false) {
|
|
8782
8824
|
for (let round = 1; ; round++) {
|
|
@@ -9411,6 +9453,11 @@ function statJson(s) {
|
|
|
9411
9453
|
async function readdirStat(fs, dir) {
|
|
9412
9454
|
return (await fs.readdirStat(dir)).map(([name2, stat]) => [name2, stat && statJson(stat)]);
|
|
9413
9455
|
}
|
|
9456
|
+
async function usageAt(entry, path) {
|
|
9457
|
+
if (!entry.statfs) return void 0;
|
|
9458
|
+
const real = await realTarget(entry.fs, path).catch(() => path);
|
|
9459
|
+
return entry.statfs(real);
|
|
9460
|
+
}
|
|
9414
9461
|
async function storageUsage() {
|
|
9415
9462
|
const estimate = await globalThis.navigator?.storage?.estimate?.();
|
|
9416
9463
|
if (typeof estimate?.quota !== "number") return null;
|
|
@@ -9727,7 +9774,7 @@ async function dispatchOne(entry, req) {
|
|
|
9727
9774
|
if (req.op === "hold") return await holdOp(entry, path, req);
|
|
9728
9775
|
const refused2 = await guarded(entry, path, req);
|
|
9729
9776
|
if (refused2) return refused2;
|
|
9730
|
-
if (req.op === "statfs") return json2(await entry
|
|
9777
|
+
if (req.op === "statfs") return json2(await usageAt(entry, path) ?? await storageUsage());
|
|
9731
9778
|
if (entry.revoked?.(path)) return { ok: false, errno: "EIO", message: `${path} was unmounted` };
|
|
9732
9779
|
if (req.op === "write" && req.mode === 1 || UNLINKED_OPS.has(req.op)) {
|
|
9733
9780
|
const serve = async () => run(entry, await keptOr(entry, path, req.handle), req);
|
|
@@ -11961,7 +12008,7 @@ function isMissing(err) {
|
|
|
11961
12008
|
if (err?.code === "ENOENT") return true;
|
|
11962
12009
|
return err instanceof Error && err.message.startsWith("ENOENT");
|
|
11963
12010
|
}
|
|
11964
|
-
function
|
|
12011
|
+
function within7(path, root) {
|
|
11965
12012
|
return path === root || path.startsWith(root.endsWith("/") ? root : `${root}/`);
|
|
11966
12013
|
}
|
|
11967
12014
|
var VfsNode = class {
|
|
@@ -12282,12 +12329,12 @@ var VfsNodes = class {
|
|
|
12282
12329
|
return node;
|
|
12283
12330
|
}
|
|
12284
12331
|
holds(prefix) {
|
|
12285
|
-
for (const path of this.byPath.keys()) if (
|
|
12332
|
+
for (const path of this.byPath.keys()) if (within7(path, prefix)) return true;
|
|
12286
12333
|
return false;
|
|
12287
12334
|
}
|
|
12288
12335
|
writes(prefix) {
|
|
12289
12336
|
for (const [path, node] of this.byPath)
|
|
12290
|
-
if (node.writers > 0 &&
|
|
12337
|
+
if (node.writers > 0 && within7(path, prefix)) return true;
|
|
12291
12338
|
return false;
|
|
12292
12339
|
}
|
|
12293
12340
|
closed(node, writable2 = false) {
|
|
@@ -12331,11 +12378,11 @@ var VfsNodes = class {
|
|
|
12331
12378
|
this.kept.delete(node);
|
|
12332
12379
|
}
|
|
12333
12380
|
async flush(path) {
|
|
12334
|
-
for (const [p, node] of this.byPath) if (
|
|
12381
|
+
for (const [p, node] of this.byPath) if (within7(p, path)) await node.serial(() => node.flush());
|
|
12335
12382
|
}
|
|
12336
12383
|
async unlinking(path) {
|
|
12337
12384
|
for (const [held, node] of [...this.byPath]) {
|
|
12338
|
-
if (!
|
|
12385
|
+
if (!within7(held, path)) continue;
|
|
12339
12386
|
await node.serial(async () => {
|
|
12340
12387
|
await Promise.all([this.keepsOnDisk || node.keep(), node.limit()]);
|
|
12341
12388
|
});
|
|
@@ -12343,14 +12390,14 @@ var VfsNodes = class {
|
|
|
12343
12390
|
}
|
|
12344
12391
|
revoke(prefix) {
|
|
12345
12392
|
for (const [path, node] of [...this.byPath]) {
|
|
12346
|
-
if (!
|
|
12393
|
+
if (!within7(path, prefix)) continue;
|
|
12347
12394
|
node.revoke();
|
|
12348
12395
|
this.forget(node);
|
|
12349
12396
|
}
|
|
12350
12397
|
}
|
|
12351
12398
|
unlinked(path) {
|
|
12352
12399
|
for (const [held, node] of [...this.byPath]) {
|
|
12353
|
-
if (!
|
|
12400
|
+
if (!within7(held, path) || this.byPath.get(held) !== node) continue;
|
|
12354
12401
|
if (!this.dropName(held, node)) this.orphan(node);
|
|
12355
12402
|
}
|
|
12356
12403
|
}
|
|
@@ -12358,8 +12405,8 @@ var VfsNodes = class {
|
|
|
12358
12405
|
if (from === to) return;
|
|
12359
12406
|
const moved2 = [];
|
|
12360
12407
|
for (const [p, node] of [...this.byPath]) {
|
|
12361
|
-
if (
|
|
12362
|
-
else if (
|
|
12408
|
+
if (within7(p, from)) moved2.push([p, node]);
|
|
12409
|
+
else if (within7(p, to) && this.byPath.get(p) === node && !this.dropName(p, node)) {
|
|
12363
12410
|
this.orphan(node);
|
|
12364
12411
|
}
|
|
12365
12412
|
}
|
|
@@ -12638,7 +12685,7 @@ function isWasmSyscall(req) {
|
|
|
12638
12685
|
var MAX_READ = 1024 * 1024;
|
|
12639
12686
|
var WRITE_ACCESS = 3;
|
|
12640
12687
|
var KEYBOARD = /* @__PURE__ */ new Set([SIG.INT, SIG.QUIT, SIG.TSTP]);
|
|
12641
|
-
var
|
|
12688
|
+
var DEFAULT_UMASK2 = 18;
|
|
12642
12689
|
function words(value) {
|
|
12643
12690
|
if (!Array.isArray(value) || !value.every((w) => typeof w === "string")) {
|
|
12644
12691
|
throw new KernelError("EINVAL");
|
|
@@ -12666,7 +12713,7 @@ var WasmProcess = class {
|
|
|
12666
12713
|
interrupt = new AbortController();
|
|
12667
12714
|
gone = new AbortController();
|
|
12668
12715
|
dying = false;
|
|
12669
|
-
umask =
|
|
12716
|
+
umask = DEFAULT_UMASK2;
|
|
12670
12717
|
cred;
|
|
12671
12718
|
execChild;
|
|
12672
12719
|
killed = false;
|
|
@@ -12688,7 +12735,7 @@ var WasmProcess = class {
|
|
|
12688
12735
|
this.fds = fds;
|
|
12689
12736
|
this.options = options;
|
|
12690
12737
|
this.inherited = options.ignored ?? 0;
|
|
12691
|
-
this.umask = options.umask ??
|
|
12738
|
+
this.umask = options.umask ?? DEFAULT_UMASK2;
|
|
12692
12739
|
this.cred = copyCred(options.cred ?? ROOT);
|
|
12693
12740
|
this.children = new ChildTable(fds, options.spawner, options.forker);
|
|
12694
12741
|
this.nodes = options.nodes ?? new VfsNodes(options.fs);
|
|
@@ -18271,7 +18318,7 @@ var Launcher = class {
|
|
|
18271
18318
|
}
|
|
18272
18319
|
}
|
|
18273
18320
|
umaskOf(pid) {
|
|
18274
|
-
return this.processes.get(pid)?.umask?.() ??
|
|
18321
|
+
return this.processes.get(pid)?.umask?.() ?? DEFAULT_UMASK2;
|
|
18275
18322
|
}
|
|
18276
18323
|
imageOf(pid) {
|
|
18277
18324
|
const members = this.jobs.list();
|