@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.
@@ -255,6 +255,10 @@ var init_protocol = __esm({
255
255
  });
256
256
 
257
257
  // src/kernel/net/loopback-names.ts
258
+ function isKernelLoopbackHost(hostname) {
259
+ const host = hostname.replace(/^\[(.*)\]$/, "$1").replace(/\.$/, "").toLowerCase();
260
+ return host === "localhost" || host.endsWith(".localhost") || host === "0.0.0.0" || LOOPBACK_V4.test(host) || LOOPBACK_V6.has(host) || MAPPED_V4.test(host);
261
+ }
258
262
  function reserved(name2) {
259
263
  const lower = name2.toLowerCase();
260
264
  return lower === "localhost" || lower.endsWith(".localhost") || lower === HOST_LOOPBACK || lower === "wasmer.sh" || /^\d+(\.\d+){3}$/.test(lower);
@@ -278,7 +282,7 @@ function hostsFile(hostname = DEFAULT_HOSTNAME) {
278
282
  ""
279
283
  ].join("\n");
280
284
  }
281
- var HOST_LOOPBACK, HOST_LOOPBACK_ADDRESS, PAGE_LOOPBACK, PAGE_LOOPBACK_URL, DEFAULT_HOSTNAME, HOSTNAME_ADDRESS, LIBC_HOSTNAMES, LABEL;
285
+ var HOST_LOOPBACK, HOST_LOOPBACK_ADDRESS, PAGE_LOOPBACK, PAGE_LOOPBACK_URL, LOOPBACK_V4, LOOPBACK_V6, MAPPED_V4, DEFAULT_HOSTNAME, HOSTNAME_ADDRESS, LIBC_HOSTNAMES, LABEL;
282
286
  var init_loopback_names = __esm({
283
287
  "src/kernel/net/loopback-names.ts"() {
284
288
  "use strict";
@@ -286,6 +290,9 @@ var init_loopback_names = __esm({
286
290
  HOST_LOOPBACK_ADDRESS = [10, 0, 2, 2];
287
291
  PAGE_LOOPBACK = "kernel.localhost";
288
292
  PAGE_LOOPBACK_URL = `http://{port}.${PAGE_LOOPBACK}`;
293
+ LOOPBACK_V4 = /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
294
+ LOOPBACK_V6 = /* @__PURE__ */ new Set(["::1", "::", "0:0:0:0:0:0:0:1"]);
295
+ MAPPED_V4 = /^::ffff:7f[0-9a-f]{2}:[0-9a-f]{1,4}$/;
289
296
  DEFAULT_HOSTNAME = "slicc";
290
297
  HOSTNAME_ADDRESS = "127.0.1.1";
291
298
  LIBC_HOSTNAMES = ["emscripten", "wasmer.sh"];
@@ -1942,6 +1949,50 @@ function useLiveChown(Fs) {
1942
1949
  Fs.chown(target, uid, gid);
1943
1950
  };
1944
1951
  }
1952
+ function flushOne(Fs, node) {
1953
+ const s = node.live;
1954
+ if (!s.dirty || s.orphan || !(s.data || s.ranged)) return;
1955
+ try {
1956
+ if (s.ranged) s.ranged.flush();
1957
+ else {
1958
+ const bytes = s.data.slice(0, s.len);
1959
+ pinnedIo(node.mount.opts.bridge, s.handle).writeFile(liveNodePath(node), bytes, true);
1960
+ }
1961
+ } catch (err) {
1962
+ throw toErrno(Fs, err);
1963
+ }
1964
+ s.dirty = false;
1965
+ s.stat = void 0;
1966
+ }
1967
+ function linkable(bridge, path) {
1968
+ try {
1969
+ return bridge.lstat(path).linkable === true;
1970
+ } catch {
1971
+ return false;
1972
+ }
1973
+ }
1974
+ function linkLive(Fs, from, to, follow2) {
1975
+ const target = to.replace(/\/+$/, "");
1976
+ const slash = target.lastIndexOf("/");
1977
+ const name2 = target.slice(slash + 1);
1978
+ const source = Fs.lookupPath(from, { follow: follow2 }).node;
1979
+ const parent = Fs.lookupPath(target.slice(0, slash) || "/", { follow: true }).node;
1980
+ if (!source.live || !parent.live) return false;
1981
+ flushOne(Fs, source);
1982
+ const base = liveNodePath(parent);
1983
+ const bridge = source.mount.opts.bridge;
1984
+ const path = liveNodePath(source);
1985
+ try {
1986
+ bridge.link(path, base === "/" ? `/${name2}` : `${base}/${name2}`);
1987
+ } catch (err) {
1988
+ const refused = toErrno(Fs, err);
1989
+ if (refused.errno !== wasiErrno("EPERM") || linkable(bridge, path)) throw refused;
1990
+ throw new Fs.ErrnoError(wasiErrno("EMLINK"));
1991
+ }
1992
+ source.live.stat = void 0;
1993
+ parent.live.listed = void 0;
1994
+ return true;
1995
+ }
1945
1996
  function readingLinks(Fs) {
1946
1997
  const readlink = Fs.readlink?.bind(Fs);
1947
1998
  if (!readlink) return;
@@ -3302,6 +3353,32 @@ function kernelAccess(imports, fs, memory, glue) {
3302
3353
  }
3303
3354
  });
3304
3355
  }
3356
+ function kernelLink(imports, fs, memory, glue) {
3357
+ wrapImport(
3358
+ imports,
3359
+ "linkat",
3360
+ glue,
3361
+ (own) => (olddirfd, oldpath, newdirfd, newpath, flags) => {
3362
+ const Fs = fs();
3363
+ const heap = memory();
3364
+ if (!Fs?.lookupPath || !heap) return own(olddirfd, oldpath, newdirfd, newpath, flags);
3365
+ const at = (dirfd, ptr) => {
3366
+ const name2 = cString(heap, ptr);
3367
+ return name2.startsWith("/") ? name2 : `${baseOf(Fs, dirfd)}/${name2}`;
3368
+ };
3369
+ try {
3370
+ const from = at(olddirfd, oldpath);
3371
+ const to = at(newdirfd, newpath);
3372
+ const follow2 = (flags & AT_SYMLINK_FOLLOW) !== 0;
3373
+ if (linkLive(Fs, from, to, follow2)) return 0;
3374
+ } catch (err) {
3375
+ return -errnoOf(err);
3376
+ }
3377
+ return own(olddirfd, oldpath, newdirfd, newpath, flags);
3378
+ },
3379
+ true
3380
+ );
3381
+ }
3305
3382
  function kernelChdir(Fs) {
3306
3383
  const { chdir, lookupPath, ErrnoError } = Fs;
3307
3384
  if (!chdir || !lookupPath || !ErrnoError) return;
@@ -3329,7 +3406,7 @@ function linuxDevices(Fs) {
3329
3406
  }
3330
3407
  }
3331
3408
  }
3332
- var O_CLOEXEC, FD_CLOEXEC, F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_DUPFD_CLOEXEC, tracked, IMPORT_NAMES, EBADF, AT_SYMLINK_NOFOLLOW, EMSCRIPTEN_EPERM, O_PATH2, LITERALS, UTIME_NOW, UTIME_OMIT, PROT_WRITE, MAP_PRIVATE, MAP_TYPE, O_WRONLY, MAP_ALIGN, DIR_MODE, LINK_MODE, CHAR_DEVICE, O_ACCMODE2, O_CREAT2, field, pinnedRoot, rootKind, NAME, AT_FDCWD, AT_EACCESS, W_ACCESS, X_ACCESS, DEVICE_MODES;
3409
+ var O_CLOEXEC, FD_CLOEXEC, F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_DUPFD_CLOEXEC, tracked, IMPORT_NAMES, EBADF, AT_SYMLINK_NOFOLLOW, EMSCRIPTEN_EPERM, O_PATH2, LITERALS, UTIME_NOW, UTIME_OMIT, PROT_WRITE, MAP_PRIVATE, MAP_TYPE, O_WRONLY, MAP_ALIGN, DIR_MODE, LINK_MODE, CHAR_DEVICE, O_ACCMODE2, O_CREAT2, field, pinnedRoot, rootKind, NAME, AT_FDCWD, AT_EACCESS, W_ACCESS, X_ACCESS, AT_SYMLINK_FOLLOW, DEVICE_MODES;
3333
3410
  var init_process_fds = __esm({
3334
3411
  "src/process/process-fds.ts"() {
3335
3412
  "use strict";
@@ -3364,6 +3441,7 @@ var init_process_fds = __esm({
3364
3441
  mknodat: "__syscall_mknodat",
3365
3442
  umask: "__syscall_umask",
3366
3443
  faccessat: "__syscall_faccessat",
3444
+ linkat: "__syscall_linkat",
3367
3445
  utimensat: "__syscall_utimensat",
3368
3446
  getppid: "slicc_getppid_js",
3369
3447
  resizeHeap: "emscripten_resize_heap",
@@ -3390,6 +3468,7 @@ var init_process_fds = __esm({
3390
3468
  AT_EACCESS = 512;
3391
3469
  W_ACCESS = 2;
3392
3470
  X_ACCESS = 1;
3471
+ AT_SYMLINK_FOLLOW = 1024;
3393
3472
  DEVICE_MODES = [
3394
3473
  ["/", 493],
3395
3474
  ["/dev", 493],
@@ -3690,12 +3769,12 @@ function anySelect(Fs, transport, read2, write2, timeoutMs) {
3690
3769
  const kernelRead = read2.filter((fd) => !own(fd));
3691
3770
  const kernelWrite = write2.filter((fd) => !own(fd));
3692
3771
  for (; ; ) {
3693
- const local2 = ownReady(Fs, read2.filter(own), write2.filter(own));
3694
- const pending = local2.read.length > 0 || local2.write.length > 0;
3772
+ const local3 = ownReady(Fs, read2.filter(own), write2.filter(own));
3773
+ const pending = local3.read.length > 0 || local3.write.length > 0;
3695
3774
  const slice = pending ? 0 : Math.min(SELECT_SLICE_MS, Math.max(0, deadline - Date.now()));
3696
3775
  const got = kernelSelect(Fs, transport, kernelRead, kernelWrite, slice);
3697
3776
  if (typeof got === "number") return got;
3698
- const ready = { read: [...local2.read, ...got.read], write: [...local2.write, ...got.write] };
3777
+ const ready = { read: [...local3.read, ...got.read], write: [...local3.write, ...got.write] };
3699
3778
  if (ready.read.length > 0 || ready.write.length > 0 || Date.now() >= deadline) {
3700
3779
  return ready;
3701
3780
  }
@@ -4213,7 +4292,7 @@ var KERNEL_VERSION, OS_RELEASE;
4213
4292
  var init_version = __esm({
4214
4293
  "src/version.ts"() {
4215
4294
  "use strict";
4216
- KERNEL_VERSION = true ? "1.89.0" : "0.0.0-dev";
4295
+ KERNEL_VERSION = true ? "1.91.0" : "0.0.0-dev";
4217
4296
  OS_RELEASE = "6.0.0-slicc";
4218
4297
  }
4219
4298
  });
@@ -4884,6 +4963,7 @@ function kernelWrappers(imports, module, deps) {
4884
4963
  const fsOf = () => ownValue(module, "FS");
4885
4964
  noFollowUtimes(imports, fsOf, kernelGlue?.utimensat ?? utimensatOf(module), memory);
4886
4965
  kernelAccess(imports, fsOf, memory, kernelGlue);
4966
+ kernelLink(imports, fsOf, memory, kernelGlue);
4887
4967
  const glue = ownValue(module, "sliccFdImports");
4888
4968
  syncFsync(imports, fsOf, glue);
4889
4969
  positionalIo(imports, { glue, fs: fsOf, sys, memory });
@@ -5182,6 +5262,7 @@ var init_process_runtime = __esm({
5182
5262
  " mknodat: typeof ___syscall_mknodat === 'function' ? ___syscall_mknodat : undefined,",
5183
5263
  " umask: typeof ___syscall_umask === 'function' ? ___syscall_umask : undefined,",
5184
5264
  " faccessat: typeof ___syscall_faccessat === 'function' ? ___syscall_faccessat : undefined,",
5265
+ " linkat: typeof ___syscall_linkat === 'function' ? ___syscall_linkat : undefined,",
5185
5266
  " utimensat: typeof ___syscall_utimensat === 'function' ? ___syscall_utimensat : undefined,",
5186
5267
  " getppid: typeof _slicc_getppid_js === 'function' ? _slicc_getppid_js : undefined,",
5187
5268
  " resizeHeap: typeof _emscripten_resize_heap === 'function' ? _emscripten_resize_heap : undefined,",
@@ -6747,34 +6828,40 @@ function readyEvents(subs, ready) {
6747
6828
  hangup: ready.hangup?.includes(s.fd) === true
6748
6829
  }));
6749
6830
  }
6831
+ function selectOnce(deps, read2, write2, timeoutMs) {
6832
+ try {
6833
+ const ready = deps.kernel.call({ op: "fd-select", read: read2, write: write2, timeoutMs });
6834
+ return { ready, interrupted: false };
6835
+ } catch (e) {
6836
+ if (!deps.interruptWakes || e.code !== "EINTR") throw e;
6837
+ return { ready: { read: [], write: [] }, interrupted: true };
6838
+ }
6839
+ }
6840
+ function waitEvents(deps, subs, { events, read: read2, write: write2 }, entered) {
6841
+ const earliest = subs.reduce((min, s) => Math.min(min, s.deadline), Infinity);
6842
+ const timeout = () => {
6843
+ if (events.length > 0 || entered) return 0;
6844
+ return earliest === Infinity ? -1 : Math.max(0, Math.ceil(earliest - performance.now()));
6845
+ };
6846
+ for (; ; ) {
6847
+ const { ready, interrupted } = selectOnce(deps, read2, write2, timeout());
6848
+ events.push(...readyEvents(subs, ready));
6849
+ if (interrupted) return true;
6850
+ if (events.length > 0 || entered || earliest === Infinity) return false;
6851
+ if (performance.now() >= earliest) return false;
6852
+ }
6853
+ }
6750
6854
  function pollOneoff(deps, inPtr, outPtr, nsubs, neventsPtr) {
6751
6855
  if (nsubs === 0) return E.INVAL;
6752
- const { mem, kernel } = deps;
6856
+ const { mem } = deps;
6753
6857
  const subs = readSubscriptions(mem, inPtr, nsubs, deps.now);
6754
- const { events, read: read2, write: write2 } = classify(deps.fds, subs);
6755
- let interrupted = false;
6756
- const earliest = subs.reduce((min, s) => Math.min(min, s.deadline), Infinity);
6757
- const expired = () => performance.now() >= earliest;
6758
- if (read2.length > 0 || write2.length > 0 || events.length === 0) {
6759
- do {
6760
- let timeoutMs = -1;
6761
- if (events.length > 0) timeoutMs = 0;
6762
- else if (earliest !== Infinity)
6763
- timeoutMs = Math.max(0, Math.ceil(earliest - performance.now()));
6764
- let ready;
6765
- try {
6766
- ready = kernel.call({ op: "fd-select", read: read2, write: write2, timeoutMs });
6767
- } catch (e) {
6768
- if (!deps.interruptWakes || e.code !== "EINTR") throw e;
6769
- interrupted = true;
6770
- ready = { read: [], write: [] };
6771
- }
6772
- events.push(
6773
- ...readyEvents(subs, ready)
6774
- );
6775
- } while (events.length === 0 && !interrupted && earliest !== Infinity && !expired());
6776
- }
6858
+ const found = classify(deps.fds, subs);
6859
+ const { events, read: read2, write: write2 } = found;
6860
+ const entered = deps.entered === true && deps.interruptWakes !== true;
6861
+ const waits = read2.length > 0 || write2.length > 0 || events.length === 0;
6862
+ const interrupted = waits && waitEvents(deps, subs, found, entered);
6777
6863
  const after = performance.now();
6864
+ if (entered && events.length === 0 && !subs.some((s) => s.deadline <= after)) return E.INTR;
6778
6865
  for (const s of subs) {
6779
6866
  if (s.type === EVENTTYPE.CLOCK && (interrupted || s.deadline <= after)) {
6780
6867
  events.push({ userdata: s.userdata, error: E.SUCCESS, type: s.type });
@@ -6980,6 +7067,7 @@ var init_wasi_host = __esm({
6980
7067
  cache;
6981
7068
  startCwd;
6982
7069
  interruptWakes = false;
7070
+ entered = false;
6983
7071
  onRaise;
6984
7072
  muted;
6985
7073
  signals;
@@ -7203,7 +7291,8 @@ var init_wasi_host = __esm({
7203
7291
  fds: this.fds,
7204
7292
  kernel: this.o.kernel,
7205
7293
  now: (id) => this.now(id),
7206
- interruptWakes: this.interruptWakes
7294
+ interruptWakes: this.interruptWakes,
7295
+ entered: this.entered
7207
7296
  },
7208
7297
  inPtr,
7209
7298
  outPtr,
@@ -7220,7 +7309,7 @@ var init_wasi_host = __esm({
7220
7309
  this.mem.view().setUint32(nevents, 0, true);
7221
7310
  if (mask.deliverUnblocked()) return E.INTR;
7222
7311
  if (n > 0) return this.poll(inPtr, outPtr, n, nevents);
7223
- return this.suspend();
7312
+ return this.entered ? E.INTR : this.suspend();
7224
7313
  } finally {
7225
7314
  mask.deliverUnblocked();
7226
7315
  mask.restore(old);
@@ -10527,10 +10616,8 @@ var init_wasix_host = __esm({
10527
10616
  const v = mem.view();
10528
10617
  const timed = timeoutPtr !== 0 && v.getUint8(timeoutPtr) === 1;
10529
10618
  const ms = timed ? Number(v.getBigUint64(timeoutPtr + 8, true)) / 1e6 : Number.POSITIVE_INFINITY;
10530
- v.setUint8(
10531
- wokenPtr,
10532
- futexWait(i32(), ptr >> 2, expected | 0, ms, host.interrupted) ? 1 : 0
10533
- );
10619
+ const woken = host.entered || futexWait(i32(), ptr >> 2, expected | 0, ms, host.interrupted);
10620
+ v.setUint8(wokenPtr, woken ? 1 : 0);
10534
10621
  },
10535
10622
  futex_wake: (ptr, wokenPtr) => {
10536
10623
  Atomics.notify(i32(), ptr >> 2, 1);
@@ -10698,9 +10785,10 @@ function delivering(ns, table, host, driver, before) {
10698
10785
  }
10699
10786
  const fn = value2;
10700
10787
  out[name2] = (...args) => {
10788
+ host.entered = false;
10701
10789
  if (driver.idle) {
10702
10790
  before?.();
10703
- host.interrupted?.();
10791
+ host.entered = host.interrupted?.() === true;
10704
10792
  }
10705
10793
  return fn(...args);
10706
10794
  };
@@ -12309,11 +12397,20 @@ function plain(status2, text) {
12309
12397
  headers: { "content-type": "text/plain; charset=utf-8" }
12310
12398
  });
12311
12399
  }
12400
+ function local2(url) {
12401
+ return isKernelLoopbackHost(new URL(url).hostname);
12402
+ }
12312
12403
  function rewrite(hop, status2, location) {
12313
12404
  const next2 = new URL(location, hop.url);
12314
12405
  if (next2.protocol !== "http:" && next2.protocol !== "https:") {
12315
12406
  throw failed3(new JsCallError("EPROTONOSUPPORT", next2.protocol));
12316
12407
  }
12408
+ if (local2(next2.href) && !local2(hop.url)) {
12409
+ const from = new URL(hop.url).origin;
12410
+ throw failed3(
12411
+ new JsCallError("EACCES", `a redirect from ${from} into the kernel's loopback: ${next2.href}`)
12412
+ );
12413
+ }
12317
12414
  const toGet = (status2 === 301 || status2 === 302) && hop.method === "POST" || status2 === 303 && hop.method !== "GET" && hop.method !== "HEAD";
12318
12415
  const crossOrigin = next2.origin !== new URL(hop.url).origin;
12319
12416
  const headers = hop.headers.filter(
@@ -12482,13 +12579,15 @@ async function bodyOf(request, cap, signal) {
12482
12579
  return out;
12483
12580
  }
12484
12581
  function fetchOp(kernel) {
12485
- let traits;
12486
- const traitsOf = () => {
12487
- traits ??= kernel.json({ op: "net-traits" });
12488
- traits.catch(() => {
12489
- traits = void 0;
12582
+ const traits = /* @__PURE__ */ new Map();
12583
+ const traitsOf = (url) => {
12584
+ const own = local2(url);
12585
+ const known = traits.get(own) ?? kernel.json({ op: "net-traits", url });
12586
+ traits.set(own, known);
12587
+ known.catch(() => {
12588
+ traits.delete(own);
12490
12589
  });
12491
- return traits;
12590
+ return known;
12492
12591
  };
12493
12592
  const close = (handle) => kernel.raw({ op: "net-close", handle });
12494
12593
  const send = async (hop, signal) => {
@@ -12575,6 +12674,13 @@ function fetchOp(kernel) {
12575
12674
  });
12576
12675
  return withMeta(response, head.url, redirected);
12577
12676
  };
12677
+ const traitsAt = (at) => traitsOf(at).catch((err) => {
12678
+ throw failed3(err);
12679
+ });
12680
+ const redirect = async (hop, status2, location, known) => {
12681
+ const next2 = rewrite(hop, status2, location);
12682
+ return [next2, local2(next2.url) === local2(hop.url) ? known : await traitsAt(next2.url)];
12683
+ };
12578
12684
  return async (input, init) => {
12579
12685
  const request = new Request(input, init);
12580
12686
  const { signal } = request;
@@ -12584,9 +12690,7 @@ function fetchOp(kernel) {
12584
12690
  if (protocol !== "http:" && protocol !== "https:") {
12585
12691
  throw failed3(new JsCallError("EPROTONOSUPPORT", protocol));
12586
12692
  }
12587
- const known = await traitsOf().catch((err) => {
12588
- throw failed3(err);
12589
- });
12693
+ let known = await traitsAt(request.url);
12590
12694
  if (!known.manualRedirects && request.redirect !== "follow") {
12591
12695
  throw failed3(new JsCallError("ENOTSUP", `redirect: ${request.redirect}`));
12592
12696
  }
@@ -12612,7 +12716,7 @@ function fetchOp(kernel) {
12612
12716
  await close(head.handle);
12613
12717
  if (request.redirect === "error") throw failed3(new JsCallError("EREDIRECT", hop.url));
12614
12718
  if (hops >= MAX_REDIRECTS) throw failed3(new JsCallError("ELOOP", hop.url));
12615
- hop = rewrite(hop, head.status, location);
12719
+ [hop, known] = await redirect(hop, head.status, location, known);
12616
12720
  }
12617
12721
  };
12618
12722
  }
@@ -12620,6 +12724,7 @@ var CHUNK2, MAX_REDIRECTS, NULL_BODY, REDIRECTS, BODY_HEADERS, DECODED, CREDENTI
12620
12724
  var init_js_fetch = __esm({
12621
12725
  "src/process/js/js-fetch.ts"() {
12622
12726
  "use strict";
12727
+ init_loopback_names();
12623
12728
  init_js_kernel();
12624
12729
  CHUNK2 = 64 * 1024;
12625
12730
  MAX_REDIRECTS = 20;
@@ -12659,7 +12764,7 @@ function port(n) {
12659
12764
  function netOps(kernel, io) {
12660
12765
  const name2 = async (fd, peer) => addressOf(await kernel.json({ op: "sock-name", fd, peer }));
12661
12766
  const connection = async (fd) => {
12662
- const [local2, remote] = [await name2(fd, false), await name2(fd, true)];
12767
+ const [local3, remote] = [await name2(fd, false), await name2(fd, true)];
12663
12768
  const stop = new AbortController();
12664
12769
  let closed;
12665
12770
  const close = () => {
@@ -12684,7 +12789,7 @@ function netOps(kernel, io) {
12684
12789
  close: async () => void await shut(SHUT_WR),
12685
12790
  abort: () => close()
12686
12791
  });
12687
- return { fd, local: local2, remote, readable: readable3, writable: writable2, close };
12792
+ return { fd, local: local3, remote, readable: readable3, writable: writable2, close };
12688
12793
  };
12689
12794
  const resolve = async (host, signal) => {
12690
12795
  if (IPV4.test(host)) return host;