@ai-ecoverse/slicc-kernel 1.166.5 → 1.167.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7489,7 +7489,7 @@ var init_version = __esm({
7489
7489
  "src/version.ts"() {
7490
7490
  "use strict";
7491
7491
  init_captured_globals();
7492
- KERNEL_VERSION = true ? "1.166.5" : "0.0.0-dev";
7492
+ KERNEL_VERSION = true ? "1.167.1" : "0.0.0-dev";
7493
7493
  OS_RELEASE = "6.0.0-slicc";
7494
7494
  }
7495
7495
  });
@@ -7488,7 +7488,7 @@ var init_version = __esm({
7488
7488
  "src/version.ts"() {
7489
7489
  "use strict";
7490
7490
  init_captured_globals();
7491
- KERNEL_VERSION = true ? "1.166.5" : "0.0.0-dev";
7491
+ KERNEL_VERSION = true ? "1.167.1" : "0.0.0-dev";
7492
7492
  OS_RELEASE = "6.0.0-slicc";
7493
7493
  }
7494
7494
  });
package/dist/node.js CHANGED
@@ -3684,7 +3684,7 @@ function satisfies(version, range2) {
3684
3684
  }
3685
3685
 
3686
3686
  // src/version.ts
3687
- var KERNEL_VERSION = true ? "1.166.5" : "0.0.0-dev";
3687
+ var KERNEL_VERSION = true ? "1.167.1" : "0.0.0-dev";
3688
3688
  var OS_RELEASE = "6.0.0-slicc";
