Browse Source

improve disposal to aid GC

Alexander Rose 1 year ago
parent
commit
e773824fb5

+ 1 - 0
CHANGELOG.md

@@ -25,6 +25,7 @@ Note that since we don't clearly distinguish between a public and private interf
 - Fix `bumpiness` scaling with `ignoreLight` enabled
 - Add `transforms` & `label` params to `ShapeFromPly`
 - Optimize `LociSelectManager.selectOnly` to avoid superfluous loci set operations
+- Dispose of viewer on `unload` event to aid GC
 
 ## [v3.42.0] - 2023-11-05
 

+ 4 - 0
src/apps/viewer/app.ts

@@ -494,6 +494,10 @@ export class Viewer {
     handleResize() {
         this.plugin.layout.events.updated.next(void 0);
     }
+
+    dispose() {
+        this.plugin.dispose();
+    }
 }
 
 export interface LoadStructureOptions {

+ 5 - 0
src/apps/viewer/index.html

@@ -120,6 +120,11 @@
 
                 var modelArchive = getParam('model-archive', '[^&]+').trim();
                 if (modelArchive) viewer.loadModelArchive(modelArchive);
+
+                window.addEventListener('unload', () => {
+                    // to aid GC
+                    viewer.dispose();
+                });
             });
         </script>
         <!-- __MOLSTAR_ANALYTICS__ -->

+ 4 - 0
src/mol-plugin-state/manager/drag-and-drop.ts

@@ -36,6 +36,10 @@ export class DragAndDropManager {
         defaultDragAndDropHandler(this.plugin, files);
     }
 
+    dispose() {
+        this.handlers.length = 0;
+    }
+
     constructor(public plugin: PluginContext) {
     }
 }

+ 16 - 0
src/mol-plugin-state/manager/interactivity.ts

@@ -55,6 +55,12 @@ class InteractivityManager extends StatefulPluginComponent<InteractivityManagerS
         this.events.propsUpdated.next(void 0);
     }
 
+    dispose() {
+        super.dispose();
+        this.lociSelects.dispose();
+        this.lociHighlights.dispose();
+    }
+
     constructor(readonly plugin: PluginContext, props: Partial<InteractivityManager.Props> = {}) {
         super({ props: { ...PD.getDefaultValues(InteractivityManager.Params), ...props } });
 
@@ -115,6 +121,11 @@ namespace InteractivityManager {
             }
         }
 
+        dispose() {
+            this.providers.length = 0;
+            this.sel.dispose();
+        }
+
         constructor(public readonly ctx: PluginContext, props: Partial<Props> = {}) {
             this.sel = ctx.managers.structure.selection;
             this.setProps(props);
@@ -181,6 +192,11 @@ namespace InteractivityManager {
                 }
             }
         }
+
+        dispose() {
+            super.dispose();
+            this.prev.length = 0;
+        }
     }
 
     //

+ 5 - 0
src/mol-plugin-state/manager/snapshots.ts

@@ -362,6 +362,11 @@ class PluginStateSnapshotManager extends StatefulPluginComponent<{
         }
     }
 
+    dispose() {
+        super.dispose();
+        this.entryMap.clear();
+    }
+
     constructor(private plugin: PluginContext) {
         super({
             current: void 0,

+ 2 - 1
src/mol-plugin/context.ts

@@ -389,14 +389,15 @@ export class PluginContext {
         this.canvas3dContext?.dispose(options);
         this.ev.dispose();
         this.state.dispose();
-        this.managers.task.dispose();
         this.helpers.substructureParent.dispose();
 
         objectForEach(this.managers, m => (m as any)?.dispose?.());
         objectForEach(this.managers.structure, m => (m as any)?.dispose?.());
+        objectForEach(this.managers.volume, m => (m as any)?.dispose?.());
 
         this.unmount();
         this.canvasContainer = undefined;
+        (this.customState as any) = {};
 
         this.disposed = true;
     }

+ 8 - 0
src/mol-util/assets.ts

@@ -141,4 +141,12 @@ class AssetManager {
         entry.refCount--;
         if (entry.refCount <= 0) this._assets.delete(asset.id);
     }
+
+    clear() {
+        this._assets.clear();
+    }
+
+    dispose() {
+        this.clear();
+    }
 }