0.2.0 - Mid migration

This commit is contained in:
Daniel Mason 2022-04-25 14:47:15 +12:00
parent 139e6a915e
commit 7e38fdbd7d
42393 changed files with 5358157 additions and 62 deletions

View file

@ -0,0 +1,137 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
class AMDDefineDependency extends NullDependency {
constructor(range, arrayRange, functionRange, objectRange, namedModule) {
super();
this.range = range;
this.arrayRange = arrayRange;
this.functionRange = functionRange;
this.objectRange = objectRange;
this.namedModule = namedModule;
this.localModule = null;
}
get type() {
return "amd define";
}
}
AMDDefineDependency.Template = class AMDDefineDependencyTemplate {
get definitions() {
return {
f: [
"var __WEBPACK_AMD_DEFINE_RESULT__;",
`!(__WEBPACK_AMD_DEFINE_RESULT__ = (#).call(exports, __webpack_require__, exports, module),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))`
],
o: ["", "!(module.exports = #)"],
of: [
"var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;",
`!(__WEBPACK_AMD_DEFINE_FACTORY__ = (#),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) :
__WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))`
],
af: [
"var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;",
`!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, __WEBPACK_AMD_DEFINE_RESULT__ = (#).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))`
],
ao: ["", "!(#, module.exports = #)"],
aof: [
"var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;",
`!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, __WEBPACK_AMD_DEFINE_FACTORY__ = (#),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))`
],
lf: [
"var XXX, XXXmodule;",
"!(XXXmodule = { id: YYY, exports: {}, loaded: false }, XXX = #.call(XXXmodule.exports, __webpack_require__, XXXmodule.exports, XXXmodule), XXXmodule.loaded = true, XXX === undefined && (XXX = XXXmodule.exports))"
],
lo: ["var XXX;", "!(XXX = #)"],
lof: [
"var XXX, XXXfactory, XXXmodule;",
"!(XXXfactory = (#), (XXXmodule = { id: YYY, exports: {}, loaded: false }), XXX = (typeof XXXfactory === 'function' ? (XXXfactory.call(XXXmodule.exports, __webpack_require__, XXXmodule.exports, XXXmodule)) : XXXfactory), (XXXmodule.loaded = true), XXX === undefined && (XXX = XXXmodule.exports))"
],
laf: [
"var __WEBPACK_AMD_DEFINE_ARRAY__, XXX;",
"!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, XXX = ((#).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)))"
],
lao: ["var XXX;", "!(#, XXX = #)"],
laof: [
"var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_FACTORY__, XXX;",
`!(__WEBPACK_AMD_DEFINE_ARRAY__ = #, __WEBPACK_AMD_DEFINE_FACTORY__ = (#),
XXX = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__))`
]
};
}
apply(dependency, source) {
const branch = this.branch(dependency);
const defAndText = this.definitions[branch];
const definitions = defAndText[0];
const text = defAndText[1];
this.replace(dependency, source, definitions, text);
}
localModuleVar(dependency) {
return (
dependency.localModule &&
dependency.localModule.used &&
dependency.localModule.variableName()
);
}
branch(dependency) {
const localModuleVar = this.localModuleVar(dependency) ? "l" : "";
const arrayRange = dependency.arrayRange ? "a" : "";
const objectRange = dependency.objectRange ? "o" : "";
const functionRange = dependency.functionRange ? "f" : "";
return localModuleVar + arrayRange + objectRange + functionRange;
}
replace(dependency, source, definition, text) {
const localModuleVar = this.localModuleVar(dependency);
if (localModuleVar) {
text = text.replace(/XXX/g, localModuleVar.replace(/\$/g, "$$$$"));
definition = definition.replace(
/XXX/g,
localModuleVar.replace(/\$/g, "$$$$")
);
}
if (dependency.namedModule) {
text = text.replace(/YYY/g, JSON.stringify(dependency.namedModule));
}
const texts = text.split("#");
if (definition) source.insert(0, definition);
let current = dependency.range[0];
if (dependency.arrayRange) {
source.replace(current, dependency.arrayRange[0] - 1, texts.shift());
current = dependency.arrayRange[1];
}
if (dependency.objectRange) {
source.replace(current, dependency.objectRange[0] - 1, texts.shift());
current = dependency.objectRange[1];
} else if (dependency.functionRange) {
source.replace(current, dependency.functionRange[0] - 1, texts.shift());
current = dependency.functionRange[1];
}
source.replace(current, dependency.range[1] - 1, texts.shift());
if (texts.length > 0) throw new Error("Implementation error");
}
};
module.exports = AMDDefineDependency;

View file

@ -0,0 +1,336 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const AMDRequireItemDependency = require("./AMDRequireItemDependency");
const AMDRequireContextDependency = require("./AMDRequireContextDependency");
const ConstDependency = require("./ConstDependency");
const AMDDefineDependency = require("./AMDDefineDependency");
const AMDRequireArrayDependency = require("./AMDRequireArrayDependency");
const LocalModuleDependency = require("./LocalModuleDependency");
const ContextDependencyHelpers = require("./ContextDependencyHelpers");
const LocalModulesHelpers = require("./LocalModulesHelpers");
const isBoundFunctionExpression = expr => {
if (expr.type !== "CallExpression") return false;
if (expr.callee.type !== "MemberExpression") return false;
if (expr.callee.computed) return false;
if (expr.callee.object.type !== "FunctionExpression") return false;
if (expr.callee.property.type !== "Identifier") return false;
if (expr.callee.property.name !== "bind") return false;
return true;
};
const isUnboundFunctionExpression = expr => {
if (expr.type === "FunctionExpression") return true;
if (expr.type === "ArrowFunctionExpression") return true;
return false;
};
const isCallable = expr => {
if (isUnboundFunctionExpression(expr)) return true;
if (isBoundFunctionExpression(expr)) return true;
return false;
};
class AMDDefineDependencyParserPlugin {
constructor(options) {
this.options = options;
}
apply(parser) {
parser.hooks.call
.for("define")
.tap(
"AMDDefineDependencyParserPlugin",
this.processCallDefine.bind(this, parser)
);
}
processArray(parser, expr, param, identifiers, namedModule) {
if (param.isArray()) {
param.items.forEach((param, idx) => {
if (
param.isString() &&
["require", "module", "exports"].includes(param.string)
)
identifiers[idx] = param.string;
const result = this.processItem(parser, expr, param, namedModule);
if (result === undefined) {
this.processContext(parser, expr, param);
}
});
return true;
} else if (param.isConstArray()) {
const deps = [];
param.array.forEach((request, idx) => {
let dep;
let localModule;
if (request === "require") {
identifiers[idx] = request;
dep = "__webpack_require__";
} else if (["exports", "module"].includes(request)) {
identifiers[idx] = request;
dep = request;
} else if (
(localModule = LocalModulesHelpers.getLocalModule(
parser.state,
request
))
) {
dep = new LocalModuleDependency(localModule, undefined, false);
dep.loc = expr.loc;
parser.state.current.addDependency(dep);
} else {
dep = this.newRequireItemDependency(request);
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
}
deps.push(dep);
});
const dep = this.newRequireArrayDependency(deps, param.range);
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
}
}
processItem(parser, expr, param, namedModule) {
if (param.isConditional()) {
param.options.forEach(param => {
const result = this.processItem(parser, expr, param);
if (result === undefined) {
this.processContext(parser, expr, param);
}
});
return true;
} else if (param.isString()) {
let dep, localModule;
if (param.string === "require") {
dep = new ConstDependency("__webpack_require__", param.range);
} else if (["require", "exports", "module"].includes(param.string)) {
dep = new ConstDependency(param.string, param.range);
} else if (
(localModule = LocalModulesHelpers.getLocalModule(
parser.state,
param.string,
namedModule
))
) {
dep = new LocalModuleDependency(localModule, param.range, false);
} else {
dep = this.newRequireItemDependency(param.string, param.range);
}
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
}
}
processContext(parser, expr, param) {
const dep = ContextDependencyHelpers.create(
AMDRequireContextDependency,
param.range,
param,
expr,
this.options,
{},
parser
);
if (!dep) return;
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
}
processCallDefine(parser, expr) {
let array, fn, obj, namedModule;
switch (expr.arguments.length) {
case 1:
if (isCallable(expr.arguments[0])) {
// define(f() {…})
fn = expr.arguments[0];
} else if (expr.arguments[0].type === "ObjectExpression") {
// define({…})
obj = expr.arguments[0];
} else {
// define(expr)
// unclear if function or object
obj = fn = expr.arguments[0];
}
break;
case 2:
if (expr.arguments[0].type === "Literal") {
namedModule = expr.arguments[0].value;
// define("…", …)
if (isCallable(expr.arguments[1])) {
// define("…", f() {…})
fn = expr.arguments[1];
} else if (expr.arguments[1].type === "ObjectExpression") {
// define("…", {…})
obj = expr.arguments[1];
} else {
// define("…", expr)
// unclear if function or object
obj = fn = expr.arguments[1];
}
} else {
array = expr.arguments[0];
if (isCallable(expr.arguments[1])) {
// define([…], f() {})
fn = expr.arguments[1];
} else if (expr.arguments[1].type === "ObjectExpression") {
// define([…], {…})
obj = expr.arguments[1];
} else {
// define([…], expr)
// unclear if function or object
obj = fn = expr.arguments[1];
}
}
break;
case 3:
// define("…", […], f() {…})
namedModule = expr.arguments[0].value;
array = expr.arguments[1];
if (isCallable(expr.arguments[2])) {
// define("…", […], f() {})
fn = expr.arguments[2];
} else if (expr.arguments[2].type === "ObjectExpression") {
// define("…", […], {…})
obj = expr.arguments[2];
} else {
// define("…", […], expr)
// unclear if function or object
obj = fn = expr.arguments[2];
}
break;
default:
return;
}
let fnParams = null;
let fnParamsOffset = 0;
if (fn) {
if (isUnboundFunctionExpression(fn)) {
fnParams = fn.params;
} else if (isBoundFunctionExpression(fn)) {
fnParams = fn.callee.object.params;
fnParamsOffset = fn.arguments.length - 1;
if (fnParamsOffset < 0) {
fnParamsOffset = 0;
}
}
}
let fnRenames = parser.scope.renames.createChild();
if (array) {
const identifiers = {};
const param = parser.evaluateExpression(array);
const result = this.processArray(
parser,
expr,
param,
identifiers,
namedModule
);
if (!result) return;
if (fnParams) {
fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => {
if (identifiers[idx]) {
fnRenames.set(param.name, identifiers[idx]);
return false;
}
return true;
});
}
} else {
const identifiers = ["require", "exports", "module"];
if (fnParams) {
fnParams = fnParams.slice(fnParamsOffset).filter((param, idx) => {
if (identifiers[idx]) {
fnRenames.set(param.name, identifiers[idx]);
return false;
}
return true;
});
}
}
let inTry;
if (fn && isUnboundFunctionExpression(fn)) {
inTry = parser.scope.inTry;
parser.inScope(fnParams, () => {
parser.scope.renames = fnRenames;
parser.scope.inTry = inTry;
if (fn.body.type === "BlockStatement") {
parser.walkStatement(fn.body);
} else {
parser.walkExpression(fn.body);
}
});
} else if (fn && isBoundFunctionExpression(fn)) {
inTry = parser.scope.inTry;
parser.inScope(
fn.callee.object.params.filter(
i => !["require", "module", "exports"].includes(i.name)
),
() => {
parser.scope.renames = fnRenames;
parser.scope.inTry = inTry;
if (fn.callee.object.body.type === "BlockStatement") {
parser.walkStatement(fn.callee.object.body);
} else {
parser.walkExpression(fn.callee.object.body);
}
}
);
if (fn.arguments) {
parser.walkExpressions(fn.arguments);
}
} else if (fn || obj) {
parser.walkExpression(fn || obj);
}
const dep = this.newDefineDependency(
expr.range,
array ? array.range : null,
fn ? fn.range : null,
obj ? obj.range : null,
namedModule ? namedModule : null
);
dep.loc = expr.loc;
if (namedModule) {
dep.localModule = LocalModulesHelpers.addLocalModule(
parser.state,
namedModule
);
}
parser.state.current.addDependency(dep);
return true;
}
newDefineDependency(
range,
arrayRange,
functionRange,
objectRange,
namedModule
) {
return new AMDDefineDependency(
range,
arrayRange,
functionRange,
objectRange,
namedModule
);
}
newRequireArrayDependency(depsArray, range) {
return new AMDRequireArrayDependency(depsArray, range);
}
newRequireItemDependency(request, range) {
return new AMDRequireItemDependency(request, range);
}
}
module.exports = AMDDefineDependencyParserPlugin;

249
web/node_modules/webpack/lib/dependencies/AMDPlugin.js generated vendored Normal file
View file

@ -0,0 +1,249 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const path = require("path");
const AMDRequireDependency = require("./AMDRequireDependency");
const AMDRequireItemDependency = require("./AMDRequireItemDependency");
const AMDRequireArrayDependency = require("./AMDRequireArrayDependency");
const AMDRequireContextDependency = require("./AMDRequireContextDependency");
const AMDDefineDependency = require("./AMDDefineDependency");
const UnsupportedDependency = require("./UnsupportedDependency");
const LocalModuleDependency = require("./LocalModuleDependency");
const NullFactory = require("../NullFactory");
const AMDRequireDependenciesBlockParserPlugin = require("./AMDRequireDependenciesBlockParserPlugin");
const AMDDefineDependencyParserPlugin = require("./AMDDefineDependencyParserPlugin");
const AliasPlugin = require("enhanced-resolve/lib/AliasPlugin");
const ParserHelpers = require("../ParserHelpers");
class AMDPlugin {
constructor(options, amdOptions) {
this.amdOptions = amdOptions;
this.options = options;
}
apply(compiler) {
const options = this.options;
const amdOptions = this.amdOptions;
compiler.hooks.compilation.tap(
"AMDPlugin",
(compilation, { contextModuleFactory, normalModuleFactory }) => {
compilation.dependencyFactories.set(
AMDRequireDependency,
new NullFactory()
);
compilation.dependencyTemplates.set(
AMDRequireDependency,
new AMDRequireDependency.Template()
);
compilation.dependencyFactories.set(
AMDRequireItemDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
AMDRequireItemDependency,
new AMDRequireItemDependency.Template()
);
compilation.dependencyFactories.set(
AMDRequireArrayDependency,
new NullFactory()
);
compilation.dependencyTemplates.set(
AMDRequireArrayDependency,
new AMDRequireArrayDependency.Template()
);
compilation.dependencyFactories.set(
AMDRequireContextDependency,
contextModuleFactory
);
compilation.dependencyTemplates.set(
AMDRequireContextDependency,
new AMDRequireContextDependency.Template()
);
compilation.dependencyFactories.set(
AMDDefineDependency,
new NullFactory()
);
compilation.dependencyTemplates.set(
AMDDefineDependency,
new AMDDefineDependency.Template()
);
compilation.dependencyFactories.set(
UnsupportedDependency,
new NullFactory()
);
compilation.dependencyTemplates.set(
UnsupportedDependency,
new UnsupportedDependency.Template()
);
compilation.dependencyFactories.set(
LocalModuleDependency,
new NullFactory()
);
compilation.dependencyTemplates.set(
LocalModuleDependency,
new LocalModuleDependency.Template()
);
const handler = (parser, parserOptions) => {
if (parserOptions.amd !== undefined && !parserOptions.amd) return;
const setExpressionToModule = (outerExpr, module) => {
parser.hooks.expression.for(outerExpr).tap("AMDPlugin", expr => {
const dep = new AMDRequireItemDependency(module, expr.range);
dep.userRequest = outerExpr;
dep.loc = expr.loc;
parser.state.current.addDependency(dep);
return true;
});
};
new AMDRequireDependenciesBlockParserPlugin(options).apply(parser);
new AMDDefineDependencyParserPlugin(options).apply(parser);
setExpressionToModule("require.amd", "!!webpack amd options");
setExpressionToModule("define.amd", "!!webpack amd options");
setExpressionToModule("define", "!!webpack amd define");
parser.hooks.expression
.for("__webpack_amd_options__")
.tap("AMDPlugin", () =>
parser.state.current.addVariable(
"__webpack_amd_options__",
JSON.stringify(amdOptions)
)
);
parser.hooks.evaluateTypeof
.for("define.amd")
.tap(
"AMDPlugin",
ParserHelpers.evaluateToString(typeof amdOptions)
);
parser.hooks.evaluateTypeof
.for("require.amd")
.tap(
"AMDPlugin",
ParserHelpers.evaluateToString(typeof amdOptions)
);
parser.hooks.evaluateIdentifier
.for("define.amd")
.tap(
"AMDPlugin",
ParserHelpers.evaluateToIdentifier("define.amd", true)
);
parser.hooks.evaluateIdentifier
.for("require.amd")
.tap(
"AMDPlugin",
ParserHelpers.evaluateToIdentifier("require.amd", true)
);
parser.hooks.typeof
.for("define")
.tap(
"AMDPlugin",
ParserHelpers.toConstantDependency(
parser,
JSON.stringify("function")
)
);
parser.hooks.evaluateTypeof
.for("define")
.tap("AMDPlugin", ParserHelpers.evaluateToString("function"));
parser.hooks.canRename
.for("define")
.tap("AMDPlugin", ParserHelpers.approve);
parser.hooks.rename.for("define").tap("AMDPlugin", expr => {
const dep = new AMDRequireItemDependency(
"!!webpack amd define",
expr.range
);
dep.userRequest = "define";
dep.loc = expr.loc;
parser.state.current.addDependency(dep);
return false;
});
parser.hooks.typeof
.for("require")
.tap(
"AMDPlugin",
ParserHelpers.toConstantDependency(
parser,
JSON.stringify("function")
)
);
parser.hooks.evaluateTypeof
.for("require")
.tap("AMDPlugin", ParserHelpers.evaluateToString("function"));
};
normalModuleFactory.hooks.parser
.for("javascript/auto")
.tap("AMDPlugin", handler);
normalModuleFactory.hooks.parser
.for("javascript/dynamic")
.tap("AMDPlugin", handler);
}
);
compiler.hooks.afterResolvers.tap("AMDPlugin", () => {
compiler.resolverFactory.hooks.resolver
.for("normal")
.tap("AMDPlugin", resolver => {
new AliasPlugin(
"described-resolve",
{
name: "amdefine",
alias: path.join(
__dirname,
"..",
"..",
"buildin",
"amd-define.js"
)
},
"resolve"
).apply(resolver);
new AliasPlugin(
"described-resolve",
{
name: "webpack amd options",
alias: path.join(
__dirname,
"..",
"..",
"buildin",
"amd-options.js"
)
},
"resolve"
).apply(resolver);
new AliasPlugin(
"described-resolve",
{
name: "webpack amd define",
alias: path.join(
__dirname,
"..",
"..",
"buildin",
"amd-define.js"
)
},
"resolve"
).apply(resolver);
});
});
}
}
module.exports = AMDPlugin;

