mirror of https://github.com/status-im/metro.git
Remove HasteMap
Reviewed By: davidaurelio Differential Revision: D5803275 fbshipit-source-id: 2e64733d8ef400a61d116b21cd53185934dd3d57
This commit is contained in:
parent
61a0116dd4
commit
b3e817285b
|
@ -18,7 +18,7 @@ import type ModuleCache from './ModuleCache';
|
||||||
module.exports = class Module {
|
module.exports = class Module {
|
||||||
hasteID: ?string;
|
hasteID: ?string;
|
||||||
moduleCache: ModuleCache;
|
moduleCache: ModuleCache;
|
||||||
name: Promise<string>;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
type: 'Module';
|
type: 'Module';
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ module.exports = class Module {
|
||||||
) {
|
) {
|
||||||
this.hasteID = info.hasteID;
|
this.hasteID = info.hasteID;
|
||||||
this.moduleCache = moduleCache;
|
this.moduleCache = moduleCache;
|
||||||
this.name = Promise.resolve(this.hasteID || getName(path));
|
this.name = this.hasteID || getName(path);
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.type = 'Module';
|
this.type = 'Module';
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,8 @@ module.exports = class Module {
|
||||||
return Promise.reject(new Error('not implemented'));
|
return Promise.reject(new Error('not implemented'));
|
||||||
}
|
}
|
||||||
|
|
||||||
getName() {
|
getName(): Promise<string> {
|
||||||
return this.name;
|
return Promise.resolve(this.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPackage() {
|
getPackage() {
|
||||||
|
|
|
@ -16,21 +16,20 @@ const AssetResolutionCache = require('../../node-haste/AssetResolutionCache');
|
||||||
const DependencyGraphHelpers = require('../../node-haste/DependencyGraph/DependencyGraphHelpers');
|
const DependencyGraphHelpers = require('../../node-haste/DependencyGraph/DependencyGraphHelpers');
|
||||||
const FilesByDirNameIndex = require('../../node-haste/FilesByDirNameIndex');
|
const FilesByDirNameIndex = require('../../node-haste/FilesByDirNameIndex');
|
||||||
const HasteFS = require('./HasteFS');
|
const HasteFS = require('./HasteFS');
|
||||||
const HasteMap = require('../../node-haste/DependencyGraph/HasteMap');
|
|
||||||
const Module = require('./Module');
|
const Module = require('./Module');
|
||||||
const ModuleCache = require('./ModuleCache');
|
const ModuleCache = require('./ModuleCache');
|
||||||
const ResolutionRequest = require('../../node-haste/DependencyGraph/ResolutionRequest');
|
const ResolutionRequest = require('../../node-haste/DependencyGraph/ResolutionRequest');
|
||||||
|
|
||||||
const defaults = require('../../defaults');
|
const defaults = require('../../defaults');
|
||||||
|
const parsePlatformFilePath = require('../../node-haste/lib/parsePlatformFilePath');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
ModuleResolver,
|
ModuleResolver,
|
||||||
} = require('../../node-haste/DependencyGraph/ModuleResolution');
|
} = require('../../node-haste/DependencyGraph/ModuleResolution');
|
||||||
|
const {ModuleMap} = require('jest-haste-map');
|
||||||
|
|
||||||
import type {
|
import type {Moduleish} from '../../node-haste/DependencyGraph/ResolutionRequest';
|
||||||
Moduleish,
|
|
||||||
Packageish,
|
|
||||||
} from '../../node-haste/DependencyGraph/ResolutionRequest';
|
|
||||||
import type {ResolveFn, TransformedCodeFile} from '../types.flow';
|
import type {ResolveFn, TransformedCodeFile} from '../types.flow';
|
||||||
import type {
|
import type {
|
||||||
// eslint-disable-line sort-requires
|
// eslint-disable-line sort-requires
|
||||||
|
@ -47,25 +46,9 @@ type ResolveOptions = {|
|
||||||
|
|
||||||
const platforms = new Set(defaults.platforms);
|
const platforms = new Set(defaults.platforms);
|
||||||
|
|
||||||
/**
|
const GENERIC_PLATFORM = 'g';
|
||||||
* We don't need to crawl the filesystem all over again so we just mock
|
const PACKAGE_JSON = path.sep + 'package.json';
|
||||||
* a jest-haste-map's ModuleMap instance. Eventually, though, we'll
|
const NULL_MODULE: Moduleish = {
|
||||||
* 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: '/',
|
path: '/',
|
||||||
getPackage() {},
|
getPackage() {},
|
||||||
hash() {
|
hash() {
|
||||||
|
@ -85,9 +68,49 @@ const nullModule: Moduleish = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.createResolveFn = function(
|
// This function maps the ModuleGraph data structure to jest-haste-map's ModuleMap
|
||||||
options: ResolveOptions,
|
const createModuleMap = ({files, helpers, moduleCache, sourceExts}) => {
|
||||||
): Promise<ResolveFn> {
|
const map = Object.create(null);
|
||||||
|
files.forEach(filePath => {
|
||||||
|
if (!helpers.isNodeModulesDir(filePath)) {
|
||||||
|
let id;
|
||||||
|
let module;
|
||||||
|
if (filePath.endsWith(PACKAGE_JSON)) {
|
||||||
|
module = moduleCache.getPackage(filePath);
|
||||||
|
id = module.data.name;
|
||||||
|
} else if (sourceExts.indexOf(path.extname(filePath).substr(1)) !== -1) {
|
||||||
|
module = moduleCache.getModule(filePath);
|
||||||
|
id = module.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id && module && module.isHaste()) {
|
||||||
|
if (!map[id]) {
|
||||||
|
map[id] = Object.create(null);
|
||||||
|
}
|
||||||
|
const platform =
|
||||||
|
parsePlatformFilePath(filePath, platforms).platform ||
|
||||||
|
GENERIC_PLATFORM;
|
||||||
|
|
||||||
|
const existingModule = map[id][platform];
|
||||||
|
// 0 = Module, 1 = Package in jest-haste-map
|
||||||
|
map[id][platform] = [filePath, module.type === 'Package' ? 1 : 0];
|
||||||
|
|
||||||
|
if (existingModule && existingModule.path !== filePath) {
|
||||||
|
throw new Error(
|
||||||
|
`@providesModule naming collision:\n` +
|
||||||
|
` Duplicate module name: ${id}\n` +
|
||||||
|
` Paths: ${filePath} collides with ${existingModule.path}\n\n` +
|
||||||
|
'This error is caused by a @providesModule declaration ' +
|
||||||
|
'with the same name across two different files.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return map;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.createResolveFn = function(options: ResolveOptions): ResolveFn {
|
||||||
const {assetExts, extraNodeModules, transformedFiles, sourceExts} = options;
|
const {assetExts, extraNodeModules, transformedFiles, sourceExts} = options;
|
||||||
const files = Object.keys(transformedFiles);
|
const files = Object.keys(transformedFiles);
|
||||||
function getTransformedFile(path) {
|
function getTransformedFile(path) {
|
||||||
|
@ -108,18 +131,9 @@ exports.createResolveFn = function(
|
||||||
filePath => hasteFS.closest(filePath, 'package.json'),
|
filePath => hasteFS.closest(filePath, 'package.json'),
|
||||||
getTransformedFile,
|
getTransformedFile,
|
||||||
);
|
);
|
||||||
const hasteMap = new HasteMap({
|
|
||||||
extensions: sourceExts,
|
|
||||||
files,
|
|
||||||
helpers,
|
|
||||||
moduleCache,
|
|
||||||
platforms,
|
|
||||||
preferNativePlatform: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const hasteMapBuilt = hasteMap.build();
|
|
||||||
const resolutionRequests = {};
|
const resolutionRequests = {};
|
||||||
const filesByDirNameIndex = new FilesByDirNameIndex(hasteMap.getAllFiles());
|
const filesByDirNameIndex = new FilesByDirNameIndex(files);
|
||||||
const assetResolutionCache = new AssetResolutionCache({
|
const assetResolutionCache = new AssetResolutionCache({
|
||||||
assetExtensions: new Set(assetExts),
|
assetExtensions: new Set(assetExts),
|
||||||
getDirFiles: dirPath => filesByDirNameIndex.getAllFiles(dirPath),
|
getDirFiles: dirPath => filesByDirNameIndex.getAllFiles(dirPath),
|
||||||
|
@ -131,14 +145,18 @@ exports.createResolveFn = function(
|
||||||
extraNodeModules,
|
extraNodeModules,
|
||||||
helpers,
|
helpers,
|
||||||
moduleCache,
|
moduleCache,
|
||||||
moduleMap: getFakeModuleMap(hasteMap),
|
moduleMap: new ModuleMap({
|
||||||
|
duplicates: Object.create(null),
|
||||||
|
map: createModuleMap({files, helpers, moduleCache, sourceExts}),
|
||||||
|
mocks: Object.create(null),
|
||||||
|
}),
|
||||||
preferNativePlatform: true,
|
preferNativePlatform: true,
|
||||||
resolveAsset: (dirPath, assetName, platform) =>
|
resolveAsset: (dirPath, assetName, platform) =>
|
||||||
assetResolutionCache.resolve(dirPath, assetName, platform),
|
assetResolutionCache.resolve(dirPath, assetName, platform),
|
||||||
sourceExts,
|
sourceExts,
|
||||||
});
|
});
|
||||||
|
|
||||||
return hasteMapBuilt.then(() => (id, source, platform, _, callback) => {
|
return (id, sourcePath, platform, _, callback) => {
|
||||||
let resolutionRequest = resolutionRequests[platform];
|
let resolutionRequest = resolutionRequests[platform];
|
||||||
if (!resolutionRequest) {
|
if (!resolutionRequest) {
|
||||||
resolutionRequest = resolutionRequests[platform] = new ResolutionRequest({
|
resolutionRequest = resolutionRequests[platform] = new ResolutionRequest({
|
||||||
|
@ -151,9 +169,9 @@ exports.createResolveFn = function(
|
||||||
}
|
}
|
||||||
|
|
||||||
const from =
|
const from =
|
||||||
source != null
|
sourcePath != null
|
||||||
? new Module(source, moduleCache, getTransformedFile(source))
|
? new Module(sourcePath, moduleCache, getTransformedFile(sourcePath))
|
||||||
: nullModule;
|
: NULL_MODULE;
|
||||||
return resolutionRequest.resolveDependency(from, id).path;
|
return resolutionRequest.resolveDependency(from, id).path;
|
||||||
});
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,243 +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 EventEmitter = require('events');
|
|
||||||
|
|
||||||
const parsePlatformFilePath = require('../lib/parsePlatformFilePath');
|
|
||||||
const path = require('path');
|
|
||||||
const throat = require('throat');
|
|
||||||
|
|
||||||
const GENERIC_PLATFORM = 'generic';
|
|
||||||
const NATIVE_PLATFORM = 'native';
|
|
||||||
const PACKAGE_JSON = path.sep + 'package.json';
|
|
||||||
|
|
||||||
import type {Moduleish, Packageish, ModuleishCache} from './ResolutionRequest';
|
|
||||||
import type DependencyGraphHelpers from './DependencyGraphHelpers';
|
|
||||||
|
|
||||||
type Options<TModule, TPackage> = {|
|
|
||||||
extensions: Array<string>,
|
|
||||||
files: Array<string>,
|
|
||||||
helpers: DependencyGraphHelpers,
|
|
||||||
moduleCache: ModuleishCache<TModule, TPackage>,
|
|
||||||
platforms: Set<string>,
|
|
||||||
preferNativePlatform: boolean,
|
|
||||||
|};
|
|
||||||
|
|
||||||
class HasteMap<TModule: Moduleish, TPackage: Packageish> extends EventEmitter {
|
|
||||||
_extensions: Array<string>;
|
|
||||||
_files: Array<string>;
|
|
||||||
_helpers: DependencyGraphHelpers;
|
|
||||||
_map: {};
|
|
||||||
_moduleCache: ModuleishCache<TModule, TPackage>;
|
|
||||||
_packages: {};
|
|
||||||
_platforms: Set<string>;
|
|
||||||
_preferNativePlatform: boolean;
|
|
||||||
|
|
||||||
constructor({
|
|
||||||
extensions,
|
|
||||||
files,
|
|
||||||
helpers,
|
|
||||||
moduleCache,
|
|
||||||
platforms,
|
|
||||||
preferNativePlatform,
|
|
||||||
}: Options<TModule, TPackage>) {
|
|
||||||
super();
|
|
||||||
this._extensions = extensions;
|
|
||||||
this._files = files;
|
|
||||||
this._helpers = helpers;
|
|
||||||
this._moduleCache = moduleCache;
|
|
||||||
this._platforms = platforms;
|
|
||||||
this._preferNativePlatform = preferNativePlatform;
|
|
||||||
|
|
||||||
(this: any)._processHastePackage = throat(
|
|
||||||
1,
|
|
||||||
this._processHastePackage.bind(this),
|
|
||||||
);
|
|
||||||
(this: any)._processHasteModule = throat(
|
|
||||||
1,
|
|
||||||
this._processHasteModule.bind(this),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
build() {
|
|
||||||
this._map = Object.create(null);
|
|
||||||
this._packages = Object.create(null);
|
|
||||||
const promises = [];
|
|
||||||
this._files.forEach(filePath => {
|
|
||||||
if (!this._helpers.isNodeModulesDir(filePath)) {
|
|
||||||
if (filePath.endsWith(PACKAGE_JSON)) {
|
|
||||||
promises.push(this._processHastePackage(filePath));
|
|
||||||
} else if (
|
|
||||||
this._extensions.indexOf(path.extname(filePath).substr(1)) !== -1
|
|
||||||
) {
|
|
||||||
promises.push(this._processHasteModule(filePath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
/* $FlowFixMe(>=0.54.0 site=react_native_fb) This comment suppresses an
|
|
||||||
* error found when Flow v0.54 was deployed. To see the error delete this
|
|
||||||
* comment and run Flow. */
|
|
||||||
return Promise.all(promises).then(() => this._map);
|
|
||||||
}
|
|
||||||
|
|
||||||
getAllFiles(): Array<string> {
|
|
||||||
return this._files;
|
|
||||||
}
|
|
||||||
|
|
||||||
processFileChange(type: string, absPath: string) {
|
|
||||||
/* $FlowFixMe(>=0.54.0 site=react_native_fb) This comment suppresses an
|
|
||||||
* error found when Flow v0.54 was deployed. To see the error delete this
|
|
||||||
* comment and run Flow. */
|
|
||||||
return Promise.resolve().then(() => {
|
|
||||||
/*eslint no-labels: 0 */
|
|
||||||
let invalidated;
|
|
||||||
if (type === 'delete' || type === 'change') {
|
|
||||||
loop: for (const name in this._map) {
|
|
||||||
const modulesMap = this._map[name];
|
|
||||||
for (const platform in modulesMap) {
|
|
||||||
const module = modulesMap[platform];
|
|
||||||
if (module.path === absPath) {
|
|
||||||
delete modulesMap[platform];
|
|
||||||
invalidated = name;
|
|
||||||
break loop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'delete') {
|
|
||||||
if (invalidated) {
|
|
||||||
this.emit('change');
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
type !== 'delete' &&
|
|
||||||
this._extensions.indexOf(this._helpers.extname(absPath)) !== -1
|
|
||||||
) {
|
|
||||||
if (path.basename(absPath) === 'package.json') {
|
|
||||||
return this._processHastePackage(absPath, invalidated);
|
|
||||||
} else {
|
|
||||||
return this._processHasteModule(absPath, invalidated);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getModule(name: string, platform: ?string): ?TModule {
|
|
||||||
const modulesMap = this._map[name];
|
|
||||||
if (modulesMap == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If platform is 'ios', we prefer .ios.js to .native.js which we prefer to
|
|
||||||
// a plain .js file.
|
|
||||||
let module;
|
|
||||||
if (module == null && platform != null) {
|
|
||||||
module = modulesMap[platform];
|
|
||||||
}
|
|
||||||
if (module == null && this._preferNativePlatform) {
|
|
||||||
module = modulesMap[NATIVE_PLATFORM];
|
|
||||||
}
|
|
||||||
if (module == null) {
|
|
||||||
module = modulesMap[GENERIC_PLATFORM];
|
|
||||||
}
|
|
||||||
return module;
|
|
||||||
}
|
|
||||||
|
|
||||||
getPackage(name: string): TPackage {
|
|
||||||
return this._packages[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
_processHasteModule(file: string, previousName: ?string) {
|
|
||||||
const module = this._moduleCache.getModule(file);
|
|
||||||
/* $FlowFixMe(>=0.54.0 site=react_native_fb) This comment suppresses an
|
|
||||||
* error found when Flow v0.54 was deployed. To see the error delete this
|
|
||||||
* comment and run Flow. */
|
|
||||||
return Promise.resolve().then(() => {
|
|
||||||
const isHaste = module.isHaste();
|
|
||||||
return (
|
|
||||||
isHaste &&
|
|
||||||
module.getName().then(name => {
|
|
||||||
const result = this._updateHasteMap(name, module);
|
|
||||||
if (previousName && name !== previousName) {
|
|
||||||
this.emit('change');
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_processHastePackage(file: string, previousName: ?string) {
|
|
||||||
const p = this._moduleCache.getPackage(file);
|
|
||||||
/* $FlowFixMe(>=0.54.0 site=react_native_fb) This comment suppresses an
|
|
||||||
* error found when Flow v0.54 was deployed. To see the error delete this
|
|
||||||
* comment and run Flow. */
|
|
||||||
return Promise.resolve()
|
|
||||||
.then(() => {
|
|
||||||
const isHaste = p.isHaste();
|
|
||||||
return (
|
|
||||||
isHaste &&
|
|
||||||
p.getName().then(name => {
|
|
||||||
const result = this._updateHasteMap(name, p);
|
|
||||||
if (previousName && name !== previousName) {
|
|
||||||
this.emit('change');
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
if (e instanceof SyntaxError) {
|
|
||||||
// Malformed package.json.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateHasteMap(name: string, mod: TModule | TPackage) {
|
|
||||||
let existingModule;
|
|
||||||
|
|
||||||
if (mod.type === 'Package') {
|
|
||||||
existingModule = this._packages[name];
|
|
||||||
this._packages[name] = mod;
|
|
||||||
} else {
|
|
||||||
if (this._map[name] == null) {
|
|
||||||
this._map[name] = Object.create(null);
|
|
||||||
}
|
|
||||||
const moduleMap = this._map[name];
|
|
||||||
const modulePlatform =
|
|
||||||
parsePlatformFilePath(mod.path, this._platforms).platform ||
|
|
||||||
GENERIC_PLATFORM;
|
|
||||||
existingModule = moduleMap[modulePlatform];
|
|
||||||
moduleMap[modulePlatform] = mod;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (existingModule && existingModule.path !== mod.path) {
|
|
||||||
throw new Error(
|
|
||||||
`@providesModule naming collision:\n` +
|
|
||||||
` Duplicate module name: ${name}\n` +
|
|
||||||
` Paths: ${mod.path} collides with ${existingModule.path}\n\n` +
|
|
||||||
'This error is caused by a @providesModule declaration ' +
|
|
||||||
'with the same name across two different files.',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = HasteMap;
|
|
|
@ -30,12 +30,12 @@ export type ModuleMap = {
|
||||||
getModule(
|
getModule(
|
||||||
name: string,
|
name: string,
|
||||||
platform: string | null,
|
platform: string | null,
|
||||||
supportsNativePlatform: boolean,
|
supportsNativePlatform: ?boolean,
|
||||||
): ?string,
|
): ?string,
|
||||||
getPackage(
|
getPackage(
|
||||||
name: string,
|
name: string,
|
||||||
platform: string | null,
|
platform: string | null,
|
||||||
supportsNativePlatform: boolean,
|
supportsNativePlatform: ?boolean,
|
||||||
): ?string,
|
): ?string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue