Default to the cheapest behavior: gate expensive work behind explicit options or conditions, and keep the parsing “fast path” strictly minimal.
Practical rules:
try/catch/throw for normal control flow).Set vs double-loop depends on duplicate rates).Example pattern (non-throwing, avoid eager ctx/allocation):
_parse(input: ParseInput) {
const status = getStatus();
// Fast path: keep ctx/allocations out unless needed
if (/* invalid condition */) {
const ctx = this._getOrReturnCtx(input); // create only now
addIssueToContext(ctx, { code: '...' });
status.dirty();
return status;
}
// No try/catch/throw in normal flow
return status;
}
Before/after any performance-sensitive change, run benchmarks or flamegraphs on realistic workloads (include the operations that trigger JIT/fast-pass warmup if relevant).
Enter the URL of a public GitHub repository