mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Summary: The existing resolution logic of assets: * goes over all the files of the asset's directory for every resolution request; * duplicates the parsing logic of `AssetPaths` by building up a custom regex for each resolution request. This changeset proposes to tweak this by building an index for each particular directory in which we're looking for assets, so that we don't have to crawl a single directory twice, and so that it reuses the logic of `AssetPaths.tryParse()` for determining variants. Reviewed By: davidaurelio Differential Revision: D5062435 fbshipit-source-id: 708fc5612f57b14565499fad741701269438c806
150 lines
4.5 KiB
JavaScript
150 lines
4.5 KiB
JavaScript
/**
|
|
* 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
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
import type { // eslint-disable-line sort-requires
|
|
Extensions,
|
|
Path,
|
|
} from './node-haste.flow';
|
|
|
|
import type {
|
|
ResolveFn,
|
|
TransformedCodeFile,
|
|
} from '../types.flow';
|
|
|
|
const AssetResolutionCache = require('../../node-haste/AssetResolutionCache');
|
|
const DependencyGraphHelpers = require('../../node-haste/DependencyGraph/DependencyGraphHelpers');
|
|
const FilesByDirNameIndex = require('../../node-haste/FilesByDirNameIndex');
|
|
const HasteFS = require('./HasteFS');
|
|
const HasteMap = require('../../node-haste/DependencyGraph/HasteMap');
|
|
const Module = require('./Module');
|
|
const ModuleCache = require('./ModuleCache');
|
|
const ResolutionRequest = require('../../node-haste/DependencyGraph/ResolutionRequest');
|
|
|
|
const defaults = require('../../../defaults');
|
|
|
|
import type {Moduleish, Packageish} from '../../node-haste/DependencyGraph/ResolutionRequest';
|
|
|
|
type ResolveOptions = {|
|
|
assetExts: Extensions,
|
|
extraNodeModules: {[id: string]: string},
|
|
+sourceExts: Extensions,
|
|
transformedFiles: {[path: Path]: TransformedCodeFile},
|
|
|};
|
|
|
|
const platforms = new Set(defaults.platforms);
|
|
|
|
/**
|
|
* We don't need to crawl the filesystem all over again so we just mock
|
|
* a jest-haste-map's ModuleMap instance. Eventually, though, we'll
|
|
* want to figure out how to reunify and get rid of `HasteMap`.
|
|
*/
|
|
function getFakeModuleMap(hasteMap: HasteMap<Module, Packageish>) {
|
|
return {
|
|
getModule(name: string, platform: ?string): ?string {
|
|
const module = hasteMap.getModule(name, platform);
|
|
return module && module.type === 'Module' ? module.path : null;
|
|
},
|
|
getPackage(name: string, platform: ?string): ?string {
|
|
const pkg = hasteMap.getPackage(name);
|
|
return pkg && pkg.path;
|
|
},
|
|
};
|
|
}
|
|
|
|
const nullModule: Moduleish = {
|
|
path: '/',
|
|
getPackage() {},
|
|
hash() {
|
|
throw new Error('not implemented');
|
|
},
|
|
readCached() { throw new Error('not implemented'); },
|
|
readFresh() { return Promise.reject(new Error('not implemented')); },
|
|
isHaste() { throw new Error('not implemented'); },
|
|
getName() { throw new Error('not implemented'); },
|
|
};
|
|
|
|
exports.createResolveFn = function(options: ResolveOptions): ResolveFn {
|
|
const {
|
|
assetExts,
|
|
extraNodeModules,
|
|
transformedFiles,
|
|
sourceExts,
|
|
} = options;
|
|
const files = Object.keys(transformedFiles);
|
|
function getTransformedFile(path) {
|
|
const result = transformedFiles[path];
|
|
if (!result) {
|
|
throw new Error(`"${path} does not exist`);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
const helpers = new DependencyGraphHelpers({
|
|
assetExts,
|
|
providesModuleNodeModules: defaults.providesModuleNodeModules,
|
|
});
|
|
|
|
const hasteFS = new HasteFS(files);
|
|
const moduleCache = new ModuleCache(
|
|
filePath => hasteFS.closest(filePath, 'package.json'),
|
|
getTransformedFile,
|
|
);
|
|
const hasteMap = new HasteMap({
|
|
extensions: sourceExts,
|
|
files,
|
|
helpers,
|
|
moduleCache,
|
|
platforms,
|
|
preferNativePlatform: true,
|
|
});
|
|
|
|
const hasteMapBuilt = hasteMap.build();
|
|
const resolutionRequests = {};
|
|
const filesByDirNameIndex = new FilesByDirNameIndex(hasteMap.getAllFiles());
|
|
const assetResolutionCache = new AssetResolutionCache({
|
|
assetExtensions: new Set(assetExts),
|
|
getDirFiles: dirPath => filesByDirNameIndex.getAllFiles(dirPath),
|
|
platforms,
|
|
});
|
|
return (id, source, platform, _, callback) => {
|
|
let resolutionRequest = resolutionRequests[platform];
|
|
if (!resolutionRequest) {
|
|
resolutionRequest = resolutionRequests[platform] = new ResolutionRequest({
|
|
dirExists: filePath => hasteFS.dirExists(filePath),
|
|
entryPath: '',
|
|
extraNodeModules,
|
|
hasteFS,
|
|
helpers,
|
|
moduleCache,
|
|
moduleMap: getFakeModuleMap(hasteMap),
|
|
platform,
|
|
preferNativePlatform: true,
|
|
resolveAsset: (dirPath, assetName) =>
|
|
assetResolutionCache.resolve(dirPath, assetName, platform),
|
|
sourceExts,
|
|
});
|
|
}
|
|
|
|
const from = source != null
|
|
? new Module(source, moduleCache, getTransformedFile(source))
|
|
: nullModule;
|
|
hasteMapBuilt
|
|
.then(() => resolutionRequest.resolveDependency(from, id))
|
|
.then(
|
|
// nextTick to escape promise error handling
|
|
module => process.nextTick(callback, null, module.path),
|
|
error => process.nextTick(callback, error),
|
|
);
|
|
};
|
|
};
|