WXL
4 天以前 9bce51f651aad297ef9eb6df832bfdaf1de05d84
node_modules/webpack/lib/schemes/VirtualUrlPlugin.js
@@ -5,36 +5,34 @@
"use strict";
const { NormalModule } = require("..");
const { getContext } = require("loader-runner");
const ModuleNotFoundError = require("../ModuleNotFoundError");
const NormalModule = require("../NormalModule");
const { isAbsolute, join } = require("../util/fs");
const { parseResourceWithoutFragment } = require("../util/identifier");
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../NormalModule")} NormalModule */
/**
 * @template T
 * @typedef {import("../../declarations/LoaderContext").LoaderContext<T>} LoaderContext
 */
const DEFAULT_SCHEME = "virtual";
const PLUGIN_NAME = "VirtualUrlPlugin";
const DEFAULT_SCHEME = "virtual";
/**
 * Defines the compiler type used by this module.
 * @typedef {import("../Compiler")} Compiler
 * @typedef {import("../../declarations/plugins/schemes/VirtualUrlPlugin").VirtualModule} VirtualModuleConfig
 * @typedef {import("../../declarations/plugins/schemes/VirtualUrlPlugin").VirtualModuleContent} VirtualModuleInput
 * @typedef {import("../../declarations/plugins/schemes/VirtualUrlPlugin").VirtualUrlOptions} VirtualUrlOptions
 */
/** @typedef {(loaderContext: LoaderContext<EXPECTED_ANY>) => Promise<string | Buffer> | string | Buffer} SourceFn */
/** @typedef {() => string} VersionFn */
/**
 * @typedef {object} VirtualModuleConfig
 * @property {string=} type the module type
 * @property {SourceFn} source the source function
 * @property {VersionFn | true | string=} version optional version function or value
 */
/**
 * @typedef {string | SourceFn | VirtualModuleConfig} VirtualModuleInput
 */
/** @typedef {{ [key: string]: VirtualModuleInput }} VirtualModules */
/**
 * Defines the loader context type used by this module.
 * @template T
 * @typedef {import("../../declarations/LoaderContext").LoaderContext<T>} LoaderContext
 */
/**
 * Normalizes a virtual module definition into a standard format
@@ -58,17 +56,19 @@
   return virtualConfig;
}
/** @typedef {{ [key: string]: VirtualModuleConfig }} NormalizedModules */
/**
 * Normalizes all virtual modules with the given scheme
 * @param {VirtualModules} virtualConfigs The virtual modules to normalize
 * @param {string} scheme The URL scheme to use
 * @returns {{ [key: string]: VirtualModuleConfig }} The normalized virtual modules
 * @returns {NormalizedModules} The normalized virtual modules
 */
function normalizeModules(virtualConfigs, scheme) {
   return Object.keys(virtualConfigs).reduce((pre, id) => {
      pre[toVid(id, scheme)] = normalizeModule(virtualConfigs[id]);
      return pre;
   }, /** @type {{ [key: string]: VirtualModuleConfig }} */ ({}));
   }, /** @type {NormalizedModules} */ ({}));
}
/**
@@ -79,6 +79,16 @@
 */
function toVid(id, scheme) {
   return `${scheme}:${id}`;
}
/**
 * Converts a virtual module id to a module id
 * @param {string} vid The virtual module id
 * @param {string} scheme The URL scheme
 * @returns {string} The module id
 */
function fromVid(vid, scheme) {
   return vid.replace(`${scheme}:`, "");
}
const VALUE_DEP_VERSION = `webpack/${PLUGIN_NAME}/version`;
@@ -93,28 +103,50 @@
   return `${VALUE_DEP_VERSION}/${toVid(id, scheme)}`;
}
/**
 * @typedef {object} VirtualUrlPluginOptions
 * @property {VirtualModules} modules - The virtual modules
 * @property {string=} scheme - The URL scheme to use
 */
