UNPKG

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