packager: remove Cache

Summary: It seems we don't need that one much anymore, as we have a FS-based cache for files, and removing the last callsites doesn't really change perf, as we have to read these files eventually (plus some of these are read from `HasteMap`, that I believe is already dead code).

Reviewed By: davidaurelio

Differential Revision: D4884220

fbshipit-source-id: 4cf59f16a6f0bdf275abe81e9de2f34816866bae
This commit is contained in:
Jean Lauliac 2017-04-18 09:26:57 -07:00 committed by Facebook Github Bot
parent c0533fc57c
commit edcaf438a7
12 changed files with 28 additions and 764 deletions

View File

@ -15,7 +15,6 @@ const assert = require('assert');
const crypto = require('crypto');
const debug = require('debug')('RNP:Bundler');
const fs = require('fs');
const Cache = require('../node-haste').Cache;
const Transformer = require('../JSTransformer');
const Resolver = require('../Resolver');
const Bundle = require('./Bundle');
@ -114,7 +113,6 @@ class Bundler {
_opts: Options;
_getModuleId: (opts: Module) => number;
_cache: Cache;
_transformer: Transformer;
_resolverPromise: Promise<Resolver>;
_projectRoots: Array<string>;
@ -165,11 +163,6 @@ class Bundler {
debug(`Using transform cache key "${transformCacheKey}"`);
this._cache = new Cache({
resetCache: opts.resetCache,
cacheKey: transformCacheKey,
});
const maxWorkerCount = Bundler.getMaxWorkerCount();
/* $FlowFixMe: in practice it's always here. */
@ -182,7 +175,6 @@ class Bundler {
this._resolverPromise = Resolver.load({
assetExts: opts.assetExts,
blacklistRE: opts.blacklistRE,
cache: this._cache,
extraNodeModules: opts.extraNodeModules,
getTransformCacheKey,
globalTransformCache: opts.globalTransformCache,
@ -213,12 +205,9 @@ class Bundler {
end() {
this._transformer.kill();
return Promise.all([
this._cache.end(),
this._resolverPromise.then(
resolver => resolver.getDependencyGraph().getWatcher().end(),
),
]);
return this._resolverPromise.then(
resolver => resolver.getDependencyGraph().getWatcher().end(),
);
}
bundle(options: {
@ -478,10 +467,6 @@ class Bundler {
});
}
invalidateFile(filePath: string) {
this._cache.invalidate(filePath);
}
getShallowDependencies({
entryFile,
platform,

View File

@ -22,7 +22,6 @@ import type {SourceMap} from '../lib/SourceMap';
import type {Options as TransformOptions} from '../JSTransformer/worker/worker';
import type {Reporter} from '../lib/reporting';
import type {TransformCode} from '../node-haste/Module';
import type Cache from '../node-haste/Cache';
import type {GetTransformCacheKey} from '../lib/TransformCache';
import type {GlobalTransformCache} from '../lib/GlobalTransformCache';
@ -32,7 +31,6 @@ type MinifyCode = (filePath: string, code: string, map: SourceMap) =>
type Options = {|
+assetExts: Array<string>,
+blacklistRE?: RegExp,
+cache: Cache,
+extraNodeModules: ?{},
+getTransformCacheKey: GetTransformCacheKey,
+globalTransformCache: ?GlobalTransformCache,

View File

@ -220,15 +220,6 @@ describe('processRequest', () => {
});
describe('file changes', () => {
it('invalides files in bundle when file is updated', () => {
return makeRequest(
requestHandler,
'mybundle.bundle?runModule=true'
).then(() => {
server.onFileChange('all', options.projectRoots[0] + '/path/file.js');
expect(invalidatorFunc.mock.calls[0][0]).toEqual('root/path/file.js');
});
});
it('does not rebuild the bundles that contain a file when that file is changed', () => {
const bundleFunc = jest.fn();

View File

@ -329,7 +329,6 @@ class Server {
onFileChange(type: string, filePath: string, stat: Stats) {
this._assetServer.onFileChange(type, filePath, stat);
this._bundler.invalidateFile(filePath);
// If Hot Loading is enabled avoid rebuilding bundles and sending live
// updates. Instead, send the HMR updates right away and clear the bundles

View File

@ -1,20 +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.
*/
'use strict';
class Cache {
get(filepath, field, cb) {
return cb(filepath);
}
invalidate(filepath) { }
end() { }
}
module.exports = Cache;

View File

@ -1,360 +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.
*/
'use strict';
jest
.dontMock('absolute-path')
.dontMock('../');
jest
.mock('fs')
.setMock('os', {
tmpdir() { return 'tmpdir'; },
});
jest.useRealTimers();
describe('Cache', () => {
let Cache, fs;
beforeEach(() => {
Cache = require('../');
fs = require('graceful-fs');
});
describe('getting/setting', () => {
it('calls loader callback for uncached file', () => {
fs.stat.mockImplementation((file, callback) => {
callback(null, {
mtime: {
getTime: () => {},
},
});
});
var cache = new Cache({
cacheKey: 'cache',
});
var loaderCb = jest.genMockFn().mockImplementation(() => Promise.resolve());
return cache
.get('/rootDir/someFile', 'field', loaderCb)
.then($ =>
expect(loaderCb).toBeCalledWith('/rootDir/someFile')
);
});
it('supports storing multiple fields', () => {
fs.stat.mockImplementation((file, callback) => {
callback(null, {
mtime: {
getTime: () => {},
},
});
});
var cache = new Cache({
cacheKey: 'cache',
});
var index = 0;
var loaderCb = jest.genMockFn().mockImplementation(() =>
Promise.resolve(index++)
);
return cache
.get('/rootDir/someFile', 'field1', loaderCb)
.then(value => {
expect(value).toBe(0);
return cache
.get('/rootDir/someFile', 'field2', loaderCb)
.then(value2 => expect(value2).toBe(1));
});
});
it('gets the value from the loader callback', () => {
fs.stat.mockImplementation((file, callback) =>
callback(null, {
mtime: {
getTime: () => {},
},
})
);
var cache = new Cache({
cacheKey: 'cache',
});
var loaderCb = jest.genMockFn().mockImplementation(() =>
Promise.resolve('lol')
);
return cache
.get('/rootDir/someFile', 'field', loaderCb)
.then(value => expect(value).toBe('lol'));
});
it('caches the value after the first call', () => {
fs.stat.mockImplementation((file, callback) => {
callback(null, {
mtime: {
getTime: () => {},
},
});
});
var cache = new Cache({
cacheKey: 'cache',
});
var loaderCb = jest.genMockFn().mockImplementation(() =>
Promise.resolve('lol')
);
return cache
.get('/rootDir/someFile', 'field', loaderCb)
.then(() => {
var shouldNotBeCalled = jest.genMockFn();
return cache.get('/rootDir/someFile', 'field', shouldNotBeCalled)
.then(value => {
expect(shouldNotBeCalled).not.toBeCalled();
expect(value).toBe('lol');
});
});
});
it('clears old field when getting new field and mtime changed', () => {
var mtime = 0;
fs.stat.mockImplementation((file, callback) => {
callback(null, {
mtime: {
getTime: () => mtime++,
},
});
});
var cache = new Cache({
cacheKey: 'cache',
});
var loaderCb = jest.genMockFn().mockImplementation(() =>
Promise.resolve('lol' + mtime)
);
return cache
.get('/rootDir/someFile', 'field1', loaderCb)
.then(value => cache
.get('/rootDir/someFile', 'field2', loaderCb)
.then(value2 => cache
.get('/rootDir/someFile', 'field1', loaderCb)
.then(value3 => expect(value3).toBe('lol2'))
)
);
});
it('does not cache rejections', () => {
fs.stat.mockImplementation((file, callback) => {
callback(null, {
mtime: {
getTime: () => {},
},
});
});
var cache = new Cache({
cacheKey: 'cache',
});
var loaderCb = () => Promise.reject('lol');
return cache
.get('/rootDir/someFile', 'field', loaderCb)
.catch(() => {
var shouldBeCalled = jest.fn(() => Promise.resolve());
const assert = value => expect(shouldBeCalled).toBeCalled();
return cache.get('/rootDir/someFile', 'field', shouldBeCalled)
.then(assert, assert);
});
});
});
describe('loading cache from disk', () => {
var fileStats;
beforeEach(() => {
fileStats = {
'/rootDir/someFile': {
mtime: {
getTime: () => 22,
},
},
'/rootDir/foo': {
mtime: {
getTime: () => 11,
},
},
};
fs.existsSync.mockImplementation(() => true);
fs.statSync.mockImplementation(filePath => fileStats[filePath]);
fs.readFileSync.mockImplementation(() => JSON.stringify({
'/rootDir/someFile': {
metadata: {mtime: 22},
data: {field: 'oh hai'},
},
'/rootDir/foo': {
metadata: {mtime: 11},
data: {field: 'lol wat'},
},
}));
});
it('should load cache from disk', () => {
var cache = new Cache({
cacheKey: 'cache',
});
var loaderCb = jest.genMockFn();
return cache
.get('/rootDir/someFile', 'field', loaderCb)
.then(value => {
expect(loaderCb).not.toBeCalled();
expect(value).toBe('oh hai');
return cache
.get('/rootDir/foo', 'field', loaderCb)
.then(val => {
expect(loaderCb).not.toBeCalled();
expect(val).toBe('lol wat');
});
});
});
it('should not load outdated cache', () => {
fs.stat.mockImplementation((file, callback) =>
callback(null, {
mtime: {
getTime: () => {},
},
})
);
fileStats['/rootDir/foo'].mtime.getTime = () => 123;
var cache = new Cache({
cacheKey: 'cache',
});
var loaderCb = jest.genMockFn().mockImplementation(() =>
Promise.resolve('new value')
);
return cache
.get('/rootDir/someFile', 'field', loaderCb)
.then(value => {
expect(loaderCb).not.toBeCalled();
expect(value).toBe('oh hai');
return cache
.get('/rootDir/foo', 'field', loaderCb)
.then(val => {
expect(loaderCb).toBeCalled();
expect(val).toBe('new value');
});
});
});
});
describe('writing cache to disk', () => {
it('should write cache to disk', done => {
var index = 0;
var mtimes = [10, 20, 30];
fs.stat.mockImplementation((file, callback) =>
callback(null, {
mtime: {
getTime: () => mtimes[index++],
},
})
);
var cache = new Cache({
cacheKey: 'cache',
});
cache.get('/rootDir/bar', 'field', () =>
Promise.resolve('bar value')
);
cache.get('/rootDir/foo', 'field', () =>
Promise.resolve('foo value')
);
cache.get('/rootDir/baz', 'field', () =>
Promise.resolve('baz value')
);
setTimeout(() => {
expect(fs.writeFile).toBeCalled();
done();
}, 2020);
});
});
describe('check for cache presence', () => {
it('synchronously resolves cache presence', () => {
fs.stat.mockImplementation((file, callback) =>
callback(null, {
mtime: {
getTime: () => {},
},
})
);
var cache = new Cache({
cacheKey: 'cache',
});
var loaderCb = jest.genMockFn().mockImplementation(() =>
Promise.resolve('banana')
);
var file = '/rootDir/someFile';
return cache
.get(file, 'field', loaderCb)
.then(() => {
expect(cache.has(file)).toBe(true);
expect(cache.has(file, 'field')).toBe(true);
expect(cache.has(file, 'foo')).toBe(false);
});
});
});
describe('invalidate', () => {
it('invalidates the cache per file or per-field', () => {
fs.stat.mockImplementation((file, callback) =>
callback(null, {
mtime: {
getTime: () => {},
},
})
);
var cache = new Cache({
cacheKey: 'cache',
});
var loaderCb = jest.genMockFn().mockImplementation(() =>
Promise.resolve('banana')
);
var file = '/rootDir/someFile';
return cache.get(file, 'field', loaderCb).then(() => {
expect(cache.has(file)).toBe(true);
cache.invalidate(file, 'field');
expect(cache.has(file)).toBe(true);
expect(cache.has(file, 'field')).toBe(false);
cache.invalidate(file);
expect(cache.has(file)).toBe(false);
});
});
});
});

View File

@ -1,254 +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
*/
'use strict';
const crypto = require('crypto');
const denodeify = require('denodeify');
const fs = require('graceful-fs');
const isAbsolutePath = require('absolute-path');
const path = require('path');
const tmpDir = require('os').tmpdir();
function getObjectValues<T>(object: {[key: string]: T}): Array<T> {
return Object.keys(object).map(key => object[key]);
}
function debounce(fn, delay) {
var timeout;
return () => {
clearTimeout(timeout);
timeout = setTimeout(fn, delay);
};
}
type Record = {
data: {[field: string]: Promise<mixed>},
metadata: {[field: string]: Promise<mixed>},
};
class Cache {
_cacheFilePath: string;
_data: {[filename: string]: Record};
_persistEventually: () => void;
_persisting: ?Promise<boolean> | void;
constructor({
resetCache,
cacheKey,
cacheDirectory = tmpDir,
}: {
resetCache: boolean,
cacheKey: string,
cacheDirectory?: string,
}) {
this._cacheFilePath = Cache.getCacheFilePath(cacheDirectory, cacheKey);
if (!resetCache) {
this._data = this._loadCacheSync(this._cacheFilePath);
} else {
this._data = Object.create(null);
}
this._persistEventually = debounce(this._persistCache.bind(this), 2000);
}
static getCacheFilePath(tmpdir, ...args) {
const hash = crypto.createHash('md5');
args.forEach(arg => hash.update(arg));
return path.join(tmpdir, hash.digest('hex'));
}
get<T>(
filepath: string,
field: string,
loaderCb: (filepath: string) => Promise<T>,
): Promise<T> {
if (!isAbsolutePath(filepath)) {
throw new Error('Use absolute paths');
}
return this.has(filepath, 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));
}
invalidate(filepath: string, field: ?string) {
if (this.has(filepath, field)) {
if (field == null) {
delete this._data[filepath];
} else {
delete this._data[filepath].data[field];
}
}
}
end() {
return this._persistCache();
}
has(filepath: string, field: ?string) {
return Object.prototype.hasOwnProperty.call(this._data, filepath) &&
(field == null || Object.prototype.hasOwnProperty.call(this._data[filepath].data, field));
}
set<T>(
filepath: string,
field: string,
loaderPromise: Promise<T>,
): Promise<T> {
let record = this._data[filepath];
if (!record) {
// $FlowFixMe: temporarily invalid record.
record = (Object.create(null): Record);
this._data[filepath] = record;
this._data[filepath].data = Object.create(null);
this._data[filepath].metadata = Object.create(null);
}
const cachedPromise = record.data[field] = loaderPromise
.then(data => Promise.all([
data,
denodeify(fs.stat)(filepath),
]))
.then(([data, stat]) => {
this._persistEventually();
// Evict all existing field data from the cache if we're putting new
// more up to date data
var mtime = stat.mtime.getTime();
if (record.metadata.mtime !== mtime) {
record.data = Object.create(null);
}
record.metadata.mtime = mtime;
return data;
});
// don't cache rejected promises
cachedPromise.catch(error => delete record.data[field]);
return cachedPromise;
}
_persistCache() {
if (this._persisting != null) {
return this._persisting;
}
const data = this._data;
const cacheFilepath = this._cacheFilePath;
const allPromises = getObjectValues(data)
.map(record => {
const fieldNames = Object.keys(record.data);
const fieldValues = getObjectValues(record.data);
return Promise
.all(fieldValues)
.then(ref => {
// $FlowFixMe: temporarily invalid record.
const ret = (Object.create(null): Record);
ret.metadata = record.metadata;
ret.data = Object.create(null);
/* $FlowFixMe(>=0.36.0 site=react_native_fb,react_native_oss) Flow
* error detected during the deploy of Flow v0.36.0. To see the
* error, remove this comment and run Flow */
fieldNames.forEach((field, index) =>
ret.data[field] = ref[index]
);
return ret;
});
}
);
this._persisting = Promise.all(allPromises)
.then(values => {
const json = Object.create(null);
Object.keys(data).forEach((key, i) => {
// make sure the key wasn't added nor removed after we started
// persisting the cache
const value = values[i];
if (!value) {
return;
}
json[key] = Object.create(null);
json[key].metadata = data[key].metadata;
json[key].data = value.data;
});
return denodeify(fs.writeFile)(cacheFilepath, JSON.stringify(json));
})
.catch(e => console.error(
'[node-haste] Encountered an error while persisting cache:\n%s',
e.stack.split('\n').map(line => '> ' + line).join('\n')
))
.then(() => {
this._persisting = null;
return true;
});
return this._persisting;
}
_loadCacheSync(cachePath) {
var ret = Object.create(null);
var cacheOnDisk = loadCacheSync(cachePath);
// Filter outdated cache and convert to promises.
Object.keys(cacheOnDisk).forEach(key => {
if (!fs.existsSync(key)) {
return;
}
var record = cacheOnDisk[key];
var stat = fs.statSync(key);
if (stat.mtime.getTime() === record.metadata.mtime) {
ret[key] = Object.create(null);
ret[key].metadata = Object.create(null);
ret[key].data = Object.create(null);
// $FlowFixMe: we should maybe avoid Object.create().
ret[key].metadata.mtime = record.metadata.mtime;
Object.keys(record.data).forEach(field => {
ret[key].data[field] = Promise.resolve(record.data[field]);
});
}
});
return ret;
}
}
function loadCacheSync(cachePath) {
if (!fs.existsSync(cachePath)) {
return Object.create(null);
}
try {
return JSON.parse(fs.readFileSync(cachePath, 'utf8'));
} catch (e) {
if (e instanceof SyntaxError) {
console.warn('Unable to parse cache file. Will clear and continue.');
try {
fs.unlinkSync(cachePath);
} catch (err) {
// Someone else might've deleted it.
}
return Object.create(null);
}
throw e;
}
}
module.exports = Cache;

View File

@ -28,7 +28,6 @@ import type {SourceMap} from '../lib/SourceMap';
import type {GetTransformCacheKey} from '../lib/TransformCache';
import type {ReadTransformProps} from '../lib/TransformCache';
import type {Reporter} from '../lib/reporting';
import type Cache from './Cache';
import type DependencyGraphHelpers from './DependencyGraph/DependencyGraphHelpers';
import type ModuleCache from './ModuleCache';
@ -68,7 +67,6 @@ export type Options = {
};
export type ConstructorArgs = {
cache: Cache,
depGraphHelpers: DependencyGraphHelpers,
globalTransformCache: ?GlobalTransformCache,
file: string,
@ -87,7 +85,6 @@ class Module {
type: string;
_moduleCache: ModuleCache;
_cache: Cache;
_transformCode: ?TransformCode;
_getTransformCacheKey: GetTransformCacheKey;
_depGraphHelpers: DependencyGraphHelpers;
@ -103,7 +100,6 @@ class Module {
_readResultsByOptionsKey: Map<string, CachedReadResult>;
constructor({
cache,
depGraphHelpers,
file,
getTransformCacheKey,
@ -121,7 +117,6 @@ class Module {
this.type = 'Module';
this._moduleCache = moduleCache;
this._cache = cache;
this._transformCode = transformCode;
this._getTransformCacheKey = getTransformCacheKey;
this._depGraphHelpers = depGraphHelpers;
@ -134,11 +129,7 @@ class Module {
}
isHaste(): Promise<boolean> {
return this._cache.get(
this.path,
'isHaste',
() => Promise.resolve().then(() => this._getHasteName() != null),
);
return Promise.resolve().then(() => this._getHasteName() != null);
}
getCode(transformOptions: TransformOptions) {
@ -150,32 +141,28 @@ class Module {
}
getName(): Promise<string> {
return this._cache.get(
this.path,
'name',
() => Promise.resolve().then(() => {
const name = this._getHasteName();
if (name != null) {
return name;
}
return Promise.resolve().then(() => {
const name = this._getHasteName();
if (name != null) {
return name;
}
const p = this.getPackage();
const p = this.getPackage();
if (!p) {
// Name is full path
return this.path;
}
if (!p) {
// Name is full path
return this.path;
}
return p.getName()
.then(packageName => {
if (!packageName) {
return this.path;
}
return p.getName()
.then(packageName => {
if (!packageName) {
return this.path;
}
return joinPath(packageName, relativePath(p.root, this.path)).replace(/\\/g, '/');
});
})
);
return joinPath(packageName, relativePath(p.root, this.path)).replace(/\\/g, '/');
});
});
}
getPackage() {
@ -192,7 +179,6 @@ class Module {
* code.
*/
invalidate() {
this._cache.invalidate(this.path);
this._readPromises.clear();
this._readResultsByOptionsKey.clear();
this._sourceCode = null;

View File

@ -19,7 +19,6 @@ const Polyfill = require('./Polyfill');
import type {GlobalTransformCache} from '../lib/GlobalTransformCache';
import type {GetTransformCacheKey} from '../lib/TransformCache';
import type {Reporter} from '../lib/reporting';
import type Cache from './Cache';
import type DependencyGraphHelpers from './DependencyGraph/DependencyGraphHelpers';
import type {TransformCode, Options as ModuleOptions} from './Module';
@ -28,7 +27,6 @@ type GetClosestPackageFn = (filePath: string) => ?string;
class ModuleCache {
_assetDependencies: Array<string>;
_cache: Cache;
_depGraphHelpers: DependencyGraphHelpers;
_getClosestPackage: GetClosestPackageFn;
_getTransformCacheKey: GetTransformCacheKey;
@ -43,7 +41,6 @@ class ModuleCache {
constructor({
assetDependencies,
cache,
depGraphHelpers,
extractRequires,
getClosestPackage,
@ -54,7 +51,6 @@ class ModuleCache {
transformCode,
}: {
assetDependencies: Array<string>,
cache: Cache,
depGraphHelpers: DependencyGraphHelpers,
getClosestPackage: GetClosestPackageFn,
getTransformCacheKey: GetTransformCacheKey,
@ -67,7 +63,6 @@ class ModuleCache {
this._getClosestPackage = getClosestPackage;
this._getTransformCacheKey = getTransformCacheKey;
this._globalTransformCache = globalTransformCache;
this._cache = cache;
this._depGraphHelpers = depGraphHelpers;
this._moduleCache = Object.create(null);
this._moduleOptions = moduleOptions;
@ -81,7 +76,6 @@ class ModuleCache {
getModule(filePath: string): Module {
if (!this._moduleCache[filePath]) {
this._moduleCache[filePath] = new Module({
cache: this._cache,
depGraphHelpers: this._depGraphHelpers,
file: filePath,
getTransformCacheKey: this._getTransformCacheKey,
@ -107,7 +101,6 @@ class ModuleCache {
this._moduleCache[filePath] = new AssetModule({
file: filePath,
moduleCache: this,
cache: this._cache,
dependencies: this._assetDependencies,
}, this._platforms);
}
@ -118,7 +111,6 @@ class ModuleCache {
if (!this._packageCache[filePath]) {
this._packageCache[filePath] = new Package({
file: filePath,
cache: this._cache,
});
}
return this._packageCache[filePath];
@ -148,7 +140,6 @@ class ModuleCache {
/* $FlowFixMe: there are missing arguments. */
return new Polyfill({
file,
cache: this._cache,
depGraphHelpers: this._depGraphHelpers,
getTransformCacheKey: this._getTransformCacheKey,
moduleCache: this,

View File

@ -15,8 +15,6 @@ const fs = require('fs');
const isAbsolutePath = require('absolute-path');
const path = require('path');
import type Cache from './Cache';
type PackageContent = {
name: string,
'react-native': mixed,
@ -29,18 +27,15 @@ class Package {
path: string;
root: string;
type: string;
_cache: Cache;
_content: ?PackageContent;
constructor({file, cache}: {
constructor({file}: {
file: string,
cache: Cache,
}) {
this.path = path.resolve(file);
this.root = path.dirname(this.path);
this.type = 'Package';
this._cache = cache;
this._content = null;
}
@ -65,20 +60,16 @@ class Package {
return path.join(this.root, main);
}
isHaste() {
return this._cache.get(this.path, 'package-haste', () =>
Promise.resolve().then(() => !!this.read().name)
);
isHaste(): Promise<boolean> {
return Promise.resolve().then(() => !!this.read().name);
}
getName(): Promise<string> {
return this._cache.get(this.path, 'package-name', () =>
Promise.resolve().then(() => this.read().name)
);
return Promise.resolve().then(() => this.read().name);
}
invalidate() {
this._cache.invalidate(this.path);
this._content = null;
}
redirectRequire(name: string): string | false {

View File

@ -63,46 +63,8 @@ describe('DependencyGraph', function() {
Module = require('../Module');
ResolutionRequest = require('../DependencyGraph/ResolutionRequest');
const Cache = jest.genMockFn().mockImplementation(function() {
this._maps = Object.create(null);
});
Cache.prototype.has = jest.genMockFn()
.mockImplementation(function(filepath, field) {
if (!(filepath in this._maps)) {
return false;
}
return !field || field in this._maps[filepath];
});
Cache.prototype.get = jest.genMockFn()
.mockImplementation(function(filepath, field, factory) {
let cacheForPath = this._maps[filepath];
if (this.has(filepath, field)) {
return field ? cacheForPath[field] : cacheForPath;
}
if (!cacheForPath) {
cacheForPath = this._maps[filepath] = Object.create(null);
}
const value = cacheForPath[field] = factory();
return value;
});
Cache.prototype.invalidate = jest.genMockFn()
.mockImplementation(function(filepath, field) {
if (!this.has(filepath, field)) {
return;
}
if (field) {
delete this._maps[filepath][field];
} else {
delete this._maps[filepath];
}
});
Cache.prototype.end = jest.genMockFn();
defaults = {
assetExts: ['png', 'jpg'],
cache: new Cache(),
extensions: ['js', 'json'],
forceNodeFilesystemAPI: true,
providesModuleNodeModules: [
@ -4970,7 +4932,7 @@ describe('DependencyGraph', function() {
},
{
dependencies: [],
id: 'aPackage/main.js',
id: 'bPackage/main.js',
isAsset: false,
isJSON: false,
isPolyfill: false,

View File

@ -11,7 +11,6 @@
'use strict';
const Cache = require('./Cache');
const DependencyGraphHelpers = require('./DependencyGraph/DependencyGraphHelpers');
const FilesByDirNameIndex = require('./FilesByDirNameIndex');
const JestHasteMap = require('jest-haste-map');
@ -52,7 +51,6 @@ import type {HasteFS} from './types';
type Options = {|
+assetDependencies: Array<string>,
+assetExts: Array<string>,
+cache: Cache,
+extensions: Array<string>,
+extraNodeModules: ?{},
+forceNodeFilesystemAPI: boolean,
@ -164,7 +162,6 @@ class DependencyGraph extends EventEmitter {
_createModuleCache() {
const {_opts} = this;
return new ModuleCache({
cache: _opts.cache,
getTransformCacheKey: _opts.getTransformCacheKey,
globalTransformCache: _opts.globalTransformCache,
transformCode: _opts.transformCode,
@ -290,7 +287,6 @@ class DependencyGraph extends EventEmitter {
return this._moduleCache.createPolyfill(options);
}
static Cache;
static Module;
static Polyfill;
static getAssetDataFromName;
@ -301,7 +297,6 @@ class DependencyGraph extends EventEmitter {
}
Object.assign(DependencyGraph, {
Cache,
Module,
Polyfill,
getAssetDataFromName,