@ai-ecoverse/slicc-jsh 0.3.4 → 0.3.6

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/jsh.mjs CHANGED
@@ -1536,56 +1536,10 @@ ${e3}`;
1536
1536
  }
1537
1537
  });
1538
1538
 
1539
- // src/runtime/exit.mjs
1540
- var NodeExitError = class extends Error {
1541
- constructor(code) {
1542
- super(`Process exited with code ${code}`);
1543
- this.name = "NodeExitError";
1544
- this.code = code;
1545
- }
1546
- };
1547
- function numericExitCode(value) {
1548
- const n = Number(value);
1549
- return Number.isFinite(n) ? n & 255 : 0;
1550
- }
1551
- function describeReceived(value) {
1552
- if (typeof value === "string") return `type string ('${value}')`;
1553
- if (typeof value === "boolean") return `type boolean (${value})`;
1554
- if (typeof value === "bigint") return `type bigint (${value}n)`;
1555
- if (Array.isArray(value)) return "an instance of Array";
1556
- if (typeof value === "object" && value !== null) return "an instance of Object";
1557
- return `type ${typeof value}`;
1558
- }
1559
- function assignProcessExitCode(value) {
1560
- if (value === null || value === void 0) return void 0;
1561
- if (typeof value === "string") {
1562
- const n = Number(value);
1563
- if (value !== "" && Number.isInteger(n)) return n === 0 ? 0 : n;
1564
- const err2 = new TypeError(
1565
- `The "code" argument must be of type number. Received ${describeReceived(value)}`
1566
- );
1567
- err2.code = "ERR_INVALID_ARG_TYPE";
1568
- throw err2;
1569
- }
1570
- if (typeof value === "number") {
1571
- if (Number.isInteger(value)) return value === 0 ? 0 : value;
1572
- const err2 = new RangeError(
1573
- `The value of "code" is out of range. It must be an integer. Received ${String(value)}`
1574
- );
1575
- err2.code = "ERR_OUT_OF_RANGE";
1576
- throw err2;
1577
- }
1578
- const err = new TypeError(
1579
- `The "code" argument must be of type number. Received ${describeReceived(value)}`
1580
- );
1581
- err.code = "ERR_INVALID_ARG_TYPE";
1582
- throw err;
1583
- }
1584
-
1585
1539
  // package.json
1586
1540
  var package_default = {
1587
1541
  name: "@ai-ecoverse/slicc-jsh",
1588
- version: "0.3.4",
1542
+ version: "0.3.6",
1589
1543
  description: "Node.js-compatible runtime for slicc-kernel: the node and jsh commands (abi: js)",
1590
1544
  type: "module",
1591
1545
  license: "Apache-2.0",
@@ -1655,7 +1609,7 @@ var package_default = {
1655
1609
  "trust:dry": "npx fledgling sync --dry-run -y --skip-publish"
1656
1610
  },
1657
1611
  devDependencies: {
1658
- "@ai-ecoverse/slicc-kernel": "1.61.0",
1612
+ "@ai-ecoverse/slicc-kernel": "1.63.0",
1659
1613
  "@ai-ecoverse/wasi-pnpm": "12.9.1-8",
1660
1614
  "abort-controller": "3.0.0",
1661
1615
  acorn: "8.19.0",
@@ -2318,16 +2272,12 @@ async function runJsh({ filename, engine, process: process2, console: console2 }
2318
2272
  const baseRequire = engine.createRequire(filename);
2319
2273
  const requireSliccy = createSliccyResolver({ engine, process: process2, require: baseRequire });
2320
2274
  const require2 = wrapRequire(baseRequire, requireSliccy, module);
2321
- try {
2275
+ const body = (async () => {
2322
2276
  const fn = engine.compile(prepareSource(source), filename);
2323
2277
  await fn(process2, console2, require2, module, module.exports, engine.fetch, dirname2, filename);
2324
2278
  module.loaded = true;
2325
- } catch (err) {
2326
- if (engine.isExit(err)) return engine.exit(err.code);
2327
- engine.writeStderr(`${err?.stack ?? err}
2328
- `);
2329
- return engine.exit(1);
2330
- }
2279
+ })();
2280
+ engine.started?.(body);
2331
2281
  return void 0;
2332
2282
  }
2333
2283
 
@@ -2365,7 +2315,7 @@ async function writeAll(stream, data2) {
2365
2315
  } catch {
2366
2316
  }
2367
2317
  }
2368
- function kernelSpawn(ctx, process2) {
2318
+ function kernelSpawn(ctx, process2, track) {
2369
2319
  return (argv, { stdin } = {}) => {
2370
2320
  let child = null;
2371
2321
  const done = (async () => {
@@ -2396,7 +2346,7 @@ function kernelSpawn(ctx, process2) {
2396
2346
  })();
2397
2347
  return {
2398
2348
  kill: async (sig = "SIGTERM") => child ? child.kill(sig) : false,
2399
- done
2349
+ done: track(done)
2400
2350
  };
2401
2351
  };
2402
2352
  }
@@ -2420,7 +2370,7 @@ async function runKernelJsh(ctx, rt, filename) {
2420
2370
  const { process: process2, console: console2 } = rt;
2421
2371
  let stdoutIsTTY = false;
2422
2372
  try {
2423
- stdoutIsTTY = !!await ctx.isatty?.(1);
2373
+ stdoutIsTTY = !!await rt.track(Promise.resolve(ctx.isatty?.(1)));
2424
2374
  } catch {
2425
2375
  stdoutIsTTY = false;
2426
2376
  }
@@ -2432,11 +2382,11 @@ async function runKernelJsh(ctx, rt, filename) {
2432
2382
  writeStdout: (s) => process2.stdout.write(String(s)),
2433
2383
  writeStderr: (s) => process2.stderr.write(String(s)),
2434
2384
  stdoutIsTTY,
2435
- spawn: kernelSpawn(ctx, process2),
2385
+ spawn: kernelSpawn(ctx, process2, rt.track),
2436
2386
  shell: ["sh", "-c"],
2437
2387
  fetch: rt.fetch,
2438
- isExit: (err) => err instanceof NodeExitError,
2439
- exit: (code) => process2.exit(code)
2388
+ exit: (code) => process2.exit(code),
2389
+ started: (body) => rt.setEntry(body, "jsh")
2440
2390
  };
2441
2391
  await runJsh({ filename, engine, process: process2, console: console2 });
2442
2392
  }
@@ -2517,7 +2467,14 @@ async function checkpoint(nextTick) {
2517
2467
  if (idle >= 6) break;
2518
2468
  }
2519
2469
  }
2520
- async function drainLoop(handles, nextTick, { onBeforeExit, shouldStop } = {}) {
2470
+ var nativeSetTimeout = globalThis.setTimeout.bind(globalThis);
2471
+ var ENTRY_GRACE_TURNS = 8;
2472
+ function macrotask() {
2473
+ return new Promise((resolve2) => {
2474
+ nativeSetTimeout(resolve2, 0);
2475
+ });
2476
+ }
2477
+ async function drainLoop(handles, nextTick, { onBeforeExit, shouldStop, weakPending } = {}) {
2521
2478
  for (; ; ) {
2522
2479
  await checkpoint(nextTick);
2523
2480
  if (shouldStop?.()) return;
@@ -2527,6 +2484,15 @@ async function drainLoop(handles, nextTick, { onBeforeExit, shouldStop } = {}) {
2527
2484
  await checkpoint(nextTick);
2528
2485
  continue;
2529
2486
  }
2487
+ if (weakPending?.()) {
2488
+ for (let i2 = 0; i2 < ENTRY_GRACE_TURNS; i2++) {
2489
+ await macrotask();
2490
+ await checkpoint(nextTick);
2491
+ if (shouldStop?.() || handles.refCount > 0 || !weakPending()) break;
2492
+ }
2493
+ if (shouldStop?.()) return;
2494
+ if (handles.refCount > 0 || !weakPending()) continue;
2495
+ }
2530
2496
  if (onBeforeExit) {
2531
2497
  onBeforeExit();
2532
2498
  await checkpoint(nextTick);
@@ -11318,8 +11284,10 @@ var ERRNO = {
11318
11284
  EACCES: -13,
11319
11285
  EINVAL: -22,
11320
11286
  EIO: -5,
11321
- ENOTEMPTY: -66,
11322
- EBADF: -9
11287
+ ENOTEMPTY: -39,
11288
+ // Linux (the shim's process.platform)
11289
+ EBADF: -9,
11290
+ ENOTSUP: -45
11323
11291
  };
11324
11292
  var DESCRIPTIONS = {
11325
11293
  ENOENT: "no such file or directory",
@@ -11331,7 +11299,8 @@ var DESCRIPTIONS = {
11331
11299
  EINVAL: "invalid argument",
11332
11300
  EIO: "i/o error",
11333
11301
  ENOTEMPTY: "directory not empty",
11334
- EBADF: "bad file descriptor"
11302
+ EBADF: "bad file descriptor",
11303
+ ENOTSUP: "operation not supported"
11335
11304
  };
11336
11305
  function nodeFsError(code, syscall, pathArg, err, dest) {
11337
11306
  const c = typeof code === "string" ? code : err?.code || "EIO";
@@ -11352,37 +11321,90 @@ function nodeFsError(code, syscall, pathArg, err, dest) {
11352
11321
  if (dest !== void 0) e.dest = dest;
11353
11322
  return e;
11354
11323
  }
11324
+ var FS_READ_STREAM = /* @__PURE__ */ Symbol("fs.ReadStream");
11325
+ var FS_WRITE_STREAM = /* @__PURE__ */ Symbol("fs.WriteStream");
11326
+ function cpInvalid(message) {
11327
+ const e = new Error(message);
11328
+ e.code = "ERR_FS_CP_EINVAL";
11329
+ return e;
11330
+ }
11331
+ function rmIsDirectoryError(pathArg) {
11332
+ const e = new Error(`Path is a directory: rm returned EISDIR (is a directory) ${pathArg}`);
11333
+ e.name = "SystemError";
11334
+ e.code = "ERR_FS_EISDIR";
11335
+ e.errno = 21;
11336
+ e.syscall = "rm";
11337
+ e.path = String(pathArg);
11338
+ e.info = { code: "EISDIR", message: "is a directory", path: String(pathArg), syscall: "rm", errno: 21 };
11339
+ return e;
11340
+ }
11355
11341
  function toBytes(data2) {
11356
11342
  if (typeof data2 === "string") return encoder3.encode(data2);
11357
11343
  if (data2 instanceof Uint8Array) return data2;
11358
11344
  if (ArrayBuffer.isView(data2)) return new Uint8Array(data2.buffer, data2.byteOffset, data2.byteLength);
11359
11345
  return encoder3.encode(String(data2));
11360
11346
  }
11347
+ var S_IFMT = 61440;
11348
+ var S_IFREG = 32768;
11349
+ var S_IFDIR = 16384;
11350
+ var S_IFLNK = 40960;
11351
+ var Stats = class {
11352
+ isFile() {
11353
+ return (this.mode & S_IFMT) === S_IFREG;
11354
+ }
11355
+ isDirectory() {
11356
+ return (this.mode & S_IFMT) === S_IFDIR;
11357
+ }
11358
+ isSymbolicLink() {
11359
+ return (this.mode & S_IFMT) === S_IFLNK;
11360
+ }
11361
+ isBlockDevice() {
11362
+ return false;
11363
+ }
11364
+ isCharacterDevice() {
11365
+ return false;
11366
+ }
11367
+ isFIFO() {
11368
+ return false;
11369
+ }
11370
+ isSocket() {
11371
+ return false;
11372
+ }
11373
+ };
11361
11374
  function statView(st) {
11362
11375
  const mtimeMs = st.mtimeMs ?? (st.mtime ? Number(st.mtime) : 0);
11363
11376
  const atimeMs = st.atimeMs ?? mtimeMs;
11364
11377
  const ctimeMs = st.ctimeMs ?? mtimeMs;
11365
- return {
11366
- isFile: () => !!st.isFile,
11367
- isDirectory: () => !!st.isDirectory,
11368
- isSymbolicLink: () => !!st.isSymbolicLink,
11369
- size: st.size ?? 0,
11370
- mode: st.mode,
11371
- mtimeMs,
11378
+ const type = st.isDirectory ? S_IFDIR : st.isSymbolicLink ? S_IFLNK : S_IFREG;
11379
+ const perm = typeof st.mode === "number" ? st.mode & ~S_IFMT : st.isDirectory ? 493 : 420;
11380
+ const size = st.size ?? 0;
11381
+ return Object.assign(new Stats(), {
11382
+ dev: st.dev ?? 0,
11383
+ mode: type | perm,
11384
+ nlink: st.nlink ?? 1,
11385
+ uid: st.uid ?? 0,
11386
+ gid: st.gid ?? 0,
11387
+ rdev: 0,
11388
+ blksize: 4096,
11389
+ ino: st.ino ?? 0,
11390
+ size,
11391
+ blocks: Math.ceil(size / 512),
11372
11392
  atimeMs,
11393
+ mtimeMs,
11373
11394
  ctimeMs,
11374
- mtime: new Date(mtimeMs),
11395
+ birthtimeMs: ctimeMs,
11375
11396
  atime: new Date(atimeMs),
11397
+ mtime: new Date(mtimeMs),
11376
11398
  ctime: new Date(ctimeMs),
11377
- birthtime: new Date(ctimeMs),
11378
- ino: st.ino,
11379
- dev: st.dev
11380
- };
11399
+ birthtime: new Date(ctimeMs)
11400
+ });
11381
11401
  }
11382
11402
  var Dirent = class {
11383
- constructor(name, type) {
11403
+ constructor(name, type, parentPath) {
11384
11404
  this.name = name;
11385
- this._type = type;
11405
+ this.parentPath = parentPath;
11406
+ this.path = parentPath;
11407
+ Object.defineProperty(this, "_type", { value: type, enumerable: false });
11386
11408
  }
11387
11409
  isFile() {
11388
11410
  return this._type === "file";
@@ -11414,6 +11436,20 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11414
11436
  const syncFs = ctx.sync.fs;
11415
11437
  const asyncFs = ctx.fs;
11416
11438
  const wrapBuffer = (bytes) => Buffer2 ? Buffer2.from(bytes) : bytes;
11439
+ const optEncoding = (options) => typeof options === "string" ? options : options?.encoding ?? null;
11440
+ const optFlag = (options, fallback) => options && typeof options === "object" && options.flag || fallback;
11441
+ const decodeAs = (bytes, encoding) => {
11442
+ if (!encoding || encoding === "buffer") return wrapBuffer(bytes);
11443
+ if (encoding === "utf8" || encoding === "utf-8") return decoder3.decode(bytes);
11444
+ return Buffer2 ? Buffer2.from(bytes).toString(encoding) : decoder3.decode(bytes);
11445
+ };
11446
+ const encodeAs = (data2, encoding) => {
11447
+ if (typeof data2 === "string" && encoding && encoding !== "utf8" && encoding !== "utf-8" && Buffer2) {
11448
+ const b = Buffer2.from(data2, encoding);
11449
+ return new Uint8Array(b.buffer, b.byteOffset, b.byteLength);
11450
+ }
11451
+ return toBytes(data2);
11452
+ };
11417
11453
  const track = (p) => handles ? trackPromise(handles, p) : p;
11418
11454
  const fdTable = /* @__PURE__ */ new Map();
11419
11455
  let nextFd = 3;
@@ -11539,12 +11575,10 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11539
11575
  function readStdinSync(encoding) {
11540
11576
  try {
11541
11577
  if (typeof process2?._readStdinSync === "function") {
11542
- const out = process2._readStdinSync();
11543
- return encoding ? decoder3.decode(out) : wrapBuffer(out);
11578
+ return decodeAs(process2._readStdinSync(), encoding);
11544
11579
  }
11545
11580
  if (typeof process2?.stdin?._readAllSync === "function") {
11546
- const out = process2.stdin._readAllSync();
11547
- return encoding ? decoder3.decode(out) : wrapBuffer(out);
11581
+ return decodeAs(process2.stdin._readAllSync(), encoding);
11548
11582
  }
11549
11583
  if (typeof ctx.sync?.read === "function") {
11550
11584
  const chunks = [];
@@ -11561,11 +11595,11 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11561
11595
  out.set(c, at2);
11562
11596
  at2 += c.length;
11563
11597
  }
11564
- return encoding ? decoder3.decode(out) : wrapBuffer(out);
11598
+ return decodeAs(out, encoding);
11565
11599
  }
11566
11600
  } catch {
11567
11601
  }
11568
- return encoding ? "" : wrapBuffer(new Uint8Array(0));
11602
+ return decodeAs(new Uint8Array(0), encoding);
11569
11603
  }
11570
11604
  function mkdirSync(p, options = {}) {
11571
11605
  const pathArg = p;
@@ -11582,42 +11616,105 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11582
11616
  }
11583
11617
  const parts = String(target).split("/").filter(Boolean);
11584
11618
  let cur = "";
11619
+ let first;
11585
11620
  for (const part of parts) {
11586
11621
  cur += `/${part}`;
11587
- if (syncFs.exists(cur)) continue;
11622
+ if (syncFs.exists(cur)) {
11623
+ let st;
11624
+ try {
11625
+ st = syncFs.stat(cur);
11626
+ } catch {
11627
+ st = null;
11628
+ }
11629
+ if (st && !st.isDirectory) throw nodeFsError("ENOTDIR", "mkdir", pathArg);
11630
+ continue;
11631
+ }
11588
11632
  try {
11589
11633
  syncFs.mkdir(cur);
11634
+ first ??= path.isAbsolute(String(p)) ? cur : path.relative(process2.cwd(), cur);
11590
11635
  } catch (err) {
11591
11636
  if (err?.code === "EEXIST") continue;
11592
11637
  throw nodeFsError(err?.code || "EIO", "mkdir", pathArg, err);
11593
11638
  }
11594
11639
  }
11640
+ return first;
11641
+ }
11642
+ const typeAt = (full) => {
11643
+ try {
11644
+ const st = syncFs.lstat(full);
11645
+ return st.isDirectory ? "dir" : st.isSymbolicLink ? "link" : st.isFile ? "file" : "unknown";
11646
+ } catch {
11647
+ return "unknown";
11648
+ }
11649
+ };
11650
+ function mustExist(p, syscall) {
11651
+ let ok = false;
11652
+ try {
11653
+ ok = syncFs.exists(abs(p));
11654
+ } catch {
11655
+ ok = false;
11656
+ }
11657
+ if (!ok) throw nodeFsError("ENOENT", syscall, p);
11595
11658
  }
11596
11659
  function readdirSync(p, options) {
11597
11660
  const pathArg = p;
11598
11661
  const target = abs(p);
11662
+ const encoding = optEncoding(options);
11663
+ const asName = (name) => encoding === "buffer" ? wrapBuffer(encoder3.encode(name)) : name;
11664
+ let names;
11599
11665
  try {
11600
- const names = syncFs.readdir(target);
11666
+ names = syncFs.readdir(target);
11667
+ } catch (err) {
11668
+ throw nodeFsError(err?.code || "ENOENT", "scandir", pathArg, err);
11669
+ }
11670
+ if (!options?.recursive) {
11601
11671
  if (options?.withFileTypes) {
11602
- return names.map((name) => {
11603
- let type = "unknown";
11672
+ return names.map((name) => new Dirent(name, typeAt(path.join(target, name)), String(pathArg)));
11673
+ }
11674
+ return names.map(asName);
11675
+ }
11676
+ const out = [];
11677
+ const queue = [{ dir: target, rel: "", parent: String(pathArg), names }];
11678
+ while (queue.length) {
11679
+ const { dir, rel, parent, names: entries } = queue.shift();
11680
+ for (const name of entries) {
11681
+ const full = path.join(dir, name);
11682
+ const type = typeAt(full);
11683
+ out.push(options.withFileTypes ? new Dirent(name, type, parent) : asName(rel ? `${rel}/${name}` : name));
11684
+ if (type === "dir") {
11685
+ let children;
11604
11686
  try {
11605
- const st = syncFs.lstat(path.join(target, name));
11606
- type = st.isDirectory ? "dir" : st.isSymbolicLink ? "link" : st.isFile ? "file" : "unknown";
11687
+ children = syncFs.readdir(full);
11607
11688
  } catch {
11689
+ children = [];
11608
11690
  }
11609
- return new Dirent(name, type);
11610
- });
11691
+ queue.push({
11692
+ dir: full,
11693
+ rel: rel ? `${rel}/${name}` : name,
11694
+ parent: path.join(parent, name),
11695
+ names: children
11696
+ });
11697
+ }
11611
11698
  }
11612
- return names;
11613
- } catch (err) {
11614
- throw nodeFsError(err?.code || "ENOENT", "scandir", pathArg, err);
11615
11699
  }
11700
+ return out;
11616
11701
  }
11617
11702
  const syncApi = {
11618
11703
  readFileSync(p, options) {
11619
- const encoding = typeof options === "string" ? options : options?.encoding;
11704
+ const encoding = optEncoding(options);
11620
11705
  if (p === 0 || p === "0") return readStdinSync(encoding);
11706
+ if (typeof p === "number") {
11707
+ const ent = fdTable.get(p);
11708
+ if (!ent || !ent.readable) throw nodeFsError("EBADF", "read", void 0);
11709
+ try {
11710
+ const bytes = syncFs.readFile(ent.path);
11711
+ const rest = bytes.subarray(Math.min(ent.pos, bytes.length));
11712
+ ent.pos += rest.length;
11713
+ return decodeAs(rest, encoding);
11714
+ } catch (err) {
11715
+ throw nodeFsError(err?.code || "EIO", "read", void 0, err);
11716
+ }
11717
+ }
11621
11718
  const pathArg = p;
11622
11719
  if (pathArg === "/dev/stdin" || pathArg === "/dev/fd/0") {
11623
11720
  return readStdinSync(encoding);
@@ -11632,32 +11729,52 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11632
11729
  e.syscall = "read";
11633
11730
  throw e;
11634
11731
  }
11635
- const bytes = syncFs.readFile(target);
11636
- if (encoding) return decoder3.decode(bytes);
11637
- return wrapBuffer(bytes);
11732
+ return decodeAs(syncFs.readFile(target), encoding);
11638
11733
  } catch (err) {
11639
11734
  if (err?.code && err.syscall) throw err;
11640
11735
  throw nodeFsError(err?.code || "ENOENT", "open", pathArg, err);
11641
11736
  }
11642
11737
  },
11643
11738
  writeFileSync(p, data2, options) {
11739
+ const bytes = encodeAs(data2, optEncoding(options));
11740
+ const flag = optFlag(options, "w");
11741
+ if (typeof p === "number") {
11742
+ syncApi.writeSync(p, bytes);
11743
+ return;
11744
+ }
11745
+ if (flag.includes("a")) {
11746
+ syncApi.appendFileSync(p, bytes);
11747
+ return;
11748
+ }
11644
11749
  const pathArg = p;
11645
11750
  const target = abs(p);
11646
- void options;
11751
+ if (flag.includes("x") && syncFs.exists(target)) throw nodeFsError("EEXIST", "open", pathArg);
11647
11752
  try {
11648
- syncFs.writeFile(target, toBytes(data2));
11753
+ syncFs.writeFile(target, bytes);
11649
11754
  } catch (err) {
11650
11755
  throw nodeFsError(err?.code || "EIO", "open", pathArg, err);
11651
11756
  }
11652
11757
  },
11653
11758
  appendFileSync(p, data2, options) {
11759
+ const next = encodeAs(data2, optEncoding(options));
11760
+ if (typeof p === "number") {
11761
+ const ent = fdTable.get(p);
11762
+ let end = null;
11763
+ if (ent) {
11764
+ try {
11765
+ end = syncFs.stat(ent.path).size ?? 0;
11766
+ } catch {
11767
+ end = 0;
11768
+ }
11769
+ }
11770
+ syncApi.writeSync(p, next, 0, next.length, end);
11771
+ return;
11772
+ }
11654
11773
  const pathArg = p;
11655
11774
  const target = abs(p);
11656
- void options;
11657
11775
  try {
11658
11776
  let prev = new Uint8Array(0);
11659
11777
  if (syncFs.exists(target)) prev = syncFs.readFile(target);
11660
- const next = toBytes(data2);
11661
11778
  const merged = new Uint8Array(prev.length + next.length);
11662
11779
  merged.set(prev);
11663
11780
  merged.set(next, prev.length);
@@ -11684,20 +11801,24 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11684
11801
  throw nodeFsError(err?.code || "ENOENT", "access", pathArg, err);
11685
11802
  }
11686
11803
  },
11687
- statSync(p) {
11804
+ statSync(p, options) {
11688
11805
  const pathArg = p;
11689
11806
  try {
11690
11807
  return statView(syncFs.stat(abs(p)));
11691
11808
  } catch (err) {
11692
- throw nodeFsError(err?.code || "ENOENT", "stat", pathArg, err);
11809
+ const code = err?.code || "ENOENT";
11810
+ if (options?.throwIfNoEntry === false && (code === "ENOENT" || code === "ENOTDIR")) return void 0;
11811
+ throw nodeFsError(code, "stat", pathArg, err);
11693
11812
  }
11694
11813
  },
11695
- lstatSync(p) {
11814
+ lstatSync(p, options) {
11696
11815
  const pathArg = p;
11697
11816
  try {
11698
11817
  return statView(syncFs.lstat(abs(p)));
11699
11818
  } catch (err) {
11700
- throw nodeFsError(err?.code || "ENOENT", "lstat", pathArg, err);
11819
+ const code = err?.code || "ENOENT";
11820
+ if (options?.throwIfNoEntry === false && (code === "ENOENT" || code === "ENOTDIR")) return void 0;
11821
+ throw nodeFsError(code, "lstat", pathArg, err);
11701
11822
  }
11702
11823
  },
11703
11824
  /**
@@ -11717,37 +11838,57 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11717
11838
  },
11718
11839
  readdirSync,
11719
11840
  mkdirSync,
11841
+ // The kernel's rm is recursive: only ever hand it an empty directory.
11720
11842
  rmdirSync(p, options = {}) {
11721
11843
  const pathArg = p;
11722
11844
  const target = abs(p);
11845
+ let st;
11723
11846
  try {
11724
- if (options.recursive) {
11725
- syncApi.rmSync(p, { recursive: true, force: options.force });
11726
- return;
11727
- }
11728
- syncFs.rm(target);
11847
+ st = syncFs.lstat(target);
11729
11848
  } catch (err) {
11730
11849
  throw nodeFsError(err?.code || "ENOENT", "rmdir", pathArg, err);
11731
11850
  }
11851
+ if (!st.isDirectory) throw nodeFsError("ENOTDIR", "rmdir", pathArg);
11852
+ if (options?.recursive) {
11853
+ syncApi.rmSync(p, { recursive: true, force: options.force });
11854
+ return;
11855
+ }
11856
+ let entries;
11857
+ try {
11858
+ entries = syncFs.readdir(target);
11859
+ } catch (err) {
11860
+ throw nodeFsError(err?.code || "EIO", "rmdir", pathArg, err);
11861
+ }
11862
+ if (entries.length > 0) throw nodeFsError("ENOTEMPTY", "rmdir", pathArg);
11863
+ try {
11864
+ syncFs.rm(target);
11865
+ } catch (err) {
11866
+ throw nodeFsError(err?.code || "EIO", "rmdir", pathArg, err);
11867
+ }
11732
11868
  },
11733
11869
  rmSync(p, options = {}) {
11734
11870
  const pathArg = p;
11735
11871
  const target = abs(p);
11872
+ let st;
11873
+ try {
11874
+ st = syncFs.lstat(target);
11875
+ } catch (err) {
11876
+ if (options?.force && (err?.code === "ENOENT" || err?.code === "ENOTDIR")) return;
11877
+ throw nodeFsError(err?.code || "ENOENT", "lstat", pathArg, err);
11878
+ }
11879
+ if (st.isDirectory && !options?.recursive) throw rmIsDirectoryError(pathArg);
11736
11880
  try {
11737
- const st = syncFs.lstat(target);
11738
11881
  if (st.isDirectory) {
11739
- if (options.recursive) {
11740
- for (const name of syncFs.readdir(target)) {
11741
- syncApi.rmSync(path.join(target, name), { recursive: true, force: options.force });
11742
- }
11882
+ for (const name of syncFs.readdir(target)) {
11883
+ syncApi.rmSync(path.join(target, name), { recursive: true, force: options.force });
11743
11884
  }
11744
11885
  syncFs.rm(target);
11745
11886
  } else {
11746
11887
  syncFs.unlink(target);
11747
11888
  }
11748
11889
  } catch (err) {
11749
- if (options.force && (err?.code === "ENOENT" || !syncFs.exists(target))) return;
11750
- throw nodeFsError(err?.code || "ENOENT", "rm", pathArg, err);
11890
+ if (err?.syscall) throw err;
11891
+ throw nodeFsError(err?.code || "EIO", "rm", pathArg, err);
11751
11892
  }
11752
11893
  },
11753
11894
  unlinkSync(p) {
@@ -11822,7 +11963,7 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11822
11963
  return n;
11823
11964
  }
11824
11965
  const ent = fdTable.get(fd);
11825
- if (!ent) throw nodeFsError("EBADF", "read", void 0);
11966
+ if (!ent || !ent.readable) throw nodeFsError("EBADF", "read", void 0);
11826
11967
  try {
11827
11968
  const bytes = syncFs.readFile(ent.path);
11828
11969
  const pos = filePosition == null ? ent.pos : filePosition;
@@ -11841,7 +11982,7 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11841
11982
  return bytes2.byteLength;
11842
11983
  }
11843
11984
  const ent = fdTable.get(fd);
11844
- if (!ent) throw nodeFsError("EBADF", "write", void 0);
11985
+ if (!ent || !ent.writable) throw nodeFsError("EBADF", "write", void 0);
11845
11986
  const { bytes, filePosition } = parseWriteSyncArgs(data2, offset2, length, position);
11846
11987
  try {
11847
11988
  return writeBytesAtPath(ent, bytes, filePosition);
@@ -11893,8 +12034,176 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11893
12034
  } catch (err) {
11894
12035
  throw nodeFsError(err?.code || "ENOENT", "readlink", p, err);
11895
12036
  }
12037
+ },
12038
+ copyFileSync(src, dest, mode = 0) {
12039
+ const from = abs(src);
12040
+ const to = abs(dest);
12041
+ let st;
12042
+ try {
12043
+ st = syncFs.stat(from);
12044
+ } catch (err) {
12045
+ throw nodeFsError(err?.code || "ENOENT", "copyfile", src, err, dest);
12046
+ }
12047
+ if (st.isDirectory) throw nodeFsError("EISDIR", "copyfile", src, void 0, dest);
12048
+ if (mode & 1 && syncFs.exists(to)) throw nodeFsError("EEXIST", "copyfile", src, void 0, dest);
12049
+ try {
12050
+ syncFs.writeFile(to, syncFs.readFile(from));
12051
+ } catch (err) {
12052
+ throw nodeFsError(err?.code || "EIO", "copyfile", src, err, dest);
12053
+ }
12054
+ },
12055
+ cpSync(src, dest, options = {}) {
12056
+ const from = abs(src);
12057
+ const to = abs(dest);
12058
+ if (from === to) throw cpInvalid(`src and dest cannot be the same ${src}`);
12059
+ if (to.startsWith(`${from}/`)) {
12060
+ throw cpInvalid(`Cannot copy ${src}/ to a subdirectory of self ${dest}`);
12061
+ }
12062
+ let st;
12063
+ try {
12064
+ st = syncFs.stat(from);
12065
+ } catch (err) {
12066
+ throw nodeFsError(err?.code || "ENOENT", "cp", src, err);
12067
+ }
12068
+ if (st.isDirectory) {
12069
+ if (!options?.recursive) {
12070
+ const e = new Error(`Recursive option not enabled, cannot copy a directory: ${src}/`);
12071
+ e.code = "ERR_FS_EISDIR";
12072
+ throw e;
12073
+ }
12074
+ mkdirSync(to, { recursive: true });
12075
+ for (const name of syncFs.readdir(from)) {
12076
+ syncApi.cpSync(path.join(from, name), path.join(to, name), options);
12077
+ }
12078
+ return;
12079
+ }
12080
+ const exists = syncFs.exists(to);
12081
+ if (exists && options?.errorOnExist && options?.force === false) {
12082
+ const e = new Error(`Target already exists: cp returned EEXIST (${to} already exists)`);
12083
+ e.name = "SystemError";
12084
+ e.code = "ERR_FS_CP_EEXIST";
12085
+ throw e;
12086
+ }
12087
+ if (exists && options?.force === false) return;
12088
+ syncFs.writeFile(to, syncFs.readFile(from));
12089
+ },
12090
+ mkdtempSync(prefix, options) {
12091
+ const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
12092
+ const bytes = new Uint8Array(6);
12093
+ for (let attempt = 0; attempt < 100; attempt++) {
12094
+ crypto.getRandomValues(bytes);
12095
+ const name = `${prefix}${[...bytes].map((b) => chars[b % chars.length]).join("")}`;
12096
+ const target = abs(name);
12097
+ if (syncFs.exists(target)) continue;
12098
+ try {
12099
+ syncFs.mkdir(target);
12100
+ } catch (err) {
12101
+ throw nodeFsError(err?.code || "ENOENT", "mkdtemp", `${prefix}XXXXXX`, err);
12102
+ }
12103
+ return optEncoding(options) === "buffer" ? wrapBuffer(encoder3.encode(name)) : name;
12104
+ }
12105
+ throw nodeFsError("EEXIST", "mkdtemp", `${prefix}XXXXXX`);
12106
+ },
12107
+ truncateSync(p, len = 0) {
12108
+ if (typeof p === "number") {
12109
+ syncApi.ftruncateSync(p, len);
12110
+ return;
12111
+ }
12112
+ const target = abs(p);
12113
+ let cur;
12114
+ try {
12115
+ cur = syncFs.readFile(target);
12116
+ } catch (err) {
12117
+ throw nodeFsError(err?.code || "ENOENT", "open", p, err);
12118
+ }
12119
+ const out = new Uint8Array(Math.max(0, len));
12120
+ out.set(cur.subarray(0, Math.min(cur.length, out.length)), 0);
12121
+ syncFs.writeFile(target, out);
12122
+ },
12123
+ // The kernel's JS fs has no mode bits, owners or times to set: these
12124
+ // check that the path exists, as Node's do, and change nothing.
12125
+ chmodSync(p) {
12126
+ mustExist(p, "chmod");
12127
+ },
12128
+ lchmodSync(p) {
12129
+ mustExist(p, "lchmod");
12130
+ },
12131
+ fchmodSync(fd) {
12132
+ syncApi.fstatSync(fd);
12133
+ },
12134
+ chownSync(p) {
12135
+ mustExist(p, "chown");
12136
+ },
12137
+ lchownSync(p) {
12138
+ mustExist(p, "lchown");
12139
+ },
12140
+ fchownSync(fd) {
12141
+ syncApi.fstatSync(fd);
12142
+ },
12143
+ utimesSync(p) {
12144
+ mustExist(p, "utime");
12145
+ },
12146
+ lutimesSync(p) {
12147
+ mustExist(p, "lutime");
12148
+ },
12149
+ futimesSync(fd) {
12150
+ syncApi.fstatSync(fd);
12151
+ },
12152
+ fsyncSync(fd) {
12153
+ if (fd !== 0 && fd !== 1 && fd !== 2 && !fdTable.has(fd)) throw nodeFsError("EBADF", "fsync", void 0);
12154
+ },
12155
+ fdatasyncSync(fd) {
12156
+ if (fd !== 0 && fd !== 1 && fd !== 2 && !fdTable.has(fd)) throw nodeFsError("EBADF", "fdatasync", void 0);
12157
+ },
12158
+ opendirSync(p) {
12159
+ const entries = readdirSync(p, { withFileTypes: true });
12160
+ return createDir(String(p), entries);
11896
12161
  }
11897
12162
  };
12163
+ function createDir(dirPath, entries) {
12164
+ let closed = false;
12165
+ const next = () => {
12166
+ if (closed) {
12167
+ const e = new Error("Directory handle was closed");
12168
+ e.code = "ERR_DIR_CLOSED";
12169
+ throw e;
12170
+ }
12171
+ return entries.length ? entries.shift() : null;
12172
+ };
12173
+ return {
12174
+ path: dirPath,
12175
+ readSync: next,
12176
+ read(cb) {
12177
+ if (typeof cb === "function") {
12178
+ queueMicrotask(() => {
12179
+ try {
12180
+ cb(null, next());
12181
+ } catch (err) {
12182
+ cb(err);
12183
+ }
12184
+ });
12185
+ return void 0;
12186
+ }
12187
+ return Promise.resolve().then(next);
12188
+ },
12189
+ closeSync() {
12190
+ closed = true;
12191
+ },
12192
+ close(cb) {
12193
+ closed = true;
12194
+ if (typeof cb === "function") queueMicrotask(() => cb(null));
12195
+ else return Promise.resolve();
12196
+ return void 0;
12197
+ },
12198
+ async *[Symbol.asyncIterator]() {
12199
+ try {
12200
+ for (let d = next(); d; d = next()) yield d;
12201
+ } finally {
12202
+ closed = true;
12203
+ }
12204
+ }
12205
+ };
12206
+ }
11898
12207
  function requireCallback(cb) {
11899
12208
  if (typeof cb === "function") return cb;
11900
12209
  let received;
@@ -11936,11 +12245,9 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11936
12245
  readFile(p, options) {
11937
12246
  return track(
11938
12247
  (async () => {
11939
- const encoding = typeof options === "string" ? options : options?.encoding;
12248
+ const encoding = optEncoding(options);
11940
12249
  try {
11941
- const bytes = await asyncFs.readFile(abs(p));
11942
- if (encoding) return decoder3.decode(bytes);
11943
- return wrapBuffer(bytes);
12250
+ return decodeAs(await asyncFs.readFile(abs(p)), encoding);
11944
12251
  } catch (err) {
11945
12252
  throw nodeFsError(err?.code || "ENOENT", "open", p, err);
11946
12253
  }
@@ -11950,23 +12257,27 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11950
12257
  writeFile(p, data2, options) {
11951
12258
  return track(
11952
12259
  (async () => {
11953
- void options;
12260
+ const bytes = encodeAs(data2, optEncoding(options));
12261
+ const flag = optFlag(options, "w");
12262
+ if (flag.includes("a")) return promises.appendFile(p, bytes);
12263
+ const target = abs(p);
12264
+ if (flag.includes("x") && await asyncFs.exists(target)) throw nodeFsError("EEXIST", "open", p);
11954
12265
  try {
11955
- await asyncFs.writeFile(abs(p), toBytes(data2));
12266
+ await asyncFs.writeFile(target, bytes);
11956
12267
  } catch (err) {
11957
12268
  throw nodeFsError(err?.code || "EIO", "open", p, err);
11958
12269
  }
12270
+ return void 0;
11959
12271
  })()
11960
12272
  );
11961
12273
  },
11962
12274
  appendFile(p, data2, options) {
11963
12275
  return track(
11964
12276
  (async () => {
11965
- void options;
11966
12277
  const target = abs(p);
11967
12278
  let prev = new Uint8Array(0);
11968
12279
  if (await asyncFs.exists(target)) prev = await asyncFs.readFile(target);
11969
- const next = toBytes(data2);
12280
+ const next = encodeAs(data2, optEncoding(options));
11970
12281
  const merged = new Uint8Array(prev.length + next.length);
11971
12282
  merged.set(prev);
11972
12283
  merged.set(next, prev.length);
@@ -11997,75 +12308,52 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
11997
12308
  );
11998
12309
  },
11999
12310
  readdir(p, options) {
12000
- return track(
12001
- (async () => {
12002
- try {
12003
- const names = await asyncFs.readdir(abs(p));
12004
- if (options?.withFileTypes) {
12005
- const out = [];
12006
- for (const name of names) {
12007
- let type = "unknown";
12008
- try {
12009
- const st = await asyncFs.lstat(path.join(abs(p), name));
12010
- type = st.isDirectory ? "dir" : st.isSymbolicLink ? "link" : st.isFile ? "file" : "unknown";
12011
- } catch {
12012
- }
12013
- out.push(new Dirent(name, type));
12014
- }
12015
- return out;
12016
- }
12017
- return names;
12018
- } catch (err) {
12019
- throw nodeFsError(err?.code || "ENOENT", "scandir", p, err);
12020
- }
12021
- })()
12022
- );
12311
+ return track((async () => readdirSync(p, options))());
12023
12312
  },
12024
12313
  mkdir(p, options = {}) {
12025
- return track(
12026
- (async () => {
12027
- const target = abs(p);
12028
- if (options?.recursive) {
12029
- const parts = String(target).split("/").filter(Boolean);
12030
- let cur = "";
12031
- for (const part of parts) {
12032
- cur += `/${part}`;
12033
- if (await asyncFs.exists(cur)) continue;
12034
- try {
12035
- await asyncFs.mkdir(cur);
12036
- } catch (err) {
12037
- if (err?.code !== "EEXIST") throw nodeFsError(err?.code || "EIO", "mkdir", p, err);
12038
- }
12039
- }
12040
- return;
12041
- }
12042
- if (await asyncFs.exists(target)) throw nodeFsError("EEXIST", "mkdir", p);
12043
- await asyncFs.mkdir(target);
12044
- })()
12045
- );
12314
+ return track((async () => mkdirSync(p, options))());
12046
12315
  },
12047
12316
  rm(p, options = {}) {
12048
- return track(
12049
- (async () => {
12050
- const target = abs(p);
12051
- try {
12052
- const st = await asyncFs.lstat(target);
12053
- if (st.isDirectory) {
12054
- if (options.recursive) {
12055
- for (const name of await asyncFs.readdir(target)) {
12056
- await promises.rm(path.join(target, name), { recursive: true, force: options.force });
12057
- }
12058
- }
12059
- await asyncFs.rm(target);
12060
- } else {
12061
- await asyncFs.unlink(target);
12062
- }
12063
- } catch (err) {
12064
- if (options.force && err?.code === "ENOENT") return;
12065
- throw nodeFsError(err?.code || "ENOENT", "rm", p, err);
12066
- }
12067
- })()
12068
- );
12317
+ return track((async () => syncApi.rmSync(p, options))());
12318
+ },
12319
+ rmdir(p, options = {}) {
12320
+ return track((async () => syncApi.rmdirSync(p, options))());
12321
+ },
12322
+ copyFile(src, dest, mode) {
12323
+ return track((async () => syncApi.copyFileSync(src, dest, mode))());
12324
+ },
12325
+ cp(src, dest, options) {
12326
+ return track((async () => syncApi.cpSync(src, dest, options))());
12327
+ },
12328
+ mkdtemp(prefix, options) {
12329
+ return track((async () => syncApi.mkdtempSync(prefix, options))());
12330
+ },
12331
+ truncate(p, len) {
12332
+ return track((async () => syncApi.truncateSync(p, len))());
12333
+ },
12334
+ realpath(p) {
12335
+ return track((async () => syncApi.realpathSync(p))());
12336
+ },
12337
+ chmod(p) {
12338
+ return track((async () => syncApi.chmodSync(p))());
12339
+ },
12340
+ lchmod(p) {
12341
+ return track((async () => syncApi.lchmodSync(p))());
12342
+ },
12343
+ chown(p) {
12344
+ return track((async () => syncApi.chownSync(p))());
12345
+ },
12346
+ lchown(p) {
12347
+ return track((async () => syncApi.lchownSync(p))());
12348
+ },
12349
+ utimes(p) {
12350
+ return track((async () => syncApi.utimesSync(p))());
12351
+ },
12352
+ lutimes(p) {
12353
+ return track((async () => syncApi.lutimesSync(p))());
12354
+ },
12355
+ opendir(p) {
12356
+ return track((async () => syncApi.opendirSync(p))());
12069
12357
  },
12070
12358
  unlink(p) {
12071
12359
  return track(
@@ -12154,10 +12442,32 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
12154
12442
  ensureOpen("truncate");
12155
12443
  syncApi.ftruncateSync(fd, len);
12156
12444
  },
12445
+ async readFile(options) {
12446
+ ensureOpen("readFile");
12447
+ return syncApi.readFileSync(fd, options);
12448
+ },
12449
+ async sync() {
12450
+ ensureOpen("fsync");
12451
+ },
12452
+ async datasync() {
12453
+ ensureOpen("fdatasync");
12454
+ },
12455
+ async chmod() {
12456
+ ensureOpen("fchmod");
12457
+ },
12458
+ async chown() {
12459
+ ensureOpen("fchown");
12460
+ },
12461
+ async utimes() {
12462
+ ensureOpen("futimes");
12463
+ },
12157
12464
  async close() {
12158
12465
  ensureOpen("close");
12159
12466
  closed = true;
12160
12467
  syncApi.closeSync(fd);
12468
+ },
12469
+ async [Symbol.asyncDispose ?? /* @__PURE__ */ Symbol.for("nodejs.asyncDispose")]() {
12470
+ if (!closed) await handle.close();
12161
12471
  }
12162
12472
  };
12163
12473
  return handle;
@@ -12219,6 +12529,7 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
12219
12529
  });
12220
12530
  r.path = p;
12221
12531
  r.bytesRead = 0;
12532
+ Object.defineProperty(r, FS_READ_STREAM, { value: true });
12222
12533
  if (!openEmitted) {
12223
12534
  queueMicrotask(() => {
12224
12535
  if (openEmitted || r.destroyed) return;
@@ -12282,6 +12593,7 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
12282
12593
  });
12283
12594
  w.path = p;
12284
12595
  w.bytesWritten = 0;
12596
+ Object.defineProperty(w, FS_WRITE_STREAM, { value: true });
12285
12597
  if (!openEmitted) {
12286
12598
  queueMicrotask(() => {
12287
12599
  if (openEmitted || w.destroyed) return;
@@ -12304,10 +12616,20 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
12304
12616
  }
12305
12617
  return w;
12306
12618
  }
12619
+ function ReadStream(p, options) {
12620
+ return createReadStream(p, options);
12621
+ }
12622
+ Object.defineProperty(ReadStream, Symbol.hasInstance, { value: (x) => !!x?.[FS_READ_STREAM] });
12623
+ function WriteStream(p, options) {
12624
+ return createWriteStream(p, options);
12625
+ }
12626
+ Object.defineProperty(WriteStream, Symbol.hasInstance, { value: (x) => !!x?.[FS_WRITE_STREAM] });
12307
12627
  return {
12308
12628
  ...syncApi,
12309
12629
  promises,
12310
12630
  Dirent,
12631
+ ReadStream,
12632
+ WriteStream,
12311
12633
  createReadStream,
12312
12634
  createWriteStream,
12313
12635
  readFile: callbackify(syncApi.readFileSync),
@@ -12355,10 +12677,55 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
12355
12677
  lstat: callbackify(syncApi.lstatSync),
12356
12678
  realpath: callbackify(syncApi.realpathSync),
12357
12679
  readdir: callbackify(syncApi.readdirSync),
12358
- mkdir: callbackify(syncApi.mkdirSync),
12680
+ mkdir: callbackify(syncApi.mkdirSync, { minArgsBeforeCb: 2 }),
12359
12681
  rmdir: callbackify(syncApi.rmdirSync),
12360
12682
  unlink: callbackify(syncApi.unlinkSync),
12361
12683
  rename: callbackify(syncApi.renameSync, { minArgsBeforeCb: 2 }),
12684
+ // Node 22's rm does not check its callback up front: without one it does
12685
+ // the work, then calls the missing callback and throws from there.
12686
+ rm(p, options, callback) {
12687
+ const cb = typeof options === "function" ? options : callback;
12688
+ const opts = typeof options === "function" ? void 0 : options;
12689
+ if (typeof cb === "function") return callbackify(syncApi.rmSync)(p, opts ?? {}, cb);
12690
+ let err = null;
12691
+ try {
12692
+ syncApi.rmSync(p, opts ?? {});
12693
+ } catch (e) {
12694
+ err = e;
12695
+ }
12696
+ void err;
12697
+ setTimeout(() => {
12698
+ const e = new TypeError("callback is not a function");
12699
+ e._fsPretty = `node:fs:1225
12700
+ return callback(err);
12701
+ ^
12702
+
12703
+ ${e.stack}
12704
+ `;
12705
+ throw e;
12706
+ }, 0);
12707
+ return void 0;
12708
+ },
12709
+ copyFile: callbackify(syncApi.copyFileSync, { minArgsBeforeCb: 2 }),
12710
+ cp: callbackify(syncApi.cpSync, { minArgsBeforeCb: 2 }),
12711
+ mkdtemp: callbackify(syncApi.mkdtempSync),
12712
+ truncate: callbackify(syncApi.truncateSync),
12713
+ ftruncate: callbackify(syncApi.ftruncateSync),
12714
+ chmod: callbackify(syncApi.chmodSync, { minArgsBeforeCb: 2 }),
12715
+ lchmod: callbackify(syncApi.lchmodSync, { minArgsBeforeCb: 2 }),
12716
+ fchmod: callbackify(syncApi.fchmodSync, { minArgsBeforeCb: 2 }),
12717
+ chown: callbackify(syncApi.chownSync, { minArgsBeforeCb: 3 }),
12718
+ lchown: callbackify(syncApi.lchownSync, { minArgsBeforeCb: 3 }),
12719
+ fchown: callbackify(syncApi.fchownSync, { minArgsBeforeCb: 3 }),
12720
+ utimes: callbackify(syncApi.utimesSync, { minArgsBeforeCb: 3 }),
12721
+ lutimes: callbackify(syncApi.lutimesSync, { minArgsBeforeCb: 3 }),
12722
+ futimes: callbackify(syncApi.futimesSync, { minArgsBeforeCb: 3 }),
12723
+ fsync: callbackify(syncApi.fsyncSync),
12724
+ fdatasync: callbackify(syncApi.fdatasyncSync),
12725
+ opendir: callbackify(syncApi.opendirSync),
12726
+ symlink: callbackify(syncApi.symlinkSync, { minArgsBeforeCb: 2 }),
12727
+ readlink: callbackify(syncApi.readlinkSync),
12728
+ Stats,
12362
12729
  constants: {
12363
12730
  F_OK: 0,
12364
12731
  R_OK: 4,
@@ -12369,7 +12736,15 @@ function createFs({ ctx, path, process: process2, Buffer: Buffer2, handles, getS
12369
12736
  O_RDWR: 2,
12370
12737
  O_CREAT: 64,
12371
12738
  O_TRUNC: 512,
12372
- O_APPEND: 1024
12739
+ O_APPEND: 1024,
12740
+ O_EXCL: 128,
12741
+ S_IFMT,
12742
+ S_IFREG,
12743
+ S_IFDIR,
12744
+ S_IFLNK,
12745
+ COPYFILE_EXCL: 1,
12746
+ COPYFILE_FICLONE: 2,
12747
+ COPYFILE_FICLONE_FORCE: 4
12373
12748
  }
12374
12749
  };
12375
12750
  }
@@ -15618,20 +15993,12 @@ ${parts.join("\n")}`
15618
15993
  return cjs.runMain(filename, src);
