WXL
4 天以前 3bd962a6d7f61239c020e2dbbeb7341e5b842dd1
node_modules/webpack/lib/dependencies/CommonJsImportsParserPlugin.js
@@ -5,19 +5,16 @@
"use strict";
const { fileURLToPath } = require("url");
const CommentCompilationWarning = require("../CommentCompilationWarning");
const RuntimeGlobals = require("../RuntimeGlobals");
const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
const WebpackError = require("../WebpackError");
const BasicEvaluatedExpression = require("../javascript/BasicEvaluatedExpression");
const { VariableInfo } = require("../javascript/JavascriptParser");
const {
   evaluateToIdentifier,
   evaluateToString,
   expressionIsUnsupported,
   toConstantDependency
} = require("../javascript/JavascriptParserHelpers");
const traverseDestructuringAssignmentProperties = require("../util/traverseDestructuringAssignmentProperties");
const CommonJsFullRequireDependency = require("./CommonJsFullRequireDependency");
const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency");
const CommonJsRequireDependency = require("./CommonJsRequireDependency");
@@ -35,165 +32,89 @@
/** @typedef {import("estree").NewExpression} NewExpression */
/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
/** @typedef {import("../Dependency").RawReferencedExports} RawReferencedExports */
/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
/** @typedef {import("../javascript/BasicEvaluatedExpression")} BasicEvaluatedExpression */
/** @typedef {import("../javascript/JavascriptParser").ImportSource} ImportSource */
/** @typedef {import("../javascript/JavascriptParser").Range} Range */
/** @typedef {import("../javascript/JavascriptParser").Members} Members */
/** @typedef {import("../javascript/JavascriptParser").CalleeMembers} CalleeMembers */
/** @typedef {import("./LocalModule")} LocalModule */
/**
 * Defines the common js import settings type used by this module.
 * @typedef {object} CommonJsImportSettings
 * @property {string=} name
 * @property {string} context
 */
