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