refactor(renderer): remove a transposition trap on the lazy-chunk failure path

exhaustedRecoveryFailure ended in two adjacent booleans with opposite
consequences: transposing them would have returned the raw SyntaxError and
silently restored the crash this branch fixes, with no test able to catch it
(the only call site passed true for both). The isChunkFailure parameter saved
one regex scan on a path that only runs after a 10s reload wait, so drop it.

Also evict recordedExhaustionKeys oldest-first instead of clearing wholesale,
matching the breadcrumb and renderer-error key stores the comment cites, so an
overflow cannot re-open the entire set to a repeat burst.
This commit is contained in:
Jinjing
2026-08-06 14:02:23 -07:00
parent d4c32a937d
commit a142828809
+11 -15
View File
@@ -151,19 +151,23 @@ function exhaustedRecoveryFailure(
outcome: string,
// Set when the caller already recorded a vetoed breadcrumb for this outcome;
// the 30-entry ring is the only diagnostic left, so it must not self-evict.
alreadyRecorded = false,
isChunkFailure = isKnownDynamicImportFailure(lastError)
alreadyRecorded = false
): unknown {
if (!isChunkFailure) {
if (!isKnownDynamicImportFailure(lastError)) {
return lastError
}
const failureName = lastError instanceof Error ? lastError.name : 'unknown'
const crumbKey = `${reloadKey}:${outcome}:${failureName}`
if (!alreadyRecorded && !recordedExhaustionKeys.has(crumbKey)) {
// error.name is library-controlled, so bound the set the way the breadcrumb
// and renderer-error key stores do rather than trusting its cardinality.
if (recordedExhaustionKeys.size >= MAX_RECORDED_EXHAUSTION_KEYS) {
recordedExhaustionKeys.clear()
// and renderer-error key stores do: evict oldest-first, never wholesale, so
// an overflow cannot re-open the whole set to a repeat burst.
while (recordedExhaustionKeys.size >= MAX_RECORDED_EXHAUSTION_KEYS) {
const oldestKey = recordedExhaustionKeys.values().next().value
if (oldestKey === undefined) {
break
}
recordedExhaustionKeys.delete(oldestKey)
}
recordedExhaustionKeys.add(crumbKey)
recordReloadBreadcrumb('lazy_chunk_recovery_exhausted', reloadKey, failureMessage, outcome)
@@ -271,7 +275,6 @@ export async function loadLazyWithRetry<T extends AnyComponent>(
// An unrelated failure must not clear a guard it did not set.
throw lastError
}
// Already classified just above; do not re-run the regex set.
// Record the veto beside the resulting report before the ring can evict it.
clearChunkReloadGuard()
recordReloadBreadcrumb(
@@ -280,14 +283,7 @@ export async function loadLazyWithRetry<T extends AnyComponent>(
failureMessage,
'guard-not-landed'
)
throw exhaustedRecoveryFailure(
lastError,
reloadKey,
failureMessage,
'guard-not-landed',
true,
true
)
throw exhaustedRecoveryFailure(lastError, reloadKey, failureMessage, 'guard-not-landed', true)
}
if (reloadGuardState === 'not-attempted') {