View file

@ -0,0 +1,49 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const Dependency = require("../Dependency");
class AMDRequireArrayDependency extends Dependency {
constructor(depsArray, range) {
super();
this.depsArray = depsArray;
this.range = range;
}
get type() {
return "amd require array";
}
}
AMDRequireArrayDependency.Template = class AMDRequireArrayDependencyTemplate {
apply(dep, source, runtime) {
const content = this.getContent(dep, runtime);
source.replace(dep.range[0], dep.range[1] - 1, content);
}
getContent(dep, runtime) {
const requires = dep.depsArray.map(dependency => {
return this.contentForDependency(dependency, runtime);
});
return `[${requires.join(", ")}]`;
}
contentForDependency(dep, runtime) {
if (typeof dep === "string") {
return dep;
}
if (dep.localModule) {
return dep.localModule.variableName();
} else {
return runtime.moduleExports({
module: dep.module,
request: dep.request
});
}
}
};
module.exports = AMDRequireArrayDependency;

View file

@ -0,0 +1,20 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ContextDependency = require("./ContextDependency");
class AMDRequireContextDependency extends ContextDependency {
constructor(options, range, valueRange) {
super(options);
this.range = range;
this.valueRange = valueRange;
}
get type() {
return "amd require context";
}
}
AMDRequireContextDependency.Template = require("./ContextDependencyTemplateAsRequireCall");
module.exports = AMDRequireContextDependency;

View file

@ -0,0 +1,47 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const AsyncDependenciesBlock = require("../AsyncDependenciesBlock");
const AMDRequireDependency = require("./AMDRequireDependency");
module.exports = class AMDRequireDependenciesBlock extends AsyncDependenciesBlock {
constructor(
expr,
arrayRange,
functionRange,
errorCallbackRange,
module,
loc,
request
) {
super(null, module, loc, request);
this.expr = expr;
this.outerRange = expr.range;
this.arrayRange = arrayRange;
this.functionBindThis = false;
this.functionRange = functionRange;
this.errorCallbackBindThis = false;
this.errorCallbackRange = errorCallbackRange;
this.bindThis = true;
if (arrayRange && functionRange && errorCallbackRange) {
this.range = [arrayRange[0], errorCallbackRange[1]];
} else if (arrayRange && functionRange) {
this.range = [arrayRange[0], functionRange[1]];
} else if (arrayRange) {
this.range = arrayRange;
} else if (functionRange) {
this.range = functionRange;
} else {
this.range = expr.range;
}
const dep = this.newRequireDependency();
dep.loc = loc;
this.addDependency(dep);
}
newRequireDependency() {
return new AMDRequireDependency(this);
}
};

View file

@ -0,0 +1,274 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const AMDRequireItemDependency = require("./AMDRequireItemDependency");
const AMDRequireArrayDependency = require("./AMDRequireArrayDependency");
const AMDRequireContextDependency = require("./AMDRequireContextDependency");
const AMDRequireDependenciesBlock = require("./AMDRequireDependenciesBlock");
const UnsupportedDependency = require("./UnsupportedDependency");
const LocalModuleDependency = require("./LocalModuleDependency");
const ContextDependencyHelpers = require("./ContextDependencyHelpers");
const LocalModulesHelpers = require("./LocalModulesHelpers");
const ConstDependency = require("./ConstDependency");
const getFunctionExpression = require("./getFunctionExpression");
const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
class AMDRequireDependenciesBlockParserPlugin {
constructor(options) {
this.options = options;
}
processFunctionArgument(parser, expression) {
let bindThis = true;
const fnData = getFunctionExpression(expression);
if (fnData) {
parser.inScope(
fnData.fn.params.filter(i => {
return !["require", "module", "exports"].includes(i.name);
}),
() => {
if (fnData.fn.body.type === "BlockStatement") {
parser.walkStatement(fnData.fn.body);
} else {
parser.walkExpression(fnData.fn.body);
}
}
);
parser.walkExpressions(fnData.expressions);
if (fnData.needThis === false) {
bindThis = false;
}
} else {
parser.walkExpression(expression);
}
return bindThis;
}
apply(parser) {
parser.hooks.call
.for("require")
.tap(
"AMDRequireDependenciesBlockParserPlugin",
this.processCallRequire.bind(this, parser)
);
}
processArray(parser, expr, param) {
if (param.isArray()) {
for (const p of param.items) {
const result = this.processItem(parser, expr, p);
if (result === undefined) {
this.processContext(parser, expr, p);
}
}
return true;
} else if (param.isConstArray()) {
const deps = [];
for (const request of param.array) {
let dep, localModule;
if (request === "require") {
dep = "__webpack_require__";
} else if (["exports", "module"].includes(request)) {
dep = request;
} else if (
(localModule = LocalModulesHelpers.getLocalModule(
parser.state,
request
))
) {
dep = new LocalModuleDependency(localModule, undefined, false);
dep.loc = expr.loc;
parser.state.current.addDependency(dep);
} else {
dep = this.newRequireItemDependency(request);
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
}
deps.push(dep);
}
const dep = this.newRequireArrayDependency(deps, param.range);
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
}
}
processItem(parser, expr, param) {
if (param.isConditional()) {
for (const p of param.options) {
const result = this.processItem(parser, expr, p);
if (result === undefined) {
this.processContext(parser, expr, p);
}
}
return true;
} else if (param.isString()) {
let dep, localModule;
if (param.string === "require") {
dep = new ConstDependency("__webpack_require__", param.string);
} else if (param.string === "module") {
dep = new ConstDependency(
parser.state.module.buildInfo.moduleArgument,
param.range
);
} else if (param.string === "exports") {
dep = new ConstDependency(
parser.state.module.buildInfo.exportsArgument,
param.range
);
} else if (
(localModule = LocalModulesHelpers.getLocalModule(
parser.state,
param.string
))
) {
dep = new LocalModuleDependency(localModule, param.range, false);
} else {
dep = this.newRequireItemDependency(param.string, param.range);
}
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
}
}
processContext(parser, expr, param) {
const dep = ContextDependencyHelpers.create(
AMDRequireContextDependency,
param.range,
param,
expr,
this.options,
{},
parser
);
if (!dep) return;
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
}
processArrayForRequestString(param) {
if (param.isArray()) {
const result = param.items.map(item =>
this.processItemForRequestString(item)
);
if (result.every(Boolean)) return result.join(" ");
} else if (param.isConstArray()) {
return param.array.join(" ");
}
}
processItemForRequestString(param) {
if (param.isConditional()) {
const result = param.options.map(item =>
this.processItemForRequestString(item)
);
if (result.every(Boolean)) return result.join("|");
} else if (param.isString()) {
return param.string;
}
}
processCallRequire(parser, expr) {
let param;
let dep;
let result;
const old = parser.state.current;
if (expr.arguments.length >= 1) {
param = parser.evaluateExpression(expr.arguments[0]);
dep = this.newRequireDependenciesBlock(
expr,
param.range,
expr.arguments.length > 1 ? expr.arguments[1].range : null,
expr.arguments.length > 2 ? expr.arguments[2].range : null,
parser.state.module,
expr.loc,
this.processArrayForRequestString(param)
);
parser.state.current = dep;
}
if (expr.arguments.length === 1) {
parser.inScope([], () => {
result = this.processArray(parser, expr, param);
});
parser.state.current = old;
if (!result) return;
parser.state.current.addBlock(dep);
return true;
}
if (expr.arguments.length === 2 || expr.arguments.length === 3) {
try {
parser.inScope([], () => {
result = this.processArray(parser, expr, param);
});
if (!result) {
dep = new UnsupportedDependency("unsupported", expr.range);
old.addDependency(dep);
if (parser.state.module) {
parser.state.module.errors.push(
new UnsupportedFeatureWarning(
parser.state.module,
"Cannot statically analyse 'require(…, …)' in line " +
expr.loc.start.line,
expr.loc
)
);
}
dep = null;
return true;
}
dep.functionBindThis = this.processFunctionArgument(
parser,
expr.arguments[1]
);
if (expr.arguments.length === 3) {
dep.errorCallbackBindThis = this.processFunctionArgument(
parser,
expr.arguments[2]
);
}
} finally {
parser.state.current = old;
if (dep) parser.state.current.addBlock(dep);
}
return true;
}
}
newRequireDependenciesBlock(
expr,
arrayRange,
functionRange,
errorCallbackRange,
module,
loc,
request
) {
return new AMDRequireDependenciesBlock(
expr,
arrayRange,
functionRange,
errorCallbackRange,
module,
loc,
request
);
}
newRequireItemDependency(request, range) {
return new AMDRequireItemDependency(request, range);
}
newRequireArrayDependency(depsArray, range) {
return new AMDRequireArrayDependency(depsArray, range);
}
}
module.exports = AMDRequireDependenciesBlockParserPlugin;

View file

@ -0,0 +1,135 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
class AMDRequireDependency extends NullDependency {
constructor(block) {
super();
this.block = block;
}
}
AMDRequireDependency.Template = class AMDRequireDependencyTemplate {
apply(dep, source, runtime) {
const depBlock = dep.block;
const promise = runtime.blockPromise({
block: depBlock,
message: "AMD require"
});
// has array range but no function range
if (depBlock.arrayRange && !depBlock.functionRange) {
const startBlock = `${promise}.then(function() {`;
const endBlock = `;}).catch(${runtime.onError()})`;
source.replace(
depBlock.outerRange[0],
depBlock.arrayRange[0] - 1,
startBlock
);
source.replace(
depBlock.arrayRange[1],
depBlock.outerRange[1] - 1,
endBlock
);
return;
}
// has function range but no array range
if (depBlock.functionRange && !depBlock.arrayRange) {
const startBlock = `${promise}.then((`;
const endBlock = `).bind(exports, __webpack_require__, exports, module)).catch(${runtime.onError()})`;
source.replace(
depBlock.outerRange[0],
depBlock.functionRange[0] - 1,
startBlock
);
source.replace(
depBlock.functionRange[1],
depBlock.outerRange[1] - 1,
endBlock
);
return;
}
// has array range, function range, and errorCallbackRange
if (
depBlock.arrayRange &&
depBlock.functionRange &&
depBlock.errorCallbackRange
) {
const startBlock = `${promise}.then(function() { `;
const errorRangeBlock = `}${
depBlock.functionBindThis ? ".bind(this)" : ""
}).catch(`;
const endBlock = `${
depBlock.errorCallbackBindThis ? ".bind(this)" : ""
})`;
source.replace(
depBlock.outerRange[0],
depBlock.arrayRange[0] - 1,
startBlock
);
source.insert(
depBlock.arrayRange[0] + 0.9,
"var __WEBPACK_AMD_REQUIRE_ARRAY__ = "
);
source.replace(
depBlock.arrayRange[1],
depBlock.functionRange[0] - 1,
"; ("
);
source.insert(
depBlock.functionRange[1],
").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__);"
);
source.replace(
depBlock.functionRange[1],
depBlock.errorCallbackRange[0] - 1,
errorRangeBlock
);
source.replace(
depBlock.errorCallbackRange[1],
depBlock.outerRange[1] - 1,
endBlock
);
return;
}
// has array range, function range, but no errorCallbackRange
if (depBlock.arrayRange && depBlock.functionRange) {
const startBlock = `${promise}.then(function() { `;
const endBlock = `}${
depBlock.functionBindThis ? ".bind(this)" : ""
}).catch(${runtime.onError()})`;
source.replace(
depBlock.outerRange[0],
depBlock.arrayRange[0] - 1,
startBlock
);
source.insert(
depBlock.arrayRange[0] + 0.9,
"var __WEBPACK_AMD_REQUIRE_ARRAY__ = "
);
source.replace(
depBlock.arrayRange[1],
depBlock.functionRange[0] - 1,
"; ("
);
source.insert(
depBlock.functionRange[1],
").apply(null, __WEBPACK_AMD_REQUIRE_ARRAY__);"
);
source.replace(
depBlock.functionRange[1],
depBlock.outerRange[1] - 1,
endBlock
);
}
}
};
module.exports = AMDRequireDependency;

View file

@ -0,0 +1,22 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
const ModuleDependencyTemplateAsRequireId = require("./ModuleDependencyTemplateAsRequireId");
class AMDRequireItemDependency extends ModuleDependency {
constructor(request, range) {
super(request);
this.range = range;
}
get type() {
return "amd require";
}
}
AMDRequireItemDependency.Template = ModuleDependencyTemplateAsRequireId;
module.exports = AMDRequireItemDependency;

View file

@ -0,0 +1,158 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ConstDependency = require("./ConstDependency");
const CommonJsRequireDependency = require("./CommonJsRequireDependency");
const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency");
const RequireResolveDependency = require("./RequireResolveDependency");
const RequireResolveContextDependency = require("./RequireResolveContextDependency");
const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency");
const RequireHeaderDependency = require("./RequireHeaderDependency");
const NullFactory = require("../NullFactory");
const RequireResolveDependencyParserPlugin = require("./RequireResolveDependencyParserPlugin");
const CommonJsRequireDependencyParserPlugin = require("./CommonJsRequireDependencyParserPlugin");
const ParserHelpers = require("../ParserHelpers");
class CommonJsPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
const options = this.options;
compiler.hooks.compilation.tap(
"CommonJsPlugin",
(compilation, { contextModuleFactory, normalModuleFactory }) => {
compilation.dependencyFactories.set(
CommonJsRequireDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
CommonJsRequireDependency,
new CommonJsRequireDependency.Template()
);
compilation.dependencyFactories.set(
CommonJsRequireContextDependency,
contextModuleFactory
);
compilation.dependencyTemplates.set(
CommonJsRequireContextDependency,
new CommonJsRequireContextDependency.Template()
);
compilation.dependencyFactories.set(
RequireResolveDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
RequireResolveDependency,
new RequireResolveDependency.Template()
);
compilation.dependencyFactories.set(
RequireResolveContextDependency,
contextModuleFactory
);
compilation.dependencyTemplates.set(
RequireResolveContextDependency,
new RequireResolveContextDependency.Template()
);
compilation.dependencyFactories.set(
RequireResolveHeaderDependency,
new NullFactory()
);
compilation.dependencyTemplates.set(
RequireResolveHeaderDependency,
new RequireResolveHeaderDependency.Template()
);
compilation.dependencyFactories.set(
RequireHeaderDependency,
new NullFactory()
);
compilation.dependencyTemplates.set(
RequireHeaderDependency,
new RequireHeaderDependency.Template()
);
const handler = (parser, parserOptions) => {
if (parserOptions.commonjs !== undefined && !parserOptions.commonjs)
return;
const requireExpressions = [
"require",
"require.resolve",
"require.resolveWeak"
];
for (let expression of requireExpressions) {
parser.hooks.typeof
.for(expression)
.tap(
"CommonJsPlugin",
ParserHelpers.toConstantDependency(
parser,
JSON.stringify("function")
)
);
parser.hooks.evaluateTypeof
.for(expression)
.tap(
"CommonJsPlugin",
ParserHelpers.evaluateToString("function")
);
parser.hooks.evaluateIdentifier
.for(expression)
.tap(
"CommonJsPlugin",
ParserHelpers.evaluateToIdentifier(expression, true)
);
}
parser.hooks.evaluateTypeof
.for("module")
.tap("CommonJsPlugin", ParserHelpers.evaluateToString("object"));
parser.hooks.assign.for("require").tap("CommonJsPlugin", expr => {
// to not leak to global "require", we need to define a local require here.
const dep = new ConstDependency("var require;", 0);
dep.loc = expr.loc;
parser.state.current.addDependency(dep);
parser.scope.definitions.add("require");
return true;
});
parser.hooks.canRename
.for("require")
.tap("CommonJsPlugin", () => true);
parser.hooks.rename.for("require").tap("CommonJsPlugin", expr => {
// define the require variable. It's still undefined, but not "not defined".
const dep = new ConstDependency("var require;", 0);
dep.loc = expr.loc;
parser.state.current.addDependency(dep);
return false;
});
parser.hooks.typeof.for("module").tap("CommonJsPlugin", () => true);
parser.hooks.evaluateTypeof
.for("exports")
.tap("CommonJsPlugin", ParserHelpers.evaluateToString("object"));
new CommonJsRequireDependencyParserPlugin(options).apply(parser);
new RequireResolveDependencyParserPlugin(options).apply(parser);
};
normalModuleFactory.hooks.parser
.for("javascript/auto")
.tap("CommonJsPlugin", handler);
normalModuleFactory.hooks.parser
.for("javascript/dynamic")
.tap("CommonJsPlugin", handler);
}
);
}
}
module.exports = CommonJsPlugin;

View file

@ -0,0 +1,23 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ContextDependency = require("./ContextDependency");
const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall");
class CommonJsRequireContextDependency extends ContextDependency {
constructor(options, range, valueRange) {
super(options);
this.range = range;
this.valueRange = valueRange;
}
get type() {
return "cjs require context";
}
}
CommonJsRequireContextDependency.Template = ContextDependencyTemplateAsRequireCall;
module.exports = CommonJsRequireContextDependency;

