refactor(editor): extract the note/chord pure tier to src/notes.js (R2, step 6) - #150
Conversation
…2, step 6) src/main.js 20,763 -> 20,601. notes.js holds the active-arrangement accessors notes()/chords() — 204 and 35 call sites, none of which needed changing — plus the pure arithmetic over them: chord-aware sustain resizing, bend-curve authoring, and the teaching-mark options. Reads S; no DOM, no undo history. Graph stays acyclic: notes -> state. main.js's whole diff is the deletions plus the import block. Tests: four more suites stop slicing @pure blocks out of source text. chord_resize, bend_shape and teaching_marks become plain real-import tests. roll_edge_resize becomes a hybrid — it still slices the edit-history block and the ResizeSustainCmd/ResizeSustainGroupCmd classes that stay in main.js (they already take `notes` as an injected sandbox param, so they were unaffected), but imports the resize arithmetic. New tests/notes.test.mjs pins what the pure-fn suites never touched: the accessors' empty-arrangement guard (200+ call sites iterate the result directly, including on the entry screen with nothing loaded) and that they hand back the live array rather than a copy. SCOPE NOTE: @pure:chord-relink, reconstructChords, flattenChords and the handshape normalizers deliberately stay in main.js. flattenChords needs _normChordFn from inside the chord-relink block, and reconstructChords is entangled with S.history — but the blocker is the tests: chord_relink, handshape_authoring and suggest_position_wiring concatenate that block's SOURCE into a sandbox and drive it against a fabricated `S`. A real import would close over the actual S from state.js and bypass their fixtures, so those three need a genuine rework. That is its own step, not a rider on this one. Verified: node --test 85/85, pytest 248/248. main.js diff mechanically checked to be deletions + the import block, nothing else. No unused import, no shadowing (`notes`/`chords` do appear as parameter names elsewhere — they shadowed the function declaration before and shadow the import now, identically). Served from local uvicorn on core@main (R0): src/notes.js 200 as text/javascript. All four headless Chromium harnesses green: draw path, state round-trip, hit test, resize. 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 (8)
📝 WalkthroughWalkthroughPure note/chord logic (accessors, chord-resize sustain arithmetic, bend-curve utilities, teaching-mark helpers) is extracted from ChangesNote/chord pure tier migration
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Test as notes.test.mjs
participant NotesModule as notes.js
participant State as S (global state)
Test->>NotesModule: call notes()
NotesModule->>State: read S.arrangements[S.currentArr]
State-->>NotesModule: active arrangement notes array (live reference)
NotesModule-->>Test: return live array
Test->>Test: mutate returned array
Test->>State: verify underlying arrangement updated
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning Tools execution failed with the following error: Failed to run tools: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error) Comment |
There was a problem hiding this comment.
Pull request overview
This PR continues the editor’s ES-module split by extracting the note/chord “pure tier” (accessors + arithmetic helpers) from src/main.js into a new leaf module src/notes.js, and updates Node-based tests to import the real module instead of slicing @pure: blocks out of main.js.
Changes:
- Added
src/notes.jsexporting arrangement accessors (notes(),chords()) and pure helpers for chord-aware sustain resizing, bend-curve authoring, and teaching marks. - Updated multiple test suites to real-import from
src/notes.js(withroll_edge_resizeremaining a hybrid that still slices undo-command code frommain.js). - Documented the refactor and test migration in
CHANGELOG.md, and removed the extracted code blocks fromsrc/main.jswhile adding a corresponding import block.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tests/teaching_marks.test.mjs | Switches from source-sliced @pure: eval to real imports from src/notes.js. |
| tests/roll_edge_resize.test.mjs | Keeps slicing undo-command code from main.js, but imports resize arithmetic from src/notes.js. |
| tests/notes.test.mjs | New tests covering notes()/chords() empty-arrangement guard and live-array identity behavior. |
| tests/chord_resize.test.mjs | Switches to real imports from src/notes.js for chord-resize arithmetic tests. |
| tests/bend_shape.test.mjs | Switches to real imports from src/notes.js for bend-curve helper tests. |
| src/notes.js | New module containing the extracted note/chord accessors and pure helper logic. |
| src/main.js | Removes extracted pure-tier code and imports the same APIs from src/notes.js. |
| CHANGELOG.md | Adds an Unreleased entry describing step 6 (notes/chords pure tier extraction and test updates). |
Comments suppressed due to low confidence (3)
tests/teaching_marks.test.mjs:5
- The header comment is now inaccurate: the helpers are imported from src/notes.js (no source slicing/eval), but the comment still references src/main.js and evaluating an extracted
@pureblock. Update the header to match the new test approach.
tests/bend_shape.test.mjs:5 - The header comment is now inaccurate: this test imports helpers from src/notes.js, but the comment still refers to src/main.js and evaluating an extracted block. Update the header to reflect the real-import setup.
tests/chord_resize.test.mjs:4 - The header comment still says these helpers are for src/main.js, but the suite now imports them from src/notes.js. Update the comment to avoid confusion.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Step 6 of the editor's ES-module split (R2).
main.js20,763 → 20,601.What moved
src/notes.js(176 lines) — the note/chord data model, pure tier. ReadsS; no DOM, no undo history. Graph stays acyclic:notes → state.notes(),chords()— 204 and 35 call sites, none of which changed_resizeTargetIndicesPure,_maxSustainBeforeCollisionPure,_resizeSustainsForDeltaPurebendPresetCurve,sanitizeBendCurve,rescaleBendCurveToPeak,BEND_INTENTSFRET_FINGER_OPTIONS,nextUnusedStrumGroupmain.js's entire diff is the deletions plus the import block (checked by reconstructing it programmatically).Tests: four more source-slicers die
chord_resize,bend_shape,teaching_marks→ plain real-import tests.roll_edge_resize→ hybrid: still slices theedit-historyblock and theResizeSustainCmd/ResizeSustainGroupCmdclasses that stay inmain.js, but imports the resize arithmetic. Those commands callnotes()through an injected sandbox param already, so they were unaffected.tests/notes.test.mjscovers what the pure-fn suites never touched: the accessors' empty-arrangement guard (200+ call sites iterate the result directly, including on the entry screen with nothing loaded) and that they return the live array, not a copy.Why
chord-relinkandreconstructChordsdid NOT come alongThey're the obvious next thing in that section, and I left them deliberately.
flattenChordsneeds_normChordFnfrom inside the@pure:chord-relinkblock, andreconstructChordsis entangled withS.history. But the real blocker is the tests:chord_relink,handshape_authoringandsuggest_position_wiringconcatenate that block's source text into anew Functionsandbox and drive it against a fabricatedS. A real import would close over the actualSfromstate.jsand quietly bypass their fixtures — the tests would still pass while testing the wrong object.So those three need a genuine rework (drive the real
S, the waylanes.test.mjsandnotes.test.mjsdo). That's a step of its own, not a rider on a mechanical move. Shipping it here would have meant a 600-line move plus three non-trivial test rewrites in one reviewable unit.Verification
node --test85/85,pytest248/248.notesandchordsdo appear as parameter names elsewhere inmain.js(e.g.dropOrphanedHandshapes(handshapes, chords, notes)) — they shadowed the function declaration before and shadow the import now, identically.src/notes.js200 astext/javascript.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes