From cae3e155e5a742692a513736ead197147cc06a50 Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Sat, 7 Sep 2024 15:16:58 -0700 Subject: [PATCH 1/2] Fix symlinked packages not respecting package.json redirections (#1349) Summary: `TreeFS.hierarchicalLookup` is a recently introduced function for finding closest package.json for an input path. It works by traversing to the input path while "collecting ancestors" - i.e. all of the directory nodes on route to the input path, and then checking each of them in reverse order for package.json. This gets a bit complicated when traversal includes symlinks. For the test case in this commit: - `n_m/workspace/link-to-pkg` is a symlink to '../workspace-pkg'. - When resolving the package scope of `n_m/workspace/link-to-pkg/subpath`, we should check: - `n_m/workspace/link-to-pkg` (realpath: `../workspace-pkg`) - `n_m/workspace` (realpath: `n_m/workspace`) In particular, when traversing to `../workspace-pkg`, we should *not* collect `..` but we *should* collect `../workspace-pkg`. We attempt to do this by keeping track of an `unseenPathFromIdx`, which lets us skip ancestor collection when we're traversing from the root to the symlink target. The logic here was effectively off-by-one - we were correctly skipping segments before the symlink target, and correctly collecting segments after, but we missed the symlink target itself. By setting `unseenPathFromIdx` to the index of the start of the target's basename, we include it correctly. Fixes https://github.com/facebook/metro/issues/1347 Changelog: ``` - **[Fix]**: Fix https://github.com/facebook/metro/issues/1347, symlinked packages not respecting package.json redirections. ``` Pull Request resolved: https://github.com/facebook/metro/pull/1349 Test Plan: - New unit test - Verified e2e by patching metro-file-map in user's repro in https://github.com/facebook/metro/issues/1347 Reviewed By: cortinico Differential Revision: D62343439 Pulled By: robhogan fbshipit-source-id: a823601daeffdc8dfd5b5bc3987b75889d44588f --- packages/metro-file-map/src/lib/TreeFS.js | 14 ++++++++++---- .../src/lib/__tests__/TreeFS-test.js | 11 +++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/packages/metro-file-map/src/lib/TreeFS.js b/packages/metro-file-map/src/lib/TreeFS.js index 28971ff326..7ddfd4583d 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 708855a95e..1964a14e84 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)', ( From 5fe680e954169cc75b873f009ba7809a45b1c9cf Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Sun, 8 Sep 2024 11:09:00 +0200 Subject: [PATCH 2/2] Publish hotfix 0.80.12 --- packages/buck-worker-tool/package.json | 4 +-- packages/metro-babel-register/package.json | 2 +- packages/metro-babel-transformer/package.json | 2 +- packages/metro-cache-key/package.json | 4 +-- packages/metro-cache/package.json | 6 ++-- packages/metro-config/package.json | 12 ++++---- packages/metro-core/package.json | 4 +-- packages/metro-file-map/package.json | 2 +- packages/metro-memory-fs/package.json | 2 +- packages/metro-minify-terser/package.json | 2 +- packages/metro-resolver/package.json | 4 +-- packages/metro-runtime/package.json | 2 +- packages/metro-source-map/package.json | 6 ++-- packages/metro-symbolicate/package.json | 4 +-- packages/metro-transform-plugins/package.json | 4 +-- packages/metro-transform-worker/package.json | 18 +++++------ packages/metro/package.json | 30 +++++++++---------- packages/ob1/package.json | 2 +- 18 files changed, 55 insertions(+), 55 deletions(-) diff --git a/packages/buck-worker-tool/package.json b/packages/buck-worker-tool/package.json index 33e4396d5b..c616138d60 100644 --- a/packages/buck-worker-tool/package.json +++ b/packages/buck-worker-tool/package.json @@ -1,6 +1,6 @@ { "name": "buck-worker-tool", - "version": "0.80.11", + "version": "0.80.12", "description": "Implementation of the Buck worker protocol for Node.js.", "license": "MIT", "main": "src/worker-tool.js", @@ -12,7 +12,7 @@ "through": ">=2.2.7 <3" }, "devDependencies": { - "metro-memory-fs": "0.80.11" + "metro-memory-fs": "0.80.12" }, "scripts": { "prepare-release": "test -d build && rm -rf src.real && mv src src.real && mv build src", diff --git a/packages/metro-babel-register/package.json b/packages/metro-babel-register/package.json index 4e9d73bc75..45306333cb 100644 --- a/packages/metro-babel-register/package.json +++ b/packages/metro-babel-register/package.json @@ -1,6 +1,6 @@ { "name": "metro-babel-register", - "version": "0.80.11", + "version": "0.80.12", "description": "🚇 babel/register configuration for Metro.", "main": "src/babel-register.js", "repository": { diff --git a/packages/metro-babel-transformer/package.json b/packages/metro-babel-transformer/package.json index 39036f067a..94acc31929 100644 --- a/packages/metro-babel-transformer/package.json +++ b/packages/metro-babel-transformer/package.json @@ -1,6 +1,6 @@ { "name": "metro-babel-transformer", - "version": "0.80.11", + "version": "0.80.12", "description": "🚇 Base Babel transformer for Metro.", "main": "src/index.js", "repository": { diff --git a/packages/metro-cache-key/package.json b/packages/metro-cache-key/package.json index 7e80116809..7caae1a5b6 100644 --- a/packages/metro-cache-key/package.json +++ b/packages/metro-cache-key/package.json @@ -1,6 +1,6 @@ { "name": "metro-cache-key", - "version": "0.80.11", + "version": "0.80.12", "description": "🚇 Cache key utility.", "main": "src/index.js", "repository": { @@ -13,7 +13,7 @@ }, "license": "MIT", "devDependencies": { - "metro-memory-fs": "0.80.11" + "metro-memory-fs": "0.80.12" }, "engines": { "node": ">=18" diff --git a/packages/metro-cache/package.json b/packages/metro-cache/package.json index 3493963200..29c68152e4 100644 --- a/packages/metro-cache/package.json +++ b/packages/metro-cache/package.json @@ -1,6 +1,6 @@ { "name": "metro-cache", - "version": "0.80.11", + "version": "0.80.12", "description": "🚇 Cache layers for Metro.", "main": "src/index.js", "repository": { @@ -14,10 +14,10 @@ "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", - "metro-core": "0.80.11" + "metro-core": "0.80.12" }, "devDependencies": { - "metro-memory-fs": "0.80.11" + "metro-memory-fs": "0.80.12" }, "license": "MIT", "engines": { diff --git a/packages/metro-config/package.json b/packages/metro-config/package.json index 3ab1d172ce..5f834c6125 100644 --- a/packages/metro-config/package.json +++ b/packages/metro-config/package.json @@ -1,6 +1,6 @@ { "name": "metro-config", - "version": "0.80.11", + "version": "0.80.12", "description": "🚇 Config parser for Metro.", "main": "src/index.js", "repository": { @@ -17,14 +17,14 @@ "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.6.3", - "metro": "0.80.11", - "metro-cache": "0.80.11", - "metro-core": "0.80.11", - "metro-runtime": "0.80.11" + "metro": "0.80.12", + "metro-cache": "0.80.12", + "metro-core": "0.80.12", + "metro-runtime": "0.80.12" }, "devDependencies": { "@types/connect": "^3.4.35", - "metro-babel-register": "0.80.11", + "metro-babel-register": "0.80.12", "pretty-format": "^29.7.0", "strip-ansi": "^6.0.0" }, diff --git a/packages/metro-core/package.json b/packages/metro-core/package.json index c0848bdb73..6915edddf2 100644 --- a/packages/metro-core/package.json +++ b/packages/metro-core/package.json @@ -1,6 +1,6 @@ { "name": "metro-core", - "version": "0.80.11", + "version": "0.80.12", "description": "🚇 Metro's core package.", "main": "src/index.js", "repository": { @@ -14,7 +14,7 @@ "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", - "metro-resolver": "0.80.11" + "metro-resolver": "0.80.12" }, "license": "MIT", "engines": { diff --git a/packages/metro-file-map/package.json b/packages/metro-file-map/package.json index 4551fdb193..b5107a9358 100644 --- a/packages/metro-file-map/package.json +++ b/packages/metro-file-map/package.json @@ -1,6 +1,6 @@ { "name": "metro-file-map", - "version": "0.80.11", + "version": "0.80.12", "description": "[Experimental] - 🚇 File crawling, watching and mapping for Metro", "main": "src/index.js", "repository": { diff --git a/packages/metro-memory-fs/package.json b/packages/metro-memory-fs/package.json index a7d0f1d8cc..6c32d73a24 100644 --- a/packages/metro-memory-fs/package.json +++ b/packages/metro-memory-fs/package.json @@ -1,6 +1,6 @@ { "name": "metro-memory-fs", - "version": "0.80.11", + "version": "0.80.12", "description": "🚇 A memory-based implementation of `fs` useful for testing.", "main": "src/index.js", "repository": { diff --git a/packages/metro-minify-terser/package.json b/packages/metro-minify-terser/package.json index 8d04b5721e..d0ba4f3e32 100644 --- a/packages/metro-minify-terser/package.json +++ b/packages/metro-minify-terser/package.json @@ -1,6 +1,6 @@ { "name": "metro-minify-terser", - "version": "0.80.11", + "version": "0.80.12", "description": "🚇 Minifier for Metro based on Terser.", "main": "src/index.js", "repository": { diff --git a/packages/metro-resolver/package.json b/packages/metro-resolver/package.json index 8a0647503c..4348f33eee 100644 --- a/packages/metro-resolver/package.json +++ b/packages/metro-resolver/package.json @@ -1,6 +1,6 @@ { "name": "metro-resolver", - "version": "0.80.11", + "version": "0.80.12", "description": "🚇 Implementation of Metro's resolution logic.", "main": "src", "repository": { @@ -16,7 +16,7 @@ "node": ">=18" }, "devDependencies": { - "metro": "0.80.11" + "metro": "0.80.12" }, "dependencies": { "flow-enums-runtime": "^0.0.6" diff --git a/packages/metro-runtime/package.json b/packages/metro-runtime/package.json index 3ef065ba71..b2f69253f1 100644 --- a/packages/metro-runtime/package.json +++ b/packages/metro-runtime/package.json @@ -1,6 +1,6 @@ { "name": "metro-runtime", - "version": "0.80.11", + "version": "0.80.12", "description": "🚇 Module required for evaluating Metro bundles.", "main": "src", "repository": { diff --git a/packages/metro-source-map/package.json b/packages/metro-source-map/package.json index 8b5df22bca..d7a4d58bde 100644 --- a/packages/metro-source-map/package.json +++ b/packages/metro-source-map/package.json @@ -1,6 +1,6 @@ { "name": "metro-source-map", - "version": "0.80.11", + "version": "0.80.12", "description": "🚇 Source map generator for Metro.", "main": "src/source-map.js", "repository": { @@ -16,9 +16,9 @@ "@babel/types": "^7.20.0", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", - "metro-symbolicate": "0.80.11", + "metro-symbolicate": "0.80.12", "nullthrows": "^1.1.1", - "ob1": "0.80.11", + "ob1": "0.80.12", "source-map": "^0.5.6", "vlq": "^1.0.0" }, diff --git a/packages/metro-symbolicate/package.json b/packages/metro-symbolicate/package.json index 0182ffa6a0..ea3b079439 100644 --- a/packages/metro-symbolicate/package.json +++ b/packages/metro-symbolicate/package.json @@ -1,6 +1,6 @@ { "name": "metro-symbolicate", - "version": "0.80.11", + "version": "0.80.12", "description": "🚇 A tool to find the source location from JS bundles and stack traces.", "license": "MIT", "main": "./src/index.js", @@ -19,7 +19,7 @@ "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", - "metro-source-map": "0.80.11", + "metro-source-map": "0.80.12", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "through2": "^2.0.1", diff --git a/packages/metro-transform-plugins/package.json b/packages/metro-transform-plugins/package.json index 3eebc3f899..b0b9723d1e 100644 --- a/packages/metro-transform-plugins/package.json +++ b/packages/metro-transform-plugins/package.json @@ -1,6 +1,6 @@ { "name": "metro-transform-plugins", - "version": "0.80.11", + "version": "0.80.12", "description": "🚇 Transform plugins for Metro.", "main": "src/index.js", "repository": { @@ -27,7 +27,7 @@ "@babel/plugin-transform-modules-commonjs": "^7.0.0", "@babel/types": "^7.20.0", "babel-plugin-tester": "^6.0.1", - "metro": "0.80.11" + "metro": "0.80.12" }, "engines": { "node": ">=18" diff --git a/packages/metro-transform-worker/package.json b/packages/metro-transform-worker/package.json index a4b20fbcf4..97023007f5 100644 --- a/packages/metro-transform-worker/package.json +++ b/packages/metro-transform-worker/package.json @@ -1,6 +1,6 @@ { "name": "metro-transform-worker", - "version": "0.80.11", + "version": "0.80.12", "description": "🚇 Transform worker for Metro.", "main": "src/index.js", "repository": { @@ -18,18 +18,18 @@ "@babel/parser": "^7.20.0", "@babel/types": "^7.20.0", "flow-enums-runtime": "^0.0.6", - "metro": "0.80.11", - "metro-babel-transformer": "0.80.11", - "metro-cache": "0.80.11", - "metro-cache-key": "0.80.11", - "metro-minify-terser": "0.80.11", - "metro-source-map": "0.80.11", - "metro-transform-plugins": "0.80.11", + "metro": "0.80.12", + "metro-babel-transformer": "0.80.12", + "metro-cache": "0.80.12", + "metro-cache-key": "0.80.12", + "metro-minify-terser": "0.80.12", + "metro-source-map": "0.80.12", + "metro-transform-plugins": "0.80.12", "nullthrows": "^1.1.1" }, "devDependencies": { "@react-native/metro-babel-transformer": "0.73.11", - "metro-memory-fs": "0.80.11" + "metro-memory-fs": "0.80.12" }, "engines": { "node": ">=18" diff --git a/packages/metro/package.json b/packages/metro/package.json index c5c171e38b..44655147ce 100644 --- a/packages/metro/package.json +++ b/packages/metro/package.json @@ -1,6 +1,6 @@ { "name": "metro", - "version": "0.80.11", + "version": "0.80.12", "description": "🚇 The JavaScript bundler for React Native.", "main": "src/index.js", "bin": "src/cli.js", @@ -35,18 +35,18 @@ "jest-worker": "^29.6.3", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", - "metro-babel-transformer": "0.80.11", - "metro-cache": "0.80.11", - "metro-cache-key": "0.80.11", - "metro-config": "0.80.11", - "metro-core": "0.80.11", - "metro-file-map": "0.80.11", - "metro-resolver": "0.80.11", - "metro-runtime": "0.80.11", - "metro-source-map": "0.80.11", - "metro-symbolicate": "0.80.11", - "metro-transform-plugins": "0.80.11", - "metro-transform-worker": "0.80.11", + "metro-babel-transformer": "0.80.12", + "metro-cache": "0.80.12", + "metro-cache-key": "0.80.12", + "metro-config": "0.80.12", + "metro-core": "0.80.12", + "metro-file-map": "0.80.12", + "metro-resolver": "0.80.12", + "metro-runtime": "0.80.12", + "metro-source-map": "0.80.12", + "metro-symbolicate": "0.80.12", + "metro-transform-plugins": "0.80.12", + "metro-transform-worker": "0.80.12", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", @@ -65,8 +65,8 @@ "dedent": "^0.7.0", "jest-snapshot": "^29.6.3", "jest-snapshot-serializer-raw": "^1.2.0", - "metro-babel-register": "0.80.11", - "metro-memory-fs": "0.80.11", + "metro-babel-register": "0.80.12", + "metro-memory-fs": "0.80.12", "mock-req": "^0.2.0", "mock-res": "^0.6.0", "stack-trace": "^0.0.10" diff --git a/packages/ob1/package.json b/packages/ob1/package.json index 887ccb904b..0bd2da16a7 100644 --- a/packages/ob1/package.json +++ b/packages/ob1/package.json @@ -1,6 +1,6 @@ { "name": "ob1", - "version": "0.80.11", + "version": "0.80.12", "description": "A small library for working with 0- and 1-based offsets in a type-checked way.", "main": "src/ob1.js", "repository": {