feat: refactoring project
This commit is contained in:
445
node_modules/webpack/lib/cache/ResolverCachePlugin.js
generated
vendored
445
node_modules/webpack/lib/cache/ResolverCachePlugin.js
generated
vendored
@@ -8,23 +8,45 @@
|
||||
const LazySet = require("../util/LazySet");
|
||||
const makeSerializable = require("../util/makeSerializable");
|
||||
|
||||
/** @typedef {import("enhanced-resolve").ResolveContext} ResolveContext */
|
||||
/** @typedef {import("enhanced-resolve").ResolveOptions} ResolveOptions */
|
||||
/** @typedef {import("enhanced-resolve").ResolveRequest} ResolveRequest */
|
||||
/** @typedef {import("enhanced-resolve").Resolver} Resolver */
|
||||
/** @typedef {import("../CacheFacade").ItemCacheFacade} ItemCacheFacade */
|
||||
/** @typedef {import("../Compiler")} Compiler */
|
||||
/** @typedef {import("../FileSystemInfo")} FileSystemInfo */
|
||||
/** @typedef {import("../FileSystemInfo").Snapshot} Snapshot */
|
||||
/** @typedef {import("../FileSystemInfo").SnapshotOptions} SnapshotOptions */
|
||||
/** @typedef {import("../ResolverFactory").ResolveOptionsWithDependencyType} ResolveOptionsWithDependencyType */
|
||||
/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
|
||||
/** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {import("tapable").SyncHook<T>} SyncHook
|
||||
*/
|
||||
|
||||
class CacheEntry {
|
||||
/**
|
||||
* @param {ResolveRequest} result result
|
||||
* @param {Snapshot} snapshot snapshot
|
||||
*/
|
||||
constructor(result, snapshot) {
|
||||
this.result = result;
|
||||
this.snapshot = snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ObjectSerializerContext} context context
|
||||
*/
|
||||
serialize({ write }) {
|
||||
write(this.result);
|
||||
write(this.snapshot);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ObjectDeserializerContext} context context
|
||||
*/
|
||||
deserialize({ read }) {
|
||||
this.result = read();
|
||||
this.snapshot = read();
|
||||
@@ -36,7 +58,7 @@ makeSerializable(CacheEntry, "webpack/lib/cache/ResolverCachePlugin");
|
||||
/**
|
||||
* @template T
|
||||
* @param {Set<T> | LazySet<T>} set set to add items to
|
||||
* @param {Set<T> | LazySet<T>} otherSet set to add items from
|
||||
* @param {Set<T> | LazySet<T> | Iterable<T>} otherSet set to add items from
|
||||
* @returns {void}
|
||||
*/
|
||||
const addAllToSet = (set, otherSet) => {
|
||||
@@ -50,7 +72,8 @@ const addAllToSet = (set, otherSet) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {object} object an object
|
||||
* @template {object} T
|
||||
* @param {T} object an object
|
||||
* @param {boolean} excludeContext if true, context is not included in string
|
||||
* @returns {string} stringified version
|
||||
*/
|
||||
@@ -59,11 +82,10 @@ const objectToString = (object, excludeContext) => {
|
||||
for (const key in object) {
|
||||
if (excludeContext && key === "context") continue;
|
||||
const value = object[key];
|
||||
if (typeof value === "object" && value !== null) {
|
||||
str += `|${key}=[${objectToString(value, false)}|]`;
|
||||
} else {
|
||||
str += `|${key}=|${value}`;
|
||||
}
|
||||
str +=
|
||||
typeof value === "object" && value !== null
|
||||
? `|${key}=[${objectToString(value, false)}|]`
|
||||
: `|${key}=|${value}`;
|
||||
}
|
||||
return str;
|
||||
};
|
||||
@@ -78,6 +100,7 @@ class ResolverCachePlugin {
|
||||
const cache = compiler.getCache("ResolverCachePlugin");
|
||||
/** @type {FileSystemInfo} */
|
||||
let fileSystemInfo;
|
||||
/** @type {SnapshotOptions | undefined} */
|
||||
let snapshotOptions;
|
||||
let realResolves = 0;
|
||||
let cachedResolves = 0;
|
||||
@@ -101,12 +124,16 @@ class ResolverCachePlugin {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/** @typedef {function((Error | null)=, ResolveRequest=): void} Callback */
|
||||
/** @typedef {ResolveRequest & { _ResolverCachePluginCacheMiss: true }} ResolveRequestWithCacheMiss */
|
||||
|
||||
/**
|
||||
* @param {ItemCacheFacade} itemCache cache
|
||||
* @param {Resolver} resolver the resolver
|
||||
* @param {object} resolveContext context for resolving meta info
|
||||
* @param {object} request the request info object
|
||||
* @param {function((Error | null)=, object=): void} callback callback function
|
||||
* @param {ResolveContext} resolveContext context for resolving meta info
|
||||
* @param {ResolveRequest} request the request info object
|
||||
* @param {Callback} callback callback function
|
||||
* @returns {void}
|
||||
*/
|
||||
const doRealResolve = (
|
||||
@@ -117,10 +144,13 @@ class ResolverCachePlugin {
|
||||
callback
|
||||
) => {
|
||||
realResolves++;
|
||||
const newRequest = {
|
||||
_ResolverCachePluginCacheMiss: true,
|
||||
...request
|
||||
};
|
||||
const newRequest =
|
||||
/** @type {ResolveRequestWithCacheMiss} */
|
||||
({
|
||||
_ResolverCachePluginCacheMiss: true,
|
||||
...request
|
||||
});
|
||||
/** @type {ResolveContext} */
|
||||
const newResolveContext = {
|
||||
...resolveContext,
|
||||
stack: new Set(),
|
||||
@@ -131,16 +161,25 @@ class ResolverCachePlugin {
|
||||
/** @type {LazySet<string>} */
|
||||
contextDependencies: new LazySet()
|
||||
};
|
||||
/** @type {ResolveRequest[] | undefined} */
|
||||
let yieldResult;
|
||||
let withYield = false;
|
||||
if (typeof newResolveContext.yield === "function") {
|
||||
yieldResult = [];
|
||||
withYield = true;
|
||||
newResolveContext.yield = obj => yieldResult.push(obj);
|
||||
newResolveContext.yield = obj =>
|
||||
/** @type {ResolveRequest[]} */
|
||||
(yieldResult).push(obj);
|
||||
}
|
||||
/**
|
||||
* @param {"fileDependencies" | "contextDependencies" | "missingDependencies"} key key
|
||||
*/
|
||||
const propagate = key => {
|
||||
if (resolveContext[key]) {
|
||||
addAllToSet(resolveContext[key], newResolveContext[key]);
|
||||
addAllToSet(
|
||||
/** @type {Set<string>} */ (resolveContext[key]),
|
||||
/** @type {Set<string>} */ (newResolveContext[key])
|
||||
);
|
||||
}
|
||||
};
|
||||
const resolveTime = Date.now();
|
||||
@@ -159,25 +198,43 @@ class ResolverCachePlugin {
|
||||
const missingDependencies = newResolveContext.missingDependencies;
|
||||
fileSystemInfo.createSnapshot(
|
||||
resolveTime,
|
||||
fileDependencies,
|
||||
contextDependencies,
|
||||
missingDependencies,
|
||||
/** @type {Set<string>} */
|
||||
(fileDependencies),
|
||||
/** @type {Set<string>} */
|
||||
(contextDependencies),
|
||||
/** @type {Set<string>} */
|
||||
(missingDependencies),
|
||||
snapshotOptions,
|
||||
(err, snapshot) => {
|
||||
if (err) return callback(err);
|
||||
const resolveResult = withYield ? yieldResult : result;
|
||||
// since we intercept resolve hook
|
||||
// we still can get result in callback
|
||||
if (withYield && result) yieldResult.push(result);
|
||||
if (withYield && result)
|
||||
/** @type {ResolveRequest[]} */ (yieldResult).push(result);
|
||||
if (!snapshot) {
|
||||
if (resolveResult) return callback(null, resolveResult);
|
||||
if (resolveResult)
|
||||
return callback(
|
||||
null,
|
||||
/** @type {ResolveRequest} */
|
||||
(resolveResult)
|
||||
);
|
||||
return callback();
|
||||
}
|
||||
itemCache.store(
|
||||
new CacheEntry(resolveResult, snapshot),
|
||||
new CacheEntry(
|
||||
/** @type {ResolveRequest} */
|
||||
(resolveResult),
|
||||
snapshot
|
||||
),
|
||||
storeErr => {
|
||||
if (storeErr) return callback(storeErr);
|
||||
if (resolveResult) return callback(null, resolveResult);
|
||||
if (resolveResult)
|
||||
return callback(
|
||||
null,
|
||||
/** @type {ResolveRequest} */
|
||||
(resolveResult)
|
||||
);
|
||||
callback();
|
||||
}
|
||||
);
|
||||
@@ -188,174 +245,192 @@ class ResolverCachePlugin {
|
||||
};
|
||||
compiler.resolverFactory.hooks.resolver.intercept({
|
||||
factory(type, hook) {
|
||||
/** @type {Map<string, (function(Error=, object=): void)[]>} */
|
||||
/** @type {Map<string, (function(Error=, ResolveRequest=): void)[]>} */
|
||||
const activeRequests = new Map();
|
||||
/** @type {Map<string, [function(Error=, object=): void, function(Error=, object=): void][]>} */
|
||||
/** @type {Map<string, [function(Error=, ResolveRequest=): void, NonNullable<ResolveContext["yield"]>][]>} */
|
||||
const activeRequestsWithYield = new Map();
|
||||
hook.tap(
|
||||
"ResolverCachePlugin",
|
||||
/**
|
||||
* @param {Resolver} resolver the resolver
|
||||
* @param {object} options resolve options
|
||||
* @param {object} userOptions resolve options passed by the user
|
||||
* @returns {void}
|
||||
*/
|
||||
(resolver, options, userOptions) => {
|
||||
if (options.cache !== true) return;
|
||||
const optionsIdent = objectToString(userOptions, false);
|
||||
const cacheWithContext =
|
||||
options.cacheWithContext !== undefined
|
||||
? options.cacheWithContext
|
||||
: false;
|
||||
resolver.hooks.resolve.tapAsync(
|
||||
{
|
||||
name: "ResolverCachePlugin",
|
||||
stage: -100
|
||||
},
|
||||
(request, resolveContext, callback) => {
|
||||
if (
|
||||
/** @type {TODO} */ (request)._ResolverCachePluginCacheMiss ||
|
||||
!fileSystemInfo
|
||||
) {
|
||||
return callback();
|
||||
}
|
||||
const withYield = typeof resolveContext.yield === "function";
|
||||
const identifier = `${type}${
|
||||
withYield ? "|yield" : "|default"
|
||||
}${optionsIdent}${objectToString(request, !cacheWithContext)}`;
|
||||
/** @type {SyncHook<[Resolver, ResolveOptions, ResolveOptionsWithDependencyType]>} */
|
||||
(hook).tap("ResolverCachePlugin", (resolver, options, userOptions) => {
|
||||
if (/** @type {TODO} */ (options).cache !== true) return;
|
||||
const optionsIdent = objectToString(userOptions, false);
|
||||
const cacheWithContext =
|
||||
options.cacheWithContext !== undefined
|
||||
? options.cacheWithContext
|
||||
: false;
|
||||
resolver.hooks.resolve.tapAsync(
|
||||
{
|
||||
name: "ResolverCachePlugin",
|
||||
stage: -100
|
||||
},
|
||||
(request, resolveContext, callback) => {
|
||||
if (
|
||||
/** @type {ResolveRequestWithCacheMiss} */
|
||||
(request)._ResolverCachePluginCacheMiss ||
|
||||
!fileSystemInfo
|
||||
) {
|
||||
return callback();
|
||||
}
|
||||
const withYield = typeof resolveContext.yield === "function";
|
||||
const identifier = `${type}${
|
||||
withYield ? "|yield" : "|default"
|
||||
}${optionsIdent}${objectToString(request, !cacheWithContext)}`;
|
||||
|
||||
if (withYield) {
|
||||
const activeRequest = activeRequestsWithYield.get(identifier);
|
||||
if (activeRequest) {
|
||||
activeRequest[0].push(callback);
|
||||
activeRequest[1].push(
|
||||
/** @type {TODO} */ (resolveContext.yield)
|
||||
);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
const activeRequest = activeRequests.get(identifier);
|
||||
if (activeRequest) {
|
||||
activeRequest.push(callback);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const itemCache = cache.getItemCache(identifier, null);
|
||||
let callbacks, yields;
|
||||
const done = withYield
|
||||
? (err, result) => {
|
||||
if (callbacks === undefined) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
if (result)
|
||||
for (const r of result) resolveContext.yield(r);
|
||||
callback(null, null);
|
||||
}
|
||||
yields = undefined;
|
||||
callbacks = false;
|
||||
} else {
|
||||
if (err) {
|
||||
for (const cb of callbacks) cb(err);
|
||||
} else {
|
||||
for (let i = 0; i < callbacks.length; i++) {
|
||||
const cb = callbacks[i];
|
||||
const yield_ = yields[i];
|
||||
if (result) for (const r of result) yield_(r);
|
||||
cb(null, null);
|
||||
}
|
||||
}
|
||||
activeRequestsWithYield.delete(identifier);
|
||||
yields = undefined;
|
||||
callbacks = false;
|
||||
}
|
||||
}
|
||||
: (err, result) => {
|
||||
if (callbacks === undefined) {
|
||||
callback(err, result);
|
||||
callbacks = false;
|
||||
} else {
|
||||
for (const callback of callbacks) {
|
||||
callback(err, result);
|
||||
}
|
||||
activeRequests.delete(identifier);
|
||||
callbacks = false;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @param {Error=} err error if any
|
||||
* @param {CacheEntry=} cacheEntry cache entry
|
||||
* @returns {void}
|
||||
*/
|
||||
const processCacheResult = (err, cacheEntry) => {
|
||||
if (err) return done(err);
|
||||
|
||||
if (cacheEntry) {
|
||||
const { snapshot, result } = cacheEntry;
|
||||
fileSystemInfo.checkSnapshotValid(
|
||||
snapshot,
|
||||
(err, valid) => {
|
||||
if (err || !valid) {
|
||||
cacheInvalidResolves++;
|
||||
return doRealResolve(
|
||||
itemCache,
|
||||
resolver,
|
||||
resolveContext,
|
||||
request,
|
||||
done
|
||||
);
|
||||
}
|
||||
cachedResolves++;
|
||||
if (resolveContext.missingDependencies) {
|
||||
addAllToSet(
|
||||
/** @type {LazySet<string>} */
|
||||
(resolveContext.missingDependencies),
|
||||
snapshot.getMissingIterable()
|
||||
);
|
||||
}
|
||||
if (resolveContext.fileDependencies) {
|
||||
addAllToSet(
|
||||
/** @type {LazySet<string>} */
|
||||
(resolveContext.fileDependencies),
|
||||
snapshot.getFileIterable()
|
||||
);
|
||||
}
|
||||
if (resolveContext.contextDependencies) {
|
||||
addAllToSet(
|
||||
/** @type {LazySet<string>} */
|
||||
(resolveContext.contextDependencies),
|
||||
snapshot.getContextIterable()
|
||||
);
|
||||
}
|
||||
done(null, result);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
doRealResolve(
|
||||
itemCache,
|
||||
resolver,
|
||||
resolveContext,
|
||||
request,
|
||||
done
|
||||
);
|
||||
}
|
||||
};
|
||||
itemCache.get(processCacheResult);
|
||||
if (withYield && callbacks === undefined) {
|
||||
callbacks = [callback];
|
||||
yields = [resolveContext.yield];
|
||||
activeRequestsWithYield.set(
|
||||
identifier,
|
||||
/** @type {[any, any]} */ ([callbacks, yields])
|
||||
if (withYield) {
|
||||
const activeRequest = activeRequestsWithYield.get(identifier);
|
||||
if (activeRequest) {
|
||||
activeRequest[0].push(callback);
|
||||
activeRequest[1].push(
|
||||
/** @type {NonNullable<ResolveContext["yield"]>} */
|
||||
(resolveContext.yield)
|
||||
);
|
||||
} else if (callbacks === undefined) {
|
||||
callbacks = [callback];
|
||||
activeRequests.set(identifier, callbacks);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
const activeRequest = activeRequests.get(identifier);
|
||||
if (activeRequest) {
|
||||
activeRequest.push(callback);
|
||||
return;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
const itemCache = cache.getItemCache(identifier, null);
|
||||
/** @type {Callback[] | false | undefined} */
|
||||
let callbacks;
|
||||
/** @type {NonNullable<ResolveContext["yield"]>[] | undefined} */
|
||||
let yields;
|
||||
|
||||
/**
|
||||
* @type {function((Error | null)=, ResolveRequest | ResolveRequest[]=): void}
|
||||
*/
|
||||
const done = withYield
|
||||
? (err, result) => {
|
||||
if (callbacks === undefined) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
if (result)
|
||||
for (const r of /** @type {ResolveRequest[]} */ (
|
||||
result
|
||||
)) {
|
||||
/** @type {NonNullable<ResolveContext["yield"]>} */
|
||||
(resolveContext.yield)(r);
|
||||
}
|
||||
callback(null, null);
|
||||
}
|
||||
yields = undefined;
|
||||
callbacks = false;
|
||||
} else {
|
||||
const definedCallbacks =
|
||||
/** @type {Callback[]} */
|
||||
(callbacks);
|
||||
|
||||
if (err) {
|
||||
for (const cb of definedCallbacks) cb(err);
|
||||
} else {
|
||||
for (let i = 0; i < definedCallbacks.length; i++) {
|
||||
const cb = definedCallbacks[i];
|
||||
const yield_ =
|
||||
/** @type {NonNullable<ResolveContext["yield"]>[]} */
|
||||
(yields)[i];
|
||||
if (result)
|
||||
for (const r of /** @type {ResolveRequest[]} */ (
|
||||
result
|
||||
))
|
||||
yield_(r);
|
||||
cb(null, null);
|
||||
}
|
||||
}
|
||||
activeRequestsWithYield.delete(identifier);
|
||||
yields = undefined;
|
||||
callbacks = false;
|
||||
}
|
||||
}
|
||||
: (err, result) => {
|
||||
if (callbacks === undefined) {
|
||||
callback(err, /** @type {ResolveRequest} */ (result));
|
||||
callbacks = false;
|
||||
} else {
|
||||
for (const callback of /** @type {Callback[]} */ (
|
||||
callbacks
|
||||
)) {
|
||||
callback(err, /** @type {ResolveRequest} */ (result));
|
||||
}
|
||||
activeRequests.delete(identifier);
|
||||
callbacks = false;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @param {(Error | null)=} err error if any
|
||||
* @param {(CacheEntry | null)=} cacheEntry cache entry
|
||||
* @returns {void}
|
||||
*/
|
||||
const processCacheResult = (err, cacheEntry) => {
|
||||
if (err) return done(err);
|
||||
|
||||
if (cacheEntry) {
|
||||
const { snapshot, result } = cacheEntry;
|
||||
fileSystemInfo.checkSnapshotValid(snapshot, (err, valid) => {
|
||||
if (err || !valid) {
|
||||
cacheInvalidResolves++;
|
||||
return doRealResolve(
|
||||
itemCache,
|
||||
resolver,
|
||||
resolveContext,
|
||||
request,
|
||||
done
|
||||
);
|
||||
}
|
||||
cachedResolves++;
|
||||
if (resolveContext.missingDependencies) {
|
||||
addAllToSet(
|
||||
/** @type {Set<string>} */
|
||||
(resolveContext.missingDependencies),
|
||||
snapshot.getMissingIterable()
|
||||
);
|
||||
}
|
||||
if (resolveContext.fileDependencies) {
|
||||
addAllToSet(
|
||||
/** @type {Set<string>} */
|
||||
(resolveContext.fileDependencies),
|
||||
snapshot.getFileIterable()
|
||||
);
|
||||
}
|
||||
if (resolveContext.contextDependencies) {
|
||||
addAllToSet(
|
||||
/** @type {Set<string>} */
|
||||
(resolveContext.contextDependencies),
|
||||
snapshot.getContextIterable()
|
||||
);
|
||||
}
|
||||
done(null, result);
|
||||
});
|
||||
} else {
|
||||
doRealResolve(
|
||||
itemCache,
|
||||
resolver,
|
||||
resolveContext,
|
||||
request,
|
||||
done
|
||||
);
|
||||
}
|
||||
};
|
||||
itemCache.get(processCacheResult);
|
||||
if (withYield && callbacks === undefined) {
|
||||
callbacks = [callback];
|
||||
yields = [
|
||||
/** @type {NonNullable<ResolveContext["yield"]>} */
|
||||
(resolveContext.yield)
|
||||
];
|
||||
activeRequestsWithYield.set(
|
||||
identifier,
|
||||
/** @type {[any, any]} */ ([callbacks, yields])
|
||||
);
|
||||
} else if (callbacks === undefined) {
|
||||
callbacks = [callback];
|
||||
activeRequests.set(identifier, callbacks);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
return hook;
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user