| | |
| | | const AsyncDependenciesBlock = require("./AsyncDependenciesBlock"); |
| | | const { makeWebpackError } = require("./HookWebpackError"); |
| | | const Module = require("./Module"); |
| | | const { JS_TYPES } = require("./ModuleSourceTypesConstants"); |
| | | const { |
| | | JAVASCRIPT_TYPE, |
| | | JAVASCRIPT_TYPES |
| | | } = require("./ModuleSourceTypeConstants"); |
| | | const { JAVASCRIPT_MODULE_TYPE_DYNAMIC } = require("./ModuleTypeConstants"); |
| | | const RuntimeGlobals = require("./RuntimeGlobals"); |
| | | const Template = require("./Template"); |
| | | const WebpackError = require("./WebpackError"); |
| | | const { |
| | | getOutgoingAsyncModules |
| | | } = require("./async-modules/AsyncModuleHelpers"); |
| | | const { ImportPhase, ImportPhaseUtils } = require("./dependencies/ImportPhase"); |
| | | const { |
| | | compareLocations, |
| | | compareModulesById, |
| | |
| | | /** @typedef {import("./Module").LibIdent} LibIdent */ |
| | | /** @typedef {import("./Module").NeedBuildCallback} NeedBuildCallback */ |
| | | /** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */ |
| | | /** @typedef {import("./Module").RuntimeRequirements} RuntimeRequirements */ |
| | | /** @typedef {import("./Module").Sources} Sources */ |
| | | /** @typedef {import("./RequestShortener")} RequestShortener */ |
| | | /** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */ |
| | | /** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */ |
| | |
| | | /** @typedef {import("./serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */ |
| | | /** @typedef {import("./serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */ |
| | | /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */ |
| | | /** @typedef {import("./dependencies/ImportPhase").ImportPhaseType} ImportPhaseType */ |
| | | |
| | | /** @typedef {"sync" | "eager" | "weak" | "async-weak" | "lazy" | "lazy-once"} ContextMode Context mode */ |
| | | |
| | |
| | | * @property {RawReferencedExports | null=} referencedExports exports referenced from modules (won't be mangled) |
| | | * @property {string | null=} layer |
| | | * @property {ImportAttributes=} attributes |
| | | * @property {ImportPhaseType=} phase |
| | | */ |
| | | |
| | | /** |
| | |
| | | /** @typedef {1 | 3 | 7 | 9} FakeMapType */ |
| | | |
| | | /** @typedef {Record<ModuleId, FakeMapType>} FakeMap */ |
| | | /** @typedef {Record<string, ModuleId>} UserRequestMap */ |
| | | /** @typedef {Record<ModuleId, ModuleId[]>} UserRequestsMap */ |
| | | |
| | | class ContextModule extends Module { |
| | | /** |
| | |
| | | } |
| | | |
| | | /** |
| | | * Returns the source types this module can generate. |
| | | * @returns {SourceTypes} types available (do not mutate) |
| | | */ |
| | | getSourceTypes() { |
| | | return JS_TYPES; |
| | | return JAVASCRIPT_TYPES; |
| | | } |
| | | |
| | | /** |
| | |
| | | if (this.options.attributes) { |
| | | identifier += `|importAttributes: ${JSON.stringify(this.options.attributes)}`; |
| | | } |
| | | if (this.options.phase) { |
| | | identifier += `|importPhase: ${this.options.phase}`; |
| | | } |
| | | if (this.layer) { |
| | | identifier += `|layer: ${this.layer}`; |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * Returns the unique identifier used to reference this module. |
| | | * @returns {string} a unique identifier of the module |
| | | */ |
| | | identifier() { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Returns a human-readable identifier for this module. |
| | | * @param {RequestShortener} requestShortener the request shortener |
| | | * @returns {string} a user readable identifier of the module |
| | | */ |
| | | readableIdentifier(requestShortener) { |
| | | /** @type {string} */ |
| | | let identifier; |
| | | |
| | | if (this.context) { |
| | | identifier = `${requestShortener.shorten(this.context)}/`; |
| | | } else if ( |
| | |
| | | } |
| | | |
| | | /** |
| | | * Gets the library identifier. |
| | | * @param {LibIdentOptions} options options |
| | | * @returns {LibIdent | null} an identifier for library inclusion |
| | | */ |
| | | libIdent(options) { |
| | | /** @type {string} */ |
| | | let identifier; |
| | | |
| | | if (this.context) { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Invalidates the cached state associated with this value. |
| | | * @returns {void} |
| | | */ |
| | | invalidateBuild() { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Checks whether the module needs to be rebuilt for the current build state. |
| | | * @param {NeedBuildContext} context context info |
| | | * @param {NeedBuildCallback} callback callback function, returns true, if the module needs a rebuild |
| | | * @returns {void} |
| | |
| | | } |
| | | |
| | | /** |
| | | * Builds the module using the provided compilation context. |
| | | * @param {WebpackOptions} options webpack options |
| | | * @param {Compilation} compilation the compilation |
| | | * @param {ResolverWithOptions} resolver the resolver |
| | |
| | | for (const dep of dependencies) { |
| | | let chunkName = this.options.chunkName; |
| | | if (chunkName) { |
| | | if (!/\[(index|request)\]/.test(chunkName)) { |
| | | if (!/\[(?:index|request)\]/.test(chunkName)) { |
| | | chunkName += "[index]"; |
| | | } |
| | | chunkName = chunkName.replace(/\[index\]/g, `${index++}`); |
| | |
| | | } |
| | | |
| | | /** |
| | | * Adds the provided file dependencies to the module. |
| | | * @param {FileSystemDependencies} fileDependencies set where file dependencies are added to |
| | | * @param {FileSystemDependencies} contextDependencies set where context dependencies are added to |
| | | * @param {FileSystemDependencies} missingDependencies set where missing dependencies are added to |
| | |
| | | /** |
| | | * @param {Dependency[]} dependencies all dependencies |
| | | * @param {ChunkGraph} chunkGraph chunk graph |
| | | * @returns {Map<string, ModuleId>} map with user requests |
| | | * @returns {UserRequestMap} map with user requests |
| | | */ |
| | | getUserRequestMap(dependencies, chunkGraph) { |
| | | const moduleGraph = chunkGraph.moduleGraph; |
| | |
| | | } |
| | | return a.userRequest < b.userRequest ? -1 : 1; |
| | | }); |
| | | /** @type {UserRequestMap} */ |
| | | const map = Object.create(null); |
| | | for (const dep of sortedDependencies) { |
| | | const module = /** @type {Module} */ (moduleGraph.getModule(dep)); |
| | | map[dep.userRequest] = chunkGraph.getModuleId(module); |
| | | map[dep.userRequest] = |
| | | /** @type {ModuleId} */ |
| | | (chunkGraph.getModuleId(module)); |
| | | } |
| | | return map; |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * @param {Dependency[]} dependencies all dependencies |
| | | * @param {ChunkGraph} chunkGraph chunk graph |
| | | * @returns {UserRequestsMap} map with user requests |
| | | */ |
| | | getModuleDeferredAsyncDepsMap(dependencies, chunkGraph) { |
| | | const moduleGraph = chunkGraph.moduleGraph; |
| | | const comparator = compareModulesById(chunkGraph); |
| | | // if we filter first we get a new array |
| | | // therefore we don't need to create a clone of dependencies explicitly |
| | | // therefore the order of this is !important! |
| | | const sortedModules = dependencies |
| | | .map( |
| | | (dependency) => |
| | | /** @type {Module} */ (moduleGraph.getModule(dependency)) |
| | | ) |
| | | .filter(Boolean) |
| | | .sort(comparator); |
| | | /** @type {UserRequestsMap} */ |
| | | const map = Object.create(null); |
| | | for (const module of sortedModules) { |
| | | if (!(/** @type {BuildMeta} */ (module.buildMeta).async)) { |
| | | const id = /** @type {ModuleId} */ (chunkGraph.getModuleId(module)); |
| | | map[id] = Array.from( |
| | | getOutgoingAsyncModules(chunkGraph.moduleGraph, module), |
| | | (m) => chunkGraph.getModuleId(m) |
| | | ).filter((id) => id !== null); |
| | | } |
| | | } |
| | | return map; |
| | | } |
| | | |
| | | /** |
| | | * @param {false | UserRequestsMap} asyncDepsMap fake map |
| | | * @returns {string} async deps map init statement |
| | | */ |
| | | getModuleDeferredAsyncDepsMapInitStatement(asyncDepsMap) { |
| | | return typeof asyncDepsMap === "object" |
| | | ? `var asyncDepsMap = ${JSON.stringify(asyncDepsMap, null, "\t")};` |
| | | : ""; |
| | | } |
| | | |
| | | /** |
| | | * @param {FakeMapType} type type |
| | | * @param {boolean=} asyncModule is async module |
| | | * @returns {string} return result |
| | |
| | | |
| | | /** |
| | | * @param {FakeMap | FakeMapType} fakeMap fake map |
| | | * @param {boolean=} asyncModule us async module |
| | | * @param {boolean=} asyncModule is async module |
| | | * @param {string=} asyncDeps async deps for deferred module |
| | | * @param {string=} fakeMapDataExpression fake map data expression |
| | | * @returns {string} module object source |
| | | */ |
| | | getReturnModuleObjectSource( |
| | | fakeMap, |
| | | asyncModule, |
| | | asyncDeps, |
| | | fakeMapDataExpression = "fakeMap[id]" |
| | | ) { |
| | | if (typeof fakeMap === "number") { |
| | | return `return ${this.getReturn(fakeMap, asyncModule)};`; |
| | | const source = |
| | | typeof fakeMap === "number" |
| | | ? this.getReturn(fakeMap, asyncModule) |
| | | : `${RuntimeGlobals.createFakeNamespaceObject}(id, ${fakeMapDataExpression}${asyncModule ? " | 16" : ""})`; |
| | | if (asyncDeps) { |
| | | if (!asyncModule) { |
| | | throw new Error("Must be async when module is deferred"); |
| | | } |
| | | const type = |
| | | typeof fakeMap === "number" ? fakeMap : fakeMapDataExpression; |
| | | return `${asyncDeps} ? ${asyncDeps}.length ? ${RuntimeGlobals.deferredModuleAsyncTransitiveDependencies}(${asyncDeps}).then(${RuntimeGlobals.makeDeferredNamespaceObject}.bind(${RuntimeGlobals.require}, id, ${type} ^ 1, true)) : ${RuntimeGlobals.makeDeferredNamespaceObject}(id, ${type} ^ 1 | 16) : ${source}`; |
| | | } |
| | | return `return ${ |
| | | RuntimeGlobals.createFakeNamespaceObject |
| | | }(id, ${fakeMapDataExpression}${asyncModule ? " | 16" : ""})`; |
| | | return source; |
| | | } |
| | | |
| | | /** |
| | |
| | | |
| | | function webpackContext(req) { |
| | | var id = webpackContextResolve(req); |
| | | ${returnModuleObject} |
| | | return ${returnModuleObject}; |
| | | } |
| | | function webpackContextResolve(req) { |
| | | if(!${RuntimeGlobals.hasOwnProperty}(map, req)) { |
| | |
| | | e.code = 'MODULE_NOT_FOUND'; |
| | | throw e; |
| | | } |
| | | ${returnModuleObject} |
| | | return ${returnModuleObject}; |
| | | } |
| | | function webpackContextResolve(req) { |
| | | if(!${RuntimeGlobals.hasOwnProperty}(map, req)) { |
| | |
| | | /** |
| | | * @param {Dependency[]} dependencies dependencies |
| | | * @param {ModuleId} id module id |
| | | * @param {ImportPhaseType} phase import phase |
| | | * @param {object} context context |
| | | * @param {ChunkGraph} context.chunkGraph the chunk graph |
| | | * @param {RuntimeTemplate} context.runtimeTemplate the chunk graph |
| | | * @returns {string} source code |
| | | */ |
| | | getAsyncWeakSource(dependencies, id, { chunkGraph, runtimeTemplate }) { |
| | | const arrow = runtimeTemplate.supportsArrowFunction(); |
| | | getAsyncWeakSource(dependencies, id, phase, { chunkGraph, runtimeTemplate }) { |
| | | const map = this.getUserRequestMap(dependencies, chunkGraph); |
| | | const fakeMap = this.getFakeMap(dependencies, chunkGraph); |
| | | const returnModuleObject = this.getReturnModuleObjectSource(fakeMap, true); |
| | | const asyncDepsMap = |
| | | ImportPhaseUtils.isDefer(phase) && |
| | | this.getModuleDeferredAsyncDepsMap(dependencies, chunkGraph); |
| | | const returnModuleObject = this.getReturnModuleObjectSource( |
| | | fakeMap, |
| | | true, |
| | | asyncDepsMap ? "asyncDepsMap[id]" : undefined |
| | | ); |
| | | |
| | | return `var map = ${JSON.stringify(map, null, "\t")}; |
| | | ${this.getFakeMapInitStatement(fakeMap)} |
| | | ${this.getModuleDeferredAsyncDepsMapInitStatement(asyncDepsMap)} |
| | | |
| | | function webpackAsyncContext(req) { |
| | | return webpackAsyncContextResolve(req).then(${ |
| | | arrow ? "id =>" : "function(id)" |
| | | } { |
| | | if(!${RuntimeGlobals.moduleFactories}[id]) { |
| | | var e = new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)"); |
| | | e.code = 'MODULE_NOT_FOUND'; |
| | | throw e; |
| | | } |
| | | ${returnModuleObject} |
| | | }); |
| | | return webpackAsyncContextResolve(req).then(${runtimeTemplate.basicFunction( |
| | | "id", |
| | | [ |
| | | `if(!${RuntimeGlobals.moduleFactories}[id]) {`, |
| | | Template.indent([ |
| | | 'var e = new Error("Module \'" + req + "\' (\'" + id + "\') is not available (weak dependency)");', |
| | | "e.code = 'MODULE_NOT_FOUND';", |
| | | "throw e;" |
| | | ]), |
| | | "}", |
| | | `return ${returnModuleObject};` |
| | | ] |
| | | )}); |
| | | } |
| | | function webpackAsyncContextResolve(req) { |
| | | // Here Promise.resolve().then() is used instead of new Promise() to prevent |
| | | // uncaught exception popping up in devtools |
| | | return Promise.resolve().then(${arrow ? "() =>" : "function()"} { |
| | | if(!${RuntimeGlobals.hasOwnProperty}(map, req)) { |
| | | var e = new Error("Cannot find module '" + req + "'"); |
| | | e.code = 'MODULE_NOT_FOUND'; |
| | | throw e; |
| | | } |
| | | return map[req]; |
| | | }); |
| | | return Promise.resolve().then(${runtimeTemplate.basicFunction("", [ |
| | | `if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {`, |
| | | Template.indent([ |
| | | 'var e = new Error("Cannot find module \'" + req + "\'");', |
| | | "e.code = 'MODULE_NOT_FOUND';", |
| | | "throw e;" |
| | | ]), |
| | | "}", |
| | | "return map[req];" |
| | | ])}); |
| | | } |
| | | webpackAsyncContext.keys = ${runtimeTemplate.returningFunction( |
| | | "Object.keys(map)" |
| | |
| | | /** |
| | | * @param {Dependency[]} dependencies dependencies |
| | | * @param {ModuleId} id module id |
| | | * @param {ImportPhaseType} phase import phase |
| | | * @param {object} context context |
| | | * @param {ChunkGraph} context.chunkGraph the chunk graph |
| | | * @param {RuntimeTemplate} context.runtimeTemplate the chunk graph |
| | | * @returns {string} source code |
| | | */ |
| | | getEagerSource(dependencies, id, { chunkGraph, runtimeTemplate }) { |
| | | const arrow = runtimeTemplate.supportsArrowFunction(); |
| | | getEagerSource(dependencies, id, phase, { chunkGraph, runtimeTemplate }) { |
| | | const map = this.getUserRequestMap(dependencies, chunkGraph); |
| | | const fakeMap = this.getFakeMap(dependencies, chunkGraph); |
| | | const thenFunction = |
| | | fakeMap !== 9 |
| | | ? `${arrow ? "id =>" : "function(id)"} { |
| | | ${this.getReturnModuleObjectSource(fakeMap, true)} |
| | | }` |
| | | : RuntimeGlobals.require; |
| | | const asyncDepsMap = |
| | | ImportPhaseUtils.isDefer(phase) && |
| | | this.getModuleDeferredAsyncDepsMap(dependencies, chunkGraph); |
| | | const thenFunction = runtimeTemplate.returningFunction( |
| | | this.getReturnModuleObjectSource( |
| | | fakeMap, |
| | | true, |
| | | asyncDepsMap ? "asyncDepsMap[id]" : undefined |
| | | ), |
| | | "id" |
| | | ); |
| | | |
| | | return `var map = ${JSON.stringify(map, null, "\t")}; |
| | | ${this.getFakeMapInitStatement(fakeMap)} |
| | | ${this.getModuleDeferredAsyncDepsMapInitStatement(asyncDepsMap)} |
| | | |
| | | function webpackAsyncContext(req) { |
| | | return webpackAsyncContextResolve(req).then(${thenFunction}); |
| | |
| | | function webpackAsyncContextResolve(req) { |
| | | // Here Promise.resolve().then() is used instead of new Promise() to prevent |
| | | // uncaught exception popping up in devtools |
| | | return Promise.resolve().then(${arrow ? "() =>" : "function()"} { |
| | | if(!${RuntimeGlobals.hasOwnProperty}(map, req)) { |
| | | var e = new Error("Cannot find module '" + req + "'"); |
| | | e.code = 'MODULE_NOT_FOUND'; |
| | | throw e; |
| | | } |
| | | return map[req]; |
| | | }); |
| | | return Promise.resolve().then(${runtimeTemplate.basicFunction("", [ |
| | | `if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {`, |
| | | Template.indent([ |
| | | 'var e = new Error("Cannot find module \'" + req + "\'");', |
| | | "e.code = 'MODULE_NOT_FOUND';", |
| | | "throw e;" |
| | | ]), |
| | | "}", |
| | | "return map[req];" |
| | | ])}); |
| | | } |
| | | webpackAsyncContext.keys = ${runtimeTemplate.returningFunction( |
| | | "Object.keys(map)" |
| | |
| | | * @param {AsyncDependenciesBlock} block block |
| | | * @param {Dependency[]} dependencies dependencies |
| | | * @param {ModuleId} id module id |
| | | * @param {ImportPhaseType} phase import phase |
| | | * @param {object} options options object |
| | | * @param {RuntimeTemplate} options.runtimeTemplate the runtime template |
| | | * @param {ChunkGraph} options.chunkGraph the chunk graph |
| | | * @returns {string} source code |
| | | */ |
| | | getLazyOnceSource(block, dependencies, id, { runtimeTemplate, chunkGraph }) { |
| | | getLazyOnceSource( |
| | | block, |
| | | dependencies, |
| | | id, |
| | | phase, |
| | | { runtimeTemplate, chunkGraph } |
| | | ) { |
| | | const promise = runtimeTemplate.blockPromise({ |
| | | chunkGraph, |
| | | block, |
| | | message: "lazy-once context", |
| | | /** @type {RuntimeRequirements} */ |
| | | runtimeRequirements: new Set() |
| | | }); |
| | | const arrow = runtimeTemplate.supportsArrowFunction(); |
| | | const map = this.getUserRequestMap(dependencies, chunkGraph); |
| | | const fakeMap = this.getFakeMap(dependencies, chunkGraph); |
| | | const thenFunction = |
| | | fakeMap !== 9 |
| | | ? `${arrow ? "id =>" : "function(id)"} { |
| | | ${this.getReturnModuleObjectSource(fakeMap, true)}; |
| | | }` |
| | | : RuntimeGlobals.require; |
| | | const asyncDepsMap = |
| | | ImportPhaseUtils.isDefer(phase) && |
| | | this.getModuleDeferredAsyncDepsMap(dependencies, chunkGraph); |
| | | const thenFunction = runtimeTemplate.returningFunction( |
| | | this.getReturnModuleObjectSource( |
| | | fakeMap, |
| | | true, |
| | | asyncDepsMap ? "asyncDepsMap[id]" : undefined |
| | | ), |
| | | "id" |
| | | ); |
| | | |
| | | return `var map = ${JSON.stringify(map, null, "\t")}; |
| | | ${this.getFakeMapInitStatement(fakeMap)} |
| | | ${this.getModuleDeferredAsyncDepsMapInitStatement(asyncDepsMap)} |
| | | |
| | | function webpackAsyncContext(req) { |
| | | return webpackAsyncContextResolve(req).then(${thenFunction}); |
| | | } |
| | | function webpackAsyncContextResolve(req) { |
| | | return ${promise}.then(${arrow ? "() =>" : "function()"} { |
| | | if(!${RuntimeGlobals.hasOwnProperty}(map, req)) { |
| | | var e = new Error("Cannot find module '" + req + "'"); |
| | | e.code = 'MODULE_NOT_FOUND'; |
| | | throw e; |
| | | } |
| | | return map[req]; |
| | | }); |
| | | return ${promise}.then(${runtimeTemplate.basicFunction("", [ |
| | | `if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {`, |
| | | Template.indent([ |
| | | 'var e = new Error("Cannot find module \'" + req + "\'");', |
| | | "e.code = 'MODULE_NOT_FOUND';", |
| | | "throw e;" |
| | | ]), |
| | | "}", |
| | | "return map[req];" |
| | | ])}); |
| | | } |
| | | webpackAsyncContext.keys = ${runtimeTemplate.returningFunction( |
| | | "Object.keys(map)" |
| | |
| | | /** |
| | | * @param {AsyncDependenciesBlock[]} blocks blocks |
| | | * @param {ModuleId} id module id |
| | | * @param {ImportPhaseType} phase import phase |
| | | * @param {object} context context |
| | | * @param {ChunkGraph} context.chunkGraph the chunk graph |
| | | * @param {RuntimeTemplate} context.runtimeTemplate the chunk graph |
| | | * @returns {string} source code |
| | | */ |
| | | getLazySource(blocks, id, { chunkGraph, runtimeTemplate }) { |
| | | getLazySource(blocks, id, phase, { chunkGraph, runtimeTemplate }) { |
| | | const moduleGraph = chunkGraph.moduleGraph; |
| | | const arrow = runtimeTemplate.supportsArrowFunction(); |
| | | let hasMultipleOrNoChunks = false; |
| | | let hasNoChunk = true; |
| | | let hasNoModuleDeferred = true; |
| | | const fakeMap = this.getFakeMap( |
| | | blocks.map((b) => b.dependencies[0]), |
| | | chunkGraph |
| | | ); |
| | | const hasFakeMap = typeof fakeMap === "object"; |
| | | /** @typedef {{userRequest: string, dependency: ContextElementDependency, chunks: undefined | Chunk[], module: Module, block: AsyncDependenciesBlock}} Item */ |
| | | /** @typedef {{ userRequest: string, dependency: ContextElementDependency, chunks: undefined | Chunk[], module: Module, block: AsyncDependenciesBlock, asyncDeps: undefined | ModuleId[] }} Item */ |
| | | /** |
| | | * @type {Item[]} |
| | | */ |
| | |
| | | module: /** @type {Module} */ (moduleGraph.getModule(dependency)), |
| | | block, |
| | | userRequest: dependency.userRequest, |
| | | chunks: undefined |
| | | chunks: undefined, |
| | | asyncDeps: undefined |
| | | }; |
| | | }) |
| | | .filter((item) => item.module); |
| | |
| | | if (chunks.length !== 1) { |
| | | hasMultipleOrNoChunks = true; |
| | | } |
| | | const isModuleDeferred = |
| | | ImportPhaseUtils.isDefer(phase) && |
| | | !(/** @type {BuildMeta} */ (item.module.buildMeta).async); |
| | | if (isModuleDeferred) { |
| | | const asyncDeps = Array.from( |
| | | getOutgoingAsyncModules(chunkGraph.moduleGraph, item.module), |
| | | (m) => chunkGraph.getModuleId(m) |
| | | ).filter((id) => id !== null); |
| | | item.asyncDeps = asyncDeps; |
| | | hasNoModuleDeferred = false; |
| | | } |
| | | } |
| | | const shortMode = hasNoChunk && !hasFakeMap; |
| | | const shortMode = hasNoChunk && hasNoModuleDeferred && !hasFakeMap; |
| | | const sortedItems = items.sort((a, b) => { |
| | | if (a.userRequest === b.userRequest) return 0; |
| | | return a.userRequest < b.userRequest ? -1 : 1; |
| | | }); |
| | | /** @type {Record<string, ModuleId | (ModuleId[] | ChunkId[])>} */ |
| | | /** @type {Record<string, ModuleId | (ModuleId | FakeMapType | ChunkId[] | (ModuleId[] | undefined))[]>} */ |
| | | const map = Object.create(null); |
| | | for (const item of sortedItems) { |
| | | const moduleId = |
| | |
| | | if (shortMode) { |
| | | map[item.userRequest] = moduleId; |
| | | } else { |
| | | /** @type {(ModuleId | ChunkId)[]} */ |
| | | const arrayStart = [moduleId]; |
| | | /** @type {(ModuleId | FakeMapType | ChunkId[] | (ModuleId[] | undefined))[]} */ |
| | | const array = [moduleId]; |
| | | if (hasFakeMap) { |
| | | arrayStart.push(fakeMap[moduleId]); |
| | | array.push(fakeMap[moduleId]); |
| | | } |
| | | map[item.userRequest] = [ |
| | | ...arrayStart, |
| | | .../** @type {Chunk[]} */ |
| | | (item.chunks).map((chunk) => /** @type {ChunkId} */ (chunk.id)) |
| | | ]; |
| | | if (!hasNoChunk) { |
| | | array.push( |
| | | /** @type {Chunk[]} */ (item.chunks).map( |
| | | (chunk) => /** @type {ChunkId} */ (chunk.id) |
| | | ) |
| | | ); |
| | | } |
| | | if (!hasNoModuleDeferred) { |
| | | array.push(item.asyncDeps); |
| | | } |
| | | map[item.userRequest] = array; |
| | | } |
| | | } |
| | | |
| | | const chunksStartPosition = hasFakeMap ? 2 : 1; |
| | | const chunksPosition = hasFakeMap ? 2 : 1; |
| | | const asyncDepsPosition = chunksPosition + 1; |
| | | const requestPrefix = hasNoChunk |
| | | ? "Promise.resolve()" |
| | | : hasMultipleOrNoChunks |
| | | ? `Promise.all(ids.slice(${chunksStartPosition}).map(${RuntimeGlobals.ensureChunk}))` |
| | | : `${RuntimeGlobals.ensureChunk}(ids[${chunksStartPosition}])`; |
| | | ? `Promise.all(ids[${chunksPosition}].map(${RuntimeGlobals.ensureChunk}))` |
| | | : `${RuntimeGlobals.ensureChunk}(ids[${chunksPosition}][0])`; |
| | | const returnModuleObject = this.getReturnModuleObjectSource( |
| | | fakeMap, |
| | | true, |
| | | hasNoModuleDeferred ? undefined : `ids[${asyncDepsPosition}]`, |
| | | shortMode ? "invalid" : "ids[1]" |
| | | ); |
| | | |
| | |
| | | requestPrefix === "Promise.resolve()" |
| | | ? ` |
| | | function webpackAsyncContext(req) { |
| | | return Promise.resolve().then(${arrow ? "() =>" : "function()"} { |
| | | if(!${RuntimeGlobals.hasOwnProperty}(map, req)) { |
| | | var e = new Error("Cannot find module '" + req + "'"); |
| | | e.code = 'MODULE_NOT_FOUND'; |
| | | throw e; |
| | | } |
| | | |
| | | ${shortMode ? "var id = map[req];" : "var ids = map[req], id = ids[0];"} |
| | | ${returnModuleObject} |
| | | }); |
| | | return Promise.resolve().then(${runtimeTemplate.basicFunction("", [ |
| | | `if(!${RuntimeGlobals.hasOwnProperty}(map, req)) {`, |
| | | Template.indent([ |
| | | 'var e = new Error("Cannot find module \'" + req + "\'");', |
| | | "e.code = 'MODULE_NOT_FOUND';", |
| | | "throw e;" |
| | | ]), |
| | | "}", |
| | | shortMode ? "var id = map[req];" : "var ids = map[req], id = ids[0];", |
| | | `return ${returnModuleObject};` |
| | | ])}); |
| | | }` |
| | | : `function webpackAsyncContext(req) { |
| | | if(!${RuntimeGlobals.hasOwnProperty}(map, req)) { |
| | | return Promise.resolve().then(${arrow ? "() =>" : "function()"} { |
| | | var e = new Error("Cannot find module '" + req + "'"); |
| | | e.code = 'MODULE_NOT_FOUND'; |
| | | throw e; |
| | | }); |
| | | try { |
| | | if(!${RuntimeGlobals.hasOwnProperty}(map, req)) { |
| | | return Promise.resolve().then(${runtimeTemplate.basicFunction("", [ |
| | | 'var e = new Error("Cannot find module \'" + req + "\'");', |
| | | "e.code = 'MODULE_NOT_FOUND';", |
| | | "throw e;" |
| | | ])}); |
| | | } |
| | | } catch(err) { |
| | | return Promise.reject(err); |
| | | } |
| | | |
| | | var ids = map[req], id = ids[0]; |
| | | return ${requestPrefix}.then(${arrow ? "() =>" : "function()"} { |
| | | ${returnModuleObject} |
| | | }); |
| | | return ${requestPrefix}.then(${runtimeTemplate.returningFunction(returnModuleObject)}); |
| | | }`; |
| | | |
| | | return `var map = ${JSON.stringify(map, null, "\t")}; |
| | |
| | | * @returns {string} source for empty async context |
| | | */ |
| | | getSourceForEmptyAsyncContext(id, runtimeTemplate) { |
| | | const arrow = runtimeTemplate.supportsArrowFunction(); |
| | | return `function webpackEmptyAsyncContext(req) { |
| | | // Here Promise.resolve().then() is used instead of new Promise() to prevent |
| | | // uncaught exception popping up in devtools |
| | | return Promise.resolve().then(${arrow ? "() =>" : "function()"} { |
| | | var e = new Error("Cannot find module '" + req + "'"); |
| | | e.code = 'MODULE_NOT_FOUND'; |
| | | throw e; |
| | | }); |
| | | return Promise.resolve().then(${runtimeTemplate.basicFunction("", [ |
| | | 'var e = new Error("Cannot find module \'" + req + "\'");', |
| | | "e.code = 'MODULE_NOT_FOUND';", |
| | | "throw e;" |
| | | ])}); |
| | | } |
| | | webpackEmptyAsyncContext.keys = ${runtimeTemplate.returningFunction("[]")}; |
| | | webpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext; |
| | |
| | | |
| | | /** |
| | | * @param {string} asyncMode module mode |
| | | * @param {ImportPhaseType} phase import phase |
| | | * @param {CodeGenerationContext} context context info |
| | | * @returns {string} the source code |
| | | */ |
| | | getSourceString(asyncMode, { runtimeTemplate, chunkGraph }) { |
| | | getSourceString(asyncMode, phase, { runtimeTemplate, chunkGraph }) { |
| | | const id = /** @type {ModuleId} */ (chunkGraph.getModuleId(this)); |
| | | if (asyncMode === "lazy") { |
| | | if (this.blocks && this.blocks.length > 0) { |
| | | return this.getLazySource(this.blocks, id, { |
| | | return this.getLazySource(this.blocks, id, phase, { |
| | | runtimeTemplate, |
| | | chunkGraph |
| | | }); |
| | |
| | | } |
| | | if (asyncMode === "eager") { |
| | | if (this.dependencies && this.dependencies.length > 0) { |
| | | return this.getEagerSource(this.dependencies, id, { |
| | | return this.getEagerSource(this.dependencies, id, phase, { |
| | | chunkGraph, |
| | | runtimeTemplate |
| | | }); |
| | |
| | | if (asyncMode === "lazy-once") { |
| | | const block = this.blocks[0]; |
| | | if (block) { |
| | | return this.getLazyOnceSource(block, block.dependencies, id, { |
| | | return this.getLazyOnceSource(block, block.dependencies, id, phase, { |
| | | runtimeTemplate, |
| | | chunkGraph |
| | | }); |
| | |
| | | } |
| | | if (asyncMode === "async-weak") { |
| | | if (this.dependencies && this.dependencies.length > 0) { |
| | | return this.getAsyncWeakSource(this.dependencies, id, { |
| | | return this.getAsyncWeakSource(this.dependencies, id, phase, { |
| | | chunkGraph, |
| | | runtimeTemplate |
| | | }); |
| | |
| | | } |
| | | |
| | | /** |
| | | * Generates code and runtime requirements for this module. |
| | | * @param {CodeGenerationContext} context context for code generation |
| | | * @returns {CodeGenerationResult} result |
| | | */ |
| | | codeGeneration(context) { |
| | | const { chunkGraph, compilation } = context; |
| | | |
| | | /** @type {Sources} */ |
| | | const sources = new Map(); |
| | | sources.set( |
| | | "javascript", |
| | | JAVASCRIPT_TYPE, |
| | | this.getSource( |
| | | this.getSourceString(this.options.mode, context), |
| | | this.getSourceString( |
| | | this.options.mode, |
| | | this.options.phase || ImportPhase.Evaluation, |
| | | context |
| | | ), |
| | | compilation |
| | | ) |
| | | ); |
| | | /** @type {RuntimeRequirements} */ |
| | | const set = new Set(); |
| | | const allDeps = |
| | | this.dependencies.length > 0 |
| | |
| | | if (this.getFakeMap(allDeps, chunkGraph) !== 9) { |
| | | set.add(RuntimeGlobals.createFakeNamespaceObject); |
| | | } |
| | | if ( |
| | | ImportPhaseUtils.isDefer(this.options.phase || ImportPhase.Evaluation) |
| | | ) { |
| | | set.add(RuntimeGlobals.makeDeferredNamespaceObject); |
| | | } |
| | | } |
| | | return { |
| | | sources, |
| | |
| | | } |
| | | |
| | | /** |
| | | * Returns the estimated size for the requested source type. |
| | | * @param {string=} type the source type for which the size should be estimated |
| | | * @returns {number} the estimated size of the module (must be non-zero) |
| | | */ |
| | |
| | | } |
| | | |
| | | /** |
| | | * Serializes this instance into the provided serializer context. |
| | | * @param {ObjectSerializerContext} context context |
| | | */ |
| | | serialize(context) { |
| | |
| | | } |
| | | |
| | | /** |
| | | * Restores this instance from the provided deserializer context. |
| | | * @param {ObjectDeserializerContext} context context |
| | | */ |
| | | deserialize(context) { |