Skip to content

Fix CodeEditor annotations overwritten by Ace worker - #8505

Merged
philippjfr merged 2 commits into
holoviz:mainfrom
ghostiee-11:fix/codeeditor-annotations-7967
Mar 14, 2026
Merged

Fix CodeEditor annotations overwritten by Ace worker#8505
philippjfr merged 2 commits into
holoviz:mainfrom
ghostiee-11:fix/codeeditor-annotations-7967

Conversation

@ghostiee-11

@ghostiee-11 ghostiee-11 commented Mar 13, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes #7967

Since the Ace upgrade (v1.4.11 to v1.40.1 in #7874), explicitly setting annotations on a CodeEditor gets overwritten by Ace's background syntax-checking worker. The worker fires asynchronously after session.setMode() and calls session.setAnnotations() with its own results, wiping out user-set annotations.

I traced the issue to panel/models/ace.ts:

  • _update_language() calls session.setMode() which spawns a worker that overwrites annotations
  • There was no mechanism to prevent the worker from clobbering user annotations

The fix:

  • When user annotations are set (non-empty), disable the Ace session worker with setUseWorker(false) so it cannot overwrite them
  • When annotations are cleared back to empty, re-enable the worker so default syntax checking resumes
  • Call _add_annotations() in _update_language() after setMode() so annotations persist across language/mode changes

Important ordering detail: setUseWorker(false) clears the session's annotations as a side effect, so the worker must be toggled before calling setAnnotations().

Known Limitations

When user annotations are set (non-empty), Ace's built-in syntax checking worker is disabled to prevent it from overwriting custom annotations. This means real-time syntax error/warning markers from Ace will not appear alongside user-set annotations. Syntax checking resumes automatically when annotations are cleared back to []. This matches the behavior of Panel < 1.7.0 where the annotations parameter gave users full control over the annotation system.

Reproducer (from the issue):

import panel as pn
pn.extension("codeeditor")

code = "test:\n- {a: 1, b: 2}\n- {c: 3, d: 4}\n- {e: 5, f: 6}\n"
editor = pn.widgets.CodeEditor(value=code, language="yaml", annotations=[])

def add_annotations(event):
    editor.annotations = [
        {"row": 1, "column": 0, "text": "a warning", "type": "warning"},
        {"row": 2, "column": 0, "text": "an error", "type": "error"},
    ]

def clear_annotations(event):
    editor.annotations = []

add_btn = pn.widgets.Button(name="Add Annotations", button_type="primary")
add_btn.on_click(add_annotations)
clear_btn = pn.widgets.Button(name="Clear Annotations", button_type="warning")
clear_btn.on_click(clear_annotations)

pn.Row(editor, pn.Column(add_btn, clear_btn)).servable()

Before fix (annotations never appear after clicking "Add Annotations"):
pr_before_click

After fix (annotations appear and persist after clicking "Add Annotations"):

pr_after_click

After fix (annotations cleared after clicking "Clear Annotations"):

pr_after_clear

How Has This Been Tested?

  • All 4 existing test_codeeditor.py UI tests pass
  • All 3 existing test_ace.py unit tests pass
  • Added 6 new UI tests:
    • test_code_editor_annotations: sets annotations dynamically, verifies worker is disabled, checks persistence across multiple checkpoints, clears and verifies worker re-enables
    • test_code_editor_annotations_constructor: verifies constructor-provided annotations are applied, worker is disabled, and annotations persist
    • test_code_editor_annotations_persist_on_language_change: sets annotations then changes language, verifies annotations survive the mode/worker respawn
    • test_code_editor_annotations_replacement: replaces one set of annotations with another, verifies the new set is applied correctly
    • test_code_editor_annotations_persist_on_value_change: sets annotations then changes code value programmatically, verifies annotations survive
    • test_code_editor_worker_resumes_after_clear: full lifecycle test — verifies Ace's JS worker produces syntax errors on invalid code, user annotations override them (worker disabled), and after clearing the worker resumes producing its own annotations
  • All annotation tests use multi-checkpoint stability assertions (5 checks x 200ms) instead of single hardcoded sleeps for CI robustness
  • Manual testing with the reproducer above confirms annotations display correctly and are not overwritten

AI Disclosure

  • This PR contains AI-generated content.
    • I have tested all AI-generated content in my PR.
    • I take responsibility for all AI-generated content in my PR.
      Tools: Claude, used to help scaffold the fix and tests after I identified the root cause.

Checklist

  • Tests added and is passing

Since the Ace upgrade to v1.40.1 (holoviz#7874), the background syntax-checking
worker overwrites user-set annotations. This fix disables the worker when
user annotations are set and re-enables it when cleared.

Key changes:
- Toggle Ace worker off when annotations are non-empty to prevent overwrites
- Call _add_annotations() during render for constructor-provided annotations
- Re-apply annotations after language/mode changes to prevent worker races
- Order setUseWorker before setAnnotations (disabling worker clears session)

Closes holoviz#7967
@codecov

codecov Bot commented Mar 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.09%. Comparing base (f6dc8a7) to head (b60ffe7).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff             @@
##             main    #8505       +/-   ##
===========================================
+ Coverage   70.34%   86.09%   +15.75%     
===========================================
  Files         348      349        +1     
  Lines       55198    55292       +94     
===========================================
+ Hits        38828    47606     +8778     
+ Misses      16370     7686     -8684     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

- Remove duplicate _add_annotations() call in render() (already called
  via _update_language())
- Replace hardcoded sleeps with multi-checkpoint stability assertions
- Add worker state verification (useWorker toggle assertions)
- Add tests: language change, annotation replacement, value change,
  and full worker lifecycle (resume after clear with invalid JS)
@philippjfr
philippjfr merged commit 2b50a33 into holoviz:main Mar 14, 2026
32 of 35 checks passed
@ghostiee-11

Copy link
Copy Markdown
Contributor Author

Thanks for the merge and review!! 😊

@github-actions

Copy link
Copy Markdown

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Jun 23, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Change in annotations behaviour of CodeEditor for panel >1.7.0

2 participants