View file

@ -0,0 +1,22 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
const ModuleDependencyTemplateAsId = require("./ModuleDependencyTemplateAsId");
class CommonJsRequireDependency extends ModuleDependency {
constructor(request, range) {
super(request);
this.range = range;
}
get type() {
return "cjs require";
}
}
CommonJsRequireDependency.Template = ModuleDependencyTemplateAsId;
module.exports = CommonJsRequireDependency;

View file

@ -0,0 +1,138 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const CommonJsRequireDependency = require("./CommonJsRequireDependency");
const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency");
const RequireHeaderDependency = require("./RequireHeaderDependency");
const LocalModuleDependency = require("./LocalModuleDependency");
const ContextDependencyHelpers = require("./ContextDependencyHelpers");
const LocalModulesHelpers = require("./LocalModulesHelpers");
const ParserHelpers = require("../ParserHelpers");
class CommonJsRequireDependencyParserPlugin {
constructor(options) {
this.options = options;
}
apply(parser) {
const options = this.options;
const processItem = (expr, param) => {
if (param.isString()) {
const dep = new CommonJsRequireDependency(param.string, param.range);
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
}
};
const processContext = (expr, param) => {
const dep = ContextDependencyHelpers.create(
CommonJsRequireContextDependency,
expr.range,
param,
expr,
options,
{},
parser
);
if (!dep) return;
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
};
parser.hooks.expression
.for("require.cache")
.tap(
"CommonJsRequireDependencyParserPlugin",
ParserHelpers.toConstantDependencyWithWebpackRequire(
parser,
"__webpack_require__.c"
)
);
parser.hooks.expression
.for("require")
.tap("CommonJsRequireDependencyParserPlugin", expr => {
const dep = new CommonJsRequireContextDependency(
{
request: options.unknownContextRequest,
recursive: options.unknownContextRecursive,
regExp: options.unknownContextRegExp,
mode: "sync"
},
expr.range
);
dep.critical =
options.unknownContextCritical &&
"require function is used in a way in which dependencies cannot be statically extracted";
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
});
const createHandler = callNew => expr => {
if (expr.arguments.length !== 1) return;
let localModule;
const param = parser.evaluateExpression(expr.arguments[0]);
if (param.isConditional()) {
let isExpression = false;
const prevLength = parser.state.current.dependencies.length;
const dep = new RequireHeaderDependency(expr.callee.range);
dep.loc = expr.loc;
parser.state.current.addDependency(dep);
for (const p of param.options) {
const result = processItem(expr, p);
if (result === undefined) {
isExpression = true;
}
}
if (isExpression) {
parser.state.current.dependencies.length = prevLength;
} else {
return true;
}
}
if (
param.isString() &&
(localModule = LocalModulesHelpers.getLocalModule(
parser.state,
param.string
))
) {
const dep = new LocalModuleDependency(localModule, expr.range, callNew);
dep.loc = expr.loc;
parser.state.current.addDependency(dep);
return true;
} else {
const result = processItem(expr, param);
if (result === undefined) {
processContext(expr, param);
} else {
const dep = new RequireHeaderDependency(expr.callee.range);
dep.loc = expr.loc;
parser.state.current.addDependency(dep);
}
return true;
}
};
parser.hooks.call
.for("require")
.tap("CommonJsRequireDependencyParserPlugin", createHandler(false));
parser.hooks.new
.for("require")
.tap("CommonJsRequireDependencyParserPlugin", createHandler(true));
parser.hooks.call
.for("module.require")
.tap("CommonJsRequireDependencyParserPlugin", createHandler(false));
parser.hooks.new
.for("module.require")
.tap("CommonJsRequireDependencyParserPlugin", createHandler(true));
}
}
module.exports = CommonJsRequireDependencyParserPlugin;

View file

@ -0,0 +1,33 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
class ConstDependency extends NullDependency {
constructor(expression, range, requireWebpackRequire) {
super();
this.expression = expression;
this.range = range;
this.requireWebpackRequire = requireWebpackRequire;
}
updateHash(hash) {
hash.update(this.range + "");
hash.update(this.expression + "");
}
}
ConstDependency.Template = class ConstDependencyTemplate {
apply(dep, source) {
if (typeof dep.range === "number") {
source.insert(dep.range, dep.expression);
return;
}
source.replace(dep.range[0], dep.range[1] - 1, dep.expression);
}
};
module.exports = ConstDependency;

View file

@ -0,0 +1,68 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const Dependency = require("../Dependency");
const CriticalDependencyWarning = require("./CriticalDependencyWarning");
const regExpToString = r => (r ? r + "" : "");
class ContextDependency extends Dependency {
// options: { request, recursive, regExp, include, exclude, mode, chunkName, groupOptions }
constructor(options) {
super();
this.options = options;
this.userRequest = this.options.request;
/** @type {false | string} */
this.critical = false;
this.hadGlobalOrStickyRegExp = false;
if (this.options.regExp.global || this.options.regExp.sticky) {
this.options.regExp = null;
this.hadGlobalOrStickyRegExp = true;
}
}
getResourceIdentifier() {
return (
`context${this.options.request} ${this.options.recursive} ` +
`${regExpToString(this.options.regExp)} ${regExpToString(
this.options.include
)} ${regExpToString(this.options.exclude)} ` +
`${this.options.mode} ${this.options.chunkName} ` +
`${JSON.stringify(this.options.groupOptions)}`
);
}
getWarnings() {
let warnings = super.getWarnings() || [];
if (this.critical) {
warnings.push(new CriticalDependencyWarning(this.critical));
}
if (this.hadGlobalOrStickyRegExp) {
warnings.push(
new CriticalDependencyWarning(
"Contexts can't use RegExps with the 'g' or 'y' flags."
)
);
}
return warnings;
}
}
// TODO remove in webpack 5
Object.defineProperty(ContextDependency.prototype, "async", {
configurable: false,
get() {
throw new Error(
"ContextDependency.async was removed. Use ContextDependency.options.mode instead."
);
},
set() {
throw new Error(
"ContextDependency.async was removed. Pass options.mode to constructor instead"
);
}
});
module.exports = ContextDependency;

View file

@ -0,0 +1,232 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ContextDependencyHelpers = exports;
/**
* Escapes regular expression metacharacters
* @param {string} str String to quote
* @returns {string} Escaped string
*/
const quotemeta = str => {
return str.replace(/[-[\]\\/{}()*+?.^$|]/g, "\\$&");
};
const splitContextFromPrefix = prefix => {
const idx = prefix.lastIndexOf("/");
let context = ".";
if (idx >= 0) {
context = prefix.substr(0, idx);
prefix = `.${prefix.substr(idx)}`;
}
return {
context,
prefix
};
};
const splitQueryFromPostfix = postfix => {
const idx = postfix.indexOf("?");
let query = "";
if (idx >= 0) {
query = postfix.substr(idx);
postfix = postfix.substr(0, idx);
}
return {
postfix,
query
};
};
ContextDependencyHelpers.create = (
Dep,
range,
param,
expr,
options,
contextOptions,
// when parser is not passed in, expressions won't be walked
parser = null
) => {
if (param.isTemplateString()) {
let prefixRaw = param.quasis[0].string;
let postfixRaw =
param.quasis.length > 1
? param.quasis[param.quasis.length - 1].string
: "";
const valueRange = param.range;
const { context, prefix } = splitContextFromPrefix(prefixRaw);
const { postfix, query } = splitQueryFromPostfix(postfixRaw);
// When there are more than two quasis, the generated RegExp can be more precise
// We join the quasis with the expression regexp
const innerQuasis = param.quasis.slice(1, param.quasis.length - 1);
const innerRegExp =
options.wrappedContextRegExp.source +
innerQuasis
.map(q => quotemeta(q.string) + options.wrappedContextRegExp.source)
.join("");
// Example: `./context/pre${e}inner${e}inner2${e}post?query`
// context: "./context"
// prefix: "./pre"
// innerQuasis: [BEE("inner"), BEE("inner2")]
// (BEE = BasicEvaluatedExpression)
// postfix: "post"
// query: "?query"
// regExp: /^\.\/pre.*inner.*inner2.*post$/
const regExp = new RegExp(
`^${quotemeta(prefix)}${innerRegExp}${quotemeta(postfix)}$`
);
const dep = new Dep(
Object.assign(
{
request: context + query,
recursive: options.wrappedContextRecursive,
regExp,
mode: "sync"
},
contextOptions
),
range,
valueRange
);
dep.loc = expr.loc;
const replaces = [];
param.parts.forEach((part, i) => {
if (i % 2 === 0) {
// Quasis or merged quasi
let range = part.range;
let value = part.string;
if (param.templateStringKind === "cooked") {
value = JSON.stringify(value);
value = value.slice(1, value.length - 1);
}
if (i === 0) {
// prefix
value = prefix;
range = [param.range[0], part.range[1]];
value =
(param.templateStringKind === "cooked" ? "`" : "String.raw`") +
value;
} else if (i === param.parts.length - 1) {
// postfix
value = postfix;
range = [part.range[0], param.range[1]];
value = value + "`";
} else if (
part.expression &&
part.expression.type === "TemplateElement" &&
part.expression.value.raw === value
) {
// Shortcut when it's a single quasi and doesn't need to be replaced
return;
}
replaces.push({
range,
value
});
} else {
// Expression
if (parser) {
parser.walkExpression(part.expression);
}
}
});
dep.replaces = replaces;
dep.critical =
options.wrappedContextCritical &&
"a part of the request of a dependency is an expression";
return dep;
} else if (
param.isWrapped() &&
((param.prefix && param.prefix.isString()) ||
(param.postfix && param.postfix.isString()))
) {
let prefixRaw =
param.prefix && param.prefix.isString() ? param.prefix.string : "";
let postfixRaw =
param.postfix && param.postfix.isString() ? param.postfix.string : "";
const prefixRange =
param.prefix && param.prefix.isString() ? param.prefix.range : null;
const postfixRange =
param.postfix && param.postfix.isString() ? param.postfix.range : null;
const valueRange = param.range;
const { context, prefix } = splitContextFromPrefix(prefixRaw);
const { postfix, query } = splitQueryFromPostfix(postfixRaw);
const regExp = new RegExp(
`^${quotemeta(prefix)}${options.wrappedContextRegExp.source}${quotemeta(
postfix
)}$`
);
const dep = new Dep(
Object.assign(
{
request: context + query,
recursive: options.wrappedContextRecursive,
regExp,
mode: "sync"
},
contextOptions
),
range,
valueRange
);
dep.loc = expr.loc;
const replaces = [];
if (prefixRange) {
replaces.push({
range: prefixRange,
value: JSON.stringify(prefix)
});
}
if (postfixRange) {
replaces.push({
range: postfixRange,
value: JSON.stringify(postfix)
});
}
dep.replaces = replaces;
dep.critical =
options.wrappedContextCritical &&
"a part of the request of a dependency is an expression";
if (parser && param.wrappedInnerExpressions) {
for (const part of param.wrappedInnerExpressions) {
if (part.expression) parser.walkExpression(part.expression);
}
}
return dep;
} else {
const dep = new Dep(
Object.assign(
{
request: options.exprContextRequest,
recursive: options.exprContextRecursive,
regExp: options.exprContextRegExp,
mode: "sync"
},
contextOptions
),
range,
param.range
);
dep.loc = expr.loc;
dep.critical =
options.exprContextCritical &&
"the request of a dependency is an expression";
if (parser) {
parser.walkExpression(param.expression);
}
return dep;
}
};

View file

@ -0,0 +1,43 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
class ContextDependencyTemplateAsId {
apply(dep, source, runtime) {
const moduleExports = runtime.moduleExports({
module: dep.module,
request: dep.request
});
if (dep.module) {
if (dep.valueRange) {
if (Array.isArray(dep.replaces)) {
for (let i = 0; i < dep.replaces.length; i++) {
const rep = dep.replaces[i];
source.replace(rep.range[0], rep.range[1] - 1, rep.value);
}
}
source.replace(dep.valueRange[1], dep.range[1] - 1, ")");
// TODO webpack 5 remove `prepend` it's no longer used
source.replace(
dep.range[0],
dep.valueRange[0] - 1,
`${moduleExports}.resolve(${
typeof dep.prepend === "string" ? JSON.stringify(dep.prepend) : ""
}`
);
} else {
source.replace(
dep.range[0],
dep.range[1] - 1,
`${moduleExports}.resolve`
);
}
} else {
source.replace(dep.range[0], dep.range[1] - 1, moduleExports);
}
}
}
module.exports = ContextDependencyTemplateAsId;

View file

@ -0,0 +1,39 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
class ContextDependencyTemplateAsRequireCall {
apply(dep, source, runtime) {
const moduleExports = runtime.moduleExports({
module: dep.module,
request: dep.request
});
if (dep.module) {
if (dep.valueRange) {
if (Array.isArray(dep.replaces)) {
for (let i = 0; i < dep.replaces.length; i++) {
const rep = dep.replaces[i];
source.replace(rep.range[0], rep.range[1] - 1, rep.value);
}
}
source.replace(dep.valueRange[1], dep.range[1] - 1, ")");
// TODO webpack 5 remove `prepend` it's no longer used
source.replace(
dep.range[0],
dep.valueRange[0] - 1,
`${moduleExports}(${
typeof dep.prepend === "string" ? JSON.stringify(dep.prepend) : ""
}`
);
} else {
source.replace(dep.range[0], dep.range[1] - 1, moduleExports);
}
} else {
source.replace(dep.range[0], dep.range[1] - 1, moduleExports);
}
}
}
module.exports = ContextDependencyTemplateAsRequireCall;

View file

@ -0,0 +1,21 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
class ContextElementDependency extends ModuleDependency {
constructor(request, userRequest) {
super(request);
if (userRequest) {
this.userRequest = userRequest;
}
}
get type() {
return "context element";
}
}
module.exports = ContextElementDependency;

View file

@ -0,0 +1,20 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const WebpackError = require("../WebpackError");
class CriticalDependencyWarning extends WebpackError {
constructor(message) {
super();
this.name = "CriticalDependencyWarning";
this.message = "Critical dependency: " + message;
Error.captureStackTrace(this, this.constructor);
}
}
module.exports = CriticalDependencyWarning;

View file

@ -0,0 +1,33 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const DependencyReference = require("./DependencyReference");
const NullDependency = require("./NullDependency");
class DelegatedExportsDependency extends NullDependency {
constructor(originModule, exports) {
super();
this.originModule = originModule;
this.exports = exports;
}
get type() {
return "delegated exports";
}
getReference() {
return new DependencyReference(this.originModule, true, false);
}
getExports() {
return {
exports: this.exports,
dependencies: undefined
};
}
}
module.exports = DelegatedExportsDependency;

View file

@ -0,0 +1,18 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
class DelegatedSourceDependency extends ModuleDependency {
constructor(request) {
super(request);
}
get type() {
return "delegated source";
}
}
module.exports = DelegatedSourceDependency;

View file

@ -0,0 +1,64 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Florent Cailhol @ooflorent
*/
"use strict";
/** @typedef {import("../Module")} Module */
class DependencyReference {
// TODO webpack 5: module must be dynamic, you must pass a function returning a module
// This is needed to remove the hack in ConcatenatedModule
// The problem is that the `module` in Dependency could be replaced i. e. because of Scope Hoisting
/**
*
* @param {Module} module the referenced module
* @param {string[] | boolean} importedNames imported named from the module
* @param {boolean=} weak if this is a weak reference
* @param {number} order the order information or NaN if don't care
*/
constructor(module, importedNames, weak = false, order = NaN) {
// TODO webpack 5: make it a getter
this.module = module;
// true: full object
// false: only sideeffects/no export
// array of strings: the exports with this names
this.importedNames = importedNames;
this.weak = !!weak;
this.order = order;
}
/**
* @param {DependencyReference[]} array an array (will be modified)
* @returns {DependencyReference[]} the array again
*/
static sort(array) {
/** @type {WeakMap<DependencyReference, number>} */
const originalOrder = new WeakMap();
let i = 0;
for (const ref of array) {
originalOrder.set(ref, i++);
}
return array.sort((a, b) => {
const aOrder = a.order;
const bOrder = b.order;
if (isNaN(aOrder)) {
if (!isNaN(bOrder)) {
return 1;
}
} else {
if (isNaN(bOrder)) {
return -1;
}
if (aOrder !== bOrder) {
return aOrder - bOrder;
}
}
const aOrg = originalOrder.get(a);
const bOrg = originalOrder.get(b);
return aOrg - bOrg;
});
}
}
module.exports = DependencyReference;

View file

@ -0,0 +1,20 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const Dependency = require("../Dependency");
class DllEntryDependency extends Dependency {
constructor(dependencies, name) {
super();
this.dependencies = dependencies;
this.name = name;
}
get type() {
return "dll entry";
}
}
module.exports = DllEntryDependency;

View file

@ -0,0 +1,48 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
const HarmonyImportDependency = require("./HarmonyImportDependency");
class HarmonyAcceptDependency extends NullDependency {
constructor(range, dependencies, hasCallback) {
super();
this.range = range;
this.dependencies = dependencies;
this.hasCallback = hasCallback;
}
get type() {
return "accepted harmony modules";
}
}
HarmonyAcceptDependency.Template = class HarmonyAcceptDependencyTemplate {
apply(dep, source, runtime) {
const content = dep.dependencies
.filter(dependency =>
HarmonyImportDependency.Template.isImportEmitted(dependency, source)
)
.map(dependency => dependency.getImportStatement(true, runtime))
.join("");
if (dep.hasCallback) {
source.insert(
dep.range[0],
`function(__WEBPACK_OUTDATED_DEPENDENCIES__) { ${content}(`
);
source.insert(
dep.range[1],
")(__WEBPACK_OUTDATED_DEPENDENCIES__); }.bind(this)"
);
return;
}
source.insert(dep.range[1] - 0.5, `, function() { ${content} }`);
}
};
module.exports = HarmonyAcceptDependency;

