@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.
package/dist/index.js CHANGED
@@ -2699,6 +2699,16 @@ var VFSEngine = class {
2699
2699
  }
2700
2700
  /** Resolve symlinks in intermediate path components */
2701
2701
  resolvePathComponents(path, followLast = true, depth = 0) {
2702
+ const result = this.resolvePathFull(path, followLast, depth);
2703
+ return result?.idx;
2704
+ }
2705
+ /**
2706
+ * Resolve a path following symlinks, returning both the inode index AND the
2707
+ * fully resolved path. This is needed by readdir: when listing a symlinked
2708
+ * directory, we must search for children under the resolved target path
2709
+ * (where files actually exist in pathIndex), not under the symlink path.
2710
+ */
2711
+ resolvePathFull(path, followLast = true, depth = 0) {
2702
2712
  if (depth > MAX_SYMLINK_DEPTH) return void 0;
2703
2713
  const parts = path.split("/").filter(Boolean);
2704
2714
  let current = "/";
@@ -2712,14 +2722,16 @@ var VFSEngine = class {
2712
2722
  const target = decoder8.decode(this.readData(inode.firstBlock, inode.blockCount, inode.size));
2713
2723
  const resolved = target.startsWith("/") ? target : this.resolveRelative(current, target);
2714
2724
  if (isLast) {
2715
- return this.resolvePathComponents(resolved, true, depth + 1);
2725
+ return this.resolvePathFull(resolved, true, depth + 1);
2716
2726
  }
2717
2727
  const remaining = parts.slice(i + 1).join("/");
2718
2728
  const newPath = resolved + (remaining ? "/" + remaining : "");
2719
- return this.resolvePathComponents(newPath, followLast, depth + 1);
2729
+ return this.resolvePathFull(newPath, followLast, depth + 1);
2720
2730
  }
2721
2731
  }
2722
- return this.pathIndex.get(current);
2732
+ const finalIdx = this.pathIndex.get(current);
2733
+ if (finalIdx === void 0) return void 0;
2734
+ return { idx: finalIdx, resolvedPath: current };
2723
2735
  }
2724
2736
  resolveRelative(from, target) {
2725
2737
  const dir = from.substring(0, from.lastIndexOf("/")) || "/";
@@ -2918,10 +2930,10 @@ var VFSEngine = class {
2918
2930
  if (idx === void 0) return { status: CODE_TO_STATUS.ENOENT, data: null };
2919
2931
  return this.encodeStatResponse(idx);
2920
2932
  }
2921
- // ---- LSTAT (no symlink follow) ----
2933
+ // ---- LSTAT (no symlink follow for the FINAL component) ----
2922
2934
  lstat(path) {
2923
2935
  path = this.normalizePath(path);
2924
- const idx = this.pathIndex.get(path);
2936
+ const idx = this.resolvePathComponents(path, false);
2925
2937
  if (idx === void 0) return { status: CODE_TO_STATUS.ENOENT, data: null };
2926
2938
  return this.encodeStatResponse(idx);
2927
2939
  }
@@ -3008,12 +3020,12 @@ var VFSEngine = class {
3008
3020
  // ---- READDIR ----
3009
3021
  readdir(path, flags = 0) {
3010
3022
  path = this.normalizePath(path);
3011
- const idx = this.resolvePathComponents(path, true);
3012
- if (idx === void 0) return { status: CODE_TO_STATUS.ENOENT, data: null };
3013
- const inode = this.readInode(idx);
3023
+ const resolved = this.resolvePathFull(path, true);
3024
+ if (!resolved) return { status: CODE_TO_STATUS.ENOENT, data: null };
3025
+ const inode = this.readInode(resolved.idx);
3014
3026
  if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR, data: null };
3015
3027
  const withFileTypes = (flags & 1) !== 0;
3016
- const children = this.getDirectChildren(path);
3028
+ const children = this.getDirectChildren(resolved.resolvedPath);
3017
3029
  if (withFileTypes) {
3018
3030
  let totalSize2 = 4;
3019
3031
  const entries = [];