@ai-ecoverse/slicc-kernel 1.158.0 → 1.159.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.
package/dist/node.js CHANGED
@@ -991,6 +991,9 @@ var KernelPipe = class {
991
991
  readers = 0;
992
992
  writers = 0;
993
993
  waiters = [];
994
+ pushed = 0;
995
+ taken = 0;
996
+ marks = [];
994
997
  capacity;
995
998
  constructor(capacity = PIPE_CAPACITY) {
996
999
  this.capacity = capacity;
@@ -1021,6 +1024,7 @@ var KernelPipe = class {
1021
1024
  if (this.readers === 0) {
1022
1025
  this.chunks = [];
1023
1026
  this.size = 0;
1027
+ this.dropMarks(() => true);
1024
1028
  }
1025
1029
  this.wake();
1026
1030
  }
@@ -1033,10 +1037,59 @@ var KernelPipe = class {
1033
1037
  if (this.writers === 0) return new Uint8Array(0);
1034
1038
  await this.changed(signal);
1035
1039
  }
1036
- const out = this.take(Math.min(max, this.size));
1040
+ const out = this.take(this.bounded(Math.min(max, this.size)));
1041
+ this.dropMarks((mark) => mark.at < this.taken);
1037
1042
  this.wake();
1038
1043
  return out;
1039
1044
  }
1045
+ get inFlight() {
1046
+ return this.marks.reduce((sum, mark) => sum + mark.count, 0);
1047
+ }
1048
+ async receive(max, nonblock, signal) {
1049
+ while (this.size === 0) {
1050
+ if (this.writers === 0) return { bytes: new Uint8Array(0), marks: [] };
1051
+ if (nonblock) throw new PipeError("EAGAIN");
1052
+ await this.changed(signal);
1053
+ }
1054
+ const marks = this.marks.filter((mark) => mark.at === this.taken);
1055
+ this.marks = this.marks.filter((mark) => mark.at !== this.taken);
1056
+ const bytes = this.take(this.bounded(Math.min(max, this.size)));
1057
+ this.dropMarks((mark) => mark.at < this.taken);
1058
+ this.wake();
1059
+ return { bytes, marks };
1060
+ }
1061
+ async writeMarked(bytes, mark, nonblock, signal) {
1062
+ while (this.readers > 0 && this.size >= this.capacity) {
1063
+ if (nonblock) throw new PipeError("EAGAIN");
1064
+ await this.changed(signal);
1065
+ }
1066
+ if (this.readers === 0) throw new PipeError("EPIPE");
1067
+ const before = this.pushed;
1068
+ const made2 = mark(before);
1069
+ this.marks.push(made2);
1070
+ try {
1071
+ const n = await this.write(bytes, signal);
1072
+ this.orphan(made2, before);
1073
+ return n;
1074
+ } catch (err) {
1075
+ this.orphan(made2, before);
1076
+ throw err;
1077
+ }
1078
+ }
1079
+ orphan(made2, before) {
1080
+ if (this.pushed !== before) return;
1081
+ this.dropMarks((mark) => mark === made2);
1082
+ }
1083
+ bounded(n) {
1084
+ const next3 = this.marks.find((mark) => mark.at > this.taken);
1085
+ return next3 ? Math.min(n, next3.at - this.taken) : n;
1086
+ }
1087
+ dropMarks(gone) {
1088
+ const dropped2 = this.marks.filter(gone);
1089
+ if (dropped2.length === 0) return;
1090
+ this.marks = this.marks.filter((mark) => !gone(mark));
1091
+ for (const mark of dropped2) mark.drop();
1092
+ }
1040
1093
  async peek(max, signal) {
1041
1094
  while (this.size === 0) {
1042
1095
  if (this.writers === 0) return new Uint8Array(0);
@@ -1069,6 +1122,7 @@ var KernelPipe = class {
1069
1122
  const n = Math.min(room, bytes.length - offset);
1070
1123
  this.chunks.push(bytes.slice(offset, offset + n));
1071
1124
  this.size += n;
1125
+ this.pushed += n;
1072
1126
  offset += n;
1073
1127
  this.wake();
1074
1128
  }
@@ -1086,6 +1140,7 @@ var KernelPipe = class {
1086
1140
  else this.chunks[0] = head.subarray(count2);
1087
1141
  }
1088
1142
  this.size -= n;
1143
+ this.taken += n;
1089
1144
  return out;
1090
1145
  }
1091
1146
  changed(signal) {
@@ -1962,6 +2017,30 @@ var KernelSocket = class _KernelSocket {
1962
2017
  if (bytes.length === 0 && this.reset) throw this.reset;
1963
2018
  return bytes;
1964
2019
  }
2020
+ rightsLink() {
2021
+ const link2 = this.connection();
2022
+ if (this.domain !== "unix" || this.switch || this.served) throw new KernelError("EOPNOTSUPP");
2023
+ if (this.refused) throw this.refused;
2024
+ return link2;
2025
+ }
2026
+ sendRights(bytes, mark, nonblock, signal) {
2027
+ const { tx } = this.rightsLink();
2028
+ if (this.writeShut) throw new KernelError("EPIPE");
2029
+ return pipeCall(() => tx.writeMarked(bytes, (at) => mark(at, tx.inFlight), nonblock, signal));
2030
+ }
2031
+ async receiveRights(max, nonblock, signal) {
2032
+ const { rx } = this.rightsLink();
2033
+ if (this.readShut || max <= 0) return { bytes: EMPTY, marks: [] };
2034
+ const got = await pipeCall(() => rx.receive(max, nonblock, signal));
2035
+ if (this.refused) {
2036
+ for (const mark of got.marks) mark.drop();
2037
+ throw this.refused;
2038
+ }
2039
+ return got;
2040
+ }
2041
+ get secured() {
2042
+ return this.served || this.tlsDial || this.serving !== void 0 || !!this.switch?.upgraded;
2043
+ }
1965
2044
  async write(bytes, signal) {
1966
2045
  const { tx } = this.connection();
1967
2046
  if (this.refused) throw this.refused;
@@ -2103,11 +2182,13 @@ var KernelSocket = class _KernelSocket {
2103
2182
  switch;
2104
2183
  connectSecure(addr, route2, secure2) {
2105
2184
  if (this.state !== "open") throw new KernelError("EISCONN");
2185
+ this.tlsDial = true;
2106
2186
  return this.dial(addr, route2, secure2);
2107
2187
  }
2108
2188
  serving;
2109
2189
  pending;
2110
2190
  served = false;
2191
+ tlsDial = false;
2111
2192
  get loopbackLinked() {
2112
2193
  return this.state === "connected" && !this.switch;
2113
2194
  }
@@ -3588,7 +3669,7 @@ function satisfies(version, range2) {
3588
3669
  }
3589
3670
 
3590
3671
  // src/version.ts
3591
- var KERNEL_VERSION = true ? "1.158.0" : "0.0.0-dev";
3672
+ var KERNEL_VERSION = true ? "1.159.0" : "0.0.0-dev";
3592
3673
  var OS_RELEASE = "6.0.0-slicc";
3593
3674
  function procVersion() {
3594
3675
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -8068,6 +8149,7 @@ function replyStream(reply) {
8068
8149
  }
8069
8150
  });
8070
8151
  }
8152
+ var HELD_MAX = 16;
8071
8153
  var Throttle = class {
8072
8154
  window = 0;
8073
8155
  count = 0;
@@ -8083,7 +8165,8 @@ var Throttle = class {
8083
8165
  var EmbedderChannel = class {
8084
8166
  access;
8085
8167
  owner;
8086
- caller;
8168
+ current;
8169
+ held = [];
8087
8170
  broker;
8088
8171
  header = new Uint8Array(0);
8089
8172
  body;
@@ -8099,12 +8182,24 @@ var EmbedderChannel = class {
8099
8182
  constructor(broker, access2, caller) {
8100
8183
  this.broker = broker;
8101
8184
  this.access = access2;
8102
- this.caller = caller;
8185
+ this.current = caller;
8103
8186
  this.owner = caller.pid;
8104
8187
  }
8105
8188
  get dispatched() {
8106
8189
  return this.body !== void 0;
8107
8190
  }
8191
+ get caller() {
8192
+ return this.current;
8193
+ }
8194
+ set caller(caller) {
8195
+ this.current = caller;
8196
+ const held = this.held;
8197
+ this.held = [];
8198
+ for (const line of held) this.tell(line);
8199
+ }
8200
+ tell(line) {
8201
+ if (!this.current.progress(line) && this.held.length < HELD_MAX) this.held.push(line);
8202
+ }
8108
8203
  fail(err) {
8109
8204
  this.failure ??= embedderFailure(err);
8110
8205
  return this.failure;
@@ -8121,7 +8216,7 @@ var EmbedderChannel = class {
8121
8216
  this.body = body;
8122
8217
  const prefix = this.caller.name;
8123
8218
  const progress = (line) => {
8124
- if (this.throttle.allow(Date.now())) this.caller.progress(`${prefix}: ${lineOf2(line)}`);
8219
+ if (this.throttle.allow(Date.now())) this.tell(`${prefix}: ${lineOf2(line)}`);
8125
8220
  };
8126
8221
  const asked = Promise.resolve().then(
8127
8222
  () => hook.handle({
@@ -10724,8 +10819,8 @@ async function guarded(entry, path, req) {
10724
10819
  const paths = await guard(g, path, req, entry.cwd);
10725
10820
  return { paths };
10726
10821
  } catch (err) {
10727
- const refusal2 = err.code === "EACCES";
10728
- const refused3 = req.op === "exists" && refusal2 ? json2(false) : toErrno(err);
10822
+ const refusal3 = err.code === "EACCES";
10823
+ const refused3 = req.op === "exists" && refusal3 ? json2(false) : toErrno(err);
10729
10824
  return { refused: refused3 };
10730
10825
  }
10731
10826
  }
@@ -17502,19 +17597,6 @@ var KernelDgram = class {
17502
17597
  }
17503
17598
  };
17504
17599
 
17505
- // src/kernel/net/datagram-wire.ts
17506
- function encodeReceived(got) {
17507
- const host = new TextEncoder().encode(got.host);
17508
- const out = new Uint8Array(4 + host.length + got.bytes.length);
17509
- const view2 = new DataView(out.buffer);
17510
- view2.setUint8(0, (got.truncated ? 1 : 0) | (got.unix ? 2 : 0));
17511
- view2.setUint16(1, got.port);
17512
- view2.setUint8(3, host.length);
17513
- out.set(host, 4);
17514
- out.set(got.bytes, 4 + host.length);
17515
- return out;
17516
- }
17517
-
17518
17600
  // src/kernel/net/sealed-binding.ts
17519
17601
  var HASH_OF_SIGNATURE = {
17520
17602
  "1.2.840.113549.1.1.4": "SHA-256",
@@ -19234,6 +19316,120 @@ function isDatagram(file) {
19234
19316
  return file instanceof KernelDgram || file instanceof UnixDgram;
19235
19317
  }
19236
19318
 
19319
+ // src/kernel/fd-rights.ts
19320
+ var RIGHTS_MAX = 253;
19321
+ var RIGHTS_IN_FLIGHT = 1024;
19322
+ var RECEIVE_MAX = 1024 * 1024;
19323
+ var CTRUNC = 1;
19324
+ var RightsMark = class {
19325
+ at;
19326
+ passed;
19327
+ constructor(at, passed) {
19328
+ this.at = at;
19329
+ this.passed = passed;
19330
+ }
19331
+ get count() {
19332
+ return this.passed.length;
19333
+ }
19334
+ drop() {
19335
+ for (const { file } of this.passed) void Promise.resolve(file.release()).catch(() => void 0);
19336
+ }
19337
+ };
19338
+ function refusal(file) {
19339
+ if (file instanceof KernelSocket) {
19340
+ if (file.domain === "unix") return "EOPNOTSUPP";
19341
+ return file.secured ? "EPERM" : void 0;
19342
+ }
19343
+ if (file instanceof UnixDgram) return "EOPNOTSUPP";
19344
+ if (file instanceof EpollFile || file instanceof TlsContext) return "EPERM";
19345
+ return file.sealed || file.clipboard || file.embedder ? "EPERM" : void 0;
19346
+ }
19347
+ function carrierAt(fds, fd) {
19348
+ const file = fds.get(fd).file;
19349
+ if (!(file instanceof KernelSocket)) {
19350
+ throw new KernelError(file instanceof UnixDgram ? "EOPNOTSUPP" : "ENOTSOCK");
19351
+ }
19352
+ return file;
19353
+ }
19354
+ async function sendRights(fds, req, signal) {
19355
+ const carrier = carrierAt(fds, req.fd);
19356
+ if (req.nonblock && !carrier.poll().writable) throw new KernelError("EAGAIN");
19357
+ if (req.nonblock) signal = AbortSignal.abort();
19358
+ if (req.fds.length === 0) return carrier.write(req.body, signal);
19359
+ if (req.fds.length > RIGHTS_MAX || req.body.length === 0) throw new KernelError("EINVAL");
19360
+ const passed = req.fds.map((fd) => ({ file: fds.get(fd), status: fds.statusFlags(fd) }));
19361
+ for (const { file } of passed) {
19362
+ const errno3 = refusal(file.file);
19363
+ if (errno3) throw new KernelError(errno3, "this descriptor cannot be passed");
19364
+ }
19365
+ for (const { file } of passed) file.retain();
19366
+ let handed2 = false;
19367
+ const mark = (at, inFlight) => {
19368
+ if (inFlight + passed.length > RIGHTS_IN_FLIGHT) {
19369
+ throw new KernelError("EMFILE", "too many descriptors in flight");
19370
+ }
19371
+ handed2 = true;
19372
+ return new RightsMark(at, passed);
19373
+ };
19374
+ try {
19375
+ return await carrier.sendRights(req.body, mark, req.nonblock, signal);
19376
+ } catch (err) {
19377
+ if (!handed2) new RightsMark(0, passed).drop();
19378
+ throw err;
19379
+ }
19380
+ }
19381
+ function installed(fds, passed, cloexec) {
19382
+ let fd;
19383
+ try {
19384
+ fd = fds.install(passed.file);
19385
+ } catch {
19386
+ return void 0;
19387
+ }
19388
+ if (passed.status !== void 0) fds.setStatusFlags(fd, passed.status);
19389
+ if (cloexec) fds.setCloseOnExec(fd);
19390
+ return fd;
19391
+ }
19392
+ function encodeRights(bytes, got, truncated2) {
19393
+ const out = new Uint8Array(8 + got.length * 4 + bytes.length);
19394
+ const view2 = new DataView(out.buffer);
19395
+ view2.setUint32(0, got.length, true);
19396
+ view2.setUint32(4, truncated2 ? CTRUNC : 0, true);
19397
+ for (const [i, fd] of got.entries()) view2.setUint32(8 + i * 4, fd, true);
19398
+ out.set(bytes, 8 + got.length * 4);
19399
+ return out;
19400
+ }
19401
+ async function receiveRights(fds, req, signal) {
19402
+ const carrier = carrierAt(fds, req.fd);
19403
+ const { bytes, marks } = await carrier.receiveRights(
19404
+ Math.min(req.max, RECEIVE_MAX),
19405
+ req.nonblock,
19406
+ signal
19407
+ );
19408
+ const got = [];
19409
+ let truncated2 = false;
19410
+ for (const mark of marks) {
19411
+ for (const passed of mark.passed) {
19412
+ const fd = installed(fds, passed, req.cloexec);
19413
+ if (fd === void 0) truncated2 = true;
19414
+ else got.push(fd);
19415
+ }
19416
+ }
19417
+ return encodeRights(bytes, got, truncated2);
19418
+ }
19419
+
19420
+ // src/kernel/net/datagram-wire.ts
19421
+ function encodeReceived(got) {
19422
+ const host = new TextEncoder().encode(got.host);
19423
+ const out = new Uint8Array(4 + host.length + got.bytes.length);
19424
+ const view2 = new DataView(out.buffer);
19425
+ view2.setUint8(0, (got.truncated ? 1 : 0) | (got.unix ? 2 : 0));
19426
+ view2.setUint16(1, got.port);
19427
+ view2.setUint8(3, host.length);
19428
+ out.set(host, 4);
19429
+ out.set(got.bytes, 4 + host.length);
19430
+ return out;
19431
+ }
19432
+
19237
19433
  // src/kernel/socket-syscalls.ts
19238
19434
  var SOCKET_OPS = [
19239
19435
  "sock-open",
@@ -19244,6 +19440,8 @@ var SOCKET_OPS = [
19244
19440
  "sock-connect",
19245
19441
  "sock-shutdown",
19246
19442
  "sock-reset",
19443
+ "sock-sendmsg",
19444
+ "sock-recvmsg",
19247
19445
  "sock-name",
19248
19446
  "sock-getopt",
19249
19447
  "sock-setopt",
@@ -19314,6 +19512,10 @@ async function socketSyscall(req, proc) {
19314
19512
  case "sock-reset":
19315
19513
  socketAt(fds, req.fd).resetOnClose();
19316
19514
  return ok3();
19515
+ case "sock-sendmsg":
19516
+ return ok3(await sendRights(fds, req, proc.blocking()));
19517
+ case "sock-recvmsg":
19518
+ return { ok: true, kind: "bytes", bytes: await receiveRights(fds, req, proc.blocking()) };
19317
19519
  case "sock-name": {
19318
19520
  const socket = anySocketAt(fds, req.fd);
19319
19521
  const addr = req.peer ? socket.peer : socket.local;
@@ -21193,7 +21395,11 @@ var WasmProcess = class {
21193
21395
  client: session.client,
21194
21396
  tags: this.options.embedder?.tagsOf(this.pid),
21195
21397
  name: name2,
21196
- progress: (line) => void this.complainLine(line),
21398
+ progress: (line) => {
21399
+ if (!this.fds.has(2)) return false;
21400
+ void this.complainLine(line);
21401
+ return true;
21402
+ },
21197
21403
  closing: () => AbortSignal.any([this.interrupt.signal, this.gone.signal])
21198
21404
  };
21199
21405
  }
@@ -24168,7 +24374,7 @@ function enableDnsStub(net, stub) {
24168
24374
 
24169
24375
  // src/kernel/net/redirect-hops.ts
24170
24376
  var HELD_MS = 3e4;
24171
- var HELD_MAX = 64;
24377
+ var HELD_MAX2 = 64;
24172
24378
  var HELD_PER_OWNER = 8;
24173
24379
  var MATCHED = ["range", "if-none-match", "if-modified-since", "if-range", "accept-encoding"];
24174
24380
  var KERNEL = -1;
@@ -24214,7 +24420,7 @@ function replayingHops(inner, heldMs = HELD_MS) {
24214
24420
  drop(key);
24215
24421
  const mine = [...held.keys()].filter((k) => held.get(k)?.owner === chain2.owner);
24216
24422
  if (mine.length >= HELD_PER_OWNER) drop(mine[0]);
24217
- if (held.size >= HELD_MAX) drop(held.keys().next().value);
24423
+ if (held.size >= HELD_MAX2) drop(held.keys().next().value);
24218
24424
  const timer = setTimeout(() => drop(key), heldMs);
24219
24425
  timer.unref?.();
24220
24426
  held.set(key, { ...chain2, timer });
@@ -33106,7 +33312,7 @@ function allows(policy, port) {
33106
33312
  if (Array.isArray(policy)) return policy.includes(port);
33107
33313
  return policy === true && !DEVTOOLS_PORTS.includes(port);
33108
33314
  }
33109
- function refusal(url, address, place) {
33315
+ function refusal2(url, address, place) {
33110
33316
  const where = `${address}:${portOf(url)}`;
33111
33317
  const why = place === "link-local" ? `nodeTransport refuses link-local ${where}` : `nodeTransport refuses the host's loopback ${where} (see nodeTransport({ hostLoopback }))`;
33112
33318
  return Object.assign(new Error(why), { status: 403, code: "EACCES" });
@@ -33128,7 +33334,7 @@ async function checkDestination(target, policy, resolve2 = resolveHost) {
33128
33334
  const place = placeOf(address);
33129
33335
  if (!place) continue;
33130
33336
  if (place === "loopback" && allows(policy, portOf(url))) continue;
33131
- throw refusal(url, address, place);
33337
+ throw refusal2(url, address, place);
33132
33338
  }
33133
33339
  }
33134
33340
  function guarded2(check, signal) {