@ai-ecoverse/slicc-kernel 1.110.0 → 1.110.1
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 +42 -4
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node-process-worker.js +1 -1
- package/dist/node.js +43 -4
- package/dist/node.js.map +3 -3
- package/dist/process-worker.js +1 -1
- package/dist/types/fs/opfs.d.ts +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -880,7 +880,7 @@ Not covered: hard links (OPFS cannot share contents between names; they work onl
|
|
|
880
880
|
|
|
881
881
|
Reads retry briefly when a concurrent write has invalidated the OPFS file snapshot (`NotReadableError`).
|
|
882
882
|
|
|
883
|
-
A kernel caches the directory handles it has walked and the sidecar entries it has read. Its own changes keep both caches current, and the other kernels on the origin hear of them through a `BroadcastChannel` named after the database (one for the sidecar, one for directories). A cached directory is checked against its path (`resolve()`) at most once a second before a lookup goes through it, so a directory moved, removed or replaced by another writer, such as a page using the OPFS API, is found at its new place or reported missing within a second.
|
|
883
|
+
A kernel caches the directory handles it has walked and the sidecar entries it has read. Its own changes keep both caches current, and the other kernels on the origin hear of them through a `BroadcastChannel` named after the database (one for the sidecar, one for directories). A cached directory is checked against its path (`resolve()`) at most once a second before a lookup goes through it, so a directory moved, removed or replaced by another writer, such as a page using the OPFS API, is found at its new place or reported missing within a second. It also keeps the file handles it has looked up (up to 4,096, the least recently used dropped first) for a second after each lookup. Before it uses one, it reads the file through it, which is the read a `stat` needs anyway, so a file another writer removed is missing at once and a rewritten one shows its new contents. One replaced by a directory is seen as a directory within a second. Its own changes, and the other kernels' notices, drop the handles they touch at once.
|
|
884
884
|
|
|
885
885
|
The filesystem is our own rather than [ZenFS](https://github.com/zen-fs/core) (which SLICC uses), because OPFS stays the single source of truth: other writers, such as the BIOS installing packages or a page writing files, need no index to stay consistent with, and nothing is preloaded into memory at mount. POSIX metadata lives in the IndexedDB sidecar described above, which has per-entry transactions instead of one JSON file rewritten on every change.
|
|
886
886
|
|
package/dist/kernel-worker.js
CHANGED
|
@@ -984,6 +984,8 @@ var S_ISGID2 = 1024;
|
|
|
984
984
|
var READ_ATTEMPTS = 3;
|
|
985
985
|
var MAX_LINKS2 = 40;
|
|
986
986
|
var CHECK_MS = 1e3;
|
|
987
|
+
var FILE_HANDLES = 4096;
|
|
988
|
+
var STALE = /* @__PURE__ */ new Set(["NotFoundError", "TypeMismatchError"]);
|
|
987
989
|
var EXECUTABLE = /\/node_modules\/(?:@[^/]+\/)?[^/]+\/bin\//;
|
|
988
990
|
var ERRNO_BY_DOM_ERROR = {
|
|
989
991
|
NotFoundError: "ENOENT",
|
|
@@ -1109,6 +1111,9 @@ var OpfsFs = class {
|
|
|
1109
1111
|
root;
|
|
1110
1112
|
meta;
|
|
1111
1113
|
dirs = new PathMap();
|
|
1114
|
+
files = new PathMap();
|
|
1115
|
+
snapshots = /* @__PURE__ */ new WeakMap();
|
|
1116
|
+
found = /* @__PURE__ */ new WeakMap();
|
|
1112
1117
|
checked = /* @__PURE__ */ new WeakMap();
|
|
1113
1118
|
channel;
|
|
1114
1119
|
remote;
|
|
@@ -1346,6 +1351,19 @@ var OpfsFs = class {
|
|
|
1346
1351
|
}
|
|
1347
1352
|
forget(path) {
|
|
1348
1353
|
this.dirs.deleteTree(path);
|
|
1354
|
+
this.files.deleteTree(path);
|
|
1355
|
+
}
|
|
1356
|
+
remember(path, handle, looked = false) {
|
|
1357
|
+
if (handle.kind !== "file") return handle;
|
|
1358
|
+
if (looked) {
|
|
1359
|
+
this.found.set(handle, performance.now());
|
|
1360
|
+
this.snapshots.delete(handle);
|
|
1361
|
+
}
|
|
1362
|
+
this.files.delete(path);
|
|
1363
|
+
if (this.files.size >= FILE_HANDLES)
|
|
1364
|
+
this.files.delete(this.files.keys().next().value);
|
|
1365
|
+
this.files.set(path, handle);
|
|
1366
|
+
return handle;
|
|
1349
1367
|
}
|
|
1350
1368
|
async inDir(path, op) {
|
|
1351
1369
|
const dir = await this.dir(path);
|
|
@@ -1369,16 +1387,30 @@ var OpfsFs = class {
|
|
|
1369
1387
|
}
|
|
1370
1388
|
async handle(path) {
|
|
1371
1389
|
if (split(path).length === 0) return this.root;
|
|
1390
|
+
const cached = this.files.get(path);
|
|
1391
|
+
const fresh2 = cached && performance.now() - (this.found.get(cached) ?? -CHECK_MS) < CHECK_MS;
|
|
1392
|
+
if (cached && !fresh2) this.files.delete(path);
|
|
1393
|
+
if (cached && fresh2) {
|
|
1394
|
+
try {
|
|
1395
|
+
this.snapshots.set(cached, await cached.getFile());
|
|
1396
|
+
return this.remember(path, cached);
|
|
1397
|
+
} catch (err) {
|
|
1398
|
+
if (!STALE.has(err?.name))
|
|
1399
|
+
throw translate(err, path, "read");
|
|
1400
|
+
this.files.delete(path);
|
|
1401
|
+
this.snapshots.delete(cached);
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1372
1404
|
const [dir, name2] = await this.parent(path);
|
|
1373
1405
|
const known = this.dirs.has(path);
|
|
1374
1406
|
return this.inDir(dir, async (parent) => {
|
|
1375
1407
|
const [first, second] = known ? ["directory", "file"] : ["file", "directory"];
|
|
1376
1408
|
try {
|
|
1377
|
-
return await this.child(parent, name2, first);
|
|
1409
|
+
return this.remember(path, await this.child(parent, name2, first), true);
|
|
1378
1410
|
} catch (err) {
|
|
1379
1411
|
if (err?.name !== "TypeMismatchError") throw err;
|
|
1380
1412
|
}
|
|
1381
|
-
return this.child(parent, name2, second);
|
|
1413
|
+
return this.remember(path, await this.child(parent, name2, second), true);
|
|
1382
1414
|
}).catch((err) => {
|
|
1383
1415
|
throw translate(err, path);
|
|
1384
1416
|
});
|
|
@@ -1521,9 +1553,15 @@ var OpfsFs = class {
|
|
|
1521
1553
|
if (this.dirTimes.get(path) === ms) this.dirTimes.delete(path);
|
|
1522
1554
|
}
|
|
1523
1555
|
}
|
|
1556
|
+
async snapshot(handle) {
|
|
1557
|
+
const taken = this.snapshots.get(handle);
|
|
1558
|
+
if (!taken) return handle.getFile();
|
|
1559
|
+
this.snapshots.delete(handle);
|
|
1560
|
+
return taken;
|
|
1561
|
+
}
|
|
1524
1562
|
async statOf(path, handle, meta, touched) {
|
|
1525
1563
|
const directory = handle.kind === "directory";
|
|
1526
|
-
const file = directory ? void 0 : await
|
|
1564
|
+
const file = directory ? void 0 : await this.snapshot(handle);
|
|
1527
1565
|
const modified = file?.lastModified ?? 0;
|
|
1528
1566
|
const kept = meta?.mtimeMs !== void 0 && meta.mtimeFor === modified ? meta.mtimeMs : modified;
|
|
1529
1567
|
const mtime = touched ?? kept;
|
|
@@ -6108,7 +6146,7 @@ function satisfies(version, range2) {
|
|
|
6108
6146
|
}
|
|
6109
6147
|
|
|
6110
6148
|
// src/version.ts
|
|
6111
|
-
var KERNEL_VERSION = true ? "1.110.
|
|
6149
|
+
var KERNEL_VERSION = true ? "1.110.1" : "0.0.0-dev";
|
|
6112
6150
|
var OS_RELEASE = "6.0.0-slicc";
|
|
6113
6151
|
function procVersion() {
|
|
6114
6152
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|