@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.
@@ -1800,6 +1800,7 @@ var OpfsFs = class {
1800
1800
  this.touch(now, parent.path, made2);
1801
1801
  }
1802
1802
  async mkdirExcl(path, owner) {
1803
+ if (normalizePath(path) === "/") throw fsError("EEXIST", path);
1803
1804
  const parent = await this.locate(parentOf3(path), true);
1804
1805
  if (parent.handle?.kind !== "directory") throw fsError("ENOTDIR", path);
1805
1806
  const dir = parent.handle;
@@ -8170,6 +8171,47 @@ var FileWatches = class {
8170
8171
  }
8171
8172
  };
8172
8173
 
8174
+ // src/fs/changes.ts
8175
+ var GEN = 0;
8176
+ var RING = 1;
8177
+ var RING_SIZE = 4096;
8178
+ var SLOT = 2;
8179
+ var CHANGES_BYTES = (RING + RING_SIZE * SLOT) * 4;
8180
+ function changeHash(path) {
8181
+ let h = 2166136261;
8182
+ for (let i = 0; i < path.length; i++) {
8183
+ h ^= path.charCodeAt(i);
8184
+ h = Math.imul(h, 16777619);
8185
+ }
8186
+ return h === 0 ? 1 : h;
8187
+ }
8188
+ function normal(path) {
8189
+ const parts2 = [];
8190
+ for (const part of path.split("/")) {
8191
+ if (part === "" || part === ".") continue;
8192
+ if (part === "..") parts2.pop();
8193
+ else parts2.push(part);
8194
+ }
8195
+ return `/${parts2.join("/")}`;
8196
+ }
8197
+ var FileChanges = class {
8198
+ sab;
8199
+ view;
8200
+ constructor(sab = new SharedArrayBuffer(CHANGES_BYTES)) {
8201
+ this.sab = sab;
8202
+ this.view = new Int32Array(sab);
8203
+ }
8204
+ publish(...paths) {
8205
+ for (const path of paths) {
8206
+ const g = Atomics.add(this.view, GEN, 1) + 1 | 0;
8207
+ const at = RING + (g & RING_SIZE - 1) * SLOT;
8208
+ Atomics.store(this.view, at, 0);
8209
+ Atomics.store(this.view, at + 1, changeHash(normal(path)));
8210
+ Atomics.store(this.view, at, g);
8211
+ }
8212
+ }
8213
+ };
8214
+
8173
8215
  // src/fs/commands.ts
8174
8216
  var S_IFDIR2 = 16384;
8175
8217
  var S_IFREG2 = 32768;
@@ -8709,6 +8751,10 @@ function touches(watcher, changed) {
8709
8751
  }