3689
3689
  function procVersion() {
3690
3690
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -4648,8 +4648,41 @@ var within2 = (path, target) => path === target || target === "/" || path.starts
4648
4648
  var TOUCHED_MAX = 4096;
4649
4649
  var parentOf2 = (path) => path.slice(0, path.lastIndexOf("/")) || "/";
4650
4650
  var PEER_RM_MS = 1e3;
4651
+ var SHARED_ACK_MS = 24 * 60 * 60 * 1e3;
4652
+ var delay = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
4651
4653
  var PEER_RENAME_MS = 1e4;
4652
4654
  var PEER_GATE_MS = PEER_RENAME_MS + 5e3;
4655
+ var SHARED_PREFIX = "shared.";
4656
+ var keptLock = (hidden) => `slicc-kept:${hidden}`;
4657
+ function sharedKept(hidden) {
4658
+ const at = `/${UNLINKED_DIR}/${SHARED_PREFIX}`;
4659
+ return hidden.startsWith(at) && /^[0-9a-f]+$/.test(hidden.slice(at.length));
4660
+ }
4661
+ function holdShared(locks, name2) {
4662
+ if (!locks) return Promise.resolve(async () => void 0);
4663
+ return new Promise((resolve2) => {
4664
+ const settled = locks.request(name2, { mode: "shared" }, () => {
4665
+ const { promise, resolve: done4 } = Promise.withResolvers();
4666
+ resolve2(async () => {
4667
+ done4();
4668
+ await settled.catch(() => void 0);
4669
+ });
4670
+ return promise;
4671
+ });
4672
+ });
4673
+ }
4674
+ async function whenLast(locks, name2, op) {
4675
+ if (!locks) {
4676
+ await op();
4677
+ return true;
4678
+ }
4679
+ let free = false;
4680
+ await locks.request(name2, { mode: "exclusive", ifAvailable: true }, async (lock) => {
4681
+ free = lock !== null;
4682
+ if (free) await op();
4683
+ });
4684
+ return free;
4685
+ }
4653
4686
  var lockName = (instance) => `slicc-unlinked:${instance}`;
4654
4687
  var dirOf = (root) => root === "/" ? `/${UNLINKED_DIR}` : `${root}/${UNLINKED_DIR}`;
4655
4688
  var PathGate = class {
@@ -4965,52 +4998,124 @@ var UnlinkedKeeper = class {
4965
4998
  void peers.ask(tab, { kept: { items: [], paths } }, PEER_RM_MS);
4966
4999
  throw fsError("EBUSY", `${target}: open in another tab that did not answer`);
4967
5000
  }
4968
- const { whole, sends } = await this.setAside(target, asked);
4969
- return { whole, undoing: (op) => this.undoing(op, peers, sends, heard) };
5001
+ const { whole, sends, shared } = await this.setAside(target, asked);
5002
+ return { whole, undoing: (op) => this.undoing(op, peers, sends, heard, shared) };
4970
5003
  }
4971
5004
  async setAside(target, asked) {
4972
5005
  const mine = this.heldWithin(target);
4973
- const taken = /* @__PURE__ */ new Set();
4974
- let whole = false;
5006
+ const tabsOf = /* @__PURE__ */ new Map();
5007
+ for (const { holders } of asked)
5008
+ for (const { path } of holders) tabsOf.set(path, (tabsOf.get(path) ?? 0) + 1);
5009
+ const done4 = /* @__PURE__ */ new Map();
5010
+ const shared = [];
4975
5011
  const sends = [];
4976
5012
  for (const { tab, holders, paths } of asked) {
4977
5013
  const items = [];
4978
5014
  for (const holder of holders) {
4979
- const free = !mine.has(holder.path) && !taken.has(holder.path);
4980
- const hidden = free ? await this.asideFor(holder.path, holder.instance) : void 0;
4981
- if (hidden !== void 0) {
4982
- taken.add(holder.path);
4983
- if (holder.path === target) whole = true;
5015
+ if (!done4.has(holder.path)) {
5016
+ const many = mine.has(holder.path) || (tabsOf.get(holder.path) ?? 0) > 1;
5017
+ done4.set(holder.path, await this.asideOne(holder, many, mine, shared));
4984
5018
  }
4985
- items.push({ path: holder.path, hidden, fid: holder.fid });
5019
+ items.push({ path: holder.path, hidden: done4.get(holder.path), fid: holder.fid });
4986
5020
  }
4987
5021
  sends.push({ tab, items, paths });
4988
5022
  }
4989
- return { whole, sends };
5023
+ return { whole: done4.get(target) !== void 0, sends, shared };
5024
+ }
5025
+ async asideOne(holder, many, mine, shared) {
5026
+ if (!many) return this.asideFor(holder.path, holder.instance);
5027
+ const one = await this.sharedAside(holder.path, mine);
5028
+ if (one) shared.push(one);
5029
+ return one?.hidden;
4990
5030
  }
4991
- async undoing(op, peers, sends, heard) {
5031
+ async sharedAside(path, mine) {
5032
+ const hidden = `${dirOf("/")}/${SHARED_PREFIX}${crypto.randomUUID().replaceAll("-", "")}`;
5033
+ const release = await holdShared(this.sharedLocks(), keptLock(hidden));
5034
+ const moved2 = await this.serial(async () => {
5035
+ try {
5036
+ const owner = this.dirOwner;
5037
+ await this.fs.mkdir(dirOf("/"), { recursive: true, ...owner ? { owner } : {} });
5038
+ await this.fs.rename(path, hidden);
5039
+ return true;
5040
+ } catch {
5041
+ return false;
5042
+ }
5043
+ });
5044
+ if (!moved2) {
5045
+ await release();
5046
+ return void 0;
5047
+ }
5048
+ const local2 = mine.get(path) ?? [];
5049
+ const file = local2.length > 0 ? await this.sharedFile(hidden, local2.length) : void 0;
5050
+ if (file) for (const holder of local2) holder.keep(path, file);
5051
+ return { path, hidden, release, local: local2, file };
5052
+ }
5053
+ async sharedFile(hidden, refs) {
5054
+ const locks = this.sharedLocks();
5055
+ const mine = await holdShared(locks, keptLock(hidden));
5056
+ let left = refs;
5057
+ return {
5058
+ hidden,
5059
+ release: () => {
5060
+ if (--left > 0) return;
5061
+ void mine().then(() => this.dropIfLast(hidden));
5062
+ }
5063
+ };
5064
+ }
5065
+ dropIfLast(hidden) {
5066
+ return this.serial(
5067
+ () => whenLast(this.sharedLocks(), keptLock(hidden), () => this.drop(hidden))
5068
+ );
5069
+ }
5070
+ sharedLocks() {
5071
+ return this.locks;
5072
+ }
5073
+ async undoing(op, peers, sends, heard, shared = []) {
4992
5074
  let failed3;
4993
5075
  let out;
4994
5076
  try {
4995
5077
  out = await op();
4996
5078
  } catch (err) {
4997
5079
  failed3 = err ?? new Error("failed");
4998
- for (const send2 of sends) {
4999
- for (const item of send2.items) {
5000
- const { hidden, path } = item;
5001
- if (hidden !== void 0 && await this.moveBack(hidden, path)) item.hidden = void 0;
5002
- }
5003
- }
5080
+ await this.rollBackAsides(sends, shared);
5004
5081
  }
5082
+ const hiddenShared = new Set(shared.map((one) => one.hidden));
5083
+ const answers2 = sends.map(({ tab, items, paths }) => {
5084
+ const keeps = items.some((item) => item.hidden && hiddenShared.has(item.hidden));
5085
+ return {
5086
+ keeps,
5087
+ told: peers.ask(tab, { kept: { items, paths } }, keeps ? SHARED_ACK_MS : PEER_RM_MS)
5088
+ };
5089
+ });
5005
5090
  await Promise.all(
5006
- sends.map(({ tab, items, paths }, i) => {
5007
- const told = peers.ask(tab, { kept: { items, paths } }, PEER_RM_MS);
5008
- return heard[i] ? told : void 0;
5009
- })
5091
+ answers2.map(({ told }, i) => heard[i] ? Promise.race([told, delay(PEER_RM_MS)]) : void 0)
5010
5092
  );
5093
+ for (const one of shared) {
5094
+ const waits = answers2.filter(
5095
+ ({ keeps }, i) => keeps && sends[i]?.items.some((item) => item.hidden === one.hidden)
5096
+ );
5097
+ const done4 = () => one.release().then(() => this.dropIfLast(one.hidden));
5098
+ void Promise.all(waits.map(({ told }) => told)).then(done4, done4);
5099
+ }
5011
5100
  if (failed3 !== void 0) throw failed3;
5012
5101
  return out;
5013
5102
  }
5103
+ async rollBackAsides(sends, shared) {
5104
+ const back = /* @__PURE__ */ new Map();
5105
+ for (const item of sends.flatMap((send2) => send2.items)) {
5106
+ const { hidden, path } = item;
5107
+ if (hidden === void 0) continue;
5108
+ if (!back.has(hidden)) back.set(hidden, await this.moveBack(hidden, path));
5109
+ if (back.get(hidden)) item.hidden = void 0;
5110
+ }
5111
+ for (const { hidden, path, local: local2, file } of shared) {
5112
+ if (!back.get(hidden) || !file) continue;
5113
+ for (const holder of local2) {
5114
+ holder.unkeep(path, file);
5115
+ file.release();
5116
+ }
5117
+ }
5118
+ }
5014
5119
  moveBack(hidden, path) {
5015
5120
  return this.serial(async () => {
5016
5121
  if (await this.present(path)) return false;
@@ -5119,6 +5224,15 @@ var UnlinkedKeeper = class {
5119
5224
  for (const name2 of names2) {
5120
5225
  const id2 = name2.slice(0, name2.lastIndexOf("."));
5121
5226
  const at = id2.indexOf("~");
5227
+ if (name2.startsWith(SHARED_PREFIX)) {
5228
+ const at2 = `${dir}/${name2}`;
5229
+ await whenLast(
5230
+ this.sharedLocks(),
5231
+ keptLock(at2),
5232
+ () => this.fs.rm(at2, { recursive: true }).catch(() => void 0)
5233
+ );
5234
+ continue;
5235
+ }
5122
5236
  const dead = id2 !== this.instance && (at < 0 ? held !== void 0 && !held.has(lockName(id2)) : owner?.alive(id2.slice(0, at)) === false);
5123
5237
  if (dead) await this.fs.rm(`${dir}/${name2}`, { recursive: true }).catch(() => void 0);
5124
5238
  }
@@ -20273,13 +20387,13 @@ var VfsNode = class {
20273
20387
  this.recount();
20274
20388
  if (!this.orphaned) this.onDirty?.();
20275
20389
  if (this.writeBack !== void 0 || this.orphaned) return;
20276
- const delay = Math.max(WRITEBACK_MS, this.writeBackCost * WRITEBACK_COST_FACTOR);
20390
+ const delay2 = Math.max(WRITEBACK_MS, this.writeBackCost * WRITEBACK_COST_FACTOR);
20277
20391
  this.writeBack = setTimeout(() => {
20278
20392
  this.writeBack = void 0;
20279
20393
  this.serial(() => this.flush()).catch(() => {
20280
20394
  this.failed = true;
20281
20395
  });
20282
- }, delay);
20396
+ }, delay2);
20283
20397
  }
20284
20398
  ensure(need2) {
20285
20399
  const cur = this.data ?? new Uint8Array(0);
@@ -23955,6 +24069,7 @@ var RemoteWatch = class {
23955
24069
  };
23956
24070
  const left = /* @__PURE__ */ new Set([to]);
23957
24071
  const timer = setTimeout(done4, cap);
24072
+ timer.unref?.();
23958
24073
  this.waiting.set(seq2, { left, done: done4 });
23959
24074
  });
23960
24075
  }
@@ -23996,6 +24111,9 @@ var RemoteWatch = class {
23996
24111
  this.keeps?.left(tab);
23997
24112
  this.ackers.delete(tab);
23998
24113
  this.holders.delete(tab);
24114
+ for (const wait2 of [...this.waiting.values()]) {
24115
+ if (wait2.left.delete(tab) && wait2.left.size === 0) wait2.done();
24116
+ }
23999
24117
  }
24000
24118
  }
24001
24119
  this.rebuild();
@@ -25550,9 +25668,9 @@ async function unlocked(name2, op) {
25550
25668
  return await op();
25551
25669
  } catch (err) {
25552
25670
  if (!LOCKED.has(err?.name)) throw err;
25553
- const delay = SYNC_BACKOFF_MS[attempt];
25554
- if (delay === void 0) throw fsError("EBUSY", name2);
25555
- await new Promise((resolve2) => setTimeout(resolve2, delay));
25671
+ const delay2 = SYNC_BACKOFF_MS[attempt];
25672
+ if (delay2 === void 0) throw fsError("EBUSY", name2);
25673
+ await new Promise((resolve2) => setTimeout(resolve2, delay2));
25556
25674
  }
25557
25675
  }
25558
25676
  }
