perf(canvas): stabilize renderer bindings and retain unchanged projections
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import type {Document,Id} from '../canvas-core/types.ts';
|
||||
import {equal,fault} from '../canvas-core/values.ts';
|
||||
import type {projectCanvas} from './projection.ts';
|
||||
|
||||
type Projection=ReturnType<typeof projectCanvas>;
|
||||
type Retained<T>={incarnation:number;ownerCanvasId:Id;value:T};
|
||||
/** View-owned rendering cache, never a document store. Keep unchanged React Flow input identities. */
|
||||
export function createProjectionCache(){
|
||||
let scope:object|undefined,projectId:Id|undefined,canvasId:Id|undefined;
|
||||
let nodes=new Map<Id,Retained<Projection['nodes'][number]>>(),edges=new Map<Id,Retained<Projection['edges'][number]>>();
|
||||
function retain<T extends{id:Id}>(document:Document,values:T[],previous:Map<Id,Retained<T>>){
|
||||
const next=new Map<Id,Retained<T>>();
|
||||
for(let index=0;index<values.length;index++){
|
||||
const value=values[index],record=document.elements.get(value.id);if(!record)throw fault('projection_identity_missing',[value.id]);
|
||||
const old=previous.get(value.id),retained=old&&old.incarnation===record.incarnation&&old.ownerCanvasId===record.ownerCanvasId&&equal(old.value,value)?old.value:value;
|
||||
values[index]=retained;next.set(value.id,{incarnation:record.incarnation,ownerCanvasId:record.ownerCanvasId,value:retained});
|
||||
}
|
||||
return next;
|
||||
}
|
||||
return Object.freeze({
|
||||
reuse(owner:object,document:Document,viewCanvasId:Id,projection:Projection):Projection{
|
||||
if(scope!==owner||projectId!==document.projectId||canvasId!==viewCanvasId){nodes.clear();edges.clear();scope=owner;projectId=document.projectId;canvasId=viewCanvasId;}
|
||||
nodes=retain(document,projection.nodes,nodes);edges=retain(document,projection.edges,edges);
|
||||
return projection;
|
||||
},
|
||||
clear(){nodes.clear();edges.clear();scope=undefined;projectId=undefined;canvasId=undefined;},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user