View file

@ -0,0 +1,23 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const HarmonyImportDependency = require("./HarmonyImportDependency");
class HarmonyAcceptImportDependency extends HarmonyImportDependency {
constructor(request, originModule, parserScope) {
super(request, originModule, NaN, parserScope);
this.weak = true;
}
get type() {
return "harmony accept";
}
}
HarmonyAcceptImportDependency.Template = class HarmonyAcceptImportDependencyTemplate extends HarmonyImportDependency.Template {
apply(dep, source, runtime) {}
};
module.exports = HarmonyAcceptImportDependency;

View file

@ -0,0 +1,31 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
class HarmonyCompatibilityDependency extends NullDependency {
constructor(originModule) {
super();
this.originModule = originModule;
}
get type() {
return "harmony export header";
}
}
HarmonyCompatibilityDependency.Template = class HarmonyExportDependencyTemplate {
apply(dep, source, runtime) {
const usedExports = dep.originModule.usedExports;
if (usedExports !== false && !Array.isArray(usedExports)) {
const content = runtime.defineEsModuleFlagStatement({
exportsArgument: dep.originModule.exportsArgument
});
source.insert(-10, content);
}
}
};
module.exports = HarmonyCompatibilityDependency;

View file

@ -0,0 +1,96 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const HarmonyCompatibilityDependency = require("./HarmonyCompatibilityDependency");
const HarmonyInitDependency = require("./HarmonyInitDependency");
module.exports = class HarmonyDetectionParserPlugin {
apply(parser) {
parser.hooks.program.tap("HarmonyDetectionParserPlugin", ast => {
const isStrictHarmony = parser.state.module.type === "javascript/esm";
const isHarmony =
isStrictHarmony ||
ast.body.some(
statement =>
statement.type === "ImportDeclaration" ||
statement.type === "ExportDefaultDeclaration" ||
statement.type === "ExportNamedDeclaration" ||
statement.type === "ExportAllDeclaration"
);
if (isHarmony) {
const module = parser.state.module;
const compatDep = new HarmonyCompatibilityDependency(module);
compatDep.loc = {
start: {
line: -1,
column: 0
},
end: {
line: -1,
column: 0
},
index: -3
};
module.addDependency(compatDep);
const initDep = new HarmonyInitDependency(module);
initDep.loc = {
start: {
line: -1,
column: 0
},
end: {
line: -1,
column: 0
},
index: -2
};
module.addDependency(initDep);
parser.state.harmonyParserScope = parser.state.harmonyParserScope || {};
parser.scope.isStrict = true;
module.buildMeta.exportsType = "namespace";
module.buildInfo.strict = true;
module.buildInfo.exportsArgument = "__webpack_exports__";
if (isStrictHarmony) {
module.buildMeta.strictHarmonyModule = true;
module.buildInfo.moduleArgument = "__webpack_module__";
}
}
});
const skipInHarmony = () => {
const module = parser.state.module;
if (module && module.buildMeta && module.buildMeta.exportsType) {
return true;
}
};
const nullInHarmony = () => {
const module = parser.state.module;
if (module && module.buildMeta && module.buildMeta.exportsType) {
return null;
}
};
const nonHarmonyIdentifiers = ["define", "exports"];
for (const identifer of nonHarmonyIdentifiers) {
parser.hooks.evaluateTypeof
.for(identifer)
.tap("HarmonyDetectionParserPlugin", nullInHarmony);
parser.hooks.typeof
.for(identifer)
.tap("HarmonyDetectionParserPlugin", skipInHarmony);
parser.hooks.evaluate
.for(identifer)
.tap("HarmonyDetectionParserPlugin", nullInHarmony);
parser.hooks.expression
.for(identifer)
.tap("HarmonyDetectionParserPlugin", skipInHarmony);
parser.hooks.call
.for(identifer)
.tap("HarmonyDetectionParserPlugin", skipInHarmony);
}
}
};

View file

@ -0,0 +1,154 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const HarmonyExportExpressionDependency = require("./HarmonyExportExpressionDependency");
const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
const HarmonyExportHeaderDependency = require("./HarmonyExportHeaderDependency");
const HarmonyExportSpecifierDependency = require("./HarmonyExportSpecifierDependency");
const HarmonyExportImportedSpecifierDependency = require("./HarmonyExportImportedSpecifierDependency");
const ConstDependency = require("./ConstDependency");
module.exports = class HarmonyExportDependencyParserPlugin {
constructor(moduleOptions) {
this.strictExportPresence = moduleOptions.strictExportPresence;
}
apply(parser) {
parser.hooks.export.tap(
"HarmonyExportDependencyParserPlugin",
statement => {
const dep = new HarmonyExportHeaderDependency(
statement.declaration && statement.declaration.range,
statement.range
);
dep.loc = Object.create(statement.loc);
dep.loc.index = -1;
parser.state.current.addDependency(dep);
return true;
}
);
parser.hooks.exportImport.tap(
"HarmonyExportDependencyParserPlugin",
(statement, source) => {
parser.state.lastHarmonyImportOrder =
(parser.state.lastHarmonyImportOrder || 0) + 1;
const clearDep = new ConstDependency("", statement.range);
clearDep.loc = Object.create(statement.loc);
clearDep.loc.index = -1;
parser.state.current.addDependency(clearDep);
const sideEffectDep = new HarmonyImportSideEffectDependency(
source,
parser.state.module,
parser.state.lastHarmonyImportOrder,
parser.state.harmonyParserScope
);
sideEffectDep.loc = Object.create(statement.loc);
sideEffectDep.loc.index = -1;
parser.state.current.addDependency(sideEffectDep);
return true;
}
);
parser.hooks.exportExpression.tap(
"HarmonyExportDependencyParserPlugin",
(statement, expr) => {
const comments = parser.getComments([
statement.range[0],
expr.range[0]
]);
const dep = new HarmonyExportExpressionDependency(
parser.state.module,
expr.range,
statement.range,
comments
.map(c => {
switch (c.type) {
case "Block":
return `/*${c.value}*/`;
case "Line":
return `//${c.value}\n`;
}
return "";
})
.join("")
);
dep.loc = Object.create(statement.loc);
dep.loc.index = -1;
parser.state.current.addDependency(dep);
return true;
}
);
parser.hooks.exportDeclaration.tap(
"HarmonyExportDependencyParserPlugin",
statement => {}
);
parser.hooks.exportSpecifier.tap(
"HarmonyExportDependencyParserPlugin",
(statement, id, name, idx) => {
const rename = parser.scope.renames.get(id);
let dep;
const harmonyNamedExports = (parser.state.harmonyNamedExports =
parser.state.harmonyNamedExports || new Set());
harmonyNamedExports.add(name);
if (rename === "imported var") {
const settings = parser.state.harmonySpecifier.get(id);
dep = new HarmonyExportImportedSpecifierDependency(
settings.source,
parser.state.module,
settings.sourceOrder,
parser.state.harmonyParserScope,
settings.id,
name,
harmonyNamedExports,
null,
this.strictExportPresence
);
} else {
dep = new HarmonyExportSpecifierDependency(
parser.state.module,
id,
name
);
}
dep.loc = Object.create(statement.loc);
dep.loc.index = idx;
parser.state.current.addDependency(dep);
return true;
}
);
parser.hooks.exportImportSpecifier.tap(
"HarmonyExportDependencyParserPlugin",
(statement, source, id, name, idx) => {
const harmonyNamedExports = (parser.state.harmonyNamedExports =
parser.state.harmonyNamedExports || new Set());
let harmonyStarExports = null;
if (name) {
harmonyNamedExports.add(name);
} else {
harmonyStarExports = parser.state.harmonyStarExports =
parser.state.harmonyStarExports || [];
}
const dep = new HarmonyExportImportedSpecifierDependency(
source,
parser.state.module,
parser.state.lastHarmonyImportOrder,
parser.state.harmonyParserScope,
id,
name,
harmonyNamedExports,
harmonyStarExports && harmonyStarExports.slice(),
this.strictExportPresence
);
if (harmonyStarExports) {
harmonyStarExports.push(dep);
}
dep.loc = Object.create(statement.loc);
dep.loc.index = idx;
parser.state.current.addDependency(dep);
return true;
}
);
}
};

View file

@ -0,0 +1,58 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
class HarmonyExportExpressionDependency extends NullDependency {
constructor(originModule, range, rangeStatement, prefix) {
super();
this.originModule = originModule;
this.range = range;
this.rangeStatement = rangeStatement;
this.prefix = prefix;
}
get type() {
return "harmony export expression";
}
getExports() {
return {
exports: ["default"],
dependencies: undefined
};
}
}
HarmonyExportExpressionDependency.Template = class HarmonyExportDependencyTemplate {
apply(dep, source) {
const used = dep.originModule.isUsed("default");
const content = this.getContent(dep.originModule, used);
if (dep.range) {
source.replace(
dep.rangeStatement[0],
dep.range[0] - 1,
content + "(" + dep.prefix
);
source.replace(dep.range[1], dep.rangeStatement[1] - 1, ");");
return;
}
source.replace(dep.rangeStatement[0], dep.rangeStatement[1] - 1, content);
}
getContent(module, used) {
const exportsName = module.exportsArgument;
if (used) {
return `/* harmony default export */ ${exportsName}[${JSON.stringify(
used
)}] = `;
}
return "/* unused harmony default export */ var _unused_webpack_default_export = ";
}
};
module.exports = HarmonyExportExpressionDependency;

View file

@ -0,0 +1,30 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
class HarmonyExportHeaderDependency extends NullDependency {
constructor(range, rangeStatement) {
super();
this.range = range;
this.rangeStatement = rangeStatement;
}
get type() {
return "harmony export header";
}
}
HarmonyExportHeaderDependency.Template = class HarmonyExportDependencyTemplate {
apply(dep, source) {
const content = "";
const replaceUntil = dep.range
? dep.range[0] - 1
: dep.rangeStatement[1] - 1;
source.replace(dep.rangeStatement[0], replaceUntil, content);
}
};
module.exports = HarmonyExportHeaderDependency;

View file

@ -0,0 +1,659 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const DependencyReference = require("./DependencyReference");
const HarmonyImportDependency = require("./HarmonyImportDependency");
const Template = require("../Template");
const HarmonyLinkingError = require("../HarmonyLinkingError");
/** @typedef {import("../Module")} Module */
/** @typedef {"missing"|"unused"|"empty-star"|"reexport-non-harmony-default"|"reexport-named-default"|"reexport-namespace-object"|"reexport-non-harmony-default-strict"|"reexport-fake-namespace-object"|"rexport-non-harmony-undefined"|"safe-reexport"|"checked-reexport"|"dynamic-reexport"} ExportModeType */
/** @type {Map<string, string>} */
const EMPTY_MAP = new Map();
class ExportMode {
/**
* @param {ExportModeType} type type of the mode
*/
constructor(type) {
/** @type {ExportModeType} */
this.type = type;
/** @type {string|null} */
this.name = null;
/** @type {Map<string, string>} */
this.map = EMPTY_MAP;
/** @type {Set<string>|null} */
this.ignored = null;
/** @type {Module|null} */
this.module = null;
/** @type {string|null} */
this.userRequest = null;
}
}
const EMPTY_STAR_MODE = new ExportMode("empty-star");
class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
constructor(
request,
originModule,
sourceOrder,
parserScope,
id,
name,
activeExports,
otherStarExports,
strictExportPresence
) {
super(request, originModule, sourceOrder, parserScope);
this.id = id;
this.redirectedId = undefined;
this.name = name;
this.activeExports = activeExports;
this.otherStarExports = otherStarExports;
this.strictExportPresence = strictExportPresence;
}
get type() {
return "harmony export imported specifier";
}
get _id() {
return this.redirectedId || this.id;
}
getMode(ignoreUnused) {
const name = this.name;
const id = this._id;
const used = this.originModule.isUsed(name);
const importedModule = this._module;
if (!importedModule) {
const mode = new ExportMode("missing");
mode.userRequest = this.userRequest;
return mode;
}
if (
!ignoreUnused &&
(name ? !used : this.originModule.usedExports === false)
) {
const mode = new ExportMode("unused");
mode.name = name || "*";
return mode;
}
const strictHarmonyModule = this.originModule.buildMeta.strictHarmonyModule;
if (name && id === "default" && importedModule.buildMeta) {
if (!importedModule.buildMeta.exportsType) {
const mode = new ExportMode(
strictHarmonyModule
? "reexport-non-harmony-default-strict"
: "reexport-non-harmony-default"
);
mode.name = name;
mode.module = importedModule;
return mode;
} else if (importedModule.buildMeta.exportsType === "named") {
const mode = new ExportMode("reexport-named-default");
mode.name = name;
mode.module = importedModule;
return mode;
}
}
const isNotAHarmonyModule =
importedModule.buildMeta && !importedModule.buildMeta.exportsType;
if (name) {
let mode;
if (id) {
// export { name as name }
if (isNotAHarmonyModule && strictHarmonyModule) {
mode = new ExportMode("rexport-non-harmony-undefined");
mode.name = name;
} else {
mode = new ExportMode("safe-reexport");
mode.map = new Map([[name, id]]);
}
} else {
// export { * as name }
if (isNotAHarmonyModule && strictHarmonyModule) {
mode = new ExportMode("reexport-fake-namespace-object");
mode.name = name;
} else {
mode = new ExportMode("reexport-namespace-object");
mode.name = name;
}
}
mode.module = importedModule;
return mode;
}
const hasUsedExports = Array.isArray(this.originModule.usedExports);
const hasProvidedExports = Array.isArray(
importedModule.buildMeta.providedExports
);
const activeFromOtherStarExports = this._discoverActiveExportsFromOtherStartExports();
// export *
if (hasUsedExports) {
// reexport * with known used exports
if (hasProvidedExports) {
const map = new Map(
this.originModule.usedExports
.filter(id => {
if (id === "default") return false;
if (this.activeExports.has(id)) return false;
if (activeFromOtherStarExports.has(id)) return false;
if (!importedModule.buildMeta.providedExports.includes(id))
return false;
return true;
})
.map(item => [item, item])
);
if (map.size === 0) {
return EMPTY_STAR_MODE;
}
const mode = new ExportMode("safe-reexport");
mode.module = importedModule;
mode.map = map;
return mode;
}
const map = new Map(
this.originModule.usedExports
.filter(id => {
if (id === "default") return false;
if (this.activeExports.has(id)) return false;
if (activeFromOtherStarExports.has(id)) return false;
return true;
})
.map(item => [item, item])
);
if (map.size === 0) {
return EMPTY_STAR_MODE;
}
const mode = new ExportMode("checked-reexport");
mode.module = importedModule;
mode.map = map;
return mode;
}
if (hasProvidedExports) {
const map = new Map(
importedModule.buildMeta.providedExports
.filter(id => {
if (id === "default") return false;
if (this.activeExports.has(id)) return false;
if (activeFromOtherStarExports.has(id)) return false;
return true;
})
.map(item => [item, item])
);
if (map.size === 0) {
return EMPTY_STAR_MODE;
}
const mode = new ExportMode("safe-reexport");
mode.module = importedModule;
mode.map = map;
return mode;
}
const mode = new ExportMode("dynamic-reexport");
mode.module = importedModule;
mode.ignored = new Set([
"default",
...this.activeExports,
...activeFromOtherStarExports
]);
return mode;
}
getReference() {
const mode = this.getMode(false);
switch (mode.type) {
case "missing":
case "unused":
case "empty-star":
return null;
case "reexport-non-harmony-default":
case "reexport-named-default":
return new DependencyReference(
mode.module,
["default"],
false,
this.sourceOrder
);
case "reexport-namespace-object":
case "reexport-non-harmony-default-strict":
case "reexport-fake-namespace-object":
case "rexport-non-harmony-undefined":
return new DependencyReference(
mode.module,
true,
false,
this.sourceOrder
);
case "safe-reexport":
case "checked-reexport":
return new DependencyReference(
mode.module,
Array.from(mode.map.values()),
false,
this.sourceOrder
);
case "dynamic-reexport":
return new DependencyReference(
mode.module,
true,
false,
this.sourceOrder
);
default:
throw new Error(`Unknown mode ${mode.type}`);
}
}
_discoverActiveExportsFromOtherStartExports() {
if (!this.otherStarExports) return new Set();
const result = new Set();
// try to learn impossible exports from other star exports with provided exports
for (const otherStarExport of this.otherStarExports) {
const otherImportedModule = otherStarExport._module;
if (
otherImportedModule &&
Array.isArray(otherImportedModule.buildMeta.providedExports)
) {
for (const exportName of otherImportedModule.buildMeta
.providedExports) {
result.add(exportName);
}
}
}
return result;
}
getExports() {
if (this.name) {
return {
exports: [this.name],
dependencies: undefined
};
}
const importedModule = this._module;
if (!importedModule) {
// no imported module available
return {
exports: null,
dependencies: undefined
};
}
if (Array.isArray(importedModule.buildMeta.providedExports)) {
const activeFromOtherStarExports = this._discoverActiveExportsFromOtherStartExports();
return {
exports: importedModule.buildMeta.providedExports.filter(
id =>
id !== "default" &&
!activeFromOtherStarExports.has(id) &&
!this.activeExports.has(id)
),
dependencies: [importedModule]
};
}
if (importedModule.buildMeta.providedExports) {
return {
exports: true,
dependencies: undefined
};
}
return {
exports: null,
dependencies: [importedModule]
};
}
getWarnings() {
if (
this.strictExportPresence ||
this.originModule.buildMeta.strictHarmonyModule
) {
return [];
}
return this._getErrors();
}
getErrors() {
if (
this.strictExportPresence ||
this.originModule.buildMeta.strictHarmonyModule
) {
return this._getErrors();
}
return [];
}
_getErrors() {
const importedModule = this._module;
if (!importedModule) {
return;
}
if (!importedModule.buildMeta || !importedModule.buildMeta.exportsType) {
// It's not an harmony module
if (
this.originModule.buildMeta.strictHarmonyModule &&
this._id &&
this._id !== "default"
) {
// In strict harmony modules we only support the default export
return [
new HarmonyLinkingError(
`Can't reexport the named export '${this._id}' from non EcmaScript module (only default export is available)`
)
];
}
return;
}
if (!this._id) {
return;
}
if (importedModule.isProvided(this._id) !== false) {
// It's provided or we are not sure
return;
}
// We are sure that it's not provided
const idIsNotNameMessage =
this._id !== this.name ? ` (reexported as '${this.name}')` : "";
const errorMessage = `"export '${this._id}'${idIsNotNameMessage} was not found in '${this.userRequest}'`;
return [new HarmonyLinkingError(errorMessage)];
}
updateHash(hash) {
super.updateHash(hash);
const hashValue = this.getHashValue(this._module);
hash.update(hashValue);
}
getHashValue(importedModule) {
if (!importedModule) {
return "";
}
const stringifiedUsedExport = JSON.stringify(importedModule.usedExports);
const stringifiedProvidedExport = JSON.stringify(
importedModule.buildMeta.providedExports
);
return (
importedModule.used + stringifiedUsedExport + stringifiedProvidedExport
);
}
disconnect() {
super.disconnect();
this.redirectedId = undefined;
}
}
module.exports = HarmonyExportImportedSpecifierDependency;
HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedSpecifierDependencyTemplate extends HarmonyImportDependency.Template {
harmonyInit(dep, source, runtime, dependencyTemplates) {
super.harmonyInit(dep, source, runtime, dependencyTemplates);
const content = this.getContent(dep);
source.insert(-1, content);
}
getHarmonyInitOrder(dep) {
if (dep.name) {
const used = dep.originModule.isUsed(dep.name);
if (!used) return NaN;
} else {
const importedModule = dep._module;
const activeFromOtherStarExports = dep._discoverActiveExportsFromOtherStartExports();
if (Array.isArray(dep.originModule.usedExports)) {
// we know which exports are used
const unused = dep.originModule.usedExports.every(id => {
if (id === "default") return true;
if (dep.activeExports.has(id)) return true;
if (importedModule.isProvided(id) === false) return true;
if (activeFromOtherStarExports.has(id)) return true;
return false;
});
if (unused) return NaN;
} else if (
dep.originModule.usedExports &&
importedModule &&
Array.isArray(importedModule.buildMeta.providedExports)
) {
// not sure which exports are used, but we know which are provided
const unused = importedModule.buildMeta.providedExports.every(id => {
if (id === "default") return true;
if (dep.activeExports.has(id)) return true;
if (activeFromOtherStarExports.has(id)) return true;
return false;
});
if (unused) return NaN;
}
}
return super.getHarmonyInitOrder(dep);
}
getContent(dep) {
const mode = dep.getMode(false);
const module = dep.originModule;
const importedModule = dep._module;
const importVar = dep.getImportVar();
switch (mode.type) {
case "missing":
return `throw new Error(${JSON.stringify(
`Cannot find module '${mode.userRequest}'`
)});\n`;
case "unused":
return `${Template.toNormalComment(
`unused harmony reexport ${mode.name}`
)}\n`;
case "reexport-non-harmony-default":
return (
"/* harmony reexport (default from non-harmony) */ " +
this.getReexportStatement(
module,
module.isUsed(mode.name),
importVar,
null
)
);
case "reexport-named-default":
return (
"/* harmony reexport (default from named exports) */ " +
this.getReexportStatement(
module,
module.isUsed(mode.name),
importVar,
""
)
);
case "reexport-fake-namespace-object":
return (
"/* harmony reexport (fake namespace object from non-harmony) */ " +
this.getReexportFakeNamespaceObjectStatement(
module,
module.isUsed(mode.name),
importVar
)
);
case "rexport-non-harmony-undefined":
return (
"/* harmony reexport (non default export from non-harmony) */ " +
this.getReexportStatement(
module,
module.isUsed(mode.name),
"undefined",
""
)
);
case "reexport-non-harmony-default-strict":
return (
"/* harmony reexport (default from non-harmony) */ " +
this.getReexportStatement(
module,
module.isUsed(mode.name),
importVar,
""
)
);
case "reexport-namespace-object":
return (
"/* harmony reexport (module object) */ " +
this.getReexportStatement(
module,
module.isUsed(mode.name),
importVar,
""
)
);
case "empty-star":
return "/* empty/unused harmony star reexport */";
case "safe-reexport":
return Array.from(mode.map.entries())
.map(item => {
return (
"/* harmony reexport (safe) */ " +
this.getReexportStatement(
module,
module.isUsed(item[0]),
importVar,
importedModule.isUsed(item[1])
) +
"\n"
);
})
.join("");
case "checked-reexport":
return Array.from(mode.map.entries())
.map(item => {
return (
"/* harmony reexport (checked) */ " +
this.getConditionalReexportStatement(
module,
item[0],
importVar,
item[1]
) +
"\n"
);
})
.join("");
case "dynamic-reexport": {
const ignoredExports = mode.ignored;
let content =
"/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in " +
importVar +
") ";
// Filter out exports which are defined by other exports
// and filter out default export because it cannot be reexported with *
if (ignoredExports.size > 0) {
content +=
"if(" +
JSON.stringify(Array.from(ignoredExports)) +
".indexOf(__WEBPACK_IMPORT_KEY__) < 0) ";
} else {
content += "if(__WEBPACK_IMPORT_KEY__ !== 'default') ";
}
const exportsName = dep.originModule.exportsArgument;
return (
content +
`(function(key) { __webpack_require__.d(${exportsName}, key, function() { return ${importVar}[key]; }) }(__WEBPACK_IMPORT_KEY__));\n`
);
}
default:
throw new Error(`Unknown mode ${mode.type}`);
}
}
getReexportStatement(module, key, name, valueKey) {
const exportsName = module.exportsArgument;
const returnValue = this.getReturnValue(name, valueKey);
return `__webpack_require__.d(${exportsName}, ${JSON.stringify(
key
)}, function() { return ${returnValue}; });\n`;
}
getReexportFakeNamespaceObjectStatement(module, key, name) {
const exportsName = module.exportsArgument;
return `__webpack_require__.d(${exportsName}, ${JSON.stringify(
key
)}, function() { return __webpack_require__.t(${name}); });\n`;
}
getConditionalReexportStatement(module, key, name, valueKey) {
if (valueKey === false) {
return "/* unused export */\n";
}
const exportsName = module.exportsArgument;
const returnValue = this.getReturnValue(name, valueKey);
return `if(__webpack_require__.o(${name}, ${JSON.stringify(
valueKey
)})) __webpack_require__.d(${exportsName}, ${JSON.stringify(
key
)}, function() { return ${returnValue}; });\n`;
}
getReturnValue(name, valueKey) {
if (valueKey === null) {
return `${name}_default.a`;
}
if (valueKey === "") {
return name;
}
if (valueKey === false) {
return "/* unused export */ undefined";
}
return `${name}[${JSON.stringify(valueKey)}]`;
}
};

