UNPKG

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