UNPKG

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