@ai-ecoverse/slicc-kernel 1.77.0 → 1.77.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.
package/dist/node.js CHANGED
@@ -3022,6 +3022,9 @@ function writerTags(protection) {
3022
3022
  return new Set(writers);
3023
3023
  }
3024
3024
  function protectedPrefixes(paths) {
3025
+ if (!Array.isArray(paths) || paths.some((p) => typeof p !== "string" || !p.startsWith("/"))) {
3026
+ throw new TypeError("protect.paths must be a list of absolute paths");
3027
+ }
3025
3028
  return [...new Set(paths.map((p) => normalizePath(p)))];
3026
3029
  }
3027
3030
  function within(path, prefix) {
@@ -3125,6 +3128,9 @@ var ProtectedFs = class {
3125
3128
  await check(path, true);
3126
3129
  return fs.utimes(path, atime, mtime);
3127
3130
  },
3131
+ async mayChange(path, follow2) {
3132
+ await check(path, follow2);
3133
+ },
3128
3134
  async stat(path) {
3129
3135
  return marked(path, await fs.stat(path));
3130
3136
  },
@@ -3800,6 +3806,10 @@ var OpfsFs = class {
3800
3806
  };
3801
3807
  }
3802
3808
  async describe(found) {
3809
+ const stat = await this.described(found);
3810
+ return isProtected(this.guarded, found.path) ? { ...stat, readonly: true } : stat;
3811
+ }
3812
+ async described(found) {
3803
3813
  if (found.link) return this.owned(this.linkStat(found.link), found.path, found.link);
3804
3814
  const touched = this.timesOf(found.path);
3805
3815
  if (!this.owners) {
@@ -5759,6 +5769,83 @@ function withCommandDirs(fs, names, userDir = async () => void 0, owners = false
5759
5769
  };
5760
5770
  }
5761
5771
 
5772
+ // src/fs/fresh-modules.ts
5773
+ var MAGIC = [0, 97, 115, 109];
5774
+ var MAX_FRESH = 65536;
5775
+ function isModule(bytes) {
5776
+ return MAGIC.every((b, i) => bytes[i] === b);
5777
+ }
5778
+ var FreshModules = class {
5779
+ fresh = /* @__PURE__ */ new Map();
5780
+ add(path, umask, pid) {
5781
+ const key = normalizePath(path);
5782
+ this.fresh.delete(key);
5783
+ const oldest = this.fresh.size >= MAX_FRESH ? this.fresh.keys().next().value : void 0;
5784
+ if (oldest !== void 0) this.fresh.delete(oldest);
5785
+ this.fresh.set(key, { umask: umask & 511, pid, added: 0 });
5786
+ }
5787
+ forget(pid) {
5788
+ for (const [path, fresh2] of this.fresh) if (fresh2.pid === pid) this.fresh.delete(path);
5789
+ }
5790
+ wrap(fs) {
5791
+ const decide = async (given, bytes) => {
5792
+ const path = normalizePath(given);
5793
+ const fresh2 = this.fresh.get(path);
5794
+ if (!fresh2 || typeof bytes === "string" || bytes.length < MAGIC.length) return;
5795
+ const want = isModule(bytes) ? 73 & ~fresh2.umask : 0;
5796
+ if (want === fresh2.added) return;
5797
+ const mode = (await fs.stat(path)).mode & 4095;
5798
+ await fs.chmod(path, mode & ~fresh2.added | want);
5799
+ fresh2.added = want;
5800
+ };
5801
+ const overrides = {
5802
+ writeFile: async (path, content, owner) => {
5803
+ await fs.writeFile(path, content, owner);
5804
+ await decide(path, content);
5805
+ },
5806
+ chmod: async (path, mode) => {
5807
+ const fresh2 = this.fresh.get(normalizePath(path));
5808
+ const creating = fresh2?.added === 0 && (mode & 4095) === (438 & ~fresh2.umask);
5809
+ if (!creating) this.fresh.delete(normalizePath(path));
5810
+ await fs.chmod(path, mode);
5811
+ },
5812
+ rm: async (path, options) => {
5813
+ this.fresh.delete(normalizePath(path));
5814
+ await fs.rm(path, options);
5815
+ },
5816
+ rename: async (from, to) => {
5817
+ await fs.rename(from, to);
5818
+ const fresh2 = this.fresh.get(normalizePath(from));
5819
+ this.fresh.delete(normalizePath(from));
5820
+ this.fresh.delete(normalizePath(to));
5821
+ if (fresh2) this.fresh.set(normalizePath(to), fresh2);
5822
+ }
5823
+ };
5824
+ const ranged2 = rangedOps(fs);
5825
+ if (ranged2) {
5826
+ overrides.pwrite = async (path, at, bytes, transfer) => {
5827
+ const head = at === 0 && this.fresh.has(normalizePath(path)) ? bytes.slice(0, 4) : void 0;
5828
+ await ranged2.pwrite(path, at, bytes, transfer);
5829
+ if (head) await decide(path, head);
5830
+ };
5831
+ }
5832
+ const bound = /* @__PURE__ */ new WeakMap();
5833
+ return new Proxy(fs, {
5834
+ get(target, key, receiver) {
5835
+ if (Object.hasOwn(overrides, key)) return overrides[key];
5836
+ const value = Reflect.get(target, key, receiver);
5837
+ if (typeof value !== "function") return value;
5838
+ let method = bound.get(value);
5839
+ if (method === void 0) {
5840
+ method = value.bind(target);
5841
+ bound.set(value, method);
5842
+ }
5843
+ return method;
5844
+ }
5845
+ });
5846
+ }
5847
+ };
5848
+
5762
5849
  // src/fs/physical-path.ts
5763
5850
  var MAX_HOPS = 40;
5764
5851
  function start(path) {
@@ -7580,6 +7667,7 @@ async function run(entry, path, req) {
7580
7667
  case "create":
7581
7668
  await createExclusive(fs, path, ownerFor2(entry, req.mode ?? 438));
7582
7669
  entry.created?.add(path);
7670
+ entry.fresh?.(path);
7583
7671
  return done;
7584
7672
  case "readlink":
7585
7673
  return json2(await fs.readlink(path));
@@ -7678,11 +7766,39 @@ async function accessOp(entry, path, req) {
7678
7766
  await need({ ...g, cred }, open ? "open" : "access", path, req.mode ?? 0, options);
7679
7767
  return done;
7680
7768
  }
7769
+ var CHANGING = /* @__PURE__ */ new Set([
7770
+ "mkdir",
7771
+ "create",
7772
+ "symlink",
7773
+ "unlink",
7774
+ "rmdir",
7775
+ "rm",
7776
+ "rename",
7777
+ "link",
7778
+ "utimes",
7779
+ "lutimes",
7780
+ "chmod",
7781
+ "chown",
7782
+ "lchown"
7783
+ ]);
7784
+ var CONTENT = /* @__PURE__ */ new Set(["write", "pwrite", "truncate"]);
7785
+ async function mayChange(entry, path, req) {
7786
+ const { mayChange: mayChange2 } = entry.fs;
7787
+ if (!mayChange2) return;
7788
+ const { op } = req;
7789
+ if (CONTENT.has(op) && req.handle === void 0) return mayChange2.call(entry.fs, path, true);
7790
+ if (!CHANGING.has(op)) return;
7791
+ await mayChange2.call(entry.fs, path, op === "utimes" || op === "chmod" || op === "chown");
7792
+ if (op === "rename" || op === "link") {
7793
+ await mayChange2.call(entry.fs, entry.fs.resolvePath(entry.cwd, req.arg2 ?? ""), false);
7794
+ }
7795
+ }
7681
7796
  async function guarded(entry, path, req) {
7682
7797
  const g = guardOf(entry);
7683
7798
  if (!g) return void 0;
7684
7799
  if (LOOKS.has(req.op) && await entry.holdsKept?.(path)) return void 0;
7685
7800
  try {
7801
+ await mayChange(entry, path, req);
7686
7802
  await guard(g, path, req, entry.cwd);
7687
7803
  return void 0;
7688
7804
  } catch (err) {
@@ -12347,6 +12463,7 @@ var WasmProcess = class {
12347
12463
  throw Object.assign(new Error(alias.refused), { code: alias.refused });
12348
12464
  if (alias !== void 0) return this.openProc(req, alias);
12349
12465
  await refuseReadonly(this.options.fs, req.path, req.flags, req);
12466
+ if (this.writesAt(req)) await this.options.fs.mayChange?.(req.path, !req.exclusive);
12350
12467
  await this.mayOpen(req);
12351
12468
  const fd = this.fds.install(heldFile(), 3);
12352
12469
  try {
@@ -13217,6 +13334,7 @@ function holdingToken(opts, holds, caller) {
13217
13334
  return mintSyncFsToken({
13218
13335
  ...opts.owners ? caller : {},
13219
13336
  ...opts.dac ? { dac: opts.dac, pid: opts.pid, created: caller.created } : {},
13337
+ ...opts.fresh ? { fresh: (path) => opts.fresh?.(path, caller.umask()) } : {},
13220
13338
  fs: opts.fs,
13221
13339
  cwd: opts.cwd,
13222
13340
  ...opts.statfs ? { statfs: opts.statfs } : {},
@@ -16158,6 +16276,7 @@ var Launcher = class {
16158
16276
  described = /* @__PURE__ */ new Map();
16159
16277
  creds = /* @__PURE__ */ new Map();
16160
16278
  tags = /* @__PURE__ */ new Map();
16279
+ freshModules = new FreshModules();
16161
16280
  granted = /* @__PURE__ */ new Map();
16162
16281
  users;
16163
16282
  sudoer;
@@ -16228,7 +16347,8 @@ var Launcher = class {
16228
16347
  changed: this.watchers.changed.bind(this.watchers),
16229
16348
  owners: this.owners
16230
16349
  });
16231
- this.base = this.watchers.wrap(this.mounts.wrap(options.fs));
16350
+ const watched = this.watchers.wrap(this.mounts.wrap(options.fs));
16351
+ this.base = this.owners ? this.freshModules.wrap(watched) : watched;
16232
16352
  this.createWorker = options.createWorker;
16233
16353
  this.createDriverWorker = options.createDriverWorker;
16234
16354
  this.media = options.media ?? memoryMedia();
@@ -16631,6 +16751,7 @@ var Launcher = class {
16631
16751
  ...req.ignored ? { ignored: req.ignored } : {},
16632
16752
  ...req.umask !== void 0 ? { umask: req.umask } : {},
16633
16753
  cred: req.cred,
16754
+ ...this.owners && req.program.abi === "wasi" ? { fresh: (path, umask) => this.freshModules.add(path, umask, pid) } : {},
16634
16755
  ...this.owners ? { owners: true } : {},
16635
16756
  sealed: this.sealed,
16636
16757
  clipboard: this.clipboard,
@@ -16693,6 +16814,7 @@ var Launcher = class {
16693
16814
  (state) => state === "stopped" ? this.stopped.add(pid) : this.stopped.delete(pid)
16694
16815
  );
16695
16816
  void handle.exited.then(() => {
16817
+ this.freshModules.forget(pid);
16696
16818
  const spent = handle.times?.();
16697
16819
  if (spent) this.spent.set(pid, spent);
16698
16820
  if (spent) addTimes(this.imageTimes, this.jobs.shown(pid), spent);
@@ -17359,8 +17481,9 @@ var Launcher = class {
17359
17481
  return this.writers;
17360
17482
  }
17361
17483
  writerStack() {
17484
+ const watched = this.watchers.wrap(this.mounts.wrap(this.unguardedRoot));
17362
17485
  const fs = withCommandDirs(
17363
- this.watchers.wrap(this.mounts.wrap(this.unguardedRoot)),
17486
+ this.owners ? this.freshModules.wrap(watched) : watched,
17364
17487
  async () => new Set((await this.commands()).keys()),
17365
17488
  (dir) => this.userCommandDir(dir),
17366
17489
  this.owners