UNPKG

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