View file

@ -0,0 +1,54 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
class HarmonyExportSpecifierDependency extends NullDependency {
constructor(originModule, id, name) {
super();
this.originModule = originModule;
this.id = id;
this.name = name;
}
get type() {
return "harmony export specifier";
}
getExports() {
return {
exports: [this.name],
dependencies: undefined
};
}
}
HarmonyExportSpecifierDependency.Template = class HarmonyExportSpecifierDependencyTemplate {
apply(dep, source) {}
getHarmonyInitOrder(dep) {
return 0;
}
harmonyInit(dep, source, runtime) {
const content = this.getContent(dep);
source.insert(-1, content);
}
getContent(dep) {
const used = dep.originModule.isUsed(dep.name);
if (!used) {
return `/* unused harmony export ${dep.name || "namespace"} */\n`;
}
const exportsName = dep.originModule.exportsArgument;
return `/* harmony export (binding) */ __webpack_require__.d(${exportsName}, ${JSON.stringify(
used
)}, function() { return ${dep.id}; });\n`;
}
};
module.exports = HarmonyExportSpecifierDependency;

View file

@ -0,0 +1,109 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const DependencyReference = require("./DependencyReference");
const ModuleDependency = require("./ModuleDependency");
const Template = require("../Template");
class HarmonyImportDependency extends ModuleDependency {
constructor(request, originModule, sourceOrder, parserScope) {
super(request);
this.redirectedModule = undefined;
this.originModule = originModule;
this.sourceOrder = sourceOrder;
this.parserScope = parserScope;
}
get _module() {
return this.redirectedModule || this.module;
}
getReference() {
if (!this._module) return null;
return new DependencyReference(
this._module,
false,
this.weak,
this.sourceOrder
);
}
getImportVar() {
let importVarMap = this.parserScope.importVarMap;
if (!importVarMap) this.parserScope.importVarMap = importVarMap = new Map();
let importVar = importVarMap.get(this._module);
if (importVar) return importVar;
importVar = `${Template.toIdentifier(
`${this.userRequest}`
)}__WEBPACK_IMPORTED_MODULE_${importVarMap.size}__`;
importVarMap.set(this._module, importVar);
return importVar;
}
getImportStatement(update, runtime) {
return runtime.importStatement({
update,
module: this._module,
importVar: this.getImportVar(),
request: this.request,
originModule: this.originModule
});
}
updateHash(hash) {
super.updateHash(hash);
const importedModule = this._module;
hash.update(
(importedModule &&
(!importedModule.buildMeta || importedModule.buildMeta.exportsType)) +
""
);
hash.update((importedModule && importedModule.id) + "");
}
disconnect() {
super.disconnect();
this.redirectedModule = undefined;
}
}
module.exports = HarmonyImportDependency;
const importEmittedMap = new WeakMap();
HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate {
apply(dep, source, runtime) {
// no-op
}
getHarmonyInitOrder(dep) {
return dep.sourceOrder;
}
static isImportEmitted(dep, source) {
let sourceInfo = importEmittedMap.get(source);
if (!sourceInfo) return false;
const key = dep._module || dep.request;
return key && sourceInfo.emittedImports.get(key);
}
harmonyInit(dep, source, runtime, dependencyTemplates) {
let sourceInfo = importEmittedMap.get(source);
if (!sourceInfo) {
importEmittedMap.set(
source,
(sourceInfo = {
emittedImports: new Map()
})
);
}
const key = dep._module || dep.request;
if (key && sourceInfo.emittedImports.get(key)) return;
sourceInfo.emittedImports.set(key, true);
const content = dep.getImportStatement(false, runtime);
source.insert(-1, content);
}
};

View file

@ -0,0 +1,222 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { SyncBailHook } = require("tapable");
const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency");
const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency");
const HarmonyAcceptDependency = require("./HarmonyAcceptDependency");
const ConstDependency = require("./ConstDependency");
module.exports = class HarmonyImportDependencyParserPlugin {
constructor(moduleOptions) {
this.strictExportPresence = moduleOptions.strictExportPresence;
this.strictThisContextOnImports = moduleOptions.strictThisContextOnImports;
}
apply(parser) {
parser.hooks.import.tap(
"HarmonyImportDependencyParserPlugin",
(statement, source) => {
parser.state.lastHarmonyImportOrder =
(parser.state.lastHarmonyImportOrder || 0) + 1;
const clearDep = new ConstDependency("", statement.range);
clearDep.loc = statement.loc;
parser.state.module.addDependency(clearDep);
const sideEffectDep = new HarmonyImportSideEffectDependency(
source,
parser.state.module,
parser.state.lastHarmonyImportOrder,
parser.state.harmonyParserScope
);
sideEffectDep.loc = statement.loc;
parser.state.module.addDependency(sideEffectDep);
return true;
}
);
parser.hooks.importSpecifier.tap(
"HarmonyImportDependencyParserPlugin",
(statement, source, id, name) => {
parser.scope.definitions.delete(name);
parser.scope.renames.set(name, "imported var");
if (!parser.state.harmonySpecifier) {
parser.state.harmonySpecifier = new Map();
}
parser.state.harmonySpecifier.set(name, {
source,
id,
sourceOrder: parser.state.lastHarmonyImportOrder
});
return true;
}
);
parser.hooks.expression
.for("imported var")
.tap("HarmonyImportDependencyParserPlugin", expr => {
const name = expr.name;
const settings = parser.state.harmonySpecifier.get(name);
const dep = new HarmonyImportSpecifierDependency(
settings.source,
parser.state.module,
settings.sourceOrder,
parser.state.harmonyParserScope,
settings.id,
name,
expr.range,
this.strictExportPresence
);
dep.shorthand = parser.scope.inShorthand;
dep.directImport = true;
dep.loc = expr.loc;
parser.state.module.addDependency(dep);
return true;
});
parser.hooks.expressionAnyMember
.for("imported var")
.tap("HarmonyImportDependencyParserPlugin", expr => {
const name = expr.object.name;
const settings = parser.state.harmonySpecifier.get(name);
if (settings.id !== null) return false;
const dep = new HarmonyImportSpecifierDependency(
settings.source,
parser.state.module,
settings.sourceOrder,
parser.state.harmonyParserScope,
expr.property.name || expr.property.value,
name,
expr.range,
this.strictExportPresence
);
dep.shorthand = parser.scope.inShorthand;
dep.directImport = false;
dep.loc = expr.loc;
parser.state.module.addDependency(dep);
return true;
});
if (this.strictThisContextOnImports) {
// only in case when we strictly follow the spec we need a special case here
parser.hooks.callAnyMember
.for("imported var")
.tap("HarmonyImportDependencyParserPlugin", expr => {
if (expr.callee.type !== "MemberExpression") return;
if (expr.callee.object.type !== "Identifier") return;
const name = expr.callee.object.name;
const settings = parser.state.harmonySpecifier.get(name);
if (settings.id !== null) return false;
const dep = new HarmonyImportSpecifierDependency(
settings.source,
parser.state.module,
settings.sourceOrder,
parser.state.harmonyParserScope,
expr.callee.property.name || expr.callee.property.value,
name,
expr.callee.range,
this.strictExportPresence
);
dep.shorthand = parser.scope.inShorthand;
dep.directImport = false;
dep.namespaceObjectAsContext = true;
dep.loc = expr.callee.loc;
parser.state.module.addDependency(dep);
if (expr.arguments) parser.walkExpressions(expr.arguments);
return true;
});
}
parser.hooks.call
.for("imported var")
.tap("HarmonyImportDependencyParserPlugin", expr => {
const args = expr.arguments;
const fullExpr = expr;
expr = expr.callee;
if (expr.type !== "Identifier") return;
const name = expr.name;
const settings = parser.state.harmonySpecifier.get(name);
const dep = new HarmonyImportSpecifierDependency(
settings.source,
parser.state.module,
settings.sourceOrder,
parser.state.harmonyParserScope,
settings.id,
name,
expr.range,
this.strictExportPresence
);
dep.directImport = true;
dep.callArgs = args;
dep.call = fullExpr;
dep.loc = expr.loc;
parser.state.module.addDependency(dep);
if (args) parser.walkExpressions(args);
return true;
});
// TODO webpack 5: refactor this, no custom hooks
if (!parser.hooks.hotAcceptCallback) {
parser.hooks.hotAcceptCallback = new SyncBailHook([
"expression",
"requests"
]);
}
if (!parser.hooks.hotAcceptWithoutCallback) {
parser.hooks.hotAcceptWithoutCallback = new SyncBailHook([
"expression",
"requests"
]);
}
parser.hooks.hotAcceptCallback.tap(
"HarmonyImportDependencyParserPlugin",
(expr, requests) => {
const harmonyParserScope = parser.state.harmonyParserScope;
if (!harmonyParserScope) {
// This is not a harmony module, skip it
return;
}
const dependencies = requests.map(request => {
const dep = new HarmonyAcceptImportDependency(
request,
parser.state.module,
harmonyParserScope
);
dep.loc = expr.loc;
parser.state.module.addDependency(dep);
return dep;
});
if (dependencies.length > 0) {
const dep = new HarmonyAcceptDependency(
expr.range,
dependencies,
true
);
dep.loc = expr.loc;
parser.state.module.addDependency(dep);
}
}
);
parser.hooks.hotAcceptWithoutCallback.tap(
"HarmonyImportDependencyParserPlugin",
(expr, requests) => {
const dependencies = requests.map(request => {
const dep = new HarmonyAcceptImportDependency(
request,
parser.state.module,
parser.state.harmonyParserScope
);
dep.loc = expr.loc;
parser.state.module.addDependency(dep);
return dep;
});
if (dependencies.length > 0) {
const dep = new HarmonyAcceptDependency(
expr.range,
dependencies,
false
);
dep.loc = expr.loc;
parser.state.module.addDependency(dep);
}
}
);
}
};

View file

@ -0,0 +1,31 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const HarmonyImportDependency = require("./HarmonyImportDependency");
class HarmonyImportSideEffectDependency extends HarmonyImportDependency {
constructor(request, originModule, sourceOrder, parserScope) {
super(request, originModule, sourceOrder, parserScope);
}
getReference() {
if (this._module && this._module.factoryMeta.sideEffectFree) return null;
return super.getReference();
}
get type() {
return "harmony side effect evaluation";
}
}
HarmonyImportSideEffectDependency.Template = class HarmonyImportSideEffectDependencyTemplate extends HarmonyImportDependency.Template {
getHarmonyInitOrder(dep) {
if (dep._module && dep._module.factoryMeta.sideEffectFree) return NaN;
return super.getHarmonyInitOrder(dep);
}
};
module.exports = HarmonyImportSideEffectDependency;

View file

