@ai-ecoverse/slicc-kernel 1.39.2 → 1.40.0

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.
@@ -2730,13 +2730,13 @@ function describeInherited(Fs, sys, streams, livePath, actions = []) {
2730
2730
  if (from) table.set(target, { stream: from.stream, cloexec: false });
2731
2731
  else table.delete(target);
2732
2732
  }
2733
- const slots = /* @__PURE__ */ new Map();
2733
+ const slots2 = /* @__PURE__ */ new Map();
2734
2734
  for (const [fd, { stream, cloexec }] of table) {
2735
- if (fd > 2 && !cloexec) slots.set(fd, stream);
2735
+ if (fd > 2 && !cloexec) slots2.set(fd, stream);
2736
2736
  }
2737
2737
  const promote = vfsPromoter(Fs, sys, streams, livePath);
2738
2738
  const out = [];
2739
- for (const [fd, stream] of slots) {
2739
+ for (const [fd, stream] of slots2) {
2740
2740
  promote(stream);
2741
2741
  const slot = inheritedSlot(fd, stream);
2742
2742
  if (slot) out.push(slot);
@@ -2928,6 +2928,7 @@ function createProcessKernel(deps) {
2928
2928
  if (!stream) return { none: true };
2929
2929
  promote?.(stream);
2930
2930
  if (stream.sliccKernelFd !== void 0) return { fd: stream.sliccKernelFd };
2931
+ if (((stream.node?.mode ?? 0) & S_IFMT) === S_IFDIR2 && stream.path) return { dir: stream.path };
2931
2932
  const device2 = deviceOfStream(stream);
2932
2933
  if (device2) return device2;
2933
2934
  return n === 0 ? { input: drain(Fs, stream) } : { capture: true };
@@ -3071,12 +3072,14 @@ function createProcessKernel(deps) {
3071
3072
  }
3072
3073
  };
3073
3074
  }
3074
- var POLLIN2, POLLOUT2, POLLERR2, POLLHUP2, POLLNVAL, SELECT_SLICE_MS, WUNTRACED, WCONTINUED;
3075
+ var S_IFMT, S_IFDIR2, POLLIN2, POLLOUT2, POLLERR2, POLLHUP2, POLLNVAL, SELECT_SLICE_MS, WUNTRACED, WCONTINUED;
3075
3076
  var init_process_children = __esm({
3076
3077
  "src/process/process-children.ts"() {
3077
3078
  "use strict";
3078
3079
  init_process_fork();
3079
3080
  init_wasi_errno();
3081
+ S_IFMT = 61440;
3082
+ S_IFDIR2 = 16384;
3080
3083
  POLLIN2 = 1;
3081
3084
  POLLOUT2 = 4;
3082
3085
  POLLERR2 = 8;
@@ -3785,7 +3788,7 @@ function kernelSys(transport) {
3785
3788
  kind(fd) {
3786
3789
  return json(call2({ op: "fd-info", fd }, `fd-info ${fd}`))?.kind;
3787
3790
  },
3788
- device(fd) {
3791
+ heldMeta(fd) {
3789
3792
  return json(call2({ op: "fd-info", fd }, `fd-info ${fd}`)).meta;
3790
3793
  },
3791
3794
  size(fd) {
@@ -3849,9 +3852,15 @@ function wireKernelFd(Fs, streams, entry) {
3849
3852
  }
3850
3853
  function openDevice(Fs, fd, meta) {
3851
3854
  const flags = meta.access === "read" ? O_RDONLY : meta.access === "write" ? O_WRONLY3 : O_RDWR3;
3855
+ return openAt(Fs, fd, `/dev/${meta.device}`, flags);
3856
+ }
3857
+ function openHeld(Fs, fd, meta) {
3858
+ return "dir" in meta ? openAt(Fs, fd, meta.dir, O_RDONLY | O_DIRECTORY) : openDevice(Fs, fd, meta);
3859
+ }
3860
+ function openAt(Fs, fd, path, flags) {
3852
3861
  let stream;
3853
3862
  try {
3854
- stream = Fs.open(`/dev/${meta.device}`, flags);
3863
+ stream = Fs.open(path, flags);
3855
3864
  } catch {
3856
3865
  return false;
3857
3866
  }
@@ -3866,8 +3875,8 @@ function wireKernelStdio(Fs, streams, sys) {
3866
3875
  const stream = Fs.getStream(fd);
3867
3876
  if (!stream) continue;
3868
3877
  const kind = sys?.kind?.(fd);
3869
- const device2 = kind === "device" ? sys?.device?.(fd) : void 0;
3870
- if (device2 && openDevice(Fs, fd, device2)) continue;
3878
+ const meta = kind === "device" || kind === "held" ? sys?.heldMeta?.(fd) : void 0;
3879
+ if (meta && openHeld(Fs, fd, meta)) continue;
3871
3880
  if (kind && PLACED.has(kind)) {
3872
3881
  const { flags } = stream;
3873
3882
  Fs.closeStream(fd);
@@ -4119,7 +4128,7 @@ function runMain(running, init) {
4119
4128
  return status2;
4120
4129
  }
4121
4130
  }
4122
- var FS_OPS, O_RDONLY, O_WRONLY3, O_RDWR3, PLACED, GLUE_TRAILER, evaluateGlue, EVAL_BLOCKED;
4131
+ var FS_OPS, O_RDONLY, O_WRONLY3, O_RDWR3, O_DIRECTORY, PLACED, GLUE_TRAILER, evaluateGlue, EVAL_BLOCKED;
4123
4132
  var init_process_runtime = __esm({
4124
4133
  "src/process/process-runtime.ts"() {
4125
4134
  "use strict";
@@ -4144,6 +4153,7 @@ var init_process_runtime = __esm({
4144
4153
  O_RDONLY = 0;
4145
4154
  O_WRONLY3 = 1;
4146
4155
  O_RDWR3 = 2;
4156
+ O_DIRECTORY = 65536;
4147
4157
  PLACED = /* @__PURE__ */ new Set(["stream", "file", "socket"]);
4148
4158
  GLUE_TRAILER = [
4149
4159
  "if (typeof ENV !== 'undefined') Object.assign(ENV, Module.sliccEnv);",
@@ -4507,10 +4517,10 @@ var init_wasi_files = __esm({
4507
4517
  readable;
4508
4518
  writable;
4509
4519
  append;
4510
- constructor(buffer, readable, writable, append) {
4520
+ constructor(buffer, readable2, writable2, append) {
4511
4521
  this.buffer = buffer;
4512
- this.readable = readable;
4513
- this.writable = writable;
4522
+ this.readable = readable2;
4523
+ this.writable = writable2;
4514
4524
  this.append = append;
4515
4525
  }
4516
4526
  get path() {
@@ -4592,9 +4602,9 @@ function entryOf(info) {
4592
4602
  function openAccess(existing, oflags, rights) {
4593
4603
  const readonly = existing?.readonly === true;
4594
4604
  const mutating = readonly ? OFLAGS.TRUNC : OFLAGS.CREAT | OFLAGS.TRUNC;
4595
- const writable = (rights & RIGHTS.FD_WRITE) !== 0n || (oflags & mutating) !== 0;
4596
- if (writable && readonly) throw new WasiError("EROFS");
4597
- return { readable: (rights & RIGHTS.FD_READ) !== 0n || !writable, writable };
4605
+ const writable2 = (rights & RIGHTS.FD_WRITE) !== 0n || (oflags & mutating) !== 0;
4606
+ if (writable2 && readonly) throw new WasiError("EROFS");
4607
+ return { readable: (rights & RIGHTS.FD_READ) !== 0n || !writable2, writable: writable2 };
4598
4608
  }
4599
4609
  function promoteRequest(fd, f, handed) {
4600
4610
  const orphan = f.buffer.isOrphan();
@@ -4640,7 +4650,7 @@ var init_wasi_fds = __esm({
4640
4650
  this.fs = fs;
4641
4651
  }
4642
4652
  setup(cwd, inherited, root = false) {
4643
- for (const fd of [0, 1, 2]) this.table.set(fd, kernelEntry2());
4653
+ for (const fd of [0, 1, 2]) this.table.set(fd, this.stdioEntry(fd));
4644
4654
  const preopens = this.preopens(cwd, root);
4645
4655
  const top = 3 + preopens.length;
4646
4656
  for (const { fd, kind, flags, device: device2 } of inherited) {
@@ -4727,6 +4737,15 @@ var init_wasi_fds = __esm({
4727
4737
  const gen = Atomics.add(this.shared, GEN, 1) + 1;
4728
4738
  if (gen - 1 === this.seen) this.seen = gen;
4729
4739
  }
4740
+ stdioEntry(fd) {
4741
+ let info;
4742
+ try {
4743
+ info = this.kernel.call({ op: "fd-info", fd });
4744
+ } catch {
4745
+ return kernelEntry2();
4746
+ }
4747
+ return info?.meta && "dir" in info.meta ? { type: "dir", path: info.meta.dir } : kernelEntry2();
4748
+ }
4730
4749
  fetch(fd) {
4731
4750
  let info;
4732
4751
  try {
@@ -5022,7 +5041,7 @@ var init_wasi_fds = __esm({
5022
5041
  return this.install({ type: "file", file: this.file(path, s, oflags, rights, fdflags) });
5023
5042
  }
5024
5043
  file(path, existing, oflags, rights, fdflags) {
5025
- const { readable, writable } = openAccess(existing, oflags, rights);
5044
+ const { readable: readable2, writable: writable2 } = openAccess(existing, oflags, rights);
5026
5045
  let buffer = this.buffers.get(path);
5027
5046
  if (buffer) {
5028
5047
  if (oflags & OFLAGS.TRUNC) buffer.truncate(0);
@@ -5037,12 +5056,12 @@ var init_wasi_fds = __esm({
5037
5056
  this.fs.hold?.(path, true, true);
5038
5057
  }
5039
5058
  buffer.opens++;
5040
- return new LocalFile(buffer, readable, writable, (fdflags & FDFLAGS.APPEND) !== 0);
5059
+ return new LocalFile(buffer, readable2, writable2, (fdflags & FDFLAGS.APPEND) !== 0);
5041
5060
  }
5042
5061
  kernelFile(path, existing, oflags, rights, fdflags) {
5043
- const { readable, writable } = openAccess(existing, oflags, rights);
5062
+ const { readable: readable2, writable: writable2 } = openAccess(existing, oflags, rights);
5044
5063
  const append = (fdflags & FDFLAGS.APPEND) !== 0;
5045
- const flags = (writable ? readable ? O_RDWR4 : O_WRONLY4 : 0) | (append ? O_APPEND : 0);
5064
+ const flags = (writable2 ? readable2 ? O_RDWR4 : O_WRONLY4 : 0) | (append ? O_APPEND : 0);
5046
5065
  const made = !existing && this.createNew(path, oflags);
5047
5066
  const truncate = made || (oflags & OFLAGS.TRUNC) !== 0;
5048
5067
  const fd = this.kernel.sys.openVfs(path, flags, 0, truncate ? { truncate } : {});
@@ -6824,8 +6843,8 @@ var init_wasix_process = __esm({
6824
6843
  ];
6825
6844
  return { stdio, inherit, cwd, opened };
6826
6845
  }
6827
- applyFdOp(op, slots, cwd) {
6828
- const { map, nulls, opened } = slots;
6846
+ applyFdOp(op, slots2, cwd) {
6847
+ const { map, nulls, opened } = slots2;
6829
6848
  const { fds } = this.host;
6830
6849
  const point = (fd, kfd) => {
6831
6850
  if (kfd === void 0) {
@@ -8188,6 +8207,17 @@ var init_async_sab = __esm({
8188
8207
  });
8189
8208
 
8190
8209
  // src/process/js/js-kernel.ts
8210
+ function untilAborted(work, signal) {
8211
+ if (!signal) return work;
8212
+ return new Promise((resolve) => {
8213
+ const done = () => {
8214
+ signal.removeEventListener("abort", done);
8215
+ resolve();
8216
+ };
8217
+ signal.addEventListener("abort", done, { once: true });
8218
+ work.then(done, done);
8219
+ });
8220
+ }
8191
8221
  var JsCallError, JsKernel;
8192
8222
  var init_js_kernel = __esm({
8193
8223
  "src/process/js/js-kernel.ts"() {
@@ -8239,20 +8269,24 @@ var init_js_kernel = __esm({
8239
8269
  const result = await this.call(req);
8240
8270
  return result.ok && result.kind === "bytes" ? result.bytes : new Uint8Array(0);
8241
8271
  }
8242
- async blocking(req) {
8272
+ async blocking(req, signal) {
8243
8273
  for (; ; ) {
8244
8274
  const id = await this.json({ op: "async-submit", req });
8245
- const result = await this.settled(id);
8275
+ const result = await this.settled(id, signal);
8246
8276
  if (result.ok) return result;
8247
8277
  if (result.errno !== "EINTR") throw new JsCallError(result.errno, req.op);
8248
8278
  }
8249
8279
  }
8250
- async settled(id) {
8280
+ async settled(id, signal) {
8251
8281
  for (; ; ) {
8252
8282
  const seen = Atomics.load(this.header, SAB_I_ASYNC);
8253
8283
  const taken = await this.raw({ op: "async-take", id });
8254
8284
  if (taken.ok || taken.errno !== "EAGAIN") return taken;
8255
- await changed(this.header, SAB_I_ASYNC, seen, this.waitAsync);
8285
+ if (signal?.aborted) {
8286
+ await this.raw({ op: "async-cancel", id });
8287
+ throw signal.reason;
8288
+ }
8289
+ await untilAborted(changed(this.header, SAB_I_ASYNC, seen, this.waitAsync), signal);
8256
8290
  }
8257
8291
  }
8258
8292
  deliver() {
@@ -8325,6 +8359,125 @@ var init_js_kernel = __esm({
8325
8359
  }
8326
8360
  });
8327
8361
 
8362
+ // src/process/js/js-children.ts
8363
+ function exitedOf(status2) {
8364
+ const signal = status2 & 127;
8365
+ return signal ? { status: 128 + signal, signal } : { status: status2 >> 8 & 255 };
8366
+ }
8367
+ function readable(io, fd) {
8368
+ const cancelled = new AbortController();
8369
+ return new ReadableStream(
8370
+ {
8371
+ async pull(controller) {
8372
+ const chunk = await io.read(fd, void 0, cancelled.signal).catch((err) => {
8373
+ if (cancelled.signal.aborted) return void 0;
8374
+ throw err;
8375
+ });
8376
+ if (chunk === void 0) return;
8377
+ if (chunk.length > 0) {
8378
+ controller.enqueue(chunk);
8379
+ return;
8380
+ }
8381
+ controller.close();
8382
+ await io.close(fd);
8383
+ },
8384
+ cancel: () => {
8385
+ cancelled.abort();
8386
+ return io.close(fd);
8387
+ }
8388
+ },
8389
+ { highWaterMark: 0 }
8390
+ );
8391
+ }
8392
+ function writable(io, fd) {
8393
+ return new WritableStream({
8394
+ write: (chunk, controller) => io.send(fd, chunk, controller.signal),
8395
+ close: () => io.close(fd),
8396
+ abort: () => io.close(fd)
8397
+ });
8398
+ }
8399
+ function childOps(kernel, io, defaults) {
8400
+ const wait = async (pid) => {
8401
+ const r = await kernel.blocking({ op: "proc-wait", pid, nohang: false });
8402
+ const [, status2] = r.ok && r.kind === "json" ? r.json : [0, 0];
8403
+ return exitedOf(status2);
8404
+ };
8405
+ const kill = async (pid, signal = SIGTERM) => {
8406
+ await kernel.call({ op: "proc-kill", pid, sig: signal === 0 ? 0 : defaults.signal(signal) });
8407
+ };
8408
+ const childOf = (pid, mine) => {
8409
+ const [stdin, stdout, stderr] = mine;
8410
+ return {
8411
+ pid,
8412
+ ...stdin !== void 0 ? { stdin: writable(io, stdin) } : {},
8413
+ ...stdout !== void 0 ? { stdout: readable(io, stdout) } : {},
8414
+ ...stderr !== void 0 ? { stderr: readable(io, stderr) } : {},
8415
+ wait: () => wait(pid),
8416
+ kill: (signal) => kill(pid, signal)
8417
+ };
8418
+ };
8419
+ const spawn = async (o) => {
8420
+ const [file] = o.argv;
8421
+ if (file === void 0) throw new JsCallError("EINVAL", "spawn");
8422
+ const mine = [];
8423
+ const theirs = [];
8424
+ try {
8425
+ const stdio = await slots(kernel, o, mine, theirs);
8426
+ const pid = await kernel.json({
8427
+ op: "proc-spawn",
8428
+ file,
8429
+ argv: [...o.argv],
8430
+ env: { ...o.env ?? defaults.env },
8431
+ cwd: o.cwd ?? defaults.cwd,
8432
+ stdio
8433
+ });
8434
+ return childOf(pid, mine);
8435
+ } catch (err) {
8436
+ await closeAll(io, mine);
8437
+ throw err;
8438
+ } finally {
8439
+ await closeAll(io, theirs);
8440
+ }
8441
+ };
8442
+ return { spawn, wait, kill };
8443
+ }
8444
+ async function closeAll(io, fds) {
8445
+ for (const fd of fds) if (fd !== void 0) await io.close(fd).catch(() => void 0);
8446
+ }
8447
+ async function preflight(kernel, hows) {
8448
+ for (const [n, how] of hows.entries()) {
8449
+ if (how === "pipe" || how === "null") continue;
8450
+ if (how !== "inherit" && typeof how !== "number") throw new JsCallError("EINVAL", "spawn");
8451
+ await kernel.json({ op: "fd-info", fd: how === "inherit" ? n : how });
8452
+ }
8453
+ }
8454
+ async function slots(kernel, o, mine, theirs) {
8455
+ const hows = STDIO2.map((name) => o[name] ?? "inherit");
8456
+ await preflight(kernel, hows);
8457
+ const stdio = [];
8458
+ for (const [n, how] of hows.entries()) {
8459
+ if (how === "inherit") stdio.push({ fd: n });
8460
+ else if (how === "null") stdio.push({ none: true });
8461
+ else if (typeof how === "number") stdio.push({ fd: how });
8462
+ else {
8463
+ const [read, write] = await kernel.json({ op: "fd-pipe" });
8464
+ mine[n] = n === 0 ? write : read;
8465
+ theirs.push(n === 0 ? read : write);
8466
+ stdio.push({ fd: n === 0 ? read : write });
8467
+ }
8468
+ }
8469
+ return stdio;
8470
+ }
8471
+ var STDIO2, SIGTERM;
8472
+ var init_js_children = __esm({
8473
+ "src/process/js/js-children.ts"() {
8474
+ "use strict";
8475
+ init_js_kernel();
8476
+ STDIO2 = ["stdin", "stdout", "stderr"];
8477
+ SIGTERM = 15;
8478
+ }
8479
+ });
8480
+
8328
8481
  // src/process/js/js-io.ts
8329
8482
  function typeOf(info) {
8330
8483
  if (info.meta && "dir" in info.meta) return "directory";
@@ -8689,22 +8842,20 @@ function createContext(o) {
8689
8842
  infos.set(fd, got);
8690
8843
  return got;
8691
8844
  };
8692
- const read = async (fd, max = CHUNK) => {
8845
+ const read = async (fd, max = CHUNK, signal) => {
8693
8846
  index(max, "read");
8694
8847
  const emulated = readDevice(await info(fd), max, random);
8695
8848
  if (emulated) return emulated;
8696
- const r = await kernel.blocking({ op: "fd-read", fd, max: Math.min(max, MAX_IO) });
8697
- return r.ok && r.kind === "bytes" ? r.bytes : new Uint8Array(0);
8849
+ return readPipe(kernel, fd, Math.min(max, MAX_IO), signal);
8698
8850
  };
8699
- const writeAll = async (fd, data) => {
8851
+ const writeAll = async (fd, data, signal) => {
8700
8852
  const i = await info(fd);
8701
8853
  if (writeDevice(i)) return;
8702
8854
  let at = 0;
8703
8855
  while (at < data.length) {
8704
8856
  const body = data.subarray(at, at + MAX_IO);
8705
8857
  try {
8706
- const r = await kernel.blocking({ op: "fd-write", fd, body });
8707
- at += written(r, body.length);
8858
+ at += signal ? await sendSome(kernel, fd, body, signal) : written(await kernel.blocking({ op: "fd-write", fd, body }), body.length);
8708
8859
  } catch (err) {
8709
8860
  if (brokenPipe(err, i)) await kernel.call({ op: "proc-kill", pid: o.pid, sig: SIG.PIPE });
8710
8861
  throw err;
@@ -8725,7 +8876,7 @@ function createContext(o) {
8725
8876
  }
8726
8877
  })();
8727
8878
  };
8728
- const writable = (fd) => new WritableStream({ write: (chunk) => write(fd, chunk) });
8879
+ const writable2 = (fd) => new WritableStream({ write: (chunk) => write(fd, chunk) });
8729
8880
  const statOf = async (op, path) => {
8730
8881
  const abs = resolve(path);
8731
8882
  await kernel.call({ op: "fd-path-flush", path: abs });
@@ -8760,6 +8911,11 @@ function createContext(o) {
8760
8911
  infos,
8761
8912
  handles
8762
8913
  });
8914
+ const children = childOps(
8915
+ kernel,
8916
+ { read, send: writeAll, close: (fd) => ctx.close(fd) },
8917
+ { env: o.env, cwd: o.cwd, signal: signalNumber }
8918
+ );
8763
8919
  const ctx = {
8764
8920
  argv: o.argv,
8765
8921
  env: o.env,
@@ -8778,8 +8934,8 @@ function createContext(o) {
8778
8934
  },
8779
8935
  { highWaterMark: 0 }
8780
8936
  ),
8781
- stdout: writable(1),
8782
- stderr: writable(2),
8937
+ stdout: writable2(1),
8938
+ stderr: writable2(2),
8783
8939
  read,
8784
8940
  write,
8785
8941
  async close(fd) {
@@ -8802,6 +8958,7 @@ function createContext(o) {
8802
8958
  reset: async (signal) => kernel.setHandler(signalNumber(signal), "default")
8803
8959
  },
8804
8960
  sync,
8961
+ ...children,
8805
8962
  exit
8806
8963
  };
8807
8964
  const drain2 = async () => {
@@ -8878,6 +9035,29 @@ function fileHandle(kernel, fd, path, append, forget) {
8878
9035
  }
8879
9036
  };
8880
9037
  }
9038
+ async function readPipe(kernel, fd, max, signal) {
9039
+ if (signal) return receiveSome(kernel, fd, max, signal);
9040
+ const r = await kernel.blocking({ op: "fd-read", fd, max });
9041
+ return r.ok && r.kind === "bytes" ? r.bytes : new Uint8Array(0);
9042
+ }
9043
+ async function receiveSome(kernel, fd, max, signal) {
9044
+ for (; ; ) {
9045
+ signal.throwIfAborted();
9046
+ const r = await kernel.raw({ op: "fd-read", fd, max, nonblock: true });
9047
+ if (r.ok) return r.kind === "bytes" ? r.bytes : new Uint8Array(0);
9048
+ if (r.errno !== "EAGAIN") throw new JsCallError(r.errno, "fd-read");
9049
+ await kernel.blocking({ op: "fd-select", read: [fd], write: [], timeoutMs: -1 }, signal);
9050
+ }
9051
+ }
9052
+ async function sendSome(kernel, fd, body, signal) {
9053
+ for (; ; ) {
9054
+ signal.throwIfAborted();
9055
+ const r = await kernel.raw({ op: "fd-write", fd, body, nonblock: true });
9056
+ if (r.ok) return written(r, body.length);
9057
+ if (r.errno !== "EAGAIN") throw new JsCallError(r.errno, "fd-write");
9058
+ await kernel.blocking({ op: "fd-select", read: [], write: [fd], timeoutMs: -1 }, signal);
9059
+ }
9060
+ }
8881
9061
  function pathOps(kernel, resolve, statOf, open) {
8882
9062
  return {
8883
9063
  stat: (path) => statOf("stat", path),
@@ -8911,6 +9091,7 @@ var init_js_context = __esm({
8911
9091
  "use strict";
8912
9092
  init_signals();
8913
9093
  init_sync_fs_wire();
9094
+ init_js_children();
8914
9095
  init_js_io();
8915
9096
  init_js_kernel();
8916
9097
  init_js_sync();