diff --git a/packages/metro-file-map/src/lib/TreeFS.js b/packages/metro-file-map/src/lib/TreeFS.js index 28971ff32..7ddfd4583 100644 --- a/packages/metro-file-map/src/lib/TreeFS.js +++ b/packages/metro-file-map/src/lib/TreeFS.js @@ -35,7 +35,11 @@ function isRegularFile(node: FileNode): boolean { return node[H.SYMLINK] === 0; } -type NormalizedSymlinkTarget = {ancestorOfRootIdx: ?number, normalPath: string}; +type NormalizedSymlinkTarget = { + ancestorOfRootIdx: ?number, + normalPath: string, + startOfBasenameIdx: number, +}; /** * OVERVIEW: @@ -667,9 +671,10 @@ export default class TreeFS implements MutableFileSystem { } // For the purpose of collecting ancestors: Ignore the traversal to - // the symlink target, and start collecting ancestors only when we - // reach the remaining part of the path. - unseenPathFromIdx = normalSymlinkTarget.normalPath.length; + // the symlink target, and start collecting ancestors only + // from the target itself (ie, the basename of the normal target path) + // onwards. + unseenPathFromIdx = normalSymlinkTarget.startOfBasenameIdx; if (seen == null) { // Optimisation: set this lazily only when we've encountered a symlink @@ -1122,6 +1127,7 @@ export default class TreeFS implements MutableFileSystem { ancestorOfRootIdx: this.#pathUtils.getAncestorOfRootIdx(normalSymlinkTarget), normalPath: normalSymlinkTarget, + startOfBasenameIdx: normalSymlinkTarget.lastIndexOf(path.sep) + 1, }; this.#cachedNormalSymlinkTargets.set(symlinkNode, result); return result; diff --git a/packages/metro-file-map/src/lib/__tests__/TreeFS-test.js b/packages/metro-file-map/src/lib/__tests__/TreeFS-test.js index 708855a95..1964a14e8 100644 --- a/packages/metro-file-map/src/lib/__tests__/TreeFS-test.js +++ b/packages/metro-file-map/src/lib/__tests__/TreeFS-test.js @@ -314,6 +314,10 @@ describe.each([['win32'], ['posix']])('TreeFS on %s', platform => { p('a/b/c/d/link-to-A'), ['', 0, 0, 0, '', '', p('../../../../../..')], ], + [ + p('n_m/workspace/link-to-pkg'), + ['', 0, 0, 0, '', '', p('../../../workspace-pkg')], + ], ].concat( [ 'a/package.json', @@ -331,6 +335,7 @@ describe.each([['win32'], ['posix']])('TreeFS on %s', platform => { 'a/n_m/pkg/n_m/pkg2/package.json', '../../package.json', '../../../a/b/package.json', + '../workspace-pkg/package.json', ].map(posixPath => [p(posixPath), ['', 0, 0, 0, '', '', 0]]), ), ), @@ -447,6 +452,12 @@ describe.each([['win32'], ['posix']])('TreeFS on %s', platform => { ['/A/B/C/a/n_m/pkg3/foo.js', null, null, ['/A/B/C/a/n_m/pkg3']], // Does not look beyond n_m, if n_m does not exist ['/A/B/C/a/b/n_m/pkg/foo', null, null, ['/A/B/C/a/b/n_m']], + [ + '/A/B/C/n_m/workspace/link-to-pkg/subpath', + '/A/B/workspace-pkg/package.json', + 'subpath', + ['/A/B/C/n_m/workspace/link-to-pkg', '/A/B/workspace-pkg/subpath'], + ], ])( '%s => %s (relative %s, invalidatedBy %s)', (