source: trip-planner-front/node_modules/webpack/lib/NormalModule.js@ 8d391a1

Last change on this file since 8d391a1 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

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