UNPKG

react-carousel-query

Version:

A infinite carousel component made with react that handles the pagination for you.

1,447 lines (1,333 loc) 170 kB
/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const asyncLib = require("neo-async"); const { HookMap, SyncHook, SyncBailHook, SyncWaterfallHook, AsyncSeriesHook, AsyncSeriesBailHook, AsyncParallelHook } = require("tapable"); const util = require("util"); const { CachedSource } = require("webpack-sources"); const { MultiItemCache } = require("./CacheFacade"); const Chunk = require("./Chunk"); const ChunkGraph = require("./ChunkGraph"); const ChunkGroup = require("./ChunkGroup"); const ChunkRenderError = require("./ChunkRenderError"); const ChunkTemplate = require("./ChunkTemplate"); const CodeGenerationError = require("./CodeGenerationError"); const CodeGenerationResults = require("./CodeGenerationResults"); const Dependency = require("./Dependency"); const DependencyTemplates = require("./DependencyTemplates"); const Entrypoint = require("./Entrypoint"); const ErrorHelpers = require("./ErrorHelpers"); const FileSystemInfo = require("./FileSystemInfo"); const { connectChunkGroupAndChunk, connectChunkGroupParentAndChild } = require("./GraphHelpers"); const { makeWebpackError, tryRunOrWebpackError } = require("./HookWebpackError"); const MainTemplate = require("./MainTemplate"); const Module = require("./Module"); const ModuleDependencyError = require("./ModuleDependencyError"); const ModuleDependencyWarning = require("./ModuleDependencyWarning"); const ModuleGraph = require("./ModuleGraph"); const ModuleHashingError = require("./ModuleHashingError"); const ModuleNotFoundError = require("./ModuleNotFoundError"); const ModuleProfile = require("./ModuleProfile"); const ModuleRestoreError = require("./ModuleRestoreError"); const ModuleStoreError = require("./ModuleStoreError"); const ModuleTemplate = require("./ModuleTemplate"); const { WEBPACK_MODULE_TYPE_RUNTIME } = require("./ModuleTypeConstants"); const RuntimeGlobals = require("./RuntimeGlobals"); const RuntimeTemplate = require("./RuntimeTemplate"); const Stats = require("./Stats"); const WebpackError = require("./WebpackError"); const buildChunkGraph = require("./buildChunkGraph"); const BuildCycleError = require("./errors/BuildCycleError"); const { Logger, LogType } = require("./logging/Logger"); const StatsFactory = require("./stats/StatsFactory"); const StatsPrinter = require("./stats/StatsPrinter"); const { equals: arrayEquals } = require("./util/ArrayHelpers"); const AsyncQueue = require("./util/AsyncQueue"); const LazySet = require("./util/LazySet"); const { getOrInsert } = require("./util/MapHelpers"); const WeakTupleMap = require("./util/WeakTupleMap"); const { cachedCleverMerge } = require("./util/cleverMerge"); const { compareLocations, concatComparators, compareSelect, compareIds, compareStringsNumeric, compareModulesByIdentifier } = require("./util/comparators"); const createHash = require("./util/createHash"); const { arrayToSetDeprecation, soonFrozenObjectDeprecation, createFakeHook } = require("./util/deprecation"); const processAsyncTree = require("./util/processAsyncTree"); const { getRuntimeKey } = require("./util/runtime"); const { isSourceEqual } = require("./util/source"); /** @template T @typedef {import("tapable").AsArray<T>} AsArray<T> */ /** @typedef {import("webpack-sources").Source} Source */ /** @typedef {import("../declarations/WebpackOptions").EntryDescriptionNormalized} EntryDescription */ /** @typedef {import("../declarations/WebpackOptions").OutputNormalized} OutputOptions */ /** @typedef {import("../declarations/WebpackOptions").StatsOptions} StatsOptions */ /** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */ /** @typedef {import("../declarations/WebpackOptions").WebpackPluginFunction} WebpackPluginFunction */ /** @typedef {import("../declarations/WebpackOptions").WebpackPluginInstance} WebpackPluginInstance */ /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */ /** @typedef {import("./Cache")} Cache */ /** @typedef {import("./CacheFacade")} CacheFacade */ /** @typedef {import("./Chunk").ChunkId} ChunkId */ /** @typedef {import("./ChunkGroup").ChunkGroupOptions} ChunkGroupOptions */ /** @typedef {import("./Compiler")} Compiler */ /** @typedef {import("./Compiler").CompilationParams} CompilationParams */ /** @typedef {import("./Compiler").ModuleMemCachesItem} ModuleMemCachesItem */ /** @typedef {import("./DependenciesBlock")} DependenciesBlock */ /** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */ /** @typedef {import("./Dependency").ReferencedExport} ReferencedExport */ /** @typedef {import("./DependencyTemplate")} DependencyTemplate */ /** @typedef {import("./Entrypoint").EntryOptions} EntryOptions */ /** @typedef {import("./Module").BuildInfo} BuildInfo */ /** @typedef {import("./Module").ValueCacheVersions} ValueCacheVersions */ /** @typedef {import("./NormalModule").NormalModuleCompilationHooks} NormalModuleCompilationHooks */ /** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */ /** @typedef {import("./ModuleFactory")} ModuleFactory */ /** @typedef {import("./ChunkGraph").ModuleId} ModuleId */ /** @typedef {import("./ModuleGraphConnection")} ModuleGraphConnection */ /** @typedef {import("./ModuleFactory").ModuleFactoryCreateDataContextInfo} ModuleFactoryCreateDataContextInfo */ /** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */ /** @typedef {import("./RequestShortener")} RequestShortener */ /** @typedef {import("./RuntimeModule")} RuntimeModule */ /** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry */ /** @typedef {import("./Template").RenderManifestOptions} RenderManifestOptions */ /** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsAsset} StatsAsset */ /** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsError} StatsError */ /** @typedef {import("./stats/DefaultStatsFactoryPlugin").StatsModule} StatsModule */ /** @typedef {import("./TemplatedPathPlugin").TemplatePath} TemplatePath */ /** @typedef {import("./util/Hash")} Hash */ /** @typedef {import("./util/createHash").Algorithm} Algorithm */ /** * @template T * @typedef {import("./util/deprecation").FakeHook<T>} FakeHook<T> */ /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */ /** @typedef {WeakMap<Dependency, Module>} References */ /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */ /** * @callback Callback * @param {(WebpackError | null)=} err * @returns {void} */ /** * @callback ModuleCallback * @param {(WebpackError | null)=} err * @param {(Module | null)=} result * @returns {void} */ /** * @callback ModuleFactoryResultCallback * @param {(WebpackError | null)=} err * @param {ModuleFactoryResult=} result * @returns {void} */ /** * @callback ModuleOrFactoryResultCallback * @param {(WebpackError | null)=} err * @param {Module | ModuleFactoryResult=} result * @returns {void} */ /** * @callback ExecuteModuleCallback * @param {WebpackError | null} err * @param {ExecuteModuleResult=} result * @returns {void} */ /** * @callback DepBlockVarDependenciesCallback * @param {Dependency} dependency * @returns {any} */ /** @typedef {new (...args: any[]) => Dependency} DepConstructor */ /** @typedef {Record<string, Source>} CompilationAssets */ /** * @typedef {object} AvailableModulesChunkGroupMapping * @property {ChunkGroup} chunkGroup * @property {Set<Module>} availableModules * @property {boolean} needCopy */ /** * @typedef {object} DependenciesBlockLike * @property {Dependency[]} dependencies * @property {AsyncDependenciesBlock[]} blocks */ /** * @typedef {object} ChunkPathData * @property {string|number} id * @property {string=} name * @property {string} hash * @property {function(number): string=} hashWithLength * @property {(Record<string, string>)=} contentHash * @property {(Record<string, (length: number) => string>)=} contentHashWithLength */ /** * @typedef {object} ChunkHashContext * @property {CodeGenerationResults} codeGenerationResults results of code generation * @property {RuntimeTemplate} runtimeTemplate the runtime template * @property {ModuleGraph} moduleGraph the module graph * @property {ChunkGraph} chunkGraph the chunk graph */ /** * @typedef {object} RuntimeRequirementsContext * @property {ChunkGraph} chunkGraph the chunk graph * @property {CodeGenerationResults} codeGenerationResults the code generation results */ /** * @typedef {object} ExecuteModuleOptions * @property {EntryOptions=} entryOptions */ /** * @typedef {object} ExecuteModuleResult * @property {any} exports * @property {boolean} cacheable * @property {Map<string, { source: Source, info: AssetInfo }>} assets * @property {LazySet<string>} fileDependencies * @property {LazySet<string>} contextDependencies * @property {LazySet<string>} missingDependencies * @property {LazySet<string>} buildDependencies */ /** * @typedef {{ id: string, exports: any, loaded: boolean }} ModuleObject * * /** * @typedef {object} ExecuteModuleArgument * @property {Module} module * @property {ModuleObject=} moduleObject * @property {any} preparedInfo * @property {CodeGenerationResult} codeGenerationResult */ /** * @typedef {object} ExecuteModuleContext * @property {Map<string, { source: Source, info: AssetInfo }>} assets * @property {Chunk} chunk * @property {ChunkGraph} chunkGraph * @property {function(string): any=} __webpack_require__ */ /** * @typedef {object} EntryData * @property {Dependency[]} dependencies dependencies of the entrypoint that should be evaluated at startup * @property {Dependency[]} includeDependencies dependencies of the entrypoint that should be included but not evaluated * @property {EntryOptions} options options of the entrypoint */ /** * @typedef {object} LogEntry * @property {string} type * @property {any[]=} args * @property {number} time * @property {string[]=} trace */ /** * @typedef {object} KnownAssetInfo * @property {boolean=} immutable true, if the asset can be long term cached forever (contains a hash) * @property {boolean=} minimized whether the asset is minimized * @property {string | string[]=} fullhash the value(s) of the full hash used for this asset * @property {string | string[]=} chunkhash the value(s) of the chunk hash used for this asset * @property {string | string[]=} modulehash the value(s) of the module hash used for this asset * @property {string | string[]=} contenthash the value(s) of the content hash used for this asset * @property {string=} sourceFilename when asset was created from a source file (potentially transformed), the original filename relative to compilation context * @property {number=} size size in bytes, only set after asset has been emitted * @property {boolean=} development true, when asset is only used for development and doesn't count towards user-facing assets * @property {boolean=} hotModuleReplacement true, when asset ships data for updating an existing application (HMR) * @property {boolean=} javascriptModule true, when asset is javascript and an ESM * @property {Record<string, string | string[]>=} related object of pointers to other assets, keyed by type of relation (only points from parent to child) */ /** @typedef {KnownAssetInfo & Record<string, any>} AssetInfo */ /** @typedef {{ path: string, info: AssetInfo }} InterpolatedPathAndAssetInfo */ /** * @typedef {object} Asset * @property {string} name the filename of the asset * @property {Source} source source of the asset * @property {AssetInfo} info info about the asset */ /** * @typedef {object} ModulePathData * @property {string|number} id * @property {string} hash * @property {function(number): string=} hashWithLength */ /** * @typedef {object} PathData * @property {ChunkGraph=} chunkGraph * @property {string=} hash * @property {function(number): string=} hashWithLength * @property {(Chunk|ChunkPathData)=} chunk * @property {(Module|ModulePathData)=} module * @property {RuntimeSpec=} runtime * @property {string=} filename * @property {string=} basename * @property {string=} query * @property {string=} contentHashType * @property {string=} contentHash * @property {function(number): string=} contentHashWithLength * @property {boolean=} noChunkHash * @property {string=} url */ /** * @typedef {object} KnownNormalizedStatsOptions * @property {string} context * @property {RequestShortener} requestShortener * @property {string} chunksSort * @property {string} modulesSort * @property {string} chunkModulesSort * @property {string} nestedModulesSort * @property {string} assetsSort * @property {boolean} ids * @property {boolean} cachedAssets * @property {boolean} groupAssetsByEmitStatus * @property {boolean} groupAssetsByPath * @property {boolean} groupAssetsByExtension * @property {number} assetsSpace * @property {((value: string, asset: StatsAsset) => boolean)[]} excludeAssets * @property {((name: string, module: StatsModule, type: "module" | "chunk" | "root-of-chunk" | "nested") => boolean)[]} excludeModules * @property {((warning: StatsError, textValue: string) => boolean)[]} warningsFilter * @property {boolean} cachedModules * @property {boolean} orphanModules * @property {boolean} dependentModules * @property {boolean} runtimeModules * @property {boolean} groupModulesByCacheStatus * @property {boolean} groupModulesByLayer * @property {boolean} groupModulesByAttributes * @property {boolean} groupModulesByPath * @property {boolean} groupModulesByExtension * @property {boolean} groupModulesByType * @property {boolean | "auto"} entrypoints * @property {boolean} chunkGroups * @property {boolean} chunkGroupAuxiliary * @property {boolean} chunkGroupChildren * @property {number} chunkGroupMaxAssets * @property {number} modulesSpace * @property {number} chunkModulesSpace * @property {number} nestedModulesSpace * @property {false|"none"|"error"|"warn"|"info"|"log"|"verbose"} logging * @property {((value: string) => boolean)[]} loggingDebug * @property {boolean} loggingTrace * @property {any} _env */ /** @typedef {KnownNormalizedStatsOptions & Omit<StatsOptions, keyof KnownNormalizedStatsOptions> & Record<string, any>} NormalizedStatsOptions */ /** * @typedef {object} KnownCreateStatsOptionsContext * @property {boolean=} forToString */ /** @typedef {Record<string, any> & KnownCreateStatsOptionsContext} CreateStatsOptionsContext */ /** @typedef {{module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[]}[]} CodeGenerationJobs */ /** @typedef {{javascript: ModuleTemplate}} ModuleTemplates */ /** @typedef {Set<Module>} NotCodeGeneratedModules */ /** @type {AssetInfo} */ const EMPTY_ASSET_INFO = Object.freeze({}); const esmDependencyCategory = "esm"; // TODO webpack 6: remove const deprecatedNormalModuleLoaderHook = util.deprecate( /** * @param {Compilation} compilation compilation * @returns {NormalModuleCompilationHooks["loader"]} hooks */ compilation => require("./NormalModule").getCompilationHooks(compilation).loader, "Compilation.hooks.normalModuleLoader was moved to NormalModule.getCompilationHooks(compilation).loader", "DEP_WEBPACK_COMPILATION_NORMAL_MODULE_LOADER_HOOK" ); // TODO webpack 6: remove /** * @param {ModuleTemplates | undefined} moduleTemplates module templates */ const defineRemovedModuleTemplates = moduleTemplates => { Object.defineProperties(moduleTemplates, { asset: { enumerable: false, configurable: false, get: () => { throw new WebpackError( "Compilation.moduleTemplates.asset has been removed" ); } }, webassembly: { enumerable: false, configurable: false, get: () => { throw new WebpackError( "Compilation.moduleTemplates.webassembly has been removed" ); } } }); moduleTemplates = undefined; }; const byId = compareSelect(c => c.id, compareIds); const byNameOrHash = concatComparators( compareSelect(c => c.name, compareIds), compareSelect(c => c.fullHash, compareIds) ); const byMessage = compareSelect(err => `${err.message}`, compareStringsNumeric); const byModule = compareSelect( err => (err.module && err.module.identifier()) || "", compareStringsNumeric ); const byLocation = compareSelect(err => err.loc, compareLocations); const compareErrors = concatComparators(byModule, byLocation, byMessage); /** @type {WeakMap<Dependency, Module & { restoreFromUnsafeCache: Function } | null>} */ const unsafeCacheDependencies = new WeakMap(); /** @type {WeakMap<Module & { restoreFromUnsafeCache: Function }, object>} */ const unsafeCacheData = new WeakMap(); class Compilation { /** * Creates an instance of Compilation. * @param {Compiler} compiler the compiler which created the compilation * @param {CompilationParams} params the compilation parameters */ constructor(compiler, params) { this._backCompat = compiler._backCompat; const getNormalModuleLoader = () => deprecatedNormalModuleLoaderHook(this); /** @typedef {{ additionalAssets?: true | Function }} ProcessAssetsAdditionalOptions */ /** @type {AsyncSeriesHook<[CompilationAssets], ProcessAssetsAdditionalOptions>} */ const processAssetsHook = new AsyncSeriesHook(["assets"]); let savedAssets = new Set(); /** * @param {CompilationAssets} assets assets * @returns {CompilationAssets} new assets */ const popNewAssets = assets => { let newAssets; for (const file of Object.keys(assets)) { if (savedAssets.has(file)) continue; if (newAssets === undefined) { newAssets = Object.create(null); } newAssets[file] = assets[file]; savedAssets.add(file); } return newAssets; }; processAssetsHook.intercept({ name: "Compilation", call: () => { savedAssets = new Set(Object.keys(this.assets)); }, register: tap => { const { type, name } = tap; const { fn, additionalAssets, ...remainingTap } = tap; const additionalAssetsFn = additionalAssets === true ? fn : additionalAssets; const processedAssets = additionalAssetsFn ? new WeakSet() : undefined; switch (type) { case "sync": if (additionalAssetsFn) { this.hooks.processAdditionalAssets.tap(name, assets => { if (processedAssets.has(this.assets)) additionalAssetsFn(assets); }); } return { ...remainingTap, type: "async", fn: (assets, callback) => { try { fn(assets); } catch (err) { return callback(err); } if (processedAssets !== undefined) processedAssets.add(this.assets); const newAssets = popNewAssets(assets); if (newAssets !== undefined) { this.hooks.processAdditionalAssets.callAsync( newAssets, callback ); return; } callback(); } }; case "async": if (additionalAssetsFn) { this.hooks.processAdditionalAssets.tapAsync( name, (assets, callback) => { if (processedAssets.has(this.assets)) return additionalAssetsFn(assets, callback); callback(); } ); } return { ...remainingTap, fn: (assets, callback) => { fn(assets, err => { if (err) return callback(err); if (processedAssets !== undefined) processedAssets.add(this.assets); const newAssets = popNewAssets(assets); if (newAssets !== undefined) { this.hooks.processAdditionalAssets.callAsync( newAssets, callback ); return; } callback(); }); } }; case "promise": if (additionalAssetsFn) { this.hooks.processAdditionalAssets.tapPromise(name, assets => { if (processedAssets.has(this.assets)) return additionalAssetsFn(assets); return Promise.resolve(); }); } return { ...remainingTap, fn: assets => { const p = fn(assets); if (!p || !p.then) return p; return p.then(() => { if (processedAssets !== undefined) processedAssets.add(this.assets); const newAssets = popNewAssets(assets); if (newAssets !== undefined) { return this.hooks.processAdditionalAssets.promise( newAssets ); } }); } }; } } }); /** @type {SyncHook<[CompilationAssets]>} */ const afterProcessAssetsHook = new SyncHook(["assets"]); /** * @template T * @param {string} name name of the hook * @param {number} stage new stage * @param {function(): AsArray<T>} getArgs get old hook function args * @param {string=} code deprecation code (not deprecated when unset) * @returns {FakeHook<Pick<AsyncSeriesHook<T>, "tap" | "tapAsync" | "tapPromise" | "name">>} fake hook which redirects */ const createProcessAssetsHook = (name, stage, getArgs, code) => { if (!this._backCompat && code) return; /** * @param {string} reason reason * @returns {string} error message */ const errorMessage = reason => `Can't automatically convert plugin using Compilation.hooks.${name} to Compilation.hooks.processAssets because ${reason}. BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a single Compilation.hooks.processAssets hook.`; const getOptions = options => { if (typeof options === "string") options = { name: options }; if (options.stage) { throw new Error(errorMessage("it's using the 'stage' option")); } return { ...options, stage }; }; return createFakeHook( { name, /** @type {AsyncSeriesHook<T>["intercept"]} */ intercept(interceptor) { throw new Error(errorMessage("it's using 'intercept'")); }, /** @type {AsyncSeriesHook<T>["tap"]} */ tap: (options, fn) => { processAssetsHook.tap(getOptions(options), () => fn(...getArgs())); }, /** @type {AsyncSeriesHook<T>["tapAsync"]} */ tapAsync: (options, fn) => { processAssetsHook.tapAsync( getOptions(options), (assets, callback) => /** @type {any} */ (fn)(...getArgs(), callback) ); }, /** @type {AsyncSeriesHook<T>["tapPromise"]} */ tapPromise: (options, fn) => { processAssetsHook.tapPromise(getOptions(options), () => fn(...getArgs()) ); } }, `${name} is deprecated (use Compilation.hooks.processAssets instead and use one of Compilation.PROCESS_ASSETS_STAGE_* as stage option)`, code ); }; this.hooks = Object.freeze({ /** @type {SyncHook<[Module]>} */ buildModule: new SyncHook(["module"]), /** @type {SyncHook<[Module]>} */ rebuildModule: new SyncHook(["module"]), /** @type {SyncHook<[Module, WebpackError]>} */ failedModule: new SyncHook(["module", "error"]), /** @type {SyncHook<[Module]>} */ succeedModule: new SyncHook(["module"]), /** @type {SyncHook<[Module]>} */ stillValidModule: new SyncHook(["module"]), /** @type {SyncHook<[Dependency, EntryOptions]>} */ addEntry: new SyncHook(["entry", "options"]), /** @type {SyncHook<[Dependency, EntryOptions, Error]>} */ failedEntry: new SyncHook(["entry", "options", "error"]), /** @type {SyncHook<[Dependency, EntryOptions, Module]>} */ succeedEntry: new SyncHook(["entry", "options", "module"]), /** @type {SyncWaterfallHook<[(string[] | ReferencedExport)[], Dependency, RuntimeSpec]>} */ dependencyReferencedExports: new SyncWaterfallHook([ "referencedExports", "dependency", "runtime" ]), /** @type {SyncHook<[ExecuteModuleArgument, ExecuteModuleContext]>} */ executeModule: new SyncHook(["options", "context"]), /** @type {AsyncParallelHook<[ExecuteModuleArgument, ExecuteModuleContext]>} */ prepareModuleExecution: new AsyncParallelHook(["options", "context"]), /** @type {AsyncSeriesHook<[Iterable<Module>]>} */ finishModules: new AsyncSeriesHook(["modules"]), /** @type {AsyncSeriesHook<[Module]>} */ finishRebuildingModule: new AsyncSeriesHook(["module"]), /** @type {SyncHook<[]>} */ unseal: new SyncHook([]), /** @type {SyncHook<[]>} */ seal: new SyncHook([]), /** @type {SyncHook<[]>} */ beforeChunks: new SyncHook([]), /** * The `afterChunks` hook is called directly after the chunks and module graph have * been created and before the chunks and modules have been optimized. This hook is useful to * inspect, analyze, and/or modify the chunk graph. * @type {SyncHook<[Iterable<Chunk>]>} */ afterChunks: new SyncHook(["chunks"]), /** @type {SyncBailHook<[Iterable<Module>], boolean | void>} */ optimizeDependencies: new SyncBailHook(["modules"]), /** @type {SyncHook<[Iterable<Module>]>} */ afterOptimizeDependencies: new SyncHook(["modules"]), /** @type {SyncHook<[]>} */ optimize: new SyncHook([]), /** @type {SyncBailHook<[Iterable<Module>], boolean | void>} */ optimizeModules: new SyncBailHook(["modules"]), /** @type {SyncHook<[Iterable<Module>]>} */ afterOptimizeModules: new SyncHook(["modules"]), /** @type {SyncBailHook<[Iterable<Chunk>, ChunkGroup[]], boolean | void>} */ optimizeChunks: new SyncBailHook(["chunks", "chunkGroups"]), /** @type {SyncHook<[Iterable<Chunk>, ChunkGroup[]]>} */ afterOptimizeChunks: new SyncHook(["chunks", "chunkGroups"]), /** @type {AsyncSeriesHook<[Iterable<Chunk>, Iterable<Module>]>} */ optimizeTree: new AsyncSeriesHook(["chunks", "modules"]), /** @type {SyncHook<[Iterable<Chunk>, Iterable<Module>]>} */ afterOptimizeTree: new SyncHook(["chunks", "modules"]), /** @type {AsyncSeriesBailHook<[Iterable<Chunk>, Iterable<Module>], void>} */ optimizeChunkModules: new AsyncSeriesBailHook(["chunks", "modules"]), /** @type {SyncHook<[Iterable<Chunk>, Iterable<Module>]>} */ afterOptimizeChunkModules: new SyncHook(["chunks", "modules"]), /** @type {SyncBailHook<[], boolean | void>} */ shouldRecord: new SyncBailHook([]), /** @type {SyncHook<[Chunk, Set<string>, RuntimeRequirementsContext]>} */ additionalChunkRuntimeRequirements: new SyncHook([ "chunk", "runtimeRequirements", "context" ]), /** @type {HookMap<SyncBailHook<[Chunk, Set<string>, RuntimeRequirementsContext], void>>} */ runtimeRequirementInChunk: new HookMap( () => new SyncBailHook(["chunk", "runtimeRequirements", "context"]) ), /** @type {SyncHook<[Module, Set<string>, RuntimeRequirementsContext]>} */ additionalModuleRuntimeRequirements: new SyncHook([ "module", "runtimeRequirements", "context" ]), /** @type {HookMap<SyncBailHook<[Module, Set<string>, RuntimeRequirementsContext], void>>} */ runtimeRequirementInModule: new HookMap( () => new SyncBailHook(["module", "runtimeRequirements", "context"]) ), /** @type {SyncHook<[Chunk, Set<string>, RuntimeRequirementsContext]>} */ additionalTreeRuntimeRequirements: new SyncHook([ "chunk", "runtimeRequirements", "context" ]), /** @type {HookMap<SyncBailHook<[Chunk, Set<string>, RuntimeRequirementsContext], void>>} */ runtimeRequirementInTree: new HookMap( () => new SyncBailHook(["chunk", "runtimeRequirements", "context"]) ), /** @type {SyncHook<[RuntimeModule, Chunk]>} */ runtimeModule: new SyncHook(["module", "chunk"]), /** @type {SyncHook<[Iterable<Module>, any]>} */ reviveModules: new SyncHook(["modules", "records"]), /** @type {SyncHook<[Iterable<Module>]>} */ beforeModuleIds: new SyncHook(["modules"]), /** @type {SyncHook<[Iterable<Module>]>} */ moduleIds: new SyncHook(["modules"]), /** @type {SyncHook<[Iterable<Module>]>} */ optimizeModuleIds: new SyncHook(["modules"]), /** @type {SyncHook<[Iterable<Module>]>} */ afterOptimizeModuleIds: new SyncHook(["modules"]), /** @type {SyncHook<[Iterable<Chunk>, any]>} */ reviveChunks: new SyncHook(["chunks", "records"]), /** @type {SyncHook<[Iterable<Chunk>]>} */ beforeChunkIds: new SyncHook(["chunks"]), /** @type {SyncHook<[Iterable<Chunk>]>} */ chunkIds: new SyncHook(["chunks"]), /** @type {SyncHook<[Iterable<Chunk>]>} */ optimizeChunkIds: new SyncHook(["chunks"]), /** @type {SyncHook<[Iterable<Chunk>]>} */ afterOptimizeChunkIds: new SyncHook(["chunks"]), /** @type {SyncHook<[Iterable<Module>, any]>} */ recordModules: new SyncHook(["modules", "records"]), /** @type {SyncHook<[Iterable<Chunk>, any]>} */ recordChunks: new SyncHook(["chunks", "records"]), /** @type {SyncHook<[Iterable<Module>]>} */ optimizeCodeGeneration: new SyncHook(["modules"]), /** @type {SyncHook<[]>} */ beforeModuleHash: new SyncHook([]), /** @type {SyncHook<[]>} */ afterModuleHash: new SyncHook([]), /** @type {SyncHook<[]>} */ beforeCodeGeneration: new SyncHook([]), /** @type {SyncHook<[]>} */ afterCodeGeneration: new SyncHook([]), /** @type {SyncHook<[]>} */ beforeRuntimeRequirements: new SyncHook([]), /** @type {SyncHook<[]>} */ afterRuntimeRequirements: new SyncHook([]), /** @type {SyncHook<[]>} */ beforeHash: new SyncHook([]), /** @type {SyncHook<[Chunk]>} */ contentHash: new SyncHook(["chunk"]), /** @type {SyncHook<[]>} */ afterHash: new SyncHook([]), /** @type {SyncHook<[any]>} */ recordHash: new SyncHook(["records"]), /** @type {SyncHook<[Compilation, any]>} */ record: new SyncHook(["compilation", "records"]), /** @type {SyncHook<[]>} */ beforeModuleAssets: new SyncHook([]), /** @type {SyncBailHook<[], boolean | void>} */ shouldGenerateChunkAssets: new SyncBailHook([]), /** @type {SyncHook<[]>} */ beforeChunkAssets: new SyncHook([]), // TODO webpack 6 remove /** @deprecated */ additionalChunkAssets: createProcessAssetsHook( "additionalChunkAssets", Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL, () => [this.chunks], "DEP_WEBPACK_COMPILATION_ADDITIONAL_CHUNK_ASSETS" ), // TODO webpack 6 deprecate /** @deprecated */ additionalAssets: createProcessAssetsHook( "additionalAssets", Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL, () => [] ), // TODO webpack 6 remove /** @deprecated */ optimizeChunkAssets: createProcessAssetsHook( "optimizeChunkAssets", Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE, () => [this.chunks], "DEP_WEBPACK_COMPILATION_OPTIMIZE_CHUNK_ASSETS" ), // TODO webpack 6 remove /** @deprecated */ afterOptimizeChunkAssets: createProcessAssetsHook( "afterOptimizeChunkAssets", Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE + 1, () => [this.chunks], "DEP_WEBPACK_COMPILATION_AFTER_OPTIMIZE_CHUNK_ASSETS" ), // TODO webpack 6 deprecate /** @deprecated */ optimizeAssets: processAssetsHook, // TODO webpack 6 deprecate /** @deprecated */ afterOptimizeAssets: afterProcessAssetsHook, processAssets: processAssetsHook, afterProcessAssets: afterProcessAssetsHook, /** @type {AsyncSeriesHook<[CompilationAssets]>} */ processAdditionalAssets: new AsyncSeriesHook(["assets"]), /** @type {SyncBailHook<[], boolean | void>} */ needAdditionalSeal: new SyncBailHook([]), /** @type {AsyncSeriesHook<[]>} */ afterSeal: new AsyncSeriesHook([]), /** @type {SyncWaterfallHook<[RenderManifestEntry[], RenderManifestOptions]>} */ renderManifest: new SyncWaterfallHook(["result", "options"]), /** @type {SyncHook<[Hash]>} */ fullHash: new SyncHook(["hash"]), /** @type {SyncHook<[Chunk, Hash, ChunkHashContext]>} */ chunkHash: new SyncHook(["chunk", "chunkHash", "ChunkHashContext"]), /** @type {SyncHook<[Module, string]>} */ moduleAsset: new SyncHook(["module", "filename"]), /** @type {SyncHook<[Chunk, string]>} */ chunkAsset: new SyncHook(["chunk", "filename"]), /** @type {SyncWaterfallHook<[string, object, AssetInfo | undefined]>} */ assetPath: new SyncWaterfallHook(["path", "options", "assetInfo"]), /** @type {SyncBailHook<[], boolean | void>} */ needAdditionalPass: new SyncBailHook([]), /** @type {SyncHook<[Compiler, string, number]>} */ childCompiler: new SyncHook([ "childCompiler", "compilerName", "compilerIndex" ]), /** @type {SyncBailHook<[string, LogEntry], boolean | void>} */ log: new SyncBailHook(["origin", "logEntry"]), /** @type {SyncWaterfallHook<[WebpackError[]]>} */ processWarnings: new SyncWaterfallHook(["warnings"]), /** @type {SyncWaterfallHook<[WebpackError[]]>} */ processErrors: new SyncWaterfallHook(["errors"]), /** @type {HookMap<SyncHook<[Partial<NormalizedStatsOptions>, CreateStatsOptionsContext]>>} */ statsPreset: new HookMap(() => new SyncHook(["options", "context"])), /** @type {SyncHook<[Partial<NormalizedStatsOptions>, CreateStatsOptionsContext]>} */ statsNormalize: new SyncHook(["options", "context"]), /** @type {SyncHook<[StatsFactory, NormalizedStatsOptions]>} */ statsFactory: new SyncHook(["statsFactory", "options"]), /** @type {SyncHook<[StatsPrinter, NormalizedStatsOptions]>} */ statsPrinter: new SyncHook(["statsPrinter", "options"]), get normalModuleLoader() { return getNormalModuleLoader(); } }); /** @type {string=} */ this.name = undefined; /** @type {number | undefined} */ this.startTime = undefined; /** @type {number | undefined} */ this.endTime = undefined; /** @type {Compiler} */ this.compiler = compiler; this.resolverFactory = compiler.resolverFactory; /** @type {InputFileSystem} */ this.inputFileSystem = /** @type {InputFileSystem} */ (compiler.inputFileSystem); this.fileSystemInfo = new FileSystemInfo(this.inputFileSystem, { unmanagedPaths: compiler.unmanagedPaths, managedPaths: compiler.managedPaths, immutablePaths: compiler.immutablePaths, logger: this.getLogger("webpack.FileSystemInfo"), hashFunction: compiler.options.output.hashFunction }); if (compiler.fileTimestamps) { this.fileSystemInfo.addFileTimestamps(compiler.fileTimestamps, true); } if (compiler.contextTimestamps) { this.fileSystemInfo.addContextTimestamps( compiler.contextTimestamps, true ); } /** @type {ValueCacheVersions} */ this.valueCacheVersions = new Map(); this.requestShortener = compiler.requestShortener; this.compilerPath = compiler.compilerPath; this.logger = this.getLogger("webpack.Compilation"); const options = /** @type {WebpackOptions} */ (compiler.options); this.options = options; this.outputOptions = options && options.output; /** @type {boolean} */ this.bail = (options && options.bail) || false; /** @type {boolean} */ this.profile = (options && options.profile) || false; this.params = params; this.mainTemplate = new MainTemplate(this.outputOptions, this); this.chunkTemplate = new ChunkTemplate(this.outputOptions, this); this.runtimeTemplate = new RuntimeTemplate( this, this.outputOptions, this.requestShortener ); /** @type {ModuleTemplates} */ this.moduleTemplates = { javascript: new ModuleTemplate(this.runtimeTemplate, this) }; defineRemovedModuleTemplates(this.moduleTemplates); /** @type {Map<Module, WeakTupleMap<any, any>> | undefined} */ this.moduleMemCaches = undefined; /** @type {Map<Module, WeakTupleMap<any, any>> | undefined} */ this.moduleMemCaches2 = undefined; this.moduleGraph = new ModuleGraph(); /** @type {ChunkGraph} */ this.chunkGraph = undefined; /** @type {CodeGenerationResults} */ this.codeGenerationResults = undefined; /** @type {AsyncQueue<Module, Module, Module>} */ this.processDependenciesQueue = new AsyncQueue({ name: "processDependencies", parallelism: options.parallelism || 100, processor: this._processModuleDependencies.bind(this) }); /** @type {AsyncQueue<Module, string, Module>} */ this.addModuleQueue = new AsyncQueue({ name: "addModule", parent: this.processDependenciesQueue, getKey: module => module.identifier(), processor: this._addModule.bind(this) }); /** @type {AsyncQueue<FactorizeModuleOptions, string, Module | ModuleFactoryResult>} */ this.factorizeQueue = new AsyncQueue({ name: "factorize", parent: this.addModuleQueue, processor: this._factorizeModule.bind(this) }); /** @type {AsyncQueue<Module, Module, Module>} */ this.buildQueue = new AsyncQueue({ name: "build", parent: this.factorizeQueue, processor: this._buildModule.bind(this) }); /** @type {AsyncQueue<Module, Module, Module>} */ this.rebuildQueue = new AsyncQueue({ name: "rebuild", parallelism: options.parallelism || 100, processor: this._rebuildModule.bind(this) }); /** * Modules in value are building during the build of Module in key. * Means value blocking key from finishing. * Needed to detect build cycles. * @type {WeakMap<Module, Set<Module>>} */ this.creatingModuleDuringBuild = new WeakMap(); /** @type {Map<string, EntryData>} */ this.entries = new Map(); /** @type {EntryData} */ this.globalEntry = { dependencies: [], includeDependencies: [], options: { name: undefined } }; /** @type {Map<string, Entrypoint>} */ this.entrypoints = new Map(); /** @type {Entrypoint[]} */ this.asyncEntrypoints = []; /** @type {Set<Chunk>} */ this.chunks = new Set(); /** @type {ChunkGroup[]} */ this.chunkGroups = []; /** @type {Map<string, ChunkGroup>} */ this.namedChunkGroups = new Map(); /** @type {Map<string, Chunk>} */ this.namedChunks = new Map(); /** @type {Set<Module>} */ this.modules = new Set(); if (this._backCompat) { arrayToSetDeprecation(this.chunks, "Compilation.chunks"); arrayToSetDeprecation(this.modules, "Compilation.modules"); } /** * @private * @type {Map<string, Module>} */ this._modules = new Map(); this.records = null; /** @type {string[]} */ this.additionalChunkAssets = []; /** @type {CompilationAssets} */ this.assets = {}; /** @type {Map<string, AssetInfo>} */ this.assetsInfo = new Map(); /** @type {Map<string, Map<string, Set<string>>>} */ this._assetsRelatedIn = new Map(); /** @type {WebpackError[]} */ this.errors = []; /** @type {WebpackError[]} */ this.warnings = []; /** @type {Compilation[]} */ this.children = []; /** @type {Map<string, LogEntry[]>} */ this.logging = new Map(); /** @type {Map<DepConstructor, ModuleFactory>} */ this.dependencyFactories = new Map(); /** @type {DependencyTemplates} */ this.dependencyTemplates = new DependencyTemplates( this.outputOptions.hashFunction ); /** @type {Record<string, number>} */ this.childrenCounters = {}; /** @type {Set<number|string>} */ this.usedChunkIds = null; /** @type {Set<number>} */ this.usedModuleIds = null; /** @type {boolean} */ this.needAdditionalPass = false; /** @type {Set<Module & { restoreFromUnsafeCache: Function }>} */ this._restoredUnsafeCacheModuleEntries = new Set(); /** @type {Map<string, Module & { restoreFromUnsafeCache: Function }>} */ this._restoredUnsafeCacheEntries = new Map(); /** @type {WeakSet<Module>} */ this.builtModules = new WeakSet(); /** @type {WeakSet<Module>} */ this.codeGeneratedModules = new WeakSet(); /** @type {WeakSet<Module>} */ this.buildTimeExecutedModules = new WeakSet(); /** @type {Set<string>} */ this.emittedAssets = new Set(); /** @type {Set<string>} */ this.comparedForEmitAssets = new Set(); /** @type {LazySet<string>} */ this.fileDependencies = new LazySet(); /** @type {LazySet<string>} */ this.contextDependencies = new LazySet(); /** @type {LazySet<string>} */ this.missingDependencies = new LazySet(); /** @type {LazySet<string>} */ this.buildDependencies = new LazySet(); // TODO webpack 6 remove this.compilationDependencies = { add: util.deprecate( /** * @param {string} item item * @returns {LazySet<string>} file dependencies */ item => this.fileDependencies.add(item), "Compilation.compilationDependencies is deprecated (used Compilation.fileDependencies instead)", "DEP_WEBPACK_COMPILATION_COMPILATION_DEPENDENCIES" ) }; this._modulesCache = this.getCache("Compilation/modules"); this._assetsCache = this.getCache("Compilation/assets"); this._codeGenerationCache = this.getCache("Compilation/codeGeneration"); const unsafeCache = options.module.unsafeCache; this._unsafeCache = Boolean(unsafeCache); this._unsafeCachePredicate = typeof unsafeCache === "function" ? unsafeCache : () => true; } getStats() { return new Stats(this); } /** * @param {string | boolean | StatsOptions | undefined} optionsOrPreset stats option value * @param {CreateStatsOptionsContext=} context context * @returns {NormalizedStatsOptions} normalized options */ createStatsOptions(optionsOrPreset, context = {}) { if (typeof optionsOrPreset === "boolean") { optionsOrPreset = { preset: optionsOrPreset === false ? "none" : "normal" }; } else if (typeof optionsOrPreset === "string") { optionsOrPreset = { preset: optionsOrPreset }; } if (typeof optionsOrPreset === "object" && optionsOrPreset !== null) { // We use this method of shallow cloning this object to include // properties in the prototype chain /** @type {Partial<NormalizedStatsOptions>} */ const options = {}; // eslint-disable-next-line guard-for-in for (const key in optionsOrPreset) { options[key] = optionsOrPreset[/** @type {keyof StatsOptions} */ (key)]; } if (options.preset !== undefined) { this.hooks.statsPreset.for(options.preset).call(options, context); } this.hooks.statsNormalize.call(options, context); return /** @type {NormalizedStatsOptions} */ (options); } /** @type {Partial<NormalizedStatsOptions>} */ const options = {}; this.hooks.statsNormalize.call(options, context); return /** @type {NormalizedStatsOptions} */ (options); } /** * @param {NormalizedStatsOptions} options options * @returns {StatsFactory} the stats factory */ createStatsFactory(options) { const statsFactory = new StatsFactory(); this.hooks.statsFactory.call(statsFactory, options); return statsFactory; } /** * @param {NormalizedStatsOptions} options options * @returns {StatsPrinter} the stats printer */ createStatsPrinter(options) { const statsPrinter = new StatsPrinter(); this.hooks.statsPrinter.call(statsPrinter, options); return statsPrinter; } /** * @param {string} name cache name * @returns {CacheFacade} the cache facade instance */ getCache(name) { return this.compiler.getCache(name); } /** * @param {string | (function(): string)} name name of the logger, or function called once to get the logger name * @returns {Logger} a logger with that name */ getLogger(name) { if (!name) { throw new TypeError("Compilation.getLogger(name) called without a name"); } /** @type {LogEntry[] | undefined} */ let logEntries; return new Logger( (type, args) => { if (typeof name === "function") { name = name(); if (!name) { throw new TypeError( "Compilation.getLogger(name) called with a function not returning a name" ); } } let trace; switch (type) { case LogType.warn: case LogType.error: case LogType.trace: trace = ErrorHelpers.cutOffLoaderExecution( /** @type {string} */ (new Error("Trace").stack) ) .split("\n") .slice(3); break; } /** @type {LogEntry} */ const logEntry = { time: Date.now(), type, args, trace }; if (this.hooks.log.call(name, logEntry) === undefined) { if ( logEntry.type === LogType.profileEnd && typeof console.profileEnd === "function" ) { console.profileEnd( `[${name}] ${/** @type {NonNullable<LogEntry["args"]>} */ (logEntry.args)[0]}` ); } if (logEntries === undefined) { logEntries = this.logging.get(name); if (logEntries === undefined) { logEntries = []; this.logging.set(name, logEntries); } } logEntries.push(logEntry); if ( logEntry.type === LogType.profile && typeof console.profile === "function" ) { console.profile( `[${name}] ${ /** @type {NonNullable<LogEntry["args"]>} */ (logEntry.args)[0] }` ); } } }, childName => { if (typeof name === "function") { if (typeof childName === "function") { return this.getLogger(() => { if (typeof name === "function") { name = name(); if (!name) { throw new TypeError( "Compilation.getLogger(name) called with a function not returning a name" ); } } if (typeof childName === "function") { childName = childName(); if (!childName) { throw new TypeError( "Logger.getChildLogger(name) called with a function not returning a name" ); } } return `${name}/${childName}`; }); } return this.getLogger(() => { if (typeof name === "function") { name = name(); if (!name) { throw new TypeError( "Compilation.getLogger(name) called with a function not returning a name" ); } } return `${name}/${childName}`; }); } if (typeof childName === "function") { return this.getLogger(() => { if (typeof childName === "function") { childName = childName(); if (!childName) { throw new TypeError( "Logger.getChildLogger(name) called with a function not returning a name" ); } } return `${name}/${childName}`; }); } return this.getLogger(`${name}/${childName}`); } ); } /** * @param {Module} module module to be added that was created * @param {ModuleCallback} callback returns the module in the compilation, * it could be the passed one (if new), or an already existing in the compilation * @returns {void} */ addModule(module, callback) { this.addModuleQueue.add(module, callback); } /** * @param {Module} module module to be added that was created * @param {ModuleCallback} callback returns the module in the compilation, * it could be the passed one (if new), or an already existing in the compilation * @returns {void} */ _addModule(module, callback) { const identifier = module.identifier(); const alreadyAddedModule = this._modules.get(identifier); if (alreadyAddedModule) { return callback(null, alreadyAddedModule); } const currentProfile = this.profile ? this.moduleGraph.getProfile(module) : undefined; if (currentProfile !== undefined) { currentProfile.markRestoringStart(); } this._modulesCache.get(identifier, null, (err, cacheModule) => { if (err) return callback(new ModuleRestoreError(module, err)); if (currentProfile !== undefined) { currentProfile.markRestoringEnd(); currentProfile.markIntegrationStart(); } if (cacheModule) { cacheModule.updateCacheModule(module); module = cacheModule; } this._modules.set(identifier, module); this.modules.add(module); if (this._backCompat) ModuleGraph.setModuleGraphForModule(module, this.moduleGraph); if (currentProfile !== undefined) { currentProfile.markIntegrationEnd(); } callback(null, module); }); } /** * Fetches a module from a compilation by its identifier * @param {Module} module the module provided * @returns {Module} the module requested */ getModule(module) { const identifier = module.identifier(); return /** @type {Module} */ (this._modules.get(identifier)); } /** * Attempts to search for a module by its identifier * @param {string} identifier identifier (usually path) for module * @returns {Module|undefined} attempt to search for module and return it, else undefined */ findModule(identifier) { return this._modules.get(identifier); } /** * Schedules a build of the module object * @param {Module} module module to be built * @param {ModuleCallback} callback the callback * @returns {void} */ buildModule(module, callback) { this.buildQueue.add(module, callback); } /** * Builds the module object * @param {Module} module module to be built * @param {ModuleCallback} callback the callback * @returns {void} */ _buildModule(module, callback) { const currentProfile = this.profile ? this.moduleGraph.getProfile(module) : undefined; if (currentProfile !== undefined) { currentProfile.markBuildingStart(); } module.needBuild( { compilation: this, fileSystemInfo: this.fileSystemInfo, valueCacheVersions: this.valueCacheVersions }, (err, needBuild) => { if (err) return callback(err); if (!needBuild) { if (currentProfile !== undefined) { currentProfile.markBuildingEnd(); } this.hooks.stillValidModule.call(module); return callback(); } this.hooks.buildModule.call(module); this.builtModules.add(module); module.build( this.options, this, this.resolverFactory.get("normal", module.resolveOptions), /** @type {InputFileSystem} */ (this.inputFileSystem), err => { if (currentProfile !== undefined) { currentProfile.markBuildingEnd(); } if (err) { this.hooks.failedModule.call(module, err); return callback(err); } if (currentProfile !== undefined) { currentProfile.markStoringStart(); } this._modulesCache.store(module.identifier(), null, module, err => { if (currentProfile !== undefined) { currentProfile.markStoringEnd(); } if (err) { this.hooks.failedModule.call( module, /** @type {WebpackError} */ (err) ); return callback(new Module