chore: fix types
Github Actions / lint (push) Waiting to run Details
Github Actions / validate-legacy-node (push) Waiting to run Details
Github Actions / benchmark (1/4) (push) Waiting to run Details
Github Actions / benchmark (2/4) (push) Waiting to run Details
Github Actions / benchmark (3/4) (push) Waiting to run Details
Github Actions / benchmark (4/4) (push) Waiting to run Details
Github Actions / basic (push) Waiting to run Details
Github Actions / unit (push) Waiting to run Details
Github Actions / integration (10.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (10.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (10.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (10.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (10.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (10.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (12.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (14.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (16.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (18.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (20.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (20.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (20.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (22.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (22.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (22.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (22.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (22.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (22.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (24.x, macos-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (24.x, macos-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (24.x, ubuntu-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (24.x, ubuntu-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (24.x, windows-latest, a) (push) Blocked by required conditions Details
Github Actions / integration (24.x, windows-latest, b) (push) Blocked by required conditions Details
Github Actions / integration (lts/*, ubuntu-latest, a, 1) (push) Blocked by required conditions Details
Github Actions / integration (lts/*, ubuntu-latest, b, 1) (push) Blocked by required conditions Details

This commit is contained in:
Alexander Akait 2025-07-10 16:30:16 +03:00 committed by GitHub
parent 34df7eec7e
commit fa54eac68b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 143 additions and 82 deletions

View File

@ -572,8 +572,11 @@ class NormalModuleFactory extends ModuleFactory {
/** @type {ModuleSettings} */
const settings = {};
/** @type {LoaderItem[]} */
const useLoadersPost = [];
/** @type {LoaderItem[]} */
const useLoaders = [];
/** @type {LoaderItem[]} */
const useLoadersPre = [];
// handle .webpack[] suffix
@ -632,7 +635,8 @@ class NormalModuleFactory extends ModuleFactory {
typeof r.value === "object" &&
r.value !== null &&
typeof settings[
/** @type {keyof ModuleSettings} */ (r.type)
/** @type {keyof ModuleSettings} */
(r.type)
] === "object" &&
settings[/** @type {keyof ModuleSettings} */ (r.type)] !== null
) {

View File

@ -10,6 +10,7 @@ const { SyncHook } = require("tapable");
/** @typedef {import("../../declarations/WebpackOptions").Falsy} Falsy */
/** @typedef {import("../../declarations/WebpackOptions").RuleSetLoaderOptions} RuleSetLoaderOptions */
/** @typedef {import("../../declarations/WebpackOptions").RuleSetRule} RuleSetRule */
/** @typedef {import("../NormalModule").LoaderItem} LoaderItem */
/** @typedef {(Falsy | RuleSetRule)[]} RuleSetRules */
@ -54,12 +55,22 @@ const { SyncHook } = require("tapable");
* @property {CompiledRule[]=} oneOf
*/
/** @typedef {"use" | "use-pre" | "use-post"} EffectUseType */
/**
* @typedef {object} Effect
* @property {string} type
* @property {TODO} value
* @typedef {object} EffectUse
* @property {EffectUseType} type
* @property {{ loader: string, options?: string | null | Record<string, EXPECTED_ANY>, ident?: string }} value
*/
/**
* @typedef {object} EffectBasic
* @property {string} type
* @property {EXPECTED_ANY} value
*/
/** @typedef {EffectUse | EffectBasic} Effect */
/** @typedef {Map<string, RuleSetLoaderOptions>} References */
/**

View File

@ -16,6 +16,7 @@ const util = require("util");
/** @typedef {import("./RuleSetCompiler")} RuleSetCompiler */
/** @typedef {import("./RuleSetCompiler").Effect} Effect */
/** @typedef {import("./RuleSetCompiler").EffectData} EffectData */
/** @typedef {import("./RuleSetCompiler").EffectUseType} EffectUseType */
const PLUGIN_NAME = "UseEffectRulePlugin";
@ -52,7 +53,9 @@ class UseEffectRulePlugin {
const use = /** @type {RuleSetUse} */ (rule.use);
const enforce = rule.enforce;
const type = enforce ? `use-${enforce}` : "use";
const type =
/** @type {EffectUseType} */
(enforce ? `use-${enforce}` : "use");
/**
* @param {string} path options path
@ -89,7 +92,7 @@ class UseEffectRulePlugin {
}
};
}
const loader = item.loader;
const loader = /** @type {string} */ (item.loader);
const options = item.options;
let ident = item.ident;
if (options && typeof options === "object") {
@ -207,12 +210,15 @@ class UseEffectRulePlugin {
const ident =
options && typeof options === "object" ? path : undefined;
references.set(
/** @type {TODO} */
(ident),
/** @type {RuleSetLoaderOptions} */
(options)
);
if (ident) {
references.set(
ident,
/** @type {RuleSetLoaderOptions} */
(options)
);
}
result.effects.push({
type: enforce ? `use-${enforce}` : "use",
value: {

View File

@ -182,7 +182,7 @@ const AUTO_FOR_TO_STRING = ({ all }, { forToString }) => {
/** @typedef {keyof NormalizedStatsOptions} DefaultsKeys */
/** @typedef {{ [Key in DefaultsKeys]: (options: Partial<NormalizedStatsOptions>, context: CreateStatsOptionsContext, compilation: Compilation) => NormalizedStatsOptions[Key] | RequestShortener }} Defaults */
/** @type {Partial<Defaults>} */
/** @type {Defaults} */
const DEFAULTS = {
context: (options, context, compilation) => compilation.compiler.context,
requestShortener: (options, context, compilation) =>
@ -307,9 +307,9 @@ const normalizeFilter = item => {
};
/** @typedef {keyof (KnownNormalizedStatsOptions | StatsOptions)} NormalizerKeys */
/** @typedef {{ [Key in NormalizerKeys]: (value: StatsOptions[Key]) => KnownNormalizedStatsOptions[Key] }} Normalizers */
/** @typedef {{ [Key in NormalizerKeys]?: (value: StatsOptions[Key]) => KnownNormalizedStatsOptions[Key] }} Normalizers */
/** @type {Partial<Normalizers>} */
/** @type {Normalizers} */
const NORMALIZER = {
excludeModules: value => {
if (!Array.isArray(value)) {
@ -391,18 +391,16 @@ class DefaultStatsPresetPlugin {
compilation.hooks.statsNormalize.tap(PLUGIN_NAME, (options, context) => {
for (const key of Object.keys(DEFAULTS)) {
if (options[key] === undefined) {
options[key] =
/** @type {Defaults[DefaultsKeys]} */
(DEFAULTS[/** @type {DefaultsKeys} */ (key)])(
options,
context,
compilation
);
options[key] = DEFAULTS[/** @type {DefaultsKeys} */ (key)](
options,
context,
compilation
);
}
}
for (const key of Object.keys(NORMALIZER)) {
options[key] =
/** @type {TODO} */
/** @type {NonNullable<Normalizers[keyof Normalizers]>} */
(NORMALIZER[/** @type {NormalizerKeys} */ (key)])(options[key]);
}
});

View File

@ -121,7 +121,8 @@ class StatsFactory {
getItemFactory: new HookMap(() => new SyncBailHook(["item", "context"]))
});
const hooks = this.hooks;
this._caches = /** @type {TODO} */ ({});
this._caches =
/** @type {{ [Key in keyof StatsFactoryHooks]: Map<string, SyncBailHook<EXPECTED_ANY, EXPECTED_ANY>[]> }} */ ({});
for (const key of Object.keys(hooks)) {
this._caches[/** @type {keyof StatsFactoryHooks} */ (key)] = new Map();
}

View File

@ -102,9 +102,7 @@ class StatsPrinter {
print: new HookMap(() => new SyncBailHook(["object", "context"])),
result: new HookMap(() => new SyncWaterfallHook(["result", "context"]))
});
/**
* @type {TODO}
*/
/** @type {Map<StatsPrintHooks[keyof StatsPrintHooks], Map<string, import("tapable").Hook<EXPECTED_ANY, EXPECTED_ANY>[]>>} */
this._levelHookCache = new Map();
this._inPrint = false;
}
@ -126,7 +124,7 @@ class StatsPrinter {
}
const cacheEntry = cache.get(type);
if (cacheEntry !== undefined) {
return cacheEntry;
return /** @type {H[]} */ (cacheEntry);
}
/** @type {H[]} */
const hooks = [];
@ -146,7 +144,7 @@ class StatsPrinter {
* @private
* @template {StatsPrintHooks[keyof StatsPrintHooks]} HM
* @template {HM extends HookMap<infer H> ? H : never} H
* @template {H extends import("tapable").Hook<any, infer R> ? R : never} R
* @template {H extends import("tapable").Hook<EXPECTED_ANY, infer R> ? R : never} R
* @param {HM} hookMap hook map
* @param {string} type type
* @param {(hooK: H) => R | undefined | void} fn fn

View File

@ -85,32 +85,43 @@ const cachedSetProperty = (obj, property, value) => {
};
/**
* @template V
* @typedef {Map<string, V | undefined>} ByValues
* @typedef {Map<string, EXPECTED_ANY>} ByValues
*/
/**
* @template T
* @typedef {object} ObjectParsedPropertyEntry
* @property {TODO | undefined} base base value
* @property {T[keyof T] | undefined} base base value
* @property {string | undefined} byProperty the name of the selector property
* @property {ByValues<TODO>} byValues value depending on selector property, merged with base
* @property {ByValues | undefined} byValues value depending on selector property, merged with base
*/
/** @typedef {(function(...EXPECTED_ANY): object) & { [DYNAMIC_INFO]: [DynamicFunction, object] }} DynamicFunction */
/**
* @typedef {object} ParsedObject
* @property {Map<string, ObjectParsedPropertyEntry>} static static properties (key is property name)
* @property {{ byProperty: string, fn: DynamicFunction } | undefined} dynamic dynamic part
* @template {object} T
* @typedef {Map<keyof T, ObjectParsedPropertyEntry<T>>} ParsedObjectStatic
*/
/** @type {WeakMap<EXPECTED_OBJECT, ParsedObject>} */
/**
* @template {object} T
* @typedef {{ byProperty: string, fn: DynamicFunction }} ParsedObjectDynamic
*/
/**
* @template {object} T
* @typedef {object} ParsedObject
* @property {ParsedObjectStatic<T>} static static properties (key is property name)
* @property {ParsedObjectDynamic<T> | undefined} dynamic dynamic part
*/
/** @type {WeakMap<EXPECTED_OBJECT, ParsedObject<EXPECTED_ANY>>} */
const parseCache = new WeakMap();
/**
* @template {object} T
* @param {T} obj the object
* @returns {ParsedObject} parsed object
* @returns {ParsedObject<T>} parsed object
*/
const cachedParseObject = obj => {
const entry = parseCache.get(/** @type {EXPECTED_OBJECT} */ (obj));
@ -120,18 +131,21 @@ const cachedParseObject = obj => {
return result;
};
/** @typedef {{ [p: string]: { [p: string]: EXPECTED_ANY } } | DynamicFunction} ByObject */
/**
* @template {object} T
* @template V
* @param {T} obj the object
* @returns {ParsedObject} parsed object
* @returns {ParsedObject<T>} parsed object
*/
const parseObject = obj => {
/** @type {ParsedObjectStatic<T>} */
const info = new Map();
/** @type {ParsedObjectDynamic<T> | undefined} */
let dynamicInfo;
/**
* @param {string} p path
* @returns {Partial<ObjectParsedPropertyEntry>} object parsed property entry
* @param {keyof T} p path
* @returns {Partial<ObjectParsedPropertyEntry<T>>} object parsed property entry
*/
const getInfo = p => {
const entry = info.get(p);
@ -144,37 +158,35 @@ const parseObject = obj => {
info.set(p, newEntry);
return newEntry;
};
for (const key of Object.keys(obj)) {
if (key.startsWith("by")) {
const byProperty = /** @type {keyof T} */ (key);
const byObj = /** @type {TODO} */ (obj[byProperty]);
for (const key_ of Object.keys(obj)) {
const key = /** @type {keyof T} */ (key_);
if (typeof key === "string" && key.startsWith("by")) {
const byProperty = key;
const byObj = /** @type {ByObject} */ (obj[byProperty]);
if (typeof byObj === "object") {
for (const byValue of Object.keys(byObj)) {
const obj = byObj[/** @type {keyof (keyof T)} */ (byValue)];
for (const key of Object.keys(obj)) {
const entry = getInfo(key);
const entry = getInfo(/** @type {keyof T} */ (key));
if (entry.byProperty === undefined) {
entry.byProperty = /** @type {string} */ (byProperty);
entry.byProperty = byProperty;
entry.byValues = new Map();
} else if (entry.byProperty !== byProperty) {
throw new Error(
`${/** @type {string} */ (byProperty)} and ${entry.byProperty} for a single property is not supported`
);
}
/** @type {ByValues<V>} */
(entry.byValues).set(
byValue,
obj[/** @type {keyof (keyof T)} */ (key)]
);
/** @type {ByValues} */
(entry.byValues).set(byValue, obj[key]);
if (byValue === "default") {
for (const otherByValue of Object.keys(byObj)) {
if (
!(
/** @type {ByValues<V>} */
/** @type {ByValues} */
(entry.byValues).has(otherByValue)
)
) {
/** @type {ByValues<V>} */
/** @type {ByValues} */
(entry.byValues).set(otherByValue, undefined);
}
}
@ -194,11 +206,11 @@ const parseObject = obj => {
}
} else {
const entry = getInfo(key);
entry.base = obj[/** @type {keyof T} */ (key)];
entry.base = obj[key];
}
} else {
const entry = getInfo(key);
entry.base = obj[/** @type {keyof T} */ (key)];
entry.base = obj[key];
}
}
return {
@ -209,8 +221,8 @@ const parseObject = obj => {
/**
* @template {object} T
* @param {Map<string, ObjectParsedPropertyEntry>} info static properties (key is property name)
* @param {{ byProperty: string, fn: (...args: EXPECTED_ANY[]) => T } | undefined} dynamicInfo dynamic part
* @param {ParsedObjectStatic<T>} info static properties (key is property name)
* @param {{ byProperty: string, fn: DynamicFunction } | undefined} dynamicInfo dynamic part
* @returns {T} the object
*/
const serializeObject = (info, dynamicInfo) => {
@ -221,7 +233,7 @@ const serializeObject = (info, dynamicInfo) => {
const byProperty = /** @type {keyof T} */ (entry.byProperty);
const byObj = (obj[byProperty] =
obj[byProperty] || /** @type {TODO} */ ({}));
for (const byValue of entry.byValues.keys()) {
for (const byValue of /** @type {ByValues} */ (entry.byValues).keys()) {
byObj[byValue] = byObj[byValue] || {};
}
}
@ -236,7 +248,11 @@ const serializeObject = (info, dynamicInfo) => {
const byObj = (obj[byProperty] =
obj[byProperty] || /** @type {TODO} */ ({}));
for (const byValue of Object.keys(byObj)) {
const value = getFromByValues(entry.byValues, byValue);
const value = getFromByValues(
/** @type {ByValues} */
(entry.byValues),
byValue
);
if (value !== undefined) byObj[byValue][key] = value;
}
}
@ -317,7 +333,7 @@ const _cleverMerge = (first, second, internalCaching = false) => {
const fnInfo = fn[DYNAMIC_INFO];
if (fnInfo) {
second =
/** @type {TODO} */
/** @type {O} */
(
internalCaching
? cachedCleverMerge(fnInfo[1], second)
@ -343,10 +359,12 @@ const _cleverMerge = (first, second, internalCaching = false) => {
? cachedParseObject(second)
: parseObject(second);
const { static: secondInfo, dynamic: secondDynamicInfo } = secondObject;
/** @type {Map<string, ObjectParsedPropertyEntry>} */
const resultInfo = new Map();
for (const [key, firstEntry] of firstInfo) {
const secondEntry = secondInfo.get(key);
const secondEntry = secondInfo.get(
/** @type {keyof (T | O)} */
(key)
);
const entry =
secondEntry !== undefined
? mergeEntries(firstEntry, secondEntry, internalCaching)
@ -354,7 +372,7 @@ const _cleverMerge = (first, second, internalCaching = false) => {
resultInfo.set(key, entry);
}
for (const [key, secondEntry] of secondInfo) {
if (!firstInfo.has(key)) {
if (!firstInfo.has(/** @type {keyof (T | O)} */ (key))) {
resultInfo.set(key, secondEntry);
}
}
@ -362,10 +380,11 @@ const _cleverMerge = (first, second, internalCaching = false) => {
};
/**
* @param {ObjectParsedPropertyEntry} firstEntry a
* @param {ObjectParsedPropertyEntry} secondEntry b
* @template T, O
* @param {ObjectParsedPropertyEntry<T>} firstEntry a
* @param {ObjectParsedPropertyEntry<O>} secondEntry b
* @param {boolean} internalCaching should parsing of objects and nested merges be cached
* @returns {ObjectParsedPropertyEntry} new entry
* @returns {ObjectParsedPropertyEntry<TODO>} new entry
*/
const mergeEntries = (firstEntry, secondEntry, internalCaching) => {
switch (getValueType(secondEntry.base)) {
@ -391,8 +410,14 @@ const mergeEntries = (firstEntry, secondEntry, internalCaching) => {
// = first.base + (first.byProperty + second.byProperty)
// need to merge first and second byValues
const newByValues = new Map(firstEntry.byValues);
for (const [key, value] of secondEntry.byValues) {
const firstValue = getFromByValues(firstEntry.byValues, key);
for (const [key, value] of /** @type {ByValues} */ (
secondEntry.byValues
)) {
const firstValue = getFromByValues(
/** @type {ByValues} */
(firstEntry.byValues),
key
);
newByValues.set(
key,
mergeSingleValue(firstValue, value, internalCaching)
@ -409,11 +434,15 @@ const mergeEntries = (firstEntry, secondEntry, internalCaching) => {
// The simple case
// = (first.base + second.base) + second.byProperty
return {
base: mergeSingleValue(
firstEntry.base,
secondEntry.base,
internalCaching
),
base:
/** @type {T[keyof T] & O[keyof O]} */
(
mergeSingleValue(
firstEntry.base,
secondEntry.base,
internalCaching
)
),
byProperty: secondEntry.byProperty,
byValues: secondEntry.byValues
};
@ -427,10 +456,12 @@ const mergeEntries = (firstEntry, secondEntry, internalCaching) => {
);
}
if (
[...firstEntry.byValues.values()].every(value => {
const type = getValueType(value);
return type === VALUE_TYPE_ATOM || type === VALUE_TYPE_DELETE;
})
[.../** @type {ByValues} */ (firstEntry.byValues).values()].every(
value => {
const type = getValueType(value);
return type === VALUE_TYPE_ATOM || type === VALUE_TYPE_DELETE;
}
)
) {
// = (first.base + second.base) + ((first.byProperty + second.base) + second.byProperty)
newBase = mergeSingleValue(
@ -458,7 +489,9 @@ const mergeEntries = (firstEntry, secondEntry, internalCaching) => {
);
}
const newByValues = new Map(intermediateByValues);
for (const [key, value] of secondEntry.byValues) {
for (const [key, value] of /** @type {ByValues} */ (
secondEntry.byValues
)) {
const firstValue = getFromByValues(intermediateByValues, key);
newByValues.set(
key,
@ -476,7 +509,7 @@ const mergeEntries = (firstEntry, secondEntry, internalCaching) => {
/**
* @template V
* @param {ByValues<V>} byValues all values
* @param {ByValues} byValues all values
* @param {string} key value of the selector
* @returns {V | undefined} value
*/

12
types.d.ts vendored
View File

@ -4158,7 +4158,8 @@ declare class DynamicEntryPlugin {
*/
apply(compiler: Compiler): void;
}
declare interface Effect {
type Effect = EffectUse | EffectBasic;
declare interface EffectBasic {
type: string;
value: any;
}
@ -4176,6 +4177,15 @@ declare interface EffectData {
issuer: string;
issuerLayer: string;
}
declare interface EffectUse {
type: EffectUseType;
value: {
loader: string;
options?: null | string | Record<string, any>;
ident?: string;
};
}
type EffectUseType = "use" | "use-pre" | "use-post";
declare class ElectronTargetPlugin {
constructor(context?: "main" | "preload" | "renderer");