@ -0,0 +1,163 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const DependencyReference = require("./DependencyReference");
const HarmonyImportDependency = require("./HarmonyImportDependency");
const HarmonyLinkingError = require("../HarmonyLinkingError");
class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
constructor(
request,
originModule,
sourceOrder,
parserScope,
id,
name,
range,
strictExportPresence
) {
super(request, originModule, sourceOrder, parserScope);
this.id = id === null ? null : `${id}`;
this.redirectedId = undefined;
this.name = name;
this.range = range;
this.strictExportPresence = strictExportPresence;
this.namespaceObjectAsContext = false;
this.callArgs = undefined;
this.call = undefined;
this.directImport = undefined;
this.shorthand = undefined;
}
get type() {
return "harmony import specifier";
}
get _id() {
return this.redirectedId || this.id;
}
getReference() {
if (!this._module) return null;
return new DependencyReference(
this._module,
this._id && !this.namespaceObjectAsContext ? [this._id] : true,
false,
this.sourceOrder
);
}
getWarnings() {
if (
this.strictExportPresence ||
this.originModule.buildMeta.strictHarmonyModule
) {
return [];
}
return this._getErrors();
}
getErrors() {
if (
this.strictExportPresence ||
this.originModule.buildMeta.strictHarmonyModule
) {
return this._getErrors();
}
return [];
}
_getErrors() {
const importedModule = this._module;
if (!importedModule) {
return;
}
if (!importedModule.buildMeta || !importedModule.buildMeta.exportsType) {
// It's not an harmony module
if (
this.originModule.buildMeta.strictHarmonyModule &&
this._id &&
this._id !== "default"
) {
// In strict harmony modules we only support the default export
return [
new HarmonyLinkingError(
`Can't import the named export '${this._id}' from non EcmaScript module (only default export is available)`
)
];
}
return;
}
if (!this._id) {
return;
}
if (importedModule.isProvided(this._id) !== false) {
// It's provided or we are not sure
return;
}
// We are sure that it's not provided
const idIsNotNameMessage =
this._id !== this.name ? ` (imported as '${this.name}')` : "";
const errorMessage = `"export '${this._id}'${idIsNotNameMessage} was not found in '${this.userRequest}'`;
return [new HarmonyLinkingError(errorMessage)];
}
// implement this method to allow the occurrence order plugin to count correctly
getNumberOfIdOccurrences() {
return 0;
}
updateHash(hash) {
super.updateHash(hash);
const importedModule = this._module;
hash.update((importedModule && this._id) + "");
hash.update(
(importedModule && this._id && importedModule.isUsed(this._id)) + ""
);
hash.update(
(importedModule &&
(!importedModule.buildMeta || importedModule.buildMeta.exportsType)) +
""
);
hash.update(
(importedModule &&
importedModule.used + JSON.stringify(importedModule.usedExports)) + ""
);
}
disconnect() {
super.disconnect();
this.redirectedId = undefined;
}
}
HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependencyTemplate extends HarmonyImportDependency.Template {
apply(dep, source, runtime) {
super.apply(dep, source, runtime);
const content = this.getContent(dep, runtime);
source.replace(dep.range[0], dep.range[1] - 1, content);
}
getContent(dep, runtime) {
const exportExpr = runtime.exportFromImport({
module: dep._module,
request: dep.request,
exportName: dep._id,
originModule: dep.originModule,
asiSafe: dep.shorthand,
isCall: dep.call,
callContext: !dep.directImport,
importVar: dep.getImportVar()
});
return dep.shorthand ? `${dep.name}: ${exportExpr}` : exportExpr;
}
};
module.exports = HarmonyImportSpecifierDependency;

View file

@ -0,0 +1,60 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
class HarmonyInitDependency extends NullDependency {
constructor(originModule) {
super();
this.originModule = originModule;
}
get type() {
return "harmony init";
}
}
module.exports = HarmonyInitDependency;
HarmonyInitDependency.Template = class HarmonyInitDependencyTemplate {
apply(dep, source, runtime, dependencyTemplates) {
const module = dep.originModule;
const list = [];
for (const dependency of module.dependencies) {
const template = dependencyTemplates.get(dependency.constructor);
if (
template &&
typeof template.harmonyInit === "function" &&
typeof template.getHarmonyInitOrder === "function"
) {
const order = template.getHarmonyInitOrder(dependency);
if (!isNaN(order)) {
list.push({
order,
listOrder: list.length,
dependency,
template
});
}
}
}
list.sort((a, b) => {
const x = a.order - b.order;
if (x) return x;
return a.listOrder - b.listOrder;
});
for (const item of list) {
item.template.harmonyInit(
item.dependency,
source,
runtime,
dependencyTemplates
);
}
}
};

View file

@ -0,0 +1,143 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const HarmonyCompatibilityDependency = require("./HarmonyCompatibilityDependency");
const HarmonyInitDependency = require("./HarmonyInitDependency");
const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency");
const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
const HarmonyExportHeaderDependency = require("./HarmonyExportHeaderDependency");
const HarmonyExportExpressionDependency = require("./HarmonyExportExpressionDependency");
const HarmonyExportSpecifierDependency = require("./HarmonyExportSpecifierDependency");
const HarmonyExportImportedSpecifierDependency = require("./HarmonyExportImportedSpecifierDependency");
const HarmonyAcceptDependency = require("./HarmonyAcceptDependency");
const HarmonyAcceptImportDependency = require("./HarmonyAcceptImportDependency");
const NullFactory = require("../NullFactory");
const HarmonyDetectionParserPlugin = require("./HarmonyDetectionParserPlugin");
const HarmonyImportDependencyParserPlugin = require("./HarmonyImportDependencyParserPlugin");
const HarmonyExportDependencyParserPlugin = require("./HarmonyExportDependencyParserPlugin");
const HarmonyTopLevelThisParserPlugin = require("./HarmonyTopLevelThisParserPlugin");
class HarmonyModulesPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
compiler.hooks.compilation.tap(
"HarmonyModulesPlugin",
(compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(
HarmonyCompatibilityDependency,
new NullFactory()
);
compilation.dependencyTemplates.set(
HarmonyCompatibilityDependency,
new HarmonyCompatibilityDependency.Template()
);
compilation.dependencyFactories.set(
HarmonyInitDependency,
new NullFactory()
);
compilation.dependencyTemplates.set(
HarmonyInitDependency,
new HarmonyInitDependency.Template()
);
compilation.dependencyFactories.set(
HarmonyImportSideEffectDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
HarmonyImportSideEffectDependency,
new HarmonyImportSideEffectDependency.Template()
);
compilation.dependencyFactories.set(
HarmonyImportSpecifierDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
HarmonyImportSpecifierDependency,
new HarmonyImportSpecifierDependency.Template()
);
compilation.dependencyFactories.set(
HarmonyExportHeaderDependency,
new NullFactory()
);
compilation.dependencyTemplates.set(
HarmonyExportHeaderDependency,
new HarmonyExportHeaderDependency.Template()
);
compilation.dependencyFactories.set(
HarmonyExportExpressionDependency,
new NullFactory()
);
compilation.dependencyTemplates.set(
HarmonyExportExpressionDependency,
new HarmonyExportExpressionDependency.Template()
);
compilation.dependencyFactories.set(
HarmonyExportSpecifierDependency,
new NullFactory()
);
compilation.dependencyTemplates.set(
HarmonyExportSpecifierDependency,
new HarmonyExportSpecifierDependency.Template()
);
compilation.dependencyFactories.set(
HarmonyExportImportedSpecifierDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
HarmonyExportImportedSpecifierDependency,
new HarmonyExportImportedSpecifierDependency.Template()
);
compilation.dependencyFactories.set(
HarmonyAcceptDependency,
new NullFactory()
);
compilation.dependencyTemplates.set(
HarmonyAcceptDependency,
new HarmonyAcceptDependency.Template()
);
compilation.dependencyFactories.set(
HarmonyAcceptImportDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
HarmonyAcceptImportDependency,
new HarmonyAcceptImportDependency.Template()
);
const handler = (parser, parserOptions) => {
if (parserOptions.harmony !== undefined && !parserOptions.harmony)
return;
new HarmonyDetectionParserPlugin().apply(parser);
new HarmonyImportDependencyParserPlugin(this.options).apply(parser);
new HarmonyExportDependencyParserPlugin(this.options).apply(parser);
new HarmonyTopLevelThisParserPlugin().apply(parser);
};
normalModuleFactory.hooks.parser
.for("javascript/auto")
.tap("HarmonyModulesPlugin", handler);
normalModuleFactory.hooks.parser
.for("javascript/esm")
.tap("HarmonyModulesPlugin", handler);
}
);
}
}
module.exports = HarmonyModulesPlugin;

View file

@ -0,0 +1,26 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Florent Cailhol @ooflorent
*/
"use strict";
const ConstDependency = require("./ConstDependency");
class HarmonyTopLevelThisParserPlugin {
apply(parser) {
parser.hooks.expression
.for("this")
.tap("HarmonyTopLevelThisParserPlugin", node => {
if (!parser.scope.topLevelScope) return;
const module = parser.state.module;
const isHarmony = !!(module.buildMeta && module.buildMeta.exportsType);
if (isHarmony) {
const dep = new ConstDependency("undefined", node.range, false);
dep.loc = node.loc;
parser.state.current.addDependency(dep);
}
});
}
}
module.exports = HarmonyTopLevelThisParserPlugin;

View file

@ -0,0 +1,23 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ContextDependency = require("./ContextDependency");
const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall");
class ImportContextDependency extends ContextDependency {
constructor(options, range, valueRange) {
super(options);
this.range = range;
this.valueRange = valueRange;
}
get type() {
return `import() context ${this.options.mode}`;
}
}
ImportContextDependency.Template = ContextDependencyTemplateAsRequireCall;
module.exports = ImportContextDependency;

View file

@ -0,0 +1,18 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const AsyncDependenciesBlock = require("../AsyncDependenciesBlock");
const ImportDependency = require("./ImportDependency");
module.exports = class ImportDependenciesBlock extends AsyncDependenciesBlock {
// TODO webpack 5 reorganize arguments
constructor(request, range, groupOptions, module, loc, originModule) {
super(groupOptions, module, loc, request);
this.range = range;
const dep = new ImportDependency(request, originModule, this);
dep.loc = loc;
this.addDependency(dep);
}
};

View file

@ -0,0 +1,34 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
class ImportDependency extends ModuleDependency {
constructor(request, originModule, block) {
super(request);
this.originModule = originModule;
this.block = block;
}
get type() {
return "import()";
}
}
ImportDependency.Template = class ImportDependencyTemplate {
apply(dep, source, runtime) {
const content = runtime.moduleNamespacePromise({
block: dep.block,
module: dep.module,
request: dep.request,
strict: dep.originModule.buildMeta.strictHarmonyModule,
message: "import()"
});
source.replace(dep.block.range[0], dep.block.range[1] - 1, content);
}
};
module.exports = ImportDependency;

View file

@ -0,0 +1,32 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
class ImportEagerDependency extends ModuleDependency {
constructor(request, originModule, range) {
super(request);
this.originModule = originModule;
this.range = range;
}
get type() {
return "import() eager";
}
}
ImportEagerDependency.Template = class ImportEagerDependencyTemplate {
apply(dep, source, runtime) {
const content = runtime.moduleNamespacePromise({
module: dep.module,
request: dep.request,
strict: dep.originModule.buildMeta.strictHarmonyModule,
message: "import() eager"
});
source.replace(dep.range[0], dep.range[1] - 1, content);
}
};
module.exports = ImportEagerDependency;

View file

@ -0,0 +1,248 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ImportContextDependency = require("./ImportContextDependency");
const ImportWeakDependency = require("./ImportWeakDependency");
const ImportDependenciesBlock = require("./ImportDependenciesBlock");
const ImportEagerDependency = require("./ImportEagerDependency");
const ContextDependencyHelpers = require("./ContextDependencyHelpers");
const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
const CommentCompilationWarning = require("../CommentCompilationWarning");
class ImportParserPlugin {
constructor(options) {
this.options = options;
}
apply(parser) {
parser.hooks.importCall.tap("ImportParserPlugin", expr => {
if (expr.arguments.length !== 1) {
throw new Error(
"Incorrect number of arguments provided to 'import(module: string) -> Promise'."
);
}
const param = parser.evaluateExpression(expr.arguments[0]);
let chunkName = null;
let mode = "lazy";
let include = null;
let exclude = null;
const groupOptions = {};
const {
options: importOptions,
errors: commentErrors
} = parser.parseCommentOptions(expr.range);
if (commentErrors) {
for (const e of commentErrors) {
const { comment } = e;
parser.state.module.warnings.push(
new CommentCompilationWarning(
`Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
parser.state.module,
comment.loc
)
);
}
}
if (importOptions) {
if (importOptions.webpackIgnore !== undefined) {
if (typeof importOptions.webpackIgnore !== "boolean") {
parser.state.module.warnings.push(
new UnsupportedFeatureWarning(
parser.state.module,
`\`webpackIgnore\` expected a boolean, but received: ${importOptions.webpackIgnore}.`,
expr.loc
)
);
} else {
// Do not instrument `import()` if `webpackIgnore` is `true`
if (importOptions.webpackIgnore) {
return false;
}
}
}
if (importOptions.webpackChunkName !== undefined) {
if (typeof importOptions.webpackChunkName !== "string") {
parser.state.module.warnings.push(
new UnsupportedFeatureWarning(
parser.state.module,
`\`webpackChunkName\` expected a string, but received: ${importOptions.webpackChunkName}.`,
expr.loc
)
);
} else {
chunkName = importOptions.webpackChunkName;
}
}
if (importOptions.webpackMode !== undefined) {
if (typeof importOptions.webpackMode !== "string") {
parser.state.module.warnings.push(
new UnsupportedFeatureWarning(
parser.state.module,
`\`webpackMode\` expected a string, but received: ${importOptions.webpackMode}.`,
expr.loc
)
);
} else {
mode = importOptions.webpackMode;
}
}
if (importOptions.webpackPrefetch !== undefined) {
if (importOptions.webpackPrefetch === true) {
groupOptions.prefetchOrder = 0;
} else if (typeof importOptions.webpackPrefetch === "number") {
groupOptions.prefetchOrder = importOptions.webpackPrefetch;
} else {
parser.state.module.warnings.push(
new UnsupportedFeatureWarning(
parser.state.module,
`\`webpackPrefetch\` expected true or a number, but received: ${importOptions.webpackPrefetch}.`,
expr.loc
)
);
}
}
if (importOptions.webpackPreload !== undefined) {
if (importOptions.webpackPreload === true) {
groupOptions.preloadOrder = 0;
} else if (typeof importOptions.webpackPreload === "number") {
groupOptions.preloadOrder = importOptions.webpackPreload;
} else {
parser.state.module.warnings.push(
new UnsupportedFeatureWarning(
parser.state.module,
`\`webpackPreload\` expected true or a number, but received: ${importOptions.webpackPreload}.`,
expr.loc
)
);
}
}
if (importOptions.webpackInclude !== undefined) {
if (
!importOptions.webpackInclude ||
importOptions.webpackInclude.constructor.name !== "RegExp"
) {
parser.state.module.warnings.push(
new UnsupportedFeatureWarning(
parser.state.module,
`\`webpackInclude\` expected a regular expression, but received: ${importOptions.webpackInclude}.`,
expr.loc
)
);
} else {
include = new RegExp(importOptions.webpackInclude);
}
}
if (importOptions.webpackExclude !== undefined) {
if (
!importOptions.webpackExclude ||
importOptions.webpackExclude.constructor.name !== "RegExp"
) {
parser.state.module.warnings.push(
new UnsupportedFeatureWarning(
parser.state.module,
`\`webpackExclude\` expected a regular expression, but received: ${importOptions.webpackExclude}.`,
expr.loc
)
);
} else {
exclude = new RegExp(importOptions.webpackExclude);
}
}
}
if (param.isString()) {
if (mode !== "lazy" && mode !== "eager" && mode !== "weak") {
parser.state.module.warnings.push(
new UnsupportedFeatureWarning(
parser.state.module,
`\`webpackMode\` expected 'lazy', 'eager' or 'weak', but received: ${mode}.`,
expr.loc
)
);
}
if (mode === "eager") {
const dep = new ImportEagerDependency(
param.string,
parser.state.module,
expr.range
);
parser.state.current.addDependency(dep);
} else if (mode === "weak") {
const dep = new ImportWeakDependency(
param.string,
parser.state.module,
expr.range
);
parser.state.current.addDependency(dep);
} else {
const depBlock = new ImportDependenciesBlock(
param.string,
expr.range,
Object.assign(groupOptions, {
name: chunkName
}),
parser.state.module,
expr.loc,
parser.state.module
);
parser.state.current.addBlock(depBlock);
}
return true;
} else {
if (
mode !== "lazy" &&
mode !== "lazy-once" &&
mode !== "eager" &&
mode !== "weak"
) {
parser.state.module.warnings.push(
new UnsupportedFeatureWarning(
parser.state.module,
`\`webpackMode\` expected 'lazy', 'lazy-once', 'eager' or 'weak', but received: ${mode}.`,
expr.loc
)
);
mode = "lazy";
}
if (mode === "weak") {
mode = "async-weak";
}
const dep = ContextDependencyHelpers.create(
ImportContextDependency,
expr.range,
param,
expr,
this.options,
{
chunkName,
groupOptions,
include,
exclude,
mode,
namespaceObject: parser.state.module.buildMeta.strictHarmonyModule
? "strict"
: true
},
parser
);
if (!dep) return;
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
}
});
}
}
module.exports = ImportParserPlugin;

View file

