@ai-ecoverse/slicc-kernel 1.89.0 → 1.91.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.
@@ -2305,34 +2305,40 @@ function readyEvents(subs, ready) {
2305
2305
  hangup: ready.hangup?.includes(s.fd) === true
2306
2306
  }));
2307
2307
  }
2308
+ function selectOnce(deps, read2, write2, timeoutMs) {
2309
+ try {
2310
+ const ready = deps.kernel.call({ op: "fd-select", read: read2, write: write2, timeoutMs });
2311
+ return { ready, interrupted: false };
2312
+ } catch (e) {
2313
+ if (!deps.interruptWakes || e.code !== "EINTR") throw e;
2314
+ return { ready: { read: [], write: [] }, interrupted: true };
2315
+ }
2316
+ }
2317
+ function waitEvents(deps, subs, { events, read: read2, write: write2 }, entered) {
2318
+ const earliest = subs.reduce((min, s) => Math.min(min, s.deadline), Infinity);
2319
+ const timeout = () => {
2320
+ if (events.length > 0 || entered) return 0;
2321
+ return earliest === Infinity ? -1 : Math.max(0, Math.ceil(earliest - performance.now()));
2322
+ };
2323
+ for (; ; ) {
2324
+ const { ready, interrupted } = selectOnce(deps, read2, write2, timeout());
2325
+ events.push(...readyEvents(subs, ready));
2326
+ if (interrupted) return true;
2327
+ if (events.length > 0 || entered || earliest === Infinity) return false;
2328
+ if (performance.now() >= earliest) return false;
2329
+ }
2330
+ }
2308
2331
  function pollOneoff(deps, inPtr, outPtr, nsubs, neventsPtr) {
2309
2332
  if (nsubs === 0) return E.INVAL;
2310
- const { mem, kernel } = deps;
2333
+ const { mem } = deps;
2311
2334
  const subs = readSubscriptions(mem, inPtr, nsubs, deps.now);
2312
- const { events, read: read2, write: write2 } = classify(deps.fds, subs);
2313
- let interrupted = false;
2314
- const earliest = subs.reduce((min, s) => Math.min(min, s.deadline), Infinity);
2315
- const expired = () => performance.now() >= earliest;
2316
- if (read2.length > 0 || write2.length > 0 || events.length === 0) {
2317
- do {
2318
- let timeoutMs = -1;
2319
- if (events.length > 0) timeoutMs = 0;
2320
- else if (earliest !== Infinity)
2321
- timeoutMs = Math.max(0, Math.ceil(earliest - performance.now()));
2322
- let ready;
2323
- try {
2324
- ready = kernel.call({ op: "fd-select", read: read2, write: write2, timeoutMs });
2325
- } catch (e) {
2326
- if (!deps.interruptWakes || e.code !== "EINTR") throw e;
2327
- interrupted = true;
2328
- ready = { read: [], write: [] };
2329
- }
2330
- events.push(
2331
- ...readyEvents(subs, ready)
2332
- );
2333
- } while (events.length === 0 && !interrupted && earliest !== Infinity && !expired());
2334
- }
2335
+ const found = classify(deps.fds, subs);
2336
+ const { events, read: read2, write: write2 } = found;
2337
+ const entered = deps.entered === true && deps.interruptWakes !== true;
2338
+ const waits = read2.length > 0 || write2.length > 0 || events.length === 0;
2339
+ const interrupted = waits && waitEvents(deps, subs, found, entered);
2335
2340
  const after = performance.now();
2341
+ if (entered && events.length === 0 && !subs.some((s) => s.deadline <= after)) return E.INTR;
2336
2342
  for (const s of subs) {
2337
2343
  if (s.type === EVENTTYPE.CLOCK && (interrupted || s.deadline <= after)) {
2338
2344
  events.push({ userdata: s.userdata, error: E.SUCCESS, type: s.type });
@@ -2538,6 +2544,7 @@ var init_wasi_host = __esm({
2538
2544
  cache;
2539
2545
  startCwd;
2540
2546
  interruptWakes = false;
2547
+ entered = false;
2541
2548
  onRaise;
2542
2549
  muted;
2543
2550
  signals;
@@ -2761,7 +2768,8 @@ var init_wasi_host = __esm({
2761
2768
  fds: this.fds,
2762
2769
  kernel: this.o.kernel,
2763
2770
  now: (id) => this.now(id),
2764
- interruptWakes: this.interruptWakes
2771
+ interruptWakes: this.interruptWakes,
2772
+ entered: this.entered
2765
2773
  },
2766
2774
  inPtr,
2767
2775
  outPtr,
@@ -2778,7 +2786,7 @@ var init_wasi_host = __esm({
2778
2786
  this.mem.view().setUint32(nevents, 0, true);
2779
2787
  if (mask.deliverUnblocked()) return E.INTR;
2780
2788
  if (n > 0) return this.poll(inPtr, outPtr, n, nevents);
2781
- return this.suspend();
2789
+ return this.entered ? E.INTR : this.suspend();
2782
2790
  } finally {
2783
2791
  mask.deliverUnblocked();
2784
2792
  mask.restore(old);
@@ -3876,7 +3884,7 @@ var KERNEL_VERSION, OS_RELEASE;
3876
3884
  var init_version = __esm({
3877
3885
  "src/version.ts"() {
3878
3886
  "use strict";
3879
- KERNEL_VERSION = true ? "1.89.0" : "0.0.0-dev";
3887
+ KERNEL_VERSION = true ? "1.91.0" : "0.0.0-dev";
3880
3888
  OS_RELEASE = "6.0.0-slicc";
3881
3889
  }
3882
3890
  });
@@ -4812,6 +4820,52 @@ var init_js_exit = __esm({
4812
4820
  }
4813
4821
  });
4814
4822
 
4823
+ // src/kernel/net/loopback-names.ts
4824
+ function isKernelLoopbackHost(hostname) {
4825
+ const host = hostname.replace(/^\[(.*)\]$/, "$1").replace(/\.$/, "").toLowerCase();
4826
+ return host === "localhost" || host.endsWith(".localhost") || host === "0.0.0.0" || LOOPBACK_V4.test(host) || LOOPBACK_V6.has(host) || MAPPED_V4.test(host);
4827
+ }
4828
+ function reserved(name2) {
4829
+ const lower = name2.toLowerCase();
4830
+ return lower === "localhost" || lower.endsWith(".localhost") || lower === HOST_LOOPBACK || lower === "wasmer.sh" || /^\d+(\.\d+){3}$/.test(lower);
4831
+ }
4832
+ function isHostname(name2) {
4833
+ if (typeof name2 !== "string" || name2.length > 253 || reserved(name2)) return false;
4834
+ return name2.split(".").every((l) => LABEL.test(l));
4835
+ }
4836
+ function hostnameOf(env) {
4837
+ return isHostname(env.HOSTNAME) ? env.HOSTNAME : DEFAULT_HOSTNAME;
4838
+ }
4839
+ function ownNames(hostname) {
4840
+ return [.../* @__PURE__ */ new Set([hostname.toLowerCase(), ...LIBC_HOSTNAMES])];
4841
+ }
4842
+ function hostsFile(hostname = DEFAULT_HOSTNAME) {
4843
+ return [
4844
+ "127.0.0.1 localhost localhost.localdomain",
4845
+ "::1 localhost ip6-localhost",
4846
+ `${HOSTNAME_ADDRESS} ${ownNames(hostname).join(" ")}`,
4847
+ `${HOST_LOOPBACK_ADDRESS.join(".")} ${HOST_LOOPBACK}`,
4848
+ ""
4849
+ ].join("\n");
4850
+ }
4851
+ var HOST_LOOPBACK, HOST_LOOPBACK_ADDRESS, PAGE_LOOPBACK, PAGE_LOOPBACK_URL, LOOPBACK_V4, LOOPBACK_V6, MAPPED_V4, DEFAULT_HOSTNAME, HOSTNAME_ADDRESS, LIBC_HOSTNAMES, LABEL;
4852
+ var init_loopback_names = __esm({
4853
+ "src/kernel/net/loopback-names.ts"() {
4854
+ "use strict";
4855
+ HOST_LOOPBACK = "host.slicc.internal";
4856
+ HOST_LOOPBACK_ADDRESS = [10, 0, 2, 2];
4857
+ PAGE_LOOPBACK = "kernel.localhost";
4858
+ PAGE_LOOPBACK_URL = `http://{port}.${PAGE_LOOPBACK}`;
4859
+ LOOPBACK_V4 = /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
4860
+ LOOPBACK_V6 = /* @__PURE__ */ new Set(["::1", "::", "0:0:0:0:0:0:0:1"]);
4861
+ MAPPED_V4 = /^::ffff:7f[0-9a-f]{2}:[0-9a-f]{1,4}$/;
4862
+ DEFAULT_HOSTNAME = "slicc";
4863
+ HOSTNAME_ADDRESS = "127.0.1.1";
4864
+ LIBC_HOSTNAMES = ["emscripten", "wasmer.sh"];
4865
+ LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i;
4866
+ }
4867
+ });
4868
+
4815
4869
  // src/process/js/js-fetch.ts
4816
4870
  function withoutFragment(url) {
4817
4871
  url.hash = "";
@@ -4826,11 +4880,20 @@ function plain(status2, text) {
4826
4880
  headers: { "content-type": "text/plain; charset=utf-8" }
4827
4881
  });
4828
4882
  }
4883
+ function local2(url) {
4884
+ return isKernelLoopbackHost(new URL(url).hostname);
4885
+ }
4829
4886
  function rewrite(hop, status2, location) {
4830
4887
  const next2 = new URL(location, hop.url);
4831
4888
  if (next2.protocol !== "http:" && next2.protocol !== "https:") {
4832
4889
  throw failed(new JsCallError("EPROTONOSUPPORT", next2.protocol));
4833
4890
  }
4891
+ if (local2(next2.href) && !local2(hop.url)) {
4892
+ const from = new URL(hop.url).origin;
4893
+ throw failed(
4894
+ new JsCallError("EACCES", `a redirect from ${from} into the kernel's loopback: ${next2.href}`)
4895
+ );
4896
+ }
4834
4897
  const toGet = (status2 === 301 || status2 === 302) && hop.method === "POST" || status2 === 303 && hop.method !== "GET" && hop.method !== "HEAD";
4835
4898
  const crossOrigin = next2.origin !== new URL(hop.url).origin;
4836
4899
  const headers = hop.headers.filter(
@@ -4999,13 +5062,15 @@ async function bodyOf(request, cap, signal) {
4999
5062
  return out;
5000
5063
  }
5001
5064
  function fetchOp(kernel) {
5002
- let traits;
5003
- const traitsOf = () => {
5004
- traits ??= kernel.json({ op: "net-traits" });
5005
- traits.catch(() => {
5006
- traits = void 0;
5065
+ const traits = /* @__PURE__ */ new Map();
5066
+ const traitsOf = (url) => {
5067
+ const own = local2(url);
5068
+ const known = traits.get(own) ?? kernel.json({ op: "net-traits", url });
5069
+ traits.set(own, known);
5070
+ known.catch(() => {
5071
+ traits.delete(own);
5007
5072
  });
5008
- return traits;
5073
+ return known;
5009
5074
  };
5010
5075
  const close = (handle) => kernel.raw({ op: "net-close", handle });
5011
5076
  const send = async (hop, signal) => {
@@ -5092,6 +5157,13 @@ function fetchOp(kernel) {
5092
5157
  });
5093
5158
  return withMeta(response, head.url, redirected);
5094
5159
  };
5160
+ const traitsAt = (at) => traitsOf(at).catch((err) => {
5161
+ throw failed(err);
5162
+ });
5163
+ const redirect = async (hop, status2, location, known) => {
5164
+ const next2 = rewrite(hop, status2, location);
5165
+ return [next2, local2(next2.url) === local2(hop.url) ? known : await traitsAt(next2.url)];
5166
+ };
5095
5167
  return async (input, init) => {
5096
5168
  const request = new Request(input, init);
5097
5169
  const { signal } = request;
@@ -5101,9 +5173,7 @@ function fetchOp(kernel) {
5101
5173
  if (protocol !== "http:" && protocol !== "https:") {
5102
5174
  throw failed(new JsCallError("EPROTONOSUPPORT", protocol));
5103
5175
  }
5104
- const known = await traitsOf().catch((err) => {
5105
- throw failed(err);
5106
- });
5176
+ let known = await traitsAt(request.url);
5107
5177
  if (!known.manualRedirects && request.redirect !== "follow") {
5108
5178
  throw failed(new JsCallError("ENOTSUP", `redirect: ${request.redirect}`));
5109
5179
  }
@@ -5129,7 +5199,7 @@ function fetchOp(kernel) {
5129
5199
  await close(head.handle);
5130
5200
  if (request.redirect === "error") throw failed(new JsCallError("EREDIRECT", hop.url));
5131
5201
  if (hops >= MAX_REDIRECTS) throw failed(new JsCallError("ELOOP", hop.url));
5132
- hop = rewrite(hop, head.status, location);
5202
+ [hop, known] = await redirect(hop, head.status, location, known);
5133
5203
  }
5134
5204
  };
5135
5205
  }
@@ -5137,6 +5207,7 @@ var CHUNK2, MAX_REDIRECTS, NULL_BODY, REDIRECTS, BODY_HEADERS, DECODED, CREDENTI
5137
5207
  var init_js_fetch = __esm({
5138
5208
  "src/process/js/js-fetch.ts"() {
5139
5209
  "use strict";
5210
+ init_loopback_names();
5140
5211
  init_js_kernel();
5141
5212
  CHUNK2 = 64 * 1024;
5142
5213
  MAX_REDIRECTS = 20;
@@ -5176,7 +5247,7 @@ function port(n) {
5176
5247
  function netOps(kernel, io) {
5177
5248
  const name2 = async (fd, peer) => addressOf(await kernel.json({ op: "sock-name", fd, peer }));
5178
5249
  const connection = async (fd) => {
5179
- const [local2, remote] = [await name2(fd, false), await name2(fd, true)];
5250
+ const [local3, remote] = [await name2(fd, false), await name2(fd, true)];
5180
5251
  const stop = new AbortController();
5181
5252
  let closed;
5182
5253
  const close = () => {
@@ -5201,7 +5272,7 @@ function netOps(kernel, io) {
5201
5272
  close: async () => void await shut(SHUT_WR),
5202
5273
  abort: () => close()
5203
5274
  });
5204
- return { fd, local: local2, remote, readable: readable3, writable: writable2, close };
5275
+ return { fd, local: local3, remote, readable: readable3, writable: writable2, close };
5205
5276
  };
5206
5277
  const resolve = async (host, signal) => {
5207
5278
  if (IPV4.test(host)) return host;
@@ -5301,45 +5372,6 @@ var init_js_net = __esm({
5301
5372
  }
5302
5373
  });
5303
5374
 
5304
- // src/kernel/net/loopback-names.ts
5305
- function reserved(name2) {
5306
- const lower = name2.toLowerCase();
5307
- return lower === "localhost" || lower.endsWith(".localhost") || lower === HOST_LOOPBACK || lower === "wasmer.sh" || /^\d+(\.\d+){3}$/.test(lower);
5308
- }
5309
- function isHostname(name2) {
5310
- if (typeof name2 !== "string" || name2.length > 253 || reserved(name2)) return false;
5311
- return name2.split(".").every((l) => LABEL.test(l));
5312
- }
5313
- function hostnameOf(env) {
5314
- return isHostname(env.HOSTNAME) ? env.HOSTNAME : DEFAULT_HOSTNAME;
5315
- }
5316
- function ownNames(hostname) {
5317
- return [.../* @__PURE__ */ new Set([hostname.toLowerCase(), ...LIBC_HOSTNAMES])];
5318
- }
5319
- function hostsFile(hostname = DEFAULT_HOSTNAME) {
5320
- return [
5321
- "127.0.0.1 localhost localhost.localdomain",
5322
- "::1 localhost ip6-localhost",
5323
- `${HOSTNAME_ADDRESS} ${ownNames(hostname).join(" ")}`,
5324
- `${HOST_LOOPBACK_ADDRESS.join(".")} ${HOST_LOOPBACK}`,
5325
- ""
5326
- ].join("\n");
5327
- }
5328
- var HOST_LOOPBACK, HOST_LOOPBACK_ADDRESS, PAGE_LOOPBACK, PAGE_LOOPBACK_URL, DEFAULT_HOSTNAME, HOSTNAME_ADDRESS, LIBC_HOSTNAMES, LABEL;
5329
- var init_loopback_names = __esm({
5330
- "src/kernel/net/loopback-names.ts"() {
5331
- "use strict";
5332
- HOST_LOOPBACK = "host.slicc.internal";
5333
- HOST_LOOPBACK_ADDRESS = [10, 0, 2, 2];
5334
- PAGE_LOOPBACK = "kernel.localhost";
5335
- PAGE_LOOPBACK_URL = `http://{port}.${PAGE_LOOPBACK}`;
5336
- DEFAULT_HOSTNAME = "slicc";
5337
- HOSTNAME_ADDRESS = "127.0.1.1";
5338
- LIBC_HOSTNAMES = ["emscripten", "wasmer.sh"];
5339
- LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i;
5340
- }
5341
- });
5342
-
5343
5375
  // src/process/wasi-errno.ts
5344
5376
  function wasiErrno(code2) {
5345
5377
  return WASI_ERRNO[code2] ?? E.IO;
@@ -6428,6 +6460,50 @@ function useLiveChown(Fs) {
6428
6460
  Fs.chown(target, uid, gid);
6429
6461
  };
6430
6462
  }
6463
+ function flushOne(Fs, node) {
6464
+ const s = node.live;
6465
+ if (!s.dirty || s.orphan || !(s.data || s.ranged)) return;
6466
+ try {
6467
+ if (s.ranged) s.ranged.flush();
6468
+ else {
6469
+ const bytes = s.data.slice(0, s.len);
6470
+ pinnedIo2(node.mount.opts.bridge, s.handle).writeFile(liveNodePath(node), bytes, true);
6471
+ }
6472
+ } catch (err) {
6473
+ throw toErrno(Fs, err);
6474
+ }
6475
+ s.dirty = false;
6476
+ s.stat = void 0;
6477
+ }
6478
+ function linkable(bridge, path) {
6479
+ try {
6480
+ return bridge.lstat(path).linkable === true;
6481
+ } catch {
6482
+ return false;
6483
+ }
6484
+ }
6485
+ function linkLive(Fs, from, to, follow2) {
6486
+ const target = to.replace(/\/+$/, "");
6487
+ const slash = target.lastIndexOf("/");
6488
+ const name2 = target.slice(slash + 1);
6489
+ const source = Fs.lookupPath(from, { follow: follow2 }).node;
6490
+ const parent = Fs.lookupPath(target.slice(0, slash) || "/", { follow: true }).node;
6491
+ if (!source.live || !parent.live) return false;
6492
+ flushOne(Fs, source);
6493
+ const base = liveNodePath(parent);
6494
+ const bridge = source.mount.opts.bridge;
6495
+ const path = liveNodePath(source);
6496
+ try {
6497
+ bridge.link(path, base === "/" ? `/${name2}` : `${base}/${name2}`);
6498
+ } catch (err) {
6499
+ const refused2 = toErrno(Fs, err);
6500
+ if (refused2.errno !== wasiErrno("EPERM") || linkable(bridge, path)) throw refused2;
6501
+ throw new Fs.ErrnoError(wasiErrno("EMLINK"));
6502
+ }
6503
+ source.live.stat = void 0;
6504
+ parent.live.listed = void 0;
6505
+ return true;
6506
+ }
6431
6507
  function readingLinks(Fs) {
6432
6508
  const readlink = Fs.readlink?.bind(Fs);
6433
6509
  if (!readlink) return;
@@ -7138,6 +7214,32 @@ function kernelAccess(imports, fs, memory, glue) {
7138
7214
  }
7139
7215
  });
7140
7216
  }
7217
+ function kernelLink(imports, fs, memory, glue) {
7218
+ wrapImport(
7219
+ imports,
7220
+ "linkat",
7221
+ glue,
7222
+ (own) => (olddirfd, oldpath, newdirfd, newpath, flags) => {
7223
+ const Fs = fs();
7224
+ const heap = memory();
7225
+ if (!Fs?.lookupPath || !heap) return own(olddirfd, oldpath, newdirfd, newpath, flags);
7226
+ const at = (dirfd, ptr) => {
7227
+ const name2 = cString(heap, ptr);
7228
+ return name2.startsWith("/") ? name2 : `${baseOf(Fs, dirfd)}/${name2}`;
7229
+ };
7230
+ try {
7231
+ const from = at(olddirfd, oldpath);
7232
+ const to = at(newdirfd, newpath);
7233
+ const follow2 = (flags & AT_SYMLINK_FOLLOW) !== 0;
7234
+ if (linkLive(Fs, from, to, follow2)) return 0;
7235
+ } catch (err) {
7236
+ return -errnoOf(err);
7237
+ }
7238
+ return own(olddirfd, oldpath, newdirfd, newpath, flags);
7239
+ },
7240
+ true
7241
+ );
7242
+ }
7141
7243
  function kernelChdir(Fs) {
7142
7244
  const { chdir, lookupPath, ErrnoError } = Fs;
7143
7245
  if (!chdir || !lookupPath || !ErrnoError) return;
@@ -7165,7 +7267,7 @@ function linuxDevices(Fs) {
7165
7267
  }
7166
7268
  }
7167
7269
  }
7168
- var O_CLOEXEC, FD_CLOEXEC, F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_DUPFD_CLOEXEC, tracked, IMPORT_NAMES, EBADF, AT_SYMLINK_NOFOLLOW2, EMSCRIPTEN_EPERM, O_PATH2, LITERALS, UTIME_NOW, UTIME_OMIT, PROT_WRITE, MAP_PRIVATE, MAP_TYPE, O_WRONLY4, MAP_ALIGN, DIR_MODE, LINK_MODE, CHAR_DEVICE, O_ACCMODE2, O_CREAT, field, pinnedRoot, rootKind, NAME, AT_FDCWD, AT_EACCESS2, W_ACCESS, X_ACCESS, DEVICE_MODES;
7270
+ var O_CLOEXEC, FD_CLOEXEC, F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_DUPFD_CLOEXEC, tracked, IMPORT_NAMES, EBADF, AT_SYMLINK_NOFOLLOW2, EMSCRIPTEN_EPERM, O_PATH2, LITERALS, UTIME_NOW, UTIME_OMIT, PROT_WRITE, MAP_PRIVATE, MAP_TYPE, O_WRONLY4, MAP_ALIGN, DIR_MODE, LINK_MODE, CHAR_DEVICE, O_ACCMODE2, O_CREAT, field, pinnedRoot, rootKind, NAME, AT_FDCWD, AT_EACCESS2, W_ACCESS, X_ACCESS, AT_SYMLINK_FOLLOW, DEVICE_MODES;
7169
7271
  var init_process_fds = __esm({
7170
7272
  "src/process/process-fds.ts"() {
7171
7273
  "use strict";
@@ -7200,6 +7302,7 @@ var init_process_fds = __esm({
7200
7302
  mknodat: "__syscall_mknodat",
7201
7303
  umask: "__syscall_umask",
7202
7304
  faccessat: "__syscall_faccessat",
7305
+ linkat: "__syscall_linkat",
7203
7306
  utimensat: "__syscall_utimensat",
7204
7307
  getppid: "slicc_getppid_js",
7205
7308
  resizeHeap: "emscripten_resize_heap",
@@ -7226,6 +7329,7 @@ var init_process_fds = __esm({
7226
7329
  AT_EACCESS2 = 512;
7227
7330
  W_ACCESS = 2;
7228
7331
  X_ACCESS = 1;
7332
+ AT_SYMLINK_FOLLOW = 1024;
7229
7333
  DEVICE_MODES = [
7230
7334
  ["/", 493],
7231
7335
  ["/dev", 493],
@@ -10220,12 +10324,12 @@ function anySelect(Fs, transport, read2, write2, timeoutMs) {
10220
10324
  const kernelRead = read2.filter((fd) => !own(fd));
10221
10325
  const kernelWrite = write2.filter((fd) => !own(fd));
10222
10326
  for (; ; ) {
10223
- const local2 = ownReady(Fs, read2.filter(own), write2.filter(own));
10224
- const pending = local2.read.length > 0 || local2.write.length > 0;
10327
+ const local3 = ownReady(Fs, read2.filter(own), write2.filter(own));
10328
+ const pending = local3.read.length > 0 || local3.write.length > 0;
10225
10329
  const slice = pending ? 0 : Math.min(SELECT_SLICE_MS, Math.max(0, deadline - Date.now()));
10226
10330
  const got = kernelSelect(Fs, transport, kernelRead, kernelWrite, slice);
10227
10331
  if (typeof got === "number") return got;
10228
- const ready = { read: [...local2.read, ...got.read], write: [...local2.write, ...got.write] };
10332
+ const ready = { read: [...local3.read, ...got.read], write: [...local3.write, ...got.write] };
10229
10333
  if (ready.read.length > 0 || ready.write.length > 0 || Date.now() >= deadline) {
10230
10334
  return ready;
10231
10335
  }
@@ -10997,6 +11101,7 @@ function kernelWrappers(imports, module, deps) {
10997
11101
  const fsOf = () => ownValue(module, "FS");
10998
11102
  noFollowUtimes(imports, fsOf, kernelGlue?.utimensat ?? utimensatOf(module), memory);
10999
11103
  kernelAccess(imports, fsOf, memory, kernelGlue);
11104
+ kernelLink(imports, fsOf, memory, kernelGlue);
11000
11105
  const glue = ownValue(module, "sliccFdImports");
11001
11106
  syncFsync(imports, fsOf, glue);
11002
11107
  positionalIo(imports, { glue, fs: fsOf, sys, memory });
@@ -11295,6 +11400,7 @@ var init_process_runtime = __esm({
11295
11400
  " mknodat: typeof ___syscall_mknodat === 'function' ? ___syscall_mknodat : undefined,",
11296
11401
  " umask: typeof ___syscall_umask === 'function' ? ___syscall_umask : undefined,",
11297
11402
  " faccessat: typeof ___syscall_faccessat === 'function' ? ___syscall_faccessat : undefined,",
11403
+ " linkat: typeof ___syscall_linkat === 'function' ? ___syscall_linkat : undefined,",
11298
11404
  " utimensat: typeof ___syscall_utimensat === 'function' ? ___syscall_utimensat : undefined,",
11299
11405
  " getppid: typeof _slicc_getppid_js === 'function' ? _slicc_getppid_js : undefined,",
11300
11406
  " resizeHeap: typeof _emscripten_resize_heap === 'function' ? _emscripten_resize_heap : undefined,",
@@ -13319,10 +13425,8 @@ var init_wasix_host = __esm({
13319
13425
  const v = mem.view();
13320
13426
  const timed = timeoutPtr !== 0 && v.getUint8(timeoutPtr) === 1;
13321
13427
  const ms = timed ? Number(v.getBigUint64(timeoutPtr + 8, true)) / 1e6 : Number.POSITIVE_INFINITY;
13322
- v.setUint8(
13323
- wokenPtr,
13324
- futexWait(i32(), ptr >> 2, expected | 0, ms, host.interrupted) ? 1 : 0
13325
- );
13428
+ const woken = host.entered || futexWait(i32(), ptr >> 2, expected | 0, ms, host.interrupted);
13429
+ v.setUint8(wokenPtr, woken ? 1 : 0);
13326
13430
  },
13327
13431
  futex_wake: (ptr, wokenPtr) => {
13328
13432
  Atomics.notify(i32(), ptr >> 2, 1);
@@ -13490,9 +13594,10 @@ function delivering(ns, table, host, driver, before) {
13490
13594
  }
13491
13595
  const fn = value2;
13492
13596
  out[name2] = (...args) => {
13597
+ host.entered = false;
13493
13598
  if (driver.idle) {
13494
13599
  before?.();
13495
- host.interrupted?.();
13600
+ host.entered = host.interrupted?.() === true;
13496
13601
  }
13497
13602
  return fn(...args);
13498
13603
  };