* Resolve context timestamp. * @private * @param {ContextFileSystemInfoEntry} entry entry * @param {(err?: WebpackError | null, resolvedContextTimestamp?: ResolvedContextTimestamp) => void} callback callback * @returns {void}
(entry, callback)
| 4001 | * @returns {void} |
| 4002 | */ |
| 4003 | _resolveContextTimestamp(entry, callback) { |
| 4004 | /** @type {string[]} */ |
| 4005 | const hashes = []; |
| 4006 | let safeTime = 0; |
| 4007 | // Skip already-visited symlink targets so cyclic pnpm/peer-variant graphs terminate (#21084). |
| 4008 | const seen = new Set(entry.symlinks); |
| 4009 | processAsyncTree( |
| 4010 | /** @type {NonNullable<ContextHash["symlinks"]>} */ (entry.symlinks), |
| 4011 | 10, |
| 4012 | (target, push, callback) => { |
| 4013 | this._getUnresolvedContextTimestamp(target, (err, entry) => { |
| 4014 | if (err) return callback(err); |
| 4015 | if (entry && entry !== "ignore") { |
| 4016 | hashes.push(/** @type {string} */ (entry.timestampHash)); |
| 4017 | if (entry.safeTime) { |
| 4018 | safeTime = Math.max(safeTime, entry.safeTime); |
| 4019 | } |
| 4020 | if (entry.symlinks !== undefined) { |
| 4021 | for (const target of entry.symlinks) { |
| 4022 | if (!seen.has(target)) { |
| 4023 | seen.add(target); |
| 4024 | push(target); |
| 4025 | } |
| 4026 | } |
| 4027 | } |
| 4028 | } |
| 4029 | callback(); |
| 4030 | }); |
| 4031 | }, |
| 4032 | (err) => { |
| 4033 | if (err) return callback(/** @type {WebpackError} */ (err)); |
| 4034 | const hash = createHash(this._hashFunction); |
| 4035 | hash.update(/** @type {string} */ (entry.timestampHash)); |
| 4036 | if (entry.safeTime) { |
| 4037 | safeTime = Math.max(safeTime, entry.safeTime); |
| 4038 | } |
| 4039 | hashes.sort(); |
| 4040 | for (const h of hashes) { |
| 4041 | hash.update(h); |
| 4042 | } |
| 4043 | callback( |
| 4044 | null, |
| 4045 | (entry.resolved = { |
| 4046 | safeTime, |
| 4047 | timestampHash: hash.digest("hex") |
| 4048 | }) |
| 4049 | ); |
| 4050 | } |
| 4051 | ); |
| 4052 | } |
| 4053 | |
| 4054 | /** |
| 4055 | * @private |
no test coverage detected