@ -0,0 +1,79 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ImportDependency = require("./ImportDependency");
const ImportEagerDependency = require("./ImportEagerDependency");
const ImportWeakDependency = require("./ImportWeakDependency");
const ImportContextDependency = require("./ImportContextDependency");
const ImportParserPlugin = require("./ImportParserPlugin");
class ImportPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
const options = this.options;
compiler.hooks.compilation.tap(
"ImportPlugin",
(compilation, { contextModuleFactory, normalModuleFactory }) => {
compilation.dependencyFactories.set(
ImportDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
ImportDependency,
new ImportDependency.Template()
);
compilation.dependencyFactories.set(
ImportEagerDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
ImportEagerDependency,
new ImportEagerDependency.Template()
);
compilation.dependencyFactories.set(
ImportWeakDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
ImportWeakDependency,
new ImportWeakDependency.Template()
);
compilation.dependencyFactories.set(
ImportContextDependency,
contextModuleFactory
);
compilation.dependencyTemplates.set(
ImportContextDependency,
new ImportContextDependency.Template()
);
const handler = (parser, parserOptions) => {
if (parserOptions.import !== undefined && !parserOptions.import)
return;
new ImportParserPlugin(options).apply(parser);
};
normalModuleFactory.hooks.parser
.for("javascript/auto")
.tap("ImportPlugin", handler);
normalModuleFactory.hooks.parser
.for("javascript/dynamic")
.tap("ImportPlugin", handler);
normalModuleFactory.hooks.parser
.for("javascript/esm")
.tap("ImportPlugin", handler);
}
);
}
}
module.exports = ImportPlugin;

View file

@ -0,0 +1,34 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
class ImportWeakDependency extends ModuleDependency {
constructor(request, originModule, range) {
super(request);
this.originModule = originModule;
this.range = range;
this.weak = true;
}
get type() {
return "import() weak";
}
}
ImportWeakDependency.Template = class ImportDependencyTemplate {
apply(dep, source, runtime) {
const content = runtime.moduleNamespacePromise({
module: dep.module,
request: dep.request,
strict: dep.originModule.buildMeta.strictHarmonyModule,
message: "import() weak",
weak: true
});
source.replace(dep.range[0], dep.range[1] - 1, content);
}
};
module.exports = ImportWeakDependency;

View file

@ -0,0 +1,26 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
class JsonExportsDependency extends NullDependency {
constructor(exports) {
super();
this.exports = exports;
}
get type() {
return "json exports";
}
getExports() {
return {
exports: this.exports,
dependencies: undefined
};
}
}
module.exports = JsonExportsDependency;

View file

@ -0,0 +1,21 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
class LoaderDependency extends ModuleDependency {
/**
* @param {string} request request string
*/
constructor(request) {
super(request);
}
get type() {
return "loader";
}
}
module.exports = LoaderDependency;

View file

@ -0,0 +1,115 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const LoaderDependency = require("./LoaderDependency");
const NormalModule = require("../NormalModule");
/** @typedef {import("../Module")} Module */
/**
* @callback LoadModuleCallback
* @param {Error=} err error object
* @param {string=} source source code
* @param {object=} map source map
* @param {Module=} module loaded module if successful
*/
class LoaderPlugin {
apply(compiler) {
compiler.hooks.compilation.tap(
"LoaderPlugin",
(compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(
LoaderDependency,
normalModuleFactory
);
}
);
compiler.hooks.compilation.tap("LoaderPlugin", compilation => {
compilation.hooks.normalModuleLoader.tap(
"LoaderPlugin",
(loaderContext, module) => {
/**
* @param {string} request the request string to load the module from
* @param {LoadModuleCallback} callback callback returning the loaded module or error
* @returns {void}
*/
loaderContext.loadModule = (request, callback) => {
const dep = new LoaderDependency(request);
dep.loc = {
name: request
};
const factory = compilation.dependencyFactories.get(
dep.constructor
);
if (factory === undefined) {
return callback(
new Error(
`No module factory available for dependency type: ${dep.constructor.name}`
)
);
}
compilation.semaphore.release();
compilation.addModuleDependencies(
module,
[
{
factory,
dependencies: [dep]
}
],
true,
"lm",
true,
err => {
compilation.semaphore.acquire(() => {
if (err) {
return callback(err);
}
if (!dep.module) {
return callback(new Error("Cannot load the module"));
}
// TODO consider removing this in webpack 5
if (dep.module instanceof NormalModule && dep.module.error) {
return callback(dep.module.error);
}
if (!dep.module._source) {
throw new Error(
"The module created for a LoaderDependency must have a property _source"
);
}
let source, map;
const moduleSource = dep.module._source;
if (moduleSource.sourceAndMap) {
const sourceAndMap = moduleSource.sourceAndMap();
map = sourceAndMap.map;
source = sourceAndMap.source;
} else {
map = moduleSource.map();
source = moduleSource.source();
}
if (dep.module.buildInfo.fileDependencies) {
for (const d of dep.module.buildInfo.fileDependencies) {
loaderContext.addDependency(d);
}
}
if (dep.module.buildInfo.contextDependencies) {
for (const d of dep.module.buildInfo.contextDependencies) {
loaderContext.addContextDependency(d);
}
}
return callback(null, source, map, dep.module);
});
}
);
};
}
);
});
}
}
module.exports = LoaderPlugin;

View file

@ -0,0 +1,23 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
class LocalModule {
constructor(module, name, idx) {
this.module = module;
this.name = name;
this.idx = idx;
this.used = false;
}
flagUsed() {
this.used = true;
}
variableName() {
return "__WEBPACK_LOCAL_MODULE_" + this.idx + "__";
}
}
module.exports = LocalModule;

View file

@ -0,0 +1,28 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
class LocalModuleDependency extends NullDependency {
constructor(localModule, range, callNew) {
super();
localModule.flagUsed();
this.localModule = localModule;
this.range = range;
this.callNew = callNew;
}
}
LocalModuleDependency.Template = class LocalModuleDependencyTemplate {
apply(dep, source) {
if (!dep.range) return;
const moduleInstance = dep.callNew
? `new (function () { return ${dep.localModule.variableName()}; })()`
: dep.localModule.variableName();
source.replace(dep.range[0], dep.range[1] - 1, moduleInstance);
}
};
module.exports = LocalModuleDependency;

View file

@ -0,0 +1,52 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const LocalModule = require("./LocalModule");
const LocalModulesHelpers = exports;
const lookup = (parent, mod) => {
if (mod.charAt(0) !== ".") return mod;
var path = parent.split("/");
var segs = mod.split("/");
path.pop();
for (let i = 0; i < segs.length; i++) {
const seg = segs[i];
if (seg === "..") {
path.pop();
} else if (seg !== ".") {
path.push(seg);
}
}
return path.join("/");
};
LocalModulesHelpers.addLocalModule = (state, name) => {
if (!state.localModules) {
state.localModules = [];
}
const m = new LocalModule(state.module, name, state.localModules.length);
state.localModules.push(m);
return m;
};
LocalModulesHelpers.getLocalModule = (state, name, namedModule) => {
if (!state.localModules) return null;
if (namedModule) {
// resolve dependency name relative to the defining named module
name = lookup(namedModule, name);
}
for (let i = 0; i < state.localModules.length; i++) {
if (state.localModules[i].name === name) {
return state.localModules[i];
}
}
return null;
};
module.exports = LocalModulesHelpers;

View file

@ -0,0 +1,23 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const Dependency = require("../Dependency");
class ModuleDependency extends Dependency {
/**
* @param {string} request request path which needs resolving
*/
constructor(request) {
super();
this.request = request;
this.userRequest = request;
}
getResourceIdentifier() {
return `module${this.request}`;
}
}
module.exports = ModuleDependency;

View file

@ -0,0 +1,17 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
class ModuleDependencyTemplateAsId {
apply(dep, source, runtime) {
if (!dep.range) return;
const content = runtime.moduleId({
module: dep.module,
request: dep.request
});
source.replace(dep.range[0], dep.range[1] - 1, content);
}
}
module.exports = ModuleDependencyTemplateAsId;

View file

@ -0,0 +1,17 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
class ModuleDependencyTemplateAsRequireId {
apply(dep, source, runtime) {
if (!dep.range) return;
const content = runtime.moduleExports({
module: dep.module,
request: dep.request
});
source.replace(dep.range[0], dep.range[1] - 1, content);
}
}
module.exports = ModuleDependencyTemplateAsRequireId;

View file

@ -0,0 +1,23 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
const ModuleDependencyTemplateAsId = require("./ModuleDependencyTemplateAsId");
class ModuleHotAcceptDependency extends ModuleDependency {
constructor(request, range) {
super(request);
this.range = range;
this.weak = true;
}
get type() {
return "module.hot.accept";
}
}
ModuleHotAcceptDependency.Template = ModuleDependencyTemplateAsId;
module.exports = ModuleHotAcceptDependency;

View file

@ -0,0 +1,23 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
const ModuleDependencyTemplateAsId = require("./ModuleDependencyTemplateAsId");
class ModuleHotDeclineDependency extends ModuleDependency {
constructor(request, range) {
super(request);
this.range = range;
this.weak = true;
}
get type() {
return "module.hot.decline";
}
}
ModuleHotDeclineDependency.Template = ModuleDependencyTemplateAsId;
module.exports = ModuleHotDeclineDependency;

View file

@ -0,0 +1,25 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/** @typedef {import("./SingleEntryDependency")} SingleEntryDependency */
const Dependency = require("../Dependency");
class MultiEntryDependency extends Dependency {
/**
* @param {SingleEntryDependency[]} dependencies an array of SingleEntryDependencies
* @param {string} name entry name
*/
constructor(dependencies, name) {
super();
this.dependencies = dependencies;
this.name = name;
}
get type() {
return "multi entry";
}
}
module.exports = MultiEntryDependency;

View file

@ -0,0 +1,20 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const Dependency = require("../Dependency");
class NullDependency extends Dependency {
get type() {
return "null";
}
updateHash() {}
}
NullDependency.Template = class NullDependencyTemplate {
apply() {}
};
module.exports = NullDependency;

View file

@ -0,0 +1,18 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
class PrefetchDependency extends ModuleDependency {
constructor(request) {
super(request);
}
get type() {
return "prefetch";
}
}
module.exports = PrefetchDependency;

View file

@ -0,0 +1,22 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ContextDependency = require("./ContextDependency");
const ModuleDependencyTemplateAsRequireId = require("./ModuleDependencyTemplateAsRequireId");
class RequireContextDependency extends ContextDependency {
constructor(options, range) {
super(options);
this.range = range;
}
get type() {
return "require.context";
}
}
RequireContextDependency.Template = ModuleDependencyTemplateAsRequireId;
module.exports = RequireContextDependency;

View file

@ -0,0 +1,56 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const RequireContextDependency = require("./RequireContextDependency");
module.exports = class RequireContextDependencyParserPlugin {
apply(parser) {
parser.hooks.call
.for("require.context")
.tap("RequireContextDependencyParserPlugin", expr => {
let regExp = /^\.\/.*$/;
let recursive = true;
let mode = "sync";
switch (expr.arguments.length) {
case 4: {
const modeExpr = parser.evaluateExpression(expr.arguments[3]);
if (!modeExpr.isString()) return;
mode = modeExpr.string;
}
// falls through
case 3: {
const regExpExpr = parser.evaluateExpression(expr.arguments[2]);
if (!regExpExpr.isRegExp()) return;
regExp = regExpExpr.regExp;
}
// falls through
case 2: {
const recursiveExpr = parser.evaluateExpression(expr.arguments[1]);
if (!recursiveExpr.isBoolean()) return;
recursive = recursiveExpr.bool;
}
// falls through
case 1: {
const requestExpr = parser.evaluateExpression(expr.arguments[0]);
if (!requestExpr.isString()) return;
const dep = new RequireContextDependency(
{
request: requestExpr.string,
recursive,
regExp,
mode
},
expr.range
);
dep.loc = expr.loc;
dep.optional = parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
}
}
});
}
};

View file

@ -0,0 +1,143 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const RequireContextDependency = require("./RequireContextDependency");
const ContextElementDependency = require("./ContextElementDependency");
const RequireContextDependencyParserPlugin = require("./RequireContextDependencyParserPlugin");
class RequireContextPlugin {
constructor(modulesDirectories, extensions, mainFiles) {
if (!Array.isArray(modulesDirectories)) {
throw new Error("modulesDirectories must be an array");
}
if (!Array.isArray(extensions)) {
throw new Error("extensions must be an array");
}
this.modulesDirectories = modulesDirectories;
this.extensions = extensions;
this.mainFiles = mainFiles;
}
apply(compiler) {
compiler.hooks.compilation.tap(
"RequireContextPlugin",
(compilation, { contextModuleFactory, normalModuleFactory }) => {
compilation.dependencyFactories.set(
RequireContextDependency,
contextModuleFactory
);
compilation.dependencyTemplates.set(
RequireContextDependency,
new RequireContextDependency.Template()
);
compilation.dependencyFactories.set(
ContextElementDependency,
normalModuleFactory
);
const handler = (parser, parserOptions) => {
if (
parserOptions.requireContext !== undefined &&
!parserOptions.requireContext
)
return;
new RequireContextDependencyParserPlugin().apply(parser);
};
normalModuleFactory.hooks.parser
.for("javascript/auto")
.tap("RequireContextPlugin", handler);
normalModuleFactory.hooks.parser
.for("javascript/dynamic")
.tap("RequireContextPlugin", handler);
contextModuleFactory.hooks.alternatives.tap(
"RequireContextPlugin",
items => {
if (items.length === 0) return items;
return items
.map(obj => {
return this.extensions
.filter(ext => {
const l = obj.request.length;
return (
l > ext.length &&
obj.request.substr(l - ext.length, l) === ext
);
})
.map(ext => {
const l = obj.request.length;
return {
context: obj.context,
request: obj.request.substr(0, l - ext.length)
};
})
.concat(obj);
})
.reduce((a, b) => a.concat(b), []);
}
);
contextModuleFactory.hooks.alternatives.tap(
"RequireContextPlugin",
items => {
if (items.length === 0) return items;
return items
.map(obj => {
return this.mainFiles
.filter(mainFile => {
const l = obj.request.length;
return (
l > mainFile.length + 1 &&
obj.request.substr(l - mainFile.length - 1, l) ===
"/" + mainFile
);
})
.map(mainFile => {
const l = obj.request.length;
return [
{
context: obj.context,
request: obj.request.substr(0, l - mainFile.length)
},
{
context: obj.context,
request: obj.request.substr(0, l - mainFile.length - 1)
}
];
})
.reduce((a, b) => a.concat(b), [])
.concat(obj);
})
.reduce((a, b) => a.concat(b), []);
}
);
contextModuleFactory.hooks.alternatives.tap(
"RequireContextPlugin",
items => {
if (items.length === 0) return items;
return items.map(obj => {
for (let i = 0; i < this.modulesDirectories.length; i++) {
const dir = this.modulesDirectories[i];
const idx = obj.request.indexOf("./" + dir + "/");
if (idx === 0) {
obj.request = obj.request.slice(dir.length + 3);
break;
}
}
return obj;
});
}
);
}
);
}
}
module.exports = RequireContextPlugin;

View file

@ -0,0 +1,33 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const AsyncDependenciesBlock = require("../AsyncDependenciesBlock");
const RequireEnsureDependency = require("./RequireEnsureDependency");
module.exports = class RequireEnsureDependenciesBlock extends AsyncDependenciesBlock {
constructor(
expr,
successExpression,
errorExpression,
chunkName,
chunkNameRange,
module,
loc
) {
super(chunkName, module, loc, null);
this.expr = expr;
const successBodyRange =
successExpression &&
successExpression.body &&
successExpression.body.range;
if (successBodyRange) {
this.range = [successBodyRange[0] + 1, successBodyRange[1] - 1];
}
this.chunkNameRange = chunkNameRange;
const dep = new RequireEnsureDependency(this);
dep.loc = loc;
this.addDependency(dep);
}
};

View file

@ -0,0 +1,116 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const RequireEnsureDependenciesBlock = require("./RequireEnsureDependenciesBlock");
const RequireEnsureItemDependency = require("./RequireEnsureItemDependency");
const getFunctionExpression = require("./getFunctionExpression");
module.exports = class RequireEnsureDependenciesBlockParserPlugin {
apply(parser) {
parser.hooks.call
.for("require.ensure")
.tap("RequireEnsureDependenciesBlockParserPlugin", expr => {
let chunkName = null;
let chunkNameRange = null;
let errorExpressionArg = null;
let errorExpression = null;
switch (expr.arguments.length) {
case 4: {
const chunkNameExpr = parser.evaluateExpression(expr.arguments[3]);
if (!chunkNameExpr.isString()) return;
chunkNameRange = chunkNameExpr.range;
chunkName = chunkNameExpr.string;
}
// falls through
case 3: {
errorExpressionArg = expr.arguments[2];
errorExpression = getFunctionExpression(errorExpressionArg);
if (!errorExpression && !chunkName) {
const chunkNameExpr = parser.evaluateExpression(
expr.arguments[2]
);
if (!chunkNameExpr.isString()) return;
chunkNameRange = chunkNameExpr.range;
chunkName = chunkNameExpr.string;
}
}
// falls through
case 2: {
const dependenciesExpr = parser.evaluateExpression(
expr.arguments[0]
);
const dependenciesItems = dependenciesExpr.isArray()
? dependenciesExpr.items
: [dependenciesExpr];
const successExpressionArg = expr.arguments[1];
const successExpression = getFunctionExpression(
successExpressionArg
);
if (successExpression) {
parser.walkExpressions(successExpression.expressions);
}
if (errorExpression) {
parser.walkExpressions(errorExpression.expressions);
}
const dep = new RequireEnsureDependenciesBlock(
expr,
successExpression ? successExpression.fn : successExpressionArg,
errorExpression ? errorExpression.fn : errorExpressionArg,
chunkName,
chunkNameRange,
parser.state.module,
expr.loc
);
const old = parser.state.current;
parser.state.current = dep;
try {
let failed = false;
parser.inScope([], () => {
for (const ee of dependenciesItems) {
if (ee.isString()) {
const edep = new RequireEnsureItemDependency(ee.string);
edep.loc = dep.loc;
dep.addDependency(edep);
} else {
failed = true;
}
}
});
if (failed) {
return;
}
if (successExpression) {
if (successExpression.fn.body.type === "BlockStatement") {
parser.walkStatement(successExpression.fn.body);
} else {
parser.walkExpression(successExpression.fn.body);
}
}
old.addBlock(dep);
} finally {
parser.state.current = old;
}
if (!successExpression) {
parser.walkExpression(successExpressionArg);
}
if (errorExpression) {
if (errorExpression.fn.body.type === "BlockStatement") {
parser.walkStatement(errorExpression.fn.body);
} else {
parser.walkExpression(errorExpression.fn.body);
}
} else if (errorExpressionArg) {
parser.walkExpression(errorExpressionArg);
}
return true;
}
}
});
}
};

