mirror of https://github.com/status-im/metro.git
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:
parent
c0533fc57c
commit
edcaf438a7
|
@ -15,7 +15,6 @@ const assert = require('assert');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const debug = require('debug')('RNP:Bundler');
|
const debug = require('debug')('RNP:Bundler');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const Cache = require('../node-haste').Cache;
|
|
||||||
const Transformer = require('../JSTransformer');
|
const Transformer = require('../JSTransformer');
|
||||||
const Resolver = require('../Resolver');
|
const Resolver = require('../Resolver');
|
||||||
const Bundle = require('./Bundle');
|
const Bundle = require('./Bundle');
|
||||||
|
@ -114,7 +113,6 @@ class Bundler {
|
||||||
|
|
||||||
_opts: Options;
|
_opts: Options;
|
||||||
_getModuleId: (opts: Module) => number;
|
_getModuleId: (opts: Module) => number;
|
||||||
_cache: Cache;
|
|
||||||
_transformer: Transformer;
|
_transformer: Transformer;
|
||||||
_resolverPromise: Promise<Resolver>;
|
_resolverPromise: Promise<Resolver>;
|
||||||
_projectRoots: Array<string>;
|
_projectRoots: Array<string>;
|
||||||
|
@ -165,11 +163,6 @@ class Bundler {
|
||||||
|
|
||||||
debug(`Using transform cache key "${transformCacheKey}"`);
|
debug(`Using transform cache key "${transformCacheKey}"`);
|
||||||
|
|
||||||
this._cache = new Cache({
|
|
||||||
resetCache: opts.resetCache,
|
|
||||||
cacheKey: transformCacheKey,
|
|
||||||
});
|
|
||||||
|
|
||||||
const maxWorkerCount = Bundler.getMaxWorkerCount();
|
const maxWorkerCount = Bundler.getMaxWorkerCount();
|
||||||
|
|
||||||
/* $FlowFixMe: in practice it's always here. */
|
/* $FlowFixMe: in practice it's always here. */
|
||||||
|
@ -182,7 +175,6 @@ class Bundler {
|
||||||
this._resolverPromise = Resolver.load({
|
this._resolverPromise = Resolver.load({
|
||||||
assetExts: opts.assetExts,
|
assetExts: opts.assetExts,
|
||||||
blacklistRE: opts.blacklistRE,
|
blacklistRE: opts.blacklistRE,
|
||||||
cache: this._cache,
|
|
||||||
extraNodeModules: opts.extraNodeModules,
|
extraNodeModules: opts.extraNodeModules,
|
||||||
getTransformCacheKey,
|
getTransformCacheKey,
|
||||||
globalTransformCache: opts.globalTransformCache,
|
globalTransformCache: opts.globalTransformCache,
|
||||||
|
@ -213,12 +205,9 @@ class Bundler {
|
||||||
|
|
||||||
end() {
|
end() {
|
||||||
this._transformer.kill();
|
this._transformer.kill();
|
||||||
return Promise.all([
|
return this._resolverPromise.then(
|
||||||
this._cache.end(),
|
resolver => resolver.getDependencyGraph().getWatcher().end(),
|
||||||
this._resolverPromise.then(
|
);
|
||||||
resolver => resolver.getDependencyGraph().getWatcher().end(),
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bundle(options: {
|
bundle(options: {
|
||||||
|
@ -478,10 +467,6 @@ class Bundler {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidateFile(filePath: string) {
|
|
||||||
this._cache.invalidate(filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
getShallowDependencies({
|
getShallowDependencies({
|
||||||
entryFile,
|
entryFile,
|
||||||
platform,
|
platform,
|
||||||
|
|
|
@ -22,7 +22,6 @@ import type {SourceMap} from '../lib/SourceMap';
|
||||||
import type {Options as TransformOptions} from '../JSTransformer/worker/worker';
|
import type {Options as TransformOptions} from '../JSTransformer/worker/worker';
|
||||||
import type {Reporter} from '../lib/reporting';
|
import type {Reporter} from '../lib/reporting';
|
||||||
import type {TransformCode} from '../node-haste/Module';
|
import type {TransformCode} from '../node-haste/Module';
|
||||||
import type Cache from '../node-haste/Cache';
|
|
||||||
import type {GetTransformCacheKey} from '../lib/TransformCache';
|
import type {GetTransformCacheKey} from '../lib/TransformCache';
|
||||||
import type {GlobalTransformCache} from '../lib/GlobalTransformCache';
|
import type {GlobalTransformCache} from '../lib/GlobalTransformCache';
|
||||||
|
|
||||||
|
@ -32,7 +31,6 @@ type MinifyCode = (filePath: string, code: string, map: SourceMap) =>
|
||||||
type Options = {|
|
type Options = {|
|
||||||
+assetExts: Array<string>,
|
+assetExts: Array<string>,
|
||||||
+blacklistRE?: RegExp,
|
+blacklistRE?: RegExp,
|
||||||
+cache: Cache,
|
|
||||||
+extraNodeModules: ?{},
|
+extraNodeModules: ?{},
|
||||||
+getTransformCacheKey: GetTransformCacheKey,
|
+getTransformCacheKey: GetTransformCacheKey,
|
||||||
+globalTransformCache: ?GlobalTransformCache,
|
+globalTransformCache: ?GlobalTransformCache,
|
||||||
|
|
|
@ -220,15 +220,6 @@ describe('processRequest', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('file changes', () => {
|
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', () => {
|
it('does not rebuild the bundles that contain a file when that file is changed', () => {
|
||||||
const bundleFunc = jest.fn();
|
const bundleFunc = jest.fn();
|
||||||
|
|
|
@ -329,7 +329,6 @@ class Server {
|
||||||
|
|
||||||
onFileChange(type: string, filePath: string, stat: Stats) {
|
onFileChange(type: string, filePath: string, stat: Stats) {
|
||||||
this._assetServer.onFileChange(type, filePath, stat);
|
this._assetServer.onFileChange(type, filePath, stat);
|
||||||
this._bundler.invalidateFile(filePath);
|
|
||||||
|
|
||||||
// If Hot Loading is enabled avoid rebuilding bundles and sending live
|
// If Hot Loading is enabled avoid rebuilding bundles and sending live
|
||||||
// updates. Instead, send the HMR updates right away and clear the bundles
|
// updates. Instead, send the HMR updates right away and clear the bundles
|
||||||
|
|
|
@ -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;
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -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;
|
|
|
@ -28,7 +28,6 @@ import type {SourceMap} from '../lib/SourceMap';
|
||||||
import type {GetTransformCacheKey} from '../lib/TransformCache';
|
import type {GetTransformCacheKey} from '../lib/TransformCache';
|
||||||
import type {ReadTransformProps} from '../lib/TransformCache';
|
import type {ReadTransformProps} from '../lib/TransformCache';
|
||||||
import type {Reporter} from '../lib/reporting';
|
import type {Reporter} from '../lib/reporting';
|
||||||
import type Cache from './Cache';
|
|
||||||
import type DependencyGraphHelpers from './DependencyGraph/DependencyGraphHelpers';
|
import type DependencyGraphHelpers from './DependencyGraph/DependencyGraphHelpers';
|
||||||
import type ModuleCache from './ModuleCache';
|
import type ModuleCache from './ModuleCache';
|
||||||
|
|
||||||
|
@ -68,7 +67,6 @@ export type Options = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ConstructorArgs = {
|
export type ConstructorArgs = {
|
||||||
cache: Cache,
|
|
||||||
depGraphHelpers: DependencyGraphHelpers,
|
depGraphHelpers: DependencyGraphHelpers,
|
||||||
globalTransformCache: ?GlobalTransformCache,
|
globalTransformCache: ?GlobalTransformCache,
|
||||||
file: string,
|
file: string,
|
||||||
|
@ -87,7 +85,6 @@ class Module {
|
||||||
type: string;
|
type: string;
|
||||||
|
|
||||||
_moduleCache: ModuleCache;
|
_moduleCache: ModuleCache;
|
||||||
_cache: Cache;
|
|
||||||
_transformCode: ?TransformCode;
|
_transformCode: ?TransformCode;
|
||||||
_getTransformCacheKey: GetTransformCacheKey;
|
_getTransformCacheKey: GetTransformCacheKey;
|
||||||
_depGraphHelpers: DependencyGraphHelpers;
|
_depGraphHelpers: DependencyGraphHelpers;
|
||||||
|
@ -103,7 +100,6 @@ class Module {
|
||||||
_readResultsByOptionsKey: Map<string, CachedReadResult>;
|
_readResultsByOptionsKey: Map<string, CachedReadResult>;
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
cache,
|
|
||||||
depGraphHelpers,
|
depGraphHelpers,
|
||||||
file,
|
file,
|
||||||
getTransformCacheKey,
|
getTransformCacheKey,
|
||||||
|
@ -121,7 +117,6 @@ class Module {
|
||||||
this.type = 'Module';
|
this.type = 'Module';
|
||||||
|
|
||||||
this._moduleCache = moduleCache;
|
this._moduleCache = moduleCache;
|
||||||
this._cache = cache;
|
|
||||||
this._transformCode = transformCode;
|
this._transformCode = transformCode;
|
||||||
this._getTransformCacheKey = getTransformCacheKey;
|
this._getTransformCacheKey = getTransformCacheKey;
|
||||||
this._depGraphHelpers = depGraphHelpers;
|
this._depGraphHelpers = depGraphHelpers;
|
||||||
|
@ -134,11 +129,7 @@ class Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
isHaste(): Promise<boolean> {
|
isHaste(): Promise<boolean> {
|
||||||
return this._cache.get(
|
return Promise.resolve().then(() => this._getHasteName() != null);
|
||||||
this.path,
|
|
||||||
'isHaste',
|
|
||||||
() => Promise.resolve().then(() => this._getHasteName() != null),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getCode(transformOptions: TransformOptions) {
|
getCode(transformOptions: TransformOptions) {
|
||||||
|
@ -150,32 +141,28 @@ class Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
getName(): Promise<string> {
|
getName(): Promise<string> {
|
||||||
return this._cache.get(
|
return Promise.resolve().then(() => {
|
||||||
this.path,
|
const name = this._getHasteName();
|
||||||
'name',
|
if (name != null) {
|
||||||
() => Promise.resolve().then(() => {
|
return name;
|
||||||
const name = this._getHasteName();
|
}
|
||||||
if (name != null) {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
const p = this.getPackage();
|
const p = this.getPackage();
|
||||||
|
|
||||||
if (!p) {
|
if (!p) {
|
||||||
// Name is full path
|
// Name is full path
|
||||||
return this.path;
|
return this.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.getName()
|
return p.getName()
|
||||||
.then(packageName => {
|
.then(packageName => {
|
||||||
if (!packageName) {
|
if (!packageName) {
|
||||||
return this.path;
|
return this.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
return joinPath(packageName, relativePath(p.root, this.path)).replace(/\\/g, '/');
|
return joinPath(packageName, relativePath(p.root, this.path)).replace(/\\/g, '/');
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getPackage() {
|
getPackage() {
|
||||||
|
@ -192,7 +179,6 @@ class Module {
|
||||||
* code.
|
* code.
|
||||||
*/
|
*/
|
||||||
invalidate() {
|
invalidate() {
|
||||||
this._cache.invalidate(this.path);
|
|
||||||
this._readPromises.clear();
|
this._readPromises.clear();
|
||||||
this._readResultsByOptionsKey.clear();
|
this._readResultsByOptionsKey.clear();
|
||||||
this._sourceCode = null;
|
this._sourceCode = null;
|
||||||
|
|
|
@ -19,7 +19,6 @@ const Polyfill = require('./Polyfill');
|
||||||
import type {GlobalTransformCache} from '../lib/GlobalTransformCache';
|
import type {GlobalTransformCache} from '../lib/GlobalTransformCache';
|
||||||
import type {GetTransformCacheKey} from '../lib/TransformCache';
|
import type {GetTransformCacheKey} from '../lib/TransformCache';
|
||||||
import type {Reporter} from '../lib/reporting';
|
import type {Reporter} from '../lib/reporting';
|
||||||
import type Cache from './Cache';
|
|
||||||
import type DependencyGraphHelpers from './DependencyGraph/DependencyGraphHelpers';
|
import type DependencyGraphHelpers from './DependencyGraph/DependencyGraphHelpers';
|
||||||
import type {TransformCode, Options as ModuleOptions} from './Module';
|
import type {TransformCode, Options as ModuleOptions} from './Module';
|
||||||
|
|
||||||
|
@ -28,7 +27,6 @@ type GetClosestPackageFn = (filePath: string) => ?string;
|
||||||
class ModuleCache {
|
class ModuleCache {
|
||||||
|
|
||||||
_assetDependencies: Array<string>;
|
_assetDependencies: Array<string>;
|
||||||
_cache: Cache;
|
|
||||||
_depGraphHelpers: DependencyGraphHelpers;
|
_depGraphHelpers: DependencyGraphHelpers;
|
||||||
_getClosestPackage: GetClosestPackageFn;
|
_getClosestPackage: GetClosestPackageFn;
|
||||||
_getTransformCacheKey: GetTransformCacheKey;
|
_getTransformCacheKey: GetTransformCacheKey;
|
||||||
|
@ -43,7 +41,6 @@ class ModuleCache {
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
assetDependencies,
|
assetDependencies,
|
||||||
cache,
|
|
||||||
depGraphHelpers,
|
depGraphHelpers,
|
||||||
extractRequires,
|
extractRequires,
|
||||||
getClosestPackage,
|
getClosestPackage,
|
||||||
|
@ -54,7 +51,6 @@ class ModuleCache {
|
||||||
transformCode,
|
transformCode,
|
||||||
}: {
|
}: {
|
||||||
assetDependencies: Array<string>,
|
assetDependencies: Array<string>,
|
||||||
cache: Cache,
|
|
||||||
depGraphHelpers: DependencyGraphHelpers,
|
depGraphHelpers: DependencyGraphHelpers,
|
||||||
getClosestPackage: GetClosestPackageFn,
|
getClosestPackage: GetClosestPackageFn,
|
||||||
getTransformCacheKey: GetTransformCacheKey,
|
getTransformCacheKey: GetTransformCacheKey,
|
||||||
|
@ -67,7 +63,6 @@ class ModuleCache {
|
||||||
this._getClosestPackage = getClosestPackage;
|
this._getClosestPackage = getClosestPackage;
|
||||||
this._getTransformCacheKey = getTransformCacheKey;
|
this._getTransformCacheKey = getTransformCacheKey;
|
||||||
this._globalTransformCache = globalTransformCache;
|
this._globalTransformCache = globalTransformCache;
|
||||||
this._cache = cache;
|
|
||||||
this._depGraphHelpers = depGraphHelpers;
|
this._depGraphHelpers = depGraphHelpers;
|
||||||
this._moduleCache = Object.create(null);
|
this._moduleCache = Object.create(null);
|
||||||
this._moduleOptions = moduleOptions;
|
this._moduleOptions = moduleOptions;
|
||||||
|
@ -81,7 +76,6 @@ class ModuleCache {
|
||||||
getModule(filePath: string): Module {
|
getModule(filePath: string): Module {
|
||||||
if (!this._moduleCache[filePath]) {
|
if (!this._moduleCache[filePath]) {
|
||||||
this._moduleCache[filePath] = new Module({
|
this._moduleCache[filePath] = new Module({
|
||||||
cache: this._cache,
|
|
||||||
depGraphHelpers: this._depGraphHelpers,
|
depGraphHelpers: this._depGraphHelpers,
|
||||||
file: filePath,
|
file: filePath,
|
||||||
getTransformCacheKey: this._getTransformCacheKey,
|
getTransformCacheKey: this._getTransformCacheKey,
|
||||||
|
@ -107,7 +101,6 @@ class ModuleCache {
|
||||||
this._moduleCache[filePath] = new AssetModule({
|
this._moduleCache[filePath] = new AssetModule({
|
||||||
file: filePath,
|
file: filePath,
|
||||||
moduleCache: this,
|
moduleCache: this,
|
||||||
cache: this._cache,
|
|
||||||
dependencies: this._assetDependencies,
|
dependencies: this._assetDependencies,
|
||||||
}, this._platforms);
|
}, this._platforms);
|
||||||
}
|
}
|
||||||
|
@ -118,7 +111,6 @@ class ModuleCache {
|
||||||
if (!this._packageCache[filePath]) {
|
if (!this._packageCache[filePath]) {
|
||||||
this._packageCache[filePath] = new Package({
|
this._packageCache[filePath] = new Package({
|
||||||
file: filePath,
|
file: filePath,
|
||||||
cache: this._cache,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return this._packageCache[filePath];
|
return this._packageCache[filePath];
|
||||||
|
@ -148,7 +140,6 @@ class ModuleCache {
|
||||||
/* $FlowFixMe: there are missing arguments. */
|
/* $FlowFixMe: there are missing arguments. */
|
||||||
return new Polyfill({
|
return new Polyfill({
|
||||||
file,
|
file,
|
||||||
cache: this._cache,
|
|
||||||
depGraphHelpers: this._depGraphHelpers,
|
depGraphHelpers: this._depGraphHelpers,
|
||||||
getTransformCacheKey: this._getTransformCacheKey,
|
getTransformCacheKey: this._getTransformCacheKey,
|
||||||
moduleCache: this,
|
moduleCache: this,
|
||||||
|
|
|
@ -15,8 +15,6 @@ const fs = require('fs');
|
||||||
const isAbsolutePath = require('absolute-path');
|
const isAbsolutePath = require('absolute-path');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
import type Cache from './Cache';
|
|
||||||
|
|
||||||
type PackageContent = {
|
type PackageContent = {
|
||||||
name: string,
|
name: string,
|
||||||
'react-native': mixed,
|
'react-native': mixed,
|
||||||
|
@ -29,18 +27,15 @@ class Package {
|
||||||
path: string;
|
path: string;
|
||||||
root: string;
|
root: string;
|
||||||
type: string;
|
type: string;
|
||||||
_cache: Cache;
|
|
||||||
|
|
||||||
_content: ?PackageContent;
|
_content: ?PackageContent;
|
||||||
|
|
||||||
constructor({file, cache}: {
|
constructor({file}: {
|
||||||
file: string,
|
file: string,
|
||||||
cache: Cache,
|
|
||||||
}) {
|
}) {
|
||||||
this.path = path.resolve(file);
|
this.path = path.resolve(file);
|
||||||
this.root = path.dirname(this.path);
|
this.root = path.dirname(this.path);
|
||||||
this.type = 'Package';
|
this.type = 'Package';
|
||||||
this._cache = cache;
|
|
||||||
this._content = null;
|
this._content = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,20 +60,16 @@ class Package {
|
||||||
return path.join(this.root, main);
|
return path.join(this.root, main);
|
||||||
}
|
}
|
||||||
|
|
||||||
isHaste() {
|
isHaste(): Promise<boolean> {
|
||||||
return this._cache.get(this.path, 'package-haste', () =>
|
return Promise.resolve().then(() => !!this.read().name);
|
||||||
Promise.resolve().then(() => !!this.read().name)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getName(): Promise<string> {
|
getName(): Promise<string> {
|
||||||
return this._cache.get(this.path, 'package-name', () =>
|
return Promise.resolve().then(() => this.read().name);
|
||||||
Promise.resolve().then(() => this.read().name)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidate() {
|
invalidate() {
|
||||||
this._cache.invalidate(this.path);
|
this._content = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
redirectRequire(name: string): string | false {
|
redirectRequire(name: string): string | false {
|
||||||
|
|
|
@ -63,46 +63,8 @@ describe('DependencyGraph', function() {
|
||||||
Module = require('../Module');
|
Module = require('../Module');
|
||||||
ResolutionRequest = require('../DependencyGraph/ResolutionRequest');
|
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 = {
|
defaults = {
|
||||||
assetExts: ['png', 'jpg'],
|
assetExts: ['png', 'jpg'],
|
||||||
cache: new Cache(),
|
|
||||||
extensions: ['js', 'json'],
|
extensions: ['js', 'json'],
|
||||||
forceNodeFilesystemAPI: true,
|
forceNodeFilesystemAPI: true,
|
||||||
providesModuleNodeModules: [
|
providesModuleNodeModules: [
|
||||||
|
@ -4970,7 +4932,7 @@ describe('DependencyGraph', function() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dependencies: [],
|
dependencies: [],
|
||||||
id: 'aPackage/main.js',
|
id: 'bPackage/main.js',
|
||||||
isAsset: false,
|
isAsset: false,
|
||||||
isJSON: false,
|
isJSON: false,
|
||||||
isPolyfill: false,
|
isPolyfill: false,
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Cache = require('./Cache');
|
|
||||||
const DependencyGraphHelpers = require('./DependencyGraph/DependencyGraphHelpers');
|
const DependencyGraphHelpers = require('./DependencyGraph/DependencyGraphHelpers');
|
||||||
const FilesByDirNameIndex = require('./FilesByDirNameIndex');
|
const FilesByDirNameIndex = require('./FilesByDirNameIndex');
|
||||||
const JestHasteMap = require('jest-haste-map');
|
const JestHasteMap = require('jest-haste-map');
|
||||||
|
@ -52,7 +51,6 @@ import type {HasteFS} from './types';
|
||||||
type Options = {|
|
type Options = {|
|
||||||
+assetDependencies: Array<string>,
|
+assetDependencies: Array<string>,
|
||||||
+assetExts: Array<string>,
|
+assetExts: Array<string>,
|
||||||
+cache: Cache,
|
|
||||||
+extensions: Array<string>,
|
+extensions: Array<string>,
|
||||||
+extraNodeModules: ?{},
|
+extraNodeModules: ?{},
|
||||||
+forceNodeFilesystemAPI: boolean,
|
+forceNodeFilesystemAPI: boolean,
|
||||||
|
@ -164,7 +162,6 @@ class DependencyGraph extends EventEmitter {
|
||||||
_createModuleCache() {
|
_createModuleCache() {
|
||||||
const {_opts} = this;
|
const {_opts} = this;
|
||||||
return new ModuleCache({
|
return new ModuleCache({
|
||||||
cache: _opts.cache,
|
|
||||||
getTransformCacheKey: _opts.getTransformCacheKey,
|
getTransformCacheKey: _opts.getTransformCacheKey,
|
||||||
globalTransformCache: _opts.globalTransformCache,
|
globalTransformCache: _opts.globalTransformCache,
|
||||||
transformCode: _opts.transformCode,
|
transformCode: _opts.transformCode,
|
||||||
|
@ -290,7 +287,6 @@ class DependencyGraph extends EventEmitter {
|
||||||
return this._moduleCache.createPolyfill(options);
|
return this._moduleCache.createPolyfill(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Cache;
|
|
||||||
static Module;
|
static Module;
|
||||||
static Polyfill;
|
static Polyfill;
|
||||||
static getAssetDataFromName;
|
static getAssetDataFromName;
|
||||||
|
@ -301,7 +297,6 @@ class DependencyGraph extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.assign(DependencyGraph, {
|
Object.assign(DependencyGraph, {
|
||||||
Cache,
|
|
||||||
Module,
|
Module,
|
||||||
Polyfill,
|
Polyfill,
|
||||||
getAssetDataFromName,
|
getAssetDataFromName,
|
||||||
|
|
Loading…
Reference in New Issue