NormalModuleFactory.js 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { getContext } = require("loader-runner");
  7. const asyncLib = require("neo-async");
  8. const {
  9. AsyncSeriesBailHook,
  10. SyncWaterfallHook,
  11. SyncBailHook,
  12. SyncHook,
  13. HookMap
  14. } = require("tapable");
  15. const ChunkGraph = require("./ChunkGraph");
  16. const Module = require("./Module");
  17. const ModuleFactory = require("./ModuleFactory");
  18. const ModuleGraph = require("./ModuleGraph");
  19. const { JAVASCRIPT_MODULE_TYPE_AUTO } = require("./ModuleTypeConstants");
  20. const NormalModule = require("./NormalModule");
  21. const BasicEffectRulePlugin = require("./rules/BasicEffectRulePlugin");
  22. const BasicMatcherRulePlugin = require("./rules/BasicMatcherRulePlugin");
  23. const ObjectMatcherRulePlugin = require("./rules/ObjectMatcherRulePlugin");
  24. const RuleSetCompiler = require("./rules/RuleSetCompiler");
  25. const UseEffectRulePlugin = require("./rules/UseEffectRulePlugin");
  26. const LazySet = require("./util/LazySet");
  27. const { getScheme } = require("./util/URLAbsoluteSpecifier");
  28. const { cachedCleverMerge, cachedSetProperty } = require("./util/cleverMerge");
  29. const { join } = require("./util/fs");
  30. const {
  31. parseResource,
  32. parseResourceWithoutFragment
  33. } = require("./util/identifier");
  34. /** @typedef {import("../declarations/WebpackOptions").ModuleOptionsNormalized} ModuleOptions */
  35. /** @typedef {import("../declarations/WebpackOptions").RuleSetRule} RuleSetRule */
  36. /** @typedef {import("./Generator")} Generator */
  37. /** @typedef {import("./ModuleFactory").ModuleFactoryCallback} ModuleFactoryCallback */
  38. /** @typedef {import("./ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */
  39. /** @typedef {import("./ModuleFactory").ModuleFactoryCreateDataContextInfo} ModuleFactoryCreateDataContextInfo */
  40. /** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
  41. /** @typedef {import("./NormalModule").GeneratorOptions} GeneratorOptions */
  42. /** @typedef {import("./NormalModule").LoaderItem} LoaderItem */
  43. /** @typedef {import("./NormalModule").NormalModuleCreateData} NormalModuleCreateData */
  44. /** @typedef {import("./NormalModule").ParserOptions} ParserOptions */
  45. /** @typedef {import("./Parser")} Parser */
  46. /** @typedef {import("./ResolverFactory")} ResolverFactory */
  47. /** @typedef {import("./ResolverFactory").ResolveContext} ResolveContext */
  48. /** @typedef {import("./ResolverFactory").ResolveRequest} ResolveRequest */
  49. /** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
  50. /** @typedef {import("./dependencies/ModuleDependency")} ModuleDependency */
  51. /** @typedef {import("./javascript/JavascriptParser").ImportAttributes} ImportAttributes */
  52. /** @typedef {import("./rules/RuleSetCompiler").RuleSetRules} RuleSetRules */
  53. /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
  54. /** @typedef {import("./util/identifier").AssociatedObjectForCache} AssociatedObjectForCache */
  55. /** @typedef {Pick<RuleSetRule, 'type' | 'sideEffects' | 'parser' | 'generator' | 'resolve' | 'layer'>} ModuleSettings */
  56. /** @typedef {Partial<NormalModuleCreateData & { settings: ModuleSettings }>} CreateData */
  57. /**
  58. * @typedef {object} ResolveData
  59. * @property {ModuleFactoryCreateData["contextInfo"]} contextInfo
  60. * @property {ModuleFactoryCreateData["resolveOptions"]} resolveOptions
  61. * @property {string} context
  62. * @property {string} request
  63. * @property {ImportAttributes | undefined} assertions
  64. * @property {ModuleDependency[]} dependencies
  65. * @property {string} dependencyType
  66. * @property {CreateData} createData
  67. * @property {LazySet<string>} fileDependencies
  68. * @property {LazySet<string>} missingDependencies
  69. * @property {LazySet<string>} contextDependencies
  70. * @property {Module=} ignoredModule
  71. * @property {boolean} cacheable allow to use the unsafe cache
  72. */
  73. /**
  74. * @typedef {object} ResourceData
  75. * @property {string} resource
  76. * @property {string=} path
  77. * @property {string=} query
  78. * @property {string=} fragment
  79. * @property {string=} context
  80. */
  81. /** @typedef {ResourceData & { data: Record<string, EXPECTED_ANY> }} ResourceDataWithData */
  82. /**
  83. * @typedef {object} ParsedLoaderRequest
  84. * @property {string} loader loader
  85. * @property {string|undefined} options options
  86. */
  87. /**
  88. * @template T
  89. * @callback Callback
  90. * @param {(Error | null)=} err
  91. * @param {T=} stats
  92. * @returns {void}
  93. */
  94. const EMPTY_RESOLVE_OPTIONS = {};
  95. /** @type {ParserOptions} */
  96. const EMPTY_PARSER_OPTIONS = {};
  97. /** @type {GeneratorOptions} */
  98. const EMPTY_GENERATOR_OPTIONS = {};
  99. /** @type {ParsedLoaderRequest[]} */
  100. const EMPTY_ELEMENTS = [];
  101. const MATCH_RESOURCE_REGEX = /^([^!]+)!=!/;
  102. const LEADING_DOT_EXTENSION_REGEX = /^[^.]/;
  103. /**
  104. * @param {LoaderItem} data data
  105. * @returns {string} ident
  106. */
  107. const loaderToIdent = data => {
  108. if (!data.options) {
  109. return data.loader;
  110. }
  111. if (typeof data.options === "string") {
  112. return `${data.loader}?${data.options}`;
  113. }
  114. if (typeof data.options !== "object") {
  115. throw new Error("loader options must be string or object");
  116. }
  117. if (data.ident) {
  118. return `${data.loader}??${data.ident}`;
  119. }
  120. return `${data.loader}?${JSON.stringify(data.options)}`;
  121. };
  122. /**
  123. * @param {LoaderItem[]} loaders loaders
  124. * @param {string} resource resource
  125. * @returns {string} stringified loaders and resource
  126. */
  127. const stringifyLoadersAndResource = (loaders, resource) => {
  128. let str = "";
  129. for (const loader of loaders) {
  130. str += `${loaderToIdent(loader)}!`;
  131. }
  132. return str + resource;
  133. };
  134. /**
  135. * @param {number} times times
  136. * @param {(err?: null | Error) => void} callback callback
  137. * @returns {(err?: null | Error) => void} callback
  138. */
  139. const needCalls = (times, callback) => err => {
  140. if (--times === 0) {
  141. return callback(err);
  142. }
  143. if (err && times > 0) {
  144. times = Number.NaN;
  145. return callback(err);
  146. }
  147. };
  148. /**
  149. * @template T
  150. * @template O
  151. * @param {T} globalOptions global options
  152. * @param {string} type type
  153. * @param {O} localOptions local options
  154. * @returns {T & O | T | O} result
  155. */
  156. const mergeGlobalOptions = (globalOptions, type, localOptions) => {
  157. const parts = type.split("/");
  158. let result;
  159. let current = "";
  160. for (const part of parts) {
  161. current = current ? `${current}/${part}` : part;
  162. const options =
  163. /** @type {T} */
  164. (globalOptions[/** @type {keyof T} */ (current)]);
  165. if (typeof options === "object") {
  166. result =
  167. result === undefined ? options : cachedCleverMerge(result, options);
  168. }
  169. }
  170. if (result === undefined) {
  171. return localOptions;
  172. }
  173. return cachedCleverMerge(result, localOptions);
  174. };
  175. // TODO webpack 6 remove
  176. /**
  177. * @template {import("tapable").Hook<EXPECTED_ANY, EXPECTED_ANY>} T
  178. * @param {string} name name
  179. * @param {T} hook hook
  180. * @returns {string} result
  181. */
  182. const deprecationChangedHookMessage = (name, hook) => {
  183. const names = hook.taps.map(tapped => tapped.name).join(", ");
  184. return (
  185. `NormalModuleFactory.${name} (${names}) is no longer a waterfall hook, but a bailing hook instead. ` +
  186. "Do not return the passed object, but modify it instead. " +
  187. "Returning false will ignore the request and results in no module created."
  188. );
  189. };
  190. const ruleSetCompiler = new RuleSetCompiler([
  191. new BasicMatcherRulePlugin("test", "resource"),
  192. new BasicMatcherRulePlugin("scheme"),
  193. new BasicMatcherRulePlugin("mimetype"),
  194. new BasicMatcherRulePlugin("dependency"),
  195. new BasicMatcherRulePlugin("include", "resource"),
  196. new BasicMatcherRulePlugin("exclude", "resource", true),
  197. new BasicMatcherRulePlugin("resource"),
  198. new BasicMatcherRulePlugin("resourceQuery"),
  199. new BasicMatcherRulePlugin("resourceFragment"),
  200. new BasicMatcherRulePlugin("realResource"),
  201. new BasicMatcherRulePlugin("issuer"),
  202. new BasicMatcherRulePlugin("compiler"),
  203. new BasicMatcherRulePlugin("issuerLayer"),
  204. new ObjectMatcherRulePlugin("assert", "assertions", value => {
  205. if (value) {
  206. return (
  207. /** @type {ImportAttributes} */ (value)._isLegacyAssert !== undefined
  208. );
  209. }
  210. return false;
  211. }),
  212. new ObjectMatcherRulePlugin("with", "assertions", value => {
  213. if (value) {
  214. return !(/** @type {ImportAttributes} */ (value)._isLegacyAssert);
  215. }
  216. return false;
  217. }),
  218. new ObjectMatcherRulePlugin("descriptionData"),
  219. new BasicEffectRulePlugin("type"),
  220. new BasicEffectRulePlugin("sideEffects"),
  221. new BasicEffectRulePlugin("parser"),
  222. new BasicEffectRulePlugin("resolve"),
  223. new BasicEffectRulePlugin("generator"),
  224. new BasicEffectRulePlugin("layer"),
  225. new UseEffectRulePlugin()
  226. ]);
  227. class NormalModuleFactory extends ModuleFactory {
  228. /**
  229. * @param {object} param params
  230. * @param {string=} param.context context
  231. * @param {InputFileSystem} param.fs file system
  232. * @param {ResolverFactory} param.resolverFactory resolverFactory
  233. * @param {ModuleOptions} param.options options
  234. * @param {AssociatedObjectForCache} param.associatedObjectForCache an object to which the cache will be attached
  235. * @param {boolean=} param.layers enable layers
  236. */
  237. constructor({
  238. context,
  239. fs,
  240. resolverFactory,
  241. options,
  242. associatedObjectForCache,
  243. layers = false
  244. }) {
  245. super();
  246. this.hooks = Object.freeze({
  247. /** @type {AsyncSeriesBailHook<[ResolveData], Module | false | void>} */
  248. resolve: new AsyncSeriesBailHook(["resolveData"]),
  249. /** @type {HookMap<AsyncSeriesBailHook<[ResourceDataWithData, ResolveData], true | void>>} */
  250. resolveForScheme: new HookMap(
  251. () => new AsyncSeriesBailHook(["resourceData", "resolveData"])
  252. ),
  253. /** @type {HookMap<AsyncSeriesBailHook<[ResourceDataWithData, ResolveData], true | void>>} */
  254. resolveInScheme: new HookMap(
  255. () => new AsyncSeriesBailHook(["resourceData", "resolveData"])
  256. ),
  257. /** @type {AsyncSeriesBailHook<[ResolveData], Module | undefined>} */
  258. factorize: new AsyncSeriesBailHook(["resolveData"]),
  259. /** @type {AsyncSeriesBailHook<[ResolveData], false | void>} */
  260. beforeResolve: new AsyncSeriesBailHook(["resolveData"]),
  261. /** @type {AsyncSeriesBailHook<[ResolveData], false | void>} */
  262. afterResolve: new AsyncSeriesBailHook(["resolveData"]),
  263. /** @type {AsyncSeriesBailHook<[CreateData, ResolveData], Module | void>} */
  264. createModule: new AsyncSeriesBailHook(["createData", "resolveData"]),
  265. /** @type {SyncWaterfallHook<[Module, CreateData, ResolveData]>} */
  266. module: new SyncWaterfallHook(["module", "createData", "resolveData"]),
  267. /** @type {HookMap<SyncBailHook<[ParserOptions], Parser | void>>} */
  268. createParser: new HookMap(() => new SyncBailHook(["parserOptions"])),
  269. /** @type {HookMap<SyncBailHook<[TODO, ParserOptions], void>>} */
  270. parser: new HookMap(() => new SyncHook(["parser", "parserOptions"])),
  271. /** @type {HookMap<SyncBailHook<[GeneratorOptions], Generator | void>>} */
  272. createGenerator: new HookMap(
  273. () => new SyncBailHook(["generatorOptions"])
  274. ),
  275. /** @type {HookMap<SyncBailHook<[TODO, GeneratorOptions], void>>} */
  276. generator: new HookMap(
  277. () => new SyncHook(["generator", "generatorOptions"])
  278. ),
  279. /** @type {HookMap<SyncBailHook<[TODO, ResolveData], Module | void>>} */
  280. createModuleClass: new HookMap(
  281. () => new SyncBailHook(["createData", "resolveData"])
  282. )
  283. });
  284. this.resolverFactory = resolverFactory;
  285. this.ruleSet = ruleSetCompiler.compile([
  286. {
  287. rules: /** @type {RuleSetRules} */ (options.defaultRules)
  288. },
  289. {
  290. rules: /** @type {RuleSetRules} */ (options.rules)
  291. }
  292. ]);
  293. this.context = context || "";
  294. this.fs = fs;
  295. this._globalParserOptions = options.parser;
  296. this._globalGeneratorOptions = options.generator;
  297. /** @type {Map<string, WeakMap<ParserOptions, Parser>>} */
  298. this.parserCache = new Map();
  299. /** @type {Map<string, WeakMap<GeneratorOptions, Generator>>} */
  300. this.generatorCache = new Map();
  301. /** @type {Set<Module>} */
  302. this._restoredUnsafeCacheEntries = new Set();
  303. const cacheParseResource = parseResource.bindCache(
  304. associatedObjectForCache
  305. );
  306. const cachedParseResourceWithoutFragment =
  307. parseResourceWithoutFragment.bindCache(associatedObjectForCache);
  308. this._parseResourceWithoutFragment = cachedParseResourceWithoutFragment;
  309. this.hooks.factorize.tapAsync(
  310. {
  311. name: "NormalModuleFactory",
  312. stage: 100
  313. },
  314. (resolveData, callback) => {
  315. this.hooks.resolve.callAsync(resolveData, (err, result) => {
  316. if (err) return callback(err);
  317. // Ignored
  318. if (result === false) return callback();
  319. // direct module
  320. if (result instanceof Module) return callback(null, result);
  321. if (typeof result === "object")
  322. throw new Error(
  323. `${deprecationChangedHookMessage(
  324. "resolve",
  325. this.hooks.resolve
  326. )} Returning a Module object will result in this module used as result.`
  327. );
  328. this.hooks.afterResolve.callAsync(resolveData, (err, result) => {
  329. if (err) return callback(err);
  330. if (typeof result === "object")
  331. throw new Error(
  332. deprecationChangedHookMessage(
  333. "afterResolve",
  334. this.hooks.afterResolve
  335. )
  336. );
  337. // Ignored
  338. if (result === false) return callback();
  339. const createData = resolveData.createData;
  340. this.hooks.createModule.callAsync(
  341. createData,
  342. resolveData,
  343. (err, createdModule) => {
  344. if (!createdModule) {
  345. if (!resolveData.request) {
  346. return callback(new Error("Empty dependency (no request)"));
  347. }
  348. // TODO webpack 6 make it required and move javascript/wasm/asset properties to own module
  349. createdModule = this.hooks.createModuleClass
  350. .for(
  351. /** @type {ModuleSettings} */
  352. (createData.settings).type
  353. )
  354. .call(createData, resolveData);
  355. if (!createdModule) {
  356. createdModule = /** @type {Module} */ (
  357. new NormalModule(
  358. /** @type {NormalModuleCreateData} */
  359. (createData)
  360. )
  361. );
  362. }
  363. }
  364. createdModule = this.hooks.module.call(
  365. createdModule,
  366. createData,
  367. resolveData
  368. );
  369. return callback(null, createdModule);
  370. }
  371. );
  372. });
  373. });
  374. }
  375. );
  376. this.hooks.resolve.tapAsync(
  377. {
  378. name: "NormalModuleFactory",
  379. stage: 100
  380. },
  381. (data, callback) => {
  382. const {
  383. contextInfo,
  384. context,
  385. dependencies,
  386. dependencyType,
  387. request,
  388. assertions,
  389. resolveOptions,
  390. fileDependencies,
  391. missingDependencies,
  392. contextDependencies
  393. } = data;
  394. const loaderResolver = this.getResolver("loader");
  395. /** @type {ResourceData | undefined} */
  396. let matchResourceData;
  397. /** @type {string} */
  398. let unresolvedResource;
  399. /** @type {ParsedLoaderRequest[]} */
  400. let elements;
  401. let noPreAutoLoaders = false;
  402. let noAutoLoaders = false;
  403. let noPrePostAutoLoaders = false;
  404. const contextScheme = getScheme(context);
  405. /** @type {string | undefined} */
  406. let scheme = getScheme(request);
  407. if (!scheme) {
  408. /** @type {string} */
  409. let requestWithoutMatchResource = request;
  410. const matchResourceMatch = MATCH_RESOURCE_REGEX.exec(request);
  411. if (matchResourceMatch) {
  412. let matchResource = matchResourceMatch[1];
  413. if (matchResource.charCodeAt(0) === 46) {
  414. // 46 === ".", 47 === "/"
  415. const secondChar = matchResource.charCodeAt(1);
  416. if (
  417. secondChar === 47 ||
  418. (secondChar === 46 && matchResource.charCodeAt(2) === 47)
  419. ) {
  420. // if matchResources startsWith ../ or ./
  421. matchResource = join(this.fs, context, matchResource);
  422. }
  423. }
  424. matchResourceData = {
  425. resource: matchResource,
  426. .../** @type {TODO} */ (cacheParseResource(matchResource))
  427. };
  428. requestWithoutMatchResource = request.slice(
  429. matchResourceMatch[0].length
  430. );
  431. }
  432. scheme = getScheme(requestWithoutMatchResource);
  433. if (!scheme && !contextScheme) {
  434. const firstChar = requestWithoutMatchResource.charCodeAt(0);
  435. const secondChar = requestWithoutMatchResource.charCodeAt(1);
  436. noPreAutoLoaders = firstChar === 45 && secondChar === 33; // startsWith "-!"
  437. noAutoLoaders = noPreAutoLoaders || firstChar === 33; // startsWith "!"
  438. noPrePostAutoLoaders = firstChar === 33 && secondChar === 33; // startsWith "!!";
  439. const rawElements = requestWithoutMatchResource
  440. .slice(
  441. noPreAutoLoaders || noPrePostAutoLoaders
  442. ? 2
  443. : noAutoLoaders
  444. ? 1
  445. : 0
  446. )
  447. .split(/!+/);
  448. unresolvedResource = /** @type {string} */ (rawElements.pop());
  449. elements = rawElements.map(el => {
  450. const { path, query } = cachedParseResourceWithoutFragment(el);
  451. return {
  452. loader: path,
  453. options: query ? query.slice(1) : undefined
  454. };
  455. });
  456. scheme = getScheme(unresolvedResource);
  457. } else {
  458. unresolvedResource = requestWithoutMatchResource;
  459. elements = EMPTY_ELEMENTS;
  460. }
  461. } else {
  462. unresolvedResource = request;
  463. elements = EMPTY_ELEMENTS;
  464. }
  465. /** @type {ResolveContext} */
  466. const resolveContext = {
  467. fileDependencies,
  468. missingDependencies,
  469. contextDependencies
  470. };
  471. /** @type {ResourceDataWithData} */
  472. let resourceData;
  473. /** @type {undefined | LoaderItem[]} */
  474. let loaders;
  475. const continueCallback = needCalls(2, err => {
  476. if (err) return callback(err);
  477. // translate option idents
  478. try {
  479. for (const item of /** @type {LoaderItem[]} */ (loaders)) {
  480. if (typeof item.options === "string" && item.options[0] === "?") {
  481. const ident = item.options.slice(1);
  482. if (ident === "[[missing ident]]") {
  483. throw new Error(
  484. "No ident is provided by referenced loader. " +
  485. "When using a function for Rule.use in config you need to " +
  486. "provide an 'ident' property for referenced loader options."
  487. );
  488. }
  489. item.options = this.ruleSet.references.get(ident);
  490. if (item.options === undefined) {
  491. throw new Error(
  492. "Invalid ident is provided by referenced loader"
  493. );
  494. }
  495. item.ident = ident;
  496. }
  497. }
  498. } catch (identErr) {
  499. return callback(/** @type {Error} */ (identErr));
  500. }
  501. if (!resourceData) {
  502. // ignored
  503. return callback(
  504. null,
  505. /** @type {TODO} */
  506. (dependencies[0].createIgnoredModule(context))
  507. );
  508. }
  509. const userRequest =
  510. (matchResourceData !== undefined
  511. ? `${matchResourceData.resource}!=!`
  512. : "") +
  513. stringifyLoadersAndResource(
  514. /** @type {LoaderItem[]} */ (loaders),
  515. resourceData.resource
  516. );
  517. /** @type {ModuleSettings} */
  518. const settings = {};
  519. const useLoadersPost = [];
  520. const useLoaders = [];
  521. const useLoadersPre = [];
  522. // handle .webpack[] suffix
  523. let resource;
  524. let match;
  525. if (
  526. matchResourceData &&
  527. typeof (resource = matchResourceData.resource) === "string" &&
  528. (match = /\.webpack\[([^\]]+)\]$/.exec(resource))
  529. ) {
  530. settings.type = match[1];
  531. matchResourceData.resource = matchResourceData.resource.slice(
  532. 0,
  533. -settings.type.length - 10
  534. );
  535. } else {
  536. settings.type = JAVASCRIPT_MODULE_TYPE_AUTO;
  537. const resourceDataForRules = matchResourceData || resourceData;
  538. const result = this.ruleSet.exec({
  539. resource: resourceDataForRules.path,
  540. realResource: resourceData.path,
  541. resourceQuery: resourceDataForRules.query,
  542. resourceFragment: resourceDataForRules.fragment,
  543. scheme,
  544. assertions,
  545. mimetype: matchResourceData
  546. ? ""
  547. : resourceData.data.mimetype || "",
  548. dependency: dependencyType,
  549. descriptionData: matchResourceData
  550. ? undefined
  551. : resourceData.data.descriptionFileData,
  552. issuer: contextInfo.issuer,
  553. compiler: contextInfo.compiler,
  554. issuerLayer: contextInfo.issuerLayer || ""
  555. });
  556. for (const r of result) {
  557. // https://github.com/webpack/webpack/issues/16466
  558. // if a request exists PrePostAutoLoaders, should disable modifying Rule.type
  559. if (r.type === "type" && noPrePostAutoLoaders) {
  560. continue;
  561. }
  562. if (r.type === "use") {
  563. if (!noAutoLoaders && !noPrePostAutoLoaders) {
  564. useLoaders.push(r.value);
  565. }
  566. } else if (r.type === "use-post") {
  567. if (!noPrePostAutoLoaders) {
  568. useLoadersPost.push(r.value);
  569. }
  570. } else if (r.type === "use-pre") {
  571. if (!noPreAutoLoaders && !noPrePostAutoLoaders) {
  572. useLoadersPre.push(r.value);
  573. }
  574. } else if (
  575. typeof r.value === "object" &&
  576. r.value !== null &&
  577. typeof settings[
  578. /** @type {keyof ModuleSettings} */ (r.type)
  579. ] === "object" &&
  580. settings[/** @type {keyof ModuleSettings} */ (r.type)] !== null
  581. ) {
  582. const type = /** @type {keyof ModuleSettings} */ (r.type);
  583. /** @type {TODO} */
  584. (settings)[type] = cachedCleverMerge(settings[type], r.value);
  585. } else {
  586. const type = /** @type {keyof ModuleSettings} */ (r.type);
  587. /** @type {TODO} */
  588. (settings)[type] = r.value;
  589. }
  590. }
  591. }
  592. /** @type {undefined | LoaderItem[]} */
  593. let postLoaders;
  594. /** @type {undefined | LoaderItem[]} */
  595. let normalLoaders;
  596. /** @type {undefined | LoaderItem[]} */
  597. let preLoaders;
  598. const continueCallback = needCalls(3, err => {
  599. if (err) {
  600. return callback(err);
  601. }
  602. const allLoaders = /** @type {LoaderItem[]} */ (postLoaders);
  603. if (matchResourceData === undefined) {
  604. for (const loader of /** @type {LoaderItem[]} */ (loaders))
  605. allLoaders.push(loader);
  606. for (const loader of /** @type {LoaderItem[]} */ (normalLoaders))
  607. allLoaders.push(loader);
  608. } else {
  609. for (const loader of /** @type {LoaderItem[]} */ (normalLoaders))
  610. allLoaders.push(loader);
  611. for (const loader of /** @type {LoaderItem[]} */ (loaders))
  612. allLoaders.push(loader);
  613. }
  614. for (const loader of /** @type {LoaderItem[]} */ (preLoaders))
  615. allLoaders.push(loader);
  616. const type = /** @type {string} */ (settings.type);
  617. const resolveOptions = settings.resolve;
  618. const layer = settings.layer;
  619. if (layer !== undefined && !layers) {
  620. return callback(
  621. new Error(
  622. "'Rule.layer' is only allowed when 'experiments.layers' is enabled"
  623. )
  624. );
  625. }
  626. try {
  627. Object.assign(data.createData, {
  628. layer:
  629. layer === undefined ? contextInfo.issuerLayer || null : layer,
  630. request: stringifyLoadersAndResource(
  631. allLoaders,
  632. resourceData.resource
  633. ),
  634. userRequest,
  635. rawRequest: request,
  636. loaders: allLoaders,
  637. resource: resourceData.resource,
  638. context:
  639. resourceData.context || getContext(resourceData.resource),
  640. matchResource: matchResourceData
  641. ? matchResourceData.resource
  642. : undefined,
  643. resourceResolveData: resourceData.data,
  644. settings,
  645. type,
  646. parser: this.getParser(type, settings.parser),
  647. parserOptions: settings.parser,
  648. generator: this.getGenerator(type, settings.generator),
  649. generatorOptions: settings.generator,
  650. resolveOptions
  651. });
  652. } catch (createDataErr) {
  653. return callback(/** @type {Error} */ (createDataErr));
  654. }
  655. callback();
  656. });
  657. this.resolveRequestArray(
  658. contextInfo,
  659. this.context,
  660. useLoadersPost,
  661. loaderResolver,
  662. resolveContext,
  663. (err, result) => {
  664. postLoaders = result;
  665. continueCallback(err);
  666. }
  667. );
  668. this.resolveRequestArray(
  669. contextInfo,
  670. this.context,
  671. useLoaders,
  672. loaderResolver,
  673. resolveContext,
  674. (err, result) => {
  675. normalLoaders = result;
  676. continueCallback(err);
  677. }
  678. );
  679. this.resolveRequestArray(
  680. contextInfo,
  681. this.context,
  682. useLoadersPre,
  683. loaderResolver,
  684. resolveContext,
  685. (err, result) => {
  686. preLoaders = result;
  687. continueCallback(err);
  688. }
  689. );
  690. });
  691. this.resolveRequestArray(
  692. contextInfo,
  693. contextScheme ? this.context : context,
  694. /** @type {LoaderItem[]} */ (elements),
  695. loaderResolver,
  696. resolveContext,
  697. (err, result) => {
  698. if (err) return continueCallback(err);
  699. loaders = result;
  700. continueCallback();
  701. }
  702. );
  703. /**
  704. * @param {string} context context
  705. */
  706. const defaultResolve = context => {
  707. if (/^($|\?)/.test(unresolvedResource)) {
  708. resourceData = {
  709. resource: unresolvedResource,
  710. data: {},
  711. .../** @type {TODO} */ (cacheParseResource(unresolvedResource))
  712. };
  713. continueCallback();
  714. }
  715. // resource without scheme and with path
  716. else {
  717. const normalResolver = this.getResolver(
  718. "normal",
  719. dependencyType
  720. ? cachedSetProperty(
  721. resolveOptions || EMPTY_RESOLVE_OPTIONS,
  722. "dependencyType",
  723. dependencyType
  724. )
  725. : resolveOptions
  726. );
  727. this.resolveResource(
  728. contextInfo,
  729. context,
  730. unresolvedResource,
  731. normalResolver,
  732. resolveContext,
  733. (err, _resolvedResource, resolvedResourceResolveData) => {
  734. if (err) return continueCallback(err);
  735. if (_resolvedResource !== false) {
  736. const resolvedResource =
  737. /** @type {string} */
  738. (_resolvedResource);
  739. resourceData = {
  740. resource: resolvedResource,
  741. data:
  742. /** @type {ResolveRequest} */
  743. (resolvedResourceResolveData),
  744. .../** @type {TODO} */
  745. (cacheParseResource(resolvedResource))
  746. };
  747. }
  748. continueCallback();
  749. }
  750. );
  751. }
  752. };
  753. // resource with scheme
  754. if (scheme) {
  755. resourceData = {
  756. resource: unresolvedResource,
  757. data: {},
  758. path: undefined,
  759. query: undefined,
  760. fragment: undefined,
  761. context: undefined
  762. };
  763. this.hooks.resolveForScheme
  764. .for(scheme)
  765. .callAsync(resourceData, data, err => {
  766. if (err) return continueCallback(err);
  767. continueCallback();
  768. });
  769. }
  770. // resource within scheme
  771. else if (contextScheme) {
  772. resourceData = {
  773. resource: unresolvedResource,
  774. data: {},
  775. path: undefined,
  776. query: undefined,
  777. fragment: undefined,
  778. context: undefined
  779. };
  780. this.hooks.resolveInScheme
  781. .for(contextScheme)
  782. .callAsync(resourceData, data, (err, handled) => {
  783. if (err) return continueCallback(err);
  784. if (!handled) return defaultResolve(this.context);
  785. continueCallback();
  786. });
  787. }
  788. // resource without scheme and without path
  789. else defaultResolve(context);
  790. }
  791. );
  792. }
  793. cleanupForCache() {
  794. for (const module of this._restoredUnsafeCacheEntries) {
  795. ChunkGraph.clearChunkGraphForModule(module);
  796. ModuleGraph.clearModuleGraphForModule(module);
  797. module.cleanupForCache();
  798. }
  799. }
  800. /**
  801. * @param {ModuleFactoryCreateData} data data object
  802. * @param {ModuleFactoryCallback} callback callback
  803. * @returns {void}
  804. */
  805. create(data, callback) {
  806. const dependencies = /** @type {ModuleDependency[]} */ (data.dependencies);
  807. const context = data.context || this.context;
  808. const resolveOptions = data.resolveOptions || EMPTY_RESOLVE_OPTIONS;
  809. const dependency = dependencies[0];
  810. const request = dependency.request;
  811. const assertions = dependency.assertions;
  812. const dependencyType = dependency.category || "";
  813. const contextInfo = data.contextInfo;
  814. const fileDependencies = new LazySet();
  815. const missingDependencies = new LazySet();
  816. const contextDependencies = new LazySet();
  817. /** @type {ResolveData} */
  818. const resolveData = {
  819. contextInfo,
  820. resolveOptions,
  821. context,
  822. request,
  823. assertions,
  824. dependencies,
  825. dependencyType,
  826. fileDependencies,
  827. missingDependencies,
  828. contextDependencies,
  829. createData: {},
  830. cacheable: true
  831. };
  832. this.hooks.beforeResolve.callAsync(resolveData, (err, result) => {
  833. if (err) {
  834. return callback(err, {
  835. fileDependencies,
  836. missingDependencies,
  837. contextDependencies,
  838. cacheable: false
  839. });
  840. }
  841. // Ignored
  842. if (result === false) {
  843. /** @type {ModuleFactoryResult} * */
  844. const factoryResult = {
  845. fileDependencies,
  846. missingDependencies,
  847. contextDependencies,
  848. cacheable: resolveData.cacheable
  849. };
  850. if (resolveData.ignoredModule) {
  851. factoryResult.module = resolveData.ignoredModule;
  852. }
  853. return callback(null, factoryResult);
  854. }
  855. if (typeof result === "object")
  856. throw new Error(
  857. deprecationChangedHookMessage(
  858. "beforeResolve",
  859. this.hooks.beforeResolve
  860. )
  861. );
  862. this.hooks.factorize.callAsync(resolveData, (err, module) => {
  863. if (err) {
  864. return callback(err, {
  865. fileDependencies,
  866. missingDependencies,
  867. contextDependencies,
  868. cacheable: false
  869. });
  870. }
  871. /** @type {ModuleFactoryResult} * */
  872. const factoryResult = {
  873. module,
  874. fileDependencies,
  875. missingDependencies,
  876. contextDependencies,
  877. cacheable: resolveData.cacheable
  878. };
  879. callback(null, factoryResult);
  880. });
  881. });
  882. }
  883. /**
  884. * @param {ModuleFactoryCreateDataContextInfo} contextInfo context info
  885. * @param {string} context context
  886. * @param {string} unresolvedResource unresolved resource
  887. * @param {ResolverWithOptions} resolver resolver
  888. * @param {ResolveContext} resolveContext resolver context
  889. * @param {(err: null | Error, res?: string | false, req?: ResolveRequest) => void} callback callback
  890. */
  891. resolveResource(
  892. contextInfo,
  893. context,
  894. unresolvedResource,
  895. resolver,
  896. resolveContext,
  897. callback
  898. ) {
  899. resolver.resolve(
  900. contextInfo,
  901. context,
  902. unresolvedResource,
  903. resolveContext,
  904. (err, resolvedResource, resolvedResourceResolveData) => {
  905. if (err) {
  906. return this._resolveResourceErrorHints(
  907. err,
  908. contextInfo,
  909. context,
  910. unresolvedResource,
  911. resolver,
  912. resolveContext,
  913. (err2, hints) => {
  914. if (err2) {
  915. err.message += `
  916. A fatal error happened during resolving additional hints for this error: ${err2.message}`;
  917. err.stack += `
  918. A fatal error happened during resolving additional hints for this error:
  919. ${err2.stack}`;
  920. return callback(err);
  921. }
  922. if (hints && hints.length > 0) {
  923. err.message += `
  924. ${hints.join("\n\n")}`;
  925. }
  926. // Check if the extension is missing a leading dot (e.g. "js" instead of ".js")
  927. let appendResolveExtensionsHint = false;
  928. const specifiedExtensions = Array.from(
  929. resolver.options.extensions
  930. );
  931. const expectedExtensions = specifiedExtensions.map(extension => {
  932. if (LEADING_DOT_EXTENSION_REGEX.test(extension)) {
  933. appendResolveExtensionsHint = true;
  934. return `.${extension}`;
  935. }
  936. return extension;
  937. });
  938. if (appendResolveExtensionsHint) {
  939. err.message += `\nDid you miss the leading dot in 'resolve.extensions'? Did you mean '${JSON.stringify(
  940. expectedExtensions
  941. )}' instead of '${JSON.stringify(specifiedExtensions)}'?`;
  942. }
  943. callback(err);
  944. }
  945. );
  946. }
  947. callback(err, resolvedResource, resolvedResourceResolveData);
  948. }
  949. );
  950. }
  951. /**
  952. * @param {Error} error error
  953. * @param {ModuleFactoryCreateDataContextInfo} contextInfo context info
  954. * @param {string} context context
  955. * @param {string} unresolvedResource unresolved resource
  956. * @param {ResolverWithOptions} resolver resolver
  957. * @param {ResolveContext} resolveContext resolver context
  958. * @param {Callback<string[]>} callback callback
  959. * @private
  960. */
  961. _resolveResourceErrorHints(
  962. error,
  963. contextInfo,
  964. context,
  965. unresolvedResource,
  966. resolver,
  967. resolveContext,
  968. callback
  969. ) {
  970. asyncLib.parallel(
  971. [
  972. callback => {
  973. if (!resolver.options.fullySpecified) return callback();
  974. resolver
  975. .withOptions({
  976. fullySpecified: false
  977. })
  978. .resolve(
  979. contextInfo,
  980. context,
  981. unresolvedResource,
  982. resolveContext,
  983. (err, resolvedResource) => {
  984. if (!err && resolvedResource) {
  985. const resource = parseResource(resolvedResource).path.replace(
  986. /^.*[\\/]/,
  987. ""
  988. );
  989. return callback(
  990. null,
  991. `Did you mean '${resource}'?
  992. BREAKING CHANGE: The request '${unresolvedResource}' failed to resolve only because it was resolved as fully specified
  993. (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"').
  994. The extension in the request is mandatory for it to be fully specified.
  995. Add the extension to the request.`
  996. );
  997. }
  998. callback();
  999. }
  1000. );
  1001. },
  1002. callback => {
  1003. if (!resolver.options.enforceExtension) return callback();
  1004. resolver
  1005. .withOptions({
  1006. enforceExtension: false,
  1007. extensions: []
  1008. })
  1009. .resolve(
  1010. contextInfo,
  1011. context,
  1012. unresolvedResource,
  1013. resolveContext,
  1014. (err, resolvedResource) => {
  1015. if (!err && resolvedResource) {
  1016. let hint = "";
  1017. const match = /(\.[^.]+)(\?|$)/.exec(unresolvedResource);
  1018. if (match) {
  1019. const fixedRequest = unresolvedResource.replace(
  1020. /(\.[^.]+)(\?|$)/,
  1021. "$2"
  1022. );
  1023. hint = resolver.options.extensions.has(match[1])
  1024. ? `Did you mean '${fixedRequest}'?`
  1025. : `Did you mean '${fixedRequest}'? Also note that '${match[1]}' is not in 'resolve.extensions' yet and need to be added for this to work?`;
  1026. } else {
  1027. hint =
  1028. "Did you mean to omit the extension or to remove 'resolve.enforceExtension'?";
  1029. }
  1030. return callback(
  1031. null,
  1032. `The request '${unresolvedResource}' failed to resolve only because 'resolve.enforceExtension' was specified.
  1033. ${hint}
  1034. Including the extension in the request is no longer possible. Did you mean to enforce including the extension in requests with 'resolve.extensions: []' instead?`
  1035. );
  1036. }
  1037. callback();
  1038. }
  1039. );
  1040. },
  1041. callback => {
  1042. if (
  1043. /^\.\.?\//.test(unresolvedResource) ||
  1044. resolver.options.preferRelative
  1045. ) {
  1046. return callback();
  1047. }
  1048. resolver.resolve(
  1049. contextInfo,
  1050. context,
  1051. `./${unresolvedResource}`,
  1052. resolveContext,
  1053. (err, resolvedResource) => {
  1054. if (err || !resolvedResource) return callback();
  1055. const moduleDirectories = resolver.options.modules
  1056. .map(m => (Array.isArray(m) ? m.join(", ") : m))
  1057. .join(", ");
  1058. callback(
  1059. null,
  1060. `Did you mean './${unresolvedResource}'?
  1061. Requests that should resolve in the current directory need to start with './'.
  1062. Requests that start with a name are treated as module requests and resolve within module directories (${moduleDirectories}).
  1063. 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.`
  1064. );
  1065. }
  1066. );
  1067. }
  1068. ],
  1069. (err, hints) => {
  1070. if (err) return callback(err);
  1071. callback(null, /** @type {string[]} */ (hints).filter(Boolean));
  1072. }
  1073. );
  1074. }
  1075. /**
  1076. * @param {ModuleFactoryCreateDataContextInfo} contextInfo context info
  1077. * @param {string} context context
  1078. * @param {LoaderItem[]} array array
  1079. * @param {ResolverWithOptions} resolver resolver
  1080. * @param {ResolveContext} resolveContext resolve context
  1081. * @param {Callback<LoaderItem[]>} callback callback
  1082. * @returns {void} result
  1083. */
  1084. resolveRequestArray(
  1085. contextInfo,
  1086. context,
  1087. array,
  1088. resolver,
  1089. resolveContext,
  1090. callback
  1091. ) {
  1092. // LoaderItem
  1093. if (array.length === 0) return callback(null, array);
  1094. asyncLib.map(
  1095. array,
  1096. (item, callback) => {
  1097. resolver.resolve(
  1098. contextInfo,
  1099. context,
  1100. item.loader,
  1101. resolveContext,
  1102. (err, result, resolveRequest) => {
  1103. if (
  1104. err &&
  1105. /^[^/]*$/.test(item.loader) &&
  1106. !item.loader.endsWith("-loader")
  1107. ) {
  1108. return resolver.resolve(
  1109. contextInfo,
  1110. context,
  1111. `${item.loader}-loader`,
  1112. resolveContext,
  1113. err2 => {
  1114. if (!err2) {
  1115. err.message =
  1116. `${err.message}\n` +
  1117. "BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix when using loaders.\n" +
  1118. ` You need to specify '${item.loader}-loader' instead of '${item.loader}',\n` +
  1119. " see https://webpack.js.org/migrate/3/#automatic-loader-module-name-extension-removed";
  1120. }
  1121. callback(err);
  1122. }
  1123. );
  1124. }
  1125. if (err) return callback(err);
  1126. const parsedResult = this._parseResourceWithoutFragment(
  1127. /** @type {string} */ (result)
  1128. );
  1129. const type = /\.mjs$/i.test(parsedResult.path)
  1130. ? "module"
  1131. : /\.cjs$/i.test(parsedResult.path)
  1132. ? "commonjs"
  1133. : /** @type {ResolveRequest} */
  1134. (resolveRequest).descriptionFileData === undefined
  1135. ? undefined
  1136. : /** @type {ResolveRequest} */
  1137. (resolveRequest).descriptionFileData.type;
  1138. const resolved = {
  1139. loader: parsedResult.path,
  1140. type,
  1141. options:
  1142. item.options === undefined
  1143. ? parsedResult.query
  1144. ? parsedResult.query.slice(1)
  1145. : undefined
  1146. : item.options,
  1147. ident:
  1148. item.options === undefined
  1149. ? undefined
  1150. : /** @type {string} */ (item.ident)
  1151. };
  1152. return callback(null, /** @type {LoaderItem} */ (resolved));
  1153. }
  1154. );
  1155. },
  1156. /** @type {Callback<TODO>} */ (callback)
  1157. );
  1158. }
  1159. /**
  1160. * @param {string} type type
  1161. * @param {ParserOptions} parserOptions parser options
  1162. * @returns {Parser} parser
  1163. */
  1164. getParser(type, parserOptions = EMPTY_PARSER_OPTIONS) {
  1165. let cache = this.parserCache.get(type);
  1166. if (cache === undefined) {
  1167. cache = new WeakMap();
  1168. this.parserCache.set(type, cache);
  1169. }
  1170. let parser = cache.get(parserOptions);
  1171. if (parser === undefined) {
  1172. parser = this.createParser(type, parserOptions);
  1173. cache.set(parserOptions, parser);
  1174. }
  1175. return parser;
  1176. }
  1177. /**
  1178. * @param {string} type type
  1179. * @param {ParserOptions} parserOptions parser options
  1180. * @returns {Parser} parser
  1181. */
  1182. createParser(type, parserOptions = {}) {
  1183. parserOptions = mergeGlobalOptions(
  1184. this._globalParserOptions,
  1185. type,
  1186. parserOptions
  1187. );
  1188. const parser = this.hooks.createParser.for(type).call(parserOptions);
  1189. if (!parser) {
  1190. throw new Error(`No parser registered for ${type}`);
  1191. }
  1192. this.hooks.parser.for(type).call(parser, parserOptions);
  1193. return parser;
  1194. }
  1195. /**
  1196. * @param {string} type type of generator
  1197. * @param {GeneratorOptions} generatorOptions generator options
  1198. * @returns {Generator} generator
  1199. */
  1200. getGenerator(type, generatorOptions = EMPTY_GENERATOR_OPTIONS) {
  1201. let cache = this.generatorCache.get(type);
  1202. if (cache === undefined) {
  1203. cache = new WeakMap();
  1204. this.generatorCache.set(type, cache);
  1205. }
  1206. let generator = cache.get(generatorOptions);
  1207. if (generator === undefined) {
  1208. generator = this.createGenerator(type, generatorOptions);
  1209. cache.set(generatorOptions, generator);
  1210. }
  1211. return generator;
  1212. }
  1213. /**
  1214. * @param {string} type type of generator
  1215. * @param {GeneratorOptions} generatorOptions generator options
  1216. * @returns {Generator} generator
  1217. */
  1218. createGenerator(type, generatorOptions = {}) {
  1219. generatorOptions = mergeGlobalOptions(
  1220. this._globalGeneratorOptions,
  1221. type,
  1222. generatorOptions
  1223. );
  1224. const generator = this.hooks.createGenerator
  1225. .for(type)
  1226. .call(generatorOptions);
  1227. if (!generator) {
  1228. throw new Error(`No generator registered for ${type}`);
  1229. }
  1230. this.hooks.generator.for(type).call(generator, generatorOptions);
  1231. return generator;
  1232. }
  1233. /**
  1234. * @param {Parameters<ResolverFactory["get"]>[0]} type type of resolver
  1235. * @param {Parameters<ResolverFactory["get"]>[1]=} resolveOptions options
  1236. * @returns {ReturnType<ResolverFactory["get"]>} the resolver
  1237. */
  1238. getResolver(type, resolveOptions) {
  1239. return this.resolverFactory.get(type, resolveOptions);
  1240. }
  1241. }
  1242. module.exports = NormalModuleFactory;