WXL
3 天以前 9bce51f651aad297ef9eb6df832bfdaf1de05d84
node_modules/webpack/lib/library/ModuleLibraryPlugin.js
@@ -7,11 +7,13 @@
const { ConcatSource } = require("webpack-sources");
const { UsageState } = require("../ExportsInfo");
const ExternalModule = require("../ExternalModule");
const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency");
const ConcatenatedModule = require("../optimize/ConcatenatedModule");
const propertyAccess = require("../util/propertyAccess");
const { getEntryRuntime } = require("../util/runtime");
const { propertyAccess } = require("../util/property");
const { getEntryRuntime, getRuntimeKey } = require("../util/runtime");
const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
/** @typedef {import("webpack-sources").Source} Source */
@@ -20,22 +22,29 @@
/** @typedef {import("../../declarations/WebpackOptions").LibraryExport} LibraryExport */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../Module").BuildMeta} BuildMeta */
/** @typedef {import("../Module").RuntimeRequirements} RuntimeRequirements */
/** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */
/** @typedef {import("../javascript/JavascriptModulesPlugin").ModuleRenderContext} ModuleRenderContext */
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
/**
 * Defines the shared type used by this module.
 * @template T
 * @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T>
 */
/**
 * Defines the module library plugin options type used by this module.
 * @typedef {object} ModuleLibraryPluginOptions
 * @property {LibraryType} type
 */
/**
 * Defines the module library plugin parsed type used by this module.
 * @typedef {object} ModuleLibraryPluginParsed
 * @property {string} name
 * @property {LibraryExport=} export
@@ -44,11 +53,13 @@
const PLUGIN_NAME = "ModuleLibraryPlugin";
/**
 * Represents the module library plugin runtime component.
 * @typedef {ModuleLibraryPluginParsed} T
 * @extends {AbstractLibraryPlugin<ModuleLibraryPluginParsed>}
 */
