diff --git a/src/watch/index.ts b/src/watch/index.ts index 36b8b5fd849..9ff1ce15784 100644 --- a/src/watch/index.ts +++ b/src/watch/index.ts @@ -229,6 +229,9 @@ export class Task { this.watchFile(id); } } + if (error.id) { + this.cache.modules = this.cache.modules.filter(module => module.id !== error.id); + } throw error; }); } diff --git a/test/watch/index.js b/test/watch/index.js index f454536bdd9..95ec46ce7ca 100644 --- a/test/watch/index.js +++ b/test/watch/index.js @@ -881,6 +881,58 @@ describe('rollup.watch', () => { }); }); + it('runs transforms again on previously erroring files that were changed back', () => { + const brokenFiles = new Set(); + const INITIAL_CONTENT = 'export default 42;'; + sander.writeFileSync('test/_tmp/input/main.js', INITIAL_CONTENT); + const watcher = rollup.watch({ + input: 'test/_tmp/input/main.js', + plugins: { + transform(code, id) { + if (code.includes('broken')) { + brokenFiles.add(id); + throw new Error('Broken in transform'); + } else { + brokenFiles.delete(id); + } + }, + generateBundle() { + if (brokenFiles.size > 0) { + throw new Error('Broken in generate'); + } + } + }, + output: { + file: 'test/_tmp/output/bundle.js', + format: 'cjs' + }, + watch: { chokidar } + }); + return sequence(watcher, [ + 'START', + 'BUNDLE_START', + 'BUNDLE_END', + 'END', + () => { + assert.strictEqual(run('../_tmp/output/bundle.js'), 42); + sander.writeFileSync('test/_tmp/input/main.js', 'export default "broken";'); + }, + 'START', + 'BUNDLE_START', + 'ERROR', + () => { + sander.writeFileSync('test/_tmp/input/main.js', INITIAL_CONTENT); + }, + 'START', + 'BUNDLE_START', + 'BUNDLE_END', + 'END', + () => { + assert.strictEqual(run('../_tmp/output/bundle.js'), 42); + } + ]); + }); + describe('addWatchFile', () => { it('supports adding additional watch files in plugin hooks', () => { const watchChangeIds = [];