facebook / metro

🚇 The JavaScript bundler for React Native
https://metrobundler.dev
MIT License
5.24k stars 626 forks source link

Fix handling of paths that leave and re-enter the project root via symlinks #1280

Closed robhogan closed 5 months ago

robhogan commented 5 months ago

Summary:

Background

The internal implementation of TreeFS uses a tree of maps representing file path segments, with a "root" node at the project root. For paths outside the project root, we traverse through '..' nodes, so that ../outside traverses from the project root through '..' and 'outside'. Basing the representation around the project root (as opposed to a volume root) minimises traversal through irrelevant paths and makes the cache portable.

Problem

However, because this map of maps is a simple (acyclic) tree, a '..' node has no entry for one of its logical (=on disk) children - the node closer to the project root. With a project root /foo/bar, the project-root-relative path ../bar cannot be traversed, because '..' is a key of 'bar' and not vice-versa.

This mostly isn't a problem because '../bar' is not a normal path - normalisation collapses this down to '': https://github.com/facebook/metro/blob/6856d00cfdddc1dd5ed9ab35249fe7ca1610ca75/packages/metro-file-map/src/lib/RootPathUtils.js#L142-L148

Observable bug

For lookups, if instead of a literal indirection we have a symlink 'link-to-parent/bar', normalisation cannot (and should not) collapse away the symlink - so after dereferencing the symlink during traversal to '..' and joining it with the remaining bar we are unable to lookup '../bar'. For the module resolver this might appear as a failed existence check, and cause a resolution failure.

This fix

When dereferencing a symlink as part of _lookupByNormalPath, we now join the symlink target to the remaining subpath using a (mostly pre-exisitng) utility function that is aware of the project root, and can collapse away the project root segments. This leaves a normalised, root-relative target path that's guaranteed not to leave and re-enter the project root.

Changelog:

- **[Fix]**: Fix some paths being unresolvable when traversing a symlink that points to an ancestor of the project root.

Reviewed By: huntie

Differential Revision: D57719224

facebook-github-bot commented 5 months ago

This pull request was exported from Phabricator. Differential Revision: D57719224

facebook-github-bot commented 5 months ago

This pull request has been merged in facebook/metro@65fd0223b3541413984a652eee43cf82d98a6f44.