From 3bd962a6d7f61239c020e2dbbeb7341e5b842dd1 Mon Sep 17 00:00:00 2001
From: WXL <wl_5969728@163.com>
Date: 星期二, 21 四月 2026 11:46:41 +0800
Subject: [PATCH] 推送

---
 node_modules/webpack/lib/schemes/VirtualUrlPlugin.js |  148 +++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 113 insertions(+), 35 deletions(-)

diff --git a/node_modules/webpack/lib/schemes/VirtualUrlPlugin.js b/node_modules/webpack/lib/schemes/VirtualUrlPlugin.js
index ef2a05f..e5d997a 100644
--- a/node_modules/webpack/lib/schemes/VirtualUrlPlugin.js
+++ b/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
 	 */

--
Gitblit v1.9.3