@ai-ecoverse/slicc-kernel 1.166.4 → 1.167.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 +1 -1
- package/dist/kernel-worker.js +183 -36
- package/dist/kernel-worker.js.map +3 -3
- package/dist/node-driver-worker.js +12 -1
- package/dist/node-driver-worker.js.map +2 -2
- package/dist/node-process-worker.cjs +18 -7
- package/dist/node-process-worker.cjs.map +3 -3
- package/dist/node-process-worker.js +18 -7
- package/dist/node-process-worker.js.map +3 -3
- package/dist/node.js +183 -36
- package/dist/node.js.map +3 -3
- package/dist/process-worker.js +1 -1
- package/dist/types/fs/unlinked.d.ts +18 -0
- package/dist/types/launcher.d.ts +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -424,7 +424,7 @@ The module's default export (or its `main` export) is called with a context and
|
|
|
424
424
|
- `sync.promiseState(promise)` (#1531, slicc-jsh#974) tells a native promise's state synchronously, as Node's `util.inspect` does: `{ state: 'pending' | 'fulfilled' | 'rejected', value }`. `value` is the very fulfillment value or rejection reason (`undefined` while pending), and probing doesn't handle a rejection. On the Node entry it reads the promise through an inspector session the process worker opens on first use, one per process and per thread; the probe runs no program code. Anything that isn't a native promise (a thenable, a proxy) is a `TypeError`. It answers `undefined` in a browser, where a worker has no inspector, on a Node built without one, once a program has changed `Object.prototype` or put a `toJSON` on a built-in prototype, and when the global object can't take a new property (`Object.preventExtensions(globalThis)`, or a frozen global).
|
|
425
425
|
- `sync.setStackFormatter(fn | null)` (#1612, slicc-jsh#1091) is Node only, so check it with `typeof ctx.sync.setStackFormatter === 'function'`. It returns the previous formatter, and `null` removes it.
|
|
426
426
|
- **When `fn` runs:** it formats an error's `.stack` the way V8's prepare-stack-trace callback does, as `fn(error, callSites)` returning the string. It runs only when no own `Error.prepareStackTrace` function is set, as in Node, so `Error.prepareStackTrace` stays an ordinary property: after `delete` it's `undefined`, `Object.getPrototypeOf(Error)` stays `Function.prototype`, and an assignment to a frozen subclass throws in strict mode.
|
|
427
|
-
- **What `fn` gets:** a fresh array of V8 CallSites holding only the program's own frames (its modules, `data:` imports, `sync.runScript` scripts, code they `eval`, `new Function` or `eval` code named by `//# sourceURL`, #1632, and code such a body `eval`s, #1648), `node:` frames and native frames. Kernel frames are dropped by script identity, so a script named like a kernel file doesn't let them through, and so are host files. A program's strict frames give `getFunction()` and `getThis()` as `undefined`.
|
|
427
|
+
- **What `fn` gets:** a fresh array of V8 CallSites holding only the program's own frames (its modules, `data:` imports, `sync.runScript` scripts, code they `eval`, `new Function` or `eval` code named by `//# sourceURL`, #1632, and code such a body `eval`s, #1648; the kernel remembers the 4096 sourceURL names it saw last, #1658), `node:` frames and native frames. Kernel frames are dropped by script identity, so a script named like a kernel file doesn't let them through, and so are host files. A program's strict frames give `getFunction()` and `getThis()` as `undefined`.
|
|
428
428
|
- **Fallback:** if `fn` throws or returns a non-string, or an error is formatted while `fn` runs, the default stack is used.
|
|
429
429
|
- **`{ own: true }`** (#1631): `setStackFormatter(fn, { own: true })` calls `fn(error, callSites, own)` for every stack. `own` is the program's own `Error.prepareStackTrace` (the realm's `Error`, then the main one, read as Node 26 reads it), or `undefined` when none is set or it's Node's default. `fn`'s result is the stack whatever its type, and a throw propagates out of the `.stack` read, as with Node's own callback.
|
|
430
430
|
- **An own `Error.prepareStackTrace` on the Node entry** (#1631): the process worker replaces Node's stack callback with a copy of Node 26's order. A program's own `Error.prepareStackTrace`, and a host preload's, still gets V8's CallSites as in Node, kernel frames included (named `slicc-kernel:/node-process-worker.js`), with its `Error` as receiver; its result and throws are the stack. To hand it the filtered CallSites instead (no kernel frame, no host path), use `setStackFormatter(fn, { own: true })` and call `own` from `fn`. 1.165.0 filtered by default, which broke runtimes that read their own frames through an own `prepareStackTrace`; the release after it went back to V8's CallSites. Node's own internal overrides still come first with raw frames, and so do the kernel's own diagnostics: a crash report and a WASI trap backtrace still show kernel and wasm frames.
|
package/dist/kernel-worker.js
CHANGED
|
@@ -1312,6 +1312,7 @@ var RemoteWatch = class {
|
|
|
1312
1312
|
};
|
|
1313
1313
|
const left = /* @__PURE__ */ new Set([to]);
|
|
1314
1314
|
const timer = setTimeout(done5, cap);
|
|
1315
|
+
timer.unref?.();
|
|
1315
1316
|
this.waiting.set(seq2, { left, done: done5 });
|
|
1316
1317
|
});
|
|
1317
1318
|
}
|
|
@@ -1353,6 +1354,9 @@ var RemoteWatch = class {
|
|
|
1353
1354
|
this.keeps?.left(tab);
|
|
1354
1355
|
this.ackers.delete(tab);
|
|
1355
1356
|
this.holders.delete(tab);
|
|
1357
|
+
for (const wait2 of [...this.waiting.values()]) {
|
|
1358
|
+
if (wait2.left.delete(tab) && wait2.left.size === 0) wait2.done();
|
|
1359
|
+
}
|
|
1356
1360
|
}
|
|
1357
1361
|
}
|
|
1358
1362
|
this.rebuild();
|
|
@@ -1598,9 +1602,9 @@ async function unlocked(name2, op) {
|
|
|
1598
1602
|
return await op();
|
|
1599
1603
|
} catch (err) {
|
|
1600
1604
|
if (!LOCKED.has(err?.name)) throw err;
|
|
1601
|
-
const
|
|
1602
|
-
if (
|
|
1603
|
-
await new Promise((resolve2) => setTimeout(resolve2,
|
|
1605
|
+
const delay2 = SYNC_BACKOFF_MS[attempt];
|
|
1606
|
+
if (delay2 === void 0) throw fsError("EBUSY", name2);
|
|
1607
|
+
await new Promise((resolve2) => setTimeout(resolve2, delay2));
|
|
1604
1608
|
}
|
|
1605
1609
|
}
|
|
1606
1610
|
}
|
|
@@ -1611,10 +1615,10 @@ async function openSync(handle) {
|
|
|
1611
1615
|
try {
|
|
1612
1616
|
return await sync.call(handle, { mode: "readwrite-unsafe" });
|
|
1613
1617
|
} catch (err) {
|
|
1614
|
-
const
|
|
1618
|
+
const delay2 = SYNC_BACKOFF_MS[attempt];
|
|
1615
1619
|
if (!LOCKED.has(err?.name)) throw err;
|
|
1616
|
-
if (
|
|
1617
|
-
await new Promise((resolve2) => setTimeout(resolve2,
|
|
1620
|
+
if (delay2 === void 0) return void 0;
|
|
1621
|
+
await new Promise((resolve2) => setTimeout(resolve2, delay2));
|
|
1618
1622
|
}
|
|
1619
1623
|
}
|
|
1620
1624
|
}
|
|
@@ -3623,9 +3627,9 @@ var OpfsFs = class {
|
|
|
3623
3627
|
if (!failed3) return true;
|
|
3624
3628
|
const error = failed3.err?.name;
|
|
3625
3629
|
if (handle.kind !== "file" || !LOCKED.has(error)) return false;
|
|
3626
|
-
const
|
|
3627
|
-
if (
|
|
3628
|
-
await new Promise((resolve2) => setTimeout(resolve2,
|
|
3630
|
+
const delay2 = SYNC_BACKOFF_MS[attempt];
|
|
3631
|
+
if (delay2 === void 0) throw fsError("EBUSY", name2);
|
|
3632
|
+
await new Promise((resolve2) => setTimeout(resolve2, delay2));
|
|
3629
3633
|
}
|
|
3630
3634
|
}
|
|
3631
3635
|
async copy(handle, dir, name2, copies, rest2 = "") {
|
|
@@ -8464,7 +8468,7 @@ function satisfies(version, range2) {
|
|
|
8464
8468
|
}
|
|
8465
8469
|
|
|
8466
8470
|
// src/version.ts
|
|
8467
|
-
var KERNEL_VERSION = true ? "1.
|
|
8471
|
+
var KERNEL_VERSION = true ? "1.167.0" : "0.0.0-dev";
|
|
8468
8472
|
var OS_RELEASE = "6.0.0-slicc";
|
|
8469
8473
|
function procVersion() {
|
|
8470
8474
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -9415,8 +9419,41 @@ var within4 = (path, target) => path === target || target === "/" || path.starts
|
|
|
9415
9419
|
var TOUCHED_MAX = 4096;
|
|
9416
9420
|
var parentOf5 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
9417
9421
|
var PEER_RM_MS = 1e3;
|
|
9422
|
+
var SHARED_ACK_MS = 24 * 60 * 60 * 1e3;
|
|
9423
|
+
var delay = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
9418
9424
|
var PEER_RENAME_MS = 1e4;
|
|
9419
9425
|
var PEER_GATE_MS = PEER_RENAME_MS + 5e3;
|
|
9426
|
+
var SHARED_PREFIX = "shared.";
|
|
9427
|
+
var keptLock = (hidden) => `slicc-kept:${hidden}`;
|
|
9428
|
+
function sharedKept(hidden) {
|
|
9429
|
+
const at = `/${UNLINKED_DIR}/${SHARED_PREFIX}`;
|
|
9430
|
+
return hidden.startsWith(at) && /^[0-9a-f]+$/.test(hidden.slice(at.length));
|
|
9431
|
+
}
|
|
9432
|
+
function holdShared(locks, name2) {
|
|
9433
|
+
if (!locks) return Promise.resolve(async () => void 0);
|
|
9434
|
+
return new Promise((resolve2) => {
|
|
9435
|
+
const settled = locks.request(name2, { mode: "shared" }, () => {
|
|
9436
|
+
const { promise, resolve: done5 } = Promise.withResolvers();
|
|
9437
|
+
resolve2(async () => {
|
|
9438
|
+
done5();
|
|
9439
|
+
await settled.catch(() => void 0);
|
|
9440
|
+
});
|
|
9441
|
+
return promise;
|
|
9442
|
+
});
|
|
9443
|
+
});
|
|
9444
|
+
}
|
|
9445
|
+
async function whenLast(locks, name2, op) {
|
|
9446
|
+
if (!locks) {
|
|
9447
|
+
await op();
|
|
9448
|
+
return true;
|
|
9449
|
+
}
|
|
9450
|
+
let free = false;
|
|
9451
|
+
await locks.request(name2, { mode: "exclusive", ifAvailable: true }, async (lock) => {
|
|
9452
|
+
free = lock !== null;
|
|
9453
|
+
if (free) await op();
|
|
9454
|
+
});
|
|
9455
|
+
return free;
|
|
9456
|
+
}
|
|
9420
9457
|
var lockName = (instance) => `slicc-unlinked:${instance}`;
|
|
9421
9458
|
var dirOf = (root) => root === "/" ? `/${UNLINKED_DIR}` : `${root}/${UNLINKED_DIR}`;
|
|
9422
9459
|
var PathGate = class {
|
|
@@ -9732,52 +9769,124 @@ var UnlinkedKeeper = class {
|
|
|
9732
9769
|
void peers.ask(tab, { kept: { items: [], paths } }, PEER_RM_MS);
|
|
9733
9770
|
throw fsError("EBUSY", `${target}: open in another tab that did not answer`);
|
|
9734
9771
|
}
|
|
9735
|
-
const { whole, sends } = await this.setAside(target, asked);
|
|
9736
|
-
return { whole, undoing: (op) => this.undoing(op, peers, sends, heard) };
|
|
9772
|
+
const { whole, sends, shared } = await this.setAside(target, asked);
|
|
9773
|
+
return { whole, undoing: (op) => this.undoing(op, peers, sends, heard, shared) };
|
|
9737
9774
|
}
|
|
9738
9775
|
async setAside(target, asked) {
|
|
9739
9776
|
const mine = this.heldWithin(target);
|
|
9740
|
-
const
|
|
9741
|
-
|
|
9777
|
+
const tabsOf = /* @__PURE__ */ new Map();
|
|
9778
|
+
for (const { holders } of asked)
|
|
9779
|
+
for (const { path } of holders) tabsOf.set(path, (tabsOf.get(path) ?? 0) + 1);
|
|
9780
|
+
const done5 = /* @__PURE__ */ new Map();
|
|
9781
|
+
const shared = [];
|
|
9742
9782
|
const sends = [];
|
|
9743
9783
|
for (const { tab, holders, paths } of asked) {
|
|
9744
9784
|
const items = [];
|
|
9745
9785
|
for (const holder of holders) {
|
|
9746
|
-
|
|
9747
|
-
|
|
9748
|
-
|
|
9749
|
-
taken.add(holder.path);
|
|
9750
|
-
if (holder.path === target) whole = true;
|
|
9786
|
+
if (!done5.has(holder.path)) {
|
|
9787
|
+
const many = mine.has(holder.path) || (tabsOf.get(holder.path) ?? 0) > 1;
|
|
9788
|
+
done5.set(holder.path, await this.asideOne(holder, many, mine, shared));
|
|
9751
9789
|
}
|
|
9752
|
-
items.push({ path: holder.path, hidden, fid: holder.fid });
|
|
9790
|
+
items.push({ path: holder.path, hidden: done5.get(holder.path), fid: holder.fid });
|
|
9753
9791
|
}
|
|
9754
9792
|
sends.push({ tab, items, paths });
|
|
9755
9793
|
}
|
|
9756
|
-
return { whole, sends };
|
|
9794
|
+
return { whole: done5.get(target) !== void 0, sends, shared };
|
|
9795
|
+
}
|
|
9796
|
+
async asideOne(holder, many, mine, shared) {
|
|
9797
|
+
if (!many) return this.asideFor(holder.path, holder.instance);
|
|
9798
|
+
const one = await this.sharedAside(holder.path, mine);
|
|
9799
|
+
if (one) shared.push(one);
|
|
9800
|
+
return one?.hidden;
|
|
9801
|
+
}
|
|
9802
|
+
async sharedAside(path, mine) {
|
|
9803
|
+
const hidden = `${dirOf("/")}/${SHARED_PREFIX}${crypto.randomUUID().replaceAll("-", "")}`;
|
|
9804
|
+
const release = await holdShared(this.sharedLocks(), keptLock(hidden));
|
|
9805
|
+
const moved2 = await this.serial(async () => {
|
|
9806
|
+
try {
|
|
9807
|
+
const owner = this.dirOwner;
|
|
9808
|
+
await this.fs.mkdir(dirOf("/"), { recursive: true, ...owner ? { owner } : {} });
|
|
9809
|
+
await this.fs.rename(path, hidden);
|
|
9810
|
+
return true;
|
|
9811
|
+
} catch {
|
|
9812
|
+
return false;
|
|
9813
|
+
}
|
|
9814
|
+
});
|
|
9815
|
+
if (!moved2) {
|
|
9816
|
+
await release();
|
|
9817
|
+
return void 0;
|
|
9818
|
+
}
|
|
9819
|
+
const local2 = mine.get(path) ?? [];
|
|
9820
|
+
const file = local2.length > 0 ? await this.sharedFile(hidden, local2.length) : void 0;
|
|
9821
|
+
if (file) for (const holder of local2) holder.keep(path, file);
|
|
9822
|
+
return { path, hidden, release, local: local2, file };
|
|
9823
|
+
}
|
|
9824
|
+
async sharedFile(hidden, refs) {
|
|
9825
|
+
const locks = this.sharedLocks();
|
|
9826
|
+
const mine = await holdShared(locks, keptLock(hidden));
|
|
9827
|
+
let left = refs;
|
|
9828
|
+
return {
|
|
9829
|
+
hidden,
|
|
9830
|
+
release: () => {
|
|
9831
|
+
if (--left > 0) return;
|
|
9832
|
+
void mine().then(() => this.dropIfLast(hidden));
|
|
9833
|
+
}
|
|
9834
|
+
};
|
|
9757
9835
|
}
|
|
9758
|
-
|
|
9836
|
+
dropIfLast(hidden) {
|
|
9837
|
+
return this.serial(
|
|
9838
|
+
() => whenLast(this.sharedLocks(), keptLock(hidden), () => this.drop(hidden))
|
|
9839
|
+
);
|
|
9840
|
+
}
|
|
9841
|
+
sharedLocks() {
|
|
9842
|
+
return this.locks;
|
|
9843
|
+
}
|
|
9844
|
+
async undoing(op, peers, sends, heard, shared = []) {
|
|
9759
9845
|
let failed3;
|
|
9760
9846
|
let out;
|
|
9761
9847
|
try {
|
|
9762
9848
|
out = await op();
|
|
9763
9849
|
} catch (err) {
|
|
9764
9850
|
failed3 = err ?? new Error("failed");
|
|
9765
|
-
|
|
9766
|
-
for (const item of send2.items) {
|
|
9767
|
-
const { hidden, path } = item;
|
|
9768
|
-
if (hidden !== void 0 && await this.moveBack(hidden, path)) item.hidden = void 0;
|
|
9769
|
-
}
|
|
9770
|
-
}
|
|
9851
|
+
await this.rollBackAsides(sends, shared);
|
|
9771
9852
|
}
|
|
9853
|
+
const hiddenShared = new Set(shared.map((one) => one.hidden));
|
|
9854
|
+
const answers2 = sends.map(({ tab, items, paths }) => {
|
|
9855
|
+
const keeps = items.some((item) => item.hidden && hiddenShared.has(item.hidden));
|
|
9856
|
+
return {
|
|
9857
|
+
keeps,
|
|
9858
|
+
told: peers.ask(tab, { kept: { items, paths } }, keeps ? SHARED_ACK_MS : PEER_RM_MS)
|
|
9859
|
+
};
|
|
9860
|
+
});
|
|
9772
9861
|
await Promise.all(
|
|
9773
|
-
|
|
9774
|
-
const told = peers.ask(tab, { kept: { items, paths } }, PEER_RM_MS);
|
|
9775
|
-
return heard[i] ? told : void 0;
|
|
9776
|
-
})
|
|
9862
|
+
answers2.map(({ told }, i) => heard[i] ? Promise.race([told, delay(PEER_RM_MS)]) : void 0)
|
|
9777
9863
|
);
|
|
9864
|
+
for (const one of shared) {
|
|
9865
|
+
const waits = answers2.filter(
|
|
9866
|
+
({ keeps }, i) => keeps && sends[i]?.items.some((item) => item.hidden === one.hidden)
|
|
9867
|
+
);
|
|
9868
|
+
const done5 = () => one.release().then(() => this.dropIfLast(one.hidden));
|
|
9869
|
+
void Promise.all(waits.map(({ told }) => told)).then(done5, done5);
|
|
9870
|
+
}
|
|
9778
9871
|
if (failed3 !== void 0) throw failed3;
|
|
9779
9872
|
return out;
|
|
9780
9873
|
}
|
|
9874
|
+
async rollBackAsides(sends, shared) {
|
|
9875
|
+
const back = /* @__PURE__ */ new Map();
|
|
9876
|
+
for (const item of sends.flatMap((send2) => send2.items)) {
|
|
9877
|
+
const { hidden, path } = item;
|
|
9878
|
+
if (hidden === void 0) continue;
|
|
9879
|
+
if (!back.has(hidden)) back.set(hidden, await this.moveBack(hidden, path));
|
|
9880
|
+
if (back.get(hidden)) item.hidden = void 0;
|
|
9881
|
+
}
|
|
9882
|
+
for (const { hidden, path, local: local2, file } of shared) {
|
|
9883
|
+
if (!back.get(hidden) || !file) continue;
|
|
9884
|
+
for (const holder of local2) {
|
|
9885
|
+
holder.unkeep(path, file);
|
|
9886
|
+
file.release();
|
|
9887
|
+
}
|
|
9888
|
+
}
|
|
9889
|
+
}
|
|
9781
9890
|
moveBack(hidden, path) {
|
|
9782
9891
|
return this.serial(async () => {
|
|
9783
9892
|
if (await this.present(path)) return false;
|
|
@@ -9886,6 +9995,15 @@ var UnlinkedKeeper = class {
|
|
|
9886
9995
|
for (const name2 of names2) {
|
|
9887
9996
|
const id2 = name2.slice(0, name2.lastIndexOf("."));
|
|
9888
9997
|
const at = id2.indexOf("~");
|
|
9998
|
+
if (name2.startsWith(SHARED_PREFIX)) {
|
|
9999
|
+
const at2 = `${dir}/${name2}`;
|
|
10000
|
+
await whenLast(
|
|
10001
|
+
this.sharedLocks(),
|
|
10002
|
+
keptLock(at2),
|
|
10003
|
+
() => this.fs.rm(at2, { recursive: true }).catch(() => void 0)
|
|
10004
|
+
);
|
|
10005
|
+
continue;
|
|
10006
|
+
}
|
|
9889
10007
|
const dead = id2 !== this.instance && (at < 0 ? held !== void 0 && !held.has(lockName(id2)) : owner?.alive(id2.slice(0, at)) === false);
|
|
9890
10008
|
if (dead) await this.fs.rm(`${dir}/${name2}`, { recursive: true }).catch(() => void 0);
|
|
9891
10009
|
}
|
|
@@ -24598,13 +24716,13 @@ var VfsNode = class {
|
|
|
24598
24716
|
this.recount();
|
|
24599
24717
|
if (!this.orphaned) this.onDirty?.();
|
|
24600
24718
|
if (this.writeBack !== void 0 || this.orphaned) return;
|
|
24601
|
-
const
|
|
24719
|
+
const delay2 = Math.max(WRITEBACK_MS, this.writeBackCost * WRITEBACK_COST_FACTOR);
|
|
24602
24720
|
this.writeBack = setTimeout(() => {
|
|
24603
24721
|
this.writeBack = void 0;
|
|
24604
24722
|
this.serial(() => this.flush()).catch(() => {
|
|
24605
24723
|
this.failed = true;
|
|
24606
24724
|
});
|
|
24607
|
-
},
|
|
24725
|
+
}, delay2);
|
|
24608
24726
|
}
|
|
24609
24727
|
ensure(need2) {
|
|
24610
24728
|
const cur = this.data ?? new Uint8Array(0);
|
|
@@ -33572,7 +33690,10 @@ var Launcher = class {
|
|
|
33572
33690
|
await Promise.all(mine);
|
|
33573
33691
|
},
|
|
33574
33692
|
kept: async (tab, items, paths) => {
|
|
33575
|
-
for (const { path, hidden, fid } of items)
|
|
33693
|
+
for (const { path, hidden, fid } of items) {
|
|
33694
|
+
if (hidden !== void 0 && sharedKept(hidden)) await this.adoptShared(path, hidden, fid);
|
|
33695
|
+
else this.adoptKept(path, hidden, fid, ours);
|
|
33696
|
+
}
|
|
33576
33697
|
await open2(tab, paths);
|
|
33577
33698
|
},
|
|
33578
33699
|
left: (tab) => {
|
|
@@ -33581,6 +33702,33 @@ var Launcher = class {
|
|
|
33581
33702
|
}
|
|
33582
33703
|
};
|
|
33583
33704
|
}
|
|
33705
|
+
async adoptShared(path, hidden, fid) {
|
|
33706
|
+
const bound3 = [...this.held].map(
|
|
33707
|
+
(holds2) => [holds2, [...holds2.boundAt(path, fid), ...holds2.boundAt(hidden, fid)]]
|
|
33708
|
+
);
|
|
33709
|
+
const keeping = bound3.filter(([, ids]) => ids.length > 0);
|
|
33710
|
+
const nodes = [...this.openFiles].filter(
|
|
33711
|
+
(open2) => [path, hidden].some((at) => open2.holdsAt(at))
|
|
33712
|
+
);
|
|
33713
|
+
const refs = keeping.length + nodes.length;
|
|
33714
|
+
if (refs === 0) {
|
|
33715
|
+
this.held.doubt([path]);
|
|
33716
|
+
return;
|
|
33717
|
+
}
|
|
33718
|
+
const file = await this.unlinked.sharedFile(hidden, refs);
|
|
33719
|
+
if (!await this.rootFs.lstat(hidden).then(
|
|
33720
|
+
() => true,
|
|
33721
|
+
() => false
|
|
33722
|
+
)) {
|
|
33723
|
+
for (let i = 0; i < refs; i++) file.release();
|
|
33724
|
+
this.held.doubt([path]);
|
|
33725
|
+
return;
|
|
33726
|
+
}
|
|
33727
|
+
const kept = nodes.filter((open2) => open2.keepBound([hidden, path], fid, file)).length;
|
|
33728
|
+
for (let i = kept; i < nodes.length; i++) file.release();
|
|
33729
|
+
for (const [holds2, ids] of keeping) holds2.keepBound(ids, path, file);
|
|
33730
|
+
void this.rootFs.announceHolds?.([], [path, hidden], false);
|
|
33731
|
+
}
|
|
33584
33732
|
adoptKept(path, hidden, fid, ours) {
|
|
33585
33733
|
if (hidden === void 0 || !ours(hidden)) {
|
|
33586
33734
|
this.held.doubt([path]);
|
|
@@ -33723,7 +33871,6 @@ var Launcher = class {
|
|
|
33723
33871
|
moved(from, to, source) {
|
|
33724
33872
|
this.renameLog.add(from, to);
|
|
33725
33873
|
for (const holds2 of this.held) holds2.renamed(from, to);
|
|
33726
|
-
if (this.mounts.locate(to) === void 0) this.rootFs.rehold?.(from, to);
|
|
33727
33874
|
if (source) return;
|
|
33728
33875
|
for (const nodes of this.openFiles) nodes.renamed(from, to);
|
|
33729
33876
|
this.watchers.moved(from, to);
|