-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
Summary
When navigating between backoffice sections (e.g., from Content to Media), workspace context APIs are not properly destroyed. The destroy() method on workspace context classes is never called, potentially causing memory leaks and preventing proper cleanup.
Steps to Reproduce
- Navigate to Content section and open a document
- Add a
console.logor breakpoint in any workspace context'sdestroy()method - Navigate to Media section (or any other section)
- Observe that
destroy()is never called on the document workspace context
Expected Behavior
When navigating away from a workspace, the workspace context's destroy() method should be called to allow proper cleanup of subscriptions, event listeners, and other resources.
Actual Behavior
The destroy() method is never called. The workspace context instance remains in memory until the page is refreshed.
Note: destroy() IS correctly called when:
- Closing a modal workspace (e.g., block editor)
- The
entityTypeproperty changes on the same workspace element
But NOT when:
- Navigating to a different section entirely
- The workspace element is removed from the DOM
Root Cause Analysis
Looking at workspace.element.ts, the UmbWorkspaceElement class does not override hostDisconnected() to destroy its extensions controller when the element is removed from the DOM.
Current code (src/packages/core/workspace/workspace.element.ts):
@customElement('umb-workspace')
export class UmbWorkspaceElement extends UmbLitElement {
#extensionsController?: UmbExtensionsElementAndApiInitializer<any>;
// ... entityType setter calls #createController which destroys old controller
// BUT there's no hostDisconnected() override
}The #createController method does destroy the old controller, but only when a NEW controller is being created. When navigating away entirely, the element is removed from DOM without triggering any cleanup.
Suggested Fix
Add a hostDisconnected() override to properly clean up:
override hostDisconnected(): void {
super.hostDisconnected();
if (this.#extensionsController) {
this.#extensionsController.destroy();
this.#extensionsController = undefined;
}
}This ensures the extensions controller (and thus the workspace context API) is properly destroyed when the workspace element is disconnected from the DOM.
Impact
- Memory leaks: Workspace contexts and their subscriptions may accumulate
- Stale state: Old workspace contexts may still be receiving updates
- Third-party extensions: Extensions that rely on
destroy()for cleanup won't work correctly
Environment
- Umbraco version: 15.x / 17.x (affects current backoffice architecture)
- Browser: All
- OS: All
This item has been added to our backlog AB#63312