diff --git a/packages/metro-resolver/src/__tests__/index-test.js b/packages/metro-resolver/src/__tests__/index-test.js index 2fb86f0d72..1aa91f4c32 100644 --- a/packages/metro-resolver/src/__tests__/index-test.js +++ b/packages/metro-resolver/src/__tests__/index-test.js @@ -56,9 +56,19 @@ const CONTEXT: ResolutionContext = (() => { }, 'other-root': { node_modules: { + 'banana-module': { + 'package.json': true, + 'main.js': true, + }, banana: { 'package.json': true, 'main.js': true, + node_modules: { + 'banana-module': { + 'package.json': true, + 'main.js': true, + }, + }, }, }, }, @@ -217,14 +227,35 @@ it('uses `nodeModulesPaths` to find additional node_modules not in the direct pa expect(() => Resolver.resolve(context, 'kiwi', null)) .toThrowErrorMatchingInlineSnapshot(` "Module does not exist in the Haste module map or in these directories: - /other-root/node_modules /root/project/node_modules /root/node_modules /node_modules + /other-root/node_modules " `); }); +it('resolves transitive dependencies when using `nodeModulesPaths`', () => { + const context = Object.assign( + {}, + {...CONTEXT, originModulePath: '/other-root/node_modules/banana/main.js'}, + { + nodeModulesPaths: ['/other-root/node_modules'], + }, + ); + + expect(Resolver.resolve(context, 'banana-module', null)).toEqual({ + type: 'sourceFile', + filePath: + '/other-root/node_modules/banana/node_modules/banana-module/main.js', + }); + + expect(Resolver.resolve(context, 'banana-module', null)).not.toEqual({ + type: 'sourceFile', + filePath: '/other-root/node_modules/banana-module/main.js', + }); +}); + describe('disableHierarchicalLookup', () => { const context = Object.assign({}, CONTEXT, { disableHierarchicalLookup: true, diff --git a/packages/metro-resolver/src/resolve.js b/packages/metro-resolver/src/resolve.js index 0dd56811fd..70109de178 100644 --- a/packages/metro-resolver/src/resolve.js +++ b/packages/metro-resolver/src/resolve.js @@ -90,9 +90,10 @@ function resolve( } catch (error) {} } - const nodeModulesPaths = Array.from(context.nodeModulesPaths); + const nodeModulesPaths = []; let next = path.dirname(originModulePath); const {disableHierarchicalLookup} = context; + if (!disableHierarchicalLookup) { let candidate; do { @@ -102,6 +103,9 @@ function resolve( } while (candidate !== next); } + // Fall back to `nodeModulesPaths` after hierarchical lookup, similar to $NODE_PATH + nodeModulesPaths.push(...context.nodeModulesPaths); + const extraPaths = []; const {extraNodeModules} = context; if (extraNodeModules) {