UNPKG

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