WXL
4 天以前 2cc85c64f1c64a2dbaeae276a3e2ca8420de76b7
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,25 +32,381 @@
/** @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";
/**
 * Checks whether this object is require call expression.
 * @param {Expression} expression expression
 * @returns {boolean} true, when expression is `require(...)` or `module.require(...)`
 */
const isRequireCallExpression = (expression) => {
   if (expression.type !== "CallExpression") return false;
   const { callee } = expression;
   if (callee.type === "Identifier") {
      return callee.name === "require";
   }
   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"
      );
   }
   return false;
};
/**
 * 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
   ]);
/**
 * 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 createRequireAsExpressionHandler =
   (parser, options, getContext) => (expr) => {
      const dep = new CommonJsRequireContextDependency(
         {
            request: /** @type {string} */ (options.unknownContextRequest),
            recursive: /** @type {boolean} */ (options.unknownContextRecursive),
            regExp: /** @type {RegExp} */ (options.unknownContextRegExp),
            mode: "sync"
         },
         /** @type {Range} */ (expr.range),
         undefined,
         parser.scope.inShorthand,
         getContext()
      );
      dep.critical =
         options.unknownContextCritical &&
         "require function is used in a way in which dependencies cannot be statically extracted";
      dep.loc = /** @type {DependencyLocation} */ (expr.loc);
      dep.optional = Boolean(parser.scope.inTry);
      parser.state.current.addDependency(dep);
      return true;
   };
