Updates to node-haste adapter

Reviewed By: matryoshcow

Differential Revision: D4197864

fbshipit-source-id: 31bc4b0fb51ea77fac09fdd0f8180e984e05087a
This commit is contained in:
David Aurelio 2016-11-17 11:05:27 -08:00 committed by Facebook Github Bot
parent 2af1de283c
commit 3a52efa614
6 changed files with 69 additions and 22 deletions

View File

@ -11,7 +11,7 @@
'use strict'; 'use strict';
const {dirname, parse} = require('path'); const {dirname, join, parse} = require('path');
module.exports = class FastFS { module.exports = class FastFS {
directories: Set<string>; directories: Set<string>;
@ -24,6 +24,18 @@ module.exports = class FastFS {
this.files = new Set(files); this.files = new Set(files);
} }
closest(path: string, fileName: string): ?string {
let {dir, root} = parse(path);
do {
const candidate = join(dir, fileName);
if (this.files.has(candidate)) {
return candidate;
}
dir = dirname(dir);
} while (dir !== '.' && dir !== root);
return null;
}
dirExists(path: string) { dirExists(path: string) {
return this.directories.has(path); return this.directories.has(path);
} }
@ -47,8 +59,8 @@ function buildDirectorySet(files) {
files.forEach(path => { files.forEach(path => {
let {dir, root} = parse(path); let {dir, root} = parse(path);
while (dir !== '.' && dir !== root && !directories.has(dir)) { while (dir !== '.' && dir !== root && !directories.has(dir)) {
directories.add(path); directories.add(dir);
dir = dirname(path); dir = dirname(dir);
} }
}); });
return directories; return directories;

View File

@ -12,15 +12,22 @@
'use strict'; 'use strict';
import type {TransformedFile} from '../types.flow'; import type {TransformedFile} from '../types.flow';
import type {ModuleCache} from './node-haste.flow';
module.exports = class Module { module.exports = class Module {
hasteID: Promise<?string>; hasteID: Promise<?string>;
moduleCache: ModuleCache;
name: Promise<string>; name: Promise<string>;
path: string; path: string;
type: 'Module'; type: 'Module';
constructor(path: string, info: Promise<TransformedFile>) { constructor(
path: string,
moduleCache: ModuleCache,
info: Promise<TransformedFile>,
) {
this.hasteID = info.then(({hasteID}) => hasteID); this.hasteID = info.then(({hasteID}) => hasteID);
this.moduleCache = moduleCache;
this.name = this.hasteID.then(name => name || getName(path)); this.name = this.hasteID.then(name => name || getName(path));
this.path = path; this.path = path;
this.type = 'Module'; this.type = 'Module';
@ -30,6 +37,10 @@ module.exports = class Module {
return this.name; return this.name;
} }
getPackage() {
return this.moduleCache.getPackageOf(this.path);
}
isHaste() { isHaste() {
return this.hasteID.then(Boolean); return this.hasteID.then(Boolean);
} }

View File

@ -15,16 +15,19 @@ const Module = require('./Module');
const Package = require('./Package'); const Package = require('./Package');
import type {PackageData, TransformedFile} from '../types.flow'; import type {PackageData, TransformedFile} from '../types.flow';
import type {FastFS} from './node-haste.flow';
type GetFn<T> = (path: string) => Promise<T>; type GetFn<T> = (path: string) => Promise<T>;
module.exports = class ModuleCache { module.exports = class ModuleCache {
fastfs: FastFS;
getPackageData: GetFn<PackageData>; getPackageData: GetFn<PackageData>;
getTransformedFile: GetFn<TransformedFile>; getTransformedFile: GetFn<TransformedFile>;
modules: Map<string, Module>; modules: Map<string, Module>;
packages: Map<string, Package>; packages: Map<string, Package>;
constructor(getTransformedFile: GetFn<TransformedFile>) { constructor(fastfs: FastFS, getTransformedFile: GetFn<TransformedFile>) {
this.fastfs = fastfs;
this.getTransformedFile = getTransformedFile; this.getTransformedFile = getTransformedFile;
this.getPackageData = path => getTransformedFile(path).then( this.getPackageData = path => getTransformedFile(path).then(
f => f.package || Promise.reject(new Error(`"${path}" does not exist`)) f => f.package || Promise.reject(new Error(`"${path}" does not exist`))
@ -40,7 +43,7 @@ module.exports = class ModuleCache {
getModule(path: string) { getModule(path: string) {
let m = this.modules.get(path); let m = this.modules.get(path);
if (!m) { if (!m) {
m = new Module(path, this.getTransformedFile(path)); m = new Module(path, this, this.getTransformedFile(path));
this.modules.set(path, m); this.modules.set(path, m);
} }
return m; return m;
@ -54,4 +57,9 @@ module.exports = class ModuleCache {
} }
return p; return p;
} }
getPackageOf(filePath: string) {
const candidate = this.fastfs.closest(filePath, 'package.json');
return candidate != null ? this.getPackage(candidate) : null;
}
}; };

View File

@ -17,11 +17,13 @@ import type {PackageData} from '../types.flow';
module.exports = class Package { module.exports = class Package {
data: Promise<PackageData>; data: Promise<PackageData>;
path: string;
root: string; root: string;
type: 'Package'; type: 'Package';
constructor(packagePath: string, data: Promise<PackageData>) { constructor(packagePath: string, data: Promise<PackageData>) {
this.data = data; this.data = data;
this.path = packagePath;
this.root = path.dirname(packagePath); this.root = path.dirname(packagePath);
this.type = 'Package'; this.type = 'Package';
} }
@ -52,6 +54,10 @@ module.exports = class Package {
return this.data.then(p => p.name); return this.data.then(p => p.name);
} }
isHaste() {
return this.data.then(p => !!p.name);
}
redirectRequire(name: string) { redirectRequire(name: string) {
// Copied from node-haste/Package.js // Copied from node-haste/Package.js
return this.data.then(data => { return this.data.then(data => {

View File

@ -24,14 +24,17 @@ export type Module = {
path: Path, path: Path,
type: 'Module', type: 'Module',
getName(): Promise<ModuleID>, getName(): Promise<ModuleID>,
getPackage(): ?Package,
isHaste(): Promise<boolean>, isHaste(): Promise<boolean>,
}; };
export type Package = { export type Package = {
type: 'Package', path: Path,
root: Path, root: Path,
type: 'Package',
getMain(): Promise<Path>, getMain(): Promise<Path>,
getName(): Promise<ModuleID>, getName(): Promise<ModuleID>,
isHaste(): Promise<boolean>,
redirectRequire(id: ModuleID): Promise<Path | false>, redirectRequire(id: ModuleID): Promise<Path | false>,
}; };
@ -40,10 +43,12 @@ export interface ModuleCache {
getAssetModule(path: Path): Module, getAssetModule(path: Path): Module,
getModule(path: Path): Module, getModule(path: Path): Module,
getPackage(path: Path): Package, getPackage(path: Path): Package,
getPackageOf(path: Path): ?Package,
} }
export type FastFS = { export type FastFS = {
dirExists(path: Path): boolean, dirExists(path: Path): boolean,
closest(path: string, fileName: string): ?string,
fileExists(path: Path): boolean, fileExists(path: Path): boolean,
getAllFiles(): Array<Path>, getAllFiles(): Array<Path>,
matches(directory: Path, pattern: RegExp): Array<Path>, matches(directory: Path, pattern: RegExp): Array<Path>,
@ -63,17 +68,19 @@ declare class DeprecatedAssetMap {
export type DeprecatedAssetMapT = DeprecatedAssetMap; export type DeprecatedAssetMapT = DeprecatedAssetMap;
type HasteMapOptions = {| type HasteMapOptions = {|
allowRelativePaths: boolean,
extensions: Extensions, extensions: Extensions,
fastfs: FastFS, fastfs: FastFS,
moduleCache: ModuleCache,
preferNativePlatform: true,
helpers: DependencyGraphHelpers, helpers: DependencyGraphHelpers,
moduleCache: ModuleCache,
platforms: Platforms, platforms: Platforms,
preferNativePlatform: true,
|}; |};
declare class HasteMap { declare class HasteMap {
// node-haste/DependencyGraph/HasteMap.js // node-haste/DependencyGraph/HasteMap.js
constructor(options: HasteMapOptions): void, constructor(options: HasteMapOptions): void,
build(): Promise<Object>,
} }
export type HasteMapT = HasteMap; export type HasteMapT = HasteMap;

View File

@ -31,22 +31,21 @@ const HasteMap: Class<HasteMapT> = require('../../node-haste/DependencyGraph/Has
const Module = require('./Module'); const Module = require('./Module');
const ModuleCache = require('./ModuleCache'); const ModuleCache = require('./ModuleCache');
const ResolutionRequest: Class<ResolutionRequestT> = require('../../node-haste/DependencyGraph/ResolutionRequest'); const ResolutionRequest: Class<ResolutionRequestT> = require('../../node-haste/DependencyGraph/ResolutionRequest');
const defaults = require('../../../../defaults');
type ResolveOptions = { type ResolveOptions = {|
assetExts: Extensions, assetExts: Extensions,
extraNodeModules: {[id: string]: string}, extraNodeModules: {[id: string]: string},
providesModuleNodeModules: Array<string>,
transformedFiles: {[path: Path]: TransformedFile}, transformedFiles: {[path: Path]: TransformedFile},
}; |};
const platforms = new Set(['android', 'ios']); const platforms = new Set(defaults.platforms);
const returnTrue = () => true; const returnTrue = () => true;
exports.createResolveFn = function(options: ResolveOptions): ResolveFn { exports.createResolveFn = function(options: ResolveOptions): ResolveFn {
const { const {
assetExts, assetExts,
extraNodeModules, extraNodeModules,
providesModuleNodeModules,
transformedFiles, transformedFiles,
} = options; } = options;
const files = Object.keys(transformedFiles); const files = Object.keys(transformedFiles);
@ -57,7 +56,7 @@ exports.createResolveFn = function(options: ResolveOptions): ResolveFn {
const helpers = new DependencyGraphHelpers({ const helpers = new DependencyGraphHelpers({
assetExts, assetExts,
providesModuleNodeModules, providesModuleNodeModules: defaults.providesModuleNodeModules,
}); });
const deprecatedAssetMap = new DeprecatedAssetMap({ const deprecatedAssetMap = new DeprecatedAssetMap({
assetExts, assetExts,
@ -67,8 +66,9 @@ exports.createResolveFn = function(options: ResolveOptions): ResolveFn {
}); });
const fastfs = new FastFS(files); const fastfs = new FastFS(files);
const moduleCache = new ModuleCache(getTransformedFile); const moduleCache = new ModuleCache(fastfs, getTransformedFile);
const hasteMap = new HasteMap({ const hasteMap = new HasteMap({
allowRelativePaths: true,
extensions: ['js', 'json'], extensions: ['js', 'json'],
fastfs, fastfs,
helpers, helpers,
@ -77,6 +77,7 @@ exports.createResolveFn = function(options: ResolveOptions): ResolveFn {
preferNativePlatform: true, preferNativePlatform: true,
}); });
const hasteMapBuilt = hasteMap.build();
const resolutionRequests = {}; const resolutionRequests = {};
return (id, source, platform, _, callback) => { return (id, source, platform, _, callback) => {
let resolutionRequest = resolutionRequests[platform]; let resolutionRequest = resolutionRequests[platform];
@ -95,11 +96,13 @@ exports.createResolveFn = function(options: ResolveOptions): ResolveFn {
}); });
} }
const from = new Module(source, getTransformedFile(source)); const from = new Module(source, moduleCache, getTransformedFile(source));
resolutionRequest.resolveDependency(from, id).then( hasteMapBuilt
// nextTick to escape promise error handling .then(() => resolutionRequest.resolveDependency(from, id))
module => process.nextTick(callback, null, module.path), .then(
error => process.nextTick(callback, error), // nextTick to escape promise error handling
); module => process.nextTick(callback, null, module.path),
error => process.nextTick(callback, error),
);
}; };
}; };