diff --git a/packages/metro/src/DeltaBundler/__tests__/resolver-test.js b/packages/metro/src/DeltaBundler/__tests__/resolver-test.js index e3ed949e51..c16735afdd 100644 --- a/packages/metro/src/DeltaBundler/__tests__/resolver-test.js +++ b/packages/metro/src/DeltaBundler/__tests__/resolver-test.js @@ -1649,6 +1649,45 @@ function dep(name: string): TransformResultDependency { filePath: p('/root/node_modules/foo/asset.png'), }); }); + + test('resolves a package whose name ends in an asset extension', async () => { + setMockFileSystem({ + 'index.js': '', + node_modules: { + 'lodash.zip': { + 'package.json': JSON.stringify({name: 'lodash.zip'}), + 'index.js': '', + }, + }, + }); + + resolver = await createResolver({ + resolver: {assetExts: ['png', 'zip']}, + }); + + expect( + resolver.resolve(p('/root/index.js'), dep('lodash.zip')), + ).toEqual({ + type: 'sourceFile', + filePath: p('/root/node_modules/lodash.zip/index.js'), + }); + }); + + test('resolves a directory whose name ends in an asset extension', async () => { + setMockFileSystem({ + 'index.js': '', + 'icons.png': {'index.js': ''}, + }); + + resolver = await createResolver(); + + expect( + resolver.resolve(p('/root/index.js'), dep('./icons.png')), + ).toEqual({ + type: 'sourceFile', + filePath: p('/root/icons.png/index.js'), + }); + }); }); describe('global packages', () => { diff --git a/packages/metro/src/node-haste/DependencyGraph/createModuleResolver.js b/packages/metro/src/node-haste/DependencyGraph/createModuleResolver.js index fa2db68a69..4483c3afa9 100644 --- a/packages/metro/src/node-haste/DependencyGraph/createModuleResolver.js +++ b/packages/metro/src/node-haste/DependencyGraph/createModuleResolver.js @@ -77,7 +77,12 @@ export default function createModuleResolver({ resolution => basePath + '@' + resolution + 'x' + extension, ), ] - .map(assetPath => fileSystemLookup(assetPath).realPath) + .map(assetPath => { + const result = fileSystemLookup(assetPath); + // A directory such as `node_modules/lodash.zip` is not an asset, and + // must fall through to directory (package) resolution. + return result.exists && result.type === 'f' ? result.realPath : null; + }) .filter(Boolean); return assets.length ? assets : null;