Skip to content

Fix Preferences apply silently discarding changes when a page fails to instantiate#33842

Open
manolo wants to merge 1 commit into
musescore:mainfrom
manolo:fix/preferences-apply-undefined
Open

Fix Preferences apply silently discarding changes when a page fails to instantiate#33842
manolo wants to merge 1 commit into
musescore:mainfrom
manolo:fix/preferences-apply-undefined

Conversation

@manolo

@manolo manolo commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Related to: #33841

When a preference page fails to instantiate (e.g. due to a null-parent binding on the first layout pass), it is skipped and never stored in prv.pagesObjects. The apply loop in PreferencesDialog iterated all
pages from availablePages() without guarding against missing entries, so obj.apply() threw a TypeError on undefined, corrupting the ok accumulator and preventing root.hide(). Changes were silently discarded with no UI feedback.

  1. PreferencesDialog.qml: guard obj before calling apply().
  2. PreferencesPage.qml: null-safe parent binding to avoid the TypeError during instantiation.

Reproduced on macOS 15 (arm64), MuseScore 4.7.3 and 5.0.0 developer builds with -DMUE_BUILD_MACOS_INTEGRATION=OFF.

  • I signed the CLA as manolo: manolo
  • The title of the PR describes the problem it addresses.
  • Each commit's message describes its purpose and effects, and references the issue it resolves.
  • The code in the PR follows the coding rules.
  • I understand all aspects of the code I'm contributing and I'm able to explain it if requested.
  • The code compiles and runs on my machine, preferably after each commit individually. I have manually tested and verified that my changes fulfil their intended purpose.
  • No prior attempts to resolve this problem exist.
  • There are no unnecessary changes.
  • I created a unit test or vtest to verify the changes I made (if applicable). (Not applicable, QML logic fix)

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Two null-safety fixes are applied to the Preferences QML components. In PreferencesDialog.qml, the onApplyRequested handler's per-page loop now checks that pagesObjects[page.id] is non-null before calling obj.apply() and accumulating the result. In PreferencesPage.qml, the root Rectangle's height binding is changed from a direct parent.height reference to parent ? parent.height : 0, guarding against an undefined parent.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix Preferences apply silently discarding changes when a page fails to instantiate' directly and clearly describes the main issue being fixed.
Linked Issues check ✅ Passed The PR successfully addresses all coding requirements from issue #33841: guards against undefined page objects in PreferencesDialog.qml and implements null-safe parent binding in PreferencesPage.qml.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the preferences apply issue; only two QML files are modified with minimal, targeted changes addressing the root cause.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The PR description comprehensively addresses all required template sections with relevant details about the issue, fixes, testing, and CLA compliance.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Linked repositories: Your configuration references 1 linked repositories, but your current plan allows 0. Analyzed ``, skipped musescore/muse_framework.git.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/preferences/qml/MuseScore/Preferences/PreferencesDialog.qml (1)

116-120: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard reset calls for missing page objects, same as apply path.

Line 119 calls obj.reset() unconditionally. In the same null-instantiation scenario, obj is undefined, so reset can still throw and abort the action flow.

Suggested fix
             for (var i in pages) {
                 var page = pages[i]
                 var obj = root.prv.pagesObjects[page.id]
-                obj.reset()
+                if (obj) {
+                    obj.reset()
+                }
             }
🤖 Prompt for 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.

In `@src/preferences/qml/MuseScore/Preferences/PreferencesDialog.qml` around lines
116 - 120, The unconditional call to obj.reset() on line 119 will throw an error
and abort the action flow when obj is undefined in the null-instantiation
scenario. Add a guard condition to check if obj is defined before calling
obj.reset(), similar to the pattern used in the apply path, to ensure reset is
only called on valid page objects.
🤖 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.

Outside diff comments:
In `@src/preferences/qml/MuseScore/Preferences/PreferencesDialog.qml`:
- Around line 116-120: The unconditional call to obj.reset() on line 119 will
throw an error and abort the action flow when obj is undefined in the
null-instantiation scenario. Add a guard condition to check if obj is defined
before calling obj.reset(), similar to the pattern used in the apply path, to
ensure reset is only called on valid page objects.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b4c807a3-8d53-4708-8c0b-99a386f23db9

📥 Commits

Reviewing files that changed from the base of the PR and between d402227 and ab146d9.

📒 Files selected for processing (2)
  • src/preferences/qml/MuseScore/Preferences/PreferencesDialog.qml
  • src/preferences/qml/MuseScore/Preferences/PreferencesPage.qml

…o instantiate

Guard obj before calling apply() in PreferencesDialog to prevent a TypeError on
undefined from corrupting the ok accumulator. Also null-safe parent binding in
PreferencesPage to avoid the root cause during instantiation.

Fixes: musescore#33841
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants