@ai-ecoverse/slicc-kernel 1.148.0 → 1.149.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
@@ -1697,6 +1697,9 @@ function link(a, b) {
1697
1697
  a.attach({ rx: ba, tx: ab });
1698
1698
  b.attach({ rx: ab, tx: ba });
1699
1699
  }
1700
+ var SERVE_CHUNK = 64 * 1024;
1701
+ var NEVER_ABORTED = new AbortController().signal;
1702
+ var EMPTY = new Uint8Array(0);
1700
1703
  var KernelSocket = class _KernelSocket {
1701
1704
  net;
1702
1705
  domain;
@@ -1894,6 +1897,54 @@ var KernelSocket = class _KernelSocket {
1894
1897
  if (this.state !== "open") throw new KernelError("EISCONN");
1895
1898
  return this.dial(addr, route2, secure2);
1896
1899
  }
1900
+ serving;
1901
+ served = false;
1902
+ get loopbackLinked() {
1903
+ return this.state === "connected" && !this.switch;
1904
+ }
1905
+ async secureLink(make, signal = NEVER_ABORTED) {
1906
+ const raw2 = this.connection();
1907
+ if (this.switch || this.served || this.writeShut || this.readShut)
1908
+ throw new KernelError("EINVAL");
1909
+ signal.throwIfAborted();
1910
+ this.served = true;
1911
+ let handshaking = true;
1912
+ const view2 = {
1913
+ localAddr: "",
1914
+ remoteAddr: "",
1915
+ read: async () => {
1916
+ const bytes = await raw2.rx.read(SERVE_CHUNK, handshaking ? signal : void 0).catch(() => EMPTY);
1917
+ return bytes.length > 0 ? bytes : null;
1918
+ },
1919
+ write: (bytes) => raw2.tx.write(bytes),
1920
+ closeWrite: () => raw2.tx.closeWrite(),
1921
+ close: () => {
1922
+ raw2.rx.closeRead();
1923
+ raw2.tx.closeWrite();
1924
+ }
1925
+ };
1926
+ let made2;
1927
+ const abandon = () => view2.close();
1928
+ signal.addEventListener("abort", abandon, { once: true });
1929
+ try {
1930
+ made2 = await make(view2);
1931
+ } catch (err) {
1932
+ view2.close();
1933
+ this.readShut = true;
1934
+ this.writeShut = true;
1935
+ this.changes.wake();
1936
+ throw signal.aborted ? signal.reason : err;
1937
+ } finally {
1938
+ handshaking = false;
1939
+ signal.removeEventListener("abort", abandon);
1940
+ }
1941
+ this.link = uplinkLink(made2.conn, (err) => {
1942
+ this.reset = err instanceof KernelError && err.code === "EPROTO" ? err : new KernelError("ECONNRESET");
1943
+ this.changes.wake();
1944
+ });
1945
+ this.changes.wake();
1946
+ return made2.info;
1947
+ }
1897
1948
  upgradeSecure(make) {
1898
1949
  if (this.state !== "connected") throw new KernelError("ENOTCONN");
1899
1950
  if (!this.switch) throw new KernelError("EOPNOTSUPP");
@@ -2025,6 +2076,8 @@ var KernelSocket = class _KernelSocket {
2025
2076
  }
2026
2077
  if (this.boundAt) this.net.release(this.boundAt, this, this.named);
2027
2078
  this.boundAt = void 0;
2079
+ this.serving?.release();
2080
+ this.serving = void 0;
2028
2081
  this.changes.wake();
2029
2082
  }
2030
2083
  static pair(net, domain, cred) {
@@ -3305,7 +3358,7 @@ function satisfies(version, range2) {
3305
3358
  }
3306
3359
 
3307
3360
  // src/version.ts
3308
- var KERNEL_VERSION = true ? "1.148.0" : "0.0.0-dev";
3361
+ var KERNEL_VERSION = true ? "1.149.0" : "0.0.0-dev";
3309
3362
  var OS_RELEASE = "6.0.0-slicc";
3310
3363
  function procVersion() {
3311
3364
  return `Linux version ${OS_RELEASE} (slicc-kernel ${KERNEL_VERSION}) #1 SMP PREEMPT_DYNAMIC
@@ -5982,7 +6035,7 @@ async function followLinks(fs, path) {
5982
6035
  return current;
5983
6036
  }
5984
6037
  var NOBODY = { ruid: -1, euid: -1, suid: -1, rgid: -1, egid: -1, sgid: -1, groups: [] };
5985
- var EMPTY = new Uint8Array(0);
6038
+ var EMPTY2 = new Uint8Array(0);
5986
6039
  function quiet2(promise) {
5987
6040
  return promise.catch(() => void 0);
5988
6041
  }
@@ -6065,13 +6118,13 @@ function withCommandDirs(fs, names2, userDir = async () => void 0, owners = fals
6065
6118
  return target?.path;
6066
6119
  }
6067
6120
  const absent2 = (err) => {
6068
- if (missing(err)) return EMPTY;
6121
+ if (missing(err)) return EMPTY2;
6069
6122
  throw err;
6070
6123
  };
6071
6124
  async function content(path, err) {
6072
6125
  if (!missing(err) || !(await linked2(path))?.isFile) throw err;
6073
6126
  const target = await redirected2(path);
6074
- return target === void 0 ? EMPTY : fs.readFileBuffer(target).catch(absent2);
6127
+ return target === void 0 ? EMPTY2 : fs.readFileBuffer(target).catch(absent2);
6075
6128
  }
6076
6129
  const ranged2 = rangedOps(fs);
6077
6130
  async function stat(path, real) {
@@ -12704,6 +12757,8 @@ function realmCa(owner, store) {
12704
12757
  var TLS_CLIENT_INSECURE_SKIP_VERIFY = 1;
12705
12758
  var TLS_CLIENT_NO_SNI = 2;
12706
12759
  var TLS_CLIENT_VERIFY_CHAIN_ONLY = 4;
12760
+ var TLS_SERVER_REQUEST_CERT = 1;
12761
+ var TLS_SERVER_REQUIRE_CERT = 2;
12707
12762
  var SCRATCH = 64 * 1024;
12708
12763
  var EOF = -1;
12709
12764
  var TlsError = class extends Error {
@@ -12752,6 +12807,35 @@ var TlsEngine = class {
12752
12807
  this.m._free(name2);
12753
12808
  }
12754
12809
  }
12810
+ get serverSessions() {
12811
+ return typeof this.m._tls_server_new === "function";
12812
+ }
12813
+ importLeaf(chain2, key, pass2) {
12814
+ const leafImport = this.m._tls_leaf_import;
12815
+ const keyLen = key[0] === 45 ? key.length + 1 : key.length;
12816
+ const ptr = this.withBytes(
12817
+ chain2,
12818
+ (c) => this.withSecret(
12819
+ key,
12820
+ (k) => this.withSecret(
12821
+ pass2,
12822
+ (p) => leafImport(c, chain2.length, k, keyLen, pass2.length > 0 ? p : 0, pass2.length)
12823
+ )
12824
+ )
12825
+ );
12826
+ if (!ptr) throw this.error(this.m._tls_last_error(), "server certificate");
12827
+ return new TlsLeaf(this, this.m, ptr);
12828
+ }
12829
+ serverSession(leaf, alpn, clientCa, flags2) {
12830
+ const open = this.m._tls_server_new;
12831
+ const wire = alpnWire(alpn);
12832
+ const ptr = this.withBytes(
12833
+ wire,
12834
+ (p) => open(leaf.ptr, wire.length > 0 ? p : 0, wire.length, clientCa?.ptr ?? 0, flags2)
12835
+ );
12836
+ if (!ptr) throw this.error(this.m._tls_last_error(), "tls server");
12837
+ return new TlsSession(this, this.m, ptr);
12838
+ }
12755
12839
  withBytes(bytes, fn) {
12756
12840
  const ptr = this.put(bytes);
12757
12841
  try {
@@ -12956,6 +13040,12 @@ var TlsSession = class {
12956
13040
  get version() {
12957
13041
  return this.c._tls_version(this.ptr);
12958
13042
  }
13043
+ get sni() {
13044
+ const out = this.engine.intoScratch(
13045
+ (p, max) => this.m._tls_sni(this.ptr, p, max)
13046
+ );
13047
+ return out instanceof Uint8Array ? new TextDecoder().decode(out) : "";
13048
+ }
12959
13049
  get alpn() {
12960
13050
  const out = this.engine.intoScratch((p, max) => this.c._tls_alpn(this.ptr, p, max));
12961
13051
  return out instanceof Uint8Array ? new TextDecoder().decode(out) : void 0;
@@ -13454,7 +13544,7 @@ var Upload = class {
13454
13544
  }
13455
13545
  }
13456
13546
  };
13457
- var EMPTY2 = new Uint8Array(0);
13547
+ var EMPTY3 = new Uint8Array(0);
13458
13548
  function message2(e) {
13459
13549
  return e instanceof Error ? e.message : String(e);
13460
13550
  }
@@ -13529,8 +13619,8 @@ var HttpHandles = class {
13529
13619
  const entry = {
13530
13620
  abort,
13531
13621
  head: Promise.resolve({ ok: true, kind: "void" }),
13532
- body: once(EMPTY2),
13533
- left: EMPTY2,
13622
+ body: once(EMPTY3),
13623
+ left: EMPTY3,
13534
13624
  done: false,
13535
13625
  reading: Promise.resolve(),
13536
13626
  cancel: async () => void 0,
@@ -14656,6 +14746,46 @@ async function tlsClient(conn, o, taken = new Uint8Array(0)) {
14656
14746
  throw err;
14657
14747
  }
14658
14748
  }
14749
+ async function serverHandshake(conn, session, inbox) {
14750
+ for (; ; ) {
14751
+ let done4;
14752
+ try {
14753
+ done4 = session.handshake();
14754
+ } catch (err) {
14755
+ await send(conn, session).catch(() => void 0);
14756
+ const text = err instanceof TlsError ? err.message : String(err);
14757
+ throw new KernelError("EPROTO", `ERR_SSL_HANDSHAKE_FAILURE: ${text}${alertOf(session)}`);
14758
+ }
14759
+ await send(conn, session);
14760
+ if (done4) return;
14761
+ if (!await inbox.more()) {
14762
+ throw new KernelError(
14763
+ "ECONNRESET",
14764
+ "the client closed the connection during the TLS handshake"
14765
+ );
14766
+ }
14767
+ }
14768
+ }
14769
+ async function tlsServer(conn, session, clientCerts) {
14770
+ const inbox = new Ciphertext(conn, session);
14771
+ try {
14772
+ await serverHandshake(conn, session, inbox);
14773
+ const chain2 = session.peerChain();
14774
+ const code = clientCerts ? verifyCode(session.verifyResult) : void 0;
14775
+ const info = {
14776
+ protocol: session.version === 772 ? "TLSv1.3" : "TLSv1.2",
14777
+ alpnProtocol: session.alpn ?? false,
14778
+ servername: session.sni,
14779
+ authorized: clientCerts && chain2.length > 0 && code === void 0,
14780
+ ...clientCerts && chain2.length > 0 && code ? { authorizationError: code } : {},
14781
+ peerCertificates: chain2
14782
+ };
14783
+ return { conn: plaintext(conn, session, inbox), info };
14784
+ } catch (err) {
14785
+ session.free();
14786
+ throw err;
14787
+ }
14788
+ }
14659
14789
 
14660
14790
  // src/kernel/net/tls-chain.ts
14661
14791
  var CN_MISMATCH = 4;
@@ -15108,7 +15238,7 @@ var RANK = {
15108
15238
  };
15109
15239
  var CR2 = 13;
15110
15240
  var LF2 = 10;
15111
- var EMPTY3 = new Uint8Array(0);
15241
+ var EMPTY4 = new Uint8Array(0);
15112
15242
  function register(automaton, sources, ids, bytes, source) {
15113
15243
  const key = Array.from(bytes).join(",");
15114
15244
  let id2 = ids.get(key);
@@ -15288,12 +15418,12 @@ function compile(secrets, options = {}) {
15288
15418
  return { text: decoder4.decode(bytes), hits };
15289
15419
  },
15290
15420
  stream() {
15291
- let pending = EMPTY3;
15421
+ let pending = EMPTY4;
15292
15422
  const hits = /* @__PURE__ */ new Map();
15293
15423
  const run2 = (final) => {
15294
15424
  if (c.secrets.length === 0 || pending.length === 0) {
15295
15425
  const out = pending;
15296
- pending = EMPTY3;
15426
+ pending = EMPTY4;
15297
15427
  return out;
15298
15428
  }
15299
15429
  const result = pass(c, pending, final);
@@ -15307,7 +15437,7 @@ function compile(secrets, options = {}) {
15307
15437
  return run2(false);
15308
15438
  },
15309
15439
  idle() {
15310
- return pending.length < FRAGMENT ? run2(true) : EMPTY3;
15440
+ return pending.length < FRAGMENT ? run2(true) : EMPTY4;
15311
15441
  },
15312
15442
  end() {
15313
15443
  return run2(true);
@@ -17469,6 +17599,7 @@ function sealedConn(conn, s) {
17469
17599
  }
17470
17600
 
17471
17601
  // src/kernel/net/tls-uplink.ts
17602
+ var handshakeAbort = (proc) => proc.cancelled ?? proc.blocking();
17472
17603
  var isIP2 = (text) => ipv4Bytes(text) !== void 0 || text.includes(":") && ipv6Groups(text) !== void 0;
17473
17604
  var LABEL2 = /^(?!-)[A-Za-z0-9-]{1,63}(?<!-)$/;
17474
17605
  function serverName(name2) {
@@ -17589,6 +17720,9 @@ function takeCert(req) {
17589
17720
  const cert = req.clientCert;
17590
17721
  if (!cert) return void 0;
17591
17722
  delete req.clientCert;
17723
+ return certBytes(cert);
17724
+ }
17725
+ function certBytes(cert) {
17592
17726
  if (!Array.isArray(cert.chain) || cert.chain.length === 0 || typeof cert.key !== "string")
17593
17727
  throw new KernelError("EINVAL", "ERR_INVALID_ARG_VALUE: cert and key go together");
17594
17728
  let ders;
@@ -17764,8 +17898,32 @@ async function connectSecure(proc, socket, host, port, req) {
17764
17898
  }
17765
17899
  return sessionOf(info, servername);
17766
17900
  }
17901
+ async function loopbackSecure(proc, socket, servername, req) {
17902
+ const prepared = await prepare2(supportOf(proc.net), req, servername);
17903
+ let ran = false;
17904
+ try {
17905
+ const info = await socket.secureLink(async (raw2) => {
17906
+ ran = true;
17907
+ try {
17908
+ return await tlsClient(raw2, prepared.options);
17909
+ } finally {
17910
+ prepared.own?.release();
17911
+ }
17912
+ }, handshakeAbort(proc));
17913
+ return sessionOf({ ...info, substitutes: false }, servername);
17914
+ } finally {
17915
+ if (!ran) {
17916
+ prepared.options.session.free();
17917
+ prepared.own?.release();
17918
+ }
17919
+ }
17920
+ }
17767
17921
  async function upgradeSecure(proc, socket, req) {
17768
17922
  const peer = socket.peer;
17923
+ if (socket.loopbackLinked) {
17924
+ const host2 = req.servername || (peer?.family === "inet" ? peer.host : "localhost");
17925
+ return loopbackSecure(proc, socket, serverName(host2), req);
17926
+ }
17769
17927
  const host = req.servername || (peer?.family === "inet" ? peer.host : "");
17770
17928
  const servername = serverName(host);
17771
17929
  const port = peer?.family === "inet" ? peer.port : 0;
@@ -17780,6 +17938,120 @@ async function upgradeSecure(proc, socket, req) {
17780
17938
  }
17781
17939
  }
17782
17940
 
17941
+ // src/kernel/net/tls-server.ts
17942
+ var HANDSHAKE_TIMEOUT_MS = 12e4;
17943
+ function leafOf(engine, cert) {
17944
+ try {
17945
+ return engine.importLeaf(cert.chain, cert.key, cert.pass);
17946
+ } catch (err) {
17947
+ throw keyRefused(err, cert.pass.length > 0 && encryptedKey(cert.key));
17948
+ } finally {
17949
+ wipe(cert);
17950
+ }
17951
+ }
17952
+ function storeOf(engine, ca) {
17953
+ const store = engine.store();
17954
+ try {
17955
+ for (const der2 of ca) store.add(base64Der(der2));
17956
+ return store;
17957
+ } catch (err) {
17958
+ store.release();
17959
+ throw new KernelError("EINVAL", `ERR_INVALID_ARG_VALUE: ca: ${err.message}`);
17960
+ }
17961
+ }
17962
+ function flagsOf(req, store) {
17963
+ if (!req.requestCert) return 0;
17964
+ if (!store) throw new KernelError("EINVAL", "ERR_INVALID_ARG_VALUE: requestCert needs a ca");
17965
+ return req.rejectUnauthorized === false ? TLS_SERVER_REQUEST_CERT : TLS_SERVER_REQUIRE_CERT;
17966
+ }
17967
+ function timeoutOf(req) {
17968
+ const ms = req.handshakeTimeout ?? HANDSHAKE_TIMEOUT_MS;
17969
+ if (!Number.isInteger(ms) || ms <= 0)
17970
+ throw new KernelError(
17971
+ "EINVAL",
17972
+ "ERR_OUT_OF_RANGE: handshakeTimeout must be a positive integer"
17973
+ );
17974
+ return ms;
17975
+ }
17976
+ function handshakeSignal(proc, ms) {
17977
+ const timer = new AbortController();
17978
+ const id2 = setTimeout(
17979
+ () => timer.abort(new KernelError("EPROTO", "ERR_TLS_HANDSHAKE_TIMEOUT: TLS handshake timeout")),
17980
+ ms
17981
+ );
17982
+ return {
17983
+ signal: AbortSignal.any([handshakeAbort(proc), timer.signal]),
17984
+ done: () => clearTimeout(id2)
17985
+ };
17986
+ }
17987
+ async function serverOf(proc, req) {
17988
+ const own = req.cert;
17989
+ delete req.cert;
17990
+ if (!own) throw new KernelError("EINVAL", "ERR_INVALID_ARG_VALUE: a server needs cert and key");
17991
+ const cert = certBytes(own);
17992
+ let engine;
17993
+ try {
17994
+ engine = await supportOf(proc.net).engine();
17995
+ if (!engine.serverSessions)
17996
+ throw new KernelError("ENOTSUP", "the installed tls engine has no server sessions");
17997
+ } catch (err) {
17998
+ wipe(cert);
17999
+ throw err;
18000
+ }
18001
+ const leaf = leafOf(engine, cert);
18002
+ let store;
18003
+ try {
18004
+ store = req.ca && req.ca.length > 0 ? storeOf(engine, req.ca) : void 0;
18005
+ const flags2 = flagsOf(req, store);
18006
+ return {
18007
+ engine,
18008
+ leaf,
18009
+ store,
18010
+ alpn: req.alpn ?? [],
18011
+ flags: flags2,
18012
+ timeoutMs: timeoutOf(req),
18013
+ release() {
18014
+ leaf.release();
18015
+ store?.release();
18016
+ }
18017
+ };
18018
+ } catch (err) {
18019
+ leaf.release();
18020
+ store?.release();
18021
+ throw err;
18022
+ }
18023
+ }
18024
+ async function listenSecure(proc, socket, req) {
18025
+ if (!socket.listening) throw new KernelError("EINVAL", "not a listening socket");
18026
+ const server = await serverOf(proc, req);
18027
+ socket.serving?.release();
18028
+ socket.serving = server;
18029
+ }
18030
+ async function serveSecure(proc, socket, req) {
18031
+ const shared = req.listener?.serving;
18032
+ if (req.listener && !shared) throw new KernelError("EINVAL", "the listener has no tls");
18033
+ const server = shared ?? await serverOf(proc, req);
18034
+ try {
18035
+ const { engine, leaf, alpn, store, flags: flags2 } = server;
18036
+ const limit = handshakeSignal(proc, server.timeoutMs);
18037
+ const info = await socket.secureLink(
18038
+ (raw2) => tlsServer(raw2, engine.serverSession(leaf, alpn, store, flags2), flags2 !== 0),
18039
+ limit.signal
18040
+ ).finally(limit.done);
18041
+ return {
18042
+ path: "kernel",
18043
+ protocol: info.protocol,
18044
+ alpnProtocol: info.alpnProtocol,
18045
+ servername: info.servername,
18046
+ authorized: info.authorized,
18047
+ ...info.authorizationError ? { authorizationError: info.authorizationError } : {},
18048
+ peerCertificates: info.peerCertificates.map(encode)
18049
+ };
18050
+ } finally {
18051
+ if (!shared) server.release();
18052
+ }
18053
+ }
18054
+
17783
18055
  // src/kernel/unix-dgram.ts
17784
18056
  var SOL_SOCKET3 = 1;
17785
18057
  var SO_TYPE3 = 3;
@@ -17942,7 +18214,9 @@ var SOCKET_OPS = [
17942
18214
  "sock-sendto",
17943
18215
  "sock-recvfrom",
17944
18216
  "sock-tls",
17945
- "sock-tls-upgrade"
18217
+ "sock-tls-upgrade",
18218
+ "sock-tls-serve",
18219
+ "sock-tls-listen"
17946
18220
  ];
17947
18221
  function socketAt(fds, fd) {
17948
18222
  const file = anySocketAt(fds, fd);
@@ -18018,6 +18292,14 @@ async function socketSyscall(req, proc) {
18018
18292
  return ok3(await secureConnect(req, proc));
18019
18293
  case "sock-tls-upgrade":
18020
18294
  return ok3(await upgradeSecure(proc, socketAt(fds, req.fd), req));
18295
+ case "sock-tls-serve": {
18296
+ const { from, ...rest2 } = req;
18297
+ const listener = from === void 0 ? {} : { listener: socketAt(fds, from) };
18298
+ return ok3(await serveSecure(proc, socketAt(fds, req.fd), { ...rest2, ...listener }));
18299
+ }
18300
+ case "sock-tls-listen":
18301
+ await listenSecure(proc, socketAt(fds, req.fd), req);
18302
+ return ok3({});
18021
18303
  default:
18022
18304
  return datagram(req, proc);
18023
18305
  }
@@ -20449,6 +20731,7 @@ var WasmProcess = class {
20449
20731
  fds: this.fds,
20450
20732
  net: this.net,
20451
20733
  blocking: () => this.blockingSignal(cancelled),
20734
+ cancelled,
20452
20735
  resolve: (name2, family, blocking) => resolver.resolve(name2, family, blocking),
20453
20736
  cred: () => ({ pid: this.pid, uid: this.cred.euid, gid: this.cred.egid }),
20454
20737
  stamp: () => this.connectorStamp(),
@@ -21791,6 +22074,9 @@ var RemoteWatch = class {
21791
22074
  await new Promise((resolve2) => setTimeout(resolve2, ANNOUNCE_POLL_MS));
21792
22075
  }
21793
22076
  }
22077
+ legacy() {
22078
+ return [...this.peers].filter((peer) => !this.ackers.has(peer));
22079
+ }
21794
22080
  crowded() {
21795
22081
  return !this.settled || this.peers.size > 0;
21796
22082
  }
@@ -21798,7 +22084,7 @@ var RemoteWatch = class {
21798
22084
  return `${this.name}:${tab}`;
21799
22085
  }
21800
22086
  receive(data) {
21801
- const sender = data.hello ?? data.here;
22087
+ const sender = data.hello ?? data.here ?? (data.paths !== void 0 ? data.tab : void 0);
21802
22088
  if (sender !== void 0 && data.renames) this.ackers.add(sender);
21803
22089
  if (data.hello !== void 0) this.greeted(data.hello);
21804
22090
  if (data.renaming !== void 0 && data.tab !== void 0) this.heard(data);
@@ -21905,7 +22191,7 @@ var RemoteWatch = class {
21905
22191
  announce(paths) {
21906
22192
  this.mine = [...paths];
21907
22193
  const seq2 = ++this.seq;
21908
- this.channel.postMessage({ tab: this.tab, paths: this.mine, seq: seq2 });
22194
+ this.channel.postMessage({ tab: this.tab, paths: this.mine, seq: seq2, renames: true });
21909
22195
  return this.acks(seq2, this.peers);
21910
22196
  }
21911
22197
  renamingTree(rename, cap = RENAME_ACK_MAX_MS) {
@@ -24837,6 +25123,17 @@ var OpfsFs = class {
24837
25123
  }
24838
25124
  async admitted(locks, lock, from, to, place, hooks) {
24839
25125
  const remote = this.remote;
25126
+ const older = remote?.legacy() ?? [];
25127
+ if (older.length > 0) {
25128
+ this.ackBusy++;
25129
+ if (!this.warnedLegacy) {
25130
+ this.warnedLegacy = true;
25131
+ console.warn(
25132
+ `slicc-kernel: renaming ${from} to ${to} gave up (EBUSY): a tab running an older slicc-kernel shares this root and can't be waited for; reload it to rename directories (#1309)`
25133
+ );
25134
+ }
25135
+ throw fsError("EBUSY", from);
25136
+ }
24840
25137
  if (remote && !this.shared() && !await remote.joinedAll(RENAME_ACK_MAX_MS)) {
24841
25138
  this.ackBusy++;
24842
25139
  console.warn(
@@ -24887,6 +25184,7 @@ var OpfsFs = class {
24887
25184
  await run2;
24888
25185
  }
24889
25186
  renameAcks = 0;
25187
+ warnedLegacy = false;
24890
25188
  ackBusy = 0;
24891
25189
  ackMs = [];
24892
25190
  ownLocks = /* @__PURE__ */ new Set();