diff --git a/packages/metro/src/node-haste/DependencyGraph/FileNameResolver.js b/packages/metro/src/node-haste/DependencyGraph/FileNameResolver.js deleted file mode 100644 index bf0ab385..00000000 --- a/packages/metro/src/node-haste/DependencyGraph/FileNameResolver.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - * @format - */ - -'use strict'; - -const path = require('path'); - -export type Options = {| - +dirPath: string, - +doesFileExist: (filePath: string) => boolean, -|}; - -/** - * When resolving a single module we want to keep track of the list of paths - * we tried to find. This class is a way to aggregate all the tries easily. - */ -class FileNameResolver { - _options: Options; - _tentativeFileNames: Array; - - constructor(options: Options) { - this._options = options; - this._tentativeFileNames = []; - } - - getTentativeFileNames(): $ReadOnlyArray { - return this._tentativeFileNames; - } - - tryToResolveFileName(fileName: string): boolean { - this._tentativeFileNames.push(fileName); - const filePath = path.join(this._options.dirPath, fileName); - return this._options.doesFileExist(filePath); - } -} - -module.exports = FileNameResolver; diff --git a/packages/metro/src/node-haste/DependencyGraph/ModuleResolution.js b/packages/metro/src/node-haste/DependencyGraph/ModuleResolution.js index 012507ea..463b0b24 100644 --- a/packages/metro/src/node-haste/DependencyGraph/ModuleResolution.js +++ b/packages/metro/src/node-haste/DependencyGraph/ModuleResolution.js @@ -12,8 +12,6 @@ 'use strict'; -const FileNameResolver = require('./FileNameResolver'); - const invariant = require('fbjs/lib/invariant'); const isAbsolutePath = require('absolute-path'); const path = require('path'); @@ -85,9 +83,10 @@ type FileCandidates = // We only tried to resolve a specific asset. | {|+type: 'asset', +name: string|} // We attempted to resolve a name as being a source file (ex. JavaScript, - // JSON...), in which case there can be several variants we tried, for - // example `foo.ios.js`, `foo.js`, etc. - | {|+type: 'sources', +fileNames: $ReadOnlyArray|}; + // JSON...), in which case there can be several extensions we tried, for + // example `foo.ios.js`, `foo.js`, etc. (The array only contain extensions, + // ie. `['ios.js', 'js']`.) + | {|+type: 'sourceFile', +candidateExts: $ReadOnlyArray|}; /** * This is a way to describe what files we tried to look for when resolving @@ -377,20 +376,15 @@ class ModuleResolver { if (this.isAssetFile(fileNameHint)) { return this._loadAsAssetFile(dirPath, fileNameHint, platform); } - const {doesFileExist} = this._options; - const resolver = new FileNameResolver({doesFileExist, dirPath}); - const fileName = this._tryToResolveAllFileNames( - resolver, - fileNameHint, - platform, - ); - if (fileName != null) { - const filePath = path.join(dirPath, fileName); + const candidateExts = []; + const filePathPrefix = path.join(dirPath, fileNameHint); + const context = {filePathPrefix, candidateExts}; + const filePath = this._tryToResolveSourceFile(context, platform); + if (filePath != null) { const module = this._options.moduleCache.getModule(filePath); return resolvedAs(module); } - const fileNames = resolver.getTentativeFileNames(); - return failedFor({type: 'sources', fileNames}); + return failedFor({type: 'sourceFile', candidateExts}); } _loadAsAssetFile( @@ -414,25 +408,27 @@ class ModuleResolver { * to `foo/bar.js`. If can also resolve to the bare path `foo/bar` itself, as * supported by Node.js resolution. On the other hand it doesn't support * `foo/bar.ios`, for historical reasons. + * + * Return the full path of the resolved module, `null` if no resolution could + * be found. */ - _tryToResolveAllFileNames( - resolver: FileNameResolver, - fileNamePrefix: string, + _tryToResolveSourceFile( + context: {| + +candidateExts: Array, + +filePathPrefix: string, + |}, platform: ?string, ): ?string { - if (resolver.tryToResolveFileName(fileNamePrefix)) { - return fileNamePrefix; + let filePath = this._tryToResolveFileForExt(context, ''); + if (filePath) { + return filePath; } const {sourceExts} = this._options; for (let i = 0; i < sourceExts.length; i++) { - const fileName = this._tryToResolveFileNamesForExt( - fileNamePrefix, - resolver, - sourceExts[i], - platform, - ); - if (fileName != null) { - return fileName; + const ext = `.${sourceExts[i]}`; + filePath = this._tryToResolveFileForExts(context, ext, platform); + if (filePath != null) { + return filePath; } } return null; @@ -441,28 +437,54 @@ class ModuleResolver { /** * For a particular extension, ex. `js`, we want to try a few possibilities, * such as `foo.ios.js`, `foo.native.js`, and of course `foo.js`. + * + * Return the full path of the resolved module, `null` if no resolution could + * be found. */ - _tryToResolveFileNamesForExt( - fileNamePrefix: string, - resolver: FileNameResolver, - ext: string, + _tryToResolveFileForExts( + context: {| + +candidateExts: Array, + +filePathPrefix: string, + |}, + sourceExt: string, platform: ?string, ): ?string { const {preferNativePlatform} = this._options; if (platform != null) { - const fileName = `${fileNamePrefix}.${platform}.${ext}`; - if (resolver.tryToResolveFileName(fileName)) { - return fileName; + const platExt = `.${platform}${sourceExt}`; + const filePath = this._tryToResolveFileForExt(context, platExt); + if (filePath) { + return filePath; } } if (preferNativePlatform) { - const fileName = `${fileNamePrefix}.native.${ext}`; - if (resolver.tryToResolveFileName(fileName)) { - return fileName; + const nativeExt = `.native${sourceExt}`; + const filePath = this._tryToResolveFileForExt(context, nativeExt); + if (filePath) { + return filePath; } } - const fileName = `${fileNamePrefix}.${ext}`; - return resolver.tryToResolveFileName(fileName) ? fileName : null; + const filePath = this._tryToResolveFileForExt(context, sourceExt); + return filePath; + } + + /** + * We try to resolve a single possible extension. If it doesn't exist, then + * we make sure to add the extension to a list of candidates for reporting. + */ + _tryToResolveFileForExt( + context: {| + +candidateExts: Array, + +filePathPrefix: string, + |}, + extension: string, + ): ?string { + const filePath = `${context.filePathPrefix}${extension}`; + if (this._options.doesFileExist(filePath)) { + return filePath; + } + context.candidateExts.push(filePath); + return null; } _getEmptyModule(fromModule: TModule, toModuleName: string): TModule {