refactor(editor): move suggested-mark persistence and the roll lock notice (R2, step 13) - #163
Conversation
…otice (R2, step 13)
src/main.js 18,671 -> 18,565. Two small moves, each to where the code already
belonged, chosen to shrink the EditHistory seam before extracting it.
- _suggestedCount / _saveSuggestedMarks / _restoreSuggestedMarks and the
@pure:suggest-marks-persist pures -> src/notes.js, next to the WeakSet they
read. They were already zero-dependency on the rest of main.js.
- _rollLockNotice -> src/keys.js, next to _rollReadOnly, the predicate that
decides when it fires. keys.js now imports setStatus from ui.js — which is
exactly why ui.js got its own module in step 10.
Also deletes a comment in main.js that step 9b left truncated mid-sentence ("A
WeakSet is invisible to serialization by") when the WeakSet moved to notes.js.
Its full rationale lives there.
Tests: suggest_position_persist loses its sandbox ENTIRELY — every symbol it
exercises is now an import, so it drives the real S with a globalThis.localStorage
stub. suggest_position_wiring's makeEnv now shares the REAL S with the imported
_suggestedCount instead of fabricating its own; a private S would have left the
count reading an arrangement the sliced commands never touched.
The lint gate caught a missing import (_suggestedStorageKeyPure, still used by
the save-as rename path in main.js) and an import left unused (_suggestedNotes,
whose readers all moved). Both are the exact class of bug it was added for.
EditHistory's coupling to main.js is now three symbols, down from four:
_historyEnsureArr, draw, updateStatus.
Verified: npm run lint 0 errors / 10 warnings, node --test 88/88, pytest 248/248.
Graph acyclic (keys -> ui is new; ui imports nothing). All five headless harnesses
green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR relocates suggested-mark persistence and roll-lock-notice logic out of ChangesES-module migration step 13
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Editor
participant Notes as src/notes.js
participant Storage as localStorage
Editor->>Notes: _saveSuggestedMarks()
Notes->>Storage: write JSON marks by filename/arrIdx key
Editor->>Notes: _restoreSuggestedMarks()
Notes->>Storage: read JSON marks by filename/arrIdx key
Notes->>Notes: _applySuggestedMarksPure(nn, marks, tol, addFn)
Notes->>Editor: notes re-marked in WeakSet
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
This PR continues the editor ES-module migration (R2 step 13) by relocating suggested-mark persistence logic and the piano-roll “read-only” lock notice into the modules where their dependencies already live, further shrinking main.js and tightening seams ahead of extracting EditHistory.
Changes:
- Moved suggested-position mark counting + persistence helpers (
_suggestedCount,_saveSuggestedMarks,_restoreSuggestedMarks, and related “pure” helpers) intosrc/notes.jsalongside theWeakSetthey operate on. - Moved
_rollLockNoticeintosrc/keys.jsnext to_rollReadOnly, adding asetStatusimport fromsrc/ui.js. - Updated tests to remove/limit sandboxing and ensure they drive the real shared
S(andlocalStorageviaglobalThis.localStorage).
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/suggest_position_wiring.test.mjs | Adjusts the sandbox harness to share the real S and pass _suggestedCount as an import rather than slicing it. |
| tests/suggest_position_persist.test.mjs | Removes sandbox extraction; drives the real notes.js exports, real S, and a stubbed globalThis.localStorage. |
| src/notes.js | Adds suggested-mark count + persistence helpers next to _suggestedNotes and imports S from state.js. |
| src/main.js | Updates imports to consume moved suggested-mark helpers and _rollLockNotice from their new modules; deletes the in-file implementations/comments. |
| src/keys.js | Adds _rollLockNotice and imports setStatus from ui.js. |
| CHANGELOG.md | Documents step 13 moves and the related test harness changes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import { WAVEFORM_H } from './geometry.js'; | ||
| import { setStatus } from './ui.js'; | ||
| import { _openMidiForArr, _soundingPitchPure, _stringCountFor } from './lanes.js'; |
There was a problem hiding this comment.
Fixed. The header claimed localStorage was the only browser surface in keys.js; _rollLockNotice reports through setStatus, which reaches document.getElementById. It now names both — that header is the thing a reader trusts when deciding whether the module is importable under node.
…tStatus Copilot on #163: the header claimed localStorage was the only browser surface in keys.js. _rollLockNotice reports through setStatus, which touches document.getElementById. Say both. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Step 13.
main.js18,671 → 18,565. Two small moves, each to where the code already belonged — chosen to shrink theEditHistoryseam before extracting it.What moved
_suggestedCount/_saveSuggestedMarks/_restoreSuggestedMarks+ the@pure:suggest-marks-persistpures →src/notes.js, next to theWeakSetthey read. They already had zero dependencies on the rest ofmain.js._rollLockNotice→src/keys.js, next to_rollReadOnly, the predicate that decides when it fires.keys.jsnow importssetStatus— which is exactly whyui.jsgot its own module in step 10.Also deletes a comment
main.jshad been carrying since step 9b, truncated mid-sentence when theWeakSetmoved out:Its full rationale lives in
notes.js.Tests
suggest_position_persistloses its sandbox entirely. Every symbol it exercises is now an import, so it drives the realSwith aglobalThis.localStoragestub.suggest_position_wiring's env now shares the realSwith the imported_suggestedCount. This mattered: a privateSwould have left the count reading an arrangement the sliced commands never touched — green, and meaningless. That's the same trap I flagged on #151, arriving from the other direction.The lint gate paid for itself, twice
_suggestedStorageKeyPure, still used by the save-as rename path inmain.js._suggestedNotes, whose readers all moved.Both are exactly the class of bug
no-undef/no-unused-varswere added for on #159, and neither would have failed a test.Why these two, together
EditHistoryis 112 lines with a single, already-typeof-guardedSreference — but it's the keystone of the 1,536-line Undo/Redo section. Its coupling tomain.jsis now three symbols, down from four:_historyEnsureArr,draw,updateStatus.The remaining obstacle to extracting it isn't the class, it's the 13 suites that slice
@pure:edit-historyand fabricate their ownS— which the sliced command classes then share. Importing the real one would split that object in two. That rewrite is its own step, andsuggest_position_wiringabove is the pattern it will follow.Verification
npm run lint0 errors, 10 warnings.node --test88/88,pytest248/248.keys → uiis new, anduiimports nothing.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes