fix(cli-demo): make failure rendering total

Contain arbitrary plugin and runtime failures even when a thrown Proxy traps instanceof checks or its string coercion throws. Fall back to a stable diagnostic instead of letting executeCli reject outside its exit-code contract.

Route abort reasons through the same total renderer so cancellation cannot escape containment through an exotic reason value.

Add a focused regression that exercises both hostile inspection paths and verifies stdout remains empty, stderr remains labelled, and the CLI resolves with exit code 1.
This commit is contained in:
Tianyi Cui
2026-07-19 14:32:41 +08:00
parent 1698f0baa6
commit 306dd2b1fe
2 changed files with 38 additions and 2 deletions

View File

@@ -91,12 +91,27 @@ class CliInterruptedError extends Error {
}
}
/** Render an arbitrary value without trusting its type traps or string coercion. */
function renderUnknown(value: unknown): string {
try {
return String(value)
} catch {
return '[unrenderable thrown value]'
}
}
/** Normalize an arbitrary thrown value without letting inspection escape containment. */
function toError(error: unknown): Error {
return error instanceof Error ? error : new Error(String(error))
try {
if (error instanceof Error) return error
} catch {
// A hostile proxy may throw during instanceof; use the total renderer below.
}
return new Error(renderUnknown(error))
}
function interruptionReason(signal: AbortSignal): string {
return signal.reason === undefined ? 'interrupted' : String(signal.reason)
return signal.reason === undefined ? 'interrupted' : renderUnknown(signal.reason)
}
/**