/**
 * 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(),
            referencedExports
         );
         dep.loc = /** @type {DependencyLocation} */ (expr.loc);
         dep.optional = Boolean(parser.scope.inTry);
         parser.state.current.addDependency(dep);
         return true;
      }
   };
   /**
    * 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),
         param,
         expr,
         options,
         {
            category: "commonjs",
            referencedExports
         },
         parser,
         undefined,
         getContext()
      );
      if (!dep) return;
      dep.loc = /** @type {DependencyLocation} */ (expr.loc);
      dep.optional = Boolean(parser.scope.inTry);
      parser.state.current.addDependency(dep);
      return true;
   };
   return (callNew) => (expr) => {
      if (options.commonjsMagicComments) {
         const { options: requireOptions, 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}`,
                     /** @type {DependencyLocation} */ (comment.loc)
                  )
               );
            }
         }
         if (requireOptions && requireOptions.webpackIgnore !== undefined) {
            if (typeof requireOptions.webpackIgnore !== "boolean") {
               parser.state.module.addWarning(
                  new UnsupportedFeatureWarning(
                     `\`webpackIgnore\` expected a boolean, but received: ${requireOptions.webpackIgnore}.`,
                     /** @type {DependencyLocation} */ (expr.loc)
                  )
               );
            } else if (requireOptions.webpackIgnore) {
               // Do not instrument `require()` if `webpackIgnore` is `true`
               return true;
            }
         }
      }
      if (expr.arguments.length !== 1) return;
      /** @type {null | LocalModule} */
      let localModule;
      const param = parser.evaluateExpression(expr.arguments[0]);
      if (param.isConditional()) {
         let isExpression = false;
         for (const p of /** @type {BasicEvaluatedExpression[]} */ (
            param.options
         )) {
            const result = processRequireItem(expr, p);
            if (result === undefined) {
               isExpression = true;
            }
         }
         if (!isExpression) {
            const dep = new RequireHeaderDependency(
               /** @type {Range} */ (expr.callee.range)
            );
            dep.loc = /** @type {DependencyLocation} */ (expr.loc);
            parser.state.module.addPresentationalDependency(dep);
            return true;
         }
      }
      if (
         param.isString() &&
         (localModule = getLocalModule(
            parser.state,
            /** @type {string} */ (param.string)
         ))
      ) {
         localModule.flagUsed();
         const dep = new LocalModuleDependency(
            localModule,
            /** @type {Range} */ (expr.range),
            callNew
         );
         dep.loc = /** @type {DependencyLocation} */ (expr.loc);
         parser.state.module.addPresentationalDependency(dep);
      } else {
         const result = processRequireItem(expr, param);
         if (result === undefined) {
            processRequireContext(expr, param);
         } else {
            const dep = new RequireHeaderDependency(
               /** @type {Range} */ (expr.callee.range)
            );
            dep.loc = /** @type {DependencyLocation} */ (expr.loc);
            parser.state.module.addPresentationalDependency(dep);
         }
      }
      return true;
   };
};
/**
 * 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 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));
         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}`,
                     /** @type {DependencyLocation} */ (comment.loc)
                  )
               );
            }
         }
         if (requireOptions && requireOptions.webpackIgnore !== undefined) {
            if (typeof requireOptions.webpackIgnore !== "boolean") {
               parser.state.module.addWarning(
                  new UnsupportedFeatureWarning(
                     `\`webpackIgnore\` expected a boolean, but received: ${requireOptions.webpackIgnore}.`,
                     /** @type {DependencyLocation} */ (expr.loc)
                  )
               );
            } else if (requireOptions.webpackIgnore) {
               // Do not instrument `require()` if `webpackIgnore` is `true`
               return true;
            }
         }
      }
      if (expr.arguments.length !== 1) return;
      const param = parser.evaluateExpression(expr.arguments[0]);
      if (param.isConditional()) {
         for (const option of /** @type {BasicEvaluatedExpression[]} */ (
            param.options
         )) {
            const result = processResolveItem(expr, option, weak);
            if (result === undefined) {
               processResolveContext(expr, option, weak);
            }
         }
         const dep = new RequireResolveHeaderDependency(
            /** @type {Range} */ (expr.callee.range)
         );
         dep.loc = /** @type {DependencyLocation} */ (expr.loc);
         parser.state.module.addPresentationalDependency(dep);
         return true;
      }
      const result = processResolveItem(expr, param, weak);
      if (result === undefined) {
         processResolveContext(expr, param, weak);
      }
      const dep = new RequireResolveHeaderDependency(
         /** @type {Range} */ (expr.callee.range)
      );
      dep.loc = /** @type {DependencyLocation} */ (expr.loc);
      parser.state.module.addPresentationalDependency(dep);
      return true;
   };
};
class CommonJsImportsParserPlugin {
   /**
    * Creates an instance of CommonJsImportsParserPlugin.
    * @param {JavascriptParserOptions} options parser options
    */
   constructor(options) {
@@ -61,11 +414,19 @@
   }
   /**
    * 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 } =
@@ -77,6 +438,7 @@
      // #region metadata
      /**
       * Tap require expression.
       * @param {string} expression expression
       * @param {() => Members} getMembers get members
       */
@@ -96,20 +458,6 @@
               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"]);
@@ -157,6 +505,7 @@
      // #region Renaming
      /**
       * Returns true when set undefined.
       * @param {Expression} expr expression
       * @returns {boolean} true when set undefined
       */
@@ -175,45 +524,22 @@
      // #endregion
      // #region Inspection
      const requireCache = toConstantDependency(
         parser,
         RuntimeGlobals.moduleCache,
         [
            RuntimeGlobals.moduleCache,
            RuntimeGlobals.moduleId,
            RuntimeGlobals.moduleLoaded
         ]
      );
      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 = (expr) => {
         const dep = new CommonJsRequireContextDependency(
            {
               request: /** @type {string} */ (options.unknownContextRequest),
               recursive: /** @type {boolean} */ (options.unknownContextRecursive),
               regExp: /** @type {RegExp} */ (options.unknownContextRegExp),
               mode: "sync"
            },
            /** @type {Range} */ (expr.range),
            undefined,
            parser.scope.inShorthand,
            getContext()
         );
         dep.critical =
            options.unknownContextCritical &&
            "require function is used in a way in which dependencies cannot be statically extracted";
         dep.loc = /** @type {DependencyLocation} */ (expr.loc);
         dep.optional = Boolean(parser.scope.inTry);
         parser.state.current.addDependency(dep);
         return true;
      };
      const requireAsExpressionHandler = createRequireAsExpressionHandler(
         parser,
         options,
         getContext
      );
      parser.hooks.expression
         .for("require")
         .tap(PLUGIN_NAME, requireAsExpressionHandler);
@@ -221,134 +547,15 @@
      // #region Require
      /**
       * @param {CallExpression | NewExpression} expr expression
       * @param {BasicEvaluatedExpression} param param
       * @returns {boolean | void} true when handled
       */
      const processRequireItem = (expr, param) => {
         if (param.isString()) {
            const dep = new CommonJsRequireDependency(
               /** @type {string} */ (param.string),
               /** @type {Range} */ (param.range),
               getContext()
            );
            dep.loc = /** @type {DependencyLocation} */ (expr.loc);
            dep.optional = Boolean(parser.scope.inTry);
            parser.state.current.addDependency(dep);
            return true;
         }
      };
      /**
       * @param {CallExpression | NewExpression} expr expression
       * @param {BasicEvaluatedExpression} param param
       * @returns {boolean | void} true when handled
       */
      const processRequireContext = (expr, param) => {
         const dep = ContextDependencyHelpers.create(
            CommonJsRequireContextDependency,
            /** @type {Range} */ (expr.range),
            param,
            expr,
            options,
            {
               category: "commonjs"
            },
            parser,
            undefined,
            getContext()
         );
         if (!dep) return;
         dep.loc = /** @type {DependencyLocation} */ (expr.loc);
         dep.optional = Boolean(parser.scope.inTry);
         parser.state.current.addDependency(dep);
         return true;
      };
      /**
       * Creates a require handler.
       * @param {boolean} callNew true, when require is called with new
       * @returns {(expr: CallExpression | NewExpression) => (boolean | void)} handler
       */
      const createRequireHandler = (callNew) => (expr) => {
         if (options.commonjsMagicComments) {
            const { options: requireOptions, 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}`,
                        /** @type {DependencyLocation} */ (comment.loc)
                     )
                  );
               }
            }
            if (requireOptions && requireOptions.webpackIgnore !== undefined) {
               if (typeof requireOptions.webpackIgnore !== "boolean") {
                  parser.state.module.addWarning(
                     new UnsupportedFeatureWarning(
                        `\`webpackIgnore\` expected a boolean, but received: ${requireOptions.webpackIgnore}.`,
                        /** @type {DependencyLocation} */ (expr.loc)
                     )
                  );
               } else if (requireOptions.webpackIgnore) {
                  // Do not instrument `require()` if `webpackIgnore` is `true`
                  return true;
               }
            }
         }
         if (expr.arguments.length !== 1) return;
         let localModule;
         const param = parser.evaluateExpression(expr.arguments[0]);
         if (param.isConditional()) {
            let isExpression = false;
            for (const p of /** @type {BasicEvaluatedExpression[]} */ (
               param.options
            )) {
               const result = processRequireItem(expr, p);
               if (result === undefined) {
                  isExpression = true;
               }
            }
            if (!isExpression) {
               const dep = new RequireHeaderDependency(
                  /** @type {Range} */ (expr.callee.range)
               );
               dep.loc = /** @type {DependencyLocation} */ (expr.loc);
               parser.state.module.addPresentationalDependency(dep);
               return true;
            }
         }
         if (
            param.isString() &&
            (localModule = getLocalModule(
               parser.state,
               /** @type {string} */ (param.string)
            ))
         ) {
            localModule.flagUsed();
            const dep = new LocalModuleDependency(
               localModule,
               /** @type {Range} */ (expr.range),
               callNew
            );
            dep.loc = /** @type {DependencyLocation} */ (expr.loc);
            parser.state.module.addPresentationalDependency(dep);
         } else {
            const result = processRequireItem(expr, param);
            if (result === undefined) {
               processRequireContext(expr, param);
            } else {
               const dep = new RequireHeaderDependency(
                  /** @type {Range} */ (expr.callee.range)
               );
               dep.loc = /** @type {DependencyLocation} */ (expr.loc);
               parser.state.module.addPresentationalDependency(dep);
            }
         }
         return true;
      };
      const createRequireHandler = createRequireCallHandler(
         parser,
         options,
         getContext
      );
      parser.hooks.call
         .for("require")
         .tap(PLUGIN_NAME, createRequireHandler(false));
