@ai-ecoverse/slicc-kernel 1.136.9 → 1.138.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
@@ -1319,6 +1319,15 @@ function isHostname(name2) {
1319
1319
  function ownNames(hostname) {
1320
1320
  return [.../* @__PURE__ */ new Set([hostname.toLowerCase(), ...LIBC_HOSTNAMES])];
1321
1321
  }
1322
+ function hostsFile(hostname = DEFAULT_HOSTNAME) {
1323
+ return [
1324
+ "127.0.0.1 localhost localhost.localdomain",
1325
+ "::1 localhost ip6-localhost",
1326
+ `${HOSTNAME_ADDRESS} ${ownNames(hostname).join(" ")}`,
1327
+ `${HOST_LOOPBACK_ADDRESS.join(".")} ${HOST_LOOPBACK}`,
1328
+ ""
1329
+ ].join("\n");
1330
+ }
1322
1331
 
1323
1332
  // src/kernel/net/routes.ts
1324
1333
  var HOST_ADDRESS = HOST_LOOPBACK_ADDRESS.join(".");
@@ -2003,6 +2012,7 @@ var LOCAL_ONLY = new Routes();
2003
2012
  var LoopbackNet = class {
2004
2013
  bound = /* @__PURE__ */ new Map();
2005
2014
  dgrams = /* @__PURE__ */ new Map();
2015
+ dgramServices = /* @__PURE__ */ new Map();
2006
2016
  unixDgrams = /* @__PURE__ */ new Map();
2007
2017
  activators = /* @__PURE__ */ new Map();
2008
2018
  internal = /* @__PURE__ */ new Set();
@@ -2053,9 +2063,16 @@ var LoopbackNet = class {
2053
2063
  releaseDgram(addr, socket) {
2054
2064
  if (this.dgrams.get(addr.port) === socket) this.dgrams.delete(addr.port);
2055
2065
  }
2056
- deliverDgram(port, datagram2) {
2066
+ serveDgram(port, serve) {
2067
+ this.dgramServices.set(port, serve);
2068
+ }
2069
+ deliverDgram(port, datagram2, to) {
2057
2070
  const target = this.dgrams.get(port);
2058
- return target ? target.deliver(datagram2) : false;
2071
+ if (target) return target.deliver(datagram2);
2072
+ const service = this.dgramServices.get(port);
2073
+ if (!service) return false;
2074
+ service(datagram2, to ?? { family: "inet", host: "127.0.0.1", port });
2075
+ return true;
2059
2076
  }
2060
2077
  bindable(addr, kernel) {
2061
2078
  if (addr.host !== "0.0.0.0" && !isLoopback(addr.host)) {
@@ -3745,7 +3762,7 @@ function noticeOf(data) {
3745
3762
  if (Array.isArray(data)) return { paths: data.filter((p) => typeof p === "string"), trees: [] };
3746
3763
  const notice = data ?? {};
3747
3764
  const strings = (list) => Array.isArray(list) ? list.filter((p) => typeof p === "string") : [];
3748
- return { paths: strings(notice.paths), trees: strings(notice.trees) };
3765
+ return { paths: strings(notice.paths), trees: strings(notice.trees), outside: true };
3749
3766
  }
3750
3767
 
3751
3768
  // src/fs/integrity.ts
@@ -4564,9 +4581,11 @@ var OpfsFs = class {
4564
4581
  for (const path of [...c.paths, ...c.trees]) this.forget(path);
4565
4582
  });
4566
4583
  this.channel.onmessage = ({ data }) => {
4567
- const { paths, trees } = noticeOf(data);
4584
+ const { paths, trees, outside } = noticeOf(data);
4568
4585
  for (const path of [...paths, ...trees]) this.forget(normalizePath(path));
4569
- remote?.emit({ paths, trees });
4586
+ const tell = () => remote?.emit({ paths, trees });
4587
+ if (!outside) tell();
4588
+ else void this.noticed(paths.map(normalizePath), Date.now()).finally(tell);
4570
4589
  };
4571
4590
  this.channel.unref?.();
4572
4591
  }
@@ -5025,6 +5044,14 @@ var OpfsFs = class {
5025
5044
  this.fileTimes.set(target, Date.now());
5026
5045
  this.scheduleFileTimes();
5027
5046
  }
5047
+ async noticed(paths, at) {
5048
+ for (const path of new Set(paths)) {
5049
+ const st = await this.lstat(path).catch(() => void 0);
5050
+ if (!st?.isFile || st.mtime.getTime() >= at) continue;
5051
+ this.fileTimes.set(path, Math.max(at, this.fileTimes.get(path) ?? 0));
5052
+ }
5053
+ this.scheduleFileTimes();
5054
+ }
5028
5055
  scheduleFileTimes() {
5029
5056
  if (this.flushing.file || this.fileTimes.size === 0) return;
5030
5057
  this.flushing.file = setTimeout(() => {
@@ -5684,8 +5711,8 @@ var OpfsFs = class {
5684
5711
  renamingDirs = /* @__PURE__ */ new Set();
5685
5712
  intents = 0;
5686
5713
  async intend(rename, at = `${RENAMES}/${crypto.randomUUID()}`) {
5687
- const record = { ...rename, at: Date.now() * 1e3 + this.intents++ % 1e3 };
5688
- await this.meta.update(at, () => ({ path: at, rename: record }));
5714
+ const record2 = { ...rename, at: Date.now() * 1e3 + this.intents++ % 1e3 };
5715
+ await this.meta.update(at, () => ({ path: at, rename: record2 }));
5689
5716
  return at;
5690
5717
  }
5691
5718
  async rollBack(from, to, intents) {
@@ -7486,7 +7513,7 @@ function satisfies(version, range2) {
7486
7513
  }
7487
7514
 
7488
7515
  // src/version.ts
7489
- var KERNEL_VERSION = true ? "1.136.9" : "0.0.0-dev";
7516
+ var KERNEL_VERSION = true ? "1.138.0" : "0.0.0-dev";
7490
7517
  var OS_RELEASE = "6.0.0-slicc";
7491
7518
  function procVersion() {
7492
7519
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -8626,11 +8653,11 @@ var CronService = class {
8626
8653
  }
8627
8654
  if (this.stopping.signal.aborted) return;
8628
8655
  const exit = ended.signal ? `signal=${ended.signal}` : `exit=${ended.status}`;
8629
- const header4 = encoder.encode(`--- ${iso} ${exit} missed=${missed} ---
8656
+ const header5 = encoder.encode(`--- ${iso} ${exit} missed=${missed} ---
8630
8657
  `);
8631
8658
  const body = output.bytes();
8632
8659
  const newline = body.length > 0 && body[body.length - 1] !== 10 ? encoder.encode("\n") : new Uint8Array();
8633
- await this.append(log, concat2([header4, body, newline]), account.uid, account.gid).catch(
8660
+ await this.append(log, concat2([header5, body, newline]), account.uid, account.gid).catch(
8634
8661
  (err) => this.error(messageOf(err))
8635
8662
  );
8636
8663
  }
@@ -9438,8 +9465,8 @@ var FileWatches = class {
9438
9465
  live = /* @__PURE__ */ new Set();
9439
9466
  local;
9440
9467
  remote;
9441
- constructor(local, remote) {
9442
- this.local = local;
9468
+ constructor(local2, remote) {
9469
+ this.local = local2;
9443
9470
  this.remote = remote;
9444
9471
  }
9445
9472
  announce() {
@@ -13159,18 +13186,18 @@ var SAB_I_ASYNC = 14;
13159
13186
  var SAB_I_STOP = 15;
13160
13187
  var SAB_I_BLOCKED = 16;
13161
13188
  var SAB_I_BLOCKED_HI = 17;
13162
- function loadBlocked(header4) {
13163
- return [Atomics.load(header4, SAB_I_BLOCKED), Atomics.load(header4, SAB_I_BLOCKED_HI)];
13189
+ function loadBlocked(header5) {
13190
+ return [Atomics.load(header5, SAB_I_BLOCKED), Atomics.load(header5, SAB_I_BLOCKED_HI)];
13164
13191
  }
13165
- function storeBlocked(header4, [low, high]) {
13166
- Atomics.store(header4, SAB_I_BLOCKED_HI, high);
13167
- Atomics.store(header4, SAB_I_BLOCKED, low);
13192
+ function storeBlocked(header5, [low, high]) {
13193
+ Atomics.store(header5, SAB_I_BLOCKED_HI, high);
13194
+ Atomics.store(header5, SAB_I_BLOCKED, low);
13168
13195
  }
13169
13196
  var anyBlocked = (mask) => mask !== void 0 && (mask[0] !== 0 || mask[1] !== 0);
13170
13197
  var U32 = 2 ** 32;
13171
- function storeU53(header4, lo, hi, value2) {
13172
- Atomics.store(header4, hi, Math.floor(value2 / U32));
13173
- Atomics.store(header4, lo, value2 % U32 | 0);
13198
+ function storeU53(header5, lo, hi, value2) {
13199
+ Atomics.store(header5, hi, Math.floor(value2 / U32));
13200
+ Atomics.store(header5, lo, value2 % U32 | 0);
13174
13201
  }
13175
13202
  var SAB_STATE_READY = 2;
13176
13203
  var SAB_STATUS_BYTES = 1;
@@ -13219,7 +13246,7 @@ function sabViews(sab) {
13219
13246
  var PENDING_TTL_MS = SYNC_FS_REQUEST_TIMEOUT_MS + 5e3;
13220
13247
  function attachSyncSabResponder(port, sab, token, opts) {
13221
13248
  const views = sabViews(sab);
13222
- const { header: header4, window } = views;
13249
+ const { header: header5, window } = views;
13223
13250
  const pending = /* @__PURE__ */ new Map();
13224
13251
  let disposed = false;
13225
13252
  const { dispatch: dispatch2 } = opts;
@@ -13230,20 +13257,20 @@ function attachSyncSabResponder(port, sab, token, opts) {
13230
13257
  pending.delete(id2);
13231
13258
  }
13232
13259
  function publish(id2, entry, offset) {
13233
- if (Atomics.load(header4, SAB_I_REQ) !== id2) {
13260
+ if (Atomics.load(header5, SAB_I_REQ) !== id2) {
13234
13261
  drop(id2);
13235
13262
  return;
13236
13263
  }
13237
13264
  const chunk2 = Math.min(window.byteLength, entry.payload.byteLength - offset);
13238
13265
  if (chunk2 > 0) window.set(entry.payload.subarray(offset, offset + chunk2));
13239
- Atomics.store(header4, SAB_I_STATUS, entry.status);
13240
- storeU53(header4, SAB_I_TOTAL, SAB_I_TOTAL_HI, entry.payload.byteLength);
13241
- Atomics.store(header4, SAB_I_CHUNK, chunk2);
13242
- storeU53(header4, SAB_I_OFFSET, SAB_I_OFFSET_HI, offset);
13243
- Atomics.store(header4, SAB_I_SEQ, id2);
13244
- Atomics.store(header4, SAB_I_STATE, SAB_STATE_READY);
13245
- Atomics.add(header4, SAB_I_PUB, 1);
13246
- Atomics.notify(header4, SAB_I_PUB);
13266
+ Atomics.store(header5, SAB_I_STATUS, entry.status);
13267
+ storeU53(header5, SAB_I_TOTAL, SAB_I_TOTAL_HI, entry.payload.byteLength);
13268
+ Atomics.store(header5, SAB_I_CHUNK, chunk2);
13269
+ storeU53(header5, SAB_I_OFFSET, SAB_I_OFFSET_HI, offset);
13270
+ Atomics.store(header5, SAB_I_SEQ, id2);
13271
+ Atomics.store(header5, SAB_I_STATE, SAB_STATE_READY);
13272
+ Atomics.add(header5, SAB_I_PUB, 1);
13273
+ Atomics.notify(header5, SAB_I_PUB);
13247
13274
  if (offset + chunk2 >= entry.payload.byteLength) drop(id2);
13248
13275
  else if (entry.timer) {
13249
13276
  clearTimeout(entry.timer);
@@ -13458,6 +13485,15 @@ var ProcessClocks = class {
13458
13485
  }
13459
13486
  };
13460
13487
 
13488
+ // src/kernel/proc-info.ts
13489
+ function mayTrace(viewer, target) {
13490
+ const by = viewer?.cred;
13491
+ const of = target.cred;
13492
+ if (!by || !of || by.euid === 0) return true;
13493
+ const uid = of.ruid === by.euid && of.euid === by.euid && of.suid === by.euid;
13494
+ return uid && of.rgid === by.egid && of.egid === by.egid && of.sgid === by.egid;
13495
+ }
13496
+
13461
13497
  // src/fs/pages.ts
13462
13498
  var PAGE = 64 * 1024;
13463
13499
  var READAHEAD = 1024 * 1024;
@@ -14013,7 +14049,16 @@ var ProcTree = class {
14013
14049
  if (!/^[1-9]\d*$/.test(top) || !this.alive(Number(top))) return void 0;
14014
14050
  if (leaf === "task") return this.task(Number(top), rest2);
14015
14051
  if (rest2.length > 0) return void 0;
14016
- if (leaf === void 0) return { kind: "dir", names: () => [...PID_NAMES, "task"] };
14052
+ if (leaf === void 0) {
14053
+ const exe = () => this.info(Number(top))?.exe === void 0 ? [] : ["exe"];
14054
+ return { kind: "dir", names: () => [...PID_NAMES, ...exe(), "task"] };
14055
+ }
14056
+ if (leaf === "exe") {
14057
+ const info = this.info(Number(top));
14058
+ if (info?.exe === void 0) return void 0;
14059
+ const denied2 = !mayTrace(this.ownInfo(), info);
14060
+ return { kind: "link", target: info.exe, ...denied2 ? { denied: denied2 } : {} };
14061
+ }
14017
14062
  if (!PID_NAMES.includes(leaf)) return void 0;
14018
14063
  return {
14019
14064
  kind: "file",
@@ -14025,6 +14070,10 @@ var ProcTree = class {
14025
14070
  }
14026
14071
  };
14027
14072
  }
14073
+ ownInfo() {
14074
+ const processes2 = this.listing().processes;
14075
+ return processes2.find((p) => p.tid === this.pid) ?? processes2.find((p) => p.pid === this.pid);
14076
+ }
14028
14077
  info(pid) {
14029
14078
  return this.listing().processes.find((p) => p.pid === pid);
14030
14079
  }
@@ -14088,6 +14137,7 @@ var ProcTree = class {
14088
14137
  readlink(path) {
14089
14138
  const node = this.find(path, false);
14090
14139
  if (node.kind !== "link") throw syncError("EINVAL", path);
14140
+ if (node.denied) throw syncError("EACCES", path);
14091
14141
  return node.target;
14092
14142
  }
14093
14143
  exists(path) {
@@ -15492,8 +15542,8 @@ function sameCert(a, b) {
15492
15542
  if (!a || !b) return a === b;
15493
15543
  return a.cert.length === b.cert.length && a.cert.every((byte, i) => byte === b.cert[i]);
15494
15544
  }
15495
- function winner(current, expected, record) {
15496
- return sameCert(current, expected) ? record : current;
15545
+ function winner(current, expected, record2) {
15546
+ return sameCert(current, expected) ? record2 : current;
15497
15547
  }
15498
15548
  var DAY = 24 * 60 * 60 * 1e3;
15499
15549
  var CA_LIFETIME = 3650 * DAY;
@@ -15510,14 +15560,14 @@ function validLeafName(host) {
15510
15560
  }
15511
15561
  var RealmCa = class _RealmCa {
15512
15562
  record;
15513
- constructor(record) {
15514
- this.record = record;
15563
+ constructor(record2) {
15564
+ this.record = record2;
15515
15565
  }
15516
15566
  static async open(owner, store, now = Date.now()) {
15517
15567
  const stored = await store.get(owner).catch(() => void 0);
15518
15568
  if (stored && stored.notAfter - now > CA_RENEW_BEFORE) return new _RealmCa(stored);
15519
- const record = await _RealmCa.create(owner, now);
15520
- return new _RealmCa(await store.swap(owner, stored, record));
15569
+ const record2 = await _RealmCa.create(owner, now);
15570
+ return new _RealmCa(await store.swap(owner, stored, record2));
15521
15571
  }
15522
15572
  static async create(owner, now) {
15523
15573
  const pair = await crypto.subtle.generateKey(ECDSA, false, ["sign", "verify"]);
@@ -15676,10 +15726,15 @@ var TlsEngine = class {
15676
15726
  const m = this.clientModule();
15677
15727
  if (servername.includes("\0")) throw new TlsError(-3, "tls engine: a server name has no NUL");
15678
15728
  const wire = alpnWire(alpn);
15679
- const name2 = this.put(new TextEncoder().encode(servername));
15729
+ const bytes = new TextEncoder().encode(servername);
15730
+ const name2 = this.put(bytes);
15680
15731
  try {
15681
15732
  const at = store?.ptr ?? 0;
15682
- const ptr = this.withBytes(wire, (p) => m._tls_client_new(at, name2, p, wire.length, flags2));
15733
+ const named = m._tls_client_new_name;
15734
+ const ptr = this.withBytes(
15735
+ wire,
15736
+ (p) => named ? named(at, name2, bytes.length, p, wire.length, flags2) : m._tls_client_new(at, name2, p, wire.length, flags2)
15737
+ );
15683
15738
  if (!ptr) throw this.error(m._tls_last_error(), "tls client");
15684
15739
  return new TlsSession(this, m, ptr);
15685
15740
  } finally {
@@ -16047,8 +16102,8 @@ function memoryCaStore() {
16047
16102
  const records = /* @__PURE__ */ new Map();
16048
16103
  return {
16049
16104
  get: async (owner) => records.get(owner),
16050
- swap: async (owner, expected, record) => {
16051
- const kept = winner(records.get(owner), expected, record);
16105
+ swap: async (owner, expected, record2) => {
16106
+ const kept = winner(records.get(owner), expected, record2);
16052
16107
  records.set(owner, kept);
16053
16108
  return kept;
16054
16109
  }
@@ -16175,10 +16230,10 @@ var WsHandles = class {
16175
16230
  open = /* @__PURE__ */ new Map();
16176
16231
  next;
16177
16232
  local;
16178
- constructor(transport, next3, local) {
16233
+ constructor(transport, next3, local2) {
16179
16234
  this.transport = transport;
16180
16235
  this.next = next3;
16181
- this.local = local;
16236
+ this.local = local2;
16182
16237
  }
16183
16238
  owns(handle) {
16184
16239
  return this.open.has(handle);
@@ -16207,8 +16262,8 @@ var WsHandles = class {
16207
16262
  return { ok: true, kind: "json", json: handle };
16208
16263
  }
16209
16264
  async connect(handle, req, entry) {
16210
- const { transport, local } = this;
16211
- const port = local?.port(req.url);
16265
+ const { transport, local: local2 } = this;
16266
+ const port = local2?.port(req.url);
16212
16267
  const open = { protocols: req.protocols, headers: req.headers, signal: entry.abort.signal };
16213
16268
  if (port === void 0 && (!transport.traits.websocket || !transport.websocket)) {
16214
16269
  return fail("ENOTSUP", NO_WEBSOCKET2);
@@ -16218,7 +16273,7 @@ var WsHandles = class {
16218
16273
  socket = port === void 0 ? await transport.websocket({
16219
16274
  url: toHostLoopback(req.url),
16220
16275
  ...open
16221
- }) : await local.websocket({ url: req.url, ...open }, port);
16276
+ }) : await local2.websocket({ url: req.url, ...open }, port);
16222
16277
  } catch (e) {
16223
16278
  return fail(errnoOf(e), message(e));
16224
16279
  }
@@ -16349,11 +16404,11 @@ var HttpHandles = class {
16349
16404
  ws;
16350
16405
  owner;
16351
16406
  local;
16352
- constructor(transport, owner, local) {
16407
+ constructor(transport, owner, local2) {
16353
16408
  this.transport = transport;
16354
16409
  this.owner = owner;
16355
- this.local = local;
16356
- this.ws = new WsHandles(transport, () => ++this.nextHandle, local);
16410
+ this.local = local2;
16411
+ this.ws = new WsHandles(transport, () => ++this.nextHandle, local2);
16357
16412
  }
16358
16413
  syscall(req) {
16359
16414
  if (req.op.startsWith("net-ws-")) return this.ws.syscall(req);
@@ -16505,6 +16560,43 @@ var HttpHandles = class {
16505
16560
  }
16506
16561
  };
16507
16562
 
16563
+ // src/kernel/net/hosts-file.ts
16564
+ var HOSTS_PATH = "/etc/hosts";
16565
+ function parseHosts(text) {
16566
+ const table = /* @__PURE__ */ new Map();
16567
+ for (const raw2 of text.split("\n")) {
16568
+ const [address, ...names2] = raw2.replace(/#.*/, "").trim().split(/\s+/);
16569
+ if (!address || names2.length === 0) continue;
16570
+ if (ipv4Bytes(address) === void 0 && ipv6Groups(address) === void 0) continue;
16571
+ for (const name2 of names2) {
16572
+ const key = name2.toLowerCase().replace(/\.$/, "");
16573
+ const known = table.get(key) ?? [];
16574
+ if (!known.includes(address)) known.push(address);
16575
+ table.set(key, known);
16576
+ }
16577
+ }
16578
+ return table;
16579
+ }
16580
+ function hostsReader(fs, path = HOSTS_PATH) {
16581
+ let stamp = "";
16582
+ let table;
16583
+ return async () => {
16584
+ const st = await fs.stat(path).catch(() => void 0);
16585
+ if (!st?.isFile) {
16586
+ stamp = "";
16587
+ table = void 0;
16588
+ return void 0;
16589
+ }
16590
+ const now = `${st.ino}:${st.size}:${st.mtime.getTime()}`;
16591
+ if (now === stamp && table) return table;
16592
+ const text = await fs.readFile(path).catch(() => void 0);
16593
+ if (text === void 0) return void 0;
16594
+ stamp = now;
16595
+ table = parseHosts(text);
16596
+ return table;
16597
+ };
16598
+ }
16599
+
16508
16600
  // src/kernel/net/uplink.ts
16509
16601
  function carriesUdp(uplink) {
16510
16602
  return uplink.traits.udp === true && typeof uplink.udp === "function";
@@ -16540,6 +16632,7 @@ var Resolver = class {
16540
16632
  timeoutMs;
16541
16633
  log;
16542
16634
  own;
16635
+ builtin;
16543
16636
  cache = /* @__PURE__ */ new Map();
16544
16637
  pending = /* @__PURE__ */ new Map();
16545
16638
  hosts;
@@ -16550,6 +16643,7 @@ var Resolver = class {
16550
16643
  this.timeoutMs = options.timeoutMs ?? RESOLVE_TIMEOUT_MS;
16551
16644
  this.log = options.log ?? ((message3) => console.warn(message3));
16552
16645
  this.own = ownNames(options.hostname ?? DEFAULT_HOSTNAME);
16646
+ this.builtin = parseHosts(hostsFile(options.hostname ?? DEFAULT_HOSTNAME));
16553
16647
  this.hosts = options.hosts;
16554
16648
  }
16555
16649
  async fromFile(key, family) {
@@ -16559,18 +16653,34 @@ var Resolver = class {
16559
16653
  const v6 = listed.filter((a) => ipv4Bytes(a) === void 0);
16560
16654
  return family === 4 ? v4 : family === 6 ? v6 : [...v4, ...v6];
16561
16655
  }
16656
+ async known(name2) {
16657
+ const key = name2.toLowerCase().replace(/\.$/, "");
16658
+ if (ipv4Bytes(key) || ipv6Groups(key)) return false;
16659
+ if (hostsEntry(key, this.own) !== void 0) return true;
16660
+ return ((await this.hosts?.().catch(() => void 0))?.get(key)?.length ?? 0) > 0;
16661
+ }
16662
+ async reverse(address) {
16663
+ const v6 = ipv6Groups(address)?.join(":");
16664
+ const same2 = (a) => a === address || v6 !== void 0 && ipv6Groups(a)?.join(":") === v6;
16665
+ const file = await this.hosts?.().catch(() => void 0);
16666
+ for (const table of [file, this.builtin]) {
16667
+ for (const [name2, addresses] of table ?? []) if (addresses.some(same2)) return name2;
16668
+ }
16669
+ if (ipv4Bytes(address)?.[0] === 127) return "localhost";
16670
+ return void 0;
16671
+ }
16562
16672
  async resolve(name2, family, blocking) {
16563
16673
  const key = name2.toLowerCase().replace(/\.$/, "");
16564
- const local = hostsEntry(key, this.own);
16674
+ const local2 = hostsEntry(key, this.own);
16565
16675
  if (ipv6Groups(key)) {
16566
- const v4 = family !== 6 && local ? [local] : [];
16676
+ const v4 = family !== 6 && local2 ? [local2] : [];
16567
16677
  return family === 4 ? v4 : [...v4, key];
16568
16678
  }
16569
16679
  const listed = this.hosts ? await this.fromFile(key, family) : void 0;
16570
16680
  if (listed?.length) return listed;
16571
- if (local) {
16681
+ if (local2) {
16572
16682
  const six = loopbackName(key, this.own) ? ["::1"] : [];
16573
- return family === 6 ? six : family === 4 ? [local] : [local, ...six];
16683
+ return family === 6 ? six : family === 4 ? [local2] : [local2, ...six];
16574
16684
  }
16575
16685
  if (!this.uplink || key === "") return [];
16576
16686
  const asked = this.uplink.traits.ipv6 ? family : 4;
@@ -17609,14 +17719,15 @@ var KernelDgram = class {
17609
17719
  const max = familyOf(target.host) === 6 ? MAX_DATAGRAM_V6 : MAX_DATAGRAM_V4;
17610
17720
  if (bytes.length > max) throw new KernelError("EMSGSIZE");
17611
17721
  const where = this.route(target.host);
17612
- const local = this.bound();
17722
+ const local2 = this.bound();
17613
17723
  if (where === "uplink") return this.sendUp(bytes, target);
17614
17724
  const from = {
17615
17725
  family: "inet",
17616
- host: local.host === "0.0.0.0" ? "127.0.0.1" : local.host,
17617
- port: local.port
17726
+ host: local2.host === "0.0.0.0" ? "127.0.0.1" : local2.host,
17727
+ port: local2.port
17618
17728
  };
17619
- const delivered = this.net.deliverDgram(target.port, { bytes: bytes.slice(), from });
17729
+ const dest = { family: "inet", host: canonicalHost(target.host), port: target.port };
17730
+ const delivered = this.net.deliverDgram(target.port, { bytes: bytes.slice(), from }, dest);
17620
17731
  if (!delivered && this.peer && sameAddr(this.peer, target)) {
17621
17732
  this.pending = "ECONNREFUSED";
17622
17733
  this.changes.wake();
@@ -19213,8 +19324,8 @@ function clientFirstOf(message3) {
19213
19324
  return m ? { header: m[1], bare: m[2] } : void 0;
19214
19325
  }
19215
19326
  var latinBytes = (text) => Uint8Array.from(text, (c) => c.charCodeAt(0));
19216
- function channelOf(header4, binding) {
19217
- const head = latinBytes(header4);
19327
+ function channelOf(header5, binding) {
19328
+ const head = latinBytes(header5);
19218
19329
  const all = new Uint8Array(head.length + (binding?.length ?? 0));
19219
19330
  all.set(head);
19220
19331
  if (binding) all.set(binding, head.length);
@@ -19439,8 +19550,8 @@ function frame3(type, body) {
19439
19550
  return out;
19440
19551
  }
19441
19552
  function pgLength(bytes, started) {
19442
- const header4 = started ? 5 : 4;
19443
- if (bytes.length < header4) return void 0;
19553
+ const header5 = started ? 5 : 4;
19554
+ if (bytes.length < header5) return void 0;
19444
19555
  const length2 = int32(bytes, started ? 1 : 0);
19445
19556
  return started ? 1 + length2 : length2;
19446
19557
  }
@@ -19468,16 +19579,16 @@ function initial(message3) {
19468
19579
  function int32Text(n) {
19469
19580
  return String.fromCharCode(n >>> 24 & 255, n >>> 16 & 255, n >>> 8 & 255, n & 255);
19470
19581
  }
19471
- function serverHeader(header4, server) {
19472
- if (header4 === "n,,") return header4;
19473
- if (header4 === "y,," && !server.plus) return header4;
19474
- if (header4 === END_POINT && server.binding) return header4;
19582
+ function serverHeader(header5, server) {
19583
+ if (header5 === "n,,") return header5;
19584
+ if (header5 === "y,," && !server.plus) return header5;
19585
+ if (header5 === END_POINT && server.binding) return header5;
19475
19586
  return server.plus && server.binding ? END_POINT : "n,,";
19476
19587
  }
19477
- function rewritten(first, header4) {
19588
+ function rewritten(first, header5) {
19478
19589
  const parsed2 = clientFirstOf(first.data);
19479
- if (!parsed2 || parsed2.header === header4) return first;
19480
- return { mechanism: header4 === END_POINT ? PLUS : PLAIN, data: `${header4}${parsed2.bare}` };
19590
+ if (!parsed2 || parsed2.header === header5) return first;
19591
+ return { mechanism: header5 === END_POINT ? PLUS : PLAIN, data: `${header5}${parsed2.bare}` };
19481
19592
  }
19482
19593
  var PgClient = class {
19483
19594
  clientFirst;
@@ -20602,8 +20713,8 @@ async function datagram(req, proc) {
20602
20713
  const ready2 = pollFile(dgram).readable;
20603
20714
  if (req.nonblock && !ready2) throw new KernelError("EAGAIN");
20604
20715
  const got = await dgram.receive(req.max, req.peek, ready2 ? void 0 : proc.blocking());
20605
- const { bytes, from, truncated } = got;
20606
- return { ok: true, kind: "bytes", bytes: encodeReceived({ bytes, truncated, ...from }) };
20716
+ const { bytes, from, truncated: truncated2 } = got;
20717
+ return { ok: true, kind: "bytes", bytes: encodeReceived({ bytes, truncated: truncated2, ...from }) };
20607
20718
  }
20608
20719
  async function unixDatagram(req, dgram, proc) {
20609
20720
  if (req.op === "sock-sendto") {
@@ -20613,11 +20724,11 @@ async function unixDatagram(req, dgram, proc) {
20613
20724
  const ready2 = pollFile(dgram).readable;
20614
20725
  if (req.nonblock && !ready2) throw new KernelError("EAGAIN");
20615
20726
  const got = await dgram.receive(req.max, req.peek, ready2 ? void 0 : proc.blocking());
20616
- const { bytes, from, truncated } = got;
20727
+ const { bytes, from, truncated: truncated2 } = got;
20617
20728
  return {
20618
20729
  ok: true,
20619
20730
  kind: "bytes",
20620
- bytes: encodeReceived({ bytes, truncated, host: from.path, port: 0, unix: true })
20731
+ bytes: encodeReceived({ bytes, truncated: truncated2, host: from.path, port: 0, unix: true })
20621
20732
  };
20622
20733
  }
20623
20734
  function domainOf(socket) {
@@ -23368,9 +23479,9 @@ var JsThreads = class {
23368
23479
  const { control, port } = msg;
23369
23480
  const tid = ++this.last;
23370
23481
  const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
23371
- const header4 = new Int32Array(sab, 0, SAB_HEADER_I32);
23482
+ const header5 = new Int32Array(sab, 0, SAB_HEADER_I32);
23372
23483
  const owned4 = new SharedArrayBuffer(4 * (1 + JS_THREAD_OWNED_FDS));
23373
- if (this.frozen) Atomics.store(header4, SAB_I_STOP, 1);
23484
+ if (this.frozen) Atomics.store(header5, SAB_I_STOP, 1);
23374
23485
  const clock = this.deps.clocks.thread(tid + 1, sab);
23375
23486
  let ended = false;
23376
23487
  const end = (code) => {
@@ -23378,7 +23489,7 @@ var JsThreads = class {
23378
23489
  ended = true;
23379
23490
  this.live.delete(tid);
23380
23491
  this.headers.delete(tid);
23381
- this.deps.wakes.delete(header4);
23492
+ this.deps.wakes.delete(header5);
23382
23493
  for (const [id2, token] of ops) {
23383
23494
  void this.deps.dispatch({ op: "async-cancel", id: id2, token });
23384
23495
  }
@@ -23428,8 +23539,8 @@ var JsThreads = class {
23428
23539
  control.addEventListener("message", onControl);
23429
23540
  control.start();
23430
23541
  this.live.set(tid, end);
23431
- this.headers.set(tid, header4);
23432
- this.deps.wakes.add(header4);
23542
+ this.headers.set(tid, header5);
23543
+ this.deps.wakes.add(header5);
23433
23544
  const init = {
23434
23545
  ...this.deps.init(sab, lane.lane),
23435
23546
  type: JS_THREAD_INIT,
@@ -23449,9 +23560,9 @@ var JsThreads = class {
23449
23560
  }
23450
23561
  stopped(stopped) {
23451
23562
  this.frozen = stopped;
23452
- for (const header4 of this.headers.values()) {
23453
- Atomics.store(header4, SAB_I_STOP, stopped ? 1 : 0);
23454
- Atomics.notify(header4, SAB_I_STOP);
23563
+ for (const header5 of this.headers.values()) {
23564
+ Atomics.store(header5, SAB_I_STOP, stopped ? 1 : 0);
23565
+ Atomics.notify(header5, SAB_I_STOP);
23455
23566
  }
23456
23567
  }
23457
23568
  close() {
@@ -23496,13 +23607,13 @@ var Dying = class {
23496
23607
  hard;
23497
23608
  busy = 0;
23498
23609
  finish;
23499
- start(code, sig, header4, process2, finish) {
23610
+ start(code, sig, header5, process2, finish) {
23500
23611
  if (this.ending) return;
23501
23612
  this.ending = { code, sig };
23502
23613
  this.finish = finish;
23503
23614
  this.hard = setTimeout(finish, KILL_HARD_MS);
23504
23615
  this.arm();
23505
- Atomics.store(header4, SAB_I_KILLED, code);
23616
+ Atomics.store(header5, SAB_I_KILLED, code);
23506
23617
  process2.die();
23507
23618
  }
23508
23619
  serve(req, work) {
@@ -23549,8 +23660,8 @@ function unblockedThread(threads, sig) {
23549
23660
  }
23550
23661
  return void 0;
23551
23662
  }
23552
- function unblocked(header4) {
23553
- return Atomics.load(header4, SAB_I_SIGNALS) & ~Atomics.load(header4, SAB_I_BLOCKED);
23663
+ function unblocked(header5) {
23664
+ return Atomics.load(header5, SAB_I_SIGNALS) & ~Atomics.load(header5, SAB_I_BLOCKED);
23554
23665
  }
23555
23666
  function threadCall(process2, req, cancelled, block) {
23556
23667
  return isWasmSyscall(req) ? process2.syscall(req, cancelled, block) : dispatchSyncFs(req);
@@ -23562,24 +23673,24 @@ function threadCancel(thread) {
23562
23673
  return unblocked(thread.header) !== 0 ? AbortSignal.abort() : thread.interrupt.signal;
23563
23674
  }
23564
23675
  var asyncFanout = /* @__PURE__ */ new WeakMap();
23565
- function notifiers(header4) {
23676
+ function notifiers(header5) {
23566
23677
  return {
23567
23678
  onPending(sig) {
23568
- Atomics.or(header4, SAB_I_SIGNALS, sigbit(sig));
23569
- Atomics.notify(header4, SAB_I_SIGNALS);
23679
+ Atomics.or(header5, SAB_I_SIGNALS, sigbit(sig));
23680
+ Atomics.notify(header5, SAB_I_SIGNALS);
23570
23681
  },
23571
23682
  onAsync() {
23572
- for (const at of [header4, ...asyncFanout.get(header4) ?? []]) {
23683
+ for (const at of [header5, ...asyncFanout.get(header5) ?? []]) {
23573
23684
  Atomics.add(at, SAB_I_ASYNC, 1);
23574
23685
  Atomics.notify(at, SAB_I_ASYNC);
23575
23686
  }
23576
23687
  }
23577
23688
  };
23578
23689
  }
23579
- function publishStops(process2, header4) {
23690
+ function publishStops(process2, header5) {
23580
23691
  process2.onState((state) => {
23581
- Atomics.store(header4, SAB_I_STOP, state === "stopped" ? 1 : 0);
23582
- Atomics.notify(header4, SAB_I_STOP);
23692
+ Atomics.store(header5, SAB_I_STOP, state === "stopped" ? 1 : 0);
23693
+ Atomics.notify(header5, SAB_I_STOP);
23583
23694
  });
23584
23695
  }
23585
23696
  function transferOf(opts, lane) {
@@ -23671,7 +23782,7 @@ function linksOf(opts) {
23671
23782
  function clipboardName(opts) {
23672
23783
  return opts.program.abi === "js" ? {} : { clipboardName: opts.argv0 };
23673
23784
  }
23674
- function processOptions(opts, header4, hooks, created4) {
23785
+ function processOptions(opts, header5, hooks, created4) {
23675
23786
  return {
23676
23787
  ...inherited(opts),
23677
23788
  ...opts.owners ? { owners: true } : {},
@@ -23710,16 +23821,16 @@ function processOptions(opts, header4, hooks, created4) {
23710
23821
  watches: opts.watches,
23711
23822
  onReap: opts.onReap,
23712
23823
  resolver: opts.resolver,
23713
- ...notifiers(header4),
23714
- onTimer: (which) => void Atomics.or(header4, SAB_I_TIMERS, 1 << which),
23715
- hasPending: () => unblocked(header4) !== 0 || Atomics.load(header4, SAB_I_TIMERS) !== 0,
23824
+ ...notifiers(header5),
23825
+ onTimer: (which) => void Atomics.or(header5, SAB_I_TIMERS, 1 << which),
23826
+ hasPending: () => unblocked(header5) !== 0 || Atomics.load(header5, SAB_I_TIMERS) !== 0,
23716
23827
  raise: hooks.raise,
23717
23828
  threadKill: hooks.threadKill,
23718
23829
  unblockedThread: hooks.unblockedThread,
23719
23830
  ...hooks.exitNow ? { exitNow: hooks.exitNow } : {},
23720
23831
  ...hooks.exitSignal ? { exitSignal: hooks.exitSignal } : {},
23721
- ...opts.program.abi === "wasi" || opts.program.abi === "js" ? { pendingBits: () => Atomics.load(header4, SAB_I_SIGNALS) } : {},
23722
- ...opts.program.abi === "wasi" ? { blockedBits: () => Atomics.load(header4, SAB_I_BLOCKED) } : {}
23832
+ ...opts.program.abi === "wasi" || opts.program.abi === "js" ? { pendingBits: () => Atomics.load(header5, SAB_I_SIGNALS) } : {},
23833
+ ...opts.program.abi === "wasi" ? { blockedBits: () => Atomics.load(header5, SAB_I_BLOCKED) } : {}
23723
23834
  };
23724
23835
  }
23725
23836
  function threadInit(opts, program, sab, cred, thread, main) {
@@ -23785,9 +23896,9 @@ async function crashReport(process2, onError, message3) {
23785
23896
  function spawnWasmProcess(opts) {
23786
23897
  const { promise: ready2, resolve: started } = readiness(opts.program.abi);
23787
23898
  const sab = new SharedArrayBuffer(SAB_HEADER_BYTES + SAB_DEFAULT_WINDOW_BYTES);
23788
- const header4 = new Int32Array(sab, 0, SAB_HEADER_I32);
23899
+ const header5 = new Int32Array(sab, 0, SAB_HEADER_I32);
23789
23900
  const blocked2 = opts.fork?.wasi?.blocked ?? opts.blocked;
23790
- if (blocked2 && anyBlocked(blocked2) && opts.program.abi === "wasi") storeBlocked(header4, blocked2);
23901
+ if (blocked2 && anyBlocked(blocked2) && opts.program.abi === "wasi") storeBlocked(header5, blocked2);
23791
23902
  const threadSignals = /* @__PURE__ */ new Map();
23792
23903
  const created4 = new Created();
23793
23904
  const process2 = new WasmProcess(
@@ -23795,7 +23906,7 @@ function spawnWasmProcess(opts) {
23795
23906
  opts.fds,
23796
23907
  processOptions(
23797
23908
  opts,
23798
- header4,
23909
+ header5,
23799
23910
  {
23800
23911
  raise: (sig, info) => signal(sig, info),
23801
23912
  threadKill: (tid, sig) => killThread(threadSignals.get(tid), process2.signalMasks().caught, sig),
@@ -23808,7 +23919,7 @@ function spawnWasmProcess(opts) {
23808
23919
  created4
23809
23920
  )
23810
23921
  );
23811
- publishStops(process2, header4);
23922
+ publishStops(process2, header5);
23812
23923
  const holds2 = new HeldPaths();
23813
23924
  opts.held?.add(holds2);
23814
23925
  const token = holdingToken(opts, holds2, {
@@ -23829,7 +23940,7 @@ function spawnWasmProcess(opts) {
23829
23940
  dispatch: clocks.timed(void 0, dispatch2)
23830
23941
  });
23831
23942
  const lane = opts.program.abi === "js" ? openLane(token, dispatch2) : void 0;
23832
- const jsThreads = jsThreadsOf(opts, process2, token, dispatch2, clocks, header4);
23943
+ const jsThreads = jsThreadsOf(opts, process2, token, dispatch2, clocks, header5);
23833
23944
  const { promise: exited, resolve: settle } = Promise.withResolvers();
23834
23945
  let done4 = false;
23835
23946
  const crash = new CrashSlot((message3) => crashReport(process2, opts.onError, message3));
@@ -23928,7 +24039,7 @@ function spawnWasmProcess(opts) {
23928
24039
  );
23929
24040
  const terminate = (code, sig) => {
23930
24041
  if (opts.program.abi !== "wasi" || done4) finish(code, sig);
23931
- else dying.start(code, sig, header4, process2, () => finish(code, sig));
24042
+ else dying.start(code, sig, header5, process2, () => finish(code, sig));
23932
24043
  };
23933
24044
  const signal = (sig, info) => {
23934
24045
  if (process2.signal(sig, info) === "terminate")
@@ -23943,16 +24054,16 @@ function spawnWasmProcess(opts) {
23943
24054
  signal,
23944
24055
  termsig: () => endedBy,
23945
24056
  onState: (listener) => process2.onState(listener),
23946
- memory: () => Atomics.load(header4, SAB_I_MEMORY) * 65536,
23947
- ...processViews(process2, opts, header4),
24057
+ memory: () => Atomics.load(header5, SAB_I_MEMORY) * 65536,
24058
+ ...processViews(process2, opts, header5),
23948
24059
  writesBack: () => opts.program.abi === "wasi" && !done4,
23949
24060
  ...clockViews(clocks)
23950
24061
  };
23951
24062
  }
23952
- function jsThreadsOf(opts, process2, token, dispatch2, clocks, header4) {
24063
+ function jsThreadsOf(opts, process2, token, dispatch2, clocks, header5) {
23953
24064
  if (opts.program.abi !== "js") return void 0;
23954
24065
  const wakes = /* @__PURE__ */ new Set();
23955
- asyncFanout.set(header4, wakes);
24066
+ asyncFanout.set(header5, wakes);
23956
24067
  const threads = new JsThreads({
23957
24068
  wakes,
23958
24069
  cap: jsThreadCap(opts.env),
@@ -23967,10 +24078,10 @@ function jsThreadsOf(opts, process2, token, dispatch2, clocks, header4) {
23967
24078
  process2.onState((state) => threads.stopped(state === "stopped"));
23968
24079
  return threads;
23969
24080
  }
23970
- function processViews(process2, opts, header4) {
24081
+ function processViews(process2, opts, header5) {
23971
24082
  return {
23972
24083
  ignoredSignals: (fork) => process2.inheritable(fork),
23973
- blockedSignals: () => opts.program.abi === "wasi" ? loadBlocked(header4) : [0, 0],
24084
+ blockedSignals: () => opts.program.abi === "wasi" ? loadBlocked(header5) : [0, 0],
23974
24085
  signalMasks: () => process2.signalMasks(),
23975
24086
  umask: () => process2.umask,
23976
24087
  cred: () => copyCred(process2.cred)
@@ -24528,42 +24639,398 @@ function isMessage(data) {
24528
24639
  return adopt !== null && Array.isArray(adopt.records) && Array.isArray(adopt.flocks);
24529
24640
  }
24530
24641
 
24531
- // src/kernel/net/hosts-file.ts
24532
- var HOSTS_PATH = "/etc/hosts";
24533
- function parseHosts(text) {
24534
- const table = /* @__PURE__ */ new Map();
24535
- for (const raw2 of text.split("\n")) {
24536
- const [address, ...names2] = raw2.replace(/#.*/, "").trim().split(/\s+/);
24537
- if (!address || names2.length === 0) continue;
24538
- if (ipv4Bytes(address) === void 0 && ipv6Groups(address) === void 0) continue;
24539
- for (const name2 of names2) {
24540
- const key = name2.toLowerCase().replace(/\.$/, "");
24541
- const known = table.get(key) ?? [];
24542
- if (!known.includes(address)) known.push(address);
24543
- table.set(key, known);
24642
+ // src/kernel/net/dns-stub.ts
24643
+ var DNS_PORT = 53;
24644
+ var DNS_STUB_ADDRESS = "127.0.0.53";
24645
+ var RESOLV_CONF_PATH = "/etc/resolv.conf";
24646
+ var RESOLV_CONF = `nameserver ${DNS_STUB_ADDRESS}
24647
+ options edns0
24648
+ `;
24649
+ var DNS_STUB_TTL = 30;
24650
+ var DNS_FORWARD_TIMEOUT_MS = 5e3;
24651
+ var DNS_TCP_IDLE_MS = 1e4;
24652
+ var DNS_TCP_MAX = 64;
24653
+ var DNS_UDP_INFLIGHT = 64;
24654
+ var TYPE_A = 1;
24655
+ var TYPE_PTR = 12;
24656
+ var TYPE_AAAA = 28;
24657
+ var TYPE_OPT = 41;
24658
+ var CLASS_IN = 1;
24659
+ var NOERROR = 0;
24660
+ var FORMERR = 1;
24661
+ var SERVFAIL = 2;
24662
+ var NXDOMAIN = 3;
24663
+ var NOTIMP = 4;
24664
+ var QR = 32768;
24665
+ var AA = 1024;
24666
+ var TC = 512;
24667
+ var RD = 256;
24668
+ var RA = 128;
24669
+ var CD = 16;
24670
+ var UDP_PLAIN = 512;
24671
+ var UDP_EDNS = 1232;
24672
+ var UDP_MAX = 4096;
24673
+ var DOH_MAX = 65535;
24674
+ var LOCAL_ZONES = ["localhost", "slicc.internal"];
24675
+ var MESSAGE = "application/dns-message";
24676
+ var u16 = (b, at) => b[at] << 8 | b[at + 1];
24677
+ function skipName(b, at) {
24678
+ let i = at;
24679
+ for (let hops = 0; hops < 128; hops++) {
24680
+ if (i >= b.length) return void 0;
24681
+ const len = b[i];
24682
+ if (len === 0) return i + 1;
24683
+ if ((len & 192) === 192) return i + 2 <= b.length ? i + 2 : void 0;
24684
+ if (len & 192) return void 0;
24685
+ i += len + 1;
24686
+ }
24687
+ return void 0;
24688
+ }
24689
+ function readName(b, at) {
24690
+ const labels = [];
24691
+ let i = at;
24692
+ let size = 0;
24693
+ for (; ; ) {
24694
+ if (i >= b.length) return void 0;
24695
+ const len = b[i];
24696
+ if (len === 0) break;
24697
+ if (len & 192) return void 0;
24698
+ size += len + 1;
24699
+ if (size > 254 || i + 1 + len > b.length) return void 0;
24700
+ labels.push(new TextDecoder().decode(b.subarray(i + 1, i + 1 + len)));
24701
+ i += len + 1;
24702
+ }
24703
+ return { name: labels.join(".").toLowerCase(), end: i + 1 };
24704
+ }
24705
+ function parseQuery(b) {
24706
+ if (b.length < 12) return void 0;
24707
+ const id2 = u16(b, 0);
24708
+ const flags2 = u16(b, 2);
24709
+ if (flags2 & QR) return void 0;
24710
+ if (flags2 >> 11 & 15) return { ok: false, id: id2, flags: flags2, rcode: NOTIMP };
24711
+ if (u16(b, 4) !== 1) return { ok: false, id: id2, flags: flags2, rcode: FORMERR };
24712
+ const read = readName(b, 12);
24713
+ if (!read || read.end + 4 > b.length) return { ok: false, id: id2, flags: flags2, rcode: FORMERR };
24714
+ const type = u16(b, read.end);
24715
+ const klass = u16(b, read.end + 2);
24716
+ const end = read.end + 4;
24717
+ let edns;
24718
+ let at = end;
24719
+ const records = u16(b, 6) + u16(b, 8) + u16(b, 10);
24720
+ for (let n = 0; n < records; n++) {
24721
+ const after = skipName(b, at);
24722
+ if (after === void 0 || after + 10 > b.length)
24723
+ return { ok: false, id: id2, flags: flags2, rcode: FORMERR };
24724
+ if (u16(b, after) === TYPE_OPT) edns = Math.max(UDP_PLAIN, u16(b, after + 2));
24725
+ at = after + 10 + u16(b, after + 8);
24726
+ if (at > b.length) return { ok: false, id: id2, flags: flags2, rcode: FORMERR };
24727
+ }
24728
+ return { ok: true, question: { id: id2, flags: flags2, name: read.name, type, klass, end, edns } };
24729
+ }
24730
+ function encodeName(name2) {
24731
+ const out = [];
24732
+ for (const label of name2.split(".").filter(Boolean)) {
24733
+ const bytes = new TextEncoder().encode(label);
24734
+ out.push(bytes.length, ...bytes);
24735
+ }
24736
+ out.push(0);
24737
+ return out;
24738
+ }
24739
+ function header2(id2, flags2, counts) {
24740
+ const out = [id2 >> 8, id2 & 255, flags2 >> 8, flags2 & 255];
24741
+ for (const c of counts) out.push(c >> 8, c & 255);
24742
+ return out;
24743
+ }
24744
+ function opt() {
24745
+ return [0, 0, TYPE_OPT, UDP_EDNS >> 8, UDP_EDNS & 255, 0, 0, 0, 0, 0, 0];
24746
+ }
24747
+ function record(type, rdata) {
24748
+ const ttl = DNS_STUB_TTL;
24749
+ return [
24750
+ 192,
24751
+ 12,
24752
+ type >> 8,
24753
+ type & 255,
24754
+ 0,
24755
+ CLASS_IN,
24756
+ ttl >>> 24 & 255,
24757
+ ttl >>> 16 & 255,
24758
+ ttl >>> 8 & 255,
24759
+ ttl & 255,
24760
+ rdata.length >> 8,
24761
+ rdata.length & 255,
24762
+ ...rdata
24763
+ ];
24764
+ }
24765
+ function replyFlags(query, rcode, aa) {
24766
+ return QR | query & 30720 | (aa ? AA : 0) | query & RD | RA | query & CD | rcode;
24767
+ }
24768
+ function answers(reply, q) {
24769
+ if (reply.length < 12 || !(u16(reply, 2) & QR) || u16(reply, 4) !== 1) return false;
24770
+ const read = readName(reply, 12);
24771
+ if (!read || read.end + 4 > reply.length) return false;
24772
+ return read.name === q.name && u16(reply, read.end) === q.type && u16(reply, read.end + 2) === q.klass;
24773
+ }
24774
+ function errorReply(id2, flags2, rcode) {
24775
+ return new Uint8Array(header2(id2, replyFlags(flags2, rcode, false), [0, 0, 0, 0]));
24776
+ }
24777
+ function answerReply(query, q, rcode, answers2, aa) {
24778
+ const extra = q.edns !== void 0 ? [opt()] : [];
24779
+ return new Uint8Array([
24780
+ ...header2(q.id, replyFlags(q.flags, rcode, aa), [1, answers2.length, 0, extra.length]),
24781
+ ...query.subarray(12, q.end),
24782
+ ...answers2.flat(),
24783
+ ...extra.flat()
24784
+ ]);
24785
+ }
24786
+ function truncated(reply, q, query) {
24787
+ const limit = q.edns !== void 0 ? Math.min(q.edns, UDP_MAX) : UDP_PLAIN;
24788
+ if (reply.length <= limit) return reply;
24789
+ const flags2 = u16(reply, 2) | TC;
24790
+ const extra = q.edns !== void 0 ? [opt()] : [];
24791
+ return new Uint8Array([
24792
+ ...header2(q.id, flags2, [1, 0, 0, extra.length]),
24793
+ ...query.subarray(12, q.end),
24794
+ ...extra.flat()
24795
+ ]);
24796
+ }
24797
+ function ipv6Text(groups) {
24798
+ return groups.map((g) => g.toString(16)).join(":");
24799
+ }
24800
+ function reverseAddress(name2) {
24801
+ if (name2.endsWith(".in-addr.arpa")) {
24802
+ const parts2 = name2.slice(0, -".in-addr.arpa".length).split(".");
24803
+ if (parts2.length !== 4) return void 0;
24804
+ const text = parts2.reverse().join(".");
24805
+ return ipv4Bytes(text) ? text.split(".").map(Number).join(".") : void 0;
24806
+ }
24807
+ if (name2.endsWith(".ip6.arpa")) {
24808
+ const nibbles = name2.slice(0, -".ip6.arpa".length).split(".");
24809
+ if (nibbles.length !== 32 || !nibbles.every((n) => /^[0-9a-f]$/.test(n))) return void 0;
24810
+ const hex4 = nibbles.reverse().join("");
24811
+ const groups = Array.from(
24812
+ { length: 8 },
24813
+ (_, i) => Number.parseInt(hex4.slice(i * 4, i * 4 + 4), 16)
24814
+ );
24815
+ return ipv6Text(groups);
24816
+ }
24817
+ return void 0;
24818
+ }
24819
+ function local(name2) {
24820
+ return LOCAL_ZONES.some((zone) => name2 === zone || name2.endsWith(`.${zone}`));
24821
+ }
24822
+ function literal(name2) {
24823
+ return ipv4Bytes(name2) !== void 0 || ipv6Groups(name2) !== void 0;
24824
+ }
24825
+ function addressData(address, type) {
24826
+ if (type === TYPE_A) return ipv4Bytes(address);
24827
+ const groups = type === TYPE_AAAA ? ipv6Groups(address) : void 0;
24828
+ return groups?.flatMap((g) => [g >> 8, g & 255]);
24829
+ }
24830
+ var DnsStub = class {
24831
+ resolver;
24832
+ forwarder;
24833
+ timeoutMs;
24834
+ constructor(options) {
24835
+ this.resolver = options.resolver;
24836
+ this.forwarder = options.forward;
24837
+ this.timeoutMs = options.timeoutMs ?? DNS_FORWARD_TIMEOUT_MS;
24838
+ }
24839
+ async answer(query, udp) {
24840
+ const parsed2 = parseQuery(query);
24841
+ if (!parsed2) return void 0;
24842
+ if (!parsed2.ok) return errorReply(parsed2.id, parsed2.flags, parsed2.rcode);
24843
+ const q = parsed2.question;
24844
+ const reply = await this.reply(query, q).catch(
24845
+ () => answerReply(query, q, SERVFAIL, [], false)
24846
+ );
24847
+ return udp ? truncated(reply, q, query) : reply;
24848
+ }
24849
+ async reply(query, q) {
24850
+ if (q.klass !== CLASS_IN || literal(q.name)) return this.forward(query, q);
24851
+ if (q.type === TYPE_PTR) {
24852
+ const address = reverseAddress(q.name);
24853
+ const name2 = address !== void 0 ? await this.reverse(address) : void 0;
24854
+ if (name2 !== void 0)
24855
+ return answerReply(query, q, NOERROR, [record(TYPE_PTR, encodeName(name2))], true);
24856
+ return this.forward(query, q);
24857
+ }
24858
+ if (q.type === TYPE_A || q.type === TYPE_AAAA) {
24859
+ const addresses = q.name === "" ? [] : await this.lookup(q.name);
24860
+ const answers2 = addresses.flatMap((a) => {
24861
+ const data = addressData(a, q.type);
24862
+ return data ? [record(q.type, data)] : [];
24863
+ });
24864
+ if (answers2.length > 0 || local(q.name) || await this.known(q.name)) {
24865
+ const rcode = addresses.length > 0 ? NOERROR : NXDOMAIN;
24866
+ return answerReply(query, q, rcode, answers2, local(q.name));
24867
+ }
24868
+ return this.forward(query, q);
24544
24869
  }
24870
+ if (await this.known(q.name)) return answerReply(query, q, NOERROR, [], true);
24871
+ if (local(q.name)) {
24872
+ const there = (await this.lookup(q.name)).length > 0;
24873
+ return answerReply(query, q, there ? NOERROR : NXDOMAIN, [], true);
24874
+ }
24875
+ return this.forward(query, q);
24545
24876
  }
24546
- return table;
24877
+ lookup(name2) {
24878
+ return this.resolver.resolve(name2, 0).catch(() => []);
24879
+ }
24880
+ known(name2) {
24881
+ return this.resolver.known(name2).catch(() => false);
24882
+ }
24883
+ reverse(address) {
24884
+ return this.resolver.reverse(address).catch(() => void 0);
24885
+ }
24886
+ async forward(query, q) {
24887
+ if (!this.forwarder) return answerReply(query, q, SERVFAIL, [], false);
24888
+ const asked = query.slice();
24889
+ asked[0] = 0;
24890
+ asked[1] = 0;
24891
+ const got = await this.forwarder(asked, AbortSignal.timeout(this.timeoutMs)).catch(
24892
+ () => void 0
24893
+ );
24894
+ if (!got || !answers(got, q)) return answerReply(query, q, SERVFAIL, [], false);
24895
+ const reply = got.slice();
24896
+ reply[0] = q.id >> 8;
24897
+ reply[1] = q.id & 255;
24898
+ return reply;
24899
+ }
24900
+ };
24901
+ async function collect(body, max) {
24902
+ const parts2 = [];
24903
+ let size = 0;
24904
+ for await (const part of body) {
24905
+ size += part.length;
24906
+ if (size > max) return void 0;
24907
+ parts2.push(part);
24908
+ }
24909
+ const out = new Uint8Array(size);
24910
+ let at = 0;
24911
+ for (const part of parts2) {
24912
+ out.set(part, at);
24913
+ at += part.length;
24914
+ }
24915
+ return out;
24547
24916
  }
24548
- function hostsReader(fs, path = HOSTS_PATH) {
24549
- let stamp = "";
24550
- let table;
24551
- return async () => {
24552
- const st = await fs.stat(path).catch(() => void 0);
24553
- if (!st?.isFile) {
24554
- stamp = "";
24555
- table = void 0;
24917
+ function dohForward(transport, url) {
24918
+ return async (query, signal) => {
24919
+ const res = await transport.fetch({
24920
+ url,
24921
+ method: "POST",
24922
+ headers: [
24923
+ ["content-type", MESSAGE],
24924
+ ["accept", MESSAGE]
24925
+ ],
24926
+ body: query,
24927
+ signal
24928
+ });
24929
+ const type = res.headers.find(([k]) => k.toLowerCase() === "content-type")?.[1] ?? "";
24930
+ if (res.status !== 200 || type.split(";")[0].trim().toLowerCase() !== MESSAGE) {
24931
+ await res.cancel().catch(() => void 0);
24556
24932
  return void 0;
24557
24933
  }
24558
- const now = `${st.ino}:${st.size}:${st.mtime.getTime()}`;
24559
- if (now === stamp && table) return table;
24560
- const text = await fs.readFile(path).catch(() => void 0);
24561
- if (text === void 0) return void 0;
24562
- stamp = now;
24563
- table = parseHosts(text);
24564
- return table;
24934
+ return collect(res.body, DOH_MAX);
24935
+ };
24936
+ }
24937
+ function uplinkForward(uplink, server) {
24938
+ return async (query, signal) => {
24939
+ const conn = await uplink.dial({ network: "tcp", host: server, port: DNS_PORT, signal });
24940
+ const stop = () => conn.close();
24941
+ signal.addEventListener("abort", stop, { once: true });
24942
+ try {
24943
+ await conn.write(new Uint8Array([query.length >> 8, query.length & 255, ...query]));
24944
+ let got = new Uint8Array();
24945
+ for (; ; ) {
24946
+ if (got.length >= 2 && got.length >= 2 + u16(got, 0)) return got.slice(2, 2 + u16(got, 0));
24947
+ const piece = await conn.read();
24948
+ if (!piece) return void 0;
24949
+ const next3 = new Uint8Array(got.length + piece.length);
24950
+ next3.set(got);
24951
+ next3.set(piece, got.length);
24952
+ got = next3;
24953
+ }
24954
+ } finally {
24955
+ signal.removeEventListener("abort", stop);
24956
+ conn.close();
24957
+ }
24565
24958
  };
24566
24959
  }
24960
+ function dnsForward(uplink, transport, doh) {
24961
+ const server = uplink?.nameserver;
24962
+ if (uplink && server && (ipv4Bytes(server) || ipv6Groups(server)))
24963
+ return uplinkForward(uplink, server);
24964
+ return typeof doh === "string" ? dohForward(transport, doh) : void 0;
24965
+ }
24966
+ function kernelDnsStub(resolver, transport, uplink, doh) {
24967
+ return new DnsStub({ resolver, forward: dnsForward(uplink, transport, doh) });
24968
+ }
24969
+ async function readExactly(conn, size, signal) {
24970
+ const out = new Uint8Array(size);
24971
+ let at = 0;
24972
+ while (at < size) {
24973
+ const piece = await conn.read(size - at, signal);
24974
+ if (piece.length === 0) return void 0;
24975
+ out.set(piece, at);
24976
+ at += piece.length;
24977
+ }
24978
+ return out;
24979
+ }
24980
+ async function serveTcp(stub, conn) {
24981
+ try {
24982
+ for (; ; ) {
24983
+ const idle2 = AbortSignal.timeout(DNS_TCP_IDLE_MS);
24984
+ const size = await readExactly(conn, 2, idle2);
24985
+ if (!size) return;
24986
+ const query = await readExactly(conn, u16(size, 0), idle2);
24987
+ if (!query) return;
24988
+ const reply = await stub.answer(query, false);
24989
+ if (!reply) return;
24990
+ const framed = new Uint8Array([reply.length >> 8, reply.length & 255, ...reply]);
24991
+ const sent = await conn.write(framed, AbortSignal.timeout(DNS_TCP_IDLE_MS));
24992
+ if (sent < framed.length) return;
24993
+ }
24994
+ } catch {
24995
+ return;
24996
+ } finally {
24997
+ conn.close();
24998
+ }
24999
+ }
25000
+ function enableDnsStub(net, stub) {
25001
+ const at = { family: "inet", host: "127.0.0.1", port: DNS_PORT };
25002
+ net.reserve(DNS_PORT);
25003
+ net.kernelOnly(DNS_PORT, true);
25004
+ net.activate(at, () => {
25005
+ const listener = net.listen(at);
25006
+ const open = /* @__PURE__ */ new Set();
25007
+ void (async () => {
25008
+ for (; ; ) {
25009
+ const conn = await listener.accept().catch(() => void 0);
25010
+ if (!conn) return;
25011
+ if (open.size >= DNS_TCP_MAX) {
25012
+ conn.close();
25013
+ continue;
25014
+ }
25015
+ open.add(conn);
25016
+ void serveTcp(stub, conn).finally(() => open.delete(conn));
25017
+ }
25018
+ })();
25019
+ });
25020
+ let inflight = 0;
25021
+ net.serveDgram(DNS_PORT, (datagram2, to) => {
25022
+ if (inflight >= DNS_UDP_INFLIGHT) return;
25023
+ inflight++;
25024
+ void stub.answer(datagram2.bytes, true).then(
25025
+ (reply) => {
25026
+ if (!reply) return;
25027
+ const from = { family: "inet", host: to.host, port: DNS_PORT };
25028
+ net.deliverDgram(datagram2.from.port, { bytes: reply, from });
25029
+ },
25030
+ () => void 0
25031
+ ).finally(() => inflight--);
25032
+ });
25033
+ }
24567
25034
 
24568
25035
  // src/kernel/net/redirect-hops.ts
24569
25036
  var HELD_MS = 3e4;
@@ -24571,13 +25038,13 @@ var HELD_MAX = 64;
24571
25038
  var HELD_PER_OWNER = 8;
24572
25039
  var MATCHED = ["range", "if-none-match", "if-modified-since", "if-range", "accept-encoding"];
24573
25040
  var KERNEL = -1;
24574
- function header2(headers, name2) {
25041
+ function header3(headers, name2) {
24575
25042
  const values = headers.filter(([n]) => n.toLowerCase() === name2).map(([, v]) => v);
24576
25043
  return values.length > 0 ? values.join(", ") : void 0;
24577
25044
  }
24578
25045
  function fingerprint(headers) {
24579
- const fields = MATCHED.map((name2) => header2(headers, name2) ?? "");
24580
- return JSON.stringify([...fields, header2(headers, "authorization") !== void 0]);
25046
+ const fields = MATCHED.map((name2) => header3(headers, name2) ?? "");
25047
+ return JSON.stringify([...fields, header3(headers, "authorization") !== void 0]);
24581
25048
  }
24582
25049
  function unauthorized(print) {
24583
25050
  return JSON.stringify([...JSON.parse(print).slice(0, -1), false]);
@@ -24620,7 +25087,7 @@ function replayingHops(inner, heldMs = HELD_MS) {
24620
25087
  };
24621
25088
  const replay = (chain2) => {
24622
25089
  const [hop, ...rest2] = chain2.hops;
24623
- const location = hop && header2(hop.headers, "location");
25090
+ const location = hop && header3(hop.headers, "location");
24624
25091
  if (!hop || location === void 0) return chain2.final;
24625
25092
  const target = new URL(location, hop.url);
24626
25093
  target.hash = "";
@@ -24745,7 +25212,7 @@ function materializable(req) {
24745
25212
  if (req.shellGrants !== true && !isStrings(req.names)) return false;
24746
25213
  return isStrings(req.argv) && typeof req.path === "string" && typeof req.cwd === "string";
24747
25214
  }
24748
- function errorReply(code, message3) {
25215
+ function errorReply2(code, message3) {
24749
25216
  return { v: 1, error: { code, message: message3 } };
24750
25217
  }
24751
25218
  function isRecord(value2) {
@@ -24757,9 +25224,9 @@ function serialized(reply) {
24757
25224
  const text = JSON.stringify(reply);
24758
25225
  plain3 = text === void 0 ? void 0 : JSON.parse(text);
24759
25226
  } catch (err) {
24760
- return JSON.stringify(errorReply("EIO", lineOf2(err)));
25227
+ return JSON.stringify(errorReply2("EIO", lineOf2(err)));
24761
25228
  }
24762
- if (!isRecord(plain3)) return JSON.stringify(errorReply("EIO", "the vault gave no reply"));
25229
+ if (!isRecord(plain3)) return JSON.stringify(errorReply2("EIO", "the vault gave no reply"));
24763
25230
  const { v: _, ...rest2 } = plain3;
24764
25231
  return JSON.stringify({ v: 1, ...rest2 });
24765
25232
  }
@@ -24807,18 +25274,18 @@ var SealedChannel = class {
24807
25274
  }
24808
25275
  async answer(req, signal) {
24809
25276
  const hook = this.broker.hook;
24810
- if (!hook) return errorReply("ENOTCONN", "no vault is connected");
25277
+ if (!hook) return errorReply2("ENOTCONN", "no vault is connected");
24811
25278
  const stopped = new Promise((resolve2) => {
24812
25279
  signal.addEventListener("abort", () => resolve2(void 0), { once: true });
24813
25280
  });
24814
25281
  if (signal.aborted) return void 0;
24815
25282
  const asked = Promise.resolve().then(() => hook(req, { signal })).then(
24816
- (reply2) => isRecord(reply2) ? reply2 : errorReply("EIO", "the vault gave no reply"),
24817
- (err) => errorReply("EIO", lineOf2(err))
25283
+ (reply2) => isRecord(reply2) ? reply2 : errorReply2("EIO", "the vault gave no reply"),
25284
+ (err) => errorReply2("EIO", lineOf2(err))
24818
25285
  );
24819
25286
  const reply = await Promise.race([asked, stopped]);
24820
25287
  if (!signal.aborted) return reply;
24821
- return signal.reason === "timeout" ? errorReply("ETIMEDOUT", "the vault did not answer within 10 s") : void 0;
25288
+ return signal.reason === "timeout" ? errorReply2("ETIMEDOUT", "the vault did not answer within 10 s") : void 0;
24822
25289
  }
24823
25290
  drop() {
24824
25291
  this.reply?.fill(0);
@@ -27232,6 +27699,10 @@ function dataModuleUrl(source) {
27232
27699
  return { url: `data:text/javascript;base64,${btoa(binary2)}`, revoke: () => {
27233
27700
  } };
27234
27701
  }
27702
+ function describe(req, tty) {
27703
+ const exe = req.exe === void 0 ? {} : { exe: req.exe };
27704
+ return { argv: [req.argv0, ...req.args], tty, started: Date.now(), ...exe };
27705
+ }
27235
27706
  function linksOf2(req) {
27236
27707
  return req.links === void 0 ? {} : { links: req.links };
27237
27708
  }
@@ -27253,6 +27724,7 @@ var LAYOUT = [
27253
27724
  ["/etc", 493],
27254
27725
  [PASSWD, 420],
27255
27726
  [GROUP, 420],
27727
+ [RESOLV_CONF_PATH, 420],
27256
27728
  ["/usr", 493],
27257
27729
  ["/usr/local", 493]
27258
27730
  ];
@@ -27595,6 +28067,10 @@ var Launcher = class {
27595
28067
  roots: packageTlsRoots(this.verifiedFs(options.fs), this.modulesDir),
27596
28068
  ca: this.ca
27597
28069
  });
28070
+ enableDnsStub(
28071
+ this.net,
28072
+ kernelDnsStub(this.resolver, this.transport, options.uplink, options.doh)
28073
+ );
27598
28074
  enableCdp(this.net, this.cdp);
27599
28075
  this.facades.enable(this.net);
27600
28076
  const fs = this.commandFs(this.base);
@@ -27682,10 +28158,10 @@ var Launcher = class {
27682
28158
  ready: () => this.fstab,
27683
28159
  lookup: (name2) => this.users.lookup(name2),
27684
28160
  watch: async (paths, notify) => {
27685
- const local = this.watchers.watch(paths, { recursive: true }, () => notify());
28161
+ const local2 = this.watchers.watch(paths, { recursive: true }, () => notify());
27686
28162
  const remote = await this.watchFiles(paths, notify);
27687
28163
  return () => {
27688
- local();
28164
+ local2();
27689
28165
  remote();
27690
28166
  };
27691
28167
  },
@@ -27871,7 +28347,7 @@ var Launcher = class {
27871
28347
  abi: "wasi",
27872
28348
  glue,
27873
28349
  wasm: glue,
27874
- argv0: baseName2(argv0 || file).replace(/\.wasm$/, ""),
28350
+ argv0,
27875
28351
  ...asked
27876
28352
  };
27877
28353
  }
@@ -28413,7 +28889,18 @@ var Launcher = class {
28413
28889
  const handle = await this.admitted(
28414
28890
  program.abi !== "js",
28415
28891
  req.fds,
28416
- (fds, quietOom) => this.start({ ...req, fds, quietOom, cwd, program, argv0: target.argv0, args, env, cwdSlot })
28892
+ (fds, quietOom) => this.start({
28893
+ ...req,
28894
+ fds,
28895
+ quietOom,
28896
+ cwd,
28897
+ program,
28898
+ argv0: target.argv0,
28899
+ exe: target.copy ?? target.glue,
28900
+ args,
28901
+ env,
28902
+ cwdSlot
28903
+ })
28417
28904
  ).finally(() => this.cwds.release(cwdSlot));
28418
28905
  void handle.exited.finally(done4);
28419
28906
  return handle;
@@ -28605,11 +29092,7 @@ var Launcher = class {
28605
29092
  if (req.pgid !== void 0) this.jobs.join(pid, req.pgid);
28606
29093
  if (req.group === "lead") this.jobs.lead(pid);
28607
29094
  if (req.group === "session") this.jobs.setsid(pid);
28608
- this.described.set(pid, {
28609
- argv: [req.argv0, ...req.args],
28610
- tty: terminal?.name ?? null,
28611
- started: Date.now()
28612
- });
29095
+ this.described.set(pid, describe(req, terminal?.name ?? null));
28613
29096
  handle.onState(
28614
29097
  (state) => state === "stopped" ? this.stopped.add(pid) : this.stopped.delete(pid)
28615
29098
  );
@@ -29217,6 +29700,19 @@ var Launcher = class {
29217
29700
  inUse(path) {
29218
29701
  return [...this.openFiles].some((nodes) => nodes.holds(path)) || heldUnder(this.held, path);
29219
29702
  }
29703
+ async resolvConf() {
29704
+ if (isProtected(this.prefixes, RESOLV_CONF_PATH)) return;
29705
+ try {
29706
+ const there = await this.base.lstat(RESOLV_CONF_PATH).then(
29707
+ () => true,
29708
+ () => false
29709
+ );
29710
+ if (there) return;
29711
+ await this.base.writeFile(RESOLV_CONF_PATH, RESOLV_CONF);
29712
+ } catch {
29713
+ return;
29714
+ }
29715
+ }
29220
29716
  async stampLayout() {
29221
29717
  const layout = [
29222
29718
  ...LAYOUT,
@@ -29352,6 +29848,7 @@ var Launcher = class {
29352
29848
  await this.mountShm();
29353
29849
  await this.pnpmReady();
29354
29850
  await this.users.ensure();
29851
+ await this.resolvConf();
29355
29852
  if (this.owners) await this.stampLayout();
29356
29853
  if (this.owners) await this.sudoer.provision();
29357
29854
  await writeCaFile(this.base, this.ca).catch(() => void 0);
@@ -29590,12 +30087,12 @@ var Launcher = class {
29590
30087
  const out = [];
29591
30088
  const err = [];
29592
30089
  const keep2 = options.collect !== false;
29593
- const collect = (chunks2, tee) => (bytes) => {
30090
+ const collect2 = (chunks2, tee) => (bytes) => {
29594
30091
  if (keep2) chunks2.push(bytes);
29595
30092
  tee?.(bytes);
29596
30093
  };
29597
- const stdout = collect(out, options.onStdout);
29598
- const stderr = collect(err, options.onStderr);
30094
+ const stdout = collect2(out, options.onStdout);
30095
+ const stderr = collect2(err, options.onStderr);
29599
30096
  const report = (message3) => stderr(encoder10.encode(`${message3}
29600
30097
  `));
29601
30098
  if (!planned) {
@@ -30457,7 +30954,7 @@ function parseHead2(bytes) {
30457
30954
  }
30458
30955
  return { status: Number(match[1]), statusText: match[2] ?? "", headers };
30459
30956
  }
30460
- function header3(head, name2) {
30957
+ function header4(head, name2) {
30461
30958
  return head.headers.find(([key]) => key.toLowerCase() === name2)?.[1];
30462
30959
  }
30463
30960
  async function* chunked2(source) {
@@ -30486,8 +30983,8 @@ async function* untilClose2(source) {
30486
30983
  }
30487
30984
  function bodyOf2(source, head, method) {
30488
30985
  if (method === "HEAD" || head.status === 204 || head.status === 304) return void 0;
30489
- if (header3(head, "transfer-encoding")?.toLowerCase().includes("chunked")) return chunked2(source);
30490
- const length2 = header3(head, "content-length");
30986
+ if (header4(head, "transfer-encoding")?.toLowerCase().includes("chunked")) return chunked2(source);
30987
+ const length2 = header4(head, "content-length");
30491
30988
  if (length2 === void 0) return untilClose2(source);
30492
30989
  const size = Number(length2);
30493
30990
  if (!/^\d+$/.test(length2.trim()) || !Number.isSafeInteger(size)) {
@@ -31107,6 +31604,7 @@ async function createNodeKernel(options = {}) {
31107
31604
  ...options.env ? { env: options.env } : {},
31108
31605
  ...transport ? { transport } : {},
31109
31606
  ...options.network?.uplink ? { uplink: options.network.uplink } : {},
31607
+ ...options.network?.doh !== void 0 ? { doh: options.network.doh } : {},
31110
31608
  ...options.processMounts !== void 0 ? { processMounts: options.processMounts } : {},
31111
31609
  ...options.fstabRetries ? { fstabRetries: options.fstabRetries } : {},
31112
31610
  ...options.hostfs ? { hostfs: options.hostfs } : {},