Skip to content

Watchdog removal - #582

Open
mmotyczynska wants to merge 14 commits into
masterfrom
ck/epic/10827-watchdog-removal
Open

mmotyczynska wants to merge 14 commits into
masterfrom
ck/epic/10827-watchdog-removal

Conversation

@mmotyczynska

@mmotyczynska mmotyczynska commented Sep 11, 2026

Copy link
Copy Markdown

See: https://github.com/ckeditor/ckeditor5-commercial/issues/10827

🚀 Summary

A brief summary of what this PR changes.


📌 Related issues

  • Closes #000

💡 Additional information

Optional: Notes on decisions, edge cases, or anything helpful for reviewers.

The component creates the editor itself and destroys it itself, instead of handing a creator to a watchdog that would call it again on every restart. Errors that escape a running editor arrive through `Editor.onEditorError()`, filtered down to this component's own editor; a failure during creation is reported by the rejected `create()`, as before.

Gone with the restarts: the `watchdog`, `editorWatchdogConfig` and `disableWatchdog` inputs, the `DisabledEditorWatchdog` stand-in, and the `itemError` wiring. Sharing a context is now what it already was in the context demo — create the `Context` and pass it in the configuration.

Also requires CKEditor 5 in version 49 or higher, which is where `onEditorError` appears.
The two watchdog demos lost their subject. One is gone, because the context demo next to it already shows what replaced it; the other became an error handling demo with three modes — one editor, two editors, and two editors sharing a context — so that it is visible that an error stays with the editor it came from.

The initialization crash demo kept one of its two sections. Both showed the same thing already: the Watchdog never covered errors during creation.
The mock editor stops carrying the Watchdog classes and carries the `onEditorError` static a real editor class has. The three watchdog blocks are gone, and in their place the component is covered for what replaced them: an error reaches the component whose editor it came from, the editor stays the same afterwards, another editor's error does not arrive, and destroying the component stops the reporting.

Those tests use a real editor. A mock is not an editor attribution knows about, so an error thrown with one is attributed to nobody and reported to no one.

The two change detection tests each expected one cycle more than they now get. That cycle was the Watchdog rendering the editor it had just rebuilt; with no restarts there is nothing to render, and what the tests are about — change detection running only when someone listens — is unchanged.
…hrows.

The `try` covered only `create()`, so a throw in what follows — reaching for a static an older editor class does not have, say — left `this.creating` rejected, and `destroyEditor()` awaited it unguarded. The component then never unregistered its callback and never destroyed a live, fully built editor.

The unsubscribe also had no test of its own: removing it left the suite green, because the reporter already refuses errors from an editor that is no longer ready. It is asserted directly now, as is destroying an editor that finishes starting after the component is gone.

The synthetic errors those tests dispatch are swallowed, so the run no longer ends with an unhandled error. The changelog names the raised version requirement.
`setMode` awaited `Context.create()` with nothing to say whether that switch was still the current one. Clicking another mode, or leaving the route, while the context was being built left the demo writing editors for a mode that was no longer chosen, or holding a context that `ngOnDestroy` had already passed and nobody would ever destroy.

A generation counter settles both: a switch that is no longer current destroys the context it created and writes nothing. Found by Bugbot on the pull request — it is only a demo, but it is the demo the changelog points integrators at when it tells them the context is theirs to own.
`destroyEditor()` asked only whether it had an editor, never whether that editor was still alive. The changelog tells integrators that the context is theirs to destroy, and `Context#destroy()` takes its editors with it — so the component could destroy an editor that was already down. The watchdog used to give this for nothing, by clearing its own reference once it had destroyed.

Prompted by a Bugbot comment about the demo destroying its context while the editors were still tearing down. That overlap is real, but the consequence it predicted is not: a probe with `editor.destroy()` in flight and `context.destroy()` in the same tick resolves cleanly, does not throw, and leaves the editor destroyed. What it did surface is the missing guard above, which is the integrator-driven ordering rather than the demo's.
The guard added a moment ago skipped the whole branch when the editor was already down, and clearing `currentEditor` sat inside it. `editorInstance` then went on naming a destroyed editor after teardown, where the watchdog used to leave `null`.

Letting go is unconditional now; only the destroy call is guarded. Found by Bugbot, and the test that covers the guard covers this too.
Replace the Watchdog with the new error handling API
Docs: correct two claims in the Watchdog removal changelog entry.
An editor that finishes starting after the component is gone is destroyed inside the pending
creation. Should that destruction fail, `destroyEditor()` must still run to the end — which is
what the catch on `this.creating` is for, and what nothing asserted until now.
@mmotyczynska

Copy link
Copy Markdown
Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Comment thread src/ckeditor/ckeditor.component.ts
@mmotyczynska

Copy link
Copy Markdown
Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 35b4fde. Configure here.

Comment on lines +403 to +407
editor = await (
supports.elementConfigAttachment ?
Editor.create( assignElementToEditorConfig( Editor, element, config ) ) :
Editor.create( element, config )
);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This condition is no longer needed for >= 49, as it supports elementConfigAttachment ootb.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I'd rather wait with the rest. The same comparison drives rootsConfigEntry, so it's eleven conditions across the three integrations, and which editor versions these majors will ultimately support isn't settled yet (ckeditor5-commercial#11613). Until it is, the dead branches don't break anything.

@Mati365 Mati365 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks fine.

@mmotyczynska
mmotyczynska requested a review from a team as a code owner September 15, 2026 21:29
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.

2 participants