@ai-ecoverse/slicc-kernel 1.142.0 → 1.142.2
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 +15 -2
- package/dist/index.js.map +1 -1
- package/dist/kernel-worker.js +504 -108
- package/dist/kernel-worker.js.map +4 -4
- package/dist/meta.js +3 -0
- package/dist/meta.js.map +2 -2
- package/dist/node-process-worker.js +13 -2
- package/dist/node-process-worker.js.map +2 -2
- package/dist/node.js +501 -108
- package/dist/node.js.map +4 -4
- package/dist/process-worker.js +13 -2
- package/dist/process-worker.js.map +2 -2
- package/dist/types/fs/meta.d.ts +2 -0
- package/dist/types/fs/opfs.d.ts +33 -0
- package/dist/types/fs/remote.d.ts +15 -0
- package/dist/types/fs/types.d.ts +7 -0
- package/dist/types/kernel/proc-info.d.ts +7 -0
- package/package.json +5 -5
package/dist/node.js
CHANGED
|
@@ -3624,6 +3624,90 @@ function serveClient(port, host) {
|
|
|
3624
3624
|
return { detach, closed: ended.promise };
|
|
3625
3625
|
}
|
|
3626
3626
|
|
|
3627
|
+
// src/fs/changes.ts
|
|
3628
|
+
var GEN = 0;
|
|
3629
|
+
var RING = 1;
|
|
3630
|
+
var RING_SIZE = 4096;
|
|
3631
|
+
var SLOT = 2;
|
|
3632
|
+
var SHARED_TTL_MS = 100;
|
|
3633
|
+
var DIRTY = RING + RING_SIZE * SLOT;
|
|
3634
|
+
var FOREIGN = DIRTY + 1;
|
|
3635
|
+
var CHANGES_BYTES = (FOREIGN + 1) * 4;
|
|
3636
|
+
function changeHash(path) {
|
|
3637
|
+
let h = 2166136261;
|
|
3638
|
+
for (let i = 0; i < path.length; i++) {
|
|
3639
|
+
h ^= path.charCodeAt(i);
|
|
3640
|
+
h = Math.imul(h, 16777619);
|
|
3641
|
+
}
|
|
3642
|
+
return h === 0 ? 1 : h;
|
|
3643
|
+
}
|
|
3644
|
+
function normal(path) {
|
|
3645
|
+
const parts2 = [];
|
|
3646
|
+
for (const part of path.split("/")) {
|
|
3647
|
+
if (part === "" || part === ".") continue;
|
|
3648
|
+
if (part === "..") parts2.pop();
|
|
3649
|
+
else parts2.push(part);
|
|
3650
|
+
}
|
|
3651
|
+
return `/${parts2.join("/")}`;
|
|
3652
|
+
}
|
|
3653
|
+
var FileChanges = class {
|
|
3654
|
+
sab;
|
|
3655
|
+
view;
|
|
3656
|
+
constructor(sab = new SharedArrayBuffer(CHANGES_BYTES)) {
|
|
3657
|
+
this.sab = sab;
|
|
3658
|
+
this.view = new Int32Array(sab);
|
|
3659
|
+
}
|
|
3660
|
+
dirtied(delta) {
|
|
3661
|
+
Atomics.add(this.view, DIRTY, delta);
|
|
3662
|
+
}
|
|
3663
|
+
foreign(on) {
|
|
3664
|
+
Atomics.store(this.view, FOREIGN, on ? 1 : 0);
|
|
3665
|
+
}
|
|
3666
|
+
flush() {
|
|
3667
|
+
Atomics.add(this.view, GEN, RING_SIZE + 1);
|
|
3668
|
+
}
|
|
3669
|
+
publish(...paths) {
|
|
3670
|
+
for (const path of paths) {
|
|
3671
|
+
const g = Atomics.add(this.view, GEN, 1) + 1 | 0;
|
|
3672
|
+
const at = RING + (g & RING_SIZE - 1) * SLOT;
|
|
3673
|
+
Atomics.store(this.view, at, 0);
|
|
3674
|
+
Atomics.store(this.view, at + 1, changeHash(normal(path)));
|
|
3675
|
+
Atomics.store(this.view, at, g);
|
|
3676
|
+
}
|
|
3677
|
+
}
|
|
3678
|
+
};
|
|
3679
|
+
var ChangeView = class {
|
|
3680
|
+
view;
|
|
3681
|
+
constructor(sab) {
|
|
3682
|
+
this.view = new Int32Array(sab);
|
|
3683
|
+
}
|
|
3684
|
+
now() {
|
|
3685
|
+
return Atomics.load(this.view, GEN);
|
|
3686
|
+
}
|
|
3687
|
+
clean() {
|
|
3688
|
+
return this.view.length > DIRTY && Atomics.load(this.view, DIRTY) === 0;
|
|
3689
|
+
}
|
|
3690
|
+
foreign() {
|
|
3691
|
+
return this.view.length > FOREIGN && Atomics.load(this.view, FOREIGN) === 1;
|
|
3692
|
+
}
|
|
3693
|
+
changedSince(seen, path) {
|
|
3694
|
+
const now = Atomics.load(this.view, GEN);
|
|
3695
|
+
const distance = now - seen >>> 0;
|
|
3696
|
+
if (distance === 0) return { now, changed: false };
|
|
3697
|
+
if (distance > RING_SIZE) return { now, changed: true };
|
|
3698
|
+
const hash = changeHash(normal(path));
|
|
3699
|
+
for (let i = 1; i <= distance; i++) {
|
|
3700
|
+
const g = seen + i | 0;
|
|
3701
|
+
const at = RING + (g & RING_SIZE - 1) * SLOT;
|
|
3702
|
+
if (Atomics.load(this.view, at) !== g) return { now, changed: true };
|
|
3703
|
+
const hit = Atomics.load(this.view, at + 1) === hash;
|
|
3704
|
+
if (Atomics.load(this.view, at) !== g) return { now, changed: true };
|
|
3705
|
+
if (hit) return { now, changed: true };
|
|
3706
|
+
}
|
|
3707
|
+
return { now, changed: false };
|
|
3708
|
+
}
|
|
3709
|
+
};
|
|
3710
|
+
|
|
3627
3711
|
// src/fs/path-map.ts
|
|
3628
3712
|
function parentOf2(path) {
|
|
3629
3713
|
if (path === "/" || path === "") return void 0;
|
|
@@ -4158,6 +4242,8 @@ var ANNOUNCE_WAIT_MS = 500;
|
|
|
4158
4242
|
var PRUNE_EVERY_MS = 3e4;
|
|
4159
4243
|
var MOURN_TRIES = 5;
|
|
4160
4244
|
var MOURN_RETRY_MS = 100;
|
|
4245
|
+
var RENAME_ACK_MAX_MS = 1e4;
|
|
4246
|
+
var ANNOUNCE_POLL_MS = 20;
|
|
4161
4247
|
function lockManager() {
|
|
4162
4248
|
return globalThis.navigator?.locks;
|
|
4163
4249
|
}
|
|
@@ -4181,6 +4267,9 @@ var RemoteWatch = class {
|
|
|
4181
4267
|
quiet;
|
|
4182
4268
|
crowd;
|
|
4183
4269
|
gone;
|
|
4270
|
+
renaming;
|
|
4271
|
+
renamed;
|
|
4272
|
+
ackers = /* @__PURE__ */ new Set();
|
|
4184
4273
|
told;
|
|
4185
4274
|
counted = 0;
|
|
4186
4275
|
recount() {
|
|
@@ -4208,7 +4297,7 @@ var RemoteWatch = class {
|
|
|
4208
4297
|
this.settled = true;
|
|
4209
4298
|
this.recount();
|
|
4210
4299
|
});
|
|
4211
|
-
this.channel.postMessage({ hello: this.tab });
|
|
4300
|
+
this.channel.postMessage({ hello: this.tab, renames: true });
|
|
4212
4301
|
}
|
|
4213
4302
|
async join() {
|
|
4214
4303
|
if (!this.locks) return;
|
|
@@ -4229,6 +4318,20 @@ var RemoteWatch = class {
|
|
|
4229
4318
|
await this.joined;
|
|
4230
4319
|
return this.peers.size > 0;
|
|
4231
4320
|
}
|
|
4321
|
+
async joinedAll(cap) {
|
|
4322
|
+
if (!this.locks) return true;
|
|
4323
|
+
const prefix = `${this.name}:`;
|
|
4324
|
+
const began = performance.now();
|
|
4325
|
+
for (; ; ) {
|
|
4326
|
+
const held = ((await this.locks.query()).held ?? []).map((lock) => lock.name ?? "");
|
|
4327
|
+
const silent = held.some(
|
|
4328
|
+
(name2) => name2.startsWith(prefix) && name2 !== this.lockOf(this.tab) && !this.peers.has(name2.slice(prefix.length))
|
|
4329
|
+
);
|
|
4330
|
+
if (!silent) return true;
|
|
4331
|
+
if (performance.now() - began >= cap) return false;
|
|
4332
|
+
await new Promise((resolve2) => setTimeout(resolve2, ANNOUNCE_POLL_MS));
|
|
4333
|
+
}
|
|
4334
|
+
}
|
|
4232
4335
|
crowded() {
|
|
4233
4336
|
return !this.settled || this.peers.size > 0;
|
|
4234
4337
|
}
|
|
@@ -4236,7 +4339,11 @@ var RemoteWatch = class {
|
|
|
4236
4339
|
return `${this.name}:${tab}`;
|
|
4237
4340
|
}
|
|
4238
4341
|
receive(data) {
|
|
4342
|
+
const sender = data.hello ?? data.here;
|
|
4343
|
+
if (sender !== void 0 && data.renames) this.ackers.add(sender);
|
|
4239
4344
|
if (data.hello !== void 0) this.greeted(data.hello);
|
|
4345
|
+
if (data.renaming !== void 0 && data.tab !== void 0) this.heard(data);
|
|
4346
|
+
if (data.renamed !== void 0) this.renamed?.(data.renamed);
|
|
4240
4347
|
if (data.here !== void 0 && data.to === this.tab) {
|
|
4241
4348
|
this.arrived(data.here);
|
|
4242
4349
|
this.met?.();
|
|
@@ -4268,6 +4375,7 @@ var RemoteWatch = class {
|
|
|
4268
4375
|
this.mourned.delete(peer);
|
|
4269
4376
|
this.others.delete(peer);
|
|
4270
4377
|
this.peers.delete(peer);
|
|
4378
|
+
this.ackers.delete(peer);
|
|
4271
4379
|
this.rebuild();
|
|
4272
4380
|
this.recount();
|
|
4273
4381
|
this.gone?.();
|
|
@@ -4279,12 +4387,18 @@ var RemoteWatch = class {
|
|
|
4279
4387
|
greeted(peer) {
|
|
4280
4388
|
this.arrived(peer);
|
|
4281
4389
|
const answer2 = () => {
|
|
4282
|
-
this.channel.postMessage({ here: this.tab, to: peer });
|
|
4390
|
+
this.channel.postMessage({ here: this.tab, to: peer, renames: true });
|
|
4283
4391
|
if (this.mine.length > 0) void this.announce(this.mine);
|
|
4284
4392
|
};
|
|
4285
4393
|
if (this.quiet) void this.quiet().then(answer2, answer2);
|
|
4286
4394
|
else answer2();
|
|
4287
4395
|
}
|
|
4396
|
+
heard({ tab, renaming, seq: seq2 }) {
|
|
4397
|
+
const ack = () => this.channel.postMessage({ ack: seq2, from: this.tab, to: tab });
|
|
4398
|
+
const heard = this.renaming?.(renaming);
|
|
4399
|
+
if (heard !== void 0) void heard.then(ack, ack);
|
|
4400
|
+
else ack();
|
|
4401
|
+
}
|
|
4288
4402
|
announced({ tab, paths, seq: seq2 }) {
|
|
4289
4403
|
const from = tab;
|
|
4290
4404
|
this.arrived(from);
|
|
@@ -4311,6 +4425,7 @@ var RemoteWatch = class {
|
|
|
4311
4425
|
if (!held.has(this.lockOf(tab))) {
|
|
4312
4426
|
if (this.peers.delete(tab)) left = true;
|
|
4313
4427
|
this.others.delete(tab);
|
|
4428
|
+
this.ackers.delete(tab);
|
|
4314
4429
|
}
|
|
4315
4430
|
}
|
|
4316
4431
|
this.rebuild();
|
|
@@ -4332,7 +4447,34 @@ var RemoteWatch = class {
|
|
|
4332
4447
|
this.mine = [...paths];
|
|
4333
4448
|
const seq2 = ++this.seq;
|
|
4334
4449
|
this.channel.postMessage({ tab: this.tab, paths: this.mine, seq: seq2 });
|
|
4335
|
-
|
|
4450
|
+
return this.acks(seq2, this.peers);
|
|
4451
|
+
}
|
|
4452
|
+
renamingTree(rename, cap = RENAME_ACK_MAX_MS) {
|
|
4453
|
+
const seq2 = ++this.seq;
|
|
4454
|
+
this.channel.postMessage({ tab: this.tab, renaming: rename, seq: seq2 });
|
|
4455
|
+
const left = new Set(this.ackers);
|
|
4456
|
+
if (left.size === 0) return Promise.resolve([]);
|
|
4457
|
+
const began = performance.now();
|
|
4458
|
+
return new Promise((resolve2) => {
|
|
4459
|
+
const done4 = () => {
|
|
4460
|
+
clearInterval(timer);
|
|
4461
|
+
this.waiting.delete(seq2);
|
|
4462
|
+
resolve2([...left]);
|
|
4463
|
+
};
|
|
4464
|
+
const timer = setInterval(() => {
|
|
4465
|
+
void this.prune().then(() => {
|
|
4466
|
+
for (const peer of left) if (!this.ackers.has(peer)) left.delete(peer);
|
|
4467
|
+
if (left.size === 0 || performance.now() - began >= cap) done4();
|
|
4468
|
+
});
|
|
4469
|
+
}, ANNOUNCE_WAIT_MS);
|
|
4470
|
+
this.waiting.set(seq2, { left, done: done4 });
|
|
4471
|
+
});
|
|
4472
|
+
}
|
|
4473
|
+
renamedTree(lock) {
|
|
4474
|
+
this.channel.postMessage({ renamed: lock });
|
|
4475
|
+
}
|
|
4476
|
+
acks(seq2, from) {
|
|
4477
|
+
if (from.size === 0) return Promise.resolve();
|
|
4336
4478
|
return new Promise((resolve2) => {
|
|
4337
4479
|
const done4 = () => {
|
|
4338
4480
|
clearTimeout(timer);
|
|
@@ -4343,7 +4485,7 @@ var RemoteWatch = class {
|
|
|
4343
4485
|
done4();
|
|
4344
4486
|
void this.prune();
|
|
4345
4487
|
}, ANNOUNCE_WAIT_MS);
|
|
4346
|
-
this.waiting.set(seq2, { left: new Set(
|
|
4488
|
+
this.waiting.set(seq2, { left: new Set(from), done: done4 });
|
|
4347
4489
|
});
|
|
4348
4490
|
}
|
|
4349
4491
|
emit(change) {
|
|
@@ -4406,6 +4548,14 @@ var RECONCILE_LISTINGS = 8;
|
|
|
4406
4548
|
var EXECUTABLE = /\/node_modules\/(?:@[^/]+\/)?[^/]+\/bin\//;
|
|
4407
4549
|
var RENAMES = "/.slicc-renames";
|
|
4408
4550
|
var RENAME_LOCK = "slicc-rename:";
|
|
4551
|
+
var RENAME_ADMIT = "slicc-rename-admit:";
|
|
4552
|
+
var escapeRoot = (name2) => name2.replace(/[%:]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
|
|
4553
|
+
var LEGACY_RENAME_LOCK = /^slicc-rename:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
4554
|
+
var PAIRED = /* @__PURE__ */ new Set(["rename", "link", "copyFile"]);
|
|
4555
|
+
var LISTINGS = /* @__PURE__ */ new Set(["readdir", "readdirStat"]);
|
|
4556
|
+
var RETRY = /* @__PURE__ */ Symbol("retry");
|
|
4557
|
+
var ACK_SAMPLES = 4096;
|
|
4558
|
+
var INTENT_POLL_MS = 5;
|
|
4409
4559
|
function movable(handle) {
|
|
4410
4560
|
return typeof handle.move === "function";
|
|
4411
4561
|
}
|
|
@@ -4450,6 +4600,7 @@ function sidecar(meta) {
|
|
|
4450
4600
|
for (const { path, change } of changes) await ops.update(path, change);
|
|
4451
4601
|
};
|
|
4452
4602
|
if (meta.absent) ops.absent = meta.absent.bind(meta);
|
|
4603
|
+
if (meta.forgetTrees) ops.forgetTrees = meta.forgetTrees.bind(meta);
|
|
4453
4604
|
const { removeFile } = meta;
|
|
4454
4605
|
if (removeFile)
|
|
4455
4606
|
ops.removeFile = (path) => removeFile.call(meta, path).catch((err) => {
|
|
@@ -4560,6 +4711,7 @@ var OpfsFs = class {
|
|
|
4560
4711
|
locks;
|
|
4561
4712
|
lockPrefix;
|
|
4562
4713
|
rootName;
|
|
4714
|
+
renamePrefix;
|
|
4563
4715
|
constructor(root, meta = new MemoryMeta(), channel, options = {}) {
|
|
4564
4716
|
this.root = root;
|
|
4565
4717
|
this.meta = sidecar(meta);
|
|
@@ -4567,11 +4719,22 @@ var OpfsFs = class {
|
|
|
4567
4719
|
this.locks = options.locks === void 0 ? lockManager() : options.locks ?? void 0;
|
|
4568
4720
|
this.lockPrefix = `slicc-excl:${channel ?? ""}:`;
|
|
4569
4721
|
this.rootName = channel;
|
|
4722
|
+
this.renamePrefix = `${RENAME_LOCK}${escapeRoot(channel ?? "")}:`;
|
|
4570
4723
|
this.channel = channel === void 0 ? void 0 : new BroadcastChannel(channel);
|
|
4571
4724
|
this.remote = channel === void 0 ? void 0 : new RemoteWatch(`${channel}:watch`, { locks: this.locks ?? null });
|
|
4572
4725
|
if (this.remote) {
|
|
4573
4726
|
this.remote.quiet = () => this.quiet().then(() => this.settle?.());
|
|
4574
|
-
this.remote.gone = () =>
|
|
4727
|
+
this.remote.gone = () => {
|
|
4728
|
+
void this.orphans();
|
|
4729
|
+
for (const move of [...this.peerMoves.values()]) void this.peerMoved(move);
|
|
4730
|
+
};
|
|
4731
|
+
this.remote.renaming = (rename) => this.heardRename(rename);
|
|
4732
|
+
this.remote.renamed = (lock) => {
|
|
4733
|
+
const move = this.peerMoves.get(lock);
|
|
4734
|
+
if (!move) return;
|
|
4735
|
+
move.done = true;
|
|
4736
|
+
void this.peerMoved(move);
|
|
4737
|
+
};
|
|
4575
4738
|
}
|
|
4576
4739
|
if (this.channel) {
|
|
4577
4740
|
const remote = this.remote;
|
|
@@ -5615,16 +5778,27 @@ var OpfsFs = class {
|
|
|
5615
5778
|
throw fsError("EPERM", `${from}: this file system has no hard links`);
|
|
5616
5779
|
}
|
|
5617
5780
|
async rename(from, to) {
|
|
5781
|
+
const call = this.renameCall;
|
|
5782
|
+
this.renameCall = void 0;
|
|
5618
5783
|
if (from === to) return;
|
|
5784
|
+
for (; ; ) {
|
|
5785
|
+
try {
|
|
5786
|
+
return await this.renameOnce(from, to, call);
|
|
5787
|
+
} catch (err) {
|
|
5788
|
+
if (err !== RETRY) throw err;
|
|
5789
|
+
}
|
|
5790
|
+
}
|
|
5791
|
+
}
|
|
5792
|
+
async renameOnce(from, to, call) {
|
|
5619
5793
|
const source = await this.locate(from, false);
|
|
5620
5794
|
this.refuse(source.path, true);
|
|
5621
5795
|
this.forget(source.path);
|
|
5622
5796
|
const parent = await this.locate(parentOf4(to), true);
|
|
5623
5797
|
const destination = resolvePath(parent.path, baseOf(to));
|
|
5624
5798
|
this.refuse(destination, true);
|
|
5625
|
-
await this.entering(destination, () => this.moveTo(source, parent, destination, to));
|
|
5799
|
+
await this.entering(destination, () => this.moveTo(source, parent, destination, to, call));
|
|
5626
5800
|
}
|
|
5627
|
-
async moveTo(source, parent, destination, to) {
|
|
5801
|
+
async moveTo(source, parent, destination, to, call) {
|
|
5628
5802
|
const sourceStat = await this.describe(source);
|
|
5629
5803
|
if (sourceStat.isDirectory && within3(destination, source.path)) throw fsError("EINVAL", to);
|
|
5630
5804
|
const target = await this.exactly(() => this.locate(destination, false)).catch((err) => {
|
|
@@ -5659,6 +5833,7 @@ var OpfsFs = class {
|
|
|
5659
5833
|
const name2 = baseOf(destination);
|
|
5660
5834
|
const swap = targetStat?.isDirectory === true;
|
|
5661
5835
|
let lock;
|
|
5836
|
+
const hooks = {};
|
|
5662
5837
|
const staging = swap ? `.${name2}.${crypto.randomUUID()}` : name2;
|
|
5663
5838
|
const copying = sourceStat.isDirectory && !movable(source.handle);
|
|
5664
5839
|
const staged = resolvePath(parent.path, staging);
|
|
@@ -5667,8 +5842,15 @@ var OpfsFs = class {
|
|
|
5667
5842
|
const copies = /* @__PURE__ */ new Map();
|
|
5668
5843
|
const root = { ino: inodeOf(source.path), ...moving };
|
|
5669
5844
|
const owned4 = lock ? { lock } : {};
|
|
5845
|
+
hooks.notify?.();
|
|
5670
5846
|
const first = copying ? await this.intend({ from: source.path, to: staged, root, ...owned4 }) : void 0;
|
|
5671
5847
|
const second = copying && swap ? await this.intend({ from: staged, to: destination, replace: true, root, ...owned4 }) : void 0;
|
|
5848
|
+
await hooks.started?.().catch(async (err) => {
|
|
5849
|
+
for (const intent of [first, second]) {
|
|
5850
|
+
if (intent) await this.meta.update(intent, () => void 0);
|
|
5851
|
+
}
|
|
5852
|
+
throw err;
|
|
5853
|
+
});
|
|
5672
5854
|
const moved2 = await this.replacingTarget(
|
|
5673
5855
|
targetStat !== null,
|
|
5674
5856
|
() => this.place(source.handle, dir, staging, copies)
|
|
@@ -5702,14 +5884,270 @@ var OpfsFs = class {
|
|
|
5702
5884
|
try {
|
|
5703
5885
|
const locks = this.locks;
|
|
5704
5886
|
if (locks) {
|
|
5705
|
-
lock = `${
|
|
5706
|
-
|
|
5887
|
+
lock = `${this.renameLocks()}${crypto.randomUUID()}`;
|
|
5888
|
+
this.ownLocks.add(lock);
|
|
5889
|
+
call?.release();
|
|
5890
|
+
await this.admitted(locks, lock, source.path, destination, place, hooks);
|
|
5707
5891
|
} else await place();
|
|
5708
5892
|
} finally {
|
|
5893
|
+
if (lock) this.ownLocks.delete(lock);
|
|
5709
5894
|
this.renamingDirs.delete(entry);
|
|
5710
5895
|
resolve2();
|
|
5711
5896
|
}
|
|
5712
5897
|
}
|
|
5898
|
+
async admitted(locks, lock, from, to, place, hooks) {
|
|
5899
|
+
const remote = this.remote;
|
|
5900
|
+
if (remote && !this.shared() && !await remote.joinedAll(RENAME_ACK_MAX_MS)) {
|
|
5901
|
+
this.ackBusy++;
|
|
5902
|
+
console.warn(
|
|
5903
|
+
`slicc-kernel: renaming ${from} to ${to} gave up (EBUSY): a tab sharing the root did not finish joining in ${RENAME_ACK_MAX_MS} ms (#1140)`
|
|
5904
|
+
);
|
|
5905
|
+
throw fsError("EBUSY", from);
|
|
5906
|
+
}
|
|
5907
|
+
if (!remote || !this.shared()) {
|
|
5908
|
+
await locks.request(lock, place);
|
|
5909
|
+
return;
|
|
5910
|
+
}
|
|
5911
|
+
let clash;
|
|
5912
|
+
let run2;
|
|
5913
|
+
await locks.request(`${RENAME_ADMIT}${this.rootName ?? ""}`, async () => {
|
|
5914
|
+
if (await this.renamingElsewhere()) await this.learnRenames();
|
|
5915
|
+
clash = this.clashing(from, to);
|
|
5916
|
+
if (clash) return;
|
|
5917
|
+
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
5918
|
+
let told;
|
|
5919
|
+
hooks.notify = () => {
|
|
5920
|
+
told = remote.renamingTree({ from, to, lock });
|
|
5921
|
+
};
|
|
5922
|
+
hooks.started = async () => {
|
|
5923
|
+
resolve2();
|
|
5924
|
+
this.renameAcks++;
|
|
5925
|
+
const at = performance.now();
|
|
5926
|
+
const stuck = await told;
|
|
5927
|
+
this.ackMs.push(performance.now() - at);
|
|
5928
|
+
if (this.ackMs.length > ACK_SAMPLES) this.ackMs.shift();
|
|
5929
|
+
if (stuck.length === 0) return;
|
|
5930
|
+
this.ackBusy++;
|
|
5931
|
+
console.warn(
|
|
5932
|
+
`slicc-kernel: renaming ${from} to ${to} gave up (EBUSY): peer tab ${stuck.join(", ")} is alive but did not answer in ${RENAME_ACK_MAX_MS} ms (#1140)`
|
|
5933
|
+
);
|
|
5934
|
+
throw fsError("EBUSY", from);
|
|
5935
|
+
};
|
|
5936
|
+
run2 = locks.request(lock, async () => {
|
|
5937
|
+
await place();
|
|
5938
|
+
remote.renamedTree(lock);
|
|
5939
|
+
});
|
|
5940
|
+
await Promise.race([promise, run2.then(nothing, nothing)]);
|
|
5941
|
+
});
|
|
5942
|
+
if (clash) {
|
|
5943
|
+
this.peerWaited++;
|
|
5944
|
+
await this.peerMoved(clash);
|
|
5945
|
+
throw RETRY;
|
|
5946
|
+
}
|
|
5947
|
+
await run2;
|
|
5948
|
+
}
|
|
5949
|
+
renameAcks = 0;
|
|
5950
|
+
ackBusy = 0;
|
|
5951
|
+
ackMs = [];
|
|
5952
|
+
ownLocks = /* @__PURE__ */ new Set();
|
|
5953
|
+
peerMoves = /* @__PURE__ */ new Map();
|
|
5954
|
+
peerWaits = /* @__PURE__ */ new Map();
|
|
5955
|
+
inflight = /* @__PURE__ */ new Set();
|
|
5956
|
+
renameCall;
|
|
5957
|
+
looking;
|
|
5958
|
+
lookedAt = Number.NEGATIVE_INFINITY;
|
|
5959
|
+
peerWaited = 0;
|
|
5960
|
+
queries = 0;
|
|
5961
|
+
renameWaits() {
|
|
5962
|
+
return {
|
|
5963
|
+
acks: this.renameAcks,
|
|
5964
|
+
busy: this.ackBusy,
|
|
5965
|
+
waits: this.peerWaited,
|
|
5966
|
+
queries: this.queries,
|
|
5967
|
+
ackMs: this.ackMs
|
|
5968
|
+
};
|
|
5969
|
+
}
|
|
5970
|
+
notePeer(lock, tree2) {
|
|
5971
|
+
let known = this.peerMoves.get(lock);
|
|
5972
|
+
if (!known) {
|
|
5973
|
+
known = { lock, trees: [] };
|
|
5974
|
+
this.peerMoves.set(lock, known);
|
|
5975
|
+
}
|
|
5976
|
+
if (!known.trees.some(([a, b]) => a === tree2[0] && b === tree2[1])) known.trees.push(tree2);
|
|
5977
|
+
return known;
|
|
5978
|
+
}
|
|
5979
|
+
renameLocks() {
|
|
5980
|
+
return this.renamePrefix;
|
|
5981
|
+
}
|
|
5982
|
+
renameHere(name2) {
|
|
5983
|
+
if (name2 === void 0) return false;
|
|
5984
|
+
return name2.startsWith(this.renameLocks()) || LEGACY_RENAME_LOCK.test(name2);
|
|
5985
|
+
}
|
|
5986
|
+
async learnRenames() {
|
|
5987
|
+
for (const { rename } of await this.meta.under(RENAMES)) {
|
|
5988
|
+
if (rename?.lock === void 0 || this.ownLocks.has(rename.lock)) continue;
|
|
5989
|
+
this.notePeer(rename.lock, [rename.from, rename.to]);
|
|
5990
|
+
}
|
|
5991
|
+
}
|
|
5992
|
+
async renamingElsewhere() {
|
|
5993
|
+
const { held = [] } = await this.locks.query();
|
|
5994
|
+
return held.some(({ name: name2 }) => this.renameHere(name2) && !this.ownLocks.has(name2));
|
|
5995
|
+
}
|
|
5996
|
+
lookForRenames() {
|
|
5997
|
+
const locks = this.locks;
|
|
5998
|
+
const age = performance.now() - this.lookedAt;
|
|
5999
|
+
if (!locks || age < SHARED_TTL_MS / 2) return Promise.resolve();
|
|
6000
|
+
this.looking ??= (async () => {
|
|
6001
|
+
for (; ; ) {
|
|
6002
|
+
const asked = performance.now();
|
|
6003
|
+
this.queries++;
|
|
6004
|
+
const { held = [] } = await locks.query();
|
|
6005
|
+
const unknown = () => held.some(
|
|
6006
|
+
({ name: name2 }) => this.renameHere(name2) && !this.ownLocks.has(name2) && !this.peerMoves.has(name2)
|
|
6007
|
+
);
|
|
6008
|
+
if (unknown()) await this.learnRenames();
|
|
6009
|
+
if (!unknown()) {
|
|
6010
|
+
this.lookedAt = asked;
|
|
6011
|
+
return;
|
|
6012
|
+
}
|
|
6013
|
+
await new Promise((resolve2) => setTimeout(resolve2, INTENT_POLL_MS));
|
|
6014
|
+
}
|
|
6015
|
+
})().finally(() => {
|
|
6016
|
+
this.looking = void 0;
|
|
6017
|
+
});
|
|
6018
|
+
if (age >= SHARED_TTL_MS) return this.looking;
|
|
6019
|
+
this.looking.catch(nothing);
|
|
6020
|
+
return Promise.resolve();
|
|
6021
|
+
}
|
|
6022
|
+
async heardRename({ from, to, lock }) {
|
|
6023
|
+
if (this.ownLocks.has(lock)) return;
|
|
6024
|
+
this.notePeer(lock, [from, to]);
|
|
6025
|
+
this.lookedAt = performance.now();
|
|
6026
|
+
const trees = [[from, to]];
|
|
6027
|
+
const running = [...this.inflight];
|
|
6028
|
+
const reached = await Promise.all(
|
|
6029
|
+
running.map(async (op) => {
|
|
6030
|
+
if (op.paths.some((at) => touches(at, trees))) return true;
|
|
6031
|
+
for (const at of op.paths) {
|
|
6032
|
+
const forms = await this.resolvedForms(at);
|
|
6033
|
+
if (forms.some((form) => touches(form, trees))) return true;
|
|
6034
|
+
}
|
|
6035
|
+
return false;
|
|
6036
|
+
})
|
|
6037
|
+
);
|
|
6038
|
+
const busy = running.filter((op, i) => reached[i] && this.inflight.has(op));
|
|
6039
|
+
if (this.aloneCalls > 0) {
|
|
6040
|
+
this.aloneDrain ??= Promise.withResolvers();
|
|
6041
|
+
busy.push({ paths: [], waiting: this.aloneDrain, release: nothing });
|
|
6042
|
+
}
|
|
6043
|
+
await Promise.all(
|
|
6044
|
+
busy.map((op) => {
|
|
6045
|
+
op.waiting ??= Promise.withResolvers();
|
|
6046
|
+
return op.waiting.promise;
|
|
6047
|
+
})
|
|
6048
|
+
);
|
|
6049
|
+
}
|
|
6050
|
+
peerAt(at, listing) {
|
|
6051
|
+
for (const move of this.peerMoves.values()) {
|
|
6052
|
+
if (this.ownLocks.has(move.lock)) continue;
|
|
6053
|
+
if (touches(at, move.trees, listing)) return move;
|
|
6054
|
+
}
|
|
6055
|
+
return void 0;
|
|
6056
|
+
}
|
|
6057
|
+
clashing(from, to) {
|
|
6058
|
+
for (const move of this.peerMoves.values()) {
|
|
6059
|
+
for (const tree2 of move.trees) {
|
|
6060
|
+
for (const mine of [from, to]) {
|
|
6061
|
+
if (tree2.some((theirs) => within3(mine, theirs) || within3(theirs, mine))) return move;
|
|
6062
|
+
}
|
|
6063
|
+
}
|
|
6064
|
+
}
|
|
6065
|
+
return void 0;
|
|
6066
|
+
}
|
|
6067
|
+
peerMoved(move) {
|
|
6068
|
+
const locks = this.locks;
|
|
6069
|
+
let wait2 = this.peerWaits.get(move.lock);
|
|
6070
|
+
if (wait2 !== void 0) return wait2;
|
|
6071
|
+
wait2 = (async () => {
|
|
6072
|
+
if (!move.done)
|
|
6073
|
+
await locks.request(move.lock, async () => {
|
|
6074
|
+
if (move.done) return;
|
|
6075
|
+
const left = (await this.meta.under(RENAMES)).filter((entry) => entry.rename?.lock === move.lock).sort(byIntent);
|
|
6076
|
+
for (const entry of left) await this.finishRename(entry);
|
|
6077
|
+
});
|
|
6078
|
+
this.peerMoves.delete(move.lock);
|
|
6079
|
+
for (const [from, to] of move.trees) {
|
|
6080
|
+
this.forget(from);
|
|
6081
|
+
this.forget(to);
|
|
6082
|
+
this.meta.forgetTrees?.([from, to]);
|
|
6083
|
+
}
|
|
6084
|
+
})().finally(() => this.peerWaits.delete(move.lock));
|
|
6085
|
+
this.peerWaits.set(move.lock, wait2);
|
|
6086
|
+
return wait2;
|
|
6087
|
+
}
|
|
6088
|
+
async peerSettled(at, listing) {
|
|
6089
|
+
await this.lookForRenames();
|
|
6090
|
+
for (let reals; ; ) {
|
|
6091
|
+
const forms = [at, ...reals ?? []];
|
|
6092
|
+
const move = forms.map((form) => this.peerAt(form, listing)).find(Boolean);
|
|
6093
|
+
if (move) {
|
|
6094
|
+
this.peerWaited++;
|
|
6095
|
+
await this.peerMoved(move);
|
|
6096
|
+
continue;
|
|
6097
|
+
}
|
|
6098
|
+
if (reals !== void 0 || at === "/" || this.peerMoves.size === 0) return forms;
|
|
6099
|
+
reals = await this.resolvedForms(at);
|
|
6100
|
+
if (reals.length === 0) return forms;
|
|
6101
|
+
}
|
|
6102
|
+
}
|
|
6103
|
+
aloneCalls = 0;
|
|
6104
|
+
aloneDrain;
|
|
6105
|
+
async alonePlain(inner, args) {
|
|
6106
|
+
this.aloneCalls++;
|
|
6107
|
+
try {
|
|
6108
|
+
return await inner.apply(this, args);
|
|
6109
|
+
} finally {
|
|
6110
|
+
this.aloneCalls--;
|
|
6111
|
+
if (this.aloneCalls === 0 && this.aloneDrain) {
|
|
6112
|
+
this.aloneDrain.resolve();
|
|
6113
|
+
this.aloneDrain = void 0;
|
|
6114
|
+
}
|
|
6115
|
+
}
|
|
6116
|
+
}
|
|
6117
|
+
async resolvedForms(at) {
|
|
6118
|
+
if (at === "/") return [];
|
|
6119
|
+
const parent = await PLAIN.realpath.call(this, parentOf4(at), true).catch(() => parentOf4(at));
|
|
6120
|
+
const named = resolvePath(parent, baseOf(at));
|
|
6121
|
+
const target = await PLAIN.realpath.call(this, at, true).catch(() => named);
|
|
6122
|
+
return [.../* @__PURE__ */ new Set([named, target])].filter((form) => form !== at);
|
|
6123
|
+
}
|
|
6124
|
+
amongPeers() {
|
|
6125
|
+
return this.remote !== void 0 && this.locks !== void 0 && this.shared();
|
|
6126
|
+
}
|
|
6127
|
+
async peerOp(name2, args, inner) {
|
|
6128
|
+
const paths = (name2 === "symlink" ? args.slice(1, 2) : PAIRED.has(name2) ? args.slice(0, 2) : args.slice(0, 1)).filter((path) => typeof path === "string").map(normalizePath);
|
|
6129
|
+
const listing = LISTINGS.has(name2);
|
|
6130
|
+
const checked = [...paths];
|
|
6131
|
+
while (this.amongPeers()) {
|
|
6132
|
+
checked.length = 0;
|
|
6133
|
+
for (const at of paths) checked.push(...await this.peerSettled(at, listing));
|
|
6134
|
+
if (!checked.some((at) => this.peerAt(at, listing))) break;
|
|
6135
|
+
}
|
|
6136
|
+
const busy = { paths: checked, release: () => void 0 };
|
|
6137
|
+
const done4 = () => {
|
|
6138
|
+
this.inflight.delete(busy);
|
|
6139
|
+
busy.waiting?.resolve();
|
|
6140
|
+
};
|
|
6141
|
+
busy.release = done4;
|
|
6142
|
+
this.inflight.add(busy);
|
|
6143
|
+
if (name2 === "rename") this.renameCall = busy;
|
|
6144
|
+
if (name2 !== "writeSession") return await inner.apply(this, args).finally(done4);
|
|
6145
|
+
const session = await inner.apply(this, args).catch((err) => {
|
|
6146
|
+
done4();
|
|
6147
|
+
throw err;
|
|
6148
|
+
});
|
|
6149
|
+
return { ...session, close: () => session.close().finally(done4) };
|
|
6150
|
+
}
|
|
5713
6151
|
renamingDirs = /* @__PURE__ */ new Set();
|
|
5714
6152
|
intents = 0;
|
|
5715
6153
|
async intend(rename, at = `${RENAMES}/${crypto.randomUUID()}`) {
|
|
@@ -5755,7 +6193,7 @@ var OpfsFs = class {
|
|
|
5755
6193
|
);
|
|
5756
6194
|
for (const entry of intents) {
|
|
5757
6195
|
const lock = entry.rename.lock;
|
|
5758
|
-
if (!
|
|
6196
|
+
if (!locks || !lock) await this.finishRename(entry);
|
|
5759
6197
|
else await locks.request(lock, () => this.finishRename(entry));
|
|
5760
6198
|
}
|
|
5761
6199
|
return intents.length;
|
|
@@ -5771,7 +6209,8 @@ var OpfsFs = class {
|
|
|
5771
6209
|
this.forget(to);
|
|
5772
6210
|
try {
|
|
5773
6211
|
const left = await this.real(from);
|
|
5774
|
-
if (left && replace && await this.real(to))
|
|
6212
|
+
if (left && replace && await this.real(to))
|
|
6213
|
+
await PLAIN.rm.call(this, to, { recursive: true });
|
|
5775
6214
|
if (left) {
|
|
5776
6215
|
const source = await this.locate(from, false);
|
|
5777
6216
|
const target = await this.locate(parentOf4(to), true);
|
|
@@ -5785,7 +6224,7 @@ var OpfsFs = class {
|
|
|
5785
6224
|
this.forget(from);
|
|
5786
6225
|
this.forget(to);
|
|
5787
6226
|
}
|
|
5788
|
-
if ((await this.meta.under(from)).
|
|
6227
|
+
if ((await this.meta.under(from)).some((entry2) => !entry2.vacated)) {
|
|
5789
6228
|
await this.meta.move(
|
|
5790
6229
|
from,
|
|
5791
6230
|
to,
|
|
@@ -6116,6 +6555,21 @@ var OpfsFs = class {
|
|
|
6116
6555
|
return removed;
|
|
6117
6556
|
}
|
|
6118
6557
|
};
|
|
6558
|
+
function nothing() {
|
|
6559
|
+
return void 0;
|
|
6560
|
+
}
|
|
6561
|
+
function touches(at, trees, listing = true) {
|
|
6562
|
+
return trees.some(
|
|
6563
|
+
([from, to]) => within3(at, from) || within3(at, to) || listing && (at === parentOf4(from) || at === parentOf4(to))
|
|
6564
|
+
);
|
|
6565
|
+
}
|
|
6566
|
+
function byIntent(a, b) {
|
|
6567
|
+
return a.rename.at - b.rename.at;
|
|
6568
|
+
}
|
|
6569
|
+
var PLAIN = {
|
|
6570
|
+
rm: OpfsFs.prototype.rm,
|
|
6571
|
+
realpath: OpfsFs.prototype.realpath
|
|
6572
|
+
};
|
|
6119
6573
|
var READS = [
|
|
6120
6574
|
"stat",
|
|
6121
6575
|
"lstat",
|
|
@@ -6146,6 +6600,14 @@ var WRITES = [
|
|
|
6146
6600
|
"lutimes",
|
|
6147
6601
|
"chown"
|
|
6148
6602
|
];
|
|
6603
|
+
{
|
|
6604
|
+
const proto = OpfsFs.prototype;
|
|
6605
|
+
const inner = proto.createExclusive;
|
|
6606
|
+
proto.createExclusive = function(...args) {
|
|
6607
|
+
if (this.amongPeers()) return this.peerOp("createExclusive", args, inner);
|
|
6608
|
+
return this.alonePlain(inner, args);
|
|
6609
|
+
};
|
|
6610
|
+
}
|
|
6149
6611
|
for (const [names2, op] of [
|
|
6150
6612
|
[READS, "read"],
|
|
6151
6613
|
[WRITES, "write"]
|
|
@@ -6156,7 +6618,9 @@ for (const [names2, op] of [
|
|
|
6156
6618
|
proto[name2] = async function(...args) {
|
|
6157
6619
|
try {
|
|
6158
6620
|
if (op === "read") await this.settledRename(args[0]);
|
|
6159
|
-
|
|
6621
|
+
if (this.amongPeers() || name2 === "writeSession")
|
|
6622
|
+
return await this.peerOp(name2, args, inner);
|
|
6623
|
+
return await this.alonePlain(inner, args);
|
|
6160
6624
|
} catch (err) {
|
|
6161
6625
|
throw translate(err, String(args[0]), op, false);
|
|
6162
6626
|
}
|
|
@@ -7515,7 +7979,7 @@ function satisfies(version, range2) {
|
|
|
7515
7979
|
}
|
|
7516
7980
|
|
|
7517
7981
|
// src/version.ts
|
|
7518
|
-
var KERNEL_VERSION = true ? "1.142.
|
|
7982
|
+
var KERNEL_VERSION = true ? "1.142.2" : "0.0.0-dev";
|
|
7519
7983
|
var OS_RELEASE = "6.0.0-slicc";
|
|
7520
7984
|
function procVersion() {
|
|
7521
7985
|
return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
|
|
@@ -9514,89 +9978,6 @@ var FileWatches = class {
|
|
|
9514
9978
|
}
|
|
9515
9979
|
};
|
|
9516
9980
|
|
|
9517
|
-
// src/fs/changes.ts
|
|
9518
|
-
var GEN = 0;
|
|
9519
|
-
var RING = 1;
|
|
9520
|
-
var RING_SIZE = 4096;
|
|
9521
|
-
var SLOT = 2;
|
|
9522
|
-
var DIRTY = RING + RING_SIZE * SLOT;
|
|
9523
|
-
var FOREIGN = DIRTY + 1;
|
|
9524
|
-
var CHANGES_BYTES = (FOREIGN + 1) * 4;
|
|
9525
|
-
function changeHash(path) {
|
|
9526
|
-
let h = 2166136261;
|
|
9527
|
-
for (let i = 0; i < path.length; i++) {
|
|
9528
|
-
h ^= path.charCodeAt(i);
|
|
9529
|
-
h = Math.imul(h, 16777619);
|
|
9530
|
-
}
|
|
9531
|
-
return h === 0 ? 1 : h;
|
|
9532
|
-
}
|
|
9533
|
-
function normal(path) {
|
|
9534
|
-
const parts2 = [];
|
|
9535
|
-
for (const part of path.split("/")) {
|
|
9536
|
-
if (part === "" || part === ".") continue;
|
|
9537
|
-
if (part === "..") parts2.pop();
|
|
9538
|
-
else parts2.push(part);
|
|
9539
|
-
}
|
|
9540
|
-
return `/${parts2.join("/")}`;
|
|
9541
|
-
}
|
|
9542
|
-
var FileChanges = class {
|
|
9543
|
-
sab;
|
|
9544
|
-
view;
|
|
9545
|
-
constructor(sab = new SharedArrayBuffer(CHANGES_BYTES)) {
|
|
9546
|
-
this.sab = sab;
|
|
9547
|
-
this.view = new Int32Array(sab);
|
|
9548
|
-
}
|
|
9549
|
-
dirtied(delta) {
|
|
9550
|
-
Atomics.add(this.view, DIRTY, delta);
|
|
9551
|
-
}
|
|
9552
|
-
foreign(on) {
|
|
9553
|
-
Atomics.store(this.view, FOREIGN, on ? 1 : 0);
|
|
9554
|
-
}
|
|
9555
|
-
flush() {
|
|
9556
|
-
Atomics.add(this.view, GEN, RING_SIZE + 1);
|
|
9557
|
-
}
|
|
9558
|
-
publish(...paths) {
|
|
9559
|
-
for (const path of paths) {
|
|
9560
|
-
const g = Atomics.add(this.view, GEN, 1) + 1 | 0;
|
|
9561
|
-
const at = RING + (g & RING_SIZE - 1) * SLOT;
|
|
9562
|
-
Atomics.store(this.view, at, 0);
|
|
9563
|
-
Atomics.store(this.view, at + 1, changeHash(normal(path)));
|
|
9564
|
-
Atomics.store(this.view, at, g);
|
|
9565
|
-
}
|
|
9566
|
-
}
|
|
9567
|
-
};
|
|
9568
|
-
var ChangeView = class {
|
|
9569
|
-
view;
|
|
9570
|
-
constructor(sab) {
|
|
9571
|
-
this.view = new Int32Array(sab);
|
|
9572
|
-
}
|
|
9573
|
-
now() {
|
|
9574
|
-
return Atomics.load(this.view, GEN);
|
|
9575
|
-
}
|
|
9576
|
-
clean() {
|
|
9577
|
-
return this.view.length > DIRTY && Atomics.load(this.view, DIRTY) === 0;
|
|
9578
|
-
}
|
|
9579
|
-
foreign() {
|
|
9580
|
-
return this.view.length > FOREIGN && Atomics.load(this.view, FOREIGN) === 1;
|
|
9581
|
-
}
|
|
9582
|
-
changedSince(seen, path) {
|
|
9583
|
-
const now = Atomics.load(this.view, GEN);
|
|
9584
|
-
const distance = now - seen >>> 0;
|
|
9585
|
-
if (distance === 0) return { now, changed: false };
|
|
9586
|
-
if (distance > RING_SIZE) return { now, changed: true };
|
|
9587
|
-
const hash = changeHash(normal(path));
|
|
9588
|
-
for (let i = 1; i <= distance; i++) {
|
|
9589
|
-
const g = seen + i | 0;
|
|
9590
|
-
const at = RING + (g & RING_SIZE - 1) * SLOT;
|
|
9591
|
-
if (Atomics.load(this.view, at) !== g) return { now, changed: true };
|
|
9592
|
-
const hit = Atomics.load(this.view, at + 1) === hash;
|
|
9593
|
-
if (Atomics.load(this.view, at) !== g) return { now, changed: true };
|
|
9594
|
-
if (hit) return { now, changed: true };
|
|
9595
|
-
}
|
|
9596
|
-
return { now, changed: false };
|
|
9597
|
-
}
|
|
9598
|
-
};
|
|
9599
|
-
|
|
9600
9981
|
// src/fs/commands.ts
|
|
9601
9982
|
var S_IFDIR2 = 16384;
|
|
9602
9983
|
var S_IFREG2 = 32768;
|
|
@@ -10025,10 +10406,10 @@ var FreshModules = class {
|
|
|
10025
10406
|
const ranged2 = rangedOps(fs);
|
|
10026
10407
|
if (ranged2) {
|
|
10027
10408
|
overrides.pwrite = async (path, at, bytes, transfer) => {
|
|
10028
|
-
const
|
|
10409
|
+
const touches3 = at < MAGIC.length && this.fresh.has(normalizePath(path));
|
|
10029
10410
|
const first = at === 0 && bytes.length >= MAGIC.length ? bytes.slice(0, MAGIC.length) : void 0;
|
|
10030
10411
|
await ranged2.pwrite(path, at, bytes, transfer);
|
|
10031
|
-
if (
|
|
10412
|
+
if (touches3) await decide(path, first);
|
|
10032
10413
|
};
|
|
10033
10414
|
overrides.truncate = async (path, size) => {
|
|
10034
10415
|
await ranged2.truncate(path, size);
|
|
@@ -10105,7 +10486,7 @@ var baseOf3 = (path) => path.slice(path.lastIndexOf("/") + 1);
|
|
|
10105
10486
|
var WATCH_BATCH_LIMIT = 1e3;
|
|
10106
10487
|
var under3 = (path, dir) => dir === "/" || path.startsWith(`${dir}/`);
|
|
10107
10488
|
var parentOf7 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
|
|
10108
|
-
function
|
|
10489
|
+
function touches2(watcher, changed) {
|
|
10109
10490
|
return watcher.paths.some(
|
|
10110
10491
|
(watched) => changed === watched || under3(watched, changed) || (watcher.recursive ? under3(changed, watched) : parentOf7(changed) === watched)
|
|
10111
10492
|
);
|
|
@@ -10233,7 +10614,7 @@ var FsWatchers = class {
|
|
|
10233
10614
|
for (const watcher of this.watchers) {
|
|
10234
10615
|
for (const path of paths) {
|
|
10235
10616
|
const changed = normalizePath(path);
|
|
10236
|
-
if (
|
|
10617
|
+
if (touches2(watcher, changed)) watcher.pending.add(changed);
|
|
10237
10618
|
}
|
|
10238
10619
|
if (watcher.pending.size === 0 || watcher.scheduled) continue;
|
|
10239
10620
|
watcher.scheduled = true;
|
|
@@ -13898,7 +14279,18 @@ var SYS_TREE = {
|
|
|
13898
14279
|
slicc_opfs_ops: (listing) => `${listing.opfsOps ?? 0}
|
|
13899
14280
|
`,
|
|
13900
14281
|
slicc_cwd_checks: (listing) => `${listing.cwdChecks ?? 0}
|
|
13901
|
-
|
|
14282
|
+
`,
|
|
14283
|
+
slicc_rename_ack_busy: (listing) => `${listing.renameAcks?.busy ?? 0}
|
|
14284
|
+
`,
|
|
14285
|
+
slicc_rename_acks: (listing) => {
|
|
14286
|
+
const samples = [...listing.renameAcks?.ackMs ?? []].sort((a, b) => a - b);
|
|
14287
|
+
const median = samples[Math.floor(samples.length / 2)] ?? 0;
|
|
14288
|
+
const most = samples.at(-1) ?? 0;
|
|
14289
|
+
const waits = listing.renameAcks?.waits ?? 0;
|
|
14290
|
+
const queries = listing.renameAcks?.queries ?? 0;
|
|
14291
|
+
return `${listing.renameAcks?.acks ?? 0} ${median.toFixed(1)} ${most.toFixed(1)} ${waits} ${queries}
|
|
14292
|
+
`;
|
|
14293
|
+
}
|
|
13902
14294
|
}
|
|
13903
14295
|
};
|
|
13904
14296
|
function isSysFile(at) {
|
|
@@ -19570,7 +19962,7 @@ function sniffPg(start2) {
|
|
|
19570
19962
|
const length2 = int32(bytes, 0);
|
|
19571
19963
|
return length2 >= 8 && length2 <= PG_MESSAGE_MAX && int32(bytes, 4) === PROTOCOL_3 ? "yes" : "no";
|
|
19572
19964
|
}
|
|
19573
|
-
var
|
|
19965
|
+
var PLAIN2 = "SCRAM-SHA-256";
|
|
19574
19966
|
var PLUS = "SCRAM-SHA-256-PLUS";
|
|
19575
19967
|
var END_POINT = "p=tls-server-end-point,,";
|
|
19576
19968
|
var SASL = 10;
|
|
@@ -19692,7 +20084,7 @@ function pgLength(bytes, started) {
|
|
|
19692
20084
|
const length2 = int32(bytes, started ? 1 : 0);
|
|
19693
20085
|
return started ? 1 + length2 : length2;
|
|
19694
20086
|
}
|
|
19695
|
-
var MECHANISMS = /* @__PURE__ */ new Set([
|
|
20087
|
+
var MECHANISMS = /* @__PURE__ */ new Set([PLAIN2, PLUS]);
|
|
19696
20088
|
async function cleartext(message3, asks) {
|
|
19697
20089
|
const body = latin2(message3.subarray(5));
|
|
19698
20090
|
if (!body.endsWith("\0") || body.indexOf("\0") !== body.length - 1)
|
|
@@ -19725,7 +20117,7 @@ function serverHeader(header5, server) {
|
|
|
19725
20117
|
function rewritten(first, header5) {
|
|
19726
20118
|
const parsed2 = clientFirstOf(first.data);
|
|
19727
20119
|
if (!parsed2 || parsed2.header === header5) return first;
|
|
19728
|
-
return { mechanism: header5 === END_POINT ? PLUS :
|
|
20120
|
+
return { mechanism: header5 === END_POINT ? PLUS : PLAIN2, data: `${header5}${parsed2.bare}` };
|
|
19729
20121
|
}
|
|
19730
20122
|
var PgClient = class {
|
|
19731
20123
|
clientFirst;
|
|
@@ -27415,7 +27807,7 @@ var RULE = new RegExp(
|
|
|
27415
27807
|
String.raw`^(NOPASSWD\s+)?(\S+)\s+(?:\(([^()\s]+)\)\s+)?(?:Cwd\s+(${WORD})\s+)?Cmnd(?:\s+(.*))?$`
|
|
27416
27808
|
);
|
|
27417
27809
|
var TERM = /^[A-Za-z0-9._+-]+$/;
|
|
27418
|
-
var
|
|
27810
|
+
var PLAIN3 = /^[A-Za-z0-9_@%+=:,./-]+$/;
|
|
27419
27811
|
var USAGE = "usage: sudo [-n] [-u user] [--] command [args...]\n sudo -l";
|
|
27420
27812
|
function failed2(errno3, error) {
|
|
27421
27813
|
return { error, errno: errno3 };
|
|
@@ -27442,7 +27834,7 @@ function splitWords(text) {
|
|
|
27442
27834
|
return words2;
|
|
27443
27835
|
}
|
|
27444
27836
|
function quoteWord(word) {
|
|
27445
|
-
return
|
|
27837
|
+
return PLAIN3.test(word) ? word : `'${word.replaceAll("'", `'\\''`)}'`;
|
|
27446
27838
|
}
|
|
27447
27839
|
function validWho(who) {
|
|
27448
27840
|
if (who === "ALL") return true;
|
|
@@ -29251,7 +29643,8 @@ var Launcher = class {
|
|
|
29251
29643
|
fsCalls: servedFsCalls(),
|
|
29252
29644
|
opfsCalls: this.rootFs.opfsCalls?.() ?? 0,
|
|
29253
29645
|
opfsOps: this.rootFs.opfsOps?.() ?? 0,
|
|
29254
|
-
cwdChecks: this.cwds.checks
|
|
29646
|
+
cwdChecks: this.cwds.checks,
|
|
29647
|
+
renameAcks: this.rootFs.renameWaits?.()
|
|
29255
29648
|
}),
|
|
29256
29649
|
sudo: (call, signal) => this.sudo(pid, call, signal),
|
|
29257
29650
|
crontab: (call) => this.crontab(pid, call),
|