Add a plugin to warn if the source type is ambiguous

This commit is contained in:
Florent Cailhol 2018-01-22 23:13:04 +01:00
parent f6e366b4be
commit b1467761c4
14 changed files with 126 additions and 0 deletions

View File

@ -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;

View File

@ -117,6 +117,8 @@ exportPlugins(exports, {
SourceMapDevToolPlugin: () => require("./SourceMapDevToolPlugin"),
Stats: () => require("./Stats"),
UmdMainTemplatePlugin: () => require("./UmdMainTemplatePlugin"),
WarnAmbiguousSourceTypePlugin: () =>
require("./WarnAmbiguousSourceTypePlugin"),
WatchIgnorePlugin: () => require("./WatchIgnorePlugin")
});
exportPlugins((exports.optimize = {}), {

View File

@ -0,0 +1,2 @@
import "./empty";
exports.type = "ambiguous";

View File

@ -0,0 +1,2 @@
require("./empty");
export default "ambiguous";

View File

@ -0,0 +1,2 @@
require.resolve("./empty");
export default "ambiguous";

View File

@ -0,0 +1,2 @@
import "./empty";
require("./empty");

View File

@ -0,0 +1,5 @@
import "./empty";
Object.assign({}, module.exports, {
type: "ambiguous"
});

View File

@ -0,0 +1,5 @@
import "./empty";
Object.assign({}, exports, {
type: "ambiguous"
});

View File

@ -0,0 +1,5 @@
require("./empty");
require.resolve("./empty");
module.exports = {};
exports.x = true;

View File

@ -0,0 +1,7 @@
import "./empty";
let define = () => {};
let require = () => {};
define();
require();

View File

@ -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");
});

View File

@ -0,0 +1,5 @@
module.exports = [];
for (let i = 1; i <= 6; ++i) {
module.exports.push([new RegExp(`amb${i}`), /ambiguous/]);
}

View File

@ -0,0 +1,5 @@
const webpack = require("../../../../");
module.exports = {
plugins: [new webpack.WarnAmbiguousSourceTypePlugin()]
};