@ai-ecoverse/slicc-kernel 1.94.0 → 1.94.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/dist/node.js CHANGED
@@ -4591,6 +4591,7 @@ var OpfsFs = class {
4591
4591
  this.touch(now, parent.path, made2);
4592
4592
  }
4593
4593
  async mkdirExcl(path, owner) {
4594
+ if (normalizePath(path) === "/") throw fsError("EEXIST", path);
4594
4595
  const parent = await this.locate(parentOf4(path), true);
4595
4596
  if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
4596
4597
  const dir = parent.handle;
@@ -7152,6 +7153,47 @@ var FileWatches = class {
7152
7153
  }
7153
7154
  };
7154
7155
 
7156
+ // src/fs/changes.ts
7157
+ var GEN = 0;
7158
+ var RING = 1;
7159
+ var RING_SIZE = 4096;
7160
+ var SLOT = 2;
7161
+ var CHANGES_BYTES = (RING + RING_SIZE * SLOT) * 4;
7162
+ function changeHash(path) {
7163
+ let h = 2166136261;
7164
+ for (let i = 0; i < path.length; i++) {
7165
+ h ^= path.charCodeAt(i);
7166
+ h = Math.imul(h, 16777619);
7167
+ }
7168
+ return h === 0 ? 1 : h;
7169
+ }
7170
+ function normal(path) {
7171
+ const parts2 = [];
7172
+ for (const part of path.split("/")) {
7173
+ if (part === "" || part === ".") continue;
7174
+ if (part === "..") parts2.pop();
7175
+ else parts2.push(part);
7176
+ }
7177
+ return `/${parts2.join("/")}`;
7178
+ }
7179
+ var FileChanges = class {
7180
+ sab;
7181
+ view;
7182
+ constructor(sab = new SharedArrayBuffer(CHANGES_BYTES)) {
7183
+ this.sab = sab;
7184
+ this.view = new Int32Array(sab);
7185
+ }
7186
+ publish(...paths) {
7187
+ for (const path of paths) {
7188
+ const g = Atomics.add(this.view, GEN, 1) + 1 | 0;
7189
+ const at = RING + (g & RING_SIZE - 1) * SLOT;
7190
+ Atomics.store(this.view, at, 0);
7191
+ Atomics.store(this.view, at + 1, changeHash(normal(path)));
7192
+ Atomics.store(this.view, at, g);
7193
+ }
7194
+ }
7195
+ };
7196
+
7155
7197
  // src/fs/commands.ts
7156
7198
  var S_IFDIR2 = 16384;
7157
7199
  var S_IFREG2 = 32768;
@@ -7469,6 +7511,10 @@ function touches(watcher, changed) {
7469
7511
  }
