UNPKG

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