@ai-ecoverse/slicc-kernel 1.102.3 → 1.102.5
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 +1 -1
- package/dist/kernel-worker.js +73 -7
- package/dist/kernel-worker.js.map +2 -2
- package/dist/node-process-worker.js +8 -4
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +73 -7
- package/dist/node.js.map +2 -2
- package/dist/process-worker.js +8 -4
- package/dist/process-worker.js.map +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -389,7 +389,7 @@ const kernel = await createKernel({ network: { transport: fetchTransport() } });
|
|
|
389
389
|
await kernel.run(['curl', '-sS', 'https://registry.npmjs.org/@ai-ecoverse/wasm-bash/latest']);
|
|
390
390
|
```
|
|
391
391
|
|
|
392
|
-
- **Sockets**: `AF_INET` stream sockets on `127.x` and `AF_UNIX` sockets are kernel descriptors on one loopback network per kernel, so processes can serve and connect to each other. They survive `dup`, `fork` and `exec` and work with `select`, `poll` and WASIX epoll, like pipe ends. A bind of an `AF_UNIX` socket creates its path in OPFS. Other addresses are unreachable (`ENETUNREACH`) unless the [uplink](#uplink) routes them: otherwise programs reach the outside world only through the proxy.
|
|
392
|
+
- **Sockets**: `AF_INET` stream sockets on `127.x` and `AF_UNIX` sockets are kernel descriptors on one loopback network per kernel, so processes can serve and connect to each other. They survive `dup`, `fork` and `exec` and work with `select`, `poll` and WASIX epoll, like pipe ends. A bind of an `AF_UNIX` socket creates its path in OPFS. A program's `connect` to a listener whose accept queue is full waits for a slot, as on Linux, instead of failing. A blocking connect waits, and a nonblocking one answers `EINPROGRESS` and turns writable once it's queued. After 30 s it fails with `ETIMEDOUT`, and it's `ECONNREFUSED` if the listener closes. Other addresses are unreachable (`ENETUNREACH`) unless the [uplink](#uplink) routes them: otherwise programs reach the outside world only through the proxy.
|
|
393
393
|
|
|
394
394
|
#### Datagram sockets (UDP)
|
|
395
395
|
|
package/dist/kernel-worker.js
CHANGED
|
@@ -3564,6 +3564,7 @@ var KernelSocket = class _KernelSocket {
|
|
|
3564
3564
|
backlog = 0;
|
|
3565
3565
|
boundAt;
|
|
3566
3566
|
changes = new Changes();
|
|
3567
|
+
room = new Changes();
|
|
3567
3568
|
options = /* @__PURE__ */ new Map();
|
|
3568
3569
|
constructor(net, domain) {
|
|
3569
3570
|
this.net = net;
|
|
@@ -3648,7 +3649,10 @@ var KernelSocket = class _KernelSocket {
|
|
|
3648
3649
|
for (; ; ) {
|
|
3649
3650
|
if (this.state !== "listening") throw new KernelError("EINVAL");
|
|
3650
3651
|
const next2 = this.queue.shift();
|
|
3651
|
-
if (next2)
|
|
3652
|
+
if (next2) {
|
|
3653
|
+
this.room.wake();
|
|
3654
|
+
return next2;
|
|
3655
|
+
}
|
|
3652
3656
|
if (nonblock) throw new KernelError("EAGAIN");
|
|
3653
3657
|
await this.changes.wait(signal);
|
|
3654
3658
|
}
|
|
@@ -3659,7 +3663,13 @@ var KernelSocket = class _KernelSocket {
|
|
|
3659
3663
|
this.changes.wake();
|
|
3660
3664
|
return true;
|
|
3661
3665
|
}
|
|
3662
|
-
|
|
3666
|
+
get full() {
|
|
3667
|
+
return this.state === "listening" && this.queue.length >= this.backlog;
|
|
3668
|
+
}
|
|
3669
|
+
waitRoom(signal) {
|
|
3670
|
+
return this.room.wait(signal);
|
|
3671
|
+
}
|
|
3672
|
+
connect(addr, viaUplink = true, cred, stamp, waits = true) {
|
|
3663
3673
|
if (this.state === "connected") throw new KernelError("EISCONN");
|
|
3664
3674
|
if (this.state === "connecting") throw new KernelError("EALREADY");
|
|
3665
3675
|
if (this.state !== "open") throw new KernelError("EINVAL");
|
|
@@ -3674,6 +3684,11 @@ var KernelSocket = class _KernelSocket {
|
|
|
3674
3684
|
this.boundAt = this.local;
|
|
3675
3685
|
} else this.local = { family: "unix", path: "" };
|
|
3676
3686
|
}
|
|
3687
|
+
if (waits && target.full) return this.queued(addr, target, cred, stamp);
|
|
3688
|
+
this.join(addr, target, cred, stamp);
|
|
3689
|
+
return void 0;
|
|
3690
|
+
}
|
|
3691
|
+
join(addr, target, cred, stamp) {
|
|
3677
3692
|
const server = new _KernelSocket(this.net, this.domain);
|
|
3678
3693
|
server.local = addr.family === "inet" ? { ...addr, host: canonicalHost(addr.host) } : addr;
|
|
3679
3694
|
server.peer = this.local;
|
|
@@ -3687,7 +3702,34 @@ var KernelSocket = class _KernelSocket {
|
|
|
3687
3702
|
server.close();
|
|
3688
3703
|
throw new KernelError("ECONNREFUSED");
|
|
3689
3704
|
}
|
|
3690
|
-
|
|
3705
|
+
}
|
|
3706
|
+
async queued(addr, target, cred, stamp) {
|
|
3707
|
+
this.state = "connecting";
|
|
3708
|
+
const abort = new AbortController();
|
|
3709
|
+
this.dialing = abort;
|
|
3710
|
+
const timer = setTimeout(
|
|
3711
|
+
() => abort.abort(new KernelError("ETIMEDOUT")),
|
|
3712
|
+
this.net.backlogWaitMs
|
|
3713
|
+
);
|
|
3714
|
+
try {
|
|
3715
|
+
while (target.full) await target.waitRoom(abort.signal);
|
|
3716
|
+
if (abort.signal.aborted) throw abort.signal.reason;
|
|
3717
|
+
this.state = "open";
|
|
3718
|
+
this.join(addr, target, cred, stamp);
|
|
3719
|
+
this.dialing = void 0;
|
|
3720
|
+
} catch (e) {
|
|
3721
|
+
const reason = abort.signal.aborted ? abort.signal.reason : e;
|
|
3722
|
+
const error = reason instanceof KernelError ? reason : new KernelError("ECONNREFUSED");
|
|
3723
|
+
if (this.dialing === abort) {
|
|
3724
|
+
this.dialing = void 0;
|
|
3725
|
+
this.failed = error.code;
|
|
3726
|
+
if (this.state === "connecting") this.state = "open";
|
|
3727
|
+
this.changes.wake();
|
|
3728
|
+
}
|
|
3729
|
+
throw error;
|
|
3730
|
+
} finally {
|
|
3731
|
+
clearTimeout(timer);
|
|
3732
|
+
}
|
|
3691
3733
|
}
|
|
3692
3734
|
dial(addr, route) {
|
|
3693
3735
|
this.state = "connecting";
|
|
@@ -3788,6 +3830,7 @@ var KernelSocket = class _KernelSocket {
|
|
|
3788
3830
|
this.dialing = void 0;
|
|
3789
3831
|
if (was === "listening") {
|
|
3790
3832
|
for (const pending of this.queue.splice(0)) pending.close();
|
|
3833
|
+
this.room.wake();
|
|
3791
3834
|
}
|
|
3792
3835
|
if (this.link) {
|
|
3793
3836
|
if (!this.readShut) this.link.rx.closeRead();
|
|
@@ -3885,9 +3928,10 @@ var LoopbackNet = class {
|
|
|
3885
3928
|
socket.listen(backlog);
|
|
3886
3929
|
return socket;
|
|
3887
3930
|
}
|
|
3931
|
+
backlogWaitMs = DIAL_TIMEOUT_MS;
|
|
3888
3932
|
connect(addr) {
|
|
3889
3933
|
const socket = this.socket(addr.family);
|
|
3890
|
-
void socket.connect(addr, false);
|
|
3934
|
+
void socket.connect(addr, false, void 0, void 0, false);
|
|
3891
3935
|
return socket;
|
|
3892
3936
|
}
|
|
3893
3937
|
bind(socket, addr, kernel = false) {
|
|
@@ -8273,7 +8317,8 @@ var GEN = 0;
|
|
|
8273
8317
|
var RING = 1;
|
|
8274
8318
|
var RING_SIZE = 4096;
|
|
8275
8319
|
var SLOT = 2;
|
|
8276
|
-
var
|
|
8320
|
+
var DIRTY = RING + RING_SIZE * SLOT;
|
|
8321
|
+
var CHANGES_BYTES = (DIRTY + 1) * 4;
|
|
8277
8322
|
function changeHash(path) {
|
|
8278
8323
|
let h = 2166136261;
|
|
8279
8324
|
for (let i = 0; i < path.length; i++) {
|
|
@@ -8298,6 +8343,9 @@ var FileChanges = class {
|
|
|
8298
8343
|
this.sab = sab;
|
|
8299
8344
|
this.view = new Int32Array(sab);
|
|
8300
8345
|
}
|
|
8346
|
+
dirtied(delta) {
|
|
8347
|
+
Atomics.add(this.view, DIRTY, delta);
|
|
8348
|
+
}
|
|
8301
8349
|
publish(...paths) {
|
|
8302
8350
|
for (const path of paths) {
|
|
8303
8351
|
const g = Atomics.add(this.view, GEN, 1) + 1 | 0;
|
|
@@ -12136,7 +12184,7 @@ var PATH_OPS = new Set(SYNC_FS_OPS);
|
|
|
12136
12184
|
var EARLY_WHOLE_FILE = 64 * 1024;
|
|
12137
12185
|
|
|
12138
12186
|
// src/version.ts
|
|
12139
|
-
var KERNEL_VERSION = true ? "1.102.
|
|
12187
|
+
var KERNEL_VERSION = true ? "1.102.5" : "0.0.0-dev";
|
|
12140
12188
|
var OS_RELEASE = "6.0.0-slicc";
|
|
12141
12189
|
function procVersion() {
|
|
12142
12190
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -13391,7 +13439,8 @@ var KernelLoopback = class {
|
|
|
13391
13439
|
{ family: "inet", host: "127.0.0.1", port },
|
|
13392
13440
|
false,
|
|
13393
13441
|
this.cred(),
|
|
13394
|
-
this.stamp ? await this.stamp() : void 0
|
|
13442
|
+
this.stamp ? await this.stamp() : void 0,
|
|
13443
|
+
false
|
|
13395
13444
|
);
|
|
13396
13445
|
} catch (err) {
|
|
13397
13446
|
socket.close();
|
|
@@ -15017,6 +15066,15 @@ var VfsNode = class {
|
|
|
15017
15066
|
orphaned;
|
|
15018
15067
|
id;
|
|
15019
15068
|
onDirty;
|
|
15069
|
+
onDirtyState;
|
|
15070
|
+
counted = false;
|
|
15071
|
+
recount() {
|
|
15072
|
+
if (!this.onDirtyState) return;
|
|
15073
|
+
const on = this.dirty && !this.orphaned;
|
|
15074
|
+
if (on === this.counted) return;
|
|
15075
|
+
this.counted = on;
|
|
15076
|
+
this.onDirtyState?.(on);
|
|
15077
|
+
}
|
|
15020
15078
|
constructor(fs, path, contents2, orphaned = false, dirty = false, pin) {
|
|
15021
15079
|
this.fs = fs;
|
|
15022
15080
|
this.pin = pin;
|
|
@@ -15166,6 +15224,7 @@ var VfsNode = class {
|
|
|
15166
15224
|
}
|
|
15167
15225
|
markDirty() {
|
|
15168
15226
|
this.dirty = true;
|
|
15227
|
+
this.recount();
|
|
15169
15228
|
if (!this.orphaned) this.onDirty?.();
|
|
15170
15229
|
if (this.writeBack !== void 0 || this.orphaned) return;
|
|
15171
15230
|
const delay = Math.max(WRITEBACK_MS, this.writeBackCost * WRITEBACK_COST_FACTOR);
|
|
@@ -15193,6 +15252,8 @@ var VfsNode = class {
|
|
|
15193
15252
|
} catch (err) {
|
|
15194
15253
|
this.dirty = true;
|
|
15195
15254
|
throw err;
|
|
15255
|
+
} finally {
|
|
15256
|
+
this.recount();
|
|
15196
15257
|
}
|
|
15197
15258
|
this.writeBackCost = performance.now() - started;
|
|
15198
15259
|
}
|
|
@@ -15203,6 +15264,7 @@ var VfsNodes = class {
|
|
|
15203
15264
|
byId = /* @__PURE__ */ new Map();
|
|
15204
15265
|
keepsOnDisk = false;
|
|
15205
15266
|
changed;
|
|
15267
|
+
dirtied;
|
|
15206
15268
|
fs;
|
|
15207
15269
|
entries;
|
|
15208
15270
|
onClosed;
|
|
@@ -15286,6 +15348,7 @@ var VfsNodes = class {
|
|
|
15286
15348
|
}
|
|
15287
15349
|
orphan(node) {
|
|
15288
15350
|
node.orphaned = true;
|
|
15351
|
+
node.recount();
|
|
15289
15352
|
this.forget(node);
|
|
15290
15353
|
}
|
|
15291
15354
|
dropName(path, node) {
|
|
@@ -15340,6 +15403,8 @@ var VfsNodes = class {
|
|
|
15340
15403
|
create(path, id2, node) {
|
|
15341
15404
|
this.reshaped();
|
|
15342
15405
|
node.onDirty = () => this.changed?.(node.path);
|
|
15406
|
+
node.onDirtyState = (on) => this.dirtied?.(on ? 1 : -1);
|
|
15407
|
+
node.recount();
|
|
15343
15408
|
this.byPath.set(path, node);
|
|
15344
15409
|
if (id2 !== void 0) this.know(node, id2);
|
|
15345
15410
|
return node;
|
|
@@ -22556,6 +22621,7 @@ var Launcher = class {
|
|
|
22556
22621
|
}
|
|
22557
22622
|
processChain(fs, nodes, unlinked) {
|
|
22558
22623
|
nodes.changed = (path) => this.changes.publish(path);
|
|
22624
|
+
nodes.dirtied = (delta) => this.changes.dirtied(delta);
|
|
22559
22625
|
return unlinked.wrap(keepingOpen(fs, nodes, (path) => this.changes.publish(path)));
|
|
22560
22626
|
}
|
|
22561
22627
|
async starting(argv, dir, account, tag) {
|