7470
7512
  var FsWatchers = class {
7471
7513
  watchers = /* @__PURE__ */ new Set();
7514
+ taps = [];
7515
+ tap(listener) {
7516
+ this.taps.push(listener);
7517
+ }
7472
7518
  watch(paths, options, notify) {
7473
7519
  const watcher = {
7474
7520
  paths: paths.map(normalizePath),
@@ -7483,6 +7529,7 @@ var FsWatchers = class {
7483
7529
  };
7484
7530
  }
7485
7531
  changed(...paths) {
7532
+ for (const tap of this.taps) tap(paths);
7486
7533
  for (const watcher of this.watchers) {
7487
7534
  for (const path of paths) {
7488
7535
  const changed = normalizePath(path);
@@ -9446,6 +9493,7 @@ var SYNC_FS_OPS = [
9446
9493
  "kept",
9447
9494
  "pread",
9448
9495
  "pwrite",
9496
+ "append",
9449
9497
  "truncate",
9450
9498
  "chown",
9451
9499
  "lchown",
@@ -9641,6 +9689,8 @@ async function run(entry, path, req) {
9641
9689
  case "pwrite":
9642
9690
  case "truncate":
9643
9691
  return ranged(fs, path, req);
9692
+ case "append":
9693
+ return json2(await appended(fs, path, req.body ?? new Uint8Array(0)));
9644
9694
  default:
9645
9695
  return { ok: false, errno: "EINVAL", message: `sync-fs: unknown op '${req.op}'` };
9646
9696
  }
@@ -9733,6 +9783,7 @@ async function guard(g, path, req, cwd) {
9733
9783
  if (req.handle === void 0) await readable(g, op, path);
9734
9784
  return { path: await walkSafe(g, path, true) };
9735
9785
  case "pwrite":
9786
+ case "append":
9736
9787
  case "truncate":
9737
9788
  if (req.handle === void 0) await fileWritable(g, op, path);
9738
9789
  return { path: await walkSafe(g, path, true) };
@@ -9793,7 +9844,7 @@ var CHANGING = /* @__PURE__ */ new Set([
9793
9844
  "chown",
9794
9845
  "lchown"
9795
9846
  ]);
9796
- var CONTENT = /* @__PURE__ */ new Set(["write", "pwrite", "truncate"]);
9847
+ var CONTENT = /* @__PURE__ */ new Set(["write", "pwrite", "append", "truncate"]);
9797
9848
  var REMOVING = /* @__PURE__ */ new Set(["unlink", "rmdir", "rm", "rename"]);
9798
9849
  async function mayChange(entry, path, req) {
9799
9850
  const { mayChange: mayChange2 } = entry.fs;
@@ -9831,6 +9882,30 @@ async function createExclusive(fs, path, owner) {
9831
9882
  throw syncError("EEXIST", path);
9832
9883
  await fs.writeFile(path, new Uint8Array(0), owner);
9833
9884
  }
9885
+ var appending = /* @__PURE__ */ new Map();
9886
+ async function appended(fs, path, body) {
9887
+ const key = await fs.realpath?.(path, true).catch(() => void 0) ?? path;
9888
+ const before = appending.get(key) ?? Promise.resolve();
9889
+ const run2 = before.then(async () => {
9890
+ if (fs.append) return fs.append(path, body);
9891
+ const size = (await fs.stat(path)).size;
9892
+ const ops = rangedOps(fs);
9893
+ if (ops) await ops.pwrite(path, size, body, true);
9894
+ else {
9895
+ const whole = new Uint8Array(size + body.length);
9896
+ whole.set(await fs.readFileBuffer(path));
9897
+ whole.set(body, size);
9898
+ await fs.writeFile(path, whole);
9899
+ }
9900
+ return size + body.length;
9901
+ });
9902
+ const settled = run2.catch(() => void 0);
9903
+ appending.set(key, settled);
9904
+ void settled.then(() => {
9905
+ if (appending.get(key) === settled) appending.delete(key);
9906
+ });
9907
+ return run2;
9908
+ }
9834
9909
  async function ranged(fs, path, req) {
9835
9910
  const ops = rangedOps(fs);
9836
9911
  if (!ops) throw syncError("ENOSYS", path);
@@ -9846,7 +9921,7 @@ async function ranged(fs, path, req) {
9846
9921
  return done;
9847
9922
  }
9848
9923
  var CHOWN_OPS = /* @__PURE__ */ new Set(["chown", "lchown"]);
9849
- var UNLINKED_OPS = /* @__PURE__ */ new Set(["read", "pread", "pwrite", "truncate"]);
9924
+ var UNLINKED_OPS = /* @__PURE__ */ new Set(["read", "pread", "pwrite", "append", "truncate"]);
9850
9925
  var OWN_OPS = /* @__PURE__ */ new Set(["rm", "unlink", "rmdir", "rename", "link"]);
9851
9926
  var TWO_PATHS = /* @__PURE__ */ new Set(["rename", "link"]);
9852
9927
  var UNLINKING_OPS = /* @__PURE__ */ new Set(["rm", "unlink", "rename"]);
@@ -10443,6 +10518,13 @@ var Pages = class {
10443
10518
  this.length = size;
10444
10519
  this.stored = size;
10445
10520
  }
10521
+ refresh(size) {
10522
+ if (this.pinned) return;
10523
+ for (const page of [...this.pages.keys()]) if (!this.dirty.has(page)) this.drop(page);
10524
+ const resized2 = this.length !== this.stored || this.shrink !== void 0;
10525
+ if (this.shrink === void 0) this.stored = size;
10526
+ this.length = resized2 ? Math.max(this.length, this.stored) : size;
10527
+ }
10446
10528
  evict() {
10447
10529
  if (this.pinned) return;
10448
10530
  let clean = (this.pages.size - this.dirty.size) * PAGE;
@@ -10542,7 +10624,7 @@ function mountTable(mounts = []) {
10542
10624
  }
10543
10625
 
10544
10626
  // src/version.ts
10545
- var KERNEL_VERSION = true ? "1.94.0" : "0.0.0-dev";
10627
+ var KERNEL_VERSION = true ? "1.94.2" : "0.0.0-dev";
10546
10628
  var OS_RELEASE = "6.0.0-slicc";
10547
10629
  function procVersion() {
10548
10630
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -10744,10 +10826,10 @@ function normalize(path) {
10744
10826
  }
10745
10827
  return `/${out.join("/")}`;
10746
10828
  }
10747
- var RING = 8;
10748
- var RING_SIZE = 64;
10749
- var SLOT = 3;
10750
- var SHARED_IDS_BYTES = (RING + RING_SIZE * SLOT) * 4;
10829
+ var RING2 = 8;
10830
+ var RING_SIZE2 = 64;
10831
+ var SLOT2 = 3;
10832
+ var SHARED_IDS_BYTES = (RING2 + RING_SIZE2 * SLOT2) * 4;
10751
10833
 
10752
10834
  // src/process/wasi/wasi-procfs.ts
10753
10835
  var DIR_MODE = 16749;
@@ -13395,6 +13477,7 @@ var VfsNode = class {
13395
13477
  path;
13396
13478
  orphaned;
13397
13479
  id;
13480
+ onDirty;
13398
13481
  constructor(fs, path, contents2, orphaned = false, dirty = false, pin) {
13399
13482
  this.fs = fs;
13400
13483
  this.pin = pin;
@@ -13544,6 +13627,7 @@ var VfsNode = class {
13544
13627
  }
13545
13628
  markDirty() {
13546
13629
  this.dirty = true;
13630
+ if (!this.orphaned) this.onDirty?.();
13547
13631
  if (this.writeBack !== void 0 || this.orphaned) return;
13548
13632
  const delay = Math.max(WRITEBACK_MS, this.writeBackCost * WRITEBACK_COST_FACTOR);
13549
13633
  this.writeBack = setTimeout(() => {
@@ -13579,6 +13663,7 @@ var VfsNodes = class {
13579
13663
  kept = /* @__PURE__ */ new Map();
13580
13664
  byId = /* @__PURE__ */ new Map();
13581
13665
  keepsOnDisk = false;
13666
+ changed;
13582
13667
  fs;
13583
13668
  entries;
13584
13669
  onClosed;
@@ -13669,12 +13754,18 @@ var VfsNodes = class {
13669
13754
  if (node.path === path) node.renamedTo(others[0]);
13670
13755
  return true;
13671
13756
  }
13757
+ holding(path) {
13758
+ if (this.byPath.size === 0) return void 0;
13759
+ const node = this.byPath.get(path);
13760
+ return node && !node.orphaned ? node : void 0;
13761
+ }
13672
13762
  named(path, id2) {
13673
13763
  const node = this.byPath.get(path) ?? (id2 === void 0 ? void 0 : this.byId.get(id2));
13674
13764
  if (node && !this.byPath.has(path)) this.byPath.set(path, node);
13675
13765
  return node;
13676
13766
  }
13677
13767
  create(path, id2, node) {
13768
+ node.onDirty = () => this.changed?.(node.path);
13678
13769
  this.byPath.set(path, node);
13679
13770
  if (id2 !== void 0) this.know(node, id2);
13680
13771
  return node;
@@ -13815,9 +13906,73 @@ async function refuseReadonly(fs, path, flags2, opts = {}) {
13815
13906
  const st = own ?? await stat(await targetDir(fs, path));
13816
13907
  if (st?.readonly) throw new KernelError("EROFS");
13817
13908
  }
13818
- function keepingOpen(fs, nodes) {
13909
+ function heldIo(fs, nodes, changed) {
13910
+ const ranged2 = rangedOps(fs);
13911
+ const node = (path) => nodes.holding(fs.resolvePath("/", path));
13912
+ const write = async (path, op, fallback) => {
13913
+ const held = node(path);
13914
+ if (!held) return fallback();
13915
+ const out = await held.serial(async () => {
13916
+ const done4 = await op(held);
13917
+ await held.flush();
13918
+ return done4;
13919
+ });
13920
+ changed(fs.resolvePath("/", path));
13921
+ return out;
13922
+ };
13923
+ return {
13924
+ append: (path, bytes) => write(
13925
+ path,
13926
+ async (held) => {
13927
+ const at = await held.size();
13928
+ await held.pwrite(bytes, at);
13929
+ return at + bytes.length;
13930
+ },
13931
+ async () => {
13932
+ const at = (await fs.stat(path)).size;
13933
+ if (ranged2) await ranged2.pwrite(path, at, bytes, true);
13934
+ else {
13935
+ const whole = new Uint8Array(at + bytes.length);
13936
+ whole.set(await fs.readFileBuffer(path));
13937
+ whole.set(bytes, at);
13938
+ await fs.writeFile(path, whole);
13939
+ }
13940
+ return at + bytes.length;
13941
+ }
13942
+ ),
13943
+ async stat(path) {
13944
+ const st = await fs.stat(path);
13945
+ const held = st.isFile ? node(path) : void 0;
13946
+ return held ? { ...st, size: await held.serial(() => held.size()) } : st;
13947
+ },
13948
+ async readFileBuffer(path) {
13949
+ const held = node(path);
13950
+ if (!held) return fs.readFileBuffer(path);
13951
+ return held.serial(async () => held.pread(await held.size(), 0));
13952
+ },
13953
+ ...ranged2 ? {
13954
+ pread: (path, at, n, version) => {
13955
+ const held = node(path);
13956
+ return held ? held.serial(() => held.pread(n, at)) : ranged2.pread(path, at, n, version);
13957
+ },
13958
+ pwrite: (path, at, bytes, transfer) => write(
13959
+ path,
13960
+ async (held) => void await held.pwrite(bytes, at),
13961
+ () => ranged2.pwrite(path, at, bytes, transfer)
13962
+ ),
13963
+ truncate: (path, size) => write(
13964
+ path,
13965
+ (held) => held.truncate(size),
13966
+ () => ranged2.truncate(path, size)
13967
+ )
13968
+ } : {}
13969
+ };
13970
+ }
13971
+ function keepingOpen(fs, nodes, changed = () => {
13972
+ }) {
13819
13973
  return {
13820
13974
  ...fs,
13975
+ ...heldIo(fs, nodes, changed),
13821
13976
  async exclusive(path, run2, follow2 = true) {
13822
13977
  const at = fs.resolvePath("/", path);
13823
13978
  const key = follow2 ? nodes.targetKey(at) : nodes.entryKey(at);
@@ -13845,7 +14000,18 @@ function keepingOpen(fs, nodes) {
13845
14000
  nodes.renamed(a, b);
13846
14001
  });
13847
14002
  },
13848
- writeFile: (path, content, owner) => nodes.onEntry(fs.resolvePath("/", path), () => fs.writeFile(path, content, owner)),
14003
+ writeFile: (path, content, owner) => {
14004
+ const at = fs.resolvePath("/", path);
14005
+ const held = nodes.holding(at);
14006
+ if (!held) return nodes.onEntry(at, () => fs.writeFile(path, content, owner));
14007
+ const bytes = typeof content === "string" ? new TextEncoder().encode(content) : content;
14008
+ return held.serial(async () => {
14009
+ await held.truncate(0);
14010
+ await held.pwrite(bytes, 0);
14011
+ await held.flush();
14012
+ changed(at);
14013
+ });
14014
+ },
13849
14015
  createExclusive: async (path, owner) => nodes.createExclusive(await nodes.entryKey(fs.resolvePath("/", path)), owner),
13850
14016
  symlink: (target, path, owner) => nodes.onEntry(fs.resolvePath("/", path), () => fs.symlink(target, path, owner)),
13851
14017
  links: (path) => mayLink(fs, path),
@@ -15356,6 +15522,7 @@ function processInit(opts, sab, umask, cred, lane) {
15356
15522
  sab,
15357
15523
  umask,
15358
15524
  cred,
15525
+ ...opts.changes ? { changes: opts.changes } : {},
15359
15526
  ...opts.owners ? { owners: true } : {},
15360
15527
  ...opts.links !== void 0 ? { links: true } : {},
15361
15528
  ...opts.ppid !== void 0 ? { ppid: opts.ppid } : {}
@@ -19115,6 +19282,7 @@ var Launcher = class {
19115
19282
  resolver;
19116
19283
  hostname;
19117
19284
  watchers = new FsWatchers();
19285
+ changes = new FileChanges();
19118
19286
  pnpmHome;
19119
19287
  pnpmChain;
19120
19288
  pnpmMade;
@@ -19166,6 +19334,7 @@ var Launcher = class {
19166
19334
  this.sealed.tickets.normalise = (path) => physicalPathAsync(this.base, path);
19167
19335
  this.sealed.userOf = async (uid) => (await this.users.lookup(uid))?.name;
19168
19336
  if (this.owners) options.fs.trackOwners?.();
19337
+ this.watchers.tap((paths) => this.changes.publish(...paths));
19169
19338
  this.mounts = new MountTable({
19170
19339
  open: (type, spec) => this.driver(type, spec),
19171
19340
  busy: (target) => [...this.openFiles].some((nodes) => nodes.holds(target)) || heldUnder(this.held, target),
@@ -19303,9 +19472,9 @@ var Launcher = class {
19303
19472
  commands(scope = "") {
19304
19473
  let found = this.catalogs.get(scope);
19305
19474
  if (!found) {
19306
- found = this.trustedAppended().then(async (appended) => {
19307
- const tiers = await this.tiers(scope, appended);
19308
- return scanCommands(this.scanned, tiers, tiers.length - appended.length);
19475
+ found = this.trustedAppended().then(async (appended2) => {
19476
+ const tiers = await this.tiers(scope, appended2);
19477
+ return scanCommands(this.scanned, tiers, tiers.length - appended2.length);
19309
19478
  }).then((commands) => commands.set(SUDO_COMMAND.name, SUDO_COMMAND));
19310
19479
  this.catalogs.set(scope, found);
19311
19480
  }
@@ -19333,11 +19502,11 @@ var Launcher = class {
19333
19502
  }
19334
19503
  return found;
19335
19504
  }
19336
- async tiers(scope = "", appended) {
19505
+ async tiers(scope = "", appended2) {
19337
19506
  const system = [
19338
19507
  [this.modulesDir],
19339
19508
  await pnpmGlobalRoots(this.base, this.pnpmHome),
19340
- ...(appended ?? await this.trustedAppended()).map((root) => [root])
19509
+ ...(appended2 ?? await this.trustedAppended()).map((root) => [root])
19341
19510
  ];
19342
19511
  return scope ? [await pnpmGlobalRoots(this.base, scope), ...system] : system;
19343
19512
  }
@@ -19890,6 +20059,7 @@ var Launcher = class {
19890
20059
  clipboard: this.clipboard,
19891
20060
  ...this.dac ? { dac: this.dac } : {},
19892
20061
  program: req.program,
20062
+ changes: this.changes.sab,
19893
20063
  argv0: req.argv0,
19894
20064
  args: req.args,
19895
20065
  env: req.env,
@@ -20724,7 +20894,8 @@ var Launcher = class {
20724
20894
  );
20725
20895
  }
20726
20896
  processChain(fs, nodes, unlinked) {
20727
- return unlinked.wrap(keepingOpen(fs, nodes));
20897
+ nodes.changed = (path) => this.changes.publish(path);
20898
+ return unlinked.wrap(keepingOpen(fs, nodes, (path) => this.changes.publish(path)));
20728
20899
  }
20729
20900
  async starting(argv, dir, account, tag) {
20730
20901
  this.resetCatalogs();