diff --git a/packager.js b/packager.js index b59fbb18..e20bb99d 100644 --- a/packager.js +++ b/packager.js @@ -28,8 +28,8 @@ var options = parseCommandLine([{ default: 8081, }]); -if (!options.projectRoot) { - options.projectRoot = path.resolve(__dirname, '..'); +if (!options.projectRoots) { + options.projectRoots = [path.resolve(__dirname, '..')]; } console.log('\n' + diff --git a/react-packager/, b/react-packager/, new file mode 100644 index 00000000..e69de29b diff --git a/react-packager/src/DependencyResolver/haste/DependencyGraph/__tests__/DependencyGraph-test.js b/react-packager/src/DependencyResolver/haste/DependencyGraph/__tests__/DependencyGraph-test.js index fbd01725..fe8a18b6 100644 --- a/react-packager/src/DependencyResolver/haste/DependencyGraph/__tests__/DependencyGraph-test.js +++ b/react-packager/src/DependencyResolver/haste/DependencyGraph/__tests__/DependencyGraph-test.js @@ -21,12 +21,8 @@ describe('DependencyGraph', function() { DependencyGraph = require('../index'); fileWatcher = { - getWatcher: function() { - return q({ - on: function() { - return this; - } - }); + on: function() { + return this; } }; }); @@ -50,7 +46,7 @@ describe('DependencyGraph', function() { } }); - var dgraph = new DependencyGraph({root: root, fileWatcher: fileWatcher}); + var dgraph = new DependencyGraph({roots: [root], fileWatcher: fileWatcher}); return dgraph.load().then(function() { expect(dgraph.getOrderedDependencies('/root/index.js')) .toEqual([ @@ -79,7 +75,7 @@ describe('DependencyGraph', function() { } }); - var dgraph = new DependencyGraph({root: root, fileWatcher: fileWatcher}); + var dgraph = new DependencyGraph({roots: [root], fileWatcher: fileWatcher}); return dgraph.load().then(function() { expect(dgraph.getOrderedDependencies('/root/index.js')) .toEqual([ @@ -109,7 +105,7 @@ describe('DependencyGraph', function() { } }); - var dgraph = new DependencyGraph({root: root, fileWatcher: fileWatcher}); + var dgraph = new DependencyGraph({roots: [root], fileWatcher: fileWatcher}); return dgraph.load().then(function() { expect(dgraph.getOrderedDependencies('/root/index.js')) .toEqual([ @@ -179,7 +175,7 @@ describe('DependencyGraph', function() { } }); - var dgraph = new DependencyGraph({root: root, fileWatcher: fileWatcher}); + var dgraph = new DependencyGraph({roots: [root], fileWatcher: fileWatcher}); return dgraph.load().then(function() { expect(dgraph.getOrderedDependencies('/root/somedir/somefile.js')) .toEqual([ @@ -220,7 +216,7 @@ describe('DependencyGraph', function() { } }); - var dgraph = new DependencyGraph({root: root, fileWatcher: fileWatcher}); + var dgraph = new DependencyGraph({roots: [root], fileWatcher: fileWatcher}); return dgraph.load().then(function() { expect(dgraph.getOrderedDependencies('/root/index.js')) .toEqual([ @@ -249,7 +245,7 @@ describe('DependencyGraph', function() { } }); - var dgraph = new DependencyGraph({root: root, fileWatcher: fileWatcher}); + var dgraph = new DependencyGraph({roots: [root], fileWatcher: fileWatcher}); return dgraph.load().then(function() { expect(dgraph.getOrderedDependencies('/root/index.js')) .toEqual([ @@ -284,7 +280,7 @@ describe('DependencyGraph', function() { } }); - var dgraph = new DependencyGraph({root: root, fileWatcher: fileWatcher}); + var dgraph = new DependencyGraph({roots: [root], fileWatcher: fileWatcher}); return dgraph.load().then(function() { expect(dgraph.getOrderedDependencies('/root/index.js')) .toEqual([ @@ -324,7 +320,7 @@ describe('DependencyGraph', function() { } }); - var dgraph = new DependencyGraph({root: root, fileWatcher: fileWatcher}); + var dgraph = new DependencyGraph({roots: [root], fileWatcher: fileWatcher}); return dgraph.load().then(function() { expect(dgraph.getOrderedDependencies('/root/index.js')) .toEqual([ @@ -364,7 +360,7 @@ describe('DependencyGraph', function() { } }); - var dgraph = new DependencyGraph({root: root, fileWatcher: fileWatcher}); + var dgraph = new DependencyGraph({roots: [root], fileWatcher: fileWatcher}); return dgraph.load().then(function() { expect(dgraph.getOrderedDependencies('/root/index.js')) .toEqual([ @@ -395,16 +391,12 @@ describe('DependencyGraph', function() { beforeEach(function() { fileWatcher = { - getWatcher: function() { - return q({ - on: function(eventType, callback) { - if (eventType !== 'all') { - throw new Error('Can only handle "all" event in watcher.'); - } - triggerFileChange = callback; - return this; - } - }); + on: function(eventType, callback) { + if (eventType !== 'all') { + throw new Error('Can only handle "all" event in watcher.'); + } + triggerFileChange = callback; + return this; } }; }); @@ -436,11 +428,11 @@ describe('DependencyGraph', function() { } }); - var dgraph = new DependencyGraph({root: root, fileWatcher: fileWatcher}); + var dgraph = new DependencyGraph({roots: [root], fileWatcher: fileWatcher}); return dgraph.load().then(function() { filesystem.root['index.js'] = filesystem.root['index.js'].replace('require("foo")', ''); - triggerFileChange('change', 'index.js'); + triggerFileChange('change', 'index.js', root); return dgraph.load().then(function() { expect(dgraph.getOrderedDependencies('/root/index.js')) .toEqual([ @@ -484,11 +476,11 @@ describe('DependencyGraph', function() { } }); - var dgraph = new DependencyGraph({root: root, fileWatcher: fileWatcher}); + var dgraph = new DependencyGraph({roots: [root], fileWatcher: fileWatcher}); return dgraph.load().then(function() { filesystem.root['index.js'] = filesystem.root['index.js'].replace('require("foo")', ''); - triggerFileChange('change', 'index.js'); + triggerFileChange('change', 'index.js', root); return dgraph.load().then(function() { expect(dgraph.getOrderedDependencies('/root/index.js')) .toEqual([ @@ -532,10 +524,10 @@ describe('DependencyGraph', function() { } }); - var dgraph = new DependencyGraph({root: root, fileWatcher: fileWatcher}); + var dgraph = new DependencyGraph({roots: [root], fileWatcher: fileWatcher}); return dgraph.load().then(function() { delete filesystem.root.foo; - triggerFileChange('delete', 'foo.js'); + triggerFileChange('delete', 'foo.js', root); return dgraph.load().then(function() { expect(dgraph.getOrderedDependencies('/root/index.js')) .toEqual([ @@ -579,7 +571,7 @@ describe('DependencyGraph', function() { } }); - var dgraph = new DependencyGraph({root: root, fileWatcher: fileWatcher}); + var dgraph = new DependencyGraph({roots: [root], fileWatcher: fileWatcher}); return dgraph.load().then(function() { filesystem.root['bar.js'] = [ '/**', @@ -587,10 +579,10 @@ describe('DependencyGraph', function() { ' */', 'require("foo")' ].join('\n'); - triggerFileChange('add', 'bar.js'); + triggerFileChange('add', 'bar.js', root); filesystem.root.aPackage['main.js'] = 'require("bar")'; - triggerFileChange('change', 'aPackage/main.js'); + triggerFileChange('change', 'aPackage/main.js', root); return dgraph.load().then(function() { expect(dgraph.getOrderedDependencies('/root/index.js')) @@ -644,7 +636,7 @@ describe('DependencyGraph', function() { }); var dgraph = new DependencyGraph({ - root: root, + roots: [root], fileWatcher: fileWatcher, ignoreFilePath: function(filePath) { if (filePath === '/root/bar.js') { @@ -660,10 +652,10 @@ describe('DependencyGraph', function() { ' */', 'require("foo")' ].join('\n'); - triggerFileChange('add', 'bar.js'); + triggerFileChange('add', 'bar.js', root); filesystem.root.aPackage['main.js'] = 'require("bar")'; - triggerFileChange('change', 'aPackage/main.js'); + triggerFileChange('change', 'aPackage/main.js', root); return dgraph.load().then(function() { expect(dgraph.getOrderedDependencies('/root/index.js')) @@ -711,7 +703,7 @@ describe('DependencyGraph', function() { } } }); - var dgraph = new DependencyGraph({root: root, fileWatcher: fileWatcher}); + var dgraph = new DependencyGraph({roots: [root], fileWatcher: fileWatcher}); return dgraph.load().then(function() { triggerFileChange('change', 'aPackage', '/root', { isDirectory: function(){ return true; } diff --git a/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js b/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js index 130708b5..0cf05411 100644 --- a/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js +++ b/react-packager/src/DependencyResolver/haste/DependencyGraph/index.js @@ -14,10 +14,10 @@ var lstat = q.nfbind(fs.lstat); var realpath = q.nfbind(fs.realpath); function DependecyGraph(options) { - this._root = options.root; + this._roots = options.roots; this._ignoreFilePath = options.ignoreFilePath || function(){}; this._loaded = false; - this._queue = [this._root]; + this._queue = this._roots.slice(); this._graph = Object.create(null); this._packageByRoot = Object.create(null); this._packagesById = Object.create(null); @@ -36,16 +36,14 @@ DependecyGraph.prototype.load = function() { * Given an entry file return an array of all the dependent module descriptors. */ DependecyGraph.prototype.getOrderedDependencies = function(entryPath) { - var absolutePath; - if (!isAbsolutePath(entryPath)) { - absolutePath = path.join(this._root, entryPath); - } else { - absolutePath = entryPath; + var absolutePath = this._getAbsolutePath(entryPath); + if (absolutePath == null) { + throw new Error('Cannot find entry file in any of the roots: ' + entryPath); } var module = this._graph[absolutePath]; if (module == null) { - throw new Error('Module with path "' + absolutePath + '" is not in graph'); + throw new Error('Module with path "' + entryPath + '" is not in graph'); } var self = this; @@ -172,15 +170,11 @@ DependecyGraph.prototype.resolveDependency = function( */ DependecyGraph.prototype._init = function() { var processChange = this._processFileChange.bind(this); - var loadingWatcher = this._fileWatcher.getWatcher(); + var watcher = this._fileWatcher; - this._loading = this.load() - .then(function() { - return loadingWatcher; - }) - .then(function(watcher) { - watcher.on('all', processChange); - }); + this._loading = this.load().then(function() { + watcher.on('all', processChange); + }); }; /** @@ -370,7 +364,6 @@ DependecyGraph.prototype._updateGraphWithModule = function(module) { * Find the nearest package to a module. */ DependecyGraph.prototype._lookupPackage = function(modulePath) { - var root = this._root; var packageByRoot = this._packageByRoot; /** @@ -380,8 +373,7 @@ DependecyGraph.prototype._lookupPackage = function(modulePath) { // ideally we stop once we're outside root and this can be a simple child // dir check. However, we have to support modules that was symlinked inside // our project root. - if (!path.relative(root, currDir) === '' || currDir === '.' - || currDir === '/') { + if (currDir === '/') { return null; } else { var packageJson = packageByRoot[currDir]; @@ -400,7 +392,7 @@ DependecyGraph.prototype._lookupPackage = function(modulePath) { * Process a filewatcher change event. */ DependecyGraph.prototype._processFileChange = function(eventType, filePath, root, stat) { - var absPath = path.join(this._root, filePath); + var absPath = path.join(root, filePath); if (this._ignoreFilePath(absPath)) { return; } @@ -420,6 +412,24 @@ DependecyGraph.prototype._processFileChange = function(eventType, filePath, root } }; +/** + * Searches all roots for the file and returns the first one that has file of the same path. + */ +DependecyGraph.prototype._getAbsolutePath = function(filePath) { + if (isAbsolutePath(filePath)) { + return filePath; + } + + for (var i = 0, root; root = this._roots[i]; i++) { + var absPath = path.join(root, filePath); + if (this._graph[absPath]) { + return absPath; + } + } + + return null; +}; + /** * Extract all required modules from a `code` string. */ diff --git a/react-packager/src/DependencyResolver/haste/index.js b/react-packager/src/DependencyResolver/haste/index.js index 40e4a1d4..feb69cce 100644 --- a/react-packager/src/DependencyResolver/haste/index.js +++ b/react-packager/src/DependencyResolver/haste/index.js @@ -23,13 +23,14 @@ var DEFINE_MODULE_REPLACE_RE = /_moduleName_|_code_|_deps_/g; var REL_REQUIRE_STMT = /require\(['"]([\.\/0-9A-Z_$\-]*)['"]\)/gi; function HasteDependencyResolver(config) { + this._fileWatcher = new FileWatcher(config.projectRoots); this._depGraph = new DependencyGraph({ - root: config.projectRoot, + roots: config.projectRoots, ignoreFilePath: function(filepath) { return filepath.indexOf('__tests__') !== -1 || (config.blacklistRE && config.blacklistRE.test(filepath)); }, - fileWatcher: new FileWatcher(config.projectRoot) + fileWatcher: this._fileWatcher }); this._polyfillModuleNames = [ @@ -118,4 +119,8 @@ HasteDependencyResolver.prototype.wrapModule = function(module, code) { }); }; +HasteDependencyResolver.prototype.end = function() { + return this._fileWatcher.end(); +}; + module.exports = HasteDependencyResolver; diff --git a/react-packager/src/FileWatcher/__tests__/FileWatcher-test.js b/react-packager/src/FileWatcher/__tests__/FileWatcher-test.js index af7a4083..8baae9e1 100644 --- a/react-packager/src/FileWatcher/__tests__/FileWatcher-test.js +++ b/react-packager/src/FileWatcher/__tests__/FileWatcher-test.js @@ -16,15 +16,17 @@ describe('FileWatcher', function() { }); }); - pit('it should get the watcher instance when ready', function() { - var fileWatcher = new FileWatcher('rootDir'); - return fileWatcher.getWatcher().then(function(watcher) { - expect(watcher instanceof Watcher).toBe(true); + it('it should get the watcher instance when ready', function() { + var fileWatcher = new FileWatcher(['rootDir']); + return fileWatcher._loading.then(function(watchers) { + watchers.forEach(function(watcher) { + expect(watcher instanceof Watcher).toBe(true); + }); }); }); pit('it should end the watcher', function() { - var fileWatcher = new FileWatcher('rootDir'); + var fileWatcher = new FileWatcher(['rootDir']); Watcher.prototype.close.mockImplementation(function(callback) { callback(); }); diff --git a/react-packager/src/FileWatcher/index.js b/react-packager/src/FileWatcher/index.js index d8b17277..c9a48058 100644 --- a/react-packager/src/FileWatcher/index.js +++ b/react-packager/src/FileWatcher/index.js @@ -1,7 +1,9 @@ 'use strict'; +var EventEmitter = require('events').EventEmitter; var sane = require('sane'); var q = require('q'); +var util = require('util'); var exec = require('child_process').exec; var Promise = q.Promise; @@ -20,37 +22,57 @@ module.exports = FileWatcher; var MAX_WAIT_TIME = 3000; -var memoizedInstances = Object.create(null); +function FileWatcher(projectRoots) { + var self = this; + this._loading = q.all( + projectRoots.map(createWatcher) + ).then(function(watchers) { + watchers.forEach(function(watcher) { + watcher.on('all', function(type, filepath, root) { + self.emit('all', type, filepath, root); + }); + }); + return watchers; + }); + this._loading.done(); +} -function FileWatcher(projectRoot) { - if (memoizedInstances[projectRoot]) { - return memoizedInstances[projectRoot]; - } else { - memoizedInstances[projectRoot] = this; +util.inherits(FileWatcher, EventEmitter); + +FileWatcher.prototype.end = function() { + return this._loading.then(function(watchers) { + watchers.forEach(function(watcher) { + delete watchersByRoot[watcher._root]; + return q.ninvoke(watcher, 'close'); + }); + }); +}; + +var watchersByRoot = Object.create(null); + +function createWatcher(root) { + if (watchersByRoot[root] != null) { + return Promise.resolve(watchersByRoot[root]); } - this._loadingWatcher = detectingWatcherClass.then(function(Watcher) { - var watcher = new Watcher(projectRoot, {glob: '**/*.js'}); + return detectingWatcherClass.then(function(Watcher) { + var watcher = new Watcher(root, {glob: '**/*.js'}); return new Promise(function(resolve, reject) { var rejectTimeout = setTimeout(function() { - reject(new Error('Watcher took too long to load.')); + reject(new Error([ + 'Watcher took too long to load', + 'Try running `watchman` from your terminal', + 'https://facebook.github.io/watchman/docs/troubleshooting.html', + ].join('\n'))); }, MAX_WAIT_TIME); watcher.once('ready', function() { clearTimeout(rejectTimeout); + watchersByRoot[root] = watcher; + watcher._root = root; resolve(watcher); }); }); }); } - -FileWatcher.prototype.getWatcher = function() { - return this._loadingWatcher; -}; - -FileWatcher.prototype.end = function() { - return this._loadingWatcher.then(function(watcher) { - return q.ninvoke(watcher, 'close'); - }); -}; diff --git a/react-packager/src/JSTransformer/Cache.js b/react-packager/src/JSTransformer/Cache.js index 4aefd6eb..577af696 100644 --- a/react-packager/src/JSTransformer/Cache.js +++ b/react-packager/src/JSTransformer/Cache.js @@ -13,12 +13,7 @@ var Promise = q.Promise; module.exports = Cache; function Cache(projectConfig) { - this._cacheFilePath = path.join( - tmpdir, - 'React-Packager-JSTransformer-' + version + '-' + - projectConfig.projectRoot.split(path.sep).join('-') + - '-' + (projectConfig.cacheVersion || '0') - ); + this._cacheFilePath = cacheFilePath(projectConfig); var data; if (!projectConfig.resetCache) { @@ -118,3 +113,17 @@ function loadCacheSync(cacheFilepath) { return ret; } + +function cacheFilePath(projectConfig) { + var roots = projectConfig.projectRoots.join(',').split(path.sep).join('-'); + var cacheVersion = projectConfig.cacheVersion || '0'; + return path.join( + tmpdir, + [ + 'react-packager-cache', + version, + cacheVersion, + roots, + ].join('-') + ); +} diff --git a/react-packager/src/JSTransformer/__tests__/Cache-test.js b/react-packager/src/JSTransformer/__tests__/Cache-test.js index 85278c25..c77c6384 100644 --- a/react-packager/src/JSTransformer/__tests__/Cache-test.js +++ b/react-packager/src/JSTransformer/__tests__/Cache-test.js @@ -23,7 +23,7 @@ describe('JSTransformer Cache', function() { describe('getting/settig', function() { it('calls loader callback for uncached file', function() { - var cache = new Cache({projectRoot: '/rootDir'}); + var cache = new Cache({projectRoots: ['/rootDir']}); var loaderCb = jest.genMockFn().mockImpl(function() { return q(); }); @@ -39,7 +39,7 @@ describe('JSTransformer Cache', function() { } }); }); - var cache = new Cache({projectRoot: '/rootDir'}); + var cache = new Cache({projectRoots: ['/rootDir']}); var loaderCb = jest.genMockFn().mockImpl(function() { return q('lol'); }); @@ -56,7 +56,7 @@ describe('JSTransformer Cache', function() { } }); }); - var cache = new Cache({projectRoot: '/rootDir'}); + var cache = new Cache({projectRoots: ['/rootDir']}); var loaderCb = jest.genMockFn().mockImpl(function() { return q('lol'); }); @@ -117,7 +117,7 @@ describe('JSTransformer Cache', function() { }); pit('should load cache from disk', function() { - var cache = new Cache({projectRoot: '/rootDir'}); + var cache = new Cache({projectRoots: ['/rootDir']}); var loaderCb = jest.genMockFn(); return cache.get('/rootDir/someFile', loaderCb).then(function(value) { expect(loaderCb).not.toBeCalled(); @@ -143,7 +143,7 @@ describe('JSTransformer Cache', function() { return 123; }; - var cache = new Cache({projectRoot: '/rootDir'}); + var cache = new Cache({projectRoots: ['/rootDir']}); var loaderCb = jest.genMockFn().mockImpl(function() { return q('new value'); }); @@ -184,7 +184,7 @@ describe('JSTransformer Cache', function() { }); }); - var cache = new Cache({projectRoot: '/rootDir'}); + var cache = new Cache({projectRoots: ['/rootDir']}); cache.get('/rootDir/bar', function() { return q('bar value'); }); diff --git a/react-packager/src/Packager/__tests__/Packager-test.js b/react-packager/src/Packager/__tests__/Packager-test.js index 335db930..21af12ca 100644 --- a/react-packager/src/Packager/__tests__/Packager-test.js +++ b/react-packager/src/Packager/__tests__/Packager-test.js @@ -35,7 +35,7 @@ describe('Packager', function() { }; }); - var packager = new Packager({}); + var packager = new Packager({projectRoots: []}); var modules = [ {id: 'foo', path: '/root/foo.js', dependencies: []}, {id: 'bar', path: '/root/bar.js', dependencies: []}, diff --git a/react-packager/src/Packager/index.js b/react-packager/src/Packager/index.js index 83af7c22..0bf3e7d8 100644 --- a/react-packager/src/Packager/index.js +++ b/react-packager/src/Packager/index.js @@ -3,6 +3,7 @@ var assert = require('assert'); var fs = require('fs'); var path = require('path'); +var q = require('q'); var Promise = require('q').Promise; var Transformer = require('../JSTransformer'); var DependencyResolver = require('../DependencyResolver'); @@ -45,10 +46,7 @@ var DEFAULT_CONFIG = { }; function Packager(projectConfig) { - // Verify that the root exists. - var root = projectConfig.projectRoot; - assert(fs.statSync(root).isDirectory(), 'Root has to be a valid directory'); - this._rootPath = root; + projectConfig.projectRoots.forEach(verifyRootExists); this._config = Object.create(DEFAULT_CONFIG); for (var key in projectConfig) { @@ -61,7 +59,10 @@ function Packager(projectConfig) { } Packager.prototype.kill = function() { - return this._transformer.kill(); + return q.all([ + this._transformer.kill(), + this._resolver.end(), + ]); }; Packager.prototype.package = function(main, runModule, sourceMapUrl) { @@ -116,4 +117,9 @@ Packager.prototype._transformModule = function(module) { }); }; +function verifyRootExists(root) { + // Verify that the root exists. + assert(fs.statSync(root).isDirectory(), 'Root has to be a valid directory'); +} + module.exports = Packager; diff --git a/react-packager/src/Server/__tests__/Server-test.js b/react-packager/src/Server/__tests__/Server-test.js index 0482d4f2..3b37c76e 100644 --- a/react-packager/src/Server/__tests__/Server-test.js +++ b/react-packager/src/Server/__tests__/Server-test.js @@ -1,6 +1,4 @@ - 'use strict'; - -jest.dontMock('worker-farm') +jest.setMock('worker-farm', function(){ return function(){}; }) .dontMock('q') .dontMock('os') .dontMock('errno/custom') @@ -19,7 +17,7 @@ describe('processRequest', function(){ var FileWatcher; var options = { - projectRoot: 'root', + projectRoots: ['root'], blacklistRE: null, cacheVersion: null, polyfillModuleNames: null @@ -59,11 +57,8 @@ describe('processRequest', function(){ } }) }; - FileWatcher.prototype.getWatcher = function() { - return q({ - on: watcherFunc - }); - }; + + FileWatcher.prototype.on = watcherFunc; Packager.prototype.invalidateFile = invalidatorFunc; @@ -98,16 +93,12 @@ describe('processRequest', function(){ describe('file changes', function() { var triggerFileChange; beforeEach(function() { - FileWatcher.prototype.getWatcher = function() { - return q({ - on: function(eventType, callback) { - if (eventType !== 'all') { - throw new Error('Can only handle "all" event in watcher.'); - } - triggerFileChange = callback; - return this; - } - }); + FileWatcher.prototype.on = function(eventType, callback) { + if (eventType !== 'all') { + throw new Error('Can only handle "all" event in watcher.'); + } + triggerFileChange = callback; + return this; }; }); @@ -115,7 +106,7 @@ describe('processRequest', function(){ result = makeRequest(requestHandler,'mybundle.includeRequire.runModule.bundle'); return result.then(function(response){ var onFileChange = watcherFunc.mock.calls[0][1]; - onFileChange('all','path/file.js'); + onFileChange('all','path/file.js', options.projectRoots[0]); expect(invalidatorFunc.mock.calls[0][0]).toEqual('root/path/file.js'); }); }); @@ -152,7 +143,7 @@ describe('processRequest', function(){ .then(function(response){ expect(response).toEqual("this is the first source"); expect(packageFunc.mock.calls.length).toBe(1); - triggerFileChange('all','path/file.js'); + triggerFileChange('all','path/file.js', options.projectRoots[0]); }) .then(function(){ expect(packageFunc.mock.calls.length).toBe(2); diff --git a/react-packager/src/Server/index.js b/react-packager/src/Server/index.js index 877b48ca..36681d63 100644 --- a/react-packager/src/Server/index.js +++ b/react-packager/src/Server/index.js @@ -8,10 +8,10 @@ var q = require('q'); module.exports = Server; function Server(options) { - this._projectRoot = options.projectRoot; + this._projectRoots = options.projectRoots; this._packages = Object.create(null); this._packager = new Packager({ - projectRoot: options.projectRoot, + projectRoots: options.projectRoots, blacklistRE: options.blacklistRE, polyfillModuleNames: options.polyfillModuleNames || [], runtimeCode: options.runtimeCode, @@ -20,18 +20,18 @@ function Server(options) { dev: options.dev, }); - this._fileWatcher = new FileWatcher(options.projectRoot); + this._fileWatcher = new FileWatcher(options.projectRoots); var onFileChange = this._onFileChange.bind(this); - this._fileWatcher.getWatcher().done(function(watcher) { - watcher.on('all', onFileChange); - }); + this._fileWatcher.on('all', onFileChange); } -Server.prototype._onFileChange = function(type, filepath) { - var absPath = path.join(this._projectRoot, filepath); +Server.prototype._onFileChange = function(type, filepath, root) { + var absPath = path.join(root, filepath); this._packager.invalidateFile(absPath); - this._rebuildPackages(absPath); + // Make sure the file watcher event runs through the system before + // we rebuild the packages. + setImmediate(this._rebuildPackages.bind(this, absPath)) }; Server.prototype._rebuildPackages = function(filepath) {