package.lib.dependencies.ImportParserPlugin.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of webpack Show documentation
Show all versions of webpack Show documentation
Packs ECMAScript/CommonJs/AMD modules for the browser. Allows you to split your codebase into multiple bundles, which can be loaded on demand. Supports loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.
The newest version!
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const AsyncDependenciesBlock = require("../AsyncDependenciesBlock");
const CommentCompilationWarning = require("../CommentCompilationWarning");
const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
const ContextDependencyHelpers = require("./ContextDependencyHelpers");
const { getAttributes } = require("./HarmonyImportDependencyParserPlugin");
const ImportContextDependency = require("./ImportContextDependency");
const ImportDependency = require("./ImportDependency");
const ImportEagerDependency = require("./ImportEagerDependency");
const ImportWeakDependency = require("./ImportWeakDependency");
/** @typedef {import("estree").ImportExpression} ImportExpression */
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
/** @typedef {import("../ChunkGroup").RawChunkGroupOptions} RawChunkGroupOptions */
/** @typedef {import("../ContextModule").ContextMode} ContextMode */
/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
/** @typedef {import("../Module").BuildMeta} BuildMeta */
/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
/** @typedef {import("../javascript/JavascriptParser").Range} Range */
class ImportParserPlugin {
/**
* @param {JavascriptParserOptions} options options
*/
constructor(options) {
this.options = options;
}
/**
* @param {JavascriptParser} parser the parser
* @returns {void}
*/
apply(parser) {
/**
* @template T
* @param {Iterable} enumerable enumerable
* @returns {T[][]} array of array
*/
const exportsFromEnumerable = enumerable =>
Array.from(enumerable, e => [e]);
parser.hooks.importCall.tap("ImportParserPlugin", expr => {
const param = parser.evaluateExpression(expr.source);
let chunkName = null;
let mode = /** @type {ContextMode} */ (this.options.dynamicImportMode);
let include = null;
let exclude = null;
/** @type {string[][] | null} */
let exports = null;
/** @type {RawChunkGroupOptions} */
const groupOptions = {};
const {
dynamicImportPreload,
dynamicImportPrefetch,
dynamicImportFetchPriority
} = this.options;
if (dynamicImportPreload !== undefined && dynamicImportPreload !== false)
groupOptions.preloadOrder =
dynamicImportPreload === true ? 0 : dynamicImportPreload;
if (
dynamicImportPrefetch !== undefined &&
dynamicImportPrefetch !== false
)
groupOptions.prefetchOrder =
dynamicImportPrefetch === true ? 0 : dynamicImportPrefetch;
if (
dynamicImportFetchPriority !== undefined &&
dynamicImportFetchPriority !== false
)
groupOptions.fetchPriority = dynamicImportFetchPriority;
const { options: importOptions, errors: commentErrors } =
parser.parseCommentOptions(/** @type {Range} */ (expr.range));
if (commentErrors) {
for (const e of commentErrors) {
const { comment } = e;
parser.state.module.addWarning(
new CommentCompilationWarning(
`Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
comment.loc
)
);
}
}
if (importOptions) {
if (importOptions.webpackIgnore !== undefined) {
if (typeof importOptions.webpackIgnore !== "boolean") {
parser.state.module.addWarning(
new UnsupportedFeatureWarning(
`\`webpackIgnore\` expected a boolean, but received: ${importOptions.webpackIgnore}.`,
/** @type {DependencyLocation} */ (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.addWarning(
new UnsupportedFeatureWarning(
`\`webpackChunkName\` expected a string, but received: ${importOptions.webpackChunkName}.`,
/** @type {DependencyLocation} */ (expr.loc)
)
);
} else {
chunkName = importOptions.webpackChunkName;
}
}
if (importOptions.webpackMode !== undefined) {
if (typeof importOptions.webpackMode !== "string") {
parser.state.module.addWarning(
new UnsupportedFeatureWarning(
`\`webpackMode\` expected a string, but received: ${importOptions.webpackMode}.`,
/** @type {DependencyLocation} */ (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.addWarning(
new UnsupportedFeatureWarning(
`\`webpackPrefetch\` expected true or a number, but received: ${importOptions.webpackPrefetch}.`,
/** @type {DependencyLocation} */ (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.addWarning(
new UnsupportedFeatureWarning(
`\`webpackPreload\` expected true or a number, but received: ${importOptions.webpackPreload}.`,
/** @type {DependencyLocation} */ (expr.loc)
)
);
}
}
if (importOptions.webpackFetchPriority !== undefined) {
if (
typeof importOptions.webpackFetchPriority === "string" &&
["high", "low", "auto"].includes(importOptions.webpackFetchPriority)
) {
groupOptions.fetchPriority = importOptions.webpackFetchPriority;
} else {
parser.state.module.addWarning(
new UnsupportedFeatureWarning(
`\`webpackFetchPriority\` expected true or "low", "high" or "auto", but received: ${importOptions.webpackFetchPriority}.`,
/** @type {DependencyLocation} */ (expr.loc)
)
);
}
}
if (importOptions.webpackInclude !== undefined) {
if (
!importOptions.webpackInclude ||
!(importOptions.webpackInclude instanceof RegExp)
) {
parser.state.module.addWarning(
new UnsupportedFeatureWarning(
`\`webpackInclude\` expected a regular expression, but received: ${importOptions.webpackInclude}.`,
/** @type {DependencyLocation} */ (expr.loc)
)
);
} else {
include = importOptions.webpackInclude;
}
}
if (importOptions.webpackExclude !== undefined) {
if (
!importOptions.webpackExclude ||
!(importOptions.webpackExclude instanceof RegExp)
) {
parser.state.module.addWarning(
new UnsupportedFeatureWarning(
`\`webpackExclude\` expected a regular expression, but received: ${importOptions.webpackExclude}.`,
/** @type {DependencyLocation} */ (expr.loc)
)
);
} else {
exclude = importOptions.webpackExclude;
}
}
if (importOptions.webpackExports !== undefined) {
if (
!(
typeof importOptions.webpackExports === "string" ||
(Array.isArray(importOptions.webpackExports) &&
/** @type {string[]} */ (importOptions.webpackExports).every(
item => typeof item === "string"
))
)
) {
parser.state.module.addWarning(
new UnsupportedFeatureWarning(
`\`webpackExports\` expected a string or an array of strings, but received: ${importOptions.webpackExports}.`,
/** @type {DependencyLocation} */ (expr.loc)
)
);
} else {
if (typeof importOptions.webpackExports === "string") {
exports = [[importOptions.webpackExports]];
} else {
exports = exportsFromEnumerable(importOptions.webpackExports);
}
}
}
}
if (
mode !== "lazy" &&
mode !== "lazy-once" &&
mode !== "eager" &&
mode !== "weak"
) {
parser.state.module.addWarning(
new UnsupportedFeatureWarning(
`\`webpackMode\` expected 'lazy', 'lazy-once', 'eager' or 'weak', but received: ${mode}.`,
/** @type {DependencyLocation} */ (expr.loc)
)
);
mode = "lazy";
}
const referencedPropertiesInDestructuring =
parser.destructuringAssignmentPropertiesFor(expr);
if (referencedPropertiesInDestructuring) {
if (exports) {
parser.state.module.addWarning(
new UnsupportedFeatureWarning(
`\`webpackExports\` could not be used with destructuring assignment.`,
/** @type {DependencyLocation} */ (expr.loc)
)
);
}
exports = exportsFromEnumerable(
[...referencedPropertiesInDestructuring].map(({ id }) => id)
);
}
if (param.isString()) {
const attributes = getAttributes(expr);
if (mode === "eager") {
const dep = new ImportEagerDependency(
/** @type {string} */ (param.string),
/** @type {Range} */ (expr.range),
exports,
attributes
);
parser.state.current.addDependency(dep);
} else if (mode === "weak") {
const dep = new ImportWeakDependency(
/** @type {string} */ (param.string),
/** @type {Range} */ (expr.range),
exports,
attributes
);
parser.state.current.addDependency(dep);
} else {
const depBlock = new AsyncDependenciesBlock(
{
...groupOptions,
name: chunkName
},
/** @type {DependencyLocation} */ (expr.loc),
param.string
);
const dep = new ImportDependency(
/** @type {string} */ (param.string),
/** @type {Range} */ (expr.range),
exports,
attributes
);
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
dep.optional = !!parser.scope.inTry;
depBlock.addDependency(dep);
parser.state.current.addBlock(depBlock);
}
return true;
} else {
if (mode === "weak") {
mode = "async-weak";
}
const dep = ContextDependencyHelpers.create(
ImportContextDependency,
/** @type {Range} */ (expr.range),
param,
expr,
this.options,
{
chunkName,
groupOptions,
include,
exclude,
mode,
namespaceObject: /** @type {BuildMeta} */ (
parser.state.module.buildMeta
).strictHarmonyModule
? "strict"
: true,
typePrefix: "import()",
category: "esm",
referencedExports: exports,
attributes: getAttributes(expr)
},
parser
);
if (!dep) return;
dep.loc = /** @type {DependencyLocation} */ (expr.loc);
dep.optional = !!parser.scope.inTry;
parser.state.current.addDependency(dep);
return true;
}
});
}
}
module.exports = ImportParserPlugin;