diff --git a/src/Module.ts b/src/Module.ts index a3ac07031fa..fbc651fd75c 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -272,8 +272,6 @@ export default class Module { props.frame = getCodeFrame(this.originalCode, location.line, location.column); } - props.watchFiles = Object.keys(this.graph.watchFiles); - error(props); } diff --git a/src/rollup/index.ts b/src/rollup/index.ts index 8f7dc6dc53e..5c5b61a664f 100644 --- a/src/rollup/index.ts +++ b/src/rollup/index.ts @@ -199,6 +199,10 @@ export default async function rollup(rawInputOptions: GenericConfigObject): Prom inputOptions.inlineDynamicImports as boolean ); } catch (err) { + const watchFiles = Object.keys(graph.watchFiles); + if (watchFiles.length > 0) { + err.watchFiles = watchFiles; + } await graph.pluginDriver.hookParallel('buildEnd', [err]); throw err; } diff --git a/test/function/samples/deprecated/emit-asset/set-asset-source-transform/_config.js b/test/function/samples/deprecated/emit-asset/set-asset-source-transform/_config.js index d24624e105f..f8aa86b8e16 100644 --- a/test/function/samples/deprecated/emit-asset/set-asset-source-transform/_config.js +++ b/test/function/samples/deprecated/emit-asset/set-asset-source-transform/_config.js @@ -20,6 +20,7 @@ module.exports = { message: 'setAssetSource cannot be called in transform for caching reasons. Use emitFile with a source, or call setAssetSource in another hook.', plugin: 'test-plugin', - pluginCode: 'INVALID_SETASSETSOURCE' + pluginCode: 'INVALID_SETASSETSOURCE', + watchFiles: [path.resolve(__dirname, 'main.js')] } }; diff --git a/test/function/samples/deprecated/emit-chunk/chunk-not-found/_config.js b/test/function/samples/deprecated/emit-chunk/chunk-not-found/_config.js index 99a8b329017..4e8fb64509b 100644 --- a/test/function/samples/deprecated/emit-chunk/chunk-not-found/_config.js +++ b/test/function/samples/deprecated/emit-chunk/chunk-not-found/_config.js @@ -1,3 +1,5 @@ +const path = require('path'); + module.exports = { description: 'Throws if an emitted entry chunk cannot be resolved', options: { @@ -11,6 +13,7 @@ module.exports = { }, error: { code: 'UNRESOLVED_ENTRY', - message: 'Could not resolve entry module (not-found.js).' + message: 'Could not resolve entry module (not-found.js).', + watchFiles: [path.resolve(__dirname, 'main.js')] } }; diff --git a/test/function/samples/deprecations/transform-dependencies/_config.js b/test/function/samples/deprecations/transform-dependencies/_config.js index 00ca6697bac..91482c8b692 100644 --- a/test/function/samples/deprecations/transform-dependencies/_config.js +++ b/test/function/samples/deprecations/transform-dependencies/_config.js @@ -16,6 +16,7 @@ module.exports = { message: 'Returning "dependencies" from the "transform" hook as done by plugin at position 1 is deprecated. The "this.addWatchFile" plugin context function should be used instead.', plugin: 'at position 1', - pluginCode: 'DEPRECATED_FEATURE' + pluginCode: 'DEPRECATED_FEATURE', + watchFiles: [path.resolve(__dirname, 'main.js')] } }; diff --git a/test/function/samples/dynamic-import-relative-not-found/_config.js b/test/function/samples/dynamic-import-relative-not-found/_config.js index fa9cf8e9d04..5e7bf79c9d5 100644 --- a/test/function/samples/dynamic-import-relative-not-found/_config.js +++ b/test/function/samples/dynamic-import-relative-not-found/_config.js @@ -1,7 +1,10 @@ +const path = require('path'); + module.exports = { description: 'throws if a dynamic relative import is not found', error: { code: 'UNRESOLVED_IMPORT', - message: `Could not resolve './mod' from main.js` + message: `Could not resolve './mod' from main.js`, + watchFiles: [path.resolve(__dirname, 'main.js')] } }; diff --git a/test/function/samples/emit-file/chunk-not-found/_config.js b/test/function/samples/emit-file/chunk-not-found/_config.js index ef5735fe5a7..b136c0750e9 100644 --- a/test/function/samples/emit-file/chunk-not-found/_config.js +++ b/test/function/samples/emit-file/chunk-not-found/_config.js @@ -1,3 +1,5 @@ +const path = require('path'); + module.exports = { description: 'Throws if an emitted entry chunk cannot be resolved', options: { @@ -10,6 +12,7 @@ module.exports = { }, error: { code: 'UNRESOLVED_ENTRY', - message: 'Could not resolve entry module (not-found.js).' + message: 'Could not resolve entry module (not-found.js).', + watchFiles: [path.resolve(__dirname, 'main.js')] } }; diff --git a/test/function/samples/emit-file/set-asset-source-transform/_config.js b/test/function/samples/emit-file/set-asset-source-transform/_config.js index 97af013ab68..74078f75505 100644 --- a/test/function/samples/emit-file/set-asset-source-transform/_config.js +++ b/test/function/samples/emit-file/set-asset-source-transform/_config.js @@ -19,6 +19,7 @@ module.exports = { message: 'setAssetSource cannot be called in transform for caching reasons. Use emitFile with a source, or call setAssetSource in another hook.', plugin: 'test-plugin', - pluginCode: 'INVALID_SETASSETSOURCE' + pluginCode: 'INVALID_SETASSETSOURCE', + watchFiles: [path.resolve(__dirname, 'main.js')] } }; diff --git a/test/function/samples/external-conflict/_config.js b/test/function/samples/external-conflict/_config.js index fe506824f90..7785cbb3d4b 100644 --- a/test/function/samples/external-conflict/_config.js +++ b/test/function/samples/external-conflict/_config.js @@ -1,22 +1,24 @@ +const path = require('path'); + module.exports = { description: 'external paths from custom resolver remain external (#633)', options: { external: (_id, parent) => parent === 'dep', plugins: [ { - resolveId (id, parent) { - if (id === 'dep') - return id; + resolveId(id, parent) { + if (id === 'dep') return id; }, - load (id) { - if (id === 'dep') - return `import 'dep'`; + load(id) { + if (id === 'dep') return `import 'dep'`; } } ] }, error: { - code: "INVALID_EXTERNAL_ID", - message: "'dep' is imported as an external by dep, but is already an existing non-external module id." + code: 'INVALID_EXTERNAL_ID', + message: + "'dep' is imported as an external by dep, but is already an existing non-external module id.", + watchFiles: [path.resolve(__dirname, 'main.js'), 'dep'] } }; diff --git a/test/function/samples/load-returns-string-or-null/_config.js b/test/function/samples/load-returns-string-or-null/_config.js index 4bc8c24f5ca..183a245ed9e 100644 --- a/test/function/samples/load-returns-string-or-null/_config.js +++ b/test/function/samples/load-returns-string-or-null/_config.js @@ -1,3 +1,5 @@ +const path = require('path'); + module.exports = { description: 'throws error if load returns something wacky', options: { @@ -12,6 +14,7 @@ module.exports = { }, error: { code: 'BAD_LOADER', - message: `Error loading main.js: plugin load hook should return a string, a { code, map } object, or nothing/null` + message: `Error loading main.js: plugin load hook should return a string, a { code, map } object, or nothing/null`, + watchFiles: [path.resolve(__dirname, 'main.js')] } }; diff --git a/test/function/samples/manual-chunks-conflict/_config.js b/test/function/samples/manual-chunks-conflict/_config.js index 75d353007fd..f84e76fb7ae 100644 --- a/test/function/samples/manual-chunks-conflict/_config.js +++ b/test/function/samples/manual-chunks-conflict/_config.js @@ -1,3 +1,5 @@ +const path = require('path'); + module.exports = { description: 'Throws for conflicts between manual chunks', options: { @@ -9,6 +11,7 @@ module.exports = { }, error: { code: 'INVALID_CHUNK', - message: `Cannot assign dep.js to the "dep2" chunk as it is already in the "dep1" chunk.` + message: `Cannot assign dep.js to the "dep2" chunk as it is already in the "dep1" chunk.`, + watchFiles: [path.resolve(__dirname, 'main.js'), path.resolve(__dirname, 'dep.js')] } }; diff --git a/test/function/samples/no-relative-external/_config.js b/test/function/samples/no-relative-external/_config.js index 2f599f61cc0..bcb0341d71d 100644 --- a/test/function/samples/no-relative-external/_config.js +++ b/test/function/samples/no-relative-external/_config.js @@ -1,7 +1,10 @@ +const path = require('path'); + module.exports = { description: 'missing relative imports are an error, not a warning', error: { code: 'UNRESOLVED_IMPORT', - message: `Could not resolve './missing.js' from main.js` + message: `Could not resolve './missing.js' from main.js`, + watchFiles: [path.resolve(__dirname, 'main.js')] } }; diff --git a/test/function/samples/paths-are-case-sensitive/_config.js b/test/function/samples/paths-are-case-sensitive/_config.js index f4139f0f410..c9a6a4cbee6 100644 --- a/test/function/samples/paths-are-case-sensitive/_config.js +++ b/test/function/samples/paths-are-case-sensitive/_config.js @@ -1,7 +1,10 @@ +const path = require('path'); + module.exports = { description: 'insists on correct casing for imports', error: { code: 'UNRESOLVED_IMPORT', - message: `Could not resolve './foo.js' from main.js` + message: `Could not resolve './foo.js' from main.js`, + watchFiles: [path.resolve(__dirname, 'main.js')] } }; diff --git a/test/function/samples/plugin-error-loc-instead-pos/_config.js b/test/function/samples/plugin-error-loc-instead-pos/_config.js index 84d37d2f370..f6a36d10a8b 100644 --- a/test/function/samples/plugin-error-loc-instead-pos/_config.js +++ b/test/function/samples/plugin-error-loc-instead-pos/_config.js @@ -18,6 +18,7 @@ module.exports = { message: 'nope', hook: 'transform', id: path.resolve(__dirname, 'main.js'), + watchFiles: [path.resolve(__dirname, 'main.js')], loc: { file: path.resolve(__dirname, 'main.js'), line: 1, diff --git a/test/function/samples/plugin-error-only-first-transform/_config.js b/test/function/samples/plugin-error-only-first-transform/_config.js index 49240cfbde5..0b9e4897960 100644 --- a/test/function/samples/plugin-error-only-first-transform/_config.js +++ b/test/function/samples/plugin-error-only-first-transform/_config.js @@ -23,6 +23,7 @@ module.exports = { message: `Something happened 1`, plugin: 'plugin1', hook: 'transform', - id: path.resolve(__dirname, 'main.js') + id: path.resolve(__dirname, 'main.js'), + watchFiles: [path.resolve(__dirname, 'main.js')] } }; diff --git a/test/function/samples/plugin-error/load/_config.js b/test/function/samples/plugin-error/load/_config.js index 7fa21705116..fd5902c20f3 100644 --- a/test/function/samples/plugin-error/load/_config.js +++ b/test/function/samples/plugin-error/load/_config.js @@ -16,6 +16,7 @@ module.exports = { code: 'PLUGIN_ERROR', plugin: 'test', message: `Could not load ${path.resolve(__dirname, 'main.js')}: nope`, - hook: 'load' + hook: 'load', + watchFiles: [path.resolve(__dirname, 'main.js')] } }; diff --git a/test/function/samples/plugin-error/transform/_config.js b/test/function/samples/plugin-error/transform/_config.js index 02dd00ff809..f67d6848750 100644 --- a/test/function/samples/plugin-error/transform/_config.js +++ b/test/function/samples/plugin-error/transform/_config.js @@ -18,6 +18,7 @@ module.exports = { message: 'nope', hook: 'transform', id: path.resolve(__dirname, 'main.js'), + watchFiles: [path.resolve(__dirname, 'main.js')], pos: 22, loc: { file: path.resolve(__dirname, 'main.js'), diff --git a/test/function/samples/throws-not-found-module/_config.js b/test/function/samples/throws-not-found-module/_config.js index 61f4eb878fe..0d0a99d4b10 100644 --- a/test/function/samples/throws-not-found-module/_config.js +++ b/test/function/samples/throws-not-found-module/_config.js @@ -1,7 +1,10 @@ +const path = require('path'); + module.exports = { description: 'throws error if module is not found', error: { code: 'UNRESOLVED_IMPORT', - message: `Could not resolve './mod' from main.js` + message: `Could not resolve './mod' from main.js`, + watchFiles: [path.resolve(__dirname, 'main.js')] } }; diff --git a/test/watch/index.js b/test/watch/index.js index 823c50a8e21..a1042679488 100644 --- a/test/watch/index.js +++ b/test/watch/index.js @@ -363,6 +363,47 @@ describe('rollup.watch', () => { }); }); + it('recovers from a plugin error on initial build', () => { + let count = 0; + return sander + .copydir('test/watch/samples/basic') + .to('test/_tmp/input') + .then(() => { + const watcher = rollup.watch({ + input: 'test/_tmp/input/main.js', + plugins: { + transform() { + if (count++ === 0) { + this.error('The first run failed, try again.'); + } + } + }, + output: { + file: 'test/_tmp/output/bundle.js', + format: 'cjs' + }, + watch: { chokidar } + }); + + return sequence(watcher, [ + 'START', + 'BUNDLE_START', + 'ERROR', + () => { + assert.strictEqual(sander.existsSync('../_tmp/output/bundle.js'), false); + sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); + }, + 'START', + 'BUNDLE_START', + 'BUNDLE_END', + 'END', + () => { + assert.strictEqual(run('../_tmp/output/bundle.js'), 43); + } + ]); + }); + }); + it('recovers from an error even when erroring file was "renamed" (#38)', () => { return sander .copydir('test/watch/samples/basic')