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,18 +3270,20 @@ 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 =
this._backCompat /** @type {CompilationAssets} */
? soonFrozenObjectDeprecation( (
this.assets, this._backCompat
"Compilation.assets", ? soonFrozenObjectDeprecation(
"DEP_WEBPACK_COMPILATION_ASSETS", this.assets,
`BREAKING CHANGE: No more changes should happen to Compilation.assets after sealing the Compilation. "Compilation.assets",
"DEP_WEBPACK_COMPILATION_ASSETS",
`BREAKING CHANGE: No more changes should happen to Compilation.assets after sealing the Compilation.
Do changes to assets earlier, e. g. in Compilation.hooks.processAssets. Do changes to assets earlier, e. g. in Compilation.hooks.processAssets.
Make sure to select an appropriate stage from Compilation.PROCESS_ASSETS_STAGE_*.` Make sure to select an appropriate stage from Compilation.PROCESS_ASSETS_STAGE_*.`
) )
: Object.freeze(this.assets) : Object.freeze(this.assets)
); );
this.summarizeDependencies(); this.summarizeDependencies();
if (shouldRecord) { if (shouldRecord) {
@ -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();
/** @type {SyncHook<[Resolver, ResolveOptions, ResolveOptionsWithDependencyType]>} */ const hook =
(hook).tap("ResolverCachePlugin", (resolver, options, userOptions) => { /** @type {SyncHook<[Resolver, ResolveOptions, ResolveOptionsWithDependencyType]>} */
(_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(
tracer.trace.end({ ...args,
name, /**
id, * @param {...EXPECTED_ANY[]} r result
cat: defaultCategory */
}); (...r) => {
callback(...r); tracer.trace.end({
}); name,
id,
cat: defaultCategory
});
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, slice
size
},
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(
decompression.on("data", chunk => buf.push(chunk)); /**
decompression.on("end", () => resolve()); * @param {(value?: undefined) => void} resolve resolve
decompression.on("error", err => reject(err)); * @param {(reason?: Error) => void} reject reject
}) */
(resolve, reject) => {
decompression.on("data", chunk => buf.push(chunk));
decompression.on("end", () => resolve());
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>} */ (
const r = lazy(); memoize(() => {
if (r && typeof r.then === "function") { const r = lazy();
return r.then(data => data && serialize(data)); if (
} r &&
return serialize(r); typeof (/** @type {Promise<LazyResult>} */ (r).then) === "function"
}); ) {
return (
/** @type {Promise<LazyResult>} */
(r).then(data => data && serialize(data))
);
}
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>} */ (
const r = lazy(); memoize(() => {
if (r && typeof r.then === "function") { const r = lazy();
return r.then(data => deserialize(data)); if (
} r &&
return deserialize(r); typeof (/** @type {Promise<LazyResult>} */ (r).then) === "function"
}); ) {
return (
/** @type {Promise<LazyResult>} */
(r).then(data => deserialize(data))
);
}
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;