@@ -25563,10 +25681,10 @@ async function openSync(handle) {
25563
25681
  try {
25564
25682
  return await sync.call(handle, { mode: "readwrite-unsafe" });
25565
25683
  } catch (err) {
25566
- const delay = SYNC_BACKOFF_MS[attempt];
25684
+ const delay2 = SYNC_BACKOFF_MS[attempt];
25567
25685
  if (!LOCKED.has(err?.name)) throw err;
25568
- if (delay === void 0) return void 0;
25569
- await new Promise((resolve2) => setTimeout(resolve2, delay));
25686
+ if (delay2 === void 0) return void 0;
25687
+ await new Promise((resolve2) => setTimeout(resolve2, delay2));
25570
25688
  }
25571
25689
  }
25572
25690
  }
@@ -26500,6 +26618,15 @@ var OpfsFs = class {
26500
26618
  }
26501
26619
  async pread(path, offset, length2) {
26502
26620
  return this.reading(path, async (handle) => {
26621
+ const seen = this.glanced(handle);
26622
+ if (seen && length2 > 0 && offset + length2 <= seen.size) {
26623
+ const bytes = await this.io(seen.slice(offset, offset + length2).arrayBuffer()).then(
26624
+ (buffer) => new Uint8Array(buffer),
26625
+ () => void 0
26626
+ );
26627
+ if (bytes?.length === length2) return bytes;
26628
+ this.glances.delete(handle);
26629
+ }
26503
26630
  const file = await this.io(handle.getFile());
26504
26631
  await this.refuseNode(path, file.size === 0);
26505
26632
  return new Uint8Array(await file.slice(offset, offset + length2).arrayBuffer());
@@ -27571,9 +27698,9 @@ var OpfsFs = class {
27571
27698
  if (!failed3) return true;
27572
27699
  const error = failed3.err?.name;
27573
27700
  if (handle.kind !== "file" || !LOCKED.has(error)) return false;
27574
- const delay = SYNC_BACKOFF_MS[attempt];
27575
- if (delay === void 0) throw fsError("EBUSY", name2);
27576
- await new Promise((resolve2) => setTimeout(resolve2, delay));
27701
+ const delay2 = SYNC_BACKOFF_MS[attempt];
27702
+ if (delay2 === void 0) throw fsError("EBUSY", name2);
27703
+ await new Promise((resolve2) => setTimeout(resolve2, delay2));
27577
27704
  }
27578
27705
  }
27579
27706
  async copy(handle, dir, name2, copies, rest2 = "") {
@@ -32679,7 +32806,10 @@ var Launcher = class {
32679
32806
  await Promise.all(mine);
32680
32807
  },
32681
32808
  kept: async (tab, items, paths) => {
32682
- for (const { path, hidden, fid } of items) this.adoptKept(path, hidden, fid, ours);
32809
+ for (const { path, hidden, fid } of items) {
32810
+ if (hidden !== void 0 && sharedKept(hidden)) await this.adoptShared(path, hidden, fid);
32811
+ else this.adoptKept(path, hidden, fid, ours);
32812
+ }
32683
32813
  await open(tab, paths);
32684
32814
  },
32685
32815
  left: (tab) => {
@@ -32688,6 +32818,33 @@ var Launcher = class {
32688
32818
  }
32689
32819
  };
32690
32820
  }
32821
+ async adoptShared(path, hidden, fid) {
32822
+ const bound3 = [...this.held].map(
32823
+ (holds2) => [holds2, [...holds2.boundAt(path, fid), ...holds2.boundAt(hidden, fid)]]
32824
+ );
32825
+ const keeping = bound3.filter(([, ids]) => ids.length > 0);
32826
+ const nodes = [...this.openFiles].filter(
32827
+ (open) => [path, hidden].some((at) => open.holdsAt(at))
32828
+ );
32829
+ const refs = keeping.length + nodes.length;
32830
+ if (refs === 0) {
32831
+ this.held.doubt([path]);
32832
+ return;
32833
+ }
32834
+ const file = await this.unlinked.sharedFile(hidden, refs);
32835
+ if (!await this.rootFs.lstat(hidden).then(
32836
+ () => true,
32837
+ () => false
32838
+ )) {
32839
+ for (let i = 0; i < refs; i++) file.release();
32840
+ this.held.doubt([path]);
32841
+ return;
32842
+ }
32843
+ const kept = nodes.filter((open) => open.keepBound([hidden, path], fid, file)).length;
32844
+ for (let i = kept; i < nodes.length; i++) file.release();
32845
+ for (const [holds2, ids] of keeping) holds2.keepBound(ids, path, file);
32846
+ void this.rootFs.announceHolds?.([], [path, hidden], false);
32847
+ }
32691
32848
  adoptKept(path, hidden, fid, ours) {
32692
32849
  if (hidden === void 0 || !ours(hidden)) {
32693
32850
  this.held.doubt([path]);
@@ -32830,7 +32987,6 @@ var Launcher = class {
32830
32987
  moved(from, to, source) {
32831
32988
  this.renameLog.add(from, to);
32832
32989
  for (const holds2 of this.held) holds2.renamed(from, to);
32833
- if (this.mounts.locate(to) === void 0) this.rootFs.rehold?.(from, to);
32834
32990
  if (source) return;
32835
32991
  for (const nodes of this.openFiles) nodes.renamed(from, to);
32836
32992
  this.watchers.moved(from, to);