UNPKG

26 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const InitFragment = require("./InitFragment");
9const RuntimeGlobals = require("./RuntimeGlobals");
10const Template = require("./Template");
11const { equals } = require("./util/ArrayHelpers");
12const propertyAccess = require("./util/propertyAccess");
13
14/** @typedef {import("../declarations/WebpackOptions").OutputNormalized} OutputOptions */
15/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
16/** @typedef {import("./ChunkGraph")} ChunkGraph */
17/** @typedef {import("./Dependency")} Dependency */
18/** @typedef {import("./InitFragment")} InitFragment */
19/** @typedef {import("./Module")} Module */
20/** @typedef {import("./ModuleGraph")} ModuleGraph */
21/** @typedef {import("./RequestShortener")} RequestShortener */
22/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
23
24/**
25 * @param {Module} module the module
26 * @param {ChunkGraph} chunkGraph the chunk graph
27 * @returns {string} error message
28 */
29const noModuleIdErrorMessage = (module, chunkGraph) => {
30 return `Module ${module.identifier()} has no id assigned.
31This should not happen.
32It's in these chunks: ${
33 Array.from(
34 chunkGraph.getModuleChunksIterable(module),
35 c => c.name || c.id || c.debugId
36 ).join(", ") || "none"
37 } (If module is in no chunk this indicates a bug in some chunk/module optimization logic)
38Module has these incoming connections: ${Array.from(
39 chunkGraph.moduleGraph.getIncomingConnections(module),
40 connection =>
41 `\n - ${
42 connection.originModule && connection.originModule.identifier()
43 } ${connection.dependency && connection.dependency.type} ${
44 (connection.explanations &&
45 Array.from(connection.explanations).join(", ")) ||
46 ""
47 }`
48 ).join("")}`;
49};
50
51class RuntimeTemplate {
52 /**
53 * @param {OutputOptions} outputOptions the compilation output options
54 * @param {RequestShortener} requestShortener the request shortener
55 */
56 constructor(outputOptions, requestShortener) {
57 this.outputOptions = outputOptions || {};
58 /** @type {RequestShortener} */
59 this.requestShortener = requestShortener;
60 }
61
62 isIIFE() {
63 return this.outputOptions.iife;
64 }
65
66 supportsConst() {
67 return this.outputOptions.environment.const;
68 }
69
70 supportsArrowFunction() {
71 return this.outputOptions.environment.arrowFunction;
72 }
73
74 supportsForOf() {
75 return this.outputOptions.environment.forOf;
76 }
77
78 supportsDestructuring() {
79 return this.outputOptions.environment.destructuring;
80 }
81
82 supportsBigIntLiteral() {
83 return this.outputOptions.environment.bigIntLiteral;
84 }
85
86 supportsDynamicImport() {
87 return this.outputOptions.environment.dynamicImport;
88 }
89
90 supportsEcmaScriptModuleSyntax() {
91 return this.outputOptions.environment.module;
92 }
93
94 supportTemplateLiteral() {
95 // TODO
96 return false;
97 }
98
99 returningFunction(returnValue, args = "") {
100 return this.supportsArrowFunction()
101 ? `(${args}) => ${returnValue}`
102 : `function(${args}) { return ${returnValue}; }`;
103 }
104
105 basicFunction(args, body) {
106 return this.supportsArrowFunction()
107 ? `(${args}) => {\n${Template.indent(body)}\n}`
108 : `function(${args}) {\n${Template.indent(body)}\n}`;
109 }
110
111 destructureArray(items, value) {
112 return this.supportsDestructuring()
113 ? `var [${items.join(", ")}] = ${value};`
114 : Template.asString(
115 items.map((item, i) => `var ${item} = ${value}[${i}];`)
116 );
117 }
118
119 iife(args, body) {
120 return `(${this.basicFunction(args, body)})()`;
121 }
122
123 forEach(variable, array, body) {
124 return this.supportsForOf()
125 ? `for(const ${variable} of ${array}) {\n${Template.indent(body)}\n}`
126 : `${array}.forEach(function(${variable}) {\n${Template.indent(
127 body
128 )}\n});`;
129 }
130
131 /**
132 * Add a comment
133 * @param {object} options Information content of the comment
134 * @param {string=} options.request request string used originally
135 * @param {string=} options.chunkName name of the chunk referenced
136 * @param {string=} options.chunkReason reason information of the chunk
137 * @param {string=} options.message additional message
138 * @param {string=} options.exportName name of the export
139 * @returns {string} comment
140 */
141 comment({ request, chunkName, chunkReason, message, exportName }) {
142 let content;
143 if (this.outputOptions.pathinfo) {
144 content = [message, request, chunkName, chunkReason]
145 .filter(Boolean)
146 .map(item => this.requestShortener.shorten(item))
147 .join(" | ");
148 } else {
149 content = [message, chunkName, chunkReason]
150 .filter(Boolean)
151 .map(item => this.requestShortener.shorten(item))
152 .join(" | ");
153 }
154 if (!content) return "";
155 if (this.outputOptions.pathinfo) {
156 return Template.toComment(content) + " ";
157 } else {
158 return Template.toNormalComment(content) + " ";
159 }
160 }
161
162 /**
163 * @param {object} options generation options
164 * @param {string=} options.request request string used originally
165 * @returns {string} generated error block
166 */
167 throwMissingModuleErrorBlock({ request }) {
168 const err = `Cannot find module '${request}'`;
169 return `var e = new Error(${JSON.stringify(
170 err
171 )}); e.code = 'MODULE_NOT_FOUND'; throw e;`;
172 }
173
174 /**
175 * @param {object} options generation options
176 * @param {string=} options.request request string used originally
177 * @returns {string} generated error function
178 */
179 throwMissingModuleErrorFunction({ request }) {
180 return `function webpackMissingModule() { ${this.throwMissingModuleErrorBlock(
181 { request }
182 )} }`;
183 }
184
185 /**
186 * @param {object} options generation options
187 * @param {string=} options.request request string used originally
188 * @returns {string} generated error IIFE
189 */
190 missingModule({ request }) {
191 return `Object(${this.throwMissingModuleErrorFunction({ request })}())`;
192 }
193
194 /**
195 * @param {object} options generation options
196 * @param {string=} options.request request string used originally
197 * @returns {string} generated error statement
198 */
199 missingModuleStatement({ request }) {
200 return `${this.missingModule({ request })};\n`;
201 }
202
203 /**
204 * @param {object} options generation options
205 * @param {string=} options.request request string used originally
206 * @returns {string} generated error code
207 */
208 missingModulePromise({ request }) {
209 return `Promise.resolve().then(${this.throwMissingModuleErrorFunction({
210 request
211 })})`;
212 }
213
214 /**
215 * @param {Object} options options object
216 * @param {ChunkGraph} options.chunkGraph the chunk graph
217 * @param {Module} options.module the module
218 * @param {string} options.request the request that should be printed as comment
219 * @param {string=} options.idExpr expression to use as id expression
220 * @param {"expression" | "promise" | "statements"} options.type which kind of code should be returned
221 * @returns {string} the code
222 */
223 weakError({ module, chunkGraph, request, idExpr, type }) {
224 const moduleId = chunkGraph.getModuleId(module);
225 const errorMessage =
226 moduleId === null
227 ? JSON.stringify("Module is not available (weak dependency)")
228 : idExpr
229 ? `"Module '" + ${idExpr} + "' is not available (weak dependency)"`
230 : JSON.stringify(
231 `Module '${moduleId}' is not available (weak dependency)`
232 );
233 const comment = request ? Template.toNormalComment(request) + " " : "";
234 const errorStatements =
235 `var e = new Error(${errorMessage}); ` +
236 comment +
237 "e.code = 'MODULE_NOT_FOUND'; throw e;";
238 switch (type) {
239 case "statements":
240 return errorStatements;
241 case "promise":
242 return `Promise.resolve().then(${this.basicFunction(
243 "",
244 errorStatements
245 )})`;
246 case "expression":
247 return this.iife("", errorStatements);
248 }
249 }
250
251 /**
252 * @param {Object} options options object
253 * @param {Module} options.module the module
254 * @param {ChunkGraph} options.chunkGraph the chunk graph
255 * @param {string} options.request the request that should be printed as comment
256 * @param {boolean=} options.weak if the dependency is weak (will create a nice error message)
257 * @returns {string} the expression
258 */
259 moduleId({ module, chunkGraph, request, weak }) {
260 if (!module) {
261 return this.missingModule({
262 request
263 });
264 }
265 const moduleId = chunkGraph.getModuleId(module);
266 if (moduleId === null) {
267 if (weak) {
268 return "null /* weak dependency, without id */";
269 }
270 throw new Error(
271 `RuntimeTemplate.moduleId(): ${noModuleIdErrorMessage(
272 module,
273 chunkGraph
274 )}`
275 );
276 }
277 return `${this.comment({ request })}${JSON.stringify(moduleId)}`;
278 }
279
280 /**
281 * @param {Object} options options object
282 * @param {Module} options.module the module
283 * @param {ChunkGraph} options.chunkGraph the chunk graph
284 * @param {string} options.request the request that should be printed as comment
285 * @param {boolean=} options.weak if the dependency is weak (will create a nice error message)
286 * @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
287 * @returns {string} the expression
288 */
289 moduleRaw({ module, chunkGraph, request, weak, runtimeRequirements }) {
290 if (!module) {
291 return this.missingModule({
292 request
293 });
294 }
295 const moduleId = chunkGraph.getModuleId(module);
296 if (moduleId === null) {
297 if (weak) {
298 // only weak referenced modules don't get an id
299 // we can always emit an error emitting code here
300 return this.weakError({
301 module,
302 chunkGraph,
303 request,
304 type: "expression"
305 });
306 }
307 throw new Error(
308 `RuntimeTemplate.moduleId(): ${noModuleIdErrorMessage(
309 module,
310 chunkGraph
311 )}`
312 );
313 }
314 runtimeRequirements.add(RuntimeGlobals.require);
315 return `__webpack_require__(${this.moduleId({
316 module,
317 chunkGraph,
318 request,
319 weak
320 })})`;
321 }
322
323 /**
324 * @param {Object} options options object
325 * @param {Module} options.module the module
326 * @param {ChunkGraph} options.chunkGraph the chunk graph
327 * @param {string} options.request the request that should be printed as comment
328 * @param {boolean=} options.weak if the dependency is weak (will create a nice error message)
329 * @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
330 * @returns {string} the expression
331 */
332 moduleExports({ module, chunkGraph, request, weak, runtimeRequirements }) {
333 return this.moduleRaw({
334 module,
335 chunkGraph,
336 request,
337 weak,
338 runtimeRequirements
339 });
340 }
341
342 /**
343 * @param {Object} options options object
344 * @param {Module} options.module the module
345 * @param {ChunkGraph} options.chunkGraph the chunk graph
346 * @param {string} options.request the request that should be printed as comment
347 * @param {boolean=} options.strict if the current module is in strict esm mode
348 * @param {boolean=} options.weak if the dependency is weak (will create a nice error message)
349 * @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
350 * @returns {string} the expression
351 */
352 moduleNamespace({
353 module,
354 chunkGraph,
355 request,
356 strict,
357 weak,
358 runtimeRequirements
359 }) {
360 if (!module) {
361 return this.missingModule({
362 request
363 });
364 }
365 if (chunkGraph.getModuleId(module) === null) {
366 if (weak) {
367 // only weak referenced modules don't get an id
368 // we can always emit an error emitting code here
369 return this.weakError({
370 module,
371 chunkGraph,
372 request,
373 type: "expression"
374 });
375 }
376 throw new Error(
377 `RuntimeTemplate.moduleNamespace(): ${noModuleIdErrorMessage(
378 module,
379 chunkGraph
380 )}`
381 );
382 }
383 const moduleId = this.moduleId({
384 module,
385 chunkGraph,
386 request,
387 weak
388 });
389 const exportsType = module.getExportsType(chunkGraph.moduleGraph, strict);
390 switch (exportsType) {
391 case "namespace":
392 return this.moduleRaw({
393 module,
394 chunkGraph,
395 request,
396 weak,
397 runtimeRequirements
398 });
399 case "default-with-named":
400 runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
401 return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 3)`;
402 case "default-only":
403 runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
404 return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 1)`;
405 case "dynamic":
406 runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
407 return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 7)`;
408 }
409 }
410
411 /**
412 * @param {Object} options options object
413 * @param {ChunkGraph} options.chunkGraph the chunk graph
414 * @param {AsyncDependenciesBlock=} options.block the current dependencies block
415 * @param {Module} options.module the module
416 * @param {string} options.request the request that should be printed as comment
417 * @param {string} options.message a message for the comment
418 * @param {boolean=} options.strict if the current module is in strict esm mode
419 * @param {boolean=} options.weak if the dependency is weak (will create a nice error message)
420 * @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
421 * @returns {string} the promise expression
422 */
423 moduleNamespacePromise({
424 chunkGraph,
425 block,
426 module,
427 request,
428 message,
429 strict,
430 weak,
431 runtimeRequirements
432 }) {
433 if (!module) {
434 return this.missingModulePromise({
435 request
436 });
437 }
438 const moduleId = chunkGraph.getModuleId(module);
439 if (moduleId === null) {
440 if (weak) {
441 // only weak referenced modules don't get an id
442 // we can always emit an error emitting code here
443 return this.weakError({
444 module,
445 chunkGraph,
446 request,
447 type: "promise"
448 });
449 }
450 throw new Error(
451 `RuntimeTemplate.moduleNamespacePromise(): ${noModuleIdErrorMessage(
452 module,
453 chunkGraph
454 )}`
455 );
456 }
457 const promise = this.blockPromise({
458 chunkGraph,
459 block,
460 message,
461 runtimeRequirements
462 });
463
464 let appending;
465 let idExpr = JSON.stringify(chunkGraph.getModuleId(module));
466 const comment = this.comment({
467 request
468 });
469 let header = "";
470 if (weak) {
471 if (idExpr.length > 8) {
472 // 'var x="nnnnnn";x,"+x+",x' vs '"nnnnnn",nnnnnn,"nnnnnn"'
473 header += `var id = ${idExpr}; `;
474 idExpr = "id";
475 }
476 runtimeRequirements.add(RuntimeGlobals.moduleFactories);
477 header += `if(!${
478 RuntimeGlobals.moduleFactories
479 }[${idExpr}]) { ${this.weakError({
480 module,
481 chunkGraph,
482 request,
483 idExpr,
484 type: "statements"
485 })} } `;
486 }
487 const moduleIdExpr = this.moduleId({
488 module,
489 chunkGraph,
490 request,
491 weak
492 });
493 const exportsType = module.getExportsType(chunkGraph.moduleGraph, strict);
494 let fakeType = 0;
495 switch (exportsType) {
496 case "namespace":
497 if (header) {
498 const rawModule = this.moduleRaw({
499 module,
500 chunkGraph,
501 request,
502 weak,
503 runtimeRequirements
504 });
505 appending = `.then(${this.basicFunction(
506 "",
507 `${header}return ${rawModule};`
508 )})`;
509 } else {
510 runtimeRequirements.add(RuntimeGlobals.require);
511 appending = `.then(__webpack_require__.bind(__webpack_require__, ${comment}${idExpr}))`;
512 }
513 break;
514 case "dynamic":
515 fakeType |= 4;
516 /* fall through */
517 case "default-with-named":
518 fakeType |= 2;
519 /* fall through */
520 case "default-only":
521 runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
522 if (chunkGraph.moduleGraph.isAsync(module)) {
523 if (header) {
524 const rawModule = this.moduleRaw({
525 module,
526 chunkGraph,
527 request,
528 weak,
529 runtimeRequirements
530 });
531 appending = `.then(${this.basicFunction(
532 "",
533 `${header}return ${rawModule};`
534 )})`;
535 } else {
536 runtimeRequirements.add(RuntimeGlobals.require);
537 appending = `.then(__webpack_require__.bind(__webpack_require__, ${comment}${idExpr}))`;
538 }
539 appending += `.then(${this.returningFunction(
540 `${RuntimeGlobals.createFakeNamespaceObject}(m, ${fakeType})`,
541 "m"
542 )})`;
543 } else {
544 fakeType |= 1;
545 if (header) {
546 const returnExpression = `${RuntimeGlobals.createFakeNamespaceObject}(${moduleIdExpr}, ${fakeType})`;
547 appending = `.then(${this.basicFunction(
548 "",
549 `${header}return ${returnExpression};`
550 )})`;
551 } else {
552 appending = `.then(${RuntimeGlobals.createFakeNamespaceObject}.bind(__webpack_require__, ${comment}${idExpr}, ${fakeType}))`;
553 }
554 }
555 break;
556 }
557
558 return `${promise || "Promise.resolve()"}${appending}`;
559 }
560
561 /**
562 *
563 * @param {Object} options options object
564 * @param {boolean=} options.update whether a new variable should be created or the existing one updated
565 * @param {Module} options.module the module
566 * @param {ChunkGraph} options.chunkGraph the chunk graph
567 * @param {string} options.request the request that should be printed as comment
568 * @param {string} options.importVar name of the import variable
569 * @param {Module} options.originModule module in which the statement is emitted
570 * @param {boolean=} options.weak true, if this is a weak dependency
571 * @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
572 * @returns {[string, string]} the import statement and the compat statement
573 */
574 importStatement({
575 update,
576 module,
577 chunkGraph,
578 request,
579 importVar,
580 originModule,
581 weak,
582 runtimeRequirements
583 }) {
584 if (!module) {
585 return [
586 this.missingModuleStatement({
587 request
588 }),
589 ""
590 ];
591 }
592 if (chunkGraph.getModuleId(module) === null) {
593 if (weak) {
594 // only weak referenced modules don't get an id
595 // we can always emit an error emitting code here
596 return [
597 this.weakError({
598 module,
599 chunkGraph,
600 request,
601 type: "statements"
602 }),
603 ""
604 ];
605 }
606 throw new Error(
607 `RuntimeTemplate.importStatement(): ${noModuleIdErrorMessage(
608 module,
609 chunkGraph
610 )}`
611 );
612 }
613 const moduleId = this.moduleId({
614 module,
615 chunkGraph,
616 request,
617 weak
618 });
619 const optDeclaration = update ? "" : "var ";
620
621 const exportsType = module.getExportsType(
622 chunkGraph.moduleGraph,
623 originModule.buildMeta.strictHarmonyModule
624 );
625 runtimeRequirements.add(RuntimeGlobals.require);
626 const importContent = `/* harmony import */ ${optDeclaration}${importVar} = __webpack_require__(${moduleId});\n`;
627
628 if (exportsType === "dynamic") {
629 runtimeRequirements.add(RuntimeGlobals.compatGetDefaultExport);
630 return [
631 importContent,
632 `/* harmony import */ ${optDeclaration}${importVar}_default = /*#__PURE__*/${RuntimeGlobals.compatGetDefaultExport}(${importVar});\n`
633 ];
634 }
635 return [importContent, ""];
636 }
637
638 /**
639 * @param {Object} options options
640 * @param {ModuleGraph} options.moduleGraph the module graph
641 * @param {Module} options.module the module
642 * @param {string} options.request the request
643 * @param {string | string[]} options.exportName the export name
644 * @param {Module} options.originModule the origin module
645 * @param {boolean|undefined} options.asiSafe true, if location is safe for ASI, a bracket can be emitted
646 * @param {boolean} options.isCall true, if expression will be called
647 * @param {boolean} options.callContext when false, call context will not be preserved
648 * @param {boolean} options.defaultInterop when true and accessing the default exports, interop code will be generated
649 * @param {string} options.importVar the identifier name of the import variable
650 * @param {InitFragment[]} options.initFragments init fragments will be added here
651 * @param {RuntimeSpec} options.runtime runtime for which this code will be generated
652 * @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
653 * @returns {string} expression
654 */
655 exportFromImport({
656 moduleGraph,
657 module,
658 request,
659 exportName,
660 originModule,
661 asiSafe,
662 isCall,
663 callContext,
664 defaultInterop,
665 importVar,
666 initFragments,
667 runtime,
668 runtimeRequirements
669 }) {
670 if (!module) {
671 return this.missingModule({
672 request
673 });
674 }
675 if (!Array.isArray(exportName)) {
676 exportName = exportName ? [exportName] : [];
677 }
678 const exportsType = module.getExportsType(
679 moduleGraph,
680 originModule.buildMeta.strictHarmonyModule
681 );
682
683 if (defaultInterop) {
684 if (exportName.length > 0 && exportName[0] === "default") {
685 switch (exportsType) {
686 case "dynamic":
687 if (isCall) {
688 return `${importVar}_default()${propertyAccess(exportName, 1)}`;
689 } else {
690 return asiSafe
691 ? `(${importVar}_default()${propertyAccess(exportName, 1)})`
692 : asiSafe === false
693 ? `;(${importVar}_default()${propertyAccess(exportName, 1)})`
694 : `${importVar}_default.a${propertyAccess(exportName, 1)}`;
695 }
696 case "default-only":
697 case "default-with-named":
698 exportName = exportName.slice(1);
699 break;
700 }
701 } else if (exportName.length > 0) {
702 if (exportsType === "default-only") {
703 return (
704 "/* non-default import from non-esm module */undefined" +
705 propertyAccess(exportName, 1)
706 );
707 }
708 } else if (
709 exportsType === "default-only" ||
710 exportsType === "default-with-named"
711 ) {
712 runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
713 initFragments.push(
714 new InitFragment(
715 `var ${importVar}_namespace_cache;\n`,
716 InitFragment.STAGE_CONSTANTS,
717 -1,
718 `${importVar}_namespace_cache`
719 )
720 );
721 return `/*#__PURE__*/ ${
722 asiSafe ? "" : asiSafe === false ? ";" : "Object"
723 }(${importVar}_namespace_cache || (${importVar}_namespace_cache = ${
724 RuntimeGlobals.createFakeNamespaceObject
725 }(${importVar}${exportsType === "default-only" ? "" : ", 2"})))`;
726 }
727 }
728
729 if (exportName.length > 0) {
730 const exportsInfo = moduleGraph.getExportsInfo(module);
731 const used = exportsInfo.getUsedName(exportName, runtime);
732 if (!used) {
733 const comment = Template.toNormalComment(
734 `unused export ${propertyAccess(exportName)}`
735 );
736 return `${comment} undefined`;
737 }
738 const comment = equals(used, exportName)
739 ? ""
740 : Template.toNormalComment(propertyAccess(exportName)) + " ";
741 const access = `${importVar}${comment}${propertyAccess(used)}`;
742 if (isCall && callContext === false) {
743 return asiSafe
744 ? `(0,${access})`
745 : asiSafe === false
746 ? `;(0,${access})`
747 : `Object(${access})`;
748 }
749 return access;
750 } else {
751 return importVar;
752 }
753 }
754
755 /**
756 * @param {Object} options options
757 * @param {AsyncDependenciesBlock} options.block the async block
758 * @param {string} options.message the message
759 * @param {ChunkGraph} options.chunkGraph the chunk graph
760 * @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
761 * @returns {string} expression
762 */
763 blockPromise({ block, message, chunkGraph, runtimeRequirements }) {
764 if (!block) {
765 const comment = this.comment({
766 message
767 });
768 return `Promise.resolve(${comment.trim()})`;
769 }
770 const chunkGroup = chunkGraph.getBlockChunkGroup(block);
771 if (!chunkGroup || chunkGroup.chunks.length === 0) {
772 const comment = this.comment({
773 message
774 });
775 return `Promise.resolve(${comment.trim()})`;
776 }
777 const chunks = chunkGroup.chunks.filter(
778 chunk => !chunk.hasRuntime() && chunk.id !== null
779 );
780 const comment = this.comment({
781 message,
782 chunkName: block.chunkName
783 });
784 if (chunks.length === 1) {
785 const chunkId = JSON.stringify(chunks[0].id);
786 runtimeRequirements.add(RuntimeGlobals.ensureChunk);
787 return `${RuntimeGlobals.ensureChunk}(${comment}${chunkId})`;
788 } else if (chunks.length > 0) {
789 runtimeRequirements.add(RuntimeGlobals.ensureChunk);
790 const requireChunkId = chunk =>
791 `${RuntimeGlobals.ensureChunk}(${JSON.stringify(chunk.id)})`;
792 return `Promise.all(${comment.trim()}[${chunks
793 .map(requireChunkId)
794 .join(", ")}])`;
795 } else {
796 return `Promise.resolve(${comment.trim()})`;
797 }
798 }
799
800 /**
801 * @param {Object} options options
802 * @param {AsyncDependenciesBlock} options.block the async block
803 * @param {ChunkGraph} options.chunkGraph the chunk graph
804 * @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
805 * @param {string=} options.request request string used originally
806 * @returns {string} expression
807 */
808 asyncModuleFactory({ block, chunkGraph, runtimeRequirements, request }) {
809 const dep = block.dependencies[0];
810 const module = chunkGraph.moduleGraph.getModule(dep);
811 const ensureChunk = this.blockPromise({
812 block,
813 message: "",
814 chunkGraph,
815 runtimeRequirements
816 });
817 const factory = this.returningFunction(
818 this.moduleRaw({
819 module,
820 chunkGraph,
821 request,
822 runtimeRequirements
823 })
824 );
825 return this.returningFunction(
826 ensureChunk.startsWith("Promise.resolve(")
827 ? `${factory}`
828 : `${ensureChunk}.then(${this.returningFunction(factory)})`
829 );
830 }
831
832 /**
833 * @param {Object} options options
834 * @param {Dependency} options.dependency the dependency
835 * @param {ChunkGraph} options.chunkGraph the chunk graph
836 * @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
837 * @param {string=} options.request request string used originally
838 * @returns {string} expression
839 */
840 syncModuleFactory({ dependency, chunkGraph, runtimeRequirements, request }) {
841 const module = chunkGraph.moduleGraph.getModule(dependency);
842 const factory = this.returningFunction(
843 this.moduleRaw({
844 module,
845 chunkGraph,
846 request,
847 runtimeRequirements
848 })
849 );
850 return this.returningFunction(factory);
851 }
852
853 /**
854 * @param {Object} options options
855 * @param {string} options.exportsArgument the name of the exports object
856 * @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
857 * @returns {string} statement
858 */
859 defineEsModuleFlagStatement({ exportsArgument, runtimeRequirements }) {
860 runtimeRequirements.add(RuntimeGlobals.makeNamespaceObject);
861 runtimeRequirements.add(RuntimeGlobals.exports);
862 return `${RuntimeGlobals.makeNamespaceObject}(${exportsArgument});\n`;
863 }
864}
865
866module.exports = RuntimeTemplate;