From 7f4049d379f5083634ab63e59c51eebaabdc4b7a Mon Sep 17 00:00:00 2001 From: Jasper De Moor Date: Sun, 24 Jun 2018 08:06:12 +0200 Subject: [PATCH] Fix bugs related to watching symlinks (#1408) --- src/Bundler.js | 10 +++++--- src/utils/fs.js | 11 +++++++- .../commonjs-with-symlinks/local.js | 2 ++ .../commonjs-with-symlinks/src/index.js | 5 ++++ .../src/symlinked_local.js | 1 + test/watcher.js | 25 +++++++++++++++++++ 6 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 test/integration/commonjs-with-symlinks/local.js create mode 100644 test/integration/commonjs-with-symlinks/src/index.js create mode 120000 test/integration/commonjs-with-symlinks/src/symlinked_local.js diff --git a/src/Bundler.js b/src/Bundler.js index 5698f5efc52..1bc7351ef44 100644 --- a/src/Bundler.js +++ b/src/Bundler.js @@ -56,6 +56,7 @@ class Bundler extends EventEmitter { this.pending = false; this.loadedAssets = new Map(); this.watchedAssets = new Map(); + this.farm = null; this.watcher = null; this.hmr = null; @@ -391,24 +392,27 @@ class Bundler extends EventEmitter { return asset; } - watch(path, asset) { + async watch(path, asset) { if (!this.watcher) { return; } + path = await fs.realpath(path); + if (!this.watchedAssets.has(path)) { this.watcher.watch(path); this.watchedAssets.set(path, new Set()); } - this.watchedAssets.get(path).add(asset); } - unwatch(path, asset) { + async unwatch(path, asset) { if (!this.watchedAssets.has(path)) { return; } + path = await fs.realpath(path); + let watched = this.watchedAssets.get(path); watched.delete(asset); diff --git a/src/utils/fs.js b/src/utils/fs.js index a301f0eadce..830efa410aa 100644 --- a/src/utils/fs.js +++ b/src/utils/fs.js @@ -7,7 +7,16 @@ exports.writeFile = promisify(fs.writeFile); exports.stat = promisify(fs.stat); exports.readdir = promisify(fs.readdir); exports.unlink = promisify(fs.unlink); -exports.realpath = promisify(fs.realpath); +exports.realpath = async function(path) { + const realpath = promisify(fs.realpath); + try { + path = await realpath(path); + } catch (e) { + // do nothing + } + return path; +}; +exports.lstat = promisify(fs.lstat); exports.exists = function(filename) { return new Promise(resolve => { diff --git a/test/integration/commonjs-with-symlinks/local.js b/test/integration/commonjs-with-symlinks/local.js new file mode 100644 index 00000000000..59aa6ffd125 --- /dev/null +++ b/test/integration/commonjs-with-symlinks/local.js @@ -0,0 +1,2 @@ +exports.a = 1; +exports.b = 2; diff --git a/test/integration/commonjs-with-symlinks/src/index.js b/test/integration/commonjs-with-symlinks/src/index.js new file mode 100644 index 00000000000..29505d1b818 --- /dev/null +++ b/test/integration/commonjs-with-symlinks/src/index.js @@ -0,0 +1,5 @@ +var local = require('./symlinked_local'); + +module.exports = function () { + return local.a + local.b; +}; diff --git a/test/integration/commonjs-with-symlinks/src/symlinked_local.js b/test/integration/commonjs-with-symlinks/src/symlinked_local.js new file mode 120000 index 00000000000..ea037a11afd --- /dev/null +++ b/test/integration/commonjs-with-symlinks/src/symlinked_local.js @@ -0,0 +1 @@ +../local.js \ No newline at end of file diff --git a/test/watcher.js b/test/watcher.js index 9b9019034b9..f5de60da3d3 100644 --- a/test/watcher.js +++ b/test/watcher.js @@ -253,4 +253,29 @@ describe('watcher', function() { assert(file.includes('function Foo')); assert(file.includes('function Bar')); }); + + it('should rebuild if the file behind a symlink changes', async function() { + await ncp( + __dirname + '/integration/commonjs-with-symlinks/', + __dirname + '/input' + ); + + b = bundler(__dirname + '/input/src/index.js', { + watch: true + }); + + let bundle = await b.bundle(); + let output = await run(bundle); + + assert.equal(output(), 3); + + await fs.writeFile( + __dirname + '/input/local.js', + 'exports.a = 5; exports.b = 5;' + ); + + bundle = await nextBundle(b); + output = await run(bundle); + assert.equal(output(), 10); + }); });