Replace var with const/let across core/js + scoping fixes#3297
Conversation
…tion - cmd.class.js: hoist eqLogic out of `if (notify)` block (was breaking callbacks at lines 87-172 with ReferenceError) - history.class.js: hoist series out of mutually-exclusive if/else blocks (referenced after the block in addSeries calls and config object) - core.js: declare loop variable `i` in `for (i in _replace)` (was leaking as implicit global) - view.class.js: declare `result` and `option` (were leaking as implicit globals in pre_success and handleViewAjax) - private.class.js: remove dead `const param = null` declaration - desktop/js/log.js: apply PR jeedom#3270 multi-term search refactor with proper const/let usage instead of var Found via ESLint (no-var, prefer-const, no-const-assign) plus targeted audit for var→let/const block-scoping regressions.
Resolved conflict in docs/release-notes.md by taking upstream version (file is auto-generated by .github/workflows/draft-release-notes.yml).
|
Hi, I’m not against revisiting JavaScript variable declarations, but in its current form this PR is almost impossible to review properly without re-reading every single file in full. A large, cross-cutting change that touches ~1400 declarations across 30+ files makes it very hard to be confident there are no subtle regressions, especially around scoping and hoisting. Even with the fixes you listed, it’s not realistic to validate all behavior changes just from the diff. Would it be possible to split this into smaller, focused PRs (for example per module or starting from the concrete bugs you already identified), so that each change set can be reviewed and tested more thoroughly? |
|
I agree with @Salvialf |
|
Thanks @Salvialf and @kwizer15 for the feedback — both points are entirely fair. Context: this work is part of a code optimization effort that has been discussed on and off for a long time (the The 13 bugs documented in the description were discovered along the way — either via ESLint ( Audit: the desktop UI pages have been audited (in part with the help of AI tooling to systematically walk through the critical paths: dashboard, history, scenarios, plugins, views, logs, configuration modals). I'm aware that a hidden regression on a rarely-used path cannot be entirely ruled out — which is precisely why @kwizer15's suggestion on automating ESLint in CI is valuable. Action: splitting as suggested.
Closing this PR in favor of the splits. Thanks for the feedback — it genuinely improves the quality of the contribution. |
Summary
This PR migrates ~1390
vardeclarations toconst/letacross all 33 files incore/js/anddesktop/js/log.js, and fixes 13 bugs identified during the migration via ESLint and runtime testing.Why
varis function-scoped and hoisted, which leaks variables out of intended blocks and creates implicitwindow.Xglobals.const/letare block-scoped and lexically bound, catching reassignment bugs at parse time and avoiding silent global pollution.Discussion in #3270 raised concerns about using outdated
varin new code; this PR addresses the underlying codebase consistently.Bugs found and fixed during migration
Critical (would crash at runtime):
core/js/plugin.template.js—const eqLogicwas reassigned bysaveEqLogic()→ changed toletcore/js/private.class.js—const valuewas reassigned byvalue += ''→ changed toletScoping regressions from
var→const/let(block-scope vs hoisting):core/js/cmd.class.jsjeedom.cmd.execute—eqLogicwas declared insideif (notify) {}but referenced in callbacks at lines 87-172 → hoisted to function scope (would throwReferenceError: eqLogic is not definedon every command execution from dashboard)core/js/history.class.js—serieswas declared in mutually-exclusiveif/elseblocks but referenced after the block inaddSeries()calls → hoisted withletGlobal property collisions (
var Xat top-level was creatingwindow.X):core/js/jeedom.class.js— removedlet Highchartsdeclaration that was shadowingwindow.Highchartsset by highstock.js (causedTypeError: Highcharts.setOptions is undefinedon dashboard load)core/js/private.class.js— renamedconst initto_initto avoidSyntaxError: redeclaration of non-configurable global property init(collides withfunction init()in core.js)Implicit globals (assignment without declaration — pre-existing):
core/js/view.class.js—resultinpre_successandoptioninhandleViewAjaxwere leaking as globalscore/js/core.js—for (i in _replace)was leakingias globalDead code:
core/js/private.class.js— removedconst param = nullthat was never usedMulti-term log search (incorporates #3270):
desktop/js/log.js— applied Improve log search with multi-term and exclusion support #3270 multi-term comma-separated search with properconst/letinstead ofvarValidation
no-var,prefer-const,no-const-assign,no-redeclarerules: 0 errorsTest plan
ReferenceError/TypeErrorin consoleeqLogicscoping)Highchartsshadowing)const eqLogicreassignment):not()works (Improve log search with multi-term and exclusion support #3270 functionality)optionvariable)