@ai-ecoverse/slicc-kernel 1.89.0 → 1.90.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.
@@ -2052,7 +2052,7 @@ function portCdpHook(ask, gone) {
2052
2052
  }
2053
2053
 
2054
2054
  // src/client/protocol.ts
2055
- var PROTOCOL = [1, 10];
2055
+ var PROTOCOL = [1, 11];
2056
2056
  var FS_METHODS = [
2057
2057
  "readFile",
2058
2058
  "writeFile",
@@ -2083,6 +2083,52 @@ function fresh(bytes, start2 = 0, end = bytes.length) {
2083
2083
  return new Uint8Array(bytes.subarray(start2, end));
2084
2084
  }
2085
2085
 
2086
+ // src/facade/port.ts
2087
+ var FACADE_GONE = "the facade host is gone";
2088
+ function portFacadeHook(ask, gone) {
2089
+ return (stamp, { name: name2 }) => new Promise((resolve2, reject) => {
2090
+ const { port1, port2 } = new MessageChannel();
2091
+ let closed = false;
2092
+ const shut = () => {
2093
+ closed = true;
2094
+ port1.close();
2095
+ };
2096
+ const conn = {
2097
+ send: (bytes) => {
2098
+ if (closed) return;
2099
+ const copy = bytes.slice();
2100
+ port1.postMessage({ b: copy }, [copy.buffer]);
2101
+ },
2102
+ onmessage: null,
2103
+ onclose: null,
2104
+ close: (reason) => {
2105
+ if (closed) return;
2106
+ port1.postMessage({ close: reason ?? true });
2107
+ shut();
2108
+ }
2109
+ };
2110
+ port1.addEventListener("message", ({ data }) => {
2111
+ if ("b" in data) conn.onmessage?.(data.b);
2112
+ else if ("open" in data) resolve2(conn);
2113
+ else if ("error" in data) {
2114
+ shut();
2115
+ reject(new Error(data.error));
2116
+ } else if (!closed) {
2117
+ shut();
2118
+ conn.onclose?.();
2119
+ }
2120
+ });
2121
+ port1.start();
2122
+ void gone?.then(() => {
2123
+ if (closed) return;
2124
+ shut();
2125
+ reject(new Error(FACADE_GONE));
2126
+ conn.onclose?.(FACADE_GONE);
2127
+ });
2128
+ ask({ name: name2, stamp }, port2);
2129
+ });
2130
+ }
2131
+
2086
2132
  // src/fs/walk.ts
2087
2133
  var MAX_LINKS3 = 40;
2088
2134
  function parentOf4(path) {
@@ -3137,6 +3183,7 @@ var KernelSocket = class _KernelSocket {
3137
3183
  local;
3138
3184
  peer;
3139
3185
  peerCred;
3186
+ peerStamp;
3140
3187
  listenerCred;
3141
3188
  link;
3142
3189
  readShut = false;
@@ -3207,10 +3254,10 @@ var KernelSocket = class _KernelSocket {
3207
3254
  for (const wait2 of waits) wait2.catch(() => void 0);
3208
3255
  return pipeCall(() => Promise.race(waits));
3209
3256
  }
3210
- bind(addr) {
3257
+ bind(addr, kernel = false) {
3211
3258
  if (this.state !== "open" || this.local) throw new KernelError("EINVAL");
3212
3259
  if (addr.family !== this.domain) throw new KernelError("EAFNOSUPPORT");
3213
- this.local = this.net.bind(this, addr);
3260
+ this.local = this.net.bind(this, addr, kernel);
3214
3261
  this.boundAt = this.local;
3215
3262
  }
3216
3263
  listen(backlog, cred) {
@@ -3239,7 +3286,7 @@ var KernelSocket = class _KernelSocket {
3239
3286
  this.changes.wake();
3240
3287
  return true;
3241
3288
  }
3242
- connect(addr, viaUplink = true, cred) {
3289
+ connect(addr, viaUplink = true, cred, stamp) {
3243
3290
  if (this.state === "connected") throw new KernelError("EISCONN");
3244
3291
  if (this.state === "connecting") throw new KernelError("EALREADY");
3245
3292
  if (this.state !== "open") throw new KernelError("EINVAL");
@@ -3258,6 +3305,7 @@ var KernelSocket = class _KernelSocket {
3258
3305
  server.local = addr.family === "inet" ? { ...addr, host: canonicalHost(addr.host) } : addr;
3259
3306
  server.peer = this.local;
3260
3307
  server.peerCred = cred;
3308
+ server.peerStamp = stamp;
3261
3309
  this.peer = server.local;
3262
3310
  this.peerCred = target.listenerCred;
3263
3311
  link(this, server);
@@ -3398,6 +3446,8 @@ var LoopbackNet = class {
3398
3446
  bound = /* @__PURE__ */ new Map();
3399
3447
  activators = /* @__PURE__ */ new Map();
3400
3448
  internal = /* @__PURE__ */ new Set();
3449
+ reserved = /* @__PURE__ */ new Set();
3450
+ facades = /* @__PURE__ */ new Map();
3401
3451
  nextEphemeral = EPHEMERAL_FIRST;
3402
3452
  route;
3403
3453
  useUplink(route) {
@@ -3412,6 +3462,18 @@ var LoopbackNet = class {
3412
3462
  if (reserve) this.internal.add(port);
3413
3463
  return this.internal.has(port);
3414
3464
  }
3465
+ reserve(port) {
3466
+ this.reserved.add(port);
3467
+ }
3468
+ facade(port, name2) {
3469
+ this.reserve(port);
3470
+ this.kernelOnly(port, true);
3471
+ this.facades.set(port, name2);
3472
+ }
3473
+ facadeAt(addr) {
3474
+ if (addr.family !== "inet" || !isLoopback(canonicalHost(addr.host))) return void 0;
3475
+ return this.facades.get(addr.port);
3476
+ }
3415
3477
  activate(addr, start2) {
3416
3478
  this.activators.set(keyOf(addr), start2);
3417
3479
  }
@@ -3420,7 +3482,7 @@ var LoopbackNet = class {
3420
3482
  }
3421
3483
  listen(addr, backlog = 128) {
3422
3484
  const socket = this.socket(addr.family);
3423
- socket.bind(addr);
3485
+ socket.bind(addr, true);
3424
3486
  socket.listen(backlog);
3425
3487
  return socket;
3426
3488
  }
@@ -3429,11 +3491,13 @@ var LoopbackNet = class {
3429
3491
  void socket.connect(addr, false);
3430
3492
  return socket;
3431
3493
  }
3432
- bind(socket, addr) {
3494
+ bind(socket, addr, kernel = false) {
3433
3495
  if (addr.family === "unix") {
3434
3496
  if (addr.path === "") throw new KernelError("EINVAL");
3435
3497
  } else if (addr.host !== "0.0.0.0" && !isLoopback(addr.host)) {
3436
3498
  throw new KernelError("EADDRNOTAVAIL");
3499
+ } else if (!kernel && this.reserved.has(addr.port)) {
3500
+ throw new KernelError("EADDRINUSE");
3437
3501
  }
3438
3502
  const named = addr.family === "inet" && addr.port === 0 ? { ...addr, port: this.ephemeral() } : addr;
3439
3503
  const key = keyOf(named);
@@ -3460,7 +3524,7 @@ var LoopbackNet = class {
3460
3524
  for (let i = 0; i < span; i++) {
3461
3525
  const port = this.nextEphemeral;
3462
3526
  this.nextEphemeral = port === EPHEMERAL_LAST ? EPHEMERAL_FIRST : port + 1;
3463
- if (!this.bound.has(`inet:${port}`)) return port;
3527
+ if (!this.bound.has(`inet:${port}`) && !this.reserved.has(port)) return port;
3464
3528
  }
3465
3529
  throw new KernelError("EADDRINUSE");
3466
3530
  }
@@ -3756,12 +3820,12 @@ function serveTransport(peer, transport, { closeWaitMs = CLOSE_WAIT_MS } = {}) {
3756
3820
  }
3757
3821
  sockets.set(call.nid, socket);
3758
3822
  peer.postMessage({ net: "ws-opened", nid: call.nid, protocol: socket.protocol });
3759
- void relay(call.nid, socket);
3823
+ void relay2(call.nid, socket);
3760
3824
  } catch (e) {
3761
3825
  fail2(call.nid, e);
3762
3826
  }
3763
3827
  };
3764
- const relay = async (nid, socket) => {
3828
+ const relay2 = async (nid, socket) => {
3765
3829
  let ending;
3766
3830
  let late;
3767
3831
  const unanswered = new Promise((resolve2) => {
@@ -4395,6 +4459,45 @@ function cdpRegistry(send, gone) {
4395
4459
  }
4396
4460
  };
4397
4461
  }
4462
+ function facadeRegistry(send, gone) {
4463
+ const registered = /* @__PURE__ */ new Map();
4464
+ const drop = (id2) => {
4465
+ registered.get(id2)?.();
4466
+ return registered.delete(id2);
4467
+ };
4468
+ return {
4469
+ serve(l, req) {
4470
+ const hook = portFacadeHook(
4471
+ (request2, facade) => send({ facadeOpen: { ...request2, registration: req.id }, port: facade }, [
4472
+ facade
4473
+ ]),
4474
+ gone
4475
+ );
4476
+ registered.set(req.id, l.facades.register(req.name, hook));
4477
+ return req.id;
4478
+ },
4479
+ drop,
4480
+ close: () => {
4481
+ for (const id2 of [...registered.keys()]) drop(id2);
4482
+ }
4483
+ };
4484
+ }
4485
+ function hostRegistries(send, gone) {
4486
+ const cdps = cdpRegistry(send, gone);
4487
+ const facades = facadeRegistry(send, gone);
4488
+ return {
4489
+ answer(l, req) {
4490
+ if (req.op === "serve-cdp") return cdps.serve(l, req);
4491
+ if (req.op === "unserve-cdp") return cdps.drop(req.registration);
4492
+ if (req.op === "serve-facade") return facades.serve(l, req);
4493
+ return facades.drop(req.registration);
4494
+ },
4495
+ close() {
4496
+ cdps.close();
4497
+ facades.close();
4498
+ }
4499
+ };
4500
+ }
4398
4501
  function visibleTo(g, notify) {
4399
4502
  if (!g?.dac.enforcing) return notify;
4400
4503
  let queue = Promise.resolve();
@@ -4438,7 +4541,7 @@ function serveClient(port, host) {
4438
4541
  if (state !== "closed") port.postMessage(message3, transfer);
4439
4542
  };
4440
4543
  const reply = (id2, body, transfer) => send({ id: id2, ...body }, transfer);
4441
- const cdps = cdpRegistry(send, ended.promise);
4544
+ const hosts = hostRegistries(send, ended.promise);
4442
4545
  function detach(kill = false, bye = "the slicc-kernel detached this client") {
4443
4546
  if (state === "closed") return;
4444
4547
  send({ bye });
@@ -4446,7 +4549,7 @@ function serveClient(port, host) {
4446
4549
  net?.close();
4447
4550
  for (const unwatch of watches.values()) unwatch();
4448
4551
  watches.clear();
4449
- cdps.close();
4552
+ hosts.close();
4450
4553
  for (const session of terminals.values()) session.close();
4451
4554
  terminals.clear();
4452
4555
  if (kill) killGroups(host, [...groups]);
@@ -4543,16 +4646,16 @@ function serveClient(port, host) {
4543
4646
  case "mount":
4544
4647
  return { result: await l.mountAs(clientCred(self), req.spec) };
4545
4648
  case "umount":
4546
- await l.umountAs(clientCred(self), req.target);
4547
- return { result: true };
4649
+ return { result: await l.umountAs(clientCred(self), req.target).then(() => true) };
4548
4650
  case "mounts":
4549
4651
  return { result: l.mounts.list() };
4550
4652
  case "dial":
4551
4653
  return dialFor(l, req, watches);
4552
4654
  case "serve-cdp":
4553
- return { result: cdps.serve(l, req) };
4554
4655
  case "unserve-cdp":
4555
- return { result: cdps.drop(req.registration) };
4656
+ case "serve-facade":
4657
+ case "unserve-facade":
4658
+ return { result: hosts.answer(l, req) };
4556
4659
  case "detach":
4557
4660
  return { result: true };
4558
4661
  default:
@@ -7127,6 +7230,7 @@ var Relay = class {
7127
7230
  function enableCdp(net, hosts) {
7128
7231
  let facade;
7129
7232
  net.kernelOnly(CDP_PORT, true);
7233
+ net.reserve(CDP_PORT);
7130
7234
  net.activate({ family: "inet", host: "127.0.0.1", port: CDP_PORT }, () => {
7131
7235
  const started = new CdpFacade({ net, hosts });
7132
7236
  facade = started;
@@ -7441,9 +7545,9 @@ async function scanFilesystems(fs, modules) {
7441
7545
  } catch {
7442
7546
  continue;
7443
7547
  }
7444
- const declared = manifest.slicc?.filesystems;
7445
- if (!declared || typeof declared !== "object") continue;
7446
- for (const [type, entry] of Object.entries(declared)) {
7548
+ const declared2 = manifest.slicc?.filesystems;
7549
+ if (!declared2 || typeof declared2 !== "object") continue;
7550
+ for (const [type, entry] of Object.entries(declared2)) {
7447
7551
  const module = inside(pkg, entry?.module);
7448
7552
  if (NAME2.test(type) && module && !found.has(type)) found.set(type, module);
7449
7553
  }
@@ -7461,9 +7565,9 @@ async function scanBinfmts(fs, modules, warn = () => {
7461
7565
  } catch {
7462
7566
  continue;
7463
7567
  }
7464
- const declared = manifest.slicc?.binfmt;
7465
- if (!declared || typeof declared !== "object") continue;
7466
- for (const [suffix, command] of Object.entries(declared)) {
7568
+ const declared2 = manifest.slicc?.binfmt;
7569
+ if (!declared2 || typeof declared2 !== "object") continue;
7570
+ for (const [suffix, command] of Object.entries(declared2)) {
7467
7571
  if (!SUFFIX.test(suffix) || typeof command !== "string" || !NAME2.test(command)) continue;
7468
7572
  const owner = owners.get(suffix);
7469
7573
  if (owner === void 0) {
@@ -7493,6 +7597,132 @@ function binfmtOf(binfmts, path) {
7493
7597
  return best === void 0 ? void 0 : binfmts.get(best);
7494
7598
  }
7495
7599
 
7600
+ // src/facade/types.ts
7601
+ var FACADE_NAME = /^[a-z][a-z0-9-]*$/;
7602
+ function facadeEnvName(name2) {
7603
+ return `SLICC_${name2.toUpperCase().replaceAll("-", "_")}_URL`;
7604
+ }
7605
+ function facadeUrl(port) {
7606
+ return `tcp://127.0.0.1:${port}`;
7607
+ }
7608
+
7609
+ // src/facade/hosts.ts
7610
+ var TAKEN_PORTS = /* @__PURE__ */ new Set([CDP_PORT, REALM_PROXY_PORT]);
7611
+ var READ_CHUNK = 64 * 1024;
7612
+ var FACADE_MAX_PENDING = 16 * 1024 * 1024;
7613
+ var FACADE_FLOODED = `slicc-kernel: more than ${FACADE_MAX_PENDING} bytes are waiting for the program to read`;
7614
+ function declared(specs) {
7615
+ const out = /* @__PURE__ */ new Map();
7616
+ const ports = /* @__PURE__ */ new Set();
7617
+ for (const [name2, spec] of Object.entries(specs ?? {})) {
7618
+ if (!FACADE_NAME.test(name2)) throw new TypeError(`facades: not a facade name: ${name2}`);
7619
+ const port = spec?.port;
7620
+ if (!Number.isInteger(port) || port < 1 || port > 65535 || TAKEN_PORTS.has(port)) {
7621
+ throw new TypeError(`facades.${name2}: not a free port: ${String(port)}`);
7622
+ }
7623
+ if (ports.has(port)) throw new TypeError(`facades.${name2}: port ${port} is taken twice`);
7624
+ if (spec.hook !== void 0 && typeof spec.hook !== "function") {
7625
+ throw new TypeError(`facades.${name2}: hook must be a function`);
7626
+ }
7627
+ ports.add(port);
7628
+ out.set(name2, { port, embedder: spec.hook, clients: [] });
7629
+ }
7630
+ return out;
7631
+ }
7632
+ var FacadeHosts = class {
7633
+ facades;
7634
+ constructor(specs) {
7635
+ this.facades = declared(specs);
7636
+ }
7637
+ env() {
7638
+ const env = {};
7639
+ for (const [name2, { port }] of this.facades) env[facadeEnvName(name2)] = facadeUrl(port);
7640
+ return env;
7641
+ }
7642
+ enable(net) {
7643
+ for (const [name2, { port }] of this.facades) {
7644
+ net.facade(port, name2);
7645
+ net.activate({ family: "inet", host: "127.0.0.1", port }, () => {
7646
+ const listener = net.listen({ family: "inet", host: "127.0.0.1", port });
7647
+ void acceptAll(listener, (socket) => this.serve(name2, socket));
7648
+ });
7649
+ }
7650
+ }
7651
+ register(name2, hook) {
7652
+ const entry = this.facades.get(name2);
7653
+ if (!entry || typeof hook !== "function") throw new KernelError("EINVAL");
7654
+ entry.clients.push(hook);
7655
+ return () => {
7656
+ const at = entry.clients.indexOf(hook);
7657
+ if (at >= 0) entry.clients.splice(at, 1);
7658
+ };
7659
+ }
7660
+ async serve(name2, socket) {
7661
+ const entry = this.facades.get(name2);
7662
+ const hook = entry.clients.at(-1) ?? entry.embedder;
7663
+ const stamp = socket.peerStamp;
7664
+ if (!hook || !stamp) return socket.close();
7665
+ let conn;
7666
+ try {
7667
+ conn = await hook(structuredClone(stamp), { name: name2 });
7668
+ } catch {
7669
+ return socket.close();
7670
+ }
7671
+ await relay(socket, conn);
7672
+ }
7673
+ };
7674
+ async function acceptAll(listener, serve) {
7675
+ for (; ; ) {
7676
+ const socket = await listener.accept();
7677
+ void serve(socket);
7678
+ }
7679
+ }
7680
+ async function relay(socket, conn) {
7681
+ let ended = false;
7682
+ let pending = 0;
7683
+ let writes = Promise.resolve();
7684
+ const end = () => {
7685
+ if (ended) return;
7686
+ ended = true;
7687
+ socket.close();
7688
+ };
7689
+ conn.onmessage = (bytes) => {
7690
+ if (ended) return;
7691
+ const chunk2 = bytes.slice();
7692
+ pending += chunk2.length;
7693
+ if (pending > FACADE_MAX_PENDING) {
7694
+ end();
7695
+ conn.close(FACADE_FLOODED);
7696
+ return;
7697
+ }
7698
+ writes = writes.then(async () => {
7699
+ if (ended) return;
7700
+ let at = 0;
7701
+ while (at < chunk2.length) at += await socket.write(chunk2.subarray(at));
7702
+ pending -= chunk2.length;
7703
+ });
7704
+ writes.catch(() => {
7705
+ end();
7706
+ conn.close();
7707
+ });
7708
+ };
7709
+ conn.onclose = () => {
7710
+ writes.then(end, end);
7711
+ };
7712
+ try {
7713
+ for (; ; ) {
7714
+ const bytes = await socket.read(READ_CHUNK);
7715
+ if (bytes.length === 0 || ended) break;
7716
+ conn.send(bytes);
7717
+ }
7718
+ } catch {
7719
+ }
7720
+ if (!ended) {
7721
+ end();
7722
+ conn.close();
7723
+ }
7724
+ }
7725
+
7496
7726
  // src/fs/attest.ts
7497
7727
  var ATTEST_MAX = 1024 * 1024;
7498
7728
  var UNOWNED = 1e3;
@@ -10849,7 +11079,7 @@ function mountTable(mounts = []) {
10849
11079
  }
10850
11080
 
10851
11081
  // src/version.ts
10852
- var KERNEL_VERSION = true ? "1.89.0" : "0.0.0-dev";
11082
+ var KERNEL_VERSION = true ? "1.90.0" : "0.0.0-dev";
10853
11083
  var OS_RELEASE = "6.0.0-slicc";
10854
11084
  function procVersion() {
10855
11085
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -12489,7 +12719,9 @@ async function socketSyscall(req, proc) {
12489
12719
  case "sock-accept":
12490
12720
  return ok(await accept(proc, req.fd, req.nonblock));
12491
12721
  case "sock-connect": {
12492
- const dialing = socketAt(fds, req.fd).connect(req.addr, true, proc.cred?.());
12722
+ const socket = socketAt(fds, req.fd);
12723
+ const stamp = net.facadeAt(req.addr) && await proc.stamp?.();
12724
+ const dialing = socket.connect(req.addr, true, proc.cred?.(), stamp || void 0);
12493
12725
  if (req.nonblock) {
12494
12726
  dialing?.catch(() => void 0);
12495
12727
  throw new KernelError("EINPROGRESS");
@@ -13668,6 +13900,9 @@ var WasmProcess = class {
13668
13900
  if (channel) channel.stamp = stamp;
13669
13901
  }
13670
13902
  }
13903
+ connectorStamp() {
13904
+ return this.sealedCaller();
13905
+ }
13671
13906
  async sealedCaller() {
13672
13907
  const shown = await this.options.identity?.();
13673
13908
  const broker = this.options.sealed;
@@ -14006,7 +14241,8 @@ var WasmProcess = class {
14006
14241
  net: this.net,
14007
14242
  blocking: () => this.blockingSignal(cancelled),
14008
14243
  resolve: (name2, family, blocking) => resolver.resolve(name2, family, blocking),
14009
- cred: () => ({ pid: this.pid, uid: this.cred.euid, gid: this.cred.egid })
14244
+ cred: () => ({ pid: this.pid, uid: this.cred.euid, gid: this.cred.egid }),
14245
+ stamp: () => this.connectorStamp()
14010
14246
  });
14011
14247
  }
14012
14248
  tty(fd) {
@@ -18010,6 +18246,7 @@ var Launcher = class {
18010
18246
  );
18011
18247
  net = new LoopbackNet();
18012
18248
  cdp;
18249
+ facades;
18013
18250
  ca;
18014
18251
  transport;
18015
18252
  uplink;
@@ -18084,10 +18321,16 @@ var Launcher = class {
18084
18321
  this.modulesDir = options.modules ?? "/node_modules";
18085
18322
  this.appended = appendedRoots(options.commands);
18086
18323
  this.cdp = new CdpHosts(options.cdp);
18324
+ this.facades = new FacadeHosts(options.facades);
18087
18325
  const hostname = options.hostname ?? DEFAULT_HOSTNAME;
18088
18326
  if (!isHostname(hostname)) throw new Error(`not a host name: ${String(hostname)}`);
18089
18327
  this.hostname = hostname;
18090
- this.env = { ...networkEnv(hostname), SLICC_CDP_URL: this.cdp.url, ...options.env };
18328
+ this.env = {
18329
+ ...networkEnv(hostname),
18330
+ SLICC_CDP_URL: this.cdp.url,
18331
+ ...this.facades.env(),
18332
+ ...options.env
18333
+ };
18091
18334
  this.ca = kernelCa(options.caStore ?? memoryCaStore());
18092
18335
  this.transport = replayingHops(options.transport ?? missingTransport());
18093
18336
  this.announcedTraits = JSON.stringify(this.transport.traits);
@@ -18102,6 +18345,7 @@ var Launcher = class {
18102
18345
  ca: this.ca
18103
18346
  });
18104
18347
  enableCdp(this.net, this.cdp);
18348
+ this.facades.enable(this.net);
18105
18349
  const fs = withCommandDirs(
18106
18350
  this.base,
18107
18351
  async () => new Set((await this.commands()).keys()),
@@ -19035,6 +19279,9 @@ var Launcher = class {
19035
19279
  }
19036
19280
  };
19037
19281
  }
19282
+ connectorStamp(pid) {
19283
+ return this.sealed.stamp(this.identityOf(pid), this.credOf(pid), this.tagOf(pid));
19284
+ }
19038
19285
  identityOf(pid) {
19039
19286
  const parent = this.jobs.shownParent(pid);
19040
19287
  const alive = parent !== void 0 && this.running(parent);
@@ -19706,6 +19953,20 @@ function cdpOption(req, port) {
19706
19953
  )
19707
19954
  };
19708
19955
  }
19956
+ function pageHooks(req, port) {
19957
+ return { ...cdpOption(req, port), ...facadesOption(req, port) };
19958
+ }
19959
+ function facadesOption(req, port) {
19960
+ if (!req.facades) return {};
19961
+ const hook = portFacadeHook(
19962
+ (request2, facade) => port.postMessage({ facadeOpen: request2, port: facade }, [facade])
19963
+ );
19964
+ const facades = {};
19965
+ for (const [name2, spec] of Object.entries(req.facades)) {
19966
+ facades[name2] = { port: spec.port, ...spec.hook ? { hook } : {} };
19967
+ }
19968
+ return { facades };
19969
+ }
19709
19970
  function remotes(port, req) {
19710
19971
  return {
19711
19972
  ...req.transport ? { transport: new RemoteTransport(port, req.transport) } : {},
@@ -19919,7 +20180,7 @@ function serveKernel(port, deps) {
19919
20180
  ...media ? { media } : {},
19920
20181
  onMountPending: (medium) => port.postMessage({ medium }),
19921
20182
  ...req.hostfs ? { hostfs: askGrant } : {},
19922
- ...cdpOption(req, port),
20183
+ ...pageHooks(req, port),
19923
20184
  ...mountPolicy(req.processMounts),
19924
20185
  caStore: caStore(deps.metadata ? caDb(req) : false)
19925
20186
  });