source: imaps-frontend/node_modules/webpack/lib/RuntimeTemplate.js

main
Last change on this file was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 4 days ago

F4 Finalna Verzija

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