Buckets:
| /* | |
| MIT License http://www.opensource.org/licenses/mit-license.php | |
| Author Tobias Koppers @sokra | |
| */ | |
| ; | |
| const InitFragment = require("./InitFragment"); | |
| const RuntimeGlobals = require("./RuntimeGlobals"); | |
| const Template = require("./Template"); | |
| const { | |
| getOutgoingAsyncModules | |
| } = require("./async-modules/AsyncModuleHelpers"); | |
| const { ImportPhaseUtils } = require("./dependencies/ImportPhase"); | |
| const { | |
| getMakeDeferredNamespaceModeFromExportsType, | |
| getOptimizedDeferredModule | |
| } = require("./runtime/MakeDeferredNamespaceObjectRuntime"); | |
| const { equals } = require("./util/ArrayHelpers"); | |
| const compileBooleanMatcher = require("./util/compileBooleanMatcher"); | |
| const memoize = require("./util/memoize"); | |
| const propertyAccess = require("./util/propertyAccess"); | |
| const { forEachRuntime, subtractRuntime } = require("./util/runtime"); | |
| const getHarmonyImportDependency = memoize(() => | |
| require("./dependencies/HarmonyImportDependency") | |
| ); | |
| const getImportDependency = memoize(() => | |
| require("./dependencies/ImportDependency") | |
| ); | |
| /** @typedef {import("./config/defaults").OutputNormalizedWithDefaults} OutputOptions */ | |
| /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */ | |
| /** @typedef {import("./Chunk")} Chunk */ | |
| /** @typedef {import("./ChunkGraph")} ChunkGraph */ | |
| /** @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 */ | |
| /** @typedef {import("./dependencies/ImportPhase").ImportPhaseType} ImportPhaseType */ | |
| /** @typedef {import("./NormalModuleFactory").ModuleDependency} ModuleDependency */ | |
| /** | |
| * @param {Module} module the module | |
| * @param {ChunkGraph} chunkGraph the chunk graph | |
| * @returns {string} error message | |
| */ | |
| const noModuleIdErrorMessage = ( | |
| module, | |
| chunkGraph | |
| ) => `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 && [...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 | |
| /^[_\p{L}][_0-9\p{L}]*$/iu.test(trimmed) || | |
| // iife | |
| // call expression | |
| // expression in parentheses | |
| /^(?:[_\p{L}][_0-9\p{L}]*)?\(.*\)$/iu.test(trimmed) | |
| ) { | |
| 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 = /** @type {OutputOptions} */ (outputOptions || {}); | |
| this.requestShortener = requestShortener; | |
| this.globalObject = | |
| /** @type {string} */ | |
| (getGlobalObject(outputOptions.globalObject)); | |
| this.contentHashReplacement = "X".repeat(outputOptions.hashDigestLength); | |
| } | |
| isIIFE() { | |
| return this.outputOptions.iife; | |
| } | |
| isModule() { | |
| return this.outputOptions.module; | |
| } | |
| isNeutralPlatform() { | |
| return ( | |
| !this.compilation.compiler.platform.web && | |
| !this.compilation.compiler.platform.node | |
| ); | |
| } | |
| supportsConst() { | |
| return this.outputOptions.environment.const; | |
| } | |
| supportsMethodShorthand() { | |
| return this.outputOptions.environment.methodShorthand; | |
| } | |
| supportsArrowFunction() { | |
| return this.outputOptions.environment.arrowFunction; | |
| } | |
| supportsAsyncFunction() { | |
| return this.outputOptions.environment.asyncFunction; | |
| } | |
| 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; | |
| } | |
| supportNodePrefixForCoreModules() { | |
| return this.outputOptions.environment.nodePrefixForCoreModules; | |
| } | |
| /** | |
| * @param {string} mod a module | |
| * @returns {string} a module with `node:` prefix when supported, otherwise an original name | |
| */ | |
| renderNodePrefixForCoreModule(mod) { | |
| return this.outputOptions.environment.nodePrefixForCoreModules | |
| ? `"node:${mod}"` | |
| : `"${mod}"`; | |
| } | |
| /** | |
| * @returns {"const" | "var"} return `const` when it is supported, otherwise `var` | |
| */ | |
| renderConst() { | |
| return this.supportsConst() ? "const" : "var"; | |
| } | |
| /** | |
| * @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 {(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 {(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 | null)=} 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 }) { | |
| /** @type {string} */ | |
| 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)} `; | |
| } | |
| 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 {Dependency} options.dependency dependency | |
| * @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, | |
| dependency, | |
| 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 | |
| }); | |
| /** @type {string} */ | |
| 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 exportsType = module.getExportsType(chunkGraph.moduleGraph, strict); | |
| const isModuleDeferred = | |
| (dependency instanceof getHarmonyImportDependency() || | |
| dependency instanceof getImportDependency()) && | |
| ImportPhaseUtils.isDefer(dependency.phase) && | |
| !(/** @type {BuildMeta} */ (module.buildMeta).async); | |
| if (isModuleDeferred) { | |
| runtimeRequirements.add(RuntimeGlobals.makeDeferredNamespaceObject); | |
| let mode = getMakeDeferredNamespaceModeFromExportsType(exportsType); | |
| if (mode) mode = `${mode} | 16`; | |
| const asyncDeps = Array.from( | |
| getOutgoingAsyncModules(chunkGraph.moduleGraph, module), | |
| (m) => chunkGraph.getModuleId(m) | |
| ).filter((id) => id !== null); | |
| if (asyncDeps.length) { | |
| if (header) { | |
| appending = `.then(${this.basicFunction( | |
| "", | |
| `${header}return ${RuntimeGlobals.deferredModuleAsyncTransitiveDependencies}(${JSON.stringify(asyncDeps)});` | |
| )})`; | |
| } else { | |
| runtimeRequirements.add(RuntimeGlobals.require); | |
| appending = `.then(${this.returningFunction(`${RuntimeGlobals.deferredModuleAsyncTransitiveDependencies}(${JSON.stringify(asyncDeps)})`)})`; | |
| } | |
| appending += `.then(${RuntimeGlobals.makeDeferredNamespaceObject}.bind(${RuntimeGlobals.require}, ${comment}${idExpr}, ${mode}))`; | |
| } else if (header) { | |
| appending = `.then(${this.basicFunction( | |
| "", | |
| `${header}return ${RuntimeGlobals.makeDeferredNamespaceObject}(${comment}${idExpr}, ${mode});` | |
| )})`; | |
| } else { | |
| runtimeRequirements.add(RuntimeGlobals.require); | |
| appending = `.then(${RuntimeGlobals.makeDeferredNamespaceObject}.bind(${RuntimeGlobals.require}, ${comment}${idExpr}, ${mode}))`; | |
| } | |
| } else { | |
| 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 moduleIdExpr = this.moduleId({ | |
| module, | |
| chunkGraph, | |
| request, | |
| weak | |
| }); | |
| 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( | |
| [...positiveRuntimeIds], | |
| [...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 {Module} options.originModule module in which the statement is emitted | |
| * @param {ModuleGraph} options.moduleGraph the module graph | |
| * @param {ChunkGraph} options.chunkGraph the chunk graph | |
| * @param {RuntimeRequirements} options.runtimeRequirements if set, will be filled with runtime requirements | |
| * @param {string} options.importVar name of the import variable | |
| * @param {string=} options.request the request that should be printed as comment | |
| * @param {boolean=} options.weak true, if this is a weak dependency | |
| * @param {ModuleDependency=} options.dependency module dependency | |
| * @returns {[string, string]} the import statement and the compat statement | |
| */ | |
| importStatement({ | |
| update, | |
| module, | |
| moduleGraph, | |
| chunkGraph, | |
| request, | |
| importVar, | |
| originModule, | |
| weak, | |
| dependency, | |
| 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); | |
| /** @type {string} */ | |
| let importContent; | |
| const isModuleDeferred = | |
| (dependency instanceof getHarmonyImportDependency() || | |
| dependency instanceof getImportDependency()) && | |
| ImportPhaseUtils.isDefer(dependency.phase) && | |
| !(/** @type {BuildMeta} */ (module.buildMeta).async); | |
| if (isModuleDeferred) { | |
| /** @type {Set<Module>} */ | |
| const outgoingAsyncModules = getOutgoingAsyncModules(moduleGraph, module); | |
| importContent = `/* deferred harmony import */ ${optDeclaration}${importVar} = ${getOptimizedDeferredModule( | |
| moduleId, | |
| exportsType, | |
| Array.from(outgoingAsyncModules, (mod) => chunkGraph.getModuleId(mod)), | |
| runtimeRequirements | |
| )};\n`; | |
| return [importContent, ""]; | |
| } | |
| 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, ""]; | |
| } | |
| /** | |
| * @template GenerateContext | |
| * @param {object} options options | |
| * @param {ModuleGraph} options.moduleGraph the module graph | |
| * @param {ChunkGraph} options.chunkGraph the chunk 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 | undefined} 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<GenerateContext>[]} 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 | |
| * @param {ModuleDependency} options.dependency module dependency | |
| * @returns {string} expression | |
| */ | |
| exportFromImport({ | |
| moduleGraph, | |
| chunkGraph, | |
| module, | |
| request, | |
| exportName, | |
| originModule, | |
| asiSafe, | |
| isCall, | |
| callContext, | |
| defaultInterop, | |
| importVar, | |
| initFragments, | |
| runtime, | |
| runtimeRequirements, | |
| dependency | |
| }) { | |
| if (!module) { | |
| return this.missingModule({ | |
| request | |
| }); | |
| } | |
| if (!Array.isArray(exportName)) { | |
| exportName = exportName ? [exportName] : []; | |
| } | |
| const exportsType = module.getExportsType( | |
| moduleGraph, | |
| /** @type {BuildMeta} */ | |
| (originModule.buildMeta).strictHarmonyModule | |
| ); | |
| const isModuleDeferred = | |
| (dependency instanceof getHarmonyImportDependency() || | |
| dependency instanceof getImportDependency()) && | |
| ImportPhaseUtils.isDefer(dependency.phase) && | |
| !(/** @type {BuildMeta} */ (module.buildMeta).async); | |
| if (defaultInterop) { | |
| // when the defaultInterop is used (when a ESM imports a CJS module), | |
| if (exportName.length > 0 && exportName[0] === "default") { | |
| if (isModuleDeferred && exportsType !== "namespace") { | |
| const exportsInfo = moduleGraph.getExportsInfo(module); | |
| const name = exportName.slice(1); | |
| const used = exportsInfo.getUsedName(name, runtime); | |
| if (!used) { | |
| const comment = Template.toNormalComment( | |
| `unused export ${propertyAccess(exportName)}` | |
| ); | |
| return `${comment} undefined`; | |
| } | |
| const access = `${importVar}.a${propertyAccess(used)}`; | |
| if (isCall || asiSafe === undefined) { | |
| return access; | |
| } | |
| return asiSafe ? `(${access})` : `;(${access})`; | |
| } | |
| // accessing the .default property is same thing as `require()` the module. | |
| // For example: | |
| // import mod from "cjs"; mod.default.x; | |
| // is translated to | |
| // var mod = require("cjs"); mod.x; | |
| switch (exportsType) { | |
| case "dynamic": | |
| if (isCall) { | |
| return `${importVar}_default()${propertyAccess(exportName, 1)}`; | |
| } | |
| 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) { | |
| // the property used is not .default. | |
| // For example: | |
| // import * as ns from "cjs"; cjs.prop; | |
| if (exportsType === "default-only") { | |
| // in the strictest case, it is a runtime error (e.g. NodeJS behavior of CJS-ESM interop). | |
| return `/* non-default import from non-esm module */undefined${propertyAccess( | |
| exportName, | |
| 1 | |
| )}`; | |
| } else if ( | |
| exportsType !== "namespace" && | |
| exportName[0] === "__esModule" | |
| ) { | |
| return "/* __esModule */true"; | |
| } | |
| } else if (isModuleDeferred) { | |
| // now exportName.length is 0 | |
| // fall through to the end of this function, create the namespace there. | |
| } else if ( | |
| exportsType === "default-only" || | |
| exportsType === "default-with-named" | |
| ) { | |
| // now exportName.length is 0, which means the namespace object is used in an unknown way | |
| // for example: | |
| // import * as ns from "cjs"; console.log(ns); | |
| // we will need to createFakeNamespaceObject that simulates ES Module namespace object | |
| 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); | |
| // in some case the exported item is renamed (get this by getUsedName). for example, | |
| // x.default might be emitted as x.Z (default is renamed to Z) | |
| 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}${ | |
| isModuleDeferred ? ".a" : "" | |
| }${comment}${propertyAccess(used)}`; | |
| if (isCall && callContext === false) { | |
| return asiSafe | |
| ? `(0,${access})` | |
| : asiSafe === false | |
| ? `;(0,${access})` | |
| : `/*#__PURE__*/Object(${access})`; | |
| } | |
| return access; | |
| } | |
| if (isModuleDeferred) { | |
| initFragments.push( | |
| new InitFragment( | |
| `var ${importVar}_deferred_namespace_cache;\n`, | |
| InitFragment.STAGE_CONSTANTS, | |
| -1, | |
| `${importVar}_deferred_namespace_cache` | |
| ) | |
| ); | |
| runtimeRequirements.add(RuntimeGlobals.makeDeferredNamespaceObject); | |
| const id = chunkGraph.getModuleId(module); | |
| const type = getMakeDeferredNamespaceModeFromExportsType(exportsType); | |
| const init = `${ | |
| RuntimeGlobals.makeDeferredNamespaceObject | |
| }(${JSON.stringify(id)}, ${type})`; | |
| return `/*#__PURE__*/ ${ | |
| asiSafe ? "" : asiSafe === false ? ";" : "Object" | |
| }(${importVar}_deferred_namespace_cache || (${importVar}_deferred_namespace_cache = ${init}))`; | |
| } | |
| // if we hit here, the importVar is either | |
| // - already a ES module namespace object | |
| // - or imported by a way that does not need interop. | |
| 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(", ")}])`; | |
| } | |
| 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`; | |
| } | |
| } | |
| module.exports = RuntimeTemplate; | |
Xet Storage Details
- Size:
- 40.3 kB
- Xet hash:
- 16807cfcf22ee19dc95b0e3f759cb0adc2bb6afba1b9970682b1ad3e4b855952
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.