@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.
package/dist/node.js CHANGED
@@ -7153,6 +7153,47 @@ var FileWatches = class {
7153
7153
  }
7154
7154
  };
7155
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
+
7156
7197
  // src/fs/commands.ts
7157
7198
  var S_IFDIR2 = 16384;
7158
7199
  var S_IFREG2 = 32768;
@@ -7470,6 +7511,10 @@ function touches(watcher, changed) {
7470
7511
  }
7471
7512
  var FsWatchers = class {
7472
7513
  watchers = /* @__PURE__ */ new Set();
7514
+ taps = [];
7515
+ tap(listener) {
7516
+ this.taps.push(listener);
7517
+ }
7473
7518
  watch(paths, options, notify) {
7474
7519
  const watcher = {
7475
7520
  paths: paths.map(normalizePath),
@@ -7484,6 +7529,7 @@ var FsWatchers = class {
7484
7529
  };
7485
7530
  }
7486
7531
  changed(...paths) {
7532
+ for (const tap of this.taps) tap(paths);
7487
7533
  for (const watcher of this.watchers) {
7488
7534
  for (const path of paths) {
7489
7535
  const changed = normalizePath(path);
@@ -9447,6 +9493,7 @@ var SYNC_FS_OPS = [
9447
9493
  "kept",
9448
9494
  "pread",
9449
9495
  "pwrite",
9496
+ "append",
9450
9497
  "truncate",
9451
9498
  "chown",
9452
9499
  "lchown",
@@ -9642,6 +9689,8 @@ async function run(entry, path, req) {
9642
9689
  case "pwrite":
9643
9690
  case "truncate":
9644
9691
  return ranged(fs, path, req);
9692
+ case "append":
9693
+ return json2(await appended(fs, path, req.body ?? new Uint8Array(0)));
9645
9694
  default:
9646
9695
  return { ok: false, errno: "EINVAL", message: `sync-fs: unknown op '${req.op}'` };
9647
9696
  }
@@ -9734,6 +9783,7 @@ async function guard(g, path, req, cwd) {
9734
9783
  if (req.handle === void 0) await readable(g, op, path);
9735
9784
  return { path: await walkSafe(g, path, true) };
9736
9785
  case "pwrite":
9786
+ case "append":
9737
9787
  case "truncate":
9738
9788
  if (req.handle === void 0) await fileWritable(g, op, path);
9739
9789
  return { path: await walkSafe(g, path, true) };
@@ -9794,7 +9844,7 @@ var CHANGING = /* @__PURE__ */ new Set([
9794
9844
  "chown",
9795
9845
  "lchown"
9796
9846
  ]);
9797
- var CONTENT = /* @__PURE__ */ new Set(["write", "pwrite", "truncate"]);
9847
+ var CONTENT = /* @__PURE__ */ new Set(["write", "pwrite", "append", "truncate"]);
9798
9848
  var REMOVING = /* @__PURE__ */ new Set(["unlink", "rmdir", "rm", "rename"]);
9799
9849
  async function mayChange(entry, path, req) {
9800
9850
  const { mayChange: mayChange2 } = entry.fs;
@@ -9832,6 +9882,30 @@ async function createExclusive(fs, path, owner) {
9832
9882
  throw syncError("EEXIST", path);
9833
9883
  await fs.writeFile(path, new Uint8Array(0), owner);
9834
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
+ }
9835
9909
  async function ranged(fs, path, req) {
9836
9910
  const ops = rangedOps(fs);
9837
9911
  if (!ops) throw syncError("ENOSYS", path);
@@ -9847,7 +9921,7 @@ async function ranged(fs, path, req) {
9847
9921
  return done;
9848
9922
  }
9849
9923
  var CHOWN_OPS = /* @__PURE__ */ new Set(["chown", "lchown"]);
9850
- var UNLINKED_OPS = /* @__PURE__ */ new Set(["read", "pread", "pwrite", "truncate"]);
9924
+ var UNLINKED_OPS = /* @__PURE__ */ new Set(["read", "pread", "pwrite", "append", "truncate"]);
9851
9925
  var OWN_OPS = /* @__PURE__ */ new Set(["rm", "unlink", "rmdir", "rename", "link"]);
9852
9926
  var TWO_PATHS = /* @__PURE__ */ new Set(["rename", "link"]);
9853
9927
  var UNLINKING_OPS = /* @__PURE__ */ new Set(["rm", "unlink", "rename"]);
@@ -10444,6 +10518,13 @@ var Pages = class {
10444
10518
  this.length = size;
10445
10519
  this.stored = size;
10446
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
+ }
10447
10528
  evict() {
10448
10529
  if (this.pinned) return;
10449
10530
  let clean = (this.pages.size - this.dirty.size) * PAGE;
@@ -10543,7 +10624,7 @@ function mountTable(mounts = []) {
10543
10624
  }
10544
10625
 
10545
10626
  // src/version.ts
10546
- var KERNEL_VERSION = true ? "1.94.1" : "0.0.0-dev";
10627
+ var KERNEL_VERSION = true ? "1.94.3" : "0.0.0-dev";
10547
10628
  var OS_RELEASE = "6.0.0-slicc";
10548
10629
  function procVersion() {
10549
10630
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -10745,10 +10826,10 @@ function normalize(path) {
10745
10826
  }
10746
10827
  return `/${out.join("/")}`;
10747
10828
  }
10748
- var RING = 8;
10749
- var RING_SIZE = 64;
10750
- var SLOT = 3;
10751
- 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;
10752
10833
 
10753
10834
  // src/process/wasi/wasi-procfs.ts
10754
10835
  var DIR_MODE = 16749;
@@ -11316,7 +11397,7 @@ var KernelLoopback = class {
11316
11397
  if (head.status !== 101) {
11317
11398
  throw errno(
11318
11399
  "EPROTO",
11319
- `the server answered ${head.status} ${head.statusText}, not an upgrade`
11400
+ `the server answered the upgrade with ${head.status}${head.statusText ? ` ${head.statusText}` : ""}`
11320
11401
  );
11321
11402
  }
11322
11403
  const upgraded = fieldTokens(head.headers, "upgrade").includes("websocket") && fieldTokens(head.headers, "connection").includes("upgrade");
@@ -13396,6 +13477,7 @@ var VfsNode = class {
13396
13477
  path;
13397
13478
  orphaned;
13398
13479
  id;
13480
+ onDirty;
13399
13481
  constructor(fs, path, contents2, orphaned = false, dirty = false, pin) {
13400
13482
  this.fs = fs;
13401
13483
  this.pin = pin;
@@ -13545,6 +13627,7 @@ var VfsNode = class {
13545
13627
  }
13546
13628
  markDirty() {
13547
13629
  this.dirty = true;
13630
+ if (!this.orphaned) this.onDirty?.();
13548
13631
  if (this.writeBack !== void 0 || this.orphaned) return;
13549
13632
  const delay = Math.max(WRITEBACK_MS, this.writeBackCost * WRITEBACK_COST_FACTOR);
13550
13633
  this.writeBack = setTimeout(() => {
@@ -13580,6 +13663,7 @@ var VfsNodes = class {
13580
13663
  kept = /* @__PURE__ */ new Map();
13581
13664
  byId = /* @__PURE__ */ new Map();
13582
13665
  keepsOnDisk = false;
13666
+ changed;
13583
13667
  fs;
13584
13668
  entries;
13585
13669
  onClosed;
@@ -13670,12 +13754,18 @@ var VfsNodes = class {
13670
13754
  if (node.path === path) node.renamedTo(others[0]);
13671
13755
  return true;
13672
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
+ }
13673
13762
  named(path, id2) {
13674
13763
  const node = this.byPath.get(path) ?? (id2 === void 0 ? void 0 : this.byId.get(id2));
13675
13764
  if (node && !this.byPath.has(path)) this.byPath.set(path, node);
13676
13765
  return node;
13677
13766
  }
13678
13767
  create(path, id2, node) {
13768
+ node.onDirty = () => this.changed?.(node.path);
13679
13769
  this.byPath.set(path, node);
13680
13770
  if (id2 !== void 0) this.know(node, id2);
13681
13771
  return node;
@@ -13816,9 +13906,73 @@ async function refuseReadonly(fs, path, flags2, opts = {}) {
13816
13906
  const st = own ?? await stat(await targetDir(fs, path));
13817
13907
  if (st?.readonly) throw new KernelError("EROFS");
13818
13908
  }
13819
- 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
+ }) {
13820
13973
  return {
13821
13974
  ...fs,
13975
+ ...heldIo(fs, nodes, changed),
13822
13976
  async exclusive(path, run2, follow2 = true) {
13823
13977
  const at = fs.resolvePath("/", path);
13824
13978
  const key = follow2 ? nodes.targetKey(at) : nodes.entryKey(at);
@@ -13846,7 +14000,18 @@ function keepingOpen(fs, nodes) {
13846
14000
  nodes.renamed(a, b);
13847
14001
  });
13848
14002
  },
13849
- 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
+ },
13850
14015
  createExclusive: async (path, owner) => nodes.createExclusive(await nodes.entryKey(fs.resolvePath("/", path)), owner),
13851
14016
  symlink: (target, path, owner) => nodes.onEntry(fs.resolvePath("/", path), () => fs.symlink(target, path, owner)),
13852
14017
  links: (path) => mayLink(fs, path),
@@ -15357,6 +15522,7 @@ function processInit(opts, sab, umask, cred, lane) {
15357
15522
  sab,
15358
15523
  umask,
15359
15524
  cred,
15525
+ ...opts.changes ? { changes: opts.changes } : {},
15360
15526
  ...opts.owners ? { owners: true } : {},
15361
15527
  ...opts.links !== void 0 ? { links: true } : {},
15362
15528
  ...opts.ppid !== void 0 ? { ppid: opts.ppid } : {}
@@ -19116,6 +19282,7 @@ var Launcher = class {
19116
19282
  resolver;
19117
19283
  hostname;
19118
19284
  watchers = new FsWatchers();
19285
+ changes = new FileChanges();
19119
19286
  pnpmHome;
19120
19287
  pnpmChain;
19121
19288
  pnpmMade;
@@ -19167,6 +19334,7 @@ var Launcher = class {
19167
19334
  this.sealed.tickets.normalise = (path) => physicalPathAsync(this.base, path);
19168
19335
  this.sealed.userOf = async (uid) => (await this.users.lookup(uid))?.name;
19169
19336
  if (this.owners) options.fs.trackOwners?.();
19337
+ this.watchers.tap((paths) => this.changes.publish(...paths));
19170
19338
  this.mounts = new MountTable({
19171
19339
  open: (type, spec) => this.driver(type, spec),
19172
19340
  busy: (target) => [...this.openFiles].some((nodes) => nodes.holds(target)) || heldUnder(this.held, target),
@@ -19304,9 +19472,9 @@ var Launcher = class {
19304
19472
  commands(scope = "") {
19305
19473
  let found = this.catalogs.get(scope);
19306
19474
  if (!found) {
19307
- found = this.trustedAppended().then(async (appended) => {
19308
- const tiers = await this.tiers(scope, appended);
19309
- 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);
19310
19478
  }).then((commands) => commands.set(SUDO_COMMAND.name, SUDO_COMMAND));
19311
19479
  this.catalogs.set(scope, found);
19312
19480
  }
@@ -19334,11 +19502,11 @@ var Launcher = class {
19334
19502
  }
19335
19503
  return found;
19336
19504
  }
19337
- async tiers(scope = "", appended) {
19505
+ async tiers(scope = "", appended2) {
19338
19506
  const system = [
19339
19507
  [this.modulesDir],
19340
19508
  await pnpmGlobalRoots(this.base, this.pnpmHome),
19341
- ...(appended ?? await this.trustedAppended()).map((root) => [root])
19509
+ ...(appended2 ?? await this.trustedAppended()).map((root) => [root])
19342
19510
  ];
19343
19511
  return scope ? [await pnpmGlobalRoots(this.base, scope), ...system] : system;
19344
19512
  }
@@ -19891,6 +20059,7 @@ var Launcher = class {
19891
20059
  clipboard: this.clipboard,
19892
20060
  ...this.dac ? { dac: this.dac } : {},
19893
20061
  program: req.program,
20062
+ changes: this.changes.sab,
19894
20063
  argv0: req.argv0,
19895
20064
  args: req.args,
19896
20065
  env: req.env,
@@ -20725,7 +20894,8 @@ var Launcher = class {
20725
20894
  );
20726
20895
  }
20727
20896
  processChain(fs, nodes, unlinked) {
20728
- 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)));
20729
20899
  }
20730
20900
  async starting(argv, dir, account, tag) {
20731
20901
  this.resetCatalogs();