2013-01-31 01:49:25 +08:00
|
|
|
/*
|
2018-07-30 23:08:51 +08:00
|
|
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
|
|
|
Author Tobias Koppers @sokra
|
|
|
|
*/
|
|
|
|
|
2017-04-04 05:28:08 +08:00
|
|
|
"use strict";
|
|
|
|
|
2021-08-06 00:47:24 +08:00
|
|
|
const { getContext } = require("loader-runner");
|
2018-02-11 12:27:09 +08:00
|
|
|
const asyncLib = require("neo-async");
|
2018-03-22 19:05:58 +08:00
|
|
|
const {
|
2019-01-05 02:17:37 +08:00
|
|
|
AsyncSeriesBailHook,
|
2025-07-03 17:06:45 +08:00
|
|
|
HookMap,
|
2018-03-22 19:05:58 +08:00
|
|
|
SyncBailHook,
|
|
|
|
SyncHook,
|
2025-07-03 17:06:45 +08:00
|
|
|
SyncWaterfallHook
|
2018-03-22 19:05:58 +08:00
|
|
|
} = require("tapable");
|
2021-07-01 17:46:59 +08:00
|
|
|
const ChunkGraph = require("./ChunkGraph");
|
2019-01-05 02:17:37 +08:00
|
|
|
const Module = require("./Module");
|
|
|
|
const ModuleFactory = require("./ModuleFactory");
|
2021-07-01 17:46:59 +08:00
|
|
|
const ModuleGraph = require("./ModuleGraph");
|
2023-04-01 01:56:32 +08:00
|
|
|
const { JAVASCRIPT_MODULE_TYPE_AUTO } = require("./ModuleTypeConstants");
|
2017-04-04 05:28:08 +08:00
|
|
|
const NormalModule = require("./NormalModule");
|
2019-05-16 17:31:41 +08:00
|
|
|
const BasicEffectRulePlugin = require("./rules/BasicEffectRulePlugin");
|
|
|
|
const BasicMatcherRulePlugin = require("./rules/BasicMatcherRulePlugin");
|
2021-07-17 04:16:06 +08:00
|
|
|
const ObjectMatcherRulePlugin = require("./rules/ObjectMatcherRulePlugin");
|
2019-05-16 17:31:41 +08:00
|
|
|
const RuleSetCompiler = require("./rules/RuleSetCompiler");
|
|
|
|
const UseEffectRulePlugin = require("./rules/UseEffectRulePlugin");
|
2019-08-07 15:54:43 +08:00
|
|
|
const LazySet = require("./util/LazySet");
|
2020-07-03 20:45:49 +08:00
|
|
|
const { getScheme } = require("./util/URLAbsoluteSpecifier");
|
2020-06-09 06:32:24 +08:00
|
|
|
const { cachedCleverMerge, cachedSetProperty } = require("./util/cleverMerge");
|
2019-06-11 19:09:42 +08:00
|
|
|
const { join } = require("./util/fs");
|
2022-02-03 23:21:06 +08:00
|
|
|
const {
|
|
|
|
parseResource,
|
|
|
|
parseResourceWithoutFragment
|
|
|
|
} = require("./util/identifier");
|
2017-11-17 21:26:23 +08:00
|
|
|
|
2025-09-10 19:38:19 +08:00
|
|
|
/** @typedef {import("enhanced-resolve").ResolveContext} ResolveContext */
|
|
|
|
/** @typedef {import("enhanced-resolve").ResolveRequest} ResolveRequest */
|
2021-01-20 22:08:58 +08:00
|
|
|
/** @typedef {import("../declarations/WebpackOptions").ModuleOptionsNormalized} ModuleOptions */
|
2022-02-15 22:37:57 +08:00
|
|
|
/** @typedef {import("../declarations/WebpackOptions").RuleSetRule} RuleSetRule */
|
2019-11-18 23:01:33 +08:00
|
|
|
/** @typedef {import("./Generator")} Generator */
|
2025-03-12 09:56:14 +08:00
|
|
|
/** @typedef {import("./ModuleFactory").ModuleFactoryCallback} ModuleFactoryCallback */
|
2019-01-05 02:17:37 +08:00
|
|
|
/** @typedef {import("./ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */
|
2024-02-17 01:39:12 +08:00
|
|
|
/** @typedef {import("./ModuleFactory").ModuleFactoryCreateDataContextInfo} ModuleFactoryCreateDataContextInfo */
|
2019-01-05 02:17:37 +08:00
|
|
|
/** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
|
2024-02-17 01:39:12 +08:00
|
|
|
/** @typedef {import("./NormalModule").GeneratorOptions} GeneratorOptions */
|
|
|
|
/** @typedef {import("./NormalModule").LoaderItem} LoaderItem */
|
2022-02-15 22:37:57 +08:00
|
|
|
/** @typedef {import("./NormalModule").NormalModuleCreateData} NormalModuleCreateData */
|
2024-02-17 01:39:12 +08:00
|
|
|
/** @typedef {import("./NormalModule").ParserOptions} ParserOptions */
|
2020-08-03 02:09:36 +08:00
|
|
|
/** @typedef {import("./Parser")} Parser */
|
2020-06-09 06:32:24 +08:00
|
|
|
/** @typedef {import("./ResolverFactory")} ResolverFactory */
|
2024-02-17 01:39:12 +08:00
|
|
|
/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
|
2019-01-05 02:17:37 +08:00
|
|
|
/** @typedef {import("./dependencies/ModuleDependency")} ModuleDependency */
|
2025-04-07 21:09:05 +08:00
|
|
|
/** @typedef {import("./javascript/JavascriptParser").ImportAttributes} ImportAttributes */
|
2025-03-27 08:07:25 +08:00
|
|
|
/** @typedef {import("./rules/RuleSetCompiler").RuleSetRules} RuleSetRules */
|
2020-06-09 06:32:24 +08:00
|
|
|
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
|
2025-04-03 00:02:22 +08:00
|
|
|
/** @typedef {import("./util/identifier").AssociatedObjectForCache} AssociatedObjectForCache */
|
2019-01-05 02:17:37 +08:00
|
|
|
|
2025-08-22 06:40:41 +08:00
|
|
|
/**
|
|
|
|
* @template T
|
|
|
|
* @typedef {import("./Compiler").Callback<T>} Callback
|
|
|
|
*/
|
|
|
|
|
2025-08-27 23:53:50 +08:00
|
|
|
/** @typedef {Pick<RuleSetRule, 'type' | 'sideEffects' | 'parser' | 'generator' | 'resolve' | 'layer' | 'extractSourceMap'>} ModuleSettings */
|
2024-10-02 05:18:10 +08:00
|
|
|
/** @typedef {Partial<NormalModuleCreateData & { settings: ModuleSettings }>} CreateData */
|
2022-02-15 22:37:57 +08:00
|
|
|
|
2019-01-05 02:17:37 +08:00
|
|
|
/**
|
2024-06-11 21:09:50 +08:00
|
|
|
* @typedef {object} ResolveData
|
2019-01-05 02:17:37 +08:00
|
|
|
* @property {ModuleFactoryCreateData["contextInfo"]} contextInfo
|
|
|
|
* @property {ModuleFactoryCreateData["resolveOptions"]} resolveOptions
|
|
|
|
* @property {string} context
|
|
|
|
* @property {string} request
|
2025-09-18 20:37:40 +08:00
|
|
|
* @property {ImportAttributes | undefined} attributes
|
2019-01-05 02:17:37 +08:00
|
|
|
* @property {ModuleDependency[]} dependencies
|
2021-08-05 23:04:52 +08:00
|
|
|
* @property {string} dependencyType
|
2022-02-15 22:37:57 +08:00
|
|
|
* @property {CreateData} createData
|
2019-08-07 15:54:43 +08:00
|
|
|
* @property {LazySet<string>} fileDependencies
|
|
|
|
* @property {LazySet<string>} missingDependencies
|
|
|
|
* @property {LazySet<string>} contextDependencies
|
2024-10-23 08:01:04 +08:00
|
|
|
* @property {Module=} ignoredModule
|
2020-06-24 20:09:10 +08:00
|
|
|
* @property {boolean} cacheable allow to use the unsafe cache
|
2019-01-05 02:17:37 +08:00
|
|
|
*/
|
|
|
|
|
2020-07-03 20:45:49 +08:00
|
|
|
/**
|
2024-06-11 21:09:50 +08:00
|
|
|
* @typedef {object} ResourceData
|
2020-07-03 20:45:49 +08:00
|
|
|
* @property {string} resource
|
2024-02-17 01:39:12 +08:00
|
|
|
* @property {string=} path
|
|
|
|
* @property {string=} query
|
|
|
|
* @property {string=} fragment
|
2021-08-06 00:47:24 +08:00
|
|
|
* @property {string=} context
|
2020-07-03 20:45:49 +08:00
|
|
|
*/
|
|
|
|
|
2025-05-13 21:03:58 +08:00
|
|
|
/**
|
|
|
|
* @typedef {object} ResourceSchemeData
|
|
|
|
* @property {string=} mimetype mime type of the resource
|
|
|
|
* @property {string=} parameters additional parameters for the resource
|
|
|
|
* @property {"base64" | false=} encoding encoding of the resource
|
|
|
|
* @property {string=} encodedContent encoded content of the resource
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** @typedef {ResourceData & { data: ResourceSchemeData & Partial<ResolveRequest> }} ResourceDataWithData */
|
2020-07-03 20:45:49 +08:00
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/**
|
2024-06-11 21:09:50 +08:00
|
|
|
* @typedef {object} ParsedLoaderRequest
|
2022-02-03 23:21:06 +08:00
|
|
|
* @property {string} loader loader
|
|
|
|
* @property {string|undefined} options options
|
|
|
|
*/
|
|
|
|
|
2025-08-28 18:34:30 +08:00
|
|
|
/** @typedef {import("./ModuleTypeConstants").JAVASCRIPT_MODULE_TYPE_AUTO} JAVASCRIPT_MODULE_TYPE_AUTO */
|
|
|
|
/** @typedef {import("./ModuleTypeConstants").JAVASCRIPT_MODULE_TYPE_DYNAMIC} JAVASCRIPT_MODULE_TYPE_DYNAMIC */
|
|
|
|
/** @typedef {import("./ModuleTypeConstants").JAVASCRIPT_MODULE_TYPE_ESM} JAVASCRIPT_MODULE_TYPE_ESM */
|
|
|
|
/** @typedef {import("./ModuleTypeConstants").JSON_MODULE_TYPE} JSON_MODULE_TYPE */
|
|
|
|
/** @typedef {import("./ModuleTypeConstants").ASSET_MODULE_TYPE} ASSET_MODULE_TYPE */
|
|
|
|
/** @typedef {import("./ModuleTypeConstants").ASSET_MODULE_TYPE_INLINE} ASSET_MODULE_TYPE_INLINE */
|
|
|
|
/** @typedef {import("./ModuleTypeConstants").ASSET_MODULE_TYPE_RESOURCE} ASSET_MODULE_TYPE_RESOURCE */
|
|
|
|
/** @typedef {import("./ModuleTypeConstants").ASSET_MODULE_TYPE_SOURCE} ASSET_MODULE_TYPE_SOURCE */
|
2025-10-02 23:26:16 +08:00
|
|
|
/** @typedef {import("./ModuleTypeConstants").ASSET_MODULE_TYPE_BYTES} ASSET_MODULE_TYPE_BYTES */
|
2025-08-28 18:34:30 +08:00
|
|
|
/** @typedef {import("./ModuleTypeConstants").WEBASSEMBLY_MODULE_TYPE_ASYNC} WEBASSEMBLY_MODULE_TYPE_ASYNC */
|
|
|
|
/** @typedef {import("./ModuleTypeConstants").WEBASSEMBLY_MODULE_TYPE_SYNC} WEBASSEMBLY_MODULE_TYPE_SYNC */
|
|
|
|
/** @typedef {import("./ModuleTypeConstants").CSS_MODULE_TYPE} CSS_MODULE_TYPE */
|
|
|
|
/** @typedef {import("./ModuleTypeConstants").CSS_MODULE_TYPE_GLOBAL} CSS_MODULE_TYPE_GLOBAL */
|
|
|
|
/** @typedef {import("./ModuleTypeConstants").CSS_MODULE_TYPE_MODULE} CSS_MODULE_TYPE_MODULE */
|
|
|
|
/** @typedef {import("./ModuleTypeConstants").CSS_MODULE_TYPE_AUTO} CSS_MODULE_TYPE_AUTO */
|
|
|
|
|
|
|
|
/** @typedef {JAVASCRIPT_MODULE_TYPE_AUTO | JAVASCRIPT_MODULE_TYPE_DYNAMIC | JAVASCRIPT_MODULE_TYPE_ESM | JSON_MODULE_TYPE | ASSET_MODULE_TYPE | ASSET_MODULE_TYPE_INLINE | ASSET_MODULE_TYPE_RESOURCE | ASSET_MODULE_TYPE_SOURCE | WEBASSEMBLY_MODULE_TYPE_ASYNC | WEBASSEMBLY_MODULE_TYPE_SYNC | CSS_MODULE_TYPE | CSS_MODULE_TYPE_GLOBAL | CSS_MODULE_TYPE_MODULE | CSS_MODULE_TYPE_AUTO} KnownNormalModuleTypes */
|
|
|
|
/** @typedef {KnownNormalModuleTypes | string} NormalModuleTypes */
|
|
|
|
|
2020-06-17 02:01:06 +08:00
|
|
|
const EMPTY_RESOLVE_OPTIONS = {};
|
2024-02-17 01:39:12 +08:00
|
|
|
/** @type {ParserOptions} */
|
2021-01-05 18:11:02 +08:00
|
|
|
const EMPTY_PARSER_OPTIONS = {};
|
2024-02-17 01:39:12 +08:00
|
|
|
/** @type {GeneratorOptions} */
|
2021-01-05 18:11:02 +08:00
|
|
|
const EMPTY_GENERATOR_OPTIONS = {};
|
2024-02-17 01:39:12 +08:00
|
|
|
/** @type {ParsedLoaderRequest[]} */
|
2021-08-04 21:55:58 +08:00
|
|
|
const EMPTY_ELEMENTS = [];
|
2016-09-14 18:04:42 +08:00
|
|
|
|
2018-06-01 20:54:54 +08:00
|
|
|
const MATCH_RESOURCE_REGEX = /^([^!]+)!=!/;
|
2023-03-27 14:50:30 +08:00
|
|
|
const LEADING_DOT_EXTENSION_REGEX = /^[^.]/;
|
2018-06-01 20:54:54 +08:00
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/**
|
|
|
|
* @param {LoaderItem} data data
|
|
|
|
* @returns {string} ident
|
|
|
|
*/
|
2025-07-17 00:13:14 +08:00
|
|
|
const loaderToIdent = (data) => {
|
2018-05-29 20:50:40 +08:00
|
|
|
if (!data.options) {
|
|
|
|
return data.loader;
|
|
|
|
}
|
|
|
|
if (typeof data.options === "string") {
|
2024-07-31 10:39:30 +08:00
|
|
|
return `${data.loader}?${data.options}`;
|
2018-05-29 20:50:40 +08:00
|
|
|
}
|
|
|
|
if (typeof data.options !== "object") {
|
2016-09-14 18:04:42 +08:00
|
|
|
throw new Error("loader options must be string or object");
|
2018-05-29 20:50:40 +08:00
|
|
|
}
|
|
|
|
if (data.ident) {
|
2024-07-31 10:39:30 +08:00
|
|
|
return `${data.loader}??${data.ident}`;
|
2018-05-29 20:50:40 +08:00
|
|
|
}
|
2024-07-31 10:39:30 +08:00
|
|
|
return `${data.loader}?${JSON.stringify(data.options)}`;
|
2017-11-08 18:32:05 +08:00
|
|
|
};
|
2013-01-31 01:49:25 +08:00
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/**
|
|
|
|
* @param {LoaderItem[]} loaders loaders
|
|
|
|
* @param {string} resource resource
|
|
|
|
* @returns {string} stringified loaders and resource
|
|
|
|
*/
|
2019-01-05 18:19:30 +08:00
|
|
|
const stringifyLoadersAndResource = (loaders, resource) => {
|
|
|
|
let str = "";
|
|
|
|
for (const loader of loaders) {
|
2024-07-31 10:39:30 +08:00
|
|
|
str += `${loaderToIdent(loader)}!`;
|
2019-01-05 18:19:30 +08:00
|
|
|
}
|
|
|
|
return str + resource;
|
|
|
|
};
|
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/**
|
|
|
|
* @param {number} times times
|
|
|
|
* @param {(err?: null | Error) => void} callback callback
|
|
|
|
* @returns {(err?: null | Error) => void} callback
|
|
|
|
*/
|
2025-07-17 00:13:14 +08:00
|
|
|
const needCalls = (times, callback) => (err) => {
|
2024-07-31 11:31:11 +08:00
|
|
|
if (--times === 0) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
if (err && times > 0) {
|
2024-08-02 02:36:27 +08:00
|
|
|
times = Number.NaN;
|
2024-07-31 11:31:11 +08:00
|
|
|
return callback(err);
|
|
|
|
}
|
2019-01-05 18:19:30 +08:00
|
|
|
};
|
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/**
|
|
|
|
* @template T
|
|
|
|
* @template O
|
|
|
|
* @param {T} globalOptions global options
|
|
|
|
* @param {string} type type
|
|
|
|
* @param {O} localOptions local options
|
|
|
|
* @returns {T & O | T | O} result
|
|
|
|
*/
|
2021-01-05 18:11:02 +08:00
|
|
|
const mergeGlobalOptions = (globalOptions, type, localOptions) => {
|
|
|
|
const parts = type.split("/");
|
|
|
|
let result;
|
|
|
|
let current = "";
|
|
|
|
for (const part of parts) {
|
|
|
|
current = current ? `${current}/${part}` : part;
|
2024-10-24 04:30:31 +08:00
|
|
|
const options =
|
|
|
|
/** @type {T} */
|
|
|
|
(globalOptions[/** @type {keyof T} */ (current)]);
|
2021-01-05 18:11:02 +08:00
|
|
|
if (typeof options === "object") {
|
2024-08-02 02:36:27 +08:00
|
|
|
result =
|
|
|
|
result === undefined ? options : cachedCleverMerge(result, options);
|
2021-01-05 18:11:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (result === undefined) {
|
|
|
|
return localOptions;
|
|
|
|
}
|
2024-07-31 04:21:27 +08:00
|
|
|
return cachedCleverMerge(result, localOptions);
|
2021-01-05 18:11:02 +08:00
|
|
|
};
|
|
|
|
|
2019-01-05 02:17:37 +08:00
|
|
|
// TODO webpack 6 remove
|
2024-02-17 01:39:12 +08:00
|
|
|
/**
|
2025-03-11 10:03:41 +08:00
|
|
|
* @template {import("tapable").Hook<EXPECTED_ANY, EXPECTED_ANY>} T
|
2024-02-17 01:39:12 +08:00
|
|
|
* @param {string} name name
|
2025-03-11 10:03:41 +08:00
|
|
|
* @param {T} hook hook
|
2024-02-17 01:39:12 +08:00
|
|
|
* @returns {string} result
|
|
|
|
*/
|
2020-11-21 03:49:27 +08:00
|
|
|
const deprecationChangedHookMessage = (name, hook) => {
|
2025-07-17 00:13:14 +08:00
|
|
|
const names = hook.taps.map((tapped) => tapped.name).join(", ");
|
2020-11-21 03:49:27 +08:00
|
|
|
|
|
|
|
return (
|
|
|
|
`NormalModuleFactory.${name} (${names}) is no longer a waterfall hook, but a bailing hook instead. ` +
|
|
|
|
"Do not return the passed object, but modify it instead. " +
|
|
|
|
"Returning false will ignore the request and results in no module created."
|
|
|
|
);
|
|
|
|
};
|
2019-01-05 02:17:37 +08:00
|
|
|
|
2019-05-16 17:31:41 +08:00
|
|
|
const ruleSetCompiler = new RuleSetCompiler([
|
|
|
|
new BasicMatcherRulePlugin("test", "resource"),
|
2021-05-19 14:48:10 +08:00
|
|
|
new BasicMatcherRulePlugin("scheme"),
|
2020-05-18 15:00:28 +08:00
|
|
|
new BasicMatcherRulePlugin("mimetype"),
|
2020-08-05 05:42:29 +08:00
|
|
|
new BasicMatcherRulePlugin("dependency"),
|
2019-05-16 17:31:41 +08:00
|
|
|
new BasicMatcherRulePlugin("include", "resource"),
|
|
|
|
new BasicMatcherRulePlugin("exclude", "resource", true),
|
|
|
|
new BasicMatcherRulePlugin("resource"),
|
|
|
|
new BasicMatcherRulePlugin("resourceQuery"),
|
2020-07-03 23:03:15 +08:00
|
|
|
new BasicMatcherRulePlugin("resourceFragment"),
|
2019-05-16 17:31:41 +08:00
|
|
|
new BasicMatcherRulePlugin("realResource"),
|
|
|
|
new BasicMatcherRulePlugin("issuer"),
|
|
|
|
new BasicMatcherRulePlugin("compiler"),
|
2020-12-22 21:51:09 +08:00
|
|
|
new BasicMatcherRulePlugin("issuerLayer"),
|
2025-09-18 20:37:40 +08:00
|
|
|
new ObjectMatcherRulePlugin("assert", "attributes", (value) => {
|
2024-10-24 04:30:31 +08:00
|
|
|
if (value) {
|
2025-04-07 21:09:05 +08:00
|
|
|
return (
|
|
|
|
/** @type {ImportAttributes} */ (value)._isLegacyAssert !== undefined
|
|
|
|
);
|
2024-10-24 04:30:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}),
|
2025-09-18 20:37:40 +08:00
|
|
|
new ObjectMatcherRulePlugin("with", "attributes", (value) => {
|
2024-10-24 04:30:31 +08:00
|
|
|
if (value) {
|
2025-04-07 21:09:05 +08:00
|
|
|
return !(/** @type {ImportAttributes} */ (value)._isLegacyAssert);
|
2024-10-24 04:30:31 +08:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}),
|
2021-07-17 04:16:06 +08:00
|
|
|
new ObjectMatcherRulePlugin("descriptionData"),
|
2019-05-16 17:31:41 +08:00
|
|
|
new BasicEffectRulePlugin("type"),
|
|
|
|
new BasicEffectRulePlugin("sideEffects"),
|
|
|
|
new BasicEffectRulePlugin("parser"),
|
|
|
|
new BasicEffectRulePlugin("resolve"),
|
2019-11-16 00:27:36 +08:00
|
|
|
new BasicEffectRulePlugin("generator"),
|
2020-12-22 21:51:09 +08:00
|
|
|
new BasicEffectRulePlugin("layer"),
|
2025-08-27 23:53:50 +08:00
|
|
|
new BasicEffectRulePlugin("extractSourceMap"),
|
2019-05-16 17:31:41 +08:00
|
|
|
new UseEffectRulePlugin()
|
|
|
|
]);
|
|
|
|
|
2025-10-02 23:26:16 +08:00
|
|
|
/** @typedef {import("./javascript/JavascriptParser")} JavascriptParser */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
|
|
|
|
/** @typedef {import("./javascript/JavascriptGenerator")} JavascriptGenerator */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").EmptyGeneratorOptions} EmptyGeneratorOptions */
|
|
|
|
|
|
|
|
/** @typedef {import("./json/JsonParser")} JsonParser */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").JsonParserOptions} JsonParserOptions */
|
|
|
|
/** @typedef {import("./json/JsonGenerator")} JsonGenerator */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").JsonGeneratorOptions} JsonGeneratorOptions */
|
|
|
|
|
|
|
|
/** @typedef {import("./asset/AssetParser")} AssetParser */
|
|
|
|
/** @typedef {import("./asset/AssetSourceParser")} AssetSourceParser */
|
|
|
|
/** @typedef {import("./asset/AssetBytesParser")} AssetBytesParser */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").AssetParserOptions} AssetParserOptions */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").EmptyParserOptions} EmptyParserOptions */
|
|
|
|
/** @typedef {import("./asset/AssetGenerator")} AssetGenerator */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").AssetGeneratorOptions} AssetGeneratorOptions */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").AssetInlineGeneratorOptions} AssetInlineGeneratorOptions */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").AssetResourceGeneratorOptions} AssetResourceGeneratorOptions */
|
|
|
|
/** @typedef {import("./asset/AssetSourceGenerator")} AssetSourceGenerator */
|
|
|
|
/** @typedef {import("./asset/AssetBytesGenerator")} AssetBytesGenerator */
|
|
|
|
|
|
|
|
/** @typedef {import("./wasm-async/AsyncWebAssemblyParser")} AsyncWebAssemblyParser */
|
|
|
|
/** @typedef {import("./wasm-sync/WebAssemblyParser")} WebAssemblyParser */
|
|
|
|
|
|
|
|
/** @typedef {import("./css/CssParser")} CssParser */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").CssParserOptions} CssParserOptions */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").CssAutoParserOptions} CssAutoParserOptions */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").CssGlobalParserOptions} CssGlobalParserOptions */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").CssModuleParserOptions} CssModuleParserOptions */
|
|
|
|
/** @typedef {import("./css/CssGenerator")} CssGenerator */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").CssGeneratorOptions} CssGeneratorOptions */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").CssGlobalGeneratorOptions} CssGlobalGeneratorOptions */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").CssModuleGeneratorOptions} CssModuleGeneratorOptions */
|
|
|
|
/** @typedef {import("../declarations/WebpackOptions").CssAutoGeneratorOptions} CssAutoGeneratorOptions */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @typedef {[
|
|
|
|
* [JAVASCRIPT_MODULE_TYPE_AUTO, JavascriptParser, JavascriptParserOptions, JavascriptGenerator, EmptyGeneratorOptions],
|
|
|
|
* [JAVASCRIPT_MODULE_TYPE_DYNAMIC, JavascriptParser, JavascriptParserOptions, JavascriptGenerator, EmptyGeneratorOptions],
|
|
|
|
* [JAVASCRIPT_MODULE_TYPE_ESM, JavascriptParser, JavascriptParserOptions, JavascriptGenerator, EmptyGeneratorOptions],
|
|
|
|
* [JSON_MODULE_TYPE, JsonParser, JsonParserOptions, JsonGenerator, JsonGeneratorOptions],
|
|
|
|
* [ASSET_MODULE_TYPE, AssetParser, AssetParserOptions, AssetGenerator, AssetGeneratorOptions],
|
|
|
|
* [ASSET_MODULE_TYPE_INLINE, AssetParser, EmptyParserOptions, AssetGenerator, AssetGeneratorOptions],
|
|
|
|
* [ASSET_MODULE_TYPE_RESOURCE, AssetParser, EmptyParserOptions, AssetGenerator, AssetGeneratorOptions],
|
|
|
|
* [ASSET_MODULE_TYPE_SOURCE, AssetSourceParser, EmptyParserOptions, AssetSourceGenerator, EmptyGeneratorOptions],
|
|
|
|
* [ASSET_MODULE_TYPE_BYTES, AssetBytesParser, EmptyParserOptions, AssetBytesGenerator, EmptyGeneratorOptions],
|
|
|
|
* [WEBASSEMBLY_MODULE_TYPE_ASYNC, AsyncWebAssemblyParser, EmptyParserOptions, Generator, EmptyParserOptions],
|
|
|
|
* [WEBASSEMBLY_MODULE_TYPE_SYNC, WebAssemblyParser, EmptyParserOptions, Generator, EmptyParserOptions],
|
|
|
|
* [CSS_MODULE_TYPE, CssParser, CssParserOptions, CssGenerator, CssGeneratorOptions],
|
|
|
|
* [CSS_MODULE_TYPE_AUTO, CssParser, CssAutoParserOptions, CssGenerator, CssAutoGeneratorOptions],
|
|
|
|
* [CSS_MODULE_TYPE_MODULE, CssParser, CssModuleParserOptions, CssGenerator, CssModuleGeneratorOptions],
|
|
|
|
* [CSS_MODULE_TYPE_GLOBAL, CssParser, CssGlobalParserOptions, CssGenerator, CssGlobalGeneratorOptions],
|
|
|
|
* [string, Parser, ParserOptions, Generator, GeneratorOptions],
|
|
|
|
* ]} ParsersAndGeneratorsByTypes
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @template {unknown[]} T
|
|
|
|
* @template {number[]} I
|
|
|
|
* @typedef {{ [K in keyof I]: K extends keyof I ? I[K] extends keyof T ? T[I[K]] : never : never }} ExtractTupleElements
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @template {unknown[]} T
|
|
|
|
* @template {number[]} A
|
|
|
|
* @template [R=void]
|
|
|
|
* @typedef {T extends [infer Head extends [string, ...unknown[]], ...infer Tail extends [string, ...unknown[]][]] ? Record<Head[0], SyncBailHook<ExtractTupleElements<Head, A>, R extends number ? Head[R] : R>> & RecordFactoryFromTuple<Tail, A, R> : unknown } RecordFactoryFromTuple
|
|
|
|
*/
|
|
|
|
|
2019-01-05 02:17:37 +08:00
|
|
|
class NormalModuleFactory extends ModuleFactory {
|
2020-06-09 06:32:24 +08:00
|
|
|
/**
|
2024-06-11 21:09:50 +08:00
|
|
|
* @param {object} param params
|
2020-06-09 06:32:24 +08:00
|
|
|
* @param {string=} param.context context
|
|
|
|
* @param {InputFileSystem} param.fs file system
|
|
|
|
* @param {ResolverFactory} param.resolverFactory resolverFactory
|
|
|
|
* @param {ModuleOptions} param.options options
|
2025-04-03 00:02:22 +08:00
|
|
|
* @param {AssociatedObjectForCache} param.associatedObjectForCache an object to which the cache will be attached
|
2020-06-09 06:32:24 +08:00
|
|
|
*/
|
2020-07-06 23:39:52 +08:00
|
|
|
constructor({
|
|
|
|
context,
|
|
|
|
fs,
|
|
|
|
resolverFactory,
|
|
|
|
options,
|
2025-08-29 21:08:28 +08:00
|
|
|
associatedObjectForCache
|
2020-07-06 23:39:52 +08:00
|
|
|
}) {
|
2019-01-05 02:17:37 +08:00
|
|
|
super();
|
2018-07-30 20:25:40 +08:00
|
|
|
this.hooks = Object.freeze({
|
2022-02-15 22:37:57 +08:00
|
|
|
/** @type {AsyncSeriesBailHook<[ResolveData], Module | false | void>} */
|
2019-01-05 02:17:37 +08:00
|
|
|
resolve: new AsyncSeriesBailHook(["resolveData"]),
|
2020-07-03 20:45:49 +08:00
|
|
|
/** @type {HookMap<AsyncSeriesBailHook<[ResourceDataWithData, ResolveData], true | void>>} */
|
|
|
|
resolveForScheme: new HookMap(
|
|
|
|
() => new AsyncSeriesBailHook(["resourceData", "resolveData"])
|
|
|
|
),
|
2021-08-04 21:55:58 +08:00
|
|
|
/** @type {HookMap<AsyncSeriesBailHook<[ResourceDataWithData, ResolveData], true | void>>} */
|
|
|
|
resolveInScheme: new HookMap(
|
|
|
|
() => new AsyncSeriesBailHook(["resourceData", "resolveData"])
|
|
|
|
),
|
2024-03-18 01:15:44 +08:00
|
|
|
/** @type {AsyncSeriesBailHook<[ResolveData], Module | undefined>} */
|
2019-01-05 02:17:37 +08:00
|
|
|
factorize: new AsyncSeriesBailHook(["resolveData"]),
|
2022-02-15 22:37:57 +08:00
|
|
|
/** @type {AsyncSeriesBailHook<[ResolveData], false | void>} */
|
2019-01-05 02:17:37 +08:00
|
|
|
beforeResolve: new AsyncSeriesBailHook(["resolveData"]),
|
2022-02-15 22:37:57 +08:00
|
|
|
/** @type {AsyncSeriesBailHook<[ResolveData], false | void>} */
|
2019-01-05 02:17:37 +08:00
|
|
|
afterResolve: new AsyncSeriesBailHook(["resolveData"]),
|
2025-03-11 10:03:41 +08:00
|
|
|
/** @type {AsyncSeriesBailHook<[CreateData, ResolveData], Module | void>} */
|
2020-06-13 20:45:37 +08:00
|
|
|
createModule: new AsyncSeriesBailHook(["createData", "resolveData"]),
|
2025-03-11 10:03:41 +08:00
|
|
|
/** @type {SyncWaterfallHook<[Module, CreateData, ResolveData]>} */
|
2019-01-05 02:17:37 +08:00
|
|
|
module: new SyncWaterfallHook(["module", "createData", "resolveData"]),
|
2025-10-02 23:26:16 +08:00
|
|
|
/** @type {import("tapable").TypedHookMap<RecordFactoryFromTuple<ParsersAndGeneratorsByTypes, [2], 1>>} */
|
2017-11-28 16:54:24 +08:00
|
|
|
createParser: new HookMap(() => new SyncBailHook(["parserOptions"])),
|
2025-10-02 23:26:16 +08:00
|
|
|
/** @type {import("tapable").TypedHookMap<RecordFactoryFromTuple<ParsersAndGeneratorsByTypes, [1, 2]>>} */
|
2017-11-28 16:54:24 +08:00
|
|
|
parser: new HookMap(() => new SyncHook(["parser", "parserOptions"])),
|
2025-10-02 23:26:16 +08:00
|
|
|
/** @type {import("tapable").TypedHookMap<RecordFactoryFromTuple<ParsersAndGeneratorsByTypes, [4], 3>>} */
|
2018-02-25 09:00:20 +08:00
|
|
|
createGenerator: new HookMap(
|
|
|
|
() => new SyncBailHook(["generatorOptions"])
|
|
|
|
),
|
2025-10-02 23:26:16 +08:00
|
|
|
/** @type {import("tapable").TypedHookMap<RecordFactoryFromTuple<ParsersAndGeneratorsByTypes, [3, 4]>>} */
|
2018-02-25 09:00:20 +08:00
|
|
|
generator: new HookMap(
|
|
|
|
() => new SyncHook(["generator", "generatorOptions"])
|
2023-04-25 20:16:42 +08:00
|
|
|
),
|
2025-07-09 18:59:21 +08:00
|
|
|
/** @type {HookMap<SyncBailHook<[CreateData, ResolveData], Module | void>>} */
|
2023-04-25 21:59:17 +08:00
|
|
|
createModuleClass: new HookMap(
|
2023-04-25 20:16:42 +08:00
|
|
|
() => new SyncBailHook(["createData", "resolveData"])
|
2018-02-25 09:00:20 +08:00
|
|
|
)
|
2018-07-30 20:25:40 +08:00
|
|
|
});
|
2017-11-17 21:26:23 +08:00
|
|
|
this.resolverFactory = resolverFactory;
|
2019-06-04 17:32:46 +08:00
|
|
|
this.ruleSet = ruleSetCompiler.compile([
|
|
|
|
{
|
2025-03-27 08:07:25 +08:00
|
|
|
rules: /** @type {RuleSetRules} */ (options.defaultRules)
|
2019-06-04 17:32:46 +08:00
|
|
|
},
|
|
|
|
{
|
2025-03-27 08:07:25 +08:00
|
|
|
rules: /** @type {RuleSetRules} */ (options.rules)
|
2019-06-04 17:32:46 +08:00
|
|
|
}
|
|
|
|
]);
|
2017-04-04 05:28:08 +08:00
|
|
|
this.context = context || "";
|
2019-06-11 19:09:42 +08:00
|
|
|
this.fs = fs;
|
2021-01-05 18:11:02 +08:00
|
|
|
this._globalParserOptions = options.parser;
|
|
|
|
this._globalGeneratorOptions = options.generator;
|
2025-04-03 00:02:22 +08:00
|
|
|
/** @type {Map<string, WeakMap<ParserOptions, Parser>>} */
|
2019-11-18 23:01:33 +08:00
|
|
|
this.parserCache = new Map();
|
2025-04-03 00:02:22 +08:00
|
|
|
/** @type {Map<string, WeakMap<GeneratorOptions, Generator>>} */
|
2019-11-18 23:01:33 +08:00
|
|
|
this.generatorCache = new Map();
|
2021-07-01 17:46:59 +08:00
|
|
|
/** @type {Set<Module>} */
|
|
|
|
this._restoredUnsafeCacheEntries = new Set();
|
2020-07-06 23:39:52 +08:00
|
|
|
|
2025-05-13 21:03:58 +08:00
|
|
|
/** @type {(resource: string) => import("./util/identifier").ParsedResource} */
|
2020-07-06 23:39:52 +08:00
|
|
|
const cacheParseResource = parseResource.bindCache(
|
|
|
|
associatedObjectForCache
|
|
|
|
);
|
2022-02-03 23:21:06 +08:00
|
|
|
const cachedParseResourceWithoutFragment =
|
|
|
|
parseResourceWithoutFragment.bindCache(associatedObjectForCache);
|
|
|
|
this._parseResourceWithoutFragment = cachedParseResourceWithoutFragment;
|
2020-07-06 23:39:52 +08:00
|
|
|
|
2019-01-05 02:17:37 +08:00
|
|
|
this.hooks.factorize.tapAsync(
|
2019-11-08 18:13:16 +08:00
|
|
|
{
|
2019-01-05 02:17:37 +08:00
|
|
|
name: "NormalModuleFactory",
|
|
|
|
stage: 100
|
2019-11-08 18:13:16 +08:00
|
|
|
},
|
2019-01-05 02:17:37 +08:00
|
|
|
(resolveData, callback) => {
|
|
|
|
this.hooks.resolve.callAsync(resolveData, (err, result) => {
|
|
|
|
if (err) return callback(err);
|
2015-05-13 06:15:01 +08:00
|
|
|
|
2019-01-05 02:17:37 +08:00
|
|
|
// Ignored
|
|
|
|
if (result === false) return callback();
|
2015-05-13 06:15:01 +08:00
|
|
|
|
2019-01-05 02:17:37 +08:00
|
|
|
// direct module
|
|
|
|
if (result instanceof Module) return callback(null, result);
|
2015-05-13 06:15:01 +08:00
|
|
|
|
2025-07-02 20:10:54 +08:00
|
|
|
if (typeof result === "object") {
|
2019-01-05 02:17:37 +08:00
|
|
|
throw new Error(
|
2024-07-31 10:39:30 +08:00
|
|
|
`${deprecationChangedHookMessage(
|
|
|
|
"resolve",
|
|
|
|
this.hooks.resolve
|
|
|
|
)} Returning a Module object will result in this module used as result.`
|
2019-01-05 02:17:37 +08:00
|
|
|
);
|
2025-07-02 20:10:54 +08:00
|
|
|
}
|
2015-05-13 06:15:01 +08:00
|
|
|
|
2019-01-05 02:17:37 +08:00
|
|
|
this.hooks.afterResolve.callAsync(resolveData, (err, result) => {
|
|
|
|
if (err) return callback(err);
|
2016-02-10 02:32:50 +08:00
|
|
|
|
2025-07-02 20:10:54 +08:00
|
|
|
if (typeof result === "object") {
|
2020-11-21 03:49:27 +08:00
|
|
|
throw new Error(
|
|
|
|
deprecationChangedHookMessage(
|
|
|
|
"afterResolve",
|
|
|
|
this.hooks.afterResolve
|
|
|
|
)
|
|
|
|
);
|
2025-07-02 20:10:54 +08:00
|
|
|
}
|
2015-05-17 00:27:59 +08:00
|
|
|
|
2019-01-05 02:17:37 +08:00
|
|
|
// Ignored
|
|
|
|
if (result === false) return callback();
|
2015-05-17 00:27:59 +08:00
|
|
|
|
2019-01-05 02:17:37 +08:00
|
|
|
const createData = resolveData.createData;
|
2017-04-04 05:28:08 +08:00
|
|
|
|
2020-06-13 20:45:37 +08:00
|
|
|
this.hooks.createModule.callAsync(
|
2019-01-05 02:17:37 +08:00
|
|
|
createData,
|
2020-06-13 20:45:37 +08:00
|
|
|
resolveData,
|
|
|
|
(err, createdModule) => {
|
|
|
|
if (!createdModule) {
|
|
|
|
if (!resolveData.request) {
|
|
|
|
return callback(new Error("Empty dependency (no request)"));
|
|
|
|
}
|
2019-01-05 02:17:37 +08:00
|
|
|
|
2023-04-25 21:59:17 +08:00
|
|
|
// TODO webpack 6 make it required and move javascript/wasm/asset properties to own module
|
|
|
|
createdModule = this.hooks.createModuleClass
|
2024-10-25 02:13:59 +08:00
|
|
|
.for(
|
|
|
|
/** @type {ModuleSettings} */
|
|
|
|
(createData.settings).type
|
|
|
|
)
|
2023-04-25 21:59:17 +08:00
|
|
|
.call(createData, resolveData);
|
|
|
|
|
|
|
|
if (!createdModule) {
|
|
|
|
createdModule = /** @type {Module} */ (
|
|
|
|
new NormalModule(
|
2024-10-24 04:30:31 +08:00
|
|
|
/** @type {NormalModuleCreateData} */
|
|
|
|
(createData)
|
2023-04-25 21:59:17 +08:00
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
2020-06-13 20:45:37 +08:00
|
|
|
}
|
2015-05-13 06:15:01 +08:00
|
|
|
|
2020-06-13 20:45:37 +08:00
|
|
|
createdModule = this.hooks.module.call(
|
|
|
|
createdModule,
|
|
|
|
createData,
|
|
|
|
resolveData
|
|
|
|
);
|
2015-05-16 20:59:50 +08:00
|
|
|
|
2020-06-13 20:45:37 +08:00
|
|
|
return callback(null, createdModule);
|
|
|
|
}
|
2019-01-05 02:17:37 +08:00
|
|
|
);
|
|
|
|
});
|
2017-07-24 17:54:58 +08:00
|
|
|
});
|
2018-06-01 20:54:54 +08:00
|
|
|
}
|
2019-01-05 02:17:37 +08:00
|
|
|
);
|
|
|
|
this.hooks.resolve.tapAsync(
|
2020-05-27 07:27:52 +08:00
|
|
|
{
|
2019-01-05 02:17:37 +08:00
|
|
|
name: "NormalModuleFactory",
|
|
|
|
stage: 100
|
2020-05-27 07:27:52 +08:00
|
|
|
},
|
2019-01-05 02:17:37 +08:00
|
|
|
(data, callback) => {
|
|
|
|
const {
|
|
|
|
contextInfo,
|
|
|
|
context,
|
2020-05-27 07:27:52 +08:00
|
|
|
dependencies,
|
2021-08-05 23:04:52 +08:00
|
|
|
dependencyType,
|
2019-01-05 02:17:37 +08:00
|
|
|
request,
|
2025-09-18 20:37:40 +08:00
|
|
|
attributes,
|
2020-05-28 06:59:23 +08:00
|
|
|
resolveOptions,
|
2019-01-05 02:17:37 +08:00
|
|
|
fileDependencies,
|
|
|
|
missingDependencies,
|
|
|
|
contextDependencies
|
|
|
|
} = data;
|
2020-05-28 06:59:23 +08:00
|
|
|
const loaderResolver = this.getResolver("loader");
|
2019-01-05 02:17:37 +08:00
|
|
|
|
2020-07-03 20:45:49 +08:00
|
|
|
/** @type {ResourceData | undefined} */
|
2024-07-31 06:15:03 +08:00
|
|
|
let matchResourceData;
|
2019-01-05 02:17:37 +08:00
|
|
|
/** @type {string} */
|
2021-08-04 21:55:58 +08:00
|
|
|
let unresolvedResource;
|
2022-02-03 23:21:06 +08:00
|
|
|
/** @type {ParsedLoaderRequest[]} */
|
2021-08-04 21:55:58 +08:00
|
|
|
let elements;
|
|
|
|
let noPreAutoLoaders = false;
|
|
|
|
let noAutoLoaders = false;
|
|
|
|
let noPrePostAutoLoaders = false;
|
|
|
|
|
|
|
|
const contextScheme = getScheme(context);
|
|
|
|
/** @type {string | undefined} */
|
|
|
|
let scheme = getScheme(request);
|
|
|
|
|
|
|
|
if (!scheme) {
|
|
|
|
/** @type {string} */
|
|
|
|
let requestWithoutMatchResource = request;
|
|
|
|
const matchResourceMatch = MATCH_RESOURCE_REGEX.exec(request);
|
|
|
|
if (matchResourceMatch) {
|
|
|
|
let matchResource = matchResourceMatch[1];
|
2025-05-13 21:03:58 +08:00
|
|
|
// Check if matchResource starts with ./ or ../
|
2021-08-04 21:55:58 +08:00
|
|
|
if (matchResource.charCodeAt(0) === 46) {
|
2025-05-13 21:03:58 +08:00
|
|
|
// 46 is "."
|
2021-08-04 21:55:58 +08:00
|
|
|
const secondChar = matchResource.charCodeAt(1);
|
|
|
|
if (
|
2025-05-13 21:03:58 +08:00
|
|
|
secondChar === 47 || // 47 is "/"
|
|
|
|
(secondChar === 46 && matchResource.charCodeAt(2) === 47) // "../"
|
2021-08-04 21:55:58 +08:00
|
|
|
) {
|
2025-05-13 21:03:58 +08:00
|
|
|
// Resolve relative path against context
|
2021-08-04 21:55:58 +08:00
|
|
|
matchResource = join(this.fs, context, matchResource);
|
|
|
|
}
|
2019-01-05 18:19:30 +08:00
|
|
|
}
|
2025-03-11 10:03:41 +08:00
|
|
|
|
2021-08-04 21:55:58 +08:00
|
|
|
matchResourceData = {
|
2025-05-13 21:03:58 +08:00
|
|
|
...cacheParseResource(matchResource),
|
|
|
|
resource: matchResource
|
2021-08-04 21:55:58 +08:00
|
|
|
};
|
2022-03-14 05:54:18 +08:00
|
|
|
requestWithoutMatchResource = request.slice(
|
2021-08-04 21:55:58 +08:00
|
|
|
matchResourceMatch[0].length
|
|
|
|
);
|
2019-01-05 02:17:37 +08:00
|
|
|
}
|
2018-06-01 20:54:54 +08:00
|
|
|
|
2021-08-04 21:55:58 +08:00
|
|
|
scheme = getScheme(requestWithoutMatchResource);
|
|
|
|
|
|
|
|
if (!scheme && !contextScheme) {
|
|
|
|
const firstChar = requestWithoutMatchResource.charCodeAt(0);
|
|
|
|
const secondChar = requestWithoutMatchResource.charCodeAt(1);
|
|
|
|
noPreAutoLoaders = firstChar === 45 && secondChar === 33; // startsWith "-!"
|
|
|
|
noAutoLoaders = noPreAutoLoaders || firstChar === 33; // startsWith "!"
|
|
|
|
noPrePostAutoLoaders = firstChar === 33 && secondChar === 33; // startsWith "!!";
|
|
|
|
const rawElements = requestWithoutMatchResource
|
|
|
|
.slice(
|
|
|
|
noPreAutoLoaders || noPrePostAutoLoaders
|
|
|
|
? 2
|
|
|
|
: noAutoLoaders
|
2024-07-31 05:43:19 +08:00
|
|
|
? 1
|
|
|
|
: 0
|
2021-08-04 21:55:58 +08:00
|
|
|
)
|
|
|
|
.split(/!+/);
|
2024-02-17 01:39:12 +08:00
|
|
|
unresolvedResource = /** @type {string} */ (rawElements.pop());
|
2025-07-17 00:13:14 +08:00
|
|
|
elements = rawElements.map((el) => {
|
2022-02-03 23:21:06 +08:00
|
|
|
const { path, query } = cachedParseResourceWithoutFragment(el);
|
|
|
|
return {
|
|
|
|
loader: path,
|
|
|
|
options: query ? query.slice(1) : undefined
|
|
|
|
};
|
|
|
|
});
|
2021-08-04 21:55:58 +08:00
|
|
|
scheme = getScheme(unresolvedResource);
|
|
|
|
} else {
|
|
|
|
unresolvedResource = requestWithoutMatchResource;
|
|
|
|
elements = EMPTY_ELEMENTS;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
unresolvedResource = request;
|
|
|
|
elements = EMPTY_ELEMENTS;
|
|
|
|
}
|
2019-01-05 02:17:37 +08:00
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/** @type {ResolveContext} */
|
2019-01-05 02:17:37 +08:00
|
|
|
const resolveContext = {
|
|
|
|
fileDependencies,
|
|
|
|
missingDependencies,
|
|
|
|
contextDependencies
|
|
|
|
};
|
|
|
|
|
2020-07-03 20:45:49 +08:00
|
|
|
/** @type {ResourceDataWithData} */
|
|
|
|
let resourceData;
|
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/** @type {undefined | LoaderItem[]} */
|
2019-01-05 18:19:30 +08:00
|
|
|
let loaders;
|
2019-01-05 02:17:37 +08:00
|
|
|
|
2025-07-17 00:13:14 +08:00
|
|
|
const continueCallback = needCalls(2, (err) => {
|
2019-01-05 18:19:30 +08:00
|
|
|
if (err) return callback(err);
|
2019-01-05 02:17:37 +08:00
|
|
|
|
2019-01-05 18:19:30 +08:00
|
|
|
// translate option idents
|
|
|
|
try {
|
2024-02-17 01:39:12 +08:00
|
|
|
for (const item of /** @type {LoaderItem[]} */ (loaders)) {
|
2019-01-05 18:19:30 +08:00
|
|
|
if (typeof item.options === "string" && item.options[0] === "?") {
|
2022-03-14 05:54:18 +08:00
|
|
|
const ident = item.options.slice(1);
|
2019-05-16 17:31:41 +08:00
|
|
|
if (ident === "[[missing ident]]") {
|
|
|
|
throw new Error(
|
|
|
|
"No ident is provided by referenced loader. " +
|
|
|
|
"When using a function for Rule.use in config you need to " +
|
|
|
|
"provide an 'ident' property for referenced loader options."
|
|
|
|
);
|
|
|
|
}
|
|
|
|
item.options = this.ruleSet.references.get(ident);
|
|
|
|
if (item.options === undefined) {
|
|
|
|
throw new Error(
|
|
|
|
"Invalid ident is provided by referenced loader"
|
|
|
|
);
|
|
|
|
}
|
2019-01-05 18:19:30 +08:00
|
|
|
item.ident = ident;
|
2018-02-25 09:00:20 +08:00
|
|
|
}
|
2017-04-04 05:28:08 +08:00
|
|
|
}
|
2024-07-31 15:37:05 +08:00
|
|
|
} catch (identErr) {
|
|
|
|
return callback(/** @type {Error} */ (identErr));
|
2019-01-05 18:19:30 +08:00
|
|
|
}
|
2017-07-24 17:54:58 +08:00
|
|
|
|
2020-07-03 20:45:49 +08:00
|
|
|
if (!resourceData) {
|
2019-01-05 18:19:30 +08:00
|
|
|
// ignored
|
2025-05-13 21:03:58 +08:00
|
|
|
return callback(null, dependencies[0].createIgnoredModule(context));
|
2019-01-05 18:19:30 +08:00
|
|
|
}
|
2017-07-24 17:54:58 +08:00
|
|
|
|
2019-01-05 18:19:30 +08:00
|
|
|
const userRequest =
|
2020-07-03 20:45:49 +08:00
|
|
|
(matchResourceData !== undefined
|
|
|
|
? `${matchResourceData.resource}!=!`
|
|
|
|
: "") +
|
2024-02-17 01:39:12 +08:00
|
|
|
stringifyLoadersAndResource(
|
|
|
|
/** @type {LoaderItem[]} */ (loaders),
|
|
|
|
resourceData.resource
|
|
|
|
);
|
2017-07-24 17:54:58 +08:00
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/** @type {ModuleSettings} */
|
2019-01-05 18:19:30 +08:00
|
|
|
const settings = {};
|
2025-07-10 21:30:16 +08:00
|
|
|
/** @type {LoaderItem[]} */
|
2019-01-05 18:19:30 +08:00
|
|
|
const useLoadersPost = [];
|
2025-07-10 21:30:16 +08:00
|
|
|
/** @type {LoaderItem[]} */
|
2019-01-05 18:19:30 +08:00
|
|
|
const useLoaders = [];
|
2025-07-10 21:30:16 +08:00
|
|
|
/** @type {LoaderItem[]} */
|
2019-01-05 18:19:30 +08:00
|
|
|
const useLoadersPre = [];
|
2021-10-08 19:53:33 +08:00
|
|
|
|
|
|
|
// handle .webpack[] suffix
|
|
|
|
let resource;
|
|
|
|
let match;
|
|
|
|
if (
|
|
|
|
matchResourceData &&
|
|
|
|
typeof (resource = matchResourceData.resource) === "string" &&
|
|
|
|
(match = /\.webpack\[([^\]]+)\]$/.exec(resource))
|
|
|
|
) {
|
|
|
|
settings.type = match[1];
|
|
|
|
matchResourceData.resource = matchResourceData.resource.slice(
|
|
|
|
0,
|
|
|
|
-settings.type.length - 10
|
|
|
|
);
|
|
|
|
} else {
|
2023-04-01 01:56:32 +08:00
|
|
|
settings.type = JAVASCRIPT_MODULE_TYPE_AUTO;
|
2021-10-08 19:53:33 +08:00
|
|
|
const resourceDataForRules = matchResourceData || resourceData;
|
|
|
|
const result = this.ruleSet.exec({
|
|
|
|
resource: resourceDataForRules.path,
|
|
|
|
realResource: resourceData.path,
|
|
|
|
resourceQuery: resourceDataForRules.query,
|
|
|
|
resourceFragment: resourceDataForRules.fragment,
|
|
|
|
scheme,
|
2025-09-18 20:37:40 +08:00
|
|
|
attributes,
|
2021-10-08 19:53:33 +08:00
|
|
|
mimetype: matchResourceData
|
|
|
|
? ""
|
|
|
|
: resourceData.data.mimetype || "",
|
|
|
|
dependency: dependencyType,
|
|
|
|
descriptionData: matchResourceData
|
|
|
|
? undefined
|
|
|
|
: resourceData.data.descriptionFileData,
|
|
|
|
issuer: contextInfo.issuer,
|
|
|
|
compiler: contextInfo.compiler,
|
|
|
|
issuerLayer: contextInfo.issuerLayer || ""
|
|
|
|
});
|
|
|
|
for (const r of result) {
|
2022-11-15 13:42:38 +08:00
|
|
|
// https://github.com/webpack/webpack/issues/16466
|
|
|
|
// if a request exists PrePostAutoLoaders, should disable modifying Rule.type
|
|
|
|
if (r.type === "type" && noPrePostAutoLoaders) {
|
|
|
|
continue;
|
|
|
|
}
|
2021-10-08 19:53:33 +08:00
|
|
|
if (r.type === "use") {
|
|
|
|
if (!noAutoLoaders && !noPrePostAutoLoaders) {
|
|
|
|
useLoaders.push(r.value);
|
|
|
|
}
|
|
|
|
} else if (r.type === "use-post") {
|
|
|
|
if (!noPrePostAutoLoaders) {
|
|
|
|
useLoadersPost.push(r.value);
|
|
|
|
}
|
|
|
|
} else if (r.type === "use-pre") {
|
|
|
|
if (!noPreAutoLoaders && !noPrePostAutoLoaders) {
|
|
|
|
useLoadersPre.push(r.value);
|
|
|
|
}
|
|
|
|
} else if (
|
|
|
|
typeof r.value === "object" &&
|
|
|
|
r.value !== null &&
|
2024-08-09 23:42:37 +08:00
|
|
|
typeof settings[
|
2025-07-10 21:30:16 +08:00
|
|
|
/** @type {keyof ModuleSettings} */
|
|
|
|
(r.type)
|
2024-08-09 23:42:37 +08:00
|
|
|
] === "object" &&
|
|
|
|
settings[/** @type {keyof ModuleSettings} */ (r.type)] !== null
|
2021-10-08 19:53:33 +08:00
|
|
|
) {
|
2025-03-11 22:20:50 +08:00
|
|
|
const type = /** @type {keyof ModuleSettings} */ (r.type);
|
2025-05-23 21:39:55 +08:00
|
|
|
settings[type] = cachedCleverMerge(settings[type], r.value);
|
2021-10-08 19:53:33 +08:00
|
|
|
} else {
|
2025-03-11 22:20:50 +08:00
|
|
|
const type = /** @type {keyof ModuleSettings} */ (r.type);
|
2025-05-23 21:39:55 +08:00
|
|
|
settings[type] = r.value;
|
2018-05-29 20:50:40 +08:00
|
|
|
}
|
2018-02-25 09:00:20 +08:00
|
|
|
}
|
2019-01-05 18:19:30 +08:00
|
|
|
}
|
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/** @type {undefined | LoaderItem[]} */
|
|
|
|
let postLoaders;
|
|
|
|
/** @type {undefined | LoaderItem[]} */
|
|
|
|
let normalLoaders;
|
|
|
|
/** @type {undefined | LoaderItem[]} */
|
|
|
|
let preLoaders;
|
2019-01-05 18:19:30 +08:00
|
|
|
|
2025-07-17 00:13:14 +08:00
|
|
|
const continueCallback = needCalls(3, (err) => {
|
2019-01-05 18:19:30 +08:00
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
2024-02-17 01:39:12 +08:00
|
|
|
const allLoaders = /** @type {LoaderItem[]} */ (postLoaders);
|
2020-07-03 20:45:49 +08:00
|
|
|
if (matchResourceData === undefined) {
|
2025-07-02 20:10:54 +08:00
|
|
|
for (const loader of /** @type {LoaderItem[]} */ (loaders)) {
|
2024-02-17 01:39:12 +08:00
|
|
|
allLoaders.push(loader);
|
2025-07-02 20:10:54 +08:00
|
|
|
}
|
|
|
|
for (const loader of /** @type {LoaderItem[]} */ (
|
|
|
|
normalLoaders
|
|
|
|
)) {
|
2024-02-17 01:39:12 +08:00
|
|
|
allLoaders.push(loader);
|
2025-07-02 20:10:54 +08:00
|
|
|
}
|
2019-07-01 17:15:52 +08:00
|
|
|
} else {
|
2025-07-02 20:10:54 +08:00
|
|
|
for (const loader of /** @type {LoaderItem[]} */ (
|
|
|
|
normalLoaders
|
|
|
|
)) {
|
2024-02-17 01:39:12 +08:00
|
|
|
allLoaders.push(loader);
|
2025-07-02 20:10:54 +08:00
|
|
|
}
|
|
|
|
for (const loader of /** @type {LoaderItem[]} */ (loaders)) {
|
2024-02-17 01:39:12 +08:00
|
|
|
allLoaders.push(loader);
|
2025-07-02 20:10:54 +08:00
|
|
|
}
|
2019-07-01 17:15:52 +08:00
|
|
|
}
|
2025-07-02 20:10:54 +08:00
|
|
|
for (const loader of /** @type {LoaderItem[]} */ (preLoaders)) {
|
2024-02-17 01:39:12 +08:00
|
|
|
allLoaders.push(loader);
|
2025-07-02 20:10:54 +08:00
|
|
|
}
|
2025-08-28 18:34:30 +08:00
|
|
|
const type = /** @type {NormalModuleTypes} */ (settings.type);
|
2019-01-05 18:19:30 +08:00
|
|
|
const resolveOptions = settings.resolve;
|
2020-12-22 21:51:09 +08:00
|
|
|
const layer = settings.layer;
|
2025-08-29 21:08:28 +08:00
|
|
|
|
2021-04-29 22:18:10 +08:00
|
|
|
try {
|
|
|
|
Object.assign(data.createData, {
|
|
|
|
layer:
|
|
|
|
layer === undefined ? contextInfo.issuerLayer || null : layer,
|
|
|
|
request: stringifyLoadersAndResource(
|
|
|
|
allLoaders,
|
|
|
|
resourceData.resource
|
|
|
|
),
|
|
|
|
userRequest,
|
|
|
|
rawRequest: request,
|
|
|
|
loaders: allLoaders,
|
|
|
|
resource: resourceData.resource,
|
2021-08-06 00:47:24 +08:00
|
|
|
context:
|
|
|
|
resourceData.context || getContext(resourceData.resource),
|
2021-04-29 22:18:10 +08:00
|
|
|
matchResource: matchResourceData
|
|
|
|
? matchResourceData.resource
|
|
|
|
: undefined,
|
|
|
|
resourceResolveData: resourceData.data,
|
|
|
|
settings,
|
|
|
|
type,
|
|
|
|
parser: this.getParser(type, settings.parser),
|
|
|
|
parserOptions: settings.parser,
|
|
|
|
generator: this.getGenerator(type, settings.generator),
|
|
|
|
generatorOptions: settings.generator,
|
2025-08-27 23:53:50 +08:00
|
|
|
resolveOptions,
|
|
|
|
extractSourceMap: settings.extractSourceMap || false
|
2021-04-29 22:18:10 +08:00
|
|
|
});
|
2024-07-31 15:37:05 +08:00
|
|
|
} catch (createDataErr) {
|
|
|
|
return callback(/** @type {Error} */ (createDataErr));
|
2021-04-29 22:18:10 +08:00
|
|
|
}
|
2019-01-05 18:19:30 +08:00
|
|
|
callback();
|
|
|
|
});
|
|
|
|
this.resolveRequestArray(
|
|
|
|
contextInfo,
|
|
|
|
this.context,
|
|
|
|
useLoadersPost,
|
|
|
|
loaderResolver,
|
|
|
|
resolveContext,
|
|
|
|
(err, result) => {
|
|
|
|
postLoaders = result;
|
|
|
|
continueCallback(err);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
this.resolveRequestArray(
|
|
|
|
contextInfo,
|
|
|
|
this.context,
|
|
|
|
useLoaders,
|
|
|
|
loaderResolver,
|
|
|
|
resolveContext,
|
|
|
|
(err, result) => {
|
|
|
|
normalLoaders = result;
|
|
|
|
continueCallback(err);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
this.resolveRequestArray(
|
|
|
|
contextInfo,
|
|
|
|
this.context,
|
|
|
|
useLoadersPre,
|
|
|
|
loaderResolver,
|
|
|
|
resolveContext,
|
|
|
|
(err, result) => {
|
|
|
|
preLoaders = result;
|
|
|
|
continueCallback(err);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
this.resolveRequestArray(
|
|
|
|
contextInfo,
|
2021-08-04 21:55:58 +08:00
|
|
|
contextScheme ? this.context : context,
|
2024-02-17 01:39:12 +08:00
|
|
|
/** @type {LoaderItem[]} */ (elements),
|
2019-01-05 18:19:30 +08:00
|
|
|
loaderResolver,
|
|
|
|
resolveContext,
|
|
|
|
(err, result) => {
|
|
|
|
if (err) return continueCallback(err);
|
|
|
|
loaders = result;
|
|
|
|
continueCallback();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/**
|
|
|
|
* @param {string} context context
|
|
|
|
*/
|
2025-07-17 00:13:14 +08:00
|
|
|
const defaultResolve = (context) => {
|
2021-08-04 21:55:58 +08:00
|
|
|
if (/^($|\?)/.test(unresolvedResource)) {
|
|
|
|
resourceData = {
|
2025-05-13 21:03:58 +08:00
|
|
|
...cacheParseResource(unresolvedResource),
|
2021-08-04 21:55:58 +08:00
|
|
|
resource: unresolvedResource,
|
2025-05-13 21:03:58 +08:00
|
|
|
data: {}
|
2021-08-04 21:55:58 +08:00
|
|
|
};
|
|
|
|
continueCallback();
|
|
|
|
}
|
|
|
|
|
|
|
|
// resource without scheme and with path
|
|
|
|
else {
|
|
|
|
const normalResolver = this.getResolver(
|
|
|
|
"normal",
|
|
|
|
dependencyType
|
|
|
|
? cachedSetProperty(
|
|
|
|
resolveOptions || EMPTY_RESOLVE_OPTIONS,
|
|
|
|
"dependencyType",
|
|
|
|
dependencyType
|
2024-07-31 05:43:19 +08:00
|
|
|
)
|
2021-08-04 21:55:58 +08:00
|
|
|
: resolveOptions
|
|
|
|
);
|
|
|
|
this.resolveResource(
|
|
|
|
contextInfo,
|
|
|
|
context,
|
|
|
|
unresolvedResource,
|
|
|
|
normalResolver,
|
|
|
|
resolveContext,
|
2024-08-09 23:42:37 +08:00
|
|
|
(err, _resolvedResource, resolvedResourceResolveData) => {
|
2021-08-04 21:55:58 +08:00
|
|
|
if (err) return continueCallback(err);
|
2024-08-09 23:42:37 +08:00
|
|
|
if (_resolvedResource !== false) {
|
|
|
|
const resolvedResource =
|
|
|
|
/** @type {string} */
|
|
|
|
(_resolvedResource);
|
2021-08-04 21:55:58 +08:00
|
|
|
resourceData = {
|
2025-05-13 21:03:58 +08:00
|
|
|
...cacheParseResource(resolvedResource),
|
2021-08-04 21:55:58 +08:00
|
|
|
resource: resolvedResource,
|
2024-08-09 23:42:37 +08:00
|
|
|
data:
|
|
|
|
/** @type {ResolveRequest} */
|
2025-05-13 21:03:58 +08:00
|
|
|
(resolvedResourceResolveData)
|
2021-08-04 21:55:58 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
continueCallback();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-07-03 20:45:49 +08:00
|
|
|
// resource with scheme
|
|
|
|
if (scheme) {
|
|
|
|
resourceData = {
|
|
|
|
resource: unresolvedResource,
|
|
|
|
data: {},
|
|
|
|
path: undefined,
|
|
|
|
query: undefined,
|
2021-08-06 00:47:24 +08:00
|
|
|
fragment: undefined,
|
|
|
|
context: undefined
|
2020-07-03 20:45:49 +08:00
|
|
|
};
|
|
|
|
this.hooks.resolveForScheme
|
|
|
|
.for(scheme)
|
2025-07-17 00:13:14 +08:00
|
|
|
.callAsync(resourceData, data, (err) => {
|
2020-07-03 20:45:49 +08:00
|
|
|
if (err) return continueCallback(err);
|
|
|
|
continueCallback();
|
|
|
|
});
|
2019-01-05 18:19:30 +08:00
|
|
|
}
|
|
|
|
|
2021-08-04 21:55:58 +08:00
|
|
|
// resource within scheme
|
|
|
|
else if (contextScheme) {
|
2020-07-03 20:45:49 +08:00
|
|
|
resourceData = {
|
|
|
|
resource: unresolvedResource,
|
|
|
|
data: {},
|
2021-08-04 21:55:58 +08:00
|
|
|
path: undefined,
|
|
|
|
query: undefined,
|
2021-08-06 00:47:24 +08:00
|
|
|
fragment: undefined,
|
|
|
|
context: undefined
|
2020-07-03 20:45:49 +08:00
|
|
|
};
|
2021-08-04 21:55:58 +08:00
|
|
|
this.hooks.resolveInScheme
|
|
|
|
.for(contextScheme)
|
|
|
|
.callAsync(resourceData, data, (err, handled) => {
|
2020-05-17 21:28:15 +08:00
|
|
|
if (err) return continueCallback(err);
|
2021-08-04 21:55:58 +08:00
|
|
|
if (!handled) return defaultResolve(this.context);
|
2020-05-17 21:28:15 +08:00
|
|
|
continueCallback();
|
2021-08-04 21:55:58 +08:00
|
|
|
});
|
2020-05-17 21:28:15 +08:00
|
|
|
}
|
2021-08-04 21:55:58 +08:00
|
|
|
|
|
|
|
// resource without scheme and without path
|
2025-07-02 20:10:54 +08:00
|
|
|
else {
|
|
|
|
defaultResolve(context);
|
|
|
|
}
|
2019-01-05 02:17:37 +08:00
|
|
|
}
|
|
|
|
);
|
2017-04-04 05:28:08 +08:00
|
|
|
}
|
2013-01-31 01:49:25 +08:00
|
|
|
|
2021-07-01 17:46:59 +08:00
|
|
|
cleanupForCache() {
|
|
|
|
for (const module of this._restoredUnsafeCacheEntries) {
|
|
|
|
ChunkGraph.clearChunkGraphForModule(module);
|
|
|
|
ModuleGraph.clearModuleGraphForModule(module);
|
|
|
|
module.cleanupForCache();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-05 02:17:37 +08:00
|
|
|
/**
|
|
|
|
* @param {ModuleFactoryCreateData} data data object
|
2025-03-12 09:56:14 +08:00
|
|
|
* @param {ModuleFactoryCallback} callback callback
|
2019-01-05 02:17:37 +08:00
|
|
|
* @returns {void}
|
|
|
|
*/
|
2017-04-04 05:28:08 +08:00
|
|
|
create(data, callback) {
|
2019-01-05 02:17:37 +08:00
|
|
|
const dependencies = /** @type {ModuleDependency[]} */ (data.dependencies);
|
2017-04-04 16:26:16 +08:00
|
|
|
const context = data.context || this.context;
|
2020-06-17 02:01:06 +08:00
|
|
|
const resolveOptions = data.resolveOptions || EMPTY_RESOLVE_OPTIONS;
|
2019-01-05 02:17:37 +08:00
|
|
|
const dependency = dependencies[0];
|
|
|
|
const request = dependency.request;
|
2025-09-18 20:37:40 +08:00
|
|
|
const attributes =
|
|
|
|
/** @type {ModuleDependency & { attributes: ImportAttributes }} */
|
|
|
|
(dependency).attributes;
|
2025-02-26 20:13:42 +08:00
|
|
|
const dependencyType = dependency.category || "";
|
2019-01-05 02:17:37 +08:00
|
|
|
const contextInfo = data.contextInfo;
|
2019-08-07 15:54:43 +08:00
|
|
|
const fileDependencies = new LazySet();
|
|
|
|
const missingDependencies = new LazySet();
|
|
|
|
const contextDependencies = new LazySet();
|
2019-01-05 02:17:37 +08:00
|
|
|
/** @type {ResolveData} */
|
|
|
|
const resolveData = {
|
|
|
|
contextInfo,
|
|
|
|
resolveOptions,
|
|
|
|
context,
|
|
|
|
request,
|
2025-09-18 20:37:40 +08:00
|
|
|
attributes,
|
2019-01-05 02:17:37 +08:00
|
|
|
dependencies,
|
2021-08-05 23:04:52 +08:00
|
|
|
dependencyType,
|
2019-01-05 02:17:37 +08:00
|
|
|
fileDependencies,
|
|
|
|
missingDependencies,
|
|
|
|
contextDependencies,
|
2020-06-24 20:09:10 +08:00
|
|
|
createData: {},
|
|
|
|
cacheable: true
|
2019-01-05 02:17:37 +08:00
|
|
|
};
|
|
|
|
this.hooks.beforeResolve.callAsync(resolveData, (err, result) => {
|
2019-07-05 06:41:30 +08:00
|
|
|
if (err) {
|
|
|
|
return callback(err, {
|
|
|
|
fileDependencies,
|
|
|
|
missingDependencies,
|
2021-09-28 01:03:55 +08:00
|
|
|
contextDependencies,
|
|
|
|
cacheable: false
|
2019-07-05 06:41:30 +08:00
|
|
|
});
|
|
|
|
}
|
2016-12-05 06:47:19 +08:00
|
|
|
|
2019-01-05 02:17:37 +08:00
|
|
|
// Ignored
|
2019-07-05 06:41:30 +08:00
|
|
|
if (result === false) {
|
2024-10-23 08:01:04 +08:00
|
|
|
/** @type {ModuleFactoryResult} * */
|
|
|
|
const factoryResult = {
|
2019-07-05 06:41:30 +08:00
|
|
|
fileDependencies,
|
|
|
|
missingDependencies,
|
2021-09-28 01:03:55 +08:00
|
|
|
contextDependencies,
|
|
|
|
cacheable: resolveData.cacheable
|
2024-10-23 08:01:04 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
if (resolveData.ignoredModule) {
|
|
|
|
factoryResult.module = resolveData.ignoredModule;
|
|
|
|
}
|
|
|
|
|
|
|
|
return callback(null, factoryResult);
|
2019-07-05 06:41:30 +08:00
|
|
|
}
|
2016-12-05 06:47:19 +08:00
|
|
|
|
2025-07-02 20:10:54 +08:00
|
|
|
if (typeof result === "object") {
|
2020-11-21 03:49:27 +08:00
|
|
|
throw new Error(
|
|
|
|
deprecationChangedHookMessage(
|
|
|
|
"beforeResolve",
|
|
|
|
this.hooks.beforeResolve
|
|
|
|
)
|
|
|
|
);
|
2025-07-02 20:10:54 +08:00
|
|
|
}
|
2013-11-06 01:19:04 +08:00
|
|
|
|
2019-01-05 02:17:37 +08:00
|
|
|
this.hooks.factorize.callAsync(resolveData, (err, module) => {
|
2019-07-05 06:41:30 +08:00
|
|
|
if (err) {
|
|
|
|
return callback(err, {
|
|
|
|
fileDependencies,
|
|
|
|
missingDependencies,
|
2021-09-28 01:03:55 +08:00
|
|
|
contextDependencies,
|
|
|
|
cacheable: false
|
2019-07-05 06:41:30 +08:00
|
|
|
});
|
|
|
|
}
|
2016-12-08 16:39:30 +08:00
|
|
|
|
2024-10-23 08:01:04 +08:00
|
|
|
/** @type {ModuleFactoryResult} * */
|
2019-01-05 02:17:37 +08:00
|
|
|
const factoryResult = {
|
|
|
|
module,
|
|
|
|
fileDependencies,
|
|
|
|
missingDependencies,
|
2021-09-28 01:03:55 +08:00
|
|
|
contextDependencies,
|
|
|
|
cacheable: resolveData.cacheable
|
2019-01-05 02:17:37 +08:00
|
|
|
};
|
2017-04-04 05:28:08 +08:00
|
|
|
|
2019-01-05 02:17:37 +08:00
|
|
|
callback(null, factoryResult);
|
|
|
|
});
|
|
|
|
});
|
2016-09-14 18:04:42 +08:00
|
|
|
}
|
2017-04-04 05:28:08 +08:00
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/**
|
|
|
|
* @param {ModuleFactoryCreateDataContextInfo} contextInfo context info
|
|
|
|
* @param {string} context context
|
|
|
|
* @param {string} unresolvedResource unresolved resource
|
|
|
|
* @param {ResolverWithOptions} resolver resolver
|
|
|
|
* @param {ResolveContext} resolveContext resolver context
|
2024-02-17 02:03:51 +08:00
|
|
|
* @param {(err: null | Error, res?: string | false, req?: ResolveRequest) => void} callback callback
|
2024-02-17 01:39:12 +08:00
|
|
|
*/
|
2020-09-15 21:10:25 +08:00
|
|
|
resolveResource(
|
|
|
|
contextInfo,
|
|
|
|
context,
|
|
|
|
unresolvedResource,
|
|
|
|
resolver,
|
|
|
|
resolveContext,
|
|
|
|
callback
|
|
|
|
) {
|
|
|
|
resolver.resolve(
|
|
|
|
contextInfo,
|
|
|
|
context,
|
|
|
|
unresolvedResource,
|
|
|
|
resolveContext,
|
|
|
|
(err, resolvedResource, resolvedResourceResolveData) => {
|
|
|
|
if (err) {
|
2021-02-09 05:11:05 +08:00
|
|
|
return this._resolveResourceErrorHints(
|
|
|
|
err,
|
|
|
|
contextInfo,
|
|
|
|
context,
|
|
|
|
unresolvedResource,
|
|
|
|
resolver,
|
|
|
|
resolveContext,
|
|
|
|
(err2, hints) => {
|
|
|
|
if (err2) {
|
|
|
|
err.message += `
|
2023-03-11 12:50:50 +08:00
|
|
|
A fatal error happened during resolving additional hints for this error: ${err2.message}`;
|
2021-02-09 05:11:05 +08:00
|
|
|
err.stack += `
|
|
|
|
|
2023-03-11 12:50:50 +08:00
|
|
|
A fatal error happened during resolving additional hints for this error:
|
2021-02-09 05:11:05 +08:00
|
|
|
${err2.stack}`;
|
|
|
|
return callback(err);
|
|
|
|
}
|
|
|
|
if (hints && hints.length > 0) {
|
|
|
|
err.message += `
|
|
|
|
${hints.join("\n\n")}`;
|
|
|
|
}
|
2023-03-11 13:30:12 +08:00
|
|
|
|
|
|
|
// Check if the extension is missing a leading dot (e.g. "js" instead of ".js")
|
2023-03-12 18:48:01 +08:00
|
|
|
let appendResolveExtensionsHint = false;
|
2025-07-03 17:06:45 +08:00
|
|
|
const specifiedExtensions = [...resolver.options.extensions];
|
2025-07-17 00:13:14 +08:00
|
|
|
const expectedExtensions = specifiedExtensions.map(
|
|
|
|
(extension) => {
|
|
|
|
if (LEADING_DOT_EXTENSION_REGEX.test(extension)) {
|
|
|
|
appendResolveExtensionsHint = true;
|
|
|
|
return `.${extension}`;
|
|
|
|
}
|
|
|
|
return extension;
|
2023-03-11 13:30:12 +08:00
|
|
|
}
|
2025-07-17 00:13:14 +08:00
|
|
|
);
|
2023-03-12 18:48:01 +08:00
|
|
|
if (appendResolveExtensionsHint) {
|
|
|
|
err.message += `\nDid you miss the leading dot in 'resolve.extensions'? Did you mean '${JSON.stringify(
|
|
|
|
expectedExtensions
|
|
|
|
)}' instead of '${JSON.stringify(specifiedExtensions)}'?`;
|
|
|
|
}
|
2023-03-11 13:30:12 +08:00
|
|
|
|
2021-02-09 05:11:05 +08:00
|
|
|
callback(err);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
callback(err, resolvedResource, resolvedResourceResolveData);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/**
|
|
|
|
* @param {Error} error error
|
|
|
|
* @param {ModuleFactoryCreateDataContextInfo} contextInfo context info
|
|
|
|
* @param {string} context context
|
|
|
|
* @param {string} unresolvedResource unresolved resource
|
|
|
|
* @param {ResolverWithOptions} resolver resolver
|
|
|
|
* @param {ResolveContext} resolveContext resolver context
|
|
|
|
* @param {Callback<string[]>} callback callback
|
|
|
|
* @private
|
|
|
|
*/
|
2021-02-09 05:11:05 +08:00
|
|
|
_resolveResourceErrorHints(
|
|
|
|
error,
|
|
|
|
contextInfo,
|
|
|
|
context,
|
|
|
|
unresolvedResource,
|
|
|
|
resolver,
|
|
|
|
resolveContext,
|
|
|
|
callback
|
|
|
|
) {
|
|
|
|
asyncLib.parallel(
|
|
|
|
[
|
2025-07-17 00:13:14 +08:00
|
|
|
(callback) => {
|
2021-02-09 05:11:05 +08:00
|
|
|
if (!resolver.options.fullySpecified) return callback();
|
|
|
|
resolver
|
|
|
|
.withOptions({
|
|
|
|
fullySpecified: false
|
|
|
|
})
|
|
|
|
.resolve(
|
|
|
|
contextInfo,
|
|
|
|
context,
|
|
|
|
unresolvedResource,
|
|
|
|
resolveContext,
|
|
|
|
(err, resolvedResource) => {
|
|
|
|
if (!err && resolvedResource) {
|
|
|
|
const resource = parseResource(resolvedResource).path.replace(
|
|
|
|
/^.*[\\/]/,
|
|
|
|
""
|
|
|
|
);
|
|
|
|
return callback(
|
|
|
|
null,
|
|
|
|
`Did you mean '${resource}'?
|
2020-09-15 21:10:25 +08:00
|
|
|
BREAKING CHANGE: The request '${unresolvedResource}' failed to resolve only because it was resolved as fully specified
|
2021-08-06 00:47:24 +08:00
|
|
|
(probably because the origin is strict EcmaScript Module, e. g. a module with javascript mimetype, a '*.mjs' file, or a '*.js' file where the package.json contains '"type": "module"').
|
2020-09-15 21:10:25 +08:00
|
|
|
The extension in the request is mandatory for it to be fully specified.
|
2021-02-09 05:11:05 +08:00
|
|
|
Add the extension to the request.`
|
|
|
|
);
|
|
|
|
}
|
|
|
|
callback();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
2025-07-17 00:13:14 +08:00
|
|
|
(callback) => {
|
2021-02-09 05:11:05 +08:00
|
|
|
if (!resolver.options.enforceExtension) return callback();
|
|
|
|
resolver
|
|
|
|
.withOptions({
|
|
|
|
enforceExtension: false,
|
|
|
|
extensions: []
|
|
|
|
})
|
|
|
|
.resolve(
|
|
|
|
contextInfo,
|
|
|
|
context,
|
|
|
|
unresolvedResource,
|
|
|
|
resolveContext,
|
|
|
|
(err, resolvedResource) => {
|
|
|
|
if (!err && resolvedResource) {
|
|
|
|
let hint = "";
|
|
|
|
const match = /(\.[^.]+)(\?|$)/.exec(unresolvedResource);
|
|
|
|
if (match) {
|
|
|
|
const fixedRequest = unresolvedResource.replace(
|
|
|
|
/(\.[^.]+)(\?|$)/,
|
|
|
|
"$2"
|
|
|
|
);
|
2024-08-02 02:36:27 +08:00
|
|
|
hint = resolver.options.extensions.has(match[1])
|
|
|
|
? `Did you mean '${fixedRequest}'?`
|
|
|
|
: `Did you mean '${fixedRequest}'? Also note that '${match[1]}' is not in 'resolve.extensions' yet and need to be added for this to work?`;
|
2021-02-09 05:11:05 +08:00
|
|
|
} else {
|
2024-07-31 12:23:44 +08:00
|
|
|
hint =
|
|
|
|
"Did you mean to omit the extension or to remove 'resolve.enforceExtension'?";
|
2020-09-15 21:10:25 +08:00
|
|
|
}
|
2021-02-09 05:11:05 +08:00
|
|
|
return callback(
|
|
|
|
null,
|
|
|
|
`The request '${unresolvedResource}' failed to resolve only because 'resolve.enforceExtension' was specified.
|
|
|
|
${hint}
|
|
|
|
Including the extension in the request is no longer possible. Did you mean to enforce including the extension in requests with 'resolve.extensions: []' instead?`
|
|
|
|
);
|
2020-09-15 21:10:25 +08:00
|
|
|
}
|
2021-02-09 05:11:05 +08:00
|
|
|
callback();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
2025-07-17 00:13:14 +08:00
|
|
|
(callback) => {
|
2021-02-09 05:11:05 +08:00
|
|
|
if (
|
|
|
|
/^\.\.?\//.test(unresolvedResource) ||
|
|
|
|
resolver.options.preferRelative
|
|
|
|
) {
|
|
|
|
return callback();
|
2020-09-15 21:10:25 +08:00
|
|
|
}
|
2021-02-09 05:11:05 +08:00
|
|
|
resolver.resolve(
|
|
|
|
contextInfo,
|
|
|
|
context,
|
|
|
|
`./${unresolvedResource}`,
|
|
|
|
resolveContext,
|
|
|
|
(err, resolvedResource) => {
|
|
|
|
if (err || !resolvedResource) return callback();
|
|
|
|
const moduleDirectories = resolver.options.modules
|
2025-07-17 00:13:14 +08:00
|
|
|
.map((m) => (Array.isArray(m) ? m.join(", ") : m))
|
2021-02-09 05:11:05 +08:00
|
|
|
.join(", ");
|
|
|
|
callback(
|
|
|
|
null,
|
|
|
|
`Did you mean './${unresolvedResource}'?
|
|
|
|
Requests that should resolve in the current directory need to start with './'.
|
|
|
|
Requests that start with a name are treated as module requests and resolve within module directories (${moduleDirectories}).
|
|
|
|
If changing the source code is not an option there is also a resolve options called 'preferRelative' which tries to resolve these kind of requests in the current directory too.`
|
|
|
|
);
|
|
|
|
}
|
|
|
|
);
|
2020-09-15 21:10:25 +08:00
|
|
|
}
|
2021-02-09 05:11:05 +08:00
|
|
|
],
|
|
|
|
(err, hints) => {
|
|
|
|
if (err) return callback(err);
|
2024-02-17 01:39:12 +08:00
|
|
|
callback(null, /** @type {string[]} */ (hints).filter(Boolean));
|
2020-09-15 21:10:25 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/**
|
|
|
|
* @param {ModuleFactoryCreateDataContextInfo} contextInfo context info
|
|
|
|
* @param {string} context context
|
|
|
|
* @param {LoaderItem[]} array array
|
|
|
|
* @param {ResolverWithOptions} resolver resolver
|
|
|
|
* @param {ResolveContext} resolveContext resolve context
|
|
|
|
* @param {Callback<LoaderItem[]>} callback callback
|
|
|
|
* @returns {void} result
|
|
|
|
*/
|
2019-01-05 02:17:37 +08:00
|
|
|
resolveRequestArray(
|
|
|
|
contextInfo,
|
|
|
|
context,
|
|
|
|
array,
|
|
|
|
resolver,
|
|
|
|
resolveContext,
|
|
|
|
callback
|
|
|
|
) {
|
2024-02-17 01:39:12 +08:00
|
|
|
// LoaderItem
|
2019-01-05 18:19:30 +08:00
|
|
|
if (array.length === 0) return callback(null, array);
|
2018-02-25 09:00:20 +08:00
|
|
|
asyncLib.map(
|
|
|
|
array,
|
2025-08-22 06:40:41 +08:00
|
|
|
/**
|
|
|
|
* @param {LoaderItem} item item
|
|
|
|
* @param {Callback<LoaderItem>} callback callback
|
|
|
|
*/
|
2018-02-25 09:00:20 +08:00
|
|
|
(item, callback) => {
|
|
|
|
resolver.resolve(
|
|
|
|
contextInfo,
|
|
|
|
context,
|
|
|
|
item.loader,
|
2019-01-05 02:17:37 +08:00
|
|
|
resolveContext,
|
2021-12-02 01:42:59 +08:00
|
|
|
(err, result, resolveRequest) => {
|
2018-02-25 09:00:20 +08:00
|
|
|
if (
|
|
|
|
err &&
|
|
|
|
/^[^/]*$/.test(item.loader) &&
|
2024-07-31 16:17:46 +08:00
|
|
|
!item.loader.endsWith("-loader")
|
2018-02-25 09:00:20 +08:00
|
|
|
) {
|
|
|
|
return resolver.resolve(
|
|
|
|
contextInfo,
|
|
|
|
context,
|
2024-07-31 10:39:30 +08:00
|
|
|
`${item.loader}-loader`,
|
2019-01-05 18:19:30 +08:00
|
|
|
resolveContext,
|
2025-07-17 00:13:14 +08:00
|
|
|
(err2) => {
|
2018-02-25 09:00:20 +08:00
|
|
|
if (!err2) {
|
|
|
|
err.message =
|
2024-07-31 10:39:30 +08:00
|
|
|
`${err.message}\n` +
|
2024-07-31 12:23:44 +08:00
|
|
|
"BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix when using loaders.\n" +
|
2019-06-09 17:23:42 +08:00
|
|
|
` You need to specify '${item.loader}-loader' instead of '${item.loader}',\n` +
|
2024-07-31 12:23:44 +08:00
|
|
|
" see https://webpack.js.org/migrate/3/#automatic-loader-module-name-extension-removed";
|
2018-02-25 09:00:20 +08:00
|
|
|
}
|
|
|
|
callback(err);
|
|
|
|
}
|
|
|
|
);
|
2017-04-04 05:28:08 +08:00
|
|
|
}
|
2018-02-25 09:00:20 +08:00
|
|
|
if (err) return callback(err);
|
|
|
|
|
2024-08-06 11:08:48 +08:00
|
|
|
const parsedResult = this._parseResourceWithoutFragment(
|
2025-08-22 06:40:41 +08:00
|
|
|
/** @type {string} */
|
|
|
|
(result)
|
2024-08-06 11:08:48 +08:00
|
|
|
);
|
2022-01-21 14:56:16 +08:00
|
|
|
|
2023-04-18 20:02:05 +08:00
|
|
|
const type = /\.mjs$/i.test(parsedResult.path)
|
2022-01-21 14:56:16 +08:00
|
|
|
? "module"
|
2023-04-18 20:02:05 +08:00
|
|
|
: /\.cjs$/i.test(parsedResult.path)
|
2024-07-31 05:43:19 +08:00
|
|
|
? "commonjs"
|
|
|
|
: /** @type {ResolveRequest} */
|
|
|
|
(resolveRequest).descriptionFileData === undefined
|
|
|
|
? undefined
|
2025-08-22 06:40:41 +08:00
|
|
|
: /** @type {string} */
|
|
|
|
(
|
|
|
|
/** @type {ResolveRequest} */
|
|
|
|
(resolveRequest).descriptionFileData.type
|
|
|
|
);
|
|
|
|
/** @type {LoaderItem} */
|
2019-01-05 18:19:30 +08:00
|
|
|
const resolved = {
|
2022-02-03 23:21:06 +08:00
|
|
|
loader: parsedResult.path,
|
2022-01-21 14:56:16 +08:00
|
|
|
type,
|
2019-01-05 18:19:30 +08:00
|
|
|
options:
|
|
|
|
item.options === undefined
|
2022-02-03 23:21:06 +08:00
|
|
|
? parsedResult.query
|
|
|
|
? parsedResult.query.slice(1)
|
|
|
|
: undefined
|
2019-01-05 18:19:30 +08:00
|
|
|
: item.options,
|
2025-08-22 19:11:29 +08:00
|
|
|
ident: item.options === undefined ? undefined : item.ident
|
2019-01-05 18:19:30 +08:00
|
|
|
};
|
2024-02-17 01:39:12 +08:00
|
|
|
|
2025-08-22 06:40:41 +08:00
|
|
|
return callback(null, resolved);
|
2018-02-25 09:00:20 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
2025-08-22 06:40:41 +08:00
|
|
|
(err, value) => {
|
|
|
|
callback(err, /** @type {(LoaderItem)[]} */ (value));
|
|
|
|
}
|
2018-02-25 09:00:20 +08:00
|
|
|
);
|
2017-04-04 05:28:08 +08:00
|
|
|
}
|
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/**
|
|
|
|
* @param {string} type type
|
|
|
|
* @param {ParserOptions} parserOptions parser options
|
|
|
|
* @returns {Parser} parser
|
|
|
|
*/
|
2021-01-05 18:11:02 +08:00
|
|
|
getParser(type, parserOptions = EMPTY_PARSER_OPTIONS) {
|
2019-11-19 01:01:54 +08:00
|
|
|
let cache = this.parserCache.get(type);
|
2019-11-18 23:01:33 +08:00
|
|
|
|
2019-11-19 01:01:54 +08:00
|
|
|
if (cache === undefined) {
|
|
|
|
cache = new WeakMap();
|
|
|
|
this.parserCache.set(type, cache);
|
|
|
|
}
|
2019-11-18 23:01:33 +08:00
|
|
|
|
2019-11-19 19:17:46 +08:00
|
|
|
let parser = cache.get(parserOptions);
|
|
|
|
|
|
|
|
if (parser === undefined) {
|
|
|
|
parser = this.createParser(type, parserOptions);
|
|
|
|
cache.set(parserOptions, parser);
|
2018-01-22 05:35:30 +08:00
|
|
|
}
|
2019-11-18 23:01:33 +08:00
|
|
|
|
2019-11-19 19:17:46 +08:00
|
|
|
return parser;
|
2017-04-04 05:28:08 +08:00
|
|
|
}
|
|
|
|
|
2020-08-03 02:09:36 +08:00
|
|
|
/**
|
|
|
|
* @param {string} type type
|
2024-02-17 01:39:12 +08:00
|
|
|
* @param {ParserOptions} parserOptions parser options
|
2020-08-03 02:09:36 +08:00
|
|
|
* @returns {Parser} parser
|
|
|
|
*/
|
2018-01-22 05:35:30 +08:00
|
|
|
createParser(type, parserOptions = {}) {
|
2021-01-05 18:11:02 +08:00
|
|
|
parserOptions = mergeGlobalOptions(
|
|
|
|
this._globalParserOptions,
|
|
|
|
type,
|
|
|
|
parserOptions
|
|
|
|
);
|
2017-11-28 16:54:24 +08:00
|
|
|
const parser = this.hooks.createParser.for(type).call(parserOptions);
|
2018-02-25 09:00:20 +08:00
|
|
|
if (!parser) {
|
2017-11-10 18:02:24 +08:00
|
|
|
throw new Error(`No parser registered for ${type}`);
|
2017-10-30 20:56:57 +08:00
|
|
|
}
|
2017-11-28 16:54:24 +08:00
|
|
|
this.hooks.parser.for(type).call(parser, parserOptions);
|
2016-09-14 18:04:42 +08:00
|
|
|
return parser;
|
2017-04-04 05:28:08 +08:00
|
|
|
}
|
2017-11-17 21:26:23 +08:00
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/**
|
|
|
|
* @param {string} type type of generator
|
|
|
|
* @param {GeneratorOptions} generatorOptions generator options
|
|
|
|
* @returns {Generator} generator
|
|
|
|
*/
|
2021-01-05 18:11:02 +08:00
|
|
|
getGenerator(type, generatorOptions = EMPTY_GENERATOR_OPTIONS) {
|
2019-11-19 01:01:54 +08:00
|
|
|
let cache = this.generatorCache.get(type);
|
2019-11-18 23:01:33 +08:00
|
|
|
|
2019-11-19 01:01:54 +08:00
|
|
|
if (cache === undefined) {
|
|
|
|
cache = new WeakMap();
|
|
|
|
this.generatorCache.set(type, cache);
|
|
|
|
}
|
2019-11-18 23:01:33 +08:00
|
|
|
|
2019-11-19 19:17:46 +08:00
|
|
|
let generator = cache.get(generatorOptions);
|
|
|
|
|
|
|
|
if (generator === undefined) {
|
|
|
|
generator = this.createGenerator(type, generatorOptions);
|
|
|
|
cache.set(generatorOptions, generator);
|
2018-01-24 06:09:26 +08:00
|
|
|
}
|
2019-11-18 23:01:33 +08:00
|
|
|
|
2019-11-19 19:17:46 +08:00
|
|
|
return generator;
|
2018-01-24 06:09:26 +08:00
|
|
|
}
|
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/**
|
|
|
|
* @param {string} type type of generator
|
|
|
|
* @param {GeneratorOptions} generatorOptions generator options
|
|
|
|
* @returns {Generator} generator
|
|
|
|
*/
|
2018-01-24 06:09:26 +08:00
|
|
|
createGenerator(type, generatorOptions = {}) {
|
2021-01-05 18:11:02 +08:00
|
|
|
generatorOptions = mergeGlobalOptions(
|
|
|
|
this._globalGeneratorOptions,
|
|
|
|
type,
|
|
|
|
generatorOptions
|
|
|
|
);
|
2018-02-25 09:00:20 +08:00
|
|
|
const generator = this.hooks.createGenerator
|
|
|
|
.for(type)
|
|
|
|
.call(generatorOptions);
|
|
|
|
if (!generator) {
|
2018-01-24 06:09:26 +08:00
|
|
|
throw new Error(`No generator registered for ${type}`);
|
|
|
|
}
|
|
|
|
this.hooks.generator.for(type).call(generator, generatorOptions);
|
|
|
|
return generator;
|
|
|
|
}
|
|
|
|
|
2024-02-17 01:39:12 +08:00
|
|
|
/**
|
|
|
|
* @param {Parameters<ResolverFactory["get"]>[0]} type type of resolver
|
|
|
|
* @param {Parameters<ResolverFactory["get"]>[1]=} resolveOptions options
|
|
|
|
* @returns {ReturnType<ResolverFactory["get"]>} the resolver
|
|
|
|
*/
|
2020-06-09 06:32:24 +08:00
|
|
|
getResolver(type, resolveOptions) {
|
2020-06-17 02:01:06 +08:00
|
|
|
return this.resolverFactory.get(type, resolveOptions);
|
2017-11-17 21:26:23 +08:00
|
|
|
}
|
2017-04-04 05:28:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = NormalModuleFactory;
|