@ai-ecoverse/slicc-kernel 1.116.1 → 1.117.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 +19 -1
- package/dist/kernel-worker.js +147 -25
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node-process-worker.js +24 -8
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +147 -25
- package/dist/node.js.map +3 -3
- package/dist/process-worker.js +24 -8
- package/dist/process-worker.js.map +3 -3
- package/dist/types/fs/opfs.d.ts +1 -0
- package/dist/types/kernel/fd-table.d.ts +1 -0
- package/dist/types/kernel/host-ops.d.ts +10 -1
- package/dist/types/kernel/locks.d.ts +11 -0
- package/dist/types/kernel/process.d.ts +2 -0
- package/dist/types/process/wasi/slicc-lock.d.ts +3 -0
- package/dist/types/process/wasi/wasi-fds.d.ts +3 -2
- package/package.json +1 -1
package/dist/node.js
CHANGED
|
@@ -931,7 +931,8 @@ function openPipe(capacity) {
|
|
|
931
931
|
},
|
|
932
932
|
close: () => pipe.closeRead(),
|
|
933
933
|
poll: () => ({ readable: pipe.readReady, writable: false, hangup: pipe.writersGone }),
|
|
934
|
-
changed: (signal) => pipe.changed(signal)
|
|
934
|
+
changed: (signal) => pipe.changed(signal),
|
|
935
|
+
identity: pipe
|
|
935
936
|
}),
|
|
936
937
|
write: new OpenFile({
|
|
937
938
|
write: async (bytes, signal) => {
|
|
@@ -943,7 +944,8 @@ function openPipe(capacity) {
|
|
|
943
944
|
},
|
|
944
945
|
close: () => pipe.closeWrite(),
|
|
945
946
|
poll: () => ({ readable: false, writable: pipe.writeReady, hangup: pipe.readersGone }),
|
|
946
|
-
changed: (signal) => pipe.changed(signal)
|
|
947
|
+
changed: (signal) => pipe.changed(signal),
|
|
948
|
+
identity: pipe
|
|
947
949
|
})
|
|
948
950
|
};
|
|
949
951
|
}
|
|
@@ -4817,13 +4819,20 @@ var OpfsFs = class {
|
|
|
4817
4819
|
if (handle.kind === "directory") throw fsError("EISDIR", path);
|
|
4818
4820
|
return handle;
|
|
4819
4821
|
}
|
|
4822
|
+
async refuseNode(path, empty) {
|
|
4823
|
+
if (!empty) return;
|
|
4824
|
+
const [entry] = await this.meta.get([(await this.locate(path, true)).path]);
|
|
4825
|
+
if (entry?.fifo || entry?.socket) throw fsError("ENXIO", path);
|
|
4826
|
+
}
|
|
4820
4827
|
async readFileBuffer(path) {
|
|
4821
4828
|
const handle = await this.existing(path);
|
|
4822
|
-
|
|
4829
|
+
const bytes = await this.retrying(
|
|
4823
4830
|
path,
|
|
4824
4831
|
async () => new Uint8Array(await (await handle.getFile()).arrayBuffer()),
|
|
4825
4832
|
false
|
|
4826
4833
|
);
|
|
4834
|
+
await this.refuseNode(path, bytes.length === 0);
|
|
4835
|
+
return bytes;
|
|
4827
4836
|
}
|
|
4828
4837
|
async readVersioned(path, cached = false) {
|
|
4829
4838
|
const handle = await this.existing(path);
|
|
@@ -4833,6 +4842,7 @@ var OpfsFs = class {
|
|
|
4833
4842
|
const stamp = await this.stamp(path, cached);
|
|
4834
4843
|
const file = await handle.getFile();
|
|
4835
4844
|
const bytes = new Uint8Array(await file.arrayBuffer());
|
|
4845
|
+
await this.refuseNode(path, bytes.length === 0);
|
|
4836
4846
|
return { bytes, version: `${file.lastModified}:${file.size}:${stamp}` };
|
|
4837
4847
|
},
|
|
4838
4848
|
false
|
|
@@ -4854,7 +4864,11 @@ var OpfsFs = class {
|
|
|
4854
4864
|
const handle = await this.existing(path);
|
|
4855
4865
|
return this.retrying(
|
|
4856
4866
|
path,
|
|
4857
|
-
async () =>
|
|
4867
|
+
async () => {
|
|
4868
|
+
const file = await handle.getFile();
|
|
4869
|
+
await this.refuseNode(path, file.size === 0);
|
|
4870
|
+
return new Uint8Array(await file.slice(offset, offset + length2).arrayBuffer());
|
|
4871
|
+
},
|
|
4858
4872
|
false
|
|
4859
4873
|
);
|
|
4860
4874
|
}
|
|
@@ -4870,6 +4884,7 @@ var OpfsFs = class {
|
|
|
4870
4884
|
}
|
|
4871
4885
|
async truncate(path, size) {
|
|
4872
4886
|
const handle = await this.existing(path, true);
|
|
4887
|
+
await this.refuseNode(path, (await handle.getFile()).size === 0);
|
|
4873
4888
|
const resolve2 = this.ranged || this.remote?.watched();
|
|
4874
4889
|
const target = resolve2 || this.counted.length > 0 ? (await this.locate(path, true)).path : path;
|
|
4875
4890
|
await this.counting(target);
|
|
@@ -4922,6 +4937,10 @@ var OpfsFs = class {
|
|
|
4922
4937
|
}
|
|
4923
4938
|
async fileFor(path) {
|
|
4924
4939
|
const [target, existed] = await this.writeTarget(path);
|
|
4940
|
+
if (existed) {
|
|
4941
|
+
const [entry] = await this.meta.get([target]);
|
|
4942
|
+
if (entry?.fifo || entry?.socket) throw fsError("ENXIO", path);
|
|
4943
|
+
}
|
|
4925
4944
|
const [dir, name2] = await this.parent(target);
|
|
4926
4945
|
try {
|
|
4927
4946
|
const handle = await this.inDir(
|
|
@@ -6559,7 +6578,7 @@ function satisfies(version, range2) {
|
|
|
6559
6578
|
}
|
|
6560
6579
|
|
|
6561
6580
|
// src/version.ts
|
|
6562
|
-
var KERNEL_VERSION = true ? "1.
|
|
6581
|
+
var KERNEL_VERSION = true ? "1.117.0" : "0.0.0-dev";
|
|
6563
6582
|
var OS_RELEASE = "6.0.0-slicc";
|
|
6564
6583
|
function procVersion() {
|
|
6565
6584
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -9703,6 +9722,7 @@ var FifoTable = class {
|
|
|
9703
9722
|
let open = true;
|
|
9704
9723
|
return new OpenFile({
|
|
9705
9724
|
fifo: path,
|
|
9725
|
+
identity: fifo,
|
|
9706
9726
|
...reads ? {
|
|
9707
9727
|
read: async (max, signal) => {
|
|
9708
9728
|
try {
|
|
@@ -13136,7 +13156,71 @@ function lockRange(start2, len) {
|
|
|
13136
13156
|
if (from < 0) throw new KernelError("EINVAL");
|
|
13137
13157
|
return { start: from, end };
|
|
13138
13158
|
}
|
|
13159
|
+
function changedAt(wakers, key, signal) {
|
|
13160
|
+
return new Promise((resolve2, reject) => {
|
|
13161
|
+
const set3 = wakers.get(key) ?? /* @__PURE__ */ new Set();
|
|
13162
|
+
wakers.set(key, set3);
|
|
13163
|
+
const done4 = () => {
|
|
13164
|
+
set3.delete(wake);
|
|
13165
|
+
if (set3.size === 0 && wakers.get(key) === set3) wakers.delete(key);
|
|
13166
|
+
signal.removeEventListener("abort", abort);
|
|
13167
|
+
};
|
|
13168
|
+
const wake = () => {
|
|
13169
|
+
done4();
|
|
13170
|
+
resolve2();
|
|
13171
|
+
};
|
|
13172
|
+
const abort = () => {
|
|
13173
|
+
done4();
|
|
13174
|
+
reject(new KernelError("EINTR"));
|
|
13175
|
+
};
|
|
13176
|
+
set3.add(wake);
|
|
13177
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
13178
|
+
});
|
|
13179
|
+
}
|
|
13180
|
+
function wakeAt(wakers, key) {
|
|
13181
|
+
for (const wake of [...wakers.get(key) ?? []]) wake();
|
|
13182
|
+
}
|
|
13183
|
+
var FlockTable = class {
|
|
13184
|
+
held = /* @__PURE__ */ new Map();
|
|
13185
|
+
keys = /* @__PURE__ */ new WeakMap();
|
|
13186
|
+
wakers = /* @__PURE__ */ new Map();
|
|
13187
|
+
free(key, owner, kind) {
|
|
13188
|
+
for (const [other, has] of this.held.get(key) ?? [])
|
|
13189
|
+
if (other !== owner && (kind === "exclusive" || has === "exclusive")) return false;
|
|
13190
|
+
return true;
|
|
13191
|
+
}
|
|
13192
|
+
set(key, owner, kind) {
|
|
13193
|
+
const has = this.held.get(key)?.get(owner);
|
|
13194
|
+
if (has === kind) return true;
|
|
13195
|
+
if (has !== void 0) this.drop(owner);
|
|
13196
|
+
if (kind === "unlock") return true;
|
|
13197
|
+
if (!this.free(key, owner, kind)) return false;
|
|
13198
|
+
const holders = this.held.get(key) ?? /* @__PURE__ */ new Map();
|
|
13199
|
+
holders.set(owner, kind);
|
|
13200
|
+
this.held.set(key, holders);
|
|
13201
|
+
this.keys.set(owner, key);
|
|
13202
|
+
return true;
|
|
13203
|
+
}
|
|
13204
|
+
async wait(key, owner, kind, blocking) {
|
|
13205
|
+
if (this.set(key, owner, kind)) return;
|
|
13206
|
+
const signal = blocking();
|
|
13207
|
+
while (!this.set(key, owner, kind)) {
|
|
13208
|
+
if (signal.aborted) throw new KernelError("EINTR");
|
|
13209
|
+
await changedAt(this.wakers, key, signal);
|
|
13210
|
+
}
|
|
13211
|
+
}
|
|
13212
|
+
drop(owner) {
|
|
13213
|
+
const key = this.keys.get(owner);
|
|
13214
|
+
if (key === void 0) return;
|
|
13215
|
+
this.keys.delete(owner);
|
|
13216
|
+
const holders = this.held.get(key);
|
|
13217
|
+
holders?.delete(owner);
|
|
13218
|
+
if (holders?.size === 0) this.held.delete(key);
|
|
13219
|
+
wakeAt(this.wakers, key);
|
|
13220
|
+
}
|
|
13221
|
+
};
|
|
13139
13222
|
var LockTable = class {
|
|
13223
|
+
flocks = new FlockTable();
|
|
13140
13224
|
records = /* @__PURE__ */ new Map();
|
|
13141
13225
|
blocked = /* @__PURE__ */ new Map();
|
|
13142
13226
|
wakers = /* @__PURE__ */ new Map();
|
|
@@ -13194,28 +13278,10 @@ var LockTable = class {
|
|
|
13194
13278
|
return false;
|
|
13195
13279
|
}
|
|
13196
13280
|
changed(key, signal) {
|
|
13197
|
-
return
|
|
13198
|
-
const set3 = this.wakers.get(key) ?? /* @__PURE__ */ new Set();
|
|
13199
|
-
this.wakers.set(key, set3);
|
|
13200
|
-
const done4 = () => {
|
|
13201
|
-
set3.delete(wake);
|
|
13202
|
-
if (set3.size === 0 && this.wakers.get(key) === set3) this.wakers.delete(key);
|
|
13203
|
-
signal.removeEventListener("abort", abort);
|
|
13204
|
-
};
|
|
13205
|
-
const wake = () => {
|
|
13206
|
-
done4();
|
|
13207
|
-
resolve2();
|
|
13208
|
-
};
|
|
13209
|
-
const abort = () => {
|
|
13210
|
-
done4();
|
|
13211
|
-
reject(new KernelError("EINTR"));
|
|
13212
|
-
};
|
|
13213
|
-
set3.add(wake);
|
|
13214
|
-
signal.addEventListener("abort", abort, { once: true });
|
|
13215
|
-
});
|
|
13281
|
+
return changedAt(this.wakers, key, signal);
|
|
13216
13282
|
}
|
|
13217
13283
|
wake(key) {
|
|
13218
|
-
|
|
13284
|
+
wakeAt(this.wakers, key);
|
|
13219
13285
|
}
|
|
13220
13286
|
store(key, locks) {
|
|
13221
13287
|
if (locks.length === 0) this.records.delete(key);
|
|
@@ -13280,6 +13346,7 @@ var HOST_OPS = [
|
|
|
13280
13346
|
"lk-set",
|
|
13281
13347
|
"lk-get",
|
|
13282
13348
|
"lk-close",
|
|
13349
|
+
"flock",
|
|
13283
13350
|
"async-submit",
|
|
13284
13351
|
"async-wait",
|
|
13285
13352
|
"async-take",
|
|
@@ -13432,6 +13499,8 @@ async function hostSyscall(req, ctx) {
|
|
|
13432
13499
|
case "lk-get":
|
|
13433
13500
|
case "lk-close":
|
|
13434
13501
|
return recordLock2(req, ctx);
|
|
13502
|
+
case "flock":
|
|
13503
|
+
return flock(req, ctx);
|
|
13435
13504
|
case "async-submit":
|
|
13436
13505
|
if (!ctx.valid(req.req)) throw new KernelError("EINVAL");
|
|
13437
13506
|
if (req.ack) ctx.ops.ack(req.ack);
|
|
@@ -13454,6 +13523,17 @@ async function hostSyscall(req, ctx) {
|
|
|
13454
13523
|
return done2;
|
|
13455
13524
|
}
|
|
13456
13525
|
}
|
|
13526
|
+
var FLOCK_KINDS = /* @__PURE__ */ new Set(["shared", "exclusive", "unlock"]);
|
|
13527
|
+
async function flock(req, ctx) {
|
|
13528
|
+
const { locks, flockOf } = ctx;
|
|
13529
|
+
if (!locks || !flockOf) throw new KernelError("ENOLCK");
|
|
13530
|
+
if (!FLOCK_KINDS.has(req.kind)) throw new KernelError("EINVAL");
|
|
13531
|
+
const { key, owner } = await flockOf(req.fd);
|
|
13532
|
+
if (req.kind !== "unlock" && req.wait)
|
|
13533
|
+
await locks.flocks.wait(key, owner, req.kind, ctx.blocking);
|
|
13534
|
+
else if (!locks.flocks.set(key, owner, req.kind)) throw new KernelError("EAGAIN");
|
|
13535
|
+
return done2;
|
|
13536
|
+
}
|
|
13457
13537
|
async function recordLock2(req, ctx) {
|
|
13458
13538
|
const { locks, fileKey } = ctx;
|
|
13459
13539
|
if (!locks || !fileKey) throw new KernelError("ENOLCK");
|
|
@@ -17424,6 +17504,18 @@ var fileKeys = /* @__PURE__ */ new WeakMap();
|
|
|
17424
17504
|
function identityKey(st, path) {
|
|
17425
17505
|
return st.ino === void 0 ? path : `${st.dev ?? 0}:${st.ino}`;
|
|
17426
17506
|
}
|
|
17507
|
+
var objectIds = /* @__PURE__ */ new WeakMap();
|
|
17508
|
+
var nextObjectId = 1;
|
|
17509
|
+
function objectKey(file) {
|
|
17510
|
+
const at = file.tty ?? file.identity ?? file.pty ?? file;
|
|
17511
|
+
let id2 = objectIds.get(at);
|
|
17512
|
+
if (id2 === void 0) {
|
|
17513
|
+
id2 = nextObjectId++;
|
|
17514
|
+
objectIds.set(at, id2);
|
|
17515
|
+
}
|
|
17516
|
+
return `object:${id2}`;
|
|
17517
|
+
}
|
|
17518
|
+
var flockHooked = /* @__PURE__ */ new WeakSet();
|
|
17427
17519
|
var DYING = { ok: false, errno: "EINTR", message: "the process is being killed" };
|
|
17428
17520
|
var HOSTS_ONLY = new Resolver({ routes: new Routes() });
|
|
17429
17521
|
function timeLeft(req, started) {
|
|
@@ -17724,6 +17816,7 @@ var WasmProcess = class {
|
|
|
17724
17816
|
pid: this.pid,
|
|
17725
17817
|
owner: () => this.lockOwner(),
|
|
17726
17818
|
fileKey: (target, kind, setting) => this.lockKey(target, kind, setting),
|
|
17819
|
+
flockOf: (fd) => this.flockOf(fd),
|
|
17727
17820
|
locks: this.options.locks,
|
|
17728
17821
|
ops: this.asyncOps,
|
|
17729
17822
|
blocking: () => this.blockingSignal(cancelled),
|
|
@@ -17792,6 +17885,7 @@ var WasmProcess = class {
|
|
|
17792
17885
|
throw new KernelError("EBADF");
|
|
17793
17886
|
const known = file ? fileKeys.get(file) : this.pathKeys.get(target.path ?? "");
|
|
17794
17887
|
if (kind === "close" && !file && target.path !== void 0) this.pathKeys.delete(target.path);
|
|
17888
|
+
if (access2 && !access2.stat) return objectKey(access2);
|
|
17795
17889
|
const want = kind === "read" ? R_OK : kind === "write" ? W_OK : 0;
|
|
17796
17890
|
const path = await this.lockPath(target, want);
|
|
17797
17891
|
if (known !== void 0) return known;
|
|
@@ -17806,6 +17900,33 @@ var WasmProcess = class {
|
|
|
17806
17900
|
else if (this.pathKeys.size < 4096) this.pathKeys.set(path, key);
|
|
17807
17901
|
return key;
|
|
17808
17902
|
}
|
|
17903
|
+
async flockOf(fd) {
|
|
17904
|
+
const open = this.fds.get(fd);
|
|
17905
|
+
const { locks } = this.options;
|
|
17906
|
+
if (locks && !flockHooked.has(open)) {
|
|
17907
|
+
flockHooked.add(open);
|
|
17908
|
+
open.onClose(() => locks.flocks.drop(open));
|
|
17909
|
+
}
|
|
17910
|
+
return { key: await this.objectKeyOf(open), owner: open };
|
|
17911
|
+
}
|
|
17912
|
+
async objectKeyOf(open) {
|
|
17913
|
+
const { file } = open;
|
|
17914
|
+
const meta = file.heldMeta;
|
|
17915
|
+
if (meta && "device" in meta) return `device:${meta.device}`;
|
|
17916
|
+
if (meta && "dir" in meta) {
|
|
17917
|
+
const st2 = await this.options.fs.stat?.(meta.dir).catch(() => void 0);
|
|
17918
|
+
return st2 ? identityKey(st2, meta.dir) : objectKey(file);
|
|
17919
|
+
}
|
|
17920
|
+
const known = fileKeys.get(open);
|
|
17921
|
+
if (known !== void 0) return known;
|
|
17922
|
+
const vfs = await file.stat?.().catch(() => void 0);
|
|
17923
|
+
if (!vfs || vfs.orphan) return objectKey(file);
|
|
17924
|
+
const st = await this.options.fs.stat?.(vfs.path).catch(() => void 0);
|
|
17925
|
+
if (!st) return objectKey(file);
|
|
17926
|
+
const key = identityKey(st, vfs.path);
|
|
17927
|
+
fileKeys.set(open, key);
|
|
17928
|
+
return key;
|
|
17929
|
+
}
|
|
17809
17930
|
async dropRecordLocks(fd) {
|
|
17810
17931
|
const { locks } = this.options;
|
|
17811
17932
|
const owner = this.options.jobs?.shown(this.pid) ?? this.pid;
|
|
@@ -20086,6 +20207,7 @@ function scrubbed(inner, scrubber, idleMs = SCRUB_IDLE_MS) {
|
|
|
20086
20207
|
},
|
|
20087
20208
|
changed,
|
|
20088
20209
|
...file.tty ? { tty: file.tty } : {},
|
|
20210
|
+
identity: file.identity ?? file,
|
|
20089
20211
|
...file.clipboard ? { clipboard: file.clipboard } : {},
|
|
20090
20212
|
...file.write ? {
|
|
20091
20213
|
write: async (bytes, signal) => {
|