source: imaps-frontend/node_modules/webpack/lib/NormalModule.js

main
Last change on this file was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 3 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 49.0 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const parseJson = require("json-parse-even-better-errors");
9const { getContext, runLoaders } = require("loader-runner");
10const querystring = require("querystring");
11const { HookMap, SyncHook, AsyncSeriesBailHook } = require("tapable");
12const {
13 CachedSource,
14 OriginalSource,
15 RawSource,
16 SourceMapSource
17} = require("webpack-sources");
18const Compilation = require("./Compilation");
19const HookWebpackError = require("./HookWebpackError");
20const Module = require("./Module");
21const ModuleBuildError = require("./ModuleBuildError");
22const ModuleError = require("./ModuleError");
23const ModuleGraphConnection = require("./ModuleGraphConnection");
24const ModuleParseError = require("./ModuleParseError");
25const { JAVASCRIPT_MODULE_TYPE_AUTO } = require("./ModuleTypeConstants");
26const ModuleWarning = require("./ModuleWarning");
27const RuntimeGlobals = require("./RuntimeGlobals");
28const UnhandledSchemeError = require("./UnhandledSchemeError");
29const WebpackError = require("./WebpackError");
30const formatLocation = require("./formatLocation");
31const LazySet = require("./util/LazySet");
32const { isSubset } = require("./util/SetHelpers");
33const { getScheme } = require("./util/URLAbsoluteSpecifier");
34const {
35 compareLocations,
36 concatComparators,
37 compareSelect,
38 keepOriginalOrder
39} = require("./util/comparators");
40const createHash = require("./util/createHash");
41const { createFakeHook } = require("./util/deprecation");
42const { join } = require("./util/fs");
43const {
44 contextify,
45 absolutify,
46 makePathsRelative
47} = require("./util/identifier");
48const makeSerializable = require("./util/makeSerializable");
49const memoize = require("./util/memoize");
50
51/** @typedef {import("webpack-sources").Source} Source */
52/** @typedef {import("../declarations/WebpackOptions").Mode} Mode */
53/** @typedef {import("../declarations/WebpackOptions").ResolveOptions} ResolveOptions */
54/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
55/** @typedef {import("./ChunkGraph")} ChunkGraph */
56/** @typedef {import("./Compiler")} Compiler */
57/** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */
58/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
59/** @typedef {import("./Generator")} Generator */
60/** @typedef {import("./Module").BuildInfo} BuildInfo */
61/** @typedef {import("./Module").BuildMeta} BuildMeta */
62/** @typedef {import("./Module").CodeGenerationContext} CodeGenerationContext */
63/** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */
64/** @typedef {import("./Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */
65/** @typedef {import("./Module").KnownBuildInfo} KnownBuildInfo */
66/** @typedef {import("./Module").LibIdentOptions} LibIdentOptions */
67/** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */
68/** @typedef {import("./Generator").SourceTypes} SourceTypes */
69/** @typedef {import("./Module").UnsafeCacheData} UnsafeCacheData */
70/** @typedef {import("./ModuleGraph")} ModuleGraph */
71/** @typedef {import("./ModuleGraphConnection").ConnectionState} ConnectionState */
72/** @typedef {import("./ModuleTypeConstants").JavaScriptModuleTypes} JavaScriptModuleTypes */
73/** @typedef {import("./NormalModuleFactory")} NormalModuleFactory */
74/** @typedef {import("./NormalModuleFactory").ResourceDataWithData} ResourceDataWithData */
75/** @typedef {import("./Parser")} Parser */
76/** @typedef {import("./RequestShortener")} RequestShortener */
77/** @typedef {import("./ResolverFactory").ResolveContext} ResolveContext */
78/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
79/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
80/** @typedef {import("./logging/Logger").Logger} WebpackLogger */
81/** @typedef {import("./serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
82/** @typedef {import("./serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
83/** @typedef {import("./util/Hash")} Hash */
84/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
85/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
86/** @typedef {import("./util/createHash").Algorithm} Algorithm */
87/**
88 * @template T
89 * @typedef {import("./util/deprecation").FakeHook<T>} FakeHook
90 */
91
92/** @typedef {{[k: string]: any}} ParserOptions */
93/** @typedef {{[k: string]: any}} GeneratorOptions */
94
95/** @typedef {UnsafeCacheData & { parser: undefined | Parser, parserOptions: undefined | ParserOptions, generator: undefined | Generator, generatorOptions: undefined | GeneratorOptions }} NormalModuleUnsafeCacheData */
96
97/**
98 * @template T
99 * @typedef {import("../declarations/LoaderContext").LoaderContext<T>} LoaderContext
100 */
101
102/**
103 * @template T
104 * @typedef {import("../declarations/LoaderContext").NormalModuleLoaderContext<T>} NormalModuleLoaderContext
105 */
106
107/**
108 * @typedef {object} SourceMap
109 * @property {number} version
110 * @property {string[]} sources
111 * @property {string} mappings
112 * @property {string=} file
113 * @property {string=} sourceRoot
114 * @property {string[]=} sourcesContent
115 * @property {string[]=} names
116 * @property {string=} debugId
117 */
118
119const getInvalidDependenciesModuleWarning = memoize(() =>
120 require("./InvalidDependenciesModuleWarning")
121);
122const getValidate = memoize(() => require("schema-utils").validate);
123
124const ABSOLUTE_PATH_REGEX = /^([a-zA-Z]:\\|\\\\|\/)/;
125
126/**
127 * @typedef {object} LoaderItem
128 * @property {string} loader
129 * @property {any} options
130 * @property {string?} ident
131 * @property {string?} type
132 */
133
134/**
135 * @param {string} context absolute context path
136 * @param {string} source a source path
137 * @param {object=} associatedObjectForCache an object to which the cache will be attached
138 * @returns {string} new source path
139 */
140const contextifySourceUrl = (context, source, associatedObjectForCache) => {
141 if (source.startsWith("webpack://")) return source;
142 return `webpack://${makePathsRelative(
143 context,
144 source,
145 associatedObjectForCache
146 )}`;
147};
148
149/**
150 * @param {string} context absolute context path
151 * @param {SourceMap} sourceMap a source map
152 * @param {object=} associatedObjectForCache an object to which the cache will be attached
153 * @returns {SourceMap} new source map
154 */
155const contextifySourceMap = (context, sourceMap, associatedObjectForCache) => {
156 if (!Array.isArray(sourceMap.sources)) return sourceMap;
157 const { sourceRoot } = sourceMap;
158 /** @type {function(string): string} */
159 const mapper = !sourceRoot
160 ? source => source
161 : sourceRoot.endsWith("/")
162 ? source =>
163 source.startsWith("/")
164 ? `${sourceRoot.slice(0, -1)}${source}`
165 : `${sourceRoot}${source}`
166 : source =>
167 source.startsWith("/")
168 ? `${sourceRoot}${source}`
169 : `${sourceRoot}/${source}`;
170 const newSources = sourceMap.sources.map(source =>
171 contextifySourceUrl(context, mapper(source), associatedObjectForCache)
172 );
173 return {
174 ...sourceMap,
175 file: "x",
176 sourceRoot: undefined,
177 sources: newSources
178 };
179};
180
181/**
182 * @param {string | Buffer} input the input
183 * @returns {string} the converted string
184 */
185const asString = input => {
186 if (Buffer.isBuffer(input)) {
187 return input.toString("utf-8");
188 }
189 return input;
190};
191
192/**
193 * @param {string | Buffer} input the input
194 * @returns {Buffer} the converted buffer
195 */
196const asBuffer = input => {
197 if (!Buffer.isBuffer(input)) {
198 return Buffer.from(input, "utf-8");
199 }
200 return input;
201};
202
203class NonErrorEmittedError extends WebpackError {
204 /**
205 * @param {any} error value which is not an instance of Error
206 */
207 constructor(error) {
208 super();
209
210 this.name = "NonErrorEmittedError";
211 this.message = `(Emitted value instead of an instance of Error) ${error}`;
212 }
213}
214
215makeSerializable(
216 NonErrorEmittedError,
217 "webpack/lib/NormalModule",
218 "NonErrorEmittedError"
219);
220
221/**
222 * @typedef {object} NormalModuleCompilationHooks
223 * @property {SyncHook<[LoaderContext<any>, NormalModule]>} loader
224 * @property {SyncHook<[LoaderItem[], NormalModule, LoaderContext<any>]>} beforeLoaders
225 * @property {SyncHook<[NormalModule]>} beforeParse
226 * @property {SyncHook<[NormalModule]>} beforeSnapshot
227 * @property {HookMap<FakeHook<AsyncSeriesBailHook<[string, NormalModule], string | Buffer | null>>>} readResourceForScheme
228 * @property {HookMap<AsyncSeriesBailHook<[LoaderContext<any>], string | Buffer | null>>} readResource
229 * @property {AsyncSeriesBailHook<[NormalModule, NeedBuildContext], boolean>} needBuild
230 */
231
232/**
233 * @typedef {object} NormalModuleCreateData
234 * @property {string=} layer an optional layer in which the module is
235 * @property {JavaScriptModuleTypes | ""} type module type. When deserializing, this is set to an empty string "".
236 * @property {string} request request string
237 * @property {string} userRequest request intended by user (without loaders from config)
238 * @property {string} rawRequest request without resolving
239 * @property {LoaderItem[]} loaders list of loaders
240 * @property {string} resource path + query of the real resource
241 * @property {Record<string, any>=} resourceResolveData resource resolve data
242 * @property {string} context context directory for resolving
243 * @property {string=} matchResource path + query of the matched resource (virtual)
244 * @property {Parser} parser the parser used
245 * @property {ParserOptions=} parserOptions the options of the parser used
246 * @property {Generator} generator the generator used
247 * @property {GeneratorOptions=} generatorOptions the options of the generator used
248 * @property {ResolveOptions=} resolveOptions options used for resolving requests from this module
249 */
250
251/** @type {WeakMap<Compilation, NormalModuleCompilationHooks>} */
252const compilationHooksMap = new WeakMap();
253
254class NormalModule extends Module {
255 /**
256 * @param {Compilation} compilation the compilation
257 * @returns {NormalModuleCompilationHooks} the attached hooks
258 */
259 static getCompilationHooks(compilation) {
260 if (!(compilation instanceof Compilation)) {
261 throw new TypeError(
262 "The 'compilation' argument must be an instance of Compilation"
263 );
264 }
265 let hooks = compilationHooksMap.get(compilation);
266 if (hooks === undefined) {
267 hooks = {
268 loader: new SyncHook(["loaderContext", "module"]),
269 beforeLoaders: new SyncHook(["loaders", "module", "loaderContext"]),
270 beforeParse: new SyncHook(["module"]),
271 beforeSnapshot: new SyncHook(["module"]),
272 // TODO webpack 6 deprecate
273 readResourceForScheme: new HookMap(scheme => {
274 const hook =
275 /** @type {NormalModuleCompilationHooks} */
276 (hooks).readResource.for(scheme);
277 return createFakeHook(
278 /** @type {AsyncSeriesBailHook<[string, NormalModule], string | Buffer | null>} */ ({
279 tap: (options, fn) =>
280 hook.tap(options, loaderContext =>
281 fn(
282 loaderContext.resource,
283 /** @type {NormalModule} */ (loaderContext._module)
284 )
285 ),
286 tapAsync: (options, fn) =>
287 hook.tapAsync(options, (loaderContext, callback) =>
288 fn(
289 loaderContext.resource,
290 /** @type {NormalModule} */ (loaderContext._module),
291 callback
292 )
293 ),
294 tapPromise: (options, fn) =>
295 hook.tapPromise(options, loaderContext =>
296 fn(
297 loaderContext.resource,
298 /** @type {NormalModule} */ (loaderContext._module)
299 )
300 )
301 })
302 );
303 }),
304 readResource: new HookMap(
305 () => new AsyncSeriesBailHook(["loaderContext"])
306 ),
307 needBuild: new AsyncSeriesBailHook(["module", "context"])
308 };
309 compilationHooksMap.set(
310 compilation,
311 /** @type {NormalModuleCompilationHooks} */ (hooks)
312 );
313 }
314 return /** @type {NormalModuleCompilationHooks} */ (hooks);
315 }
316
317 /**
318 * @param {NormalModuleCreateData} options options object
319 */
320 constructor({
321 layer,
322 type,
323 request,
324 userRequest,
325 rawRequest,
326 loaders,
327 resource,
328 resourceResolveData,
329 context,
330 matchResource,
331 parser,
332 parserOptions,
333 generator,
334 generatorOptions,
335 resolveOptions
336 }) {
337 super(type, context || getContext(resource), layer);
338
339 // Info from Factory
340 /** @type {string} */
341 this.request = request;
342 /** @type {string} */
343 this.userRequest = userRequest;
344 /** @type {string} */
345 this.rawRequest = rawRequest;
346 /** @type {boolean} */
347 this.binary = /^(asset|webassembly)\b/.test(type);
348 /** @type {undefined | Parser} */
349 this.parser = parser;
350 /** @type {undefined | ParserOptions} */
351 this.parserOptions = parserOptions;
352 /** @type {undefined | Generator} */
353 this.generator = generator;
354 /** @type {undefined | GeneratorOptions} */
355 this.generatorOptions = generatorOptions;
356 /** @type {string} */
357 this.resource = resource;
358 this.resourceResolveData = resourceResolveData;
359 /** @type {string | undefined} */
360 this.matchResource = matchResource;
361 /** @type {LoaderItem[]} */
362 this.loaders = loaders;
363 if (resolveOptions !== undefined) {
364 // already declared in super class
365 this.resolveOptions = resolveOptions;
366 }
367
368 // Info from Build
369 /** @type {WebpackError | null} */
370 this.error = null;
371 /**
372 * @private
373 * @type {Source | null}
374 */
375 this._source = null;
376 /**
377 * @private
378 * @type {Map<string | undefined, number> | undefined}
379 */
380 this._sourceSizes = undefined;
381 /**
382 * @private
383 * @type {undefined | SourceTypes}
384 */
385 this._sourceTypes = undefined;
386
387 // Cache
388 this._lastSuccessfulBuildMeta = {};
389 this._forceBuild = true;
390 this._isEvaluatingSideEffects = false;
391 /** @type {WeakSet<ModuleGraph> | undefined} */
392 this._addedSideEffectsBailout = undefined;
393 /** @type {Map<string, any>} */
394 this._codeGeneratorData = new Map();
395 }
396
397 /**
398 * @returns {string} a unique identifier of the module
399 */
400 identifier() {
401 if (this.layer === null) {
402 if (this.type === JAVASCRIPT_MODULE_TYPE_AUTO) {
403 return this.request;
404 }
405 return `${this.type}|${this.request}`;
406 }
407 return `${this.type}|${this.request}|${this.layer}`;
408 }
409
410 /**
411 * @param {RequestShortener} requestShortener the request shortener
412 * @returns {string} a user readable identifier of the module
413 */
414 readableIdentifier(requestShortener) {
415 return /** @type {string} */ (requestShortener.shorten(this.userRequest));
416 }
417
418 /**
419 * @param {LibIdentOptions} options options
420 * @returns {string | null} an identifier for library inclusion
421 */
422 libIdent(options) {
423 let ident = contextify(
424 options.context,
425 this.userRequest,
426 options.associatedObjectForCache
427 );
428 if (this.layer) ident = `(${this.layer})/${ident}`;
429 return ident;
430 }
431
432 /**
433 * @returns {string | null} absolute path which should be used for condition matching (usually the resource path)
434 */
435 nameForCondition() {
436 const resource = this.matchResource || this.resource;
437 const idx = resource.indexOf("?");
438 if (idx >= 0) return resource.slice(0, idx);
439 return resource;
440 }
441
442 /**
443 * Assuming this module is in the cache. Update the (cached) module with
444 * the fresh module from the factory. Usually updates internal references
445 * and properties.
446 * @param {Module} module fresh module
447 * @returns {void}
448 */
449 updateCacheModule(module) {
450 super.updateCacheModule(module);
451 const m = /** @type {NormalModule} */ (module);
452 this.binary = m.binary;
453 this.request = m.request;
454 this.userRequest = m.userRequest;
455 this.rawRequest = m.rawRequest;
456 this.parser = m.parser;
457 this.parserOptions = m.parserOptions;
458 this.generator = m.generator;
459 this.generatorOptions = m.generatorOptions;
460 this.resource = m.resource;
461 this.resourceResolveData = m.resourceResolveData;
462 this.context = m.context;
463 this.matchResource = m.matchResource;
464 this.loaders = m.loaders;
465 }
466
467 /**
468 * Assuming this module is in the cache. Remove internal references to allow freeing some memory.
469 */
470 cleanupForCache() {
471 // Make sure to cache types and sizes before cleanup when this module has been built
472 // They are accessed by the stats and we don't want them to crash after cleanup
473 // TODO reconsider this for webpack 6
474 if (this.buildInfo) {
475 if (this._sourceTypes === undefined) this.getSourceTypes();
476 for (const type of /** @type {SourceTypes} */ (this._sourceTypes)) {
477 this.size(type);
478 }
479 }
480 super.cleanupForCache();
481 this.parser = undefined;
482 this.parserOptions = undefined;
483 this.generator = undefined;
484 this.generatorOptions = undefined;
485 }
486
487 /**
488 * Module should be unsafe cached. Get data that's needed for that.
489 * This data will be passed to restoreFromUnsafeCache later.
490 * @returns {UnsafeCacheData} cached data
491 */
492 getUnsafeCacheData() {
493 const data =
494 /** @type {NormalModuleUnsafeCacheData} */
495 (super.getUnsafeCacheData());
496 data.parserOptions = this.parserOptions;
497 data.generatorOptions = this.generatorOptions;
498 return data;
499 }
500
501 /**
502 * restore unsafe cache data
503 * @param {NormalModuleUnsafeCacheData} unsafeCacheData data from getUnsafeCacheData
504 * @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching
505 */
506 restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) {
507 this._restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory);
508 }
509
510 /**
511 * restore unsafe cache data
512 * @param {object} unsafeCacheData data from getUnsafeCacheData
513 * @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching
514 */
515 _restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) {
516 super._restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory);
517 this.parserOptions = unsafeCacheData.parserOptions;
518 this.parser = normalModuleFactory.getParser(this.type, this.parserOptions);
519 this.generatorOptions = unsafeCacheData.generatorOptions;
520 this.generator = normalModuleFactory.getGenerator(
521 this.type,
522 this.generatorOptions
523 );
524 // we assume the generator behaves identically and keep cached sourceTypes/Sizes
525 }
526
527 /**
528 * @param {string} context the compilation context
529 * @param {string} name the asset name
530 * @param {string | Buffer} content the content
531 * @param {(string | SourceMap)=} sourceMap an optional source map
532 * @param {object=} associatedObjectForCache object for caching
533 * @returns {Source} the created source
534 */
535 createSourceForAsset(
536 context,
537 name,
538 content,
539 sourceMap,
540 associatedObjectForCache
541 ) {
542 if (sourceMap) {
543 if (
544 typeof sourceMap === "string" &&
545 (this.useSourceMap || this.useSimpleSourceMap)
546 ) {
547 return new OriginalSource(
548 content,
549 contextifySourceUrl(context, sourceMap, associatedObjectForCache)
550 );
551 }
552
553 if (this.useSourceMap) {
554 return new SourceMapSource(
555 content,
556 name,
557 contextifySourceMap(
558 context,
559 /** @type {SourceMap} */ (sourceMap),
560 associatedObjectForCache
561 )
562 );
563 }
564 }
565
566 return new RawSource(content);
567 }
568
569 /**
570 * @private
571 * @template T
572 * @param {ResolverWithOptions} resolver a resolver
573 * @param {WebpackOptions} options webpack options
574 * @param {Compilation} compilation the compilation
575 * @param {InputFileSystem} fs file system from reading
576 * @param {NormalModuleCompilationHooks} hooks the hooks
577 * @returns {import("../declarations/LoaderContext").NormalModuleLoaderContext<T>} loader context
578 */
579 _createLoaderContext(resolver, options, compilation, fs, hooks) {
580 const { requestShortener } = compilation.runtimeTemplate;
581 const getCurrentLoaderName = () => {
582 const currentLoader = this.getCurrentLoader(loaderContext);
583 if (!currentLoader) return "(not in loader scope)";
584 return requestShortener.shorten(currentLoader.loader);
585 };
586 /**
587 * @returns {ResolveContext} resolve context
588 */
589 const getResolveContext = () => ({
590 fileDependencies: {
591 add: d => /** @type {TODO} */ (loaderContext).addDependency(d)
592 },
593 contextDependencies: {
594 add: d => /** @type {TODO} */ (loaderContext).addContextDependency(d)
595 },
596 missingDependencies: {
597 add: d => /** @type {TODO} */ (loaderContext).addMissingDependency(d)
598 }
599 });
600 const getAbsolutify = memoize(() =>
601 absolutify.bindCache(compilation.compiler.root)
602 );
603 const getAbsolutifyInContext = memoize(() =>
604 absolutify.bindContextCache(
605 /** @type {string} */
606 (this.context),
607 compilation.compiler.root
608 )
609 );
610 const getContextify = memoize(() =>
611 contextify.bindCache(compilation.compiler.root)
612 );
613 const getContextifyInContext = memoize(() =>
614 contextify.bindContextCache(
615 /** @type {string} */
616 (this.context),
617 compilation.compiler.root
618 )
619 );
620 const utils = {
621 /**
622 * @param {string} context context
623 * @param {string} request request
624 * @returns {string} result
625 */
626 absolutify: (context, request) =>
627 context === this.context
628 ? getAbsolutifyInContext()(request)
629 : getAbsolutify()(context, request),
630 /**
631 * @param {string} context context
632 * @param {string} request request
633 * @returns {string} result
634 */
635 contextify: (context, request) =>
636 context === this.context
637 ? getContextifyInContext()(request)
638 : getContextify()(context, request),
639 /**
640 * @param {(string | typeof import("./util/Hash"))=} type type
641 * @returns {Hash} hash
642 */
643 createHash: type =>
644 createHash(
645 type ||
646 /** @type {Algorithm} */
647 (compilation.outputOptions.hashFunction)
648 )
649 };
650 /** @type {import("../declarations/LoaderContext").NormalModuleLoaderContext<T>} */
651 const loaderContext = {
652 version: 2,
653 getOptions: schema => {
654 const loader = this.getCurrentLoader(loaderContext);
655
656 let { options } = /** @type {LoaderItem} */ (loader);
657
658 if (typeof options === "string") {
659 if (options.startsWith("{") && options.endsWith("}")) {
660 try {
661 options = parseJson(options);
662 } catch (err) {
663 throw new Error(
664 `Cannot parse string options: ${/** @type {Error} */ (err).message}`
665 );
666 }
667 } else {
668 options = querystring.parse(options, "&", "=", {
669 maxKeys: 0
670 });
671 }
672 }
673
674 if (options === null || options === undefined) {
675 options = {};
676 }
677
678 if (schema) {
679 let name = "Loader";
680 let baseDataPath = "options";
681 let match;
682 if (schema.title && (match = /^(.+) (.+)$/.exec(schema.title))) {
683 [, name, baseDataPath] = match;
684 }
685 getValidate()(schema, options, {
686 name,
687 baseDataPath
688 });
689 }
690
691 return options;
692 },
693 emitWarning: warning => {
694 if (!(warning instanceof Error)) {
695 warning = new NonErrorEmittedError(warning);
696 }
697 this.addWarning(
698 new ModuleWarning(warning, {
699 from: getCurrentLoaderName()
700 })
701 );
702 },
703 emitError: error => {
704 if (!(error instanceof Error)) {
705 error = new NonErrorEmittedError(error);
706 }
707 this.addError(
708 new ModuleError(error, {
709 from: getCurrentLoaderName()
710 })
711 );
712 },
713 getLogger: name => {
714 const currentLoader = this.getCurrentLoader(loaderContext);
715 return compilation.getLogger(() =>
716 [currentLoader && currentLoader.loader, name, this.identifier()]
717 .filter(Boolean)
718 .join("|")
719 );
720 },
721 resolve(context, request, callback) {
722 resolver.resolve({}, context, request, getResolveContext(), callback);
723 },
724 getResolve(options) {
725 const child = options ? resolver.withOptions(options) : resolver;
726 return (context, request, callback) => {
727 if (callback) {
728 child.resolve({}, context, request, getResolveContext(), callback);
729 } else {
730 return new Promise((resolve, reject) => {
731 child.resolve(
732 {},
733 context,
734 request,
735 getResolveContext(),
736 (err, result) => {
737 if (err) reject(err);
738 else resolve(result);
739 }
740 );
741 });
742 }
743 };
744 },
745 emitFile: (name, content, sourceMap, assetInfo) => {
746 const buildInfo = /** @type {BuildInfo} */ (this.buildInfo);
747
748 if (!buildInfo.assets) {
749 buildInfo.assets = Object.create(null);
750 buildInfo.assetsInfo = new Map();
751 }
752
753 const assets =
754 /** @type {NonNullable<KnownBuildInfo["assets"]>} */
755 (buildInfo.assets);
756 const assetsInfo =
757 /** @type {NonNullable<KnownBuildInfo["assetsInfo"]>} */
758 (buildInfo.assetsInfo);
759
760 assets[name] = this.createSourceForAsset(
761 /** @type {string} */ (options.context),
762 name,
763 content,
764 sourceMap,
765 compilation.compiler.root
766 );
767 assetsInfo.set(name, assetInfo);
768 },
769 addBuildDependency: dep => {
770 const buildInfo = /** @type {BuildInfo} */ (this.buildInfo);
771
772 if (buildInfo.buildDependencies === undefined) {
773 buildInfo.buildDependencies = new LazySet();
774 }
775 buildInfo.buildDependencies.add(dep);
776 },
777 utils,
778 rootContext: /** @type {string} */ (options.context),
779 webpack: true,
780 sourceMap: Boolean(this.useSourceMap),
781 mode: options.mode || "production",
782 hashFunction: /** @type {TODO} */ (options.output.hashFunction),
783 hashDigest: /** @type {string} */ (options.output.hashDigest),
784 hashDigestLength: /** @type {number} */ (options.output.hashDigestLength),
785 hashSalt: /** @type {string} */ (options.output.hashSalt),
786 _module: this,
787 _compilation: compilation,
788 _compiler: compilation.compiler,
789 fs
790 };
791
792 Object.assign(loaderContext, options.loader);
793
794 hooks.loader.call(/** @type {LoaderContext<any>} */ (loaderContext), this);
795
796 return loaderContext;
797 }
798
799 // TODO remove `loaderContext` in webpack@6
800 /**
801 * @param {TODO} loaderContext loader context
802 * @param {number} index index
803 * @returns {LoaderItem | null} loader
804 */
805 getCurrentLoader(loaderContext, index = loaderContext.loaderIndex) {
806 if (
807 this.loaders &&
808 this.loaders.length &&
809 index < this.loaders.length &&
810 index >= 0 &&
811 this.loaders[index]
812 ) {
813 return this.loaders[index];
814 }
815 return null;
816 }
817
818 /**
819 * @param {string} context the compilation context
820 * @param {string | Buffer} content the content
821 * @param {(string | SourceMapSource | null)=} sourceMap an optional source map
822 * @param {object=} associatedObjectForCache object for caching
823 * @returns {Source} the created source
824 */
825 createSource(context, content, sourceMap, associatedObjectForCache) {
826 if (Buffer.isBuffer(content)) {
827 return new RawSource(content);
828 }
829
830 // if there is no identifier return raw source
831 if (!this.identifier) {
832 return new RawSource(content);
833 }
834
835 // from here on we assume we have an identifier
836 const identifier = this.identifier();
837
838 if (this.useSourceMap && sourceMap) {
839 return new SourceMapSource(
840 content,
841 contextifySourceUrl(context, identifier, associatedObjectForCache),
842 contextifySourceMap(
843 context,
844 /** @type {TODO} */ (sourceMap),
845 associatedObjectForCache
846 )
847 );
848 }
849
850 if (this.useSourceMap || this.useSimpleSourceMap) {
851 return new OriginalSource(
852 content,
853 contextifySourceUrl(context, identifier, associatedObjectForCache)
854 );
855 }
856
857 return new RawSource(content);
858 }
859
860 /**
861 * @param {WebpackOptions} options webpack options
862 * @param {Compilation} compilation the compilation
863 * @param {ResolverWithOptions} resolver the resolver
864 * @param {InputFileSystem} fs the file system
865 * @param {NormalModuleCompilationHooks} hooks the hooks
866 * @param {function((WebpackError | null)=): void} callback callback function
867 * @returns {void}
868 */
869 _doBuild(options, compilation, resolver, fs, hooks, callback) {
870 const loaderContext = this._createLoaderContext(
871 resolver,
872 options,
873 compilation,
874 fs,
875 hooks
876 );
877
878 /** @typedef {[string | Buffer, string | SourceMapSource, Record<string, any>]} Result */
879
880 /**
881 * @param {Error | null} err err
882 * @param {(Result | null)=} _result result
883 * @returns {void}
884 */
885 const processResult = (err, _result) => {
886 if (err) {
887 if (!(err instanceof Error)) {
888 err = new NonErrorEmittedError(err);
889 }
890 const currentLoader = this.getCurrentLoader(loaderContext);
891 const error = new ModuleBuildError(err, {
892 from:
893 currentLoader &&
894 compilation.runtimeTemplate.requestShortener.shorten(
895 currentLoader.loader
896 )
897 });
898 return callback(error);
899 }
900
901 const result = /** @type {Result} */ (_result);
902 const source = result[0];
903 const sourceMap = result.length >= 1 ? result[1] : null;
904 const extraInfo = result.length >= 2 ? result[2] : null;
905
906 if (!Buffer.isBuffer(source) && typeof source !== "string") {
907 const currentLoader = this.getCurrentLoader(loaderContext, 0);
908 const err = new Error(
909 `Final loader (${
910 currentLoader
911 ? compilation.runtimeTemplate.requestShortener.shorten(
912 currentLoader.loader
913 )
914 : "unknown"
915 }) didn't return a Buffer or String`
916 );
917 const error = new ModuleBuildError(err);
918 return callback(error);
919 }
920
921 const isBinaryModule =
922 this.generatorOptions && this.generatorOptions.binary !== undefined
923 ? this.generatorOptions.binary
924 : this.binary;
925
926 this._source = this.createSource(
927 /** @type {string} */ (options.context),
928 isBinaryModule ? asBuffer(source) : asString(source),
929 sourceMap,
930 compilation.compiler.root
931 );
932 if (this._sourceSizes !== undefined) this._sourceSizes.clear();
933 this._ast =
934 typeof extraInfo === "object" &&
935 extraInfo !== null &&
936 extraInfo.webpackAST !== undefined
937 ? extraInfo.webpackAST
938 : null;
939 return callback();
940 };
941
942 const buildInfo = /** @type {BuildInfo} */ (this.buildInfo);
943
944 buildInfo.fileDependencies = new LazySet();
945 buildInfo.contextDependencies = new LazySet();
946 buildInfo.missingDependencies = new LazySet();
947 buildInfo.cacheable = true;
948
949 try {
950 hooks.beforeLoaders.call(
951 this.loaders,
952 this,
953 /** @type {LoaderContext<any>} */ (loaderContext)
954 );
955 } catch (err) {
956 processResult(/** @type {Error} */ (err));
957 return;
958 }
959
960 if (this.loaders.length > 0) {
961 /** @type {BuildInfo} */
962 (this.buildInfo).buildDependencies = new LazySet();
963 }
964
965 runLoaders(
966 {
967 resource: this.resource,
968 loaders: this.loaders,
969 context: loaderContext,
970 /**
971 * @param {LoaderContext<TODO>} loaderContext the loader context
972 * @param {string} resourcePath the resource Path
973 * @param {(err: Error | null, result?: string | Buffer) => void} callback callback
974 */
975 processResource: (loaderContext, resourcePath, callback) => {
976 const resource = loaderContext.resource;
977 const scheme = getScheme(resource);
978 hooks.readResource
979 .for(scheme)
980 .callAsync(loaderContext, (err, result) => {
981 if (err) return callback(err);
982 if (typeof result !== "string" && !result) {
983 return callback(
984 new UnhandledSchemeError(
985 /** @type {string} */
986 (scheme),
987 resource
988 )
989 );
990 }
991 return callback(null, result);
992 });
993 }
994 },
995 (err, result) => {
996 // Cleanup loaderContext to avoid leaking memory in ICs
997 loaderContext._compilation =
998 loaderContext._compiler =
999 loaderContext._module =
1000 // eslint-disable-next-line no-warning-comments
1001 // @ts-ignore
1002 loaderContext.fs =
1003 undefined;
1004
1005 if (!result) {
1006 /** @type {BuildInfo} */
1007 (this.buildInfo).cacheable = false;
1008 return processResult(
1009 err || new Error("No result from loader-runner processing"),
1010 null
1011 );
1012 }
1013
1014 const buildInfo = /** @type {BuildInfo} */ (this.buildInfo);
1015
1016 const fileDependencies =
1017 /** @type {NonNullable<KnownBuildInfo["fileDependencies"]>} */
1018 (buildInfo.fileDependencies);
1019 const contextDependencies =
1020 /** @type {NonNullable<KnownBuildInfo["contextDependencies"]>} */
1021 (buildInfo.contextDependencies);
1022 const missingDependencies =
1023 /** @type {NonNullable<KnownBuildInfo["missingDependencies"]>} */
1024 (buildInfo.missingDependencies);
1025
1026 fileDependencies.addAll(result.fileDependencies);
1027 contextDependencies.addAll(result.contextDependencies);
1028 missingDependencies.addAll(result.missingDependencies);
1029 for (const loader of this.loaders) {
1030 const buildDependencies =
1031 /** @type {NonNullable<KnownBuildInfo["buildDependencies"]>} */
1032 (buildInfo.buildDependencies);
1033
1034 buildDependencies.add(loader.loader);
1035 }
1036 buildInfo.cacheable = buildInfo.cacheable && result.cacheable;
1037 processResult(err, result.result);
1038 }
1039 );
1040 }
1041
1042 /**
1043 * @param {WebpackError} error the error
1044 * @returns {void}
1045 */
1046 markModuleAsErrored(error) {
1047 // Restore build meta from successful build to keep importing state
1048 this.buildMeta = { ...this._lastSuccessfulBuildMeta };
1049 this.error = error;
1050 this.addError(error);
1051 }
1052
1053 /**
1054 * @param {TODO} rule rule
1055 * @param {string} content content
1056 * @returns {boolean} result
1057 */
1058 applyNoParseRule(rule, content) {
1059 // must start with "rule" if rule is a string
1060 if (typeof rule === "string") {
1061 return content.startsWith(rule);
1062 }
1063
1064 if (typeof rule === "function") {
1065 return rule(content);
1066 }
1067 // we assume rule is a regexp
1068 return rule.test(content);
1069 }
1070
1071 /**
1072 * @param {TODO} noParseRule no parse rule
1073 * @param {string} request request
1074 * @returns {boolean} check if module should not be parsed, returns "true" if the module should !not! be parsed, returns "false" if the module !must! be parsed
1075 */
1076 shouldPreventParsing(noParseRule, request) {
1077 // if no noParseRule exists, return false
1078 // the module !must! be parsed.
1079 if (!noParseRule) {
1080 return false;
1081 }
1082
1083 // we only have one rule to check
1084 if (!Array.isArray(noParseRule)) {
1085 // returns "true" if the module is !not! to be parsed
1086 return this.applyNoParseRule(noParseRule, request);
1087 }
1088
1089 for (let i = 0; i < noParseRule.length; i++) {
1090 const rule = noParseRule[i];
1091 // early exit on first truthy match
1092 // this module is !not! to be parsed
1093 if (this.applyNoParseRule(rule, request)) {
1094 return true;
1095 }
1096 }
1097 // no match found, so this module !should! be parsed
1098 return false;
1099 }
1100
1101 /**
1102 * @param {Compilation} compilation compilation
1103 * @private
1104 */
1105 _initBuildHash(compilation) {
1106 const hash = createHash(
1107 /** @type {Algorithm} */
1108 (compilation.outputOptions.hashFunction)
1109 );
1110 if (this._source) {
1111 hash.update("source");
1112 this._source.updateHash(hash);
1113 }
1114 hash.update("meta");
1115 hash.update(JSON.stringify(this.buildMeta));
1116 /** @type {BuildInfo} */
1117 (this.buildInfo).hash = /** @type {string} */ (hash.digest("hex"));
1118 }
1119
1120 /**
1121 * @param {WebpackOptions} options webpack options
1122 * @param {Compilation} compilation the compilation
1123 * @param {ResolverWithOptions} resolver the resolver
1124 * @param {InputFileSystem} fs the file system
1125 * @param {function(WebpackError=): void} callback callback function
1126 * @returns {void}
1127 */
1128 build(options, compilation, resolver, fs, callback) {
1129 this._forceBuild = false;
1130 this._source = null;
1131 if (this._sourceSizes !== undefined) this._sourceSizes.clear();
1132 this._sourceTypes = undefined;
1133 this._ast = null;
1134 this.error = null;
1135 this.clearWarningsAndErrors();
1136 this.clearDependenciesAndBlocks();
1137 this.buildMeta = {};
1138 this.buildInfo = {
1139 cacheable: false,
1140 parsed: true,
1141 fileDependencies: undefined,
1142 contextDependencies: undefined,
1143 missingDependencies: undefined,
1144 buildDependencies: undefined,
1145 valueDependencies: undefined,
1146 hash: undefined,
1147 assets: undefined,
1148 assetsInfo: undefined
1149 };
1150
1151 const startTime = compilation.compiler.fsStartTime || Date.now();
1152
1153 const hooks = NormalModule.getCompilationHooks(compilation);
1154
1155 return this._doBuild(options, compilation, resolver, fs, hooks, err => {
1156 // if we have an error mark module as failed and exit
1157 if (err) {
1158 this.markModuleAsErrored(err);
1159 this._initBuildHash(compilation);
1160 return callback();
1161 }
1162
1163 /**
1164 * @param {Error} e error
1165 * @returns {void}
1166 */
1167 const handleParseError = e => {
1168 const source = /** @type {Source} */ (this._source).source();
1169 const loaders = this.loaders.map(item =>
1170 contextify(
1171 /** @type {string} */ (options.context),
1172 item.loader,
1173 compilation.compiler.root
1174 )
1175 );
1176 const error = new ModuleParseError(source, e, loaders, this.type);
1177 this.markModuleAsErrored(error);
1178 this._initBuildHash(compilation);
1179 return callback();
1180 };
1181
1182 const handleParseResult = () => {
1183 this.dependencies.sort(
1184 concatComparators(
1185 compareSelect(a => a.loc, compareLocations),
1186 keepOriginalOrder(this.dependencies)
1187 )
1188 );
1189 this._initBuildHash(compilation);
1190 this._lastSuccessfulBuildMeta =
1191 /** @type {BuildMeta} */
1192 (this.buildMeta);
1193 return handleBuildDone();
1194 };
1195
1196 const handleBuildDone = () => {
1197 try {
1198 hooks.beforeSnapshot.call(this);
1199 } catch (err) {
1200 this.markModuleAsErrored(/** @type {WebpackError} */ (err));
1201 return callback();
1202 }
1203
1204 const snapshotOptions = compilation.options.snapshot.module;
1205 const { cacheable } = /** @type {BuildInfo} */ (this.buildInfo);
1206 if (!cacheable || !snapshotOptions) {
1207 return callback();
1208 }
1209 // add warning for all non-absolute paths in fileDependencies, etc
1210 // This makes it easier to find problems with watching and/or caching
1211 /** @type {undefined | Set<string>} */
1212 let nonAbsoluteDependencies;
1213 /**
1214 * @param {LazySet<string>} deps deps
1215 */
1216 const checkDependencies = deps => {
1217 for (const dep of deps) {
1218 if (!ABSOLUTE_PATH_REGEX.test(dep)) {
1219 if (nonAbsoluteDependencies === undefined)
1220 nonAbsoluteDependencies = new Set();
1221 nonAbsoluteDependencies.add(dep);
1222 deps.delete(dep);
1223 try {
1224 const depWithoutGlob = dep.replace(/[\\/]?\*.*$/, "");
1225 const absolute = join(
1226 compilation.fileSystemInfo.fs,
1227 /** @type {string} */
1228 (this.context),
1229 depWithoutGlob
1230 );
1231 if (absolute !== dep && ABSOLUTE_PATH_REGEX.test(absolute)) {
1232 (depWithoutGlob !== dep
1233 ? /** @type {NonNullable<KnownBuildInfo["contextDependencies"]>} */
1234 (
1235 /** @type {BuildInfo} */ (this.buildInfo)
1236 .contextDependencies
1237 )
1238 : deps
1239 ).add(absolute);
1240 }
1241 } catch (_err) {
1242 // ignore
1243 }
1244 }
1245 }
1246 };
1247 const buildInfo = /** @type {BuildInfo} */ (this.buildInfo);
1248 const fileDependencies =
1249 /** @type {NonNullable<KnownBuildInfo["fileDependencies"]>} */
1250 (buildInfo.fileDependencies);
1251 const contextDependencies =
1252 /** @type {NonNullable<KnownBuildInfo["contextDependencies"]>} */
1253 (buildInfo.contextDependencies);
1254 const missingDependencies =
1255 /** @type {NonNullable<KnownBuildInfo["missingDependencies"]>} */
1256 (buildInfo.missingDependencies);
1257 checkDependencies(fileDependencies);
1258 checkDependencies(missingDependencies);
1259 checkDependencies(contextDependencies);
1260 if (nonAbsoluteDependencies !== undefined) {
1261 const InvalidDependenciesModuleWarning =
1262 getInvalidDependenciesModuleWarning();
1263 this.addWarning(
1264 new InvalidDependenciesModuleWarning(this, nonAbsoluteDependencies)
1265 );
1266 }
1267 // convert file/context/missingDependencies into filesystem snapshot
1268 compilation.fileSystemInfo.createSnapshot(
1269 startTime,
1270 fileDependencies,
1271 contextDependencies,
1272 missingDependencies,
1273 snapshotOptions,
1274 (err, snapshot) => {
1275 if (err) {
1276 this.markModuleAsErrored(err);
1277 return;
1278 }
1279 buildInfo.fileDependencies = undefined;
1280 buildInfo.contextDependencies = undefined;
1281 buildInfo.missingDependencies = undefined;
1282 buildInfo.snapshot = snapshot;
1283 return callback();
1284 }
1285 );
1286 };
1287
1288 try {
1289 hooks.beforeParse.call(this);
1290 } catch (err) {
1291 this.markModuleAsErrored(/** @type {WebpackError} */ (err));
1292 this._initBuildHash(compilation);
1293 return callback();
1294 }
1295
1296 // check if this module should !not! be parsed.
1297 // if so, exit here;
1298 const noParseRule = options.module && options.module.noParse;
1299 if (this.shouldPreventParsing(noParseRule, this.request)) {
1300 // We assume that we need module and exports
1301 /** @type {BuildInfo} */
1302 (this.buildInfo).parsed = false;
1303 this._initBuildHash(compilation);
1304 return handleBuildDone();
1305 }
1306
1307 try {
1308 const source = /** @type {Source} */ (this._source).source();
1309 /** @type {Parser} */
1310 (this.parser).parse(this._ast || source, {
1311 source,
1312 current: this,
1313 module: this,
1314 compilation,
1315 options
1316 });
1317 } catch (parseErr) {
1318 handleParseError(/** @type {Error} */ (parseErr));
1319 return;
1320 }
1321 handleParseResult();
1322 });
1323 }
1324
1325 /**
1326 * @param {ConcatenationBailoutReasonContext} context context
1327 * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated
1328 */
1329 getConcatenationBailoutReason(context) {
1330 return /** @type {Generator} */ (
1331 this.generator
1332 ).getConcatenationBailoutReason(this, context);
1333 }
1334
1335 /**
1336 * @param {ModuleGraph} moduleGraph the module graph
1337 * @returns {ConnectionState} how this module should be connected to referencing modules when consumed for side-effects only
1338 */
1339 getSideEffectsConnectionState(moduleGraph) {
1340 if (this.factoryMeta !== undefined) {
1341 if (this.factoryMeta.sideEffectFree) return false;
1342 if (this.factoryMeta.sideEffectFree === false) return true;
1343 }
1344 if (this.buildMeta !== undefined && this.buildMeta.sideEffectFree) {
1345 if (this._isEvaluatingSideEffects)
1346 return ModuleGraphConnection.CIRCULAR_CONNECTION;
1347 this._isEvaluatingSideEffects = true;
1348 /** @type {ConnectionState} */
1349 let current = false;
1350 for (const dep of this.dependencies) {
1351 const state = dep.getModuleEvaluationSideEffectsState(moduleGraph);
1352 if (state === true) {
1353 if (
1354 this._addedSideEffectsBailout === undefined
1355 ? ((this._addedSideEffectsBailout = new WeakSet()), true)
1356 : !this._addedSideEffectsBailout.has(moduleGraph)
1357 ) {
1358 this._addedSideEffectsBailout.add(moduleGraph);
1359 moduleGraph
1360 .getOptimizationBailout(this)
1361 .push(
1362 () =>
1363 `Dependency (${
1364 dep.type
1365 }) with side effects at ${formatLocation(dep.loc)}`
1366 );
1367 }
1368 this._isEvaluatingSideEffects = false;
1369 return true;
1370 } else if (state !== ModuleGraphConnection.CIRCULAR_CONNECTION) {
1371 current = ModuleGraphConnection.addConnectionStates(current, state);
1372 }
1373 }
1374 this._isEvaluatingSideEffects = false;
1375 // When caching is implemented here, make sure to not cache when
1376 // at least one circular connection was in the loop above
1377 return current;
1378 }
1379 return true;
1380 }
1381
1382 /**
1383 * @returns {SourceTypes} types available (do not mutate)
1384 */
1385 getSourceTypes() {
1386 if (this._sourceTypes === undefined) {
1387 this._sourceTypes = /** @type {Generator} */ (this.generator).getTypes(
1388 this
1389 );
1390 }
1391 return this._sourceTypes;
1392 }
1393
1394 /**
1395 * @param {CodeGenerationContext} context context for code generation
1396 * @returns {CodeGenerationResult} result
1397 */
1398 codeGeneration({
1399 dependencyTemplates,
1400 runtimeTemplate,
1401 moduleGraph,
1402 chunkGraph,
1403 runtime,
1404 concatenationScope,
1405 codeGenerationResults,
1406 sourceTypes
1407 }) {
1408 /** @type {Set<string>} */
1409 const runtimeRequirements = new Set();
1410
1411 const { parsed } = /** @type {BuildInfo} */ (this.buildInfo);
1412
1413 if (!parsed) {
1414 runtimeRequirements.add(RuntimeGlobals.module);
1415 runtimeRequirements.add(RuntimeGlobals.exports);
1416 runtimeRequirements.add(RuntimeGlobals.thisAsExports);
1417 }
1418
1419 /** @type {function(): Map<string, any>} */
1420 const getData = () => this._codeGeneratorData;
1421
1422 const sources = new Map();
1423 for (const type of sourceTypes || chunkGraph.getModuleSourceTypes(this)) {
1424 const source = this.error
1425 ? new RawSource(
1426 `throw new Error(${JSON.stringify(this.error.message)});`
1427 )
1428 : /** @type {Generator} */ (this.generator).generate(this, {
1429 dependencyTemplates,
1430 runtimeTemplate,
1431 moduleGraph,
1432 chunkGraph,
1433 runtimeRequirements,
1434 runtime,
1435 concatenationScope,
1436 codeGenerationResults,
1437 getData,
1438 type
1439 });
1440
1441 if (source) {
1442 sources.set(type, new CachedSource(source));
1443 }
1444 }
1445
1446 /** @type {CodeGenerationResult} */
1447 const resultEntry = {
1448 sources,
1449 runtimeRequirements,
1450 data: this._codeGeneratorData
1451 };
1452 return resultEntry;
1453 }
1454
1455 /**
1456 * @returns {Source | null} the original source for the module before webpack transformation
1457 */
1458 originalSource() {
1459 return this._source;
1460 }
1461
1462 /**
1463 * @returns {void}
1464 */
1465 invalidateBuild() {
1466 this._forceBuild = true;
1467 }
1468
1469 /**
1470 * @param {NeedBuildContext} context context info
1471 * @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
1472 * @returns {void}
1473 */
1474 needBuild(context, callback) {
1475 const { fileSystemInfo, compilation, valueCacheVersions } = context;
1476 // build if enforced
1477 if (this._forceBuild) return callback(null, true);
1478
1479 // always try to build in case of an error
1480 if (this.error) return callback(null, true);
1481
1482 const { cacheable, snapshot, valueDependencies } =
1483 /** @type {BuildInfo} */ (this.buildInfo);
1484
1485 // always build when module is not cacheable
1486 if (!cacheable) return callback(null, true);
1487
1488 // build when there is no snapshot to check
1489 if (!snapshot) return callback(null, true);
1490
1491 // build when valueDependencies have changed
1492 if (valueDependencies) {
1493 if (!valueCacheVersions) return callback(null, true);
1494 for (const [key, value] of valueDependencies) {
1495 if (value === undefined) return callback(null, true);
1496 const current = valueCacheVersions.get(key);
1497 if (
1498 value !== current &&
1499 (typeof value === "string" ||
1500 typeof current === "string" ||
1501 current === undefined ||
1502 !isSubset(value, current))
1503 ) {
1504 return callback(null, true);
1505 }
1506 }
1507 }
1508
1509 // check snapshot for validity
1510 fileSystemInfo.checkSnapshotValid(snapshot, (err, valid) => {
1511 if (err) return callback(err);
1512 if (!valid) return callback(null, true);
1513 const hooks = NormalModule.getCompilationHooks(compilation);
1514 hooks.needBuild.callAsync(this, context, (err, needBuild) => {
1515 if (err) {
1516 return callback(
1517 HookWebpackError.makeWebpackError(
1518 err,
1519 "NormalModule.getCompilationHooks().needBuild"
1520 )
1521 );
1522 }
1523 callback(null, Boolean(needBuild));
1524 });
1525 });
1526 }
1527
1528 /**
1529 * @param {string=} type the source type for which the size should be estimated
1530 * @returns {number} the estimated size of the module (must be non-zero)
1531 */
1532 size(type) {
1533 const cachedSize =
1534 this._sourceSizes === undefined ? undefined : this._sourceSizes.get(type);
1535 if (cachedSize !== undefined) {
1536 return cachedSize;
1537 }
1538 const size = Math.max(
1539 1,
1540 /** @type {Generator} */ (this.generator).getSize(this, type)
1541 );
1542 if (this._sourceSizes === undefined) {
1543 this._sourceSizes = new Map();
1544 }
1545 this._sourceSizes.set(type, size);
1546 return size;
1547 }
1548
1549 /**
1550 * @param {LazySet<string>} fileDependencies set where file dependencies are added to
1551 * @param {LazySet<string>} contextDependencies set where context dependencies are added to
1552 * @param {LazySet<string>} missingDependencies set where missing dependencies are added to
1553 * @param {LazySet<string>} buildDependencies set where build dependencies are added to
1554 */
1555 addCacheDependencies(
1556 fileDependencies,
1557 contextDependencies,
1558 missingDependencies,
1559 buildDependencies
1560 ) {
1561 const { snapshot, buildDependencies: buildDeps } =
1562 /** @type {BuildInfo} */ (this.buildInfo);
1563 if (snapshot) {
1564 fileDependencies.addAll(snapshot.getFileIterable());
1565 contextDependencies.addAll(snapshot.getContextIterable());
1566 missingDependencies.addAll(snapshot.getMissingIterable());
1567 } else {
1568 const {
1569 fileDependencies: fileDeps,
1570 contextDependencies: contextDeps,
1571 missingDependencies: missingDeps
1572 } = /** @type {BuildInfo} */ (this.buildInfo);
1573 if (fileDeps !== undefined) fileDependencies.addAll(fileDeps);
1574 if (contextDeps !== undefined) contextDependencies.addAll(contextDeps);
1575 if (missingDeps !== undefined) missingDependencies.addAll(missingDeps);
1576 }
1577 if (buildDeps !== undefined) {
1578 buildDependencies.addAll(buildDeps);
1579 }
1580 }
1581
1582 /**
1583 * @param {Hash} hash the hash used to track dependencies
1584 * @param {UpdateHashContext} context context
1585 * @returns {void}
1586 */
1587 updateHash(hash, context) {
1588 hash.update(/** @type {BuildInfo} */ (this.buildInfo).hash);
1589 /** @type {Generator} */
1590 (this.generator).updateHash(hash, {
1591 module: this,
1592 ...context
1593 });
1594 super.updateHash(hash, context);
1595 }
1596
1597 /**
1598 * @param {ObjectSerializerContext} context context
1599 */
1600 serialize(context) {
1601 const { write } = context;
1602 // deserialize
1603 write(this._source);
1604 write(this.error);
1605 write(this._lastSuccessfulBuildMeta);
1606 write(this._forceBuild);
1607 write(this._codeGeneratorData);
1608 super.serialize(context);
1609 }
1610
1611 /**
1612 * @param {ObjectDeserializerContext} context context
1613 * @returns {TODO} Module
1614 */
1615 static deserialize(context) {
1616 const obj = new NormalModule({
1617 // will be deserialized by Module
1618 layer: /** @type {EXPECTED_ANY} */ (null),
1619 type: "",
1620 // will be filled by updateCacheModule
1621 resource: "",
1622 context: "",
1623 request: /** @type {EXPECTED_ANY} */ (null),
1624 userRequest: /** @type {EXPECTED_ANY} */ (null),
1625 rawRequest: /** @type {EXPECTED_ANY} */ (null),
1626 loaders: /** @type {EXPECTED_ANY} */ (null),
1627 matchResource: /** @type {EXPECTED_ANY} */ (null),
1628 parser: /** @type {EXPECTED_ANY} */ (null),
1629 parserOptions: /** @type {EXPECTED_ANY} */ (null),
1630 generator: /** @type {EXPECTED_ANY} */ (null),
1631 generatorOptions: /** @type {EXPECTED_ANY} */ (null),
1632 resolveOptions: /** @type {EXPECTED_ANY} */ (null)
1633 });
1634 obj.deserialize(context);
1635 return obj;
1636 }
1637
1638 /**
1639 * @param {ObjectDeserializerContext} context context
1640 */
1641 deserialize(context) {
1642 const { read } = context;
1643 this._source = read();
1644 this.error = read();
1645 this._lastSuccessfulBuildMeta = read();
1646 this._forceBuild = read();
1647 this._codeGeneratorData = read();
1648 super.deserialize(context);
1649 }
1650}
1651
1652makeSerializable(NormalModule, "webpack/lib/NormalModule");
1653
1654module.exports = NormalModule;
Note: See TracBrowser for help on using the repository browser.