refactor(highway): lift 79 per-instance closure vars into hwState (R3c H lift)#849
Conversation
…R3c H lift) Collapses createHighway()'s 79 mutable closure `let`s into one per-instance `hwState` object. Scope-resolved rewrite via acorn + eslint-scope: 1059 edits (1057 references + 79 defs - the deleted `let canvas, ctx, ws`), with the four names shadowed in inner scopes (chartTime/ctx/notes/chordTemplates) resolved correctly so only closure-bound refs move. Enables the later module split: extracted renderer/ws modules close over `hwState` as a factory arg, so multi-panel plugins (highway_3d, note_detect, splitscreen) don't share one highway's state. Container is `hwState`, NOT `H` — `H` is already canvas height (70 uses). The frame-time gate caught that collision instantly (0 draws, `H._drawHooks is not iterable` in the shared draw-hook path). PERF (the whole risk): identical to the pre-lift baseline. Draw p50 2.1-2.2 ms, p95 2.7-3.0 ms (pre-lift 2.7-3.2), measured on the Arcturus feedpak, headless. Each closure-slot read became a `hwState.<slot>` monomorphic property load; the hot loop pays nothing. On-device: Byron confirmed the 2D highway plays smoothly. Tests: the ~30 highway JS suites brace-extract functions/patterns from the source; their state references + the monotonic-clock vm sandbox now use `hwState.<slot>` (the const _CHART_MAX_INTERP_MS etc. stay top-level, not lifted). node --test: 1030/1030 green. Two self-inflicted over-replacements caught and reverted (`_lefty` is a prefix of the 3D-local `_leftyCached`; `STRING_COLORS` a suffix of `DEFAULT_STRING_COLORS`) — substring replaces on the brace-extract regexes need word care. Transformer saved at ~/.local/share/feedback-editor/highway-h-lift.mjs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthrough
ChangesHighway state refactor
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant WebSocket
participant JUCE routing
participant hwState
participant Renderer
WebSocket->>JUCE routing: route incoming message
JUCE routing->>hwState: update song and connection state
hwState->>hwState: validate connection generation and message chain
hwState->>Renderer: expose updated bundle and readiness
Renderer->>hwState: read timing, canvas, and filtered data
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@static/highway.js`:
- Line 1501: static/highway.js exceeds the repository’s max-lines limit and must
be reduced below 1500 lines. Extract cohesive functionality—starting with
drawing primitives and chord-cache helpers such as drawNote, drawSustains,
drawChords, and drawLyrics—into modules whose factories accept hwState and
required helpers, then update highway.js imports and call sites while preserving
behavior.
In `@tests/js/highway_note_state.test.js`:
- Line 42: Update the setter assertion in the test to require assignment
specifically to hwState._noteStateProvider, rather than any unqualified
_noteStateProvider. Adjust the regex for setNoteStateProvider so it matches the
hwState-qualified property assignment and continues verifying the setter
behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f13af998-b59f-4ffd-8ce7-1723726f1b9a
📒 Files selected for processing (15)
static/highway.jstests/js/beats_loaded.test.jstests/js/handshapes_pipeline.test.jstests/js/highway_3d_lefty.test.jstests/js/highway_3d_smooth_clock_pause.test.jstests/js/highway_adaptive_scale.test.jstests/js/highway_chord_render_cache.test.jstests/js/highway_filtered_notes.test.jstests/js/highway_monotonic_clock.test.jstests/js/highway_note_state.test.jstests/js/highway_pause_throttle.test.jstests/js/highway_phrases.test.jstests/js/highway_renderer_swap_canvas_reset.test.jstests/js/highway_string_colors.test.jstests/js/highway_visibility.test.js
…eStateProvider (CodeRabbit) The [^}]* form matched an unqualified _noteStateProvider =, so a regression to closure-level state could still pass. Require the hwState-qualified assignment.
|
On the two threads: max-lines (4224 vs 1500) — expected and tracked. note_state:42 — fixed in |
The
H-container lift — the enabler for splittinghighway.js. CollapsescreateHighway()'s 79 mutable closurelets into one per-instancehwStateobject, so extracted renderer/ws modules can later close overhwStateas a factory argument without multi-panel plugins (highway_3d,note_detect, splitscreen) sharing one highway's state.Depends conceptually on the frame-time gate in #848 (the
--songharness mode); functionally independent.The transform
Scope-resolved rewrite via acorn + eslint-scope (not regex — that would corrupt the 4 shadowed names): 1059 edits, 1057 references + 79 declaration ids − the deleted
let canvas, ctx, ws. The four names shadowed in inner scopes (chartTime,ctx,notes,chordTemplates) are resolved correctly, so only closure-bound references move. Verified: re-parses, 0 leftover mutable closure vars, and the added lines are allhwState.(plus 2 comment lines).Container is
hwState, notH—His already the canvas-height local (70 uses). The frame gate caught the collision instantly (0 draws,H._drawHooks is not iterablein the shared draw-hook path).Perf — the whole risk — holds
Frame-time gate (
docs/perf-baseline.md), Arcturus feedpak, headless:Each closure-slot read became a
hwState.<slot>monomorphic property load on a stable-shape object; the 60fps loop pays nothing. On-device: Byron confirmed the 2D highway plays smoothly.Tests
The ~30 highway JS suites brace-extract functions/patterns from the source; their state references and the
monotonic_clockvm sandbox now usehwState.<slot>(consts like_CHART_MAX_INTERP_MSstay top-level — not lifted).node --test: 1030/1030 green. Two self-inflicted over-replacements caught and reverted along the way (_leftyis a prefix of the 3D-local_leftyCached;STRING_COLORSa suffix ofDEFAULT_STRING_COLORS) — substring replaces on brace-extract regexes need word care.npm run lint0 errors; Codex 0 findings. Transformer saved for reproducibility.Next (R3c cont.): with
hwStatein place, the renderer/ws/geometry modules can be extracted ascreateRenderer2d(hwState)etc.🤖 Generated with Claude Code
Summary by CodeRabbit