@ai-ecoverse/slicc-kernel 1.172.1 → 1.173.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 +12 -5
- package/dist/index.js +37 -5
- package/dist/index.js.map +3 -3
- package/dist/kernel-worker.js +443 -190
- package/dist/kernel-worker.js.map +4 -4
- package/dist/meta.js +204 -27
- package/dist/meta.js.map +4 -4
- package/dist/node-process-worker.cjs +3 -1
- package/dist/node-process-worker.cjs.map +2 -2
- package/dist/node-process-worker.js +3 -1
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +18 -3
- package/dist/node.js.map +2 -2
- package/dist/process-worker.js +3 -1
- package/dist/process-worker.js.map +2 -2
- package/dist/types/fs/meta-reads.d.ts +41 -0
- package/dist/types/fs/meta.d.ts +12 -1
- package/dist/types/fs/opfs.d.ts +2 -1
- package/dist/types/fs/portable.d.ts +11 -0
- package/dist/types/fs/roots.d.ts +1 -1
- package/dist/types/fs/types.d.ts +4 -0
- package/dist/types/fs/watch.d.ts +3 -0
- package/dist/types/kernel/proc-info.d.ts +4 -0
- package/dist/types/mount/media.d.ts +3 -1
- package/dist/types/serve.d.ts +6 -4
- package/package.json +4 -4
package/dist/kernel-worker.js
CHANGED
|
@@ -1,5 +1,149 @@
|
|
|
1
|
+
// src/fs/meta-reads.ts
|
|
2
|
+
var parentOf = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
3
|
+
var within = (path, root) => root === "/" || path === root || path.startsWith(`${root}/`);
|
|
4
|
+
var Invalidations = class {
|
|
5
|
+
seq = 0;
|
|
6
|
+
log = [];
|
|
7
|
+
open = /* @__PURE__ */ new Map();
|
|
8
|
+
start() {
|
|
9
|
+
const at = this.seq;
|
|
10
|
+
this.open.set(at, (this.open.get(at) ?? 0) + 1);
|
|
11
|
+
return at;
|
|
12
|
+
}
|
|
13
|
+
end(at) {
|
|
14
|
+
const left = (this.open.get(at) ?? 1) - 1;
|
|
15
|
+
if (left > 0) this.open.set(at, left);
|
|
16
|
+
else this.open.delete(at);
|
|
17
|
+
const oldest = this.open.keys().next();
|
|
18
|
+
if (oldest.done) this.log.length = 0;
|
|
19
|
+
else while (this.log.length > 0 && this.log[0].at <= oldest.value) this.log.shift();
|
|
20
|
+
}
|
|
21
|
+
note({ paths = [], trees = [] }) {
|
|
22
|
+
this.seq++;
|
|
23
|
+
if (this.open.size > 0) this.log.push({ at: this.seq, paths, trees });
|
|
24
|
+
}
|
|
25
|
+
since(at, hit) {
|
|
26
|
+
for (let i = this.log.length - 1; i >= 0; i--) {
|
|
27
|
+
const noted2 = this.log[i];
|
|
28
|
+
if (noted2.at <= at) return false;
|
|
29
|
+
if (hit(noted2)) return true;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
entryStale(at, path) {
|
|
34
|
+
return this.since(
|
|
35
|
+
at,
|
|
36
|
+
({ paths, trees }) => paths.includes(path) || trees.some((tree2) => within(path, tree2))
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
listingStale(at, dir) {
|
|
40
|
+
return this.since(
|
|
41
|
+
at,
|
|
42
|
+
({ paths, trees }) => paths.some((path) => path !== "/" && parentOf(path) === dir) || trees.some((tree2) => within(dir, tree2) || tree2 !== "/" && parentOf(tree2) === dir)
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var META_READS_IN_FLIGHT = 4;
|
|
47
|
+
var BatchedReads = class {
|
|
48
|
+
run;
|
|
49
|
+
invalidations;
|
|
50
|
+
keep;
|
|
51
|
+
queued = {
|
|
52
|
+
entry: /* @__PURE__ */ new Map(),
|
|
53
|
+
links: /* @__PURE__ */ new Map()
|
|
54
|
+
};
|
|
55
|
+
reading = {
|
|
56
|
+
entry: /* @__PURE__ */ new Map(),
|
|
57
|
+
links: /* @__PURE__ */ new Map()
|
|
58
|
+
};
|
|
59
|
+
inFlight = 0;
|
|
60
|
+
constructor(invalidations, run2, keep2) {
|
|
61
|
+
this.invalidations = invalidations;
|
|
62
|
+
this.run = run2;
|
|
63
|
+
this.keep = keep2;
|
|
64
|
+
}
|
|
65
|
+
entries(paths) {
|
|
66
|
+
const wanted = paths.map((path) => [path, this.want("entry", path)]);
|
|
67
|
+
this.pump();
|
|
68
|
+
return Promise.all(wanted.map(([, w]) => w.promise)).then(
|
|
69
|
+
(found) => new Map(wanted.map(([path], i) => [path, found[i]]))
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
links(dir) {
|
|
73
|
+
const wanted = this.want("links", dir);
|
|
74
|
+
this.pump();
|
|
75
|
+
return wanted.promise;
|
|
76
|
+
}
|
|
77
|
+
stale(kind, key, at) {
|
|
78
|
+
return kind === "entry" ? this.invalidations.entryStale(at, key) : this.invalidations.listingStale(at, key);
|
|
79
|
+
}
|
|
80
|
+
want(kind, key) {
|
|
81
|
+
const reading = this.reading[kind].get(key);
|
|
82
|
+
if (reading && !this.stale(kind, key, reading.at)) return reading;
|
|
83
|
+
const queued = this.queued[kind].get(key);
|
|
84
|
+
if (queued) return queued;
|
|
85
|
+
const made2 = Promise.withResolvers();
|
|
86
|
+
made2.promise.catch(() => void 0);
|
|
87
|
+
this.queued[kind].set(key, made2);
|
|
88
|
+
return made2;
|
|
89
|
+
}
|
|
90
|
+
pump() {
|
|
91
|
+
while (this.inFlight < META_READS_IN_FLIGHT && (this.queued.entry.size > 0 || this.queued.links.size > 0)) {
|
|
92
|
+
this.flush();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
flush() {
|
|
96
|
+
const entries = this.queued.entry;
|
|
97
|
+
const links = this.queued.links;
|
|
98
|
+
this.queued.entry = /* @__PURE__ */ new Map();
|
|
99
|
+
this.queued.links = /* @__PURE__ */ new Map();
|
|
100
|
+
const at = this.invalidations.start();
|
|
101
|
+
for (const [kind, taken] of [
|
|
102
|
+
["entry", entries],
|
|
103
|
+
["links", links]
|
|
104
|
+
]) {
|
|
105
|
+
for (const [key, wanted] of taken) {
|
|
106
|
+
wanted.at = at;
|
|
107
|
+
this.reading[kind].set(key, wanted);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
this.inFlight++;
|
|
111
|
+
const settled = (result, error) => {
|
|
112
|
+
this.inFlight--;
|
|
113
|
+
for (const [kind, taken, found] of [
|
|
114
|
+
["entry", entries, result?.entries],
|
|
115
|
+
["links", links, result?.links]
|
|
116
|
+
]) {
|
|
117
|
+
for (const [key, wanted] of taken) {
|
|
118
|
+
if (this.reading[kind].get(key) === wanted) this.reading[kind].delete(key);
|
|
119
|
+
if (!found) {
|
|
120
|
+
wanted.reject(error);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const value2 = found.get(key) ?? (kind === "entry" ? null : []);
|
|
124
|
+
if (!this.stale(kind, key, at)) this.keep(kind, key, value2);
|
|
125
|
+
wanted.resolve(value2);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
this.invalidations.end(at);
|
|
129
|
+
this.pump();
|
|
130
|
+
};
|
|
131
|
+
let reading;
|
|
132
|
+
try {
|
|
133
|
+
reading = this.run({ entries: [...entries.keys()], links: [...links.keys()] });
|
|
134
|
+
} catch (error) {
|
|
135
|
+
settled(void 0, error);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
reading.then(
|
|
139
|
+
(result) => settled(result),
|
|
140
|
+
(error) => settled(void 0, error)
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
1
145
|
// src/fs/path-map.ts
|
|
2
|
-
function
|
|
146
|
+
function parentOf2(path) {
|
|
3
147
|
if (path === "/" || path === "") return void 0;
|
|
4
148
|
const at = path.lastIndexOf("/");
|
|
5
149
|
return at <= 0 ? "/" : path.slice(0, at);
|
|
@@ -57,24 +201,24 @@ var PathMap = class {
|
|
|
57
201
|
this.children.clear();
|
|
58
202
|
}
|
|
59
203
|
link(path) {
|
|
60
|
-
for (let child = path, parent =
|
|
204
|
+
for (let child = path, parent = parentOf2(path); parent !== void 0; ) {
|
|
61
205
|
const set3 = this.children.get(parent);
|
|
62
206
|
if (set3?.has(child)) return;
|
|
63
207
|
if (set3) set3.add(child);
|
|
64
208
|
else this.children.set(parent, /* @__PURE__ */ new Set([child]));
|
|
65
209
|
child = parent;
|
|
66
|
-
parent =
|
|
210
|
+
parent = parentOf2(parent);
|
|
67
211
|
}
|
|
68
212
|
}
|
|
69
213
|
prune(path) {
|
|
70
|
-
for (let child = path, parent =
|
|
214
|
+
for (let child = path, parent = parentOf2(path); parent !== void 0; ) {
|
|
71
215
|
if (this.values.has(child) || this.children.has(child)) return;
|
|
72
216
|
const set3 = this.children.get(parent);
|
|
73
217
|
set3?.delete(child);
|
|
74
218
|
if (set3 && set3.size > 0) return;
|
|
75
219
|
this.children.delete(parent);
|
|
76
220
|
child = parent;
|
|
77
|
-
parent =
|
|
221
|
+
parent = parentOf2(parent);
|
|
78
222
|
}
|
|
79
223
|
}
|
|
80
224
|
};
|
|
@@ -83,11 +227,11 @@ var PathMap = class {
|
|
|
83
227
|
var META_DB = "slicc-kernel";
|
|
84
228
|
var META_VERSION = 1;
|
|
85
229
|
var META_STORE = "entries";
|
|
86
|
-
function
|
|
230
|
+
function parentOf3(path) {
|
|
87
231
|
return path.slice(0, path.lastIndexOf("/")) || "/";
|
|
88
232
|
}
|
|
89
233
|
function moved(entry, path) {
|
|
90
|
-
return entry.link === void 0 ? { ...entry, path } : { ...entry, path, dir:
|
|
234
|
+
return entry.link === void 0 ? { ...entry, path } : { ...entry, path, dir: parentOf3(path) };
|
|
91
235
|
}
|
|
92
236
|
function under(path, root) {
|
|
93
237
|
return path === root || path.startsWith(`${root}/`);
|
|
@@ -146,11 +290,21 @@ function settle(transaction, value2) {
|
|
|
146
290
|
}
|
|
147
291
|
var REMOVE_BATCH = 256;
|
|
148
292
|
var REMOVE_WAIT_MS = 5;
|
|
293
|
+
var LISTINGS_KEPT = 4096;
|
|
149
294
|
var IndexedDbMeta = class {
|
|
150
295
|
db;
|
|
151
296
|
cache = new PathMap();
|
|
297
|
+
listings = new PathMap();
|
|
152
298
|
channel;
|
|
153
|
-
|
|
299
|
+
invalidations = new Invalidations();
|
|
300
|
+
reads = new BatchedReads(
|
|
301
|
+
this.invalidations,
|
|
302
|
+
(batch) => this.read(batch),
|
|
303
|
+
(kind, key, value2) => {
|
|
304
|
+
if (kind === "entry") this.cache.set(key, value2);
|
|
305
|
+
else this.keepListing(key, value2);
|
|
306
|
+
}
|
|
307
|
+
);
|
|
154
308
|
listeners = /* @__PURE__ */ new Set();
|
|
155
309
|
listen(listener) {
|
|
156
310
|
this.listeners.add(listener);
|
|
@@ -169,32 +323,56 @@ var IndexedDbMeta = class {
|
|
|
169
323
|
this.drop({ trees: [...trees] });
|
|
170
324
|
}
|
|
171
325
|
drop({ paths = [], trees = [] }) {
|
|
172
|
-
this.
|
|
173
|
-
for (const path of paths)
|
|
174
|
-
|
|
326
|
+
this.invalidations.note({ paths, trees });
|
|
327
|
+
for (const path of paths) {
|
|
328
|
+
this.cache.delete(path);
|
|
329
|
+
if (path !== "/") this.listings.delete(parentOf3(path));
|
|
330
|
+
}
|
|
331
|
+
for (const tree2 of trees) {
|
|
332
|
+
this.cache.deleteTree(tree2);
|
|
333
|
+
this.listings.deleteTree(tree2);
|
|
334
|
+
if (tree2 !== "/") this.listings.delete(parentOf3(tree2));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
keepListing(dir, links) {
|
|
338
|
+
if (this.listings.size >= LISTINGS_KEPT) this.listings.clear();
|
|
339
|
+
this.listings.set(dir, links);
|
|
340
|
+
}
|
|
341
|
+
async read({ entries, links }) {
|
|
342
|
+
this.settleRemoves();
|
|
343
|
+
const [transaction, store] = this.transaction("readonly");
|
|
344
|
+
const result = { entries: /* @__PURE__ */ new Map(), links: /* @__PURE__ */ new Map() };
|
|
345
|
+
for (const path of entries) {
|
|
346
|
+
const request3 = store.get(path);
|
|
347
|
+
request3.onsuccess = () => void result.entries.set(path, request3.result ?? null);
|
|
348
|
+
}
|
|
349
|
+
if (links.length > 0) {
|
|
350
|
+
const index = store.index("dir");
|
|
351
|
+
for (const dir of links) {
|
|
352
|
+
const request3 = index.getAll(dir);
|
|
353
|
+
request3.onsuccess = () => void result.links.set(dir, request3.result);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return settle(transaction, () => result);
|
|
175
357
|
}
|
|
176
358
|
changed(invalidation2) {
|
|
177
359
|
this.drop(invalidation2);
|
|
178
360
|
this.channel.postMessage(invalidation2);
|
|
179
361
|
}
|
|
362
|
+
counted = { reads: 0, writes: 0 };
|
|
363
|
+
transactions() {
|
|
364
|
+
return { ...this.counted };
|
|
365
|
+
}
|
|
180
366
|
transaction(mode) {
|
|
367
|
+
if (mode === "readonly") this.counted.reads++;
|
|
368
|
+
else this.counted.writes++;
|
|
181
369
|
const transaction = this.db.transaction(META_STORE, mode);
|
|
182
370
|
return [transaction, transaction.objectStore(META_STORE)];
|
|
183
371
|
}
|
|
184
372
|
async get(paths) {
|
|
185
373
|
const missing6 = paths.filter((path) => !this.cache.has(path));
|
|
186
374
|
if (missing6.length > 0) {
|
|
187
|
-
this.
|
|
188
|
-
const generation = this.generation;
|
|
189
|
-
const [transaction, store] = this.transaction("readonly");
|
|
190
|
-
const found = /* @__PURE__ */ new Map();
|
|
191
|
-
for (const path of missing6) {
|
|
192
|
-
const request3 = store.get(path);
|
|
193
|
-
request3.onsuccess = () => void found.set(path, request3.result ?? null);
|
|
194
|
-
}
|
|
195
|
-
await settle(transaction, () => void 0);
|
|
196
|
-
if (generation === this.generation)
|
|
197
|
-
for (const [path, entry] of found) this.cache.set(path, entry);
|
|
375
|
+
const found = await this.reads.entries(missing6);
|
|
198
376
|
return paths.map(
|
|
199
377
|
(path) => (found.has(path) ? found.get(path) : this.cache.get(path)) ?? void 0
|
|
200
378
|
);
|
|
@@ -276,7 +454,8 @@ var IndexedDbMeta = class {
|
|
|
276
454
|
async removeFile(path) {
|
|
277
455
|
const known = this.cache.get(path);
|
|
278
456
|
if (!known) return this.remove([path]);
|
|
279
|
-
this.
|
|
457
|
+
this.invalidations.note({ paths: [path] });
|
|
458
|
+
if (path !== "/") this.listings.delete(parentOf3(path));
|
|
280
459
|
this.cache.set(path, null);
|
|
281
460
|
this.removing.set(path, JSON.stringify(known));
|
|
282
461
|
if (this.removing.size >= REMOVE_BATCH) return this.flushRemoves();
|
|
@@ -316,10 +495,8 @@ var IndexedDbMeta = class {
|
|
|
316
495
|
return settle(transaction, () => void this.channel.postMessage({ paths }));
|
|
317
496
|
}
|
|
318
497
|
async links(dir) {
|
|
319
|
-
this.
|
|
320
|
-
|
|
321
|
-
const request3 = store.index("dir").getAll(dir);
|
|
322
|
-
return settle(transaction, () => request3.result);
|
|
498
|
+
const known = this.listings.get(dir);
|
|
499
|
+
return [...known ?? await this.reads.links(dir)];
|
|
323
500
|
}
|
|
324
501
|
async under(path) {
|
|
325
502
|
this.settleRemoves();
|
|
@@ -803,14 +980,14 @@ function protectedPrefixes(paths) {
|
|
|
803
980
|
}
|
|
804
981
|
return [...new Set(paths.map((p) => normalizePath(p)))];
|
|
805
982
|
}
|
|
806
|
-
function
|
|
983
|
+
function within2(path, prefix) {
|
|
807
984
|
return prefix === "/" || path === prefix || path.startsWith(`${prefix}/`);
|
|
808
985
|
}
|
|
809
986
|
function isProtected(prefixes2, path) {
|
|
810
|
-
return prefixes2.some((prefix) =>
|
|
987
|
+
return prefixes2.some((prefix) => within2(path, prefix));
|
|
811
988
|
}
|
|
812
989
|
function holdsProtected(prefixes2, path) {
|
|
813
|
-
return prefixes2.some((prefix) =>
|
|
990
|
+
return prefixes2.some((prefix) => within2(prefix, path));
|
|
814
991
|
}
|
|
815
992
|
var MAX_LINKS = 40;
|
|
816
993
|
function partsOf(path) {
|
|
@@ -1537,6 +1714,7 @@ function sidecar(meta) {
|
|
|
1537
1714
|
};
|
|
1538
1715
|
if (meta.absent) ops.absent = meta.absent.bind(meta);
|
|
1539
1716
|
if (meta.forgetTrees) ops.forgetTrees = meta.forgetTrees.bind(meta);
|
|
1717
|
+
if (meta.transactions) ops.transactions = meta.transactions.bind(meta);
|
|
1540
1718
|
const { removeFile } = meta;
|
|
1541
1719
|
if (removeFile)
|
|
1542
1720
|
ops.removeFile = (path) => removeFile.call(meta, path).catch((err) => {
|
|
@@ -1559,7 +1737,7 @@ function missing2(err) {
|
|
|
1559
1737
|
function split(path) {
|
|
1560
1738
|
return path.split("/").filter(Boolean);
|
|
1561
1739
|
}
|
|
1562
|
-
function
|
|
1740
|
+
function parentOf4(path) {
|
|
1563
1741
|
return path.slice(0, path.lastIndexOf("/")) || "/";
|
|
1564
1742
|
}
|
|
1565
1743
|
function baseOf(path) {
|
|
@@ -1569,7 +1747,7 @@ function prefixes(path) {
|
|
|
1569
1747
|
const parts2 = split(path);
|
|
1570
1748
|
return parts2.map((_, i) => `/${parts2.slice(0, i + 1).join("/")}`);
|
|
1571
1749
|
}
|
|
1572
|
-
function
|
|
1750
|
+
function within3(path, root) {
|
|
1573
1751
|
return path === root || path.startsWith(`${root}/`);
|
|
1574
1752
|
}
|
|
1575
1753
|
var unstored = () => Object.assign(new Error("the file system kept fewer bytes than were written"), {
|
|
@@ -1931,7 +2109,7 @@ var OpfsFs = class {
|
|
|
1931
2109
|
async ownerAt(path, entry) {
|
|
1932
2110
|
const own = ownOf(entry);
|
|
1933
2111
|
if (own) return own;
|
|
1934
|
-
return path === "/" ? { ...ROOT_OWNER } : this.handedTo(
|
|
2112
|
+
return path === "/" ? { ...ROOT_OWNER } : this.handedTo(parentOf4(path));
|
|
1935
2113
|
}
|
|
1936
2114
|
async owned(stat, path, entry) {
|
|
1937
2115
|
return this.owners ? { ...stat, ...await this.ownerAt(path, entry) } : stat;
|
|
@@ -2026,18 +2204,18 @@ var OpfsFs = class {
|
|
|
2026
2204
|
async chown(path, change) {
|
|
2027
2205
|
if (!this.owners) return;
|
|
2028
2206
|
if (change.kind === "new") {
|
|
2029
|
-
const at = resolvePath((await this.locate(
|
|
2207
|
+
const at = resolvePath((await this.locate(parentOf4(path), true)).path, baseOf(path));
|
|
2030
2208
|
this.refuse(at);
|
|
2031
2209
|
const { uid = 0, gid = 0, mode } = change;
|
|
2032
2210
|
return this.stampNew(at, { uid, gid, ...mode !== void 0 ? { mode } : {} }, false);
|
|
2033
2211
|
}
|
|
2034
2212
|
const found = await this.locate(path, change.follow !== false);
|
|
2035
2213
|
this.refuse(found.path);
|
|
2036
|
-
const [
|
|
2037
|
-
const current = await this.ownerAt(found.path,
|
|
2214
|
+
const [stored2] = found.link ? [found.link] : await this.meta.get([found.path]);
|
|
2215
|
+
const current = await this.ownerAt(found.path, stored2);
|
|
2038
2216
|
const next3 = { uid: change.uid ?? current.uid, gid: change.gid ?? current.gid };
|
|
2039
2217
|
const handing = found.handle?.kind === "directory" && !sameOwner(next3, current);
|
|
2040
|
-
const heir = change.kind === "adopt" ? void 0 :
|
|
2218
|
+
const heir = change.kind === "adopt" ? void 0 : stored2?.heir ?? (handing ? [current.uid, current.gid] : void 0);
|
|
2041
2219
|
const ctimeMs = Date.now();
|
|
2042
2220
|
await this.meta.update(found.path, (entry) => {
|
|
2043
2221
|
const { heir: _, ...rest2 } = entry ?? found.link ?? { path: found.path };
|
|
@@ -2053,8 +2231,8 @@ var OpfsFs = class {
|
|
|
2053
2231
|
}
|
|
2054
2232
|
async movedOwner(source) {
|
|
2055
2233
|
if (!this.owners) return void 0;
|
|
2056
|
-
const [
|
|
2057
|
-
return ownOf(
|
|
2234
|
+
const [stored2] = source.link ? [source.link] : await this.meta.get([source.path]);
|
|
2235
|
+
return ownOf(stored2) ? void 0 : this.ownerAt(source.path, stored2);
|
|
2058
2236
|
}
|
|
2059
2237
|
async walk(parts2, from, start2) {
|
|
2060
2238
|
let dir = start2;
|
|
@@ -2107,6 +2285,9 @@ var OpfsFs = class {
|
|
|
2107
2285
|
opfsOps() {
|
|
2108
2286
|
return this.calls + this.others;
|
|
2109
2287
|
}
|
|
2288
|
+
metaTransactions() {
|
|
2289
|
+
return this.meta.transactions?.();
|
|
2290
|
+
}
|
|
2110
2291
|
io(request3) {
|
|
2111
2292
|
this.others++;
|
|
2112
2293
|
return request3;
|
|
@@ -2229,7 +2410,7 @@ var OpfsFs = class {
|
|
|
2229
2410
|
for (const entry of await this.meta.get(prefixes(path))) {
|
|
2230
2411
|
if (entry?.link === void 0) continue;
|
|
2231
2412
|
if (entry.path !== path && await this.real(entry.path)) continue;
|
|
2232
|
-
if (await this.real(
|
|
2413
|
+
if (await this.real(parentOf4(entry.path))) return entry;
|
|
2233
2414
|
}
|
|
2234
2415
|
return void 0;
|
|
2235
2416
|
}
|
|
@@ -2261,11 +2442,11 @@ var OpfsFs = class {
|
|
|
2261
2442
|
if (this.rejectLinks) throw fsError("ELOOP", path);
|
|
2262
2443
|
const target = `${link2.link}${current.slice(link2.path.length)}`;
|
|
2263
2444
|
if (target.split("/").includes("..")) {
|
|
2264
|
-
const resolved2 = await this.physical(
|
|
2445
|
+
const resolved2 = await this.physical(parentOf4(link2.path), target, hops + 1, path);
|
|
2265
2446
|
current = resolved2.path;
|
|
2266
2447
|
hops = resolved2.hops - 1;
|
|
2267
2448
|
} else {
|
|
2268
|
-
current = resolvePath(
|
|
2449
|
+
current = resolvePath(parentOf4(link2.path), target);
|
|
2269
2450
|
}
|
|
2270
2451
|
this.crossing(path, current);
|
|
2271
2452
|
}
|
|
@@ -2356,11 +2537,11 @@ var OpfsFs = class {
|
|
|
2356
2537
|
movePending(from, to) {
|
|
2357
2538
|
if (to !== void 0) {
|
|
2358
2539
|
for (const path of [...this.fileTimes.keys()]) {
|
|
2359
|
-
if (
|
|
2540
|
+
if (within3(path, to)) this.fileTimes.delete(path);
|
|
2360
2541
|
}
|
|
2361
2542
|
}
|
|
2362
2543
|
for (const [path, ms] of [...this.fileTimes]) {
|
|
2363
|
-
if (!
|
|
2544
|
+
if (!within3(path, from)) continue;
|
|
2364
2545
|
this.fileTimes.delete(path);
|
|
2365
2546
|
if (to !== void 0) this.fileTimes.set(to + path.slice(from.length), ms);
|
|
2366
2547
|
}
|
|
@@ -2637,8 +2818,8 @@ var OpfsFs = class {
|
|
|
2637
2818
|
const file = this.movingFiles.get(at);
|
|
2638
2819
|
if (file !== void 0) return { done: file, away: true };
|
|
2639
2820
|
for (const m of this.renamingDirs) {
|
|
2640
|
-
if (
|
|
2641
|
-
if (
|
|
2821
|
+
if (within3(at, m.from)) return { done: m.done, away: true };
|
|
2822
|
+
if (within3(at, m.to)) return { done: m.done, away: false };
|
|
2642
2823
|
}
|
|
2643
2824
|
return void 0;
|
|
2644
2825
|
}
|
|
@@ -2674,7 +2855,7 @@ var OpfsFs = class {
|
|
|
2674
2855
|
idle2.resolve();
|
|
2675
2856
|
}
|
|
2676
2857
|
async writesDrained(tree2) {
|
|
2677
|
-
while ([...this.fileWrites.keys()].some((at) =>
|
|
2858
|
+
while ([...this.fileWrites.keys()].some((at) => within3(at, tree2))) {
|
|
2678
2859
|
this.writesIdle ??= Promise.withResolvers();
|
|
2679
2860
|
await this.writesIdle.promise;
|
|
2680
2861
|
}
|
|
@@ -2790,8 +2971,8 @@ var OpfsFs = class {
|
|
|
2790
2971
|
if (!missing2(err)) throw err;
|
|
2791
2972
|
}
|
|
2792
2973
|
const [entry] = await this.meta.get([path]);
|
|
2793
|
-
const wanted = entry?.link === void 0 ? path : resolvePath(
|
|
2794
|
-
return [resolvePath((await this.locate(
|
|
2974
|
+
const wanted = entry?.link === void 0 ? path : resolvePath(parentOf4(path), entry.link);
|
|
2975
|
+
return [resolvePath((await this.locate(parentOf4(wanted), true)).path, baseOf(wanted)), false];
|
|
2795
2976
|
}
|
|
2796
2977
|
async fileFor(path, create = true) {
|
|
2797
2978
|
const [target, existed] = await this.writeTarget(path);
|
|
@@ -2806,7 +2987,7 @@ var OpfsFs = class {
|
|
|
2806
2987
|
dir,
|
|
2807
2988
|
(parent) => this.io(parent.getFileHandle(name2, { create }))
|
|
2808
2989
|
);
|
|
2809
|
-
if (!existed) this.touch(Date.now(),
|
|
2990
|
+
if (!existed) this.touch(Date.now(), parentOf4(target));
|
|
2810
2991
|
return [handle, existed, target];
|
|
2811
2992
|
} catch (err) {
|
|
2812
2993
|
const code = err?.name === "TypeMismatchError" ? "EISDIR" : null;
|
|
@@ -2895,8 +3076,8 @@ var OpfsFs = class {
|
|
|
2895
3076
|
gid: owner.gid,
|
|
2896
3077
|
...mode !== void 0 ? { mode, parents: mode } : {}
|
|
2897
3078
|
};
|
|
2898
|
-
await this.mkdir(
|
|
2899
|
-
const parent = await this.locate(
|
|
3079
|
+
await this.mkdir(parentOf4(path), { recursive: true, ...above ? { owner: above } : {} });
|
|
3080
|
+
const parent = await this.locate(parentOf4(path), true);
|
|
2900
3081
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
2901
3082
|
this.refuse(resolvePath(parent.path, baseOf(path)));
|
|
2902
3083
|
await this.io(parent.handle.getDirectoryHandle(baseOf(path), { create: true }));
|
|
@@ -2907,7 +3088,7 @@ var OpfsFs = class {
|
|
|
2907
3088
|
}
|
|
2908
3089
|
async mkdirExcl(path, owner) {
|
|
2909
3090
|
if (normalizePath(path) === "/") throw fsError("EEXIST", path);
|
|
2910
|
-
const parent = await this.locate(
|
|
3091
|
+
const parent = await this.locate(parentOf4(path), true);
|
|
2911
3092
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
2912
3093
|
const dir = parent.handle;
|
|
2913
3094
|
const name2 = baseOf(path);
|
|
@@ -2929,7 +3110,7 @@ var OpfsFs = class {
|
|
|
2929
3110
|
}
|
|
2930
3111
|
async createExclusive(path, owner) {
|
|
2931
3112
|
if (normalizePath(path) === "/") throw fsError("EEXIST", path);
|
|
2932
|
-
const parent = await this.locate(
|
|
3113
|
+
const parent = await this.locate(parentOf4(path), true);
|
|
2933
3114
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
2934
3115
|
const dir = parent.handle;
|
|
2935
3116
|
const name2 = baseOf(path);
|
|
@@ -2991,12 +3172,12 @@ var OpfsFs = class {
|
|
|
2991
3172
|
else this.forget(found.path);
|
|
2992
3173
|
this.movePending(found.path);
|
|
2993
3174
|
if (file && this.meta.absent?.(found.path)) {
|
|
2994
|
-
this.touch(now,
|
|
3175
|
+
this.touch(now, parentOf4(found.path));
|
|
2995
3176
|
return;
|
|
2996
3177
|
}
|
|
2997
3178
|
if (file && this.meta.removeFile) {
|
|
2998
3179
|
await this.meta.removeFile(found.path);
|
|
2999
|
-
this.touch(now,
|
|
3180
|
+
this.touch(now, parentOf4(found.path));
|
|
3000
3181
|
return;
|
|
3001
3182
|
}
|
|
3002
3183
|
}
|
|
@@ -3004,14 +3185,14 @@ var OpfsFs = class {
|
|
|
3004
3185
|
[found.path],
|
|
3005
3186
|
found.handle?.kind === "directory" ? vacatedAt(found.path) : void 0
|
|
3006
3187
|
);
|
|
3007
|
-
this.touch(Date.now(),
|
|
3188
|
+
this.touch(Date.now(), parentOf4(found.path));
|
|
3008
3189
|
}
|
|
3009
3190
|
links() {
|
|
3010
3191
|
return false;
|
|
3011
3192
|
}
|
|
3012
3193
|
async link(from, to, follow2) {
|
|
3013
3194
|
await (follow2 ? this.stat(from) : this.lstat(from));
|
|
3014
|
-
if (!(await this.stat(
|
|
3195
|
+
if (!(await this.stat(parentOf4(to))).isDirectory) throw fsError("ENOTDIR", to);
|
|
3015
3196
|
const taken = await this.exactly(() => this.lstat(to)).then(
|
|
3016
3197
|
() => true,
|
|
3017
3198
|
(err) => {
|
|
@@ -3038,14 +3219,14 @@ var OpfsFs = class {
|
|
|
3038
3219
|
const source = await this.locate(from, false);
|
|
3039
3220
|
this.refuse(source.path, true);
|
|
3040
3221
|
this.forget(source.path);
|
|
3041
|
-
const parent = await this.locate(
|
|
3222
|
+
const parent = await this.locate(parentOf4(to), true);
|
|
3042
3223
|
const destination = resolvePath(parent.path, baseOf(to));
|
|
3043
3224
|
this.refuse(destination, true);
|
|
3044
3225
|
await this.entering(destination, () => this.moveTo(source, parent, destination, to, call));
|
|
3045
3226
|
}
|
|
3046
3227
|
async moveTo(source, parent, destination, to, call) {
|
|
3047
3228
|
const sourceStat = await this.describe(source);
|
|
3048
|
-
if (sourceStat.isDirectory &&
|
|
3229
|
+
if (sourceStat.isDirectory && within3(destination, source.path)) throw fsError("EINVAL", to);
|
|
3049
3230
|
const target = await this.exactly(() => this.locate(destination, false)).catch((err) => {
|
|
3050
3231
|
if (missing2(err)) return null;
|
|
3051
3232
|
throw err;
|
|
@@ -3072,7 +3253,7 @@ var OpfsFs = class {
|
|
|
3072
3253
|
if (source.link) {
|
|
3073
3254
|
if (target?.handle) await this.rm(destination);
|
|
3074
3255
|
await this.meta.move(source.path, destination, carry, left);
|
|
3075
|
-
this.touch(Date.now(),
|
|
3256
|
+
this.touch(Date.now(), parentOf4(source.path), parent.path);
|
|
3076
3257
|
return;
|
|
3077
3258
|
}
|
|
3078
3259
|
const dir = parent.handle;
|
|
@@ -3121,7 +3302,7 @@ var OpfsFs = class {
|
|
|
3121
3302
|
if (second) await this.meta.update(second, () => void 0);
|
|
3122
3303
|
await this.restamp(destination, copies);
|
|
3123
3304
|
this.changed(source.path, destination);
|
|
3124
|
-
this.touch(Date.now(),
|
|
3305
|
+
this.touch(Date.now(), parentOf4(source.path), parent.path);
|
|
3125
3306
|
};
|
|
3126
3307
|
if (!copying) return sourceStat.isDirectory ? place() : this.movingFile(source.path, place);
|
|
3127
3308
|
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
@@ -3318,7 +3499,7 @@ var OpfsFs = class {
|
|
|
3318
3499
|
for (const move of this.peerMoves.values()) {
|
|
3319
3500
|
for (const tree2 of move.trees) {
|
|
3320
3501
|
for (const mine of [from, to]) {
|
|
3321
|
-
if (tree2.some((theirs) =>
|
|
3502
|
+
if (tree2.some((theirs) => within3(mine, theirs) || within3(theirs, mine))) return move;
|
|
3322
3503
|
}
|
|
3323
3504
|
}
|
|
3324
3505
|
}
|
|
@@ -3376,7 +3557,7 @@ var OpfsFs = class {
|
|
|
3376
3557
|
}
|
|
3377
3558
|
async resolvedForms(at) {
|
|
3378
3559
|
if (at === "/") return [];
|
|
3379
|
-
const parent = await PLAIN.realpath.call(this,
|
|
3560
|
+
const parent = await PLAIN.realpath.call(this, parentOf4(at), true).catch(() => parentOf4(at));
|
|
3380
3561
|
const named = resolvePath(parent, baseOf(at));
|
|
3381
3562
|
const target = await PLAIN.realpath.call(this, at, true).catch(() => named);
|
|
3382
3563
|
return [.../* @__PURE__ */ new Set([named, target])].filter((form) => form !== at);
|
|
@@ -3420,7 +3601,7 @@ var OpfsFs = class {
|
|
|
3420
3601
|
try {
|
|
3421
3602
|
if (await this.real(from)) {
|
|
3422
3603
|
const moved2 = await this.locate(from, false);
|
|
3423
|
-
const back = await this.locate(
|
|
3604
|
+
const back = await this.locate(parentOf4(to), true);
|
|
3424
3605
|
await this.copy(
|
|
3425
3606
|
moved2.handle,
|
|
3426
3607
|
back.handle,
|
|
@@ -3474,7 +3655,7 @@ var OpfsFs = class {
|
|
|
3474
3655
|
await PLAIN.rm.call(this, to, { recursive: true });
|
|
3475
3656
|
if (left) {
|
|
3476
3657
|
const source = await this.locate(from, false);
|
|
3477
|
-
const target = await this.locate(
|
|
3658
|
+
const target = await this.locate(parentOf4(to), true);
|
|
3478
3659
|
await this.copy(
|
|
3479
3660
|
source.handle,
|
|
3480
3661
|
target.handle,
|
|
@@ -3516,7 +3697,7 @@ var OpfsFs = class {
|
|
|
3516
3697
|
continue;
|
|
3517
3698
|
}
|
|
3518
3699
|
if (real !== void 0 || at === "/") return;
|
|
3519
|
-
const parent = await this.realpath(
|
|
3700
|
+
const parent = await this.realpath(parentOf4(at), true).catch(() => parentOf4(at));
|
|
3520
3701
|
real = resolvePath(parent, baseOf(at));
|
|
3521
3702
|
if (real === at) return;
|
|
3522
3703
|
}
|
|
@@ -3530,7 +3711,7 @@ var OpfsFs = class {
|
|
|
3530
3711
|
if (source.handle?.kind !== "file") throw fsError("EINVAL", `${from}: not a regular file`);
|
|
3531
3712
|
const [entry] = await this.meta.get([source.path]);
|
|
3532
3713
|
if (entry?.fifo || entry?.socket) throw fsError("EINVAL", `${from}: not a regular file`);
|
|
3533
|
-
const parent = await this.locate(
|
|
3714
|
+
const parent = await this.locate(parentOf4(to), true);
|
|
3534
3715
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", to);
|
|
3535
3716
|
const destination = resolvePath(parent.path, baseOf(to));
|
|
3536
3717
|
if (destination === source.path) throw fsError("EINVAL", `${from}: copied onto itself`);
|
|
@@ -3585,7 +3766,7 @@ var OpfsFs = class {
|
|
|
3585
3766
|
}
|
|
3586
3767
|
renameAt(at) {
|
|
3587
3768
|
for (const m of this.renamingDirs) {
|
|
3588
|
-
if (
|
|
3769
|
+
if (within3(at, m.from) || within3(at, m.to) || at === parentOf4(m.from) || at === parentOf4(m.to))
|
|
3589
3770
|
return m;
|
|
3590
3771
|
}
|
|
3591
3772
|
return void 0;
|
|
@@ -3678,7 +3859,7 @@ var OpfsFs = class {
|
|
|
3678
3859
|
}
|
|
3679
3860
|
}
|
|
3680
3861
|
async symlink(target, path, owner) {
|
|
3681
|
-
const parent = await this.locate(
|
|
3862
|
+
const parent = await this.locate(parentOf4(path), true);
|
|
3682
3863
|
if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
|
|
3683
3864
|
const at = resolvePath(parent.path, baseOf(path));
|
|
3684
3865
|
this.refuse(at);
|
|
@@ -3769,7 +3950,7 @@ var OpfsFs = class {
|
|
|
3769
3950
|
const known = listed.get(dir);
|
|
3770
3951
|
if (known !== void 0) return known;
|
|
3771
3952
|
const listing = (async () => {
|
|
3772
|
-
const above = dir === "/" ? void 0 : await list(
|
|
3953
|
+
const above = dir === "/" ? void 0 : await list(parentOf4(dir));
|
|
3773
3954
|
if (above === null) return null;
|
|
3774
3955
|
const handle = dir === "/" ? this.root : above?.get(baseOf(dir));
|
|
3775
3956
|
if (handle?.kind !== "directory") return void 0;
|
|
@@ -3789,7 +3970,7 @@ var OpfsFs = class {
|
|
|
3789
3970
|
listed.set(dir, listing);
|
|
3790
3971
|
return listing;
|
|
3791
3972
|
};
|
|
3792
|
-
const dirs = [...new Set(paths.filter((p) => split(p).length > 0).map(
|
|
3973
|
+
const dirs = [...new Set(paths.filter((p) => split(p).length > 0).map(parentOf4))];
|
|
3793
3974
|
let next3 = 0;
|
|
3794
3975
|
const lister = async () => {
|
|
3795
3976
|
while (next3 < dirs.length) await list(dirs[next3++]);
|
|
@@ -3797,7 +3978,7 @@ var OpfsFs = class {
|
|
|
3797
3978
|
await Promise.all(Array.from({ length: Math.min(RECONCILE_LISTINGS, dirs.length) }, lister));
|
|
3798
3979
|
return async (path) => {
|
|
3799
3980
|
if (split(path).length === 0) return true;
|
|
3800
|
-
const listing = done5.get(
|
|
3981
|
+
const listing = done5.get(parentOf4(path));
|
|
3801
3982
|
if (listing === null) return this.real(path);
|
|
3802
3983
|
return listing?.has(baseOf(path)) === true;
|
|
3803
3984
|
};
|
|
@@ -3813,10 +3994,10 @@ var OpfsFs = class {
|
|
|
3813
3994
|
const carried = new Set(entries.filter((e) => !e.vacated).map((e) => e.ino));
|
|
3814
3995
|
const checked = entries.filter((e) => !(e.vacated && carried.has(inodeOf(e.path))));
|
|
3815
3996
|
const real = await this.present(
|
|
3816
|
-
checked.flatMap((e) => e.link === void 0 ? [e.path] : [e.path,
|
|
3997
|
+
checked.flatMap((e) => e.link === void 0 ? [e.path] : [e.path, parentOf4(e.path)])
|
|
3817
3998
|
);
|
|
3818
3999
|
for (const entry of checked) {
|
|
3819
|
-
const stale = entry.link === void 0 ? !await real(entry.path) : await real(entry.path) || !await real(
|
|
4000
|
+
const stale = entry.link === void 0 ? !await real(entry.path) : await real(entry.path) || !await real(parentOf4(entry.path));
|
|
3820
4001
|
if (!stale) continue;
|
|
3821
4002
|
const seen = JSON.stringify(entry);
|
|
3822
4003
|
await this.meta.update(
|
|
@@ -3837,7 +4018,7 @@ function nothing() {
|
|
|
3837
4018
|
}
|
|
3838
4019
|
function touches(at, trees, listing = true, removing = false) {
|
|
3839
4020
|
return trees.some(
|
|
3840
|
-
([from, to]) =>
|
|
4021
|
+
([from, to]) => within3(at, from) || within3(at, to) || listing && (at === parentOf4(from) || at === parentOf4(to)) || removing && (at === "/" || within3(from, at) || within3(to, at))
|
|
3841
4022
|
);
|
|
3842
4023
|
}
|
|
3843
4024
|
function byIntent(a, b) {
|
|
@@ -3905,6 +4086,38 @@ for (const [names2, op] of [
|
|
|
3905
4086
|
}
|
|
3906
4087
|
}
|
|
3907
4088
|
|
|
4089
|
+
// src/fs/portable.ts
|
|
4090
|
+
var privateTop = () => navigator.storage.getDirectory();
|
|
4091
|
+
function clonable(handle) {
|
|
4092
|
+
const { port1, port2 } = new MessageChannel();
|
|
4093
|
+
try {
|
|
4094
|
+
port1.postMessage(handle);
|
|
4095
|
+
return true;
|
|
4096
|
+
} catch (err) {
|
|
4097
|
+
if (err?.name === "DataCloneError") return false;
|
|
4098
|
+
throw err;
|
|
4099
|
+
} finally {
|
|
4100
|
+
port1.close();
|
|
4101
|
+
port2.close();
|
|
4102
|
+
}
|
|
4103
|
+
}
|
|
4104
|
+
async function portable(handle, top = privateTop) {
|
|
4105
|
+
if (clonable(handle)) return { handle };
|
|
4106
|
+
const path = await (await top()).resolve(handle);
|
|
4107
|
+
if (path === null) {
|
|
4108
|
+
throw new Error(
|
|
4109
|
+
"this browser cannot hand a folder to a worker unless it is in the origin private file system"
|
|
4110
|
+
);
|
|
4111
|
+
}
|
|
4112
|
+
return { path };
|
|
4113
|
+
}
|
|
4114
|
+
async function directoryAt(top, path) {
|
|
4115
|
+
let dir = top;
|
|
4116
|
+
for (const name2 of path) dir = await dir.getDirectoryHandle(name2);
|
|
4117
|
+
return dir;
|
|
4118
|
+
}
|
|
4119
|
+
var samePath = (a, b) => a.length === b.length && a.every((name2, at) => name2 === b[at]);
|
|
4120
|
+
|
|
3908
4121
|
// src/fs/roots.ts
|
|
3909
4122
|
var ROOTS_DB = "slicc-kernel-roots";
|
|
3910
4123
|
var ROOTS_STORE = "roots";
|
|
@@ -3926,6 +4139,10 @@ async function same(a, b) {
|
|
|
3926
4139
|
return false;
|
|
3927
4140
|
}
|
|
3928
4141
|
}
|
|
4142
|
+
async function matches(record2, root, at) {
|
|
4143
|
+
if (record2.handle) return same(record2.handle, root);
|
|
4144
|
+
return "path" in at && record2.path !== void 0 && samePath(record2.path, at.path);
|
|
4145
|
+
}
|
|
3929
4146
|
var nameOf = (id2) => `${META_DB}:${id2}`;
|
|
3930
4147
|
function done(tx) {
|
|
3931
4148
|
return new Promise((resolve2, reject) => {
|
|
@@ -3959,18 +4176,19 @@ async function seed(factory, name2) {
|
|
|
3959
4176
|
to.close();
|
|
3960
4177
|
}
|
|
3961
4178
|
}
|
|
3962
|
-
async function rootId(factory, root, locks = globalThis.navigator?.locks) {
|
|
4179
|
+
async function rootId(factory, root, locks = globalThis.navigator?.locks, top) {
|
|
3963
4180
|
const find = async () => {
|
|
4181
|
+
const at = await portable(root, top);
|
|
3964
4182
|
const db = await open(factory);
|
|
3965
4183
|
try {
|
|
3966
4184
|
const all = await request(
|
|
3967
4185
|
db.transaction(ROOTS_STORE, "readonly").objectStore(ROOTS_STORE).getAll()
|
|
3968
4186
|
);
|
|
3969
|
-
for (const record2 of all) if (await
|
|
4187
|
+
for (const record2 of all) if (await matches(record2, root, at)) return record2.id;
|
|
3970
4188
|
const id2 = crypto.randomUUID();
|
|
3971
4189
|
if (await used(root)) await seed(factory, nameOf(id2));
|
|
3972
4190
|
const tx = db.transaction(ROOTS_STORE, "readwrite");
|
|
3973
|
-
tx.objectStore(ROOTS_STORE).put({ id: id2,
|
|
4191
|
+
tx.objectStore(ROOTS_STORE).put({ id: id2, ...at });
|
|
3974
4192
|
await done(tx);
|
|
3975
4193
|
return id2;
|
|
3976
4194
|
} finally {
|
|
@@ -4986,7 +5204,7 @@ function portFacadeHook(ask, gone) {
|
|
|
4986
5204
|
|
|
4987
5205
|
// src/fs/walk.ts
|
|
4988
5206
|
var MAX_LINKS3 = 40;
|
|
4989
|
-
function
|
|
5207
|
+
function parentOf5(path) {
|
|
4990
5208
|
return path.slice(0, path.lastIndexOf("/")) || "/";
|
|
4991
5209
|
}
|
|
4992
5210
|
async function mustBeDir(fs, path) {
|
|
@@ -5004,7 +5222,7 @@ async function realDir(fs, dir, budget = { hops: 0 }) {
|
|
|
5004
5222
|
const part = queue.shift();
|
|
5005
5223
|
if (part === ".") continue;
|
|
5006
5224
|
if (part === "..") {
|
|
5007
|
-
at =
|
|
5225
|
+
at = parentOf5(at);
|
|
5008
5226
|
continue;
|
|
5009
5227
|
}
|
|
5010
5228
|
const next3 = at === "/" ? `/${part}` : `${at}/${part}`;
|
|
@@ -5026,7 +5244,7 @@ function joinName(dir, name2) {
|
|
|
5026
5244
|
}
|
|
5027
5245
|
async function realTarget(fs, path) {
|
|
5028
5246
|
const budget = { hops: 0 };
|
|
5029
|
-
let dir = await realDir(fs,
|
|
5247
|
+
let dir = await realDir(fs, parentOf5(path), budget);
|
|
5030
5248
|
let name2 = path.slice(path.lastIndexOf("/") + 1);
|
|
5031
5249
|
for (; ; ) {
|
|
5032
5250
|
const link2 = await linkOf(fs, joinName(dir, name2));
|
|
@@ -5034,7 +5252,7 @@ async function realTarget(fs, path) {
|
|
|
5034
5252
|
if (budget.hops >= MAX_LINKS3) throw fsError("ELOOP", path);
|
|
5035
5253
|
budget.hops++;
|
|
5036
5254
|
const target = link2.startsWith("/") ? link2 : joinName(dir, link2);
|
|
5037
|
-
dir = await realDir(fs,
|
|
5255
|
+
dir = await realDir(fs, parentOf5(target), budget);
|
|
5038
5256
|
name2 = target.slice(target.lastIndexOf("/") + 1);
|
|
5039
5257
|
}
|
|
5040
5258
|
return joinName(dir, name2);
|
|
@@ -5111,7 +5329,7 @@ async function walk(fs, cred, path, follow2, links) {
|
|
|
5111
5329
|
if (!dir) return { path: joinName(at, [part, ...queue].join("/")), perm: void 0 };
|
|
5112
5330
|
if (!permits(cred, dir, X_OK)) return { path, perm: void 0, denied: at };
|
|
5113
5331
|
if (part === "..") {
|
|
5114
|
-
at =
|
|
5332
|
+
at = parentOf5(at);
|
|
5115
5333
|
continue;
|
|
5116
5334
|
}
|
|
5117
5335
|
const next3 = joinName(at, part);
|
|
@@ -5232,7 +5450,7 @@ function deny(g, op, path, errno3 = "EACCES") {
|
|
|
5232
5450
|
}
|
|
5233
5451
|
var FENCE_HOPS = 40;
|
|
5234
5452
|
async function entryAt(g, path) {
|
|
5235
|
-
const parent =
|
|
5453
|
+
const parent = parentOf5(path);
|
|
5236
5454
|
const real = await g.fs.realpath?.(parent, true).catch(() => void 0);
|
|
5237
5455
|
return real ? joinName(real, path.slice(path.lastIndexOf("/") + 1)) : path;
|
|
5238
5456
|
}
|
|
@@ -5243,7 +5461,7 @@ async function fencedNames(g, path) {
|
|
|
5243
5461
|
names2.push(at);
|
|
5244
5462
|
const link2 = await g.fs.readlink(at).catch(() => void 0);
|
|
5245
5463
|
if (link2 === void 0) break;
|
|
5246
|
-
at = await entryAt(g, normalizePath(g.fs.resolvePath(
|
|
5464
|
+
at = await entryAt(g, normalizePath(g.fs.resolvePath(parentOf5(at), link2)));
|
|
5247
5465
|
}
|
|
5248
5466
|
return names2;
|
|
5249
5467
|
}
|
|
@@ -5294,7 +5512,7 @@ async function unwritable(g, op, path, dir) {
|
|
|
5294
5512
|
}
|
|
5295
5513
|
async function inParent(g, op, path, old = false) {
|
|
5296
5514
|
await fence(g, op, path);
|
|
5297
|
-
const dir = await access(g.fs, g.cred,
|
|
5515
|
+
const dir = await access(g.fs, g.cred, parentOf5(path), W_OK | X_OK, linked(g, DIR));
|
|
5298
5516
|
if (old !== true) {
|
|
5299
5517
|
if (await unwritable(g, op, path, dir)) deny(g, op, path);
|
|
5300
5518
|
else if (old === "replaced" && dir.denied === void 0) await stickyEntry(g, op, path, dir);
|
|
@@ -5306,7 +5524,7 @@ async function inParent(g, op, path, old = false) {
|
|
|
5306
5524
|
if (!lookup2 || await present(g.fs, entryIn(dir, path), false)) deny(g, op, path);
|
|
5307
5525
|
}
|
|
5308
5526
|
async function makeIn(g, op, path, parents = true) {
|
|
5309
|
-
for (let dir =
|
|
5527
|
+
for (let dir = parentOf5(path); ; dir = parentOf5(dir)) {
|
|
5310
5528
|
const walked = await access(g.fs, g.cred, dir, W_OK | X_OK, linked(g, DIR));
|
|
5311
5529
|
if (await unwritable(g, op, path, walked)) {
|
|
5312
5530
|
if (!await present(g.fs, path, true)) deny(g, op, path);
|
|
@@ -5334,7 +5552,7 @@ async function renamable(g, from, to) {
|
|
|
5334
5552
|
if (from === to) return void await need(g, "rename", from, 0, { follow: false });
|
|
5335
5553
|
await inParent(g, "rename", from, true);
|
|
5336
5554
|
await inParent(g, "rename", to, "replaced");
|
|
5337
|
-
if (g.cred.euid === 0 ||
|
|
5555
|
+
if (g.cred.euid === 0 || parentOf5(from) === parentOf5(to)) return;
|
|
5338
5556
|
const st = await g.fs.lstat(from).catch(() => void 0);
|
|
5339
5557
|
if (st?.isDirectory && !permits(g.cred, permOf(st), W_OK)) deny(g, "rename", from);
|
|
5340
5558
|
}
|
|
@@ -5401,7 +5619,7 @@ async function writable(g, op, path) {
|
|
|
5401
5619
|
}
|
|
5402
5620
|
async function creatable(g, op, path) {
|
|
5403
5621
|
const target = await need(g, op, path, 0);
|
|
5404
|
-
if (target.denied === void 0) await need(g, op,
|
|
5622
|
+
if (target.denied === void 0) await need(g, op, parentOf5(target.path), W_OK | X_OK, DIR, path);
|
|
5405
5623
|
}
|
|
5406
5624
|
async function openable(g, op, path, want, create) {
|
|
5407
5625
|
const st = create ? await g.fs.stat(path).catch(() => void 0) : void 0;
|
|
@@ -6157,7 +6375,7 @@ function parsePrefix(text) {
|
|
|
6157
6375
|
if (length2 < 0 || length2 > max) return void 0;
|
|
6158
6376
|
return { ...parsed2, length: length2 };
|
|
6159
6377
|
}
|
|
6160
|
-
function
|
|
6378
|
+
function within4(prefix, addr) {
|
|
6161
6379
|
if (prefix.v6 !== addr.v6) return false;
|
|
6162
6380
|
const shift = BigInt((prefix.v6 ? 128 : 32) - prefix.length);
|
|
6163
6381
|
return addr.bits >> shift === prefix.bits >> shift;
|
|
@@ -6197,9 +6415,9 @@ var Routes = class {
|
|
|
6197
6415
|
if (!addr) return "unreachable";
|
|
6198
6416
|
if (addr.v6 && addr.bits === 1n) return "loopback";
|
|
6199
6417
|
if (!addr.v6 && addr.bits >> 24n === 127n) return "loopback";
|
|
6200
|
-
if (RESERVED.some((p) =>
|
|
6418
|
+
if (RESERVED.some((p) => within4(p, addr))) return "reserved";
|
|
6201
6419
|
if (addr.v6 && !this.ipv6) return "unreachable";
|
|
6202
|
-
if (this.exit || this.table.some((p) =>
|
|
6420
|
+
if (this.exit || this.table.some((p) => within4(p, addr))) return "uplink";
|
|
6203
6421
|
return "unreachable";
|
|
6204
6422
|
}
|
|
6205
6423
|
};
|
|
@@ -8151,7 +8369,7 @@ function hostRegistries(send2, gone, port) {
|
|
|
8151
8369
|
function visibleTo(g, notify) {
|
|
8152
8370
|
if (!g?.dac.enforcing) return notify;
|
|
8153
8371
|
let queue = Promise.resolve();
|
|
8154
|
-
const seen = async (path) => (await access(g.fs, g.cred,
|
|
8372
|
+
const seen = async (path) => (await access(g.fs, g.cred, parentOf5(path), R_OK | X_OK, { directory: true })).denied === void 0;
|
|
8155
8373
|
return (change) => {
|
|
8156
8374
|
queue = queue.then(async () => {
|
|
8157
8375
|
if (!("paths" in change)) return notify(change);
|
|
@@ -8169,7 +8387,7 @@ async function watchOp(l, req, watches, send2, g) {
|
|
|
8169
8387
|
}
|
|
8170
8388
|
if (g) for (const path of req.paths) await readable(g, "watch", l.fs.resolvePath("/", path));
|
|
8171
8389
|
const notify = visibleTo(g, (change) => send2({ watch: req.id, change }));
|
|
8172
|
-
const unwatch = l.watchers.watch(req.paths, { recursive: req.recursive }, notify);
|
|
8390
|
+
const unwatch = l.watchers.watch(req.paths, { recursive: req.recursive, peers: true }, notify);
|
|
8173
8391
|
watches.set(req.id, unwatch);
|
|
8174
8392
|
return { result: req.id };
|
|
8175
8393
|
}
|
|
@@ -8522,7 +8740,7 @@ function satisfies(version, range2) {
|
|
|
8522
8740
|
}
|
|
8523
8741
|
|
|
8524
8742
|
// src/version.ts
|
|
8525
|
-
var KERNEL_VERSION = true ? "1.
|
|
8743
|
+
var KERNEL_VERSION = true ? "1.173.0" : "0.0.0-dev";
|
|
8526
8744
|
var OS_RELEASE = "6.0.0-slicc";
|
|
8527
8745
|
function procVersion() {
|
|
8528
8746
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -9433,7 +9651,7 @@ var PathMarks = class {
|
|
|
9433
9651
|
}
|
|
9434
9652
|
changedSince(path, gen) {
|
|
9435
9653
|
if (gen < this.floor) return true;
|
|
9436
|
-
for (let p = path; this.touched.size > 0; p =
|
|
9654
|
+
for (let p = path; this.touched.size > 0; p = parentOf6(p)) {
|
|
9437
9655
|
if ((this.touched.get(p) ?? 0) > gen) return true;
|
|
9438
9656
|
if (p === "/") return false;
|
|
9439
9657
|
}
|
|
@@ -9468,7 +9686,7 @@ var PathMarks = class {
|
|
|
9468
9686
|
});
|
|
9469
9687
|
}
|
|
9470
9688
|
inFlight(path) {
|
|
9471
|
-
for (let p = path; this.flying.size > 0; p =
|
|
9689
|
+
for (let p = path; this.flying.size > 0; p = parentOf6(p)) {
|
|
9472
9690
|
if (this.flying.has(p)) return true;
|
|
9473
9691
|
if (p === "/") return false;
|
|
9474
9692
|
}
|
|
@@ -9488,9 +9706,9 @@ var LOOKUP_OPS = [
|
|
|
9488
9706
|
"readlink",
|
|
9489
9707
|
"realpath"
|
|
9490
9708
|
];
|
|
9491
|
-
var
|
|
9709
|
+
var within5 = (path, target) => path === target || target === "/" || path.startsWith(`${target}/`);
|
|
9492
9710
|
var TOUCHED_MAX = 4096;
|
|
9493
|
-
var
|
|
9711
|
+
var parentOf6 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
9494
9712
|
var PEER_RM_MS = 1e3;
|
|
9495
9713
|
var SHARED_ACK_MS = 24 * 60 * 60 * 1e3;
|
|
9496
9714
|
var delay = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
@@ -9570,14 +9788,14 @@ var UnlinkedKeeper = class {
|
|
|
9570
9788
|
linked = /* @__PURE__ */ new Map();
|
|
9571
9789
|
dirOwner;
|
|
9572
9790
|
peers;
|
|
9573
|
-
constructor(fs, holders,
|
|
9791
|
+
constructor(fs, holders, rootOf2, options = {}) {
|
|
9574
9792
|
this.peers = options.peers;
|
|
9575
9793
|
this.marks = options.marks ?? new PathMarks();
|
|
9576
9794
|
const { locks, owner } = options;
|
|
9577
9795
|
this.dirOwner = options.dirOwner;
|
|
9578
9796
|
this.fs = fs;
|
|
9579
9797
|
this.holders = holders;
|
|
9580
|
-
this.rootOf =
|
|
9798
|
+
this.rootOf = rootOf2;
|
|
9581
9799
|
this.locks = locks;
|
|
9582
9800
|
this.busy = options.busy ?? (() => false);
|
|
9583
9801
|
this.owner = owner;
|
|
@@ -9678,7 +9896,7 @@ var UnlinkedKeeper = class {
|
|
|
9678
9896
|
};
|
|
9679
9897
|
}
|
|
9680
9898
|
async settled(path) {
|
|
9681
|
-
for (let p = path; this.replacing.size > 0; p =
|
|
9899
|
+
for (let p = path; this.replacing.size > 0; p = parentOf6(p)) {
|
|
9682
9900
|
await this.replacing.get(p)?.done;
|
|
9683
9901
|
if (p === "/") return;
|
|
9684
9902
|
}
|
|
@@ -9696,7 +9914,7 @@ var UnlinkedKeeper = class {
|
|
|
9696
9914
|
return this.marks.inFlight(path);
|
|
9697
9915
|
}
|
|
9698
9916
|
missed(path) {
|
|
9699
|
-
for (let p = path; this.replacing.size > 0; p =
|
|
9917
|
+
for (let p = path; this.replacing.size > 0; p = parentOf6(p)) {
|
|
9700
9918
|
if (this.replacing.get(p)?.sealed) return true;
|
|
9701
9919
|
if (p === "/") return false;
|
|
9702
9920
|
}
|
|
@@ -9716,7 +9934,7 @@ var UnlinkedKeeper = class {
|
|
|
9716
9934
|
for (const holder of this.holders) {
|
|
9717
9935
|
if (holder.owns(target)) continue;
|
|
9718
9936
|
for (const path of holder.held()) {
|
|
9719
|
-
if (!
|
|
9937
|
+
if (!within5(path, target) || holder.isKept(path)) continue;
|
|
9720
9938
|
held.set(path, [...held.get(path) ?? [], holder]);
|
|
9721
9939
|
}
|
|
9722
9940
|
}
|
|
@@ -9796,7 +10014,7 @@ var UnlinkedKeeper = class {
|
|
|
9796
10014
|
await this.serial(async () => {
|
|
9797
10015
|
await Promise.allSettled([this.fs.rename(file.hidden, path)]);
|
|
9798
10016
|
this.unlinkedName(file.hidden);
|
|
9799
|
-
await this.tidy(
|
|
10017
|
+
await this.tidy(parentOf6(file.hidden));
|
|
9800
10018
|
});
|
|
9801
10019
|
}
|
|
9802
10020
|
done5();
|
|
@@ -10035,7 +10253,7 @@ var UnlinkedKeeper = class {
|
|
|
10035
10253
|
}
|
|
10036
10254
|
await this.fs.rm(hidden).catch(() => void 0);
|
|
10037
10255
|
this.unlinkedName(hidden);
|
|
10038
|
-
await this.tidy(
|
|
10256
|
+
await this.tidy(parentOf6(hidden));
|
|
10039
10257
|
}
|
|
10040
10258
|
async linkedName(hidden) {
|
|
10041
10259
|
if (!mayLink(this.fs, hidden)) return;
|
|
@@ -11584,7 +11802,7 @@ function devCreation(path, cred) {
|
|
|
11584
11802
|
var HOSTNAME_PATH = "/etc/hostname";
|
|
11585
11803
|
var S_IFREG3 = 32768;
|
|
11586
11804
|
var MAX_HOPS2 = 40;
|
|
11587
|
-
var
|
|
11805
|
+
var parentOf7 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
11588
11806
|
var baseOf2 = (path) => path.slice(path.lastIndexOf("/") + 1);
|
|
11589
11807
|
function missing5(err) {
|
|
11590
11808
|
return err?.code === "ENOENT";
|
|
@@ -11614,7 +11832,7 @@ function linkFollower(fs, files) {
|
|
|
11614
11832
|
);
|
|
11615
11833
|
const viaParent = async (path) => {
|
|
11616
11834
|
if (!bases.has(baseOf2(path)) || !fs.realpath) return path;
|
|
11617
|
-
const parent =
|
|
11835
|
+
const parent = parentOf7(path);
|
|
11618
11836
|
const dir = await fs.realpath(parent, true).catch(() => parent);
|
|
11619
11837
|
return fs.resolvePath(dir, baseOf2(path));
|
|
11620
11838
|
};
|
|
@@ -11623,7 +11841,7 @@ function linkFollower(fs, files) {
|
|
|
11623
11841
|
for (let hop = 0; hop < MAX_HOPS2 && !files.has(current); hop++) {
|
|
11624
11842
|
const link2 = await linkOf2(current);
|
|
11625
11843
|
if (link2 === void 0) return viaParent(current);
|
|
11626
|
-
current = fs.resolvePath(
|
|
11844
|
+
current = fs.resolvePath(parentOf7(current), link2);
|
|
11627
11845
|
}
|
|
11628
11846
|
return current;
|
|
11629
11847
|
};
|
|
@@ -11704,7 +11922,7 @@ var DEFAULT_UMASK = 18;
|
|
|
11704
11922
|
function isModule(bytes) {
|
|
11705
11923
|
return MAGIC.every((b, i) => bytes[i] === b);
|
|
11706
11924
|
}
|
|
11707
|
-
function
|
|
11925
|
+
function within6(path, dir) {
|
|
11708
11926
|
return path.startsWith(dir === "/" ? "/" : `${dir}/`);
|
|
11709
11927
|
}
|
|
11710
11928
|
var FreshModules = class {
|
|
@@ -11728,10 +11946,10 @@ var FreshModules = class {
|
|
|
11728
11946
|
const target = normalizePath(to);
|
|
11729
11947
|
if (source === target) return;
|
|
11730
11948
|
for (const key of [...this.fresh.keys()]) {
|
|
11731
|
-
if (key === target ||
|
|
11949
|
+
if (key === target || within6(key, target)) this.fresh.delete(key);
|
|
11732
11950
|
}
|
|
11733
11951
|
for (const [key, fresh3] of [...this.fresh]) {
|
|
11734
|
-
if (key !== source && !
|
|
11952
|
+
if (key !== source && !within6(key, source)) continue;
|
|
11735
11953
|
this.fresh.delete(key);
|
|
11736
11954
|
this.fresh.set(target + key.slice(source.length), fresh3);
|
|
11737
11955
|
}
|
|
@@ -11773,7 +11991,7 @@ var FreshModules = class {
|
|
|
11773
11991
|
await fs.rm(path, options);
|
|
11774
11992
|
const at = normalizePath(path);
|
|
11775
11993
|
for (const key of [...this.fresh.keys()]) {
|
|
11776
|
-
if (key === at ||
|
|
11994
|
+
if (key === at || within6(key, at)) this.fresh.delete(key);
|
|
11777
11995
|
}
|
|
11778
11996
|
},
|
|
11779
11997
|
rename: async (from, to) => {
|
|
@@ -11878,10 +12096,10 @@ var WATCH_NOTES_LIMIT = 1e3;
|
|
|
11878
12096
|
var baseOf3 = (path) => path.slice(path.lastIndexOf("/") + 1);
|
|
11879
12097
|
var WATCH_BATCH_LIMIT = 1e3;
|
|
11880
12098
|
var under3 = (path, dir) => dir === "/" || path.startsWith(`${dir}/`);
|
|
11881
|
-
var
|
|
12099
|
+
var parentOf8 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
11882
12100
|
function touches2(watcher, changed) {
|
|
11883
12101
|
return watcher.paths.some(
|
|
11884
|
-
(watched) => changed === watched || under3(watched, changed) || (watcher.recursive ? under3(changed, watched) :
|
|
12102
|
+
(watched) => changed === watched || under3(watched, changed) || (watcher.recursive ? under3(changed, watched) : parentOf8(changed) === watched)
|
|
11885
12103
|
);
|
|
11886
12104
|
}
|
|
11887
12105
|
var REALS_KEPT = 4096;
|
|
@@ -11909,7 +12127,7 @@ function routed(watch, root, type, path, seq2) {
|
|
|
11909
12127
|
if (type === "rename") noted(watch, { ended: true, seq: seq2 });
|
|
11910
12128
|
return true;
|
|
11911
12129
|
}
|
|
11912
|
-
if (
|
|
12130
|
+
if (parentOf8(path) === root) noted(watch, { type, filename: baseOf3(path), seq: seq2 });
|
|
11913
12131
|
else if (watch.recursive && under3(path, root)) {
|
|
11914
12132
|
noted(watch, { type, filename: path.slice(root === "/" ? 1 : root.length + 1), seq: seq2 });
|
|
11915
12133
|
} else return false;
|
|
@@ -11941,6 +12159,7 @@ var FsWatchers = class {
|
|
|
11941
12159
|
const watcher = {
|
|
11942
12160
|
paths: paths.map(normalizePath),
|
|
11943
12161
|
recursive: options.recursive === true,
|
|
12162
|
+
peers: options.peers === true,
|
|
11944
12163
|
notify,
|
|
11945
12164
|
pending: /* @__PURE__ */ new Set(),
|
|
11946
12165
|
scheduled: false
|
|
@@ -11994,7 +12213,7 @@ var FsWatchers = class {
|
|
|
11994
12213
|
covers(path) {
|
|
11995
12214
|
for (const watch of this.typed) {
|
|
11996
12215
|
for (const root of watch.roots) {
|
|
11997
|
-
if (path === root ||
|
|
12216
|
+
if (path === root || parentOf8(path) === root || watch.recursive && under3(path, root))
|
|
11998
12217
|
return true;
|
|
11999
12218
|
}
|
|
12000
12219
|
}
|
|
@@ -12062,10 +12281,16 @@ var FsWatchers = class {
|
|
|
12062
12281
|
this.report(paths);
|
|
12063
12282
|
this.emit("change", paths);
|
|
12064
12283
|
}
|
|
12284
|
+
peerChanged(paths) {
|
|
12285
|
+
if (paths.length > 0) this.notify(paths, true);
|
|
12286
|
+
}
|
|
12065
12287
|
report(paths, notify = true) {
|
|
12066
12288
|
for (const tap of this.taps) tap(paths);
|
|
12067
|
-
if (
|
|
12289
|
+
if (notify) this.notify(paths);
|
|
12290
|
+
}
|
|
12291
|
+
notify(paths, peer = false) {
|
|
12068
12292
|
for (const watcher of this.watchers) {
|
|
12293
|
+
if (peer && !watcher.peers) continue;
|
|
12069
12294
|
for (const path of paths) {
|
|
12070
12295
|
const changed = normalizePath(path);
|
|
12071
12296
|
if (touches2(watcher, changed)) watcher.pending.add(changed);
|
|
@@ -13534,7 +13759,7 @@ function linkedTo(mount, path) {
|
|
|
13534
13759
|
return own?.kind !== "directory" && (attr2.nlink ?? 1) > 1;
|
|
13535
13760
|
};
|
|
13536
13761
|
}
|
|
13537
|
-
var
|
|
13762
|
+
var within7 = (path, target) => path === target || target === "/" || path.startsWith(`${target}/`);
|
|
13538
13763
|
var HeldSet = class extends Set {
|
|
13539
13764
|
idle;
|
|
13540
13765
|
moved;
|
|
@@ -13570,7 +13795,7 @@ var HeldSet = class extends Set {
|
|
|
13570
13795
|
}
|
|
13571
13796
|
};
|
|
13572
13797
|
function heldUnder(held, target) {
|
|
13573
|
-
for (const paths of held) for (const path of paths.keys()) if (
|
|
13798
|
+
for (const paths of held) for (const path of paths.keys()) if (within7(path, target)) return true;
|
|
13574
13799
|
return false;
|
|
13575
13800
|
}
|
|
13576
13801
|
var HeldPaths = class extends Map {
|
|
@@ -13611,7 +13836,7 @@ var HeldPaths = class extends Map {
|
|
|
13611
13836
|
if (this.bound.size === 0) return;
|
|
13612
13837
|
for (const [handle, key] of this.handles) {
|
|
13613
13838
|
if (!this.bound.has(handle) || this.keptHandles.has(handle)) continue;
|
|
13614
|
-
if (exact ? key === over :
|
|
13839
|
+
if (exact ? key === over : within7(key, over)) this.doubted.set(handle, ++this.doubts);
|
|
13615
13840
|
}
|
|
13616
13841
|
}
|
|
13617
13842
|
boundIno(handle) {
|
|
@@ -13747,24 +13972,24 @@ var HeldPaths = class extends Map {
|
|
|
13747
13972
|
return this.owning === path;
|
|
13748
13973
|
}
|
|
13749
13974
|
revoke(prefix) {
|
|
13750
|
-
for (const path of this.keys()) if (
|
|
13975
|
+
for (const path of this.keys()) if (within7(path, prefix)) this.revoked.add(path);
|
|
13751
13976
|
}
|
|
13752
13977
|
renamed(from, to) {
|
|
13753
13978
|
for (const [path, count2] of [...this]) {
|
|
13754
|
-
if (!
|
|
13979
|
+
if (!within7(path, from)) continue;
|
|
13755
13980
|
const moved2 = to + path.slice(from.length);
|
|
13756
13981
|
this.delete(path);
|
|
13757
13982
|
this.set(moved2, (this.get(moved2) ?? 0) + count2);
|
|
13758
13983
|
if (this.revoked.delete(path)) this.revoked.add(moved2);
|
|
13759
13984
|
}
|
|
13760
13985
|
for (const [path, count2] of [...this.opens]) {
|
|
13761
|
-
if (!
|
|
13986
|
+
if (!within7(path, from)) continue;
|
|
13762
13987
|
const moved2 = to + path.slice(from.length);
|
|
13763
13988
|
this.opens.delete(path);
|
|
13764
13989
|
this.opens.set(moved2, (this.opens.get(moved2) ?? 0) + count2);
|
|
13765
13990
|
}
|
|
13766
13991
|
for (const [id2, key] of this.handles) {
|
|
13767
|
-
if (
|
|
13992
|
+
if (within7(key, from)) this.handles.set(id2, to + key.slice(from.length));
|
|
13768
13993
|
}
|
|
13769
13994
|
this.onMoved?.(from, to);
|
|
13770
13995
|
}
|
|
@@ -13772,7 +13997,7 @@ var HeldPaths = class extends Map {
|
|
|
13772
13997
|
return this.revoked.has(path);
|
|
13773
13998
|
}
|
|
13774
13999
|
};
|
|
13775
|
-
var
|
|
14000
|
+
var parentOf9 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
13776
14001
|
var readonly = (mount) => mount.caps.readonly === true || mount.options.ro !== void 0;
|
|
13777
14002
|
function inodeless(mount, attr2) {
|
|
13778
14003
|
if (attr2.ino !== void 0) return false;
|
|
@@ -13879,13 +14104,13 @@ var MountTable = class {
|
|
|
13879
14104
|
});
|
|
13880
14105
|
}
|
|
13881
14106
|
under(path) {
|
|
13882
|
-
for (const mount of this.mounts.values()) if (
|
|
14107
|
+
for (const mount of this.mounts.values()) if (within7(mount.target, path)) return true;
|
|
13883
14108
|
return false;
|
|
13884
14109
|
}
|
|
13885
14110
|
locate(path) {
|
|
13886
14111
|
let best;
|
|
13887
14112
|
for (const mount of this.mounts.values()) {
|
|
13888
|
-
if (
|
|
14113
|
+
if (within7(path, mount.target) && (!best || mount.target.length > best.target.length))
|
|
13889
14114
|
best = mount;
|
|
13890
14115
|
}
|
|
13891
14116
|
if (!best) return void 0;
|
|
@@ -14032,7 +14257,7 @@ var MountTable = class {
|
|
|
14032
14257
|
async commitUnder(prefix) {
|
|
14033
14258
|
const at = normalizePath(prefix);
|
|
14034
14259
|
await Promise.all(
|
|
14035
|
-
[...this.sessions.keys()].filter((p) =>
|
|
14260
|
+
[...this.sessions.keys()].filter((p) => within7(p, at)).map((p) => this.commit(p))
|
|
14036
14261
|
);
|
|
14037
14262
|
}
|
|
14038
14263
|
async commitOverlapping(real, offset, length2) {
|
|
@@ -14070,11 +14295,11 @@ var MountTable = class {
|
|
|
14070
14295
|
mount.epoch++;
|
|
14071
14296
|
const linked2 = mount.caps.links ? linkedTo(mount, path) : () => false;
|
|
14072
14297
|
for (const [key, cached] of [...mount.attrs])
|
|
14073
|
-
if (
|
|
14298
|
+
if (within7(key, path) || linked2(cached.value)) mount.attrs.delete(key);
|
|
14074
14299
|
mount.lists.delete(path);
|
|
14075
|
-
mount.lists.delete(
|
|
14300
|
+
mount.lists.delete(parentOf9(path));
|
|
14076
14301
|
for (const [key, cached] of [...mount.lists])
|
|
14077
|
-
if (
|
|
14302
|
+
if (within7(key, path) || cached.value.some((e) => linked2(e.attr))) mount.lists.delete(key);
|
|
14078
14303
|
}
|
|
14079
14304
|
async getattr(mount, path, rel2, settled = false) {
|
|
14080
14305
|
for (let round = 1; ; round++) {
|
|
@@ -14193,7 +14418,7 @@ var MountFs = class _MountFs {
|
|
|
14193
14418
|
const real = normalizePath(path);
|
|
14194
14419
|
if (this.at(real)) return real;
|
|
14195
14420
|
try {
|
|
14196
|
-
await this.base.stat(
|
|
14421
|
+
await this.base.stat(parentOf9(real));
|
|
14197
14422
|
return real;
|
|
14198
14423
|
} catch (err) {
|
|
14199
14424
|
const moved2 = redirectOf(err);
|
|
@@ -14215,7 +14440,7 @@ var MountFs = class _MountFs {
|
|
|
14215
14440
|
if (redirects >= MAX_LINKS7) throw errnoError("ELOOP", paths[0]);
|
|
14216
14441
|
const at = paths.map((path) => {
|
|
14217
14442
|
const real = normalizePath(path);
|
|
14218
|
-
return
|
|
14443
|
+
return within7(real, moved2.of) ? normalizePath(moved2.to + real.slice(moved2.of.length)) : real;
|
|
14219
14444
|
});
|
|
14220
14445
|
return again(at, redirects + 1);
|
|
14221
14446
|
}
|
|
@@ -14235,7 +14460,7 @@ var MountFs = class _MountFs {
|
|
|
14235
14460
|
if (this.rejectLinks) throw errnoError("ELOOP", path);
|
|
14236
14461
|
if (hops >= MAX_LINKS7) throw errnoError("ELOOP", path);
|
|
14237
14462
|
const target = await found.mount.conn.call({ op: "readlink", path: found.rel });
|
|
14238
|
-
return this.follow(this.base.resolvePath(
|
|
14463
|
+
return this.follow(this.base.resolvePath(parentOf9(real), target), hops + 1, create);
|
|
14239
14464
|
}
|
|
14240
14465
|
async open(mount, rel2, write, owner, create = write) {
|
|
14241
14466
|
return await mount.conn.call({
|
|
@@ -14251,8 +14476,8 @@ var MountFs = class _MountFs {
|
|
|
14251
14476
|
async driverOwner(found, real, owner, directory) {
|
|
14252
14477
|
const { mount, rel: rel2 } = found;
|
|
14253
14478
|
if (!owner || !mount.owners || !mount.caps.owners) return void 0;
|
|
14254
|
-
const dir =
|
|
14255
|
-
const above = statOf2(await this.table.getattr(mount, dir,
|
|
14479
|
+
const dir = parentOf9(real);
|
|
14480
|
+
const above = statOf2(await this.table.getattr(mount, dir, parentOf9(rel2)), dir, mount);
|
|
14256
14481
|
const setgid = (above.mode & S_ISGID4) !== 0;
|
|
14257
14482
|
let mode = owner.mode;
|
|
14258
14483
|
if (directory && setgid) mode = (mode ?? 493) | S_ISGID4;
|
|
@@ -14771,7 +14996,7 @@ var MountFs = class _MountFs {
|
|
|
14771
14996
|
}
|
|
14772
14997
|
async named(path) {
|
|
14773
14998
|
const at = normalizePath(path);
|
|
14774
|
-
return joinName(await realDir(this,
|
|
14999
|
+
return joinName(await realDir(this, parentOf9(at)), at.slice(at.lastIndexOf("/") + 1));
|
|
14775
15000
|
}
|
|
14776
15001
|
async link(source, target, follow2 = false) {
|
|
14777
15002
|
const from = follow2 ? await realTarget(this, normalizePath(source)) : await this.named(source);
|
|
@@ -15266,7 +15491,7 @@ async function timesOf(entry, path, req) {
|
|
|
15266
15491
|
const st = await look.call(entry.fs, path).catch(() => void 0);
|
|
15267
15492
|
if (!st || (st.uid ?? 0) === g.cred.euid) return given;
|
|
15268
15493
|
const now = /* @__PURE__ */ new Date();
|
|
15269
|
-
const kept = (ms,
|
|
15494
|
+
const kept = (ms, stored2) => ms === stored2.getTime() ? stored2 : now;
|
|
15270
15495
|
return [kept(req.atimeMs, st.atime), kept(req.mtimeMs, st.mtime)];
|
|
15271
15496
|
}
|
|
15272
15497
|
function guardOf(entry) {
|
|
@@ -16445,6 +16670,8 @@ var SYS_TREE = {
|
|
|
16445
16670
|
slicc_opfs_calls: (listing) => `${listing.opfsCalls ?? 0}
|
|
16446
16671
|
`,
|
|
16447
16672
|
slicc_opfs_ops: (listing) => `${listing.opfsOps ?? 0}
|
|
16673
|
+
`,
|
|
16674
|
+
slicc_meta_transactions: ({ meta }) => `${meta?.reads ?? 0} ${meta?.writes ?? 0}
|
|
16448
16675
|
`,
|
|
16449
16676
|
slicc_cwd_checks: (listing) => `${listing.cwdChecks ?? 0}
|
|
16450
16677
|
`,
|
|
@@ -18286,19 +18513,19 @@ function indexedDbCaStore(dbName = "slicc-realm-ca") {
|
|
|
18286
18513
|
async swap(owner, expected, record2) {
|
|
18287
18514
|
const tx = (await open2()).transaction("ca", "readwrite");
|
|
18288
18515
|
const store = tx.objectStore("ca");
|
|
18289
|
-
let
|
|
18516
|
+
let stored2 = record2;
|
|
18290
18517
|
const read = store.get(owner);
|
|
18291
18518
|
read.onsuccess = () => {
|
|
18292
18519
|
const current = read.result;
|
|
18293
18520
|
const kept = winner(current, expected, record2);
|
|
18294
18521
|
if (kept === record2) store.put(record2, owner);
|
|
18295
|
-
else
|
|
18522
|
+
else stored2 = kept;
|
|
18296
18523
|
};
|
|
18297
18524
|
await new Promise((resolve2, reject) => {
|
|
18298
18525
|
tx.oncomplete = () => resolve2();
|
|
18299
18526
|
tx.onerror = () => reject(tx.error);
|
|
18300
18527
|
});
|
|
18301
|
-
return
|
|
18528
|
+
return stored2;
|
|
18302
18529
|
}
|
|
18303
18530
|
};
|
|
18304
18531
|
}
|
|
@@ -18315,10 +18542,10 @@ var RealmCa = class _RealmCa {
|
|
|
18315
18542
|
this.record = record2;
|
|
18316
18543
|
}
|
|
18317
18544
|
static async open(owner, store, now = Date.now()) {
|
|
18318
|
-
const
|
|
18319
|
-
if (
|
|
18545
|
+
const stored2 = await store.get(owner).catch(() => void 0);
|
|
18546
|
+
if (stored2 && stored2.notAfter - now > CA_RENEW_BEFORE) return new _RealmCa(stored2);
|
|
18320
18547
|
const record2 = await _RealmCa.create(owner, now);
|
|
18321
|
-
return new _RealmCa(await store.swap(owner,
|
|
18548
|
+
return new _RealmCa(await store.swap(owner, stored2, record2));
|
|
18322
18549
|
}
|
|
18323
18550
|
static async create(owner, now) {
|
|
18324
18551
|
const pair = await crypto.subtle.generateKey(ECDSA, false, ["sign", "verify"]);
|
|
@@ -22645,7 +22872,7 @@ function ranges(text) {
|
|
|
22645
22872
|
return [Number.parseInt(lo, 16), Number.parseInt(hi, 16)];
|
|
22646
22873
|
});
|
|
22647
22874
|
}
|
|
22648
|
-
function
|
|
22875
|
+
function within8(table, code) {
|
|
22649
22876
|
let lo = 0;
|
|
22650
22877
|
let hi = table.length - 1;
|
|
22651
22878
|
while (lo <= hi) {
|
|
@@ -22668,10 +22895,10 @@ var LCAT = ranges(LCAT_TEXT);
|
|
|
22668
22895
|
function prepFails(prepared) {
|
|
22669
22896
|
const codes = Array.from(prepared, (ch) => ch.codePointAt(0) ?? 0);
|
|
22670
22897
|
if (codes.length === 0) return true;
|
|
22671
|
-
if (codes.some((c) =>
|
|
22672
|
-
if (!codes.some((c) =>
|
|
22673
|
-
if (codes.some((c) =>
|
|
22674
|
-
return !
|
|
22898
|
+
if (codes.some((c) => within8(PROHIBITED, c) || within8(UNASSIGNED, c))) return true;
|
|
22899
|
+
if (!codes.some((c) => within8(RANDAL, c))) return false;
|
|
22900
|
+
if (codes.some((c) => within8(LCAT, c))) return true;
|
|
22901
|
+
return !within8(RANDAL, codes[0] ?? 0) || !within8(RANDAL, codes.at(-1) ?? 0);
|
|
22675
22902
|
}
|
|
22676
22903
|
|
|
22677
22904
|
// src/kernel/net/sealed-scram.ts
|
|
@@ -22763,15 +22990,15 @@ async function scramKeys(password, x) {
|
|
|
22763
22990
|
)
|
|
22764
22991
|
);
|
|
22765
22992
|
const clientKey = await hmac(salted, encoder9.encode("Client Key"));
|
|
22766
|
-
const
|
|
22993
|
+
const stored2 = new Uint8Array(
|
|
22767
22994
|
await crypto.subtle.digest("SHA-256", clientKey)
|
|
22768
22995
|
);
|
|
22769
22996
|
const auth = encoder9.encode(`${x.clientFirstBare},${x.serverFirst},${x.clientFinalBare}`);
|
|
22770
|
-
const signature = await hmac(
|
|
22997
|
+
const signature = await hmac(stored2, auth);
|
|
22771
22998
|
const proof = clientKey.map((b, i) => b ^ signature[i]);
|
|
22772
22999
|
const serverKey = await hmac(salted, encoder9.encode("Server Key"));
|
|
22773
23000
|
const serverSignature = await hmac(serverKey, auth);
|
|
22774
|
-
for (const k of [salted, clientKey,
|
|
23001
|
+
for (const k of [salted, clientKey, stored2, signature, serverKey]) k.fill(0);
|
|
22775
23002
|
return { proof, serverSignature };
|
|
22776
23003
|
}
|
|
22777
23004
|
var SPACES = /[\u00A0\u1680\u2000-\u200B\u202F\u205F\u3000]/g;
|
|
@@ -24646,7 +24873,7 @@ function isMissing(err) {
|
|
|
24646
24873
|
if (err?.code === "ENOENT") return true;
|
|
24647
24874
|
return err instanceof Error && err.message.startsWith("ENOENT");
|
|
24648
24875
|
}
|
|
24649
|
-
function
|
|
24876
|
+
function within9(path, root) {
|
|
24650
24877
|
return path === root || path.startsWith(root.endsWith("/") ? root : `${root}/`);
|
|
24651
24878
|
}
|
|
24652
24879
|
var VfsNode = class {
|
|
@@ -25027,7 +25254,7 @@ var VfsNodes = class {
|
|
|
25027
25254
|
return run2;
|
|
25028
25255
|
}
|
|
25029
25256
|
async entryKey(path) {
|
|
25030
|
-
const parent =
|
|
25257
|
+
const parent = parentOf5(path);
|
|
25031
25258
|
const dir = await this.real(parent, true, () => realDir(this.fs, parent));
|
|
25032
25259
|
return joinName(dir, path.slice(path.lastIndexOf("/") + 1));
|
|
25033
25260
|
}
|
|
@@ -25183,12 +25410,12 @@ var VfsNodes = class {
|
|
|
25183
25410
|
return node;
|
|
25184
25411
|
}
|
|
25185
25412
|
holds(prefix) {
|
|
25186
|
-
for (const path of this.byPath.keys()) if (
|
|
25413
|
+
for (const path of this.byPath.keys()) if (within9(path, prefix)) return true;
|
|
25187
25414
|
return false;
|
|
25188
25415
|
}
|
|
25189
25416
|
writes(prefix) {
|
|
25190
25417
|
for (const [path, node] of this.byPath)
|
|
25191
|
-
if (node.writers > 0 &&
|
|
25418
|
+
if (node.writers > 0 && within9(path, prefix)) return true;
|
|
25192
25419
|
return false;
|
|
25193
25420
|
}
|
|
25194
25421
|
closed(node, writable2 = false) {
|
|
@@ -25271,17 +25498,17 @@ var VfsNodes = class {
|
|
|
25271
25498
|
this.byPath.get(path)?.reread();
|
|
25272
25499
|
}
|
|
25273
25500
|
rewrittenUnder(tree2) {
|
|
25274
|
-
for (const [p, node] of this.byPath) if (
|
|
25501
|
+
for (const [p, node] of this.byPath) if (within9(p, tree2)) node.reread();
|
|
25275
25502
|
}
|
|
25276
25503
|
doubted(path) {
|
|
25277
|
-
for (const [p, node] of this.byPath) if (
|
|
25504
|
+
for (const [p, node] of this.byPath) if (within9(p, path)) node.doubted();
|
|
25278
25505
|
}
|
|
25279
25506
|
async flush(path) {
|
|
25280
|
-
for (const [p, node] of this.byPath) if (
|
|
25507
|
+
for (const [p, node] of this.byPath) if (within9(p, path)) await node.serial(() => node.flush());
|
|
25281
25508
|
}
|
|
25282
25509
|
async unlinking(path) {
|
|
25283
25510
|
for (const [held, node] of [...this.byPath]) {
|
|
25284
|
-
if (!
|
|
25511
|
+
if (!within9(held, path)) continue;
|
|
25285
25512
|
await node.serial(async () => {
|
|
25286
25513
|
await Promise.all([this.keepsOnDisk || node.keep(), node.limit()]);
|
|
25287
25514
|
});
|
|
@@ -25289,14 +25516,14 @@ var VfsNodes = class {
|
|
|
25289
25516
|
}
|
|
25290
25517
|
revoke(prefix) {
|
|
25291
25518
|
for (const [path, node] of [...this.byPath]) {
|
|
25292
|
-
if (!
|
|
25519
|
+
if (!within9(path, prefix)) continue;
|
|
25293
25520
|
node.revoke();
|
|
25294
25521
|
this.forget(node);
|
|
25295
25522
|
}
|
|
25296
25523
|
}
|
|
25297
25524
|
unlinked(path) {
|
|
25298
25525
|
for (const [held, node] of [...this.byPath]) {
|
|
25299
|
-
if (!
|
|
25526
|
+
if (!within9(held, path) || this.byPath.get(held) !== node) continue;
|
|
25300
25527
|
if (!this.dropName(held, node)) this.orphan(node);
|
|
25301
25528
|
}
|
|
25302
25529
|
}
|
|
@@ -25304,8 +25531,8 @@ var VfsNodes = class {
|
|
|
25304
25531
|
if (from === to) return;
|
|
25305
25532
|
const moved2 = [];
|
|
25306
25533
|
for (const [p, node] of [...this.byPath]) {
|
|
25307
|
-
if (
|
|
25308
|
-
else if (
|
|
25534
|
+
if (within9(p, from)) moved2.push([p, node]);
|
|
25535
|
+
else if (within9(p, to) && this.byPath.get(p) === node && !this.dropName(p, node)) {
|
|
25309
25536
|
this.orphan(node);
|
|
25310
25537
|
}
|
|
25311
25538
|
}
|
|
@@ -25331,7 +25558,7 @@ function errCode(err) {
|
|
|
25331
25558
|
return err?.code;
|
|
25332
25559
|
}
|
|
25333
25560
|
async function targetDir(fs, path) {
|
|
25334
|
-
return
|
|
25561
|
+
return parentOf5(await realTarget(fs, path).catch(() => path));
|
|
25335
25562
|
}
|
|
25336
25563
|
async function refuseReadonly(fs, path, flags2, opts = {}) {
|
|
25337
25564
|
const writes = (flags2 & O_ACCMODE) !== 0 || opts.truncate === true;
|
|
@@ -25594,7 +25821,7 @@ function isWatchSyscall(req) {
|
|
|
25594
25821
|
return WATCHING.has(req.op);
|
|
25595
25822
|
}
|
|
25596
25823
|
var WATCHES_MAX = 8192;
|
|
25597
|
-
var
|
|
25824
|
+
var parentOf10 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
25598
25825
|
function visibleTo2(watch, root, visible) {
|
|
25599
25826
|
return {
|
|
25600
25827
|
close: () => watch.close(),
|
|
@@ -25605,7 +25832,7 @@ function visibleTo2(watch, root, visible) {
|
|
|
25605
25832
|
notes.map(async (note) => {
|
|
25606
25833
|
if (!("filename" in note) || !note.filename.includes("/")) return true;
|
|
25607
25834
|
const at = watch.root?.() ?? root;
|
|
25608
|
-
const dir =
|
|
25835
|
+
const dir = parentOf10(`${at === "/" ? "" : at}/${note.filename}`);
|
|
25609
25836
|
if (!seen.has(dir)) seen.set(dir, visible(dir));
|
|
25610
25837
|
return seen.get(dir);
|
|
25611
25838
|
})
|
|
@@ -29550,7 +29777,7 @@ function sealedFetcher(hook, stop, idleMs = BODY_IDLE_MS) {
|
|
|
29550
29777
|
var SWAP_GAP_MS = 2e3;
|
|
29551
29778
|
var STAGES = ["_tmp_", "_pacquet-stage_"];
|
|
29552
29779
|
function staged(source, target) {
|
|
29553
|
-
if (
|
|
29780
|
+
if (parentOf5(source) !== parentOf5(target)) return false;
|
|
29554
29781
|
const name2 = target.slice(target.lastIndexOf("/") + 1);
|
|
29555
29782
|
const from = source.slice(source.lastIndexOf("/") + 1);
|
|
29556
29783
|
return from.startsWith(`.${name2}-`) || STAGES.some((stage) => from.startsWith(`${name2}${stage}`));
|
|
@@ -29647,7 +29874,7 @@ var PackageSwaps = class {
|
|
|
29647
29874
|
|
|
29648
29875
|
// src/kernel/rename-log.ts
|
|
29649
29876
|
var RENAME_LOG_SIZE = 4096;
|
|
29650
|
-
function
|
|
29877
|
+
function within10(path, root) {
|
|
29651
29878
|
return path === root || path.startsWith(root === "/" ? "/" : `${root}/`);
|
|
29652
29879
|
}
|
|
29653
29880
|
var RenameLog = class {
|
|
@@ -29674,9 +29901,9 @@ var RenameLog = class {
|
|
|
29674
29901
|
const renames = [];
|
|
29675
29902
|
let paths = [...held];
|
|
29676
29903
|
for (const { seq: seq2, from, to } of this.entries) {
|
|
29677
|
-
if (seq2 <= seen || !paths.some((path) =>
|
|
29904
|
+
if (seq2 <= seen || !paths.some((path) => within10(path, from))) continue;
|
|
29678
29905
|
renames.push([from, to]);
|
|
29679
|
-
paths = paths.map((path) =>
|
|
29906
|
+
paths = paths.map((path) => within10(path, from) ? to + path.slice(from.length) : path);
|
|
29680
29907
|
}
|
|
29681
29908
|
return { now, renames };
|
|
29682
29909
|
}
|
|
@@ -31028,18 +31255,28 @@ function settle2(request3, value2) {
|
|
|
31028
31255
|
request3.onerror = () => reject(request3.error);
|
|
31029
31256
|
});
|
|
31030
31257
|
}
|
|
31031
|
-
|
|
31258
|
+
var privateTop2 = () => navigator.storage.getDirectory();
|
|
31259
|
+
async function stored(kept, top) {
|
|
31260
|
+
const path = kept?.path;
|
|
31261
|
+
if (!Array.isArray(path)) return kept;
|
|
31262
|
+
return directoryAt(await top(), path).catch(() => void 0);
|
|
31263
|
+
}
|
|
31264
|
+
function openMedia(name2, factory, top = privateTop2) {
|
|
31032
31265
|
const request3 = factory.open(name2, 1);
|
|
31033
31266
|
request3.onupgradeneeded = () => request3.result.createObjectStore(MEDIA_STORE);
|
|
31034
31267
|
return settle2(request3, () => {
|
|
31035
31268
|
const db = request3.result;
|
|
31036
31269
|
const store = (mode) => db.transaction(MEDIA_STORE, mode).objectStore(MEDIA_STORE);
|
|
31037
31270
|
return {
|
|
31038
|
-
get: (id2) => {
|
|
31271
|
+
get: async (id2) => {
|
|
31039
31272
|
const got = store("readonly").get(id2);
|
|
31040
|
-
return settle2(got, () => got.result);
|
|
31273
|
+
return stored(await settle2(got, () => got.result), top);
|
|
31041
31274
|
},
|
|
31042
|
-
put: (id2, handle) =>
|
|
31275
|
+
put: async (id2, handle) => {
|
|
31276
|
+
const at = await portable(handle, top);
|
|
31277
|
+
const kept = "path" in at ? at : handle;
|
|
31278
|
+
await settle2(store("readwrite").put(kept, id2), () => void 0);
|
|
31279
|
+
}
|
|
31043
31280
|
};
|
|
31044
31281
|
});
|
|
31045
31282
|
}
|
|
@@ -32647,6 +32884,7 @@ var Launcher = class {
|
|
|
32647
32884
|
this.rewritten(change.paths, change.trees);
|
|
32648
32885
|
this.watchers.heard(change.content ? "change" : "rename", change.paths);
|
|
32649
32886
|
this.watchers.heard("rename", change.trees ?? []);
|
|
32887
|
+
this.watchers.peerChanged([...change.paths, ...change.trees ?? []]);
|
|
32650
32888
|
if (change.outside && this.catalogChanged([...change.paths, ...change.trees ?? []])) {
|
|
32651
32889
|
this.resetCatalogs();
|
|
32652
32890
|
}
|
|
@@ -33400,9 +33638,9 @@ var Launcher = class {
|
|
|
33400
33638
|
}
|
|
33401
33639
|
packageRootIs(path) {
|
|
33402
33640
|
const at = normalizePath(path);
|
|
33403
|
-
const
|
|
33641
|
+
const within11 = `${at}/`;
|
|
33404
33642
|
const roots = [this.modulesDir, ...this.appended];
|
|
33405
|
-
const root = PACKAGE_ROOT.exec(
|
|
33643
|
+
const root = PACKAGE_ROOT.exec(within11)?.[1] ?? packageRootOf(within11, roots);
|
|
33406
33644
|
return root === at;
|
|
33407
33645
|
}
|
|
33408
33646
|
packageRoots(planned) {
|
|
@@ -33601,6 +33839,7 @@ var Launcher = class {
|
|
|
33601
33839
|
fsCalls: servedFsCalls(),
|
|
33602
33840
|
opfsCalls: this.rootFs.opfsCalls?.() ?? 0,
|
|
33603
33841
|
opfsOps: this.rootFs.opfsOps?.() ?? 0,
|
|
33842
|
+
meta: this.rootFs.metaTransactions?.(),
|
|
33604
33843
|
cwdChecks: this.cwds.checks,
|
|
33605
33844
|
renameAcks: this.rootFs.renameWaits?.(),
|
|
33606
33845
|
swaps: this.swaps.counts(),
|
|
@@ -33791,7 +34030,7 @@ var Launcher = class {
|
|
|
33791
34030
|
}
|
|
33792
34031
|
list(viewer = ROOT) {
|
|
33793
34032
|
const members = new Map(this.jobs.list().map((member) => [member.pid, member]));
|
|
33794
|
-
const
|
|
34033
|
+
const rootOf2 = (member) => {
|
|
33795
34034
|
let root = member;
|
|
33796
34035
|
for (let up = members.get(root.execParent ?? -1); up; up = members.get(up.execParent ?? -1)) {
|
|
33797
34036
|
root = up;
|
|
@@ -33800,7 +34039,7 @@ var Launcher = class {
|
|
|
33800
34039
|
};
|
|
33801
34040
|
const shown = (pid) => {
|
|
33802
34041
|
const member = pid === void 0 ? void 0 : members.get(pid);
|
|
33803
|
-
const root = member &&
|
|
34042
|
+
const root = member && rootOf2(member).pid;
|
|
33804
34043
|
return root !== void 0 && this.running(root) ? root : INIT_PID;
|
|
33805
34044
|
};
|
|
33806
34045
|
const superseded = new Set([...members.values()].map((m) => m.execParent));
|
|
@@ -33810,7 +34049,7 @@ var Launcher = class {
|
|
|
33810
34049
|
if (member.execed && superseded.has(member.pid) || !described2) continue;
|
|
33811
34050
|
const cred = this.credOf(member.pid);
|
|
33812
34051
|
if (!maySee(viewer, cred)) continue;
|
|
33813
|
-
const root =
|
|
34052
|
+
const root = rootOf2(member);
|
|
33814
34053
|
const tags = this.tagsOf(member.pid) ?? this.tagsOf(root.pid);
|
|
33815
34054
|
listed.push({
|
|
33816
34055
|
pid: root.pid,
|
|
@@ -34209,9 +34448,9 @@ var Launcher = class {
|
|
|
34209
34448
|
const served2 = serveFilesystem(port2, medium.handlers, FSA_CAPABILITIES);
|
|
34210
34449
|
const id2 = source.slice("fsa:".length);
|
|
34211
34450
|
this.removable.set(target, { id: id2, medium, served: served2 });
|
|
34212
|
-
const
|
|
34213
|
-
if (
|
|
34214
|
-
else ask(
|
|
34451
|
+
const stored2 = this.inserted.get(id2) ?? await this.media.get(id2);
|
|
34452
|
+
if (stored2 && await granted(stored2)) medium.insert(stored2);
|
|
34453
|
+
else ask(stored2);
|
|
34215
34454
|
return {
|
|
34216
34455
|
port: port1,
|
|
34217
34456
|
present: () => medium.present(),
|
|
@@ -34344,7 +34583,7 @@ var Launcher = class {
|
|
|
34344
34583
|
const path = normalizePath(given);
|
|
34345
34584
|
if (!await this.base.exists(path)) return void 0;
|
|
34346
34585
|
if (path === "/") return path;
|
|
34347
|
-
return joinName(await realDir(this.base,
|
|
34586
|
+
return joinName(await realDir(this.base, parentOf5(path)), baseName2(path));
|
|
34348
34587
|
}
|
|
34349
34588
|
pnpmReady() {
|
|
34350
34589
|
if (this.pnpmMade !== void 0) return this.pnpmMade;
|
|
@@ -35124,11 +35363,24 @@ async function inOpfs(deps, root) {
|
|
|
35124
35363
|
return await opfs?.resolve(root).catch(() => null) != null;
|
|
35125
35364
|
}
|
|
35126
35365
|
async function rootNamed(deps, req, root) {
|
|
35127
|
-
if (req.metadata !== void 0 || !req.root || !deps.rootId) return req;
|
|
35366
|
+
if (req.metadata !== void 0 || !req.root && !req.rootPath || !deps.rootId) return req;
|
|
35128
35367
|
const top = await deps.storage().catch(() => void 0);
|
|
35129
35368
|
const name2 = await metadataName(top, root, deps.rootId);
|
|
35130
35369
|
return name2 === META_DB ? req : { ...req, metadata: name2 };
|
|
35131
35370
|
}
|
|
35371
|
+
async function rootOf(deps, req) {
|
|
35372
|
+
if (req.root) return req.root;
|
|
35373
|
+
const top = await deps.storage();
|
|
35374
|
+
return req.rootPath ? directoryAt(top, req.rootPath) : top;
|
|
35375
|
+
}
|
|
35376
|
+
async function insertedHandle(deps, req) {
|
|
35377
|
+
return "path" in req ? directoryAt(await deps.storage(), req.path) : req.handle;
|
|
35378
|
+
}
|
|
35379
|
+
function crossable(medium) {
|
|
35380
|
+
if (!medium.handle || clonable(medium.handle)) return medium;
|
|
35381
|
+
const { handle: _, ...rest2 } = medium;
|
|
35382
|
+
return rest2;
|
|
35383
|
+
}
|
|
35132
35384
|
function workers(deps) {
|
|
35133
35385
|
return {
|
|
35134
35386
|
createWorker: deps.createWorker,
|
|
@@ -35411,7 +35663,7 @@ function serveKernel(port, deps) {
|
|
|
35411
35663
|
}
|
|
35412
35664
|
}
|
|
35413
35665
|
async function init(req) {
|
|
35414
|
-
launcher = (
|
|
35666
|
+
launcher = rootOf(deps, req).then(async (root) => {
|
|
35415
35667
|
req = await rootNamed(deps, req, root);
|
|
35416
35668
|
const name2 = req.metadata ?? META_DB;
|
|
35417
35669
|
const { meta, media } = await stores(deps, name2, req.media);
|
|
@@ -35439,7 +35691,7 @@ function serveKernel(port, deps) {
|
|
|
35439
35691
|
...req.approve ? { approve: approvals.ask } : {},
|
|
35440
35692
|
...net,
|
|
35441
35693
|
...media ? { media } : {},
|
|
35442
|
-
onMountPending: (medium) => port.postMessage({ medium }),
|
|
35694
|
+
onMountPending: (medium) => port.postMessage({ medium: crossable(medium) }),
|
|
35443
35695
|
...req.hostfs ? { hostfs: askGrant } : {},
|
|
35444
35696
|
...pageHooks(req, port),
|
|
35445
35697
|
...mountPolicy(req.processMounts),
|
|
@@ -35455,7 +35707,8 @@ function serveKernel(port, deps) {
|
|
|
35455
35707
|
const l = await ready2();
|
|
35456
35708
|
if (req.op === "mount") return l.mount(req.spec);
|
|
35457
35709
|
if (req.op === "umount") return l.umount(req.target);
|
|
35458
|
-
if (req.op === "insert")
|
|
35710
|
+
if (req.op === "insert")
|
|
35711
|
+
return l.insert(req.target, await insertedHandle(deps, req), req.source);
|
|
35459
35712
|
return l.mounts.listed();
|
|
35460
35713
|
}
|
|
35461
35714
|
const attestOp = attestOps(port);
|