mirror of https://github.com/status-im/metro.git
Updates from Tue 11 Aug
This commit is contained in:
commit
a457202f9b
|
@ -17,9 +17,6 @@ var sharedBlacklist = [
|
|||
'node_modules/react-tools/src/React.js',
|
||||
'node_modules/react-tools/src/renderers/shared/event/EventPropagators.js',
|
||||
'node_modules/react-tools/src/renderers/shared/event/eventPlugins/ResponderEventPlugin.js',
|
||||
'node_modules/react-tools/src/renderers/shared/event/eventPlugins/ResponderSyntheticEvent.js',
|
||||
'node_modules/react-tools/src/renderers/shared/event/eventPlugins/ResponderTouchHistoryStore.js',
|
||||
'node_modules/react-tools/src/renderers/shared/reconciler/ReactInstanceHandles.js',
|
||||
'node_modules/react-tools/src/shared/vendor/core/ExecutionEnvironment.js',
|
||||
];
|
||||
|
||||
|
|
|
@ -27,6 +27,12 @@ window.onbeforeunload = function() {
|
|||
}
|
||||
};
|
||||
|
||||
window.addEventListener('load', function () {
|
||||
if (typeof window.__REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
|
||||
document.getElementById('devtools-banner').style.display = 'block';
|
||||
}
|
||||
});
|
||||
|
||||
// Alias native implementations needed by the debugger before platform-specific
|
||||
// implementations are loaded into the global namespace
|
||||
var debuggerSetTimeout = window.setTimeout;
|
||||
|
@ -112,6 +118,13 @@ function loadScript(src, callback) {
|
|||
})();
|
||||
</script>
|
||||
<style type="text/css">
|
||||
body {
|
||||
font-size: large;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Helvetica, Verdana, sans-serif;
|
||||
font-weight: 200;
|
||||
}
|
||||
.shortcut {
|
||||
font-family: monospace;
|
||||
color: #eee;
|
||||
|
@ -120,16 +133,52 @@ function loadScript(src, callback) {
|
|||
border-radius: 4px;
|
||||
letter-spacing: 3px;
|
||||
}
|
||||
body {
|
||||
font-size: large;
|
||||
#devtools-banner {
|
||||
display: none;
|
||||
background-color: #FDFDD5;
|
||||
padding: 10px;
|
||||
}
|
||||
#devtools-banner h3 {
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
#devtools-banner a {
|
||||
display: none;
|
||||
padding: 10px 20px 10px 20px;
|
||||
margin-bottom: 10px;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
font-size: 11px;
|
||||
text-shadow: 0 1px 1px rgba(0,0,0,0.1);
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
background-color: #4d7bd6;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #2d53af;
|
||||
display: inline-block;
|
||||
}
|
||||
.content {
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
React Native JS code runs inside this Chrome tab
|
||||
</p>
|
||||
<p>Press <span class="shortcut">⌘⌥J</span> to open Developer Tools. Enable <a href="http://stackoverflow.com/a/17324511/232122" target="_blank">Pause On Caught Exceptions</a> for a better debugging experience.</p>
|
||||
<p>Status: <span id="status">Loading</span></p>
|
||||
<div id="devtools-banner">
|
||||
<h3>Install React DevTools</h3>
|
||||
<p>
|
||||
React Developer Tools is an extension that allows you to inspect the
|
||||
React component hierarchies in the Chrome Developer Tools.
|
||||
</p>
|
||||
<a href="https://fb.me/react-devtools" target="_blank">
|
||||
Install
|
||||
</a>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>
|
||||
React Native JS code runs inside this Chrome tab
|
||||
</p>
|
||||
<p>Press <span class="shortcut">⌘⌥J</span> to open Developer Tools. Enable <a href="http://stackoverflow.com/a/17324511/232122" target="_blank">Pause On Caught Exceptions</a> for a better debugging experience.</p>
|
||||
<p>Status: <span id="status">Loading</span></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# 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.
|
||||
|
||||
# Set terminal title
|
||||
echo -en "\033]0;React Packager\a"
|
||||
clear
|
||||
|
||||
THIS_DIR=$(dirname "$0")
|
||||
$THIS_DIR/packager.sh --platform android --port 8082
|
||||
echo "Process terminated. Press <enter> to close the window"
|
||||
read
|
|
@ -10,15 +10,17 @@
|
|||
"es6.constants",
|
||||
"es6.classes",
|
||||
"es6.destructuring",
|
||||
"es6.parameters.rest",
|
||||
"es6.parameters",
|
||||
"es6.properties.computed",
|
||||
"es6.properties.shorthand",
|
||||
"es6.spread",
|
||||
"es6.templateLiterals",
|
||||
"es7.asyncFunctions",
|
||||
"es7.trailingFunctionCommas",
|
||||
"es7.objectRestSpread",
|
||||
"flow",
|
||||
"react"
|
||||
"react",
|
||||
"regenerator"
|
||||
],
|
||||
"sourceMaps": false
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* 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;
|
|
@ -0,0 +1,288 @@
|
|||
/**
|
||||
* 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('underscore')
|
||||
.dontMock('absolute-path')
|
||||
.dontMock('../');
|
||||
|
||||
jest
|
||||
.mock('os')
|
||||
.mock('fs');
|
||||
|
||||
var Promise = require('promise');
|
||||
|
||||
describe('JSTransformer Cache', () => {
|
||||
var Cache;
|
||||
|
||||
beforeEach(() => {
|
||||
require('os').tmpDir.mockImpl(() => 'tmpDir');
|
||||
|
||||
Cache = require('../');
|
||||
});
|
||||
|
||||
describe('getting/setting', () => {
|
||||
pit('calls loader callback for uncached file', () => {
|
||||
require('fs').stat.mockImpl((file, callback) => {
|
||||
callback(null, {
|
||||
mtime: {
|
||||
getTime: () => {}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var cache = new Cache({
|
||||
projectRoots: ['/rootDir'],
|
||||
transformModulePath: 'x.js',
|
||||
});
|
||||
var loaderCb = jest.genMockFn().mockImpl(() => Promise.resolve());
|
||||
|
||||
return cache
|
||||
.get('/rootDir/someFile', 'field', loaderCb)
|
||||
.then($ =>
|
||||
expect(loaderCb).toBeCalledWith('/rootDir/someFile')
|
||||
);
|
||||
});
|
||||
|
||||
pit('supports storing multiple fields', () => {
|
||||
var cache = new Cache({
|
||||
projectRoots: ['/rootDir'],
|
||||
transformModulePath: 'x.js',
|
||||
});
|
||||
var index = 0;
|
||||
var loaderCb = jest.genMockFn().mockImpl(() =>
|
||||
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));
|
||||
});
|
||||
});
|
||||
|
||||
pit('gets the value from the loader callback', () => {
|
||||
require('fs').stat.mockImpl((file, callback) =>
|
||||
callback(null, {
|
||||
mtime: {
|
||||
getTime: () => {}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
var cache = new Cache({
|
||||
projectRoots: ['/rootDir'],
|
||||
transformModulePath: 'x.js',
|
||||
});
|
||||
var loaderCb = jest.genMockFn().mockImpl(() =>
|
||||
Promise.resolve('lol')
|
||||
);
|
||||
|
||||
return cache
|
||||
.get('/rootDir/someFile', 'field', loaderCb)
|
||||
.then(value => expect(value).toBe('lol'));
|
||||
});
|
||||
|
||||
pit('caches the value after the first call', () => {
|
||||
require('fs').stat.mockImpl((file, callback) => {
|
||||
callback(null, {
|
||||
mtime: {
|
||||
getTime: () => {}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var cache = new Cache({
|
||||
projectRoots: ['/rootDir'],
|
||||
transformModulePath: 'x.js',
|
||||
});
|
||||
var loaderCb = jest.genMockFn().mockImpl(() =>
|
||||
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');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
pit('clears old field when getting new field and mtime changed', () => {
|
||||
var mtime = 0;
|
||||
require('fs').stat.mockImpl((file, callback) => {
|
||||
callback(null, {
|
||||
mtime: {
|
||||
getTime: () => mtime++
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var cache = new Cache({
|
||||
projectRoots: ['/rootDir'],
|
||||
transformModulePath: 'x.js',
|
||||
});
|
||||
var loaderCb = jest.genMockFn().mockImpl(() =>
|
||||
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'))
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('loading cache from disk', () => {
|
||||
var fileStats;
|
||||
|
||||
beforeEach(() => {
|
||||
fileStats = {
|
||||
'/rootDir/someFile': {
|
||||
mtime: {
|
||||
getTime: () => 22
|
||||
}
|
||||
},
|
||||
'/rootDir/foo': {
|
||||
mtime: {
|
||||
getTime: () => 11
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
fs.existsSync.mockImpl(() => true);
|
||||
|
||||
fs.statSync.mockImpl(filePath => fileStats[filePath]);
|
||||
|
||||
fs.readFileSync.mockImpl(() => JSON.stringify({
|
||||
'/rootDir/someFile': {
|
||||
metadata: {mtime: 22},
|
||||
data: {field: 'oh hai'},
|
||||
},
|
||||
'/rootDir/foo': {
|
||||
metadata: {mtime: 11},
|
||||
data: {field: 'lol wat'},
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
pit('should load cache from disk', () => {
|
||||
var cache = new Cache({
|
||||
projectRoots: ['/rootDir'],
|
||||
transformModulePath: 'x.js',
|
||||
});
|
||||
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');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
pit('should not load outdated cache', () => {
|
||||
require('fs').stat.mockImpl((file, callback) =>
|
||||
callback(null, {
|
||||
mtime: {
|
||||
getTime: () => {}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
fileStats['/rootDir/foo'].mtime.getTime = () => 123;
|
||||
|
||||
var cache = new Cache({
|
||||
projectRoots: ['/rootDir'],
|
||||
transformModulePath: 'x.js',
|
||||
});
|
||||
var loaderCb = jest.genMockFn().mockImpl(() =>
|
||||
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', () => {
|
||||
var index = 0;
|
||||
var mtimes = [10, 20, 30];
|
||||
var debounceIndex = 0;
|
||||
require('underscore').debounce = callback => {
|
||||
return () => {
|
||||
if (++debounceIndex === 3) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var fs = require('fs');
|
||||
fs.stat.mockImpl((file, callback) =>
|
||||
callback(null, {
|
||||
mtime: {
|
||||
getTime: () => mtimes[index++]
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
var cache = new Cache({
|
||||
projectRoots: ['/rootDir'],
|
||||
transformModulePath: 'x.js',
|
||||
});
|
||||
|
||||
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')
|
||||
);
|
||||
|
||||
jest.runAllTicks();
|
||||
expect(fs.writeFile).toBeCalled();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,222 @@
|
|||
/**
|
||||
* 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';
|
||||
|
||||
var _ = require('underscore');
|
||||
var crypto = require('crypto');
|
||||
var declareOpts = require('../lib/declareOpts');
|
||||
var fs = require('fs');
|
||||
var isAbsolutePath = require('absolute-path');
|
||||
var path = require('path');
|
||||
var Promise = require('promise');
|
||||
var tmpdir = require('os').tmpDir();
|
||||
var version = require('../../../../package.json').version;
|
||||
|
||||
var validateOpts = declareOpts({
|
||||
resetCache: {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
cacheVersion: {
|
||||
type: 'string',
|
||||
default: '1.0',
|
||||
},
|
||||
projectRoots: {
|
||||
type: 'array',
|
||||
required: true,
|
||||
},
|
||||
transformModulePath: {
|
||||
type:'string',
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
// TODO: move to Packager directory
|
||||
class Cache {
|
||||
constructor(options) {
|
||||
var opts = validateOpts(options);
|
||||
|
||||
this._cacheFilePath = this._getCacheFilePath(opts);
|
||||
|
||||
var data;
|
||||
if (!opts.resetCache) {
|
||||
data = this._loadCacheSync(this._cacheFilePath);
|
||||
} else {
|
||||
data = Object.create(null);
|
||||
}
|
||||
this._data = data;
|
||||
|
||||
this._persistEventually = _.debounce(
|
||||
this._persistCache.bind(this),
|
||||
2000,
|
||||
);
|
||||
}
|
||||
|
||||
get(filepath, field, loaderCb) {
|
||||
if (!isAbsolutePath(filepath)) {
|
||||
throw new Error('Use absolute paths');
|
||||
}
|
||||
|
||||
var recordP = this._has(filepath, field)
|
||||
? this._data[filepath].data[field]
|
||||
: this._set(filepath, field, loaderCb(filepath));
|
||||
|
||||
return recordP.then(record => record);
|
||||
}
|
||||
|
||||
invalidate(filepath) {
|
||||
if (this._has(filepath)) {
|
||||
delete this._data[filepath];
|
||||
}
|
||||
}
|
||||
|
||||
end() {
|
||||
return this._persistCache();
|
||||
}
|
||||
|
||||
_has(filepath, field) {
|
||||
return Object.prototype.hasOwnProperty.call(this._data, filepath) &&
|
||||
(!field || Object.prototype.hasOwnProperty.call(this._data[filepath].data, field));
|
||||
}
|
||||
|
||||
_set(filepath, field, loaderPromise) {
|
||||
let record = this._data[filepath];
|
||||
if (!record) {
|
||||
record = Object.create(null);
|
||||
this._data[filepath] = record;
|
||||
this._data[filepath].data = Object.create(null);
|
||||
this._data[filepath].metadata = Object.create(null);
|
||||
}
|
||||
|
||||
record.data[field] = loaderPromise
|
||||
.then(data => Promise.all([
|
||||
data,
|
||||
Promise.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;
|
||||
});
|
||||
|
||||
return record.data[field];
|
||||
}
|
||||
|
||||
_persistCache() {
|
||||
if (this._persisting != null) {
|
||||
return this._persisting;
|
||||
}
|
||||
|
||||
var data = this._data;
|
||||
var cacheFilepath = this._cacheFilePath;
|
||||
|
||||
var allPromises = _.values(data)
|
||||
.map(record => {
|
||||
var fieldNames = Object.keys(record.data);
|
||||
var fieldValues = _.values(record.data);
|
||||
|
||||
return Promise
|
||||
.all(fieldValues)
|
||||
.then(ref => {
|
||||
var ret = Object.create(null);
|
||||
ret.metadata = record.metadata;
|
||||
ret.data = Object.create(null);
|
||||
fieldNames.forEach((field, index) =>
|
||||
ret.data[field] = ref[index]
|
||||
);
|
||||
|
||||
return ret;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
this._persisting = Promise.all(allPromises)
|
||||
.then(values => {
|
||||
var json = Object.create(null);
|
||||
Object.keys(data).forEach((key, i) => {
|
||||
json[key] = Object.create(null);
|
||||
json[key].metadata = data[key].metadata;
|
||||
json[key].data = values[i].data;
|
||||
});
|
||||
return Promise.denodeify(fs.writeFile)(cacheFilepath, JSON.stringify(json));
|
||||
})
|
||||
.then(() => {
|
||||
this._persisting = null;
|
||||
return true;
|
||||
});
|
||||
|
||||
return this._persisting;
|
||||
}
|
||||
|
||||
_loadCacheSync(cachePath) {
|
||||
var ret = Object.create(null);
|
||||
if (!fs.existsSync(cachePath)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
var cacheOnDisk;
|
||||
try {
|
||||
cacheOnDisk = JSON.parse(fs.readFileSync(cachePath));
|
||||
} catch (e) {
|
||||
if (e instanceof SyntaxError) {
|
||||
console.warn('Unable to parse cache file. Will clear and continue.');
|
||||
fs.unlinkSync(cachePath);
|
||||
return ret;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
// 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);
|
||||
ret[key].metadata.mtime = record.metadata.mtime;
|
||||
|
||||
Object.keys(record.data).forEach(field => {
|
||||
ret[key].data[field] = Promise.resolve(record.data[field]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
_getCacheFilePath(options) {
|
||||
var hash = crypto.createHash('md5');
|
||||
hash.update(version);
|
||||
|
||||
var roots = options.projectRoots.join(',').split(path.sep).join('-');
|
||||
hash.update(roots);
|
||||
|
||||
var cacheVersion = options.cacheVersion || '0';
|
||||
hash.update(cacheVersion);
|
||||
|
||||
hash.update(options.transformModulePath);
|
||||
|
||||
var name = 'react-packager-cache-' + hash.digest('hex');
|
||||
return path.join(tmpdir, name);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Cache;
|
|
@ -29,12 +29,15 @@ const Promise = require('promise');
|
|||
jest.mock('fs');
|
||||
|
||||
describe('DependencyGraph', function() {
|
||||
var cache;
|
||||
var Cache;
|
||||
var DependencyGraph;
|
||||
var fileWatcher;
|
||||
var fs;
|
||||
|
||||
beforeEach(function() {
|
||||
fs = require('fs');
|
||||
Cache = require('../../../Cache');
|
||||
DependencyGraph = require('../index');
|
||||
|
||||
fileWatcher = {
|
||||
|
@ -43,6 +46,8 @@ describe('DependencyGraph', function() {
|
|||
},
|
||||
isWatchman: () => Promise.resolve(false)
|
||||
};
|
||||
|
||||
cache = new Cache({});
|
||||
});
|
||||
|
||||
describe('getOrderedDependencies', function() {
|
||||
|
@ -68,6 +73,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -125,6 +131,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -176,6 +183,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -235,6 +243,7 @@ describe('DependencyGraph', function() {
|
|||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
assetRoots_DEPRECATED: ['/root/imgs'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -286,6 +295,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -342,6 +352,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -419,6 +430,7 @@ describe('DependencyGraph', function() {
|
|||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
assetRoots_DEPRECATED: ['/root/imgs'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -480,6 +492,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -532,6 +545,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -584,6 +598,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -644,6 +659,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -700,6 +716,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -750,6 +767,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -799,6 +817,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -845,6 +864,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -895,6 +915,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -943,6 +964,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -996,6 +1018,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/somedir/somefile.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -1053,6 +1076,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -1100,6 +1124,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -1146,6 +1171,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -1204,6 +1230,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -1262,6 +1289,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -1340,6 +1368,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -1396,6 +1425,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -1452,6 +1482,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -1508,6 +1539,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -1579,6 +1611,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -1681,6 +1714,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -1761,6 +1795,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -1809,6 +1844,78 @@ describe('DependencyGraph', function() {
|
|||
});
|
||||
});
|
||||
|
||||
pit('platform should work with node_modules', function() {
|
||||
var root = '/root';
|
||||
fs.__setMockFilesystem({
|
||||
'root': {
|
||||
'index.ios.js': [
|
||||
'/**',
|
||||
' * @providesModule index',
|
||||
' */',
|
||||
'require("foo");',
|
||||
'require("bar");',
|
||||
].join('\n'),
|
||||
'node_modules': {
|
||||
'foo': {
|
||||
'package.json': JSON.stringify({
|
||||
name: 'foo',
|
||||
}),
|
||||
'index.ios.js': '',
|
||||
},
|
||||
'bar': {
|
||||
'package.json': JSON.stringify({
|
||||
name: 'bar',
|
||||
main: 'main'
|
||||
}),
|
||||
'main.ios.js': '',
|
||||
},
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
var dgraph = new DependencyGraph({
|
||||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.ios.js').then(function(deps) {
|
||||
expect(deps)
|
||||
.toEqual([
|
||||
{
|
||||
id: 'index',
|
||||
path: '/root/index.ios.js',
|
||||
dependencies: ['foo', 'bar'],
|
||||
isAsset: false,
|
||||
isAsset_DEPRECATED: false,
|
||||
isJSON: false,
|
||||
isPolyfill: false,
|
||||
resolution: undefined,
|
||||
},
|
||||
{
|
||||
id: 'foo/index.ios.js',
|
||||
path: '/root/node_modules/foo/index.ios.js',
|
||||
dependencies: [],
|
||||
isAsset: false,
|
||||
isAsset_DEPRECATED: false,
|
||||
isJSON: false,
|
||||
isPolyfill: false,
|
||||
resolution: undefined,
|
||||
},
|
||||
{
|
||||
id: 'bar/main.ios.js',
|
||||
path: '/root/node_modules/bar/main.ios.js',
|
||||
dependencies: [],
|
||||
isAsset: false,
|
||||
isAsset_DEPRECATED: false,
|
||||
isJSON: false,
|
||||
isPolyfill: false,
|
||||
resolution: undefined,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
pit('nested node_modules with specific paths', function() {
|
||||
var root = '/root';
|
||||
fs.__setMockFilesystem({
|
||||
|
@ -1853,6 +1960,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -1949,6 +2057,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -2034,6 +2143,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -2138,6 +2248,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -2206,6 +2317,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/react-tools/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -2262,6 +2374,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -2306,6 +2419,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -2333,6 +2447,172 @@ describe('DependencyGraph', function() {
|
|||
]);
|
||||
});
|
||||
});
|
||||
|
||||
pit('should work with multiple platforms (haste)', function() {
|
||||
var root = '/root';
|
||||
fs.__setMockFilesystem({
|
||||
'root': {
|
||||
'index.ios.js': `
|
||||
/**
|
||||
* @providesModule index
|
||||
*/
|
||||
require('a');
|
||||
`,
|
||||
'a.ios.js': `
|
||||
/**
|
||||
* @providesModule a
|
||||
*/
|
||||
`,
|
||||
'a.android.js': `
|
||||
/**
|
||||
* @providesModule a
|
||||
*/
|
||||
`,
|
||||
'a.js': `
|
||||
/**
|
||||
* @providesModule a
|
||||
*/
|
||||
`,
|
||||
}
|
||||
});
|
||||
|
||||
var dgraph = new DependencyGraph({
|
||||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.ios.js').then(function(deps) {
|
||||
expect(deps)
|
||||
.toEqual([
|
||||
{
|
||||
id: 'index',
|
||||
path: '/root/index.ios.js',
|
||||
dependencies: ['a'],
|
||||
isAsset: false,
|
||||
isAsset_DEPRECATED: false,
|
||||
isJSON: false,
|
||||
isPolyfill: false,
|
||||
resolution: undefined,
|
||||
},
|
||||
{
|
||||
id: 'a',
|
||||
path: '/root/a.ios.js',
|
||||
dependencies: [],
|
||||
isAsset: false,
|
||||
isAsset_DEPRECATED: false,
|
||||
isJSON: false,
|
||||
isPolyfill: false,
|
||||
resolution: undefined,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
pit('should pick the generic file', function() {
|
||||
var root = '/root';
|
||||
fs.__setMockFilesystem({
|
||||
'root': {
|
||||
'index.ios.js': `
|
||||
/**
|
||||
* @providesModule index
|
||||
*/
|
||||
require('a');
|
||||
`,
|
||||
'a.android.js': `
|
||||
/**
|
||||
* @providesModule a
|
||||
*/
|
||||
`,
|
||||
'a.js': `
|
||||
/**
|
||||
* @providesModule a
|
||||
*/
|
||||
`,
|
||||
}
|
||||
});
|
||||
|
||||
var dgraph = new DependencyGraph({
|
||||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.ios.js').then(function(deps) {
|
||||
expect(deps)
|
||||
.toEqual([
|
||||
{
|
||||
id: 'index',
|
||||
path: '/root/index.ios.js',
|
||||
dependencies: ['a'],
|
||||
isAsset: false,
|
||||
isAsset_DEPRECATED: false,
|
||||
isJSON: false,
|
||||
isPolyfill: false,
|
||||
resolution: undefined,
|
||||
},
|
||||
{
|
||||
id: 'a',
|
||||
path: '/root/a.js',
|
||||
dependencies: [],
|
||||
isAsset: false,
|
||||
isAsset_DEPRECATED: false,
|
||||
isJSON: false,
|
||||
isPolyfill: false,
|
||||
resolution: undefined,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
pit('should work with multiple platforms (node)', function() {
|
||||
var root = '/root';
|
||||
fs.__setMockFilesystem({
|
||||
'root': {
|
||||
'index.ios.js': `
|
||||
/**
|
||||
* @providesModule index
|
||||
*/
|
||||
require('./a');
|
||||
`,
|
||||
'a.ios.js': '',
|
||||
'a.android.js': '',
|
||||
'a.js': '',
|
||||
}
|
||||
});
|
||||
|
||||
var dgraph = new DependencyGraph({
|
||||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.ios.js').then(function(deps) {
|
||||
expect(deps)
|
||||
.toEqual([
|
||||
{
|
||||
id: 'index',
|
||||
path: '/root/index.ios.js',
|
||||
dependencies: ['./a'],
|
||||
isAsset: false,
|
||||
isAsset_DEPRECATED: false,
|
||||
isJSON: false,
|
||||
isPolyfill: false,
|
||||
resolution: undefined,
|
||||
},
|
||||
{
|
||||
id: '/root/a.ios.js',
|
||||
path: '/root/a.ios.js',
|
||||
dependencies: [],
|
||||
isAsset: false,
|
||||
isAsset_DEPRECATED: false,
|
||||
isJSON: false,
|
||||
isPolyfill: false,
|
||||
resolution: undefined,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('file watch updating', function() {
|
||||
|
@ -2389,6 +2669,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function() {
|
||||
filesystem.root['index.js'] =
|
||||
|
@ -2453,6 +2734,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function() {
|
||||
filesystem.root['index.js'] =
|
||||
|
@ -2517,6 +2799,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function() {
|
||||
delete filesystem.root.foo;
|
||||
|
@ -2580,6 +2863,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function() {
|
||||
filesystem.root['bar.js'] = [
|
||||
|
@ -2661,6 +2945,7 @@ describe('DependencyGraph', function() {
|
|||
assetRoots_DEPRECATED: [root],
|
||||
assetExts: ['png'],
|
||||
fileWatcher: fileWatcher,
|
||||
cache: cache,
|
||||
});
|
||||
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
|
@ -2732,6 +3017,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
assetExts: ['png'],
|
||||
fileWatcher: fileWatcher,
|
||||
cache: cache,
|
||||
});
|
||||
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
|
@ -2818,7 +3104,8 @@ describe('DependencyGraph', function() {
|
|||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function() {
|
||||
filesystem.root['bar.js'] = [
|
||||
|
@ -2903,6 +3190,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function() {
|
||||
triggerFileChange('change', 'aPackage', '/root', {
|
||||
|
@ -2973,6 +3261,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function() {
|
||||
filesystem.root['index.js'] = filesystem.root['index.js'].replace(/aPackage/, 'bPackage');
|
||||
|
@ -3039,6 +3328,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function() {
|
||||
filesystem.root.aPackage['package.json'] = JSON.stringify({
|
||||
|
@ -3103,6 +3393,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function() {
|
||||
filesystem.root.aPackage['package.json'] = JSON.stringify({
|
||||
|
@ -3165,6 +3456,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
expect(deps)
|
||||
|
@ -3264,6 +3556,7 @@ describe('DependencyGraph', function() {
|
|||
roots: [root],
|
||||
fileWatcher: fileWatcher,
|
||||
assetExts: ['png', 'jpg'],
|
||||
cache: cache,
|
||||
});
|
||||
return dgraph.getOrderedDependencies('/root/index.js').then(function(deps) {
|
||||
filesystem.root.node_modules.foo['package.json'] = JSON.stringify({
|
||||
|
|
|
@ -56,6 +56,14 @@ const validateOpts = declareOpts({
|
|||
'parse',
|
||||
],
|
||||
},
|
||||
platforms: {
|
||||
type: 'array',
|
||||
default: ['ios', 'android'],
|
||||
},
|
||||
cache: {
|
||||
type: 'object',
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
class DependencyGraph {
|
||||
|
@ -63,6 +71,7 @@ class DependencyGraph {
|
|||
this._opts = validateOpts(options);
|
||||
this._hasteMap = Object.create(null);
|
||||
this._immediateResolutionCache = Object.create(null);
|
||||
this._cache = this._opts.cache;
|
||||
this.load();
|
||||
}
|
||||
|
||||
|
@ -80,17 +89,21 @@ class DependencyGraph {
|
|||
});
|
||||
this._crawling.then((files) => Activity.endEvent(crawlActivity));
|
||||
|
||||
this._fastfs = new Fastfs(this._opts.roots,this._opts.fileWatcher, {
|
||||
this._fastfs = new Fastfs(this._opts.roots, this._opts.fileWatcher, {
|
||||
ignore: this._opts.ignoreFilePath,
|
||||
crawling: this._crawling,
|
||||
});
|
||||
|
||||
this._fastfs.on('change', this._processFileChange.bind(this));
|
||||
|
||||
this._moduleCache = new ModuleCache(this._fastfs);
|
||||
this._moduleCache = new ModuleCache(this._fastfs, this._cache);
|
||||
|
||||
this._loading = Promise.all([
|
||||
this._fastfs.build().then(() => this._buildHasteMap()),
|
||||
this._fastfs.build()
|
||||
.then(() => {
|
||||
const hasteActivity = Activity.startEvent('Building Haste Map');
|
||||
this._buildHasteMap().then(() => Activity.endEvent(hasteActivity));
|
||||
}),
|
||||
this._buildAssetMap_DEPRECATED(),
|
||||
]);
|
||||
|
||||
|
@ -137,7 +150,7 @@ class DependencyGraph {
|
|||
() => this._resolveNodeDependency(fromModule, toModuleName)
|
||||
).then(
|
||||
cacheResult,
|
||||
forgive
|
||||
forgive,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -169,6 +182,13 @@ class DependencyGraph {
|
|||
);
|
||||
}
|
||||
|
||||
const platformExt = getPlatformExt(entryPath);
|
||||
if (platformExt && this._opts.platforms.indexOf(platformExt) > -1) {
|
||||
this._platformExt = platformExt;
|
||||
} else {
|
||||
this._platformExt = null;
|
||||
}
|
||||
|
||||
const entry = this._moduleCache.getModule(absolutePath);
|
||||
const deps = [];
|
||||
const visited = Object.create(null);
|
||||
|
@ -237,16 +257,14 @@ class DependencyGraph {
|
|||
}
|
||||
|
||||
return p.then((realModuleName) => {
|
||||
let dep = this._hasteMap[realModuleName];
|
||||
|
||||
let dep = this._getHasteModule(realModuleName);
|
||||
if (dep && dep.type === 'Module') {
|
||||
return dep;
|
||||
}
|
||||
|
||||
let packageName = realModuleName;
|
||||
|
||||
while (packageName && packageName !== '.') {
|
||||
dep = this._hasteMap[packageName];
|
||||
dep = this._getHasteModule(packageName);
|
||||
if (dep && dep.type === 'Package') {
|
||||
break;
|
||||
}
|
||||
|
@ -349,6 +367,9 @@ class DependencyGraph {
|
|||
let file;
|
||||
if (this._fastfs.fileExists(potentialModulePath)) {
|
||||
file = potentialModulePath;
|
||||
} else if (this._platformExt != null &&
|
||||
this._fastfs.fileExists(potentialModulePath + '.' + this._platformExt + '.js')) {
|
||||
file = potentialModulePath + '.' + this._platformExt + '.js';
|
||||
} else if (this._fastfs.fileExists(potentialModulePath + '.js')) {
|
||||
file = potentialModulePath + '.js';
|
||||
} else if (this._fastfs.fileExists(potentialModulePath + '.json')) {
|
||||
|
@ -419,15 +440,32 @@ class DependencyGraph {
|
|||
}
|
||||
|
||||
_updateHasteMap(name, mod) {
|
||||
if (this._hasteMap[name]) {
|
||||
debug('WARNING: conflicting haste modules: ' + name);
|
||||
if (mod.type === 'Package' &&
|
||||
this._hasteMap[name].type === 'Module') {
|
||||
// Modules takes precendence over packages.
|
||||
return;
|
||||
}
|
||||
if (this._hasteMap[name] == null) {
|
||||
this._hasteMap[name] = [];
|
||||
}
|
||||
this._hasteMap[name] = mod;
|
||||
|
||||
if (mod.type === 'Module') {
|
||||
// Modules takes precendence over packages.
|
||||
this._hasteMap[name].unshift(mod);
|
||||
} else {
|
||||
this._hasteMap[name].push(mod);
|
||||
}
|
||||
}
|
||||
|
||||
_getHasteModule(name) {
|
||||
if (this._hasteMap[name]) {
|
||||
const modules = this._hasteMap[name];
|
||||
if (this._platformExt != null) {
|
||||
for (let i = 0; i < modules.length; i++) {
|
||||
if (getPlatformExt(modules[i].path) === this._platformExt) {
|
||||
return modules[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return modules[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
_isNodeModulesDir(file) {
|
||||
|
@ -480,9 +518,18 @@ class DependencyGraph {
|
|||
fastfs.on('change', this._processAssetChange_DEPRECATED.bind(this));
|
||||
|
||||
return fastfs.build().then(
|
||||
() => fastfs.findFilesByExts(this._opts.assetExts).map(
|
||||
file => this._processAsset_DEPRECATED(file)
|
||||
)
|
||||
() => {
|
||||
const processAsset_DEPRECATEDActivity = Activity.startEvent(
|
||||
'Building (deprecated) Asset Map',
|
||||
);
|
||||
|
||||
const assets = fastfs.findFilesByExts(this._opts.assetExts).map(
|
||||
file => this._processAsset_DEPRECATED(file)
|
||||
);
|
||||
|
||||
Activity.endEvent(processAsset_DEPRECATEDActivity);
|
||||
return assets;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -511,12 +558,17 @@ class DependencyGraph {
|
|||
return;
|
||||
}
|
||||
|
||||
/*eslint no-labels: 0 */
|
||||
if (type === 'delete' || type === 'change') {
|
||||
_.each(this._hasteMap, (mod, name) => {
|
||||
if (mod.path === absPath) {
|
||||
delete this._hasteMap[name];
|
||||
loop: for (let name in this._hasteMap) {
|
||||
let modules = this._hasteMap[name];
|
||||
for (var i = 0; i < modules.length; i++) {
|
||||
if (modules[i].path === absPath) {
|
||||
modules.splice(i, 1);
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (type === 'delete') {
|
||||
return;
|
||||
|
@ -566,6 +618,15 @@ function normalizePath(modulePath) {
|
|||
return modulePath.replace(/\/$/, '');
|
||||
}
|
||||
|
||||
// Extract platform extension: index.ios.js -> ios
|
||||
function getPlatformExt(file) {
|
||||
const parts = path.basename(file).split('.');
|
||||
if (parts.length < 3) {
|
||||
return null;
|
||||
}
|
||||
return parts[parts.length - 2];
|
||||
}
|
||||
|
||||
util.inherits(NotFoundError, Error);
|
||||
|
||||
module.exports = DependencyGraph;
|
||||
|
|
|
@ -8,7 +8,7 @@ const replacePatterns = require('./replacePatterns');
|
|||
|
||||
class Module {
|
||||
|
||||
constructor(file, fastfs, moduleCache) {
|
||||
constructor(file, fastfs, moduleCache, cache) {
|
||||
if (!isAbsolutePath(file)) {
|
||||
throw new Error('Expected file to be absolute path but got ' + file);
|
||||
}
|
||||
|
@ -18,34 +18,41 @@ class Module {
|
|||
|
||||
this._fastfs = fastfs;
|
||||
this._moduleCache = moduleCache;
|
||||
this._cache = cache;
|
||||
}
|
||||
|
||||
isHaste() {
|
||||
return this._read().then(data => !!data.id);
|
||||
return this._cache.get(this.path, 'haste', () =>
|
||||
this._read().then(data => !!data.id)
|
||||
);
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this._read().then(data => {
|
||||
if (data.id) {
|
||||
return data.id;
|
||||
}
|
||||
return this._cache.get(
|
||||
this.path,
|
||||
'name',
|
||||
() => this._read().then(data => {
|
||||
if (data.id) {
|
||||
return data.id;
|
||||
}
|
||||
|
||||
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(name => {
|
||||
if (!name) {
|
||||
return this.path;
|
||||
}
|
||||
return p.getName()
|
||||
.then(name => {
|
||||
if (!name) {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
return path.join(name, path.relative(p.root, this.path));
|
||||
});
|
||||
});
|
||||
return path.join(name, path.relative(p.root, this.path));
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
getPackage() {
|
||||
|
@ -53,7 +60,13 @@ class Module {
|
|||
}
|
||||
|
||||
getDependencies() {
|
||||
return this._read().then(data => data.dependencies);
|
||||
return this._cache.get(this.path, 'dependencies', () =>
|
||||
this._read().then(data => data.dependencies)
|
||||
);
|
||||
}
|
||||
|
||||
invalidate() {
|
||||
this._cache.invalidate(this.path);
|
||||
}
|
||||
|
||||
_read() {
|
||||
|
|
|
@ -7,17 +7,23 @@ const path = require('path');
|
|||
|
||||
class ModuleCache {
|
||||
|
||||
constructor(fastfs) {
|
||||
constructor(fastfs, cache) {
|
||||
this._moduleCache = Object.create(null);
|
||||
this._packageCache = Object.create(null);
|
||||
this._fastfs = fastfs;
|
||||
this._cache = cache;
|
||||
fastfs.on('change', this._processFileChange.bind(this));
|
||||
}
|
||||
|
||||
getModule(filePath) {
|
||||
filePath = path.resolve(filePath);
|
||||
if (!this._moduleCache[filePath]) {
|
||||
this._moduleCache[filePath] = new Module(filePath, this._fastfs, this);
|
||||
this._moduleCache[filePath] = new Module(
|
||||
filePath,
|
||||
this._fastfs,
|
||||
this,
|
||||
this._cache,
|
||||
);
|
||||
}
|
||||
return this._moduleCache[filePath];
|
||||
}
|
||||
|
@ -28,7 +34,8 @@ class ModuleCache {
|
|||
this._moduleCache[filePath] = new AssetModule(
|
||||
filePath,
|
||||
this._fastfs,
|
||||
this
|
||||
this,
|
||||
this._cache,
|
||||
);
|
||||
}
|
||||
return this._moduleCache[filePath];
|
||||
|
@ -37,7 +44,11 @@ class ModuleCache {
|
|||
getPackage(filePath) {
|
||||
filePath = path.resolve(filePath);
|
||||
if (!this._packageCache[filePath]){
|
||||
this._packageCache[filePath] = new Package(filePath, this._fastfs);
|
||||
this._packageCache[filePath] = new Package(
|
||||
filePath,
|
||||
this._fastfs,
|
||||
this._cache,
|
||||
);
|
||||
}
|
||||
return this._packageCache[filePath];
|
||||
}
|
||||
|
@ -64,8 +75,15 @@ class ModuleCache {
|
|||
|
||||
_processFileChange(type, filePath, root) {
|
||||
const absPath = path.join(root, filePath);
|
||||
delete this._moduleCache[absPath];
|
||||
delete this._packageCache[absPath];
|
||||
|
||||
if (this._moduleCache[absPath]) {
|
||||
this._moduleCache[absPath].invalidate();
|
||||
delete this._moduleCache[absPath];
|
||||
}
|
||||
if (this._packageCache[absPath]) {
|
||||
this._packageCache[absPath].invalidate();
|
||||
delete this._packageCache[absPath];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,11 +5,12 @@ const path = require('path');
|
|||
|
||||
class Package {
|
||||
|
||||
constructor(file, fastfs) {
|
||||
constructor(file, fastfs, cache) {
|
||||
this.path = path.resolve(file);
|
||||
this.root = path.dirname(this.path);
|
||||
this._fastfs = fastfs;
|
||||
this.type = 'Package';
|
||||
this._cache = cache;
|
||||
}
|
||||
|
||||
getMain() {
|
||||
|
@ -33,11 +34,19 @@ class Package {
|
|||
}
|
||||
|
||||
isHaste() {
|
||||
return this._read().then(json => !!json.name);
|
||||
return this._cache.get(this.path, 'haste', () =>
|
||||
this._read().then(json => !!json.name)
|
||||
);
|
||||
}
|
||||
|
||||
getName() {
|
||||
return this._read().then(json => json.name);
|
||||
return this._cache.get(this.path, 'name', () =>
|
||||
this._read().then(json => json.name)
|
||||
);
|
||||
}
|
||||
|
||||
invalidate() {
|
||||
this._cache.invalidate(this.path);
|
||||
}
|
||||
|
||||
redirectRequire(name) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const Activity = require('../Activity');
|
||||
const Promise = require('promise');
|
||||
const {EventEmitter} = require('events');
|
||||
|
||||
|
@ -28,6 +29,7 @@ class Fastfs extends EventEmitter {
|
|||
);
|
||||
|
||||
return this._crawling.then(files => {
|
||||
const fastfsActivity = Activity.startEvent('Building in-memory fs');
|
||||
files.forEach(filePath => {
|
||||
if (filePath.match(rootsPattern)) {
|
||||
const newFile = new File(filePath, { isDir: false });
|
||||
|
@ -44,6 +46,7 @@ class Fastfs extends EventEmitter {
|
|||
}
|
||||
}
|
||||
});
|
||||
Activity.endEvent(fastfsActivity);
|
||||
this._fileWatcher.on('all', this._processFileChange.bind(this));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -45,7 +45,11 @@ var validateOpts = declareOpts({
|
|||
assetExts: {
|
||||
type: 'array',
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
cache: {
|
||||
type: 'object',
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
function HasteDependencyResolver(options) {
|
||||
|
@ -60,6 +64,7 @@ function HasteDependencyResolver(options) {
|
|||
(opts.blacklistRE && opts.blacklistRE.test(filepath));
|
||||
},
|
||||
fileWatcher: opts.fileWatcher,
|
||||
cache: opts.cache,
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -1,175 +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';
|
||||
|
||||
var _ = require('underscore');
|
||||
var crypto = require('crypto');
|
||||
var declareOpts = require('../lib/declareOpts');
|
||||
var fs = require('fs');
|
||||
var isAbsolutePath = require('absolute-path');
|
||||
var path = require('path');
|
||||
var Promise = require('promise');
|
||||
var tmpdir = require('os').tmpDir();
|
||||
var version = require('../../../../package.json').version;
|
||||
|
||||
var validateOpts = declareOpts({
|
||||
resetCache: {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
cacheVersion: {
|
||||
type: 'string',
|
||||
default: '1.0',
|
||||
},
|
||||
projectRoots: {
|
||||
type: 'array',
|
||||
required: true,
|
||||
},
|
||||
transformModulePath: {
|
||||
type:'string',
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
module.exports = Cache;
|
||||
|
||||
function Cache(options) {
|
||||
var opts = validateOpts(options);
|
||||
|
||||
this._cacheFilePath = cacheFilePath(opts);
|
||||
|
||||
var data;
|
||||
if (!opts.resetCache) {
|
||||
data = loadCacheSync(this._cacheFilePath);
|
||||
} else {
|
||||
data = Object.create(null);
|
||||
}
|
||||
this._data = data;
|
||||
|
||||
this._has = Object.prototype.hasOwnProperty.bind(data);
|
||||
this._persistEventually = _.debounce(
|
||||
this._persistCache.bind(this),
|
||||
2000
|
||||
);
|
||||
}
|
||||
|
||||
Cache.prototype.get = function(filepath, loaderCb) {
|
||||
if (!isAbsolutePath(filepath)) {
|
||||
throw new Error('Use absolute paths');
|
||||
}
|
||||
|
||||
var recordP = this._has(filepath)
|
||||
? this._data[filepath]
|
||||
: this._set(filepath, loaderCb(filepath));
|
||||
|
||||
return recordP.then(function(record) {
|
||||
return record.data;
|
||||
});
|
||||
};
|
||||
|
||||
Cache.prototype._set = function(filepath, loaderPromise) {
|
||||
this._data[filepath] = loaderPromise.then(function(data) {
|
||||
return Promise.all([
|
||||
data,
|
||||
Promise.denodeify(fs.stat)(filepath)
|
||||
]);
|
||||
}).then(function(ref) {
|
||||
var data = ref[0];
|
||||
var stat = ref[1];
|
||||
this._persistEventually();
|
||||
return {
|
||||
data: data,
|
||||
mtime: stat.mtime.getTime(),
|
||||
};
|
||||
}.bind(this));
|
||||
|
||||
return this._data[filepath];
|
||||
};
|
||||
|
||||
Cache.prototype.invalidate = function(filepath){
|
||||
if (this._has(filepath)) {
|
||||
delete this._data[filepath];
|
||||
}
|
||||
};
|
||||
|
||||
Cache.prototype.end = function() {
|
||||
return this._persistCache();
|
||||
};
|
||||
|
||||
Cache.prototype._persistCache = function() {
|
||||
if (this._persisting != null) {
|
||||
return this._persisting;
|
||||
}
|
||||
|
||||
var data = this._data;
|
||||
var cacheFilepath = this._cacheFilePath;
|
||||
|
||||
this._persisting = Promise.all(_.values(data))
|
||||
.then(function(values) {
|
||||
var json = Object.create(null);
|
||||
Object.keys(data).forEach(function(key, i) {
|
||||
json[key] = values[i];
|
||||
});
|
||||
return Promise.denodeify(fs.writeFile)(cacheFilepath, JSON.stringify(json));
|
||||
})
|
||||
.then(function() {
|
||||
this._persisting = null;
|
||||
return true;
|
||||
}.bind(this));
|
||||
|
||||
return this._persisting;
|
||||
};
|
||||
|
||||
function loadCacheSync(cachePath) {
|
||||
var ret = Object.create(null);
|
||||
if (!fs.existsSync(cachePath)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
var cacheOnDisk;
|
||||
try {
|
||||
cacheOnDisk = JSON.parse(fs.readFileSync(cachePath));
|
||||
} catch (e) {
|
||||
if (e instanceof SyntaxError) {
|
||||
console.warn('Unable to parse cache file. Will clear and continue.');
|
||||
fs.unlinkSync(cachePath);
|
||||
return ret;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
// Filter outdated cache and convert to promises.
|
||||
Object.keys(cacheOnDisk).forEach(function(key) {
|
||||
if (!fs.existsSync(key)) {
|
||||
return;
|
||||
}
|
||||
var value = cacheOnDisk[key];
|
||||
var stat = fs.statSync(key);
|
||||
if (stat.mtime.getTime() === value.mtime) {
|
||||
ret[key] = Promise.resolve(value);
|
||||
}
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function cacheFilePath(options) {
|
||||
var hash = crypto.createHash('md5');
|
||||
hash.update(version);
|
||||
|
||||
var roots = options.projectRoots.join(',').split(path.sep).join('-');
|
||||
hash.update(roots);
|
||||
|
||||
var cacheVersion = options.cacheVersion || '0';
|
||||
hash.update(cacheVersion);
|
||||
|
||||
hash.update(options.transformModulePath);
|
||||
|
||||
var name = 'react-packager-cache-' + hash.digest('hex');
|
||||
return path.join(tmpdir, name);
|
||||
}
|
|
@ -1,236 +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('underscore')
|
||||
.dontMock('absolute-path')
|
||||
.dontMock('../Cache');
|
||||
|
||||
jest
|
||||
.mock('os')
|
||||
.mock('fs');
|
||||
|
||||
var Promise = require('promise');
|
||||
|
||||
describe('JSTransformer Cache', function() {
|
||||
var Cache;
|
||||
|
||||
beforeEach(function() {
|
||||
require('os').tmpDir.mockImpl(function() {
|
||||
return 'tmpDir';
|
||||
});
|
||||
|
||||
Cache = require('../Cache');
|
||||
});
|
||||
|
||||
describe('getting/setting', function() {
|
||||
it('calls loader callback for uncached file', function() {
|
||||
var cache = new Cache({
|
||||
projectRoots: ['/rootDir'],
|
||||
transformModulePath: 'x.js',
|
||||
});
|
||||
var loaderCb = jest.genMockFn().mockImpl(function() {
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
cache.get('/rootDir/someFile', loaderCb);
|
||||
expect(loaderCb).toBeCalledWith('/rootDir/someFile');
|
||||
});
|
||||
|
||||
pit('gets the value from the loader callback', function() {
|
||||
require('fs').stat.mockImpl(function(file, callback) {
|
||||
callback(null, {
|
||||
mtime: {
|
||||
getTime: function() {}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var cache = new Cache({
|
||||
projectRoots: ['/rootDir'],
|
||||
transformModulePath: 'x.js',
|
||||
});
|
||||
var loaderCb = jest.genMockFn().mockImpl(function() {
|
||||
return Promise.resolve('lol');
|
||||
});
|
||||
|
||||
return cache.get('/rootDir/someFile', loaderCb).then(function(value) {
|
||||
expect(value).toBe('lol');
|
||||
});
|
||||
});
|
||||
|
||||
pit('caches the value after the first call', function() {
|
||||
require('fs').stat.mockImpl(function(file, callback) {
|
||||
callback(null, {
|
||||
mtime: {
|
||||
getTime: function() {}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var cache = new Cache({
|
||||
projectRoots: ['/rootDir'],
|
||||
transformModulePath: 'x.js',
|
||||
});
|
||||
var loaderCb = jest.genMockFn().mockImpl(function() {
|
||||
return Promise.resolve('lol');
|
||||
});
|
||||
|
||||
return cache.get('/rootDir/someFile', loaderCb).then(function() {
|
||||
var shouldNotBeCalled = jest.genMockFn();
|
||||
return cache.get('/rootDir/someFile', shouldNotBeCalled)
|
||||
.then(function(value) {
|
||||
expect(shouldNotBeCalled).not.toBeCalled();
|
||||
expect(value).toBe('lol');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('loading cache from disk', function() {
|
||||
var fileStats;
|
||||
|
||||
beforeEach(function() {
|
||||
fileStats = {
|
||||
'/rootDir/someFile': {
|
||||
mtime: {
|
||||
getTime: function() {
|
||||
return 22;
|
||||
}
|
||||
}
|
||||
},
|
||||
'/rootDir/foo': {
|
||||
mtime: {
|
||||
getTime: function() {
|
||||
return 11;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
fs.existsSync.mockImpl(function() {
|
||||
return true;
|
||||
});
|
||||
|
||||
fs.statSync.mockImpl(function(filePath) {
|
||||
return fileStats[filePath];
|
||||
});
|
||||
|
||||
fs.readFileSync.mockImpl(function() {
|
||||
return JSON.stringify({
|
||||
'/rootDir/someFile': {
|
||||
mtime: 22,
|
||||
data: 'oh hai'
|
||||
},
|
||||
'/rootDir/foo': {
|
||||
mtime: 11,
|
||||
data: 'lol wat'
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
pit('should load cache from disk', function() {
|
||||
var cache = new Cache({
|
||||
projectRoots: ['/rootDir'],
|
||||
transformModulePath: 'x.js',
|
||||
});
|
||||
var loaderCb = jest.genMockFn();
|
||||
|
||||
return cache.get('/rootDir/someFile', loaderCb).then(function(value) {
|
||||
expect(loaderCb).not.toBeCalled();
|
||||
expect(value).toBe('oh hai');
|
||||
|
||||
return cache.get('/rootDir/foo', loaderCb).then(function(value) {
|
||||
expect(loaderCb).not.toBeCalled();
|
||||
expect(value).toBe('lol wat');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
pit('should not load outdated cache', function() {
|
||||
require('fs').stat.mockImpl(function(file, callback) {
|
||||
callback(null, {
|
||||
mtime: {
|
||||
getTime: function() {}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
fileStats['/rootDir/foo'].mtime.getTime = function() {
|
||||
return 123;
|
||||
};
|
||||
|
||||
var cache = new Cache({
|
||||
projectRoots: ['/rootDir'],
|
||||
transformModulePath: 'x.js',
|
||||
});
|
||||
var loaderCb = jest.genMockFn().mockImpl(function() {
|
||||
return Promise.resolve('new value');
|
||||
});
|
||||
|
||||
return cache.get('/rootDir/someFile', loaderCb).then(function(value) {
|
||||
expect(loaderCb).not.toBeCalled();
|
||||
expect(value).toBe('oh hai');
|
||||
|
||||
return cache.get('/rootDir/foo', loaderCb).then(function(value) {
|
||||
expect(loaderCb).toBeCalled();
|
||||
expect(value).toBe('new value');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('writing cache to disk', function() {
|
||||
it('should write cache to disk', function() {
|
||||
var index = 0;
|
||||
var mtimes = [10, 20, 30];
|
||||
var debounceIndex = 0;
|
||||
require('underscore').debounce = function(callback) {
|
||||
return function () {
|
||||
if (++debounceIndex === 3) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var fs = require('fs');
|
||||
fs.stat.mockImpl(function(file, callback) {
|
||||
callback(null, {
|
||||
mtime: {
|
||||
getTime: function() {
|
||||
return mtimes[index++];
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var cache = new Cache({
|
||||
projectRoots: ['/rootDir'],
|
||||
transformModulePath: 'x.js',
|
||||
});
|
||||
|
||||
cache.get('/rootDir/bar', function() {
|
||||
return Promise.resolve('bar value');
|
||||
});
|
||||
cache.get('/rootDir/foo', function() {
|
||||
return Promise.resolve('foo value');
|
||||
});
|
||||
cache.get('/rootDir/baz', function() {
|
||||
return Promise.resolve('baz value');
|
||||
});
|
||||
|
||||
jest.runAllTicks();
|
||||
expect(fs.writeFile).toBeCalled();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -15,8 +15,11 @@ jest
|
|||
|
||||
jest.mock('fs');
|
||||
|
||||
var Cache = require('../../Cache');
|
||||
|
||||
var OPTIONS = {
|
||||
transformModulePath: '/foo/bar'
|
||||
transformModulePath: '/foo/bar',
|
||||
cache: new Cache({}),
|
||||
};
|
||||
|
||||
describe('Transformer', function() {
|
||||
|
@ -28,9 +31,6 @@ describe('Transformer', function() {
|
|||
jest.setMock('worker-farm', jest.genMockFn().mockImpl(function() {
|
||||
return workers;
|
||||
}));
|
||||
require('../Cache').prototype.get.mockImpl(function(filePath, callback) {
|
||||
return callback();
|
||||
});
|
||||
require('fs').readFile.mockImpl(function(file, callback) {
|
||||
callback(null, 'content');
|
||||
});
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
var fs = require('fs');
|
||||
var Promise = require('promise');
|
||||
var Cache = require('./Cache');
|
||||
var workerFarm = require('worker-farm');
|
||||
var declareOpts = require('../lib/declareOpts');
|
||||
var util = require('util');
|
||||
|
@ -33,35 +32,20 @@ var validateOpts = declareOpts({
|
|||
type: 'array',
|
||||
default: [],
|
||||
},
|
||||
cacheVersion: {
|
||||
type: 'string',
|
||||
default: '1.0',
|
||||
},
|
||||
resetCache: {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
transformModulePath: {
|
||||
type:'string',
|
||||
required: false,
|
||||
},
|
||||
nonPersistent: {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
cache: {
|
||||
type: 'object',
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
function Transformer(options) {
|
||||
var opts = validateOpts(options);
|
||||
|
||||
this._cache = opts.nonPersistent
|
||||
? new DummyCache()
|
||||
: new Cache({
|
||||
resetCache: options.resetCache,
|
||||
cacheVersion: options.cacheVersion,
|
||||
projectRoots: options.projectRoots,
|
||||
transformModulePath: options.transformModulePath,
|
||||
});
|
||||
this._cache = opts.cache;
|
||||
|
||||
if (options.transformModulePath != null) {
|
||||
this._workers = workerFarm(
|
||||
|
@ -75,7 +59,6 @@ function Transformer(options) {
|
|||
|
||||
Transformer.prototype.kill = function() {
|
||||
this._workers && workerFarm.end(this._workers);
|
||||
return this._cache.end();
|
||||
};
|
||||
|
||||
Transformer.prototype.invalidateFile = function(filePath) {
|
||||
|
@ -88,7 +71,8 @@ Transformer.prototype.loadFileAndTransform = function(filePath) {
|
|||
}
|
||||
|
||||
var transform = this._transform;
|
||||
return this._cache.get(filePath, function() {
|
||||
return this._cache.get(filePath, 'transformedSource', function() {
|
||||
// TODO: use fastfs to avoid reading file from disk again
|
||||
return readFile(filePath)
|
||||
.then(function(buffer) {
|
||||
var sourceCode = buffer.toString();
|
||||
|
@ -121,7 +105,9 @@ Transformer.prototype.loadFileAndTransform = function(filePath) {
|
|||
});
|
||||
};
|
||||
|
||||
function TransformError() {}
|
||||
function TransformError() {
|
||||
Error.captureStackTrace && Error.captureStackTrace(this, TransformError);
|
||||
}
|
||||
util.inherits(TransformError, SyntaxError);
|
||||
|
||||
function formatError(err, filename, source) {
|
||||
|
@ -155,10 +141,3 @@ function formatBabelError(err, filename) {
|
|||
error.description = err.message;
|
||||
return error;
|
||||
}
|
||||
|
||||
function DummyCache() {}
|
||||
DummyCache.prototype.get = function(filePath, loaderCb) {
|
||||
return loaderCb();
|
||||
};
|
||||
DummyCache.prototype.end =
|
||||
DummyCache.prototype.invalidate = function(){};
|
||||
|
|
|
@ -12,6 +12,7 @@ var assert = require('assert');
|
|||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var Promise = require('promise');
|
||||
var Cache = require('../Cache');
|
||||
var Transformer = require('../JSTransformer');
|
||||
var DependencyResolver = require('../DependencyResolver');
|
||||
var Package = require('./Package');
|
||||
|
@ -78,6 +79,15 @@ function Packager(options) {
|
|||
|
||||
opts.projectRoots.forEach(verifyRootExists);
|
||||
|
||||
this._cache = opts.nonPersistent
|
||||
? new DummyCache()
|
||||
: new Cache({
|
||||
resetCache: opts.resetCache,
|
||||
cacheVersion: opts.cacheVersion,
|
||||
projectRoots: opts.projectRoots,
|
||||
transformModulePath: opts.transformModulePath,
|
||||
});
|
||||
|
||||
this._resolver = new DependencyResolver({
|
||||
projectRoots: opts.projectRoots,
|
||||
blacklistRE: opts.blacklistRE,
|
||||
|
@ -87,15 +97,14 @@ function Packager(options) {
|
|||
assetRoots: opts.assetRoots,
|
||||
fileWatcher: opts.fileWatcher,
|
||||
assetExts: opts.assetExts,
|
||||
cache: this._cache,
|
||||
});
|
||||
|
||||
this._transformer = new Transformer({
|
||||
projectRoots: opts.projectRoots,
|
||||
blacklistRE: opts.blacklistRE,
|
||||
cacheVersion: opts.cacheVersion,
|
||||
resetCache: opts.resetCache,
|
||||
cache: this._cache,
|
||||
transformModulePath: opts.transformModulePath,
|
||||
nonPersistent: opts.nonPersistent,
|
||||
});
|
||||
|
||||
this._projectRoots = opts.projectRoots;
|
||||
|
@ -103,7 +112,8 @@ function Packager(options) {
|
|||
}
|
||||
|
||||
Packager.prototype.kill = function() {
|
||||
return this._transformer.kill();
|
||||
this._transformer.kill();
|
||||
return this._cache.end();
|
||||
};
|
||||
|
||||
Packager.prototype.package = function(main, runModule, sourceMapUrl, isDev) {
|
||||
|
@ -267,4 +277,13 @@ function verifyRootExists(root) {
|
|||
assert(fs.statSync(root).isDirectory(), 'Root has to be a valid directory');
|
||||
}
|
||||
|
||||
class DummyCache {
|
||||
get(filepath, field, loaderCb) {
|
||||
return loaderCb();
|
||||
}
|
||||
|
||||
end(){}
|
||||
invalidate(filepath){}
|
||||
}
|
||||
|
||||
module.exports = Packager;
|
||||
|
|
|
@ -372,12 +372,36 @@ Server.prototype.processRequest = function(req, res, next) {
|
|||
Activity.endEvent(startReqEventId);
|
||||
}
|
||||
},
|
||||
function(error) {
|
||||
handleError(res, error);
|
||||
}
|
||||
this._handleError.bind(this, res, optionsJson)
|
||||
).done();
|
||||
};
|
||||
|
||||
Server.prototype._handleError = function(res, packageID, error) {
|
||||
res.writeHead(error.status || 500, {
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
});
|
||||
|
||||
if (error.type === 'TransformError' || error.type === 'NotFoundError') {
|
||||
error.errors = [{
|
||||
description: error.description,
|
||||
filename: error.filename,
|
||||
lineNumber: error.lineNumber,
|
||||
}];
|
||||
res.end(JSON.stringify(error));
|
||||
|
||||
if (error.type === 'NotFoundError') {
|
||||
delete this._packages[packageID];
|
||||
}
|
||||
} else {
|
||||
console.error(error.stack || error);
|
||||
res.end(JSON.stringify({
|
||||
type: 'InternalError',
|
||||
message: 'react-packager has encountered an internal error, ' +
|
||||
'please check your terminal error output for more details',
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
function getOptionsFromUrl(reqUrl) {
|
||||
// `true` to parse the query param as an object.
|
||||
var urlObj = url.parse(reqUrl, true);
|
||||
|
@ -417,26 +441,3 @@ function getBoolOptionFromQuery(query, opt, defaultVal) {
|
|||
|
||||
return query[opt] === 'true' || query[opt] === '1';
|
||||
}
|
||||
|
||||
function handleError(res, error) {
|
||||
res.writeHead(error.status || 500, {
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
});
|
||||
|
||||
if (error.type === 'TransformError' || error.type === 'NotFoundError') {
|
||||
error.errors = [{
|
||||
description: error.description,
|
||||
filename: error.filename,
|
||||
lineNumber: error.lineNumber,
|
||||
}];
|
||||
console.error(error);
|
||||
res.end(JSON.stringify(error));
|
||||
} else {
|
||||
console.error(error.stack || error);
|
||||
res.end(JSON.stringify({
|
||||
type: 'InternalError',
|
||||
message: 'react-packager has encountered an internal error, ' +
|
||||
'please check your terminal error output for more details',
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,16 +23,17 @@ function transform(srcTxt, filename, options) {
|
|||
'es6.blockScoping',
|
||||
'es6.classes',
|
||||
'es6.destructuring',
|
||||
'es6.parameters.rest',
|
||||
'es6.parameters',
|
||||
'es6.properties.computed',
|
||||
'es6.properties.shorthand',
|
||||
'es6.spread',
|
||||
'es6.templateLiterals',
|
||||
'es7.asyncFunctions',
|
||||
'es7.trailingFunctionCommas',
|
||||
'es7.objectRestSpread',
|
||||
'flow',
|
||||
'react',
|
||||
'react.displayName',
|
||||
'regenerator',
|
||||
],
|
||||
sourceFileName: filename,
|
||||
sourceMaps: false,
|
||||
|
|
Loading…
Reference in New Issue