diff options
Diffstat (limited to 'node_modules/webpack/lib/RuntimeTemplate.js')
| -rw-r--r-- | node_modules/webpack/lib/RuntimeTemplate.js | 1059 |
1 files changed, 1059 insertions, 0 deletions
diff --git a/node_modules/webpack/lib/RuntimeTemplate.js b/node_modules/webpack/lib/RuntimeTemplate.js new file mode 100644 index 00000000..e4b6a141 --- /dev/null +++ b/node_modules/webpack/lib/RuntimeTemplate.js @@ -0,0 +1,1059 @@ +/* + 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").OutputNormalized} OutputOptions */ +/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */ +/** @typedef {import("./ChunkGraph")} ChunkGraph */ +/** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */ +/** @typedef {import("./Compilation")} Compilation */ +/** @typedef {import("./Dependency")} Dependency */ +/** @typedef {import("./Module")} Module */ +/** @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} 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 = getGlobalObject(outputOptions.globalObject); + this.contentHashReplacement = "X".repeat(outputOptions.hashDigestLength); + } + + isIIFE() { + return this.outputOptions.iife; + } + + isModule() { + return this.outputOptions.module; + } + + supportsConst() { + return this.outputOptions.environment.const; + } + + supportsArrowFunction() { + return this.outputOptions.environment.arrowFunction; + } + + supportsOptionalChaining() { + return this.outputOptions.environment.optionalChaining; + } + + supportsForOf() { + return this.outputOptions.environment.forOf; + } + + supportsDestructuring() { + return this.outputOptions.environment.destructuring; + } + + supportsBigIntLiteral() { + return this.outputOptions.environment.bigIntLiteral; + } + + supportsDynamicImport() { + return this.outputOptions.environment.dynamicImport; + } + + supportsEcmaScriptModuleSyntax() { + return this.outputOptions.environment.module; + } + + supportTemplateLiteral() { + return this.outputOptions.environment.templateLiteral; + } + + returningFunction(returnValue, args = "") { + return this.supportsArrowFunction() + ? `(${args}) => (${returnValue})` + : `function(${args}) { return ${returnValue}; }`; + } + + 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; + } + + expressionFunction(expression, args = "") { + return this.supportsArrowFunction() + ? `(${args}) => (${expression})` + : `function(${args}) { ${expression}; }`; + } + + emptyFunction() { + return this.supportsArrowFunction() ? "x => {}" : "function() {}"; + } + + destructureArray(items, value) { + return this.supportsDestructuring() + ? `var [${items.join(", ")}] = ${value};` + : Template.asString( + items.map((item, i) => `var ${item} = ${value}[${i}];`) + ); + } + + destructureObject(items, value) { + return this.supportsDestructuring() + ? `var {${items.join(", ")}} = ${value};` + : Template.asString( + items.map(item => `var ${item} = ${value}${propertyAccess([item])};`) + ); + } + + iife(args, body) { + return `(${this.basicFunction(args, body)})()`; + } + + 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 {Set<string>} 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 {Set<string>} 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 {Set<string>} 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 {Set<string>} 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 {Set<string>} 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(runtime)}`) + ); + /** @type {Set<string>} */ + const negativeRuntimeIds = new Set(); + forEachRuntime(subtractRuntime(runtime, runtimeCondition), runtime => + negativeRuntimeIds.add(`${chunkGraph.getRuntimeId(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 {Set<string>} 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, + 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 {Set<string>} 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, + 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} options.block the async block + * @param {string} options.message the message + * @param {ChunkGraph} options.chunkGraph the chunk graph + * @param {Set<string>} 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); + } + + 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 {Set<string>} 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 {Set<string>} 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 {Set<string>} 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 {string} options.publicPath the public path + * @param {RuntimeSpec=} options.runtime runtime + * @param {CodeGenerationResults} options.codeGenerationResults the code generation results + * @returns {string} the url of the asset + */ + assetUrl({ publicPath, runtime, module, codeGenerationResults }) { + if (!module) { + return "data:,"; + } + const codeGen = codeGenerationResults.get(module, runtime); + const { data } = codeGen; + const url = data.get("url"); + if (url) return url.toString(); + const filename = data.get("filename"); + return publicPath + filename; + } +} + +module.exports = RuntimeTemplate; |
