Reuse preallocated import identities and stable recovery document views
This commit is contained in:
@@ -1,11 +1,17 @@
|
||||
import type { CanvasRecord, Change, Document, ElementRecord, Geometry, Id, Registry, Target } from './types.ts';
|
||||
import { clone, equal, fault, freeze, readMap, validJson } from './values.ts';
|
||||
|
||||
// This owns only the envelope and fixed table membership, not validation or
|
||||
// immutability of values inherited by applyChanges from an external document.
|
||||
const factoryDocuments=new WeakSet<object>();
|
||||
function documentEnvelope(document:Document):Document{const value=Object.freeze(document);factoryDocuments.add(value);return value;}
|
||||
export const isFactoryDocument=(document:Document)=>factoryDocuments.has(document);
|
||||
|
||||
export function createDocument(projectId: Id, canvases: readonly CanvasRecord[], elements: readonly ElementRecord[] = [], tombstones: ReadonlyMap<Id, number> = new Map()): Document {
|
||||
for (const element of elements) { const id = element.id; if (!validJson(element)) throw fault('invalid_element', [id]); }
|
||||
for (const canvas of canvases) if (!validJson(canvas)) throw fault('invalid_canvas');
|
||||
if (!projectId || new Set(canvases.map(item => item.id)).size !== canvases.length || new Set(elements.map(item => item.id)).size !== elements.length) throw fault('duplicate_identity');
|
||||
return Object.freeze({ projectId, canvases: readMap(new Map(canvases.map(item => [item.id, freeze(clone(item))]))), elements: readMap(new Map(elements.map(item => [item.id, freeze(clone(item))]))), tombstones: readMap(tombstones) });
|
||||
return documentEnvelope({ projectId, canvases: readMap(new Map(canvases.map(item => [item.id, freeze(clone(item))]))), elements: readMap(new Map(elements.map(item => [item.id, freeze(clone(item))]))), tombstones: readMap(tombstones) });
|
||||
}
|
||||
export function geometryValid(value: Geometry): boolean {
|
||||
return !!value && typeof value === 'object' && [value.x, value.y, value.width, value.height, value.rotation].every(Number.isFinite) && value.width > 0 && value.height > 0 && value.rotation >= 0 && value.rotation < 360;
|
||||
@@ -115,7 +121,7 @@ export function applyChanges(document: Document, changes: readonly Change[], con
|
||||
} else canvases.delete(change.id);
|
||||
} else throw fault('invalid_change');
|
||||
}
|
||||
return Object.freeze({ projectId: document.projectId, elements: readMap(elements), canvases: readMap(canvases), tombstones: readMap(tombstones) });
|
||||
return documentEnvelope({ projectId: document.projectId, elements: readMap(elements), canvases: readMap(canvases), tombstones: readMap(tombstones) });
|
||||
}
|
||||
export function invert(changes: readonly Change[]): readonly Change[] {
|
||||
return changes.slice().reverse().map(change => {
|
||||
|
||||
Reference in New Issue
Block a user