summaryrefslogtreecommitdiff
path: root/node_modules/webpack/lib/dependencies/CommonJsExportsParserPlugin.js
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2023-10-31 15:37:35 +0800
committerlittleblack111 <littleblack11111@gmail.com>2023-10-31 15:37:35 +0800
commitd5f14083061f2ce6a42313188443a42e30796320 (patch)
treecc6a9889e08b29595a76a33b9e7b4ef84866468b /node_modules/webpack/lib/dependencies/CommonJsExportsParserPlugin.js
parentb1a6ea021f29f182b62f9f81024a3d8ac8621b7f (diff)
added make browserlist(autoprefixer) work fixed
Diffstat (limited to 'node_modules/webpack/lib/dependencies/CommonJsExportsParserPlugin.js')
-rw-r--r--node_modules/webpack/lib/dependencies/CommonJsExportsParserPlugin.js407
1 files changed, 407 insertions, 0 deletions
diff --git a/node_modules/webpack/lib/dependencies/CommonJsExportsParserPlugin.js b/node_modules/webpack/lib/dependencies/CommonJsExportsParserPlugin.js
new file mode 100644
index 00000000..ce3e998f
--- /dev/null
+++ b/node_modules/webpack/lib/dependencies/CommonJsExportsParserPlugin.js
@@ -0,0 +1,407 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+const RuntimeGlobals = require("../RuntimeGlobals");
+const formatLocation = require("../formatLocation");
+const { evaluateToString } = require("../javascript/JavascriptParserHelpers");
+const propertyAccess = require("../util/propertyAccess");
+const CommonJsExportRequireDependency = require("./CommonJsExportRequireDependency");
+const CommonJsExportsDependency = require("./CommonJsExportsDependency");
+const CommonJsSelfReferenceDependency = require("./CommonJsSelfReferenceDependency");
+const DynamicExports = require("./DynamicExports");
+const HarmonyExports = require("./HarmonyExports");
+const ModuleDecoratorDependency = require("./ModuleDecoratorDependency");
+
+/** @typedef {import("estree").AssignmentExpression} AssignmentExpression */
+/** @typedef {import("estree").CallExpression} CallExpression */
+/** @typedef {import("estree").Expression} Expression */
+/** @typedef {import("estree").Super} Super */
+
+/** @typedef {import("../ModuleGraph")} ModuleGraph */
+/** @typedef {import("../NormalModule")} NormalModule */
+/** @typedef {import("../javascript/BasicEvaluatedExpression")} BasicEvaluatedExpression */
+/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
+/** @typedef {import("./CommonJsDependencyHelpers").CommonJSDependencyBaseKeywords} CommonJSDependencyBaseKeywords */
+
+/**
+ * This function takes a generic expression and detects whether it is an ObjectExpression.
+ * This is used in the context of parsing CommonJS exports to get the value of the property descriptor
+ * when the `exports` object is assigned to `Object.defineProperty`.
+ *
+ * In CommonJS modules, the `exports` object can be assigned to `Object.defineProperty` and therefore
+ * webpack has to detect this case and get the value key of the property descriptor. See the following example
+ * for more information: https://astexplorer.net/#/gist/83ce51a4e96e59d777df315a6d111da6/8058ead48a1bb53c097738225db0967ef7f70e57
+ *
+ * This would be an example of a CommonJS module that exports an object with a property descriptor:
+ * ```js
+ * Object.defineProperty(exports, "__esModule", { value: true });
+ * exports.foo = void 0;
+ * exports.foo = "bar";
+ * ```
+ *
+ * @param {TODO} expr expression
+ * @returns {Expression | undefined} returns the value of property descriptor
+ */
+const getValueOfPropertyDescription = expr => {
+ if (expr.type !== "ObjectExpression") return;
+ for (const property of expr.properties) {
+ if (property.computed) continue;
+ const key = property.key;
+ if (key.type !== "Identifier" || key.name !== "value") continue;
+ return property.value;
+ }
+};
+
+/**
+ * The purpose of this function is to check whether an expression is a truthy literal or not. This is
+ * useful when parsing CommonJS exports, because CommonJS modules can export any value, including falsy
+ * values like `null` and `false`. However, exports should only be created if the exported value is truthy.
+ *
+ * @param {Expression} expr expression being checked
+ * @returns {boolean} true, when the expression is a truthy literal
+ *
+ */
+const isTruthyLiteral = expr => {
+ switch (expr.type) {
+ case "Literal":
+ return !!expr.value;
+ case "UnaryExpression":
+ if (expr.operator === "!") return isFalsyLiteral(expr.argument);
+ }
+ return false;
+};
+
+/**
+ * The purpose of this function is to check whether an expression is a falsy literal or not. This is
+ * useful when parsing CommonJS exports, because CommonJS modules can export any value, including falsy
+ * values like `null` and `false`. However, exports should only be created if the exported value is truthy.
+ *
+ * @param {Expression} expr expression being checked
+ * @returns {boolean} true, when the expression is a falsy literal
+ */
+const isFalsyLiteral = expr => {
+ switch (expr.type) {
+ case "Literal":
+ return !expr.value;
+ case "UnaryExpression":
+ if (expr.operator === "!") return isTruthyLiteral(expr.argument);
+ }
+ return false;
+};
+
+/**
+ * @param {JavascriptParser} parser the parser
+ * @param {Expression} expr expression
+ * @returns {{ argument: BasicEvaluatedExpression, ids: string[] } | undefined} parsed call
+ */
+const parseRequireCall = (parser, expr) => {
+ const ids = [];
+ while (expr.type === "MemberExpression") {
+ if (expr.object.type === "Super") return;
+ if (!expr.property) return;
+ const prop = expr.property;
+ if (expr.computed) {
+ if (prop.type !== "Literal") return;
+ ids.push(`${prop.value}`);
+ } else {
+ if (prop.type !== "Identifier") return;
+ ids.push(prop.name);
+ }
+ expr = expr.object;
+ }
+ if (expr.type !== "CallExpression" || expr.arguments.length !== 1) return;
+ const callee = expr.callee;
+ if (
+ callee.type !== "Identifier" ||
+ parser.getVariableInfo(callee.name) !== "require"
+ ) {
+ return;
+ }
+ const arg = expr.arguments[0];
+ if (arg.type === "SpreadElement") return;
+ const argValue = parser.evaluateExpression(arg);
+ return { argument: argValue, ids: ids.reverse() };
+};
+
+class CommonJsExportsParserPlugin {
+ /**
+ * @param {ModuleGraph} moduleGraph module graph
+ */
+ constructor(moduleGraph) {
+ this.moduleGraph = moduleGraph;
+ }
+
+ /**
+ * @param {JavascriptParser} parser the parser
+ * @returns {void}
+ */
+ apply(parser) {
+ const enableStructuredExports = () => {
+ DynamicExports.enable(parser.state);
+ };
+
+ /**
+ * @param {boolean} topLevel true, when the export is on top level
+ * @param {string[]} members members of the export
+ * @param {Expression | undefined} valueExpr expression for the value
+ * @returns {void}
+ */
+ const checkNamespace = (topLevel, members, valueExpr) => {
+ if (!DynamicExports.isEnabled(parser.state)) return;
+ if (members.length > 0 && members[0] === "__esModule") {
+ if (valueExpr && isTruthyLiteral(valueExpr) && topLevel) {
+ DynamicExports.setFlagged(parser.state);
+ } else {
+ DynamicExports.setDynamic(parser.state);
+ }
+ }
+ };
+ /**
+ * @param {string=} reason reason
+ */
+ const bailout = reason => {
+ DynamicExports.bailout(parser.state);
+ if (reason) bailoutHint(reason);
+ };
+ /**
+ * @param {string} reason reason
+ */
+ const bailoutHint = reason => {
+ this.moduleGraph
+ .getOptimizationBailout(parser.state.module)
+ .push(`CommonJS bailout: ${reason}`);
+ };
+
+ // metadata //
+ parser.hooks.evaluateTypeof
+ .for("module")
+ .tap("CommonJsExportsParserPlugin", evaluateToString("object"));
+ parser.hooks.evaluateTypeof
+ .for("exports")
+ .tap("CommonJsPlugin", evaluateToString("object"));
+
+ // exporting //
+
+ /**
+ * @param {AssignmentExpression} expr expression
+ * @param {CommonJSDependencyBaseKeywords} base commonjs base keywords
+ * @param {string[]} members members of the export
+ * @returns {boolean} true, when the expression was handled
+ */
+ const handleAssignExport = (expr, base, members) => {
+ if (HarmonyExports.isEnabled(parser.state)) return;
+ // Handle reexporting
+ const requireCall = parseRequireCall(parser, expr.right);
+ if (
+ requireCall &&
+ requireCall.argument.isString() &&
+ (members.length === 0 || members[0] !== "__esModule")
+ ) {
+ enableStructuredExports();
+ // It's possible to reexport __esModule, so we must convert to a dynamic module
+ if (members.length === 0) DynamicExports.setDynamic(parser.state);
+ const dep = new CommonJsExportRequireDependency(
+ expr.range,
+ null,
+ base,
+ members,
+ requireCall.argument.string,
+ requireCall.ids,
+ !parser.isStatementLevelExpression(expr)
+ );
+ dep.loc = expr.loc;
+ dep.optional = !!parser.scope.inTry;
+ parser.state.module.addDependency(dep);
+ return true;
+ }
+ if (members.length === 0) return;
+ enableStructuredExports();
+ const remainingMembers = members;
+ checkNamespace(
+ parser.statementPath.length === 1 &&
+ parser.isStatementLevelExpression(expr),
+ remainingMembers,
+ expr.right
+ );
+ const dep = new CommonJsExportsDependency(
+ expr.left.range,
+ null,
+ base,
+ remainingMembers
+ );
+ dep.loc = expr.loc;
+ parser.state.module.addDependency(dep);
+ parser.walkExpression(expr.right);
+ return true;
+ };
+ parser.hooks.assignMemberChain
+ .for("exports")
+ .tap("CommonJsExportsParserPlugin", (expr, members) => {
+ return handleAssignExport(expr, "exports", members);
+ });
+ parser.hooks.assignMemberChain
+ .for("this")
+ .tap("CommonJsExportsParserPlugin", (expr, members) => {
+ if (!parser.scope.topLevelScope) return;
+ return handleAssignExport(expr, "this", members);
+ });
+ parser.hooks.assignMemberChain
+ .for("module")
+ .tap("CommonJsExportsParserPlugin", (expr, members) => {
+ if (members[0] !== "exports") return;
+ return handleAssignExport(expr, "module.exports", members.slice(1));
+ });
+ parser.hooks.call
+ .for("Object.defineProperty")
+ .tap("CommonJsExportsParserPlugin", expression => {
+ const expr = /** @type {CallExpression} */ (expression);
+ if (!parser.isStatementLevelExpression(expr)) return;
+ if (expr.arguments.length !== 3) return;
+ if (expr.arguments[0].type === "SpreadElement") return;
+ if (expr.arguments[1].type === "SpreadElement") return;
+ if (expr.arguments[2].type === "SpreadElement") return;
+ const exportsArg = parser.evaluateExpression(expr.arguments[0]);
+ if (!exportsArg.isIdentifier()) return;
+ if (
+ exportsArg.identifier !== "exports" &&
+ exportsArg.identifier !== "module.exports" &&
+ (exportsArg.identifier !== "this" || !parser.scope.topLevelScope)
+ ) {
+ return;
+ }
+ const propertyArg = parser.evaluateExpression(expr.arguments[1]);
+ const property = propertyArg.asString();
+ if (typeof property !== "string") return;
+ enableStructuredExports();
+ const descArg = expr.arguments[2];
+ checkNamespace(
+ parser.statementPath.length === 1,
+ [property],
+ getValueOfPropertyDescription(descArg)
+ );
+ const dep = new CommonJsExportsDependency(
+ expr.range,
+ expr.arguments[2].range,
+ `Object.defineProperty(${exportsArg.identifier})`,
+ [property]
+ );
+ dep.loc = expr.loc;
+ parser.state.module.addDependency(dep);
+
+ parser.walkExpression(expr.arguments[2]);
+ return true;
+ });
+
+ // Self reference //
+
+ /**
+ * @param {Expression | Super} expr expression
+ * @param {CommonJSDependencyBaseKeywords} base commonjs base keywords
+ * @param {string[]} members members of the export
+ * @param {CallExpression=} call call expression
+ * @returns {boolean | void} true, when the expression was handled
+ */
+ const handleAccessExport = (expr, base, members, call = undefined) => {
+ if (HarmonyExports.isEnabled(parser.state)) return;
+ if (members.length === 0) {
+ bailout(`${base} is used directly at ${formatLocation(expr.loc)}`);
+ }
+ if (call && members.length === 1) {
+ bailoutHint(
+ `${base}${propertyAccess(
+ members
+ )}(...) prevents optimization as ${base} is passed as call context at ${formatLocation(
+ expr.loc
+ )}`
+ );
+ }
+ const dep = new CommonJsSelfReferenceDependency(
+ expr.range,
+ base,
+ members,
+ !!call
+ );
+ dep.loc = expr.loc;
+ parser.state.module.addDependency(dep);
+ if (call) {
+ parser.walkExpressions(call.arguments);
+ }
+ return true;
+ };
+ parser.hooks.callMemberChain
+ .for("exports")
+ .tap("CommonJsExportsParserPlugin", (expr, members) => {
+ return handleAccessExport(expr.callee, "exports", members, expr);
+ });
+ parser.hooks.expressionMemberChain
+ .for("exports")
+ .tap("CommonJsExportsParserPlugin", (expr, members) => {
+ return handleAccessExport(expr, "exports", members);
+ });
+ parser.hooks.expression
+ .for("exports")
+ .tap("CommonJsExportsParserPlugin", expr => {
+ return handleAccessExport(expr, "exports", []);
+ });
+ parser.hooks.callMemberChain
+ .for("module")
+ .tap("CommonJsExportsParserPlugin", (expr, members) => {
+ if (members[0] !== "exports") return;
+ return handleAccessExport(
+ expr.callee,
+ "module.exports",
+ members.slice(1),
+ expr
+ );
+ });
+ parser.hooks.expressionMemberChain
+ .for("module")
+ .tap("CommonJsExportsParserPlugin", (expr, members) => {
+ if (members[0] !== "exports") return;
+ return handleAccessExport(expr, "module.exports", members.slice(1));
+ });
+ parser.hooks.expression
+ .for("module.exports")
+ .tap("CommonJsExportsParserPlugin", expr => {
+ return handleAccessExport(expr, "module.exports", []);
+ });
+ parser.hooks.callMemberChain
+ .for("this")
+ .tap("CommonJsExportsParserPlugin", (expr, members) => {
+ if (!parser.scope.topLevelScope) return;
+ return handleAccessExport(expr.callee, "this", members, expr);
+ });
+ parser.hooks.expressionMemberChain
+ .for("this")
+ .tap("CommonJsExportsParserPlugin", (expr, members) => {
+ if (!parser.scope.topLevelScope) return;
+ return handleAccessExport(expr, "this", members);
+ });
+ parser.hooks.expression
+ .for("this")
+ .tap("CommonJsExportsParserPlugin", expr => {
+ if (!parser.scope.topLevelScope) return;
+ return handleAccessExport(expr, "this", []);
+ });
+
+ // Bailouts //
+ parser.hooks.expression.for("module").tap("CommonJsPlugin", expr => {
+ bailout();
+ const isHarmony = HarmonyExports.isEnabled(parser.state);
+ const dep = new ModuleDecoratorDependency(
+ isHarmony
+ ? RuntimeGlobals.harmonyModuleDecorator
+ : RuntimeGlobals.nodeModuleDecorator,
+ !isHarmony
+ );
+ dep.loc = expr.loc;
+ parser.state.module.addDependency(dep);
+ return true;
+ });
+ }
+}
+module.exports = CommonJsExportsParserPlugin;