@ai-ecoverse/slicc-kernel 1.20.1 → 1.21.1

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
@@ -498,7 +498,7 @@ var KernelSocket = class _KernelSocket {
498
498
  const own = this.changes.wait(signal);
499
499
  if (this.state !== "connected" || !this.link) return own;
500
500
  const waits = [own, this.link.rx.changed(signal), this.link.tx.changed(signal)];
501
- for (const wait of waits) wait.catch(() => void 0);
501
+ for (const wait2 of waits) wait2.catch(() => void 0);
502
502
  return pipeCall(() => Promise.race(waits));
503
503
  }
504
504
  bind(addr) {
@@ -3101,6 +3101,13 @@ var SAB_I_PUB = 7;
3101
3101
  var SAB_I_SIGNALS = 8;
3102
3102
  var SAB_I_TIMERS = 9;
3103
3103
  var SAB_I_MEMORY = 10;
3104
+ var SAB_I_TOTAL_HI = 11;
3105
+ var SAB_I_OFFSET_HI = 12;
3106
+ var U32 = 2 ** 32;
3107
+ function storeU53(header3, lo, hi, value) {
3108
+ Atomics.store(header3, hi, Math.floor(value / U32));
3109
+ Atomics.store(header3, lo, value % U32 | 0);
3110
+ }
3104
3111
  var SAB_STATE_READY = 2;
3105
3112
  var SAB_STATUS_BYTES = 1;
3106
3113
  var SAB_STATUS_JSON = 2;
@@ -3160,9 +3167,9 @@ function attachSyncSabResponder(port, sab, token, opts) {
3160
3167
  const chunk2 = Math.min(window.byteLength, entry.payload.byteLength - offset);
3161
3168
  if (chunk2 > 0) window.set(entry.payload.subarray(offset, offset + chunk2));
3162
3169
  Atomics.store(header3, SAB_I_STATUS, entry.status);
3163
- Atomics.store(header3, SAB_I_TOTAL, entry.payload.byteLength);
3170
+ storeU53(header3, SAB_I_TOTAL, SAB_I_TOTAL_HI, entry.payload.byteLength);
3164
3171
  Atomics.store(header3, SAB_I_CHUNK, chunk2);
3165
- Atomics.store(header3, SAB_I_OFFSET, offset);
3172
+ storeU53(header3, SAB_I_OFFSET, SAB_I_OFFSET_HI, offset);
3166
3173
  Atomics.store(header3, SAB_I_SEQ, id);
3167
3174
  Atomics.store(header3, SAB_I_STATE, SAB_STATE_READY);
3168
3175
  Atomics.add(header3, SAB_I_PUB, 1);
@@ -6952,10 +6959,164 @@ function removableMedium(onLost, open = (handle) => new OpfsFs(handle)) {
6952
6959
  };
6953
6960
  }
6954
6961
 
6962
+ // src/mount/syscall.ts
6963
+ var MS_RDONLY = 1;
6964
+ var MS_MGC_MSK = 4294901760;
6965
+ var MS_MGC_VAL = 3236757504;
6966
+ var IGNORED_FLAGS = 2 | 4 | 8 | 16 | 128 | 1024 | 2048 | 32768 | 1 << 21 | 1 << 24 | 1 << 25;
6967
+ var MNT_FORCE = 1;
6968
+ var MNT_DETACH = 2;
6969
+ var UMOUNT_NOFOLLOW = 8;
6970
+ var GENERIC = /* @__PURE__ */ new Set([
6971
+ "defaults",
6972
+ "async",
6973
+ "sync",
6974
+ "dirsync",
6975
+ "atime",
6976
+ "noatime",
6977
+ "diratime",
6978
+ "nodiratime",
6979
+ "relatime",
6980
+ "norelatime",
6981
+ "strictatime",
6982
+ "nostrictatime",
6983
+ "lazytime",
6984
+ "nolazytime",
6985
+ "suid",
6986
+ "nosuid",
6987
+ "dev",
6988
+ "nodev",
6989
+ "exec",
6990
+ "noexec",
6991
+ "auto",
6992
+ "noauto",
6993
+ "user",
6994
+ "nouser",
6995
+ "users",
6996
+ "nofail",
6997
+ "_netdev",
6998
+ "silent",
6999
+ "loud"
7000
+ ]);
7001
+ function parseMountOptions(data) {
7002
+ const options = {};
7003
+ for (const raw of data.split(",")) {
7004
+ const item = raw.trim();
7005
+ if (!item || GENERIC.has(item)) continue;
7006
+ if (item === "rw") {
7007
+ delete options.ro;
7008
+ continue;
7009
+ }
7010
+ const eq = item.indexOf("=");
7011
+ if (eq === 0) throw errnoError("EINVAL", `bad mount option ${item}`);
7012
+ if (eq < 0) options[item] = "";
7013
+ else options[item.slice(0, eq)] = item.slice(eq + 1);
7014
+ }
7015
+ if (options.maxfile !== void 0) parseSize(options.maxfile);
7016
+ return options;
7017
+ }
7018
+ function refusedTarget(target) {
7019
+ const at = normalizePath(target);
7020
+ const kernel = at === "/" || [`/proc`, `/dev`].some((k) => at === k || at.startsWith(`${k}/`));
7021
+ if (kernel) throw errnoError("EBUSY", `${at} belongs to the kernel`);
7022
+ }
7023
+ function absolute(target) {
7024
+ if (!target) throw errnoError("ENOENT", "no mount point");
7025
+ if (!target.startsWith("/")) throw errnoError("EINVAL", `not an absolute path: ${target}`);
7026
+ return normalizePath(target);
7027
+ }
7028
+ function mountCall(call) {
7029
+ let flags = call.flags >>> 0;
7030
+ if ((flags & MS_MGC_MSK) >>> 0 === MS_MGC_VAL) flags &= ~MS_MGC_MSK;
7031
+ if (flags & ~(MS_RDONLY | IGNORED_FLAGS)) {
7032
+ throw errnoError("EINVAL", `unsupported mount flags ${flags.toString(16)}`);
7033
+ }
7034
+ if (!call.type) throw errnoError("EINVAL", "no file system type");
7035
+ const target = absolute(call.target);
7036
+ refusedTarget(target);
7037
+ const options = parseMountOptions(call.data);
7038
+ if (flags & MS_RDONLY) options.ro = "";
7039
+ return { type: call.type, source: call.source || "none", target, options };
7040
+ }
7041
+ function umountCall(target, flags) {
7042
+ const known = MNT_FORCE | MNT_DETACH | UMOUNT_NOFOLLOW;
7043
+ if (flags >>> 0 & ~known) throw errnoError("EINVAL", `unsupported umount flags ${flags}`);
7044
+ const at = absolute(target);
7045
+ refusedTarget(at);
7046
+ return { target: at, detach: (flags & (MNT_FORCE | MNT_DETACH)) !== 0 };
7047
+ }
7048
+
7049
+ // src/mount/fstab.ts
7050
+ var FSTAB_PATH = "/etc/fstab";
7051
+ var FSTAB_RETRIES = [1e3, 4e3, 16e3];
7052
+ var FINAL = /* @__PURE__ */ new Set(["EINVAL", "EBUSY", "EPERM", "EACCES"]);
7053
+ function unescape(field) {
7054
+ return field.replace(
7055
+ /\\([0-7]{3})/g,
7056
+ (_, octal) => String.fromCharCode(Number.parseInt(octal, 8))
7057
+ );
7058
+ }
7059
+ function parseFstab(text) {
7060
+ const lines = [];
7061
+ text.split("\n").forEach((raw, index) => {
7062
+ const content = raw.replace(/#.*$/, "").trim();
7063
+ if (!content) return;
7064
+ const [source, target, type, options = "defaults"] = content.split(/\s+/).map(unescape);
7065
+ if (source === void 0 || target === void 0 || type === void 0) return;
7066
+ if (options.split(",").includes("noauto")) return;
7067
+ const spec = { source, target, type, options: {} };
7068
+ try {
7069
+ lines.push({ line: index + 1, spec: { ...spec, options: parseMountOptions(options) } });
7070
+ } catch (err) {
7071
+ lines.push({ line: index + 1, spec, invalid: err });
7072
+ }
7073
+ });
7074
+ return lines;
7075
+ }
7076
+ function codeOf3(err) {
7077
+ const code = err?.code;
7078
+ return typeof code === "string" ? code : "EIO";
7079
+ }
7080
+ function wait(ms, signal) {
7081
+ if (signal.aborted) return Promise.resolve();
7082
+ return new Promise((resolve) => {
7083
+ const done4 = () => {
7084
+ clearTimeout(timer);
7085
+ signal.removeEventListener("abort", done4);
7086
+ resolve();
7087
+ };
7088
+ const timer = setTimeout(done4, ms);
7089
+ signal.addEventListener("abort", done4, { once: true });
7090
+ });
7091
+ }
7092
+ async function mountFstab(lines, mount, signal, retries = FSTAB_RETRIES, discard = () => {
7093
+ }) {
7094
+ return Promise.all(
7095
+ lines.map(async ({ line, spec, invalid }) => {
7096
+ let failed = invalid;
7097
+ for (let attempt = 0; !invalid && attempt <= retries.length && !signal.aborted; attempt++) {
7098
+ try {
7099
+ const entry = await mount(spec);
7100
+ if (!signal.aborted) return { line, target: spec.target, entry };
7101
+ discard(entry);
7102
+ failed = Object.assign(new Error("the kernel stopped"), { code: "ECANCELED" });
7103
+ break;
7104
+ } catch (err) {
7105
+ failed = err;
7106
+ if (FINAL.has(codeOf3(err)) || attempt === retries.length) break;
7107
+ await wait(retries[attempt], signal);
7108
+ }
7109
+ }
7110
+ const code = codeOf3(failed);
7111
+ return { line, target: spec.target, code, error: String(failed?.message ?? code) };
7112
+ })
7113
+ );
7114
+ }
7115
+
6955
7116
  // src/mount/hostfs.ts
6956
7117
  var HOSTFS_IO = 16 * 1024 * 1024;
6957
- var codeOf3 = (err) => err?.code;
6958
- var unreachable = (err) => codeOf3(err) === "ENOTCONN";
7118
+ var codeOf4 = (err) => err?.code;
7119
+ var unreachable = (err) => codeOf4(err) === "ENOTCONN";
6959
7120
  function rel(path) {
6960
7121
  return path.replace(/^\/+/, "");
6961
7122
  }
@@ -7090,7 +7251,7 @@ function hostfsHandlers(current) {
7090
7251
  try {
7091
7252
  return { opened: await opening(), restore: void 0 };
7092
7253
  } catch (err) {
7093
- if (!flags.write || codeOf3(err) !== "EACCES") throw err;
7254
+ if (!flags.write || codeOf4(err) !== "EACCES") throw err;
7094
7255
  const mode = (await client.call("stat", { path: rel(path) })).mode ?? 0;
7095
7256
  if (mode & 128) throw err;
7096
7257
  const restore = { path: rel(path), mode };
@@ -7179,7 +7340,7 @@ function keepWatching(loop, signal) {
7179
7340
  const uncap = () => clearTimeout(capped);
7180
7341
  void ready2.promise.then(uncap);
7181
7342
  signal.addEventListener("abort", uncap, { once: true });
7182
- let wait = first;
7343
+ let wait2 = first;
7183
7344
  let up = false;
7184
7345
  let current;
7185
7346
  async function session() {
@@ -7224,7 +7385,7 @@ function keepWatching(loop, signal) {
7224
7385
  const opened2 = await session();
7225
7386
  if (signal.aborted) return;
7226
7387
  if (opened2 && Date.now() - began >= first) {
7227
- wait = first;
7388
+ wait2 = first;
7228
7389
  continue;
7229
7390
  }
7230
7391
  if (!opened2 && up) {
@@ -7232,8 +7393,8 @@ function keepWatching(loop, signal) {
7232
7393
  loop.down();
7233
7394
  }
7234
7395
  ready2.resolve();
7235
- await sleep(wait, signal);
7236
- wait = Math.min(wait * 2, most);
7396
+ await sleep(wait2, signal);
7397
+ wait2 = Math.min(wait2 * 2, most);
7237
7398
  }
7238
7399
  })();
7239
7400
  return { ready: ready2.promise, kick: () => current?.abort() };
@@ -7297,93 +7458,6 @@ function memoryMedia() {
7297
7458
  };
7298
7459
  }
7299
7460
 
7300
- // src/mount/syscall.ts
7301
- var MS_RDONLY = 1;
7302
- var MS_MGC_MSK = 4294901760;
7303
- var MS_MGC_VAL = 3236757504;
7304
- var IGNORED_FLAGS = 2 | 4 | 8 | 16 | 128 | 1024 | 2048 | 32768 | 1 << 21 | 1 << 24 | 1 << 25;
7305
- var MNT_FORCE = 1;
7306
- var MNT_DETACH = 2;
7307
- var UMOUNT_NOFOLLOW = 8;
7308
- var GENERIC = /* @__PURE__ */ new Set([
7309
- "defaults",
7310
- "async",
7311
- "sync",
7312
- "dirsync",
7313
- "atime",
7314
- "noatime",
7315
- "diratime",
7316
- "nodiratime",
7317
- "relatime",
7318
- "norelatime",
7319
- "strictatime",
7320
- "nostrictatime",
7321
- "lazytime",
7322
- "nolazytime",
7323
- "suid",
7324
- "nosuid",
7325
- "dev",
7326
- "nodev",
7327
- "exec",
7328
- "noexec",
7329
- "auto",
7330
- "noauto",
7331
- "user",
7332
- "nouser",
7333
- "users",
7334
- "nofail",
7335
- "_netdev",
7336
- "silent",
7337
- "loud"
7338
- ]);
7339
- function parseMountOptions(data) {
7340
- const options = {};
7341
- for (const raw of data.split(",")) {
7342
- const item = raw.trim();
7343
- if (!item || GENERIC.has(item)) continue;
7344
- if (item === "rw") {
7345
- delete options.ro;
7346
- continue;
7347
- }
7348
- const eq = item.indexOf("=");
7349
- if (eq === 0) throw errnoError("EINVAL", `bad mount option ${item}`);
7350
- if (eq < 0) options[item] = "";
7351
- else options[item.slice(0, eq)] = item.slice(eq + 1);
7352
- }
7353
- if (options.maxfile !== void 0) parseSize(options.maxfile);
7354
- return options;
7355
- }
7356
- function refusedTarget(target) {
7357
- const at = normalizePath(target);
7358
- const kernel = at === "/" || [`/proc`, `/dev`].some((k) => at === k || at.startsWith(`${k}/`));
7359
- if (kernel) throw errnoError("EBUSY", `${at} belongs to the kernel`);
7360
- }
7361
- function absolute(target) {
7362
- if (!target) throw errnoError("ENOENT", "no mount point");
7363
- if (!target.startsWith("/")) throw errnoError("EINVAL", `not an absolute path: ${target}`);
7364
- return normalizePath(target);
7365
- }
7366
- function mountCall(call) {
7367
- let flags = call.flags >>> 0;
7368
- if ((flags & MS_MGC_MSK) >>> 0 === MS_MGC_VAL) flags &= ~MS_MGC_MSK;
7369
- if (flags & ~(MS_RDONLY | IGNORED_FLAGS)) {
7370
- throw errnoError("EINVAL", `unsupported mount flags ${flags.toString(16)}`);
7371
- }
7372
- if (!call.type) throw errnoError("EINVAL", "no file system type");
7373
- const target = absolute(call.target);
7374
- refusedTarget(target);
7375
- const options = parseMountOptions(call.data);
7376
- if (flags & MS_RDONLY) options.ro = "";
7377
- return { type: call.type, source: call.source || "none", target, options };
7378
- }
7379
- function umountCall(target, flags) {
7380
- const known = MNT_FORCE | MNT_DETACH | UMOUNT_NOFOLLOW;
7381
- if (flags >>> 0 & ~known) throw errnoError("EINVAL", `unsupported umount flags ${flags}`);
7382
- const at = absolute(target);
7383
- refusedTarget(at);
7384
- return { target: at, detach: (flags & (MNT_FORCE | MNT_DETACH)) !== 0 };
7385
- }
7386
-
7387
7461
  // src/mount/tmpfs.ts
7388
7462
  function tmpfs() {
7389
7463
  let inodes = 0;
@@ -7802,6 +7876,8 @@ var Launcher = class {
7802
7876
  openFiles = /* @__PURE__ */ new Set();
7803
7877
  held = /* @__PURE__ */ new Set();
7804
7878
  processMounts;
7879
+ booting = new AbortController();
7880
+ fstab = Promise.resolve([]);
7805
7881
  nextPid = 1e3;
7806
7882
  boot = Date.now();
7807
7883
  terminals = 0;
@@ -8209,6 +8285,7 @@ var Launcher = class {
8209
8285
  for (const holds of this.held) holds.revoke(at);
8210
8286
  }
8211
8287
  unmountAll() {
8288
+ this.booting.abort();
8212
8289
  const targets = this.mounts.list().map((m) => m.target);
8213
8290
  for (const target of targets.sort((a, b) => b.length - a.length)) this.umount(target, true);
8214
8291
  }
@@ -8240,6 +8317,17 @@ var Launcher = class {
8240
8317
  async prepare() {
8241
8318
  for (const dir of SHARED_DIRS) await this.base.mkdir(dir, { recursive: true });
8242
8319
  await writeCaFile(this.base, this.ca).catch(() => void 0);
8320
+ this.fstab = this.mountFstab();
8321
+ }
8322
+ async mountFstab() {
8323
+ const text = await this.base.readFile(FSTAB_PATH).catch(() => "");
8324
+ return mountFstab(
8325
+ parseFstab(text),
8326
+ (spec) => this.mount(spec),
8327
+ this.booting.signal,
8328
+ FSTAB_RETRIES,
8329
+ (entry) => this.umount(entry.target, true)
8330
+ );
8243
8331
  }
8244
8332
  environment(cwd, extra) {
8245
8333
  return {