@componentor/fs 3.0.22 → 3.0.23

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.
@@ -653,6 +653,16 @@ var VFSEngine = class {
653
653
  }
654
654
  /** Resolve symlinks in intermediate path components */
655
655
  resolvePathComponents(path, followLast = true, depth = 0) {
656
+ const result = this.resolvePathFull(path, followLast, depth);
657
+ return result?.idx;
658
+ }
659
+ /**
660
+ * Resolve a path following symlinks, returning both the inode index AND the
661
+ * fully resolved path. This is needed by readdir: when listing a symlinked
662
+ * directory, we must search for children under the resolved target path
663
+ * (where files actually exist in pathIndex), not under the symlink path.
664
+ */
665
+ resolvePathFull(path, followLast = true, depth = 0) {
656
666
  if (depth > MAX_SYMLINK_DEPTH) return void 0;
657
667
  const parts = path.split("/").filter(Boolean);
658
668
  let current = "/";
@@ -666,14 +676,16 @@ var VFSEngine = class {
666
676
  const target = decoder.decode(this.readData(inode.firstBlock, inode.blockCount, inode.size));
667
677
  const resolved = target.startsWith("/") ? target : this.resolveRelative(current, target);
668
678
  if (isLast) {
669
- return this.resolvePathComponents(resolved, true, depth + 1);
679
+ return this.resolvePathFull(resolved, true, depth + 1);
670
680
  }
671
681
  const remaining = parts.slice(i + 1).join("/");
672
682
  const newPath = resolved + (remaining ? "/" + remaining : "");
673
- return this.resolvePathComponents(newPath, followLast, depth + 1);
683
+ return this.resolvePathFull(newPath, followLast, depth + 1);
674
684
  }
675
685
  }
676
- return this.pathIndex.get(current);
686
+ const finalIdx = this.pathIndex.get(current);
687
+ if (finalIdx === void 0) return void 0;
688
+ return { idx: finalIdx, resolvedPath: current };
677
689
  }
678
690
  resolveRelative(from, target) {
679
691
  const dir = from.substring(0, from.lastIndexOf("/")) || "/";
@@ -872,10 +884,10 @@ var VFSEngine = class {
872
884
  if (idx === void 0) return { status: CODE_TO_STATUS.ENOENT, data: null };
873
885
  return this.encodeStatResponse(idx);
874
886
  }
875
- // ---- LSTAT (no symlink follow) ----
887
+ // ---- LSTAT (no symlink follow for the FINAL component) ----
876
888
  lstat(path) {
877
889
  path = this.normalizePath(path);
878
- const idx = this.pathIndex.get(path);
890
+ const idx = this.resolvePathComponents(path, false);
879
891
  if (idx === void 0) return { status: CODE_TO_STATUS.ENOENT, data: null };
880
892
  return this.encodeStatResponse(idx);
881
893
  }
@@ -962,12 +974,12 @@ var VFSEngine = class {
962
974
  // ---- READDIR ----
963
975
  readdir(path, flags = 0) {
964
976
  path = this.normalizePath(path);
965
- const idx = this.resolvePathComponents(path, true);
966
- if (idx === void 0) return { status: CODE_TO_STATUS.ENOENT, data: null };
967
- const inode = this.readInode(idx);
977
+ const resolved = this.resolvePathFull(path, true);
978
+ if (!resolved) return { status: CODE_TO_STATUS.ENOENT, data: null };
979
+ const inode = this.readInode(resolved.idx);
968
980
  if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR, data: null };
969
981
  const withFileTypes = (flags & 1) !== 0;
970
- const children = this.getDirectChildren(path);
982
+ const children = this.getDirectChildren(resolved.resolvedPath);
971
983
  if (withFileTypes) {
972
984
  let totalSize2 = 4;
973
985
  const entries = [];