diff --git a/src/mol-plugin-state/transforms/representation.ts b/src/mol-plugin-state/transforms/representation.ts index 3c04b3089985b6e14f2b619a9a4b6d91aa59bf71..fb49d9b308476841ef3a9b30732b5bb366923cd7 100644 --- a/src/mol-plugin-state/transforms/representation.ts +++ b/src/mol-plugin-state/transforms/representation.ts @@ -141,12 +141,13 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({ }, update({ a, b, oldParams, newParams, cache }, plugin: PluginContext) { return Task.create('Structure Representation', async ctx => { + if (newParams.type.name !== oldParams.type.name) return StateTransformer.UpdateResult.Recreate; + + // dispose isn't called on update so we need to handle it manually const oldProvider = plugin.representation.structure.registry.get(oldParams.type.name); if (oldProvider.ensureCustomProperties) oldProvider.ensureCustomProperties.detach(a.data); Theme.releaseDependencies(plugin.representation.structure.themes, { structure: a.data }, oldParams); - if (newParams.type.name !== oldParams.type.name) return StateTransformer.UpdateResult.Recreate; - const provider = plugin.representation.structure.registry.get(newParams.type.name); const propertyCtx = { runtime: ctx, fetch: plugin.fetch }; if (provider.ensureCustomProperties) await provider.ensureCustomProperties.attach(propertyCtx, a.data); diff --git a/src/mol-state/state.ts b/src/mol-state/state.ts index b81c2cb4032fb8ff1d3676f02f627dcfbf209412..45845752b52dc090e54dff47ccedb7c297386f65 100644 --- a/src/mol-state/state.ts +++ b/src/mol-state/state.ts @@ -477,7 +477,9 @@ async function update(ctx: UpdateContext) { for (let i = deletes.length - 1; i >= 0; i--) { const cell = ctx.cells.get(deletes[i]); - cell?.transform.transformer.definition.dispose?.({ b: cell.obj, params: cell.transform.params, cache: cell.cache }, ctx.parent.globalContext); + if (cell) { + dispose(cell.transform, cell.obj, cell?.transform.params, cell.cache, ctx.parent.globalContext); + } } for (const d of deletes) { @@ -866,9 +868,11 @@ async function updateNode(ctx: UpdateContext, currentRef: Ref): Promise<UpdateNo return { ref: currentRef, action: 'created', obj }; } else { const oldParams = current.params.values; + const oldCache = current.cache; const newParams = params.values; current.params = params; + const updateKind = !!current.obj && current.obj !== StateObject.Null ? await updateObject(ctx, current, transform.transformer, parent, current.obj!, oldParams, newParams) : StateTransformer.UpdateResult.Recreate; @@ -876,7 +880,10 @@ async function updateNode(ctx: UpdateContext, currentRef: Ref): Promise<UpdateNo switch (updateKind) { case StateTransformer.UpdateResult.Recreate: { const oldObj = current.obj; + dispose(transform, oldObj, oldParams, oldCache, ctx.parent.globalContext); + const newObj = await createObject(ctx, current, transform.transformer, parent, newParams); + updateTag(newObj, transform); current.obj = newObj; return { ref: currentRef, action: 'replaced', oldObj, obj: newObj }; @@ -885,6 +892,8 @@ async function updateNode(ctx: UpdateContext, currentRef: Ref): Promise<UpdateNo updateTag(current.obj, transform); return { ref: currentRef, action: 'updated', obj: current.obj! }; case StateTransformer.UpdateResult.Null: { + dispose(transform, current.obj, oldParams, oldCache, ctx.parent.globalContext); + current.obj = StateObject.Null; return { ref: currentRef, action: 'updated', obj: current.obj! }; } @@ -894,6 +903,14 @@ async function updateNode(ctx: UpdateContext, currentRef: Ref): Promise<UpdateNo } } +function dispose(transform: StateTransform, b: StateObject | undefined, params: any, cache: any, globalContext: any) { + transform.transformer.definition.dispose?.({ + b: b !== StateObject.Null ? b : void 0, + params, + cache + }, globalContext); +} + function updateTag(obj: StateObject | undefined, transform: StateTransform) { if (!obj || obj === StateObject.Null) return; (obj.tags as string[] | undefined) = transform.tags; diff --git a/src/mol-state/transformer.ts b/src/mol-state/transformer.ts index aceb10ffb443e2e300d779e8355a62857712fc54..9770ab58d2a2e7bd5634ada31e9ab88130514eb9 100644 --- a/src/mol-state/transformer.ts +++ b/src/mol-state/transformer.ts @@ -103,7 +103,16 @@ namespace Transformer { /** Parameter interpolation */ interpolate?(src: P, target: P, t: number, globalCtx: unknown): P - /** Cleanup resources */ + /** + * Cleanup resources + * + * Automatically called on deleting an object and on recreating it + * (i.e. when update returns UpdateResult.Recreate or UpdateResult.Null) + * + * Not called on UpdateResult.Updated because the resources might not + * have been invalidated. In this case, the possible cleanup has to be handled + * manually. + */ dispose?(params: DisposeParams<B, P>, globalCtx: unknown): void /** Custom conversion to and from JSON */