@ai-ecoverse/slicc-kernel 1.94.1 → 1.94.3

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.
@@ -8171,6 +8171,47 @@ var FileWatches = class {
8171
8171
  }
8172
8172
  };
8173
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
+
8174
8215
  // src/fs/commands.ts
8175
8216
  var S_IFDIR2 = 16384;
8176
8217
  var S_IFREG2 = 32768;
@@ -8710,6 +8751,10 @@ function touches(watcher, changed) {
8710
8751
  }
8711
8752
  var FsWatchers = class {
8712
8753
  watchers = /* @__PURE__ */ new Set();
8754
+ taps = [];
8755
+ tap(listener) {
8756
+ this.taps.push(listener);
8757
+ }
8713
8758
  watch(paths, options, notify) {
8714
8759
  const watcher = {
8715
8760
  paths: paths.map(normalizePath),
@@ -8724,6 +8769,7 @@ var FsWatchers = class {
8724
8769
  };
8725
8770
  }
8726
8771
  changed(...paths) {
8772
+ for (const tap of this.taps) tap(paths);
8727
8773
  for (const watcher of this.watchers) {
8728
8774
  for (const path of paths) {
8729
8775
  const changed = normalizePath(path);
@@ -10516,6 +10562,7 @@ var SYNC_FS_OPS = [
10516
10562
  "kept",
10517
10563
  "pread",
10518
10564
  "pwrite",
10565
+ "append",
10519
10566
  "truncate",
10520
10567
  "chown",
10521
10568
  "lchown",
@@ -10711,6 +10758,8 @@ async function run(entry, path, req) {
10711
10758
  case "pwrite":
10712
10759
  case "truncate":
10713
10760
  return ranged(fs, path, req);
10761
+ case "append":
10762
+ return json2(await appended(fs, path, req.body ?? new Uint8Array(0)));
10714
10763
  default:
10715
10764
  return { ok: false, errno: "EINVAL", message: `sync-fs: unknown op '${req.op}'` };
10716
10765
  }
@@ -10803,6 +10852,7 @@ async function guard(g, path, req, cwd) {
10803
10852
  if (req.handle === void 0) await readable(g, op, path);
10804
10853
  return { path: await walkSafe(g, path, true) };
10805
10854
  case "pwrite":
10855
+ case "append":
10806
10856
  case "truncate":
10807
10857
  if (req.handle === void 0) await fileWritable(g, op, path);
10808
10858
  return { path: await walkSafe(g, path, true) };
@@ -10863,7 +10913,7 @@ var CHANGING = /* @__PURE__ */ new Set([
10863
10913
  "chown",
10864
10914
  "lchown"
10865
10915
  ]);
10866
- var CONTENT = /* @__PURE__ */ new Set(["write", "pwrite", "truncate"]);
10916
+ var CONTENT = /* @__PURE__ */ new Set(["write", "pwrite", "append", "truncate"]);
10867
10917
  var REMOVING = /* @__PURE__ */ new Set(["unlink", "rmdir", "rm", "rename"]);
10868
10918
  async function mayChange(entry, path, req) {
10869
10919
  const { mayChange: mayChange2 } = entry.fs;
@@ -10901,6 +10951,30 @@ async function createExclusive(fs, path, owner) {
10901
10951
  throw syncError("EEXIST", path);
10902
10952
  await fs.writeFile(path, new Uint8Array(0), owner);
10903
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
+ }
10904
10978
  async function ranged(fs, path, req) {
10905
10979
  const ops = rangedOps(fs);
10906
10980
  if (!ops) throw syncError("ENOSYS", path);
@@ -10916,7 +10990,7 @@ async function ranged(fs, path, req) {
10916
10990
  return done;
10917
10991
  }
10918
10992
  var CHOWN_OPS = /* @__PURE__ */ new Set(["chown", "lchown"]);
10919
- var UNLINKED_OPS = /* @__PURE__ */ new Set(["read", "pread", "pwrite", "truncate"]);
10993
+ var UNLINKED_OPS = /* @__PURE__ */ new Set(["read", "pread", "pwrite", "append", "truncate"]);
10920
10994
  var OWN_OPS = /* @__PURE__ */ new Set(["rm", "unlink", "rmdir", "rename", "link"]);
10921
10995
  var TWO_PATHS = /* @__PURE__ */ new Set(["rename", "link"]);
10922
10996
  var UNLINKING_OPS = /* @__PURE__ */ new Set(["rm", "unlink", "rename"]);
@@ -11513,6 +11587,13 @@ var Pages = class {
11513
11587
  this.length = size;
11514
11588
  this.stored = size;
11515
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
+ }
11516
11597
  evict() {
11517
11598
  if (this.pinned) return;
11518
11599
  let clean = (this.pages.size - this.dirty.size) * PAGE;
@@ -11612,7 +11693,7 @@ function mountTable(mounts = []) {
11612
11693
  }
11613
11694
 
11614
11695
  // src/version.ts
11615
- var KERNEL_VERSION = true ? "1.94.1" : "0.0.0-dev";
11696
+ var KERNEL_VERSION = true ? "1.94.3" : "0.0.0-dev";
11616
11697
  var OS_RELEASE = "6.0.0-slicc";
11617
11698
  function procVersion() {
11618
11699
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -11814,10 +11895,10 @@ function normalize(path) {
11814
11895
  }
11815
11896
  return `/${out.join("/")}`;
11816
11897
  }
11817
- var RING = 8;
11818
- var RING_SIZE = 64;
11819
- var SLOT = 3;
11820
- 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;
11821
11902
 
11822
11903
  // src/process/wasi/wasi-procfs.ts
11823
11904
  var DIR_MODE = 16749;
@@ -12385,7 +12466,7 @@ var KernelLoopback = class {
12385
12466
  if (head.status !== 101) {
12386
12467
  throw errno(
12387
12468
  "EPROTO",
12388
- `the server answered ${head.status} ${head.statusText}, not an upgrade`
12469
+ `the server answered the upgrade with ${head.status}${head.statusText ? ` ${head.statusText}` : ""}`
12389
12470
  );
12390
12471
  }
12391
12472
  const upgraded = fieldTokens(head.headers, "upgrade").includes("websocket") && fieldTokens(head.headers, "connection").includes("upgrade");
@@ -13701,6 +13782,7 @@ var VfsNode = class {
13701
13782
  path;
13702
13783
  orphaned;
13703
13784
  id;
13785
+ onDirty;
13704
13786
  constructor(fs, path, contents2, orphaned = false, dirty = false, pin) {
13705
13787
  this.fs = fs;
13706
13788
  this.pin = pin;
@@ -13850,6 +13932,7 @@ var VfsNode = class {
13850
13932
  }
13851
13933
  markDirty() {
13852
13934
  this.dirty = true;
13935
+ if (!this.orphaned) this.onDirty?.();
13853
13936
  if (this.writeBack !== void 0 || this.orphaned) return;
13854
13937
  const delay = Math.max(WRITEBACK_MS, this.writeBackCost * WRITEBACK_COST_FACTOR);
13855
13938
  this.writeBack = setTimeout(() => {
@@ -13885,6 +13968,7 @@ var VfsNodes = class {
13885
13968
  kept = /* @__PURE__ */ new Map();
13886
13969
  byId = /* @__PURE__ */ new Map();
13887
13970
  keepsOnDisk = false;
13971
+ changed;
13888
13972
  fs;
13889
13973
  entries;
13890
13974
  onClosed;
@@ -13975,12 +14059,18 @@ var VfsNodes = class {
13975
14059
  if (node.path === path) node.renamedTo(others[0]);
13976
14060
  return true;
13977
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
+ }
13978
14067
  named(path, id2) {
13979
14068
  const node = this.byPath.get(path) ?? (id2 === void 0 ? void 0 : this.byId.get(id2));
13980
14069
  if (node && !this.byPath.has(path)) this.byPath.set(path, node);
13981
14070
  return node;
13982
14071
  }
13983
14072
  create(path, id2, node) {
14073
+ node.onDirty = () => this.changed?.(node.path);
13984
14074
  this.byPath.set(path, node);
13985
14075
  if (id2 !== void 0) this.know(node, id2);
13986
14076
  return node;
@@ -14121,9 +14211,73 @@ async function refuseReadonly(fs, path, flags2, opts = {}) {
14121
14211
  const st = own ?? await stat(await targetDir(fs, path));
14122
14212
  if (st?.readonly) throw new KernelError("EROFS");
14123
14213
  }
14124
- 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
+ }) {
14125
14278
  return {
14126
14279
  ...fs,
14280
+ ...heldIo(fs, nodes, changed),
14127
14281
  async exclusive(path, run2, follow2 = true) {
14128
14282
  const at = fs.resolvePath("/", path);
14129
14283
  const key = follow2 ? nodes.targetKey(at) : nodes.entryKey(at);
@@ -14151,7 +14305,18 @@ function keepingOpen(fs, nodes) {
14151
14305
  nodes.renamed(a, b);
14152
14306
  });
14153
14307
  },
14154
- 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
+ },
14155
14320
  createExclusive: async (path, owner) => nodes.createExclusive(await nodes.entryKey(fs.resolvePath("/", path)), owner),
14156
14321
  symlink: (target, path, owner) => nodes.onEntry(fs.resolvePath("/", path), () => fs.symlink(target, path, owner)),
14157
14322
  links: (path) => mayLink(fs, path),
@@ -15662,6 +15827,7 @@ function processInit(opts, sab, umask, cred, lane) {
15662
15827
  sab,
15663
15828
  umask,
15664
15829
  cred,
15830
+ ...opts.changes ? { changes: opts.changes } : {},
15665
15831
  ...opts.owners ? { owners: true } : {},
15666
15832
  ...opts.links !== void 0 ? { links: true } : {},
15667
15833
  ...opts.ppid !== void 0 ? { ppid: opts.ppid } : {}
@@ -19318,6 +19484,7 @@ var Launcher = class {
19318
19484
  resolver;
19319
19485
  hostname;
19320
19486
  watchers = new FsWatchers();
19487
+ changes = new FileChanges();
19321
19488
  pnpmHome;
19322
19489
  pnpmChain;
19323
19490
  pnpmMade;
@@ -19369,6 +19536,7 @@ var Launcher = class {
19369
19536
  this.sealed.tickets.normalise = (path) => physicalPathAsync(this.base, path);
19370
19537
  this.sealed.userOf = async (uid) => (await this.users.lookup(uid))?.name;
19371
19538
  if (this.owners) options.fs.trackOwners?.();
19539
+ this.watchers.tap((paths) => this.changes.publish(...paths));
19372
19540
  this.mounts = new MountTable({
19373
19541
  open: (type, spec) => this.driver(type, spec),
19374
19542
  busy: (target) => [...this.openFiles].some((nodes) => nodes.holds(target)) || heldUnder(this.held, target),
@@ -19506,9 +19674,9 @@ var Launcher = class {
19506
19674
  commands(scope = "") {
19507
19675
  let found = this.catalogs.get(scope);
19508
19676
  if (!found) {
19509
- found = this.trustedAppended().then(async (appended) => {
19510
- const tiers = await this.tiers(scope, appended);
19511
- 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);
19512
19680
  }).then((commands) => commands.set(SUDO_COMMAND.name, SUDO_COMMAND));
19513
19681
  this.catalogs.set(scope, found);
19514
19682
  }
@@ -19536,11 +19704,11 @@ var Launcher = class {
19536
19704
  }
19537
19705
  return found;
19538
19706
  }
19539
- async tiers(scope = "", appended) {
19707
+ async tiers(scope = "", appended2) {
19540
19708
  const system = [
19541
19709
  [this.modulesDir],
19542
19710
  await pnpmGlobalRoots(this.base, this.pnpmHome),
19543
- ...(appended ?? await this.trustedAppended()).map((root) => [root])
19711
+ ...(appended2 ?? await this.trustedAppended()).map((root) => [root])
19544
19712
  ];
19545
19713
  return scope ? [await pnpmGlobalRoots(this.base, scope), ...system] : system;
19546
19714
  }
@@ -20093,6 +20261,7 @@ var Launcher = class {
20093
20261
  clipboard: this.clipboard,
20094
20262
  ...this.dac ? { dac: this.dac } : {},
20095
20263
  program: req.program,
20264
+ changes: this.changes.sab,
20096
20265
  argv0: req.argv0,
20097
20266
  args: req.args,
20098
20267
  env: req.env,
@@ -20927,7 +21096,8 @@ var Launcher = class {
20927
21096
  );
20928
21097
  }
20929
21098
  processChain(fs, nodes, unlinked) {
20930
- 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)));
20931
21101
  }
20932
21102
  async starting(argv, dir, account, tag) {
20933
21103
  this.resetCatalogs();