View file

@ -0,0 +1,58 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
class RequireEnsureDependency extends NullDependency {
constructor(block) {
super();
this.block = block;
}
get type() {
return "require.ensure";
}
}
RequireEnsureDependency.Template = class RequireEnsureDependencyTemplate {
apply(dep, source, runtime) {
const depBlock = dep.block;
const promise = runtime.blockPromise({
block: depBlock,
message: "require.ensure"
});
const errorCallbackExists =
depBlock.expr.arguments.length === 4 ||
(!depBlock.chunkName && depBlock.expr.arguments.length === 3);
const startBlock = `${promise}.then((`;
const middleBlock = ").bind(null, __webpack_require__)).catch(";
const endBlock = `).bind(null, __webpack_require__)).catch(${runtime.onError()})`;
source.replace(
depBlock.expr.range[0],
depBlock.expr.arguments[1].range[0] - 1,
startBlock
);
if (errorCallbackExists) {
source.replace(
depBlock.expr.arguments[1].range[1],
depBlock.expr.arguments[2].range[0] - 1,
middleBlock
);
source.replace(
depBlock.expr.arguments[2].range[1],
depBlock.expr.range[1] - 1,
")"
);
} else {
source.replace(
depBlock.expr.arguments[1].range[1],
depBlock.expr.range[1] - 1,
endBlock
);
}
}
};
module.exports = RequireEnsureDependency;

View file

@ -0,0 +1,21 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
const NullDependency = require("./NullDependency");
class RequireEnsureItemDependency extends ModuleDependency {
constructor(request) {
super(request);
}
get type() {
return "require.ensure item";
}
}
RequireEnsureItemDependency.Template = NullDependency.Template;
module.exports = RequireEnsureItemDependency;

View file

@ -0,0 +1,74 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const RequireEnsureItemDependency = require("./RequireEnsureItemDependency");
const RequireEnsureDependency = require("./RequireEnsureDependency");
const NullFactory = require("../NullFactory");
const RequireEnsureDependenciesBlockParserPlugin = require("./RequireEnsureDependenciesBlockParserPlugin");
const ParserHelpers = require("../ParserHelpers");
class RequireEnsurePlugin {
apply(compiler) {
compiler.hooks.compilation.tap(
"RequireEnsurePlugin",
(compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(
RequireEnsureItemDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
RequireEnsureItemDependency,
new RequireEnsureItemDependency.Template()
);
compilation.dependencyFactories.set(
RequireEnsureDependency,
new NullFactory()
);
compilation.dependencyTemplates.set(
RequireEnsureDependency,
new RequireEnsureDependency.Template()
);
const handler = (parser, parserOptions) => {
if (
parserOptions.requireEnsure !== undefined &&
!parserOptions.requireEnsure
)
return;
new RequireEnsureDependenciesBlockParserPlugin().apply(parser);
parser.hooks.evaluateTypeof
.for("require.ensure")
.tap(
"RequireEnsurePlugin",
ParserHelpers.evaluateToString("function")
);
parser.hooks.typeof
.for("require.ensure")
.tap(
"RequireEnsurePlugin",
ParserHelpers.toConstantDependency(
parser,
JSON.stringify("function")
)
);
};
normalModuleFactory.hooks.parser
.for("javascript/auto")
.tap("RequireEnsurePlugin", handler);
normalModuleFactory.hooks.parser
.for("javascript/dynamic")
.tap("RequireEnsurePlugin", handler);
}
);
}
}
module.exports = RequireEnsurePlugin;

View file

@ -0,0 +1,26 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
class RequireHeaderDependency extends NullDependency {
constructor(range) {
super();
if (!Array.isArray(range)) throw new Error("range must be valid");
this.range = range;
}
}
RequireHeaderDependency.Template = class RequireHeaderDependencyTemplate {
apply(dep, source) {
source.replace(dep.range[0], dep.range[1] - 1, "__webpack_require__");
}
applyAsTemplateArgument(name, dep, source) {
source.replace(dep.range[0], dep.range[1] - 1, "require");
}
};
module.exports = RequireHeaderDependency;

View file

@ -0,0 +1,39 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const DependencyReference = require("./DependencyReference");
const ModuleDependency = require("./ModuleDependency");
const Template = require("../Template");
class RequireIncludeDependency extends ModuleDependency {
constructor(request, range) {
super(request);
this.range = range;
}
getReference() {
if (!this.module) return null;
// This doesn't use any export
return new DependencyReference(this.module, [], false);
}
get type() {
return "require.include";
}
}
RequireIncludeDependency.Template = class RequireIncludeDependencyTemplate {
apply(dep, source, runtime) {
const comment = runtime.outputOptions.pathinfo
? Template.toComment(
`require.include ${runtime.requestShortener.shorten(dep.request)}`
)
: "";
source.replace(dep.range[0], dep.range[1] - 1, `undefined${comment}`);
}
};
module.exports = RequireIncludeDependency;

View file

@ -0,0 +1,23 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const RequireIncludeDependency = require("./RequireIncludeDependency");
module.exports = class RequireIncludeDependencyParserPlugin {
apply(parser) {
parser.hooks.call
.for("require.include")
.tap("RequireIncludeDependencyParserPlugin", expr => {
if (expr.arguments.length !== 1) return;
const param = parser.evaluateExpression(expr.arguments[0]);
if (!param.isString()) return;
const dep = new RequireIncludeDependency(param.string, expr.range);
dep.loc = expr.loc;
parser.state.current.addDependency(dep);
return true;
});
}
};

View file

@ -0,0 +1,61 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const RequireIncludeDependency = require("./RequireIncludeDependency");
const RequireIncludeDependencyParserPlugin = require("./RequireIncludeDependencyParserPlugin");
const ParserHelpers = require("../ParserHelpers");
class RequireIncludePlugin {
apply(compiler) {
compiler.hooks.compilation.tap(
"RequireIncludePlugin",
(compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(
RequireIncludeDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
RequireIncludeDependency,
new RequireIncludeDependency.Template()
);
const handler = (parser, parserOptions) => {
if (
parserOptions.requireInclude !== undefined &&
!parserOptions.requireInclude
)
return;
new RequireIncludeDependencyParserPlugin().apply(parser);
parser.hooks.evaluateTypeof
.for("require.include")
.tap(
"RequireIncludePlugin",
ParserHelpers.evaluateToString("function")
);
parser.hooks.typeof
.for("require.include")
.tap(
"RequireIncludePlugin",
ParserHelpers.toConstantDependency(
parser,
JSON.stringify("function")
)
);
};
normalModuleFactory.hooks.parser
.for("javascript/auto")
.tap("RequireIncludePlugin", handler);
normalModuleFactory.hooks.parser
.for("javascript/dynamic")
.tap("RequireIncludePlugin", handler);
}
);
}
}
module.exports = RequireIncludePlugin;

View file

@ -0,0 +1,23 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ContextDependency = require("./ContextDependency");
const ContextDependencyTemplateAsId = require("./ContextDependencyTemplateAsId");
class RequireResolveContextDependency extends ContextDependency {
constructor(options, range, valueRange) {
super(options);
this.range = range;
this.valueRange = valueRange;
}
get type() {
return "amd require context";
}
}
RequireResolveContextDependency.Template = ContextDependencyTemplateAsId;
module.exports = RequireResolveContextDependency;

View file

@ -0,0 +1,22 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
const ModuleDependencyAsId = require("./ModuleDependencyTemplateAsId");
class RequireResolveDependency extends ModuleDependency {
constructor(request, range) {
super(request);
this.range = range;
}
get type() {
return "require.resolve";
}
}
RequireResolveDependency.Template = ModuleDependencyAsId;
module.exports = RequireResolveDependency;

View file

@ -0,0 +1,86 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const RequireResolveDependency = require("./RequireResolveDependency");
const RequireResolveContextDependency = require("./RequireResolveContextDependency");
const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency");
const ContextDependencyHelpers = require("./ContextDependencyHelpers");
class RequireResolveDependencyParserPlugin {
constructor(options) {
this.options = options;
}
apply(parser) {
const options = this.options;
const process = (expr, weak) => {
if (expr.arguments.length !== 1) return;
const param = parser.evaluateExpression(expr.arguments[0]);
if (param.isConditional()) {
for (const option of param.options) {
const result = processItem(expr, option, weak);
if (result === undefined) {
processContext(expr, option, weak);
}
}
const dep = new RequireResolveHeaderDependency(expr.callee.range);
dep.loc = expr.loc;
parser.state.current.addDependency(dep);
return true;
} else {
const result = processItem(expr, param, weak);
if (result === undefined) {
processContext(expr, param, weak);
}
const dep = new RequireResolveHeaderDependency(expr.callee.range);
dep.loc = expr.loc;
parser.state.current.addDependency(dep);
return true;
}
};
const processItem = (expr, param, weak) => {
if (param.isString()) {
const dep = new RequireResolveDependency(param.string, param.range);
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
dep.weak = weak;
parser.state.current.addDependency(dep);
return true;
}
};
const processContext = (expr, param, weak) => {
const dep = ContextDependencyHelpers.create(
RequireResolveContextDependency,
param.range,
param,
expr,
options,
{
mode: weak ? "weak" : "sync"
},
parser
);
if (!dep) return;
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
};
parser.hooks.call
.for("require.resolve")
.tap("RequireResolveDependencyParserPlugin", expr => {
return process(expr, false);
});
parser.hooks.call
.for("require.resolveWeak")
.tap("RequireResolveDependencyParserPlugin", expr => {
return process(expr, true);
});
}
}
module.exports = RequireResolveDependencyParserPlugin;

View file

@ -0,0 +1,26 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
class RequireResolveHeaderDependency extends NullDependency {
constructor(range) {
super();
if (!Array.isArray(range)) throw new Error("range must be valid");
this.range = range;
}
}
RequireResolveHeaderDependency.Template = class RequireResolveHeaderDependencyTemplate {
apply(dep, source) {
source.replace(dep.range[0], dep.range[1] - 1, "/*require.resolve*/");
}
applyAsTemplateArgument(name, dep, source) {
source.replace(dep.range[0], dep.range[1] - 1, "/*require.resolve*/");
}
};
module.exports = RequireResolveHeaderDependency;

View file

@ -0,0 +1,21 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
class SingleEntryDependency extends ModuleDependency {
/**
* @param {string} request request path for entry
*/
constructor(request) {
super(request);
}
get type() {
return "single entry";
}
}
module.exports = SingleEntryDependency;

View file

@ -0,0 +1,122 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ParserHelpers = require("../ParserHelpers");
const WebpackError = require("../WebpackError");
class SystemPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
compiler.hooks.compilation.tap(
"SystemPlugin",
(compilation, { normalModuleFactory }) => {
const handler = (parser, parserOptions) => {
if (parserOptions.system !== undefined && !parserOptions.system)
return;
const shouldWarn = parserOptions.system === undefined;
const setNotSupported = name => {
parser.hooks.evaluateTypeof
.for(name)
.tap("SystemPlugin", ParserHelpers.evaluateToString("undefined"));
parser.hooks.expression
.for(name)
.tap(
"SystemPlugin",
ParserHelpers.expressionIsUnsupported(
parser,
name + " is not supported by webpack."
)
);
};
parser.hooks.typeof
.for("System.import")
.tap(
"SystemPlugin",
ParserHelpers.toConstantDependency(
parser,
JSON.stringify("function")
)
);
parser.hooks.evaluateTypeof
.for("System.import")
.tap("SystemPlugin", ParserHelpers.evaluateToString("function"));
parser.hooks.typeof
.for("System")
.tap(
"SystemPlugin",
ParserHelpers.toConstantDependency(
parser,
JSON.stringify("object")
)
);
parser.hooks.evaluateTypeof
.for("System")
.tap("SystemPlugin", ParserHelpers.evaluateToString("object"));
setNotSupported("System.set");
setNotSupported("System.get");
setNotSupported("System.register");
parser.hooks.expression.for("System").tap("SystemPlugin", () => {
const systemPolyfillRequire = ParserHelpers.requireFileAsExpression(
parser.state.module.context,
require.resolve("../../buildin/system")
);
return ParserHelpers.addParsedVariableToModule(
parser,
"System",
systemPolyfillRequire
);
});
parser.hooks.call.for("System.import").tap("SystemPlugin", expr => {
if (shouldWarn) {
parser.state.module.warnings.push(
new SystemImportDeprecationWarning(
parser.state.module,
expr.loc
)
);
}
return parser.hooks.importCall.call(expr);
});
};
normalModuleFactory.hooks.parser
.for("javascript/auto")
.tap("SystemPlugin", handler);
normalModuleFactory.hooks.parser
.for("javascript/dynamic")
.tap("SystemPlugin", handler);
}
);
}
}
class SystemImportDeprecationWarning extends WebpackError {
constructor(module, loc) {
super(
"System.import() is deprecated and will be removed soon. Use import() instead.\n" +
"For more info visit https://webpack.js.org/guides/code-splitting/"
);
this.name = "SystemImportDeprecationWarning";
this.module = module;
this.loc = loc;
Error.captureStackTrace(this, this.constructor);
}
}
module.exports = SystemPlugin;

View file

@ -0,0 +1,27 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
const webpackMissingModule = require("./WebpackMissingModule").module;
class UnsupportedDependency extends NullDependency {
constructor(request, range) {
super();
this.request = request;
this.range = range;
}
}
UnsupportedDependency.Template = class UnsupportedDependencyTemplate {
apply(dep, source, runtime) {
source.replace(
dep.range[0],
dep.range[1],
webpackMissingModule(dep.request)
);
}
};
module.exports = UnsupportedDependency;

View file

@ -0,0 +1,31 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const DependencyReference = require("./DependencyReference");
const ModuleDependency = require("./ModuleDependency");
class WebAssemblyExportImportedDependency extends ModuleDependency {
constructor(exportName, request, name, valueType) {
super(request);
/** @type {string} */
this.exportName = exportName;
/** @type {string} */
this.name = name;
/** @type {string} */
this.valueType = valueType;
}
getReference() {
if (!this.module) return null;
return new DependencyReference(this.module, [this.name], false);
}
get type() {
return "wasm export import";
}
}
module.exports = WebAssemblyExportImportedDependency;

View file

@ -0,0 +1,54 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const DependencyReference = require("./DependencyReference");
const ModuleDependency = require("./ModuleDependency");
const UnsupportedWebAssemblyFeatureError = require("../wasm/UnsupportedWebAssemblyFeatureError");
/** @typedef {import("@webassemblyjs/ast").ModuleImportDescription} ModuleImportDescription */
class WebAssemblyImportDependency extends ModuleDependency {
/**
* @param {string} request the request
* @param {string} name the imported name
* @param {ModuleImportDescription} description the WASM ast node
* @param {false | string} onlyDirectImport if only direct imports are allowed
*/
constructor(request, name, description, onlyDirectImport) {
super(request);
/** @type {string} */
this.name = name;
/** @type {ModuleImportDescription} */
this.description = description;
/** @type {false | string} */
this.onlyDirectImport = onlyDirectImport;
}
getReference() {
if (!this.module) return null;
return new DependencyReference(this.module, [this.name], false);
}
getErrors() {
if (
this.onlyDirectImport &&
this.module &&
!this.module.type.startsWith("webassembly")
) {
return [
new UnsupportedWebAssemblyFeatureError(
`Import "${this.name}" from "${this.request}" with ${this.onlyDirectImport} can only be used for direct wasm to wasm dependencies`
)
];
}
}
get type() {
return "wasm import";
}
}
module.exports = WebAssemblyImportDependency;

View file

@ -0,0 +1,20 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const toErrorCode = err =>
`var e = new Error(${JSON.stringify(err)}); e.code = 'MODULE_NOT_FOUND';`;
exports.module = request =>
`!(function webpackMissingModule() { ${exports.moduleCode(request)} }())`;
exports.promise = request => {
const errorCode = toErrorCode(`Cannot find module '${request}'`);
return `Promise.reject(function webpackMissingModule() { ${errorCode} return e; }())`;
};
exports.moduleCode = request => {
const errorCode = toErrorCode(`Cannot find module '${request}'`);
return `${errorCode} throw e;`;
};

View file

@ -0,0 +1,52 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
module.exports = expr => {
// <FunctionExpression>
if (
expr.type === "FunctionExpression" ||
expr.type === "ArrowFunctionExpression"
) {
return {
fn: expr,
expressions: [],
needThis: false
};
}
// <FunctionExpression>.bind(<Expression>)
if (
expr.type === "CallExpression" &&
expr.callee.type === "MemberExpression" &&
expr.callee.object.type === "FunctionExpression" &&
expr.callee.property.type === "Identifier" &&
expr.callee.property.name === "bind" &&
expr.arguments.length === 1
) {
return {
fn: expr.callee.object,
expressions: [expr.arguments[0]],
needThis: undefined
};
}
// (function(_this) {return <FunctionExpression>})(this) (Coffeescript)
if (
expr.type === "CallExpression" &&
expr.callee.type === "FunctionExpression" &&
expr.callee.body.type === "BlockStatement" &&
expr.arguments.length === 1 &&
expr.arguments[0].type === "ThisExpression" &&
expr.callee.body.body &&
expr.callee.body.body.length === 1 &&
expr.callee.body.body[0].type === "ReturnStatement" &&
expr.callee.body.body[0].argument &&
expr.callee.body.body[0].argument.type === "FunctionExpression"
) {
return {
fn: expr.callee.body.body[0].argument,
expressions: [],
needThis: true
};
}
};