UNPKG

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