15619
15994
  }
15620
15995
  const { hasTopLevelAwait } = transformEsm(src, filename);
15621
- if (hasTopLevelAwait) {
15622
- const p = evaluateEsmAsync(filename, src);
15623
- if (trackPromise2 && handles) trackPromise2(handles, p);
15624
- return p;
15625
- }
15996
+ if (hasTopLevelAwait) return evaluateEsmAsync(filename, src);
15626
15997
  return evaluateEsm(filename, src);
15627
15998
  }
15628
15999
  function runEsmEval(code, filename = "[eval]") {
15629
16000
  const { hasTopLevelAwait } = transformEsm(code, filename);
15630
- if (hasTopLevelAwait) {
15631
- const p = evaluateEsmAsync(filename, code);
15632
- if (trackPromise2 && handles) trackPromise2(handles, p);
15633
- return p;
15634
- }
16001
+ if (hasTopLevelAwait) return evaluateEsmAsync(filename, code);
15635
16002
  return evaluateEsm(filename, code);
15636
16003
  }
15637
16004
  function requireEsm(filename) {
@@ -15848,7 +16215,7 @@ function frameLocation(stack) {
15848
16215
  const file = m[1] === void 0 || m[0].includes("[eval]") ? "[eval]" : m[1];
15849
16216
  return { file, line: Number(m[2]), column: Number(m[3]) };
15850
16217
  }
15851
- function snippetFor(ctx, loc, evalCode) {
16218
+ function snippetFor(ctx, loc, evalCode, fromPromise = false) {
15852
16219
  if (!loc) return null;
15853
16220
  let source;
15854
16221
  if (loc.file === "[eval]") source = evalCode;
@@ -15868,7 +16235,9 @@ function snippetFor(ctx, loc, evalCode) {
15868
16235
  let col2 = loc.column;
15869
16236
  const throwAt = text.search(/\bthrow\b/);
15870
16237
  const isAsyncLine = /\basync\b/.test(text);
15871
- if (loc.file === "[eval]" && throwAt === 0) {
16238
+ if (fromPromise && loc.column >= 1) {
16239
+ col2 = loc.column;
16240
+ } else if (loc.file === "[eval]" && throwAt === 0) {
15872
16241
  col2 = 1;
15873
16242
  } else if (throwAt >= 0 && isAsyncLine && /\bthrow\s+new\b/.test(text)) {
15874
16243
  col2 = text.indexOf("new", throwAt) + 1;
@@ -15931,7 +16300,7 @@ function glueStackAndProps(stack, props) {
15931
16300
  if (!props) return frames;
15932
16301
  return `${frames} ${finalizeProps(props)}`;
15933
16302
  }
15934
- function formatUncaughtError(err, { ctx, util: util2, version: version2, evalCode } = {}) {
16303
+ function formatUncaughtError(err, { ctx, util: util2, version: version2, evalCode, fromPromise } = {}) {
15935
16304
  const trailer = `
15936
16305
  Node.js v${version2}
15937
16306
  `;
@@ -16005,7 +16374,7 @@ ${trailer}` };
16005
16374
  }
16006
16375
  }
16007
16376
  const loc = frameLocation(rawStack);
16008
- const snip = snippetFor(ctx, loc, evalCode);
16377
+ const snip = snippetFor(ctx, loc, evalCode, fromPromise);
16009
16378
  if (snip) head = `${snip.file}:${snip.lineNo}
16010
16379
  ${snip.text}
16011
16380
  ${snip.caret}
@@ -16102,7 +16471,7 @@ function collapseMatchingCauseFrames(body, err) {
16102
16471
  }
16103
16472
  function formatUnhandledRejection(reason, { ctx, util: util2, version: version2, evalCode } = {}) {
16104
16473
  if (reason instanceof Error) {
16105
- return formatUncaughtError(reason, { ctx, util: util2, version: version2, evalCode });
16474
+ return formatUncaughtError(reason, { ctx, util: util2, version: version2, evalCode, fromPromise: true });
16106
16475
  }
16107
16476
  const trailer = `
16108
16477
  Node.js v${version2}
@@ -16114,13 +16483,84 @@ Node.js v${version2}
16114
16483
  new UnhandledPromiseRejection(reason);
16115
16484
  ^
16116
16485
 
16117
- UnhandledPromiseRejection: ${msg} {
16486
+ UnhandledPromiseRejection: ${msg}
16487
+ at throwUnhandledRejectionsMode (node:internal/process/promises:392:7)
16488
+ at processPromiseRejections (node:internal/process/promises:475:17)
16489
+ at process.processTicksAndRejections (node:internal/process/task_queues:106:32) {
16118
16490
  code: 'ERR_UNHANDLED_REJECTION'
16119
16491
  }
16120
16492
  `;
16121
16493
  return { body: body + trailer };
16122
16494
  }
16123
16495
 
16496
+ // src/runtime/exit.mjs
16497
+ var NodeExitError = class extends Error {
16498
+ constructor(code) {
16499
+ super(`Process exited with code ${code}`);
16500
+ this.name = "NodeExitError";
16501
+ this.code = code;
16502
+ this.status = code;
16503
+ }
16504
+ };
16505
+ function isExitError2(err) {
16506
+ return err instanceof NodeExitError || err?.name === "NodeExitError" || err?.name === "JsExit";
16507
+ }
16508
+ function hardExitError(ctx, code) {
16509
+ if (typeof ctx?.exit === "function") {
16510
+ try {
16511
+ ctx.exit(code);
16512
+ } catch (err) {
16513
+ if (err && typeof err === "object" && err.name === "JsExit") {
16514
+ try {
16515
+ Object.defineProperty(err, "name", { value: "NodeExitError", configurable: true, writable: true });
16516
+ err.message = `Process exited with code ${code}`;
16517
+ err.code = code;
16518
+ } catch {
16519
+ }
16520
+ return err;
16521
+ }
16522
+ }
16523
+ }
16524
+ return new NodeExitError(code);
16525
+ }
16526
+ function numericExitCode(value) {
16527
+ const n = Number(value);
16528
+ return Number.isFinite(n) ? n & 255 : 0;
16529
+ }
16530
+ function describeReceived(value) {
16531
+ if (typeof value === "string") return `type string ('${value}')`;
16532
+ if (typeof value === "boolean") return `type boolean (${value})`;
16533
+ if (typeof value === "bigint") return `type bigint (${value}n)`;
16534
+ if (Array.isArray(value)) return "an instance of Array";
16535
+ if (typeof value === "object" && value !== null) return "an instance of Object";
16536
+ return `type ${typeof value}`;
16537
+ }
16538
+ function assignProcessExitCode(value) {
16539
+ if (value === null || value === void 0) return void 0;
16540
+ if (typeof value === "string") {
16541
+ const n = Number(value);
16542
+ if (value !== "" && Number.isInteger(n)) return n === 0 ? 0 : n;
16543
+ const err2 = new TypeError(
16544
+ `The "code" argument must be of type number. Received ${describeReceived(value)}`
16545
+ );
16546
+ err2.code = "ERR_INVALID_ARG_TYPE";
16547
+ throw err2;
16548
+ }
16549
+ if (typeof value === "number") {
16550
+ if (Number.isInteger(value)) return value === 0 ? 0 : value;
16551
+ const err2 = new RangeError(
16552
+ `The value of "code" is out of range. It must be an integer. Received ${String(value)}`
16553
+ );
16554
+ err2.code = "ERR_OUT_OF_RANGE";
16555
+ throw err2;
16556
+ }
16557
+ const err = new TypeError(
16558
+ `The "code" argument must be of type number. Received ${describeReceived(value)}`
16559
+ );
16560
+ err.code = "ERR_INVALID_ARG_TYPE";
16561
+ throw err;
16562
+ }
16563
+
16124
16564
  // src/runtime/handles.mjs
16125
16565
  function createHandleTable() {
16126
16566
  const refed = /* @__PURE__ */ new Set();
@@ -16156,6 +16596,7 @@ function createHandleTable() {
16156
16596
  // src/runtime/next-tick.mjs
16157
16597
  function createNextTick() {
16158
16598
  const queue = [];
16599
+ let stopped = false;
16159
16600
  return {
16160
16601
  nextTick(fn, ...args) {
16161
16602
  if (typeof fn !== "function") {
@@ -16171,7 +16612,12 @@ function createNextTick() {
16171
16612
  err.code = "ERR_INVALID_ARG_TYPE";
16172
16613
  throw err;
16173
16614
  }
16174
- queue.push(() => fn(...args));
16615
+ if (!stopped) queue.push(() => fn(...args));
16616
+ },
16617
+ /** process.exit(): drop what is queued and ignore new ticks. */
16618
+ stop() {
16619
+ stopped = true;
16620
+ queue.length = 0;
16175
16621
  },
16176
16622
  /** Run queued ticks synchronously. */
16177
16623
  flushSync() {
@@ -16513,8 +16959,12 @@ var Process = class extends EventEmitter {
16513
16959
  tls: false,
16514
16960
  cached_builtins: true
16515
16961
  };
16516
- const writeStdout = (value) => ctx.sync.write(1, toBytes2(value));
16517
- const writeStderr = (value) => ctx.sync.write(2, toBytes2(value));
16962
+ const writeStdout = (value) => {
16963
+ if (!this._silenced) ctx.sync.write(1, toBytes2(value));
16964
+ };
16965
+ const writeStderr = (value) => {
16966
+ if (!this._silenced) ctx.sync.write(2, toBytes2(value));
16967
+ };
16518
16968
  this._writeStdout = writeStdout;
16519
16969
  this._writeStderr = writeStderr;
16520
16970
  this.stdout = writableStream(1, writeStdout, false);
@@ -16640,24 +17090,29 @@ var Process = class extends EventEmitter {
16640
17090
  }
16641
17091
  this._cwd = this._ctx.resolve(path);
16642
17092
  }
17093
+ /**
17094
+ * Node's process.exit: 'exit' listeners run, then the program ends. The
17095
+ * kernel is told the status at once (see hardExitError); what still runs
17096
+ * while the throw unwinds — a user `catch` or `finally` — is silenced:
17097
+ * its output is dropped, a second exit() keeps the first status, and
17098
+ * timers and ticks are stopped.
17099
+ */
16643
17100
  exit(...args) {
16644
- if (args.length === 0) {
16645
- const code2 = numericExitCode(this._assignedExitCode);
16646
- this._recordExit(code2);
16647
- try {
16648
- this.emit("exit", code2);
16649
- } catch {
16650
- }
16651
- throw new NodeExitError(code2);
16652
- }
16653
- this._assignedExitCode = assignProcessExitCode(args[0]);
17101
+ if (this._exitError) throw this._exitError;
17102
+ if (args.length > 0) this._assignedExitCode = assignProcessExitCode(args[0]);
16654
17103
  const code = numericExitCode(this._assignedExitCode);
16655
17104
  this._recordExit(code);
16656
17105
  try {
16657
17106
  this.emit("exit", code);
16658
17107
  } catch {
16659
17108
  }
16660
- throw new NodeExitError(code);
17109
+ this._silenced = true;
17110
+ try {
17111
+ this._onHardExit?.(code);
17112
+ } catch {
17113
+ }
17114
+ this._exitError = hardExitError(this._ctx, code);
17115
+ throw this._exitError;
16661
17116
  }
16662
17117
  _recordExit(code) {
16663
17118
  this._didExit = true;
@@ -16666,8 +17121,9 @@ var Process = class extends EventEmitter {
16666
17121
  this._onExit?.(code);
16667
17122
  }
16668
17123
  };
16669
- function createProcess({ ctx, argv, nextTick, onExit, handles, Buffer: Buffer2 }) {
17124
+ function createProcess({ ctx, argv, nextTick, onExit, onHardExit, handles, Buffer: Buffer2 }) {
16670
17125
  const process2 = new Process({ ctx, argv, nextTick, onExit, handles, Buffer: Buffer2 });
17126
+ process2._onHardExit = onHardExit;
16671
17127
  return {
16672
17128
  process: process2,
16673
17129
  writeStdout: process2._writeStdout,
@@ -16690,11 +17146,12 @@ function Timeout() {
16690
17146
  function Immediate() {
16691
17147
  }
16692
17148
  function createTimers(handles, { onCallbackError } = {}) {
16693
- const nativeSetTimeout = globalThis.setTimeout.bind(globalThis);
17149
+ const nativeSetTimeout2 = globalThis.setTimeout.bind(globalThis);
16694
17150
  const nativeClearTimeout = globalThis.clearTimeout.bind(globalThis);
16695
17151
  const nativeSetInterval = globalThis.setInterval.bind(globalThis);
16696
17152
  const nativeClearInterval = globalThis.clearInterval.bind(globalThis);
16697
17153
  const byId = /* @__PURE__ */ new Map();
17154
+ let stopped = false;
16698
17155
  const runMethod = (handle, method, args) => {
16699
17156
  try {
16700
17157
  handle[method](...args);
@@ -16728,6 +17185,9 @@ function createTimers(handles, { onCallbackError } = {}) {
16728
17185
  };
16729
17186
  };
16730
17187
  const makeTimeout = (fn, delay, args, repeating) => {
17188
+ if (stopped) {
17189
+ return repeating ? nativeSetInterval(fn, delay, ...args) : nativeSetTimeout2(fn, delay, ...args);
17190
+ }
16731
17191
  const state = {
16732
17192
  refed: true,
16733
17193
  id: null,
@@ -16737,18 +17197,20 @@ function createTimers(handles, { onCallbackError } = {}) {
16737
17197
  handle._onTimeout = fn;
16738
17198
  attachRefApi(handle, state);
16739
17199
  const fire = () => {
17200
+ if (stopped) return;
16740
17201
  if (!state.repeating) {
16741
17202
  byId.delete(state.id);
16742
17203
  handles.delete(state);
16743
17204
  }
16744
17205
  runMethod(handle, "_onTimeout", args);
16745
17206
  };
16746
- state.id = repeating ? nativeSetInterval(fire, delay ?? 0) : nativeSetTimeout(fire, delay ?? 0);
17207
+ state.id = repeating ? nativeSetInterval(fire, delay ?? 0) : nativeSetTimeout2(fire, delay ?? 0);
16747
17208
  byId.set(state.id, state);
16748
17209
  handles.add(state);
16749
17210
  return handle;
16750
17211
  };
16751
17212
  const makeImmediate = (fn, args) => {
17213
+ if (stopped) return nativeSetTimeout2(fn, 0, ...args);
16752
17214
  const state = {
16753
17215
  refed: true,
16754
17216
  id: null,
@@ -16758,11 +17220,12 @@ function createTimers(handles, { onCallbackError } = {}) {
16758
17220
  handle._onImmediate = fn;
16759
17221
  attachRefApi(handle, state);
16760
17222
  const fire = () => {
17223
+ if (stopped) return;
16761
17224
  byId.delete(state.id);
16762
17225
  handles.delete(state);
16763
17226
  runMethod(handle, "_onImmediate", args);
16764
17227
  };
16765
- state.id = nativeSetTimeout(fire, 0);
17228
+ state.id = nativeSetTimeout2(fire, 0);
16766
17229
  byId.set(state.id, state);
16767
17230
  handles.add(state);
16768
17231
  return handle;
@@ -16778,7 +17241,7 @@ function createTimers(handles, { onCallbackError } = {}) {
16778
17241
  };
16779
17242
  return {
16780
17243
  setTimeout: (fn, delay, ...args) => {
16781
- if (typeof fn !== "function") return nativeSetTimeout(fn, delay, ...args);
17244
+ if (typeof fn !== "function") return nativeSetTimeout2(fn, delay, ...args);
16782
17245
  return makeTimeout(fn, delay, args, false);
16783
17246
  },
16784
17247
  clearTimeout: (handle) => clear(handle, nativeClearTimeout),
@@ -16788,7 +17251,7 @@ function createTimers(handles, { onCallbackError } = {}) {
16788
17251
  },
16789
17252
  clearInterval: (handle) => clear(handle, nativeClearInterval),
16790
17253
  setImmediate: (fn, ...args) => {
16791
- if (typeof fn !== "function") return nativeSetTimeout(fn, 0, ...args);
17254
+ if (typeof fn !== "function") return nativeSetTimeout2(fn, 0, ...args);
16792
17255
  return makeImmediate(fn, args);
16793
17256
  },
16794
17257
  clearImmediate: (handle) => clear(handle, nativeClearTimeout),
@@ -16800,12 +17263,60 @@ function createTimers(handles, { onCallbackError } = {}) {
16800
17263
  }
16801
17264
  byId.clear();
16802
17265
  handles.notify();
17266
+ },
17267
+ /** The program is ending: clear its timers; later ones bypass the table. */
17268
+ stop() {
17269
+ stopped = true;
17270
+ this.clearPending();
16803
17271
  }
16804
17272
  };
16805
17273
  }
16806
17274
 
16807
17275
  // src/runtime/web/fetch.mjs
16808
- function createFetch(ctx) {
17276
+ var BODY_METHODS = ["arrayBuffer", "blob", "bytes", "formData", "json", "text"];
17277
+ function trackBody(response, track) {
17278
+ for (const name of BODY_METHODS) {
17279
+ const method = response[name];
17280
+ if (typeof method !== "function") continue;
17281
+ Object.defineProperty(response, name, {
17282
+ value: function tracked(...args) {
17283
+ return track(method.apply(response, args));
17284
+ },
17285
+ configurable: true,
17286
+ writable: true
17287
+ });
17288
+ }
17289
+ const bodyDesc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(response), "body");
17290
+ if (!bodyDesc?.get) return response;
17291
+ let wrapped;
17292
+ Object.defineProperty(response, "body", {
17293
+ configurable: true,
17294
+ get() {
17295
+ if (wrapped !== void 0) return wrapped;
17296
+ const original = bodyDesc.get.call(response);
17297
+ if (original == null || typeof ReadableStream !== "function") {
17298
+ wrapped = original;
17299
+ return wrapped;
17300
+ }
17301
+ let reader;
17302
+ wrapped = new ReadableStream({
17303
+ async pull(controller) {
17304
+ reader ??= original.getReader();
17305
+ const { value, done } = await track(reader.read());
17306
+ if (done) controller.close();
17307
+ else controller.enqueue(value);
17308
+ },
17309
+ cancel(reason) {
17310
+ return (reader ?? original).cancel(reason);
17311
+ }
17312
+ });
17313
+ return wrapped;
17314
+ }
17315
+ });
17316
+ return response;
17317
+ }
17318
+ function createFetch(ctx, { handles } = {}) {
17319
+ const track = (p) => handles ? trackPromise(handles, p) : p;
16809
17320
  async function fetch(input, init) {
16810
17321
  if (typeof ctx.fetch !== "function") {
16811
17322
  const err = new TypeError("fetch failed");
@@ -16814,7 +17325,13 @@ function createFetch(ctx) {
16814
17325
  });
16815
17326
  throw err;
16816
17327
  }
16817
- return ctx.fetch(input, init);
17328
+ const response = await track(ctx.fetch(input, init));
17329
+ if (!handles || response == null || typeof response !== "object") return response;
17330
+ try {
17331
+ return trackBody(response, track);
17332
+ } catch {
17333
+ return response;
17334
+ }
16818
17335
  }
16819
17336
  return fetch;
16820
17337
  }
@@ -17129,6 +17646,43 @@ function installJshGlobals(bindings) {
17129
17646
  }
17130
17647
  };
17131
17648
  }
17649
+ function trackPlatformAsync(handles) {
17650
+ const undo = [];
17651
+ const wrap = (target, names) => {
17652
+ if (!target) return;
17653
+ for (const name of names) {
17654
+ const original = target[name];
17655
+ if (typeof original !== "function") continue;
17656
+ try {
17657
+ target[name] = function tracked(...args) {
17658
+ return trackPromise(handles, original.apply(this, args));
17659
+ };
17660
+ undo.push(() => {
17661
+ target[name] = original;
17662
+ });
17663
+ } catch {
17664
+ }
17665
+ }
17666
+ };
17667
+ wrap(globalThis.SubtleCrypto?.prototype, [
17668
+ "decrypt",
17669
+ "deriveBits",
17670
+ "deriveKey",
17671
+ "digest",
17672
+ "encrypt",
17673
+ "exportKey",
17674
+ "generateKey",
17675
+ "importKey",
17676
+ "sign",
17677
+ "unwrapKey",
17678
+ "verify",
17679
+ "wrapKey"
17680
+ ]);
17681
+ wrap(globalThis.WebAssembly, ["compile", "compileStreaming", "instantiate", "instantiateStreaming"]);
17682
+ return () => {
17683
+ for (const fn of undo.reverse()) fn();
17684
+ };
17685
+ }
17132
17686
  async function runNode(ctx, options = {}) {
17133
17687
  installStackPrepare();
17134
17688
  const handles = createHandleTable();
@@ -17188,6 +17742,12 @@ slicc-jsh ${NODE_SHIM_VERSION} (Node-compatible, abi: js)
17188
17742
  Buffer: Buffer2,
17189
17743
  onExit: (code) => {
17190
17744
  exitStatus = code;
17745
+ },
17746
+ // process.exit(): nothing the unwinding code schedules may run.
17747
+ onHardExit: () => {
17748
+ timers.stop();
17749
+ nextTick.stop();
17750
+ handles.notify();
17191
17751
  }
17192
17752
  });
17193
17753
  process2.execArgv = parsed.execArgv ? [...parsed.execArgv] : [];
@@ -17196,12 +17756,13 @@ slicc-jsh ${NODE_SHIM_VERSION} (Node-compatible, abi: js)
17196
17756
  lastEvalCode = parsed.code;
17197
17757
  }
17198
17758
  const console2 = createConsole(writeStdout, writeStderr, util2);
17199
- const fetch = createFetch(ctx);
17759
+ const fetch = createFetch(ctx, { handles });
17760
+ const restorePlatform = trackPlatformAsync(handles);
17200
17761
  const WebSocket = createWebSocket(ctx, { handles, trackPromise });
17201
17762
  const timers = createTimers(handles, {
17202
17763
  onCallbackError: (err) => {
17203
- if (err instanceof NodeExitError) {
17204
- exitStatus = err.code;
17764
+ if (isExitError2(err) || getDidExit()) {
17765
+ exitStatus = getDidExit() ? getExitCode() : err.code;
17205
17766
  timers.clearPending();
17206
17767
  try {
17207
17768
  handles.notify();
@@ -17249,16 +17810,16 @@ slicc-jsh ${NODE_SHIM_VERSION} (Node-compatible, abi: js)
17249
17810
  } catch {
17250
17811
  }
17251
17812
  exitStatus = 1;
17252
- timers.clearPending();
17813
+ timers.stop();
17253
17814
  try {
17254
17815
  ctx.exit?.(1);
17255
17816
  } catch {
17256
17817
  }
17257
17818
  };
17258
- const isExit = (err) => err instanceof NodeExitError || err?.name === "NodeExitError" || getDidExit();
17819
+ const isExit = (err) => isExitError2(err) || getDidExit();
17259
17820
  const rejectionHandler = (reason, promise) => {
17260
17821
  if (isExit(reason)) {
17261
- exitStatus = reason instanceof NodeExitError || reason?.name === "NodeExitError" ? Number(reason.code) & 255 : getExitCode();
17822
+ exitStatus = getDidExit() ? getExitCode() : Number(reason.code) & 255;
17262
17823
  timers.clearPending();
17263
17824
  try {
17264
17825
  handles.notify();
@@ -17277,16 +17838,16 @@ slicc-jsh ${NODE_SHIM_VERSION} (Node-compatible, abi: js)
17277
17838
  evalCode: lastEvalCode
17278
17839
  });
17279
17840
  writeStderr(body);
17841
+ exitStatus = 1;
17842
+ timers.stop();
17280
17843
  try {
17281
17844
  ctx.exit?.(1);
17282
17845
  } catch {
17283
17846
  }
17284
- exitStatus = 1;
17285
- timers.clearPending();
17286
17847
  };
17287
17848
  const exceptionHandler = (err) => {
17288
17849
  if (isExit(err)) {
17289
- exitStatus = err instanceof NodeExitError || err?.name === "NodeExitError" ? Number(err.code) & 255 : getExitCode();
17850
+ exitStatus = getDidExit() ? getExitCode() : Number(err.code) & 255;
17290
17851
  timers.clearPending();
17291
17852
  try {
17292
17853
  handles.notify();
@@ -17357,8 +17918,27 @@ slicc-jsh ${NODE_SHIM_VERSION} (Node-compatible, abi: js)
17357
17918
  });
17358
17919
  cjs.setRequireEsmHook((filename) => esm.requireEsm(filename));
17359
17920
  cjs.setImportModuleHook((specifier, parent) => esm.importModule(specifier, parent));
17921
+ let entry = null;
17922
+ const setEntry = (promise, kind) => {
17923
+ const current2 = { kind, pending: true, promise };
17924
+ entry = current2;
17925
+ Promise.resolve(promise).then(
17926
+ () => {
17927
+ current2.pending = false;
17928
+ handles.notify();
17929
+ },
17930
+ (err) => {
17931
+ current2.pending = false;
17932
+ if (kind === "jsh") rejectionHandler(err, promise);
17933
+ else exceptionHandler(err);
17934
+ handles.notify();
17935
+ }
17936
+ );
17937
+ };
17360
17938
  try {
17361
17939
  const rt = {
17940
+ setEntry,
17941
+ track: (promise) => trackPromise(handles, promise),
17362
17942
  process: process2,
17363
17943
  console: console2,
17364
17944
  Buffer: Buffer2,
@@ -17378,7 +17958,7 @@ slicc-jsh ${NODE_SHIM_VERSION} (Node-compatible, abi: js)
17378
17958
  }
17379
17959
  nextTick.flushSync();
17380
17960
  } catch (err) {
17381
- if (err instanceof NodeExitError) throw err;
17961
+ if (isExitError2(err)) throw err;
17382
17962
  if (process2.listenerCount("uncaughtException") > 0) {
17383
17963
  process2.emit(
17384
17964
  "uncaughtException",
@@ -17426,7 +18006,7 @@ slicc-jsh ${NODE_SHIM_VERSION} (Node-compatible, abi: js)
17426
18006
  cjs.runMain("[stdin]", source, { setMain: false });
17427
18007
  nextTick.flushSync();
17428
18008
  } catch (err) {
17429
- if (err instanceof NodeExitError) throw err;
18009
+ if (isExitError2(err)) throw err;
17430
18010
  if (process2.listenerCount("uncaughtException") > 0) {
17431
18011
  process2.emit(
17432
18012
  "uncaughtException",
@@ -17448,10 +18028,7 @@ slicc-jsh ${NODE_SHIM_VERSION} (Node-compatible, abi: js)
17448
18028
  )` : parsed.code,
17449
18029
  "[eval]"
17450
18030
  );
17451
- if (result != null && typeof result.then === "function") {
17452
- trackPromise(handles, result);
17453
- await result;
17454
- }
18031
+ if (result != null && typeof result.then === "function") setEntry(result, "esm");
17455
18032
  nextTick.flushSync();
17456
18033
  } else {
17457
18034
  const evalParent = `${process2.cwd()}/[eval]`;
@@ -17485,7 +18062,7 @@ slicc-jsh ${NODE_SHIM_VERSION} (Node-compatible, abi: js)
17485
18062
  }
17486
18063
  }
17487
18064
  } catch (err) {
17488
- if (err instanceof NodeExitError) throw err;
18065
+ if (isExitError2(err)) throw err;
17489
18066
  if (process2.listenerCount("uncaughtException") > 0) {
17490
18067
  process2.emit(
17491
18068
  "uncaughtException",
@@ -17513,16 +18090,13 @@ slicc-jsh ${NODE_SHIM_VERSION} (Node-compatible, abi: js)
17513
18090
  const useEsm = esm.isEsmFilename(filePath, source);
17514
18091
  if (useEsm) {
17515
18092
  const result = esm.runMain(filePath, source);
17516
- if (result != null && typeof result.then === "function") {
17517
- trackPromise(handles, result);
17518
- await result;
17519
- }
18093
+ if (result != null && typeof result.then === "function") setEntry(result, "esm");
17520
18094
  } else {
17521
18095
  cjs.runMain(filePath, source);
17522
18096
  }
17523
18097
  nextTick.flushSync();
17524
18098
  } catch (err) {
17525
- if (err instanceof NodeExitError) throw err;
18099
+ if (isExitError2(err)) throw err;
17526
18100
  if (process2.listenerCount("uncaughtException") > 0) {
17527
18101
  process2.emit(
17528
18102
  "uncaughtException",
@@ -17543,8 +18117,17 @@ slicc-jsh ${NODE_SHIM_VERSION} (Node-compatible, abi: js)
17543
18117
  onBeforeExit: () => {
17544
18118
  emitBeforeExit();
17545
18119
  },
17546
- shouldStop: () => getDidExit() || exitStatus !== void 0
18120
+ shouldStop: () => getDidExit() || exitStatus !== void 0,
18121
+ weakPending: () => entry?.pending === true
17547
18122
  });
18123
+ if (entry?.pending && entry.kind === "esm" && exitStatus === void 0 && !getDidExit()) {
18124
+ const where = parsed.mode === "file" ? `file://${process2.argv[1]}` : "[eval1]";
18125
+ writeStderr(`Warning: Detected unsettled top-level await at ${where}
18126
+
18127
+
18128
+ `);
18129
+ exitStatus = 13;
18130
+ }
17548
18131
  for (let i2 = 0; i2 < 3; i2++) {
17549
18132
  if (exitStatus !== void 0 || getDidExit()) break;
17550
18133
  await new Promise((resolve2) => {
@@ -17569,9 +18152,9 @@ slicc-jsh ${NODE_SHIM_VERSION} (Node-compatible, abi: js)
17569
18152
  }
17570
18153
  return code;
17571
18154
  } catch (err) {
17572
- if (err instanceof NodeExitError) {
18155
+ if (isExitError2(err)) {
17573
18156
  timers.clearPending();
17574
- return err.code;
18157
+ return getDidExit() ? getExitCode() : err.code;
17575
18158
  }
17576
18159
  try {
17577
18160
  printUncaught(err);
@@ -17582,7 +18165,7 @@ slicc-jsh ${NODE_SHIM_VERSION} (Node-compatible, abi: js)
17582
18165
  return 1;
17583
18166
  } finally {
17584
18167
  timers.clearPending();
17585
- for (const remove of removeCtxHooks) {
18168
+ for (const remove of getDidExit() ? [] : removeCtxHooks) {
17586
18169
  try {
17587
18170
  remove?.();
17588
18171
  } catch {
@@ -17590,6 +18173,7 @@ slicc-jsh ${NODE_SHIM_VERSION} (Node-compatible, abi: js)
17590
18173
  }
17591
18174
  try {
17592
18175
  restoreGlobals();
18176
+ restorePlatform();
17593
18177
  removeJshHandoff();
17594
18178
  } catch {
17595
18179
  }