1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135 |
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
- */
- "use strict";
- const InitFragment = require("./InitFragment");
- const RuntimeGlobals = require("./RuntimeGlobals");
- const Template = require("./Template");
- const { equals } = require("./util/ArrayHelpers");
- const compileBooleanMatcher = require("./util/compileBooleanMatcher");
- const propertyAccess = require("./util/propertyAccess");
- const { forEachRuntime, subtractRuntime } = require("./util/runtime");
- /** @typedef {import("../declarations/WebpackOptions").Environment} Environment */
- /** @typedef {import("../declarations/WebpackOptions").OutputNormalized} OutputOptions */
- /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
- /** @typedef {import("./Chunk")} Chunk */
- /** @typedef {import("./ChunkGraph")} ChunkGraph */
- /** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */
- /** @typedef {import("./CodeGenerationResults").CodeGenerationResult} CodeGenerationResult */
- /** @typedef {import("./Compilation")} Compilation */
- /** @typedef {import("./Dependency")} Dependency */
- /** @typedef {import("./Module")} Module */
- /** @typedef {import("./Module").BuildMeta} BuildMeta */
- /** @typedef {import("./Module").RuntimeRequirements} RuntimeRequirements */
- /** @typedef {import("./ModuleGraph")} ModuleGraph */
- /** @typedef {import("./RequestShortener")} RequestShortener */
- /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
- /**
- * @param {Module} module the module
- * @param {ChunkGraph} chunkGraph the chunk graph
- * @returns {string} error message
- */
- const noModuleIdErrorMessage = (module, chunkGraph) => {
- return `Module ${module.identifier()} has no id assigned.
- This should not happen.
- It's in these chunks: ${
- Array.from(
- chunkGraph.getModuleChunksIterable(module),
- c => c.name || c.id || c.debugId
- ).join(", ") || "none"
- } (If module is in no chunk this indicates a bug in some chunk/module optimization logic)
- Module has these incoming connections: ${Array.from(
- chunkGraph.moduleGraph.getIncomingConnections(module),
- connection =>
- `\n - ${
- connection.originModule && connection.originModule.identifier()
- } ${connection.dependency && connection.dependency.type} ${
- (connection.explanations &&
- Array.from(connection.explanations).join(", ")) ||
- ""
- }`
- ).join("")}`;
- };
- /**
- * @param {string | undefined} definition global object definition
- * @returns {string | undefined} save to use global object
- */
- function getGlobalObject(definition) {
- if (!definition) return definition;
- const trimmed = definition.trim();
- if (
- // identifier, we do not need real identifier regarding ECMAScript/Unicode
- trimmed.match(/^[_\p{L}][_0-9\p{L}]*$/iu) ||
- // iife
- // call expression
- // expression in parentheses
- trimmed.match(/^([_\p{L}][_0-9\p{L}]*)?\(.*\)$/iu)
- )
- return trimmed;
- return `Object(${trimmed})`;
- }
- class RuntimeTemplate {
- /**
- * @param {Compilation} compilation the compilation
- * @param {OutputOptions} outputOptions the compilation output options
- * @param {RequestShortener} requestShortener the request shortener
- */
- constructor(compilation, outputOptions, requestShortener) {
- this.compilation = compilation;
- this.outputOptions = outputOptions || {};
- this.requestShortener = requestShortener;
- this.globalObject =
- /** @type {string} */
- (getGlobalObject(outputOptions.globalObject));
- this.contentHashReplacement = "X".repeat(
- /** @type {NonNullable<OutputOptions["hashDigestLength"]>} */
- (outputOptions.hashDigestLength)
- );
- }
- isIIFE() {
- return this.outputOptions.iife;
- }
- isModule() {
- return this.outputOptions.module;
- }
- supportsConst() {
- return /** @type {Environment} */ (this.outputOptions.environment).const;
- }
- supportsArrowFunction() {
- return /** @type {Environment} */ (this.outputOptions.environment)
- .arrowFunction;
- }
- supportsAsyncFunction() {
- return /** @type {Environment} */ (this.outputOptions.environment)
- .asyncFunction;
- }
- supportsOptionalChaining() {
- return /** @type {Environment} */ (this.outputOptions.environment)
- .optionalChaining;
- }
- supportsForOf() {
- return /** @type {Environment} */ (this.outputOptions.environment).forOf;
- }
- supportsDestructuring() {
- return /** @type {Environment} */ (this.outputOptions.environment)
- .destructuring;
- }
- supportsBigIntLiteral() {
- return /** @type {Environment} */ (this.outputOptions.environment)
- .bigIntLiteral;
- }
- supportsDynamicImport() {
- return /** @type {Environment} */ (this.outputOptions.environment)
- .dynamicImport;
- }
- supportsEcmaScriptModuleSyntax() {
- return /** @type {Environment} */ (this.outputOptions.environment).module;
- }
- supportTemplateLiteral() {
- return /** @type {Environment} */ (this.outputOptions.environment)
- .templateLiteral;
- }
- supportNodePrefixForCoreModules() {
- return /** @type {Environment} */ (this.outputOptions.environment)
- .nodePrefixForCoreModules;
- }
- /**
- * @param {string} returnValue return value
- * @param {string} args arguments
- * @returns {string} returning function
- */
- returningFunction(returnValue, args = "") {
- return this.supportsArrowFunction()
- ? `(${args}) => (${returnValue})`
- : `function(${args}) { return ${returnValue}; }`;
- }
- /**
- * @param {string} args arguments
- * @param {string | string[]} body body
- * @returns {string} basic function
- */
- basicFunction(args, body) {
- return this.supportsArrowFunction()
- ? `(${args}) => {\n${Template.indent(body)}\n}`
- : `function(${args}) {\n${Template.indent(body)}\n}`;
- }
- /**
- * @param {Array<string|{expr: string}>} args args
- * @returns {string} result expression
- */
- concatenation(...args) {
- const len = args.length;
- if (len === 2) return this._es5Concatenation(args);
- if (len === 0) return '""';
- if (len === 1) {
- return typeof args[0] === "string"
- ? JSON.stringify(args[0])
- : `"" + ${args[0].expr}`;
- }
- if (!this.supportTemplateLiteral()) return this._es5Concatenation(args);
- // cost comparison between template literal and concatenation:
- // both need equal surroundings: `xxx` vs "xxx"
- // template literal has constant cost of 3 chars for each expression
- // es5 concatenation has cost of 3 + n chars for n expressions in row
- // when a es5 concatenation ends with an expression it reduces cost by 3
- // when a es5 concatenation starts with an single expression it reduces cost by 3
- // e. g. `${a}${b}${c}` (3*3 = 9) is longer than ""+a+b+c ((3+3)-3 = 3)
- // 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)
- let templateCost = 0;
- let concatenationCost = 0;
- let lastWasExpr = false;
- for (const arg of args) {
- const isExpr = typeof arg !== "string";
- if (isExpr) {
- templateCost += 3;
- concatenationCost += lastWasExpr ? 1 : 4;
- }
- lastWasExpr = isExpr;
- }
- if (lastWasExpr) concatenationCost -= 3;
- if (typeof args[0] !== "string" && typeof args[1] === "string")
- concatenationCost -= 3;
- if (concatenationCost <= templateCost) return this._es5Concatenation(args);
- return `\`${args
- .map(arg => (typeof arg === "string" ? arg : `\${${arg.expr}}`))
- .join("")}\``;
- }
- /**
- * @param {Array<string|{expr: string}>} args args (len >= 2)
- * @returns {string} result expression
- * @private
- */
- _es5Concatenation(args) {
- const str = args
- .map(arg => (typeof arg === "string" ? JSON.stringify(arg) : arg.expr))
- .join(" + ");
- // when the first two args are expression, we need to prepend "" + to force string
- // concatenation instead of number addition.
- return typeof args[0] !== "string" && typeof args[1] !== "string"
- ? `"" + ${str}`
- : str;
- }
- /**
- * @param {string} expression expression
- * @param {string} args arguments
- * @returns {string} expression function code
- */
- expressionFunction(expression, args = "") {
- return this.supportsArrowFunction()
- ? `(${args}) => (${expression})`
- : `function(${args}) { ${expression}; }`;
- }
- /**
- * @returns {string} empty function code
- */
- emptyFunction() {
- return this.supportsArrowFunction() ? "x => {}" : "function() {}";
- }
- /**
- * @param {string[]} items items
- * @param {string} value value
- * @returns {string} destructure array code
- */
- destructureArray(items, value) {
- return this.supportsDestructuring()
- ? `var [${items.join(", ")}] = ${value};`
- : Template.asString(
- items.map((item, i) => `var ${item} = ${value}[${i}];`)
- );
- }
- /**
- * @param {string[]} items items
- * @param {string} value value
- * @returns {string} destructure object code
- */
- destructureObject(items, value) {
- return this.supportsDestructuring()
- ? `var {${items.join(", ")}} = ${value};`
- : Template.asString(
- items.map(item => `var ${item} = ${value}${propertyAccess([item])};`)
- );
- }
- /**
- * @param {string} args arguments
- * @param {string} body body
- * @returns {string} IIFE code
- */
- iife(args, body) {
- return `(${this.basicFunction(args, body)})()`;
- }
- /**
- * @param {string} variable variable
- * @param {string} array array
- * @param {string | string[]} body body
- * @returns {string} for each code
- */
- forEach(variable, array, body) {
- return this.supportsForOf()
- ? `for(const ${variable} of ${array}) {\n${Template.indent(body)}\n}`
- : `${array}.forEach(function(${variable}) {\n${Template.indent(
- body
- )}\n});`;
- }
- /**
- * Add a comment
- * @param {object} options Information content of the comment
- * @param {string=} options.request request string used originally
- * @param {string=} options.chunkName name of the chunk referenced
- * @param {string=} options.chunkReason reason information of the chunk
- * @param {string=} options.message additional message
- * @param {string=} options.exportName name of the export
- * @returns {string} comment
- */
- comment({ request, chunkName, chunkReason, message, exportName }) {
- let content;
- if (this.outputOptions.pathinfo) {
- content = [message, request, chunkName, chunkReason]
- .filter(Boolean)
- .map(item => this.requestShortener.shorten(item))
- .join(" | ");
- } else {
- content = [message, chunkName, chunkReason]
- .filter(Boolean)
- .map(item => this.requestShortener.shorten(item))
- .join(" | ");
- }
- if (!content) return "";
- if (this.outputOptions.pathinfo) {
- return Template.toComment(content) + " ";
- } else {
- return Template.toNormalComment(content) + " ";
- }
- }
- /**
- * @param {object} options generation options
- * @param {string=} options.request request string used originally
- * @returns {string} generated error block
- */
- throwMissingModuleErrorBlock({ request }) {
- const err = `Cannot find module '${request}'`;
- return `var e = new Error(${JSON.stringify(
- err
- )}); e.code = 'MODULE_NOT_FOUND'; throw e;`;
- }
- /**
- * @param {object} options generation options
- * @param {string=} options.request request string used originally
- * @returns {string} generated error function
- */
- throwMissingModuleErrorFunction({ request }) {
- return `function webpackMissingModule() { ${this.throwMissingModuleErrorBlock(
- { request }
- )} }`;
- }
- /**
- * @param {object} options generation options
- * @param {string=} options.request request string used originally
- * @returns {string} generated error IIFE
- */
- missingModule({ request }) {
- return `Object(${this.throwMissingModuleErrorFunction({ request })}())`;
- }
- /**
- * @param {object} options generation options
- * @param {string=} options.request request string used originally
- * @returns {string} generated error statement
- */
- missingModuleStatement({ request }) {
- return `${this.missingModule({ request })};\n`;
- }
- /**
- * @param {object} options generation options
- * @param {string=} options.request request string used originally
- * @returns {string} generated error code
- */
- missingModulePromise({ request }) {
- return `Promise.resolve().then(${this.throwMissingModuleErrorFunction({
- request
- })})`;
- }
- /**
- * @param {object} options options object
- * @param {ChunkGraph} options.chunkGraph the chunk graph
- * @param {Module} options.module the module
- * @param {string=} options.request the request that should be printed as comment
- * @param {string=} options.idExpr expression to use as id expression
- * @param {"expression" | "promise" | "statements"} options.type which kind of code should be returned
- * @returns {string} the code
- */
- weakError({ module, chunkGraph, request, idExpr, type }) {
- const moduleId = chunkGraph.getModuleId(module);
- const errorMessage =
- moduleId === null
- ? JSON.stringify("Module is not available (weak dependency)")
- : idExpr
- ? `"Module '" + ${idExpr} + "' is not available (weak dependency)"`
- : JSON.stringify(
- `Module '${moduleId}' is not available (weak dependency)`
- );
- const comment = request ? Template.toNormalComment(request) + " " : "";
- const errorStatements =
- `var e = new Error(${errorMessage}); ` +
- comment +
- "e.code = 'MODULE_NOT_FOUND'; throw e;";
- switch (type) {
- case "statements":
- return errorStatements;
- case "promise":
- return `Promise.resolve().then(${this.basicFunction(
- "",
- errorStatements
- )})`;
- case "expression":
- return this.iife("", errorStatements);
- }
- }
- /**
- * @param {object} options options object
- * @param {Module} options.module the module
- * @param {ChunkGraph} options.chunkGraph the chunk graph
- * @param {string=} options.request the request that should be printed as comment
- * @param {boolean=} options.weak if the dependency is weak (will create a nice error message)
- * @returns {string} the expression
- */
- moduleId({ module, chunkGraph, request, weak }) {
- if (!module) {
- return this.missingModule({
- request
- });
- }
- const moduleId = chunkGraph.getModuleId(module);
- if (moduleId === null) {
- if (weak) {
- return "null /* weak dependency, without id */";
- }
- throw new Error(
- `RuntimeTemplate.moduleId(): ${noModuleIdErrorMessage(
- module,
- chunkGraph
- )}`
- );
- }
- return `${this.comment({ request })}${JSON.stringify(moduleId)}`;
- }
- /**
- * @param {object} options options object
- * @param {Module | null} options.module the module
- * @param {ChunkGraph} options.chunkGraph the chunk graph
- * @param {string=} options.request the request that should be printed as comment
- * @param {boolean=} options.weak if the dependency is weak (will create a nice error message)
- * @param {RuntimeRequirements} options.runtimeRequirements if set, will be filled with runtime requirements
- * @returns {string} the expression
- */
- moduleRaw({ module, chunkGraph, request, weak, runtimeRequirements }) {
- if (!module) {
- return this.missingModule({
- request
- });
- }
- const moduleId = chunkGraph.getModuleId(module);
- if (moduleId === null) {
- if (weak) {
- // only weak referenced modules don't get an id
- // we can always emit an error emitting code here
- return this.weakError({
- module,
- chunkGraph,
- request,
- type: "expression"
- });
- }
- throw new Error(
- `RuntimeTemplate.moduleId(): ${noModuleIdErrorMessage(
- module,
- chunkGraph
- )}`
- );
- }
- runtimeRequirements.add(RuntimeGlobals.require);
- return `${RuntimeGlobals.require}(${this.moduleId({
- module,
- chunkGraph,
- request,
- weak
- })})`;
- }
- /**
- * @param {object} options options object
- * @param {Module | null} options.module the module
- * @param {ChunkGraph} options.chunkGraph the chunk graph
- * @param {string} options.request the request that should be printed as comment
- * @param {boolean=} options.weak if the dependency is weak (will create a nice error message)
- * @param {RuntimeRequirements} options.runtimeRequirements if set, will be filled with runtime requirements
- * @returns {string} the expression
- */
- moduleExports({ module, chunkGraph, request, weak, runtimeRequirements }) {
- return this.moduleRaw({
- module,
- chunkGraph,
- request,
- weak,
- runtimeRequirements
- });
- }
- /**
- * @param {object} options options object
- * @param {Module} options.module the module
- * @param {ChunkGraph} options.chunkGraph the chunk graph
- * @param {string} options.request the request that should be printed as comment
- * @param {boolean=} options.strict if the current module is in strict esm mode
- * @param {boolean=} options.weak if the dependency is weak (will create a nice error message)
- * @param {RuntimeRequirements} options.runtimeRequirements if set, will be filled with runtime requirements
- * @returns {string} the expression
- */
- moduleNamespace({
- module,
- chunkGraph,
- request,
- strict,
- weak,
- runtimeRequirements
- }) {
- if (!module) {
- return this.missingModule({
- request
- });
- }
- if (chunkGraph.getModuleId(module) === null) {
- if (weak) {
- // only weak referenced modules don't get an id
- // we can always emit an error emitting code here
- return this.weakError({
- module,
- chunkGraph,
- request,
- type: "expression"
- });
- }
- throw new Error(
- `RuntimeTemplate.moduleNamespace(): ${noModuleIdErrorMessage(
- module,
- chunkGraph
- )}`
- );
- }
- const moduleId = this.moduleId({
- module,
- chunkGraph,
- request,
- weak
- });
- const exportsType = module.getExportsType(chunkGraph.moduleGraph, strict);
- switch (exportsType) {
- case "namespace":
- return this.moduleRaw({
- module,
- chunkGraph,
- request,
- weak,
- runtimeRequirements
- });
- case "default-with-named":
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
- return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 3)`;
- case "default-only":
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
- return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 1)`;
- case "dynamic":
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
- return `${RuntimeGlobals.createFakeNamespaceObject}(${moduleId}, 7)`;
- }
- }
- /**
- * @param {object} options options object
- * @param {ChunkGraph} options.chunkGraph the chunk graph
- * @param {AsyncDependenciesBlock=} options.block the current dependencies block
- * @param {Module} options.module the module
- * @param {string} options.request the request that should be printed as comment
- * @param {string} options.message a message for the comment
- * @param {boolean=} options.strict if the current module is in strict esm mode
- * @param {boolean=} options.weak if the dependency is weak (will create a nice error message)
- * @param {RuntimeRequirements} options.runtimeRequirements if set, will be filled with runtime requirements
- * @returns {string} the promise expression
- */
- moduleNamespacePromise({
- chunkGraph,
- block,
- module,
- request,
- message,
- strict,
- weak,
- runtimeRequirements
- }) {
- if (!module) {
- return this.missingModulePromise({
- request
- });
- }
- const moduleId = chunkGraph.getModuleId(module);
- if (moduleId === null) {
- if (weak) {
- // only weak referenced modules don't get an id
- // we can always emit an error emitting code here
- return this.weakError({
- module,
- chunkGraph,
- request,
- type: "promise"
- });
- }
- throw new Error(
- `RuntimeTemplate.moduleNamespacePromise(): ${noModuleIdErrorMessage(
- module,
- chunkGraph
- )}`
- );
- }
- const promise = this.blockPromise({
- chunkGraph,
- block,
- message,
- runtimeRequirements
- });
- let appending;
- let idExpr = JSON.stringify(chunkGraph.getModuleId(module));
- const comment = this.comment({
- request
- });
- let header = "";
- if (weak) {
- if (idExpr.length > 8) {
- // 'var x="nnnnnn";x,"+x+",x' vs '"nnnnnn",nnnnnn,"nnnnnn"'
- header += `var id = ${idExpr}; `;
- idExpr = "id";
- }
- runtimeRequirements.add(RuntimeGlobals.moduleFactories);
- header += `if(!${
- RuntimeGlobals.moduleFactories
- }[${idExpr}]) { ${this.weakError({
- module,
- chunkGraph,
- request,
- idExpr,
- type: "statements"
- })} } `;
- }
- const moduleIdExpr = this.moduleId({
- module,
- chunkGraph,
- request,
- weak
- });
- const exportsType = module.getExportsType(chunkGraph.moduleGraph, strict);
- let fakeType = 16;
- switch (exportsType) {
- case "namespace":
- if (header) {
- const rawModule = this.moduleRaw({
- module,
- chunkGraph,
- request,
- weak,
- runtimeRequirements
- });
- appending = `.then(${this.basicFunction(
- "",
- `${header}return ${rawModule};`
- )})`;
- } else {
- runtimeRequirements.add(RuntimeGlobals.require);
- appending = `.then(${RuntimeGlobals.require}.bind(${RuntimeGlobals.require}, ${comment}${idExpr}))`;
- }
- break;
- case "dynamic":
- fakeType |= 4;
- /* fall through */
- case "default-with-named":
- fakeType |= 2;
- /* fall through */
- case "default-only":
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
- if (chunkGraph.moduleGraph.isAsync(module)) {
- if (header) {
- const rawModule = this.moduleRaw({
- module,
- chunkGraph,
- request,
- weak,
- runtimeRequirements
- });
- appending = `.then(${this.basicFunction(
- "",
- `${header}return ${rawModule};`
- )})`;
- } else {
- runtimeRequirements.add(RuntimeGlobals.require);
- appending = `.then(${RuntimeGlobals.require}.bind(${RuntimeGlobals.require}, ${comment}${idExpr}))`;
- }
- appending += `.then(${this.returningFunction(
- `${RuntimeGlobals.createFakeNamespaceObject}(m, ${fakeType})`,
- "m"
- )})`;
- } else {
- fakeType |= 1;
- if (header) {
- const returnExpression = `${RuntimeGlobals.createFakeNamespaceObject}(${moduleIdExpr}, ${fakeType})`;
- appending = `.then(${this.basicFunction(
- "",
- `${header}return ${returnExpression};`
- )})`;
- } else {
- appending = `.then(${RuntimeGlobals.createFakeNamespaceObject}.bind(${RuntimeGlobals.require}, ${comment}${idExpr}, ${fakeType}))`;
- }
- }
- break;
- }
- return `${promise || "Promise.resolve()"}${appending}`;
- }
- /**
- * @param {object} options options object
- * @param {ChunkGraph} options.chunkGraph the chunk graph
- * @param {RuntimeSpec=} options.runtime runtime for which this code will be generated
- * @param {RuntimeSpec | boolean=} options.runtimeCondition only execute the statement in some runtimes
- * @param {RuntimeRequirements} options.runtimeRequirements if set, will be filled with runtime requirements
- * @returns {string} expression
- */
- runtimeConditionExpression({
- chunkGraph,
- runtimeCondition,
- runtime,
- runtimeRequirements
- }) {
- if (runtimeCondition === undefined) return "true";
- if (typeof runtimeCondition === "boolean") return `${runtimeCondition}`;
- /** @type {Set<string>} */
- const positiveRuntimeIds = new Set();
- forEachRuntime(runtimeCondition, runtime =>
- positiveRuntimeIds.add(
- `${chunkGraph.getRuntimeId(/** @type {string} */ (runtime))}`
- )
- );
- /** @type {Set<string>} */
- const negativeRuntimeIds = new Set();
- forEachRuntime(subtractRuntime(runtime, runtimeCondition), runtime =>
- negativeRuntimeIds.add(
- `${chunkGraph.getRuntimeId(/** @type {string} */ (runtime))}`
- )
- );
- runtimeRequirements.add(RuntimeGlobals.runtimeId);
- return compileBooleanMatcher.fromLists(
- Array.from(positiveRuntimeIds),
- Array.from(negativeRuntimeIds)
- )(RuntimeGlobals.runtimeId);
- }
- /**
- *
- * @param {object} options options object
- * @param {boolean=} options.update whether a new variable should be created or the existing one updated
- * @param {Module} options.module the module
- * @param {ChunkGraph} options.chunkGraph the chunk graph
- * @param {string} options.request the request that should be printed as comment
- * @param {string} options.importVar name of the import variable
- * @param {Module} options.originModule module in which the statement is emitted
- * @param {boolean=} options.weak true, if this is a weak dependency
- * @param {RuntimeRequirements} options.runtimeRequirements if set, will be filled with runtime requirements
- * @returns {[string, string]} the import statement and the compat statement
- */
- importStatement({
- update,
- module,
- chunkGraph,
- request,
- importVar,
- originModule,
- weak,
- runtimeRequirements
- }) {
- if (!module) {
- return [
- this.missingModuleStatement({
- request
- }),
- ""
- ];
- }
- if (chunkGraph.getModuleId(module) === null) {
- if (weak) {
- // only weak referenced modules don't get an id
- // we can always emit an error emitting code here
- return [
- this.weakError({
- module,
- chunkGraph,
- request,
- type: "statements"
- }),
- ""
- ];
- }
- throw new Error(
- `RuntimeTemplate.importStatement(): ${noModuleIdErrorMessage(
- module,
- chunkGraph
- )}`
- );
- }
- const moduleId = this.moduleId({
- module,
- chunkGraph,
- request,
- weak
- });
- const optDeclaration = update ? "" : "var ";
- const exportsType = module.getExportsType(
- chunkGraph.moduleGraph,
- /** @type {BuildMeta} */
- (originModule.buildMeta).strictHarmonyModule
- );
- runtimeRequirements.add(RuntimeGlobals.require);
- const importContent = `/* harmony import */ ${optDeclaration}${importVar} = ${RuntimeGlobals.require}(${moduleId});\n`;
- if (exportsType === "dynamic") {
- runtimeRequirements.add(RuntimeGlobals.compatGetDefaultExport);
- return [
- importContent,
- `/* harmony import */ ${optDeclaration}${importVar}_default = /*#__PURE__*/${RuntimeGlobals.compatGetDefaultExport}(${importVar});\n`
- ];
- }
- return [importContent, ""];
- }
- /**
- * @param {object} options options
- * @param {ModuleGraph} options.moduleGraph the module graph
- * @param {Module} options.module the module
- * @param {string} options.request the request
- * @param {string | string[]} options.exportName the export name
- * @param {Module} options.originModule the origin module
- * @param {boolean|undefined} options.asiSafe true, if location is safe for ASI, a bracket can be emitted
- * @param {boolean} options.isCall true, if expression will be called
- * @param {boolean | null} options.callContext when false, call context will not be preserved
- * @param {boolean} options.defaultInterop when true and accessing the default exports, interop code will be generated
- * @param {string} options.importVar the identifier name of the import variable
- * @param {InitFragment<TODO>[]} options.initFragments init fragments will be added here
- * @param {RuntimeSpec} options.runtime runtime for which this code will be generated
- * @param {RuntimeRequirements} options.runtimeRequirements if set, will be filled with runtime requirements
- * @returns {string} expression
- */
- exportFromImport({
- moduleGraph,
- module,
- request,
- exportName,
- originModule,
- asiSafe,
- isCall,
- callContext,
- defaultInterop,
- importVar,
- initFragments,
- runtime,
- runtimeRequirements
- }) {
- if (!module) {
- return this.missingModule({
- request
- });
- }
- if (!Array.isArray(exportName)) {
- exportName = exportName ? [exportName] : [];
- }
- const exportsType = module.getExportsType(
- moduleGraph,
- /** @type {BuildMeta} */
- (originModule.buildMeta).strictHarmonyModule
- );
- if (defaultInterop) {
- if (exportName.length > 0 && exportName[0] === "default") {
- switch (exportsType) {
- case "dynamic":
- if (isCall) {
- return `${importVar}_default()${propertyAccess(exportName, 1)}`;
- } else {
- return asiSafe
- ? `(${importVar}_default()${propertyAccess(exportName, 1)})`
- : asiSafe === false
- ? `;(${importVar}_default()${propertyAccess(exportName, 1)})`
- : `${importVar}_default.a${propertyAccess(exportName, 1)}`;
- }
- case "default-only":
- case "default-with-named":
- exportName = exportName.slice(1);
- break;
- }
- } else if (exportName.length > 0) {
- if (exportsType === "default-only") {
- return (
- "/* non-default import from non-esm module */undefined" +
- propertyAccess(exportName, 1)
- );
- } else if (
- exportsType !== "namespace" &&
- exportName[0] === "__esModule"
- ) {
- return "/* __esModule */true";
- }
- } else if (
- exportsType === "default-only" ||
- exportsType === "default-with-named"
- ) {
- runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject);
- initFragments.push(
- new InitFragment(
- `var ${importVar}_namespace_cache;\n`,
- InitFragment.STAGE_CONSTANTS,
- -1,
- `${importVar}_namespace_cache`
- )
- );
- return `/*#__PURE__*/ ${
- asiSafe ? "" : asiSafe === false ? ";" : "Object"
- }(${importVar}_namespace_cache || (${importVar}_namespace_cache = ${
- RuntimeGlobals.createFakeNamespaceObject
- }(${importVar}${exportsType === "default-only" ? "" : ", 2"})))`;
- }
- }
- if (exportName.length > 0) {
- const exportsInfo = moduleGraph.getExportsInfo(module);
- const used = exportsInfo.getUsedName(exportName, runtime);
- if (!used) {
- const comment = Template.toNormalComment(
- `unused export ${propertyAccess(exportName)}`
- );
- return `${comment} undefined`;
- }
- const comment = equals(used, exportName)
- ? ""
- : Template.toNormalComment(propertyAccess(exportName)) + " ";
- const access = `${importVar}${comment}${propertyAccess(used)}`;
- if (isCall && callContext === false) {
- return asiSafe
- ? `(0,${access})`
- : asiSafe === false
- ? `;(0,${access})`
- : `/*#__PURE__*/Object(${access})`;
- }
- return access;
- } else {
- return importVar;
- }
- }
- /**
- * @param {object} options options
- * @param {AsyncDependenciesBlock | undefined} options.block the async block
- * @param {string} options.message the message
- * @param {ChunkGraph} options.chunkGraph the chunk graph
- * @param {RuntimeRequirements} options.runtimeRequirements if set, will be filled with runtime requirements
- * @returns {string} expression
- */
- blockPromise({ block, message, chunkGraph, runtimeRequirements }) {
- if (!block) {
- const comment = this.comment({
- message
- });
- return `Promise.resolve(${comment.trim()})`;
- }
- const chunkGroup = chunkGraph.getBlockChunkGroup(block);
- if (!chunkGroup || chunkGroup.chunks.length === 0) {
- const comment = this.comment({
- message
- });
- return `Promise.resolve(${comment.trim()})`;
- }
- const chunks = chunkGroup.chunks.filter(
- chunk => !chunk.hasRuntime() && chunk.id !== null
- );
- const comment = this.comment({
- message,
- chunkName: block.chunkName
- });
- if (chunks.length === 1) {
- const chunkId = JSON.stringify(chunks[0].id);
- runtimeRequirements.add(RuntimeGlobals.ensureChunk);
- const fetchPriority = chunkGroup.options.fetchPriority;
- if (fetchPriority) {
- runtimeRequirements.add(RuntimeGlobals.hasFetchPriority);
- }
- return `${RuntimeGlobals.ensureChunk}(${comment}${chunkId}${
- fetchPriority ? `, ${JSON.stringify(fetchPriority)}` : ""
- })`;
- } else if (chunks.length > 0) {
- runtimeRequirements.add(RuntimeGlobals.ensureChunk);
- const fetchPriority = chunkGroup.options.fetchPriority;
- if (fetchPriority) {
- runtimeRequirements.add(RuntimeGlobals.hasFetchPriority);
- }
- /**
- * @param {Chunk} chunk chunk
- * @returns {string} require chunk id code
- */
- const requireChunkId = chunk =>
- `${RuntimeGlobals.ensureChunk}(${JSON.stringify(chunk.id)}${
- fetchPriority ? `, ${JSON.stringify(fetchPriority)}` : ""
- })`;
- return `Promise.all(${comment.trim()}[${chunks
- .map(requireChunkId)
- .join(", ")}])`;
- } else {
- return `Promise.resolve(${comment.trim()})`;
- }
- }
- /**
- * @param {object} options options
- * @param {AsyncDependenciesBlock} options.block the async block
- * @param {ChunkGraph} options.chunkGraph the chunk graph
- * @param {RuntimeRequirements} options.runtimeRequirements if set, will be filled with runtime requirements
- * @param {string=} options.request request string used originally
- * @returns {string} expression
- */
- asyncModuleFactory({ block, chunkGraph, runtimeRequirements, request }) {
- const dep = block.dependencies[0];
- const module = chunkGraph.moduleGraph.getModule(dep);
- const ensureChunk = this.blockPromise({
- block,
- message: "",
- chunkGraph,
- runtimeRequirements
- });
- const factory = this.returningFunction(
- this.moduleRaw({
- module,
- chunkGraph,
- request,
- runtimeRequirements
- })
- );
- return this.returningFunction(
- ensureChunk.startsWith("Promise.resolve(")
- ? `${factory}`
- : `${ensureChunk}.then(${this.returningFunction(factory)})`
- );
- }
- /**
- * @param {object} options options
- * @param {Dependency} options.dependency the dependency
- * @param {ChunkGraph} options.chunkGraph the chunk graph
- * @param {RuntimeRequirements} options.runtimeRequirements if set, will be filled with runtime requirements
- * @param {string=} options.request request string used originally
- * @returns {string} expression
- */
- syncModuleFactory({ dependency, chunkGraph, runtimeRequirements, request }) {
- const module = chunkGraph.moduleGraph.getModule(dependency);
- const factory = this.returningFunction(
- this.moduleRaw({
- module,
- chunkGraph,
- request,
- runtimeRequirements
- })
- );
- return this.returningFunction(factory);
- }
- /**
- * @param {object} options options
- * @param {string} options.exportsArgument the name of the exports object
- * @param {RuntimeRequirements} options.runtimeRequirements if set, will be filled with runtime requirements
- * @returns {string} statement
- */
- defineEsModuleFlagStatement({ exportsArgument, runtimeRequirements }) {
- runtimeRequirements.add(RuntimeGlobals.makeNamespaceObject);
- runtimeRequirements.add(RuntimeGlobals.exports);
- return `${RuntimeGlobals.makeNamespaceObject}(${exportsArgument});\n`;
- }
- /**
- * @param {object} options options object
- * @param {Module} options.module the module
- * @param {RuntimeSpec=} options.runtime runtime
- * @param {CodeGenerationResults} options.codeGenerationResults the code generation results
- * @returns {string} the url of the asset
- */
- assetUrl({ runtime, module, codeGenerationResults }) {
- if (!module) {
- return "data:,";
- }
- const codeGen = codeGenerationResults.get(module, runtime);
- const data = /** @type {NonNullable<CodeGenerationResult["data"]>} */ (
- codeGen.data
- );
- const url = data.get("url");
- if (url) return url.toString();
- const assetPath = data.get("assetPathForCss");
- return assetPath;
- }
- }
- module.exports = RuntimeTemplate;
|