source: imaps-frontend/node_modules/webpack/lib/ContextModule.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: 37.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 { OriginalSource, RawSource } = require("webpack-sources");
9const AsyncDependenciesBlock = require("./AsyncDependenciesBlock");
10const { makeWebpackError } = require("./HookWebpackError");
11const Module = require("./Module");
12const { JS_TYPES } = require("./ModuleSourceTypesConstants");
13const { JAVASCRIPT_MODULE_TYPE_DYNAMIC } = require("./ModuleTypeConstants");
14const RuntimeGlobals = require("./RuntimeGlobals");
15const Template = require("./Template");
16const WebpackError = require("./WebpackError");
17const {
18 compareLocations,
19 concatComparators,
20 compareSelect,
21 keepOriginalOrder,
22 compareModulesById
23} = require("./util/comparators");
24const {
25 contextify,
26 parseResource,
27 makePathsRelative
28} = require("./util/identifier");
29const makeSerializable = require("./util/makeSerializable");
30
31/** @typedef {import("webpack-sources").Source} Source */
32/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
33/** @typedef {import("./Chunk")} Chunk */
34/** @typedef {import("./Chunk").ChunkId} ChunkId */
35/** @typedef {import("./ChunkGraph")} ChunkGraph */
36/** @typedef {import("./ChunkGraph").ModuleId} ModuleId */
37/** @typedef {import("./ChunkGroup").RawChunkGroupOptions} RawChunkGroupOptions */
38/** @typedef {import("./Compilation")} Compilation */
39/** @typedef {import("./Dependency")} Dependency */
40/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
41/** @typedef {import("./Generator").SourceTypes} SourceTypes */
42/** @typedef {import("./Module").BuildInfo} BuildInfo */
43/** @typedef {import("./Module").BuildMeta} BuildMeta */
44/** @typedef {import("./Module").CodeGenerationContext} CodeGenerationContext */
45/** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */
46/** @typedef {import("./Module").LibIdentOptions} LibIdentOptions */
47/** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */
48/** @typedef {import("./ModuleGraph")} ModuleGraph */
49/** @typedef {import("./RequestShortener")} RequestShortener */
50/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
51/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
52/** @typedef {import("./dependencies/ContextElementDependency")} ContextElementDependency */
53/** @typedef {import("./javascript/JavascriptParser").ImportAttributes} ImportAttributes */
54/** @typedef {import("./serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
55/** @typedef {import("./serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
56/** @template T @typedef {import("./util/LazySet")<T>} LazySet<T> */
57/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
58
59/** @typedef {"sync" | "eager" | "weak" | "async-weak" | "lazy" | "lazy-once"} ContextMode Context mode */
60
61/**
62 * @typedef {object} ContextOptions
63 * @property {ContextMode} mode
64 * @property {boolean} recursive
65 * @property {RegExp} regExp
66 * @property {("strict" | boolean)=} namespaceObject
67 * @property {string=} addon
68 * @property {(string | null)=} chunkName
69 * @property {(RegExp | null)=} include
70 * @property {(RegExp | null)=} exclude
71 * @property {RawChunkGroupOptions=} groupOptions
72 * @property {string=} typePrefix
73 * @property {string=} category
74 * @property {(string[][] | null)=} referencedExports exports referenced from modules (won't be mangled)
75 * @property {string=} layer
76 * @property {ImportAttributes=} attributes
77 */
78
79/**
80 * @typedef {object} ContextModuleOptionsExtras
81 * @property {false|string|string[]} resource
82 * @property {string=} resourceQuery
83 * @property {string=} resourceFragment
84 * @property {TODO} resolveOptions
85 */
86
87/** @typedef {ContextOptions & ContextModuleOptionsExtras} ContextModuleOptions */
88
89/**
90 * @callback ResolveDependenciesCallback
91 * @param {Error | null} err
92 * @param {ContextElementDependency[]=} dependencies
93 */
94
95/**
96 * @callback ResolveDependencies
97 * @param {InputFileSystem} fs
98 * @param {ContextModuleOptions} options
99 * @param {ResolveDependenciesCallback} callback
100 */
101
102/** @typedef {1 | 3 | 7 | 9} FakeMapType */
103
104/** @typedef {Record<ModuleId, FakeMapType>} FakeMap */
105
106const SNAPSHOT_OPTIONS = { timestamp: true };
107
108class ContextModule extends Module {
109 /**
110 * @param {ResolveDependencies} resolveDependencies function to get dependencies in this context
111 * @param {ContextModuleOptions} options options object
112 */
113 constructor(resolveDependencies, options) {
114 if (!options || typeof options.resource === "string") {
115 const parsed = parseResource(
116 options ? /** @type {string} */ (options.resource) : ""
117 );
118 const resource = parsed.path;
119 const resourceQuery = (options && options.resourceQuery) || parsed.query;
120 const resourceFragment =
121 (options && options.resourceFragment) || parsed.fragment;
122 const layer = options && options.layer;
123
124 super(JAVASCRIPT_MODULE_TYPE_DYNAMIC, resource, layer);
125 /** @type {ContextModuleOptions} */
126 this.options = {
127 ...options,
128 resource,
129 resourceQuery,
130 resourceFragment
131 };
132 } else {
133 super(JAVASCRIPT_MODULE_TYPE_DYNAMIC, undefined, options.layer);
134 /** @type {ContextModuleOptions} */
135 this.options = {
136 ...options,
137 resource: options.resource,
138 resourceQuery: options.resourceQuery || "",
139 resourceFragment: options.resourceFragment || ""
140 };
141 }
142
143 // Info from Factory
144 /** @type {ResolveDependencies | undefined} */
145 this.resolveDependencies = resolveDependencies;
146 if (options && options.resolveOptions !== undefined) {
147 this.resolveOptions = options.resolveOptions;
148 }
149
150 if (options && typeof options.mode !== "string") {
151 throw new Error("options.mode is a required option");
152 }
153
154 this._identifier = this._createIdentifier();
155 this._forceBuild = true;
156 }
157
158 /**
159 * @returns {SourceTypes} types available (do not mutate)
160 */
161 getSourceTypes() {
162 return JS_TYPES;
163 }
164
165 /**
166 * Assuming this module is in the cache. Update the (cached) module with
167 * the fresh module from the factory. Usually updates internal references
168 * and properties.
169 * @param {Module} module fresh module
170 * @returns {void}
171 */
172 updateCacheModule(module) {
173 const m = /** @type {ContextModule} */ (module);
174 this.resolveDependencies = m.resolveDependencies;
175 this.options = m.options;
176 }
177
178 /**
179 * Assuming this module is in the cache. Remove internal references to allow freeing some memory.
180 */
181 cleanupForCache() {
182 super.cleanupForCache();
183 this.resolveDependencies = undefined;
184 }
185
186 /**
187 * @private
188 * @param {RegExp} regexString RegExp as a string
189 * @param {boolean=} stripSlash do we need to strip a slsh
190 * @returns {string} pretty RegExp
191 */
192 _prettyRegExp(regexString, stripSlash = true) {
193 const str = stripSlash
194 ? regexString.source + regexString.flags
195 : `${regexString}`;
196 return str.replace(/!/g, "%21").replace(/\|/g, "%7C");
197 }
198
199 _createIdentifier() {
200 let identifier =
201 this.context ||
202 (typeof this.options.resource === "string" ||
203 this.options.resource === false
204 ? `${this.options.resource}`
205 : this.options.resource.join("|"));
206 if (this.options.resourceQuery) {
207 identifier += `|${this.options.resourceQuery}`;
208 }
209 if (this.options.resourceFragment) {
210 identifier += `|${this.options.resourceFragment}`;
211 }
212 if (this.options.mode) {
213 identifier += `|${this.options.mode}`;
214 }
215 if (!this.options.recursive) {
216 identifier += "|nonrecursive";
217 }
218 if (this.options.addon) {
219 identifier += `|${this.options.addon}`;
220 }
221 if (this.options.regExp) {
222 identifier += `|${this._prettyRegExp(this.options.regExp, false)}`;
223 }
224 if (this.options.include) {
225 identifier += `|include: ${this._prettyRegExp(
226 this.options.include,
227 false
228 )}`;
229 }
230 if (this.options.exclude) {
231 identifier += `|exclude: ${this._prettyRegExp(
232 this.options.exclude,
233 false
234 )}`;
235 }
236 if (this.options.referencedExports) {
237 identifier += `|referencedExports: ${JSON.stringify(
238 this.options.referencedExports
239 )}`;
240 }
241 if (this.options.chunkName) {
242 identifier += `|chunkName: ${this.options.chunkName}`;
243 }
244 if (this.options.groupOptions) {
245 identifier += `|groupOptions: ${JSON.stringify(
246 this.options.groupOptions
247 )}`;
248 }
249 if (this.options.namespaceObject === "strict") {
250 identifier += "|strict namespace object";
251 } else if (this.options.namespaceObject) {
252 identifier += "|namespace object";
253 }
254 if (this.layer) {
255 identifier += `|layer: ${this.layer}`;
256 }
257
258 return identifier;
259 }
260
261 /**
262 * @returns {string} a unique identifier of the module
263 */
264 identifier() {
265 return this._identifier;
266 }
267
268 /**
269 * @param {RequestShortener} requestShortener the request shortener
270 * @returns {string} a user readable identifier of the module
271 */
272 readableIdentifier(requestShortener) {
273 let identifier;
274 if (this.context) {
275 identifier = `${requestShortener.shorten(this.context)}/`;
276 } else if (
277 typeof this.options.resource === "string" ||
278 this.options.resource === false
279 ) {
280 identifier = `${requestShortener.shorten(`${this.options.resource}`)}/`;
281 } else {
282 identifier = this.options.resource
283 .map(r => `${requestShortener.shorten(r)}/`)
284 .join(" ");
285 }
286 if (this.options.resourceQuery) {
287 identifier += ` ${this.options.resourceQuery}`;
288 }
289 if (this.options.mode) {
290 identifier += ` ${this.options.mode}`;
291 }
292 if (!this.options.recursive) {
293 identifier += " nonrecursive";
294 }
295 if (this.options.addon) {
296 identifier += ` ${requestShortener.shorten(this.options.addon)}`;
297 }
298 if (this.options.regExp) {
299 identifier += ` ${this._prettyRegExp(this.options.regExp)}`;
300 }
301 if (this.options.include) {
302 identifier += ` include: ${this._prettyRegExp(this.options.include)}`;
303 }
304 if (this.options.exclude) {
305 identifier += ` exclude: ${this._prettyRegExp(this.options.exclude)}`;
306 }
307 if (this.options.referencedExports) {
308 identifier += ` referencedExports: ${this.options.referencedExports
309 .map(e => e.join("."))
310 .join(", ")}`;
311 }
312 if (this.options.chunkName) {
313 identifier += ` chunkName: ${this.options.chunkName}`;
314 }
315 if (this.options.groupOptions) {
316 const groupOptions = this.options.groupOptions;
317 for (const key of Object.keys(groupOptions)) {
318 identifier += ` ${key}: ${
319 groupOptions[/** @type {keyof RawChunkGroupOptions} */ (key)]
320 }`;
321 }
322 }
323 if (this.options.namespaceObject === "strict") {
324 identifier += " strict namespace object";
325 } else if (this.options.namespaceObject) {
326 identifier += " namespace object";
327 }
328
329 return identifier;
330 }
331
332 /**
333 * @param {LibIdentOptions} options options
334 * @returns {string | null} an identifier for library inclusion
335 */
336 libIdent(options) {
337 let identifier;
338
339 if (this.context) {
340 identifier = contextify(
341 options.context,
342 this.context,
343 options.associatedObjectForCache
344 );
345 } else if (typeof this.options.resource === "string") {
346 identifier = contextify(
347 options.context,
348 this.options.resource,
349 options.associatedObjectForCache
350 );
351 } else if (this.options.resource === false) {
352 identifier = "false";
353 } else {
354 identifier = this.options.resource
355 .map(res =>
356 contextify(options.context, res, options.associatedObjectForCache)
357 )
358 .join(" ");
359 }
360
361 if (this.layer) identifier = `(${this.layer})/${identifier}`;
362 if (this.options.mode) {
363 identifier += ` ${this.options.mode}`;
364 }
365 if (this.options.recursive) {
366 identifier += " recursive";
367 }
368 if (this.options.addon) {
369 identifier += ` ${contextify(
370 options.context,
371 this.options.addon,
372 options.associatedObjectForCache
373 )}`;
374 }
375 if (this.options.regExp) {
376 identifier += ` ${this._prettyRegExp(this.options.regExp)}`;
377 }
378 if (this.options.include) {
379 identifier += ` include: ${this._prettyRegExp(this.options.include)}`;
380 }
381 if (this.options.exclude) {
382 identifier += ` exclude: ${this._prettyRegExp(this.options.exclude)}`;
383 }
384 if (this.options.referencedExports) {
385 identifier += ` referencedExports: ${this.options.referencedExports
386 .map(e => e.join("."))
387 .join(", ")}`;
388 }
389
390 return identifier;
391 }
392
393 /**
394 * @returns {void}
395 */
396 invalidateBuild() {
397 this._forceBuild = true;
398 }
399
400 /**
401 * @param {NeedBuildContext} context context info
402 * @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
403 * @returns {void}
404 */
405 needBuild({ fileSystemInfo }, callback) {
406 // build if enforced
407 if (this._forceBuild) return callback(null, true);
408
409 const buildInfo = /** @type {BuildInfo} */ (this.buildInfo);
410
411 // always build when we have no snapshot and context
412 if (!buildInfo.snapshot)
413 return callback(null, Boolean(this.context || this.options.resource));
414
415 fileSystemInfo.checkSnapshotValid(buildInfo.snapshot, (err, valid) => {
416 callback(err, !valid);
417 });
418 }
419
420 /**
421 * @param {WebpackOptions} options webpack options
422 * @param {Compilation} compilation the compilation
423 * @param {ResolverWithOptions} resolver the resolver
424 * @param {InputFileSystem} fs the file system
425 * @param {function(WebpackError=): void} callback callback function
426 * @returns {void}
427 */
428 build(options, compilation, resolver, fs, callback) {
429 this._forceBuild = false;
430 /** @type {BuildMeta} */
431 this.buildMeta = {
432 exportsType: "default",
433 defaultObject: "redirect-warn"
434 };
435 this.buildInfo = {
436 snapshot: undefined
437 };
438 this.dependencies.length = 0;
439 this.blocks.length = 0;
440 const startTime = Date.now();
441 /** @type {ResolveDependencies} */
442 (this.resolveDependencies)(fs, this.options, (err, dependencies) => {
443 if (err) {
444 return callback(
445 makeWebpackError(err, "ContextModule.resolveDependencies")
446 );
447 }
448
449 // abort if something failed
450 // this will create an empty context
451 if (!dependencies) {
452 callback();
453 return;
454 }
455
456 // enhance dependencies with meta info
457 for (const dep of dependencies) {
458 dep.loc = {
459 name: dep.userRequest
460 };
461 dep.request = this.options.addon + dep.request;
462 }
463 dependencies.sort(
464 concatComparators(
465 compareSelect(a => a.loc, compareLocations),
466 keepOriginalOrder(this.dependencies)
467 )
468 );
469
470 if (this.options.mode === "sync" || this.options.mode === "eager") {
471 // if we have an sync or eager context
472 // just add all dependencies and continue
473 this.dependencies = dependencies;
474 } else if (this.options.mode === "lazy-once") {
475 // for the lazy-once mode create a new async dependency block
476 // and add that block to this context
477 if (dependencies.length > 0) {
478 const block = new AsyncDependenciesBlock({
479 ...this.options.groupOptions,
480 name: this.options.chunkName
481 });
482 for (const dep of dependencies) {
483 block.addDependency(dep);
484 }
485 this.addBlock(block);
486 }
487 } else if (
488 this.options.mode === "weak" ||
489 this.options.mode === "async-weak"
490 ) {
491 // we mark all dependencies as weak
492 for (const dep of dependencies) {
493 dep.weak = true;
494 }
495 this.dependencies = dependencies;
496 } else if (this.options.mode === "lazy") {
497 // if we are lazy create a new async dependency block per dependency
498 // and add all blocks to this context
499 let index = 0;
500 for (const dep of dependencies) {
501 let chunkName = this.options.chunkName;
502 if (chunkName) {
503 if (!/\[(index|request)\]/.test(chunkName)) {
504 chunkName += "[index]";
505 }
506 chunkName = chunkName.replace(/\[index\]/g, `${index++}`);
507 chunkName = chunkName.replace(
508 /\[request\]/g,
509 Template.toPath(dep.userRequest)
510 );
511 }
512 const block = new AsyncDependenciesBlock(
513 {
514 ...this.options.groupOptions,
515 name: chunkName
516 },
517 dep.loc,
518 dep.userRequest
519 );
520 block.addDependency(dep);
521 this.addBlock(block);
522 }
523 } else {
524 callback(
525 new WebpackError(`Unsupported mode "${this.options.mode}" in context`)
526 );
527 return;
528 }
529 if (!this.context && !this.options.resource) return callback();
530
531 compilation.fileSystemInfo.createSnapshot(
532 startTime,
533 null,
534 this.context
535 ? [this.context]
536 : typeof this.options.resource === "string"
537 ? [this.options.resource]
538 : /** @type {string[]} */ (this.options.resource),
539 null,
540 SNAPSHOT_OPTIONS,
541 (err, snapshot) => {
542 if (err) return callback(err);
543 /** @type {BuildInfo} */
544 (this.buildInfo).snapshot = snapshot;
545 callback();
546 }
547 );
548 });
549 }
550
551 /**
552 * @param {LazySet<string>} fileDependencies set where file dependencies are added to
553 * @param {LazySet<string>} contextDependencies set where context dependencies are added to
554 * @param {LazySet<string>} missingDependencies set where missing dependencies are added to
555 * @param {LazySet<string>} buildDependencies set where build dependencies are added to
556 */
557 addCacheDependencies(
558 fileDependencies,
559 contextDependencies,
560 missingDependencies,
561 buildDependencies
562 ) {
563 if (this.context) {
564 contextDependencies.add(this.context);
565 } else if (typeof this.options.resource === "string") {
566 contextDependencies.add(this.options.resource);
567 } else if (this.options.resource === false) {
568 // Do nothing
569 } else {
570 for (const res of this.options.resource) contextDependencies.add(res);
571 }
572 }
573
574 /**
575 * @param {Dependency[]} dependencies all dependencies
576 * @param {ChunkGraph} chunkGraph chunk graph
577 * @returns {Map<string, string | number>} map with user requests
578 */
579 getUserRequestMap(dependencies, chunkGraph) {
580 const moduleGraph = chunkGraph.moduleGraph;
581 // if we filter first we get a new array
582 // therefore we don't need to create a clone of dependencies explicitly
583 // therefore the order of this is !important!
584 const sortedDependencies =
585 /** @type {ContextElementDependency[]} */
586 (dependencies)
587 .filter(dependency => moduleGraph.getModule(dependency))
588 .sort((a, b) => {
589 if (a.userRequest === b.userRequest) {
590 return 0;
591 }
592 return a.userRequest < b.userRequest ? -1 : 1;
593 });
594 const map = Object.create(null);
595 for (const dep of sortedDependencies) {
596 const module = /** @type {Module} */ (moduleGraph.getModule(dep));
597 map[dep.userRequest] = chunkGraph.getModuleId(module);
598 }
599 return map;
600 }
601
602 /**
603 * @param {Dependency[]} dependencies all dependencies
604 * @param {ChunkGraph} chunkGraph chunk graph
605 * @returns {FakeMap | FakeMapType} fake map
606 */
607 getFakeMap(dependencies, chunkGraph) {
608 if (!this.options.namespaceObject) {
609 return 9;
610 }
611 const moduleGraph = chunkGraph.moduleGraph;
612 // bitfield
613 let hasType = 0;
614 const comparator = compareModulesById(chunkGraph);
615 // if we filter first we get a new array
616 // therefore we don't need to create a clone of dependencies explicitly
617 // therefore the order of this is !important!
618 const sortedModules = dependencies
619 .map(
620 dependency => /** @type {Module} */ (moduleGraph.getModule(dependency))
621 )
622 .filter(Boolean)
623 .sort(comparator);
624 /** @type {FakeMap} */
625 const fakeMap = Object.create(null);
626 for (const module of sortedModules) {
627 const exportsType = module.getExportsType(
628 moduleGraph,
629 this.options.namespaceObject === "strict"
630 );
631 const id = /** @type {ModuleId} */ (chunkGraph.getModuleId(module));
632 switch (exportsType) {
633 case "namespace":
634 fakeMap[id] = 9;
635 hasType |= 1;
636 break;
637 case "dynamic":
638 fakeMap[id] = 7;
639 hasType |= 2;
640 break;
641 case "default-only":
642 fakeMap[id] = 1;
643 hasType |= 4;
644 break;
645 case "default-with-named":
646 fakeMap[id] = 3;
647 hasType |= 8;
648 break;
649 default:
650 throw new Error(`Unexpected exports type ${exportsType}`);
651 }
652 }
653 if (hasType === 1) {
654 return 9;
655 }
656 if (hasType === 2) {
657 return 7;
658 }
659 if (hasType === 4) {
660 return 1;
661 }
662 if (hasType === 8) {
663 return 3;
664 }
665 if (hasType === 0) {
666 return 9;
667 }
668 return fakeMap;
669 }
670
671 /**
672 * @param {FakeMap | FakeMapType} fakeMap fake map
673 * @returns {string} fake map init statement
674 */
675 getFakeMapInitStatement(fakeMap) {
676 return typeof fakeMap === "object"
677 ? `var fakeMap = ${JSON.stringify(fakeMap, null, "\t")};`
678 : "";
679 }
680
681 /**
682 * @param {FakeMapType} type type
683 * @param {boolean=} asyncModule is async module
684 * @returns {string} return result
685 */
686 getReturn(type, asyncModule) {
687 if (type === 9) {
688 return `${RuntimeGlobals.require}(id)`;
689 }
690 return `${RuntimeGlobals.createFakeNamespaceObject}(id, ${type}${
691 asyncModule ? " | 16" : ""
692 })`;
693 }
694
695 /**
696 * @param {FakeMap | FakeMapType} fakeMap fake map
697 * @param {boolean=} asyncModule us async module
698 * @param {string=} fakeMapDataExpression fake map data expression
699 * @returns {string} module object source
700 */
701 getReturnModuleObjectSource(
702 fakeMap,
703 asyncModule,
704 fakeMapDataExpression = "fakeMap[id]"
705 ) {
706 if (typeof fakeMap === "number") {
707 return `return ${this.getReturn(fakeMap, asyncModule)};`;
708 }
709 return `return ${
710 RuntimeGlobals.createFakeNamespaceObject
711 }(id, ${fakeMapDataExpression}${asyncModule ? " | 16" : ""})`;
712 }
713
714 /**
715 * @param {Dependency[]} dependencies dependencies
716 * @param {ModuleId} id module id
717 * @param {ChunkGraph} chunkGraph the chunk graph
718 * @returns {string} source code
719 */
720 getSyncSource(dependencies, id, chunkGraph) {
721 const map = this.getUserRequestMap(dependencies, chunkGraph);
722 const fakeMap = this.getFakeMap(dependencies, chunkGraph);
723 const returnModuleObject = this.getReturnModuleObjectSource(fakeMap);
724
725 return `var map = ${JSON.stringify(map, null, "\t")};
726${this.getFakeMapInitStatement(fakeMap)}
727
728function webpackContext(req) {
729 var id = webpackContextResolve(req);
730 ${returnModuleObject}
731}
732function webpackContextResolve(req) {
733 if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
734 var e = new Error("Cannot find module '" + req + "'");
735 e.code = 'MODULE_NOT_FOUND';
736 throw e;
737 }
738 return map[req];
739}
740webpackContext.keys = function webpackContextKeys() {
741 return Object.keys(map);
742};
743webpackContext.resolve = webpackContextResolve;
744module.exports = webpackContext;
745webpackContext.id = ${JSON.stringify(id)};`;
746 }
747
748 /**
749 * @param {Dependency[]} dependencies dependencies
750 * @param {ModuleId} id module id
751 * @param {ChunkGraph} chunkGraph the chunk graph
752 * @returns {string} source code
753 */
754 getWeakSyncSource(dependencies, id, chunkGraph) {
755 const map = this.getUserRequestMap(dependencies, chunkGraph);
756 const fakeMap = this.getFakeMap(dependencies, chunkGraph);
757 const returnModuleObject = this.getReturnModuleObjectSource(fakeMap);
758
759 return `var map = ${JSON.stringify(map, null, "\t")};
760${this.getFakeMapInitStatement(fakeMap)}
761
762function webpackContext(req) {
763 var id = webpackContextResolve(req);
764 if(!${RuntimeGlobals.moduleFactories}[id]) {
765 var e = new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)");
766 e.code = 'MODULE_NOT_FOUND';
767 throw e;
768 }
769 ${returnModuleObject}
770}
771function webpackContextResolve(req) {
772 if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
773 var e = new Error("Cannot find module '" + req + "'");
774 e.code = 'MODULE_NOT_FOUND';
775 throw e;
776 }
777 return map[req];
778}
779webpackContext.keys = function webpackContextKeys() {
780 return Object.keys(map);
781};
782webpackContext.resolve = webpackContextResolve;
783webpackContext.id = ${JSON.stringify(id)};
784module.exports = webpackContext;`;
785 }
786
787 /**
788 * @param {Dependency[]} dependencies dependencies
789 * @param {ModuleId} id module id
790 * @param {object} context context
791 * @param {ChunkGraph} context.chunkGraph the chunk graph
792 * @param {RuntimeTemplate} context.runtimeTemplate the chunk graph
793 * @returns {string} source code
794 */
795 getAsyncWeakSource(dependencies, id, { chunkGraph, runtimeTemplate }) {
796 const arrow = runtimeTemplate.supportsArrowFunction();
797 const map = this.getUserRequestMap(dependencies, chunkGraph);
798 const fakeMap = this.getFakeMap(dependencies, chunkGraph);
799 const returnModuleObject = this.getReturnModuleObjectSource(fakeMap, true);
800
801 return `var map = ${JSON.stringify(map, null, "\t")};
802${this.getFakeMapInitStatement(fakeMap)}
803
804function webpackAsyncContext(req) {
805 return webpackAsyncContextResolve(req).then(${
806 arrow ? "id =>" : "function(id)"
807 } {
808 if(!${RuntimeGlobals.moduleFactories}[id]) {
809 var e = new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)");
810 e.code = 'MODULE_NOT_FOUND';
811 throw e;
812 }
813 ${returnModuleObject}
814 });
815}
816function webpackAsyncContextResolve(req) {
817 // Here Promise.resolve().then() is used instead of new Promise() to prevent
818 // uncaught exception popping up in devtools
819 return Promise.resolve().then(${arrow ? "() =>" : "function()"} {
820 if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
821 var e = new Error("Cannot find module '" + req + "'");
822 e.code = 'MODULE_NOT_FOUND';
823 throw e;
824 }
825 return map[req];
826 });
827}
828webpackAsyncContext.keys = ${runtimeTemplate.returningFunction(
829 "Object.keys(map)"
830 )};
831webpackAsyncContext.resolve = webpackAsyncContextResolve;
832webpackAsyncContext.id = ${JSON.stringify(id)};
833module.exports = webpackAsyncContext;`;
834 }
835
836 /**
837 * @param {Dependency[]} dependencies dependencies
838 * @param {ModuleId} id module id
839 * @param {object} context context
840 * @param {ChunkGraph} context.chunkGraph the chunk graph
841 * @param {RuntimeTemplate} context.runtimeTemplate the chunk graph
842 * @returns {string} source code
843 */
844 getEagerSource(dependencies, id, { chunkGraph, runtimeTemplate }) {
845 const arrow = runtimeTemplate.supportsArrowFunction();
846 const map = this.getUserRequestMap(dependencies, chunkGraph);
847 const fakeMap = this.getFakeMap(dependencies, chunkGraph);
848 const thenFunction =
849 fakeMap !== 9
850 ? `${arrow ? "id =>" : "function(id)"} {
851 ${this.getReturnModuleObjectSource(fakeMap, true)}
852 }`
853 : RuntimeGlobals.require;
854 return `var map = ${JSON.stringify(map, null, "\t")};
855${this.getFakeMapInitStatement(fakeMap)}
856
857function webpackAsyncContext(req) {
858 return webpackAsyncContextResolve(req).then(${thenFunction});
859}
860function webpackAsyncContextResolve(req) {
861 // Here Promise.resolve().then() is used instead of new Promise() to prevent
862 // uncaught exception popping up in devtools
863 return Promise.resolve().then(${arrow ? "() =>" : "function()"} {
864 if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
865 var e = new Error("Cannot find module '" + req + "'");
866 e.code = 'MODULE_NOT_FOUND';
867 throw e;
868 }
869 return map[req];
870 });
871}
872webpackAsyncContext.keys = ${runtimeTemplate.returningFunction(
873 "Object.keys(map)"
874 )};
875webpackAsyncContext.resolve = webpackAsyncContextResolve;
876webpackAsyncContext.id = ${JSON.stringify(id)};
877module.exports = webpackAsyncContext;`;
878 }
879
880 /**
881 * @param {AsyncDependenciesBlock} block block
882 * @param {Dependency[]} dependencies dependencies
883 * @param {ModuleId} id module id
884 * @param {object} options options object
885 * @param {RuntimeTemplate} options.runtimeTemplate the runtime template
886 * @param {ChunkGraph} options.chunkGraph the chunk graph
887 * @returns {string} source code
888 */
889 getLazyOnceSource(block, dependencies, id, { runtimeTemplate, chunkGraph }) {
890 const promise = runtimeTemplate.blockPromise({
891 chunkGraph,
892 block,
893 message: "lazy-once context",
894 runtimeRequirements: new Set()
895 });
896 const arrow = runtimeTemplate.supportsArrowFunction();
897 const map = this.getUserRequestMap(dependencies, chunkGraph);
898 const fakeMap = this.getFakeMap(dependencies, chunkGraph);
899 const thenFunction =
900 fakeMap !== 9
901 ? `${arrow ? "id =>" : "function(id)"} {
902 ${this.getReturnModuleObjectSource(fakeMap, true)};
903 }`
904 : RuntimeGlobals.require;
905
906 return `var map = ${JSON.stringify(map, null, "\t")};
907${this.getFakeMapInitStatement(fakeMap)}
908
909function webpackAsyncContext(req) {
910 return webpackAsyncContextResolve(req).then(${thenFunction});
911}
912function webpackAsyncContextResolve(req) {
913 return ${promise}.then(${arrow ? "() =>" : "function()"} {
914 if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
915 var e = new Error("Cannot find module '" + req + "'");
916 e.code = 'MODULE_NOT_FOUND';
917 throw e;
918 }
919 return map[req];
920 });
921}
922webpackAsyncContext.keys = ${runtimeTemplate.returningFunction(
923 "Object.keys(map)"
924 )};
925webpackAsyncContext.resolve = webpackAsyncContextResolve;
926webpackAsyncContext.id = ${JSON.stringify(id)};
927module.exports = webpackAsyncContext;`;
928 }
929
930 /**
931 * @param {AsyncDependenciesBlock[]} blocks blocks
932 * @param {ModuleId} id module id
933 * @param {object} context context
934 * @param {ChunkGraph} context.chunkGraph the chunk graph
935 * @param {RuntimeTemplate} context.runtimeTemplate the chunk graph
936 * @returns {string} source code
937 */
938 getLazySource(blocks, id, { chunkGraph, runtimeTemplate }) {
939 const moduleGraph = chunkGraph.moduleGraph;
940 const arrow = runtimeTemplate.supportsArrowFunction();
941 let hasMultipleOrNoChunks = false;
942 let hasNoChunk = true;
943 const fakeMap = this.getFakeMap(
944 blocks.map(b => b.dependencies[0]),
945 chunkGraph
946 );
947 const hasFakeMap = typeof fakeMap === "object";
948 /** @typedef {{userRequest: string, dependency: ContextElementDependency, chunks: undefined | Chunk[], module: Module, block: AsyncDependenciesBlock}} Item */
949 /**
950 * @type {Item[]}
951 */
952 const items = blocks
953 .map(block => {
954 const dependency =
955 /** @type {ContextElementDependency} */
956 (block.dependencies[0]);
957 return {
958 dependency,
959 module: /** @type {Module} */ (moduleGraph.getModule(dependency)),
960 block,
961 userRequest: dependency.userRequest,
962 chunks: undefined
963 };
964 })
965 .filter(item => item.module);
966 for (const item of items) {
967 const chunkGroup = chunkGraph.getBlockChunkGroup(item.block);
968 const chunks = (chunkGroup && chunkGroup.chunks) || [];
969 item.chunks = chunks;
970 if (chunks.length > 0) {
971 hasNoChunk = false;
972 }
973 if (chunks.length !== 1) {
974 hasMultipleOrNoChunks = true;
975 }
976 }
977 const shortMode = hasNoChunk && !hasFakeMap;
978 const sortedItems = items.sort((a, b) => {
979 if (a.userRequest === b.userRequest) return 0;
980 return a.userRequest < b.userRequest ? -1 : 1;
981 });
982 /** @type {Record<string, ModuleId | (ModuleId[] | ChunkId[])>} */
983 const map = Object.create(null);
984 for (const item of sortedItems) {
985 const moduleId =
986 /** @type {ModuleId} */
987 (chunkGraph.getModuleId(item.module));
988 if (shortMode) {
989 map[item.userRequest] = moduleId;
990 } else {
991 /** @type {(ModuleId | ChunkId)[]} */
992 const arrayStart = [moduleId];
993 if (hasFakeMap) {
994 arrayStart.push(fakeMap[moduleId]);
995 }
996 map[item.userRequest] = arrayStart.concat(
997 /** @type {Chunk[]} */
998 (item.chunks).map(chunk => /** @type {ChunkId} */ (chunk.id))
999 );
1000 }
1001 }
1002
1003 const chunksStartPosition = hasFakeMap ? 2 : 1;
1004 const requestPrefix = hasNoChunk
1005 ? "Promise.resolve()"
1006 : hasMultipleOrNoChunks
1007 ? `Promise.all(ids.slice(${chunksStartPosition}).map(${RuntimeGlobals.ensureChunk}))`
1008 : `${RuntimeGlobals.ensureChunk}(ids[${chunksStartPosition}])`;
1009 const returnModuleObject = this.getReturnModuleObjectSource(
1010 fakeMap,
1011 true,
1012 shortMode ? "invalid" : "ids[1]"
1013 );
1014
1015 const webpackAsyncContext =
1016 requestPrefix === "Promise.resolve()"
1017 ? `
1018function webpackAsyncContext(req) {
1019 return Promise.resolve().then(${arrow ? "() =>" : "function()"} {
1020 if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
1021 var e = new Error("Cannot find module '" + req + "'");
1022 e.code = 'MODULE_NOT_FOUND';
1023 throw e;
1024 }
1025
1026 ${shortMode ? "var id = map[req];" : "var ids = map[req], id = ids[0];"}
1027 ${returnModuleObject}
1028 });
1029}`
1030 : `function webpackAsyncContext(req) {
1031 if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {
1032 return Promise.resolve().then(${arrow ? "() =>" : "function()"} {
1033 var e = new Error("Cannot find module '" + req + "'");
1034 e.code = 'MODULE_NOT_FOUND';
1035 throw e;
1036 });
1037 }
1038
1039 var ids = map[req], id = ids[0];
1040 return ${requestPrefix}.then(${arrow ? "() =>" : "function()"} {
1041 ${returnModuleObject}
1042 });
1043}`;
1044
1045 return `var map = ${JSON.stringify(map, null, "\t")};
1046${webpackAsyncContext}
1047webpackAsyncContext.keys = ${runtimeTemplate.returningFunction(
1048 "Object.keys(map)"
1049 )};
1050webpackAsyncContext.id = ${JSON.stringify(id)};
1051module.exports = webpackAsyncContext;`;
1052 }
1053
1054 /**
1055 * @param {ModuleId} id module id
1056 * @param {RuntimeTemplate} runtimeTemplate runtime template
1057 * @returns {string} source for empty async context
1058 */
1059 getSourceForEmptyContext(id, runtimeTemplate) {
1060 return `function webpackEmptyContext(req) {
1061 var e = new Error("Cannot find module '" + req + "'");
1062 e.code = 'MODULE_NOT_FOUND';
1063 throw e;
1064}
1065webpackEmptyContext.keys = ${runtimeTemplate.returningFunction("[]")};
1066webpackEmptyContext.resolve = webpackEmptyContext;
1067webpackEmptyContext.id = ${JSON.stringify(id)};
1068module.exports = webpackEmptyContext;`;
1069 }
1070
1071 /**
1072 * @param {ModuleId} id module id
1073 * @param {RuntimeTemplate} runtimeTemplate runtime template
1074 * @returns {string} source for empty async context
1075 */
1076 getSourceForEmptyAsyncContext(id, runtimeTemplate) {
1077 const arrow = runtimeTemplate.supportsArrowFunction();
1078 return `function webpackEmptyAsyncContext(req) {
1079 // Here Promise.resolve().then() is used instead of new Promise() to prevent
1080 // uncaught exception popping up in devtools
1081 return Promise.resolve().then(${arrow ? "() =>" : "function()"} {
1082 var e = new Error("Cannot find module '" + req + "'");
1083 e.code = 'MODULE_NOT_FOUND';
1084 throw e;
1085 });
1086}
1087webpackEmptyAsyncContext.keys = ${runtimeTemplate.returningFunction("[]")};
1088webpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext;
1089webpackEmptyAsyncContext.id = ${JSON.stringify(id)};
1090module.exports = webpackEmptyAsyncContext;`;
1091 }
1092
1093 /**
1094 * @param {string} asyncMode module mode
1095 * @param {CodeGenerationContext} context context info
1096 * @returns {string} the source code
1097 */
1098 getSourceString(asyncMode, { runtimeTemplate, chunkGraph }) {
1099 const id = /** @type {ModuleId} */ (chunkGraph.getModuleId(this));
1100 if (asyncMode === "lazy") {
1101 if (this.blocks && this.blocks.length > 0) {
1102 return this.getLazySource(this.blocks, id, {
1103 runtimeTemplate,
1104 chunkGraph
1105 });
1106 }
1107 return this.getSourceForEmptyAsyncContext(id, runtimeTemplate);
1108 }
1109 if (asyncMode === "eager") {
1110 if (this.dependencies && this.dependencies.length > 0) {
1111 return this.getEagerSource(this.dependencies, id, {
1112 chunkGraph,
1113 runtimeTemplate
1114 });
1115 }
1116 return this.getSourceForEmptyAsyncContext(id, runtimeTemplate);
1117 }
1118 if (asyncMode === "lazy-once") {
1119 const block = this.blocks[0];
1120 if (block) {
1121 return this.getLazyOnceSource(block, block.dependencies, id, {
1122 runtimeTemplate,
1123 chunkGraph
1124 });
1125 }
1126 return this.getSourceForEmptyAsyncContext(id, runtimeTemplate);
1127 }
1128 if (asyncMode === "async-weak") {
1129 if (this.dependencies && this.dependencies.length > 0) {
1130 return this.getAsyncWeakSource(this.dependencies, id, {
1131 chunkGraph,
1132 runtimeTemplate
1133 });
1134 }
1135 return this.getSourceForEmptyAsyncContext(id, runtimeTemplate);
1136 }
1137 if (
1138 asyncMode === "weak" &&
1139 this.dependencies &&
1140 this.dependencies.length > 0
1141 ) {
1142 return this.getWeakSyncSource(this.dependencies, id, chunkGraph);
1143 }
1144 if (this.dependencies && this.dependencies.length > 0) {
1145 return this.getSyncSource(this.dependencies, id, chunkGraph);
1146 }
1147 return this.getSourceForEmptyContext(id, runtimeTemplate);
1148 }
1149
1150 /**
1151 * @param {string} sourceString source content
1152 * @param {Compilation=} compilation the compilation
1153 * @returns {Source} generated source
1154 */
1155 getSource(sourceString, compilation) {
1156 if (this.useSourceMap || this.useSimpleSourceMap) {
1157 return new OriginalSource(
1158 sourceString,
1159 `webpack://${makePathsRelative(
1160 (compilation && compilation.compiler.context) || "",
1161 this.identifier(),
1162 compilation && compilation.compiler.root
1163 )}`
1164 );
1165 }
1166 return new RawSource(sourceString);
1167 }
1168
1169 /**
1170 * @param {CodeGenerationContext} context context for code generation
1171 * @returns {CodeGenerationResult} result
1172 */
1173 codeGeneration(context) {
1174 const { chunkGraph, compilation } = context;
1175 const sources = new Map();
1176 sources.set(
1177 "javascript",
1178 this.getSource(
1179 this.getSourceString(this.options.mode, context),
1180 compilation
1181 )
1182 );
1183 const set = new Set();
1184 const allDeps =
1185 this.dependencies.length > 0
1186 ? /** @type {ContextElementDependency[]} */ (this.dependencies).slice()
1187 : [];
1188 for (const block of this.blocks)
1189 for (const dep of block.dependencies)
1190 allDeps.push(/** @type {ContextElementDependency} */ (dep));
1191 set.add(RuntimeGlobals.module);
1192 set.add(RuntimeGlobals.hasOwnProperty);
1193 if (allDeps.length > 0) {
1194 const asyncMode = this.options.mode;
1195 set.add(RuntimeGlobals.require);
1196 if (asyncMode === "weak") {
1197 set.add(RuntimeGlobals.moduleFactories);
1198 } else if (asyncMode === "async-weak") {
1199 set.add(RuntimeGlobals.moduleFactories);
1200 set.add(RuntimeGlobals.ensureChunk);
1201 } else if (asyncMode === "lazy" || asyncMode === "lazy-once") {
1202 set.add(RuntimeGlobals.ensureChunk);
1203 }
1204 if (this.getFakeMap(allDeps, chunkGraph) !== 9) {
1205 set.add(RuntimeGlobals.createFakeNamespaceObject);
1206 }
1207 }
1208 return {
1209 sources,
1210 runtimeRequirements: set
1211 };
1212 }
1213
1214 /**
1215 * @param {string=} type the source type for which the size should be estimated
1216 * @returns {number} the estimated size of the module (must be non-zero)
1217 */
1218 size(type) {
1219 // base penalty
1220 let size = 160;
1221
1222 // if we don't have dependencies we stop here.
1223 for (const dependency of this.dependencies) {
1224 const element = /** @type {ContextElementDependency} */ (dependency);
1225 size += 5 + element.userRequest.length;
1226 }
1227 return size;
1228 }
1229
1230 /**
1231 * @param {ObjectSerializerContext} context context
1232 */
1233 serialize(context) {
1234 const { write } = context;
1235 write(this._identifier);
1236 write(this._forceBuild);
1237 super.serialize(context);
1238 }
1239
1240 /**
1241 * @param {ObjectDeserializerContext} context context
1242 */
1243 deserialize(context) {
1244 const { read } = context;
1245 this._identifier = read();
1246 this._forceBuild = read();
1247 super.deserialize(context);
1248 }
1249}
1250
1251makeSerializable(ContextModule, "webpack/lib/ContextModule");
1252
1253module.exports = ContextModule;
Note: See TracBrowser for help on using the repository browser.