class VirtualUrlPlugin {
   /**
    * Creates an instance of VirtualUrlPlugin.
    * @param {VirtualModules} modules The virtual modules
    * @param {string=} scheme The URL scheme to use
    * @param {Omit<VirtualUrlOptions, "modules"> | string=} schemeOrOptions The URL scheme to use
    */
   constructor(modules, scheme) {
      this.scheme = scheme || DEFAULT_SCHEME;
      this.modules = normalizeModules(modules, this.scheme);
   constructor(modules, schemeOrOptions) {
      /** @type {VirtualUrlOptions} */
      this.options = {
         modules,
         ...(typeof schemeOrOptions === "string"
            ? { scheme: schemeOrOptions }
            : schemeOrOptions || {})
      };
      /** @type {string} */
      this.scheme = this.options.scheme || DEFAULT_SCHEME;
      /** @type {VirtualUrlOptions["context"]} */
      this.context = this.options.context || "auto";
      /** @type {NormalizedModules} */
      this.modules = normalizeModules(this.options.modules, this.scheme);
   }
   /**
    * Apply the plugin
    * Applies the plugin by registering its hooks on the compiler.
    * @param {Compiler} compiler the compiler instance
    * @returns {void}
    */
   apply(compiler) {
      compiler.hooks.validate.tap(PLUGIN_NAME, () => {
         compiler.validate(
            () => require("../../schemas/plugins/schemes/VirtualUrlPlugin.json"),
            this.options,
            {
               name: "Virtual Url Plugin",
               baseDataPath: "options"
            },
            (options) =>
               require("../../schemas/plugins/schemes/VirtualUrlPlugin.check")(
                  options
               )
         );
      });
      const scheme = this.scheme;
      const cachedParseResourceWithoutFragment =
         parseResourceWithoutFragment.bindCache(compiler.root);
@@ -122,6 +154,28 @@
      compiler.hooks.compilation.tap(
         PLUGIN_NAME,
         (compilation, { normalModuleFactory }) => {
            compilation.hooks.assetPath.tap(
               { name: PLUGIN_NAME, before: "TemplatedPathPlugin" },
               (path, data) => {
                  if (data.filename && this.modules[data.filename]) {
                     /**
                      * Returns safe path.
                      * @param {string} str path
                      * @returns {string} safe path
                      */
                     const toSafePath = (str) =>
                        `__${str
                           .replace(/:/g, "__")
                           .replace(/^[^a-z0-9]+|[^a-z0-9]+$/gi, "")
                           .replace(/[^a-z0-9._-]+/gi, "_")}`;
                     // filename: virtual:logo.svg -> __virtual__logo.svg
                     data.filename = toSafePath(data.filename);
                  }
                  return path;
               }
            );
            normalModuleFactory.hooks.resolveForScheme
               .for(scheme)
               .tap(PLUGIN_NAME, (resourceData) => {
@@ -132,9 +186,32 @@
                     resourceData.resource
                  );
                  const path = url.path;
                  const type = virtualConfig.type;
                  const type = virtualConfig.type || "";
                  const context = virtualConfig.context || this.context;
                  resourceData.path = path + type;
                  resourceData.resource = path;
                  if (context === "auto") {
                     const context = getContext(path);
                     if (context === path) {
                        resourceData.context = compiler.context;
                     } else {
                        const resolvedContext = fromVid(context, scheme);
                        resourceData.context = isAbsolute(resolvedContext)
                           ? resolvedContext
                           : join(
                                 /** @type {import("..").InputFileSystem} */
                                 (compiler.inputFileSystem),
                                 compiler.context,
                                 resolvedContext
                              );
                     }
                  } else if (context && typeof context === "string") {
                     resourceData.context = context;
                  } else {
                     resourceData.context = compiler.context;
                  }
                  if (virtualConfig.version) {
                     const cacheKey = toCacheKey(resourceData.resource, scheme);
@@ -188,6 +265,7 @@
   }
   /**
    * Finds virtual module config by id.
    * @param {string} id The module id
    * @returns {VirtualModuleConfig} The virtual module config
    */