ContextModule.js 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { OriginalSource, RawSource } = require("webpack-sources");
  7. const AsyncDependenciesBlock = require("./AsyncDependenciesBlock");
  8. const Module = require("./Module");
  9. const {
  10. JAVASCRIPT_TYPE,
  11. JAVASCRIPT_TYPES
  12. } = require("./ModuleSourceTypeConstants");
  13. const { JAVASCRIPT_MODULE_TYPE_DYNAMIC } = require("./ModuleTypeConstants");
  14. const RuntimeGlobals = require("./RuntimeGlobals");
  15. const Template = require("./Template");
  16. const {
  17. getOutgoingAsyncModules
  18. } = require("./async-modules/AsyncModuleHelpers");
  19. const { ImportPhase, ImportPhaseUtils } = require("./dependencies/ImportPhase");
  20. const { makeWebpackError } = require("./errors/HookWebpackError");
  21. const WebpackError = require("./errors/WebpackError");
  22. const {
  23. compareLocations,
  24. compareModulesById,
  25. compareSelect,
  26. concatComparators,
  27. keepOriginalOrder
  28. } = require("./util/comparators");
  29. const {
  30. contextify,
  31. makePathsRelative,
  32. parseResource
  33. } = require("./util/identifier");
  34. const makeSerializable = require("./util/makeSerializable");
  35. const { propertyAccess } = require("./util/property");
  36. /** @import { Source } from "webpack-sources" */
  37. /** @import { ResolveOptions } from "../declarations/WebpackOptions" */
  38. /**
  39. * @import {
  40. * WebpackOptionsNormalizedWithDefaults as WebpackOptions
  41. * } from "./config/defaults"
  42. */
  43. /** @import Chunk, { ChunkId, ChunkName } from "./Chunk" */
  44. /** @import ChunkGraph, { ModuleId } from "./ChunkGraph" */
  45. /** @import { RawChunkGroupOptions } from "./ChunkGroup" */
  46. /** @import Compilation, { FileSystemDependencies } from "./Compilation" */
  47. /** @import Dependency, { RawReferencedExports } from "./Dependency" */
  48. /** @import { Snapshot } from "./FileSystemInfo" */
  49. /**
  50. * @import {
  51. * BuildCallback,
  52. * BuildInfo,
  53. * BuildMeta,
  54. * CodeGenerationContext,
  55. * CodeGenerationResult,
  56. * LibIdentOptions,
  57. * LibIdent,
  58. * NeedBuildCallback,
  59. * NeedBuildContext,
  60. * RuntimeRequirements,
  61. * Sources,
  62. * SourceTypes
  63. * } from "./Module"
  64. */
  65. /** @import RequestShortener from "./RequestShortener" */
  66. /** @import { ResolverWithOptions } from "./ResolverFactory" */
  67. /** @import RuntimeTemplate from "./RuntimeTemplate" */
  68. /** @import ContextElementDependency from "./dependencies/ContextElementDependency" */
  69. /** @import { ImportAttributes } from "./javascript/JavascriptParser" */
  70. /** @typedef {import("./serialization/ObjectMiddleware").ObjectDeserializerContext<[string, boolean]>} ObjectDeserializerContext */
  71. /** @typedef {import("./serialization/ObjectMiddleware").ObjectSerializerContext<[string, boolean]>} ObjectSerializerContext */
  72. /** @import { InputFileSystem } from "./util/fs" */
  73. /** @import { ImportPhaseType } from "./dependencies/ImportPhase" */
  74. /** @typedef {"sync" | "eager" | "weak" | "async-weak" | "lazy" | "lazy-once"} ContextMode Context mode */
  75. /**
  76. * @typedef {object} ContextOptions
  77. * @property {ContextMode} mode
  78. * @property {boolean} recursive
  79. * @property {RegExp | false | null} regExp
  80. * @property {"strict" | boolean=} namespaceObject
  81. * @property {string=} addon
  82. * @property {ChunkName=} chunkName
  83. * @property {RegExp | null=} include
  84. * @property {RegExp | null=} exclude
  85. * @property {RawChunkGroupOptions=} groupOptions
  86. * @property {string=} typePrefix
  87. * @property {string=} category
  88. * @property {RawReferencedExports | null=} referencedExports exports referenced from modules (won't be mangled)
  89. * @property {string | null=} layer
  90. * @property {ImportAttributes=} attributes
  91. * @property {ImportPhaseType=} phase
  92. * @property {string[]=} patterns glob patterns for import.meta.glob
  93. * @property {string=} requestContext importer context for import.meta.glob
  94. * @property {string=} importName import selection for import.meta.glob
  95. * @property {boolean=} exhaustive exhaustive mode for import.meta.glob
  96. * @property {boolean=} caseSensitive case-sensitive matching for import.meta.glob
  97. */
  98. /**
  99. * @typedef {object} ContextModuleOptionsExtras
  100. * @property {string=} request the request of the context as written by the user, before it was resolved
  101. * @property {false | string | string[]} resource
  102. * @property {string=} resourceQuery
  103. * @property {string=} resourceFragment
  104. * @property {ResolveOptions=} resolveOptions
  105. */
  106. /** @typedef {ContextOptions & ContextModuleOptionsExtras} ContextModuleOptions */
  107. /**
  108. * @callback ResolveDependenciesCallback
  109. * @param {Error | null} err
  110. * @param {ContextElementDependency[]=} dependencies
  111. * @returns {void}
  112. */
  113. /**
  114. * @callback ResolveDependencies
  115. * @param {InputFileSystem} fs
  116. * @param {ContextModuleOptions} options
  117. * @param {ResolveDependenciesCallback} callback
  118. */
  119. /** @typedef {1 | 3 | 7 | 9} FakeMapType */
  120. /** @typedef {Record<ModuleId, FakeMapType>} FakeMap */
  121. /** @typedef {Record<string, ModuleId>} UserRequestMap */
  122. /** @typedef {Record<ModuleId, ModuleId[]>} UserRequestsMap */
  123. /**
  124. * Defines the build info properties specific to context modules.
  125. * @typedef {object} KnownContextModuleBuildInfo
  126. * @property {(InstanceType<Snapshot> | null)=} snapshot
  127. */
  128. /** @typedef {BuildInfo & KnownContextModuleBuildInfo} ContextModuleBuildInfo */
  129. class ContextModule extends Module {
  130. /**
  131. * @param {ResolveDependencies} resolveDependencies function to get dependencies in this context
  132. * @param {ContextModuleOptions} options options object
  133. */
  134. constructor(resolveDependencies, options) {
  135. if (!options || typeof options.resource === "string") {
  136. const parsed = parseResource(
  137. options ? /** @type {string} */ (options.resource) : ""
  138. );
  139. const resource = parsed.path;
  140. const resourceQuery = (options && options.resourceQuery) || parsed.query;
  141. const resourceFragment =
  142. (options && options.resourceFragment) || parsed.fragment;
  143. const layer = options && options.layer;
  144. super(JAVASCRIPT_MODULE_TYPE_DYNAMIC, resource, layer);
  145. /** @type {ContextModuleOptions} */
  146. this.options = {
  147. ...options,
  148. resource,
  149. resourceQuery,
  150. resourceFragment
  151. };
  152. } else {
  153. super(JAVASCRIPT_MODULE_TYPE_DYNAMIC, undefined, options.layer);
  154. /** @type {ContextModuleOptions} */
  155. this.options = {
  156. ...options,
  157. resource: options.resource,
  158. resourceQuery: options.resourceQuery || "",
  159. resourceFragment: options.resourceFragment || ""
  160. };
  161. }
  162. // Redeclared with the context module specific shape
  163. /** @type {ContextModuleBuildInfo | undefined} */
  164. this.buildInfo = undefined;
  165. // Info from Factory
  166. /** @type {ResolveDependencies | undefined} */
  167. this.resolveDependencies = resolveDependencies;
  168. if (options && options.resolveOptions !== undefined) {
  169. /** @type {ResolveOptions | undefined} */
  170. this.resolveOptions = options.resolveOptions;
  171. }
  172. if (options && typeof options.mode !== "string") {
  173. throw new Error("options.mode is a required option");
  174. }
  175. /** @type {string} */
  176. this._identifier = this._createIdentifier();
  177. /** @type {boolean} */
  178. this._forceBuild = true;
  179. }
  180. /**
  181. * Returns the source types this module can generate.
  182. * @returns {SourceTypes} types available (do not mutate)
  183. */
  184. getSourceTypes() {
  185. return JAVASCRIPT_TYPES;
  186. }
  187. /**
  188. * Assuming this module is in the cache. Update the (cached) module with
  189. * the fresh module from the factory. Usually updates internal references
  190. * and properties.
  191. * @param {Module} module fresh module
  192. * @returns {void}
  193. */
  194. updateCacheModule(module) {
  195. const m = /** @type {ContextModule} */ (module);
  196. this.resolveDependencies = m.resolveDependencies;
  197. this.options = m.options;
  198. }
  199. /**
  200. * Assuming this module is in the cache. Remove internal references to allow freeing some memory.
  201. */
  202. cleanupForCache() {
  203. super.cleanupForCache();
  204. this.resolveDependencies = undefined;
  205. }
  206. /**
  207. * @private
  208. * @param {RegExp} regexString RegExp as a string
  209. * @param {boolean=} stripSlash do we need to strip a slsh
  210. * @returns {string} pretty RegExp
  211. */
  212. _prettyRegExp(regexString, stripSlash = true) {
  213. const str = stripSlash
  214. ? regexString.source + regexString.flags
  215. : `${regexString}`;
  216. // Escape chars that are structural in the identifier/source-name URL
  217. // (`!`/`|` separators, `?` query, `#` fragment) so a regex like
  218. // `(?:a|b)` isn't misread and truncated when it becomes a source name.
  219. return str
  220. .replace(/!/g, "%21")
  221. .replace(/\|/g, "%7C")
  222. .replace(/\?/g, "%3F")
  223. .replace(/#/g, "%23");
  224. }
  225. _createIdentifier() {
  226. let identifier =
  227. this.context ||
  228. (typeof this.options.resource === "string" ||
  229. this.options.resource === false
  230. ? `${this.options.resource}`
  231. : this.options.resource.join("|"));
  232. if (this.options.resourceQuery) {
  233. identifier += `|${this.options.resourceQuery}`;
  234. }
  235. if (this.options.resourceFragment) {
  236. identifier += `|${this.options.resourceFragment}`;
  237. }
  238. if (this.options.mode) {
  239. identifier += `|${this.options.mode}`;
  240. }
  241. if (!this.options.recursive) {
  242. identifier += "|nonrecursive";
  243. }
  244. if (this.options.addon) {
  245. identifier += `|${this.options.addon}`;
  246. }
  247. if (this.options.regExp) {
  248. identifier += `|${this._prettyRegExp(this.options.regExp, false)}`;
  249. } else if (this.options.patterns) {
  250. identifier += `|patterns: ${this.options.patterns.join(", ")}`;
  251. }
  252. if (this.options.requestContext) {
  253. identifier += `|requestContext: ${this.options.requestContext}`;
  254. }
  255. if (this.options.include) {
  256. identifier += `|include: ${this._prettyRegExp(
  257. this.options.include,
  258. false
  259. )}`;
  260. }
  261. if (this.options.exclude) {
  262. identifier += `|exclude: ${this._prettyRegExp(
  263. this.options.exclude,
  264. false
  265. )}`;
  266. }
  267. if (this.options.referencedExports) {
  268. identifier += `|referencedExports: ${JSON.stringify(
  269. this.options.referencedExports
  270. )}`;
  271. }
  272. if (this.options.importName) {
  273. identifier += `|import: ${this.options.importName}`;
  274. }
  275. if (this.options.exhaustive) {
  276. identifier += "|exhaustive";
  277. }
  278. if (this.options.caseSensitive === false) {
  279. identifier += "|case-insensitive";
  280. }
  281. if (this.options.chunkName) {
  282. identifier += `|chunkName: ${this.options.chunkName}`;
  283. }
  284. if (this.options.groupOptions) {
  285. identifier += `|groupOptions: ${JSON.stringify(
  286. this.options.groupOptions
  287. )}`;
  288. }
  289. if (this.options.namespaceObject === "strict") {
  290. identifier += "|strict namespace object";
  291. } else if (this.options.namespaceObject) {
  292. identifier += "|namespace object";
  293. }
  294. if (this.options.attributes) {
  295. identifier += `|importAttributes: ${JSON.stringify(this.options.attributes)}`;
  296. }
  297. if (this.options.phase) {
  298. identifier += `|importPhase: ${this.options.phase}`;
  299. }
  300. if (this.layer) {
  301. identifier += `|layer: ${this.layer}`;
  302. }
  303. return identifier;
  304. }
  305. /**
  306. * Returns the unique identifier used to reference this module.
  307. * @returns {string} a unique identifier of the module
  308. */
  309. identifier() {
  310. return this._identifier;
  311. }
  312. /**
  313. * Returns a human-readable identifier for this module.
  314. * @param {RequestShortener} requestShortener the request shortener
  315. * @returns {string} a user readable identifier of the module
  316. */
  317. readableIdentifier(requestShortener) {
  318. /** @type {string} */
  319. let identifier;
  320. if (this.context) {
  321. identifier = `${requestShortener.shorten(this.context)}/`;
  322. } else if (
  323. typeof this.options.resource === "string" ||
  324. this.options.resource === false
  325. ) {
  326. identifier = `${requestShortener.shorten(`${this.options.resource}`)}/`;
  327. } else {
  328. identifier = this.options.resource
  329. .map((r) => `${requestShortener.shorten(r)}/`)
  330. .join(" ");
  331. }
  332. if (this.options.resourceQuery) {
  333. identifier += ` ${this.options.resourceQuery}`;
  334. }
  335. if (this.options.mode) {
  336. identifier += ` ${this.options.mode}`;
  337. }
  338. if (!this.options.recursive) {
  339. identifier += " nonrecursive";
  340. }
  341. if (this.options.addon) {
  342. identifier += ` ${requestShortener.shorten(this.options.addon)}`;
  343. }
  344. if (this.options.regExp) {
  345. identifier += ` ${this._prettyRegExp(this.options.regExp)}`;
  346. } else if (this.options.patterns) {
  347. identifier += ` patterns: ${this.options.patterns.join(", ")}`;
  348. }
  349. if (this.options.requestContext) {
  350. identifier += ` requestContext: ${this.options.requestContext}`;
  351. }
  352. if (this.options.exhaustive) {
  353. identifier += " exhaustive";
  354. }
  355. if (this.options.caseSensitive === false) {
  356. identifier += " case-insensitive";
  357. }
  358. if (this.options.include) {
  359. identifier += ` include: ${this._prettyRegExp(this.options.include)}`;
  360. }
  361. if (this.options.exclude) {
  362. identifier += ` exclude: ${this._prettyRegExp(this.options.exclude)}`;
  363. }
  364. if (this.options.referencedExports) {
  365. identifier += ` referencedExports: ${this.options.referencedExports
  366. .map((e) => e.join("."))
  367. .join(", ")}`;
  368. }
  369. if (this.options.chunkName) {
  370. identifier += ` chunkName: ${this.options.chunkName}`;
  371. }
  372. if (this.options.groupOptions) {
  373. const groupOptions = this.options.groupOptions;
  374. for (const key of Object.keys(groupOptions)) {
  375. identifier += ` ${key}: ${
  376. groupOptions[/** @type {keyof RawChunkGroupOptions} */ (key)]
  377. }`;
  378. }
  379. }
  380. if (this.options.namespaceObject === "strict") {
  381. identifier += " strict namespace object";
  382. } else if (this.options.namespaceObject) {
  383. identifier += " namespace object";
  384. }
  385. return identifier;
  386. }
  387. /**
  388. * Gets the library identifier.
  389. * @param {LibIdentOptions} options options
  390. * @returns {LibIdent | null} an identifier for library inclusion
  391. */
  392. libIdent(options) {
  393. /** @type {string} */
  394. let identifier;
  395. if (this.context) {
  396. identifier = contextify(
  397. options.context,
  398. this.context,
  399. options.associatedObjectForCache
  400. );
  401. } else if (typeof this.options.resource === "string") {
  402. identifier = contextify(
  403. options.context,
  404. this.options.resource,
  405. options.associatedObjectForCache
  406. );
  407. } else if (this.options.resource === false) {
  408. identifier = "false";
  409. } else {
  410. identifier = this.options.resource
  411. .map((res) =>
  412. contextify(options.context, res, options.associatedObjectForCache)
  413. )
  414. .join(" ");
  415. }
  416. if (this.layer) identifier = `(${this.layer})/${identifier}`;
  417. if (this.options.mode) {
  418. identifier += ` ${this.options.mode}`;
  419. }
  420. if (this.options.recursive) {
  421. identifier += " recursive";
  422. }
  423. if (this.options.addon) {
  424. identifier += ` ${contextify(
  425. options.context,
  426. this.options.addon,
  427. options.associatedObjectForCache
  428. )}`;
  429. }
  430. if (this.options.regExp) {
  431. identifier += ` ${this._prettyRegExp(this.options.regExp)}`;
  432. } else if (this.options.patterns) {
  433. identifier += ` patterns: ${this.options.patterns.join(", ")}`;
  434. }
  435. if (this.options.requestContext) {
  436. identifier += ` requestContext: ${this.options.requestContext}`;
  437. }
  438. if (this.options.exhaustive) {
  439. identifier += " exhaustive";
  440. }
  441. if (this.options.caseSensitive === false) {
  442. identifier += " case-insensitive";
  443. }
  444. if (this.options.include) {
  445. identifier += ` include: ${this._prettyRegExp(this.options.include)}`;
  446. }
  447. if (this.options.exclude) {
  448. identifier += ` exclude: ${this._prettyRegExp(this.options.exclude)}`;
  449. }
  450. if (this.options.referencedExports) {
  451. identifier += ` referencedExports: ${this.options.referencedExports
  452. .map((e) => e.join("."))
  453. .join(", ")}`;
  454. }
  455. return identifier;
  456. }
  457. /**
  458. * Invalidates the cached state associated with this value.
  459. * @returns {void}
  460. */
  461. invalidateBuild() {
  462. this._forceBuild = true;
  463. }
  464. /**
  465. * Checks whether the module needs to be rebuilt for the current build state.
  466. * @param {NeedBuildContext} context context info
  467. * @param {NeedBuildCallback} callback callback function, returns true, if the module needs a rebuild
  468. * @returns {void}
  469. */
  470. needBuild({ fileSystemInfo }, callback) {
  471. // build if enforced
  472. if (this._forceBuild) return callback(null, true);
  473. const buildInfo = /** @type {ContextModuleBuildInfo} */ (this.buildInfo);
  474. // always build when we have no snapshot and context
  475. if (!buildInfo.snapshot) {
  476. return callback(null, Boolean(this.context || this.options.resource));
  477. }
  478. fileSystemInfo.checkSnapshotValid(buildInfo.snapshot, (err, valid) => {
  479. callback(err, !valid);
  480. });
  481. }
  482. /**
  483. * Builds the module using the provided compilation context.
  484. * @param {WebpackOptions} options webpack options
  485. * @param {Compilation} compilation the compilation
  486. * @param {ResolverWithOptions} resolver the resolver
  487. * @param {InputFileSystem} fs the file system
  488. * @param {BuildCallback} callback callback function
  489. * @returns {void}
  490. */
  491. build(options, compilation, resolver, fs, callback) {
  492. this._forceBuild = false;
  493. /** @type {BuildMeta} */
  494. this.buildMeta = {
  495. exportsType: "default",
  496. defaultObject: "redirect-warn"
  497. };
  498. // Respect the global module parser `overrideStrict` option
  499. const overrideStrict =
  500. options.module.parser &&
  501. options.module.parser.javascript &&
  502. options.module.parser.javascript.overrideStrict;
  503. this.buildInfo = {
  504. strict: overrideStrict ? overrideStrict === "strict" : undefined,
  505. snapshot: undefined
  506. };
  507. this.dependencies.length = 0;
  508. this.blocks.length = 0;
  509. const startTime = Date.now();
  510. /** @type {ResolveDependencies} */
  511. (this.resolveDependencies)(fs, this.options, (err, dependencies) => {
  512. if (err) {
  513. return callback(
  514. makeWebpackError(err, "ContextModule.resolveDependencies")
  515. );
  516. }
  517. // abort if something failed
  518. // this will create an empty context
  519. if (!dependencies) {
  520. callback();
  521. return;
  522. }
  523. // enhance dependencies with meta info
  524. for (const dep of dependencies) {
  525. dep.loc = {
  526. name: dep.userRequest
  527. };
  528. dep.request = this.options.addon + dep.request;
  529. }
  530. dependencies.sort(
  531. concatComparators(
  532. compareSelect((a) => a.loc, compareLocations),
  533. keepOriginalOrder(this.dependencies)
  534. )
  535. );
  536. if (this.options.mode === "sync" || this.options.mode === "eager") {
  537. // if we have an sync or eager context
  538. // just add all dependencies and continue
  539. this.dependencies = dependencies;
  540. } else if (this.options.mode === "lazy-once") {
  541. // for the lazy-once mode create a new async dependency block
  542. // and add that block to this context
  543. if (dependencies.length > 0) {
  544. const block = new AsyncDependenciesBlock({
  545. ...this.options.groupOptions,
  546. name: this.options.chunkName
  547. });
  548. for (const dep of dependencies) {
  549. block.addDependency(dep);
  550. }
  551. this.addBlock(block);
  552. }
  553. } else if (
  554. this.options.mode === "weak" ||
  555. this.options.mode === "async-weak"
  556. ) {
  557. // we mark all dependencies as weak
  558. for (const dep of dependencies) {
  559. dep.weak = true;
  560. }
  561. this.dependencies = dependencies;
  562. } else if (this.options.mode === "lazy") {
  563. // if we are lazy create a new async dependency block per dependency
  564. // and add all blocks to this context
  565. let index = 0;
  566. for (const dep of dependencies) {
  567. let chunkName = this.options.chunkName;
  568. if (chunkName) {
  569. if (!/\[(?:index|request)\]/.test(chunkName)) {
  570. chunkName += "[index]";
  571. }
  572. chunkName = chunkName.replace(/\[index\]/g, `${index++}`);
  573. chunkName = chunkName.replace(
  574. /\[request\]/g,
  575. Template.toPath(dep.userRequest)
  576. );
  577. }
  578. const block = new AsyncDependenciesBlock(
  579. {
  580. ...this.options.groupOptions,
  581. name: chunkName
  582. },
  583. dep.loc,
  584. dep.userRequest
  585. );
  586. block.addDependency(dep);
  587. this.addBlock(block);
  588. }
  589. } else {
  590. callback(
  591. new WebpackError(`Unsupported mode "${this.options.mode}" in context`)
  592. );
  593. return;
  594. }
  595. if (!this.context && !this.options.resource) return callback();
  596. const snapshotOptions = compilation.options.snapshot.contextModule;
  597. compilation.fileSystemInfo.createSnapshot(
  598. startTime,
  599. null,
  600. this.context
  601. ? [this.context]
  602. : typeof this.options.resource === "string"
  603. ? [this.options.resource]
  604. : /** @type {string[]} */ (this.options.resource),
  605. null,
  606. snapshotOptions,
  607. (err, snapshot) => {
  608. if (err) return callback(err);
  609. /** @type {BuildInfo} */
  610. (this.buildInfo).snapshot = snapshot;
  611. callback();
  612. }
  613. );
  614. });
  615. }
  616. /**
  617. * Adds the provided file dependencies to the module.
  618. * @param {FileSystemDependencies} fileDependencies set where file dependencies are added to
  619. * @param {FileSystemDependencies} contextDependencies set where context dependencies are added to
  620. * @param {FileSystemDependencies} missingDependencies set where missing dependencies are added to
  621. * @param {FileSystemDependencies} buildDependencies set where build dependencies are added to
  622. */
  623. addCacheDependencies(
  624. fileDependencies,
  625. contextDependencies,
  626. missingDependencies,
  627. buildDependencies
  628. ) {
  629. if (this.context) {
  630. contextDependencies.add(this.context);
  631. } else if (typeof this.options.resource === "string") {
  632. contextDependencies.add(this.options.resource);
  633. } else if (this.options.resource === false) {
  634. // Do nothing
  635. } else {
  636. for (const res of this.options.resource) contextDependencies.add(res);
  637. }
  638. }
  639. /**
  640. * @param {Dependency[]} dependencies all dependencies
  641. * @param {ChunkGraph} chunkGraph chunk graph
  642. * @returns {UserRequestMap} map with user requests
  643. */
  644. getUserRequestMap(dependencies, chunkGraph) {
  645. const moduleGraph = chunkGraph.moduleGraph;
  646. // if we filter first we get a new array
  647. // therefore we don't need to create a clone of dependencies explicitly
  648. // therefore the order of this is !important!
  649. const sortedDependencies =
  650. /** @type {ContextElementDependency[]} */
  651. (dependencies)
  652. .filter((dependency) => moduleGraph.getModule(dependency))
  653. .sort((a, b) => {
  654. if (a.userRequest === b.userRequest) {
  655. return 0;
  656. }
  657. return a.userRequest < b.userRequest ? -1 : 1;
  658. });
  659. /** @type {UserRequestMap} */
  660. const map = Object.create(null);
  661. for (const dep of sortedDependencies) {
  662. const module = /** @type {Module} */ (moduleGraph.getModule(dep));
  663. map[dep.userRequest] =
  664. /** @type {ModuleId} */
  665. (chunkGraph.getModuleId(module));
  666. }
  667. return map;
  668. }
  669. /**
  670. * @param {Dependency[]} dependencies all dependencies
  671. * @param {ChunkGraph} chunkGraph chunk graph
  672. * @returns {FakeMap | FakeMapType} fake map
  673. */
  674. getFakeMap(dependencies, chunkGraph) {
  675. if (!this.options.namespaceObject) {
  676. return 9;
  677. }
  678. const moduleGraph = chunkGraph.moduleGraph;
  679. // bitfield
  680. let hasType = 0;
  681. const comparator = compareModulesById(chunkGraph);
  682. // if we filter first we get a new array
  683. // therefore we don't need to create a clone of dependencies explicitly
  684. // therefore the order of this is !important!
  685. const sortedModules = dependencies
  686. .map(
  687. (dependency) =>
  688. /** @type {Module} */ (moduleGraph.getModule(dependency))
  689. )
  690. .filter(Boolean)
  691. .sort(comparator);
  692. /** @type {FakeMap} */
  693. const fakeMap = Object.create(null);
  694. for (const module of sortedModules) {
  695. const exportsType = module.getExportsType(
  696. moduleGraph,
  697. this.options.namespaceObject === "strict"
  698. );
  699. const id = /** @type {ModuleId} */ (chunkGraph.getModuleId(module));
  700. switch (exportsType) {
  701. case "namespace":
  702. fakeMap[id] = 9;
  703. hasType |= 1;
  704. break;
  705. case "dynamic":
  706. fakeMap[id] = 7;
  707. hasType |= 2;
  708. break;
  709. case "default-only":
  710. fakeMap[id] = 1;
  711. hasType |= 4;
  712. break;
  713. case "default-with-named":
  714. fakeMap[id] = 3;
  715. hasType |= 8;
  716. break;
  717. default:
  718. throw new Error(`Unexpected exports type ${exportsType}`);
  719. }
  720. }
  721. if (hasType === 1) {
  722. return 9;
  723. }
  724. if (hasType === 2) {
  725. return 7;
  726. }
  727. if (hasType === 4) {
  728. return 1;
  729. }
  730. if (hasType === 8) {
  731. return 3;
  732. }
  733. if (hasType === 0) {
  734. return 9;
  735. }
  736. return fakeMap;
  737. }
  738. /**
  739. * @param {FakeMap | FakeMapType} fakeMap fake map
  740. * @param {RuntimeTemplate=} runtimeTemplate the runtime template
  741. * @returns {string} fake map init statement
  742. */
  743. getFakeMapInitStatement(fakeMap, runtimeTemplate) {
  744. const decl = runtimeTemplate ? runtimeTemplate.renderConst() : "var";
  745. return typeof fakeMap === "object"
  746. ? `${decl} fakeMap = ${JSON.stringify(fakeMap, null, "\t")};`
  747. : "";
  748. }
  749. /**
  750. * @param {Dependency[]} dependencies all dependencies
  751. * @param {ChunkGraph} chunkGraph chunk graph
  752. * @returns {UserRequestsMap} map with user requests
  753. */
  754. getModuleDeferredAsyncDepsMap(dependencies, chunkGraph) {
  755. const moduleGraph = chunkGraph.moduleGraph;
  756. const comparator = compareModulesById(chunkGraph);
  757. // if we filter first we get a new array
  758. // therefore we don't need to create a clone of dependencies explicitly
  759. // therefore the order of this is !important!
  760. const sortedModules = dependencies
  761. .map(
  762. (dependency) =>
  763. /** @type {Module} */ (moduleGraph.getModule(dependency))
  764. )
  765. .filter(Boolean)
  766. .sort(comparator);
  767. /** @type {UserRequestsMap} */
  768. const map = Object.create(null);
  769. for (const module of sortedModules) {
  770. if (!(/** @type {BuildMeta} */ (module.buildMeta).async)) {
  771. const id = /** @type {ModuleId} */ (chunkGraph.getModuleId(module));
  772. map[id] = Array.from(
  773. getOutgoingAsyncModules(chunkGraph.moduleGraph, module),
  774. (m) => chunkGraph.getModuleId(m)
  775. ).filter((id) => id !== null);
  776. }
  777. }
  778. return map;
  779. }
  780. /**
  781. * @param {false | UserRequestsMap} asyncDepsMap fake map
  782. * @param {RuntimeTemplate=} runtimeTemplate the runtime template
  783. * @returns {string} async deps map init statement
  784. */
  785. getModuleDeferredAsyncDepsMapInitStatement(asyncDepsMap, runtimeTemplate) {
  786. const decl = runtimeTemplate ? runtimeTemplate.renderConst() : "var";
  787. return typeof asyncDepsMap === "object"
  788. ? `${decl} asyncDepsMap = ${JSON.stringify(asyncDepsMap, null, "\t")};`
  789. : "";
  790. }
  791. /**
  792. * @param {FakeMapType} type type
  793. * @param {boolean=} asyncModule is async module
  794. * @returns {string} return result
  795. */
  796. getReturn(type, asyncModule) {
  797. if (type === 9) {
  798. return `${RuntimeGlobals.require}(id)`;
  799. }
  800. return `${RuntimeGlobals.createFakeNamespaceObject}(id, ${type}${
  801. asyncModule ? " | 16" : ""
  802. })`;
  803. }
  804. /**
  805. * @param {FakeMap | FakeMapType} fakeMap fake map
  806. * @param {boolean=} asyncModule is async module
  807. * @param {string=} asyncDeps async deps for deferred module
  808. * @param {string=} fakeMapDataExpression fake map data expression
  809. * @returns {string} module object source
  810. */
  811. getReturnModuleObjectSource(
  812. fakeMap,
  813. asyncModule,
  814. asyncDeps,
  815. fakeMapDataExpression = "fakeMap[id]"
  816. ) {
  817. const source =
  818. typeof fakeMap === "number"
  819. ? this.getReturn(fakeMap, asyncModule)
  820. : `${RuntimeGlobals.createFakeNamespaceObject}(id, ${fakeMapDataExpression}${asyncModule ? " | 16" : ""})`;
  821. if (asyncDeps) {
  822. if (!asyncModule) {
  823. throw new Error("Must be async when module is deferred");
  824. }
  825. const type =
  826. typeof fakeMap === "number" ? fakeMap : fakeMapDataExpression;
  827. return `${asyncDeps} ? ${asyncDeps}.length ? ${RuntimeGlobals.deferredModuleAsyncTransitiveDependencies}(${asyncDeps}).then(${RuntimeGlobals.makeDeferredNamespaceObject}.bind(${RuntimeGlobals.require}, id, ${type} ^ 1, true)) : ${RuntimeGlobals.makeDeferredNamespaceObject}(id, ${type} ^ 1 | 16) : ${source}`;
  828. }
  829. return source;
  830. }
  831. /**
  832. * @param {Dependency[]} dependencies dependencies
  833. * @param {ModuleId} id module id
  834. * @param {ChunkGraph} chunkGraph the chunk graph
  835. * @param {RuntimeTemplate=} runtimeTemplate the runtime template
  836. * @returns {string} source code
  837. */
  838. getSyncSource(dependencies, id, chunkGraph, runtimeTemplate) {
  839. const map = this.getUserRequestMap(dependencies, chunkGraph);
  840. const fakeMap = this.getFakeMap(dependencies, chunkGraph);
  841. const returnModuleObject = this.getReturnModuleObjectSource(fakeMap);
  842. const cst = runtimeTemplate ? runtimeTemplate.renderConst() : "var";
  843. return `${cst} map = ${JSON.stringify(map, null, "\t")};
  844. ${this.getFakeMapInitStatement(fakeMap, runtimeTemplate)}
  845. function webpackContext(req) {
  846. ${cst} id = webpackContextResolve(req);
  847. return ${returnModuleObject};
  848. }
  849. function webpackContextResolve(req) {
  850. if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
  851. ${cst} e = new Error("Cannot find module '" + req + "'");
  852. e.code = 'MODULE_NOT_FOUND';
  853. throw e;
  854. }
  855. return map[req];
  856. }
  857. webpackContext.keys = function webpackContextKeys() {
  858. return Object.keys(map);
  859. };
  860. webpackContext.resolve = webpackContextResolve;
  861. module.exports = webpackContext;
  862. webpackContext.id = ${JSON.stringify(id)};`;
  863. }
  864. /**
  865. * @param {Dependency[]} dependencies dependencies
  866. * @param {ModuleId} id module id
  867. * @param {ChunkGraph} chunkGraph the chunk graph
  868. * @param {RuntimeTemplate=} runtimeTemplate the runtime template
  869. * @returns {string} source code
  870. */
  871. getWeakSyncSource(dependencies, id, chunkGraph, runtimeTemplate) {
  872. const map = this.getUserRequestMap(dependencies, chunkGraph);
  873. const fakeMap = this.getFakeMap(dependencies, chunkGraph);
  874. const returnModuleObject = this.getReturnModuleObjectSource(fakeMap);
  875. const cst = runtimeTemplate ? runtimeTemplate.renderConst() : "var";
  876. return `${cst} map = ${JSON.stringify(map, null, "\t")};
  877. ${this.getFakeMapInitStatement(fakeMap, runtimeTemplate)}
  878. function webpackContext(req) {
  879. ${cst} id = webpackContextResolve(req);
  880. if(!${RuntimeGlobals.moduleFactories}[id]) {
  881. ${cst} e = new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)");
  882. e.code = 'MODULE_NOT_FOUND';
  883. throw e;
  884. }
  885. return ${returnModuleObject};
  886. }
  887. function webpackContextResolve(req) {
  888. if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
  889. ${cst} e = new Error("Cannot find module '" + req + "'");
  890. e.code = 'MODULE_NOT_FOUND';
  891. throw e;
  892. }
  893. return map[req];
  894. }
  895. webpackContext.keys = function webpackContextKeys() {
  896. return Object.keys(map);
  897. };
  898. webpackContext.resolve = webpackContextResolve;
  899. webpackContext.id = ${JSON.stringify(id)};
  900. module.exports = webpackContext;`;
  901. }
  902. /**
  903. * @param {Dependency[]} dependencies dependencies
  904. * @param {ModuleId} id module id
  905. * @param {ImportPhaseType} phase import phase
  906. * @param {object} context context
  907. * @param {ChunkGraph} context.chunkGraph the chunk graph
  908. * @param {RuntimeTemplate} context.runtimeTemplate the chunk graph
  909. * @returns {string} source code
  910. */
  911. getAsyncWeakSource(dependencies, id, phase, { chunkGraph, runtimeTemplate }) {
  912. const map = this.getUserRequestMap(dependencies, chunkGraph);
  913. const fakeMap = this.getFakeMap(dependencies, chunkGraph);
  914. const asyncDepsMap =
  915. ImportPhaseUtils.isDefer(phase) &&
  916. this.getModuleDeferredAsyncDepsMap(dependencies, chunkGraph);
  917. const returnModuleObject = this.getReturnModuleObjectSource(
  918. fakeMap,
  919. true,
  920. asyncDepsMap ? "asyncDepsMap[id]" : undefined
  921. );
  922. const cst = runtimeTemplate.renderConst();
  923. return `${cst} map = ${JSON.stringify(map, null, "\t")};
  924. ${this.getFakeMapInitStatement(fakeMap, runtimeTemplate)}
  925. ${this.getModuleDeferredAsyncDepsMapInitStatement(asyncDepsMap, runtimeTemplate)}
  926. function webpackAsyncContext(req) {
  927. return webpackAsyncContextResolve(req).then(${runtimeTemplate.basicFunction(
  928. "id",
  929. [
  930. `if(!${RuntimeGlobals.moduleFactories}[id]) {`,
  931. Template.indent([
  932. `${cst} e = new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)");`,
  933. "e.code = 'MODULE_NOT_FOUND';",
  934. "throw e;"
  935. ]),
  936. "}",
  937. `return ${returnModuleObject};`
  938. ]
  939. )});
  940. }
  941. function webpackAsyncContextResolve(req) {
  942. // Here Promise.resolve().then() is used instead of new Promise() to prevent
  943. // uncaught exception popping up in devtools
  944. return Promise.resolve().then(${runtimeTemplate.basicFunction("", [
  945. `if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {`,
  946. Template.indent([
  947. `${cst} e = new Error("Cannot find module '" + req + "'");`,
  948. "e.code = 'MODULE_NOT_FOUND';",
  949. "throw e;"
  950. ]),
  951. "}",
  952. "return map[req];"
  953. ])});
  954. }
  955. webpackAsyncContext.keys = ${runtimeTemplate.returningFunction(
  956. "Object.keys(map)"
  957. )};
  958. webpackAsyncContext.resolve = webpackAsyncContextResolve;
  959. webpackAsyncContext.id = ${JSON.stringify(id)};
  960. module.exports = webpackAsyncContext;`;
  961. }
  962. /**
  963. * @param {Dependency[]} dependencies dependencies
  964. * @param {ModuleId} id module id
  965. * @param {ImportPhaseType} phase import phase
  966. * @param {object} context context
  967. * @param {ChunkGraph} context.chunkGraph the chunk graph
  968. * @param {RuntimeTemplate} context.runtimeTemplate the chunk graph
  969. * @returns {string} source code
  970. */
  971. getEagerSource(dependencies, id, phase, { chunkGraph, runtimeTemplate }) {
  972. const map = this.getUserRequestMap(dependencies, chunkGraph);
  973. const fakeMap = this.getFakeMap(dependencies, chunkGraph);
  974. const asyncDepsMap =
  975. ImportPhaseUtils.isDefer(phase) &&
  976. this.getModuleDeferredAsyncDepsMap(dependencies, chunkGraph);
  977. const thenFunction = runtimeTemplate.returningFunction(
  978. this.getReturnModuleObjectSource(
  979. fakeMap,
  980. true,
  981. asyncDepsMap ? "asyncDepsMap[id]" : undefined
  982. ),
  983. "id"
  984. );
  985. const cst = runtimeTemplate.renderConst();
  986. return `${cst} map = ${JSON.stringify(map, null, "\t")};
  987. ${this.getFakeMapInitStatement(fakeMap, runtimeTemplate)}
  988. ${this.getModuleDeferredAsyncDepsMapInitStatement(asyncDepsMap, runtimeTemplate)}
  989. function webpackAsyncContext(req) {
  990. return webpackAsyncContextResolve(req).then(${thenFunction});
  991. }
  992. function webpackAsyncContextResolve(req) {
  993. // Here Promise.resolve().then() is used instead of new Promise() to prevent
  994. // uncaught exception popping up in devtools
  995. return Promise.resolve().then(${runtimeTemplate.basicFunction("", [
  996. `if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {`,
  997. Template.indent([
  998. `${cst} e = new Error("Cannot find module '" + req + "'");`,
  999. "e.code = 'MODULE_NOT_FOUND';",
  1000. "throw e;"
  1001. ]),
  1002. "}",
  1003. "return map[req];"
  1004. ])});
  1005. }
  1006. webpackAsyncContext.keys = ${runtimeTemplate.returningFunction(
  1007. "Object.keys(map)"
  1008. )};
  1009. webpackAsyncContext.resolve = webpackAsyncContextResolve;
  1010. webpackAsyncContext.id = ${JSON.stringify(id)};
  1011. module.exports = webpackAsyncContext;`;
  1012. }
  1013. /**
  1014. * @param {AsyncDependenciesBlock} block block
  1015. * @param {Dependency[]} dependencies dependencies
  1016. * @param {ModuleId} id module id
  1017. * @param {ImportPhaseType} phase import phase
  1018. * @param {object} options options object
  1019. * @param {RuntimeTemplate} options.runtimeTemplate the runtime template
  1020. * @param {ChunkGraph} options.chunkGraph the chunk graph
  1021. * @param {RuntimeRequirements} options.runtimeRequirements runtime requirements
  1022. * @returns {string} source code
  1023. */
  1024. getLazyOnceSource(
  1025. block,
  1026. dependencies,
  1027. id,
  1028. phase,
  1029. { runtimeTemplate, chunkGraph, runtimeRequirements }
  1030. ) {
  1031. const promise = runtimeTemplate.blockPromise({
  1032. chunkGraph,
  1033. block,
  1034. message: "lazy-once context",
  1035. runtimeRequirements,
  1036. originModule: this
  1037. });
  1038. const map = this.getUserRequestMap(dependencies, chunkGraph);
  1039. const fakeMap = this.getFakeMap(dependencies, chunkGraph);
  1040. const asyncDepsMap =
  1041. ImportPhaseUtils.isDefer(phase) &&
  1042. this.getModuleDeferredAsyncDepsMap(dependencies, chunkGraph);
  1043. const thenFunction = runtimeTemplate.returningFunction(
  1044. this.getReturnModuleObjectSource(
  1045. fakeMap,
  1046. true,
  1047. asyncDepsMap ? "asyncDepsMap[id]" : undefined
  1048. ),
  1049. "id"
  1050. );
  1051. const cst = runtimeTemplate.renderConst();
  1052. return `${cst} map = ${JSON.stringify(map, null, "\t")};
  1053. ${this.getFakeMapInitStatement(fakeMap, runtimeTemplate)}
  1054. ${this.getModuleDeferredAsyncDepsMapInitStatement(asyncDepsMap, runtimeTemplate)}
  1055. function webpackAsyncContext(req) {
  1056. return webpackAsyncContextResolve(req).then(${thenFunction});
  1057. }
  1058. function webpackAsyncContextResolve(req) {
  1059. return ${promise}.then(${runtimeTemplate.basicFunction("", [
  1060. `if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {`,
  1061. Template.indent([
  1062. `${cst} e = new Error("Cannot find module '" + req + "'");`,
  1063. "e.code = 'MODULE_NOT_FOUND';",
  1064. "throw e;"
  1065. ]),
  1066. "}",
  1067. "return map[req];"
  1068. ])});
  1069. }
  1070. webpackAsyncContext.keys = ${runtimeTemplate.returningFunction(
  1071. "Object.keys(map)"
  1072. )};
  1073. webpackAsyncContext.resolve = webpackAsyncContextResolve;
  1074. webpackAsyncContext.id = ${JSON.stringify(id)};
  1075. module.exports = webpackAsyncContext;`;
  1076. }
  1077. /**
  1078. * @param {AsyncDependenciesBlock[]} blocks blocks
  1079. * @param {ModuleId} id module id
  1080. * @param {ImportPhaseType} phase import phase
  1081. * @param {object} context context
  1082. * @param {ChunkGraph} context.chunkGraph the chunk graph
  1083. * @param {RuntimeTemplate} context.runtimeTemplate the chunk graph
  1084. * @param {RuntimeRequirements} context.runtimeRequirements runtime requirements
  1085. * @returns {string} source code
  1086. */
  1087. getLazySource(
  1088. blocks,
  1089. id,
  1090. phase,
  1091. { chunkGraph, runtimeTemplate, runtimeRequirements }
  1092. ) {
  1093. const moduleGraph = chunkGraph.moduleGraph;
  1094. let hasMultipleOrNoChunks = false;
  1095. let hasNoChunk = true;
  1096. let hasNoModuleDeferred = true;
  1097. const fakeMap = this.getFakeMap(
  1098. blocks.map((b) => b.dependencies[0]),
  1099. chunkGraph
  1100. );
  1101. const hasFakeMap = typeof fakeMap === "object";
  1102. /** @typedef {{ userRequest: string, dependency: ContextElementDependency, chunks: undefined | Chunk[], module: Module, block: AsyncDependenciesBlock, asyncDeps: undefined | ModuleId[] }} Item */
  1103. /**
  1104. * @type {Item[]}
  1105. */
  1106. const items = blocks
  1107. .map((block) => {
  1108. const dependency =
  1109. /** @type {ContextElementDependency} */
  1110. (block.dependencies[0]);
  1111. return {
  1112. dependency,
  1113. module: /** @type {Module} */ (moduleGraph.getModule(dependency)),
  1114. block,
  1115. userRequest: dependency.userRequest,
  1116. chunks: undefined,
  1117. asyncDeps: undefined
  1118. };
  1119. })
  1120. .filter((item) => item.module);
  1121. for (const item of items) {
  1122. const chunkGroup = chunkGraph.getBlockChunkGroup(item.block);
  1123. const chunks = (chunkGroup && chunkGroup.chunks) || [];
  1124. item.chunks = chunks;
  1125. if (chunks.length > 0) {
  1126. hasNoChunk = false;
  1127. }
  1128. if (chunks.length !== 1) {
  1129. hasMultipleOrNoChunks = true;
  1130. }
  1131. const isModuleDeferred =
  1132. ImportPhaseUtils.isDefer(phase) &&
  1133. !(/** @type {BuildMeta} */ (item.module.buildMeta).async);
  1134. if (isModuleDeferred) {
  1135. const asyncDeps = Array.from(
  1136. getOutgoingAsyncModules(chunkGraph.moduleGraph, item.module),
  1137. (m) => chunkGraph.getModuleId(m)
  1138. ).filter((id) => id !== null);
  1139. item.asyncDeps = asyncDeps;
  1140. hasNoModuleDeferred = false;
  1141. }
  1142. }
  1143. const shortMode = hasNoChunk && hasNoModuleDeferred && !hasFakeMap;
  1144. // Sorted before anything is keyed by request, so two items sharing one leave the
  1145. // same last writer in the map and in the loaders beside it.
  1146. const sortedItems = items.sort((a, b) => {
  1147. if (a.userRequest === b.userRequest) return 0;
  1148. return a.userRequest < b.userRequest ? -1 : 1;
  1149. });
  1150. let needEnsureChunk = !hasNoChunk;
  1151. /** @type {Map<string, string[]> | undefined} */
  1152. let loaders;
  1153. // Only module output can name a chunk in an `import()`, so nothing else pays for
  1154. // building the loaders just to throw them away.
  1155. if (!hasNoChunk && runtimeTemplate.isModule()) {
  1156. /** @type {Map<string, string[]>} */
  1157. const perRequest = new Map();
  1158. let hasAnalyzable = false;
  1159. let hasFallback = false;
  1160. /**
  1161. * @param {Chunk} chunk one chunk a request needs
  1162. * @returns {string} a thunk loading it, by literal name where the chunk has one
  1163. */
  1164. const loaderFor = (chunk) => {
  1165. // `.ei` always imports, where `.e` skips a chunk already loaded — the same
  1166. // filter `blockPromise` applies before reaching for it.
  1167. const analyzable =
  1168. chunk.hasRuntime() || chunk.id === null
  1169. ? null
  1170. : runtimeTemplate.analyzableChunkImport(
  1171. chunk,
  1172. "",
  1173. runtimeRequirements,
  1174. this,
  1175. chunkGraph
  1176. );
  1177. if (analyzable !== null) {
  1178. hasAnalyzable = true;
  1179. return runtimeTemplate.returningFunction(analyzable);
  1180. }
  1181. hasFallback = true;
  1182. return runtimeTemplate.returningFunction(
  1183. `${RuntimeGlobals.ensureChunk}(${JSON.stringify(chunk.id)})`
  1184. );
  1185. };
  1186. for (const item of sortedItems) {
  1187. perRequest.set(
  1188. item.userRequest,
  1189. /** @type {Chunk[]} */ (item.chunks).map(loaderFor)
  1190. );
  1191. }
  1192. // Nothing gained when no chunk can be spelled out, and the plain id map is
  1193. // smaller, so the loaders are only written when at least one names its chunk.
  1194. if (hasAnalyzable) {
  1195. loaders = perRequest;
  1196. needEnsureChunk = hasFallback;
  1197. }
  1198. }
  1199. /** @type {Record<string, ModuleId | (ModuleId | FakeMapType | ChunkId[] | (ModuleId[] | undefined))[]>} */
  1200. const map = Object.create(null);
  1201. for (const item of sortedItems) {
  1202. const moduleId =
  1203. /** @type {ModuleId} */
  1204. (chunkGraph.getModuleId(item.module));
  1205. if (shortMode) {
  1206. map[item.userRequest] = moduleId;
  1207. } else {
  1208. /** @type {(ModuleId | FakeMapType | ChunkId[] | (ModuleId[] | undefined))[]} */
  1209. const array = [moduleId];
  1210. if (hasFakeMap) {
  1211. array.push(fakeMap[moduleId]);
  1212. }
  1213. if (!hasNoChunk) {
  1214. array.push(
  1215. /** @type {Chunk[]} */ (item.chunks).map(
  1216. (chunk) => /** @type {ChunkId} */ (chunk.id)
  1217. )
  1218. );
  1219. }
  1220. if (!hasNoModuleDeferred) {
  1221. array.push(item.asyncDeps);
  1222. }
  1223. map[item.userRequest] = array;
  1224. }
  1225. }
  1226. const chunksPosition = hasFakeMap ? 2 : 1;
  1227. // No chunks slot is pushed when `hasNoChunk`, so `asyncDeps` sits at `chunksPosition`.
  1228. const asyncDepsPosition = hasNoChunk ? chunksPosition : chunksPosition + 1;
  1229. const requestPrefix = hasNoChunk
  1230. ? "Promise.resolve()"
  1231. : loaders !== undefined
  1232. ? hasMultipleOrNoChunks
  1233. ? `Promise.all(ids[${chunksPosition}].map(${runtimeTemplate.returningFunction("load()", "load")}))`
  1234. : `ids[${chunksPosition}][0]()`
  1235. : hasMultipleOrNoChunks
  1236. ? `Promise.all(ids[${chunksPosition}].map(${RuntimeGlobals.ensureChunk}))`
  1237. : `${RuntimeGlobals.ensureChunk}(ids[${chunksPosition}][0])`;
  1238. // Only the id map reads it; nothing loads a chunk when there is none to load, and
  1239. // a map of loaders spells out every one it could reach for.
  1240. if (needEnsureChunk) {
  1241. runtimeRequirements.add(RuntimeGlobals.ensureChunk);
  1242. }
  1243. const returnModuleObject = this.getReturnModuleObjectSource(
  1244. fakeMap,
  1245. true,
  1246. hasNoModuleDeferred ? undefined : `ids[${asyncDepsPosition}]`,
  1247. shortMode ? "invalid" : "ids[1]"
  1248. );
  1249. const cst = runtimeTemplate.renderConst();
  1250. const webpackAsyncContext =
  1251. requestPrefix === "Promise.resolve()"
  1252. ? `
  1253. function webpackAsyncContext(req) {
  1254. return Promise.resolve().then(${runtimeTemplate.basicFunction("", [
  1255. `if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {`,
  1256. Template.indent([
  1257. `${cst} e = new Error("Cannot find module '" + req + "'");`,
  1258. "e.code = 'MODULE_NOT_FOUND';",
  1259. "throw e;"
  1260. ]),
  1261. "}",
  1262. shortMode ? `${cst} id = map[req];` : `${cst} ids = map[req], id = ids[0];`,
  1263. `return ${returnModuleObject};`
  1264. ])});
  1265. }`
  1266. : `function webpackAsyncContext(req) {
  1267. try {
  1268. if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
  1269. return Promise.resolve().then(${runtimeTemplate.basicFunction("", [
  1270. `${cst} e = new Error("Cannot find module '" + req + "'");`,
  1271. "e.code = 'MODULE_NOT_FOUND';",
  1272. "throw e;"
  1273. ])});
  1274. }
  1275. } catch(err) {
  1276. return Promise.reject(err);
  1277. }
  1278. ${cst} ids = map[req], id = ids[0];
  1279. return ${requestPrefix}.then(${runtimeTemplate.returningFunction(returnModuleObject)});
  1280. }`;
  1281. // A loader is source, not data, so the map holding one is written out rather than
  1282. // serialized — one entry per line, keeping the request next to what loads it.
  1283. const mapSource =
  1284. loaders === undefined
  1285. ? JSON.stringify(map, null, "\t")
  1286. : `{\n${Object.keys(map)
  1287. .map((request) => {
  1288. const slots =
  1289. /** @type {(ModuleId | FakeMapType | ChunkId[] | (ModuleId[] | undefined))[]} */
  1290. (map[request]).map((slot, index) =>
  1291. index === chunksPosition
  1292. ? `[${/** @type {string[]} */ (loaders.get(request)).join(", ")}]`
  1293. : // An absent `asyncDeps` slot is `null` to `JSON.stringify`.
  1294. slot === undefined
  1295. ? "null"
  1296. : JSON.stringify(slot)
  1297. );
  1298. return `\t${JSON.stringify(request)}: [${slots.join(", ")}]`;
  1299. })
  1300. .join(",\n")}\n}`;
  1301. return `${cst} map = ${mapSource};
  1302. ${webpackAsyncContext}
  1303. webpackAsyncContext.keys = ${runtimeTemplate.returningFunction(
  1304. "Object.keys(map)"
  1305. )};
  1306. webpackAsyncContext.id = ${JSON.stringify(id)};
  1307. module.exports = webpackAsyncContext;`;
  1308. }
  1309. /**
  1310. * @param {ModuleId} id module id
  1311. * @param {RuntimeTemplate} runtimeTemplate runtime template
  1312. * @returns {string} source for empty async context
  1313. */
  1314. getSourceForEmptyContext(id, runtimeTemplate) {
  1315. return `function webpackEmptyContext(req) {
  1316. ${runtimeTemplate.renderConst()} e = new Error("Cannot find module '" + req + "'");
  1317. e.code = 'MODULE_NOT_FOUND';
  1318. throw e;
  1319. }
  1320. webpackEmptyContext.keys = ${runtimeTemplate.returningFunction("[]")};
  1321. webpackEmptyContext.resolve = webpackEmptyContext;
  1322. webpackEmptyContext.id = ${JSON.stringify(id)};
  1323. module.exports = webpackEmptyContext;`;
  1324. }
  1325. /**
  1326. * @param {ModuleId} id module id
  1327. * @param {RuntimeTemplate} runtimeTemplate runtime template
  1328. * @returns {string} source for empty async context
  1329. */
  1330. getSourceForEmptyAsyncContext(id, runtimeTemplate) {
  1331. return `function webpackEmptyAsyncContext(req) {
  1332. // Here Promise.resolve().then() is used instead of new Promise() to prevent
  1333. // uncaught exception popping up in devtools
  1334. return Promise.resolve().then(${runtimeTemplate.basicFunction("", [
  1335. `${runtimeTemplate.renderConst()} e = new Error("Cannot find module '" + req + "'");`,
  1336. "e.code = 'MODULE_NOT_FOUND';",
  1337. "throw e;"
  1338. ])});
  1339. }
  1340. webpackEmptyAsyncContext.keys = ${runtimeTemplate.returningFunction("[]")};
  1341. webpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext;
  1342. webpackEmptyAsyncContext.id = ${JSON.stringify(id)};
  1343. module.exports = webpackEmptyAsyncContext;`;
  1344. }
  1345. /**
  1346. * @returns {string | undefined} import property access
  1347. */
  1348. getImportPropertyAccess() {
  1349. const importName = this.options.importName;
  1350. if (!importName || importName === "*") return;
  1351. return propertyAccess([importName]);
  1352. }
  1353. /**
  1354. * @param {number} index index
  1355. * @param {string} userRequest user request
  1356. * @param {string} value value expression
  1357. * @param {string[]} entries entries
  1358. * @returns {void}
  1359. */
  1360. appendGlobMapEntry(index, userRequest, value, entries) {
  1361. entries.push(`\n ${JSON.stringify(userRequest)}: ${value}`);
  1362. }
  1363. /**
  1364. * @param {string} entries entries
  1365. * @returns {string} object export source
  1366. */
  1367. getGlobObjectExportSource(entries) {
  1368. return `\nmodule.exports = {${entries}\n};\n`;
  1369. }
  1370. /**
  1371. * @returns {string} empty object export source
  1372. */
  1373. getEmptyObjectExportSource() {
  1374. return "\nmodule.exports = {};\n";
  1375. }
  1376. /**
  1377. * @param {AsyncDependenciesBlock[]} blocks blocks
  1378. * @param {ImportPhaseType} phase import phase
  1379. * @param {object} context context
  1380. * @param {RuntimeTemplate} context.runtimeTemplate runtime template
  1381. * @param {ChunkGraph} context.chunkGraph chunk graph
  1382. * @param {RuntimeRequirements=} context.runtimeRequirements runtime requirements
  1383. * @returns {string} glob lazy source
  1384. */
  1385. getGlobLazySource(
  1386. blocks,
  1387. phase,
  1388. { runtimeTemplate, chunkGraph, runtimeRequirements }
  1389. ) {
  1390. if (!blocks || blocks.length === 0) {
  1391. return this.getEmptyObjectExportSource();
  1392. }
  1393. const moduleGraph = chunkGraph.moduleGraph;
  1394. const globImportAccess = this.getImportPropertyAccess();
  1395. /** @type {RuntimeRequirements} */
  1396. const localRuntimeRequirements = runtimeRequirements || new Set();
  1397. /** @type {{ userRequest: string, block: AsyncDependenciesBlock, dependency: ContextElementDependency }[]} */
  1398. const blockInfo = blocks
  1399. .map((block) => {
  1400. const dependency =
  1401. /** @type {ContextElementDependency} */
  1402. (block.dependencies[0]);
  1403. return {
  1404. userRequest: dependency.userRequest,
  1405. block,
  1406. dependency
  1407. };
  1408. })
  1409. .sort((a, b) =>
  1410. a.userRequest < b.userRequest
  1411. ? -1
  1412. : a.userRequest > b.userRequest
  1413. ? 1
  1414. : 0
  1415. );
  1416. /** @type {string[]} */
  1417. const entries = [];
  1418. for (let i = 0; i < blockInfo.length; i++) {
  1419. const info = blockInfo[i];
  1420. let importPromise = runtimeTemplate.moduleNamespacePromise({
  1421. chunkGraph,
  1422. block: info.block,
  1423. module: /** @type {Module} */ (moduleGraph.getModule(info.dependency)),
  1424. request: info.userRequest,
  1425. message: "import.meta.glob",
  1426. strict: this.options.namespaceObject === "strict",
  1427. dependency: info.dependency,
  1428. runtimeRequirements: localRuntimeRequirements,
  1429. originModule: this
  1430. });
  1431. if (globImportAccess) {
  1432. importPromise = `${importPromise}.then(function(m) { return m${globImportAccess}; })`;
  1433. }
  1434. this.appendGlobMapEntry(
  1435. i,
  1436. info.userRequest,
  1437. `function() { return ${importPromise}; }`,
  1438. entries
  1439. );
  1440. }
  1441. return this.getGlobObjectExportSource(entries.join(","));
  1442. }
  1443. /**
  1444. * @param {Dependency[]} dependencies dependencies
  1445. * @param {ChunkGraph} chunkGraph chunk graph
  1446. * @param {RuntimeTemplate} runtimeTemplate runtime template
  1447. * @returns {string} glob sync source
  1448. */
  1449. getGlobSyncSource(dependencies, chunkGraph, runtimeTemplate) {
  1450. if (!dependencies || dependencies.length === 0) {
  1451. return this.getEmptyObjectExportSource();
  1452. }
  1453. const moduleGraph = chunkGraph.moduleGraph;
  1454. const fakeMap = this.getFakeMap(dependencies, chunkGraph);
  1455. const returnModuleObject = this.getReturnModuleObjectSource(fakeMap);
  1456. const globImportAccess = this.getImportPropertyAccess();
  1457. const sortedDependencies =
  1458. /** @type {import("./dependencies/ContextElementDependency")[]} */
  1459. (dependencies).sort((a, b) =>
  1460. a.userRequest < b.userRequest
  1461. ? -1
  1462. : a.userRequest > b.userRequest
  1463. ? 1
  1464. : 0
  1465. );
  1466. /** @type {string[]} */
  1467. const entries = [];
  1468. let index = 0;
  1469. for (const dep of sortedDependencies) {
  1470. const module = moduleGraph.getModule(dep);
  1471. let moduleExpr;
  1472. if (module) {
  1473. const moduleId = chunkGraph.getModuleId(module);
  1474. moduleExpr = `(function() { var id = ${JSON.stringify(moduleId)}; return ${returnModuleObject}; })()`;
  1475. if (globImportAccess) {
  1476. moduleExpr += globImportAccess;
  1477. }
  1478. } else {
  1479. moduleExpr = `undefined /* ${JSON.stringify(dep.userRequest)} */`;
  1480. }
  1481. this.appendGlobMapEntry(index++, dep.userRequest, moduleExpr, entries);
  1482. }
  1483. const fakeMapInit = this.getFakeMapInitStatement(fakeMap, runtimeTemplate);
  1484. return `${fakeMapInit}\n${this.getGlobObjectExportSource(entries.join(","))}`;
  1485. }
  1486. /**
  1487. * @param {string} asyncMode module mode
  1488. * @param {ImportPhaseType} phase import phase
  1489. * @param {CodeGenerationContext} context context info
  1490. * @returns {string} the source code
  1491. */
  1492. getGlobSourceString(asyncMode, phase, context) {
  1493. if (asyncMode === "lazy") {
  1494. if (this.blocks && this.blocks.length > 0) {
  1495. return this.getGlobLazySource(this.blocks, phase, context);
  1496. }
  1497. return this.getEmptyObjectExportSource();
  1498. }
  1499. if (this.dependencies && this.dependencies.length > 0) {
  1500. return this.getGlobSyncSource(
  1501. this.dependencies,
  1502. context.chunkGraph,
  1503. context.runtimeTemplate
  1504. );
  1505. }
  1506. return this.getEmptyObjectExportSource();
  1507. }
  1508. /**
  1509. * @param {string} asyncMode module mode
  1510. * @param {ImportPhaseType} phase import phase
  1511. * @param {CodeGenerationContext & { runtimeRequirements: RuntimeRequirements }} context context info
  1512. * @returns {string} the source code
  1513. */
  1514. getSourceString(asyncMode, phase, context) {
  1515. if (this.options.patterns) {
  1516. return this.getGlobSourceString(asyncMode, phase, context);
  1517. }
  1518. return this.getContextSourceString(asyncMode, phase, context);
  1519. }
  1520. /**
  1521. * @param {string} asyncMode module mode
  1522. * @param {ImportPhaseType} phase import phase
  1523. * @param {CodeGenerationContext & { runtimeRequirements: RuntimeRequirements }} context context info
  1524. * @returns {string} the source code
  1525. */
  1526. getContextSourceString(asyncMode, phase, context) {
  1527. const { runtimeTemplate, chunkGraph, runtimeRequirements } = context;
  1528. const id = /** @type {ModuleId} */ (chunkGraph.getModuleId(this));
  1529. if (asyncMode === "lazy") {
  1530. if (this.blocks && this.blocks.length > 0) {
  1531. return this.getLazySource(this.blocks, id, phase, {
  1532. runtimeTemplate,
  1533. chunkGraph,
  1534. runtimeRequirements
  1535. });
  1536. }
  1537. return this.getSourceForEmptyAsyncContext(id, runtimeTemplate);
  1538. }
  1539. if (asyncMode === "eager") {
  1540. if (this.dependencies && this.dependencies.length > 0) {
  1541. return this.getEagerSource(this.dependencies, id, phase, {
  1542. chunkGraph,
  1543. runtimeTemplate
  1544. });
  1545. }
  1546. return this.getSourceForEmptyAsyncContext(id, runtimeTemplate);
  1547. }
  1548. if (asyncMode === "lazy-once") {
  1549. const block = this.blocks[0];
  1550. if (block) {
  1551. return this.getLazyOnceSource(block, block.dependencies, id, phase, {
  1552. runtimeTemplate,
  1553. chunkGraph,
  1554. runtimeRequirements
  1555. });
  1556. }
  1557. return this.getSourceForEmptyAsyncContext(id, runtimeTemplate);
  1558. }
  1559. if (asyncMode === "async-weak") {
  1560. if (this.dependencies && this.dependencies.length > 0) {
  1561. return this.getAsyncWeakSource(this.dependencies, id, phase, {
  1562. chunkGraph,
  1563. runtimeTemplate
  1564. });
  1565. }
  1566. return this.getSourceForEmptyAsyncContext(id, runtimeTemplate);
  1567. }
  1568. if (
  1569. asyncMode === "weak" &&
  1570. this.dependencies &&
  1571. this.dependencies.length > 0
  1572. ) {
  1573. return this.getWeakSyncSource(
  1574. this.dependencies,
  1575. id,
  1576. chunkGraph,
  1577. runtimeTemplate
  1578. );
  1579. }
  1580. if (this.dependencies && this.dependencies.length > 0) {
  1581. return this.getSyncSource(
  1582. this.dependencies,
  1583. id,
  1584. chunkGraph,
  1585. runtimeTemplate
  1586. );
  1587. }
  1588. return this.getSourceForEmptyContext(id, runtimeTemplate);
  1589. }
  1590. /**
  1591. * @param {string} sourceString source content
  1592. * @param {Compilation=} compilation the compilation
  1593. * @returns {Source} generated source
  1594. */
  1595. getSource(sourceString, compilation) {
  1596. if (this.useSourceMap || this.useSimpleSourceMap) {
  1597. return new OriginalSource(
  1598. sourceString,
  1599. `webpack://${makePathsRelative(
  1600. (compilation && compilation.compiler.context) || "",
  1601. this.identifier(),
  1602. compilation && compilation.compiler.root
  1603. )}`
  1604. );
  1605. }
  1606. return new RawSource(sourceString);
  1607. }
  1608. /**
  1609. * Generates code and runtime requirements for this module.
  1610. * @param {CodeGenerationContext} context context for code generation
  1611. * @returns {CodeGenerationResult} result
  1612. */
  1613. codeGeneration(context) {
  1614. const { chunkGraph, compilation } = context;
  1615. /** @type {RuntimeRequirements} */
  1616. const set = new Set();
  1617. /** @type {Sources} */
  1618. const sources = new Map();
  1619. sources.set(
  1620. JAVASCRIPT_TYPE,
  1621. this.getSource(
  1622. this.getSourceString(
  1623. this.options.mode,
  1624. this.options.phase || ImportPhase.Evaluation,
  1625. { ...context, runtimeRequirements: set }
  1626. ),
  1627. compilation
  1628. )
  1629. );
  1630. const allDeps =
  1631. this.dependencies.length > 0
  1632. ? /** @type {ContextElementDependency[]} */ [...this.dependencies]
  1633. : [];
  1634. for (const block of this.blocks) {
  1635. for (const dep of block.dependencies) {
  1636. allDeps.push(/** @type {ContextElementDependency} */ (dep));
  1637. }
  1638. }
  1639. set.add(RuntimeGlobals.module);
  1640. set.add(RuntimeGlobals.hasOwnProperty);
  1641. if (allDeps.length > 0) {
  1642. const asyncMode = this.options.mode;
  1643. set.add(RuntimeGlobals.require);
  1644. // `ensureChunk` is not listed per mode: the source generators above add it
  1645. // where they emit a call, so a baked context or one with no chunk drops it.
  1646. if (asyncMode === "weak" || asyncMode === "async-weak") {
  1647. set.add(RuntimeGlobals.moduleFactories);
  1648. }
  1649. if (this.getFakeMap(allDeps, chunkGraph) !== 9) {
  1650. set.add(RuntimeGlobals.createFakeNamespaceObject);
  1651. }
  1652. if (
  1653. ImportPhaseUtils.isDefer(this.options.phase || ImportPhase.Evaluation)
  1654. ) {
  1655. set.add(RuntimeGlobals.makeDeferredNamespaceObject);
  1656. }
  1657. }
  1658. return {
  1659. sources,
  1660. runtimeRequirements: set
  1661. };
  1662. }
  1663. /**
  1664. * Returns the estimated size for the requested source type.
  1665. * @param {string=} type the source type for which the size should be estimated
  1666. * @returns {number} the estimated size of the module (must be non-zero)
  1667. */
  1668. size(type) {
  1669. // base penalty
  1670. let size = 160;
  1671. // if we don't have dependencies we stop here.
  1672. for (const dependency of this.dependencies) {
  1673. const element = /** @type {ContextElementDependency} */ (dependency);
  1674. size += 5 + element.userRequest.length;
  1675. }
  1676. return size;
  1677. }
  1678. /**
  1679. * Serializes this instance into the provided serializer context.
  1680. * @param {ObjectSerializerContext} context context
  1681. */
  1682. serialize(context) {
  1683. context.write(this._identifier).write(this._forceBuild);
  1684. super.serialize(context);
  1685. }
  1686. /**
  1687. * Restores this instance from the provided deserializer context.
  1688. * @param {ObjectDeserializerContext} context context
  1689. */
  1690. deserialize(context) {
  1691. this._identifier = context.read();
  1692. const c1 = context.rest;
  1693. this._forceBuild = c1.read();
  1694. super.deserialize(c1.rest);
  1695. }
  1696. }
  1697. makeSerializable(ContextModule, "webpack/lib/ContextModule");
  1698. module.exports = ContextModule;