@ai-ecoverse/slicc-kernel 1.34.0 → 1.35.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
@@ -339,14 +339,6 @@ function sinkFile(onData) {
339
339
  }
340
340
  });
341
341
  }
342
- function nullFile() {
343
- return new OpenFile({
344
- read: async () => new Uint8Array(0),
345
- write: async (bytes) => bytes.length,
346
- close: () => {
347
- }
348
- });
349
- }
350
342
  function written(device, bytes) {
351
343
  if (device === "full" && bytes.length > 0) throw new KernelError("ENOSPC");
352
344
  return bytes.length;
@@ -2253,6 +2245,9 @@ var OpfsFs = class {
2253
2245
  ctimeMs: now
2254
2246
  }));
2255
2247
  }
2248
+ async realpath(path, follow) {
2249
+ return (await this.locate(path, follow)).path;
2250
+ }
2256
2251
  async readlink(path) {
2257
2252
  const found = await this.locate(path, false);
2258
2253
  if (found.link) return found.link.link;
@@ -3311,6 +3306,7 @@ function withCommandDirs(fs, names) {
3311
3306
  rename: (from, to) => fs.rename(from, to),
3312
3307
  symlink: (target, path) => fs.symlink(target, path),
3313
3308
  readlink: (path) => fs.readlink(path),
3309
+ ...fs.realpath ? { realpath: fs.realpath.bind(fs) } : {},
3314
3310
  chmod: (path, mode) => fs.chmod(path, mode),
3315
3311
  utimes: (path, atime, mtime) => fs.utimes(path, atime, mtime),
3316
3312
  lutimes: (path, atime, mtime) => lutimesOf(fs, path, atime, mtime),
@@ -3519,7 +3515,7 @@ var ChildTable = class {
3519
3515
  captured.set(n, chunks2);
3520
3516
  return sinkFile((bytes) => chunks2.push(bytes));
3521
3517
  }
3522
- return nullFile();
3518
+ return deviceFile("null");
3523
3519
  }
3524
3520
  async wait(pid, nohang, signal, flags = {}) {
3525
3521
  let interrupt;
@@ -4308,6 +4304,12 @@ var MountFs = class {
4308
4304
  this.table.forget(found.mount, normalizePath(path));
4309
4305
  await found.mount.conn.call({ op: "symlink", target, path: found.rel });
4310
4306
  }
4307
+ async realpath(path, follow) {
4308
+ if (this.at(path) || !this.base.realpath) throw errnoError("ENOSYS", path);
4309
+ const real = await this.base.realpath(path, follow);
4310
+ if (this.at(real)) throw errnoError("ENOSYS", path);
4311
+ return real;
4312
+ }
4311
4313
  async readlink(path) {
4312
4314
  const found = this.at(path);
4313
4315
  if (!found) return this.base.readlink(path);
@@ -7282,9 +7284,21 @@ var VfsNodes = class {
7282
7284
  }
7283
7285
  async entryKey(path) {
7284
7286
  const parent = parentOf5(path);
7285
- const dir = await realDir(this.fs, parent).catch(() => parent);
7286
- const name2 = path.slice(path.lastIndexOf("/") + 1);
7287
- return dir === "/" ? `/${name2}` : `${dir}/${name2}`;
7287
+ const dir = await this.real(parent, true, () => realDir(this.fs, parent));
7288
+ return joinName(dir, path.slice(path.lastIndexOf("/") + 1));
7289
+ }
7290
+ targetKey(path) {
7291
+ return this.real(path, true, () => realTarget(this.fs, path));
7292
+ }
7293
+ async real(path, follow, walk) {
7294
+ if (this.fs.realpath) {
7295
+ try {
7296
+ return await this.fs.realpath(path, follow);
7297
+ } catch (err) {
7298
+ if (errCode(err) === "ELOOP") throw err;
7299
+ }
7300
+ }
7301
+ return walk();
7288
7302
  }
7289
7303
  createExclusive(path) {
7290
7304
  return this.onEntry(path, async () => {
@@ -7379,10 +7393,9 @@ function parentOf5(path) {
7379
7393
  async function linkOf(fs, path) {
7380
7394
  return fs.readlink?.(path).catch(() => void 0);
7381
7395
  }
7382
- async function realDir(fs, dir) {
7396
+ async function realDir(fs, dir, budget = { hops: 0 }) {
7383
7397
  const queue = dir.split("/").filter(Boolean);
7384
7398
  let at = "/";
7385
- let hops = 0;
7386
7399
  while (queue.length > 0) {
7387
7400
  const part = queue.shift();
7388
7401
  if (part === ".") continue;
@@ -7391,28 +7404,41 @@ async function realDir(fs, dir) {
7391
7404
  continue;
7392
7405
  }
7393
7406
  const next = at === "/" ? `/${part}` : `${at}/${part}`;
7394
- const link2 = hops < MAX_LINKS5 ? await linkOf(fs, next) : void 0;
7407
+ const link2 = await linkOf(fs, next);
7395
7408
  if (link2 === void 0) {
7396
7409
  at = next;
7397
7410
  continue;
7398
7411
  }
7399
- hops++;
7412
+ if (budget.hops >= MAX_LINKS5) throw fsError("ELOOP", dir);
7413
+ budget.hops++;
7400
7414
  queue.unshift(...link2.split("/").filter(Boolean));
7401
7415
  if (link2.startsWith("/")) at = "/";
7402
7416
  }
7403
7417
  return at;
7404
7418
  }
7405
- async function targetDir(fs, path) {
7406
- let dir = await realDir(fs, parentOf5(path));
7419
+ function errCode(err) {
7420
+ return err?.code;
7421
+ }
7422
+ function joinName(dir, name2) {
7423
+ return dir === "/" ? `/${name2}` : `${dir}/${name2}`;
7424
+ }
7425
+ async function realTarget(fs, path) {
7426
+ const budget = { hops: 0 };
7427
+ let dir = await realDir(fs, parentOf5(path), budget);
7407
7428
  let name2 = path.slice(path.lastIndexOf("/") + 1);
7408
- for (let hops = 0; hops < MAX_LINKS5; hops++) {
7409
- const link2 = await linkOf(fs, dir === "/" ? `/${name2}` : `${dir}/${name2}`);
7410
- if (link2 === void 0) return dir;
7411
- const target = link2.startsWith("/") ? link2 : `${dir}/${link2}`;
7412
- dir = await realDir(fs, parentOf5(target));
7429
+ for (; ; ) {
7430
+ const link2 = await linkOf(fs, joinName(dir, name2));
7431
+ if (link2 === void 0) break;
7432
+ if (budget.hops >= MAX_LINKS5) throw fsError("ELOOP", path);
7433
+ budget.hops++;
7434
+ const target = link2.startsWith("/") ? link2 : joinName(dir, link2);
7435
+ dir = await realDir(fs, parentOf5(target), budget);
7413
7436
  name2 = target.slice(target.lastIndexOf("/") + 1);
7414
7437
  }
7415
- return dir;
7438
+ return joinName(dir, name2);
7439
+ }
7440
+ async function targetDir(fs, path) {
7441
+ return parentOf5(await realTarget(fs, path).catch(() => path));
7416
7442
  }
7417
7443
  async function refuseReadonly(fs, path, flags, opts = {}) {
7418
7444
  const writes = (flags & O_ACCMODE) !== 0 || opts.truncate === true;
@@ -7431,13 +7457,14 @@ function keepingOpen(fs, nodes) {
7431
7457
  return {
7432
7458
  ...fs,
7433
7459
  async rm(path, options) {
7434
- const at = fs.resolvePath("/", path);
7460
+ const at = await nodes.entryKey(fs.resolvePath("/", path));
7435
7461
  await nodes.unlinking(at);
7436
7462
  await fs.rm(path, options);
7437
7463
  nodes.unlinked(at);
7438
7464
  },
7439
- rename(from, to) {
7440
- const [a, b] = [fs.resolvePath("/", from), fs.resolvePath("/", to)];
7465
+ async rename(from, to) {
7466
+ const a = await nodes.entryKey(fs.resolvePath("/", from));
7467
+ const b = await nodes.entryKey(fs.resolvePath("/", to));
7441
7468
  return nodes.onEntry(b, async () => {
7442
7469
  await nodes.unlinking(b);
7443
7470
  await fs.rename(from, to);
@@ -7583,10 +7610,12 @@ var SYSCALL_OPS = /* @__PURE__ */ new Set([
7583
7610
  "fd-cloexec",
7584
7611
  "fd-list",
7585
7612
  "proc-alarm",
7613
+ "proc-umask",
7586
7614
  "dl-log",
7587
7615
  "fd-renumber",
7588
7616
  "fd-promote",
7589
7617
  "fd-open-tty",
7618
+ "fd-tty-names",
7590
7619
  "tty-get",
7591
7620
  "tty-set",
7592
7621
  "tty-winsz",
@@ -7620,6 +7649,7 @@ function isWasmSyscall(req) {
7620
7649
  return typeof op === "string" && SYSCALL_OPS.has(op);
7621
7650
  }
7622
7651
  var MAX_READ = 1024 * 1024;
7652
+ var DEFAULT_UMASK = 18;
7623
7653
  var DYING = { ok: false, errno: "EINTR", message: "the process is being killed" };
7624
7654
  var HOSTS_ONLY = new Resolver({ routes: new Routes() });
7625
7655
  var WasmProcess = class {
@@ -7630,6 +7660,7 @@ var WasmProcess = class {
7630
7660
  inherited = 0;
7631
7661
  interrupt = new AbortController();
7632
7662
  dying = false;
7663
+ umask = DEFAULT_UMASK;
7633
7664
  execChild;
7634
7665
  execTermsig;
7635
7666
  stopped = 0;
@@ -7647,6 +7678,7 @@ var WasmProcess = class {
7647
7678
  this.fds = fds;
7648
7679
  this.options = options;
7649
7680
  this.inherited = options.ignored ?? 0;
7681
+ this.umask = options.umask ?? DEFAULT_UMASK;
7650
7682
  this.children = new ChildTable(fds, options.spawner, options.forker);
7651
7683
  this.nodes = options.nodes ?? new VfsNodes(options.fs);
7652
7684
  if (!options.nodes) options.openFiles?.add(this.nodes);
@@ -7719,6 +7751,11 @@ var WasmProcess = class {
7719
7751
  return result;
7720
7752
  }
7721
7753
  }
7754
+ setUmask(mask) {
7755
+ const old = this.umask;
7756
+ if (mask !== void 0) this.umask = mask & 511;
7757
+ return old;
7758
+ }
7722
7759
  die() {
7723
7760
  if (this.dying) return;
7724
7761
  this.dying = true;
@@ -7789,9 +7826,21 @@ var WasmProcess = class {
7789
7826
  await refuseReadonly(this.options.fs, req.path, req.flags, req);
7790
7827
  const fd = this.fds.install(heldFile(), 3);
7791
7828
  try {
7792
- if (req.exclusive) await this.nodes.createExclusive(req.path);
7793
- this.fds.installAt(fd, this.openVfsFile(req));
7794
- if (req.existing && !await present(this.options.fs, req.path, true)) {
7829
+ const nodes = this.nodes;
7830
+ const path = req.orphan ? req.path : req.exclusive ? await nodes.entryKey(req.path) : await nodes.targetKey(req.path);
7831
+ const open = { ...req, path };
7832
+ if (req.exclusive) {
7833
+ await nodes.createExclusive(path);
7834
+ this.fds.installAt(fd, this.openVfsFile(open));
7835
+ } else if (req.create) {
7836
+ await nodes.onEntry(path, async () => {
7837
+ this.fds.installAt(fd, this.openVfsFile(open));
7838
+ await this.fds.get(fd).file.stat?.();
7839
+ });
7840
+ } else {
7841
+ this.fds.installAt(fd, this.openVfsFile(open));
7842
+ }
7843
+ if (req.existing && !await present(this.options.fs, path, true)) {
7795
7844
  throw new KernelError("ENOENT");
7796
7845
  }
7797
7846
  } catch (err) {
@@ -7870,7 +7919,7 @@ var WasmProcess = class {
7870
7919
  case "fd-reserve":
7871
7920
  return { ok: true, kind: "json", json: this.reserve(req.fd, req.min, req.meta) };
7872
7921
  case "fd-promote":
7873
- this.promote(req);
7922
+ await this.promote(req);
7874
7923
  return { ok: true, kind: "void" };
7875
7924
  case "fd-renumber":
7876
7925
  if (req.from !== req.to) {
@@ -7883,6 +7932,8 @@ var WasmProcess = class {
7883
7932
  if (!tty) throw new KernelError("ENXIO");
7884
7933
  return { ok: true, kind: "json", json: this.fds.install(tty.file(), 3) };
7885
7934
  }
7935
+ case "fd-tty-names":
7936
+ return { ok: true, kind: "json", json: this.options.jobs?.terminalNames() ?? [] };
7886
7937
  case "fd-select": {
7887
7938
  const { read, write, timeoutMs } = req;
7888
7939
  const signal = this.blockingSignal();
@@ -7904,10 +7955,14 @@ var WasmProcess = class {
7904
7955
  async vfsSyscall(req) {
7905
7956
  if ("path" in req || "from" in req) {
7906
7957
  const nodes = this.nodes;
7907
- if (req.op === "fd-path-flush") await nodes.flush(req.path);
7908
- else if (req.op === "fd-path-unlinking") await nodes.unlinking(req.path);
7909
- else if (req.op === "fd-path-unlinked") nodes.unlinked(req.path);
7910
- else if (req.op === "fd-path-renamed") nodes.renamed(req.from, req.to);
7958
+ if (req.op === "fd-path-flush") {
7959
+ await nodes.flush(await nodes.targetKey(req.path).catch(() => req.path));
7960
+ } else if (req.op === "fd-path-unlinking")
7961
+ await nodes.unlinking(await nodes.entryKey(req.path));
7962
+ else if (req.op === "fd-path-unlinked") nodes.unlinked(await nodes.entryKey(req.path));
7963
+ else if (req.op === "fd-path-renamed") {
7964
+ nodes.renamed(await nodes.entryKey(req.from), await nodes.entryKey(req.to));
7965
+ }
7911
7966
  return { ok: true, kind: "void" };
7912
7967
  }
7913
7968
  const file = this.fds.get(req.fd).file;
@@ -7928,17 +7983,19 @@ var WasmProcess = class {
7928
7983
  return { ok: true, kind: "json", json: await file.stat() };
7929
7984
  }
7930
7985
  }
7931
- promote(req) {
7986
+ async promote(req) {
7932
7987
  if (!this.fds.get(req.fd).file.held) throw new KernelError("EBADF");
7933
7988
  if (req.share !== void 0) {
7934
7989
  this.fds.dup2(req.share, req.fd);
7935
7990
  return;
7936
7991
  }
7937
7992
  if (req.path === void 0) throw new KernelError("EINVAL");
7993
+ const path = req.orphan ? req.path : await this.nodes.targetKey(req.path);
7994
+ if (!this.fds.get(req.fd).file.held) throw new KernelError("EBADF");
7938
7995
  const file = vfsFile(
7939
7996
  this.options.fs,
7940
7997
  {
7941
- path: req.path,
7998
+ path,
7942
7999
  flags: req.flags ?? 0,
7943
8000
  position: req.position ?? 0,
7944
8001
  ...req.contents !== void 0 ? { contents: req.contents } : {},
@@ -8114,6 +8171,8 @@ var WasmProcess = class {
8114
8171
  case "proc-alarm":
8115
8172
  this.setAlarm(req.sig, req.firstMs ?? req.ms, req.repeat ? req.ms : 0, req.timer);
8116
8173
  return { ok: true, kind: "void" };
8174
+ case "proc-umask":
8175
+ return { ok: true, kind: "json", json: this.setUmask(req.mask) };
8117
8176
  case "dl-log":
8118
8177
  if (req.append) this.dlLog.push(req.append);
8119
8178
  return { ok: true, kind: "json", json: this.dlLog.slice(req.from) };
@@ -8263,7 +8322,7 @@ var Dying = class {
8263
8322
  return [typeof reported === "number" ? reported : CRASHED, void 0];
8264
8323
  }
8265
8324
  };
8266
- function processInit(opts, sab) {
8325
+ function processInit(opts, sab, umask) {
8267
8326
  const base = {
8268
8327
  type: WASM_PROCESS_INIT,
8269
8328
  pid: opts.shownPid ?? opts.pid,
@@ -8272,6 +8331,7 @@ function processInit(opts, sab) {
8272
8331
  env: opts.env,
8273
8332
  cwd: opts.cwd,
8274
8333
  sab,
8334
+ umask,
8275
8335
  ...opts.ppid !== void 0 ? { ppid: opts.ppid } : {}
8276
8336
  };
8277
8337
  if (opts.program.abi === "js") {
@@ -8283,11 +8343,17 @@ function processInit(opts, sab) {
8283
8343
  ...opts.fork ? { fork: opts.fork } : { fds: inheritedFds(opts.fds) }
8284
8344
  };
8285
8345
  }
8346
+ function inherited(opts) {
8347
+ return {
8348
+ ...opts.ignored ? { ignored: opts.ignored } : {},
8349
+ ...opts.umask !== void 0 ? { umask: opts.umask } : {}
8350
+ };
8351
+ }
8286
8352
  function spawnWasmProcess(opts) {
8287
8353
  const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
8288
8354
  const header3 = new Int32Array(sab, 0, SAB_HEADER_I32);
8289
8355
  const process = new WasmProcess(opts.pid, opts.fds, {
8290
- ...opts.ignored ? { ignored: opts.ignored } : {},
8356
+ ...inherited(opts),
8291
8357
  ...opts.identity ? { identity: opts.identity } : {},
8292
8358
  ...opts.onSyscall ? { onSyscall: opts.onSyscall } : {},
8293
8359
  spawner: opts.spawner,
@@ -8421,7 +8487,7 @@ function spawnWasmProcess(opts) {
8421
8487
  };
8422
8488
  tw.postMessage(tinit);
8423
8489
  };
8424
- const init = processInit(opts, sab);
8490
+ const init = processInit(opts, sab, process.umask);
8425
8491
  worker.postMessage(init, opts.fork ? [opts.fork.memory.buffer] : []);
8426
8492
  const signal = (sig) => {
8427
8493
  if (process.signal(sig) !== "terminate") return;
@@ -8439,6 +8505,7 @@ function spawnWasmProcess(opts) {
8439
8505
  onState: (listener) => process.onState(listener),
8440
8506
  memory: () => Atomics.load(header3, SAB_I_MEMORY) * 65536,
8441
8507
  ignoredSignals: (fork) => process.inheritable(fork),
8508
+ umask: () => process.umask,
8442
8509
  writesBack: () => opts.program.abi === "wasi" && !done4
8443
8510
  };
8444
8511
  }
@@ -8544,8 +8611,13 @@ var JobTable = class {
8544
8611
  return id;
8545
8612
  }
8546
8613
  terminalNamed(name2) {
8547
- const known = /* @__PURE__ */ new Set([...this.terminals.values(), ...this.foreground.keys()]);
8548
- return [...known].find((tty) => tty.name === name2);
8614
+ return this.knownTerminals().find((tty) => tty.name === name2);
8615
+ }
8616
+ terminalNames() {
8617
+ return this.knownTerminals().flatMap((tty) => tty.name ? [tty.name] : []);
8618
+ }
8619
+ knownTerminals() {
8620
+ return [.../* @__PURE__ */ new Set([...this.terminals.values(), ...this.foreground.keys()])];
8549
8621
  }
8550
8622
  controllingTerminal(pid) {
8551
8623
  const member = this.members.get(pid);
@@ -10188,6 +10260,7 @@ var Launcher = class {
10188
10260
  this.settling.syscall(pid, call.op);
10189
10261
  },
10190
10262
  ...req.ignored ? { ignored: req.ignored } : {},
10263
+ ...req.umask !== void 0 ? { umask: req.umask } : {},
10191
10264
  program: req.program,
10192
10265
  argv0: req.argv0,
10193
10266
  args: req.args,
@@ -10279,7 +10352,8 @@ var Launcher = class {
10279
10352
  ...described,
10280
10353
  started: (this.described.get(root.pid) ?? described).started,
10281
10354
  state: this.processes.has(member.pid) ? "S" : "Z",
10282
- memory: this.processes.get(member.pid)?.memory() ?? 0
10355
+ memory: this.processes.get(member.pid)?.memory() ?? 0,
10356
+ umask: this.umaskOf(member.pid)
10283
10357
  });
10284
10358
  }
10285
10359
  return listed;
@@ -10301,6 +10375,7 @@ var Launcher = class {
10301
10375
  report,
10302
10376
  ppid,
10303
10377
  ignored: this.ignoredBy(ppid),
10378
+ umask: this.umaskOf(ppid),
10304
10379
  ...exec
10305
10380
  });
10306
10381
  deciding?.attach();
@@ -10345,7 +10420,8 @@ var Launcher = class {
10345
10420
  fds,
10346
10421
  ppid,
10347
10422
  fork: state,
10348
- ignored: this.ignoredBy(ppid, true)
10423
+ ignored: this.ignoredBy(ppid, true),
10424
+ umask: this.umaskOf(ppid)
10349
10425
  })
10350
10426
  );
10351
10427
  }
@@ -10354,6 +10430,9 @@ var Launcher = class {
10354
10430
  const foreground = () => this.jobs.tcgetpgrp(tty, fallback);
10355
10431
  this.settling.deliver(sig, pgid, send, tty.reading ? void 0 : foreground);
10356
10432
  }
10433
+ umaskOf(pid) {
10434
+ return this.processes.get(pid)?.umask?.() ?? DEFAULT_UMASK;
10435
+ }
10357
10436
  ignoredBy(pid, fork = false) {
10358
10437
  return this.processes.get(pid)?.ignoredSignals(fork) ?? 0;
10359
10438
  }
@@ -10600,7 +10679,7 @@ var Launcher = class {
10600
10679
  return { status: NOT_FOUND, stdout: concat5(out), stderr: concat5(err) };
10601
10680
  }
10602
10681
  const fds = new FdTable();
10603
- fds.installAt(0, options.stdin ? bytesSource(options.stdin) : nullFile());
10682
+ fds.installAt(0, options.stdin ? bytesSource(options.stdin) : deviceFile("null"));
10604
10683
  fds.installAt(1, sinkFile(stdout));
10605
10684
  fds.installAt(2, sinkFile(stderr));
10606
10685
  const group = options.pgid !== void 0 ? { pgid: options.pgid } : {};
@@ -11539,10 +11618,11 @@ function hostfsFetchOf(options) {
11539
11618
  if (hostfsOrigin === void 0) return hostfsFetch ? { hostfsFetch } : {};
11540
11619
  const base = hostfsFetch ?? ((url, init) => fetch(url, init));
11541
11620
  return {
11542
- hostfsFetch: (url, init) => base(url, {
11543
- ...init,
11544
- headers: { ...init.headers, Origin: hostfsOrigin }
11545
- })
11621
+ hostfsFetch: (url, init) => {
11622
+ const headers = new Headers(init.headers);
11623
+ headers.set("Origin", hostfsOrigin);
11624
+ return base(url, { ...init, headers });
11625
+ }
11546
11626
  };
11547
11627
  }
11548
11628
  function nodeTransport() {