class ModuleLibraryPlugin extends AbstractLibraryPlugin {
   /**
    * Creates an instance of ModuleLibraryPlugin.
    * @param {ModuleLibraryPluginOptions} options the plugin options
    */
   constructor(options) {
@@ -59,7 +70,7 @@
   }
   /**
    * Apply the plugin
    * Applies the plugin by registering its hooks on the compiler.
    * @param {Compiler} compiler the compiler instance
    * @returns {void}
    */
@@ -69,11 +80,36 @@
      compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
         const { onDemandExportsGeneration } =
            ConcatenatedModule.getCompilationHooks(compilation);
         onDemandExportsGeneration.tap(PLUGIN_NAME, (_module) => true);
         onDemandExportsGeneration.tap(
            PLUGIN_NAME,
            (module, runtimes, source, finalName) => {
               /** @type {BuildMeta} */
               const buildMeta = module.buildMeta || (module.buildMeta = {});
               /** @type {BuildMeta["exportsSourceByRuntime"]} */
               const exportsSourceByRuntime =
                  buildMeta.exportsSourceByRuntime ||
                  (buildMeta.exportsSourceByRuntime = new Map());
               /** @type {BuildMeta["exportsFinalNameByRuntime"]} */
               const exportsFinalNameByRuntime =
                  buildMeta.exportsFinalNameByRuntime ||
                  (buildMeta.exportsFinalNameByRuntime = new Map());
               for (const runtime of runtimes) {
                  const key = getRuntimeKey(runtime);
                  exportsSourceByRuntime.set(key, source);
                  exportsFinalNameByRuntime.set(key, finalName);
               }
               return true;
            }
         );
      });
   }
   /**
    * Finish entry module.
    * @param {Module} module the exporting entry module
    * @param {string} entryName the name of the entrypoint
    * @param {LibraryContext<T>} libraryContext context
@@ -94,8 +130,13 @@
         exportsInfo.canMangleUse = false;
      } else {
         const exportsInfo = moduleGraph.getExportsInfo(module);
         // If the entry module is commonjs, its exports cannot be mangled
         if (module.buildMeta && module.buildMeta.treatAsCommonJs) {
         if (
            // If the entry module is commonjs, its exports cannot be mangled
            (module.buildMeta && module.buildMeta.treatAsCommonJs) ||
            // The entry module provides unknown exports
            exportsInfo._otherExportsInfo.provided === null
         ) {
            exportsInfo.setUsedInUnknownWay(runtime);
         } else {
            exportsInfo.setAllKnownExportsUsed(runtime);
@@ -105,8 +146,9 @@
   }
   /**
    * Returns preprocess as needed by overriding.
    * @param {LibraryOptions} library normalized library option
    * @returns {T | false} preprocess as needed by overriding
    * @returns {T} preprocess as needed by overriding
    */
   parseOptions(library) {
      const { name } = library;
@@ -123,28 +165,114 @@
   }
   /**
    * Analyze unknown provided exports.
    * @param {Source} source source
    * @param {Module} module module
    * @param {ModuleGraph} moduleGraph moduleGraph
    * @param {RuntimeSpec} runtime chunk runtime
    * @param {[string, string][]} exports exports
    * @param {Set<string>} alreadyRenderedExports already rendered exports
    * @returns {ConcatSource} source with null provided exports
    */
   _analyzeUnknownProvidedExports(
      source,
      module,
      moduleGraph,
      runtime,
      exports,
      alreadyRenderedExports
   ) {
      const result = new ConcatSource(source);
      /** @type {Set<string>} */
      const moduleRequests = new Set();
      /** @type {Map<string, string>} */
      const unknownProvidedExports = new Map();
      /**
       * Resolves dynamic star reexport.
       * @param {Module} module the module
       * @param {boolean} isDynamicReexport if module is dynamic reexported
       */
      const resolveDynamicStarReexport = (module, isDynamicReexport) => {
         for (const connection of moduleGraph.getOutgoingConnections(module)) {
            const dep = connection.dependency;
            // Only handle star-reexport statement
            if (
               dep instanceof HarmonyExportImportedSpecifierDependency &&
               dep.name === null
            ) {
               const importedModule = connection.resolvedModule;
               const importedModuleExportsInfo =
                  moduleGraph.getExportsInfo(importedModule);
               // The imported module provides unknown exports
               // So keep the reexports rendered in the bundle
               if (
                  dep.getMode(moduleGraph, runtime).type === "dynamic-reexport" &&
                  importedModuleExportsInfo._otherExportsInfo.provided === null
               ) {
                  // Handle export * from 'external'
                  if (importedModule instanceof ExternalModule) {
                     moduleRequests.add(importedModule.userRequest);
                  } else {
                     resolveDynamicStarReexport(importedModule, true);
                  }
               }
               // If importer modules existing `dynamic-reexport` dependency
               // We should keep export statement rendered in the bundle
               else if (isDynamicReexport) {
                  for (const exportInfo of importedModuleExportsInfo.orderedExports) {
                     if (!exportInfo.provided || exportInfo.name === "default") {
                        continue;
                     }
                     const originalName = exportInfo.name;
                     const usedName = exportInfo.getUsedName(originalName, runtime);
                     if (!alreadyRenderedExports.has(originalName) && usedName) {
                        unknownProvidedExports.set(originalName, usedName);
                     }
                  }
               }
            }
         }
      };
      resolveDynamicStarReexport(module, false);
      for (const request of moduleRequests) {
         result.add(`export * from "${request}";\n`);
      }
      for (const [origin, used] of unknownProvidedExports) {
         exports.push([
            origin,
            `${RuntimeGlobals.exports}${propertyAccess([used])}`
         ]);
      }
      return result;
   }
   /**
    * Renders source with library export.
    * @param {Source} source source
    * @param {Module} module module
    * @param {StartupRenderContext} renderContext render context
    * @param {LibraryContext<T>} libraryContext context
    * @returns {Source} source with library export
    */
   renderStartup(
      source,
      module,
      {
   renderStartup(source, module, renderContext, { options, compilation }) {
      const {
         moduleGraph,
         chunk,
         codeGenerationResults,
         inlined,
         inlinedInIIFE,
         runtimeTemplate
      },
      { options, compilation }
   ) {
      const result = new ConcatSource(source);
      const exportsInfo = options.export
      } = renderContext;
      let result = new ConcatSource(source);
      const exportInfos = options.export
         ? [
               moduleGraph.getExportInfo(
                  module,
@@ -152,19 +280,46 @@
               )
            ]
         : moduleGraph.getExportsInfo(module).orderedExports;
      const definitions =
         inlined && !inlinedInIIFE
            ? (module.buildMeta && module.buildMeta.exportsFinalName) || {}
            : {};
      const exportsFinalNameByRuntime =
         (module.buildMeta &&
            module.buildMeta.exportsFinalNameByRuntime &&
            module.buildMeta.exportsFinalNameByRuntime.get(
               getRuntimeKey(chunk.runtime)
            )) ||
         {};
      const isInlinedEntryWithoutIIFE = inlined && !inlinedInIIFE;
      // Direct export bindings from on-demand concatenation
      const definitions = isInlinedEntryWithoutIIFE
         ? exportsFinalNameByRuntime
         : {};
      /** @type {string[]} */
      const shortHandedExports = [];
      /** @type {[string, string][]} */
      const exports = [];
      /** @type {Set<string>} */
      const alreadyRenderedExports = new Set();
      const isAsync = moduleGraph.isAsync(module);
      const treatAsCommonJs =
         module.buildMeta && module.buildMeta.treatAsCommonJs;
      const skipRenderDefaultExport = Boolean(treatAsCommonJs);
      const moduleExportsInfo = moduleGraph.getExportsInfo(module);
      // Define ESM compatibility flag will rely on `__webpack_exports__`
      const needHarmonyCompatibilityFlag =
         moduleExportsInfo.otherExportsInfo.getUsed(chunk.runtime) !==
            UsageState.Unused ||
         moduleExportsInfo
            .getReadOnlyExportInfo("__esModule")
            .getUsed(chunk.runtime) !== UsageState.Unused;
      let needExportsDeclaration =
         !isInlinedEntryWithoutIIFE || isAsync || needHarmonyCompatibilityFlag;
      if (isAsync) {
         result.add(
@@ -172,17 +327,18 @@
         );
      }
      outer: for (const exportInfo of exportsInfo) {
      // Try to find all known exports of the entry module
      outer: for (const exportInfo of exportInfos) {
         if (!exportInfo.provided) continue;
         const originalName = exportInfo.name;
         // Skip rendering the default export in some cases
         if (skipRenderDefaultExport && originalName === "default") continue;
         // Try to find all exports from the reexported modules
         const target = exportInfo.findTarget(moduleGraph, (_m) => true);
         if (target) {
            const reexportsInfo = moduleGraph.getExportsInfo(target.module);
            for (const reexportInfo of reexportsInfo.orderedExports) {
               if (
                  reexportInfo.provided === false &&
@@ -199,14 +355,16 @@
            (exportInfo.getUsedName(originalName, chunk.runtime));
         /** @type {string | undefined} */
         const definition = definitions[usedName];
         /** @type {string | undefined} */
         let finalName;
         if (definition) {
            finalName = definition;
         } else {
            // Fallback to `__webpack_exports__` property access
            // when no direct export binding was found
            finalName = `${RuntimeGlobals.exports}${Template.toIdentifier(originalName)}`;
            needExportsDeclaration = true;
            result.add(
               `${runtimeTemplate.renderConst()} ${finalName} = ${RuntimeGlobals.exports}${propertyAccess(
                  [usedName]
@@ -215,6 +373,7 @@
         }
         if (
            // If the name includes `property access` and `call expressions`
            finalName &&
            (finalName.includes(".") ||
               finalName.includes("[") ||
@@ -245,9 +404,13 @@
                  : `${finalName} as ${originalName}`
            );
         }
         alreadyRenderedExports.add(originalName);
      }
      // Add default export `__webpack_exports__` statement to keep better compatibility
      if (treatAsCommonJs) {
         needExportsDeclaration = true;
         shortHandedExports.push(`${RuntimeGlobals.exports} as default`);
      }
@@ -255,36 +418,51 @@
         result.add(`export { ${shortHandedExports.join(", ")} };\n`);
      }
      result = this._analyzeUnknownProvidedExports(
         result,
         module,
         moduleGraph,
         chunk.runtime,
         exports,
         alreadyRenderedExports
      );
      for (const [exportName, final] of exports) {
         result.add(
            `export ${runtimeTemplate.renderConst()} ${exportName} = ${final};\n`
         );
      }
      if (!needExportsDeclaration) {
         renderContext.needExportsDeclaration = false;
      }
      return result;
   }
   /**
    * Renders module content.
    * @param {Source} source source
    * @param {Module} module module
    * @param {ModuleRenderContext} renderContext render context
    * @param {Omit<LibraryContext<T>, 'options'>} libraryContext context
    * @param {Omit<LibraryContext<T>, "options">} libraryContext context
    * @returns {Source} source with library export
    */
   renderModuleContent(
      source,
      module,
      { factory, inlinedInIIFE },
      { factory, inlinedInIIFE, chunk },
      libraryContext
   ) {
      // Re-add `factoryExportsBinding` to the source
      // when the module is rendered as a factory or treated as an inlined (startup) module but wrapped in an IIFE
      if (
         (inlinedInIIFE || factory) &&
      const exportsSource =
         module.buildMeta &&
         module.buildMeta.factoryExportsBinding
      ) {
         return new ConcatSource(module.buildMeta.factoryExportsBinding, source);
         module.buildMeta.exportsSourceByRuntime &&
         module.buildMeta.exportsSourceByRuntime.get(getRuntimeKey(chunk.runtime));
      // Re-add the module's exports source when rendered in factory
      // or as an inlined startup module wrapped in an IIFE
      if ((inlinedInIIFE || factory) && exportsSource) {
         return new ConcatSource(exportsSource, source);
      }
      return source;
   }