const createRequireSpecifierTag = Symbol("createRequire");
const createdRequireIdentifierTag = Symbol("createRequire()");
const PLUGIN_NAME = "CommonJsImportsParserPlugin";
class CommonJsImportsParserPlugin {
   /**
    * @param {JavascriptParserOptions} options parser options
 * Checks whether this object is require call expression.
 * @param {Expression} expression expression
 * @returns {boolean} true, when expression is `require(...)` or `module.require(...)`
    */
   constructor(options) {
      this.options = options;
const isRequireCallExpression = (expression) => {
   if (expression.type !== "CallExpression") return false;
   const { callee } = expression;
   if (callee.type === "Identifier") {
      return callee.name === "require";
   }
   /**
    * @param {JavascriptParser} parser the parser
    * @returns {void}
    */
   apply(parser) {
      const options = this.options;
      const getContext = () => {
         if (parser.currentTagData) {
            const { context } =
               /** @type {CommonJsImportSettings} */
               (parser.currentTagData);
            return context;
   if (callee.type === "MemberExpression" && !callee.computed) {
      const object = callee.object;
      const property = callee.property;
      return (
         object.type === "Identifier" &&
         object.name === "module" &&
         property.type === "Identifier" &&
         property.name === "require"
      );
         }
      };
      // #region metadata
      /**
       * @param {string} expression expression
       * @param {() => Members} getMembers get members
       */
      const tapRequireExpression = (expression, getMembers) => {
         parser.hooks.typeof
            .for(expression)
            .tap(
               PLUGIN_NAME,
               toConstantDependency(parser, JSON.stringify("function"))
            );
         parser.hooks.evaluateTypeof
            .for(expression)
            .tap(PLUGIN_NAME, evaluateToString("function"));
         parser.hooks.evaluateIdentifier
            .for(expression)
            .tap(
               PLUGIN_NAME,
               evaluateToIdentifier(expression, "require", getMembers, true)
            );
      };
      /**
       * @param {string | symbol} tag tag
       */
      const tapRequireExpressionTag = (tag) => {
         parser.hooks.typeof
            .for(tag)
            .tap(
               PLUGIN_NAME,
               toConstantDependency(parser, JSON.stringify("function"))
            );
         parser.hooks.evaluateTypeof
            .for(tag)
            .tap(PLUGIN_NAME, evaluateToString("function"));
      };
      tapRequireExpression("require", () => []);
      tapRequireExpression("require.resolve", () => ["resolve"]);
      tapRequireExpression("require.resolveWeak", () => ["resolveWeak"]);
      // #endregion
      // Weird stuff //
      parser.hooks.assign.for("require").tap(PLUGIN_NAME, (expr) => {
         // to not leak to global "require", we need to define a local require here.
         const dep = new ConstDependency("var require;", 0);
         dep.loc = /** @type {DependencyLocation} */ (expr.loc);
         parser.state.module.addPresentationalDependency(dep);
         return true;
      });
      // #region Unsupported
      parser.hooks.call
         .for("require.main.require")
         .tap(
            PLUGIN_NAME,
            expressionIsUnsupported(
               parser,
               "require.main.require is not supported by webpack."
            )
         );
      parser.hooks.expression
         .for("module.parent.require")
         .tap(
            PLUGIN_NAME,
            expressionIsUnsupported(
               parser,
               "module.parent.require is not supported by webpack."
            )
         );
      parser.hooks.call
         .for("module.parent.require")
         .tap(
            PLUGIN_NAME,
            expressionIsUnsupported(
               parser,
               "module.parent.require is not supported by webpack."
            )
         );
      // #endregion
      // #region Renaming
      /**
       * @param {Expression} expr expression
       * @returns {boolean} true when set undefined
       */
      const defineUndefined = (expr) => {
         // To avoid "not defined" error, replace the value with undefined
         const dep = new ConstDependency(
            "undefined",
            /** @type {Range} */ (expr.range)
         );
         dep.loc = /** @type {DependencyLocation} */ (expr.loc);
         parser.state.module.addPresentationalDependency(dep);
         return false;
      };
      parser.hooks.canRename.for("require").tap(PLUGIN_NAME, () => true);
      parser.hooks.rename.for("require").tap(PLUGIN_NAME, defineUndefined);
      // #endregion
      // #region Inspection
      const requireCache = toConstantDependency(
         parser,
         RuntimeGlobals.moduleCache,
         [
/**
 * Gets require referenced exports from destructuring.
 * @param {JavascriptParser} parser parser
 * @param {CallExpression | NewExpression} expr expression
 * @returns {RawReferencedExports | null} referenced exports from destructuring
 */
const getRequireReferencedExportsFromDestructuring = (parser, expr) => {
   const referencedPropertiesInDestructuring =
      parser.destructuringAssignmentPropertiesFor(expr);
   if (!referencedPropertiesInDestructuring) return null;
   /** @type {RawReferencedExports} */
   const referencedExports = [];
   traverseDestructuringAssignmentProperties(
      referencedPropertiesInDestructuring,
      (stack) => referencedExports.push(stack.map((p) => p.id))
   );
   return referencedExports;
};
/**
 * Creates a require cache dependency.
 * @param {JavascriptParser} parser parser
 * @returns {(expr: Expression) => boolean} handler
 */
const createRequireCacheDependency = (parser) =>
   toConstantDependency(parser, RuntimeGlobals.moduleCache, [
            RuntimeGlobals.moduleCache,
            RuntimeGlobals.moduleId,
            RuntimeGlobals.moduleLoaded
         ]
      );
   ]);
      parser.hooks.expression.for("require.cache").tap(PLUGIN_NAME, requireCache);
      // #endregion
      // #region Require as expression
      /**
       * @param {Expression} expr expression
       * @returns {boolean} true when handled
 * Creates a require as expression handler.
 * @param {JavascriptParser} parser parser
 * @param {JavascriptParserOptions} options options
 * @param {() => undefined | string} getContext context accessor
 * @returns {(expr: Expression) => boolean} handler
       */
      const requireAsExpressionHandler = (expr) => {
const createRequireAsExpressionHandler =
   (parser, options, getContext) => (expr) => {
         const dep = new CommonJsRequireContextDependency(
            {
               request: /** @type {string} */ (options.unknownContextRequest),
@@ -214,23 +135,32 @@
         parser.state.current.addDependency(dep);
         return true;
      };
      parser.hooks.expression
         .for("require")
         .tap(PLUGIN_NAME, requireAsExpressionHandler);
      // #endregion
      // #region Require
      /**
 * Creates a require call handler.
 * @param {JavascriptParser} parser parser
 * @param {JavascriptParserOptions} options options
 * @param {() => undefined | string} getContext context accessor
 * @returns {(callNew: boolean) => (expr: CallExpression | NewExpression) => (boolean | void)} handler factory
 */
const createRequireCallHandler = (parser, options, getContext) => {
   /**
    * Process require item.
       * @param {CallExpression | NewExpression} expr expression
       * @param {BasicEvaluatedExpression} param param
       * @returns {boolean | void} true when handled
       */
      const processRequireItem = (expr, param) => {
         if (param.isString()) {
         const referencedExports = getRequireReferencedExportsFromDestructuring(
            parser,
            expr
         );
            const dep = new CommonJsRequireDependency(
               /** @type {string} */ (param.string),
               /** @type {Range} */ (param.range),
               getContext()
            getContext(),
            referencedExports
            );
            dep.loc = /** @type {DependencyLocation} */ (expr.loc);
            dep.optional = Boolean(parser.scope.inTry);
@@ -239,11 +169,16 @@
         }
      };
      /**
    * Process require context.
       * @param {CallExpression | NewExpression} expr expression
       * @param {BasicEvaluatedExpression} param param
       * @returns {boolean | void} true when handled
       */
      const processRequireContext = (expr, param) => {
      const referencedExports = getRequireReferencedExportsFromDestructuring(
         parser,
         expr
      );
         const dep = ContextDependencyHelpers.create(
            CommonJsRequireContextDependency,
            /** @type {Range} */ (expr.range),
@@ -251,7 +186,8 @@
            expr,
            options,
            {
               category: "commonjs"
            category: "commonjs",
            referencedExports
            },
            parser,
            undefined,
@@ -263,11 +199,8 @@
         parser.state.current.addDependency(dep);
         return true;
      };
      /**
       * @param {boolean} callNew true, when require is called with new
       * @returns {(expr: CallExpression | NewExpression) => (boolean | void)} handler
       */
      const createRequireHandler = (callNew) => (expr) => {
   return (callNew) => (expr) => {
         if (options.commonjsMagicComments) {
            const { options: requireOptions, errors: commentErrors } =
               parser.parseCommentOptions(/** @type {Range} */ (expr.range));
@@ -299,6 +232,7 @@
         }
         if (expr.arguments.length !== 1) return;
      /** @type {null | LocalModule} */
         let localModule;
         const param = parser.evaluateExpression(expr.arguments[0]);
         if (param.isConditional()) {
@@ -349,116 +283,66 @@
         }
         return true;
      };
      parser.hooks.call
         .for("require")
         .tap(PLUGIN_NAME, createRequireHandler(false));
      parser.hooks.new
         .for("require")
         .tap(PLUGIN_NAME, createRequireHandler(true));
      parser.hooks.call
         .for("module.require")
         .tap(PLUGIN_NAME, createRequireHandler(false));
      parser.hooks.new
         .for("module.require")
         .tap(PLUGIN_NAME, createRequireHandler(true));
      // #endregion
      // #region Require with property access
      /**
       * @param {Expression} expr expression
       * @param {CalleeMembers} calleeMembers callee members
       * @param {CallExpression} callExpr call expression
       * @param {Members} members members
       * @param {Range[]} memberRanges member ranges
       * @returns {boolean | void} true when handled
       */
      const chainHandler = (
         expr,
         calleeMembers,
         callExpr,
         members,
         memberRanges
      ) => {
         if (callExpr.arguments.length !== 1) return;
         const param = parser.evaluateExpression(callExpr.arguments[0]);
         if (
            param.isString() &&
            !getLocalModule(parser.state, /** @type {string} */ (param.string))
         ) {
            const dep = new CommonJsFullRequireDependency(
               /** @type {string} */ (param.string),
               /** @type {Range} */ (expr.range),
               members,
               /** @type {Range[]} */ memberRanges
            );
            dep.asiSafe = !parser.isAsiPosition(
               /** @type {Range} */ (expr.range)[0]
            );
            dep.optional = Boolean(parser.scope.inTry);
            dep.loc = /** @type {DependencyLocation} */ (expr.loc);
            parser.state.current.addDependency(dep);
            return true;
         }
      };
      /**
       * @param {CallExpression} expr expression
       * @param {CalleeMembers} calleeMembers callee members
       * @param {CallExpression} callExpr call expression
       * @param {Members} members members
       * @param {Range[]} memberRanges member ranges
       * @returns {boolean | void} true when handled
       */
      const callChainHandler = (
         expr,
         calleeMembers,
         callExpr,
         members,
         memberRanges
      ) => {
         if (callExpr.arguments.length !== 1) return;
         const param = parser.evaluateExpression(callExpr.arguments[0]);
         if (
            param.isString() &&
            !getLocalModule(parser.state, /** @type {string} */ (param.string))
         ) {
            const dep = new CommonJsFullRequireDependency(
               /** @type {string} */ (param.string),
               /** @type {Range} */ (expr.callee.range),
               members,
               /** @type {Range[]} */ memberRanges
            );
            dep.call = true;
            dep.asiSafe = !parser.isAsiPosition(
               /** @type {Range} */ (expr.range)[0]
            );
            dep.optional = Boolean(parser.scope.inTry);
            dep.loc = /** @type {DependencyLocation} */ (expr.callee.loc);
            parser.state.current.addDependency(dep);
            parser.walkExpressions(expr.arguments);
            return true;
         }
      };
      parser.hooks.memberChainOfCallMemberChain
         .for("require")
         .tap(PLUGIN_NAME, chainHandler);
      parser.hooks.memberChainOfCallMemberChain
         .for("module.require")
         .tap(PLUGIN_NAME, chainHandler);
      parser.hooks.callMemberChainOfCallMemberChain
         .for("require")
         .tap(PLUGIN_NAME, callChainHandler);
      parser.hooks.callMemberChainOfCallMemberChain
         .for("module.require")
         .tap(PLUGIN_NAME, callChainHandler);
      // #endregion
      // #region Require.resolve
      /**
 * Creates a process resolve handler.
 * @param {JavascriptParser} parser parser
 * @param {JavascriptParserOptions} options options
 * @param {() => undefined | string} getContext context accessor
 * @returns {(expr: CallExpression, weak: boolean) => (boolean | void)} resolver
 */
const createProcessResolveHandler = (parser, options, getContext) => {
   /**
    * Process resolve item.
       * @param {CallExpression} expr call expression
    * @param {BasicEvaluatedExpression} param param
       * @param {boolean} weak weak
       * @returns {boolean | void} true when handled
       */
      const processResolve = (expr, weak) => {
   const processResolveItem = (expr, param, weak) => {
      if (param.isString()) {
         const dep = new RequireResolveDependency(
            /** @type {string} */ (param.string),
            /** @type {Range} */ (param.range),
            getContext()
         );
         dep.loc = /** @type {DependencyLocation} */ (expr.loc);
         dep.optional = Boolean(parser.scope.inTry);
         dep.weak = weak;
         parser.state.current.addDependency(dep);
         return true;
      }
   };
   /**
    * Process resolve context.
    * @param {CallExpression} expr call expression
    * @param {BasicEvaluatedExpression} param param
    * @param {boolean} weak weak
    * @returns {boolean | void} true when handled
    */
   const processResolveContext = (expr, param, weak) => {
      const dep = ContextDependencyHelpers.create(
         RequireResolveContextDependency,
         /** @type {Range} */ (param.range),
         param,
         expr,
         options,
         {
            category: "commonjs",
            mode: weak ? "weak" : "sync"
         },
         parser,
         getContext()
      );
      if (!dep) return;
      dep.loc = /** @type {DependencyLocation} */ (expr.loc);
      dep.optional = Boolean(parser.scope.inTry);
      parser.state.current.addDependency(dep);
      return true;
   };
   return (expr, weak) => {
         if (!weak && options.commonjsMagicComments) {
            const { options: requireOptions, errors: commentErrors } =
               parser.parseCommentOptions(/** @type {Range} */ (expr.range));
@@ -518,52 +402,277 @@
         parser.state.module.addPresentationalDependency(dep);
         return true;
      };
};
class CommonJsImportsParserPlugin {
      /**
       * @param {CallExpression} expr call expression
       * @param {BasicEvaluatedExpression} param param
       * @param {boolean} weak weak
       * @returns {boolean | void} true when handled
    * Creates an instance of CommonJsImportsParserPlugin.
    * @param {JavascriptParserOptions} options parser options
       */
      const processResolveItem = (expr, param, weak) => {
         if (param.isString()) {
            const dep = new RequireResolveDependency(
               /** @type {string} */ (param.string),
               /** @type {Range} */ (param.range),
               getContext()
   constructor(options) {
      this.options = options;
   }
   /**
    * Applies the plugin by registering its hooks on the compiler.
    * @param {JavascriptParser} parser the parser
    * @returns {void}
    */
   apply(parser) {
      const options = this.options;
      parser.hooks.collectDestructuringAssignmentProperties.tap(
         PLUGIN_NAME,
         (expr) => {
            if (isRequireCallExpression(expr)) return true;
         }
      );
      const getContext = () => {
         if (parser.currentTagData) {
            const { context } =
               /** @type {CommonJsImportSettings} */
               (parser.currentTagData);
            return context;
         }
      };
      // #region metadata
      /**
       * Tap require expression.
       * @param {string} expression expression
       * @param {() => Members} getMembers get members
       */
      const tapRequireExpression = (expression, getMembers) => {
         parser.hooks.typeof
            .for(expression)
            .tap(
               PLUGIN_NAME,
               toConstantDependency(parser, JSON.stringify("function"))
            );
         parser.hooks.evaluateTypeof
            .for(expression)
            .tap(PLUGIN_NAME, evaluateToString("function"));
         parser.hooks.evaluateIdentifier
            .for(expression)
            .tap(
               PLUGIN_NAME,
               evaluateToIdentifier(expression, "require", getMembers, true)
            );
      };
      tapRequireExpression("require", () => []);
      tapRequireExpression("require.resolve", () => ["resolve"]);
      tapRequireExpression("require.resolveWeak", () => ["resolveWeak"]);
      // #endregion
      // Weird stuff //
      parser.hooks.assign.for("require").tap(PLUGIN_NAME, (expr) => {
         // to not leak to global "require", we need to define a local require here.
         const dep = new ConstDependency("var require;", 0);
         dep.loc = /** @type {DependencyLocation} */ (expr.loc);
         parser.state.module.addPresentationalDependency(dep);
         return true;
      });
      // #region Unsupported
      parser.hooks.call
         .for("require.main.require")
         .tap(
            PLUGIN_NAME,
            expressionIsUnsupported(
               parser,
               "require.main.require is not supported by webpack."
            )
         );
      parser.hooks.expression
         .for("module.parent.require")
         .tap(
            PLUGIN_NAME,
            expressionIsUnsupported(
               parser,
               "module.parent.require is not supported by webpack."
            )
         );
      parser.hooks.call
         .for("module.parent.require")
         .tap(
            PLUGIN_NAME,
            expressionIsUnsupported(
               parser,
               "module.parent.require is not supported by webpack."
            )
         );
      // #endregion
      // #region Renaming
      /**
       * Returns true when set undefined.
       * @param {Expression} expr expression
       * @returns {boolean} true when set undefined
       */
      const defineUndefined = (expr) => {
         // To avoid "not defined" error, replace the value with undefined
         const dep = new ConstDependency(
            "undefined",
            /** @type {Range} */ (expr.range)
            );
            dep.loc = /** @type {DependencyLocation} */ (expr.loc);
         parser.state.module.addPresentationalDependency(dep);
         return false;
      };
      parser.hooks.canRename.for("require").tap(PLUGIN_NAME, () => true);
      parser.hooks.rename.for("require").tap(PLUGIN_NAME, defineUndefined);
      // #endregion
      // #region Inspection
      const requireCache = createRequireCacheDependency(parser);
      parser.hooks.expression.for("require.cache").tap(PLUGIN_NAME, requireCache);
      // #endregion
      // #region Require as expression
      /**
       * Require as expression handler.
       * @param {Expression} expr expression
       * @returns {boolean} true when handled
       */
      const requireAsExpressionHandler = createRequireAsExpressionHandler(
         parser,
         options,
         getContext
      );
      parser.hooks.expression
         .for("require")
         .tap(PLUGIN_NAME, requireAsExpressionHandler);
      // #endregion
      // #region Require
      /**
       * Creates a require handler.
       * @param {boolean} callNew true, when require is called with new
       * @returns {(expr: CallExpression | NewExpression) => (boolean | void)} handler
       */
      const createRequireHandler = createRequireCallHandler(
         parser,
         options,
         getContext
      );
      parser.hooks.call
         .for("require")
         .tap(PLUGIN_NAME, createRequireHandler(false));
      parser.hooks.new
         .for("require")
         .tap(PLUGIN_NAME, createRequireHandler(true));
      parser.hooks.call
         .for("module.require")
         .tap(PLUGIN_NAME, createRequireHandler(false));
      parser.hooks.new
         .for("module.require")
         .tap(PLUGIN_NAME, createRequireHandler(true));
      // #endregion
      // #region Require with property access
      /**
       * Returns true when handled.
       * @param {Expression} expr expression
       * @param {CalleeMembers} calleeMembers callee members
       * @param {CallExpression} callExpr call expression
       * @param {Members} members members
       * @param {Range[]} memberRanges member ranges
       * @returns {boolean | void} true when handled
       */
      const chainHandler = (
         expr,
         calleeMembers,
         callExpr,
         members,
         memberRanges
      ) => {
         if (callExpr.arguments.length !== 1) return;
         const param = parser.evaluateExpression(callExpr.arguments[0]);
         if (
            param.isString() &&
            !getLocalModule(parser.state, /** @type {string} */ (param.string))
         ) {
            const dep = new CommonJsFullRequireDependency(
               /** @type {string} */ (param.string),
               /** @type {Range} */ (expr.range),
               members,
               /** @type {Range[]} */ memberRanges
            );
            dep.asiSafe = !parser.isAsiPosition(
               /** @type {Range} */ (expr.range)[0]
            );
            dep.optional = Boolean(parser.scope.inTry);
            dep.weak = weak;
            dep.loc = /** @type {DependencyLocation} */ (expr.loc);
            parser.state.current.addDependency(dep);
            return true;
         }
      };
      /**
       * Call chain handler.
       * @param {CallExpression} expr expression
       * @param {CalleeMembers} calleeMembers callee members
       * @param {CallExpression} callExpr call expression
       * @param {Members} members members
       * @param {Range[]} memberRanges member ranges
       * @returns {boolean | void} true when handled
       */
      const callChainHandler = (
         expr,
         calleeMembers,
         callExpr,
         members,
         memberRanges
      ) => {
         if (callExpr.arguments.length !== 1) return;
         const param = parser.evaluateExpression(callExpr.arguments[0]);
         if (
            param.isString() &&
            !getLocalModule(parser.state, /** @type {string} */ (param.string))
         ) {
            const dep = new CommonJsFullRequireDependency(
               /** @type {string} */ (param.string),
               /** @type {Range} */ (expr.callee.range),
               members,
               /** @type {Range[]} */ memberRanges
            );
            dep.call = true;
            dep.asiSafe = !parser.isAsiPosition(
               /** @type {Range} */ (expr.range)[0]
            );
            dep.optional = Boolean(parser.scope.inTry);
            dep.loc = /** @type {DependencyLocation} */ (expr.callee.loc);
            parser.state.current.addDependency(dep);
            parser.walkExpressions(expr.arguments);
            return true;
         }
      };
      parser.hooks.memberChainOfCallMemberChain
         .for("require")
         .tap(PLUGIN_NAME, chainHandler);
      parser.hooks.memberChainOfCallMemberChain
         .for("module.require")
         .tap(PLUGIN_NAME, chainHandler);
      parser.hooks.callMemberChainOfCallMemberChain
         .for("require")
         .tap(PLUGIN_NAME, callChainHandler);
      parser.hooks.callMemberChainOfCallMemberChain
         .for("module.require")
         .tap(PLUGIN_NAME, callChainHandler);
      // #endregion
      // #region Require.resolve
      /**
       * Processes the provided expr.
       * @param {CallExpression} expr call expression
       * @param {BasicEvaluatedExpression} param param
       * @param {boolean} weak weak
       * @returns {boolean | void} true when handled
       */
      const processResolveContext = (expr, param, weak) => {
         const dep = ContextDependencyHelpers.create(
            RequireResolveContextDependency,
            /** @type {Range} */ (param.range),
            param,
            expr,
            options,
            {
               category: "commonjs",
               mode: weak ? "weak" : "sync"
            },
      const processResolve = createProcessResolveHandler(
            parser,
            getContext()
         options,
         getContext
         );
         if (!dep) return;
         dep.loc = /** @type {DependencyLocation} */ (expr.loc);
         dep.optional = Boolean(parser.scope.inTry);
         parser.state.current.addDependency(dep);
         return true;
      };
      parser.hooks.call
         .for("require.resolve")
@@ -572,231 +681,12 @@
         .for("require.resolveWeak")
         .tap(PLUGIN_NAME, (expr) => processResolve(expr, true));
      // #endregion
      // #region Create require
      if (!options.createRequire) return;
      /** @type {ImportSource[]} */
      let moduleName = [];
      /** @type {string | undefined} */
      let specifierName;
      if (options.createRequire === true) {
         moduleName = ["module", "node:module"];
         specifierName = "createRequire";
      } else {
         let moduleName;
         const match = /^(.*) from (.*)$/.exec(options.createRequire);
         if (match) {
            [, specifierName, moduleName] = match;
         }
         if (!specifierName || !moduleName) {
            const err = new WebpackError(
               `Parsing javascript parser option "createRequire" failed, got ${JSON.stringify(
                  options.createRequire
               )}`
            );
            err.details =
               'Expected string in format "createRequire from module", where "createRequire" is specifier name and "module" name of the module';
            throw err;
         }
      }
      tapRequireExpressionTag(createdRequireIdentifierTag);
      tapRequireExpressionTag(createRequireSpecifierTag);
      parser.hooks.evaluateCallExpression
         .for(createRequireSpecifierTag)
         .tap(PLUGIN_NAME, (expr) => {
            const context = parseCreateRequireArguments(expr);
            if (context === undefined) return;
            const ident = parser.evaluatedVariable({
               tag: createdRequireIdentifierTag,
               data: { context },
               next: undefined
            });
            return new BasicEvaluatedExpression()
               .setIdentifier(ident, ident, () => [])
               .setSideEffects(false)
               .setRange(/** @type {Range} */ (expr.range));
         });
      parser.hooks.unhandledExpressionMemberChain
         .for(createdRequireIdentifierTag)
         .tap(PLUGIN_NAME, (expr, members) =>
            expressionIsUnsupported(
               parser,
               `createRequire().${members.join(".")} is not supported by webpack.`
            )(expr)
         );
      parser.hooks.canRename
         .for(createdRequireIdentifierTag)
         .tap(PLUGIN_NAME, () => true);
      parser.hooks.canRename
         .for(createRequireSpecifierTag)
         .tap(PLUGIN_NAME, () => true);
      parser.hooks.rename
         .for(createRequireSpecifierTag)
         .tap(PLUGIN_NAME, defineUndefined);
      parser.hooks.expression
         .for(createdRequireIdentifierTag)
         .tap(PLUGIN_NAME, requireAsExpressionHandler);
      parser.hooks.call
         .for(createdRequireIdentifierTag)
         .tap(PLUGIN_NAME, createRequireHandler(false));
      /**
       * @param {CallExpression} expr call expression
       * @returns {string | void} context
       */
      const parseCreateRequireArguments = (expr) => {
         const args = expr.arguments;
         if (args.length !== 1) {
            const err = new WebpackError(
               "module.createRequire supports only one argument."
            );
            err.loc = /** @type {DependencyLocation} */ (expr.loc);
            parser.state.module.addWarning(err);
            return;
         }
         const arg = args[0];
         const evaluated = parser.evaluateExpression(arg);
         if (!evaluated.isString()) {
            const err = new WebpackError(
               "module.createRequire failed parsing argument."
            );
            err.loc = /** @type {DependencyLocation} */ (arg.loc);
            parser.state.module.addWarning(err);
            return;
         }
         const ctx = /** @type {string} */ (evaluated.string).startsWith("file://")
            ? fileURLToPath(/** @type {string} */ (evaluated.string))
            : /** @type {string} */ (evaluated.string);
         // argument always should be a filename
         return ctx.slice(0, ctx.lastIndexOf(ctx.startsWith("/") ? "/" : "\\"));
      };
      parser.hooks.import.tap(
         {
            name: PLUGIN_NAME,
            stage: -10
         },
         (statement, source) => {
            if (
               !moduleName.includes(source) ||
               statement.specifiers.length !== 1 ||
               statement.specifiers[0].type !== "ImportSpecifier" ||
               statement.specifiers[0].imported.type !== "Identifier" ||
               statement.specifiers[0].imported.name !== specifierName
            ) {
               return;
            }
            // clear for 'import { createRequire as x } from "module"'
            // if any other specifier was used import module
            const clearDep = new ConstDependency(
               parser.isAsiPosition(/** @type {Range} */ (statement.range)[0])
                  ? ";"
                  : "",
               /** @type {Range} */ (statement.range)
            );
            clearDep.loc = /** @type {DependencyLocation} */ (statement.loc);
            parser.state.module.addPresentationalDependency(clearDep);
            parser.unsetAsiPosition(/** @type {Range} */ (statement.range)[1]);
            return true;
         }
      );
      parser.hooks.importSpecifier.tap(
         {
            name: PLUGIN_NAME,
            stage: -10
         },
         (statement, source, id, name) => {
            if (!moduleName.includes(source) || id !== specifierName) return;
            parser.tagVariable(name, createRequireSpecifierTag);
            return true;
         }
      );
      parser.hooks.preDeclarator.tap(PLUGIN_NAME, (declarator) => {
         if (
            declarator.id.type !== "Identifier" ||
            !declarator.init ||
            declarator.init.type !== "CallExpression" ||
            declarator.init.callee.type !== "Identifier"
         ) {
            return;
         }
         const variableInfo = parser.getVariableInfo(declarator.init.callee.name);
         if (
            variableInfo instanceof VariableInfo &&
            variableInfo.tagInfo &&
            variableInfo.tagInfo.tag === createRequireSpecifierTag
         ) {
            const context = parseCreateRequireArguments(declarator.init);
            if (context === undefined) return;
            parser.tagVariable(declarator.id.name, createdRequireIdentifierTag, {
               name: declarator.id.name,
               context
            });
            return true;
         }
      });
      parser.hooks.memberChainOfCallMemberChain
         .for(createRequireSpecifierTag)
         .tap(PLUGIN_NAME, (expr, calleeMembers, callExpr, members) => {
            if (
               calleeMembers.length !== 0 ||
               members.length !== 1 ||
               members[0] !== "cache"
            ) {
               return;
            }
            // createRequire().cache
            const context = parseCreateRequireArguments(callExpr);
            if (context === undefined) return;
            return requireCache(expr);
         });
      parser.hooks.callMemberChainOfCallMemberChain
         .for(createRequireSpecifierTag)
         .tap(PLUGIN_NAME, (expr, calleeMembers, innerCallExpression, members) => {
            if (
               calleeMembers.length !== 0 ||
               members.length !== 1 ||
               members[0] !== "resolve"
            ) {
               return;
            }
            // createRequire().resolve()
            return processResolve(expr, false);
         });
      parser.hooks.expressionMemberChain
         .for(createdRequireIdentifierTag)
         .tap(PLUGIN_NAME, (expr, members) => {
            // require.cache
            if (members.length === 1 && members[0] === "cache") {
               return requireCache(expr);
            }
         });
      parser.hooks.callMemberChain
         .for(createdRequireIdentifierTag)
         .tap(PLUGIN_NAME, (expr, members) => {
            // require.resolve()
            if (members.length === 1 && members[0] === "resolve") {
               return processResolve(expr, false);
            }
         });
      parser.hooks.call
         .for(createRequireSpecifierTag)
         .tap(PLUGIN_NAME, (expr) => {
            const clearDep = new ConstDependency(
               "/* createRequire() */ undefined",
               /** @type {Range} */ (expr.range)
            );
            clearDep.loc = /** @type {DependencyLocation} */ (expr.loc);
            parser.state.module.addPresentationalDependency(clearDep);
            return true;
         });
      // #endregion
   }
}
module.exports = CommonJsImportsParserPlugin;
module.exports.createProcessResolveHandler = createProcessResolveHandler;
module.exports.createRequireAsExpressionHandler =
   createRequireAsExpressionHandler;
module.exports.createRequireCacheDependency = createRequireCacheDependency;
module.exports.createRequireHandler = createRequireCallHandler;