From b1467761c4c78a27fcc5a436d8efa00d7113cbb4 Mon Sep 17 00:00:00 2001 From: Florent Cailhol Date: Mon, 22 Jan 2018 23:13:04 +0100 Subject: [PATCH] Add a plugin to warn if the source type is ambiguous --- lib/WarnAmbiguousSourceTypePlugin.js | 74 +++++++++++++++++++ lib/webpack.js | 2 + .../parsing/ambiguous/cases/amb1.js | 2 + .../parsing/ambiguous/cases/amb2.js | 2 + .../parsing/ambiguous/cases/amb3.js | 2 + .../parsing/ambiguous/cases/amb4.js | 2 + .../parsing/ambiguous/cases/amb5.js | 5 ++ .../parsing/ambiguous/cases/amb6.js | 5 ++ .../parsing/ambiguous/cases/dyn.js | 5 ++ .../parsing/ambiguous/cases/empty.js | 0 .../parsing/ambiguous/cases/esm.js | 7 ++ test/configCases/parsing/ambiguous/index.js | 10 +++ .../configCases/parsing/ambiguous/warnings.js | 5 ++ .../parsing/ambiguous/webpack.config.js | 5 ++ 14 files changed, 126 insertions(+) create mode 100644 lib/WarnAmbiguousSourceTypePlugin.js create mode 100644 test/configCases/parsing/ambiguous/cases/amb1.js create mode 100644 test/configCases/parsing/ambiguous/cases/amb2.js create mode 100644 test/configCases/parsing/ambiguous/cases/amb3.js create mode 100644 test/configCases/parsing/ambiguous/cases/amb4.js create mode 100644 test/configCases/parsing/ambiguous/cases/amb5.js create mode 100644 test/configCases/parsing/ambiguous/cases/amb6.js create mode 100644 test/configCases/parsing/ambiguous/cases/dyn.js create mode 100644 test/configCases/parsing/ambiguous/cases/empty.js create mode 100644 test/configCases/parsing/ambiguous/cases/esm.js create mode 100644 test/configCases/parsing/ambiguous/index.js create mode 100644 test/configCases/parsing/ambiguous/warnings.js create mode 100644 test/configCases/parsing/ambiguous/webpack.config.js diff --git a/lib/WarnAmbiguousSourceTypePlugin.js b/lib/WarnAmbiguousSourceTypePlugin.js new file mode 100644 index 000000000..d2d427d5d --- /dev/null +++ b/lib/WarnAmbiguousSourceTypePlugin.js @@ -0,0 +1,74 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Florent Cailhol @ooflorent +*/ +"use strict"; + +const WebpackError = require("./WebpackError"); + +class WarnAmbiguousSourceTypePlugin { + apply(compiler) { + compiler.hooks.compilation.tap( + "WarnAmbiguousSourceTypePlugin", + (compilation, { normalModuleFactory }) => { + normalModuleFactory.hooks.parser + .for("javascript/auto") + .tap("WarnAmbiguousSourceTypePlugin", parser => { + function flagAsDynamic() { + const module = parser.state.module; + if (!module.buildInfo) module.buildInfo = {}; + module.buildInfo.dynamic = true; + } + parser.hooks.call + .for("define") + .tap("WarnAmbiguousSourceTypePlugin", flagAsDynamic); + parser.hooks.call + .for("require") + .tap("WarnAmbiguousSourceTypePlugin", flagAsDynamic); + parser.hooks.call + .for("require.resolve") + .tap("WarnAmbiguousSourceTypePlugin", flagAsDynamic); + parser.hooks.expression + .for("module") + .tap("WarnAmbiguousSourceTypePlugin", flagAsDynamic); + parser.hooks.expression + .for("exports") + .tap("WarnAmbiguousSourceTypePlugin", flagAsDynamic); + }); + compilation.hooks.finishModules.tap( + "WarnAmbiguousSourceTypePlugin", + modules => { + for (const module of modules) { + if (module.type === "javascript/auto") { + if ( + module.buildMeta && + module.buildMeta.exportsType && + module.buildInfo && + module.buildInfo.dynamic + ) { + compilation.warnings.push( + new AmbiguousSourceTypeWarning(module) + ); + } + } + } + } + ); + } + ); + } +} + +class AmbiguousSourceTypeWarning extends WebpackError { + constructor(module) { + super(); + + this.name = "AmbiguousSourceTypeWarning"; + this.message = "Source type is ambiguous"; + this.origin = this.module = module; + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = WarnAmbiguousSourceTypePlugin; diff --git a/lib/webpack.js b/lib/webpack.js index ed9fa612a..fdd72e54e 100644 --- a/lib/webpack.js +++ b/lib/webpack.js @@ -117,6 +117,8 @@ exportPlugins(exports, { SourceMapDevToolPlugin: () => require("./SourceMapDevToolPlugin"), Stats: () => require("./Stats"), UmdMainTemplatePlugin: () => require("./UmdMainTemplatePlugin"), + WarnAmbiguousSourceTypePlugin: () => + require("./WarnAmbiguousSourceTypePlugin"), WatchIgnorePlugin: () => require("./WatchIgnorePlugin") }); exportPlugins((exports.optimize = {}), { diff --git a/test/configCases/parsing/ambiguous/cases/amb1.js b/test/configCases/parsing/ambiguous/cases/amb1.js new file mode 100644 index 000000000..ac757293d --- /dev/null +++ b/test/configCases/parsing/ambiguous/cases/amb1.js @@ -0,0 +1,2 @@ +import "./empty"; +exports.type = "ambiguous"; diff --git a/test/configCases/parsing/ambiguous/cases/amb2.js b/test/configCases/parsing/ambiguous/cases/amb2.js new file mode 100644 index 000000000..bab5262db --- /dev/null +++ b/test/configCases/parsing/ambiguous/cases/amb2.js @@ -0,0 +1,2 @@ +require("./empty"); +export default "ambiguous"; diff --git a/test/configCases/parsing/ambiguous/cases/amb3.js b/test/configCases/parsing/ambiguous/cases/amb3.js new file mode 100644 index 000000000..5f90296ac --- /dev/null +++ b/test/configCases/parsing/ambiguous/cases/amb3.js @@ -0,0 +1,2 @@ +require.resolve("./empty"); +export default "ambiguous"; diff --git a/test/configCases/parsing/ambiguous/cases/amb4.js b/test/configCases/parsing/ambiguous/cases/amb4.js new file mode 100644 index 000000000..1e2aaec2d --- /dev/null +++ b/test/configCases/parsing/ambiguous/cases/amb4.js @@ -0,0 +1,2 @@ +import "./empty"; +require("./empty"); diff --git a/test/configCases/parsing/ambiguous/cases/amb5.js b/test/configCases/parsing/ambiguous/cases/amb5.js new file mode 100644 index 000000000..3364fb0d3 --- /dev/null +++ b/test/configCases/parsing/ambiguous/cases/amb5.js @@ -0,0 +1,5 @@ +import "./empty"; + +Object.assign({}, module.exports, { + type: "ambiguous" +}); diff --git a/test/configCases/parsing/ambiguous/cases/amb6.js b/test/configCases/parsing/ambiguous/cases/amb6.js new file mode 100644 index 000000000..957911793 --- /dev/null +++ b/test/configCases/parsing/ambiguous/cases/amb6.js @@ -0,0 +1,5 @@ +import "./empty"; + +Object.assign({}, exports, { + type: "ambiguous" +}); diff --git a/test/configCases/parsing/ambiguous/cases/dyn.js b/test/configCases/parsing/ambiguous/cases/dyn.js new file mode 100644 index 000000000..1f643d48d --- /dev/null +++ b/test/configCases/parsing/ambiguous/cases/dyn.js @@ -0,0 +1,5 @@ +require("./empty"); +require.resolve("./empty"); + +module.exports = {}; +exports.x = true; diff --git a/test/configCases/parsing/ambiguous/cases/empty.js b/test/configCases/parsing/ambiguous/cases/empty.js new file mode 100644 index 000000000..e69de29bb diff --git a/test/configCases/parsing/ambiguous/cases/esm.js b/test/configCases/parsing/ambiguous/cases/esm.js new file mode 100644 index 000000000..4ec6fc443 --- /dev/null +++ b/test/configCases/parsing/ambiguous/cases/esm.js @@ -0,0 +1,7 @@ +import "./empty"; + +let define = () => {}; +let require = () => {}; + +define(); +require(); diff --git a/test/configCases/parsing/ambiguous/index.js b/test/configCases/parsing/ambiguous/index.js new file mode 100644 index 000000000..4fb4b281b --- /dev/null +++ b/test/configCases/parsing/ambiguous/index.js @@ -0,0 +1,10 @@ +it("should compile and run the test", () => { + require("./cases/amb1"); + require("./cases/amb2"); + require("./cases/amb3"); + require("./cases/amb4"); + require("./cases/amb5"); + require("./cases/amb6"); + require("./cases/dyn"); + require("./cases/esm"); +}); diff --git a/test/configCases/parsing/ambiguous/warnings.js b/test/configCases/parsing/ambiguous/warnings.js new file mode 100644 index 000000000..6c19bf50a --- /dev/null +++ b/test/configCases/parsing/ambiguous/warnings.js @@ -0,0 +1,5 @@ +module.exports = []; + +for (let i = 1; i <= 6; ++i) { + module.exports.push([new RegExp(`amb${i}`), /ambiguous/]); +} diff --git a/test/configCases/parsing/ambiguous/webpack.config.js b/test/configCases/parsing/ambiguous/webpack.config.js new file mode 100644 index 000000000..345cab8f1 --- /dev/null +++ b/test/configCases/parsing/ambiguous/webpack.config.js @@ -0,0 +1,5 @@ +const webpack = require("../../../../"); + +module.exports = { + plugins: [new webpack.WarnAmbiguousSourceTypePlugin()] +};