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",
"snitin",
"Nitin",
"Kumarr",
"Kumar",
"spacek",
"thelarkinn"
],

View File

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

View File

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

View File

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

View File

@ -31,6 +31,7 @@ const { register } = require("./util/serialization");
/** @typedef {import("./Chunk")} Chunk */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./Compilation")} Compilation */
/** @typedef {import("./Compilation").UnsafeCacheData} UnsafeCacheData */
/** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
/** @typedef {import("./ExportsInfo")} ExportsInfo */
@ -647,7 +648,7 @@ class ExternalModule extends Module {
/**
* 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
*/
restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) {

View File

@ -24,6 +24,7 @@ const makeSerializable = require("./util/makeSerializable");
/** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */
/** @typedef {import("./Compilation")} Compilation */
/** @typedef {import("./Compilation").AssetInfo} AssetInfo */
/** @typedef {import("./Compilation").UnsafeCacheData} UnsafeCacheData */
/** @typedef {import("./ConcatenationScope")} ConcatenationScope */
/** @typedef {import("./Dependency")} Dependency */
/** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */
@ -141,8 +142,6 @@ const makeSerializable = require("./util/makeSerializable");
* @property {boolean=} sideEffectFree
*/
/** @typedef {{ factoryMeta: FactoryMeta | undefined, resolveOptions: ResolveOptions | undefined }} UnsafeCacheData */
const EMPTY_RESOLVE_OPTIONS = {};
let debugId = 1000;
@ -1030,7 +1029,7 @@ class Module extends DependenciesBlock {
/**
* 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
*/
_restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) {

View File

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

View File

@ -186,20 +186,13 @@ const mergeGlobalOptions = (globalOptions, type, localOptions) => {
// TODO webpack 6 remove
/**
* @template {import("tapable").Hook<EXPECTED_ANY, EXPECTED_ANY>} T
* @param {string} name name
* @param {TODO} hook hook
* @param {T} hook hook
* @returns {string} result
*/
const deprecationChangedHookMessage = (name, hook) => {
const names = hook.taps
.map(
/**
* @param {TODO} tapped tapped
* @returns {string} name
*/
tapped => tapped.name
)
.join(", ");
const names = hook.taps.map(tapped => tapped.name).join(", ");
return (
`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"]),
/** @type {AsyncSeriesBailHook<[ResolveData], false | void>} */
afterResolve: new AsyncSeriesBailHook(["resolveData"]),
/** @type {AsyncSeriesBailHook<[ResolveData["createData"], ResolveData], Module | void>} */
/** @type {AsyncSeriesBailHook<[CreateData, ResolveData], Module | void>} */
createModule: new AsyncSeriesBailHook(["createData", "resolveData"]),
/** @type {SyncWaterfallHook<[Module, ResolveData["createData"], ResolveData]>} */
/** @type {SyncWaterfallHook<[Module, CreateData, ResolveData]>} */
module: new SyncWaterfallHook(["module", "createData", "resolveData"]),
/** @type {HookMap<SyncBailHook<[ParserOptions], Parser | void>>} */
createParser: new HookMap(() => new SyncBailHook(["parserOptions"])),
@ -459,6 +452,7 @@ class NormalModuleFactory extends ModuleFactory {
matchResource = join(this.fs, context, matchResource);
}
}
matchResourceData = {
resource: matchResource,
...cacheParseResource(matchResource)
@ -546,7 +540,11 @@ class NormalModuleFactory extends ModuleFactory {
if (!resourceData) {
// ignored
return callback(null, dependencies[0].createIgnoredModule(context));
return callback(
null,
/** @type {TODO} */
(dependencies[0].createIgnoredModule(context))
);
}
const userRequest =
@ -624,12 +622,11 @@ class NormalModuleFactory extends ModuleFactory {
] === "object" &&
settings[/** @type {keyof ModuleSettings} */ (r.type)] !== null
) {
settings[r.type] = cachedCleverMerge(
settings[/** @type {keyof ModuleSettings} */ (r.type)],
r.value
);
const type = /** @type {TODO} */ (r.type);
settings[type] = cachedCleverMerge(settings[type], r.value);
} 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];
if (content !== undefined) {
write(content.items);
content.writeLazy(lazy => writeSeparate(lazy, { name: `${i}` }));
content.writeLazy(lazy =>
/** @type {NonNullable<ObjectSerializerContext["writeSeparate"]>} */
(writeSeparate)(lazy, { name: `${i}` })
);
} else {
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 }) {
if (profile) {
@ -792,7 +795,7 @@ makeSerializable(
"PackContentItems"
);
/** @typedef {(function(): Promise<PackContentItems> | PackContentItems)} LazyFn */
/** @typedef {(function(): Promise<PackContentItems> | PackContentItems)} LazyFunction */
class PackContent {
/*
@ -823,7 +826,7 @@ class PackContent {
*/
constructor(items, usedItems, dataOrFn, logger, lazyName) {
this.items = items;
/** @type {LazyFn | undefined} */
/** @type {TODO | undefined} */
this.lazy = typeof dataOrFn === "function" ? dataOrFn : undefined;
/** @type {Content | undefined} */
this.content = typeof dataOrFn === "function" ? undefined : dataOrFn.map;
@ -861,7 +864,7 @@ class PackContent {
);
logger.time(timeMessage);
}
const value = /** @type {LazyFn} */ (this.lazy)();
const value = /** @type {LazyFunction} */ (this.lazy)();
if ("then" in value) {
return value.then(data => {
const map = data.map;
@ -871,7 +874,7 @@ class PackContent {
// Move to state C
this.content = map;
this.lazy = SerializerMiddleware.unMemoizeLazy(
/** @type {LazyFn} */
/** @type {LazyFunction} */
(this.lazy)
);
return map.get(identifier);
@ -885,7 +888,7 @@ class PackContent {
// Move to state C
this.content = map;
this.lazy = SerializerMiddleware.unMemoizeLazy(
/** @type {LazyFn} */
/** @type {LazyFunction} */
(this.lazy)
);
return map.get(identifier);
@ -917,7 +920,9 @@ class PackContent {
);
logger.time(timeMessage);
}
const value = this.lazy();
const value =
/** @type {PackContentItems | Promise<PackContentItems>} */
(this.lazy());
if ("then" in value) {
return value.then(data => {
if (timeMessage) {
@ -1008,7 +1013,7 @@ class PackContent {
);
logger.time(timeMessage);
}
const value = /** @type {LazyFn} */ (this.lazy)();
const value = /** @type {LazyFunction} */ (this.lazy)();
this.outdated = false;
if ("then" in value) {
// Move to state B1
@ -1026,7 +1031,7 @@ class PackContent {
// Move to state C1 (or maybe C2)
this.content = map;
this.lazy = SerializerMiddleware.unMemoizeLazy(
/** @type {LazyFn} */
/** @type {LazyFunction} */
(this.lazy)
);

View File

@ -26,6 +26,11 @@ const makeSerializable = require("../util/makeSerializable");
* @typedef {import("tapable").SyncHook<T>} SyncHook
*/
/**
* @template H
* @typedef {import("tapable").HookMapInterceptor<H>} HookMapInterceptor
*/
class CacheEntry {
/**
* @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 */
/**
@ -244,13 +249,15 @@ class ResolverCachePlugin {
);
};
compiler.resolverFactory.hooks.resolver.intercept({
factory(type, hook) {
factory(type, _hook) {
/** @type {Map<string, (function(Error=, ResolveRequest=): void)[]>} */
const activeRequests = new Map();
/** @type {Map<string, [function(Error=, ResolveRequest=): void, NonNullable<ResolveContext["yield"]>][]>} */
const activeRequestsWithYield = new Map();
const hook =
/** @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;
const optionsIdent = objectToString(userOptions, false);
const cacheWithContext =
@ -299,7 +306,7 @@ class ResolverCachePlugin {
let yields;
/**
* @type {function((Error | null)=, ResolveRequest | ResolveRequest[]=): void}
* @type {function((Error | null)=, (ResolveRequest | ResolveRequest[] | null)=): void}
*/
const done = withYield
? (err, result) => {

View File

@ -1656,7 +1656,8 @@ const getResolveDefaults = ({
styleConditions.push(mode === "development" ? "development" : "production");
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`
// and CSS `@import` does not handle `main` files in directories,
// you should always specify the full URL for styles

View File

@ -22,12 +22,12 @@ const getDefaultTarget = context => {
/**
* @typedef {object} PlatformTargetProperties
* @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} 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} 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} [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} [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} [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
*/
/**

View File

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

View File

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

View File

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

View File

@ -8,10 +8,14 @@ const memoize = require("../util/memoize");
const SerializerMiddleware = require("./SerializerMiddleware");
/** @typedef {import("./SerializerMiddleware").Context} Context */
/** @typedef {import("./SerializerMiddleware").LazyFn} LazyFn */
/** @typedef {import("./types").BufferSerializableType} BufferSerializableType */
/** @typedef {import("./types").PrimitiveSerializableType} PrimitiveSerializableType */
/**
* @template LAZY_RESULT
* @typedef {import("./SerializerMiddleware").LazyFunction<LAZY_RESULT>} LazyFunction
*/
/*
Format:
@ -146,16 +150,16 @@ class BinaryMiddleware extends SerializerMiddleware {
/**
* @param {DeserializedType} data data
* @param {Context} context context object
* @returns {SerializedType | Promise<SerializedType>} serialized data
* @returns {SerializedType | Promise<SerializedType> | null} serialized data
*/
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
* @returns {function(): Promise<any> | any} new lazy
* @returns {LazyFunction<SerializedType>} new lazy
*/
_serializeLazy(fn, context) {
return SerializerMiddleware.serializeLazy(fn, data =>
@ -277,7 +281,7 @@ class BinaryMiddleware extends SerializerMiddleware {
case "function": {
if (!SerializerMiddleware.isLazy(thing))
throw new Error(`Unexpected function ${thing}`);
/** @type {SerializedType | (() => SerializedType)} */
/** @type {SerializedType | LazyFunction<SerializedType>} */
let serializedData =
SerializerMiddleware.getLazySerializedValue(thing);
if (serializedData === undefined) {
@ -285,16 +289,23 @@ class BinaryMiddleware extends SerializerMiddleware {
flush();
allocationScope.leftOverBuffer = leftOverBuffer;
const result =
/** @type {(Exclude<PrimitiveSerializableType, Promise<PrimitiveSerializableType>>)[]} */ (
thing()
);
/** @type {PrimitiveSerializableType[]} */
(thing());
const data = this._serialize(result, context, allocationScope);
leftOverBuffer = allocationScope.leftOverBuffer;
allocationScope.leftOverBuffer = null;
SerializerMiddleware.setLazySerializedValue(thing, data);
SerializerMiddleware.setLazySerializedValue(
/** @type {LazyFunction<DeserializedType>} */
(thing),
data
);
serializedData = data;
} else {
serializedData = this._serializeLazy(thing, context);
serializedData = this._serializeLazy(
/** @type {LazyFunction<DeserializedType>} */
(thing),
context
);
flush();
buffers.push(serializedData);
break;
@ -655,7 +666,7 @@ class BinaryMiddleware extends SerializerMiddleware {
* @private
* @param {SerializedType} content content
* @param {Context} context context object
* @returns {LazyFn} lazy function
* @returns {LazyFunction<DeserializedType>} lazy function
*/
_createLazyDeserialized(content, context) {
return SerializerMiddleware.createLazy(
@ -668,9 +679,9 @@ class BinaryMiddleware extends SerializerMiddleware {
/**
* @private
* @param {LazyFn} fn lazy function
* @param {LazyFunction<SerializedType>} fn lazy function
* @param {Context} context context object
* @returns {TODO} new lazy
* @returns {LazyFunction<DeserializedType>} new lazy
*/
_deserializeLazy(fn, context) {
return SerializerMiddleware.deserializeLazy(fn, data =>
@ -807,13 +818,17 @@ class BinaryMiddleware extends SerializerMiddleware {
return () => {
const count = readU32();
const lengths = Array.from({ length: count }).map(() => readU32());
/** @type {(Buffer | LazyFunction<BufferSerializableType[]>)[]} */
const content = [];
for (let l of lengths) {
if (l === 0) {
if (typeof currentBuffer !== "function") {
throw new Error("Unexpected non-lazy element in stream");
}
content.push(currentBuffer);
content.push(
/** @type {LazyFunction<BufferSerializableType[]>} */
(currentBuffer)
);
currentDataItem++;
currentBuffer =
currentDataItem < data.length ? data[currentDataItem] : null;
@ -1129,7 +1144,13 @@ class BinaryMiddleware extends SerializerMiddleware {
let result = [];
while (currentBuffer !== null) {
if (typeof currentBuffer === "function") {
result.push(this._deserializeLazy(currentBuffer, context));
result.push(
this._deserializeLazy(
/** @type {LazyFunction<SerializedType>} */
(currentBuffer),
context
)
);
currentDataItem++;
currentBuffer =
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").IntermediateFileSystem} IntermediateFileSystem */
/** @typedef {import("./SerializerMiddleware").Context} Context */
/** @typedef {import("./SerializerMiddleware").LazyFn} LazyFn */
/** @typedef {import("./types").BufferSerializableType} BufferSerializableType */
/**
* @template LAZY_RESULT
* @typedef {import("./SerializerMiddleware").LazyFunction<LAZY_RESULT>} LazyFunction
*/
/*
Format:
@ -81,11 +85,13 @@ const readUInt64LE = Buffer.prototype.readBigUInt64LE
return high * 0x100000000 + low;
};
/** @typedef {Promise<void | void[]>} BackgroundJob */
/**
* @typedef {object} SerializeResult
* @property {string | false} name
* @property {number} size
* @property {Promise<any>=} backgroundJob
* @property {BackgroundJob=} backgroundJob
*/
/**
@ -103,9 +109,9 @@ const serialize = async (
writeFile,
hashFunction = "md4"
) => {
/** @type {(Buffer[] | Buffer | SerializeResult | Promise<SerializeResult>)[]} */
/** @type {(Buffer[] | Buffer | Promise<SerializeResult>)[]} */
const processedData = [];
/** @type {WeakMap<SerializeResult, LazyFn>} */
/** @type {WeakMap<SerializeResult, LazyFunction<BufferSerializableType[]>>} */
const resultToLazy = new WeakMap();
/** @type {Buffer[] | undefined} */
let lastBuffers;
@ -131,7 +137,10 @@ const serialize = async (
} else {
const content = item();
if (content) {
const options = SerializerMiddleware.getLazyOptions(item);
const options = SerializerMiddleware.getLazyOptions(
/** @type {LazyFunction<Buffer[]>} */
(item)
);
processedData.push(
serialize(
middleware,
@ -140,8 +149,13 @@ const serialize = async (
writeFile,
hashFunction
).then(result => {
/** @type {any} */ (item).options.size = result.size;
resultToLazy.set(result, item);
/** @type {LazyFunction<Buffer[]>} */
(item).options.size = result.size;
resultToLazy.set(
result,
/** @type {LazyFunction<Buffer[]>} */
(item)
);
return result;
})
);
@ -162,24 +176,24 @@ const serialize = async (
throw new Error("Unexpected falsy value in items array");
}
}
/** @type {Promise<any>[]} */
/** @type {BackgroundJob[]} */
const backgroundJobs = [];
const resolvedData = (
await Promise.all(
/** @type {Promise<Buffer[] | Buffer | SerializeResult>[]} */
(processedData)
)
).map(item => {
const resolvedData = (await Promise.all(processedData)).map(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
const name = /** @type {string} */ (item.name);
const nameBuffer = Buffer.from(name);
const buf = Buffer.allocUnsafe(8 + nameBuffer.length);
writeUInt64LE(buf, item.size, 0);
nameBuffer.copy(buf, 8, 0);
const lazy = resultToLazy.get(item);
const lazy =
/** @type {LazyFunction<BufferSerializableType[]>} */
(resultToLazy.get(item));
SerializerMiddleware.setLazySerializedValue(lazy, buf);
return buf;
});
@ -227,7 +241,7 @@ const serialize = async (
backgroundJob:
backgroundJobs.length === 1
? backgroundJobs[0]
: Promise.all(backgroundJobs)
: /** @type {BackgroundJob} */ (Promise.all(backgroundJobs))
};
};
@ -336,6 +350,7 @@ const deserialize = async (middleware, name, readFile) => {
lastLengthPositive = valuePositive;
}
}
/** @type {(Buffer | LazyFunction<BufferSerializableType[]>)[]} */
const result = [];
for (let length of lengths) {
if (length < 0) {
@ -343,17 +358,14 @@ const deserialize = async (middleware, name, readFile) => {
const size = Number(readUInt64LE(slice, 0));
const nameBuffer = slice.slice(8);
const name = nameBuffer.toString();
result.push(
SerializerMiddleware.createLazy(
/** @type {LazyFunction<BufferSerializableType[]>} */
const lazy = SerializerMiddleware.createLazy(
memoize(() => deserialize(middleware, name, readFile)),
middleware,
{
name,
size
},
{ name, size },
slice
)
);
result.push(lazy);
} else {
if (contentPosition === contentItemLength) {
nextContent();
@ -431,7 +443,7 @@ class FileMiddleware extends SerializerMiddleware {
/**
* @param {DeserializedType} data data
* @param {Context} context context object
* @returns {SerializedType | Promise<SerializedType>} serialized data
* @returns {SerializedType | Promise<SerializedType> | null} serialized data
*/
serialize(data, context) {
const { filename, extension = "" } = context;
@ -616,7 +628,7 @@ class FileMiddleware extends SerializerMiddleware {
let currentBuffer;
/** @type {number | undefined} */
let currentBufferUsed;
/** @type {any[]} */
/** @type {Buffer[]} */
const buf = [];
/** @type {import("zlib").Zlib & import("stream").Transform | undefined} */
let decompression;
@ -630,7 +642,12 @@ class FileMiddleware extends SerializerMiddleware {
});
}
if (decompression) {
/** @typedef {(value: Buffer[] | PromiseLike<Buffer[]>) => void} NewResolve */
/** @typedef {(reason?: Error) => void} NewReject */
/** @type {NewResolve | undefined} */
let newResolve;
/** @type {NewReject | undefined} */
let newReject;
resolve(
Promise.all([
@ -638,15 +655,21 @@ class FileMiddleware extends SerializerMiddleware {
newResolve = rs;
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("end", () => resolve());
decompression.on("error", err => reject(err));
})
}
)
]).then(() => buf)
);
resolve = newResolve;
reject = newReject;
resolve = /** @type {NewResolve} */ (newResolve);
reject = /** @type {NewReject} */ (newReject);
}
this.fs.open(file, "r", (err, _fd) => {
if (err) {
@ -696,12 +719,16 @@ class FileMiddleware extends SerializerMiddleware {
remaining -= bytesRead;
if (
currentBufferUsed ===
/** @type {Buffer} */ (currentBuffer).length
/** @type {Buffer} */
(currentBuffer).length
) {
if (decompression) {
decompression.write(currentBuffer);
} else {
buf.push(currentBuffer);
buf.push(
/** @type {Buffer} */
(currentBuffer)
);
}
currentBuffer = undefined;
if (remaining === 0) {

View File

@ -20,7 +20,12 @@ const SetObjectSerializer = require("./SetObjectSerializer");
/** @typedef {import("./types").ComplexSerializableType} ComplexSerializableType */
/** @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 {Context} context context object
* @returns {SerializedType | Promise<SerializedType>} serialized data
* @returns {SerializedType | Promise<SerializedType> | null} serialized data
*/
serialize(data, context) {
/** @type {Item[]} */
@ -785,8 +790,11 @@ class ObjectMiddleware extends SerializerMiddleware {
return item;
} else if (typeof item === "function") {
return SerializerMiddleware.deserializeLazy(
item,
data => this.deserialize(data, context)[0]
/** @type {LazyFunction<SerializedType>} */
(item),
data =>
/** @type {[DeserializedType]} */
(this.deserialize(data, context))[0]
);
} else {
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
* @returns {Promise<any>} result
* @returns {Promise<TODO>} result
*/
serialize(obj, context) {
const ctx = { ...context, ...this.context };
let current = obj;
for (const middleware of this.serializeMiddlewares) {
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) {
try {
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
* @returns {Promise<any>} result
* @returns {Promise<TODO>} result
*/
deserialize(value, context) {
const ctx = { ...context, ...this.context };
/** @type {any} */
let current = value;
for (const middleware of this.deserializeMiddlewares) {
current =
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);
}
return current;

View File

@ -10,8 +10,18 @@ const LAZY_TARGET = Symbol("lazy serialization target");
const LAZY_SERIALIZED_VALUE = Symbol("lazy serialization data");
/** @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
@ -23,7 +33,7 @@ class SerializerMiddleware {
* @abstract
* @param {DeserializedType} data data
* @param {Context} context context object
* @returns {SerializedType | Promise<SerializedType>} serialized data
* @returns {SerializedType | Promise<SerializedType> | null} serialized data
*/
serialize(data, context) {
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 {LazyOptions=} options lazy options
* @param {any=} serializedValue serialized value
* @returns {LazyFn} lazy function
* @returns {LazyFunction<LazyResult>} lazy function
*/
static createLazy(value, target, options = {}, serializedValue = undefined) {
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;
/** @type {any} */ (fn).options = options;
fn.options = options;
fn[LAZY_SERIALIZED_VALUE] = serializedValue;
return fn;
}
/**
* @param {LazyFn} fn lazy function
* @param {EXPECTED_ANY} fn lazy function
* @param {SerializerMiddleware<any, any>=} target target middleware
* @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
*/
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
*/
static getLazySerializedValue(fn) {
@ -88,8 +103,9 @@ class SerializerMiddleware {
}
/**
* @param {LazyFn} fn lazy function
* @param {any} value serialized value
* @template LazyResult
* @param {LazyFunction<LazyResult>} fn lazy function
* @param {TODO} value serialized value
* @returns {void}
*/
static setLazySerializedValue(fn, value) {
@ -97,50 +113,69 @@ class SerializerMiddleware {
}
/**
* @param {LazyFn} lazy lazy function
* @param {function(any): Promise<any> | any} serialize serialize function
* @returns {LazyFn} new lazy
* @template LazyResult, R
* @param {LazyFunction<LazyResult>} lazy lazy function
* @param {function(LazyResult): Promise<R> | R} serialize serialize function
* @returns {LazyFunction<R>} new lazy
*/
static serializeLazy(lazy, serialize) {
const fn = memoize(() => {
const fn = /** @type {LazyFunction<R>} */ (
memoize(() => {
const r = lazy();
if (r && typeof r.then === "function") {
return r.then(data => data && serialize(data));
if (
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];
/** @type {any} */ (fn).options = /** @type {any} */ (lazy).options;
fn.options = lazy.options;
lazy[LAZY_SERIALIZED_VALUE] = fn;
return fn;
}
/**
* @template T
* @param {LazyFn} lazy lazy function
* @param {function(T): Promise<T> | T} deserialize deserialize function
* @returns {function(): Promise<T> | T} new lazy
* @template LazyResult, R
* @param {LazyFunction<LazyResult>} lazy lazy function
* @param {function(LazyResult): Promise<R> | R} deserialize deserialize function
* @returns {LazyFunction<R>} new lazy
*/
static deserializeLazy(lazy, deserialize) {
const fn = memoize(() => {
const fn = /** @type {LazyFunction<R>} */ (
memoize(() => {
const r = lazy();
if (r && typeof r.then === "function") {
return r.then(data => deserialize(data));
if (
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];
/** @type {any} */ (fn).options = /** @type {any} */ (lazy).options;
fn.options = lazy.options;
fn[LAZY_SERIALIZED_VALUE] = lazy;
return fn;
}
/**
* @param {LazyFn} lazy lazy function
* @returns {LazyFn} new lazy
* @template LazyResult
* @param {LazyFunction<LazyResult> | EXPECTED_ANY} lazy lazy function
* @returns {LazyFunction<LazyResult> | EXPECTED_ANY} new lazy
*/
static unMemoizeLazy(lazy) {
if (!SerializerMiddleware.isLazy(lazy)) return lazy;
/** @type {LazyFunction<LazyResult>} */
const fn = () => {
throw new Error(
"A lazy value that has been unmemorized can't be called again"
@ -150,7 +185,7 @@ class SerializerMiddleware {
lazy[LAZY_SERIALIZED_VALUE]
);
fn[LAZY_TARGET] = lazy[LAZY_TARGET];
fn.options = /** @type {any} */ (lazy).options;
fn.options = lazy.options;
return fn;
}
}

View File

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

View File

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

View File

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