8710
8752
  var FsWatchers = class {
8711
8753
  watchers = /* @__PURE__ */ new Set();
8754
+ taps = [];
8755
+ tap(listener) {
8756
+ this.taps.push(listener);
8757
+ }
8712
8758
  watch(paths, options, notify) {
8713
8759
  const watcher = {
8714
8760
  paths: paths.map(normalizePath),
@@ -8723,6 +8769,7 @@ var FsWatchers = class {
8723
8769
  };
8724
8770
  }
8725
8771
  changed(...paths) {
8772
+ for (const tap of this.taps) tap(paths);
8726
8773
  for (const watcher of this.watchers) {
8727
8774
  for (const path of paths) {
8728
8775
  const changed = normalizePath(path);
@@ -10515,6 +10562,7 @@ var SYNC_FS_OPS = [
10515
10562
  "kept",
10516
10563
  "pread",
10517
10564
  "pwrite",
10565
+ "append",
10518
10566
  "truncate",
10519
10567
  "chown",
10520
10568
  "lchown",
@@ -10710,6 +10758,8 @@ async function run(entry, path, req) {
10710
10758
  case "pwrite":
10711
10759
  case "truncate":
10712
10760
  return ranged(fs, path, req);
10761
+ case "append":
10762
+ return json2(await appended(fs, path, req.body ?? new Uint8Array(0)));
10713
10763
  default:
10714
10764
  return { ok: false, errno: "EINVAL", message: `sync-fs: unknown op '${req.op}'` };
10715
10765
  }
@@ -10802,6 +10852,7 @@ async function guard(g, path, req, cwd) {
10802
10852
  if (req.handle === void 0) await readable(g, op, path);
10803
10853
  return { path: await walkSafe(g, path, true) };
10804
10854
  case "pwrite":
10855
+ case "append":
10805
10856
  case "truncate":
10806
10857
  if (req.handle === void 0) await fileWritable(g, op, path);
10807
10858
  return { path: await walkSafe(g, path, true) };
@@ -10862,7 +10913,7 @@ var CHANGING = /* @__PURE__ */ new Set([
10862
10913
  "chown",
10863
10914
  "lchown"
10864
10915
  ]);
10865
- var CONTENT = /* @__PURE__ */ new Set(["write", "pwrite", "truncate"]);
10916
+ var CONTENT = /* @__PURE__ */ new Set(["write", "pwrite", "append", "truncate"]);
10866
10917
  var REMOVING = /* @__PURE__ */ new Set(["unlink", "rmdir", "rm", "rename"]);
10867
10918
  async function mayChange(entry, path, req) {
10868
10919
  const { mayChange: mayChange2 } = entry.fs;
@@ -10900,6 +10951,30 @@ async function createExclusive(fs, path, owner) {
10900
10951
  throw syncError("EEXIST", path);
10901
10952
  await fs.writeFile(path, new Uint8Array(0), owner);
10902
10953
  }
10954
+ var appending = /* @__PURE__ */ new Map();
10955
+ async function appended(fs, path, body) {
10956
+ const key = await fs.realpath?.(path, true).catch(() => void 0) ?? path;
10957
+ const before = appending.get(key) ?? Promise.resolve();
10958
+ const run2 = before.then(async () => {
10959
+ if (fs.append) return fs.append(path, body);
10960
+ const size = (await fs.stat(path)).size;
10961
+ const ops = rangedOps(fs);
10962
+ if (ops) await ops.pwrite(path, size, body, true);
10963
+ else {
10964
+ const whole = new Uint8Array(size + body.length);
10965
+ whole.set(await fs.readFileBuffer(path));
10966
+ whole.set(body, size);
10967
+ await fs.writeFile(path, whole);
10968
+ }
10969
+ return size + body.length;
10970
+ });
10971
+ const settled = run2.catch(() => void 0);
10972
+ appending.set(key, settled);
10973
+ void settled.then(() => {
10974
+ if (appending.get(key) === settled) appending.delete(key);
10975
+ });
10976
+ return run2;
10977
+ }
10903
10978
  async function ranged(fs, path, req) {
10904
10979
  const ops = rangedOps(fs);
10905
10980
  if (!ops) throw syncError("ENOSYS", path);
@@ -10915,7 +10990,7 @@ async function ranged(fs, path, req) {
10915
10990
  return done;
10916
10991
  }
10917
10992
  var CHOWN_OPS = /* @__PURE__ */ new Set(["chown", "lchown"]);
10918
- var UNLINKED_OPS = /* @__PURE__ */ new Set(["read", "pread", "pwrite", "truncate"]);
10993
+ var UNLINKED_OPS = /* @__PURE__ */ new Set(["read", "pread", "pwrite", "append", "truncate"]);
10919
10994
  var OWN_OPS = /* @__PURE__ */ new Set(["rm", "unlink", "rmdir", "rename", "link"]);
10920
10995
  var TWO_PATHS = /* @__PURE__ */ new Set(["rename", "link"]);
10921
10996
  var UNLINKING_OPS = /* @__PURE__ */ new Set(["rm", "unlink", "rename"]);
@@ -11512,6 +11587,13 @@ var Pages = class {
11512
11587
  this.length = size;
11513
11588
  this.stored = size;
11514
11589
  }
11590
+ refresh(size) {
11591
+ if (this.pinned) return;
11592
+ for (const page of [...this.pages.keys()]) if (!this.dirty.has(page)) this.drop(page);
11593
+ const resized2 = this.length !== this.stored || this.shrink !== void 0;
11594
+ if (this.shrink === void 0) this.stored = size;
11595
+ this.length = resized2 ? Math.max(this.length, this.stored) : size;
11596
+ }
11515
11597
  evict() {
11516
11598
  if (this.pinned) return;
11517
11599
  let clean = (this.pages.size - this.dirty.size) * PAGE;
@@ -11611,7 +11693,7 @@ function mountTable(mounts = []) {
11611
11693
  }
11612
11694
 
11613
11695
  // src/version.ts
11614
- var KERNEL_VERSION = true ? "1.94.0" : "0.0.0-dev";
11696
+ var KERNEL_VERSION = true ? "1.94.2" : "0.0.0-dev";
11615
11697
  var OS_RELEASE = "6.0.0-slicc";
11616
11698
  function procVersion() {
11617
11699
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -11813,10 +11895,10 @@ function normalize(path) {
11813
11895
  }
11814
11896
  return `/${out.join("/")}`;
11815
11897
  }
11816
- var RING = 8;
11817
- var RING_SIZE = 64;
11818
- var SLOT = 3;
11819
- var SHARED_IDS_BYTES = (RING + RING_SIZE * SLOT) * 4;
11898
+ var RING2 = 8;
11899
+ var RING_SIZE2 = 64;
11900
+ var SLOT2 = 3;
11901
+ var SHARED_IDS_BYTES = (RING2 + RING_SIZE2 * SLOT2) * 4;
11820
11902
 
11821
11903
  // src/process/wasi/wasi-procfs.ts
11822
11904
  var DIR_MODE = 16749;
@@ -13700,6 +13782,7 @@ var VfsNode = class {
13700
13782
  path;
13701
13783
  orphaned;
13702
13784
  id;
13785
+ onDirty;
13703
13786
  constructor(fs, path, contents2, orphaned = false, dirty = false, pin) {
13704
13787
  this.fs = fs;
13705
13788
  this.pin = pin;
@@ -13849,6 +13932,7 @@ var VfsNode = class {
13849
13932
  }
13850
13933
  markDirty() {
13851
13934
  this.dirty = true;
13935
+ if (!this.orphaned) this.onDirty?.();
13852
13936
  if (this.writeBack !== void 0 || this.orphaned) return;
13853
13937
  const delay = Math.max(WRITEBACK_MS, this.writeBackCost * WRITEBACK_COST_FACTOR);
13854
13938
  this.writeBack = setTimeout(() => {
@@ -13884,6 +13968,7 @@ var VfsNodes = class {
13884
13968
  kept = /* @__PURE__ */ new Map();
13885
13969
  byId = /* @__PURE__ */ new Map();
13886
13970
  keepsOnDisk = false;
13971
+ changed;
13887
13972
  fs;
13888
13973
  entries;
13889
13974
  onClosed;
@@ -13974,12 +14059,18 @@ var VfsNodes = class {
13974
14059
  if (node.path === path) node.renamedTo(others[0]);
13975
14060
  return true;
13976
14061
  }
14062
+ holding(path) {
14063
+ if (this.byPath.size === 0) return void 0;
14064
+ const node = this.byPath.get(path);
14065
+ return node && !node.orphaned ? node : void 0;
14066
+ }
13977
14067
  named(path, id2) {
13978
14068
  const node = this.byPath.get(path) ?? (id2 === void 0 ? void 0 : this.byId.get(id2));
13979
14069
  if (node && !this.byPath.has(path)) this.byPath.set(path, node);
13980
14070
  return node;
13981
14071
  }
13982
14072
  create(path, id2, node) {
14073
+ node.onDirty = () => this.changed?.(node.path);
13983
14074
  this.byPath.set(path, node);
13984
14075
  if (id2 !== void 0) this.know(node, id2);
13985
14076
  return node;
@@ -14120,9 +14211,73 @@ async function refuseReadonly(fs, path, flags2, opts = {}) {
14120
14211
  const st = own ?? await stat(await targetDir(fs, path));
14121
14212
  if (st?.readonly) throw new KernelError("EROFS");
14122
14213
  }
14123
- function keepingOpen(fs, nodes) {
14214
+ function heldIo(fs, nodes, changed) {
14215
+ const ranged2 = rangedOps(fs);
14216
+ const node = (path) => nodes.holding(fs.resolvePath("/", path));
14217
+ const write = async (path, op, fallback) => {
14218
+ const held = node(path);
14219
+ if (!held) return fallback();
14220
+ const out = await held.serial(async () => {
14221
+ const done4 = await op(held);
14222
+ await held.flush();
14223
+ return done4;
14224
+ });
14225
+ changed(fs.resolvePath("/", path));
14226
+ return out;
14227
+ };
14228
+ return {
14229
+ append: (path, bytes) => write(
14230
+ path,
14231
+ async (held) => {
14232
+ const at = await held.size();
14233
+ await held.pwrite(bytes, at);
14234
+ return at + bytes.length;
14235
+ },
14236
+ async () => {
14237
+ const at = (await fs.stat(path)).size;
14238
+ if (ranged2) await ranged2.pwrite(path, at, bytes, true);
14239
+ else {
14240
+ const whole = new Uint8Array(at + bytes.length);
14241
+ whole.set(await fs.readFileBuffer(path));
14242
+ whole.set(bytes, at);
14243
+ await fs.writeFile(path, whole);
14244
+ }
14245
+ return at + bytes.length;
14246
+ }
14247
+ ),
14248
+ async stat(path) {
14249
+ const st = await fs.stat(path);
14250
+ const held = st.isFile ? node(path) : void 0;
14251
+ return held ? { ...st, size: await held.serial(() => held.size()) } : st;
14252
+ },
14253
+ async readFileBuffer(path) {
14254
+ const held = node(path);
14255
+ if (!held) return fs.readFileBuffer(path);
14256
+ return held.serial(async () => held.pread(await held.size(), 0));
14257
+ },
14258
+ ...ranged2 ? {
14259
+ pread: (path, at, n, version) => {
14260
+ const held = node(path);
14261
+ return held ? held.serial(() => held.pread(n, at)) : ranged2.pread(path, at, n, version);
14262
+ },
14263
+ pwrite: (path, at, bytes, transfer) => write(
14264
+ path,
14265
+ async (held) => void await held.pwrite(bytes, at),
14266
+ () => ranged2.pwrite(path, at, bytes, transfer)
14267
+ ),
14268
+ truncate: (path, size) => write(
14269
+ path,
14270
+ (held) => held.truncate(size),
14271
+ () => ranged2.truncate(path, size)
14272
+ )
14273
+ } : {}
14274
+ };
14275
+ }
14276
+ function keepingOpen(fs, nodes, changed = () => {
14277
+ }) {
14124
14278
  return {
14125
14279
  ...fs,
14280
+ ...heldIo(fs, nodes, changed),
14126
14281
  async exclusive(path, run2, follow2 = true) {
14127
14282
  const at = fs.resolvePath("/", path);
14128
14283
  const key = follow2 ? nodes.targetKey(at) : nodes.entryKey(at);
@@ -14150,7 +14305,18 @@ function keepingOpen(fs, nodes) {
14150
14305
  nodes.renamed(a, b);
14151
14306
  });
14152
14307
  },
14153
- writeFile: (path, content, owner) => nodes.onEntry(fs.resolvePath("/", path), () => fs.writeFile(path, content, owner)),
14308
+ writeFile: (path, content, owner) => {
14309
+ const at = fs.resolvePath("/", path);
14310
+ const held = nodes.holding(at);
14311
+ if (!held) return nodes.onEntry(at, () => fs.writeFile(path, content, owner));
14312
+ const bytes = typeof content === "string" ? new TextEncoder().encode(content) : content;
14313
+ return held.serial(async () => {
14314
+ await held.truncate(0);
14315
+ await held.pwrite(bytes, 0);
14316
+ await held.flush();
14317
+ changed(at);
14318
+ });
14319
+ },
14154
14320
  createExclusive: async (path, owner) => nodes.createExclusive(await nodes.entryKey(fs.resolvePath("/", path)), owner),
14155
14321
  symlink: (target, path, owner) => nodes.onEntry(fs.resolvePath("/", path), () => fs.symlink(target, path, owner)),
14156
14322
  links: (path) => mayLink(fs, path),
@@ -15661,6 +15827,7 @@ function processInit(opts, sab, umask, cred, lane) {
15661
15827
  sab,
15662
15828
  umask,
15663
15829
  cred,
15830
+ ...opts.changes ? { changes: opts.changes } : {},
15664
15831
  ...opts.owners ? { owners: true } : {},
15665
15832
  ...opts.links !== void 0 ? { links: true } : {},
15666
15833
  ...opts.ppid !== void 0 ? { ppid: opts.ppid } : {}
@@ -19317,6 +19484,7 @@ var Launcher = class {
19317
19484
  resolver;
19318
19485
  hostname;
19319
19486
  watchers = new FsWatchers();
19487
+ changes = new FileChanges();
19320
19488
  pnpmHome;
19321
19489
  pnpmChain;
19322
19490
  pnpmMade;
@@ -19368,6 +19536,7 @@ var Launcher = class {
19368
19536
  this.sealed.tickets.normalise = (path) => physicalPathAsync(this.base, path);
19369
19537
  this.sealed.userOf = async (uid) => (await this.users.lookup(uid))?.name;
19370
19538
  if (this.owners) options.fs.trackOwners?.();
19539
+ this.watchers.tap((paths) => this.changes.publish(...paths));
19371
19540
  this.mounts = new MountTable({
19372
19541
  open: (type, spec) => this.driver(type, spec),
19373
19542
  busy: (target) => [...this.openFiles].some((nodes) => nodes.holds(target)) || heldUnder(this.held, target),
@@ -19505,9 +19674,9 @@ var Launcher = class {
19505
19674
  commands(scope = "") {
19506
19675
  let found = this.catalogs.get(scope);
19507
19676
  if (!found) {
19508
- found = this.trustedAppended().then(async (appended) => {
19509
- const tiers = await this.tiers(scope, appended);
19510
- return scanCommands(this.scanned, tiers, tiers.length - appended.length);
19677
+ found = this.trustedAppended().then(async (appended2) => {
19678
+ const tiers = await this.tiers(scope, appended2);
19679
+ return scanCommands(this.scanned, tiers, tiers.length - appended2.length);
19511
19680
  }).then((commands) => commands.set(SUDO_COMMAND.name, SUDO_COMMAND));
19512
19681
  this.catalogs.set(scope, found);
19513
19682
  }
@@ -19535,11 +19704,11 @@ var Launcher = class {
19535
19704
  }
19536
19705
  return found;
19537
19706
  }
19538
- async tiers(scope = "", appended) {
19707
+ async tiers(scope = "", appended2) {
19539
19708
  const system = [
19540
19709
  [this.modulesDir],
19541
19710
  await pnpmGlobalRoots(this.base, this.pnpmHome),
19542
- ...(appended ?? await this.trustedAppended()).map((root) => [root])
19711
+ ...(appended2 ?? await this.trustedAppended()).map((root) => [root])
19543
19712
  ];
19544
19713
  return scope ? [await pnpmGlobalRoots(this.base, scope), ...system] : system;
19545
19714
  }
@@ -20092,6 +20261,7 @@ var Launcher = class {
20092
20261
  clipboard: this.clipboard,
20093
20262
  ...this.dac ? { dac: this.dac } : {},
20094
20263
  program: req.program,
20264
+ changes: this.changes.sab,
20095
20265
  argv0: req.argv0,
20096
20266
  args: req.args,
20097
20267
  env: req.env,
@@ -20926,7 +21096,8 @@ var Launcher = class {
20926
21096
  );
20927
21097
  }
20928
21098
  processChain(fs, nodes, unlinked) {
20929
- return unlinked.wrap(keepingOpen(fs, nodes));
21099
+ nodes.changed = (path) => this.changes.publish(path);
21100
+ return unlinked.wrap(keepingOpen(fs, nodes, (path) => this.changes.publish(path)));
20930
21101
  }
20931
21102
  async starting(argv, dir, account, tag) {
20932
21103
  this.resetCatalogs();