RM node-haste DependencyGraph: @flow

Summary: In addition to adding flow in that file, I also had to fix `Module.js` and others to make everything compatible together.

Reviewed By: davidaurelio

Differential Revision: D4118829

fbshipit-source-id: 4f6dbc515741c38817cc4c9757e981fabb03915a
This commit is contained in:
Jean Lauliac 2016-11-04 10:42:41 -07:00 committed by Facebook Github Bot
parent dee58678c6
commit 403d4ed721
6 changed files with 111 additions and 45 deletions

View File

@ -67,21 +67,24 @@ class Cache {
return path.join(tmpdir, hash.digest('hex')); return path.join(tmpdir, hash.digest('hex'));
} }
get( get<T>(
filepath: string, filepath: string,
field: string, field: string,
loaderCb: (filepath: string) => Promise<mixed>, loaderCb: (filepath: string) => Promise<T>,
): Promise<mixed> { ): Promise<T> {
if (!isAbsolutePath(filepath)) { if (!isAbsolutePath(filepath)) {
throw new Error('Use absolute paths'); throw new Error('Use absolute paths');
} }
return this.has(filepath, field) return this.has(filepath, field)
? this._data[filepath].data[field] /* $FlowFixMe: this class is unsound as a whole because it uses
* untyped storage where in fact each "field" has a particular type.
* We cannot express this using Flow. */
? (this._data[filepath].data[field]: Promise<T>)
: this.set(filepath, field, loaderCb(filepath)); : this.set(filepath, field, loaderCb(filepath));
} }
invalidate(filepath: string, field: string) { invalidate(filepath: string, field: ?string) {
if (this.has(filepath, field)) { if (this.has(filepath, field)) {
if (field == null) { if (field == null) {
delete this._data[filepath]; delete this._data[filepath];
@ -95,16 +98,16 @@ class Cache {
return this._persistCache(); return this._persistCache();
} }
has(filepath: string, field: string) { has(filepath: string, field: ?string) {
return Object.prototype.hasOwnProperty.call(this._data, filepath) && return Object.prototype.hasOwnProperty.call(this._data, filepath) &&
(field == null || Object.prototype.hasOwnProperty.call(this._data[filepath].data, field)); (field == null || Object.prototype.hasOwnProperty.call(this._data[filepath].data, field));
} }
set( set<T>(
filepath: string, filepath: string,
field: string, field: string,
loaderPromise: Promise<mixed>, loaderPromise: Promise<T>,
): Promise<mixed> { ): Promise<T> {
let record = this._data[filepath]; let record = this._data[filepath];
if (!record) { if (!record) {
// $FlowFixMe: temporarily invalid record. // $FlowFixMe: temporarily invalid record.

View File

@ -18,7 +18,9 @@ const isAbsolutePath = require('absolute-path');
const jsonStableStringify = require('json-stable-stringify'); const jsonStableStringify = require('json-stable-stringify');
const path = require('path'); const path = require('path');
import type Cache from './Cache';
import type ModuleCache from './ModuleCache'; import type ModuleCache from './ModuleCache';
import type FastFs from './fastfs';
export type Extractor = (sourceCode: string) => {deps: {sync: Array<string>}}; export type Extractor = (sourceCode: string) => {deps: {sync: Array<string>}};
type TransformedCode = { type TransformedCode = {
@ -37,23 +39,7 @@ export type TransformCode = (
dependencyOffsets?: Array<number>, dependencyOffsets?: Array<number>,
map?: string, map?: string,
}>; }>;
export type Cache = {
get<T>(
filePath: string,
key: string,
loadFunc: () => Promise<T>,
): Promise<T>,
invalidate(filePath: string): void,
};
export type Options = {cacheTransformResults?: boolean}; export type Options = {cacheTransformResults?: boolean};
export type FastFs = {
readFile: (filePath: string) => Promise<string>,
closest: (innerFilePath: string, fileName: string) => string,
on: (
event: 'change',
onChange: (type: string, filePath: string, root: string) => void,
) => FastFs,
};
export type DepGraphHelpers = {isNodeModulesDir: (filePath: string) => boolean}; export type DepGraphHelpers = {isNodeModulesDir: (filePath: string) => boolean};
export type ConstructorArgs = { export type ConstructorArgs = {

View File

@ -18,14 +18,14 @@ const Polyfill = require('./Polyfill');
const path = require('path'); const path = require('path');
import type Cache from './Cache';
import type { import type {
Cache,
DepGraphHelpers, DepGraphHelpers,
FastFs,
Extractor, Extractor,
TransformCode, TransformCode,
Options as ModuleOptions, Options as ModuleOptions,
} from './Module'; } from './Module';
import type FastFs from './fastfs';
class ModuleCache { class ModuleCache {

View File

@ -14,10 +14,8 @@
const isAbsolutePath = require('absolute-path'); const isAbsolutePath = require('absolute-path');
const path = require('path'); const path = require('path');
import type { import type Cache from './Cache';
Cache, import type FastFs from './fastfs';
FastFs,
} from './Module';
class Package { class Package {
@ -74,7 +72,7 @@ class Package {
); );
} }
getName() { getName(): Promise<string> {
return this._cache.get(this.path, 'package-name', () => return this._cache.get(this.path, 'package-name', () =>
this.read().then(json => json.name) this.read().then(json => json.name)
); );

View File

@ -18,11 +18,6 @@ const {EventEmitter} = require('events');
const NOT_FOUND_IN_ROOTS = 'NotFoundInRootsError'; const NOT_FOUND_IN_ROOTS = 'NotFoundInRootsError';
interface Activity {
startEvent(title: string, m: mixed, opts: mixed): mixed,
endEvent(activity: mixed): void,
}
interface FileWatcher { interface FileWatcher {
on(event: 'all', handler: (type: string, filePath: string, rootPath: string, fstat: fs.Stats) => void): void, on(event: 'all', handler: (type: string, filePath: string, rootPath: string, fstat: fs.Stats) => void): void,
} }
@ -41,16 +36,14 @@ class Fastfs extends EventEmitter {
_ignore: (filePath: string) => boolean; _ignore: (filePath: string) => boolean;
_roots: Array<File>; _roots: Array<File>;
_fastPaths: {[filePath: string]: File}; _fastPaths: {[filePath: string]: File};
_activity: mixed;
constructor( constructor(
name: string, name: string,
roots: Array<string>, roots: Array<string>,
fileWatcher: FileWatcher, fileWatcher: FileWatcher,
files: Array<string>, files: Array<string>,
{ignore, activity}: { {ignore}: {
ignore: (filePath: string) => boolean, ignore: (filePath: string) => boolean,
activity: Activity,
}, },
) { ) {
super(); super();

View File

@ -5,7 +5,10 @@
* This source code is licensed under the BSD-style license found in the * 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 * 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. * of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
*/ */
'use strict'; 'use strict';
const Cache = require('./Cache'); const Cache = require('./Cache');
@ -31,6 +34,12 @@ const path = require('path');
const replacePatterns = require('./lib/replacePatterns'); const replacePatterns = require('./lib/replacePatterns');
const util = require('util'); const util = require('util');
import type {
TransformCode,
Options as ModuleOptions,
Extractor,
} from './Module';
const ERROR_BUILDING_DEP_GRAPH = 'DependencyGraphError'; const ERROR_BUILDING_DEP_GRAPH = 'DependencyGraphError';
const { const {
@ -41,6 +50,39 @@ const {
} = require('../Logger'); } = require('../Logger');
class DependencyGraph { class DependencyGraph {
_opts: {
roots: Array<string>,
ignoreFilePath: (filePath: string) => boolean,
fileWatcher: FileWatcher,
assetRoots_DEPRECATED: Array<string>,
assetExts: Array<string>,
providesModuleNodeModules: mixed,
platforms: Set<mixed>,
preferNativePlatform: boolean,
extensions: Array<string>,
mocksPattern: mixed,
extractRequires: Extractor,
transformCode: TransformCode,
shouldThrowOnUnresolvedErrors: () => boolean,
enableAssetMap: boolean,
moduleOptions: ModuleOptions,
extraNodeModules: mixed,
useWatchman: boolean,
maxWorkers: number,
resetCache: boolean,
};
_cache: Cache;
_assetDependencies: mixed;
_helpers: DependencyGraphHelpers;
_fastfs: Fastfs;
_moduleCache: ModuleCache;
_hasteMap: HasteMap;
_deprecatedAssetMap: DeprecatedAssetMap;
_hasteMapError: ?Error;
_loading: ?Promise<mixed>;
constructor({ constructor({
roots, roots,
ignoreFilePath, ignoreFilePath,
@ -64,6 +106,28 @@ class DependencyGraph {
useWatchman, useWatchman,
maxWorkers, maxWorkers,
resetCache, resetCache,
}: {
roots: Array<string>,
ignoreFilePath: (filePath: string) => boolean,
fileWatcher: FileWatcher,
assetRoots_DEPRECATED: Array<string>,
assetExts: Array<string>,
providesModuleNodeModules: mixed,
platforms: mixed,
preferNativePlatform: boolean,
cache: Cache,
extensions: Array<string>,
mocksPattern: mixed,
extractRequires: Extractor,
transformCode: TransformCode,
shouldThrowOnUnresolvedErrors: () => boolean,
enableAssetMap: boolean,
assetDependencies: mixed,
moduleOptions: ?ModuleOptions,
extraNodeModules: mixed,
useWatchman: boolean,
maxWorkers: number,
resetCache: boolean,
}) { }) {
this._opts = { this._opts = {
roots, roots,
@ -187,6 +251,7 @@ class DependencyGraph {
const error = new Error( const error = new Error(
`Failed to build DependencyGraph: ${err.message}` `Failed to build DependencyGraph: ${err.message}`
); );
/* $FlowFixMe: monkey-patching */
error.type = ERROR_BUILDING_DEP_GRAPH; error.type = ERROR_BUILDING_DEP_GRAPH;
error.stack = err.stack; error.stack = err.stack;
throw error; throw error;
@ -201,7 +266,7 @@ class DependencyGraph {
* Returns a promise with the direct dependencies the module associated to * Returns a promise with the direct dependencies the module associated to
* the given entryPath has. * the given entryPath has.
*/ */
getShallowDependencies(entryPath, transformOptions) { getShallowDependencies(entryPath: string, transformOptions: mixed) {
return this._moduleCache return this._moduleCache
.getModule(entryPath) .getModule(entryPath)
.getDependencies(transformOptions); .getDependencies(transformOptions);
@ -214,7 +279,7 @@ class DependencyGraph {
/** /**
* Returns the module object for the given path. * Returns the module object for the given path.
*/ */
getModuleForPath(entryFile) { getModuleForPath(entryFile: string) {
return this._moduleCache.getModule(entryFile); return this._moduleCache.getModule(entryFile);
} }
@ -228,6 +293,12 @@ class DependencyGraph {
transformOptions, transformOptions,
onProgress, onProgress,
recursive = true, recursive = true,
}: {
entryPath: string,
platform: string,
transformOptions: mixed,
onProgress: () => void,
recursive: boolean,
}) { }) {
return this.load().then(() => { return this.load().then(() => {
platform = this._getRequestPlatform(entryPath, platform); platform = this._getRequestPlatform(entryPath, platform);
@ -258,11 +329,11 @@ class DependencyGraph {
}); });
} }
matchFilesByPattern(pattern) { matchFilesByPattern(pattern: RegExp) {
return this.load().then(() => this._fastfs.matchFilesByPattern(pattern)); return this.load().then(() => this._fastfs.matchFilesByPattern(pattern));
} }
_getRequestPlatform(entryPath, platform) { _getRequestPlatform(entryPath: string, platform: string) {
if (platform == null) { if (platform == null) {
platform = getPlatformExtension(entryPath, this._opts.platforms); platform = getPlatformExtension(entryPath, this._opts.platforms);
} else if (!this._opts.platforms.has(platform)) { } else if (!this._opts.platforms.has(platform)) {
@ -322,16 +393,30 @@ class DependencyGraph {
} }
return this._loading; return this._loading;
}; };
/* $FlowFixMe: there is a risk this happen before we assign that
* variable in the load() function. */
this._loading = this._loading.then(resolve, resolve); this._loading = this._loading.then(resolve, resolve);
} }
createPolyfill(options) { createPolyfill(options: {file: string}) {
return this._moduleCache.createPolyfill(options); return this._moduleCache.createPolyfill(options);
} }
getHasteMap() { getHasteMap() {
return this._hasteMap; return this._hasteMap;
} }
static Cache;
static Fastfs;
static FileWatcher;
static Module;
static Polyfill;
static extractRequires;
static getAssetDataFromName;
static getPlatformExtension;
static replacePatterns;
static getInverseDependencies;
} }
Object.assign(DependencyGraph, { Object.assign(DependencyGraph, {
@ -348,6 +433,7 @@ Object.assign(DependencyGraph, {
}); });
function NotFoundError() { function NotFoundError() {
/* $FlowFixMe: monkey-patching */
Error.call(this); Error.call(this);
Error.captureStackTrace(this, this.constructor); Error.captureStackTrace(this, this.constructor);
var msg = util.format.apply(util, arguments); var msg = util.format.apply(util, arguments);