Replacing node-haste with jest-haste-map
Summary: Modified `node-haste` implementation to use the much faster `jest-haste-map` under the hood. The underlying `fastfs` now gets passed the entire file list from the `jest-haste-map` rather than crawl the filesystem. Reviewed By: cpojer Differential Revision: D3724387 fbshipit-source-id: 447d58ea0edf283662ec23d1e2deee992cf8d240
This commit is contained in:
parent
d7d89172c2
commit
6130650d93
|
@ -166,6 +166,7 @@
|
||||||
"image-size": "^0.3.5",
|
"image-size": "^0.3.5",
|
||||||
"immutable": "~3.7.6",
|
"immutable": "~3.7.6",
|
||||||
"inquirer": "^0.12.0",
|
"inquirer": "^0.12.0",
|
||||||
|
"jest-haste-map": "15.0.1",
|
||||||
"joi": "^6.6.1",
|
"joi": "^6.6.1",
|
||||||
"json-stable-stringify": "^1.0.1",
|
"json-stable-stringify": "^1.0.1",
|
||||||
"json5": "^0.4.0",
|
"json5": "^0.4.0",
|
||||||
|
|
|
@ -143,19 +143,20 @@ class Bundler {
|
||||||
});
|
});
|
||||||
|
|
||||||
this._resolver = new Resolver({
|
this._resolver = new Resolver({
|
||||||
projectRoots: opts.projectRoots,
|
|
||||||
blacklistRE: opts.blacklistRE,
|
|
||||||
polyfillModuleNames: opts.polyfillModuleNames,
|
|
||||||
moduleFormat: opts.moduleFormat,
|
|
||||||
assetRoots: opts.assetRoots,
|
|
||||||
fileWatcher: opts.fileWatcher,
|
|
||||||
assetExts: opts.assetExts,
|
assetExts: opts.assetExts,
|
||||||
|
assetRoots: opts.assetRoots,
|
||||||
|
blacklistRE: opts.blacklistRE,
|
||||||
cache: this._cache,
|
cache: this._cache,
|
||||||
|
extraNodeModules: opts.extraNodeModules,
|
||||||
|
fileWatcher: opts.fileWatcher,
|
||||||
|
minifyCode: this._transformer.minify,
|
||||||
|
moduleFormat: opts.moduleFormat,
|
||||||
|
polyfillModuleNames: opts.polyfillModuleNames,
|
||||||
|
projectRoots: opts.projectRoots,
|
||||||
|
resetCache: opts.resetCache,
|
||||||
transformCode:
|
transformCode:
|
||||||
(module, code, options) =>
|
(module, code, options) =>
|
||||||
this._transformer.transformFile(module.path, code, options),
|
this._transformer.transformFile(module.path, code, options),
|
||||||
extraNodeModules: opts.extraNodeModules,
|
|
||||||
minifyCode: this._transformer.minify,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this._projectRoots = opts.projectRoots;
|
this._projectRoots = opts.projectRoots;
|
||||||
|
|
|
@ -57,6 +57,10 @@ const validateOpts = declareOpts({
|
||||||
minifyCode: {
|
minifyCode: {
|
||||||
type: 'function',
|
type: 'function',
|
||||||
},
|
},
|
||||||
|
resetCache: {
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const getDependenciesValidateOpts = declareOpts({
|
const getDependenciesValidateOpts = declareOpts({
|
||||||
|
@ -109,6 +113,8 @@ class Resolver {
|
||||||
transformCode: opts.transformCode,
|
transformCode: opts.transformCode,
|
||||||
extraNodeModules: opts.extraNodeModules,
|
extraNodeModules: opts.extraNodeModules,
|
||||||
assetDependencies: ['react-native/Libraries/Image/AssetRegistry'],
|
assetDependencies: ['react-native/Libraries/Image/AssetRegistry'],
|
||||||
|
// for jest-haste-map
|
||||||
|
resetCache: options.resetCache,
|
||||||
});
|
});
|
||||||
|
|
||||||
this._minifyCode = opts.minifyCode;
|
this._minifyCode = opts.minifyCode;
|
||||||
|
|
|
@ -87,6 +87,7 @@ describe('processRequest', () => {
|
||||||
jest.fn().mockReturnValue({
|
jest.fn().mockReturnValue({
|
||||||
getDependecyGraph: jest.fn().mockReturnValue({
|
getDependecyGraph: jest.fn().mockReturnValue({
|
||||||
getHasteMap: jest.fn().mockReturnValue({on: jest.fn()}),
|
getHasteMap: jest.fn().mockReturnValue({on: jest.fn()}),
|
||||||
|
load: jest.fn(() => Promise.resolve()),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -241,14 +241,14 @@ class Server {
|
||||||
this._fileWatcher.on('all', this._onFileChange.bind(this));
|
this._fileWatcher.on('all', this._onFileChange.bind(this));
|
||||||
|
|
||||||
// changes to the haste map can affect resolution of files in the bundle
|
// changes to the haste map can affect resolution of files in the bundle
|
||||||
this._bundler
|
const dependencyGraph = this._bundler.getResolver().getDependecyGraph();
|
||||||
.getResolver()
|
|
||||||
.getDependecyGraph()
|
dependencyGraph.load().then(() => {
|
||||||
.getHasteMap()
|
dependencyGraph.getHasteMap().on('change', () => {
|
||||||
.on('change', () => {
|
|
||||||
debug('Clearing bundle cache due to haste map change');
|
debug('Clearing bundle cache due to haste map change');
|
||||||
this._clearBundles();
|
this._clearBundles();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
this._debouncedFileChangeHandler = debounceAndBatch(filePaths => {
|
this._debouncedFileChangeHandler = debounceAndBatch(filePaths => {
|
||||||
// only clear bundles for non-JS changes
|
// only clear bundles for non-JS changes
|
||||||
|
@ -292,7 +292,7 @@ class Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
buildBundle(options) {
|
buildBundle(options) {
|
||||||
return Promise.resolve().then(() => {
|
return this._bundler.getResolver().getDependecyGraph().load().then(() => {
|
||||||
if (!options.platform) {
|
if (!options.platform) {
|
||||||
options.platform = getPlatformExtension(options.entryFile);
|
options.platform = getPlatformExtension(options.entryFile);
|
||||||
}
|
}
|
||||||
|
@ -692,7 +692,11 @@ class Server {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error => this._handleError(res, JSON.stringify(options), error)
|
error => this._handleError(res, JSON.stringify(options), error)
|
||||||
).done();
|
).catch(error => {
|
||||||
|
process.nextTick(() => {
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_symbolicate(req, res) {
|
_symbolicate(req, res) {
|
||||||
|
|
|
@ -9,73 +9,22 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const AssetModule_DEPRECATED = require('../AssetModule_DEPRECATED');
|
const AssetModule_DEPRECATED = require('../AssetModule_DEPRECATED');
|
||||||
const Fastfs = require('../fastfs');
|
|
||||||
const debug = require('debug')('ReactNativePackager:DependencyGraph');
|
const debug = require('debug')('ReactNativePackager:DependencyGraph');
|
||||||
const path = require('../fastpath');
|
const path = require('../fastpath');
|
||||||
|
|
||||||
class DeprecatedAssetMap {
|
class DeprecatedAssetMap {
|
||||||
constructor({
|
constructor({
|
||||||
fsCrawl,
|
|
||||||
roots,
|
|
||||||
assetExts,
|
assetExts,
|
||||||
fileWatcher,
|
|
||||||
ignoreFilePath,
|
|
||||||
helpers,
|
helpers,
|
||||||
activity,
|
|
||||||
enabled,
|
|
||||||
platforms,
|
platforms,
|
||||||
|
files,
|
||||||
}) {
|
}) {
|
||||||
if (roots == null || roots.length === 0 || !enabled) {
|
|
||||||
this._disabled = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._helpers = helpers;
|
this._helpers = helpers;
|
||||||
this._map = Object.create(null);
|
this._map = Object.create(null);
|
||||||
this._assetExts = assetExts;
|
this._assetExts = assetExts;
|
||||||
this._activity = activity;
|
|
||||||
this._platforms = platforms;
|
this._platforms = platforms;
|
||||||
|
|
||||||
if (!this._disabled) {
|
files.forEach(file => this._processAsset(file));
|
||||||
this._fastfs = new Fastfs(
|
|
||||||
'Assets',
|
|
||||||
roots,
|
|
||||||
fileWatcher,
|
|
||||||
{ ignore: ignoreFilePath, crawling: fsCrawl, activity }
|
|
||||||
);
|
|
||||||
|
|
||||||
this._fastfs.on('change', this._processFileChange.bind(this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
build() {
|
|
||||||
if (this._disabled) {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._fastfs.build().then(
|
|
||||||
() => {
|
|
||||||
const activity = this._activity;
|
|
||||||
let processAsset_DEPRECATEDActivity;
|
|
||||||
if (activity) {
|
|
||||||
processAsset_DEPRECATEDActivity = activity.startEvent(
|
|
||||||
'Building (deprecated) Asset Map',
|
|
||||||
null,
|
|
||||||
{
|
|
||||||
telemetric: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._fastfs.findFilesByExts(this._assetExts).forEach(
|
|
||||||
file => this._processAsset(file)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (activity) {
|
|
||||||
activity.endEvent(processAsset_DEPRECATEDActivity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(fromModule, toModuleName) {
|
resolve(fromModule, toModuleName) {
|
||||||
|
@ -105,7 +54,7 @@ class DeprecatedAssetMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_processFileChange(type, filePath, root, fstat) {
|
processFileChange(type, filePath, root, fstat) {
|
||||||
const name = assetName(filePath);
|
const name = assetName(filePath);
|
||||||
if (type === 'change' || type === 'delete') {
|
if (type === 'change' || type === 'delete') {
|
||||||
delete this._map[name];
|
delete this._map[name];
|
||||||
|
|
|
@ -77,6 +77,15 @@ fs.readFile.mockImpl(function(filepath, encoding, callback) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
fs.readFileSync.mockImpl(function(filepath, encoding) {
|
||||||
|
const node = getToNode(filepath);
|
||||||
|
// dir check
|
||||||
|
if (node && typeof node === 'object' && node.SYMLINK == null) {
|
||||||
|
throw new Error('Error readFileSync a dir: ' + filepath);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
});
|
||||||
|
|
||||||
fs.stat.mockImpl((filepath, callback) => {
|
fs.stat.mockImpl((filepath, callback) => {
|
||||||
callback = asyncCallback(callback);
|
callback = asyncCallback(callback);
|
||||||
let node;
|
let node;
|
||||||
|
@ -121,6 +130,31 @@ fs.statSync.mockImpl((filepath) => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
fs.lstat.mockImpl((filepath, callback) => {
|
||||||
|
callback = asyncCallback(callback);
|
||||||
|
let node;
|
||||||
|
try {
|
||||||
|
node = getToNode(filepath);
|
||||||
|
} catch (e) {
|
||||||
|
callback(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node && typeof node === 'object') {
|
||||||
|
callback(null, {
|
||||||
|
isDirectory: () => true,
|
||||||
|
isSymbolicLink: () => false,
|
||||||
|
mtime,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
callback(null, {
|
||||||
|
isDirectory: () => false,
|
||||||
|
isSymbolicLink: () => false,
|
||||||
|
mtime,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
fs.lstatSync.mockImpl((filepath) => {
|
fs.lstatSync.mockImpl((filepath) => {
|
||||||
const node = getToNode(filepath);
|
const node = getToNode(filepath);
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,99 @@ jest.autoMockOff();
|
||||||
jest.useRealTimers();
|
jest.useRealTimers();
|
||||||
jest.mock('fs');
|
jest.mock('fs');
|
||||||
|
|
||||||
|
// This is an ugly hack:
|
||||||
|
// * jest-haste-map uses `find` for fast file system crawling which won't work
|
||||||
|
// when we mock the file system in node. This mock copies the node crawler's
|
||||||
|
// implementation and always falls back to the node crawling mechanism.
|
||||||
|
// Ideally we'll make this an option in jest-haste-map to force it to use
|
||||||
|
// the node crawler.
|
||||||
|
jest.mock('jest-haste-map/build/crawlers/node', () => {
|
||||||
|
const H = require('jest-haste-map/build/constants');
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
function find(
|
||||||
|
roots,
|
||||||
|
extensions,
|
||||||
|
ignore,
|
||||||
|
callback)
|
||||||
|
{
|
||||||
|
const result = [];
|
||||||
|
let activeCalls = 0;
|
||||||
|
|
||||||
|
function search(directory) {
|
||||||
|
activeCalls++;
|
||||||
|
fs.readdir(directory, (err, names) => {
|
||||||
|
activeCalls--;
|
||||||
|
|
||||||
|
names.forEach(file => {
|
||||||
|
file = process.platform === 'win32' ?
|
||||||
|
path.win32.join(directory, file) :
|
||||||
|
path.join(directory, file);
|
||||||
|
if (ignore(file)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
activeCalls++;
|
||||||
|
|
||||||
|
fs.lstat(file, (err, stat) => {
|
||||||
|
activeCalls--;
|
||||||
|
|
||||||
|
if (!err && stat && !stat.isSymbolicLink()) {
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
search(file);
|
||||||
|
} else {
|
||||||
|
const ext = path.extname(file).substr(1);
|
||||||
|
if (extensions.indexOf(ext) !== -1) {
|
||||||
|
result.push([file, stat.mtime.getTime()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (activeCalls === 0) {
|
||||||
|
callback(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (activeCalls === 0) {
|
||||||
|
callback(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
roots.forEach(search);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function nodeCrawl(
|
||||||
|
roots,
|
||||||
|
extensions,
|
||||||
|
ignore,
|
||||||
|
data)
|
||||||
|
{
|
||||||
|
return new Promise(resolve => {
|
||||||
|
const callback = list => {
|
||||||
|
const files = Object.create(null);
|
||||||
|
list.forEach(fileData => {
|
||||||
|
const name = fileData[0];
|
||||||
|
const mtime = fileData[1];
|
||||||
|
const existingFile = data.files[name];
|
||||||
|
if (existingFile && existingFile[H.MTIME] === mtime) {
|
||||||
|
files[name] = existingFile;
|
||||||
|
} else {
|
||||||
|
// See ../constants.js
|
||||||
|
files[name] = ['', mtime, 0, []];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
data.files = files;
|
||||||
|
resolve(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
find(roots, extensions, ignore, callback);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
const mocksPattern = /(?:[\\/]|^)__mocks__[\\/]([^\/]+)\.js$/;
|
const mocksPattern = /(?:[\\/]|^)__mocks__[\\/]([^\/]+)\.js$/;
|
||||||
|
|
||||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
|
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
|
||||||
|
@ -103,11 +196,15 @@ describe('DependencyGraph', function() {
|
||||||
],
|
],
|
||||||
platforms: ['ios', 'android'],
|
platforms: ['ios', 'android'],
|
||||||
shouldThrowOnUnresolvedErrors: () => false,
|
shouldThrowOnUnresolvedErrors: () => false,
|
||||||
|
useWatchman: false,
|
||||||
|
maxWorkers: 1,
|
||||||
|
resetCache: true,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('get sync dependencies (posix)', function() {
|
describe('get sync dependencies (posix)', function() {
|
||||||
let DependencyGraph;
|
let DependencyGraph;
|
||||||
|
const consoleWarn = console.warn;
|
||||||
const realPlatform = process.platform;
|
const realPlatform = process.platform;
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
process.platform = 'linux';
|
process.platform = 'linux';
|
||||||
|
@ -115,10 +212,11 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
|
console.warn = consoleWarn;
|
||||||
process.platform = realPlatform;
|
process.platform = realPlatform;
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should get dependencies', function() {
|
it('should get dependencies', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -186,7 +284,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should resolve relative entry path', function() {
|
it('should resolve relative entry path', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -219,7 +317,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should get shallow dependencies', function() {
|
it('should get shallow dependencies', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -274,7 +372,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should get dependencies with the correct extensions', function() {
|
it('should get dependencies with the correct extensions', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -328,7 +426,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should get json dependencies', function() {
|
it('should get json dependencies', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -388,7 +486,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should get package json as a dep', () => {
|
it('should get package json as a dep', () => {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -435,7 +533,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should get dependencies with deprecated assets', function() {
|
it('should get dependencies with deprecated assets', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -483,7 +581,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should get dependencies with relative assets', function() {
|
it('should get dependencies with relative assets', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -533,7 +631,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should get dependencies with assets and resolution', function() {
|
it('should get dependencies with assets and resolution', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -612,7 +710,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should respect platform extension in assets', function() {
|
it('should respect platform extension in assets', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -692,7 +790,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('Deprecated and relative assets can live together', function() {
|
it('Deprecated and relative assets can live together', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -754,7 +852,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should get recursive dependencies', function() {
|
it('should get recursive dependencies', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -804,7 +902,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with packages', function() {
|
it('should work with packages', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -855,7 +953,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with packages', function() {
|
it('should work with packages', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -906,7 +1004,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with packages with a dot in the name', function() {
|
it('should work with packages with a dot in the name', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -975,7 +1073,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should default main package to index.js', function() {
|
it('should default main package to index.js', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1020,7 +1118,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should resolve using alternative ids', () => {
|
it('should resolve using alternative ids', () => {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1069,7 +1167,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should default use index.js if main is a dir', function() {
|
it('should default use index.js if main is a dir', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1117,7 +1215,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should resolve require to index if it is a dir', function() {
|
it('should resolve require to index if it is a dir', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1162,7 +1260,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should resolve require to main if it is a dir w/ a package.json', function() {
|
it('should resolve require to main if it is a dir w/ a package.json', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1211,7 +1309,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should ignore malformed packages', function() {
|
it('should ignore malformed packages', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1248,8 +1346,9 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should fatal on multiple modules with the same name', function() {
|
it('should fatal on multiple modules with the same name', function() {
|
||||||
var root = '/root';
|
const root = '/root';
|
||||||
|
console.warn = jest.fn();
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
'index.js': [
|
'index.js': [
|
||||||
|
@ -1279,10 +1378,11 @@ describe('DependencyGraph', function() {
|
||||||
'with the same name across two different files.'
|
'with the same name across two different files.'
|
||||||
);
|
);
|
||||||
expect(err.type).toEqual('DependencyGraphError');
|
expect(err.type).toEqual('DependencyGraphError');
|
||||||
|
expect(console.warn).toBeCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should be forgiving with missing requires', function() {
|
it('should be forgiving with missing requires', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1317,7 +1417,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with packages with subdirs', function() {
|
it('should work with packages with subdirs', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1373,7 +1473,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with packages with symlinked subdirs', function() {
|
it('should work with packages with symlinked subdirs', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'symlinkedPackage': {
|
'symlinkedPackage': {
|
||||||
|
@ -1430,7 +1530,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with relative modules in packages', function() {
|
it('should work with relative modules in packages', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1522,7 +1622,7 @@ describe('DependencyGraph', function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function testBrowserField(fieldName) {
|
function testBrowserField(fieldName) {
|
||||||
pit('should support simple browser field in packages ("' + fieldName + '")', function() {
|
it('should support simple browser field in packages ("' + fieldName + '")', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1577,7 +1677,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should support browser field in packages w/o .js ext ("' + fieldName + '")', function() {
|
it('should support browser field in packages w/o .js ext ("' + fieldName + '")', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1630,7 +1730,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should support mapping main in browser field json ("' + fieldName + '")', function() {
|
it('should support mapping main in browser field json ("' + fieldName + '")', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1686,7 +1786,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work do correct browser mapping w/o js ext ("' + fieldName + '")', function() {
|
it('should work do correct browser mapping w/o js ext ("' + fieldName + '")', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1744,7 +1844,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should support browser mapping of files ("' + fieldName + '")', function() {
|
it('should support browser mapping of files ("' + fieldName + '")', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1848,7 +1948,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should support browser mapping for packages ("' + fieldName + '")', function() {
|
it('should support browser mapping for packages ("' + fieldName + '")', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1920,7 +2020,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should support browser mapping of a package to a file ("' + fieldName + '")', () => {
|
it('should support browser mapping of a package to a file ("' + fieldName + '")', () => {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -1999,7 +2099,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should support browser mapping for packages ("' + fieldName + '")', function() {
|
it('should support browser mapping for packages ("' + fieldName + '")', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -2071,7 +2171,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should support browser exclude of a package ("' + fieldName + '")', function() {
|
it('should support browser exclude of a package ("' + fieldName + '")', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -2128,7 +2228,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should support browser exclude of a file ("' + fieldName + '")', function() {
|
it('should support browser exclude of a file ("' + fieldName + '")', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -2181,7 +2281,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pit('should fall back to browser mapping from react-native mapping', function() {
|
it('should fall back to browser mapping from react-native mapping', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -2273,7 +2373,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with absolute paths', () => {
|
it('should work with absolute paths', () => {
|
||||||
const root = '/root';
|
const root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
[root.slice(1)]: {
|
[root.slice(1)]: {
|
||||||
|
@ -2313,7 +2413,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should merge browser mapping with react-native mapping', function() {
|
it('should merge browser mapping with react-native mapping', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -2451,7 +2551,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should fall back to `extraNodeModules`', () => {
|
it('should fall back to `extraNodeModules`', () => {
|
||||||
const root = '/root';
|
const root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
[root.slice(1)]: {
|
[root.slice(1)]: {
|
||||||
|
@ -2513,7 +2613,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit(
|
it(
|
||||||
'should only use `extraNodeModules` after checking all possible filesystem locations',
|
'should only use `extraNodeModules` after checking all possible filesystem locations',
|
||||||
() => {
|
() => {
|
||||||
const root = '/root';
|
const root = '/root';
|
||||||
|
@ -2561,7 +2661,7 @@ describe('DependencyGraph', function() {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
pit('should be able to resolve paths within `extraNodeModules`', () => {
|
it('should be able to resolve paths within `extraNodeModules`', () => {
|
||||||
const root = '/root';
|
const root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
[root.slice(1)]: {
|
[root.slice(1)]: {
|
||||||
|
@ -2692,7 +2792,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with absolute paths', () => {
|
it('should work with absolute paths', () => {
|
||||||
const root = 'C:\\root';
|
const root = 'C:\\root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -2745,7 +2845,7 @@ describe('DependencyGraph', function() {
|
||||||
process.platform = realPlatform;
|
process.platform = realPlatform;
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with nested node_modules', function() {
|
it('should work with nested node_modules', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -2835,7 +2935,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('platform should work with node_modules', function() {
|
it('platform should work with node_modules', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -2905,7 +3005,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('nested node_modules with specific paths', function() {
|
it('nested node_modules with specific paths', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -2996,7 +3096,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('nested node_modules with browser field', function() {
|
it('nested node_modules with browser field', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -3091,7 +3191,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('node_modules should support multi level', function() {
|
it('node_modules should support multi level', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -3165,7 +3265,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should selectively ignore providesModule in node_modules', function() {
|
it('should selectively ignore providesModule in node_modules', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
var otherRoot = '/anotherRoot';
|
var otherRoot = '/anotherRoot';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
|
@ -3339,7 +3439,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should not be confused by prev occuring whitelisted names', function() {
|
it('should not be confused by prev occuring whitelisted names', function() {
|
||||||
var root = '/react-haste';
|
var root = '/react-haste';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'react-haste': {
|
'react-haste': {
|
||||||
|
@ -3397,7 +3497,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
pit('should ignore modules it cant find (assumes own require system)', function() {
|
it('should ignore modules it cant find (assumes own require system)', function() {
|
||||||
// For example SourceMap.js implements it's own require system.
|
// For example SourceMap.js implements it's own require system.
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
|
@ -3441,7 +3541,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with node packages with a .js in the name', function() {
|
it('should work with node packages with a .js in the name', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -3494,7 +3594,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with multiple platforms (haste)', function() {
|
it('should work with multiple platforms (haste)', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -3553,7 +3653,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should pick the generic file', function() {
|
it('should pick the generic file', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -3613,7 +3713,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with multiple platforms (node)', function() {
|
it('should work with multiple platforms (node)', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -3660,7 +3760,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should require package.json', () => {
|
it('should require package.json', () => {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -3741,7 +3841,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with one-character node_modules', () => {
|
it('should work with one-character node_modules', () => {
|
||||||
const root = '/root';
|
const root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
[root.slice(1)]: {
|
[root.slice(1)]: {
|
||||||
|
@ -3796,7 +3896,7 @@ describe('DependencyGraph', function() {
|
||||||
|
|
||||||
const DependencyGraph = require('../index');
|
const DependencyGraph = require('../index');
|
||||||
|
|
||||||
pit('should work with nested node_modules', function() {
|
it('should work with nested node_modules', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -3886,7 +3986,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('platform should work with node_modules', function() {
|
it('platform should work with node_modules', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -3956,7 +4056,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('nested node_modules with specific paths', function() {
|
it('nested node_modules with specific paths', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -4047,7 +4147,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('nested node_modules with browser field', function() {
|
it('nested node_modules with browser field', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -4142,7 +4242,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('node_modules should support multi level', function() {
|
it('node_modules should support multi level', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -4216,7 +4316,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should selectively ignore providesModule in node_modules', function() {
|
it('should selectively ignore providesModule in node_modules', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
var otherRoot = '/anotherRoot';
|
var otherRoot = '/anotherRoot';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
|
@ -4390,7 +4490,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should not be confused by prev occuring whitelisted names', function() {
|
it('should not be confused by prev occuring whitelisted names', function() {
|
||||||
var root = '/react-haste';
|
var root = '/react-haste';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'react-haste': {
|
'react-haste': {
|
||||||
|
@ -4447,7 +4547,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should ignore modules it cant find (assumes own require system)', function() {
|
it('should ignore modules it cant find (assumes own require system)', function() {
|
||||||
// For example SourceMap.js implements it's own require system.
|
// For example SourceMap.js implements it's own require system.
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
|
@ -4491,7 +4591,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with node packages with a .js in the name', function() {
|
it('should work with node packages with a .js in the name', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -4544,7 +4644,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with multiple platforms (haste)', function() {
|
it('should work with multiple platforms (haste)', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -4603,7 +4703,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should pick the generic file', function() {
|
it('should pick the generic file', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -4662,7 +4762,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should work with multiple platforms (node)', function() {
|
it('should work with multiple platforms (node)', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -4709,7 +4809,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should require package.json', () => {
|
it('should require package.json', () => {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -4824,7 +4924,7 @@ describe('DependencyGraph', function() {
|
||||||
process.platform = realPlatform;
|
process.platform = realPlatform;
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('updates module dependencies', function() {
|
it('updates module dependencies', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
var filesystem = setMockFileSystem({
|
var filesystem = setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -4887,7 +4987,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('updates module dependencies on file change', function() {
|
it('updates module dependencies on file change', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
var filesystem = setMockFileSystem({
|
var filesystem = setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -4950,7 +5050,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('updates module dependencies on file delete', function() {
|
it('updates module dependencies on file delete', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
var filesystem = setMockFileSystem({
|
var filesystem = setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -5012,7 +5112,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('updates module dependencies on file add', function() {
|
it('updates module dependencies on file add', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
var filesystem = setMockFileSystem({
|
var filesystem = setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -5105,7 +5205,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('updates module dependencies on deprecated asset add', function() {
|
it('updates module dependencies on deprecated asset add', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
var filesystem = setMockFileSystem({
|
var filesystem = setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -5174,7 +5274,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('updates module dependencies on relative asset add', function() {
|
it('updates module dependencies on relative asset add', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
var filesystem = setMockFileSystem({
|
var filesystem = setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -5244,7 +5344,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('runs changes through ignore filter', function() {
|
it('runs changes through ignore filter', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
var filesystem = setMockFileSystem({
|
var filesystem = setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -5334,7 +5434,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should ignore directory updates', function() {
|
it('should ignore directory updates', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -5409,7 +5509,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('changes to browser field', function() {
|
it('changes to browser field', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
var filesystem = setMockFileSystem({
|
var filesystem = setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -5472,7 +5572,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('removes old package from cache', function() {
|
it('removes old package from cache', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
var filesystem = setMockFileSystem({
|
var filesystem = setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -5523,7 +5623,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should update node package changes', function() {
|
it('should update node package changes', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
var filesystem = setMockFileSystem({
|
var filesystem = setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -5629,7 +5729,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should update node package main changes', function() {
|
it('should update node package main changes', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
var filesystem = setMockFileSystem({
|
var filesystem = setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -5694,7 +5794,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('should not error when the watcher reports a known file as added', function() {
|
it('should not error when the watcher reports a known file as added', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -5737,7 +5837,7 @@ describe('DependencyGraph', function() {
|
||||||
process.platform = realPlatform;
|
process.platform = realPlatform;
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('supports custom file extensions', () => {
|
it('supports custom file extensions', () => {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -5808,7 +5908,7 @@ describe('DependencyGraph', function() {
|
||||||
process.platform = realPlatform;
|
process.platform = realPlatform;
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('resolves to null if mocksPattern is not specified', () => {
|
it('resolves to null if mocksPattern is not specified', () => {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -5830,7 +5930,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('retrieves a list of all required mocks', () => {
|
it('retrieves a list of all required mocks', () => {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -5863,7 +5963,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('adds mocks as a dependency of their actual module', () => {
|
it('adds mocks as a dependency of their actual module', () => {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -5936,7 +6036,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('resolves mocks that do not have a real module associated with them', () => {
|
it('resolves mocks that do not have a real module associated with them', () => {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
'root': {
|
'root': {
|
||||||
|
@ -6035,20 +6135,20 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('calls back for each finished module', () => {
|
it('calls back for each finished module', () => {
|
||||||
return getDependencies().then(() =>
|
return getDependencies().then(() =>
|
||||||
expect(onProgress.mock.calls.length).toBe(8)
|
expect(onProgress.mock.calls.length).toBe(8)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('increases the number of finished modules in steps of one', () => {
|
it('increases the number of finished modules in steps of one', () => {
|
||||||
return getDependencies().then(() => {
|
return getDependencies().then(() => {
|
||||||
const increments = onProgress.mock.calls.map(([finished]) => finished);
|
const increments = onProgress.mock.calls.map(([finished]) => finished);
|
||||||
expect(increments).toEqual([1, 2, 3, 4, 5, 6, 7, 8]);
|
expect(increments).toEqual([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('adds the number of discovered modules to the number of total modules', () => {
|
it('adds the number of discovered modules to the number of total modules', () => {
|
||||||
return getDependencies().then(() => {
|
return getDependencies().then(() => {
|
||||||
const increments = onProgress.mock.calls.map(([, total]) => total);
|
const increments = onProgress.mock.calls.map(([, total]) => total);
|
||||||
expect(increments).toEqual([3, 5, 6, 6, 7, 7, 8, 8]);
|
expect(increments).toEqual([3, 5, 6, 6, 7, 7, 8, 8]);
|
||||||
|
@ -6062,7 +6162,7 @@ describe('DependencyGraph', function() {
|
||||||
DependencyGraph = require('../index');
|
DependencyGraph = require('../index');
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('allows setting dependencies for asset modules', () => {
|
it('allows setting dependencies for asset modules', () => {
|
||||||
const assetDependencies = ['arbitrary', 'dependencies'];
|
const assetDependencies = ['arbitrary', 'dependencies'];
|
||||||
|
|
||||||
setMockFileSystem({
|
setMockFileSystem({
|
||||||
|
@ -6121,7 +6221,7 @@ describe('DependencyGraph', function() {
|
||||||
roots: ['/root'],
|
roots: ['/root'],
|
||||||
});
|
});
|
||||||
moduleReadDeferreds = {};
|
moduleReadDeferreds = {};
|
||||||
callDeferreds = [defer()/* a.js */, defer()/* b.js */];
|
callDeferreds = [defer(), defer()]; // [a.js, b.js]
|
||||||
|
|
||||||
Module.prototype.read = jest.genMockFn().mockImplementation(function() {
|
Module.prototype.read = jest.genMockFn().mockImplementation(function() {
|
||||||
const returnValue = moduleRead.apply(this, arguments);
|
const returnValue = moduleRead.apply(this, arguments);
|
||||||
|
@ -6143,7 +6243,7 @@ describe('DependencyGraph', function() {
|
||||||
Module.prototype.read = moduleRead;
|
Module.prototype.read = moduleRead;
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('produces a deterministic tree if the "a" module resolves first', () => {
|
it('produces a deterministic tree if the "a" module resolves first', () => {
|
||||||
const dependenciesPromise = getOrderedDependenciesAsJSON(dependencyGraph, 'index.js');
|
const dependenciesPromise = getOrderedDependenciesAsJSON(dependencyGraph, 'index.js');
|
||||||
|
|
||||||
return Promise.all(callDeferreds.map(deferred => deferred.promise))
|
return Promise.all(callDeferreds.map(deferred => deferred.promise))
|
||||||
|
@ -6168,7 +6268,7 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('produces a deterministic tree if the "b" module resolves first', () => {
|
it('produces a deterministic tree if the "b" module resolves first', () => {
|
||||||
const dependenciesPromise = getOrderedDependenciesAsJSON(dependencyGraph, 'index.js');
|
const dependenciesPromise = getOrderedDependenciesAsJSON(dependencyGraph, 'index.js');
|
||||||
|
|
||||||
return Promise.all(callDeferreds.map(deferred => deferred.promise))
|
return Promise.all(callDeferreds.map(deferred => deferred.promise))
|
||||||
|
|
|
@ -78,17 +78,16 @@ describe('Module', () => {
|
||||||
const createJSONModule =
|
const createJSONModule =
|
||||||
(options) => createModule({...options, file: '/root/package.json'});
|
(options) => createModule({...options, file: '/root/package.json'});
|
||||||
|
|
||||||
beforeEach(function(done) {
|
beforeEach(function() {
|
||||||
process.platform = 'linux';
|
process.platform = 'linux';
|
||||||
cache = createCache();
|
cache = createCache();
|
||||||
fastfs = new Fastfs(
|
fastfs = new Fastfs(
|
||||||
'test',
|
'test',
|
||||||
['/root'],
|
['/root'],
|
||||||
fileWatcher,
|
fileWatcher,
|
||||||
{crawling: Promise.resolve([fileName, '/root/package.json']), ignore: []},
|
['/root/index.js', '/root/package.json'],
|
||||||
|
{ignore: []},
|
||||||
);
|
);
|
||||||
|
|
||||||
fastfs.build().then(done);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Module ID', () => {
|
describe('Module ID', () => {
|
||||||
|
|
|
@ -22,13 +22,17 @@ const contents = fs.readFileSync(fileName, 'utf-8');
|
||||||
|
|
||||||
describe('fastfs:', function() {
|
describe('fastfs:', function() {
|
||||||
let fastfs;
|
let fastfs;
|
||||||
const crawling = Promise.resolve([fileName]);
|
|
||||||
const roots = [__dirname];
|
const roots = [__dirname];
|
||||||
const watcher = new EventEmitter();
|
const watcher = new EventEmitter();
|
||||||
|
|
||||||
beforeEach(function(done) {
|
beforeEach(function() {
|
||||||
fastfs = new Fastfs('arbitrary', roots, watcher, {crawling});
|
fastfs = new Fastfs(
|
||||||
fastfs.build().then(done);
|
'arbitrary',
|
||||||
|
roots,
|
||||||
|
watcher,
|
||||||
|
[`${__dirname}/fastfs-data`],
|
||||||
|
{}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('partial reading', () => {
|
describe('partial reading', () => {
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const nodeCrawl = require('./node');
|
|
||||||
const watchmanCrawl = require('./watchman');
|
|
||||||
|
|
||||||
function crawl(roots, options) {
|
|
||||||
const {fileWatcher} = options;
|
|
||||||
return (fileWatcher ? fileWatcher.isWatchman() : Promise.resolve(false)).then(
|
|
||||||
isWatchman => isWatchman ? watchmanCrawl(roots, options) : nodeCrawl(roots, options)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = crawl;
|
|
|
@ -1,61 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const denodeify = require('denodeify');
|
|
||||||
const debug = require('debug')('ReactNativePackager:DependencyGraph');
|
|
||||||
const fs = require('graceful-fs');
|
|
||||||
const path = require('../fastpath');
|
|
||||||
|
|
||||||
const readDir = denodeify(fs.readdir);
|
|
||||||
const stat = denodeify(fs.stat);
|
|
||||||
|
|
||||||
function nodeRecReadDir(roots, {ignore, exts}) {
|
|
||||||
const queue = roots.slice();
|
|
||||||
const retFiles = [];
|
|
||||||
const extPattern = new RegExp(
|
|
||||||
'\.(' + exts.join('|') + ')$'
|
|
||||||
);
|
|
||||||
|
|
||||||
function search() {
|
|
||||||
const currDir = queue.shift();
|
|
||||||
if (!currDir) {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
return readDir(currDir)
|
|
||||||
.then(files => files.map(f => path.join(currDir, f)))
|
|
||||||
.then(files => Promise.all(
|
|
||||||
files.map(f => stat(f).catch(handleBrokenLink))
|
|
||||||
).then(stats => [
|
|
||||||
// Remove broken links.
|
|
||||||
files.filter((file, i) => !!stats[i]),
|
|
||||||
stats.filter(Boolean),
|
|
||||||
]))
|
|
||||||
.then(([files, stats]) => {
|
|
||||||
files.forEach((filePath, i) => {
|
|
||||||
if (ignore(filePath)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stats[i].isDirectory()) {
|
|
||||||
queue.push(filePath);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filePath.match(extPattern)) {
|
|
||||||
retFiles.push(path.resolve(filePath));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return search();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return search().then(() => retFiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleBrokenLink(e) {
|
|
||||||
debug('WARNING: error stating, possibly broken symlink', e.message);
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = nodeRecReadDir;
|
|
|
@ -1,76 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const denodeify = require('denodeify');
|
|
||||||
const path = require('../fastpath');
|
|
||||||
|
|
||||||
const watchmanURL = 'https://facebook.github.io/watchman/docs/troubleshooting.html';
|
|
||||||
|
|
||||||
function watchmanRecReadDir(roots, {ignore, fileWatcher, exts}) {
|
|
||||||
const files = [];
|
|
||||||
return Promise.all(
|
|
||||||
roots.map(
|
|
||||||
root => fileWatcher.getWatcherForRoot(root)
|
|
||||||
)
|
|
||||||
).then(
|
|
||||||
watchers => {
|
|
||||||
// All watchman roots for all watches we have.
|
|
||||||
const watchmanRoots = watchers.map(
|
|
||||||
watcher => watcher.watchProjectInfo.root
|
|
||||||
);
|
|
||||||
|
|
||||||
// Actual unique watchers (because we use watch-project we may end up with
|
|
||||||
// duplicate "real" watches, and that's by design).
|
|
||||||
// TODO(amasad): push this functionality into the `FileWatcher`.
|
|
||||||
const uniqueWatchers = watchers.filter(
|
|
||||||
(watcher, i) => watchmanRoots.indexOf(watcher.watchProjectInfo.root) === i
|
|
||||||
);
|
|
||||||
|
|
||||||
return Promise.all(
|
|
||||||
uniqueWatchers.map(watcher => {
|
|
||||||
const watchedRoot = watcher.watchProjectInfo.root;
|
|
||||||
|
|
||||||
// Build up an expression to filter the output by the relevant roots.
|
|
||||||
const dirExpr = ['anyof'];
|
|
||||||
for (let i = 0; i < roots.length; i++) {
|
|
||||||
const root = roots[i];
|
|
||||||
if (isDescendant(watchedRoot, root)) {
|
|
||||||
dirExpr.push(['dirname', path.relative(watchedRoot, root)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const cmd = denodeify(watcher.client.command.bind(watcher.client));
|
|
||||||
return cmd(['query', watchedRoot, {
|
|
||||||
suffix: exts,
|
|
||||||
expression: ['allof', ['type', 'f'], 'exists', dirExpr],
|
|
||||||
fields: ['name'],
|
|
||||||
}]).then(resp => {
|
|
||||||
if ('warning' in resp) {
|
|
||||||
console.warn('watchman warning: ', resp.warning);
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.files.forEach(filePath => {
|
|
||||||
filePath = watchedRoot + path.sep + filePath;
|
|
||||||
if (!ignore(filePath)) {
|
|
||||||
files.push(filePath);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}).then(
|
|
||||||
() => files,
|
|
||||||
error => {
|
|
||||||
throw new Error(
|
|
||||||
`Watchman error: ${error.message.trim()}. Make sure watchman ` +
|
|
||||||
`is running for this project. See ${watchmanURL}.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isDescendant(root, child) {
|
|
||||||
return root === child || child.startsWith(root + path.sep);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = watchmanRecReadDir;
|
|
|
@ -20,7 +20,7 @@ const stat = denodeify(fs.stat);
|
||||||
const NOT_FOUND_IN_ROOTS = 'NotFoundInRootsError';
|
const NOT_FOUND_IN_ROOTS = 'NotFoundInRootsError';
|
||||||
|
|
||||||
class Fastfs extends EventEmitter {
|
class Fastfs extends EventEmitter {
|
||||||
constructor(name, roots, fileWatcher, {ignore, crawling, activity}) {
|
constructor(name, roots, fileWatcher, files, {ignore, activity}) {
|
||||||
super();
|
super();
|
||||||
this._name = name;
|
this._name = name;
|
||||||
this._fileWatcher = fileWatcher;
|
this._fileWatcher = fileWatcher;
|
||||||
|
@ -37,45 +37,39 @@ class Fastfs extends EventEmitter {
|
||||||
return new File(root, true);
|
return new File(root, true);
|
||||||
});
|
});
|
||||||
this._fastPaths = Object.create(null);
|
this._fastPaths = Object.create(null);
|
||||||
this._crawling = crawling;
|
|
||||||
this._activity = activity;
|
this._activity = activity;
|
||||||
}
|
|
||||||
|
|
||||||
build() {
|
let fastfsActivity;
|
||||||
return this._crawling.then(files => {
|
if (activity) {
|
||||||
let fastfsActivity;
|
fastfsActivity = activity.startEvent(
|
||||||
const activity = this._activity;
|
'Building in-memory fs for ' + this._name,
|
||||||
if (activity) {
|
null,
|
||||||
fastfsActivity = activity.startEvent(
|
{
|
||||||
'Building in-memory fs for ' + this._name,
|
telemetric: true,
|
||||||
null,
|
},
|
||||||
{
|
);
|
||||||
telemetric: true,
|
}
|
||||||
},
|
files.forEach(filePath => {
|
||||||
);
|
const root = this._getRoot(filePath);
|
||||||
}
|
if (root) {
|
||||||
files.forEach(filePath => {
|
const newFile = new File(filePath, false);
|
||||||
const root = this._getRoot(filePath);
|
const dirname = filePath.substr(0, filePath.lastIndexOf(path.sep));
|
||||||
if (root) {
|
const parent = this._fastPaths[dirname];
|
||||||
const newFile = new File(filePath, false);
|
this._fastPaths[filePath] = newFile;
|
||||||
const dirname = filePath.substr(0, filePath.lastIndexOf(path.sep));
|
if (parent) {
|
||||||
const parent = this._fastPaths[dirname];
|
parent.addChild(newFile, this._fastPaths);
|
||||||
this._fastPaths[filePath] = newFile;
|
} else {
|
||||||
if (parent) {
|
root.addChild(newFile, this._fastPaths);
|
||||||
parent.addChild(newFile, this._fastPaths);
|
|
||||||
} else {
|
|
||||||
root.addChild(newFile, this._fastPaths);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
if (activity) {
|
|
||||||
activity.endEvent(fastfsActivity);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._fileWatcher) {
|
|
||||||
this._fileWatcher.on('all', this._processFileChange.bind(this));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (activity) {
|
||||||
|
activity.endEvent(fastfsActivity);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._fileWatcher) {
|
||||||
|
this._fileWatcher.on('all', this._processFileChange.bind(this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stat(filePath) {
|
stat(filePath) {
|
||||||
|
|
|
@ -11,10 +11,10 @@
|
||||||
const Cache = require('./Cache');
|
const Cache = require('./Cache');
|
||||||
const Fastfs = require('./fastfs');
|
const Fastfs = require('./fastfs');
|
||||||
const FileWatcher = require('./FileWatcher');
|
const FileWatcher = require('./FileWatcher');
|
||||||
|
const JestHasteMap = require('jest-haste-map');
|
||||||
const Module = require('./Module');
|
const Module = require('./Module');
|
||||||
const ModuleCache = require('./ModuleCache');
|
const ModuleCache = require('./ModuleCache');
|
||||||
const Polyfill = require('./Polyfill');
|
const Polyfill = require('./Polyfill');
|
||||||
const crawl = require('./crawlers');
|
|
||||||
const extractRequires = require('./lib/extractRequires');
|
const extractRequires = require('./lib/extractRequires');
|
||||||
const getAssetDataFromName = require('./lib/getAssetDataFromName');
|
const getAssetDataFromName = require('./lib/getAssetDataFromName');
|
||||||
const getInverseDependencies = require('./lib/getInverseDependencies');
|
const getInverseDependencies = require('./lib/getInverseDependencies');
|
||||||
|
@ -23,6 +23,7 @@ const isAbsolutePath = require('absolute-path');
|
||||||
const replacePatterns = require('./lib/replacePatterns');
|
const replacePatterns = require('./lib/replacePatterns');
|
||||||
const path = require('./fastpath');
|
const path = require('./fastpath');
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
|
const os = require('os');
|
||||||
const DependencyGraphHelpers = require('./DependencyGraph/DependencyGraphHelpers');
|
const DependencyGraphHelpers = require('./DependencyGraph/DependencyGraphHelpers');
|
||||||
const ResolutionRequest = require('./DependencyGraph/ResolutionRequest');
|
const ResolutionRequest = require('./DependencyGraph/ResolutionRequest');
|
||||||
const ResolutionResponse = require('./DependencyGraph/ResolutionResponse');
|
const ResolutionResponse = require('./DependencyGraph/ResolutionResponse');
|
||||||
|
@ -57,6 +58,10 @@ class DependencyGraph {
|
||||||
assetDependencies,
|
assetDependencies,
|
||||||
moduleOptions,
|
moduleOptions,
|
||||||
extraNodeModules,
|
extraNodeModules,
|
||||||
|
// additional arguments for jest-haste-map
|
||||||
|
useWatchman,
|
||||||
|
maxWorkers,
|
||||||
|
resetCache,
|
||||||
}) {
|
}) {
|
||||||
this._opts = {
|
this._opts = {
|
||||||
activity: activity || defaultActivity,
|
activity: activity || defaultActivity,
|
||||||
|
@ -78,6 +83,10 @@ class DependencyGraph {
|
||||||
cacheTransformResults: true,
|
cacheTransformResults: true,
|
||||||
},
|
},
|
||||||
extraNodeModules,
|
extraNodeModules,
|
||||||
|
// additional arguments for jest-haste-map & defaults
|
||||||
|
useWatchman: useWatchman !== false,
|
||||||
|
maxWorkers,
|
||||||
|
resetCache,
|
||||||
};
|
};
|
||||||
this._cache = cache;
|
this._cache = cache;
|
||||||
this._assetDependencies = assetDependencies;
|
this._assetDependencies = assetDependencies;
|
||||||
|
@ -90,103 +99,110 @@ class DependencyGraph {
|
||||||
return this._loading;
|
return this._loading;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {activity} = this._opts;
|
const mw = this._opts.maxWorkers;
|
||||||
const depGraphActivity = activity.startEvent(
|
const haste = new JestHasteMap({
|
||||||
'Initializing Packager',
|
extensions: this._opts.extensions.concat(this._opts.assetExts),
|
||||||
null,
|
ignorePattern: {test: this._opts.ignoreFilePath},
|
||||||
{
|
maxWorkers: typeof mw === 'number' && mw >= 1 ? mw : getMaxWorkers(),
|
||||||
telemetric: true,
|
mocksPattern: '',
|
||||||
},
|
name: 'react-native-packager',
|
||||||
);
|
platforms: Array.from(this._opts.platforms),
|
||||||
const crawlActivity = activity.startEvent(
|
providesModuleNodeModules: this._opts.providesModuleNodeModules,
|
||||||
'Crawling File System',
|
resetCache: this._opts.resetCache,
|
||||||
null,
|
retainAllFiles: true,
|
||||||
{
|
roots: this._opts.roots.concat(this._opts.assetRoots_DEPRECATED),
|
||||||
telemetric: true,
|
useWatchman: this._opts.useWatchman,
|
||||||
},
|
|
||||||
);
|
|
||||||
const allRoots = this._opts.roots.concat(this._opts.assetRoots_DEPRECATED);
|
|
||||||
this._crawling = crawl(allRoots, {
|
|
||||||
ignore: this._opts.ignoreFilePath,
|
|
||||||
exts: this._opts.extensions.concat(this._opts.assetExts),
|
|
||||||
fileWatcher: this._opts.fileWatcher,
|
|
||||||
});
|
|
||||||
this._crawling.then((files) => activity.endEvent(crawlActivity));
|
|
||||||
|
|
||||||
this._fastfs = new Fastfs(
|
|
||||||
'JavaScript',
|
|
||||||
this._opts.roots,
|
|
||||||
this._opts.fileWatcher,
|
|
||||||
{
|
|
||||||
ignore: this._opts.ignoreFilePath,
|
|
||||||
crawling: this._crawling,
|
|
||||||
activity: activity,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
this._fastfs.on('change', this._processFileChange.bind(this));
|
|
||||||
|
|
||||||
this._moduleCache = new ModuleCache({
|
|
||||||
fastfs: this._fastfs,
|
|
||||||
cache: this._cache,
|
|
||||||
extractRequires: this._opts.extractRequires,
|
|
||||||
transformCode: this._opts.transformCode,
|
|
||||||
depGraphHelpers: this._helpers,
|
|
||||||
assetDependencies: this._assetDependencies,
|
|
||||||
moduleOptions: this._opts.moduleOptions,
|
|
||||||
}, this._opts.platforms);
|
|
||||||
|
|
||||||
this._hasteMap = new HasteMap({
|
|
||||||
fastfs: this._fastfs,
|
|
||||||
extensions: this._opts.extensions,
|
|
||||||
moduleCache: this._moduleCache,
|
|
||||||
preferNativePlatform: this._opts.preferNativePlatform,
|
|
||||||
helpers: this._helpers,
|
|
||||||
platforms: this._opts.platforms,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this._deprecatedAssetMap = new DeprecatedAssetMap({
|
this._loading = haste.build().then(hasteMap => {
|
||||||
fsCrawl: this._crawling,
|
const {activity} = this._opts;
|
||||||
roots: this._opts.assetRoots_DEPRECATED,
|
const depGraphActivity = activity.startEvent(
|
||||||
helpers: this._helpers,
|
'Initializing Packager',
|
||||||
fileWatcher: this._opts.fileWatcher,
|
null,
|
||||||
ignoreFilePath: this._opts.ignoreFilePath,
|
{
|
||||||
assetExts: this._opts.assetExts,
|
telemetric: true,
|
||||||
activity: this._opts.activity,
|
},
|
||||||
enabled: this._opts.enableAssetMap,
|
);
|
||||||
platforms: this._opts.platforms,
|
|
||||||
});
|
|
||||||
|
|
||||||
this._loading = Promise.all([
|
const hasteFSFiles = hasteMap.hasteFS.getAllFiles();
|
||||||
this._fastfs.build()
|
|
||||||
.then(() => {
|
this._fastfs = new Fastfs(
|
||||||
const hasteActivity = activity.startEvent(
|
'JavaScript',
|
||||||
'Building Haste Map',
|
this._opts.roots,
|
||||||
null,
|
this._opts.fileWatcher,
|
||||||
{
|
hasteFSFiles,
|
||||||
telemetric: true,
|
{
|
||||||
},
|
ignore: this._opts.ignoreFilePath,
|
||||||
|
activity: activity,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this._fastfs.on('change', this._processFileChange.bind(this));
|
||||||
|
|
||||||
|
this._moduleCache = new ModuleCache({
|
||||||
|
fastfs: this._fastfs,
|
||||||
|
cache: this._cache,
|
||||||
|
extractRequires: this._opts.extractRequires,
|
||||||
|
transformCode: this._opts.transformCode,
|
||||||
|
depGraphHelpers: this._helpers,
|
||||||
|
assetDependencies: this._assetDependencies,
|
||||||
|
moduleOptions: this._opts.moduleOptions,
|
||||||
|
}, this._opts.platforms);
|
||||||
|
|
||||||
|
this._hasteMap = new HasteMap({
|
||||||
|
fastfs: this._fastfs,
|
||||||
|
extensions: this._opts.extensions,
|
||||||
|
moduleCache: this._moduleCache,
|
||||||
|
preferNativePlatform: this._opts.preferNativePlatform,
|
||||||
|
helpers: this._helpers,
|
||||||
|
platforms: this._opts.platforms,
|
||||||
|
});
|
||||||
|
|
||||||
|
const escapePath = (p: string) => {
|
||||||
|
return (path.sep === '\\') ? p.replace(/(\/|\\(?!\.))/g, '\\\\') : p;
|
||||||
|
};
|
||||||
|
|
||||||
|
const assetPattern =
|
||||||
|
new RegExp('^' + this._opts.assetRoots_DEPRECATED.map(escapePath).join('|'));
|
||||||
|
|
||||||
|
const assetFiles = hasteMap.hasteFS.matchFiles(assetPattern);
|
||||||
|
|
||||||
|
this._deprecatedAssetMap = new DeprecatedAssetMap({
|
||||||
|
helpers: this._helpers,
|
||||||
|
assetExts: this._opts.assetExts,
|
||||||
|
platforms: this._opts.platforms,
|
||||||
|
files: assetFiles,
|
||||||
|
});
|
||||||
|
|
||||||
|
this._fastfs.on('change', (type, filePath, root, fstat) => {
|
||||||
|
if (assetPattern.test(path.join(root, filePath))) {
|
||||||
|
this._deprecatedAssetMap.processFileChange(type, filePath, root, fstat);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const hasteActivity = activity.startEvent(
|
||||||
|
'Building Haste Map',
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
telemetric: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return this._hasteMap.build().then(
|
||||||
|
map => {
|
||||||
|
activity.endEvent(hasteActivity);
|
||||||
|
activity.endEvent(depGraphActivity);
|
||||||
|
return map;
|
||||||
|
},
|
||||||
|
err => {
|
||||||
|
const error = new Error(
|
||||||
|
`Failed to build DependencyGraph: ${err.message}`
|
||||||
);
|
);
|
||||||
return this._hasteMap.build().then(map => {
|
error.type = ERROR_BUILDING_DEP_GRAPH;
|
||||||
activity.endEvent(hasteActivity);
|
error.stack = err.stack;
|
||||||
return map;
|
throw error;
|
||||||
});
|
}
|
||||||
}),
|
);
|
||||||
this._deprecatedAssetMap.build(),
|
});
|
||||||
]).then(
|
|
||||||
response => {
|
|
||||||
activity.endEvent(depGraphActivity);
|
|
||||||
return response[0]; // Return the haste map
|
|
||||||
},
|
|
||||||
err => {
|
|
||||||
const error = new Error(
|
|
||||||
`Failed to build DependencyGraph: ${err.message}`
|
|
||||||
);
|
|
||||||
error.type = ERROR_BUILDING_DEP_GRAPH;
|
|
||||||
error.stack = err.stack;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return this._loading;
|
return this._loading;
|
||||||
}
|
}
|
||||||
|
@ -312,7 +328,7 @@ class DependencyGraph {
|
||||||
this._loading = this._hasteMap.build();
|
this._loading = this._hasteMap.build();
|
||||||
} else {
|
} else {
|
||||||
this._loading = this._hasteMap.processFileChange(type, absPath);
|
this._loading = this._hasteMap.processFileChange(type, absPath);
|
||||||
this._loading.catch((e) => this._hasteMapError = e);
|
this._loading.catch((e) => {this._hasteMapError = e;});
|
||||||
}
|
}
|
||||||
return this._loading;
|
return this._loading;
|
||||||
};
|
};
|
||||||
|
@ -351,4 +367,28 @@ function NotFoundError() {
|
||||||
}
|
}
|
||||||
util.inherits(NotFoundError, Error);
|
util.inherits(NotFoundError, Error);
|
||||||
|
|
||||||
|
function getMaxWorkers() {
|
||||||
|
const cores = os.cpus().length;
|
||||||
|
|
||||||
|
if (cores <= 1) {
|
||||||
|
// oh well...
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (cores <= 4) {
|
||||||
|
// don't starve the CPU while still reading reasonably rapidly
|
||||||
|
return cores - 1;
|
||||||
|
}
|
||||||
|
if (cores <= 8) {
|
||||||
|
// empirical testing showed massive diminishing returns when going over
|
||||||
|
// 4 or 5 workers on 8-core machines
|
||||||
|
return Math.floor(cores * 0.75) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pretty much guesswork
|
||||||
|
if (cores < 24) {
|
||||||
|
return Math.floor(3 / 8 * cores + 3);
|
||||||
|
}
|
||||||
|
return cores / 2;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = DependencyGraph;
|
module.exports = DependencyGraph;
|
||||||
|
|
Loading…
Reference in New Issue