Module.js 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const util = require("util");
  7. const ChunkGraph = require("./ChunkGraph");
  8. const DependenciesBlock = require("./DependenciesBlock");
  9. const ModuleGraph = require("./ModuleGraph");
  10. const RuntimeGlobals = require("./RuntimeGlobals");
  11. const { first } = require("./util/SetHelpers");
  12. const { compareChunksById } = require("./util/comparators");
  13. const makeSerializable = require("./util/makeSerializable");
  14. /** @typedef {import("webpack-sources").Source} Source */
  15. /** @typedef {import("../declarations/WebpackOptions").ResolveOptions} ResolveOptions */
  16. /** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
  17. /** @typedef {import("./Chunk")} Chunk */
  18. /** @typedef {import("./ChunkGroup")} ChunkGroup */
  19. /** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */
  20. /** @typedef {import("./Compilation")} Compilation */
  21. /** @typedef {import("./Compilation").AssetInfo} AssetInfo */
  22. /** @typedef {import("./ConcatenationScope")} ConcatenationScope */
  23. /** @typedef {import("./Dependency")} Dependency */
  24. /** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */
  25. /** @typedef {import("./DependencyTemplates")} DependencyTemplates */
  26. /** @typedef {import("./ExportsInfo").UsageStateType} UsageStateType */
  27. /** @typedef {import("./FileSystemInfo")} FileSystemInfo */
  28. /** @typedef {import("./FileSystemInfo").Snapshot} Snapshot */
  29. /** @typedef {import("./ModuleGraphConnection").ConnectionState} ConnectionState */
  30. /** @typedef {import("./ModuleTypeConstants").ModuleTypes} ModuleTypes */
  31. /** @typedef {import("./NormalModuleFactory")} NormalModuleFactory */
  32. /** @typedef {import("./RequestShortener")} RequestShortener */
  33. /** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
  34. /** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
  35. /** @typedef {import("./WebpackError")} WebpackError */
  36. /** @typedef {import("./serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
  37. /** @typedef {import("./serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
  38. /** @typedef {import("./util/Hash")} Hash */
  39. /** @template T @typedef {import("./util/LazySet")<T>} LazySet<T> */
  40. /** @template T @typedef {import("./util/SortableSet")<T>} SortableSet<T> */
  41. /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
  42. /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
  43. /**
  44. * @typedef {Object} SourceContext
  45. * @property {DependencyTemplates} dependencyTemplates the dependency templates
  46. * @property {RuntimeTemplate} runtimeTemplate the runtime template
  47. * @property {ModuleGraph} moduleGraph the module graph
  48. * @property {ChunkGraph} chunkGraph the chunk graph
  49. * @property {RuntimeSpec} runtime the runtimes code should be generated for
  50. * @property {string=} type the type of source that should be generated
  51. */
  52. // TODO webpack 6: compilation will be required in CodeGenerationContext
  53. /**
  54. * @typedef {Object} CodeGenerationContext
  55. * @property {DependencyTemplates} dependencyTemplates the dependency templates
  56. * @property {RuntimeTemplate} runtimeTemplate the runtime template
  57. * @property {ModuleGraph} moduleGraph the module graph
  58. * @property {ChunkGraph} chunkGraph the chunk graph
  59. * @property {RuntimeSpec} runtime the runtime code should be generated for
  60. * @property {RuntimeSpec[]} [runtimes] the runtimes code should be generated for
  61. * @property {ConcatenationScope=} concatenationScope when in concatenated module, information about other concatenated modules
  62. * @property {CodeGenerationResults | undefined} codeGenerationResults code generation results of other modules (need to have a codeGenerationDependency to use that)
  63. * @property {Compilation=} compilation the compilation
  64. * @property {ReadonlySet<string>=} sourceTypes source types
  65. */
  66. /**
  67. * @typedef {Object} ConcatenationBailoutReasonContext
  68. * @property {ModuleGraph} moduleGraph the module graph
  69. * @property {ChunkGraph} chunkGraph the chunk graph
  70. */
  71. /** @typedef {Set<string>} RuntimeRequirements */
  72. /** @typedef {ReadonlySet<string>} ReadOnlyRuntimeRequirements */
  73. /**
  74. * @typedef {Object} CodeGenerationResult
  75. * @property {Map<string, Source>} sources the resulting sources for all source types
  76. * @property {Map<string, any>=} data the resulting data for all source types
  77. * @property {ReadOnlyRuntimeRequirements} runtimeRequirements the runtime requirements
  78. * @property {string=} hash a hash of the code generation result (will be automatically calculated from sources and runtimeRequirements if not provided)
  79. */
  80. /**
  81. * @typedef {Object} LibIdentOptions
  82. * @property {string} context absolute context path to which lib ident is relative to
  83. * @property {Object=} associatedObjectForCache object for caching
  84. */
  85. /**
  86. * @typedef {Object} KnownBuildMeta
  87. * @property {string=} moduleArgument
  88. * @property {string=} exportsArgument
  89. * @property {boolean=} strict
  90. * @property {string=} moduleConcatenationBailout
  91. * @property {("default" | "namespace" | "flagged" | "dynamic")=} exportsType
  92. * @property {(false | "redirect" | "redirect-warn")=} defaultObject
  93. * @property {boolean=} strictHarmonyModule
  94. * @property {boolean=} async
  95. * @property {boolean=} sideEffectFree
  96. */
  97. /**
  98. * @typedef {Object} KnownBuildInfo
  99. * @property {boolean=} cacheable
  100. * @property {boolean=} parsed
  101. * @property {LazySet<string>=} fileDependencies
  102. * @property {LazySet<string>=} contextDependencies
  103. * @property {LazySet<string>=} missingDependencies
  104. * @property {LazySet<string>=} buildDependencies
  105. * @property {(Map<string, string | Set<string>>)=} valueDependencies
  106. * @property {TODO=} hash
  107. * @property {Record<string, Source>=} assets
  108. * @property {Map<string, AssetInfo | undefined>=} assetsInfo
  109. * @property {(Snapshot | null)=} snapshot
  110. */
  111. /**
  112. * @typedef {Object} NeedBuildContext
  113. * @property {Compilation} compilation
  114. * @property {FileSystemInfo} fileSystemInfo
  115. * @property {Map<string, string | Set<string>>} valueCacheVersions
  116. */
  117. /** @typedef {KnownBuildMeta & Record<string, any>} BuildMeta */
  118. /** @typedef {KnownBuildInfo & Record<string, any>} BuildInfo */
  119. /**
  120. * @typedef {Object} FactoryMeta
  121. * @property {boolean=} sideEffectFree
  122. */
  123. /** @typedef {Set<string>} SourceTypes */
  124. /** @typedef {{ factoryMeta: FactoryMeta | undefined, resolveOptions: ResolveOptions | undefined }} UnsafeCacheData */
  125. const EMPTY_RESOLVE_OPTIONS = {};
  126. let debugId = 1000;
  127. const DEFAULT_TYPES_UNKNOWN = new Set(["unknown"]);
  128. const DEFAULT_TYPES_JS = new Set(["javascript"]);
  129. const deprecatedNeedRebuild = util.deprecate(
  130. /**
  131. * @param {Module} module the module
  132. * @param {NeedBuildContext} context context info
  133. * @returns {boolean} true, when rebuild is needed
  134. */
  135. (module, context) => {
  136. return module.needRebuild(
  137. context.fileSystemInfo.getDeprecatedFileTimestamps(),
  138. context.fileSystemInfo.getDeprecatedContextTimestamps()
  139. );
  140. },
  141. "Module.needRebuild is deprecated in favor of Module.needBuild",
  142. "DEP_WEBPACK_MODULE_NEED_REBUILD"
  143. );
  144. /** @typedef {(requestShortener: RequestShortener) => string} OptimizationBailoutFunction */
  145. class Module extends DependenciesBlock {
  146. /**
  147. * @param {ModuleTypes | ""} type the module type, when deserializing the type is not known and is an empty string
  148. * @param {(string | null)=} context an optional context
  149. * @param {(string | null)=} layer an optional layer in which the module is
  150. */
  151. constructor(type, context = null, layer = null) {
  152. super();
  153. /** @type {ModuleTypes} */
  154. this.type = type;
  155. /** @type {string | null} */
  156. this.context = context;
  157. /** @type {string | null} */
  158. this.layer = layer;
  159. /** @type {boolean} */
  160. this.needId = true;
  161. // Unique Id
  162. /** @type {number} */
  163. this.debugId = debugId++;
  164. // Info from Factory
  165. /** @type {ResolveOptions | undefined} */
  166. this.resolveOptions = EMPTY_RESOLVE_OPTIONS;
  167. /** @type {FactoryMeta | undefined} */
  168. this.factoryMeta = undefined;
  169. // TODO refactor this -> options object filled from Factory
  170. // TODO webpack 6: use an enum
  171. /** @type {boolean} */
  172. this.useSourceMap = false;
  173. /** @type {boolean} */
  174. this.useSimpleSourceMap = false;
  175. // Info from Build
  176. /** @type {WebpackError[] | undefined} */
  177. this._warnings = undefined;
  178. /** @type {WebpackError[] | undefined} */
  179. this._errors = undefined;
  180. /** @type {BuildMeta | undefined} */
  181. this.buildMeta = undefined;
  182. /** @type {BuildInfo | undefined} */
  183. this.buildInfo = undefined;
  184. /** @type {Dependency[] | undefined} */
  185. this.presentationalDependencies = undefined;
  186. /** @type {Dependency[] | undefined} */
  187. this.codeGenerationDependencies = undefined;
  188. }
  189. // TODO remove in webpack 6
  190. // BACKWARD-COMPAT START
  191. get id() {
  192. return ChunkGraph.getChunkGraphForModule(
  193. this,
  194. "Module.id",
  195. "DEP_WEBPACK_MODULE_ID"
  196. ).getModuleId(this);
  197. }
  198. set id(value) {
  199. if (value === "") {
  200. this.needId = false;
  201. return;
  202. }
  203. ChunkGraph.getChunkGraphForModule(
  204. this,
  205. "Module.id",
  206. "DEP_WEBPACK_MODULE_ID"
  207. ).setModuleId(this, value);
  208. }
  209. /**
  210. * @returns {string} the hash of the module
  211. */
  212. get hash() {
  213. return ChunkGraph.getChunkGraphForModule(
  214. this,
  215. "Module.hash",
  216. "DEP_WEBPACK_MODULE_HASH"
  217. ).getModuleHash(this, undefined);
  218. }
  219. /**
  220. * @returns {string} the shortened hash of the module
  221. */
  222. get renderedHash() {
  223. return ChunkGraph.getChunkGraphForModule(
  224. this,
  225. "Module.renderedHash",
  226. "DEP_WEBPACK_MODULE_RENDERED_HASH"
  227. ).getRenderedModuleHash(this, undefined);
  228. }
  229. get profile() {
  230. return ModuleGraph.getModuleGraphForModule(
  231. this,
  232. "Module.profile",
  233. "DEP_WEBPACK_MODULE_PROFILE"
  234. ).getProfile(this);
  235. }
  236. set profile(value) {
  237. ModuleGraph.getModuleGraphForModule(
  238. this,
  239. "Module.profile",
  240. "DEP_WEBPACK_MODULE_PROFILE"
  241. ).setProfile(this, value);
  242. }
  243. /**
  244. * @returns {number | null} the pre order index
  245. */
  246. get index() {
  247. return ModuleGraph.getModuleGraphForModule(
  248. this,
  249. "Module.index",
  250. "DEP_WEBPACK_MODULE_INDEX"
  251. ).getPreOrderIndex(this);
  252. }
  253. /**
  254. * @param {number} value the pre order index
  255. */
  256. set index(value) {
  257. ModuleGraph.getModuleGraphForModule(
  258. this,
  259. "Module.index",
  260. "DEP_WEBPACK_MODULE_INDEX"
  261. ).setPreOrderIndex(this, value);
  262. }
  263. /**
  264. * @returns {number | null} the post order index
  265. */
  266. get index2() {
  267. return ModuleGraph.getModuleGraphForModule(
  268. this,
  269. "Module.index2",
  270. "DEP_WEBPACK_MODULE_INDEX2"
  271. ).getPostOrderIndex(this);
  272. }
  273. /**
  274. * @param {number} value the post order index
  275. */
  276. set index2(value) {
  277. ModuleGraph.getModuleGraphForModule(
  278. this,
  279. "Module.index2",
  280. "DEP_WEBPACK_MODULE_INDEX2"
  281. ).setPostOrderIndex(this, value);
  282. }
  283. /**
  284. * @returns {number | null} the depth
  285. */
  286. get depth() {
  287. return ModuleGraph.getModuleGraphForModule(
  288. this,
  289. "Module.depth",
  290. "DEP_WEBPACK_MODULE_DEPTH"
  291. ).getDepth(this);
  292. }
  293. /**
  294. * @param {number} value the depth
  295. */
  296. set depth(value) {
  297. ModuleGraph.getModuleGraphForModule(
  298. this,
  299. "Module.depth",
  300. "DEP_WEBPACK_MODULE_DEPTH"
  301. ).setDepth(this, value);
  302. }
  303. /**
  304. * @returns {Module | null | undefined} issuer
  305. */
  306. get issuer() {
  307. return ModuleGraph.getModuleGraphForModule(
  308. this,
  309. "Module.issuer",
  310. "DEP_WEBPACK_MODULE_ISSUER"
  311. ).getIssuer(this);
  312. }
  313. /**
  314. * @param {Module | null} value issuer
  315. */
  316. set issuer(value) {
  317. ModuleGraph.getModuleGraphForModule(
  318. this,
  319. "Module.issuer",
  320. "DEP_WEBPACK_MODULE_ISSUER"
  321. ).setIssuer(this, value);
  322. }
  323. get usedExports() {
  324. return ModuleGraph.getModuleGraphForModule(
  325. this,
  326. "Module.usedExports",
  327. "DEP_WEBPACK_MODULE_USED_EXPORTS"
  328. ).getUsedExports(this, undefined);
  329. }
  330. /**
  331. * @deprecated
  332. * @returns {(string | OptimizationBailoutFunction)[]} list
  333. */
  334. get optimizationBailout() {
  335. return ModuleGraph.getModuleGraphForModule(
  336. this,
  337. "Module.optimizationBailout",
  338. "DEP_WEBPACK_MODULE_OPTIMIZATION_BAILOUT"
  339. ).getOptimizationBailout(this);
  340. }
  341. get optional() {
  342. return this.isOptional(
  343. ModuleGraph.getModuleGraphForModule(
  344. this,
  345. "Module.optional",
  346. "DEP_WEBPACK_MODULE_OPTIONAL"
  347. )
  348. );
  349. }
  350. /**
  351. * @param {Chunk} chunk the chunk
  352. * @returns {boolean} true, when the module was added
  353. */
  354. addChunk(chunk) {
  355. const chunkGraph = ChunkGraph.getChunkGraphForModule(
  356. this,
  357. "Module.addChunk",
  358. "DEP_WEBPACK_MODULE_ADD_CHUNK"
  359. );
  360. if (chunkGraph.isModuleInChunk(this, chunk)) return false;
  361. chunkGraph.connectChunkAndModule(chunk, this);
  362. return true;
  363. }
  364. /**
  365. * @param {Chunk} chunk the chunk
  366. * @returns {void}
  367. */
  368. removeChunk(chunk) {
  369. return ChunkGraph.getChunkGraphForModule(
  370. this,
  371. "Module.removeChunk",
  372. "DEP_WEBPACK_MODULE_REMOVE_CHUNK"
  373. ).disconnectChunkAndModule(chunk, this);
  374. }
  375. /**
  376. * @param {Chunk} chunk the chunk
  377. * @returns {boolean} true, when the module is in the chunk
  378. */
  379. isInChunk(chunk) {
  380. return ChunkGraph.getChunkGraphForModule(
  381. this,
  382. "Module.isInChunk",
  383. "DEP_WEBPACK_MODULE_IS_IN_CHUNK"
  384. ).isModuleInChunk(this, chunk);
  385. }
  386. isEntryModule() {
  387. return ChunkGraph.getChunkGraphForModule(
  388. this,
  389. "Module.isEntryModule",
  390. "DEP_WEBPACK_MODULE_IS_ENTRY_MODULE"
  391. ).isEntryModule(this);
  392. }
  393. getChunks() {
  394. return ChunkGraph.getChunkGraphForModule(
  395. this,
  396. "Module.getChunks",
  397. "DEP_WEBPACK_MODULE_GET_CHUNKS"
  398. ).getModuleChunks(this);
  399. }
  400. getNumberOfChunks() {
  401. return ChunkGraph.getChunkGraphForModule(
  402. this,
  403. "Module.getNumberOfChunks",
  404. "DEP_WEBPACK_MODULE_GET_NUMBER_OF_CHUNKS"
  405. ).getNumberOfModuleChunks(this);
  406. }
  407. get chunksIterable() {
  408. return ChunkGraph.getChunkGraphForModule(
  409. this,
  410. "Module.chunksIterable",
  411. "DEP_WEBPACK_MODULE_CHUNKS_ITERABLE"
  412. ).getOrderedModuleChunksIterable(this, compareChunksById);
  413. }
  414. /**
  415. * @param {string} exportName a name of an export
  416. * @returns {boolean | null} true, if the export is provided why the module.
  417. * null, if it's unknown.
  418. * false, if it's not provided.
  419. */
  420. isProvided(exportName) {
  421. return ModuleGraph.getModuleGraphForModule(
  422. this,
  423. "Module.usedExports",
  424. "DEP_WEBPACK_MODULE_USED_EXPORTS"
  425. ).isExportProvided(this, exportName);
  426. }
  427. // BACKWARD-COMPAT END
  428. /**
  429. * @returns {string} name of the exports argument
  430. */
  431. get exportsArgument() {
  432. return (this.buildInfo && this.buildInfo.exportsArgument) || "exports";
  433. }
  434. /**
  435. * @returns {string} name of the module argument
  436. */
  437. get moduleArgument() {
  438. return (this.buildInfo && this.buildInfo.moduleArgument) || "module";
  439. }
  440. /**
  441. * @param {ModuleGraph} moduleGraph the module graph
  442. * @param {boolean | undefined} strict the importing module is strict
  443. * @returns {"namespace" | "default-only" | "default-with-named" | "dynamic"} export type
  444. * "namespace": Exports is already a namespace object. namespace = exports.
  445. * "dynamic": Check at runtime if __esModule is set. When set: namespace = { ...exports, default: exports }. When not set: namespace = { default: exports }.
  446. * "default-only": Provide a namespace object with only default export. namespace = { default: exports }
  447. * "default-with-named": Provide a namespace object with named and default export. namespace = { ...exports, default: exports }
  448. */
  449. getExportsType(moduleGraph, strict) {
  450. switch (this.buildMeta && this.buildMeta.exportsType) {
  451. case "flagged":
  452. return strict ? "default-with-named" : "namespace";
  453. case "namespace":
  454. return "namespace";
  455. case "default":
  456. switch (/** @type {BuildMeta} */ (this.buildMeta).defaultObject) {
  457. case "redirect":
  458. return "default-with-named";
  459. case "redirect-warn":
  460. return strict ? "default-only" : "default-with-named";
  461. default:
  462. return "default-only";
  463. }
  464. case "dynamic": {
  465. if (strict) return "default-with-named";
  466. // Try to figure out value of __esModule by following reexports
  467. const handleDefault = () => {
  468. switch (/** @type {BuildMeta} */ (this.buildMeta).defaultObject) {
  469. case "redirect":
  470. case "redirect-warn":
  471. return "default-with-named";
  472. default:
  473. return "default-only";
  474. }
  475. };
  476. const exportInfo = moduleGraph.getReadOnlyExportInfo(
  477. this,
  478. "__esModule"
  479. );
  480. if (exportInfo.provided === false) {
  481. return handleDefault();
  482. }
  483. const target = exportInfo.getTarget(moduleGraph);
  484. if (
  485. !target ||
  486. !target.export ||
  487. target.export.length !== 1 ||
  488. target.export[0] !== "__esModule"
  489. ) {
  490. return "dynamic";
  491. }
  492. switch (
  493. target.module.buildMeta &&
  494. target.module.buildMeta.exportsType
  495. ) {
  496. case "flagged":
  497. case "namespace":
  498. return "namespace";
  499. case "default":
  500. return handleDefault();
  501. default:
  502. return "dynamic";
  503. }
  504. }
  505. default:
  506. return strict ? "default-with-named" : "dynamic";
  507. }
  508. }
  509. /**
  510. * @param {Dependency} presentationalDependency dependency being tied to module.
  511. * This is a Dependency without edge in the module graph. It's only for presentation.
  512. * @returns {void}
  513. */
  514. addPresentationalDependency(presentationalDependency) {
  515. if (this.presentationalDependencies === undefined) {
  516. this.presentationalDependencies = [];
  517. }
  518. this.presentationalDependencies.push(presentationalDependency);
  519. }
  520. /**
  521. * @param {Dependency} codeGenerationDependency dependency being tied to module.
  522. * This is a Dependency where the code generation result of the referenced module is needed during code generation.
  523. * The Dependency should also be added to normal dependencies via addDependency.
  524. * @returns {void}
  525. */
  526. addCodeGenerationDependency(codeGenerationDependency) {
  527. if (this.codeGenerationDependencies === undefined) {
  528. this.codeGenerationDependencies = [];
  529. }
  530. this.codeGenerationDependencies.push(codeGenerationDependency);
  531. }
  532. /**
  533. * Removes all dependencies and blocks
  534. * @returns {void}
  535. */
  536. clearDependenciesAndBlocks() {
  537. if (this.presentationalDependencies !== undefined) {
  538. this.presentationalDependencies.length = 0;
  539. }
  540. if (this.codeGenerationDependencies !== undefined) {
  541. this.codeGenerationDependencies.length = 0;
  542. }
  543. super.clearDependenciesAndBlocks();
  544. }
  545. /**
  546. * @param {WebpackError} warning the warning
  547. * @returns {void}
  548. */
  549. addWarning(warning) {
  550. if (this._warnings === undefined) {
  551. this._warnings = [];
  552. }
  553. this._warnings.push(warning);
  554. }
  555. /**
  556. * @returns {Iterable<WebpackError> | undefined} list of warnings if any
  557. */
  558. getWarnings() {
  559. return this._warnings;
  560. }
  561. /**
  562. * @returns {number} number of warnings
  563. */
  564. getNumberOfWarnings() {
  565. return this._warnings !== undefined ? this._warnings.length : 0;
  566. }
  567. /**
  568. * @param {WebpackError} error the error
  569. * @returns {void}
  570. */
  571. addError(error) {
  572. if (this._errors === undefined) {
  573. this._errors = [];
  574. }
  575. this._errors.push(error);
  576. }
  577. /**
  578. * @returns {Iterable<WebpackError> | undefined} list of errors if any
  579. */
  580. getErrors() {
  581. return this._errors;
  582. }
  583. /**
  584. * @returns {number} number of errors
  585. */
  586. getNumberOfErrors() {
  587. return this._errors !== undefined ? this._errors.length : 0;
  588. }
  589. /**
  590. * removes all warnings and errors
  591. * @returns {void}
  592. */
  593. clearWarningsAndErrors() {
  594. if (this._warnings !== undefined) {
  595. this._warnings.length = 0;
  596. }
  597. if (this._errors !== undefined) {
  598. this._errors.length = 0;
  599. }
  600. }
  601. /**
  602. * @param {ModuleGraph} moduleGraph the module graph
  603. * @returns {boolean} true, if the module is optional
  604. */
  605. isOptional(moduleGraph) {
  606. let hasConnections = false;
  607. for (const r of moduleGraph.getIncomingConnections(this)) {
  608. if (
  609. !r.dependency ||
  610. !r.dependency.optional ||
  611. !r.isTargetActive(undefined)
  612. ) {
  613. return false;
  614. }
  615. hasConnections = true;
  616. }
  617. return hasConnections;
  618. }
  619. /**
  620. * @param {ChunkGraph} chunkGraph the chunk graph
  621. * @param {Chunk} chunk a chunk
  622. * @param {Chunk=} ignoreChunk chunk to be ignored
  623. * @returns {boolean} true, if the module is accessible from "chunk" when ignoring "ignoreChunk"
  624. */
  625. isAccessibleInChunk(chunkGraph, chunk, ignoreChunk) {
  626. // Check if module is accessible in ALL chunk groups
  627. for (const chunkGroup of chunk.groupsIterable) {
  628. if (!this.isAccessibleInChunkGroup(chunkGraph, chunkGroup)) return false;
  629. }
  630. return true;
  631. }
  632. /**
  633. * @param {ChunkGraph} chunkGraph the chunk graph
  634. * @param {ChunkGroup} chunkGroup a chunk group
  635. * @param {Chunk=} ignoreChunk chunk to be ignored
  636. * @returns {boolean} true, if the module is accessible from "chunkGroup" when ignoring "ignoreChunk"
  637. */
  638. isAccessibleInChunkGroup(chunkGraph, chunkGroup, ignoreChunk) {
  639. const queue = new Set([chunkGroup]);
  640. // Check if module is accessible from all items of the queue
  641. queueFor: for (const cg of queue) {
  642. // 1. If module is in one of the chunks of the group we can continue checking the next items
  643. // because it's accessible.
  644. for (const chunk of cg.chunks) {
  645. if (chunk !== ignoreChunk && chunkGraph.isModuleInChunk(this, chunk))
  646. continue queueFor;
  647. }
  648. // 2. If the chunk group is initial, we can break here because it's not accessible.
  649. if (chunkGroup.isInitial()) return false;
  650. // 3. Enqueue all parents because it must be accessible from ALL parents
  651. for (const parent of chunkGroup.parentsIterable) queue.add(parent);
  652. }
  653. // When we processed through the whole list and we didn't bailout, the module is accessible
  654. return true;
  655. }
  656. /**
  657. * @param {Chunk} chunk a chunk
  658. * @param {ModuleGraph} moduleGraph the module graph
  659. * @param {ChunkGraph} chunkGraph the chunk graph
  660. * @returns {boolean} true, if the module has any reason why "chunk" should be included
  661. */
  662. hasReasonForChunk(chunk, moduleGraph, chunkGraph) {
  663. // check for each reason if we need the chunk
  664. for (const [
  665. fromModule,
  666. connections
  667. ] of moduleGraph.getIncomingConnectionsByOriginModule(this)) {
  668. if (!connections.some(c => c.isTargetActive(chunk.runtime))) continue;
  669. for (const originChunk of chunkGraph.getModuleChunksIterable(
  670. /** @type {Module} */ (fromModule)
  671. )) {
  672. // return true if module this is not reachable from originChunk when ignoring chunk
  673. if (!this.isAccessibleInChunk(chunkGraph, originChunk, chunk))
  674. return true;
  675. }
  676. }
  677. return false;
  678. }
  679. /**
  680. * @param {ModuleGraph} moduleGraph the module graph
  681. * @param {RuntimeSpec} runtime the runtime
  682. * @returns {boolean} true if at least one other module depends on this module
  683. */
  684. hasReasons(moduleGraph, runtime) {
  685. for (const c of moduleGraph.getIncomingConnections(this)) {
  686. if (c.isTargetActive(runtime)) return true;
  687. }
  688. return false;
  689. }
  690. /**
  691. * @returns {string} for debugging
  692. */
  693. toString() {
  694. return `Module[${this.debugId}: ${this.identifier()}]`;
  695. }
  696. /**
  697. * @param {NeedBuildContext} context context info
  698. * @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
  699. * @returns {void}
  700. */
  701. needBuild(context, callback) {
  702. callback(
  703. null,
  704. !this.buildMeta ||
  705. this.needRebuild === Module.prototype.needRebuild ||
  706. deprecatedNeedRebuild(this, context)
  707. );
  708. }
  709. /**
  710. * @deprecated Use needBuild instead
  711. * @param {Map<string, number|null>} fileTimestamps timestamps of files
  712. * @param {Map<string, number|null>} contextTimestamps timestamps of directories
  713. * @returns {boolean} true, if the module needs a rebuild
  714. */
  715. needRebuild(fileTimestamps, contextTimestamps) {
  716. return true;
  717. }
  718. /**
  719. * @param {Hash} hash the hash used to track dependencies
  720. * @param {UpdateHashContext} context context
  721. * @returns {void}
  722. */
  723. updateHash(
  724. hash,
  725. context = {
  726. chunkGraph: ChunkGraph.getChunkGraphForModule(
  727. this,
  728. "Module.updateHash",
  729. "DEP_WEBPACK_MODULE_UPDATE_HASH"
  730. ),
  731. runtime: undefined
  732. }
  733. ) {
  734. const { chunkGraph, runtime } = context;
  735. hash.update(chunkGraph.getModuleGraphHash(this, runtime));
  736. if (this.presentationalDependencies !== undefined) {
  737. for (const dep of this.presentationalDependencies) {
  738. dep.updateHash(hash, context);
  739. }
  740. }
  741. super.updateHash(hash, context);
  742. }
  743. /**
  744. * @returns {void}
  745. */
  746. invalidateBuild() {
  747. // should be overridden to support this feature
  748. }
  749. /* istanbul ignore next */
  750. /**
  751. * @abstract
  752. * @returns {string} a unique identifier of the module
  753. */
  754. identifier() {
  755. const AbstractMethodError = require("./AbstractMethodError");
  756. throw new AbstractMethodError();
  757. }
  758. /* istanbul ignore next */
  759. /**
  760. * @abstract
  761. * @param {RequestShortener} requestShortener the request shortener
  762. * @returns {string} a user readable identifier of the module
  763. */
  764. readableIdentifier(requestShortener) {
  765. const AbstractMethodError = require("./AbstractMethodError");
  766. throw new AbstractMethodError();
  767. }
  768. /* istanbul ignore next */
  769. /**
  770. * @abstract
  771. * @param {WebpackOptions} options webpack options
  772. * @param {Compilation} compilation the compilation
  773. * @param {ResolverWithOptions} resolver the resolver
  774. * @param {InputFileSystem} fs the file system
  775. * @param {function(WebpackError=): void} callback callback function
  776. * @returns {void}
  777. */
  778. build(options, compilation, resolver, fs, callback) {
  779. const AbstractMethodError = require("./AbstractMethodError");
  780. throw new AbstractMethodError();
  781. }
  782. /**
  783. * @abstract
  784. * @returns {SourceTypes} types available (do not mutate)
  785. */
  786. getSourceTypes() {
  787. // Better override this method to return the correct types
  788. if (this.source === Module.prototype.source) {
  789. return DEFAULT_TYPES_UNKNOWN;
  790. } else {
  791. return DEFAULT_TYPES_JS;
  792. }
  793. }
  794. /**
  795. * @abstract
  796. * @deprecated Use codeGeneration() instead
  797. * @param {DependencyTemplates} dependencyTemplates the dependency templates
  798. * @param {RuntimeTemplate} runtimeTemplate the runtime template
  799. * @param {string=} type the type of source that should be generated
  800. * @returns {Source} generated source
  801. */
  802. source(dependencyTemplates, runtimeTemplate, type = "javascript") {
  803. if (this.codeGeneration === Module.prototype.codeGeneration) {
  804. const AbstractMethodError = require("./AbstractMethodError");
  805. throw new AbstractMethodError();
  806. }
  807. const chunkGraph = ChunkGraph.getChunkGraphForModule(
  808. this,
  809. "Module.source() is deprecated. Use Compilation.codeGenerationResults.getSource(module, runtime, type) instead",
  810. "DEP_WEBPACK_MODULE_SOURCE"
  811. );
  812. /** @type {CodeGenerationContext} */
  813. const codeGenContext = {
  814. dependencyTemplates,
  815. runtimeTemplate,
  816. moduleGraph: chunkGraph.moduleGraph,
  817. chunkGraph,
  818. runtime: undefined,
  819. codeGenerationResults: undefined
  820. };
  821. const sources = this.codeGeneration(codeGenContext).sources;
  822. return type ? sources.get(type) : sources.get(first(this.getSourceTypes()));
  823. }
  824. /* istanbul ignore next */
  825. /**
  826. * @abstract
  827. * @param {string=} type the source type for which the size should be estimated
  828. * @returns {number} the estimated size of the module (must be non-zero)
  829. */
  830. size(type) {
  831. const AbstractMethodError = require("./AbstractMethodError");
  832. throw new AbstractMethodError();
  833. }
  834. /**
  835. * @param {LibIdentOptions} options options
  836. * @returns {string | null} an identifier for library inclusion
  837. */
  838. libIdent(options) {
  839. return null;
  840. }
  841. /**
  842. * @returns {string | null} absolute path which should be used for condition matching (usually the resource path)
  843. */
  844. nameForCondition() {
  845. return null;
  846. }
  847. /**
  848. * @param {ConcatenationBailoutReasonContext} context context
  849. * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated
  850. */
  851. getConcatenationBailoutReason(context) {
  852. return `Module Concatenation is not implemented for ${this.constructor.name}`;
  853. }
  854. /**
  855. * @param {ModuleGraph} moduleGraph the module graph
  856. * @returns {ConnectionState} how this module should be connected to referencing modules when consumed for side-effects only
  857. */
  858. getSideEffectsConnectionState(moduleGraph) {
  859. return true;
  860. }
  861. /**
  862. * @param {CodeGenerationContext} context context for code generation
  863. * @returns {CodeGenerationResult} result
  864. */
  865. codeGeneration(context) {
  866. // Best override this method
  867. const sources = new Map();
  868. for (const type of this.getSourceTypes()) {
  869. if (type !== "unknown") {
  870. sources.set(
  871. type,
  872. this.source(
  873. context.dependencyTemplates,
  874. context.runtimeTemplate,
  875. type
  876. )
  877. );
  878. }
  879. }
  880. return {
  881. sources,
  882. runtimeRequirements: new Set([
  883. RuntimeGlobals.module,
  884. RuntimeGlobals.exports,
  885. RuntimeGlobals.require
  886. ])
  887. };
  888. }
  889. /**
  890. * @param {Chunk} chunk the chunk which condition should be checked
  891. * @param {Compilation} compilation the compilation
  892. * @returns {boolean} true, if the chunk is ok for the module
  893. */
  894. chunkCondition(chunk, compilation) {
  895. return true;
  896. }
  897. hasChunkCondition() {
  898. return this.chunkCondition !== Module.prototype.chunkCondition;
  899. }
  900. /**
  901. * Assuming this module is in the cache. Update the (cached) module with
  902. * the fresh module from the factory. Usually updates internal references
  903. * and properties.
  904. * @param {Module} module fresh module
  905. * @returns {void}
  906. */
  907. updateCacheModule(module) {
  908. this.type = module.type;
  909. this.layer = module.layer;
  910. this.context = module.context;
  911. this.factoryMeta = module.factoryMeta;
  912. this.resolveOptions = module.resolveOptions;
  913. }
  914. /**
  915. * Module should be unsafe cached. Get data that's needed for that.
  916. * This data will be passed to restoreFromUnsafeCache later.
  917. * @returns {UnsafeCacheData} cached data
  918. */
  919. getUnsafeCacheData() {
  920. return {
  921. factoryMeta: this.factoryMeta,
  922. resolveOptions: this.resolveOptions
  923. };
  924. }
  925. /**
  926. * restore unsafe cache data
  927. * @param {object} unsafeCacheData data from getUnsafeCacheData
  928. * @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching
  929. */
  930. _restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) {
  931. this.factoryMeta = unsafeCacheData.factoryMeta;
  932. this.resolveOptions = unsafeCacheData.resolveOptions;
  933. }
  934. /**
  935. * Assuming this module is in the cache. Remove internal references to allow freeing some memory.
  936. */
  937. cleanupForCache() {
  938. this.factoryMeta = undefined;
  939. this.resolveOptions = undefined;
  940. }
  941. /**
  942. * @returns {Source | null} the original source for the module before webpack transformation
  943. */
  944. originalSource() {
  945. return null;
  946. }
  947. /**
  948. * @param {LazySet<string>} fileDependencies set where file dependencies are added to
  949. * @param {LazySet<string>} contextDependencies set where context dependencies are added to
  950. * @param {LazySet<string>} missingDependencies set where missing dependencies are added to
  951. * @param {LazySet<string>} buildDependencies set where build dependencies are added to
  952. */
  953. addCacheDependencies(
  954. fileDependencies,
  955. contextDependencies,
  956. missingDependencies,
  957. buildDependencies
  958. ) {}
  959. /**
  960. * @param {ObjectSerializerContext} context context
  961. */
  962. serialize(context) {
  963. const { write } = context;
  964. write(this.type);
  965. write(this.layer);
  966. write(this.context);
  967. write(this.resolveOptions);
  968. write(this.factoryMeta);
  969. write(this.useSourceMap);
  970. write(this.useSimpleSourceMap);
  971. write(
  972. this._warnings !== undefined && this._warnings.length === 0
  973. ? undefined
  974. : this._warnings
  975. );
  976. write(
  977. this._errors !== undefined && this._errors.length === 0
  978. ? undefined
  979. : this._errors
  980. );
  981. write(this.buildMeta);
  982. write(this.buildInfo);
  983. write(this.presentationalDependencies);
  984. write(this.codeGenerationDependencies);
  985. super.serialize(context);
  986. }
  987. /**
  988. * @param {ObjectDeserializerContext} context context
  989. */
  990. deserialize(context) {
  991. const { read } = context;
  992. this.type = read();
  993. this.layer = read();
  994. this.context = read();
  995. this.resolveOptions = read();
  996. this.factoryMeta = read();
  997. this.useSourceMap = read();
  998. this.useSimpleSourceMap = read();
  999. this._warnings = read();
  1000. this._errors = read();
  1001. this.buildMeta = read();
  1002. this.buildInfo = read();
  1003. this.presentationalDependencies = read();
  1004. this.codeGenerationDependencies = read();
  1005. super.deserialize(context);
  1006. }
  1007. }
  1008. makeSerializable(Module, "webpack/lib/Module");
  1009. // TODO remove in webpack 6
  1010. Object.defineProperty(Module.prototype, "hasEqualsChunks", {
  1011. get() {
  1012. throw new Error(
  1013. "Module.hasEqualsChunks was renamed (use hasEqualChunks instead)"
  1014. );
  1015. }
  1016. });
  1017. // TODO remove in webpack 6
  1018. Object.defineProperty(Module.prototype, "isUsed", {
  1019. get() {
  1020. throw new Error(
  1021. "Module.isUsed was renamed (use getUsedName, isExportUsed or isModuleUsed instead)"
  1022. );
  1023. }
  1024. });
  1025. // TODO remove in webpack 6
  1026. Object.defineProperty(Module.prototype, "errors", {
  1027. get: util.deprecate(
  1028. /**
  1029. * @this {Module}
  1030. * @returns {WebpackError[]} array
  1031. */
  1032. function () {
  1033. if (this._errors === undefined) {
  1034. this._errors = [];
  1035. }
  1036. return this._errors;
  1037. },
  1038. "Module.errors was removed (use getErrors instead)",
  1039. "DEP_WEBPACK_MODULE_ERRORS"
  1040. )
  1041. });
  1042. // TODO remove in webpack 6
  1043. Object.defineProperty(Module.prototype, "warnings", {
  1044. get: util.deprecate(
  1045. /**
  1046. * @this {Module}
  1047. * @returns {WebpackError[]} array
  1048. */
  1049. function () {
  1050. if (this._warnings === undefined) {
  1051. this._warnings = [];
  1052. }
  1053. return this._warnings;
  1054. },
  1055. "Module.warnings was removed (use getWarnings instead)",
  1056. "DEP_WEBPACK_MODULE_WARNINGS"
  1057. )
  1058. });
  1059. // TODO remove in webpack 6
  1060. Object.defineProperty(Module.prototype, "used", {
  1061. get() {
  1062. throw new Error(
  1063. "Module.used was refactored (use ModuleGraph.getUsedExports instead)"
  1064. );
  1065. },
  1066. set(value) {
  1067. throw new Error(
  1068. "Module.used was refactored (use ModuleGraph.setUsedExports instead)"
  1069. );
  1070. }
  1071. });
  1072. module.exports = Module;