Document intentional empty catches, fix one real gap, allow == null in eqeqeq (#44)

ESLint flagged ~20 empty catch blocks and 4 loose-equality comparisons
in assets/js/. Auditing each: all ~19 remaining empty catches are
localStorage/sessionStorage access (persisted tab/theme/column-
visibility state, recent command-palette entries) or the terminal
beep's AudioContext calls — genuinely intentional best-effort UX
affordances that must silently no-op if storage is disabled/full or
audio is blocked, not oversights. One (a viewport-change listener
callback) was a real gap: swallowing an arbitrary caller-supplied
callback's exception could hide a genuine bug, so that one now logs
via console.error instead.

Documented the storage/audio convention once in a file-level comment
rather than repeating the same explanation on ~19 near-identical
one-line try/catches. All 4 flagged loose-equality comparisons turned
out to be `== null`/`!= null` checks — the one loose-equality idiom
that's deliberately safe (catches both null and undefined in one
comparison; ESLint's own eqeqeq rule has a "smart" mode specifically
for this). Converting them to strict equality would have been a
behavior change (no longer catching undefined), not a fix, so switched
.eslintrc.json's eqeqeq rule to "smart" instead — flags every other
loose comparison as before, correctly stops flagging this one safe
idiom.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Lhz7pGMaoTfL5sdYS5XiKv
This commit is contained in:
2026-09-11 15:08:50 -04:00
co-authored by Claude Sonnet 5
parent b6c17096b5
commit e1448d8ea2
2 changed files with 12 additions and 2 deletions
+1 -1
View File
@@ -20,6 +20,6 @@
"no-useless-escape": "warn",
"no-regex-spaces": "warn",
"semi": ["error", "always"],
"eqeqeq": "warn"
"eqeqeq": ["warn", "smart"]
}
}
+11 -1
View File
@@ -41,6 +41,16 @@
* 32. Drag & Drop Upload
* 33. Intersection Observer
* 34. Full Initialisation
*
* NOTE ON EMPTY CATCH BLOCKS: throughout this file, `try { ... } catch (_) {}`
* around localStorage/sessionStorage access (persisted tab/theme/column-
* visibility state, recent command-palette entries, etc.) and the terminal
* beep's AudioContext calls is intentional, not an oversight — these are
* best-effort UX affordances that must silently no-op rather than break the
* surrounding feature if storage is disabled/full (private browsing, quota)
* or audio is blocked (autoplay policy). Swallowing errors from arbitrary
* caller-supplied callbacks (e.g. viewport-change listeners) is handled
* separately with real logging, since those can hide genuine bugs.
*/
(function (global) {
@@ -1398,7 +1408,7 @@
_vpCurrent = bp;
if (bp !== prev) {
const evt = { bp, w, h, prev };
_vpListeners.forEach(cb => { try { cb(evt); } catch (_) {} });
_vpListeners.forEach(cb => { try { cb(evt); } catch (e) { console.error('[lt.viewport] listener threw:', e); } });
bus.emit('viewport:change', evt);
}
}