25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1192 lines
33 KiB

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