@ai-ecoverse/slicc-kernel 1.53.3 → 1.54.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 +7 -1
- package/dist/index.js +76 -2
- package/dist/index.js.map +4 -4
- package/dist/kernel-worker.js +133 -11
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node.js +199 -12
- package/dist/node.js.map +3 -3
- package/package.json +2 -2
package/dist/node.js
CHANGED
|
@@ -10369,9 +10369,11 @@ var JobTable = class {
|
|
|
10369
10369
|
const member = this.member(pid);
|
|
10370
10370
|
const id2 = this.idOf(pid);
|
|
10371
10371
|
if (member.pgid === id2) throw new KernelError("EPERM");
|
|
10372
|
+
const left = member.pgid;
|
|
10372
10373
|
member.sid = id2;
|
|
10373
10374
|
member.pgid = id2;
|
|
10374
10375
|
this.terminals.delete(id2);
|
|
10376
|
+
this.prune(left);
|
|
10375
10377
|
return id2;
|
|
10376
10378
|
}
|
|
10377
10379
|
terminalNamed(name2) {
|
|
@@ -10415,18 +10417,18 @@ var JobTable = class {
|
|
|
10415
10417
|
const inSession = [...this.members.values()].some((m) => m.pgid === pgid && m.sid === self.sid);
|
|
10416
10418
|
if (!inSession) throw new KernelError("EPERM");
|
|
10417
10419
|
const current = this.foreground.get(tty);
|
|
10418
|
-
if (settling && pgid === self.pgid && current !== pgid && this.reclaimed(pgid,
|
|
10419
|
-
|
|
10420
|
-
if (pgid !== self.pgid) this.handoffs.set(pgid, { by
|
|
10420
|
+
if (settling && pgid === self.pgid && current !== pgid && this.reclaimed(pgid, caller)) return;
|
|
10421
|
+
const by = this.shown(caller);
|
|
10422
|
+
if (pgid !== self.pgid) this.handoffs.set(pgid, { by, reclaimed: false });
|
|
10421
10423
|
else if (current !== void 0) {
|
|
10422
10424
|
const handoff = this.handoffs.get(current);
|
|
10423
|
-
if (handoff?.by ===
|
|
10425
|
+
if (handoff?.by === by) handoff.reclaimed = true;
|
|
10424
10426
|
}
|
|
10425
10427
|
this.foreground.set(tty, pgid);
|
|
10426
10428
|
}
|
|
10427
|
-
reclaimed(pgid,
|
|
10429
|
+
reclaimed(pgid, caller) {
|
|
10428
10430
|
const handoff = this.handoffs.get(pgid);
|
|
10429
|
-
return handoff?.reclaimed === true && handoff.by ===
|
|
10431
|
+
return handoff?.reclaimed === true && handoff.by === this.shownParent(caller);
|
|
10430
10432
|
}
|
|
10431
10433
|
signalOwnedForeground(tty, sig) {
|
|
10432
10434
|
const pgid = this.foreground.get(tty);
|
|
@@ -11154,7 +11156,7 @@ function hostfsHandlers(current) {
|
|
|
11154
11156
|
const handles = /* @__PURE__ */ new Map();
|
|
11155
11157
|
let nextFh = 0;
|
|
11156
11158
|
const fresh = (remote) => {
|
|
11157
|
-
if (remote.client.token === remote.token) return remote;
|
|
11159
|
+
if (remote.client.token === remote.token && !remote.client.gone) return remote;
|
|
11158
11160
|
throw fsError2("ESTALE", "the folder was granted again, so this open file is gone");
|
|
11159
11161
|
};
|
|
11160
11162
|
const live = (fh) => {
|
|
@@ -11359,10 +11361,190 @@ function keepWatching(loop, signal) {
|
|
|
11359
11361
|
function invalidation(event) {
|
|
11360
11362
|
return event.paths ?? true;
|
|
11361
11363
|
}
|
|
11362
|
-
|
|
11364
|
+
var PORT_REQUEST_MS = 6e4;
|
|
11365
|
+
var PORT_MS_PER_MIB = 1e3;
|
|
11366
|
+
var nextPortToken = 0;
|
|
11367
|
+
var PortTransport = class {
|
|
11368
|
+
capabilities;
|
|
11369
|
+
token;
|
|
11370
|
+
port;
|
|
11371
|
+
requestMs;
|
|
11372
|
+
waiting = /* @__PURE__ */ new Map();
|
|
11373
|
+
next = 0;
|
|
11374
|
+
dead;
|
|
11375
|
+
constructor(grant, requestMs = PORT_REQUEST_MS) {
|
|
11376
|
+
this.port = grant.port;
|
|
11377
|
+
this.requestMs = requestMs;
|
|
11378
|
+
this.capabilities = grant.capabilities ?? {};
|
|
11379
|
+
this.token = grant.token ?? `port-${++nextPortToken}`;
|
|
11380
|
+
this.port.addEventListener("message", (event) => {
|
|
11381
|
+
this.waiting.get(event.data?.id)?.(event.data);
|
|
11382
|
+
});
|
|
11383
|
+
this.port.addEventListener("close", () => this.fail("the folder's port closed"));
|
|
11384
|
+
this.port.start();
|
|
11385
|
+
}
|
|
11386
|
+
get maxIo() {
|
|
11387
|
+
return this.capabilities.maxIo ?? HOSTFS_IO;
|
|
11388
|
+
}
|
|
11389
|
+
get gone() {
|
|
11390
|
+
return this.dead !== void 0;
|
|
11391
|
+
}
|
|
11392
|
+
fail(why) {
|
|
11393
|
+
if (this.dead === void 0) this.port.close();
|
|
11394
|
+
this.dead ??= why;
|
|
11395
|
+
for (const settle of [...this.waiting.values()])
|
|
11396
|
+
settle({ id: 0, error: { code: "ENOTCONN", message: why } });
|
|
11397
|
+
}
|
|
11398
|
+
ask(message3, bytes = 0, transfer = []) {
|
|
11399
|
+
const id2 = ++this.next;
|
|
11400
|
+
if (this.dead) return Promise.reject(fsError2("ENOTCONN", this.dead));
|
|
11401
|
+
return new Promise((resolve, reject) => {
|
|
11402
|
+
const timer = setTimeout(
|
|
11403
|
+
() => {
|
|
11404
|
+
this.waiting.delete(id2);
|
|
11405
|
+
reject(fsError2("ETIMEDOUT", "the folder's port did not answer"));
|
|
11406
|
+
this.fail("the folder's port stopped answering");
|
|
11407
|
+
},
|
|
11408
|
+
this.requestMs + Math.ceil(bytes / 1048576) * PORT_MS_PER_MIB
|
|
11409
|
+
);
|
|
11410
|
+
this.waiting.set(id2, (reply) => {
|
|
11411
|
+
clearTimeout(timer);
|
|
11412
|
+
this.waiting.delete(id2);
|
|
11413
|
+
if (reply.error) reject(fsError2(reply.error.code ?? "EIO", reply.error.message ?? ""));
|
|
11414
|
+
else resolve(reply);
|
|
11415
|
+
});
|
|
11416
|
+
try {
|
|
11417
|
+
this.port.postMessage({ id: id2, ...message3 }, transfer);
|
|
11418
|
+
} catch (err) {
|
|
11419
|
+
this.fail(`the folder's port is closed: ${err.message}`);
|
|
11420
|
+
}
|
|
11421
|
+
});
|
|
11422
|
+
}
|
|
11423
|
+
async call(op, body = {}) {
|
|
11424
|
+
return (await this.ask({ op: "call", name: op, body })).result;
|
|
11425
|
+
}
|
|
11426
|
+
async read(fh, offset, size, ifMatch) {
|
|
11427
|
+
const reply = await this.ask(
|
|
11428
|
+
{ op: "read", fh, offset, size, ...ifMatch ? { ifMatch } : {} },
|
|
11429
|
+
size
|
|
11430
|
+
);
|
|
11431
|
+
return reply.bytes ?? new Uint8Array(0);
|
|
11432
|
+
}
|
|
11433
|
+
async write(fh, offset, bytes) {
|
|
11434
|
+
await this.ask({ op: "write", fh, offset, bytes }, bytes.length);
|
|
11435
|
+
}
|
|
11436
|
+
watch(signal, onEvent, onOpen = () => void 0) {
|
|
11437
|
+
const id2 = ++this.next;
|
|
11438
|
+
if (this.dead) return Promise.reject(fsError2("ENOTCONN", this.dead));
|
|
11439
|
+
if (signal.aborted) {
|
|
11440
|
+
this.fail("the folder's watch ended");
|
|
11441
|
+
return Promise.resolve();
|
|
11442
|
+
}
|
|
11443
|
+
return new Promise((resolve, reject) => {
|
|
11444
|
+
const finish = () => {
|
|
11445
|
+
this.waiting.delete(id2);
|
|
11446
|
+
signal.removeEventListener("abort", stop);
|
|
11447
|
+
};
|
|
11448
|
+
const stop = () => {
|
|
11449
|
+
finish();
|
|
11450
|
+
try {
|
|
11451
|
+
this.port.postMessage({ id: id2, op: "unwatch" });
|
|
11452
|
+
} catch {
|
|
11453
|
+
}
|
|
11454
|
+
resolve();
|
|
11455
|
+
};
|
|
11456
|
+
this.waiting.set(id2, (reply) => {
|
|
11457
|
+
if (reply.open) return onOpen();
|
|
11458
|
+
if (reply.event) return onEvent(reply.event);
|
|
11459
|
+
finish();
|
|
11460
|
+
if (reply.error) reject(fsError2(reply.error.code ?? "ENOTCONN", reply.error.message ?? ""));
|
|
11461
|
+
else resolve();
|
|
11462
|
+
});
|
|
11463
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
11464
|
+
try {
|
|
11465
|
+
this.port.postMessage({ id: id2, op: "watch" });
|
|
11466
|
+
} catch (err) {
|
|
11467
|
+
finish();
|
|
11468
|
+
reject(fsError2("ENOTCONN", `the folder's port is closed: ${err.message}`));
|
|
11469
|
+
}
|
|
11470
|
+
}).finally(() => this.fail("the folder's watch ended"));
|
|
11471
|
+
}
|
|
11472
|
+
};
|
|
11473
|
+
var errorOf = (err) => ({
|
|
11474
|
+
code: typeof codeOf4(err) === "string" ? codeOf4(err) : "EIO",
|
|
11475
|
+
message: err?.message ?? String(err)
|
|
11476
|
+
});
|
|
11477
|
+
function serveHostfsPort(port, transport) {
|
|
11478
|
+
const watches = /* @__PURE__ */ new Map();
|
|
11479
|
+
const send = (reply, transfer = []) => port.postMessage(reply, transfer);
|
|
11480
|
+
const listener = async ({
|
|
11481
|
+
data
|
|
11482
|
+
}) => {
|
|
11483
|
+
const { id: id2, op } = data;
|
|
11484
|
+
if (op === "unwatch") return watches.get(id2)?.abort();
|
|
11485
|
+
if (op === "watch") {
|
|
11486
|
+
const stop2 = new AbortController();
|
|
11487
|
+
watches.set(id2, stop2);
|
|
11488
|
+
try {
|
|
11489
|
+
await transport.watch(
|
|
11490
|
+
stop2.signal,
|
|
11491
|
+
(event) => send({ id: id2, event }),
|
|
11492
|
+
() => send({ id: id2, open: true })
|
|
11493
|
+
);
|
|
11494
|
+
send({ id: id2, end: true });
|
|
11495
|
+
} catch (err) {
|
|
11496
|
+
send({ id: id2, error: errorOf(err) });
|
|
11497
|
+
} finally {
|
|
11498
|
+
watches.delete(id2);
|
|
11499
|
+
}
|
|
11500
|
+
return;
|
|
11501
|
+
}
|
|
11502
|
+
try {
|
|
11503
|
+
if (op === "read") {
|
|
11504
|
+
const read = await transport.read(
|
|
11505
|
+
data.fh,
|
|
11506
|
+
data.offset,
|
|
11507
|
+
data.size,
|
|
11508
|
+
data.ifMatch
|
|
11509
|
+
);
|
|
11510
|
+
const bytes = read.slice();
|
|
11511
|
+
return send({ id: id2, bytes }, [bytes.buffer]);
|
|
11512
|
+
}
|
|
11513
|
+
if (op === "write") {
|
|
11514
|
+
await transport.write(data.fh, data.offset, data.bytes);
|
|
11515
|
+
return send({ id: id2 });
|
|
11516
|
+
}
|
|
11517
|
+
if (op !== "call") throw fsError2("EINVAL", `unknown hostfs port op ${op}`);
|
|
11518
|
+
send({
|
|
11519
|
+
id: id2,
|
|
11520
|
+
result: await transport.call(data.name, data.body)
|
|
11521
|
+
});
|
|
11522
|
+
} catch (err) {
|
|
11523
|
+
send({ id: id2, error: errorOf(err) });
|
|
11524
|
+
}
|
|
11525
|
+
};
|
|
11526
|
+
const stop = () => {
|
|
11527
|
+
port.removeEventListener("message", listener);
|
|
11528
|
+
port.removeEventListener("close", stop);
|
|
11529
|
+
for (const watch of watches.values()) watch.abort();
|
|
11530
|
+
port.close();
|
|
11531
|
+
};
|
|
11532
|
+
port.addEventListener("message", listener);
|
|
11533
|
+
port.addEventListener("close", stop);
|
|
11534
|
+
port.start();
|
|
11535
|
+
return stop;
|
|
11536
|
+
}
|
|
11537
|
+
function grantConnect(hook, fetch2, requestMs) {
|
|
11363
11538
|
return async (source, options) => {
|
|
11364
|
-
const
|
|
11365
|
-
return new
|
|
11539
|
+
const first = await hook(source, options);
|
|
11540
|
+
if ("port" in first) return new PortTransport(first, requestMs);
|
|
11541
|
+
const grant = async () => {
|
|
11542
|
+
const again = await hook(source, options);
|
|
11543
|
+
if ("port" in again)
|
|
11544
|
+
throw fsError2("ESTALE", "the folder moved to a port, so its open files are gone");
|
|
11545
|
+
return again;
|
|
11546
|
+
};
|
|
11547
|
+
return new HostfsClient(first, grant, fetch2);
|
|
11366
11548
|
};
|
|
11367
11549
|
}
|
|
11368
11550
|
async function openHostfs(spec, connect, timing = {}) {
|
|
@@ -12417,7 +12599,11 @@ var Launcher = class {
|
|
|
12417
12599
|
throw fsError("ENODEV", "this kernel has no hostfs hook (createKernel({ hostfs }))");
|
|
12418
12600
|
return openHostfs(
|
|
12419
12601
|
spec,
|
|
12420
|
-
grantConnect(
|
|
12602
|
+
grantConnect(
|
|
12603
|
+
hostfs,
|
|
12604
|
+
hostfsFetch ?? ((url, init) => fetch(url, init)),
|
|
12605
|
+
hostfsTiming?.requestMs
|
|
12606
|
+
),
|
|
12421
12607
|
hostfsTiming
|
|
12422
12608
|
);
|
|
12423
12609
|
}
|
|
@@ -13874,6 +14060,7 @@ export {
|
|
|
13874
14060
|
createNodeKernel,
|
|
13875
14061
|
fetchTransport,
|
|
13876
14062
|
memoryRoot,
|
|
13877
|
-
nodeTransport
|
|
14063
|
+
nodeTransport,
|
|
14064
|
+
serveHostfsPort
|
|
13878
14065
|
};
|
|
13879
14066
|
//# sourceMappingURL=node.js.map
|