@@ -365,6 +572,7 @@
      // #region Require with property access
      /**
       * Returns true when handled.
       * @param {Expression} expr expression
       * @param {CalleeMembers} calleeMembers callee members
       * @param {CallExpression} callExpr call expression
@@ -401,6 +609,7 @@
         }
      };
      /**
       * Call chain handler.
       * @param {CallExpression} expr expression
       * @param {CalleeMembers} calleeMembers callee members
       * @param {CallExpression} callExpr call expression
@@ -454,116 +663,16 @@
      // #region Require.resolve
      /**
       * Processes the provided expr.
       * @param {CallExpression} expr call expression
       * @param {boolean} weak weak
       * @returns {boolean | void} true when handled
       */
      const processResolve = (expr, weak) => {
         if (!weak && options.commonjsMagicComments) {
            const { options: requireOptions, 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}`,
                        /** @type {DependencyLocation} */ (comment.loc)
                     )
                  );
               }
            }
            if (requireOptions && requireOptions.webpackIgnore !== undefined) {
               if (typeof requireOptions.webpackIgnore !== "boolean") {
                  parser.state.module.addWarning(
                     new UnsupportedFeatureWarning(
                        `\`webpackIgnore\` expected a boolean, but received: ${requireOptions.webpackIgnore}.`,
                        /** @type {DependencyLocation} */ (expr.loc)
                     )
                  );
               } else if (requireOptions.webpackIgnore) {
                  // Do not instrument `require()` if `webpackIgnore` is `true`
                  return true;
               }
            }
         }
         if (expr.arguments.length !== 1) return;
         const param = parser.evaluateExpression(expr.arguments[0]);
         if (param.isConditional()) {
            for (const option of /** @type {BasicEvaluatedExpression[]} */ (
               param.options
            )) {
               const result = processResolveItem(expr, option, weak);
               if (result === undefined) {
                  processResolveContext(expr, option, weak);
               }
            }
            const dep = new RequireResolveHeaderDependency(
               /** @type {Range} */ (expr.callee.range)
            );
            dep.loc = /** @type {DependencyLocation} */ (expr.loc);
            parser.state.module.addPresentationalDependency(dep);
            return true;
         }
         const result = processResolveItem(expr, param, weak);
         if (result === undefined) {
            processResolveContext(expr, param, weak);
         }
         const dep = new RequireResolveHeaderDependency(
            /** @type {Range} */ (expr.callee.range)
         );
         dep.loc = /** @type {DependencyLocation} */ (expr.loc);
         parser.state.module.addPresentationalDependency(dep);
         return true;
      };
      /**
       * @param {CallExpression} expr call expression
       * @param {BasicEvaluatedExpression} param param
       * @param {boolean} weak weak
       * @returns {boolean | void} true when handled
       */
      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;
         }
      };
      /**
       * @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;
      };
      const processResolve = createProcessResolveHandler(
         parser,
         options,
         getContext
      );
      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;