@ifc-lite/mutations 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bulk-query-engine.d.ts +2 -4
- package/dist/bulk-query-engine.d.ts.map +1 -1
- package/dist/bulk-query-engine.js +2 -1
- package/dist/bulk-query-engine.js.map +1 -1
- package/dist/cooperative-clone.d.ts +4 -0
- package/dist/cooperative-clone.d.ts.map +1 -0
- package/dist/cooperative-clone.js +93 -0
- package/dist/cooperative-clone.js.map +1 -0
- package/dist/cooperative-control.d.ts +17 -0
- package/dist/cooperative-control.d.ts.map +1 -0
- package/dist/cooperative-control.js +67 -0
- package/dist/cooperative-control.js.map +1 -0
- package/dist/cooperative-operation-types.d.ts +53 -0
- package/dist/cooperative-operation-types.d.ts.map +1 -0
- package/dist/cooperative-operation-types.js +2 -0
- package/dist/cooperative-operation-types.js.map +1 -0
- package/dist/cooperative-overlay-access.d.ts +14 -0
- package/dist/cooperative-overlay-access.d.ts.map +1 -0
- package/dist/cooperative-overlay-access.js +12 -0
- package/dist/cooperative-overlay-access.js.map +1 -0
- package/dist/execute-entity-operation.d.ts +6 -0
- package/dist/execute-entity-operation.d.ts.map +1 -0
- package/dist/execute-entity-operation.js +39 -0
- package/dist/execute-entity-operation.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/mutable-overlay-state.d.ts +143 -0
- package/dist/mutable-overlay-state.d.ts.map +1 -0
- package/dist/mutable-overlay-state.js +115 -0
- package/dist/mutable-overlay-state.js.map +1 -0
- package/dist/mutable-property-view.d.ts +22 -84
- package/dist/mutable-property-view.d.ts.map +1 -1
- package/dist/mutable-property-view.js +86 -75
- package/dist/mutable-property-view.js.map +1 -1
- package/dist/overlay-value-equality.d.ts +3 -0
- package/dist/overlay-value-equality.d.ts.map +1 -0
- package/dist/overlay-value-equality.js +52 -0
- package/dist/overlay-value-equality.js.map +1 -0
- package/dist/prepare-entity-operations.d.ts +7 -0
- package/dist/prepare-entity-operations.d.ts.map +1 -0
- package/dist/prepare-entity-operations.js +117 -0
- package/dist/prepare-entity-operations.js.map +1 -0
- package/dist/store-editor.d.ts +12 -14
- package/dist/store-editor.d.ts.map +1 -1
- package/dist/store-editor.js +42 -0
- package/dist/store-editor.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutable-overlay-state.d.ts","sourceRoot":"","sources":["../src/mutable-overlay-state.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EACpF,kBAAkB,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG9D;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,KAAK,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAClE,eAAe,EAAE,KAAK,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAClE,gBAAgB,EAAE,KAAK,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC;IACpE,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,IAAI,CAAC;IACvD,YAAY,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACxC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,IAAI,CAAC;IAC1C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,IAAI,CAAC;IAC1C,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,iFAAiF;IACjF,cAAc,EAAE,QAAQ,EAAE,CAAC;CAC5B;AAED,qFAAqF;AACrF,qBAAa,mBAAmB;IAC9B,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAa;IACvE,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAa;IACvE;;;;;;OAMG;IACH,SAAS,CAAC,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAa;IACrE,SAAS,CAAC,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAa;IACrE,SAAS,CAAC,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAa;IACtE,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAa;IAChD,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAa;IAChD,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAa;IACtE,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAa;IACtE,SAAS,CAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAa;IACzE,SAAS,CAAC,uBAAuB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAa;IAC3F,SAAS,CAAC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAa;IACrE,SAAS,CAAC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAa;IAC1D,SAAS,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAa;IAC9C;;;;;;;;OAQG;IACH,SAAS,CAAC,wBAAwB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAa;IAC5D;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,SAAS,CAAC,sBAAsB,EAAE,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAa;IAClF;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,CAAC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAa;IACzD,SAAS,CAAC,eAAe,EAAE,MAAM,CAAK;IACtC,SAAS,CAAC,eAAe,EAAE,QAAQ,EAAE,CAAM;IAE3C,2EAA2E;IAC3E,SAAS,CAAC,YAAY;;;;;;;;;;;;;;;;;;;;;IAwBtB,SAAS,CAAC,gBAAgB;;;;;;;;;;;;;;;;;;;;;IAI1B,SAAS,CAAC,mBAAmB,CAAC,KAAK,EAAE,UAAU,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,CAAC,GAAG,IAAI;IAI/F,SAAS,CAAC,mBAAmB,CAAC,KAAK,EAAE,UAAU,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,CAAC,GAAG,OAAO;CAGnG"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { sameOverlayValue } from './overlay-value-equality.js';
|
|
5
|
+
/** Internal mutable overlay state; source tables and extractors are never copied. */
|
|
6
|
+
export class MutableOverlayState {
|
|
7
|
+
propertyMutations = new Map();
|
|
8
|
+
quantityMutations = new Map();
|
|
9
|
+
/**
|
|
10
|
+
* Secondary indices: entityId → mutation keys for that entity.
|
|
11
|
+
*
|
|
12
|
+
* `getForEntity` previously iterated the entire `propertyMutations` /
|
|
13
|
+
* `quantityMutations` map per pset to find newly-added properties — O(M·P)
|
|
14
|
+
* per call. These indices keep that step O(M_entity) instead.
|
|
15
|
+
*/
|
|
16
|
+
propertyKeysByEntity = new Map();
|
|
17
|
+
quantityKeysByEntity = new Map();
|
|
18
|
+
attributeKeysByEntity = new Map();
|
|
19
|
+
deletedPsets = new Set(); // `${entityId}:${psetName}`
|
|
20
|
+
deletedQsets = new Set(); // `${entityId}:${qsetName}`
|
|
21
|
+
newPsets = new Map(); // entityId -> psetName -> PropertySet
|
|
22
|
+
newQsets = new Map(); // entityId -> qsetName -> QuantitySet
|
|
23
|
+
attributeMutations = new Map(); // `${entityId}:attr:${attrName}`
|
|
24
|
+
positionalAttrMutations = new Map(); // entityId -> argIndex -> value
|
|
25
|
+
typeMutations = new Map(); // entityId -> retype intent
|
|
26
|
+
newEntities = new Map();
|
|
27
|
+
tombstones = new Set();
|
|
28
|
+
/**
|
|
29
|
+
* Ids `createEntity` allocated and `deleteEntity` then forgot (removed from
|
|
30
|
+
* `newEntities`, per that method's "existing entities are tombstoned; new
|
|
31
|
+
* entities are simply forgotten" contract). Tracked separately so
|
|
32
|
+
* `getEffectiveChanges()` / `collectEffectiveChanges` can tell "overlay-created
|
|
33
|
+
* then forgotten" apart from "an ordinary source-buffer entity" — both are
|
|
34
|
+
* otherwise indistinguishable, being simply absent from `newEntities`.
|
|
35
|
+
* `restoreNewEntity` (the undo-of-delete counterpart) clears the id back out.
|
|
36
|
+
*/
|
|
37
|
+
forgottenCreatedEntities = new Set();
|
|
38
|
+
/**
|
|
39
|
+
* Snapshot of a forgotten-created entity's overlay rows, stashed by
|
|
40
|
+
* `deleteEntity` and restored by `restoreNewEntity`.
|
|
41
|
+
*
|
|
42
|
+
* `deleteEntity` on an overlay-created entity does more than drop it from
|
|
43
|
+
* `newEntities` — it also PURGES every other overlay entry the entity left
|
|
44
|
+
* behind (property/quantity/attribute/positional/type mutations, its
|
|
45
|
+
* `newPsets`/`newQsets` entries, and its own `mutationHistory` records).
|
|
46
|
+
* Without that purge, an entity that was created, edited, then deleted
|
|
47
|
+
* before export left a dangling reference: `StepExporter` derives its
|
|
48
|
+
* property/quantity work list from `getMutations()` (the append-only
|
|
49
|
+
* history) and reads `getForEntity()` / `getQuantitiesForEntity()` straight
|
|
50
|
+
* off `newPsets` / `newQsets` — neither of which the review-side
|
|
51
|
+
* `forgottenCreatedEntities` filter in `effective-changes.ts` touches. The
|
|
52
|
+
* review dialog looked clean while the exported file still contained an
|
|
53
|
+
* `IFCPROPERTYSET` + `IFCRELDEFINESBYPROPERTIES` pointing at an expressId
|
|
54
|
+
* that was never actually created (maintainer finding on #1967).
|
|
55
|
+
*
|
|
56
|
+
* The purged data is captured here, not discarded, because `restoreNewEntity`
|
|
57
|
+
* (undo of the delete) must bring it all back — rows AND count AND what the
|
|
58
|
+
* exporter would see — not just re-add the bare `NewEntity` record.
|
|
59
|
+
*/
|
|
60
|
+
forgottenEntityOverlay = new Map();
|
|
61
|
+
/**
|
|
62
|
+
* Overlay-entity → source-entity aliases for property/quantity reads.
|
|
63
|
+
*
|
|
64
|
+
* When the viewer duplicates an existing entity, the new entity has
|
|
65
|
+
* no row in the parsed property table — `getBasePropertiesForEntity`
|
|
66
|
+
* would return `[]` and the property panel would show "No property
|
|
67
|
+
* sets". Aliasing redirects the BASE read to the source entity so
|
|
68
|
+
* the duplicate inherits its psets / qsets visually, while overlay
|
|
69
|
+
* mutations (overrides, creates, deletes) stay scoped to the
|
|
70
|
+
* overlay-entity's own id — so editing a property on the duplicate
|
|
71
|
+
* doesn't bleed into the source.
|
|
72
|
+
*
|
|
73
|
+
* Aliases follow at most one hop (no chains). They never affect
|
|
74
|
+
* STEP export — the export overlay emits the duplicate exactly as
|
|
75
|
+
* the StoreEditor recorded it, with whatever new IfcRel*ByProperties
|
|
76
|
+
* the caller chose to add.
|
|
77
|
+
*/
|
|
78
|
+
entityAliases = new Map();
|
|
79
|
+
nextAllocatedId = 0;
|
|
80
|
+
mutationHistory = [];
|
|
81
|
+
/** Borrowed only for synchronous comparison; never returned to callers. */
|
|
82
|
+
overlayState() {
|
|
83
|
+
return {
|
|
84
|
+
propertyMutations: this.propertyMutations,
|
|
85
|
+
quantityMutations: this.quantityMutations,
|
|
86
|
+
propertyKeysByEntity: this.propertyKeysByEntity,
|
|
87
|
+
quantityKeysByEntity: this.quantityKeysByEntity,
|
|
88
|
+
attributeKeysByEntity: this.attributeKeysByEntity,
|
|
89
|
+
deletedPsets: this.deletedPsets,
|
|
90
|
+
deletedQsets: this.deletedQsets,
|
|
91
|
+
newPsets: this.newPsets,
|
|
92
|
+
newQsets: this.newQsets,
|
|
93
|
+
attributeMutations: this.attributeMutations,
|
|
94
|
+
positionalAttrMutations: this.positionalAttrMutations,
|
|
95
|
+
typeMutations: this.typeMutations,
|
|
96
|
+
newEntities: this.newEntities,
|
|
97
|
+
tombstones: this.tombstones,
|
|
98
|
+
forgottenCreatedEntities: this.forgottenCreatedEntities,
|
|
99
|
+
forgottenEntityOverlay: this.forgottenEntityOverlay,
|
|
100
|
+
entityAliases: this.entityAliases,
|
|
101
|
+
nextAllocatedId: this.nextAllocatedId,
|
|
102
|
+
mutationHistory: this.mutationHistory,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
copyOverlayState() {
|
|
106
|
+
return structuredClone(this.overlayState());
|
|
107
|
+
}
|
|
108
|
+
restoreOverlayState(state) {
|
|
109
|
+
Object.assign(this, state);
|
|
110
|
+
}
|
|
111
|
+
matchesOverlayState(state) {
|
|
112
|
+
return sameOverlayValue(this.overlayState(), state);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=mutable-overlay-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutable-overlay-state.js","sourceRoot":"","sources":["../src/mutable-overlay-state.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAyB/D,qFAAqF;AACrF,MAAM,OAAO,mBAAmB;IACpB,iBAAiB,GAAkC,IAAI,GAAG,EAAE,CAAC;IAC7D,iBAAiB,GAAkC,IAAI,GAAG,EAAE,CAAC;IACvE;;;;;;OAMG;IACO,oBAAoB,GAA6B,IAAI,GAAG,EAAE,CAAC;IAC3D,oBAAoB,GAA6B,IAAI,GAAG,EAAE,CAAC;IAC3D,qBAAqB,GAA6B,IAAI,GAAG,EAAE,CAAC;IAC5D,YAAY,GAAgB,IAAI,GAAG,EAAE,CAAC,CAAC,4BAA4B;IACnE,YAAY,GAAgB,IAAI,GAAG,EAAE,CAAC,CAAC,4BAA4B;IACnE,QAAQ,GAA0C,IAAI,GAAG,EAAE,CAAC,CAAC,sCAAsC;IACnG,QAAQ,GAA0C,IAAI,GAAG,EAAE,CAAC,CAAC,sCAAsC;IACnG,kBAAkB,GAAmC,IAAI,GAAG,EAAE,CAAC,CAAC,iCAAiC;IACjG,uBAAuB,GAAgD,IAAI,GAAG,EAAE,CAAC,CAAC,gCAAgC;IAClH,aAAa,GAAoC,IAAI,GAAG,EAAE,CAAC,CAAC,4BAA4B;IACxF,WAAW,GAA2B,IAAI,GAAG,EAAE,CAAC;IAChD,UAAU,GAAgB,IAAI,GAAG,EAAE,CAAC;IAC9C;;;;;;;;OAQG;IACO,wBAAwB,GAAgB,IAAI,GAAG,EAAE,CAAC;IAC5D;;;;;;;;;;;;;;;;;;;;;OAqBG;IACO,sBAAsB,GAAwC,IAAI,GAAG,EAAE,CAAC;IAClF;;;;;;;;;;;;;;;;OAgBG;IACO,aAAa,GAAwB,IAAI,GAAG,EAAE,CAAC;IAC/C,eAAe,GAAW,CAAC,CAAC;IAC5B,eAAe,GAAe,EAAE,CAAC;IAE3C,2EAA2E;IACjE,YAAY;QACpB,OAAO;YACL,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;YACzC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;YACzC,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;YAC/C,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;YAC/C,qBAAqB,EAAE,IAAI,CAAC,qBAAqB;YACjD,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;YAC3C,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;YACrD,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,wBAAwB,EAAE,IAAI,CAAC,wBAAwB;YACvD,sBAAsB,EAAE,IAAI,CAAC,sBAAsB;YACnD,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,eAAe,EAAE,IAAI,CAAC,eAAe;SACtC,CAAC;IACJ,CAAC;IAES,gBAAgB;QACxB,OAAO,eAAe,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;IAC9C,CAAC;IAES,mBAAmB,CAAC,KAA0D;QACtF,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAES,mBAAmB,CAAC,KAA0D;QACtF,OAAO,gBAAgB,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;CACF"}
|
|
@@ -1,16 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mutable property view - overlay pattern for property mutations
|
|
3
|
-
*
|
|
4
|
-
* This class provides a mutable view over an immutable PropertyTable.
|
|
5
|
-
* Changes are tracked separately and applied on-the-fly during reads.
|
|
6
|
-
*
|
|
7
|
-
* Supports both pre-built property tables and on-demand property extraction
|
|
8
|
-
* for optimal performance with large models.
|
|
9
|
-
*/
|
|
10
1
|
import type { PropertyTable, PropertySet, QuantitySet } from '@ifc-lite/data';
|
|
11
2
|
import { PropertyValueType, QuantityType } from '@ifc-lite/data';
|
|
12
3
|
import type { IfcAttributeValue, PropertyValue, PropertyMutation, EntityTypeMutation, Mutation, NewEntity, EffectiveChange } from './types.js';
|
|
13
4
|
import { type AttributeExtractor } from './effective-changes.js';
|
|
5
|
+
import { MutableOverlayState } from './mutable-overlay-state.js';
|
|
14
6
|
export type { AttributeExtractor } from './effective-changes.js';
|
|
15
7
|
/**
|
|
16
8
|
* Function type for on-demand property extraction
|
|
@@ -30,87 +22,33 @@ export type PropertyExtractor = (entityId: number) => Array<{
|
|
|
30
22
|
* Function type for on-demand quantity extraction
|
|
31
23
|
*/
|
|
32
24
|
export type QuantityExtractor = (entityId: number) => QuantitySet[];
|
|
33
|
-
export declare class MutablePropertyView {
|
|
25
|
+
export declare class MutablePropertyView extends MutableOverlayState {
|
|
34
26
|
private baseTable;
|
|
35
27
|
private onDemandExtractor;
|
|
36
28
|
private quantityExtractor;
|
|
37
29
|
private attributeExtractor;
|
|
38
|
-
private propertyMutations;
|
|
39
|
-
private quantityMutations;
|
|
40
|
-
/**
|
|
41
|
-
* Secondary indices: entityId → mutation keys for that entity.
|
|
42
|
-
*
|
|
43
|
-
* `getForEntity` previously iterated the entire `propertyMutations` /
|
|
44
|
-
* `quantityMutations` map per pset to find newly-added properties — O(M·P)
|
|
45
|
-
* per call. These indices keep that step O(M_entity) instead.
|
|
46
|
-
*/
|
|
47
|
-
private propertyKeysByEntity;
|
|
48
|
-
private quantityKeysByEntity;
|
|
49
|
-
private attributeKeysByEntity;
|
|
50
|
-
private deletedPsets;
|
|
51
|
-
private deletedQsets;
|
|
52
|
-
private newPsets;
|
|
53
|
-
private newQsets;
|
|
54
|
-
private attributeMutations;
|
|
55
|
-
private positionalAttrMutations;
|
|
56
|
-
private typeMutations;
|
|
57
|
-
private newEntities;
|
|
58
|
-
private tombstones;
|
|
59
|
-
/**
|
|
60
|
-
* Ids `createEntity` allocated and `deleteEntity` then forgot (removed from
|
|
61
|
-
* `newEntities`, per that method's "existing entities are tombstoned; new
|
|
62
|
-
* entities are simply forgotten" contract). Tracked separately so
|
|
63
|
-
* `getEffectiveChanges()` / `collectEffectiveChanges` can tell "overlay-created
|
|
64
|
-
* then forgotten" apart from "an ordinary source-buffer entity" — both are
|
|
65
|
-
* otherwise indistinguishable, being simply absent from `newEntities`.
|
|
66
|
-
* `restoreNewEntity` (the undo-of-delete counterpart) clears the id back out.
|
|
67
|
-
*/
|
|
68
|
-
private forgottenCreatedEntities;
|
|
69
|
-
/**
|
|
70
|
-
* Snapshot of a forgotten-created entity's overlay rows, stashed by
|
|
71
|
-
* `deleteEntity` and restored by `restoreNewEntity`.
|
|
72
|
-
*
|
|
73
|
-
* `deleteEntity` on an overlay-created entity does more than drop it from
|
|
74
|
-
* `newEntities` — it also PURGES every other overlay entry the entity left
|
|
75
|
-
* behind (property/quantity/attribute/positional/type mutations, its
|
|
76
|
-
* `newPsets`/`newQsets` entries, and its own `mutationHistory` records).
|
|
77
|
-
* Without that purge, an entity that was created, edited, then deleted
|
|
78
|
-
* before export left a dangling reference: `StepExporter` derives its
|
|
79
|
-
* property/quantity work list from `getMutations()` (the append-only
|
|
80
|
-
* history) and reads `getForEntity()` / `getQuantitiesForEntity()` straight
|
|
81
|
-
* off `newPsets` / `newQsets` — neither of which the review-side
|
|
82
|
-
* `forgottenCreatedEntities` filter in `effective-changes.ts` touches. The
|
|
83
|
-
* review dialog looked clean while the exported file still contained an
|
|
84
|
-
* `IFCPROPERTYSET` + `IFCRELDEFINESBYPROPERTIES` pointing at an expressId
|
|
85
|
-
* that was never actually created (maintainer finding on #1967).
|
|
86
|
-
*
|
|
87
|
-
* The purged data is captured here, not discarded, because `restoreNewEntity`
|
|
88
|
-
* (undo of the delete) must bring it all back — rows AND count AND what the
|
|
89
|
-
* exporter would see — not just re-add the bare `NewEntity` record.
|
|
90
|
-
*/
|
|
91
|
-
private forgottenEntityOverlay;
|
|
92
|
-
/**
|
|
93
|
-
* Overlay-entity → source-entity aliases for property/quantity reads.
|
|
94
|
-
*
|
|
95
|
-
* When the viewer duplicates an existing entity, the new entity has
|
|
96
|
-
* no row in the parsed property table — `getBasePropertiesForEntity`
|
|
97
|
-
* would return `[]` and the property panel would show "No property
|
|
98
|
-
* sets". Aliasing redirects the BASE read to the source entity so
|
|
99
|
-
* the duplicate inherits its psets / qsets visually, while overlay
|
|
100
|
-
* mutations (overrides, creates, deletes) stay scoped to the
|
|
101
|
-
* overlay-entity's own id — so editing a property on the duplicate
|
|
102
|
-
* doesn't bleed into the source.
|
|
103
|
-
*
|
|
104
|
-
* Aliases follow at most one hop (no chains). They never affect
|
|
105
|
-
* STEP export — the export overlay emits the duplicate exactly as
|
|
106
|
-
* the StoreEditor recorded it, with whatever new IfcRel*ByProperties
|
|
107
|
-
* the caller chose to add.
|
|
108
|
-
*/
|
|
109
|
-
private entityAliases;
|
|
110
|
-
private nextAllocatedId;
|
|
111
|
-
private mutationHistory;
|
|
112
30
|
private modelId;
|
|
113
31
|
constructor(baseTable: PropertyTable | null, modelId: string);
|
|
32
|
+
/**
|
|
33
|
+
* Stage synchronous overlay edits and publish them together (#4243).
|
|
34
|
+
* Throws leave the original overlay, history and allocator untouched.
|
|
35
|
+
* Source tables/extractors are shared read-only; mutable state is detached
|
|
36
|
+
* both before editing and on commit, so an escaped draft cannot edit this view.
|
|
37
|
+
* External effects (files, renderer or network) belong outside this callback.
|
|
38
|
+
*/
|
|
39
|
+
runAtomic<T>(edit: (draft: MutablePropertyView) => T): T;
|
|
40
|
+
/**
|
|
41
|
+
* Prepare an overlay publication without changing live IFC state (#4243).
|
|
42
|
+
* Use for commands that must validate other synchronous resources first.
|
|
43
|
+
* `validate` and `commit` reject intervening edits, including skip-history
|
|
44
|
+
* edits. Commit is idempotent; the prepared draft is never published by reference.
|
|
45
|
+
*/
|
|
46
|
+
prepareAtomic<T>(edit: (draft: MutablePropertyView) => T): {
|
|
47
|
+
result: T;
|
|
48
|
+
validate(): void;
|
|
49
|
+
commit(): void;
|
|
50
|
+
rollback(): void;
|
|
51
|
+
};
|
|
114
52
|
/**
|
|
115
53
|
* Seed the express-ID allocator. Should be called once after parsing with
|
|
116
54
|
* the highest existing expressId in the store; subsequent `createEntity`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mutable-property-view.d.ts","sourceRoot":"","sources":["../src/mutable-property-view.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mutable-property-view.d.ts","sourceRoot":"","sources":["../src/mutable-property-view.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* Mutable property view - overlay pattern for property mutations
|
|
6
|
+
*
|
|
7
|
+
* This class provides a mutable view over an immutable PropertyTable.
|
|
8
|
+
* Changes are tracked separately and applied on-the-fly during reads.
|
|
9
|
+
*
|
|
10
|
+
* Supports both pre-built property tables and on-demand property extraction
|
|
11
|
+
* for optimal performance with large models.
|
|
12
|
+
*/
|
|
13
|
+
import { registerCooperativeOverlay } from './cooperative-overlay-access.js';
|
|
4
14
|
import { findQuantityInBaseSets } from './base-qset-lookup.js';
|
|
5
15
|
import { computeSetClaims, mutatedMembersForInstance } from './same-name-set-claims.js';
|
|
6
16
|
import { encodeNonFiniteNumbers, decodeNonFiniteNumbers } from './nonfinite-json.js';
|
|
@@ -8,89 +18,90 @@ import { PropertyValueType, QuantityType } from '@ifc-lite/data';
|
|
|
8
18
|
import { propertyKey, quantityKey, attributeKey, generateMutationId } from './types.js';
|
|
9
19
|
import { collectEffectiveChanges } from './effective-changes.js';
|
|
10
20
|
import { applyMutationsBatch } from './apply-mutations.js';
|
|
11
|
-
|
|
21
|
+
import { MutableOverlayState } from './mutable-overlay-state.js';
|
|
22
|
+
export class MutablePropertyView extends MutableOverlayState {
|
|
12
23
|
baseTable;
|
|
13
24
|
onDemandExtractor = null;
|
|
14
25
|
quantityExtractor = null;
|
|
15
26
|
attributeExtractor = null;
|
|
16
|
-
propertyMutations = new Map();
|
|
17
|
-
quantityMutations = new Map();
|
|
18
|
-
/**
|
|
19
|
-
* Secondary indices: entityId → mutation keys for that entity.
|
|
20
|
-
*
|
|
21
|
-
* `getForEntity` previously iterated the entire `propertyMutations` /
|
|
22
|
-
* `quantityMutations` map per pset to find newly-added properties — O(M·P)
|
|
23
|
-
* per call. These indices keep that step O(M_entity) instead.
|
|
24
|
-
*/
|
|
25
|
-
propertyKeysByEntity = new Map();
|
|
26
|
-
quantityKeysByEntity = new Map();
|
|
27
|
-
attributeKeysByEntity = new Map();
|
|
28
|
-
deletedPsets = new Set(); // `${entityId}:${psetName}`
|
|
29
|
-
deletedQsets = new Set(); // `${entityId}:${qsetName}`
|
|
30
|
-
newPsets = new Map(); // entityId -> psetName -> PropertySet
|
|
31
|
-
newQsets = new Map(); // entityId -> qsetName -> QuantitySet
|
|
32
|
-
attributeMutations = new Map(); // `${entityId}:attr:${attrName}`
|
|
33
|
-
positionalAttrMutations = new Map(); // entityId -> argIndex -> value
|
|
34
|
-
typeMutations = new Map(); // entityId -> retype intent
|
|
35
|
-
newEntities = new Map();
|
|
36
|
-
tombstones = new Set();
|
|
37
|
-
/**
|
|
38
|
-
* Ids `createEntity` allocated and `deleteEntity` then forgot (removed from
|
|
39
|
-
* `newEntities`, per that method's "existing entities are tombstoned; new
|
|
40
|
-
* entities are simply forgotten" contract). Tracked separately so
|
|
41
|
-
* `getEffectiveChanges()` / `collectEffectiveChanges` can tell "overlay-created
|
|
42
|
-
* then forgotten" apart from "an ordinary source-buffer entity" — both are
|
|
43
|
-
* otherwise indistinguishable, being simply absent from `newEntities`.
|
|
44
|
-
* `restoreNewEntity` (the undo-of-delete counterpart) clears the id back out.
|
|
45
|
-
*/
|
|
46
|
-
forgottenCreatedEntities = new Set();
|
|
47
|
-
/**
|
|
48
|
-
* Snapshot of a forgotten-created entity's overlay rows, stashed by
|
|
49
|
-
* `deleteEntity` and restored by `restoreNewEntity`.
|
|
50
|
-
*
|
|
51
|
-
* `deleteEntity` on an overlay-created entity does more than drop it from
|
|
52
|
-
* `newEntities` — it also PURGES every other overlay entry the entity left
|
|
53
|
-
* behind (property/quantity/attribute/positional/type mutations, its
|
|
54
|
-
* `newPsets`/`newQsets` entries, and its own `mutationHistory` records).
|
|
55
|
-
* Without that purge, an entity that was created, edited, then deleted
|
|
56
|
-
* before export left a dangling reference: `StepExporter` derives its
|
|
57
|
-
* property/quantity work list from `getMutations()` (the append-only
|
|
58
|
-
* history) and reads `getForEntity()` / `getQuantitiesForEntity()` straight
|
|
59
|
-
* off `newPsets` / `newQsets` — neither of which the review-side
|
|
60
|
-
* `forgottenCreatedEntities` filter in `effective-changes.ts` touches. The
|
|
61
|
-
* review dialog looked clean while the exported file still contained an
|
|
62
|
-
* `IFCPROPERTYSET` + `IFCRELDEFINESBYPROPERTIES` pointing at an expressId
|
|
63
|
-
* that was never actually created (maintainer finding on #1967).
|
|
64
|
-
*
|
|
65
|
-
* The purged data is captured here, not discarded, because `restoreNewEntity`
|
|
66
|
-
* (undo of the delete) must bring it all back — rows AND count AND what the
|
|
67
|
-
* exporter would see — not just re-add the bare `NewEntity` record.
|
|
68
|
-
*/
|
|
69
|
-
forgottenEntityOverlay = new Map();
|
|
70
|
-
/**
|
|
71
|
-
* Overlay-entity → source-entity aliases for property/quantity reads.
|
|
72
|
-
*
|
|
73
|
-
* When the viewer duplicates an existing entity, the new entity has
|
|
74
|
-
* no row in the parsed property table — `getBasePropertiesForEntity`
|
|
75
|
-
* would return `[]` and the property panel would show "No property
|
|
76
|
-
* sets". Aliasing redirects the BASE read to the source entity so
|
|
77
|
-
* the duplicate inherits its psets / qsets visually, while overlay
|
|
78
|
-
* mutations (overrides, creates, deletes) stay scoped to the
|
|
79
|
-
* overlay-entity's own id — so editing a property on the duplicate
|
|
80
|
-
* doesn't bleed into the source.
|
|
81
|
-
*
|
|
82
|
-
* Aliases follow at most one hop (no chains). They never affect
|
|
83
|
-
* STEP export — the export overlay emits the duplicate exactly as
|
|
84
|
-
* the StoreEditor recorded it, with whatever new IfcRel*ByProperties
|
|
85
|
-
* the caller chose to add.
|
|
86
|
-
*/
|
|
87
|
-
entityAliases = new Map();
|
|
88
|
-
nextAllocatedId = 0;
|
|
89
|
-
mutationHistory = [];
|
|
90
27
|
modelId;
|
|
91
28
|
constructor(baseTable, modelId) {
|
|
29
|
+
super();
|
|
92
30
|
this.baseTable = baseTable;
|
|
93
31
|
this.modelId = modelId;
|
|
32
|
+
registerCooperativeOverlay(this, {
|
|
33
|
+
capture: () => this.overlayState(),
|
|
34
|
+
matches: snapshot => this.matchesOverlayState(snapshot),
|
|
35
|
+
publish: snapshot => this.restoreOverlayState(snapshot),
|
|
36
|
+
draft: snapshot => {
|
|
37
|
+
const draft = new MutablePropertyView(this.baseTable, this.modelId);
|
|
38
|
+
draft.onDemandExtractor = this.onDemandExtractor;
|
|
39
|
+
draft.quantityExtractor = this.quantityExtractor;
|
|
40
|
+
draft.attributeExtractor = this.attributeExtractor;
|
|
41
|
+
draft.restoreOverlayState(snapshot);
|
|
42
|
+
return draft;
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Stage synchronous overlay edits and publish them together (#4243).
|
|
48
|
+
* Throws leave the original overlay, history and allocator untouched.
|
|
49
|
+
* Source tables/extractors are shared read-only; mutable state is detached
|
|
50
|
+
* both before editing and on commit, so an escaped draft cannot edit this view.
|
|
51
|
+
* External effects (files, renderer or network) belong outside this callback.
|
|
52
|
+
*/
|
|
53
|
+
runAtomic(edit) {
|
|
54
|
+
const prepared = this.prepareAtomic(edit);
|
|
55
|
+
prepared.commit();
|
|
56
|
+
return prepared.result;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Prepare an overlay publication without changing live IFC state (#4243).
|
|
60
|
+
* Use for commands that must validate other synchronous resources first.
|
|
61
|
+
* `validate` and `commit` reject intervening edits, including skip-history
|
|
62
|
+
* edits. Commit is idempotent; the prepared draft is never published by reference.
|
|
63
|
+
*/
|
|
64
|
+
prepareAtomic(edit) {
|
|
65
|
+
const original = this.copyOverlayState();
|
|
66
|
+
const draft = new MutablePropertyView(this.baseTable, this.modelId);
|
|
67
|
+
draft.onDemandExtractor = this.onDemandExtractor;
|
|
68
|
+
draft.quantityExtractor = this.quantityExtractor;
|
|
69
|
+
draft.attributeExtractor = this.attributeExtractor;
|
|
70
|
+
draft.restoreOverlayState(structuredClone(original));
|
|
71
|
+
const result = edit(draft);
|
|
72
|
+
if (result !== null && (typeof result === 'object' || typeof result === 'function')
|
|
73
|
+
&& 'then' in result && typeof result.then === 'function') {
|
|
74
|
+
void Promise.resolve(result).catch(error => console.error('Discarded asynchronous overlay transaction failed', error));
|
|
75
|
+
throw new TypeError('Overlay transactions must be synchronous; prepare asynchronous work before editing');
|
|
76
|
+
}
|
|
77
|
+
const prepared = draft.copyOverlayState();
|
|
78
|
+
// Keep the rollback checkpoint detached from maps published to live readers.
|
|
79
|
+
const publication = structuredClone(prepared);
|
|
80
|
+
let committed = false;
|
|
81
|
+
let rolledBack = false;
|
|
82
|
+
const validate = () => {
|
|
83
|
+
if (rolledBack)
|
|
84
|
+
throw new Error('The prepared IFC transaction was rolled back.');
|
|
85
|
+
if (!committed && !this.matchesOverlayState(original))
|
|
86
|
+
throw new Error('The IFC overlay changed during a prepared transaction.');
|
|
87
|
+
};
|
|
88
|
+
validate(); // A callback that re-enters the original view cannot erase that edit.
|
|
89
|
+
return { result, validate, commit: () => {
|
|
90
|
+
if (rolledBack)
|
|
91
|
+
throw new Error('The prepared IFC transaction was rolled back.');
|
|
92
|
+
if (committed)
|
|
93
|
+
return;
|
|
94
|
+
validate();
|
|
95
|
+
this.restoreOverlayState(publication);
|
|
96
|
+
committed = true;
|
|
97
|
+
}, rollback: () => {
|
|
98
|
+
if (!committed || rolledBack)
|
|
99
|
+
return;
|
|
100
|
+
if (!this.matchesOverlayState(prepared))
|
|
101
|
+
throw new Error('The IFC overlay changed after the prepared transaction committed.');
|
|
102
|
+
this.restoreOverlayState(original);
|
|
103
|
+
rolledBack = true;
|
|
104
|
+
} };
|
|
94
105
|
}
|
|
95
106
|
/**
|
|
96
107
|
* Seed the express-ID allocator. Should be called once after parsing with
|