source: trip-planner-front/node_modules/webpack/lib/javascript/JavascriptModulesPlugin.js@ 59329aa

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

initial commit

  • Property mode set to 100644
File size: 42.3 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 { SyncWaterfallHook, SyncHook, SyncBailHook } = require("tapable");
9const vm = require("vm");
10const {
11 ConcatSource,
12 OriginalSource,
13 PrefixSource,
14 RawSource,
15 CachedSource
16} = require("webpack-sources");
17const Compilation = require("../Compilation");
18const { tryRunOrWebpackError } = require("../HookWebpackError");
19const HotUpdateChunk = require("../HotUpdateChunk");
20const InitFragment = require("../InitFragment");
21const RuntimeGlobals = require("../RuntimeGlobals");
22const Template = require("../Template");
23const { last, someInIterable } = require("../util/IterableHelpers");
24const StringXor = require("../util/StringXor");
25const { compareModulesByIdentifier } = require("../util/comparators");
26const createHash = require("../util/createHash");
27const { intersectRuntime } = require("../util/runtime");
28const JavascriptGenerator = require("./JavascriptGenerator");
29const JavascriptParser = require("./JavascriptParser");
30
31/** @typedef {import("webpack-sources").Source} Source */
32/** @typedef {import("../Chunk")} Chunk */
33/** @typedef {import("../ChunkGraph")} ChunkGraph */
34/** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
35/** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
36/** @typedef {import("../Compiler")} Compiler */
37/** @typedef {import("../DependencyTemplates")} DependencyTemplates */
38/** @typedef {import("../Module")} Module */
39/** @typedef {import("../ModuleGraph")} ModuleGraph */
40/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
41/** @typedef {import("../util/Hash")} Hash */
42
43/**
44 * @param {Chunk} chunk a chunk
45 * @param {ChunkGraph} chunkGraph the chunk graph
46 * @returns {boolean} true, when a JS file is needed for this chunk
47 */
48const chunkHasJs = (chunk, chunkGraph) => {
49 if (chunkGraph.getNumberOfEntryModules(chunk) > 0) return true;
50
51 return chunkGraph.getChunkModulesIterableBySourceType(chunk, "javascript")
52 ? true
53 : false;
54};
55
56const printGeneratedCodeForStack = (module, code) => {
57 const lines = code.split("\n");
58 const n = `${lines.length}`.length;
59 return `\n\nGenerated code for ${module.identifier()}\n${lines
60 .map((line, i, lines) => {
61 const iStr = `${i + 1}`;
62 return `${" ".repeat(n - iStr.length)}${iStr} | ${line}`;
63 })
64 .join("\n")}`;
65};
66
67/**
68 * @typedef {Object} RenderContext
69 * @property {Chunk} chunk the chunk
70 * @property {DependencyTemplates} dependencyTemplates the dependency templates
71 * @property {RuntimeTemplate} runtimeTemplate the runtime template
72 * @property {ModuleGraph} moduleGraph the module graph
73 * @property {ChunkGraph} chunkGraph the chunk graph
74 * @property {CodeGenerationResults} codeGenerationResults results of code generation
75 * @property {boolean} strictMode rendering in strict context
76 */
77
78/**
79 * @typedef {Object} MainRenderContext
80 * @property {Chunk} chunk the chunk
81 * @property {DependencyTemplates} dependencyTemplates the dependency templates
82 * @property {RuntimeTemplate} runtimeTemplate the runtime template
83 * @property {ModuleGraph} moduleGraph the module graph
84 * @property {ChunkGraph} chunkGraph the chunk graph
85 * @property {CodeGenerationResults} codeGenerationResults results of code generation
86 * @property {string} hash hash to be used for render call
87 * @property {boolean} strictMode rendering in strict context
88 */
89
90/**
91 * @typedef {Object} ChunkRenderContext
92 * @property {Chunk} chunk the chunk
93 * @property {DependencyTemplates} dependencyTemplates the dependency templates
94 * @property {RuntimeTemplate} runtimeTemplate the runtime template
95 * @property {ModuleGraph} moduleGraph the module graph
96 * @property {ChunkGraph} chunkGraph the chunk graph
97 * @property {CodeGenerationResults} codeGenerationResults results of code generation
98 * @property {InitFragment<ChunkRenderContext>[]} chunkInitFragments init fragments for the chunk
99 * @property {boolean} strictMode rendering in strict context
100 */
101
102/**
103 * @typedef {Object} RenderBootstrapContext
104 * @property {Chunk} chunk the chunk
105 * @property {RuntimeTemplate} runtimeTemplate the runtime template
106 * @property {ModuleGraph} moduleGraph the module graph
107 * @property {ChunkGraph} chunkGraph the chunk graph
108 * @property {string} hash hash to be used for render call
109 */
110
111/** @typedef {RenderContext & { inlined: boolean }} StartupRenderContext */
112
113/**
114 * @typedef {Object} CompilationHooks
115 * @property {SyncWaterfallHook<[Source, Module, ChunkRenderContext]>} renderModuleContent
116 * @property {SyncWaterfallHook<[Source, Module, ChunkRenderContext]>} renderModuleContainer
117 * @property {SyncWaterfallHook<[Source, Module, ChunkRenderContext]>} renderModulePackage
118 * @property {SyncWaterfallHook<[Source, RenderContext]>} renderChunk
119 * @property {SyncWaterfallHook<[Source, RenderContext]>} renderMain
120 * @property {SyncWaterfallHook<[Source, RenderContext]>} renderContent
121 * @property {SyncWaterfallHook<[Source, RenderContext]>} render
122 * @property {SyncWaterfallHook<[Source, Module, StartupRenderContext]>} renderStartup
123 * @property {SyncWaterfallHook<[string, RenderBootstrapContext]>} renderRequire
124 * @property {SyncBailHook<[Module, RenderBootstrapContext], string>} inlineInRuntimeBailout
125 * @property {SyncBailHook<[Module, RenderContext], string>} embedInRuntimeBailout
126 * @property {SyncBailHook<[RenderContext], string>} strictRuntimeBailout
127 * @property {SyncHook<[Chunk, Hash, ChunkHashContext]>} chunkHash
128 * @property {SyncBailHook<[Chunk, RenderContext], boolean>} useSourceMap
129 */
130
131/** @type {WeakMap<Compilation, CompilationHooks>} */
132const compilationHooksMap = new WeakMap();
133
134class JavascriptModulesPlugin {
135 /**
136 * @param {Compilation} compilation the compilation
137 * @returns {CompilationHooks} the attached hooks
138 */
139 static getCompilationHooks(compilation) {
140 if (!(compilation instanceof Compilation)) {
141 throw new TypeError(
142 "The 'compilation' argument must be an instance of Compilation"
143 );
144 }
145 let hooks = compilationHooksMap.get(compilation);
146 if (hooks === undefined) {
147 hooks = {
148 renderModuleContent: new SyncWaterfallHook([
149 "source",
150 "module",
151 "renderContext"
152 ]),
153 renderModuleContainer: new SyncWaterfallHook([
154 "source",
155 "module",
156 "renderContext"
157 ]),
158 renderModulePackage: new SyncWaterfallHook([
159 "source",
160 "module",
161 "renderContext"
162 ]),
163 render: new SyncWaterfallHook(["source", "renderContext"]),
164 renderContent: new SyncWaterfallHook(["source", "renderContext"]),
165 renderStartup: new SyncWaterfallHook([
166 "source",
167 "module",
168 "startupRenderContext"
169 ]),
170 renderChunk: new SyncWaterfallHook(["source", "renderContext"]),
171 renderMain: new SyncWaterfallHook(["source", "renderContext"]),
172 renderRequire: new SyncWaterfallHook(["code", "renderContext"]),
173 inlineInRuntimeBailout: new SyncBailHook(["module", "renderContext"]),
174 embedInRuntimeBailout: new SyncBailHook(["module", "renderContext"]),
175 strictRuntimeBailout: new SyncBailHook(["renderContext"]),
176 chunkHash: new SyncHook(["chunk", "hash", "context"]),
177 useSourceMap: new SyncBailHook(["chunk", "renderContext"])
178 };
179 compilationHooksMap.set(compilation, hooks);
180 }
181 return hooks;
182 }
183
184 constructor(options = {}) {
185 this.options = options;
186 /** @type {WeakMap<Source, TODO>} */
187 this._moduleFactoryCache = new WeakMap();
188 }
189
190 /**
191 * Apply the plugin
192 * @param {Compiler} compiler the compiler instance
193 * @returns {void}
194 */
195 apply(compiler) {
196 compiler.hooks.compilation.tap(
197 "JavascriptModulesPlugin",
198 (compilation, { normalModuleFactory }) => {
199 const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation);
200 normalModuleFactory.hooks.createParser
201 .for("javascript/auto")
202 .tap("JavascriptModulesPlugin", options => {
203 return new JavascriptParser("auto");
204 });
205 normalModuleFactory.hooks.createParser
206 .for("javascript/dynamic")
207 .tap("JavascriptModulesPlugin", options => {
208 return new JavascriptParser("script");
209 });
210 normalModuleFactory.hooks.createParser
211 .for("javascript/esm")
212 .tap("JavascriptModulesPlugin", options => {
213 return new JavascriptParser("module");
214 });
215 normalModuleFactory.hooks.createGenerator
216 .for("javascript/auto")
217 .tap("JavascriptModulesPlugin", () => {
218 return new JavascriptGenerator();
219 });
220 normalModuleFactory.hooks.createGenerator
221 .for("javascript/dynamic")
222 .tap("JavascriptModulesPlugin", () => {
223 return new JavascriptGenerator();
224 });
225 normalModuleFactory.hooks.createGenerator
226 .for("javascript/esm")
227 .tap("JavascriptModulesPlugin", () => {
228 return new JavascriptGenerator();
229 });
230 compilation.hooks.renderManifest.tap(
231 "JavascriptModulesPlugin",
232 (result, options) => {
233 const {
234 hash,
235 chunk,
236 chunkGraph,
237 moduleGraph,
238 runtimeTemplate,
239 dependencyTemplates,
240 outputOptions,
241 codeGenerationResults
242 } = options;
243
244 const hotUpdateChunk =
245 chunk instanceof HotUpdateChunk ? chunk : null;
246
247 let render;
248 const filenameTemplate =
249 JavascriptModulesPlugin.getChunkFilenameTemplate(
250 chunk,
251 outputOptions
252 );
253 if (hotUpdateChunk) {
254 render = () =>
255 this.renderChunk(
256 {
257 chunk,
258 dependencyTemplates,
259 runtimeTemplate,
260 moduleGraph,
261 chunkGraph,
262 codeGenerationResults,
263 strictMode: runtimeTemplate.isModule()
264 },
265 hooks
266 );
267 } else if (chunk.hasRuntime()) {
268 render = () =>
269 this.renderMain(
270 {
271 hash,
272 chunk,
273 dependencyTemplates,
274 runtimeTemplate,
275 moduleGraph,
276 chunkGraph,
277 codeGenerationResults,
278 strictMode: runtimeTemplate.isModule()
279 },
280 hooks,
281 compilation
282 );
283 } else {
284 if (!chunkHasJs(chunk, chunkGraph)) {
285 return result;
286 }
287
288 render = () =>
289 this.renderChunk(
290 {
291 chunk,
292 dependencyTemplates,
293 runtimeTemplate,
294 moduleGraph,
295 chunkGraph,
296 codeGenerationResults,
297 strictMode: runtimeTemplate.isModule()
298 },
299 hooks
300 );
301 }
302
303 result.push({
304 render,
305 filenameTemplate,
306 pathOptions: {
307 hash,
308 runtime: chunk.runtime,
309 chunk,
310 contentHashType: "javascript"
311 },
312 info: {
313 javascriptModule: compilation.runtimeTemplate.isModule()
314 },
315 identifier: hotUpdateChunk
316 ? `hotupdatechunk${chunk.id}`
317 : `chunk${chunk.id}`,
318 hash: chunk.contentHash.javascript
319 });
320
321 return result;
322 }
323 );
324 compilation.hooks.chunkHash.tap(
325 "JavascriptModulesPlugin",
326 (chunk, hash, context) => {
327 hooks.chunkHash.call(chunk, hash, context);
328 if (chunk.hasRuntime()) {
329 this.updateHashWithBootstrap(
330 hash,
331 {
332 hash: "0000",
333 chunk,
334 chunkGraph: context.chunkGraph,
335 moduleGraph: context.moduleGraph,
336 runtimeTemplate: context.runtimeTemplate
337 },
338 hooks
339 );
340 }
341 }
342 );
343 compilation.hooks.contentHash.tap("JavascriptModulesPlugin", chunk => {
344 const {
345 chunkGraph,
346 moduleGraph,
347 runtimeTemplate,
348 outputOptions: {
349 hashSalt,
350 hashDigest,
351 hashDigestLength,
352 hashFunction
353 }
354 } = compilation;
355 const hash = createHash(hashFunction);
356 if (hashSalt) hash.update(hashSalt);
357 if (chunk.hasRuntime()) {
358 this.updateHashWithBootstrap(
359 hash,
360 {
361 hash: "0000",
362 chunk,
363 chunkGraph: compilation.chunkGraph,
364 moduleGraph: compilation.moduleGraph,
365 runtimeTemplate: compilation.runtimeTemplate
366 },
367 hooks
368 );
369 } else {
370 hash.update(`${chunk.id} `);
371 hash.update(chunk.ids ? chunk.ids.join(",") : "");
372 }
373 hooks.chunkHash.call(chunk, hash, {
374 chunkGraph,
375 moduleGraph,
376 runtimeTemplate
377 });
378 const modules = chunkGraph.getChunkModulesIterableBySourceType(
379 chunk,
380 "javascript"
381 );
382 if (modules) {
383 const xor = new StringXor();
384 for (const m of modules) {
385 xor.add(chunkGraph.getModuleHash(m, chunk.runtime));
386 }
387 xor.updateHash(hash);
388 }
389 const runtimeModules = chunkGraph.getChunkModulesIterableBySourceType(
390 chunk,
391 "runtime"
392 );
393 if (runtimeModules) {
394 const xor = new StringXor();
395 for (const m of runtimeModules) {
396 xor.add(chunkGraph.getModuleHash(m, chunk.runtime));
397 }
398 xor.updateHash(hash);
399 }
400 const digest = /** @type {string} */ (hash.digest(hashDigest));
401 chunk.contentHash.javascript = digest.substr(0, hashDigestLength);
402 });
403 compilation.hooks.additionalTreeRuntimeRequirements.tap(
404 "JavascriptModulesPlugin",
405 (chunk, set, { chunkGraph }) => {
406 if (
407 !set.has(RuntimeGlobals.startupNoDefault) &&
408 chunkGraph.hasChunkEntryDependentChunks(chunk)
409 ) {
410 set.add(RuntimeGlobals.onChunksLoaded);
411 set.add(RuntimeGlobals.require);
412 }
413 }
414 );
415 compilation.hooks.executeModule.tap(
416 "JavascriptModulesPlugin",
417 (options, context) => {
418 const source =
419 options.codeGenerationResult.sources.get("javascript");
420 if (source === undefined) return;
421 const { module, moduleObject } = options;
422 const code = source.source();
423
424 const fn = vm.runInThisContext(
425 `(function(${module.moduleArgument}, ${module.exportsArgument}, __webpack_require__) {\n${code}\n/**/})`,
426 {
427 filename: module.identifier(),
428 lineOffset: -1
429 }
430 );
431 try {
432 fn.call(
433 moduleObject.exports,
434 moduleObject,
435 moduleObject.exports,
436 context.__webpack_require__
437 );
438 } catch (e) {
439 e.stack += printGeneratedCodeForStack(options.module, code);
440 throw e;
441 }
442 }
443 );
444 compilation.hooks.executeModule.tap(
445 "JavascriptModulesPlugin",
446 (options, context) => {
447 const source = options.codeGenerationResult.sources.get("runtime");
448 if (source === undefined) return;
449 let code = source.source();
450 if (typeof code !== "string") code = code.toString();
451
452 const fn = vm.runInThisContext(
453 `(function(__webpack_require__) {\n${code}\n/**/})`,
454 {
455 filename: options.module.identifier(),
456 lineOffset: -1
457 }
458 );
459 try {
460 fn.call(null, context.__webpack_require__);
461 } catch (e) {
462 e.stack += printGeneratedCodeForStack(options.module, code);
463 throw e;
464 }
465 }
466 );
467 }
468 );
469 }
470
471 static getChunkFilenameTemplate(chunk, outputOptions) {
472 if (chunk.filenameTemplate) {
473 return chunk.filenameTemplate;
474 } else if (chunk instanceof HotUpdateChunk) {
475 return outputOptions.hotUpdateChunkFilename;
476 } else if (chunk.canBeInitial()) {
477 return outputOptions.filename;
478 } else {
479 return outputOptions.chunkFilename;
480 }
481 }
482
483 /**
484 * @param {Module} module the rendered module
485 * @param {ChunkRenderContext} renderContext options object
486 * @param {CompilationHooks} hooks hooks
487 * @param {boolean} factory true: renders as factory method, false: pure module content
488 * @returns {Source} the newly generated source from rendering
489 */
490 renderModule(module, renderContext, hooks, factory) {
491 const {
492 chunk,
493 chunkGraph,
494 runtimeTemplate,
495 codeGenerationResults,
496 strictMode
497 } = renderContext;
498 try {
499 const codeGenResult = codeGenerationResults.get(module, chunk.runtime);
500 const moduleSource = codeGenResult.sources.get("javascript");
501 if (!moduleSource) return null;
502 if (codeGenResult.data !== undefined) {
503 const chunkInitFragments = codeGenResult.data.get("chunkInitFragments");
504 if (chunkInitFragments) {
505 for (const i of chunkInitFragments)
506 renderContext.chunkInitFragments.push(i);
507 }
508 }
509 const moduleSourcePostContent = tryRunOrWebpackError(
510 () =>
511 hooks.renderModuleContent.call(moduleSource, module, renderContext),
512 "JavascriptModulesPlugin.getCompilationHooks().renderModuleContent"
513 );
514 let moduleSourcePostContainer;
515 if (factory) {
516 const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
517 module,
518 chunk.runtime
519 );
520 const needModule = runtimeRequirements.has(RuntimeGlobals.module);
521 const needExports = runtimeRequirements.has(RuntimeGlobals.exports);
522 const needRequire =
523 runtimeRequirements.has(RuntimeGlobals.require) ||
524 runtimeRequirements.has(RuntimeGlobals.requireScope);
525 const needThisAsExports = runtimeRequirements.has(
526 RuntimeGlobals.thisAsExports
527 );
528 const needStrict = module.buildInfo.strict && !strictMode;
529 const cacheEntry = this._moduleFactoryCache.get(
530 moduleSourcePostContent
531 );
532 let source;
533 if (
534 cacheEntry &&
535 cacheEntry.needModule === needModule &&
536 cacheEntry.needExports === needExports &&
537 cacheEntry.needRequire === needRequire &&
538 cacheEntry.needThisAsExports === needThisAsExports &&
539 cacheEntry.needStrict === needStrict
540 ) {
541 source = cacheEntry.source;
542 } else {
543 const factorySource = new ConcatSource();
544 const args = [];
545 if (needExports || needRequire || needModule)
546 args.push(
547 needModule
548 ? module.moduleArgument
549 : "__unused_webpack_" + module.moduleArgument
550 );
551 if (needExports || needRequire)
552 args.push(
553 needExports
554 ? module.exportsArgument
555 : "__unused_webpack_" + module.exportsArgument
556 );
557 if (needRequire) args.push("__webpack_require__");
558 if (!needThisAsExports && runtimeTemplate.supportsArrowFunction()) {
559 factorySource.add("/***/ ((" + args.join(", ") + ") => {\n\n");
560 } else {
561 factorySource.add("/***/ (function(" + args.join(", ") + ") {\n\n");
562 }
563 if (needStrict) {
564 factorySource.add('"use strict";\n');
565 }
566 factorySource.add(moduleSourcePostContent);
567 factorySource.add("\n\n/***/ })");
568 source = new CachedSource(factorySource);
569 this._moduleFactoryCache.set(moduleSourcePostContent, {
570 source,
571 needModule,
572 needExports,
573 needRequire,
574 needThisAsExports,
575 needStrict
576 });
577 }
578 moduleSourcePostContainer = tryRunOrWebpackError(
579 () => hooks.renderModuleContainer.call(source, module, renderContext),
580 "JavascriptModulesPlugin.getCompilationHooks().renderModuleContainer"
581 );
582 } else {
583 moduleSourcePostContainer = moduleSourcePostContent;
584 }
585 return tryRunOrWebpackError(
586 () =>
587 hooks.renderModulePackage.call(
588 moduleSourcePostContainer,
589 module,
590 renderContext
591 ),
592 "JavascriptModulesPlugin.getCompilationHooks().renderModulePackage"
593 );
594 } catch (e) {
595 e.module = module;
596 throw e;
597 }
598 }
599
600 /**
601 * @param {RenderContext} renderContext the render context
602 * @param {CompilationHooks} hooks hooks
603 * @returns {Source} the rendered source
604 */
605 renderChunk(renderContext, hooks) {
606 const { chunk, chunkGraph } = renderContext;
607 const modules = chunkGraph.getOrderedChunkModulesIterableBySourceType(
608 chunk,
609 "javascript",
610 compareModulesByIdentifier
611 );
612 const allModules = modules ? Array.from(modules) : [];
613 let strictHeader;
614 let allStrict = renderContext.strictMode;
615 if (!allStrict && allModules.every(m => m.buildInfo.strict)) {
616 const strictBailout = hooks.strictRuntimeBailout.call(renderContext);
617 strictHeader = strictBailout
618 ? `// runtime can't be in strict mode because ${strictBailout}.\n`
619 : '"use strict";\n';
620 if (!strictBailout) allStrict = true;
621 }
622 /** @type {ChunkRenderContext} */
623 const chunkRenderContext = {
624 ...renderContext,
625 chunkInitFragments: [],
626 strictMode: allStrict
627 };
628 const moduleSources =
629 Template.renderChunkModules(chunkRenderContext, allModules, module =>
630 this.renderModule(module, chunkRenderContext, hooks, true)
631 ) || new RawSource("{}");
632 let source = tryRunOrWebpackError(
633 () => hooks.renderChunk.call(moduleSources, chunkRenderContext),
634 "JavascriptModulesPlugin.getCompilationHooks().renderChunk"
635 );
636 source = tryRunOrWebpackError(
637 () => hooks.renderContent.call(source, chunkRenderContext),
638 "JavascriptModulesPlugin.getCompilationHooks().renderContent"
639 );
640 if (!source) {
641 throw new Error(
642 "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().renderContent plugins should return something"
643 );
644 }
645 source = InitFragment.addToSource(
646 source,
647 chunkRenderContext.chunkInitFragments,
648 chunkRenderContext
649 );
650 source = tryRunOrWebpackError(
651 () => hooks.render.call(source, chunkRenderContext),
652 "JavascriptModulesPlugin.getCompilationHooks().render"
653 );
654 if (!source) {
655 throw new Error(
656 "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().render plugins should return something"
657 );
658 }
659 chunk.rendered = true;
660 return strictHeader
661 ? new ConcatSource(strictHeader, source, ";")
662 : renderContext.runtimeTemplate.isModule()
663 ? source
664 : new ConcatSource(source, ";");
665 }
666
667 /**
668 * @param {MainRenderContext} renderContext options object
669 * @param {CompilationHooks} hooks hooks
670 * @param {Compilation} compilation the compilation
671 * @returns {Source} the newly generated source from rendering
672 */
673 renderMain(renderContext, hooks, compilation) {
674 const { chunk, chunkGraph, runtimeTemplate } = renderContext;
675
676 const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
677 const iife = runtimeTemplate.isIIFE();
678
679 const bootstrap = this.renderBootstrap(renderContext, hooks);
680 const useSourceMap = hooks.useSourceMap.call(chunk, renderContext);
681
682 const allModules = Array.from(
683 chunkGraph.getOrderedChunkModulesIterableBySourceType(
684 chunk,
685 "javascript",
686 compareModulesByIdentifier
687 ) || []
688 );
689
690 const hasEntryModules = chunkGraph.getNumberOfEntryModules(chunk) > 0;
691 let inlinedModules;
692 if (bootstrap.allowInlineStartup && hasEntryModules) {
693 inlinedModules = new Set(chunkGraph.getChunkEntryModulesIterable(chunk));
694 }
695
696 let source = new ConcatSource();
697 let prefix;
698 if (iife) {
699 if (runtimeTemplate.supportsArrowFunction()) {
700 source.add("/******/ (() => { // webpackBootstrap\n");
701 } else {
702 source.add("/******/ (function() { // webpackBootstrap\n");
703 }
704 prefix = "/******/ \t";
705 } else {
706 prefix = "/******/ ";
707 }
708 let allStrict = renderContext.strictMode;
709 if (!allStrict && allModules.every(m => m.buildInfo.strict)) {
710 const strictBailout = hooks.strictRuntimeBailout.call(renderContext);
711 if (strictBailout) {
712 source.add(
713 prefix +
714 `// runtime can't be in strict mode because ${strictBailout}.\n`
715 );
716 } else {
717 allStrict = true;
718 source.add(prefix + '"use strict";\n');
719 }
720 }
721
722 /** @type {ChunkRenderContext} */
723 const chunkRenderContext = {
724 ...renderContext,
725 chunkInitFragments: [],
726 strictMode: allStrict
727 };
728
729 const chunkModules = Template.renderChunkModules(
730 chunkRenderContext,
731 inlinedModules
732 ? allModules.filter(m => !inlinedModules.has(m))
733 : allModules,
734 module => this.renderModule(module, chunkRenderContext, hooks, true),
735 prefix
736 );
737 if (
738 chunkModules ||
739 runtimeRequirements.has(RuntimeGlobals.moduleFactories) ||
740 runtimeRequirements.has(RuntimeGlobals.moduleFactoriesAddOnly) ||
741 runtimeRequirements.has(RuntimeGlobals.require)
742 ) {
743 source.add(prefix + "var __webpack_modules__ = (");
744 source.add(chunkModules || "{}");
745 source.add(");\n");
746 source.add(
747 "/************************************************************************/\n"
748 );
749 }
750
751 if (bootstrap.header.length > 0) {
752 const header = Template.asString(bootstrap.header) + "\n";
753 source.add(
754 new PrefixSource(
755 prefix,
756 useSourceMap
757 ? new OriginalSource(header, "webpack/bootstrap")
758 : new RawSource(header)
759 )
760 );
761 source.add(
762 "/************************************************************************/\n"
763 );
764 }
765
766 const runtimeModules =
767 renderContext.chunkGraph.getChunkRuntimeModulesInOrder(chunk);
768
769 if (runtimeModules.length > 0) {
770 source.add(
771 new PrefixSource(
772 prefix,
773 Template.renderRuntimeModules(runtimeModules, chunkRenderContext)
774 )
775 );
776 source.add(
777 "/************************************************************************/\n"
778 );
779 // runtimeRuntimeModules calls codeGeneration
780 for (const module of runtimeModules) {
781 compilation.codeGeneratedModules.add(module);
782 }
783 }
784 if (inlinedModules) {
785 if (bootstrap.beforeStartup.length > 0) {
786 const beforeStartup = Template.asString(bootstrap.beforeStartup) + "\n";
787 source.add(
788 new PrefixSource(
789 prefix,
790 useSourceMap
791 ? new OriginalSource(beforeStartup, "webpack/before-startup")
792 : new RawSource(beforeStartup)
793 )
794 );
795 }
796 const lastInlinedModule = last(inlinedModules);
797 const startupSource = new ConcatSource();
798 startupSource.add(`var __webpack_exports__ = {};\n`);
799 for (const m of inlinedModules) {
800 const renderedModule = this.renderModule(
801 m,
802 chunkRenderContext,
803 hooks,
804 false
805 );
806 if (renderedModule) {
807 const innerStrict = !allStrict && m.buildInfo.strict;
808 const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
809 m,
810 chunk.runtime
811 );
812 const exports = runtimeRequirements.has(RuntimeGlobals.exports);
813 const webpackExports =
814 exports && m.exportsArgument === "__webpack_exports__";
815 let iife = innerStrict
816 ? "it need to be in strict mode."
817 : inlinedModules.size > 1
818 ? // TODO check globals and top-level declarations of other entries and chunk modules
819 // to make a better decision
820 "it need to be isolated against other entry modules."
821 : chunkModules
822 ? "it need to be isolated against other modules in the chunk."
823 : exports && !webpackExports
824 ? `it uses a non-standard name for the exports (${m.exportsArgument}).`
825 : hooks.embedInRuntimeBailout.call(m, renderContext);
826 let footer;
827 if (iife !== undefined) {
828 startupSource.add(
829 `// This entry need to be wrapped in an IIFE because ${iife}\n`
830 );
831 const arrow = runtimeTemplate.supportsArrowFunction();
832 if (arrow) {
833 startupSource.add("(() => {\n");
834 footer = "\n})();\n\n";
835 } else {
836 startupSource.add("!function() {\n");
837 footer = "\n}();\n";
838 }
839 if (innerStrict) startupSource.add('"use strict";\n');
840 } else {
841 footer = "\n";
842 }
843 if (exports) {
844 if (m !== lastInlinedModule)
845 startupSource.add(`var ${m.exportsArgument} = {};\n`);
846 else if (m.exportsArgument !== "__webpack_exports__")
847 startupSource.add(
848 `var ${m.exportsArgument} = __webpack_exports__;\n`
849 );
850 }
851 startupSource.add(renderedModule);
852 startupSource.add(footer);
853 }
854 }
855 if (runtimeRequirements.has(RuntimeGlobals.onChunksLoaded)) {
856 startupSource.add(
857 `__webpack_exports__ = ${RuntimeGlobals.onChunksLoaded}(__webpack_exports__);\n`
858 );
859 }
860 source.add(
861 hooks.renderStartup.call(startupSource, lastInlinedModule, {
862 ...renderContext,
863 inlined: true
864 })
865 );
866 if (bootstrap.afterStartup.length > 0) {
867 const afterStartup = Template.asString(bootstrap.afterStartup) + "\n";
868 source.add(
869 new PrefixSource(
870 prefix,
871 useSourceMap
872 ? new OriginalSource(afterStartup, "webpack/after-startup")
873 : new RawSource(afterStartup)
874 )
875 );
876 }
877 } else {
878 const lastEntryModule = last(
879 chunkGraph.getChunkEntryModulesIterable(chunk)
880 );
881 const toSource = useSourceMap
882 ? (content, name) =>
883 new OriginalSource(Template.asString(content), name)
884 : content => new RawSource(Template.asString(content));
885 source.add(
886 new PrefixSource(
887 prefix,
888 new ConcatSource(
889 toSource(bootstrap.beforeStartup, "webpack/before-startup"),
890 "\n",
891 hooks.renderStartup.call(
892 toSource(bootstrap.startup.concat(""), "webpack/startup"),
893 lastEntryModule,
894 {
895 ...renderContext,
896 inlined: false
897 }
898 ),
899 toSource(bootstrap.afterStartup, "webpack/after-startup"),
900 "\n"
901 )
902 )
903 );
904 }
905 if (
906 hasEntryModules &&
907 runtimeRequirements.has(RuntimeGlobals.returnExportsFromRuntime)
908 ) {
909 source.add(`${prefix}return __webpack_exports__;\n`);
910 }
911 if (iife) {
912 source.add("/******/ })()\n");
913 }
914
915 /** @type {Source} */
916 let finalSource = tryRunOrWebpackError(
917 () => hooks.renderMain.call(source, renderContext),
918 "JavascriptModulesPlugin.getCompilationHooks().renderMain"
919 );
920 if (!finalSource) {
921 throw new Error(
922 "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().renderMain plugins should return something"
923 );
924 }
925 finalSource = tryRunOrWebpackError(
926 () => hooks.renderContent.call(finalSource, renderContext),
927 "JavascriptModulesPlugin.getCompilationHooks().renderContent"
928 );
929 if (!finalSource) {
930 throw new Error(
931 "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().renderContent plugins should return something"
932 );
933 }
934 finalSource = InitFragment.addToSource(
935 finalSource,
936 chunkRenderContext.chunkInitFragments,
937 chunkRenderContext
938 );
939 finalSource = tryRunOrWebpackError(
940 () => hooks.render.call(finalSource, renderContext),
941 "JavascriptModulesPlugin.getCompilationHooks().render"
942 );
943 if (!finalSource) {
944 throw new Error(
945 "JavascriptModulesPlugin error: JavascriptModulesPlugin.getCompilationHooks().render plugins should return something"
946 );
947 }
948 chunk.rendered = true;
949 return iife ? new ConcatSource(finalSource, ";") : finalSource;
950 }
951
952 /**
953 * @param {Hash} hash the hash to be updated
954 * @param {RenderBootstrapContext} renderContext options object
955 * @param {CompilationHooks} hooks hooks
956 */
957 updateHashWithBootstrap(hash, renderContext, hooks) {
958 const bootstrap = this.renderBootstrap(renderContext, hooks);
959 for (const key of Object.keys(bootstrap)) {
960 hash.update(key);
961 if (Array.isArray(bootstrap[key])) {
962 for (const line of bootstrap[key]) {
963 hash.update(line);
964 }
965 } else {
966 hash.update(JSON.stringify(bootstrap[key]));
967 }
968 }
969 }
970
971 /**
972 * @param {RenderBootstrapContext} renderContext options object
973 * @param {CompilationHooks} hooks hooks
974 * @returns {{ header: string[], beforeStartup: string[], startup: string[], afterStartup: string[], allowInlineStartup: boolean }} the generated source of the bootstrap code
975 */
976 renderBootstrap(renderContext, hooks) {
977 const { chunkGraph, moduleGraph, chunk, runtimeTemplate } = renderContext;
978
979 const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
980
981 const requireFunction = runtimeRequirements.has(RuntimeGlobals.require);
982 const moduleCache = runtimeRequirements.has(RuntimeGlobals.moduleCache);
983 const moduleFactories = runtimeRequirements.has(
984 RuntimeGlobals.moduleFactories
985 );
986 const moduleUsed = runtimeRequirements.has(RuntimeGlobals.module);
987 const requireScopeUsed = runtimeRequirements.has(
988 RuntimeGlobals.requireScope
989 );
990 const interceptModuleExecution = runtimeRequirements.has(
991 RuntimeGlobals.interceptModuleExecution
992 );
993
994 const useRequire =
995 requireFunction || interceptModuleExecution || moduleUsed;
996
997 const result = {
998 header: [],
999 beforeStartup: [],
1000 startup: [],
1001 afterStartup: [],
1002 allowInlineStartup: true
1003 };
1004
1005 let { header: buf, startup, beforeStartup, afterStartup } = result;
1006
1007 if (result.allowInlineStartup && moduleFactories) {
1008 startup.push(
1009 "// module factories are used so entry inlining is disabled"
1010 );
1011 result.allowInlineStartup = false;
1012 }
1013 if (result.allowInlineStartup && moduleCache) {
1014 startup.push("// module cache are used so entry inlining is disabled");
1015 result.allowInlineStartup = false;
1016 }
1017 if (result.allowInlineStartup && interceptModuleExecution) {
1018 startup.push(
1019 "// module execution is intercepted so entry inlining is disabled"
1020 );
1021 result.allowInlineStartup = false;
1022 }
1023
1024 if (useRequire || moduleCache) {
1025 buf.push("// The module cache");
1026 buf.push("var __webpack_module_cache__ = {};");
1027 buf.push("");
1028 }
1029
1030 if (useRequire) {
1031 buf.push("// The require function");
1032 buf.push(`function __webpack_require__(moduleId) {`);
1033 buf.push(Template.indent(this.renderRequire(renderContext, hooks)));
1034 buf.push("}");
1035 buf.push("");
1036 } else if (runtimeRequirements.has(RuntimeGlobals.requireScope)) {
1037 buf.push("// The require scope");
1038 buf.push("var __webpack_require__ = {};");
1039 buf.push("");
1040 }
1041
1042 if (
1043 moduleFactories ||
1044 runtimeRequirements.has(RuntimeGlobals.moduleFactoriesAddOnly)
1045 ) {
1046 buf.push("// expose the modules object (__webpack_modules__)");
1047 buf.push(`${RuntimeGlobals.moduleFactories} = __webpack_modules__;`);
1048 buf.push("");
1049 }
1050
1051 if (moduleCache) {
1052 buf.push("// expose the module cache");
1053 buf.push(`${RuntimeGlobals.moduleCache} = __webpack_module_cache__;`);
1054 buf.push("");
1055 }
1056
1057 if (interceptModuleExecution) {
1058 buf.push("// expose the module execution interceptor");
1059 buf.push(`${RuntimeGlobals.interceptModuleExecution} = [];`);
1060 buf.push("");
1061 }
1062
1063 if (!runtimeRequirements.has(RuntimeGlobals.startupNoDefault)) {
1064 if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
1065 /** @type {string[]} */
1066 const buf2 = [];
1067 const runtimeRequirements =
1068 chunkGraph.getTreeRuntimeRequirements(chunk);
1069 buf2.push("// Load entry module and return exports");
1070 let i = chunkGraph.getNumberOfEntryModules(chunk);
1071 for (const [
1072 entryModule,
1073 entrypoint
1074 ] of chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)) {
1075 const chunks = entrypoint.chunks.filter(c => c !== chunk);
1076 if (result.allowInlineStartup && chunks.length > 0) {
1077 buf2.push(
1078 "// This entry module depends on other loaded chunks and execution need to be delayed"
1079 );
1080 result.allowInlineStartup = false;
1081 }
1082 if (
1083 result.allowInlineStartup &&
1084 someInIterable(
1085 moduleGraph.getIncomingConnectionsByOriginModule(entryModule),
1086 ([originModule, connections]) =>
1087 originModule &&
1088 connections.some(c => c.isTargetActive(chunk.runtime)) &&
1089 someInIterable(
1090 chunkGraph.getModuleRuntimes(originModule),
1091 runtime =>
1092 intersectRuntime(runtime, chunk.runtime) !== undefined
1093 )
1094 )
1095 ) {
1096 buf2.push(
1097 "// This entry module is referenced by other modules so it can't be inlined"
1098 );
1099 result.allowInlineStartup = false;
1100 }
1101 if (
1102 result.allowInlineStartup &&
1103 (!entryModule.buildInfo ||
1104 !entryModule.buildInfo.topLevelDeclarations)
1105 ) {
1106 buf2.push(
1107 "// This entry module doesn't tell about it's top-level declarations so it can't be inlined"
1108 );
1109 result.allowInlineStartup = false;
1110 }
1111 if (result.allowInlineStartup) {
1112 const bailout = hooks.inlineInRuntimeBailout.call(
1113 entryModule,
1114 renderContext
1115 );
1116 if (bailout !== undefined) {
1117 buf2.push(
1118 `// This entry module can't be inlined because ${bailout}`
1119 );
1120 result.allowInlineStartup = false;
1121 }
1122 }
1123 i--;
1124 const moduleId = chunkGraph.getModuleId(entryModule);
1125 const entryRuntimeRequirements =
1126 chunkGraph.getModuleRuntimeRequirements(entryModule, chunk.runtime);
1127 let moduleIdExpr = JSON.stringify(moduleId);
1128 if (runtimeRequirements.has(RuntimeGlobals.entryModuleId)) {
1129 moduleIdExpr = `${RuntimeGlobals.entryModuleId} = ${moduleIdExpr}`;
1130 }
1131 if (
1132 result.allowInlineStartup &&
1133 entryRuntimeRequirements.has(RuntimeGlobals.module)
1134 ) {
1135 result.allowInlineStartup = false;
1136 buf2.push(
1137 "// This entry module used 'module' so it can't be inlined"
1138 );
1139 }
1140 if (chunks.length > 0) {
1141 buf2.push(
1142 `${i === 0 ? "var __webpack_exports__ = " : ""}${
1143 RuntimeGlobals.onChunksLoaded
1144 }(undefined, ${JSON.stringify(
1145 chunks.map(c => c.id)
1146 )}, ${runtimeTemplate.returningFunction(
1147 `__webpack_require__(${moduleIdExpr})`
1148 )})`
1149 );
1150 } else if (useRequire) {
1151 buf2.push(
1152 `${
1153 i === 0 ? "var __webpack_exports__ = " : ""
1154 }__webpack_require__(${moduleIdExpr});`
1155 );
1156 } else {
1157 if (i === 0) buf2.push("var __webpack_exports__ = {};");
1158 if (requireScopeUsed) {
1159 buf2.push(
1160 `__webpack_modules__[${moduleIdExpr}](0, ${
1161 i === 0 ? "__webpack_exports__" : "{}"
1162 }, __webpack_require__);`
1163 );
1164 } else if (entryRuntimeRequirements.has(RuntimeGlobals.exports)) {
1165 buf2.push(
1166 `__webpack_modules__[${moduleIdExpr}](0, ${
1167 i === 0 ? "__webpack_exports__" : "{}"
1168 });`
1169 );
1170 } else {
1171 buf2.push(`__webpack_modules__[${moduleIdExpr}]();`);
1172 }
1173 }
1174 }
1175 if (runtimeRequirements.has(RuntimeGlobals.onChunksLoaded)) {
1176 buf2.push(
1177 `__webpack_exports__ = ${RuntimeGlobals.onChunksLoaded}(__webpack_exports__);`
1178 );
1179 }
1180 if (
1181 runtimeRequirements.has(RuntimeGlobals.startup) ||
1182 (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) &&
1183 runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter))
1184 ) {
1185 result.allowInlineStartup = false;
1186 buf.push("// the startup function");
1187 buf.push(
1188 `${RuntimeGlobals.startup} = ${runtimeTemplate.basicFunction("", [
1189 ...buf2,
1190 "return __webpack_exports__;"
1191 ])};`
1192 );
1193 buf.push("");
1194 startup.push("// run startup");
1195 startup.push(
1196 `var __webpack_exports__ = ${RuntimeGlobals.startup}();`
1197 );
1198 } else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore)) {
1199 buf.push("// the startup function");
1200 buf.push(
1201 `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
1202 );
1203 beforeStartup.push("// run runtime startup");
1204 beforeStartup.push(`${RuntimeGlobals.startup}();`);
1205 startup.push("// startup");
1206 startup.push(Template.asString(buf2));
1207 } else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)) {
1208 buf.push("// the startup function");
1209 buf.push(
1210 `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
1211 );
1212 startup.push("// startup");
1213 startup.push(Template.asString(buf2));
1214 afterStartup.push("// run runtime startup");
1215 afterStartup.push(`${RuntimeGlobals.startup}();`);
1216 } else {
1217 startup.push("// startup");
1218 startup.push(Template.asString(buf2));
1219 }
1220 } else if (
1221 runtimeRequirements.has(RuntimeGlobals.startup) ||
1222 runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) ||
1223 runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)
1224 ) {
1225 buf.push(
1226 "// the startup function",
1227 "// It's empty as no entry modules are in this chunk",
1228 `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`,
1229 ""
1230 );
1231 }
1232 } else if (
1233 runtimeRequirements.has(RuntimeGlobals.startup) ||
1234 runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) ||
1235 runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)
1236 ) {
1237 result.allowInlineStartup = false;
1238 buf.push(
1239 "// the startup function",
1240 "// It's empty as some runtime module handles the default behavior",
1241 `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
1242 );
1243 startup.push("// run startup");
1244 startup.push(`var __webpack_exports__ = ${RuntimeGlobals.startup}();`);
1245 }
1246 return result;
1247 }
1248
1249 /**
1250 * @param {RenderBootstrapContext} renderContext options object
1251 * @param {CompilationHooks} hooks hooks
1252 * @returns {string} the generated source of the require function
1253 */
1254 renderRequire(renderContext, hooks) {
1255 const {
1256 chunk,
1257 chunkGraph,
1258 runtimeTemplate: { outputOptions }
1259 } = renderContext;
1260 const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
1261 const moduleExecution = runtimeRequirements.has(
1262 RuntimeGlobals.interceptModuleExecution
1263 )
1264 ? Template.asString([
1265 "var execOptions = { id: moduleId, module: module, factory: __webpack_modules__[moduleId], require: __webpack_require__ };",
1266 `${RuntimeGlobals.interceptModuleExecution}.forEach(function(handler) { handler(execOptions); });`,
1267 "module = execOptions.module;",
1268 "execOptions.factory.call(module.exports, module, module.exports, execOptions.require);"
1269 ])
1270 : runtimeRequirements.has(RuntimeGlobals.thisAsExports)
1271 ? Template.asString([
1272 "__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);"
1273 ])
1274 : Template.asString([
1275 "__webpack_modules__[moduleId](module, module.exports, __webpack_require__);"
1276 ]);
1277 const needModuleId = runtimeRequirements.has(RuntimeGlobals.moduleId);
1278 const needModuleLoaded = runtimeRequirements.has(
1279 RuntimeGlobals.moduleLoaded
1280 );
1281 const content = Template.asString([
1282 "// Check if module is in cache",
1283 "var cachedModule = __webpack_module_cache__[moduleId];",
1284 "if (cachedModule !== undefined) {",
1285 outputOptions.strictModuleErrorHandling
1286 ? Template.indent([
1287 "if (cachedModule.error !== undefined) throw cachedModule.error;",
1288 "return cachedModule.exports;"
1289 ])
1290 : Template.indent("return cachedModule.exports;"),
1291 "}",
1292 "// Create a new module (and put it into the cache)",
1293 "var module = __webpack_module_cache__[moduleId] = {",
1294 Template.indent([
1295 needModuleId ? "id: moduleId," : "// no module.id needed",
1296 needModuleLoaded ? "loaded: false," : "// no module.loaded needed",
1297 "exports: {}"
1298 ]),
1299 "};",
1300 "",
1301 outputOptions.strictModuleExceptionHandling
1302 ? Template.asString([
1303 "// Execute the module function",
1304 "var threw = true;",
1305 "try {",
1306 Template.indent([moduleExecution, "threw = false;"]),
1307 "} finally {",
1308 Template.indent([
1309 "if(threw) delete __webpack_module_cache__[moduleId];"
1310 ]),
1311 "}"
1312 ])
1313 : outputOptions.strictModuleErrorHandling
1314 ? Template.asString([
1315 "// Execute the module function",
1316 "try {",
1317 Template.indent(moduleExecution),
1318 "} catch(e) {",
1319 Template.indent(["module.error = e;", "throw e;"]),
1320 "}"
1321 ])
1322 : Template.asString([
1323 "// Execute the module function",
1324 moduleExecution
1325 ]),
1326 needModuleLoaded
1327 ? Template.asString([
1328 "",
1329 "// Flag the module as loaded",
1330 "module.loaded = true;",
1331 ""
1332 ])
1333 : "",
1334 "// Return the exports of the module",
1335 "return module.exports;"
1336 ]);
1337 return tryRunOrWebpackError(
1338 () => hooks.renderRequire.call(content, renderContext),
1339 "JavascriptModulesPlugin.getCompilationHooks().renderRequire"
1340 );
1341 }
1342}
1343
1344module.exports = JavascriptModulesPlugin;
1345module.exports.chunkHasJs = chunkHasJs;
Note: See TracBrowser for help on using the repository browser.