fix types

This commit is contained in:
Alexander Akait 2025-03-11 09:15:34 +03:00 committed by GitHub
commit c282c96ca1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 547 additions and 279 deletions

View File

@ -310,7 +310,7 @@
"Wunder", "Wunder",
"snitin", "snitin",
"Nitin", "Nitin",
"Kumarr", "Kumar",
"spacek", "spacek",
"thelarkinn" "thelarkinn"
], ],

View File

@ -107,12 +107,16 @@ const { isSourceEqual } = require("./util/source");
/** @typedef {import("./Module").BuildInfo} BuildInfo */ /** @typedef {import("./Module").BuildInfo} BuildInfo */
/** @typedef {import("./Module").ValueCacheVersions} ValueCacheVersions */ /** @typedef {import("./Module").ValueCacheVersions} ValueCacheVersions */
/** @typedef {import("./NormalModule").NormalModuleCompilationHooks} NormalModuleCompilationHooks */ /** @typedef {import("./NormalModule").NormalModuleCompilationHooks} NormalModuleCompilationHooks */
/** @typedef {import("./Module").FactoryMeta} FactoryMeta */
/** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */ /** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */
/** @typedef {import("./ModuleFactory")} ModuleFactory */ /** @typedef {import("./ModuleFactory")} ModuleFactory */
/** @typedef {import("../declarations/WebpackOptions").ResolveOptions} ResolveOptions */
/** @typedef {import("./ChunkGraph").ModuleId} ModuleId */ /** @typedef {import("./ChunkGraph").ModuleId} ModuleId */
/** @typedef {import("./ModuleGraphConnection")} ModuleGraphConnection */ /** @typedef {import("./ModuleGraphConnection")} ModuleGraphConnection */
/** @typedef {import("./ModuleFactory").ModuleFactoryCreateDataContextInfo} ModuleFactoryCreateDataContextInfo */ /** @typedef {import("./ModuleFactory").ModuleFactoryCreateDataContextInfo} ModuleFactoryCreateDataContextInfo */
/** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */ /** @typedef {import("./ModuleFactory").ModuleFactoryResult} ModuleFactoryResult */
/** @typedef {import("./NormalModule").ParserOptions} ParserOptions */
/** @typedef {import("./NormalModule").GeneratorOptions} GeneratorOptions */
/** @typedef {import("./RequestShortener")} RequestShortener */ /** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {import("./RuntimeModule")} RuntimeModule */ /** @typedef {import("./RuntimeModule")} RuntimeModule */
/** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry */ /** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry */
@ -227,10 +231,17 @@ const { isSourceEqual } = require("./util/source");
* @property {LazySet<string>} buildDependencies * @property {LazySet<string>} buildDependencies
*/ */
/** @typedef {(id: string) => void} WebpackRequire */
/**
* @typedef {{ id: string | undefined, exports: any, loaded: boolean, error?: Error }} ModuleObject
*/
/**
* @typedef {{ id: string | undefined, module: ModuleObject, require: WebpackRequire }} ExecuteOptions
*/
/** /**
* @typedef {{ id: string, exports: any, loaded: boolean }} ModuleObject
*
* /**
* @typedef {object} ExecuteModuleArgument * @typedef {object} ExecuteModuleArgument
* @property {Module} module * @property {Module} module
* @property {ModuleObject=} moduleObject * @property {ModuleObject=} moduleObject
@ -364,7 +375,9 @@ const { isSourceEqual } = require("./util/source");
/** @typedef {Record<string, any> & KnownCreateStatsOptionsContext} CreateStatsOptionsContext */ /** @typedef {Record<string, any> & KnownCreateStatsOptionsContext} CreateStatsOptionsContext */
/** @typedef {{module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[]}[]} CodeGenerationJobs */ /** @typedef {{ module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[]}} CodeGenerationJob */
/** @typedef {CodeGenerationJob[]} CodeGenerationJobs */
/** @typedef {{javascript: ModuleTemplate}} ModuleTemplates */ /** @typedef {{javascript: ModuleTemplate}} ModuleTemplates */
@ -438,7 +451,17 @@ const compareErrors = concatComparators(byModule, byLocation, byMessage);
/** @type {WeakMap<Dependency, Module & { restoreFromUnsafeCache: Function } | null>} */ /** @type {WeakMap<Dependency, Module & { restoreFromUnsafeCache: Function } | null>} */
const unsafeCacheDependencies = new WeakMap(); const unsafeCacheDependencies = new WeakMap();
/** @type {WeakMap<Module & { restoreFromUnsafeCache: Function }, object>} */ /**
* @typedef {object} KnownUnsafeCacheData
* @property {FactoryMeta} [factoryMeta] factory meta
* @property {ResolveOptions} [resolveOptions] resolve options
* @property {ParserOptions} [parserOptions]
* @property {GeneratorOptions} [generatorOptions]
*/
/** @typedef {KnownUnsafeCacheData & Record<string, any>} UnsafeCacheData */
/** @type {WeakMap<Module & { restoreFromUnsafeCache: Function }, UnsafeCacheData>} */
const unsafeCacheData = new WeakMap(); const unsafeCacheData = new WeakMap();
class Compilation { class Compilation {
@ -482,12 +505,18 @@ class Compilation {
const { fn, additionalAssets, ...remainingTap } = tap; const { fn, additionalAssets, ...remainingTap } = tap;
const additionalAssetsFn = const additionalAssetsFn =
additionalAssets === true ? fn : additionalAssets; additionalAssets === true ? fn : additionalAssets;
/** @typedef {WeakSet<CompilationAssets>} ProcessedAssets */
/** @type {ProcessedAssets | undefined} */
const processedAssets = additionalAssetsFn ? new WeakSet() : undefined; const processedAssets = additionalAssetsFn ? new WeakSet() : undefined;
switch (type) { switch (type) {
case "sync": case "sync":
if (additionalAssetsFn) { if (additionalAssetsFn) {
this.hooks.processAdditionalAssets.tap(name, assets => { this.hooks.processAdditionalAssets.tap(name, assets => {
if (processedAssets.has(this.assets)) if (
/** @type {ProcessedAssets} */
(processedAssets).has(this.assets)
)
additionalAssetsFn(assets); additionalAssetsFn(assets);
}); });
} }
@ -518,7 +547,10 @@ class Compilation {
this.hooks.processAdditionalAssets.tapAsync( this.hooks.processAdditionalAssets.tapAsync(
name, name,
(assets, callback) => { (assets, callback) => {
if (processedAssets.has(this.assets)) if (
/** @type {ProcessedAssets} */
(processedAssets).has(this.assets)
)
return additionalAssetsFn(assets, callback); return additionalAssetsFn(assets, callback);
callback(); callback();
} }
@ -546,7 +578,10 @@ class Compilation {
case "promise": case "promise":
if (additionalAssetsFn) { if (additionalAssetsFn) {
this.hooks.processAdditionalAssets.tapPromise(name, assets => { this.hooks.processAdditionalAssets.tapPromise(name, assets => {
if (processedAssets.has(this.assets)) if (
/** @type {ProcessedAssets} */
(processedAssets).has(this.assets)
)
return additionalAssetsFn(assets); return additionalAssetsFn(assets);
return Promise.resolve(); return Promise.resolve();
}); });
@ -2096,7 +2131,9 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
resolveOptions: originModule ? originModule.resolveOptions : undefined, resolveOptions: originModule ? originModule.resolveOptions : undefined,
context: context:
context || context ||
(originModule ? originModule.context : this.compiler.context), (originModule
? /** @type {string} */ (originModule.context)
: /** @type {string} */ (this.compiler.context)),
dependencies dependencies
}, },
(err, result) => { (err, result) => {
@ -2271,7 +2308,8 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
); );
} else { } else {
entryData[target].push(entry); entryData[target].push(entry);
for (const key of Object.keys(options)) { for (const _key of Object.keys(options)) {
const key = /** @type {keyof EntryOptions} */ (_key);
if (options[key] === undefined) continue; if (options[key] === undefined) continue;
if (entryData.options[key] === options[key]) continue; if (entryData.options[key] === options[key]) continue;
if ( if (
@ -2282,7 +2320,9 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
continue; continue;
} }
if (entryData.options[key] === undefined) { if (entryData.options[key] === undefined) {
entryData.options[key] = options[key]; entryData.options[/** @type {TODO} */ (key)] = /** @type {TODO} */ (
options[key]
);
} else { } else {
return callback( return callback(
new WebpackError( new WebpackError(
@ -2308,7 +2348,12 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
this.hooks.failedEntry.call(entry, options, err); this.hooks.failedEntry.call(entry, options, err);
return callback(err); return callback(err);
} }
this.hooks.succeedEntry.call(entry, options, module); this.hooks.succeedEntry.call(
entry,
options,
/** @type {Module} */
(module)
);
return callback(null, module); return callback(null, module);
} }
); );
@ -3225,7 +3270,9 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
} }
this.hooks.afterProcessAssets.call(this.assets); this.hooks.afterProcessAssets.call(this.assets);
this.logger.timeEnd("process assets"); this.logger.timeEnd("process assets");
this.assets = /** @type {CompilationAssets} */ ( this.assets =
/** @type {CompilationAssets} */
(
this._backCompat this._backCompat
? soonFrozenObjectDeprecation( ? soonFrozenObjectDeprecation(
this.assets, this.assets,
@ -3766,7 +3813,8 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
module, module,
/** @type {DependencyLocation} */ /** @type {DependencyLocation} */
(loc), (loc),
request /** @type {string} */
(request)
); );
} }
return chunkGroup; return chunkGroup;
@ -3778,7 +3826,8 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
module, module,
/** @type {DependencyLocation} */ /** @type {DependencyLocation} */
(loc), (loc),
request /** @type {string} */
(request)
); );
const chunk = this.addChunk(name); const chunk = this.addChunk(name);
@ -4322,9 +4371,9 @@ This prevents using hashes of each other and should be avoided.`);
this.logger.timeEnd("hashing: sort chunks"); this.logger.timeEnd("hashing: sort chunks");
const fullHashChunks = new Set(); const fullHashChunks = new Set();
/** @type {{module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[]}[]} */ /** @type {CodeGenerationJobs} */
const codeGenerationJobs = []; const codeGenerationJobs = [];
/** @type {Map<string, Map<Module, {module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[]}>>} */ /** @type {Map<string, Map<Module, CodeGenerationJob>>} */
const codeGenerationJobsMap = new Map(); const codeGenerationJobsMap = new Map();
/** @type {WebpackError[]} */ /** @type {WebpackError[]} */
const errors = []; const errors = [];
@ -4441,7 +4490,11 @@ This prevents using hashes of each other and should be avoided.`);
moduleHashDigest, moduleHashDigest,
moduleHashDigest.slice(0, hashDigestLength) moduleHashDigest.slice(0, hashDigestLength)
); );
codeGenerationJobsMap.get(oldHash).get(module).hash = moduleHashDigest; /** @type {CodeGenerationJob} */
(
/** @type {Map<Module, CodeGenerationJob>} */
(codeGenerationJobsMap.get(oldHash)).get(module)
).hash = moduleHashDigest;
} }
const chunkHash = createHash(/** @type {Algorithm} */ (hashFunction)); const chunkHash = createHash(/** @type {Algorithm} */ (hashFunction));
chunkHash.update(chunk.hash); chunkHash.update(chunk.hash);
@ -4491,7 +4544,7 @@ This prevents using hashes of each other and should be avoided.`);
/** /**
* @private * @private
* @param {string} file file name * @param {string} file file name
* @param {AssetInfo} newInfo new asset information * @param {AssetInfo=} newInfo new asset information
* @param {AssetInfo=} oldInfo old asset information * @param {AssetInfo=} oldInfo old asset information
*/ */
_setAssetInfo(file, newInfo, oldInfo = this.assetsInfo.get(file)) { _setAssetInfo(file, newInfo, oldInfo = this.assetsInfo.get(file)) {
@ -4801,7 +4854,7 @@ This prevents using hashes of each other and should be avoided.`);
manifest, manifest,
(fileManifest, callback) => { (fileManifest, callback) => {
const ident = fileManifest.identifier; const ident = fileManifest.identifier;
const usedHash = fileManifest.hash; const usedHash = /** @type {string} */ (fileManifest.hash);
const assetCacheItem = this._assetsCache.getItemCache( const assetCacheItem = this._assetsCache.getItemCache(
ident, ident,
@ -5253,21 +5306,27 @@ This prevents using hashes of each other and should be avoided.`);
strictModuleErrorHandling, strictModuleErrorHandling,
strictModuleExceptionHandling strictModuleExceptionHandling
} = this.outputOptions; } = this.outputOptions;
/** @type {WebpackRequire} */
const __webpack_require__ = id => { const __webpack_require__ = id => {
const cached = moduleCache[id]; const cached = moduleCache[id];
if (cached !== undefined) { if (cached !== undefined) {
if (cached.error) throw cached.error; if (cached.error) throw cached.error;
return cached.exports; return cached.exports;
} }
const moduleArgument = moduleArgumentsById.get(id); const moduleArgument =
/** @type {TODO} */
(moduleArgumentsById).get(id);
return __webpack_require_module__(moduleArgument, id); return __webpack_require_module__(moduleArgument, id);
}; };
/** @type {((options: ExecuteOptions) => void)[]} */
const interceptModuleExecution = (__webpack_require__[ const interceptModuleExecution = (__webpack_require__[
RuntimeGlobals.interceptModuleExecution.replace( RuntimeGlobals.interceptModuleExecution.replace(
`${RuntimeGlobals.require}.`, `${RuntimeGlobals.require}.`,
"" ""
) )
] = []); ] = []);
/** @type {Record<string, ModuleObject>} */
const moduleCache = (__webpack_require__[ const moduleCache = (__webpack_require__[
RuntimeGlobals.moduleCache.replace( RuntimeGlobals.moduleCache.replace(
`${RuntimeGlobals.require}.`, `${RuntimeGlobals.require}.`,
@ -5283,6 +5342,7 @@ This prevents using hashes of each other and should be avoided.`);
* @returns {any} exports * @returns {any} exports
*/ */
const __webpack_require_module__ = (moduleArgument, id) => { const __webpack_require_module__ = (moduleArgument, id) => {
/** @type {ExecuteOptions} */
const execOptions = { const execOptions = {
id, id,
module: { module: {
@ -5317,9 +5377,14 @@ This prevents using hashes of each other and should be avoided.`);
if (strictModuleExceptionHandling) { if (strictModuleExceptionHandling) {
if (id) delete moduleCache[id]; if (id) delete moduleCache[id];
} else if (strictModuleErrorHandling) { } else if (strictModuleErrorHandling) {
moduleObject.error = execErr; moduleObject.error = /** @type {WebpackError} */ (
execErr
);
}
if (!(/** @type {WebpackError} */ (execErr).module)) {
/** @type {WebpackError} */
(execErr).module = module;
} }
if (!execErr.module) execErr.module = module;
throw execErr; throw execErr;
} }
}; };
@ -5334,13 +5399,16 @@ This prevents using hashes of each other and should be avoided.`);
} }
exports = __webpack_require__(module.identifier()); exports = __webpack_require__(module.identifier());
} catch (execErr) { } catch (execErr) {
const { message, stack, module } = /** @type {TODO} */ (
execErr
);
const err = new WebpackError( const err = new WebpackError(
`Execution of module code from module graph (${module.readableIdentifier( `Execution of module code from module graph (${module.readableIdentifier(
this.requestShortener this.requestShortener
)}) failed: ${execErr.message}` )}) failed: ${message}`
); );
err.stack = execErr.stack; err.stack = stack;
err.module = execErr.module; err.module = module;
return callback(err); return callback(err);
} }

View File

@ -9,13 +9,16 @@ const ContextElementDependency = require("./dependencies/ContextElementDependenc
const { join } = require("./util/fs"); const { join } = require("./util/fs");
/** @typedef {import("./Compiler")} Compiler */ /** @typedef {import("./Compiler")} Compiler */
/** @typedef {import("./ContextModule").ContextModuleOptions} ContextModuleOptions */
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */ /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
/** @typedef {Record<string, string>} NewContentCreateContextMap */
class ContextReplacementPlugin { class ContextReplacementPlugin {
/** /**
* @param {RegExp} resourceRegExp A regular expression that determines which files will be selected * @param {RegExp} resourceRegExp A regular expression that determines which files will be selected
* @param {TODO=} newContentResource A new resource to replace the match * @param {(string | ((context: TODO) => void) | RegExp | boolean)=} newContentResource A new resource to replace the match
* @param {TODO=} newContentRecursive If true, all subdirectories are searched for matches * @param {(boolean | NewContentCreateContextMap | RegExp)=} newContentRecursive If true, all subdirectories are searched for matches
* @param {RegExp=} newContentRegExp A regular expression that determines which files will be selected * @param {RegExp=} newContentRegExp A regular expression that determines which files will be selected
*/ */
constructor( constructor(
@ -26,35 +29,56 @@ class ContextReplacementPlugin {
) { ) {
this.resourceRegExp = resourceRegExp; this.resourceRegExp = resourceRegExp;
// new webpack.ContextReplacementPlugin(/selector/, (context) => { /* Logic */ });
if (typeof newContentResource === "function") { if (typeof newContentResource === "function") {
this.newContentCallback = newContentResource; this.newContentCallback = newContentResource;
} else if ( }
// new ContextReplacementPlugin(/selector/, './folder', { './request': './request' });
else if (
typeof newContentResource === "string" && typeof newContentResource === "string" &&
typeof newContentRecursive === "object" typeof newContentRecursive === "object"
) { ) {
this.newContentResource = newContentResource; this.newContentResource = newContentResource;
/**
* @param {InputFileSystem} fs input file system
* @param {(err: null | Error, newContentRecursive: NewContentCreateContextMap) => void} callback callback
*/
this.newContentCreateContextMap = (fs, callback) => { this.newContentCreateContextMap = (fs, callback) => {
callback(null, newContentRecursive); callback(
null,
/** @type {NewContentCreateContextMap} */ (newContentRecursive)
);
}; };
} else if ( }
// new ContextReplacementPlugin(/selector/, './folder', (context) => { /* Logic */ });
else if (
typeof newContentResource === "string" && typeof newContentResource === "string" &&
typeof newContentRecursive === "function" typeof newContentRecursive === "function"
) { ) {
this.newContentResource = newContentResource; this.newContentResource = newContentResource;
this.newContentCreateContextMap = newContentRecursive; this.newContentCreateContextMap = newContentRecursive;
} else { } else {
// new webpack.ContextReplacementPlugin(/selector/, false, /reg-exp/);
if (typeof newContentResource !== "string") { if (typeof newContentResource !== "string") {
newContentRegExp = newContentRecursive; newContentRegExp = /** @type {RegExp} */ (newContentRecursive);
newContentRecursive = newContentResource; newContentRecursive = /** @type {boolean} */ (newContentResource);
newContentResource = undefined; newContentResource = undefined;
} }
// new webpack.ContextReplacementPlugin(/selector/, /de|fr|hu/);
if (typeof newContentRecursive !== "boolean") { if (typeof newContentRecursive !== "boolean") {
newContentRegExp = newContentRecursive; newContentRegExp = /** @type {RegExp} */ (newContentRecursive);
newContentRecursive = undefined; newContentRecursive = undefined;
} }
this.newContentResource = newContentResource; // new webpack.ContextReplacementPlugin(/selector/, './folder', false, /selector/);
this.newContentRecursive = newContentRecursive; this.newContentResource =
this.newContentRegExp = newContentRegExp; /** @type {string | undefined} */
(newContentResource);
this.newContentRecursive =
/** @type {boolean | undefined} */
(newContentRecursive);
this.newContentRegExp =
/** @type {RegExp | undefined} */
(newContentRegExp);
} }
} }
@ -150,8 +174,12 @@ class ContextReplacementPlugin {
} }
} }
const createResolveDependenciesFromContextMap = createContextMap => { /**
const resolveDependenciesFromContextMap = (fs, options, callback) => { * @param {(fs: InputFileSystem, callback: (err: null | Error, map: NewContentCreateContextMap) => void) => void} createContextMap create context map function
* @returns {(fs: InputFileSystem, options: ContextModuleOptions, callback: (err: null | Error, dependencies?: ContextElementDependency[]) => void) => void} resolve resolve dependencies from context map function
*/
const createResolveDependenciesFromContextMap =
createContextMap => (fs, options, callback) => {
createContextMap(fs, (err, map) => { createContextMap(fs, (err, map) => {
if (err) return callback(err); if (err) return callback(err);
const dependencies = Object.keys(map).map( const dependencies = Object.keys(map).map(
@ -159,14 +187,13 @@ const createResolveDependenciesFromContextMap = createContextMap => {
new ContextElementDependency( new ContextElementDependency(
map[key] + options.resourceQuery + options.resourceFragment, map[key] + options.resourceQuery + options.resourceFragment,
key, key,
options.category, options.typePrefix,
/** @type {string} */ (options.category),
options.referencedExports options.referencedExports
) )
); );
callback(null, dependencies); callback(null, dependencies);
}); });
}; };
return resolveDependenciesFromContextMap;
};
module.exports = ContextReplacementPlugin; module.exports = ContextReplacementPlugin;

View File

@ -34,6 +34,12 @@ const RETURNS_TRUE = () => true;
const CIRCULAR = Symbol("circular target"); const CIRCULAR = Symbol("circular target");
class RestoreProvidedData { class RestoreProvidedData {
/**
* @param {TODO[]} exports exports
* @param {ExportInfo["provided"]} otherProvided other provided
* @param {ExportInfo["canMangleProvide"]} otherCanMangleProvide other can mangle provide
* @param {ExportInfo["terminalBinding"]} otherTerminalBinding other terminal binding
*/
constructor( constructor(
exports, exports,
otherProvided, otherProvided,
@ -78,7 +84,7 @@ class ExportsInfo {
constructor() { constructor() {
/** @type {Exports} */ /** @type {Exports} */
this._exports = new Map(); this._exports = new Map();
this._otherExportsInfo = new ExportInfo(null); this._otherExportsInfo = new ExportInfo(/** @type {TODO} */ (null));
this._sideEffectsOnlyInfo = new ExportInfo("*side effects only*"); this._sideEffectsOnlyInfo = new ExportInfo("*side effects only*");
this._exportsAreOrdered = false; this._exportsAreOrdered = false;
/** @type {ExportsInfo=} */ /** @type {ExportsInfo=} */
@ -809,9 +815,13 @@ class ExportsInfo {
} }
} }
/** @typedef {Map<string, RuntimeUsageStateType>} UsedInRuntime */
/** @typedef {{ module: Module, export: string[] }} TargetItemWithoutConnection */ /** @typedef {{ module: Module, export: string[] }} TargetItemWithoutConnection */
/** @typedef {{ module: Module, connection: ModuleGraphConnection, export: string[] | undefined }} TargetItem */ /** @typedef {{ module: Module, connection: ModuleGraphConnection, export: string[] | undefined }} TargetItem */
/** @typedef {Map<any, { connection: ModuleGraphConnection | null, export: string[], priority: number }>} Target */
/** @typedef {Map<any, { connection: ModuleGraphConnection, export: string[], priority: number }>} Target */
class ExportInfo { class ExportInfo {
/** /**
@ -833,7 +843,7 @@ class ExportInfo {
this._globalUsed = initFrom ? initFrom._globalUsed : undefined; this._globalUsed = initFrom ? initFrom._globalUsed : undefined;
/** /**
* @private * @private
* @type {Map<string, RuntimeUsageStateType>} * @type {UsedInRuntime | undefined}
*/ */
this._usedInRuntime = this._usedInRuntime =
initFrom && initFrom._usedInRuntime initFrom && initFrom._usedInRuntime
@ -1015,7 +1025,8 @@ class ExportInfo {
if (newValue !== UsageState.Unused && condition(UsageState.Unused)) { if (newValue !== UsageState.Unused && condition(UsageState.Unused)) {
this._usedInRuntime = new Map(); this._usedInRuntime = new Map();
forEachRuntime(runtime, runtime => forEachRuntime(runtime, runtime =>
this._usedInRuntime.set(/** @type {string} */ (runtime), newValue) /** @type {UsedInRuntime} */
(this._usedInRuntime).set(/** @type {string} */ (runtime), newValue)
); );
return true; return true;
} }
@ -1023,15 +1034,18 @@ class ExportInfo {
let changed = false; let changed = false;
forEachRuntime(runtime, _runtime => { forEachRuntime(runtime, _runtime => {
const runtime = /** @type {string} */ (_runtime); const runtime = /** @type {string} */ (_runtime);
const usedInRuntime =
/** @type {UsedInRuntime} */
(this._usedInRuntime);
let oldValue = let oldValue =
/** @type {UsageStateType} */ /** @type {UsageStateType} */
(this._usedInRuntime.get(runtime)); (usedInRuntime.get(runtime));
if (oldValue === undefined) oldValue = UsageState.Unused; if (oldValue === undefined) oldValue = UsageState.Unused;
if (newValue !== oldValue && condition(oldValue)) { if (newValue !== oldValue && condition(oldValue)) {
if (newValue === UsageState.Unused) { if (newValue === UsageState.Unused) {
this._usedInRuntime.delete(runtime); usedInRuntime.delete(runtime);
} else { } else {
this._usedInRuntime.set(runtime, newValue); usedInRuntime.set(runtime, newValue);
} }
changed = true; changed = true;
} }
@ -1059,7 +1073,8 @@ class ExportInfo {
if (newValue !== UsageState.Unused) { if (newValue !== UsageState.Unused) {
this._usedInRuntime = new Map(); this._usedInRuntime = new Map();
forEachRuntime(runtime, runtime => forEachRuntime(runtime, runtime =>
this._usedInRuntime.set(/** @type {string} */ (runtime), newValue) /** @type {UsedInRuntime} */
(this._usedInRuntime).set(/** @type {string} */ (runtime), newValue)
); );
return true; return true;
} }
@ -1067,15 +1082,18 @@ class ExportInfo {
let changed = false; let changed = false;
forEachRuntime(runtime, _runtime => { forEachRuntime(runtime, _runtime => {
const runtime = /** @type {string} */ (_runtime); const runtime = /** @type {string} */ (_runtime);
const usedInRuntime =
/** @type {UsedInRuntime} */
(this._usedInRuntime);
let oldValue = let oldValue =
/** @type {UsageStateType} */ /** @type {UsageStateType} */
(this._usedInRuntime.get(runtime)); (usedInRuntime.get(runtime));
if (oldValue === undefined) oldValue = UsageState.Unused; if (oldValue === undefined) oldValue = UsageState.Unused;
if (newValue !== oldValue) { if (newValue !== oldValue) {
if (newValue === UsageState.Unused) { if (newValue === UsageState.Unused) {
this._usedInRuntime.delete(runtime); usedInRuntime.delete(runtime);
} else { } else {
this._usedInRuntime.set(runtime, newValue); usedInRuntime.set(runtime, newValue);
} }
changed = true; changed = true;
} }
@ -1203,7 +1221,8 @@ class ExportInfo {
} else if ( } else if (
runtime !== undefined && runtime !== undefined &&
Array.from(runtime).every( Array.from(runtime).every(
runtime => !this._usedInRuntime.has(runtime) runtime =>
!(/** @type {UsedInRuntime} */ (this._usedInRuntime).has(runtime))
) )
) { ) {
return false; return false;
@ -1262,6 +1281,7 @@ class ExportInfo {
if (maxPriority === minPriority) return (this._maxTarget = this._target); if (maxPriority === minPriority) return (this._maxTarget = this._target);
// This is an edge case // This is an edge case
/** @type {Target} */
const map = new Map(); const map = new Map();
for (const [key, value] of /** @type {Target} */ (this._target)) { for (const [key, value] of /** @type {Target} */ (this._target)) {
if (maxPriority === value.priority) { if (maxPriority === value.priority) {
@ -1441,9 +1461,10 @@ class ExportInfo {
const target = this._getTarget(moduleGraph, resolveTargetFilter, undefined); const target = this._getTarget(moduleGraph, resolveTargetFilter, undefined);
if (target === CIRCULAR) return; if (target === CIRCULAR) return;
if (!target) return; if (!target) return;
const originalTarget = const originalTarget = /** @type {TargetItem} */ (
/** @type {Target} */ /** @type {Target} */
(this._getMaxTarget()).values().next().value; (this._getMaxTarget()).values().next().value
);
if ( if (
originalTarget.connection === target.connection && originalTarget.connection === target.connection &&
originalTarget.export === target.export originalTarget.export === target.export

View File

@ -31,6 +31,7 @@ const { register } = require("./util/serialization");
/** @typedef {import("./Chunk")} Chunk */ /** @typedef {import("./Chunk")} Chunk */
/** @typedef {import("./ChunkGraph")} ChunkGraph */ /** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./Compilation")} Compilation */ /** @typedef {import("./Compilation")} Compilation */
/** @typedef {import("./Compilation").UnsafeCacheData} UnsafeCacheData */
/** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */ /** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */ /** @typedef {import("./DependencyTemplates")} DependencyTemplates */
/** @typedef {import("./ExportsInfo")} ExportsInfo */ /** @typedef {import("./ExportsInfo")} ExportsInfo */
@ -647,7 +648,7 @@ class ExternalModule extends Module {
/** /**
* restore unsafe cache data * restore unsafe cache data
* @param {object} unsafeCacheData data from getUnsafeCacheData * @param {UnsafeCacheData} unsafeCacheData data from getUnsafeCacheData
* @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching * @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching
*/ */
restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) { restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) {

View File

@ -24,6 +24,7 @@ const makeSerializable = require("./util/makeSerializable");
/** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */ /** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */
/** @typedef {import("./Compilation")} Compilation */ /** @typedef {import("./Compilation")} Compilation */
/** @typedef {import("./Compilation").AssetInfo} AssetInfo */ /** @typedef {import("./Compilation").AssetInfo} AssetInfo */
/** @typedef {import("./Compilation").UnsafeCacheData} UnsafeCacheData */
/** @typedef {import("./ConcatenationScope")} ConcatenationScope */ /** @typedef {import("./ConcatenationScope")} ConcatenationScope */
/** @typedef {import("./Dependency")} Dependency */ /** @typedef {import("./Dependency")} Dependency */
/** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */ /** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */
@ -141,8 +142,6 @@ const makeSerializable = require("./util/makeSerializable");
* @property {boolean=} sideEffectFree * @property {boolean=} sideEffectFree
*/ */
/** @typedef {{ factoryMeta: FactoryMeta | undefined, resolveOptions: ResolveOptions | undefined }} UnsafeCacheData */
const EMPTY_RESOLVE_OPTIONS = {}; const EMPTY_RESOLVE_OPTIONS = {};
let debugId = 1000; let debugId = 1000;
@ -1030,7 +1029,7 @@ class Module extends DependenciesBlock {
/** /**
* restore unsafe cache data * restore unsafe cache data
* @param {object} unsafeCacheData data from getUnsafeCacheData * @param {UnsafeCacheData} unsafeCacheData data from getUnsafeCacheData
* @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching * @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching
*/ */
_restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) { _restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) {

View File

@ -97,8 +97,6 @@ const memoize = require("./util/memoize");
/** @typedef {{[k: string]: any}} ParserOptions */ /** @typedef {{[k: string]: any}} ParserOptions */
/** @typedef {{[k: string]: any}} GeneratorOptions */ /** @typedef {{[k: string]: any}} GeneratorOptions */
/** @typedef {UnsafeCacheData & { parser: undefined | Parser, parserOptions: undefined | ParserOptions, generator: undefined | Generator, generatorOptions: undefined | GeneratorOptions }} NormalModuleUnsafeCacheData */
/** /**
* @template T * @template T
* @typedef {import("../declarations/LoaderContext").LoaderContext<T>} LoaderContext * @typedef {import("../declarations/LoaderContext").LoaderContext<T>} LoaderContext
@ -499,9 +497,7 @@ class NormalModule extends Module {
* @returns {UnsafeCacheData} cached data * @returns {UnsafeCacheData} cached data
*/ */
getUnsafeCacheData() { getUnsafeCacheData() {
const data = const data = super.getUnsafeCacheData();
/** @type {NormalModuleUnsafeCacheData} */
(super.getUnsafeCacheData());
data.parserOptions = this.parserOptions; data.parserOptions = this.parserOptions;
data.generatorOptions = this.generatorOptions; data.generatorOptions = this.generatorOptions;
return data; return data;
@ -509,7 +505,7 @@ class NormalModule extends Module {
/** /**
* restore unsafe cache data * restore unsafe cache data
* @param {NormalModuleUnsafeCacheData} unsafeCacheData data from getUnsafeCacheData * @param {UnsafeCacheData} unsafeCacheData data from getUnsafeCacheData
* @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching * @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching
*/ */
restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) { restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) {
@ -518,7 +514,7 @@ class NormalModule extends Module {
/** /**
* restore unsafe cache data * restore unsafe cache data
* @param {object} unsafeCacheData data from getUnsafeCacheData * @param {UnsafeCacheData} unsafeCacheData data from getUnsafeCacheData
* @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching * @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching
*/ */
_restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) { _restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) {

View File

@ -186,20 +186,13 @@ const mergeGlobalOptions = (globalOptions, type, localOptions) => {
// TODO webpack 6 remove // TODO webpack 6 remove
/** /**
* @template {import("tapable").Hook<EXPECTED_ANY, EXPECTED_ANY>} T
* @param {string} name name * @param {string} name name
* @param {TODO} hook hook * @param {T} hook hook
* @returns {string} result * @returns {string} result
*/ */
const deprecationChangedHookMessage = (name, hook) => { const deprecationChangedHookMessage = (name, hook) => {
const names = hook.taps const names = hook.taps.map(tapped => tapped.name).join(", ");
.map(
/**
* @param {TODO} tapped tapped
* @returns {string} name
*/
tapped => tapped.name
)
.join(", ");
return ( return (
`NormalModuleFactory.${name} (${names}) is no longer a waterfall hook, but a bailing hook instead. ` + `NormalModuleFactory.${name} (${names}) is no longer a waterfall hook, but a bailing hook instead. ` +
@ -281,9 +274,9 @@ class NormalModuleFactory extends ModuleFactory {
beforeResolve: new AsyncSeriesBailHook(["resolveData"]), beforeResolve: new AsyncSeriesBailHook(["resolveData"]),
/** @type {AsyncSeriesBailHook<[ResolveData], false | void>} */ /** @type {AsyncSeriesBailHook<[ResolveData], false | void>} */
afterResolve: new AsyncSeriesBailHook(["resolveData"]), afterResolve: new AsyncSeriesBailHook(["resolveData"]),
/** @type {AsyncSeriesBailHook<[ResolveData["createData"], ResolveData], Module | void>} */ /** @type {AsyncSeriesBailHook<[CreateData, ResolveData], Module | void>} */
createModule: new AsyncSeriesBailHook(["createData", "resolveData"]), createModule: new AsyncSeriesBailHook(["createData", "resolveData"]),
/** @type {SyncWaterfallHook<[Module, ResolveData["createData"], ResolveData]>} */ /** @type {SyncWaterfallHook<[Module, CreateData, ResolveData]>} */
module: new SyncWaterfallHook(["module", "createData", "resolveData"]), module: new SyncWaterfallHook(["module", "createData", "resolveData"]),
/** @type {HookMap<SyncBailHook<[ParserOptions], Parser | void>>} */ /** @type {HookMap<SyncBailHook<[ParserOptions], Parser | void>>} */
createParser: new HookMap(() => new SyncBailHook(["parserOptions"])), createParser: new HookMap(() => new SyncBailHook(["parserOptions"])),
@ -459,6 +452,7 @@ class NormalModuleFactory extends ModuleFactory {
matchResource = join(this.fs, context, matchResource); matchResource = join(this.fs, context, matchResource);
} }
} }
matchResourceData = { matchResourceData = {
resource: matchResource, resource: matchResource,
...cacheParseResource(matchResource) ...cacheParseResource(matchResource)
@ -546,7 +540,11 @@ class NormalModuleFactory extends ModuleFactory {
if (!resourceData) { if (!resourceData) {
// ignored // ignored
return callback(null, dependencies[0].createIgnoredModule(context)); return callback(
null,
/** @type {TODO} */
(dependencies[0].createIgnoredModule(context))
);
} }
const userRequest = const userRequest =
@ -624,12 +622,11 @@ class NormalModuleFactory extends ModuleFactory {
] === "object" && ] === "object" &&
settings[/** @type {keyof ModuleSettings} */ (r.type)] !== null settings[/** @type {keyof ModuleSettings} */ (r.type)] !== null
) { ) {
settings[r.type] = cachedCleverMerge( const type = /** @type {TODO} */ (r.type);
settings[/** @type {keyof ModuleSettings} */ (r.type)], settings[type] = cachedCleverMerge(settings[type], r.value);
r.value
);
} else { } else {
settings[r.type] = r.value; const type = /** @type {TODO} */ (r.type);
settings[type] = r.value;
} }
} }
} }

View File

@ -598,7 +598,10 @@ class Pack {
const content = this.content[i]; const content = this.content[i];
if (content !== undefined) { if (content !== undefined) {
write(content.items); write(content.items);
content.writeLazy(lazy => writeSeparate(lazy, { name: `${i}` })); content.writeLazy(lazy =>
/** @type {NonNullable<ObjectSerializerContext["writeSeparate"]>} */
(writeSeparate)(lazy, { name: `${i}` })
);
} else { } else {
write(undefined); // undefined marks an empty content slot write(undefined); // undefined marks an empty content slot
} }
@ -671,7 +674,7 @@ class PackContentItems {
} }
/** /**
* @param {ObjectSerializerContext & { snapshot: TODO, rollback: TODO, logger: Logger, profile: boolean | undefined }} context context * @param {ObjectSerializerContext & { logger: Logger, profile: boolean | undefined }} context context
*/ */
serialize({ write, snapshot, rollback, logger, profile }) { serialize({ write, snapshot, rollback, logger, profile }) {
if (profile) { if (profile) {
@ -792,7 +795,7 @@ makeSerializable(
"PackContentItems" "PackContentItems"
); );
/** @typedef {(function(): Promise<PackContentItems> | PackContentItems)} LazyFn */ /** @typedef {(function(): Promise<PackContentItems> | PackContentItems)} LazyFunction */
class PackContent { class PackContent {
/* /*
@ -823,7 +826,7 @@ class PackContent {
*/ */
constructor(items, usedItems, dataOrFn, logger, lazyName) { constructor(items, usedItems, dataOrFn, logger, lazyName) {
this.items = items; this.items = items;
/** @type {LazyFn | undefined} */ /** @type {TODO | undefined} */
this.lazy = typeof dataOrFn === "function" ? dataOrFn : undefined; this.lazy = typeof dataOrFn === "function" ? dataOrFn : undefined;
/** @type {Content | undefined} */ /** @type {Content | undefined} */
this.content = typeof dataOrFn === "function" ? undefined : dataOrFn.map; this.content = typeof dataOrFn === "function" ? undefined : dataOrFn.map;
@ -861,7 +864,7 @@ class PackContent {
); );
logger.time(timeMessage); logger.time(timeMessage);
} }
const value = /** @type {LazyFn} */ (this.lazy)(); const value = /** @type {LazyFunction} */ (this.lazy)();
if ("then" in value) { if ("then" in value) {
return value.then(data => { return value.then(data => {
const map = data.map; const map = data.map;
@ -871,7 +874,7 @@ class PackContent {
// Move to state C // Move to state C
this.content = map; this.content = map;
this.lazy = SerializerMiddleware.unMemoizeLazy( this.lazy = SerializerMiddleware.unMemoizeLazy(
/** @type {LazyFn} */ /** @type {LazyFunction} */
(this.lazy) (this.lazy)
); );
return map.get(identifier); return map.get(identifier);
@ -885,7 +888,7 @@ class PackContent {
// Move to state C // Move to state C
this.content = map; this.content = map;
this.lazy = SerializerMiddleware.unMemoizeLazy( this.lazy = SerializerMiddleware.unMemoizeLazy(
/** @type {LazyFn} */ /** @type {LazyFunction} */
(this.lazy) (this.lazy)
); );
return map.get(identifier); return map.get(identifier);
@ -917,7 +920,9 @@ class PackContent {
); );
logger.time(timeMessage); logger.time(timeMessage);
} }
const value = this.lazy(); const value =
/** @type {PackContentItems | Promise<PackContentItems>} */
(this.lazy());
if ("then" in value) { if ("then" in value) {
return value.then(data => { return value.then(data => {
if (timeMessage) { if (timeMessage) {
@ -1008,7 +1013,7 @@ class PackContent {
); );
logger.time(timeMessage); logger.time(timeMessage);
} }
const value = /** @type {LazyFn} */ (this.lazy)(); const value = /** @type {LazyFunction} */ (this.lazy)();
this.outdated = false; this.outdated = false;
if ("then" in value) { if ("then" in value) {
// Move to state B1 // Move to state B1
@ -1026,7 +1031,7 @@ class PackContent {
// Move to state C1 (or maybe C2) // Move to state C1 (or maybe C2)
this.content = map; this.content = map;
this.lazy = SerializerMiddleware.unMemoizeLazy( this.lazy = SerializerMiddleware.unMemoizeLazy(
/** @type {LazyFn} */ /** @type {LazyFunction} */
(this.lazy) (this.lazy)
); );

View File

@ -26,6 +26,11 @@ const makeSerializable = require("../util/makeSerializable");
* @typedef {import("tapable").SyncHook<T>} SyncHook * @typedef {import("tapable").SyncHook<T>} SyncHook
*/ */
/**
* @template H
* @typedef {import("tapable").HookMapInterceptor<H>} HookMapInterceptor
*/
class CacheEntry { class CacheEntry {
/** /**
* @param {ResolveRequest} result result * @param {ResolveRequest} result result
@ -125,7 +130,7 @@ class ResolverCachePlugin {
}); });
}); });
/** @typedef {function((Error | null)=, ResolveRequest=): void} Callback */ /** @typedef {function((Error | null)=, (ResolveRequest | null)=): void} Callback */
/** @typedef {ResolveRequest & { _ResolverCachePluginCacheMiss: true }} ResolveRequestWithCacheMiss */ /** @typedef {ResolveRequest & { _ResolverCachePluginCacheMiss: true }} ResolveRequestWithCacheMiss */
/** /**
@ -244,13 +249,15 @@ class ResolverCachePlugin {
); );
}; };
compiler.resolverFactory.hooks.resolver.intercept({ compiler.resolverFactory.hooks.resolver.intercept({
factory(type, hook) { factory(type, _hook) {
/** @type {Map<string, (function(Error=, ResolveRequest=): void)[]>} */ /** @type {Map<string, (function(Error=, ResolveRequest=): void)[]>} */
const activeRequests = new Map(); const activeRequests = new Map();
/** @type {Map<string, [function(Error=, ResolveRequest=): void, NonNullable<ResolveContext["yield"]>][]>} */ /** @type {Map<string, [function(Error=, ResolveRequest=): void, NonNullable<ResolveContext["yield"]>][]>} */
const activeRequestsWithYield = new Map(); const activeRequestsWithYield = new Map();
const hook =
/** @type {SyncHook<[Resolver, ResolveOptions, ResolveOptionsWithDependencyType]>} */ /** @type {SyncHook<[Resolver, ResolveOptions, ResolveOptionsWithDependencyType]>} */
(hook).tap("ResolverCachePlugin", (resolver, options, userOptions) => { (_hook);
hook.tap("ResolverCachePlugin", (resolver, options, userOptions) => {
if (/** @type {TODO} */ (options).cache !== true) return; if (/** @type {TODO} */ (options).cache !== true) return;
const optionsIdent = objectToString(userOptions, false); const optionsIdent = objectToString(userOptions, false);
const cacheWithContext = const cacheWithContext =
@ -299,7 +306,7 @@ class ResolverCachePlugin {
let yields; let yields;
/** /**
* @type {function((Error | null)=, ResolveRequest | ResolveRequest[]=): void} * @type {function((Error | null)=, (ResolveRequest | ResolveRequest[] | null)=): void}
*/ */
const done = withYield const done = withYield
? (err, result) => { ? (err, result) => {

View File

@ -1656,7 +1656,8 @@ const getResolveDefaults = ({
styleConditions.push(mode === "development" ? "development" : "production"); styleConditions.push(mode === "development" ? "development" : "production");
styleConditions.push("style"); styleConditions.push("style");
resolveOptions.byDependency["css-import"] = { /** @type {NonNullable<ResolveOptions["byDependency"]>} */
(resolveOptions.byDependency)["css-import"] = {
// We avoid using any main files because we have to be consistent with CSS `@import` // We avoid using any main files because we have to be consistent with CSS `@import`
// and CSS `@import` does not handle `main` files in directories, // and CSS `@import` does not handle `main` files in directories,
// you should always specify the full URL for styles // you should always specify the full URL for styles

View File

@ -22,12 +22,12 @@ const getDefaultTarget = context => {
/** /**
* @typedef {object} PlatformTargetProperties * @typedef {object} PlatformTargetProperties
* @property {boolean | null} web web platform, importing of http(s) and std: is available * @property {boolean | null} [web] web platform, importing of http(s) and std: is available
* @property {boolean | null} browser browser platform, running in a normal web browser * @property {boolean | null} [browser] browser platform, running in a normal web browser
* @property {boolean | null} webworker (Web)Worker platform, running in a web/shared/service worker * @property {boolean | null} [webworker] (Web)Worker platform, running in a web/shared/service worker
* @property {boolean | null} node node platform, require of node built-in modules is available * @property {boolean | null} [node] node platform, require of node built-in modules is available
* @property {boolean | null} nwjs nwjs platform, require of legacy nw.gui is available * @property {boolean | null} [nwjs] nwjs platform, require of legacy nw.gui is available
* @property {boolean | null} electron electron platform, require of some electron built-in modules is available * @property {boolean | null} [electron] electron platform, require of some electron built-in modules is available
*/ */
/** /**

View File

@ -16,6 +16,7 @@ const {
const createSchemaValidation = require("../util/create-schema-validation"); const createSchemaValidation = require("../util/create-schema-validation");
const { dirname, mkdirpSync } = require("../util/fs"); const { dirname, mkdirpSync } = require("../util/fs");
/** @typedef {import("tapable").FullTap} FullTap */
/** @typedef {import("../../declarations/plugins/debug/ProfilingPlugin").ProfilingPluginOptions} ProfilingPluginOptions */ /** @typedef {import("../../declarations/plugins/debug/ProfilingPlugin").ProfilingPluginOptions} ProfilingPluginOptions */
/** @typedef {import("../Compilation")} Compilation */ /** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Compiler")} Compiler */ /** @typedef {import("../Compiler")} Compiler */
@ -89,7 +90,7 @@ class Profiler {
/** /**
* @param {string} method method name * @param {string} method method name
* @param {object} [params] params * @param {Record<string, EXPECTED_ANY>} [params] params
* @returns {Promise<TODO>} Promise for the result * @returns {Promise<TODO>} Promise for the result
*/ */
sendCommand(method, params) { sendCommand(method, params) {
@ -408,29 +409,33 @@ const interceptAllJavascriptModulesPluginHooks = (compilation, tracer) => {
); );
}; };
/** @typedef {(...args: EXPECTED_ANY[]) => EXPECTED_ANY | Promise<(...args: EXPECTED_ANY[]) => EXPECTED_ANY>} PluginFunction */
/** /**
* @param {string} instance instance * @param {string} instance instance
* @param {Trace} tracer tracer * @param {Trace} tracer tracer
* @returns {TODO} interceptor * @returns {(hookName: string) => TODO} interceptor
*/ */
const makeInterceptorFor = (instance, tracer) => hookName => ({ const makeInterceptorFor = (instance, tracer) => hookName => ({
/**
* @param {FullTap} tapInfo tap info
* @returns {FullTap} modified full tap
*/
register: tapInfo => { register: tapInfo => {
const { name, type, fn } = tapInfo; const { name, type, fn: internalFn } = tapInfo;
const newFn = const newFn =
// Don't tap our own hooks to ensure stream can close cleanly // Don't tap our own hooks to ensure stream can close cleanly
name === PLUGIN_NAME name === PLUGIN_NAME
? fn ? internalFn
: makeNewProfiledTapFn(hookName, tracer, { : makeNewProfiledTapFn(hookName, tracer, {
name, name,
type, type,
fn fn: /** @type {PluginFunction} */ (internalFn)
}); });
return { ...tapInfo, fn: newFn }; return { ...tapInfo, fn: newFn };
} }
}); });
/** @typedef {(...args: TODO[]) => void | Promise<TODO>} PluginFunction */
/** /**
* @param {string} hookName Name of the hook to profile. * @param {string} hookName Name of the hook to profile.
* @param {Trace} tracer The trace object. * @param {Trace} tracer The trace object.
@ -452,7 +457,9 @@ const makeNewProfiledTapFn = (hookName, tracer, { name, type, fn }) => {
id, id,
cat: defaultCategory cat: defaultCategory
}); });
const promise = /** @type {Promise<*>} */ (fn(...args)); const promise =
/** @type {Promise<(...args: EXPECTED_ANY[]) => EXPECTED_ANY>} */
(fn(...args));
return promise.then(r => { return promise.then(r => {
tracer.trace.end({ tracer.trace.end({
name, name,
@ -471,14 +478,20 @@ const makeNewProfiledTapFn = (hookName, tracer, { name, type, fn }) => {
cat: defaultCategory cat: defaultCategory
}); });
const callback = args.pop(); const callback = args.pop();
fn(...args, (...r) => { fn(
...args,
/**
* @param {...EXPECTED_ANY[]} r result
*/
(...r) => {
tracer.trace.end({ tracer.trace.end({
name, name,
id, id,
cat: defaultCategory cat: defaultCategory
}); });
callback(...r); callback(...r);
}); }
);
}; };
case "sync": case "sync":
return (...args) => { return (...args) => {
@ -513,7 +526,7 @@ const makeNewProfiledTapFn = (hookName, tracer, { name, type, fn }) => {
return r; return r;
}; };
default: default:
break; return fn;
} }
}; };

View File

@ -385,7 +385,7 @@ class AMDDefineDependencyParserPlugin {
let inTry; let inTry;
if (fn && isUnboundFunctionExpression(fn)) { if (fn && isUnboundFunctionExpression(fn)) {
inTry = parser.scope.inTry; inTry = parser.scope.inTry;
parser.inScope(fnParams, () => { parser.inScope(/** @type {Identifier[]} */ (fnParams), () => {
for (const [name, varInfo] of fnRenames) { for (const [name, varInfo] of fnRenames) {
parser.setVariable(name, varInfo); parser.setVariable(name, varInfo);
} }

View File

@ -122,6 +122,7 @@ class ModernModuleLibraryPlugin extends AbstractLibraryPlugin {
chunk.runtime chunk.runtime
); );
const finalName = const finalName =
definitions &&
definitions[ definitions[
/** @type {string} */ /** @type {string} */
(webpackExportsProperty) (webpackExportsProperty)

View File

@ -8,10 +8,14 @@ const memoize = require("../util/memoize");
const SerializerMiddleware = require("./SerializerMiddleware"); const SerializerMiddleware = require("./SerializerMiddleware");
/** @typedef {import("./SerializerMiddleware").Context} Context */ /** @typedef {import("./SerializerMiddleware").Context} Context */
/** @typedef {import("./SerializerMiddleware").LazyFn} LazyFn */
/** @typedef {import("./types").BufferSerializableType} BufferSerializableType */ /** @typedef {import("./types").BufferSerializableType} BufferSerializableType */
/** @typedef {import("./types").PrimitiveSerializableType} PrimitiveSerializableType */ /** @typedef {import("./types").PrimitiveSerializableType} PrimitiveSerializableType */
/**
* @template LAZY_RESULT
* @typedef {import("./SerializerMiddleware").LazyFunction<LAZY_RESULT>} LazyFunction
*/
/* /*
Format: Format:
@ -146,16 +150,16 @@ class BinaryMiddleware extends SerializerMiddleware {
/** /**
* @param {DeserializedType} data data * @param {DeserializedType} data data
* @param {Context} context context object * @param {Context} context context object
* @returns {SerializedType | Promise<SerializedType>} serialized data * @returns {SerializedType | Promise<SerializedType> | null} serialized data
*/ */
serialize(data, context) { serialize(data, context) {
return this._serialize(data, context); return this._serialize(data, context);
} }
/** /**
* @param {function(): Promise<any> | any} fn lazy function * @param {LazyFunction<DeserializedType>} fn lazy function
* @param {Context} context serialize function * @param {Context} context serialize function
* @returns {function(): Promise<any> | any} new lazy * @returns {LazyFunction<SerializedType>} new lazy
*/ */
_serializeLazy(fn, context) { _serializeLazy(fn, context) {
return SerializerMiddleware.serializeLazy(fn, data => return SerializerMiddleware.serializeLazy(fn, data =>
@ -277,7 +281,7 @@ class BinaryMiddleware extends SerializerMiddleware {
case "function": { case "function": {
if (!SerializerMiddleware.isLazy(thing)) if (!SerializerMiddleware.isLazy(thing))
throw new Error(`Unexpected function ${thing}`); throw new Error(`Unexpected function ${thing}`);
/** @type {SerializedType | (() => SerializedType)} */ /** @type {SerializedType | LazyFunction<SerializedType>} */
let serializedData = let serializedData =
SerializerMiddleware.getLazySerializedValue(thing); SerializerMiddleware.getLazySerializedValue(thing);
if (serializedData === undefined) { if (serializedData === undefined) {
@ -285,16 +289,23 @@ class BinaryMiddleware extends SerializerMiddleware {
flush(); flush();
allocationScope.leftOverBuffer = leftOverBuffer; allocationScope.leftOverBuffer = leftOverBuffer;
const result = const result =
/** @type {(Exclude<PrimitiveSerializableType, Promise<PrimitiveSerializableType>>)[]} */ ( /** @type {PrimitiveSerializableType[]} */
thing() (thing());
);
const data = this._serialize(result, context, allocationScope); const data = this._serialize(result, context, allocationScope);
leftOverBuffer = allocationScope.leftOverBuffer; leftOverBuffer = allocationScope.leftOverBuffer;
allocationScope.leftOverBuffer = null; allocationScope.leftOverBuffer = null;
SerializerMiddleware.setLazySerializedValue(thing, data); SerializerMiddleware.setLazySerializedValue(
/** @type {LazyFunction<DeserializedType>} */
(thing),
data
);
serializedData = data; serializedData = data;
} else { } else {
serializedData = this._serializeLazy(thing, context); serializedData = this._serializeLazy(
/** @type {LazyFunction<DeserializedType>} */
(thing),
context
);
flush(); flush();
buffers.push(serializedData); buffers.push(serializedData);
break; break;
@ -655,7 +666,7 @@ class BinaryMiddleware extends SerializerMiddleware {
* @private * @private
* @param {SerializedType} content content * @param {SerializedType} content content
* @param {Context} context context object * @param {Context} context context object
* @returns {LazyFn} lazy function * @returns {LazyFunction<DeserializedType>} lazy function
*/ */
_createLazyDeserialized(content, context) { _createLazyDeserialized(content, context) {
return SerializerMiddleware.createLazy( return SerializerMiddleware.createLazy(
@ -668,9 +679,9 @@ class BinaryMiddleware extends SerializerMiddleware {
/** /**
* @private * @private
* @param {LazyFn} fn lazy function * @param {LazyFunction<SerializedType>} fn lazy function
* @param {Context} context context object * @param {Context} context context object
* @returns {TODO} new lazy * @returns {LazyFunction<DeserializedType>} new lazy
*/ */
_deserializeLazy(fn, context) { _deserializeLazy(fn, context) {
return SerializerMiddleware.deserializeLazy(fn, data => return SerializerMiddleware.deserializeLazy(fn, data =>
@ -807,13 +818,17 @@ class BinaryMiddleware extends SerializerMiddleware {
return () => { return () => {
const count = readU32(); const count = readU32();
const lengths = Array.from({ length: count }).map(() => readU32()); const lengths = Array.from({ length: count }).map(() => readU32());
/** @type {(Buffer | LazyFunction<BufferSerializableType[]>)[]} */
const content = []; const content = [];
for (let l of lengths) { for (let l of lengths) {
if (l === 0) { if (l === 0) {
if (typeof currentBuffer !== "function") { if (typeof currentBuffer !== "function") {
throw new Error("Unexpected non-lazy element in stream"); throw new Error("Unexpected non-lazy element in stream");
} }
content.push(currentBuffer); content.push(
/** @type {LazyFunction<BufferSerializableType[]>} */
(currentBuffer)
);
currentDataItem++; currentDataItem++;
currentBuffer = currentBuffer =
currentDataItem < data.length ? data[currentDataItem] : null; currentDataItem < data.length ? data[currentDataItem] : null;
@ -1129,7 +1144,13 @@ class BinaryMiddleware extends SerializerMiddleware {
let result = []; let result = [];
while (currentBuffer !== null) { while (currentBuffer !== null) {
if (typeof currentBuffer === "function") { if (typeof currentBuffer === "function") {
result.push(this._deserializeLazy(currentBuffer, context)); result.push(
this._deserializeLazy(
/** @type {LazyFunction<SerializedType>} */
(currentBuffer),
context
)
);
currentDataItem++; currentDataItem++;
currentBuffer = currentBuffer =
currentDataItem < data.length ? data[currentDataItem] : null; currentDataItem < data.length ? data[currentDataItem] : null;

View File

@ -22,9 +22,13 @@ const SerializerMiddleware = require("./SerializerMiddleware");
/** @typedef {import("../util/fs").IStats} IStats */ /** @typedef {import("../util/fs").IStats} IStats */
/** @typedef {import("../util/fs").IntermediateFileSystem} IntermediateFileSystem */ /** @typedef {import("../util/fs").IntermediateFileSystem} IntermediateFileSystem */
/** @typedef {import("./SerializerMiddleware").Context} Context */ /** @typedef {import("./SerializerMiddleware").Context} Context */
/** @typedef {import("./SerializerMiddleware").LazyFn} LazyFn */
/** @typedef {import("./types").BufferSerializableType} BufferSerializableType */ /** @typedef {import("./types").BufferSerializableType} BufferSerializableType */
/**
* @template LAZY_RESULT
* @typedef {import("./SerializerMiddleware").LazyFunction<LAZY_RESULT>} LazyFunction
*/
/* /*
Format: Format:
@ -81,11 +85,13 @@ const readUInt64LE = Buffer.prototype.readBigUInt64LE
return high * 0x100000000 + low; return high * 0x100000000 + low;
}; };
/** @typedef {Promise<void | void[]>} BackgroundJob */
/** /**
* @typedef {object} SerializeResult * @typedef {object} SerializeResult
* @property {string | false} name * @property {string | false} name
* @property {number} size * @property {number} size
* @property {Promise<any>=} backgroundJob * @property {BackgroundJob=} backgroundJob
*/ */
/** /**
@ -103,9 +109,9 @@ const serialize = async (
writeFile, writeFile,
hashFunction = "md4" hashFunction = "md4"
) => { ) => {
/** @type {(Buffer[] | Buffer | SerializeResult | Promise<SerializeResult>)[]} */ /** @type {(Buffer[] | Buffer | Promise<SerializeResult>)[]} */
const processedData = []; const processedData = [];
/** @type {WeakMap<SerializeResult, LazyFn>} */ /** @type {WeakMap<SerializeResult, LazyFunction<BufferSerializableType[]>>} */
const resultToLazy = new WeakMap(); const resultToLazy = new WeakMap();
/** @type {Buffer[] | undefined} */ /** @type {Buffer[] | undefined} */
let lastBuffers; let lastBuffers;
@ -131,7 +137,10 @@ const serialize = async (
} else { } else {
const content = item(); const content = item();
if (content) { if (content) {
const options = SerializerMiddleware.getLazyOptions(item); const options = SerializerMiddleware.getLazyOptions(
/** @type {LazyFunction<Buffer[]>} */
(item)
);
processedData.push( processedData.push(
serialize( serialize(
middleware, middleware,
@ -140,8 +149,13 @@ const serialize = async (
writeFile, writeFile,
hashFunction hashFunction
).then(result => { ).then(result => {
/** @type {any} */ (item).options.size = result.size; /** @type {LazyFunction<Buffer[]>} */
resultToLazy.set(result, item); (item).options.size = result.size;
resultToLazy.set(
result,
/** @type {LazyFunction<Buffer[]>} */
(item)
);
return result; return result;
}) })
); );
@ -162,24 +176,24 @@ const serialize = async (
throw new Error("Unexpected falsy value in items array"); throw new Error("Unexpected falsy value in items array");
} }
} }
/** @type {Promise<any>[]} */ /** @type {BackgroundJob[]} */
const backgroundJobs = []; const backgroundJobs = [];
const resolvedData = ( const resolvedData = (await Promise.all(processedData)).map(item => {
await Promise.all(
/** @type {Promise<Buffer[] | Buffer | SerializeResult>[]} */
(processedData)
)
).map(item => {
if (Array.isArray(item) || Buffer.isBuffer(item)) return item; if (Array.isArray(item) || Buffer.isBuffer(item)) return item;
backgroundJobs.push(item.backgroundJob); backgroundJobs.push(
/** @type {BackgroundJob} */
(item.backgroundJob)
);
// create pointer buffer from size and name // create pointer buffer from size and name
const name = /** @type {string} */ (item.name); const name = /** @type {string} */ (item.name);
const nameBuffer = Buffer.from(name); const nameBuffer = Buffer.from(name);
const buf = Buffer.allocUnsafe(8 + nameBuffer.length); const buf = Buffer.allocUnsafe(8 + nameBuffer.length);
writeUInt64LE(buf, item.size, 0); writeUInt64LE(buf, item.size, 0);
nameBuffer.copy(buf, 8, 0); nameBuffer.copy(buf, 8, 0);
const lazy = resultToLazy.get(item); const lazy =
/** @type {LazyFunction<BufferSerializableType[]>} */
(resultToLazy.get(item));
SerializerMiddleware.setLazySerializedValue(lazy, buf); SerializerMiddleware.setLazySerializedValue(lazy, buf);
return buf; return buf;
}); });
@ -227,7 +241,7 @@ const serialize = async (
backgroundJob: backgroundJob:
backgroundJobs.length === 1 backgroundJobs.length === 1
? backgroundJobs[0] ? backgroundJobs[0]
: Promise.all(backgroundJobs) : /** @type {BackgroundJob} */ (Promise.all(backgroundJobs))
}; };
}; };
@ -336,6 +350,7 @@ const deserialize = async (middleware, name, readFile) => {
lastLengthPositive = valuePositive; lastLengthPositive = valuePositive;
} }
} }
/** @type {(Buffer | LazyFunction<BufferSerializableType[]>)[]} */
const result = []; const result = [];
for (let length of lengths) { for (let length of lengths) {
if (length < 0) { if (length < 0) {
@ -343,17 +358,14 @@ const deserialize = async (middleware, name, readFile) => {
const size = Number(readUInt64LE(slice, 0)); const size = Number(readUInt64LE(slice, 0));
const nameBuffer = slice.slice(8); const nameBuffer = slice.slice(8);
const name = nameBuffer.toString(); const name = nameBuffer.toString();
result.push( /** @type {LazyFunction<BufferSerializableType[]>} */
SerializerMiddleware.createLazy( const lazy = SerializerMiddleware.createLazy(
memoize(() => deserialize(middleware, name, readFile)), memoize(() => deserialize(middleware, name, readFile)),
middleware, middleware,
{ { name, size },
name,
size
},
slice slice
)
); );
result.push(lazy);
} else { } else {
if (contentPosition === contentItemLength) { if (contentPosition === contentItemLength) {
nextContent(); nextContent();
@ -431,7 +443,7 @@ class FileMiddleware extends SerializerMiddleware {
/** /**
* @param {DeserializedType} data data * @param {DeserializedType} data data
* @param {Context} context context object * @param {Context} context context object
* @returns {SerializedType | Promise<SerializedType>} serialized data * @returns {SerializedType | Promise<SerializedType> | null} serialized data
*/ */
serialize(data, context) { serialize(data, context) {
const { filename, extension = "" } = context; const { filename, extension = "" } = context;
@ -616,7 +628,7 @@ class FileMiddleware extends SerializerMiddleware {
let currentBuffer; let currentBuffer;
/** @type {number | undefined} */ /** @type {number | undefined} */
let currentBufferUsed; let currentBufferUsed;
/** @type {any[]} */ /** @type {Buffer[]} */
const buf = []; const buf = [];
/** @type {import("zlib").Zlib & import("stream").Transform | undefined} */ /** @type {import("zlib").Zlib & import("stream").Transform | undefined} */
let decompression; let decompression;
@ -630,7 +642,12 @@ class FileMiddleware extends SerializerMiddleware {
}); });
} }
if (decompression) { if (decompression) {
/** @typedef {(value: Buffer[] | PromiseLike<Buffer[]>) => void} NewResolve */
/** @typedef {(reason?: Error) => void} NewReject */
/** @type {NewResolve | undefined} */
let newResolve; let newResolve;
/** @type {NewReject | undefined} */
let newReject; let newReject;
resolve( resolve(
Promise.all([ Promise.all([
@ -638,15 +655,21 @@ class FileMiddleware extends SerializerMiddleware {
newResolve = rs; newResolve = rs;
newReject = rj; newReject = rj;
}), }),
new Promise((resolve, reject) => { new Promise(
/**
* @param {(value?: undefined) => void} resolve resolve
* @param {(reason?: Error) => void} reject reject
*/
(resolve, reject) => {
decompression.on("data", chunk => buf.push(chunk)); decompression.on("data", chunk => buf.push(chunk));
decompression.on("end", () => resolve()); decompression.on("end", () => resolve());
decompression.on("error", err => reject(err)); decompression.on("error", err => reject(err));
}) }
)
]).then(() => buf) ]).then(() => buf)
); );
resolve = newResolve; resolve = /** @type {NewResolve} */ (newResolve);
reject = newReject; reject = /** @type {NewReject} */ (newReject);
} }
this.fs.open(file, "r", (err, _fd) => { this.fs.open(file, "r", (err, _fd) => {
if (err) { if (err) {
@ -696,12 +719,16 @@ class FileMiddleware extends SerializerMiddleware {
remaining -= bytesRead; remaining -= bytesRead;
if ( if (
currentBufferUsed === currentBufferUsed ===
/** @type {Buffer} */ (currentBuffer).length /** @type {Buffer} */
(currentBuffer).length
) { ) {
if (decompression) { if (decompression) {
decompression.write(currentBuffer); decompression.write(currentBuffer);
} else { } else {
buf.push(currentBuffer); buf.push(
/** @type {Buffer} */
(currentBuffer)
);
} }
currentBuffer = undefined; currentBuffer = undefined;
if (remaining === 0) { if (remaining === 0) {

View File

@ -20,7 +20,12 @@ const SetObjectSerializer = require("./SetObjectSerializer");
/** @typedef {import("./types").ComplexSerializableType} ComplexSerializableType */ /** @typedef {import("./types").ComplexSerializableType} ComplexSerializableType */
/** @typedef {import("./types").PrimitiveSerializableType} PrimitiveSerializableType */ /** @typedef {import("./types").PrimitiveSerializableType} PrimitiveSerializableType */
/** @typedef {new (...params: any[]) => any} Constructor */ /** @typedef {new (...params: EXPECTED_ANY[]) => EXPECTED_ANY} Constructor */
/**
* @template LAZY_RESULT
* @typedef {import("./SerializerMiddleware").LazyFunction<LAZY_RESULT>} LazyFunction
*/
/* /*
@ -315,7 +320,7 @@ class ObjectMiddleware extends SerializerMiddleware {
/** /**
* @param {DeserializedType} data data * @param {DeserializedType} data data
* @param {Context} context context object * @param {Context} context context object
* @returns {SerializedType | Promise<SerializedType>} serialized data * @returns {SerializedType | Promise<SerializedType> | null} serialized data
*/ */
serialize(data, context) { serialize(data, context) {
/** @type {Item[]} */ /** @type {Item[]} */
@ -785,8 +790,11 @@ class ObjectMiddleware extends SerializerMiddleware {
return item; return item;
} else if (typeof item === "function") { } else if (typeof item === "function") {
return SerializerMiddleware.deserializeLazy( return SerializerMiddleware.deserializeLazy(
item, /** @type {LazyFunction<SerializedType>} */
data => this.deserialize(data, context)[0] (item),
data =>
/** @type {[DeserializedType]} */
(this.deserialize(data, context))[0]
); );
} else { } else {
return item; return item;

View File

@ -23,16 +23,18 @@ class Serializer {
} }
/** /**
* @param {any} obj object * @param {TODO | Promise<TODO>} obj object
* @param {Context} context context object * @param {Context} context context object
* @returns {Promise<any>} result * @returns {Promise<TODO>} result
*/ */
serialize(obj, context) { serialize(obj, context) {
const ctx = { ...context, ...this.context }; const ctx = { ...context, ...this.context };
let current = obj; let current = obj;
for (const middleware of this.serializeMiddlewares) { for (const middleware of this.serializeMiddlewares) {
if (current && typeof current.then === "function") { if (current && typeof current.then === "function") {
current = current.then(data => data && middleware.serialize(data, ctx)); current =
/** @type {Promise<TODO>} */
(current).then(data => data && middleware.serialize(data, ctx));
} else if (current) { } else if (current) {
try { try {
current = middleware.serialize(current, ctx); current = middleware.serialize(current, ctx);
@ -45,18 +47,19 @@ class Serializer {
} }
/** /**
* @param {any} value value * @param {TODO | Promise<TODO>} value value
* @param {Context} context object * @param {Context} context object
* @returns {Promise<any>} result * @returns {Promise<TODO>} result
*/ */
deserialize(value, context) { deserialize(value, context) {
const ctx = { ...context, ...this.context }; const ctx = { ...context, ...this.context };
/** @type {any} */
let current = value; let current = value;
for (const middleware of this.deserializeMiddlewares) { for (const middleware of this.deserializeMiddlewares) {
current = current =
current && typeof current.then === "function" current && typeof current.then === "function"
? current.then(data => middleware.deserialize(data, ctx)) ? /** @type {Promise<TODO>} */ (current).then(data =>
middleware.deserialize(data, ctx)
)
: middleware.deserialize(current, ctx); : middleware.deserialize(current, ctx);
} }
return current; return current;

View File

@ -10,8 +10,18 @@ const LAZY_TARGET = Symbol("lazy serialization target");
const LAZY_SERIALIZED_VALUE = Symbol("lazy serialization data"); const LAZY_SERIALIZED_VALUE = Symbol("lazy serialization data");
/** @typedef {TODO} Context */ /** @typedef {TODO} Context */
/** @typedef {function(): Promise<any> | any} LazyFn */
/** @typedef {Record<any, any>} LazyOptions */ /**
* @template LazyResult
* @typedef {function(): LazyResult | Promise<LazyResult>} InternalLazyFunction
*/
/** @typedef {Record<string, any>} LazyOptions */
/**
* @template LazyResult
* @typedef {InternalLazyFunction<LazyResult> & { [LAZY_TARGET]: TODO, [LAZY_SERIALIZED_VALUE]?: TODO, options: LazyOptions }} LazyFunction
*/
/** /**
* @template DeserializedType * @template DeserializedType
@ -23,7 +33,7 @@ class SerializerMiddleware {
* @abstract * @abstract
* @param {DeserializedType} data data * @param {DeserializedType} data data
* @param {Context} context context object * @param {Context} context context object
* @returns {SerializedType | Promise<SerializedType>} serialized data * @returns {SerializedType | Promise<SerializedType> | null} serialized data
*/ */
serialize(data, context) { serialize(data, context) {
const AbstractMethodError = require("../AbstractMethodError"); const AbstractMethodError = require("../AbstractMethodError");
@ -43,23 +53,26 @@ class SerializerMiddleware {
} }
/** /**
* @param {any | LazyFn} value contained value or function to value * @template LazyResult
* @param {LazyFunction<LazyResult> | EXPECTED_ANY} value contained value or function to value
* @param {SerializerMiddleware<any, any>} target target middleware * @param {SerializerMiddleware<any, any>} target target middleware
* @param {LazyOptions=} options lazy options * @param {LazyOptions=} options lazy options
* @param {any=} serializedValue serialized value * @param {any=} serializedValue serialized value
* @returns {LazyFn} lazy function * @returns {LazyFunction<LazyResult>} lazy function
*/ */
static createLazy(value, target, options = {}, serializedValue = undefined) { static createLazy(value, target, options = {}, serializedValue = undefined) {
if (SerializerMiddleware.isLazy(value, target)) return value; if (SerializerMiddleware.isLazy(value, target)) return value;
const fn = typeof value === "function" ? value : () => value; const fn =
/** @type {LazyFunction<LazyResult>} */
(typeof value === "function" ? value : () => value);
fn[LAZY_TARGET] = target; fn[LAZY_TARGET] = target;
/** @type {any} */ (fn).options = options; fn.options = options;
fn[LAZY_SERIALIZED_VALUE] = serializedValue; fn[LAZY_SERIALIZED_VALUE] = serializedValue;
return fn; return fn;
} }
/** /**
* @param {LazyFn} fn lazy function * @param {EXPECTED_ANY} fn lazy function
* @param {SerializerMiddleware<any, any>=} target target middleware * @param {SerializerMiddleware<any, any>=} target target middleware
* @returns {boolean} true, when fn is a lazy function (optionally of that target) * @returns {boolean} true, when fn is a lazy function (optionally of that target)
*/ */
@ -70,7 +83,8 @@ class SerializerMiddleware {
} }
/** /**
* @param {LazyFn} fn lazy function * @template LazyResult
* @param {LazyFunction<LazyResult>} fn lazy function
* @returns {LazyOptions | undefined} options * @returns {LazyOptions | undefined} options
*/ */
static getLazyOptions(fn) { static getLazyOptions(fn) {
@ -79,7 +93,8 @@ class SerializerMiddleware {
} }
/** /**
* @param {LazyFn} fn lazy function * @template LazyResult
* @param {LazyFunction<LazyResult> | EXPECTED_ANY} fn lazy function
* @returns {any | undefined} serialized value * @returns {any | undefined} serialized value
*/ */
static getLazySerializedValue(fn) { static getLazySerializedValue(fn) {
@ -88,8 +103,9 @@ class SerializerMiddleware {
} }
/** /**
* @param {LazyFn} fn lazy function * @template LazyResult
* @param {any} value serialized value * @param {LazyFunction<LazyResult>} fn lazy function
* @param {TODO} value serialized value
* @returns {void} * @returns {void}
*/ */
static setLazySerializedValue(fn, value) { static setLazySerializedValue(fn, value) {
@ -97,50 +113,69 @@ class SerializerMiddleware {
} }
/** /**
* @param {LazyFn} lazy lazy function * @template LazyResult, R
* @param {function(any): Promise<any> | any} serialize serialize function * @param {LazyFunction<LazyResult>} lazy lazy function
* @returns {LazyFn} new lazy * @param {function(LazyResult): Promise<R> | R} serialize serialize function
* @returns {LazyFunction<R>} new lazy
*/ */
static serializeLazy(lazy, serialize) { static serializeLazy(lazy, serialize) {
const fn = memoize(() => { const fn = /** @type {LazyFunction<R>} */ (
memoize(() => {
const r = lazy(); const r = lazy();
if (r && typeof r.then === "function") { if (
return r.then(data => data && serialize(data)); r &&
typeof (/** @type {Promise<LazyResult>} */ (r).then) === "function"
) {
return (
/** @type {Promise<LazyResult>} */
(r).then(data => data && serialize(data))
);
} }
return serialize(r); return serialize(/** @type {LazyResult} */ (r));
}); })
);
fn[LAZY_TARGET] = lazy[LAZY_TARGET]; fn[LAZY_TARGET] = lazy[LAZY_TARGET];
/** @type {any} */ (fn).options = /** @type {any} */ (lazy).options; fn.options = lazy.options;
lazy[LAZY_SERIALIZED_VALUE] = fn; lazy[LAZY_SERIALIZED_VALUE] = fn;
return fn; return fn;
} }
/** /**
* @template T * @template LazyResult, R
* @param {LazyFn} lazy lazy function * @param {LazyFunction<LazyResult>} lazy lazy function
* @param {function(T): Promise<T> | T} deserialize deserialize function * @param {function(LazyResult): Promise<R> | R} deserialize deserialize function
* @returns {function(): Promise<T> | T} new lazy * @returns {LazyFunction<R>} new lazy
*/ */
static deserializeLazy(lazy, deserialize) { static deserializeLazy(lazy, deserialize) {
const fn = memoize(() => { const fn = /** @type {LazyFunction<R>} */ (
memoize(() => {
const r = lazy(); const r = lazy();
if (r && typeof r.then === "function") { if (
return r.then(data => deserialize(data)); r &&
typeof (/** @type {Promise<LazyResult>} */ (r).then) === "function"
) {
return (
/** @type {Promise<LazyResult>} */
(r).then(data => deserialize(data))
);
} }
return deserialize(r); return deserialize(/** @type {LazyResult} */ (r));
}); })
);
fn[LAZY_TARGET] = lazy[LAZY_TARGET]; fn[LAZY_TARGET] = lazy[LAZY_TARGET];
/** @type {any} */ (fn).options = /** @type {any} */ (lazy).options; fn.options = lazy.options;
fn[LAZY_SERIALIZED_VALUE] = lazy; fn[LAZY_SERIALIZED_VALUE] = lazy;
return fn; return fn;
} }
/** /**
* @param {LazyFn} lazy lazy function * @template LazyResult
* @returns {LazyFn} new lazy * @param {LazyFunction<LazyResult> | EXPECTED_ANY} lazy lazy function
* @returns {LazyFunction<LazyResult> | EXPECTED_ANY} new lazy
*/ */
static unMemoizeLazy(lazy) { static unMemoizeLazy(lazy) {
if (!SerializerMiddleware.isLazy(lazy)) return lazy; if (!SerializerMiddleware.isLazy(lazy)) return lazy;
/** @type {LazyFunction<LazyResult>} */
const fn = () => { const fn = () => {
throw new Error( throw new Error(
"A lazy value that has been unmemorized can't be called again" "A lazy value that has been unmemorized can't be called again"
@ -150,7 +185,7 @@ class SerializerMiddleware {
lazy[LAZY_SERIALIZED_VALUE] lazy[LAZY_SERIALIZED_VALUE]
); );
fn[LAZY_TARGET] = lazy[LAZY_TARGET]; fn[LAZY_TARGET] = lazy[LAZY_TARGET];
fn.options = /** @type {any} */ (lazy).options; fn.options = lazy.options;
return fn; return fn;
} }
} }

View File

@ -18,7 +18,7 @@ class SingleItemMiddleware extends SerializerMiddleware {
/** /**
* @param {DeserializedType} data data * @param {DeserializedType} data data
* @param {Context} context context object * @param {Context} context context object
* @returns {SerializedType | Promise<SerializedType>} serialized data * @returns {SerializedType | Promise<SerializedType> | null} serialized data
*/ */
serialize(data, context) { serialize(data, context) {
return [data]; return [data];

View File

@ -431,7 +431,7 @@ const path = require("path");
*/ */
/** /**
* @template {NodeJS.ArrayBufferView} [TBuffer=Buffer] * @template {NodeJS.ArrayBufferView} [TBuffer=NodeJS.ArrayBufferView]
* @typedef {{ * @typedef {{
* (fd: number, buffer: TBuffer, offset: number, length: number, position: ReadPosition | null, callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: TBuffer) => void): void; * (fd: number, buffer: TBuffer, offset: number, length: number, position: ReadPosition | null, callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: TBuffer) => void): void;
* (fd: number, options: ReadAsyncOptions<TBuffer>, callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: TBuffer) => void): void; * (fd: number, options: ReadAsyncOptions<TBuffer>, callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: TBuffer) => void): void;

View File

@ -4,7 +4,10 @@
"use strict"; "use strict";
/** @template T @typedef {function(): T} FunctionReturning */ /**
* @template T
* @typedef {function(): T} FunctionReturning
*/
/** /**
* @template T * @template T

View File

@ -0,0 +1 @@
module.exports = "a";

View File

@ -0,0 +1,7 @@
This
should
result
in
an
error
}])

View File

@ -0,0 +1,6 @@
it("should replace a context with a new regExp", function() {
function rqInContext(x) {
return require('./folder/' + x);
}
expect(rqInContext("a")).toBe("a");
});

View File

@ -0,0 +1,6 @@
var webpack = require("../../../../");
/** @type {import("../../../../").Configuration} */
module.exports = {
plugins: [new webpack.ContextReplacementPlugin(/folder$/, false, /(a|b)/)]
};

93
types.d.ts vendored
View File

@ -1704,6 +1704,12 @@ declare interface CodeGenerationContext {
*/ */
sourceTypes?: ReadonlySet<string>; sourceTypes?: ReadonlySet<string>;
} }
declare interface CodeGenerationJob {
module: Module;
hash: string;
runtime: RuntimeSpec;
runtimes: RuntimeSpec[];
}
declare interface CodeGenerationResult { declare interface CodeGenerationResult {
/** /**
* the resulting sources for all source types * the resulting sources for all source types
@ -2168,12 +2174,7 @@ declare class Compilation {
sortItemsWithChunkIds(): void; sortItemsWithChunkIds(): void;
summarizeDependencies(): void; summarizeDependencies(): void;
createModuleHashes(): void; createModuleHashes(): void;
createHash(): { createHash(): CodeGenerationJob[];
module: Module;
hash: string;
runtime: RuntimeSpec;
runtimes: RuntimeSpec[];
}[];
fullHash?: string; fullHash?: string;
hash?: string; hash?: string;
emitAsset(file: string, source: Source, assetInfo?: AssetInfo): void; emitAsset(file: string, source: Source, assetInfo?: AssetInfo): void;
@ -3060,15 +3061,21 @@ declare interface ContextModuleOptions {
declare class ContextReplacementPlugin { declare class ContextReplacementPlugin {
constructor( constructor(
resourceRegExp: RegExp, resourceRegExp: RegExp,
newContentResource?: any, newContentResource?: string | boolean | RegExp | ((context?: any) => void),
newContentRecursive?: any, newContentRecursive?: boolean | RegExp | NewContentCreateContextMap,
newContentRegExp?: RegExp newContentRegExp?: RegExp
); );
resourceRegExp: RegExp; resourceRegExp: RegExp;
newContentCallback: any; newContentCallback?: (context?: any) => void;
newContentResource: any; newContentResource?: string;
newContentCreateContextMap: any; newContentCreateContextMap?: (
newContentRecursive: any; fs: InputFileSystem,
callback: (
err: null | Error,
newContentRecursive: NewContentCreateContextMap
) => void
) => void;
newContentRecursive?: boolean;
newContentRegExp?: RegExp; newContentRegExp?: RegExp;
/** /**
@ -4791,7 +4798,7 @@ declare class ExternalModule extends Module {
* restore unsafe cache data * restore unsafe cache data
*/ */
restoreFromUnsafeCache( restoreFromUnsafeCache(
unsafeCacheData: object, unsafeCacheData: UnsafeCacheData,
normalModuleFactory: NormalModuleFactory normalModuleFactory: NormalModuleFactory
): void; ): void;
} }
@ -5832,7 +5839,7 @@ declare interface IntermediateFileSystemExtras {
| WriteStreamOptions | WriteStreamOptions
) => NodeJS.WritableStream; ) => NodeJS.WritableStream;
open: Open; open: Open;
read: Read<Buffer>; read: Read<ArrayBufferView>;
close: ( close: (
arg0: number, arg0: number,
arg1: (arg0: null | NodeJS.ErrnoException) => void arg1: (arg0: null | NodeJS.ErrnoException) => void
@ -7830,6 +7837,19 @@ declare interface KnownStatsProfile {
factory: number; factory: number;
dependencies: number; dependencies: number;
} }
declare interface KnownUnsafeCacheData {
/**
* factory meta
*/
factoryMeta?: FactoryMeta;
/**
* resolve options
*/
resolveOptions?: ResolveOptions;
parserOptions?: ParserOptions;
generatorOptions?: GeneratorOptions;
}
declare interface LStatFs { declare interface LStatFs {
( (
path: PathLikeFs, path: PathLikeFs,
@ -9195,9 +9215,10 @@ declare interface ModuleMemCachesItem {
memCache: WeakTupleMap<any, any>; memCache: WeakTupleMap<any, any>;
} }
declare interface ModuleObject { declare interface ModuleObject {
id: string; id?: string;
exports: any; exports: any;
loaded: boolean; loaded: boolean;
error?: Error;
} }
/** /**
@ -9616,6 +9637,9 @@ declare interface NeedBuildContext {
fileSystemInfo: FileSystemInfo; fileSystemInfo: FileSystemInfo;
valueCacheVersions: Map<string, string | Set<string>>; valueCacheVersions: Map<string, string | Set<string>>;
} }
declare interface NewContentCreateContextMap {
[index: string]: string;
}
declare class NoEmitOnErrorsPlugin { declare class NoEmitOnErrorsPlugin {
constructor(); constructor();
@ -9714,7 +9738,7 @@ declare class NormalModule extends Module {
* restore unsafe cache data * restore unsafe cache data
*/ */
restoreFromUnsafeCache( restoreFromUnsafeCache(
unsafeCacheData: NormalModuleUnsafeCacheData, unsafeCacheData: UnsafeCacheData,
normalModuleFactory: NormalModuleFactory normalModuleFactory: NormalModuleFactory
): void; ): void;
createSourceForAsset( createSourceForAsset(
@ -9984,12 +10008,6 @@ declare class NormalModuleReplacementPlugin {
*/ */
apply(compiler: Compiler): void; apply(compiler: Compiler): void;
} }
type NormalModuleUnsafeCacheData = UnsafeCacheData & {
parser?: Parser;
parserOptions?: ParserOptions;
generator?: Generator;
generatorOptions?: GeneratorOptions;
};
type NormalizedStatsOptions = KnownNormalizedStatsOptions & type NormalizedStatsOptions = KnownNormalizedStatsOptions &
Omit< Omit<
StatsOptions, StatsOptions,
@ -11335,32 +11353,32 @@ declare interface PlatformTargetProperties {
/** /**
* web platform, importing of http(s) and std: is available * web platform, importing of http(s) and std: is available
*/ */
web: null | boolean; web?: null | boolean;
/** /**
* browser platform, running in a normal web browser * browser platform, running in a normal web browser
*/ */
browser: null | boolean; browser?: null | boolean;
/** /**
* (Web)Worker platform, running in a web/shared/service worker * (Web)Worker platform, running in a web/shared/service worker
*/ */
webworker: null | boolean; webworker?: null | boolean;
/** /**
* node platform, require of node built-in modules is available * node platform, require of node built-in modules is available
*/ */
node: null | boolean; node?: null | boolean;
/** /**
* nwjs platform, require of legacy nw.gui is available * nwjs platform, require of legacy nw.gui is available
*/ */
nwjs: null | boolean; nwjs?: null | boolean;
/** /**
* electron platform, require of some electron built-in modules is available * electron platform, require of some electron built-in modules is available
*/ */
electron: null | boolean; electron?: null | boolean;
} }
type Plugin = type Plugin =
| undefined | undefined
@ -11422,7 +11440,7 @@ declare class Profiler {
inspector: any; inspector: any;
hasSession(): boolean; hasSession(): boolean;
startProfiling(): Promise<void> | Promise<[any, any, any]>; startProfiling(): Promise<void> | Promise<[any, any, any]>;
sendCommand(method: string, params?: object): Promise<any>; sendCommand(method: string, params?: Record<string, any>): Promise<any>;
destroy(): Promise<void>; destroy(): Promise<void>;
stopProfiling(): Promise<{ profile: any }>; stopProfiling(): Promise<{ profile: any }>;
} }
@ -11625,7 +11643,7 @@ declare interface RawSourceMap {
mappings: string; mappings: string;
file: string; file: string;
} }
declare interface Read<TBuffer extends ArrayBufferView = Buffer> { declare interface Read<TBuffer extends ArrayBufferView = ArrayBufferView> {
( (
fd: number, fd: number,
buffer: TBuffer, buffer: TBuffer,
@ -12988,10 +13006,10 @@ declare interface ResourceDataWithData {
data: Record<string, any>; data: Record<string, any>;
} }
declare abstract class RestoreProvidedData { declare abstract class RestoreProvidedData {
exports: any; exports: any[];
otherProvided: any; otherProvided?: null | boolean;
otherCanMangleProvide: any; otherCanMangleProvide?: boolean;
otherTerminalBinding: any; otherTerminalBinding: boolean;
serialize(__0: ObjectSerializerContext): void; serialize(__0: ObjectSerializerContext): void;
} }
declare interface RmDirOptions { declare interface RmDirOptions {
@ -13981,7 +13999,7 @@ declare abstract class SerializerMiddleware<DeserializedType, SerializedType> {
serialize( serialize(
data: DeserializedType, data: DeserializedType,
context?: any context?: any
): SerializedType | Promise<SerializedType>; ): null | SerializedType | Promise<SerializedType>;
deserialize( deserialize(
data: SerializedType, data: SerializedType,
context?: any context?: any
@ -15271,10 +15289,7 @@ declare const UNDEFINED_MARKER: unique symbol;
* https://nodejs.org/api/url.html#the-whatwg-url-api * https://nodejs.org/api/url.html#the-whatwg-url-api
*/ */
declare interface URL_url extends URL {} declare interface URL_url extends URL {}
declare interface UnsafeCacheData { type UnsafeCacheData = KnownUnsafeCacheData & Record<string, any>;
factoryMeta?: FactoryMeta;
resolveOptions?: ResolveOptions;
}
declare interface UpdateHashContextDependency { declare interface UpdateHashContextDependency {
chunkGraph: ChunkGraph; chunkGraph: ChunkGraph;
runtime: RuntimeSpec; runtime: RuntimeSpec;