You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
JointJS papers are never disposed, so every remount leaves one listening to the shared graph #8582
WorkflowEditorComponent and MiniMapComponent each construct a joint.dia.Paper bound to the joint graph owned by WorkflowActionService, which is providedIn: "root" and lives for the whole tab. Neither ngOnDestroy disposes its paper, and a repo-wide search finds no paper.remove() anywhere in frontend/src/app.
WorkflowEditorComponent.ngAfterViewInit -> attachMainJointPaper(...) -> new joint.dia.Paper({ model: this.jointGraph, ... }); its ngOnDestroy disconnects a resize observer, removes a keydown listener and resets the heat-map view, and leaves the paper.
MiniMapComponent.ngAfterViewInit constructs its own paper on the same graph; its ngOnDestroy only writes a localStorage flag.
So every remount of either component adds a paper that keeps listening to the one graph and rendering into a DOM node that is no longer on the page. The Hub's read-only workflow preview already remounts the editor, and the Form View mounts a second editor for its workflow preview strip.
The visible risk is pointer handling: two live papers on one model both receive the model's events, and paper-wide interactivity (setInteractivity, which is what makes operators draggable) is per paper. A stale paper carrying the Form View's structureLocked settings is a plausible cause of the "undraggable operators" symptom recorded in the comments that made the canvas <-> Form View switch a full page load (see #8580).
Proposed: call paper.remove() in both ngOnDestroys, with a test in each spec that the paper is disposed when the fixture is destroyed.
Found while working on #8580; kept out of that PR because it is a pre-existing leak on any remount, not specific to the switch, and wants its own tests.
It looks like the issue description doesn't quite follow our template yet:
This issue doesn't appear to use one of our templates (Bug, Feature, or Task). Please open it using a template so the required details are captured.
Filling out the template helps reviewers understand and triage your contribution faster. Please edit the description to complete it. This message will disappear automatically once the template is followed.
You can find the template prompts by editing the description, or see CONTRIBUTING.md for the full contribution flow.
Already done on main: WorkflowEditorComponent.ngOnDestroy calls this.paper?.remove() and MiniMapComponent.ngOnDestroy calls this.ownPaper?.remove(), so a remount no longer leaves a paper listening to the shared graph. Closing.
Activity
github-actions commentedon Sep 17, 2026
👋 Thanks for opening this issue, @yangzhang75!
It looks like the issue description doesn't quite follow our template yet:
Filling out the template helps reviewers understand and triage your contribution faster. Please edit the description to complete it. This message will disappear automatically once the template is followed.
You can find the template prompts by editing the description, or see CONTRIBUTING.md for the full contribution flow.
fix(frontend): keep a handed-over run visible and locked, and let eac…
docs(frontend): say only what held up about the undisposed papers
fix(frontend): keep a handed-over run visible and locked, and let eac…
docs(frontend): say only what held up about the undisposed papers
perf(workflow): switch between a workflow's two views without reloadi…
yangzhang75 commentedon Oct 5, 2026
/take
yangzhang75 commentedon Oct 19, 2026
Already done on main:
WorkflowEditorComponent.ngOnDestroycallsthis.paper?.remove()andMiniMapComponent.ngOnDestroycallsthis.ownPaper?.remove(), so a remount no longer leaves a paper listening to the shared graph. Closing.