@ai-ecoverse/slicc-kernel 1.57.0 → 1.58.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 +4 -3
- package/dist/driver-worker.js +3 -0
- package/dist/driver-worker.js.map +2 -2
- package/dist/driver.js +3 -0
- package/dist/driver.js.map +2 -2
- package/dist/index.js.map +2 -2
- package/dist/kernel-worker.js +290 -111
- package/dist/kernel-worker.js.map +4 -4
- package/dist/node-driver-worker.js +3 -0
- package/dist/node-driver-worker.js.map +2 -2
- package/dist/node-process-worker.js +459 -107
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +290 -111
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +459 -107
- package/dist/process-worker.js.map +3 -3
- package/package.json +1 -1
package/dist/process-worker.js
CHANGED
|
@@ -600,11 +600,54 @@ function toMs(v) {
|
|
|
600
600
|
if (v === void 0 || v === null) return void 0;
|
|
601
601
|
return v instanceof Date ? v.getTime() : v;
|
|
602
602
|
}
|
|
603
|
+
function linkedStates(bridgeOf) {
|
|
604
|
+
const opens = /* @__PURE__ */ new Map();
|
|
605
|
+
const byId = /* @__PURE__ */ new Map();
|
|
606
|
+
const idOf2 = (st) => st?.ino === void 0 || (st.nlink ?? 1) < 2 ? void 0 : `${st.dev}:${st.ino}`;
|
|
607
|
+
function know(s, id) {
|
|
608
|
+
s.id = id;
|
|
609
|
+
if (!byId.has(id)) byId.set(id, s);
|
|
610
|
+
}
|
|
611
|
+
function opening(node, on) {
|
|
612
|
+
const s = node.live;
|
|
613
|
+
if (!on) {
|
|
614
|
+
opens.delete(s);
|
|
615
|
+
if (s.id !== void 0 && byId.get(s.id) === s) byId.delete(s.id);
|
|
616
|
+
s.id = void 0;
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
opens.set(s, node);
|
|
620
|
+
const id = idOf2(s.stat);
|
|
621
|
+
if (id !== void 0) know(s, id);
|
|
622
|
+
}
|
|
623
|
+
function sharedWith(node) {
|
|
624
|
+
const st = node.live.stat;
|
|
625
|
+
if (st?.ino === void 0) return void 0;
|
|
626
|
+
const id = `${st.dev}:${st.ino}`;
|
|
627
|
+
if (!byId.has(id) && idOf2(st) !== void 0) {
|
|
628
|
+
for (const [s2, other] of opens) {
|
|
629
|
+
if (s2.id !== void 0 || s2.orphan) continue;
|
|
630
|
+
let st2;
|
|
631
|
+
try {
|
|
632
|
+
st2 = bridgeOf(other).lstat(liveNodePath(other));
|
|
633
|
+
} catch {
|
|
634
|
+
}
|
|
635
|
+
const known = idOf2(st2);
|
|
636
|
+
if (known !== void 0) know(s2, known);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
const s = byId.get(id);
|
|
640
|
+
return s && s !== node.live && !stale(s) ? s : void 0;
|
|
641
|
+
}
|
|
642
|
+
const holder = (node) => opens.get(node.live) ?? node;
|
|
643
|
+
return { opening, sharedWith, know, idOf: idOf2, holder };
|
|
644
|
+
}
|
|
603
645
|
function createHelpers(Fs, ops) {
|
|
604
646
|
const bridgeOf = (node) => node.mount.opts.bridge;
|
|
605
647
|
const fileIo = (node) => pinnedIo(bridgeOf(node), node.live.handle);
|
|
606
648
|
const dirty = /* @__PURE__ */ new Set();
|
|
607
649
|
const handled = /* @__PURE__ */ new Set();
|
|
650
|
+
const linked = linkedStates(bridgeOf);
|
|
608
651
|
function markDirty(node) {
|
|
609
652
|
node.live.dirty = true;
|
|
610
653
|
dirty.add(node);
|
|
@@ -612,7 +655,7 @@ function createHelpers(Fs, ops) {
|
|
|
612
655
|
function flushDirty() {
|
|
613
656
|
for (const node of [...dirty]) {
|
|
614
657
|
const s = node.live;
|
|
615
|
-
if (!s.dirty || s
|
|
658
|
+
if (!s.dirty || stale(s)) {
|
|
616
659
|
dirty.delete(node);
|
|
617
660
|
continue;
|
|
618
661
|
}
|
|
@@ -654,7 +697,7 @@ function createHelpers(Fs, ops) {
|
|
|
654
697
|
return { ...node.live.stat, size };
|
|
655
698
|
}
|
|
656
699
|
if (!node.live.stat) {
|
|
657
|
-
const st = call2(() => bridgeOf(node).lstat(liveNodePath(node)));
|
|
700
|
+
const st = call2(() => bridgeOf(node).lstat(liveNodePath(linked.holder(node))));
|
|
658
701
|
node.live.stat = st;
|
|
659
702
|
node.mode = modeFromStat(st);
|
|
660
703
|
}
|
|
@@ -667,7 +710,7 @@ function createHelpers(Fs, ops) {
|
|
|
667
710
|
function ensureLoaded(node) {
|
|
668
711
|
const s = node.live;
|
|
669
712
|
if (s.loaded) return;
|
|
670
|
-
const bytes = call2(() => fileIo(node).readFile(liveNodePath(node)));
|
|
713
|
+
const bytes = call2(() => fileIo(node).readFile(liveNodePath(linked.holder(node))));
|
|
671
714
|
s.data = bytes;
|
|
672
715
|
s.len = bytes.length;
|
|
673
716
|
s.loaded = true;
|
|
@@ -676,7 +719,7 @@ function createHelpers(Fs, ops) {
|
|
|
676
719
|
const s = node.live;
|
|
677
720
|
if (s.ranged || !s.ranges) return s.ranged;
|
|
678
721
|
const bridge = bridgeOf(node);
|
|
679
|
-
const path = () => liveNodePath(node);
|
|
722
|
+
const path = () => liveNodePath(linked.holder(node));
|
|
680
723
|
const file = () => fileIo(node);
|
|
681
724
|
const io = {
|
|
682
725
|
pread: (_, at, n, version) => file().pread(path(), at, n, version),
|
|
@@ -698,11 +741,11 @@ function createHelpers(Fs, ops) {
|
|
|
698
741
|
}
|
|
699
742
|
function flushNode(node) {
|
|
700
743
|
const s = node.live;
|
|
701
|
-
if (!s.dirty || s
|
|
744
|
+
if (!s.dirty || stale(s) || !(s.data || s.ranged)) return;
|
|
702
745
|
if (s.ranged) call2(() => s.ranged?.flush());
|
|
703
746
|
else {
|
|
704
747
|
const bytes = s.data.slice(0, s.len);
|
|
705
|
-
call2(() => fileIo(node).writeFile(liveNodePath(node), bytes, true));
|
|
748
|
+
call2(() => fileIo(node).writeFile(liveNodePath(linked.holder(node)), bytes, true));
|
|
706
749
|
}
|
|
707
750
|
s.dirty = false;
|
|
708
751
|
s.stat = void 0;
|
|
@@ -750,6 +793,7 @@ function createHelpers(Fs, ops) {
|
|
|
750
793
|
Fs,
|
|
751
794
|
bridgeOf,
|
|
752
795
|
handled,
|
|
796
|
+
linked,
|
|
753
797
|
call: call2,
|
|
754
798
|
metadataCall,
|
|
755
799
|
makeNode,
|
|
@@ -764,6 +808,33 @@ function createHelpers(Fs, ops) {
|
|
|
764
808
|
truncate
|
|
765
809
|
};
|
|
766
810
|
}
|
|
811
|
+
function freshStat(h, node) {
|
|
812
|
+
const { statOf } = h;
|
|
813
|
+
const st = statOf(node);
|
|
814
|
+
if (!st.linkable) return st;
|
|
815
|
+
node.live.stat = void 0;
|
|
816
|
+
return statOf(node);
|
|
817
|
+
}
|
|
818
|
+
function orphaned(h, node, st) {
|
|
819
|
+
const { bridgeOf } = h;
|
|
820
|
+
const s = node.live;
|
|
821
|
+
const nlink = st.nlink ?? 1;
|
|
822
|
+
let kept = false;
|
|
823
|
+
try {
|
|
824
|
+
kept = nlink > 1 && s.handle !== void 0 && bridgeOf(node).kept?.(s.handle) === true;
|
|
825
|
+
} catch {
|
|
826
|
+
}
|
|
827
|
+
if (nlink > 1 && !kept && h.linked.holder(node) !== node) {
|
|
828
|
+
s.stat = void 0;
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
s.orphan = true;
|
|
832
|
+
if (!kept) return;
|
|
833
|
+
s.kept = true;
|
|
834
|
+
s.stat = { ...st, nlink: nlink - 1 };
|
|
835
|
+
const id = h.linked.idOf(st);
|
|
836
|
+
if (id !== void 0) h.linked.know(s, id);
|
|
837
|
+
}
|
|
767
838
|
function createNodeOps(h) {
|
|
768
839
|
const { Fs, bridgeOf, call: call2, metadataCall, makeNode, statOf, childPath, flushNode, truncate } = h;
|
|
769
840
|
const { ensureLoaded } = h;
|
|
@@ -794,7 +865,7 @@ function createNodeOps(h) {
|
|
|
794
865
|
dev: st.dev ?? 1,
|
|
795
866
|
ino: st.ino ?? inodeOf(liveNodePath(node)),
|
|
796
867
|
mode: node.mode,
|
|
797
|
-
nlink: 1,
|
|
868
|
+
nlink: st.nlink ?? 1,
|
|
798
869
|
uid: owned ? st.uid ?? 0 : 0,
|
|
799
870
|
gid: owned ? st.gid ?? 0 : 0,
|
|
800
871
|
rdev: 0,
|
|
@@ -889,14 +960,14 @@ function createNodeOps(h) {
|
|
|
889
960
|
if (node && node.live?.openCount > 0 && Fs.isFile(node.mode)) open = node;
|
|
890
961
|
} catch {
|
|
891
962
|
}
|
|
963
|
+
const st = open && freshStat(h, open);
|
|
892
964
|
if (open) {
|
|
893
|
-
statOf(open);
|
|
894
965
|
const ranged = h.rangedOf(open);
|
|
895
966
|
if (ranged) ranged.pin();
|
|
896
967
|
else ensureLoaded(open);
|
|
897
968
|
}
|
|
898
969
|
call2(() => bridgeOf(parent).unlink(childPath(parent, name2)));
|
|
899
|
-
if (open) open
|
|
970
|
+
if (open && st) orphaned(h, open, st);
|
|
900
971
|
},
|
|
901
972
|
rmdir(parent, name2) {
|
|
902
973
|
parent.live.listed = void 0;
|
|
@@ -944,6 +1015,7 @@ function createStreamOps(h) {
|
|
|
944
1015
|
try {
|
|
945
1016
|
const handle = bridgeOf(node).hold?.(liveNodePath(node), on, true, s.handle);
|
|
946
1017
|
s.handle = on ? handle : void 0;
|
|
1018
|
+
h.linked.opening(node, on);
|
|
947
1019
|
if (s.handle === void 0) h.handled.delete(node);
|
|
948
1020
|
else h.handled.add(node);
|
|
949
1021
|
} catch {
|
|
@@ -956,7 +1028,9 @@ function createStreamOps(h) {
|
|
|
956
1028
|
if (s.openCount === 0 && !s.orphan) {
|
|
957
1029
|
const bridge = bridgeOf(stream.node);
|
|
958
1030
|
s.ranges = !!(bridge.pread && bridge.pwrite && bridge.truncate && statOf(stream.node).ranged);
|
|
959
|
-
|
|
1031
|
+
const shared = h.linked.sharedWith(stream.node);
|
|
1032
|
+
if (shared) stream.node.live = shared;
|
|
1033
|
+
else rangedOf(stream.node);
|
|
960
1034
|
}
|
|
961
1035
|
if ((stream.flags & 3) !== 0) {
|
|
962
1036
|
try {
|
|
@@ -1278,7 +1352,7 @@ function useLiveChown(Fs) {
|
|
|
1278
1352
|
Fs.chown(target, uid, gid);
|
|
1279
1353
|
};
|
|
1280
1354
|
}
|
|
1281
|
-
var S_IFDIR, S_IFREG, S_IFLNK, PERM_MASK, DEFAULT_DIR_PERM, UMASK, SEEK_CUR, SEEK_END, EARLY_WHOLE_FILE;
|
|
1355
|
+
var S_IFDIR, S_IFREG, S_IFLNK, PERM_MASK, DEFAULT_DIR_PERM, UMASK, SEEK_CUR, SEEK_END, EARLY_WHOLE_FILE, stale;
|
|
1282
1356
|
var init_live_vfs_fs = __esm({
|
|
1283
1357
|
"src/realm/live-vfs-fs.ts"() {
|
|
1284
1358
|
"use strict";
|
|
@@ -1294,6 +1368,7 @@ var init_live_vfs_fs = __esm({
|
|
|
1294
1368
|
SEEK_CUR = 1;
|
|
1295
1369
|
SEEK_END = 2;
|
|
1296
1370
|
EARLY_WHOLE_FILE = 64 * 1024;
|
|
1371
|
+
stale = (s) => !!s.orphan && !s.kept;
|
|
1297
1372
|
}
|
|
1298
1373
|
});
|
|
1299
1374
|
|
|
@@ -1369,10 +1444,12 @@ function parseSyncFsStat(json) {
|
|
|
1369
1444
|
...typeof s.atimeMs === "number" ? { atimeMs: s.atimeMs } : {},
|
|
1370
1445
|
...typeof s.ctimeMs === "number" ? { ctimeMs: s.ctimeMs } : {},
|
|
1371
1446
|
...typeof s.ino === "number" ? { ino: s.ino } : {},
|
|
1447
|
+
...typeof s.nlink === "number" ? { nlink: s.nlink } : {},
|
|
1372
1448
|
...typeof s.dev === "number" ? { dev: s.dev } : {},
|
|
1373
1449
|
...s.readonly === true ? { readonly: true } : {},
|
|
1374
1450
|
...typeof s.maxFile === "number" ? { maxFile: s.maxFile } : {},
|
|
1375
1451
|
...s.ranged === true ? { ranged: true } : {},
|
|
1452
|
+
...s.linkable === true ? { linkable: true } : {},
|
|
1376
1453
|
...typeof s.version === "string" ? { version: s.version } : {},
|
|
1377
1454
|
...typeof s.uid === "number" ? { uid: s.uid } : {},
|
|
1378
1455
|
...typeof s.gid === "number" ? { gid: s.gid } : {}
|
|
@@ -1393,6 +1470,7 @@ var init_sync_fs_wire = __esm({
|
|
|
1393
1470
|
"mkdir",
|
|
1394
1471
|
"rm",
|
|
1395
1472
|
"rename",
|
|
1473
|
+
"link",
|
|
1396
1474
|
"unlink",
|
|
1397
1475
|
"rmdir",
|
|
1398
1476
|
"symlink",
|
|
@@ -1639,6 +1717,9 @@ function createSyncFsSabBridge(transport, opts = {}) {
|
|
|
1639
1717
|
rename: (from, to) => {
|
|
1640
1718
|
run({ op: "rename", path: from, arg2: to }, from);
|
|
1641
1719
|
},
|
|
1720
|
+
link: (from, to, follow2) => {
|
|
1721
|
+
run({ op: "link", path: from, arg2: to, ...follow2 ? { mode: 1 } : {} }, from);
|
|
1722
|
+
},
|
|
1642
1723
|
unlink: (path) => {
|
|
1643
1724
|
run({ op: "unlink", path }, path);
|
|
1644
1725
|
},
|
|
@@ -4555,10 +4636,26 @@ function pathInode(path) {
|
|
|
4555
4636
|
}
|
|
4556
4637
|
return h;
|
|
4557
4638
|
}
|
|
4558
|
-
function
|
|
4559
|
-
|
|
4560
|
-
|
|
4639
|
+
function inoKey(st) {
|
|
4640
|
+
return "ino" in st && typeof st.ino === "number" ? st.ino % 4294967296 | 0 : 0;
|
|
4641
|
+
}
|
|
4642
|
+
function pathHash(path) {
|
|
4643
|
+
let h = 2166136261;
|
|
4644
|
+
for (let i = 0; i < path.length; i++) h = Math.imul(h ^ path.charCodeAt(i), 16777619);
|
|
4645
|
+
return h === 0 ? 1 : h;
|
|
4646
|
+
}
|
|
4647
|
+
function index(map, key, path) {
|
|
4648
|
+
const paths = map.get(key) ?? /* @__PURE__ */ new Set();
|
|
4649
|
+
paths.add(path);
|
|
4650
|
+
map.set(key, paths);
|
|
4651
|
+
}
|
|
4652
|
+
function cachingBridge(bridge, now = () => performance.now(), shared) {
|
|
4653
|
+
const blind = shared !== void 0 && shared.length * 4 < SHARED_IDS_BYTES;
|
|
4654
|
+
const cache = new StatCache(blind ? void 0 : shared);
|
|
4655
|
+
const { stats, lstats } = cache;
|
|
4561
4656
|
const cached = (map, path, get) => {
|
|
4657
|
+
if (blind) return get();
|
|
4658
|
+
cache.fresh();
|
|
4562
4659
|
let hit = map.get(path);
|
|
4563
4660
|
if (hit === void 0 || "until" in hit && hit.until <= now()) {
|
|
4564
4661
|
try {
|
|
@@ -4566,22 +4663,29 @@ function cachingBridge(bridge, now = () => performance.now()) {
|
|
|
4566
4663
|
} catch (e) {
|
|
4567
4664
|
hit = { error: e, until: now() + MISS_TTL_MS };
|
|
4568
4665
|
}
|
|
4569
|
-
|
|
4666
|
+
cache.put(map, path, hit);
|
|
4570
4667
|
}
|
|
4571
4668
|
if ("until" in hit) throw hit.error;
|
|
4572
4669
|
return hit;
|
|
4573
4670
|
};
|
|
4574
|
-
const invalidate = () =>
|
|
4575
|
-
|
|
4576
|
-
|
|
4671
|
+
const invalidate = () => cache.mutated([]);
|
|
4672
|
+
const touched = (path, ino) => cache.changed(path, ino);
|
|
4673
|
+
const mutating = (op, ...paths) => {
|
|
4674
|
+
try {
|
|
4675
|
+
return op();
|
|
4676
|
+
} finally {
|
|
4677
|
+
cache.mutated(paths);
|
|
4678
|
+
}
|
|
4577
4679
|
};
|
|
4578
|
-
const
|
|
4680
|
+
const rewriting = (p, op, ...also) => {
|
|
4681
|
+
const ino = cache.inoOf(p, () => bridge.stat(p));
|
|
4579
4682
|
try {
|
|
4580
4683
|
return op();
|
|
4581
4684
|
} finally {
|
|
4582
|
-
|
|
4685
|
+
cache.mutated([p, ...also], ino);
|
|
4583
4686
|
}
|
|
4584
4687
|
};
|
|
4688
|
+
const entry = (p) => [p, p.slice(0, p.lastIndexOf("/")) || "/"];
|
|
4585
4689
|
return {
|
|
4586
4690
|
readFile: (p) => bridge.readFile(p),
|
|
4587
4691
|
readdir: (p) => bridge.readdir(p),
|
|
@@ -4589,9 +4693,9 @@ function cachingBridge(bridge, now = () => performance.now()) {
|
|
|
4589
4693
|
const list = bridge.readdirStat(p);
|
|
4590
4694
|
const base = p === "/" ? "" : p;
|
|
4591
4695
|
for (const [name2, st] of list) {
|
|
4592
|
-
if (!st) continue;
|
|
4593
|
-
|
|
4594
|
-
if (!st.isSymbolicLink)
|
|
4696
|
+
if (!st || blind) continue;
|
|
4697
|
+
cache.put(lstats, `${base}/${name2}`, st);
|
|
4698
|
+
if (!st.isSymbolicLink) cache.put(stats, `${base}/${name2}`, st);
|
|
4595
4699
|
}
|
|
4596
4700
|
return list;
|
|
4597
4701
|
},
|
|
@@ -4606,40 +4710,42 @@ function cachingBridge(bridge, now = () => performance.now()) {
|
|
|
4606
4710
|
return false;
|
|
4607
4711
|
}
|
|
4608
4712
|
},
|
|
4609
|
-
writeFile: (p, bytes, open) =>
|
|
4610
|
-
mkdir: (p) => mutating(() => bridge.mkdir(p)),
|
|
4713
|
+
writeFile: (p, bytes, open) => rewriting(p, () => bridge.writeFile(p, bytes, open), ...entry(p).slice(1)),
|
|
4714
|
+
mkdir: (p) => mutating(() => bridge.mkdir(p), ...entry(p)),
|
|
4611
4715
|
rm: (p) => mutating(() => bridge.rm(p)),
|
|
4612
4716
|
rename: (from, to) => mutating(() => bridge.rename(from, to)),
|
|
4717
|
+
link: (from, to, follow2) => mutating(() => bridge.link(from, to, follow2)),
|
|
4613
4718
|
unlink: (p) => mutating(() => bridge.unlink(p)),
|
|
4614
4719
|
rmdir: (p) => mutating(() => bridge.rmdir(p)),
|
|
4615
|
-
symlink: (target, link) => mutating(() => bridge.symlink(target, link)),
|
|
4616
|
-
chmod: (p, mode) =>
|
|
4617
|
-
utimes: (p, a, m) =>
|
|
4618
|
-
lutimes: (p, a, m) => mutating(() => bridge.lutimes(p, a, m)),
|
|
4720
|
+
symlink: (target, link) => mutating(() => bridge.symlink(target, link), ...entry(link)),
|
|
4721
|
+
chmod: (p, mode) => rewriting(p, () => bridge.chmod(p, mode)),
|
|
4722
|
+
utimes: (p, a, m) => rewriting(p, () => bridge.utimes(p, a, m)),
|
|
4723
|
+
lutimes: (p, a, m) => mutating(() => bridge.lutimes(p, a, m), p),
|
|
4619
4724
|
...bridge.hold ? { hold: bridge.hold.bind(bridge) } : {},
|
|
4620
4725
|
...bridge.kept ? { kept: bridge.kept.bind(bridge) } : {},
|
|
4621
|
-
...bridge.pinned ? { pinned: (handle) => pinnedIo2(bridge, handle,
|
|
4622
|
-
...bridge.create ? { create: (p) => mutating(() => bridge.create?.(p)) } : {},
|
|
4726
|
+
...bridge.pinned ? { pinned: (handle) => pinnedIo2(bridge, handle, rewriting) } : {},
|
|
4727
|
+
...bridge.create ? { create: (p) => mutating(() => bridge.create?.(p), ...entry(p)) } : {},
|
|
4623
4728
|
...bridge.pread && bridge.pwrite && bridge.truncate ? {
|
|
4624
4729
|
pread: bridge.pread.bind(bridge),
|
|
4625
|
-
pwrite: (p, at, bytes, transfer) =>
|
|
4626
|
-
truncate: (p, size) =>
|
|
4730
|
+
pwrite: (p, at, bytes, transfer) => rewriting(p, () => bridge.pwrite?.(p, at, bytes, transfer)),
|
|
4731
|
+
truncate: (p, size) => rewriting(p, () => bridge.truncate?.(p, size))
|
|
4627
4732
|
} : {},
|
|
4628
|
-
invalidate
|
|
4733
|
+
invalidate,
|
|
4734
|
+
touched
|
|
4629
4735
|
};
|
|
4630
4736
|
}
|
|
4631
|
-
function pinnedIo2(bridge, handle,
|
|
4737
|
+
function pinnedIo2(bridge, handle, rewriting) {
|
|
4632
4738
|
const io = bridge.pinned(handle);
|
|
4633
4739
|
const { pread, pwrite, truncate } = io;
|
|
4634
4740
|
return {
|
|
4635
4741
|
readFile: (p) => io.readFile(p),
|
|
4636
|
-
writeFile: (p, bytes, open) =>
|
|
4742
|
+
writeFile: (p, bytes, open) => rewriting(p, () => io.writeFile(p, bytes, open)),
|
|
4637
4743
|
pread: (p, at, n, version) => pread(p, at, n, version),
|
|
4638
|
-
pwrite: (p, at, bytes, transfer) =>
|
|
4639
|
-
truncate: (p, size) =>
|
|
4744
|
+
pwrite: (p, at, bytes, transfer) => rewriting(p, () => pwrite(p, at, bytes, transfer)),
|
|
4745
|
+
truncate: (p, size) => rewriting(p, () => truncate(p, size))
|
|
4640
4746
|
};
|
|
4641
4747
|
}
|
|
4642
|
-
var WasiError, FileBuffer, LocalFile, MAX_LINKS, MISS_TTL_MS;
|
|
4748
|
+
var WasiError, FileBuffer, LocalFile, MAX_LINKS, MISS_TTL_MS, FS_GEN, RING, RING_SIZE, SLOT, SHARED_IDS_BYTES, StatCache;
|
|
4643
4749
|
var init_wasi_files = __esm({
|
|
4644
4750
|
"src/process/wasi/wasi-files.ts"() {
|
|
4645
4751
|
"use strict";
|
|
@@ -4829,6 +4935,110 @@ var init_wasi_files = __esm({
|
|
|
4829
4935
|
};
|
|
4830
4936
|
MAX_LINKS = 40;
|
|
4831
4937
|
MISS_TTL_MS = 20;
|
|
4938
|
+
FS_GEN = 4;
|
|
4939
|
+
RING = 8;
|
|
4940
|
+
RING_SIZE = 64;
|
|
4941
|
+
SLOT = 3;
|
|
4942
|
+
SHARED_IDS_BYTES = (RING + RING_SIZE * SLOT) * 4;
|
|
4943
|
+
StatCache = class {
|
|
4944
|
+
stats = /* @__PURE__ */ new Map();
|
|
4945
|
+
lstats = /* @__PURE__ */ new Map();
|
|
4946
|
+
byHash = /* @__PURE__ */ new Map();
|
|
4947
|
+
byIno = /* @__PURE__ */ new Map();
|
|
4948
|
+
shared;
|
|
4949
|
+
seen;
|
|
4950
|
+
constructor(shared) {
|
|
4951
|
+
this.shared = shared;
|
|
4952
|
+
this.seen = shared ? Atomics.load(shared, FS_GEN) : 0;
|
|
4953
|
+
}
|
|
4954
|
+
put(map, path, entry) {
|
|
4955
|
+
map.set(path, entry);
|
|
4956
|
+
if (!this.shared) return;
|
|
4957
|
+
index(this.byHash, pathHash(path), path);
|
|
4958
|
+
const ino = inoKey(entry);
|
|
4959
|
+
if (ino !== 0) index(this.byIno, ino, path);
|
|
4960
|
+
}
|
|
4961
|
+
fresh() {
|
|
4962
|
+
if (!this.shared) return;
|
|
4963
|
+
const now = Atomics.load(this.shared, FS_GEN);
|
|
4964
|
+
if (now === this.seen) return;
|
|
4965
|
+
this.replay(now);
|
|
4966
|
+
this.seen = now;
|
|
4967
|
+
}
|
|
4968
|
+
changed(path, ino = 0) {
|
|
4969
|
+
const key = ino % 4294967296 | 0;
|
|
4970
|
+
if (this.shared) {
|
|
4971
|
+
const g = this.publish(this.shared, path === void 0 ? 0 : pathHash(path), key);
|
|
4972
|
+
this.replay(g - 1);
|
|
4973
|
+
this.seen = g;
|
|
4974
|
+
if (path === void 0) this.clear();
|
|
4975
|
+
else this.drop(pathHash(path), key);
|
|
4976
|
+
}
|
|
4977
|
+
if (path === void 0) return;
|
|
4978
|
+
this.stats.delete(path);
|
|
4979
|
+
this.lstats.delete(path);
|
|
4980
|
+
}
|
|
4981
|
+
mutated(paths, ino = 0) {
|
|
4982
|
+
this.clear();
|
|
4983
|
+
if (!this.shared) return;
|
|
4984
|
+
const key = ino % 4294967296 | 0;
|
|
4985
|
+
for (const [i, hash] of (paths.length > 0 ? paths.map(pathHash) : [0]).entries()) {
|
|
4986
|
+
this.seen = this.publish(this.shared, hash, i === 0 ? key : 0);
|
|
4987
|
+
}
|
|
4988
|
+
}
|
|
4989
|
+
inoOf(path, look) {
|
|
4990
|
+
if (!this.shared) return 0;
|
|
4991
|
+
this.fresh();
|
|
4992
|
+
const hit = this.stats.get(path);
|
|
4993
|
+
if (hit && "ino" in hit && typeof hit.ino === "number") return hit.ino;
|
|
4994
|
+
try {
|
|
4995
|
+
return look().ino ?? 0;
|
|
4996
|
+
} catch {
|
|
4997
|
+
return 0;
|
|
4998
|
+
}
|
|
4999
|
+
}
|
|
5000
|
+
publish(shared, hash, ino) {
|
|
5001
|
+
const g = Atomics.add(shared, FS_GEN, 1) + 1;
|
|
5002
|
+
const at = RING + g % RING_SIZE * SLOT;
|
|
5003
|
+
Atomics.store(shared, at, 0);
|
|
5004
|
+
Atomics.store(shared, at + 1, hash);
|
|
5005
|
+
Atomics.store(shared, at + 2, ino);
|
|
5006
|
+
Atomics.store(shared, at, g);
|
|
5007
|
+
return g;
|
|
5008
|
+
}
|
|
5009
|
+
replay(upTo) {
|
|
5010
|
+
const shared = this.shared;
|
|
5011
|
+
const missed = [];
|
|
5012
|
+
for (let g = this.seen + 1; g <= upTo && upTo - this.seen <= RING_SIZE; g++) {
|
|
5013
|
+
const at = RING + g % RING_SIZE * SLOT;
|
|
5014
|
+
const tag = Atomics.load(shared, at);
|
|
5015
|
+
const hash = Atomics.load(shared, at + 1);
|
|
5016
|
+
const ino = Atomics.load(shared, at + 2);
|
|
5017
|
+
if (tag !== g || hash === 0 || Atomics.load(shared, at) !== g) break;
|
|
5018
|
+
missed.push([hash, ino]);
|
|
5019
|
+
}
|
|
5020
|
+
if (missed.length < upTo - this.seen) this.clear();
|
|
5021
|
+
else for (const [hash, ino] of missed) this.drop(hash, ino);
|
|
5022
|
+
}
|
|
5023
|
+
drop(hash, ino) {
|
|
5024
|
+
const paths = [
|
|
5025
|
+
...this.byHash.get(hash) ?? [],
|
|
5026
|
+
...ino === 0 ? [] : this.byIno.get(ino) ?? []
|
|
5027
|
+
];
|
|
5028
|
+
for (const path of paths) {
|
|
5029
|
+
this.stats.delete(path);
|
|
5030
|
+
this.lstats.delete(path);
|
|
5031
|
+
}
|
|
5032
|
+
this.byHash.delete(hash);
|
|
5033
|
+
if (ino !== 0) this.byIno.delete(ino);
|
|
5034
|
+
}
|
|
5035
|
+
clear() {
|
|
5036
|
+
this.stats.clear();
|
|
5037
|
+
this.lstats.clear();
|
|
5038
|
+
this.byHash.clear();
|
|
5039
|
+
this.byIno.clear();
|
|
5040
|
+
}
|
|
5041
|
+
};
|
|
4832
5042
|
}
|
|
4833
5043
|
});
|
|
4834
5044
|
|
|
@@ -4923,6 +5133,8 @@ var init_wasi_fds = __esm({
|
|
|
4923
5133
|
WasiFds = class {
|
|
4924
5134
|
table = /* @__PURE__ */ new Map();
|
|
4925
5135
|
buffers = /* @__PURE__ */ new Map();
|
|
5136
|
+
byId = /* @__PURE__ */ new Map();
|
|
5137
|
+
ids = /* @__PURE__ */ new Map();
|
|
4926
5138
|
kernel;
|
|
4927
5139
|
fs;
|
|
4928
5140
|
constructor(kernel, fs) {
|
|
@@ -5161,11 +5373,18 @@ var init_wasi_fds = __esm({
|
|
|
5161
5373
|
handed.add(e.file.buffer);
|
|
5162
5374
|
promoted.set(e.file, fd);
|
|
5163
5375
|
}
|
|
5164
|
-
this.table.set(fd, {
|
|
5376
|
+
this.table.set(fd, {
|
|
5377
|
+
type: "kernel",
|
|
5378
|
+
kind: "file",
|
|
5379
|
+
nonblock: false,
|
|
5380
|
+
append: e.file.append,
|
|
5381
|
+
path: e.file.path,
|
|
5382
|
+
ino: this.inoOf(e.file.path)
|
|
5383
|
+
});
|
|
5165
5384
|
}
|
|
5166
5385
|
for (const file of promoted.keys()) {
|
|
5167
5386
|
if (--file.buffer.opens <= 0) {
|
|
5168
|
-
this.
|
|
5387
|
+
this.forget(file.buffer);
|
|
5169
5388
|
this.letGo(file.buffer);
|
|
5170
5389
|
}
|
|
5171
5390
|
}
|
|
@@ -5236,9 +5455,48 @@ var init_wasi_fds = __esm({
|
|
|
5236
5455
|
const { buffer } = e.file;
|
|
5237
5456
|
buffer.flush();
|
|
5238
5457
|
if (--buffer.opens > 0) return;
|
|
5239
|
-
|
|
5458
|
+
this.forget(buffer);
|
|
5240
5459
|
this.letGo(buffer);
|
|
5241
5460
|
}
|
|
5461
|
+
forget(buffer) {
|
|
5462
|
+
for (const [p, b] of [...this.buffers]) if (b === buffer) this.buffers.delete(p);
|
|
5463
|
+
const id = this.ids.get(buffer);
|
|
5464
|
+
if (id !== void 0 && this.byId.get(id) === buffer) this.byId.delete(id);
|
|
5465
|
+
this.ids.delete(buffer);
|
|
5466
|
+
}
|
|
5467
|
+
know(buffer, id) {
|
|
5468
|
+
if (this.ids.has(buffer)) return;
|
|
5469
|
+
this.ids.set(buffer, id);
|
|
5470
|
+
if (!this.byId.has(id)) this.byId.set(id, buffer);
|
|
5471
|
+
}
|
|
5472
|
+
identity(st) {
|
|
5473
|
+
if (!st || st.ino === void 0 || (st.nlink ?? 1) < 2) return void 0;
|
|
5474
|
+
return `${st.dev ?? 0}:${st.ino}`;
|
|
5475
|
+
}
|
|
5476
|
+
sharing(path, st) {
|
|
5477
|
+
if (st?.ino === void 0) return void 0;
|
|
5478
|
+
const id = `${st.dev ?? 0}:${st.ino}`;
|
|
5479
|
+
if (!this.byId.has(id) && this.identity(st) !== void 0) this.learn();
|
|
5480
|
+
const buffer = this.byId.get(id);
|
|
5481
|
+
if (!buffer) return void 0;
|
|
5482
|
+
this.buffers.set(path, buffer);
|
|
5483
|
+
return buffer;
|
|
5484
|
+
}
|
|
5485
|
+
learn() {
|
|
5486
|
+
for (const [p, buffer] of this.buffers) {
|
|
5487
|
+
if (this.ids.has(buffer) || buffer.isOrphan()) continue;
|
|
5488
|
+
const known = this.identity(this.statOrMissing(p));
|
|
5489
|
+
if (known !== void 0) this.know(buffer, known);
|
|
5490
|
+
}
|
|
5491
|
+
}
|
|
5492
|
+
linked(from, to) {
|
|
5493
|
+
const buffer = this.buffers.get(from);
|
|
5494
|
+
if (!buffer || buffer.isOrphan()) return;
|
|
5495
|
+
const id = this.identity(this.statOrMissing(to));
|
|
5496
|
+
if (id === void 0) return;
|
|
5497
|
+
this.know(buffer, id);
|
|
5498
|
+
if (!this.buffers.has(to)) this.buffers.set(to, buffer);
|
|
5499
|
+
}
|
|
5242
5500
|
letGo(buffer) {
|
|
5243
5501
|
this.fs.hold?.(buffer.path, false, true, buffer.handle);
|
|
5244
5502
|
}
|
|
@@ -5264,32 +5522,63 @@ var init_wasi_fds = __esm({
|
|
|
5264
5522
|
for (const [p, buffer] of this.buffers) if (within(p, path)) buffer.flush();
|
|
5265
5523
|
if (this.shared) this.kernel.call({ op: "fd-path-flush", path });
|
|
5266
5524
|
}
|
|
5267
|
-
|
|
5268
|
-
this.buffers.
|
|
5525
|
+
holdsUnder(path) {
|
|
5526
|
+
for (const p of this.buffers.keys()) if (within(p, path)) return true;
|
|
5527
|
+
return false;
|
|
5528
|
+
}
|
|
5529
|
+
unlinking(path, linked) {
|
|
5530
|
+
const buffer = this.buffers.get(path);
|
|
5531
|
+
if (buffer && this.survives(buffer, linked)) buffer.flush();
|
|
5532
|
+
else buffer?.keep();
|
|
5269
5533
|
if (this.shared) this.kernel.call({ op: "fd-path-unlinking", path });
|
|
5270
5534
|
}
|
|
5271
|
-
unlinked(path) {
|
|
5535
|
+
unlinked(path, linked) {
|
|
5272
5536
|
if (this.shared) this.kernel.call({ op: "fd-path-unlinked", path });
|
|
5273
5537
|
const buffer = this.buffers.get(path);
|
|
5274
5538
|
if (!buffer) return;
|
|
5275
|
-
|
|
5539
|
+
this.detach(buffer, linked);
|
|
5276
5540
|
this.buffers.delete(path);
|
|
5277
5541
|
}
|
|
5278
|
-
|
|
5542
|
+
inoOf(path) {
|
|
5543
|
+
try {
|
|
5544
|
+
return this.fs.stat(path).ino;
|
|
5545
|
+
} catch {
|
|
5546
|
+
return void 0;
|
|
5547
|
+
}
|
|
5548
|
+
}
|
|
5549
|
+
survives(buffer, linked) {
|
|
5550
|
+
return linked !== void 0 && buffer.handle !== void 0;
|
|
5551
|
+
}
|
|
5552
|
+
detach(buffer, linked) {
|
|
5553
|
+
if (this.survives(buffer, linked)) {
|
|
5554
|
+
const id = this.identity(linked);
|
|
5555
|
+
if (id !== void 0) this.know(buffer, id);
|
|
5556
|
+
return;
|
|
5557
|
+
}
|
|
5558
|
+
buffer.orphan();
|
|
5559
|
+
this.forget(buffer);
|
|
5560
|
+
}
|
|
5561
|
+
renamed(from, to, replacedLinked) {
|
|
5279
5562
|
if (from === to) return;
|
|
5280
5563
|
if (this.shared) this.kernel.call({ op: "fd-path-renamed", from, to });
|
|
5564
|
+
for (const e of this.table.values()) {
|
|
5565
|
+
if (e.type === "kernel" && e.path !== void 0 && within(e.path, from)) {
|
|
5566
|
+
e.path = to + e.path.slice(from.length);
|
|
5567
|
+
}
|
|
5568
|
+
}
|
|
5281
5569
|
const moved = [];
|
|
5282
5570
|
for (const [p, buffer] of this.buffers) {
|
|
5283
5571
|
if (within(p, from)) moved.push([p, buffer]);
|
|
5284
5572
|
else if (within(p, to)) {
|
|
5285
|
-
|
|
5573
|
+
this.detach(buffer, replacedLinked);
|
|
5286
5574
|
this.buffers.delete(p);
|
|
5287
5575
|
}
|
|
5288
5576
|
}
|
|
5577
|
+
for (const [p] of moved) this.buffers.delete(p);
|
|
5289
5578
|
for (const [p, buffer] of moved) {
|
|
5290
|
-
|
|
5291
|
-
buffer.path
|
|
5292
|
-
this.buffers.set(
|
|
5579
|
+
const next2 = to + p.slice(from.length);
|
|
5580
|
+
if (buffer.path === p) buffer.path = next2;
|
|
5581
|
+
this.buffers.set(next2, buffer);
|
|
5293
5582
|
}
|
|
5294
5583
|
}
|
|
5295
5584
|
resolve(dirfd, path) {
|
|
@@ -5332,6 +5621,7 @@ var init_wasi_fds = __esm({
|
|
|
5332
5621
|
this.buffers.delete(path);
|
|
5333
5622
|
buffer = void 0;
|
|
5334
5623
|
}
|
|
5624
|
+
buffer ??= this.sharing(path, existing);
|
|
5335
5625
|
if (buffer) {
|
|
5336
5626
|
if (oflags & OFLAGS.TRUNC) buffer.truncate(0);
|
|
5337
5627
|
} else {
|
|
@@ -5345,6 +5635,8 @@ var init_wasi_fds = __esm({
|
|
|
5345
5635
|
buffer = new FileBuffer(io, path, empty, st.maxFile, ranged, st.version);
|
|
5346
5636
|
buffer.handle = handle;
|
|
5347
5637
|
this.buffers.set(path, buffer);
|
|
5638
|
+
const id = this.identity(st);
|
|
5639
|
+
if (id !== void 0) this.know(buffer, id);
|
|
5348
5640
|
}
|
|
5349
5641
|
buffer.opens++;
|
|
5350
5642
|
return new LocalFile(buffer, readable2, writable2, (fdflags & FDFLAGS.APPEND) !== 0);
|
|
@@ -5356,7 +5648,10 @@ var init_wasi_fds = __esm({
|
|
|
5356
5648
|
const made = !existing && this.createNew(path, oflags);
|
|
5357
5649
|
const truncate = made || (oflags & OFLAGS.TRUNC) !== 0;
|
|
5358
5650
|
const fd = this.kernel.sys.openVfs(path, flags, 0, truncate ? { truncate } : {});
|
|
5359
|
-
|
|
5651
|
+
const was = existing && this.inoOf(path);
|
|
5652
|
+
if (truncate) this.fs.touched?.(path, was);
|
|
5653
|
+
const ino = existing ? was : this.inoOf(path);
|
|
5654
|
+
this.table.set(fd, { type: "kernel", kind: "file", nonblock: false, append, path, ino });
|
|
5360
5655
|
if (append) this.publishFlags(fd, { nonblock: false, append });
|
|
5361
5656
|
this.bump();
|
|
5362
5657
|
return fd;
|
|
@@ -5675,6 +5970,16 @@ var init_wasi_termios = __esm({
|
|
|
5675
5970
|
});
|
|
5676
5971
|
|
|
5677
5972
|
// src/process/wasi/wasi-host.ts
|
|
5973
|
+
function linkedOf(st) {
|
|
5974
|
+
return (st.nlink ?? 1) > 1 ? st : void 0;
|
|
5975
|
+
}
|
|
5976
|
+
function linkedElsewhere(fs, path) {
|
|
5977
|
+
try {
|
|
5978
|
+
return linkedOf(fs.lstat(path));
|
|
5979
|
+
} catch {
|
|
5980
|
+
return void 0;
|
|
5981
|
+
}
|
|
5982
|
+
}
|
|
5678
5983
|
function filetypeOf(s) {
|
|
5679
5984
|
if (!s) return FILETYPE.UNKNOWN;
|
|
5680
5985
|
if (s.isSymbolicLink) return FILETYPE.SYMBOLIC_LINK;
|
|
@@ -5686,6 +5991,7 @@ function filestatOf(path, s) {
|
|
|
5686
5991
|
filetype: filetypeOf(s),
|
|
5687
5992
|
size: BigInt(s.size),
|
|
5688
5993
|
ino: s.ino !== void 0 ? BigInt(s.ino) : pathInode(path),
|
|
5994
|
+
...s.nlink !== void 0 ? { nlink: BigInt(s.nlink) } : {},
|
|
5689
5995
|
mtimeNs: BigInt(Math.round(s.mtimeMs ?? 0)) * NS_PER_MS
|
|
5690
5996
|
};
|
|
5691
5997
|
}
|
|
@@ -5736,6 +6042,7 @@ var WasiExit, IDS, NS_PER_MS, AT_SYMLINK_NOFOLLOW2, S_IFIFO, DEFAULT_UMASK, MONO
|
|
|
5736
6042
|
var init_wasi_host = __esm({
|
|
5737
6043
|
"src/process/wasi/wasi-host.ts"() {
|
|
5738
6044
|
"use strict";
|
|
6045
|
+
init_physical_path();
|
|
5739
6046
|
init_cred();
|
|
5740
6047
|
init_wasi_abi();
|
|
5741
6048
|
init_wasi_fds();
|
|
@@ -6045,17 +6352,20 @@ var init_wasi_host = __esm({
|
|
|
6045
6352
|
path_remove_directory: (dirfd, p, l) => void o.fs.rmdir(at(dirfd, p, l)),
|
|
6046
6353
|
path_unlink_file: (dirfd, p, l) => {
|
|
6047
6354
|
const path = at(dirfd, p, l);
|
|
6048
|
-
|
|
6049
|
-
|
|
6355
|
+
const st = o.fs.lstat(path);
|
|
6356
|
+
if (st.isDirectory) throw new WasiError("EISDIR");
|
|
6357
|
+
const linked = linkedOf(st);
|
|
6358
|
+
fds.unlinking(path, linked);
|
|
6050
6359
|
o.fs.unlink(path);
|
|
6051
|
-
fds.unlinked(path);
|
|
6360
|
+
fds.unlinked(path, linked);
|
|
6052
6361
|
},
|
|
6053
6362
|
path_rename: (fd, p, l, fd2, p2, l2) => {
|
|
6054
6363
|
const from = at(fd, p, l);
|
|
6055
6364
|
const to = at(fd2, p2, l2);
|
|
6056
6365
|
fds.flushPath(from);
|
|
6366
|
+
const replaced = fds.holdsUnder(to) ? linkedElsewhere(o.fs, to) : void 0;
|
|
6057
6367
|
o.fs.rename(from, to);
|
|
6058
|
-
fds.renamed(from, to);
|
|
6368
|
+
fds.renamed(from, to, replaced);
|
|
6059
6369
|
},
|
|
6060
6370
|
path_symlink: (tp, tl, dirfd, p, l) => void o.fs.symlink(mem.string(tp, tl), at(dirfd, p, l)),
|
|
6061
6371
|
path_readlink: (dirfd, p, l, buf, len, used) => {
|
|
@@ -6064,7 +6374,17 @@ var init_wasi_host = __esm({
|
|
|
6064
6374
|
mem.bytes(buf, n).set(target.subarray(0, n));
|
|
6065
6375
|
mem.view().setUint32(used, n, true);
|
|
6066
6376
|
},
|
|
6067
|
-
path_link: () =>
|
|
6377
|
+
path_link: (fd, lookup, p, l, fd2, p2, l2) => {
|
|
6378
|
+
const from = at(fd, p, l);
|
|
6379
|
+
const to = at(fd2, p2, l2);
|
|
6380
|
+
const follow2 = (lookup & LOOKUP_SYMLINK_FOLLOW) !== 0;
|
|
6381
|
+
const source = follow2 ? physicalPath(o.fs, from) : from;
|
|
6382
|
+
fds.flushPath(from);
|
|
6383
|
+
if (source !== from) fds.flushPath(source);
|
|
6384
|
+
o.fs.link(from, to, follow2);
|
|
6385
|
+
fds.linked(from, to);
|
|
6386
|
+
if (source !== from) fds.linked(source, to);
|
|
6387
|
+
}
|
|
6068
6388
|
};
|
|
6069
6389
|
}
|
|
6070
6390
|
socket(fd) {
|
|
@@ -6150,11 +6470,29 @@ var init_wasi_host = __esm({
|
|
|
6150
6470
|
if (!kernel.sys.pread) throw new WasiError("ESPIPE");
|
|
6151
6471
|
return kernel.sys.pread(fd, Math.min(max, MAX_READ), at);
|
|
6152
6472
|
},
|
|
6153
|
-
pwrite: (body, at) => kernel.call({ op: "fd-pwrite", fd, offset: at, body }),
|
|
6473
|
+
pwrite: (body, at) => this.changed(fd, e, kernel.call({ op: "fd-pwrite", fd, offset: at, body })),
|
|
6154
6474
|
size: () => this.kernelStat(fd).size,
|
|
6155
|
-
truncate: (size) => void kernel.call({ op: "fd-resize", fd, size })
|
|
6475
|
+
truncate: (size) => this.changed(fd, e, void kernel.call({ op: "fd-resize", fd, size }))
|
|
6156
6476
|
};
|
|
6157
6477
|
}
|
|
6478
|
+
unnamed = /* @__PURE__ */ new WeakSet();
|
|
6479
|
+
changed(fd, e, result) {
|
|
6480
|
+
if (e.path === void 0 && !this.unnamed.has(e)) this.learnPath(fd, e);
|
|
6481
|
+
this.o.fs.touched?.(e.path, e.ino);
|
|
6482
|
+
return result;
|
|
6483
|
+
}
|
|
6484
|
+
learnPath(fd, e) {
|
|
6485
|
+
this.unnamed.add(e);
|
|
6486
|
+
let path;
|
|
6487
|
+
try {
|
|
6488
|
+
const st = this.kernelStat(fd);
|
|
6489
|
+
path = st.orphan ? void 0 : st.path;
|
|
6490
|
+
if (path !== void 0) e.ino = this.o.fs.stat(path).ino;
|
|
6491
|
+
} catch {
|
|
6492
|
+
return;
|
|
6493
|
+
}
|
|
6494
|
+
e.path = path;
|
|
6495
|
+
}
|
|
6158
6496
|
kernelStat(fd) {
|
|
6159
6497
|
return this.o.kernel.call({ op: "fd-vfs-stat", fd });
|
|
6160
6498
|
}
|
|
@@ -6163,7 +6501,8 @@ var init_wasi_host = __esm({
|
|
|
6163
6501
|
const e = this.fds.get(fd);
|
|
6164
6502
|
if (e.type === "kernel") {
|
|
6165
6503
|
try {
|
|
6166
|
-
|
|
6504
|
+
const n = this.o.kernel.sys.write(fd, data, { nonblock: e.nonblock });
|
|
6505
|
+
return this.fds.kind(fd, e) === "file" ? this.changed(fd, e, n) : n;
|
|
6167
6506
|
} catch (err) {
|
|
6168
6507
|
const broken = err.code === "EPIPE";
|
|
6169
6508
|
if (broken && this.fds.kind(fd, e) !== "socket") throw new WasiExit(SIGPIPE_EXIT);
|
|
@@ -6249,7 +6588,7 @@ var init_wasi_host = __esm({
|
|
|
6249
6588
|
v.setBigUint64(ptr, 1n, true);
|
|
6250
6589
|
v.setBigUint64(ptr + 8, f.ino, true);
|
|
6251
6590
|
v.setUint8(ptr + 16, f.filetype);
|
|
6252
|
-
v.setBigUint64(ptr + 24, 1n, true);
|
|
6591
|
+
v.setBigUint64(ptr + 24, f.nlink ?? 1n, true);
|
|
6253
6592
|
v.setBigUint64(ptr + 32, f.size, true);
|
|
6254
6593
|
v.setBigUint64(ptr + 40, f.mtimeNs, true);
|
|
6255
6594
|
v.setBigUint64(ptr + 48, f.mtimeNs, true);
|
|
@@ -6360,6 +6699,7 @@ var init_wasi_threads = __esm({
|
|
|
6360
6699
|
"src/process/wasi/wasi-threads.ts"() {
|
|
6361
6700
|
"use strict";
|
|
6362
6701
|
init_protocol();
|
|
6702
|
+
init_wasi_files();
|
|
6363
6703
|
LAST_TID = 0;
|
|
6364
6704
|
RUNNING = 1;
|
|
6365
6705
|
MAIN_TID = 1;
|
|
@@ -6382,7 +6722,7 @@ var init_wasi_threads = __esm({
|
|
|
6382
6722
|
this.memory = memory;
|
|
6383
6723
|
this.cap = cap;
|
|
6384
6724
|
this.tid = tid;
|
|
6385
|
-
this.ids = new Int32Array(ids ?? new SharedArrayBuffer(
|
|
6725
|
+
this.ids = new Int32Array(ids ?? new SharedArrayBuffer(SHARED_IDS_BYTES));
|
|
6386
6726
|
if (!ids) Atomics.store(this.ids, LAST_TID, MAIN_TID);
|
|
6387
6727
|
}
|
|
6388
6728
|
spawn(arg) {
|
|
@@ -7052,6 +7392,13 @@ function procfsBridge(fs, tree) {
|
|
|
7052
7392
|
() => fs.rename(from, to)
|
|
7053
7393
|
),
|
|
7054
7394
|
symlink: (target, link) => readOnly([[link, false]], () => fs.symlink(target, link)),
|
|
7395
|
+
link: (from, to, follow2) => readOnly(
|
|
7396
|
+
[
|
|
7397
|
+
[from, follow2 === true],
|
|
7398
|
+
[to, false]
|
|
7399
|
+
],
|
|
7400
|
+
() => fs.link(from, to, follow2)
|
|
7401
|
+
),
|
|
7055
7402
|
hold: (p, held, open, handle) => {
|
|
7056
7403
|
if (handle !== void 0 && snapshots.delete(handle)) return void 0;
|
|
7057
7404
|
if (!held) return fs.hold?.(p, held, open, handle);
|
|
@@ -7824,8 +8171,8 @@ function readExports(r, s) {
|
|
|
7824
8171
|
for (let i = r.u32(); i > 0; i--) {
|
|
7825
8172
|
const name2 = r.name();
|
|
7826
8173
|
const kind = r.byte();
|
|
7827
|
-
const
|
|
7828
|
-
if (kind === 0) s.info.exports[name2] =
|
|
8174
|
+
const index3 = r.u32();
|
|
8175
|
+
if (kind === 0) s.info.exports[name2] = index3;
|
|
7829
8176
|
}
|
|
7830
8177
|
}
|
|
7831
8178
|
function readElems(r, s) {
|
|
@@ -8128,15 +8475,15 @@ var init_wasix_linker = __esm({
|
|
|
8128
8475
|
return out;
|
|
8129
8476
|
}
|
|
8130
8477
|
allocateClosure() {
|
|
8131
|
-
const
|
|
8132
|
-
growTable(this.table,
|
|
8133
|
-
this.live.add(
|
|
8134
|
-
return
|
|
8478
|
+
const index3 = this.indices.allocate(this.table.length);
|
|
8479
|
+
growTable(this.table, index3 + 1);
|
|
8480
|
+
this.live.add(index3);
|
|
8481
|
+
return index3;
|
|
8135
8482
|
}
|
|
8136
|
-
freeClosure(
|
|
8137
|
-
this.indices?.free(
|
|
8138
|
-
this.live.delete(
|
|
8139
|
-
this.table.set(
|
|
8483
|
+
freeClosure(index3) {
|
|
8484
|
+
this.indices?.free(index3);
|
|
8485
|
+
this.live.delete(index3);
|
|
8486
|
+
this.table.set(index3, null);
|
|
8140
8487
|
}
|
|
8141
8488
|
live = /* @__PURE__ */ new Set();
|
|
8142
8489
|
prepareClosure(record) {
|
|
@@ -8369,12 +8716,12 @@ var init_wasix_linker = __esm({
|
|
|
8369
8716
|
this.indexTable();
|
|
8370
8717
|
const known = this.slots.get(fn);
|
|
8371
8718
|
if (known !== void 0) return known;
|
|
8372
|
-
const
|
|
8373
|
-
growTable(this.table,
|
|
8374
|
-
this.table.set(
|
|
8375
|
-
this.slots.set(fn,
|
|
8376
|
-
this.publisher?.({ kind: "slot", index:
|
|
8377
|
-
return
|
|
8719
|
+
const index3 = this.reserve(1);
|
|
8720
|
+
growTable(this.table, index3 + 1);
|
|
8721
|
+
this.table.set(index3, fn);
|
|
8722
|
+
this.slots.set(fn, index3);
|
|
8723
|
+
this.publisher?.({ kind: "slot", index: index3, handle, name: name2 });
|
|
8724
|
+
return index3;
|
|
8378
8725
|
}
|
|
8379
8726
|
allocate(size, alignment) {
|
|
8380
8727
|
if (size === 0) return 0;
|
|
@@ -8659,11 +9006,11 @@ var init_wasix_sockets = __esm({
|
|
|
8659
9006
|
});
|
|
8660
9007
|
|
|
8661
9008
|
// src/process/wasi/wasix-host.ts
|
|
8662
|
-
function futexWait(view,
|
|
9009
|
+
function futexWait(view, index3, expected, ms, interrupted) {
|
|
8663
9010
|
const deadline = performance.now() + ms;
|
|
8664
9011
|
for (; ; ) {
|
|
8665
9012
|
const slice = interrupted ? Math.min(FUTEX_SLICE_MS, ms) : ms;
|
|
8666
|
-
if (Atomics.wait(view,
|
|
9013
|
+
if (Atomics.wait(view, index3, expected, slice) !== "timed-out") return true;
|
|
8667
9014
|
if (interrupted?.()) return true;
|
|
8668
9015
|
ms = deadline - performance.now();
|
|
8669
9016
|
if (ms <= 0) return false;
|
|
@@ -8792,21 +9139,21 @@ var init_wasix_host = __esm({
|
|
|
8792
9139
|
if (!this.linker) throw new WasiError("ENOTSUP");
|
|
8793
9140
|
this.mem.view().setUint32(out, this.linker.allocateClosure(), true);
|
|
8794
9141
|
},
|
|
8795
|
-
closure_prepare: (backing,
|
|
9142
|
+
closure_prepare: (backing, index3, argTypes, argCount, resultTypes, resultCount, userData) => {
|
|
8796
9143
|
if (!this.linker) throw new WasiError("ENOTSUP");
|
|
8797
9144
|
const params = valueTypes(this.mem.bytes(argTypes, argCount));
|
|
8798
9145
|
const results = valueTypes(this.mem.bytes(resultTypes, resultCount));
|
|
8799
9146
|
if (!params || !results) throw new WasiError("EINVAL");
|
|
8800
9147
|
try {
|
|
8801
|
-
this.linker.prepareClosure({ index:
|
|
9148
|
+
this.linker.prepareClosure({ index: index3, backing, userData, params, results });
|
|
8802
9149
|
} catch (e) {
|
|
8803
9150
|
if (e instanceof DlError) throw new WasiError("EINVAL");
|
|
8804
9151
|
throw e;
|
|
8805
9152
|
}
|
|
8806
9153
|
},
|
|
8807
|
-
closure_free: (
|
|
9154
|
+
closure_free: (index3) => {
|
|
8808
9155
|
if (!this.linker) throw new WasiError("ENOTSUP");
|
|
8809
|
-
this.linker.freeClosure(
|
|
9156
|
+
this.linker.freeClosure(index3);
|
|
8810
9157
|
},
|
|
8811
9158
|
call_dynamic: (...a) => void callDynamic(
|
|
8812
9159
|
{ mem: this.mem, table: () => this.table, types: this.types },
|
|
@@ -9111,10 +9458,10 @@ function parseFunctionNames(payload) {
|
|
|
9111
9458
|
if (end > payload.length) throw new RangeError("truncated name section");
|
|
9112
9459
|
if (id === 1) {
|
|
9113
9460
|
for (let count = leb(); count > 0; count--) {
|
|
9114
|
-
const
|
|
9461
|
+
const index3 = leb();
|
|
9115
9462
|
const length = leb();
|
|
9116
9463
|
if (at + length > end) throw new RangeError("truncated name section");
|
|
9117
|
-
names.set(
|
|
9464
|
+
names.set(index3, decoder3.decode(payload.subarray(at, at + length)));
|
|
9118
9465
|
at += length;
|
|
9119
9466
|
}
|
|
9120
9467
|
}
|
|
@@ -9138,7 +9485,7 @@ function nameFrame(line, module, name2) {
|
|
|
9138
9485
|
}
|
|
9139
9486
|
function sidecarNames(read2, path) {
|
|
9140
9487
|
let names;
|
|
9141
|
-
return (
|
|
9488
|
+
return (index3) => {
|
|
9142
9489
|
if (!names) {
|
|
9143
9490
|
try {
|
|
9144
9491
|
names = parseFunctionNames(read2(path));
|
|
@@ -9146,7 +9493,7 @@ function sidecarNames(read2, path) {
|
|
|
9146
9493
|
names = /* @__PURE__ */ new Map();
|
|
9147
9494
|
}
|
|
9148
9495
|
}
|
|
9149
|
-
return names.get(
|
|
9496
|
+
return names.get(index3);
|
|
9150
9497
|
};
|
|
9151
9498
|
}
|
|
9152
9499
|
var UNNAMED_FRAME, WASM_MODULE;
|
|
@@ -9507,7 +9854,7 @@ async function runWasiProcess(init, port2) {
|
|
|
9507
9854
|
parent: () => identify(transport, init).ppid,
|
|
9508
9855
|
kernel: { sys: traced(stats, "kernel", sys), call: call2 },
|
|
9509
9856
|
fs: procfsBridge(
|
|
9510
|
-
cachingBridge(traced(stats, "fs", createSyncFsSabBridge(transport))),
|
|
9857
|
+
cachingBridge(traced(stats, "fs", createSyncFsSabBridge(transport)), void 0, threads?.ids),
|
|
9511
9858
|
procTree(call2, id.pid)
|
|
9512
9859
|
),
|
|
9513
9860
|
...descriptors(init, fork, threads)
|
|
@@ -9600,7 +9947,10 @@ async function runWasiThread(init, port2) {
|
|
|
9600
9947
|
ppid: id.ppid,
|
|
9601
9948
|
parent: () => identify(transport, init).ppid,
|
|
9602
9949
|
kernel: { sys, call: call2 },
|
|
9603
|
-
fs: procfsBridge(
|
|
9950
|
+
fs: procfsBridge(
|
|
9951
|
+
cachingBridge(createSyncFsSabBridge(transport), void 0, threads.ids),
|
|
9952
|
+
procTree(call2, id.pid)
|
|
9953
|
+
),
|
|
9604
9954
|
shared: threads.ids
|
|
9605
9955
|
});
|
|
9606
9956
|
const program = await programImports(init.program, host, transport, thread.tid);
|
|
@@ -9712,13 +10062,13 @@ var init_wasi_runtime = __esm({
|
|
|
9712
10062
|
},
|
|
9713
10063
|
unlock: () => this.call({ op: "dl-unlock", owner: this.owner }),
|
|
9714
10064
|
allocate: (floor) => {
|
|
9715
|
-
const
|
|
10065
|
+
const index3 = this.call({ op: "dl-closure", floor });
|
|
9716
10066
|
this.catchUp();
|
|
9717
10067
|
this.bump();
|
|
9718
|
-
return
|
|
10068
|
+
return index3;
|
|
9719
10069
|
},
|
|
9720
|
-
free: (
|
|
9721
|
-
this.call({ op: "dl-closure-free", index:
|
|
10070
|
+
free: (index3) => {
|
|
10071
|
+
this.call({ op: "dl-closure-free", index: index3 });
|
|
9722
10072
|
this.bump();
|
|
9723
10073
|
}
|
|
9724
10074
|
};
|
|
@@ -9771,8 +10121,8 @@ var init_wasi_runtime = __esm({
|
|
|
9771
10121
|
});
|
|
9772
10122
|
|
|
9773
10123
|
// src/process/js/async-sab.ts
|
|
9774
|
-
async function changed(header,
|
|
9775
|
-
const waited = waitAsync(header,
|
|
10124
|
+
async function changed(header, index3, seen, waitAsync = defaultWaitAsync) {
|
|
10125
|
+
const waited = waitAsync(header, index3, seen);
|
|
9776
10126
|
if (waited.async) await waited.value;
|
|
9777
10127
|
}
|
|
9778
10128
|
function createAsyncSabTransport(sab, port2, waitAsync = defaultWaitAsync) {
|
|
@@ -10534,7 +10884,7 @@ function openRequest(abs, o) {
|
|
|
10534
10884
|
...o.truncate ? { truncate: true } : {}
|
|
10535
10885
|
};
|
|
10536
10886
|
}
|
|
10537
|
-
function
|
|
10887
|
+
function index2(n, what) {
|
|
10538
10888
|
if (!Number.isSafeInteger(n) || n < 0) throw new JsCallError("EINVAL", what);
|
|
10539
10889
|
}
|
|
10540
10890
|
var CHUNK2, MAX_IO, O_WRONLY6, O_RDWR6, O_APPEND3;
|
|
@@ -10707,7 +11057,7 @@ function syncOps(kernel, shared) {
|
|
|
10707
11057
|
return got;
|
|
10708
11058
|
};
|
|
10709
11059
|
const read2 = (fd, max = CHUNK2) => {
|
|
10710
|
-
|
|
11060
|
+
index2(max, "read");
|
|
10711
11061
|
const emulated = readDevice(info(fd), max, shared.random);
|
|
10712
11062
|
if (emulated) return emulated;
|
|
10713
11063
|
const r = kernel.blocking({ op: "fd-read", fd, max: Math.min(max, MAX_IO) });
|
|
@@ -10785,8 +11135,8 @@ function syncFile(kernel, fd, path, append, forget) {
|
|
|
10785
11135
|
return kernel.json({ op: "fd-vfs-stat", fd }).size;
|
|
10786
11136
|
},
|
|
10787
11137
|
read(position, length) {
|
|
10788
|
-
|
|
10789
|
-
|
|
11138
|
+
index2(position, "read");
|
|
11139
|
+
index2(length, "read");
|
|
10790
11140
|
const parts = [];
|
|
10791
11141
|
let got = 0;
|
|
10792
11142
|
do {
|
|
@@ -10801,7 +11151,7 @@ function syncFile(kernel, fd, path, append, forget) {
|
|
|
10801
11151
|
return joined(parts, got);
|
|
10802
11152
|
},
|
|
10803
11153
|
write(position, data) {
|
|
10804
|
-
|
|
11154
|
+
index2(position, "write");
|
|
10805
11155
|
let at = 0;
|
|
10806
11156
|
do {
|
|
10807
11157
|
live();
|
|
@@ -10815,7 +11165,7 @@ function syncFile(kernel, fd, path, append, forget) {
|
|
|
10815
11165
|
},
|
|
10816
11166
|
truncate(size) {
|
|
10817
11167
|
live();
|
|
10818
|
-
|
|
11168
|
+
index2(size, "truncate");
|
|
10819
11169
|
kernel.call({ op: "fd-resize", fd, size });
|
|
10820
11170
|
},
|
|
10821
11171
|
sync() {
|
|
@@ -10846,6 +11196,7 @@ function syncPathOps(kernel, resolve, statOf, open) {
|
|
|
10846
11196
|
rm: (path) => void kernel.call({ op: "rm", path: resolve(path) }),
|
|
10847
11197
|
unlink: (path) => void kernel.call({ op: "unlink", path: resolve(path) }),
|
|
10848
11198
|
rename: (from, to) => void kernel.call({ op: "rename", path: resolve(from), arg2: resolve(to) }),
|
|
11199
|
+
link: (from, to) => void kernel.call({ op: "link", path: resolve(from), arg2: resolve(to) }),
|
|
10849
11200
|
symlink: (target, path) => void kernel.call({ op: "symlink", path: resolve(path), arg2: target }),
|
|
10850
11201
|
readlink: (path) => String(kernel.json({ op: "readlink", path: resolve(path) })),
|
|
10851
11202
|
readFile(path) {
|
|
@@ -11211,7 +11562,7 @@ function createContext(o) {
|
|
|
11211
11562
|
return got;
|
|
11212
11563
|
};
|
|
11213
11564
|
const read2 = async (fd, max = CHUNK2, signal) => {
|
|
11214
|
-
|
|
11565
|
+
index2(max, "read");
|
|
11215
11566
|
const emulated = readDevice(await info(fd), max, random);
|
|
11216
11567
|
if (emulated) return emulated;
|
|
11217
11568
|
return readPipe(kernel, fd, Math.min(max, MAX_IO), signal);
|
|
@@ -11358,8 +11709,8 @@ function fileHandle(kernel, fd, path, append, forget) {
|
|
|
11358
11709
|
return s.size;
|
|
11359
11710
|
},
|
|
11360
11711
|
async read(position, length) {
|
|
11361
|
-
|
|
11362
|
-
|
|
11712
|
+
index2(position, "read");
|
|
11713
|
+
index2(length, "read");
|
|
11363
11714
|
const parts = [];
|
|
11364
11715
|
let got = 0;
|
|
11365
11716
|
do {
|
|
@@ -11374,7 +11725,7 @@ function fileHandle(kernel, fd, path, append, forget) {
|
|
|
11374
11725
|
return joined(parts, got);
|
|
11375
11726
|
},
|
|
11376
11727
|
async write(position, data) {
|
|
11377
|
-
|
|
11728
|
+
index2(position, "write");
|
|
11378
11729
|
let at = 0;
|
|
11379
11730
|
do {
|
|
11380
11731
|
live();
|
|
@@ -11388,7 +11739,7 @@ function fileHandle(kernel, fd, path, append, forget) {
|
|
|
11388
11739
|
},
|
|
11389
11740
|
async truncate(size) {
|
|
11390
11741
|
live();
|
|
11391
|
-
|
|
11742
|
+
index2(size, "truncate");
|
|
11392
11743
|
await kernel.call({ op: "fd-resize", fd, size });
|
|
11393
11744
|
},
|
|
11394
11745
|
async sync() {
|
|
@@ -11442,6 +11793,7 @@ function pathOps(kernel, resolve, statOf, open) {
|
|
|
11442
11793
|
rm: async (path) => void await kernel.call({ op: "rm", path: resolve(path) }),
|
|
11443
11794
|
unlink: async (path) => void await kernel.call({ op: "unlink", path: resolve(path) }),
|
|
11444
11795
|
rename: async (from, to) => void await kernel.call({ op: "rename", path: resolve(from), arg2: resolve(to) }),
|
|
11796
|
+
link: async (from, to) => void await kernel.call({ op: "link", path: resolve(from), arg2: resolve(to) }),
|
|
11445
11797
|
symlink: async (target, path) => void await kernel.call({ op: "symlink", path: resolve(path), arg2: target }),
|
|
11446
11798
|
readlink: async (path) => String(await kernel.json({ op: "readlink", path: resolve(path) })),
|
|
11447
11799
|
async readFile(path) {
|