Fix issue with appState change detection

This commit is contained in:
Marcel Mraz 2025-04-30 12:26:27 +02:00
parent 09135e827e
commit becdbcb2d7
No known key found for this signature in database
GPG key ID: 4EBD6E62DC830CD2

View file

@ -105,7 +105,7 @@ export class Store {
action: CaptureUpdateActionType, action: CaptureUpdateActionType,
elements: SceneElementsMap | undefined, elements: SceneElementsMap | undefined,
appState: AppState | ObservedAppState | undefined = undefined, appState: AppState | ObservedAppState | undefined = undefined,
/** delta is only relevant for `CaptureUpdateAction.IMMEDIATELY`, as it's the only action producing `DurableStoreIncrement` containing a delta */ /** delta is only relevant for `CaptureUpdateAction.IMMEDIATELY`, as it's the only action producing `DurableStoreIncrement` containing a delta and it's also expected to be immutable! */
delta: StoreDelta | undefined = undefined, delta: StoreDelta | undefined = undefined,
) { ) {
// create a snapshot first, so that it couldn't mutate in the meantime // create a snapshot first, so that it couldn't mutate in the meantime
@ -135,21 +135,9 @@ export class Store {
this.flushMicroActions(); this.flushMicroActions();
try { try {
const macroAction = this.getScheduledMacroAction();
const nextSnapshot = this.maybeCloneSnapshot(
macroAction,
elements,
appState,
);
if (!nextSnapshot) {
// don't continue if there is not change detected
return;
}
// execute a single scheduled "macro" function // execute a single scheduled "macro" function
// similar to macro tasks, there can be only one within a single commit // similar to macro tasks, there can be only one within a single commit (loop)
this.executeAction(macroAction, nextSnapshot); this.processMacroAction(elements, appState);
} finally { } finally {
this.satisfiesScheduledActionsInvariant(); this.satisfiesScheduledActionsInvariant();
// defensively reset all scheduled "macro" actions, possibly cleans up other runtime garbage // defensively reset all scheduled "macro" actions, possibly cleans up other runtime garbage
@ -231,7 +219,7 @@ export class Store {
assertNever(action, `Unknown store action`); assertNever(action, `Unknown store action`);
} }
} finally { } finally {
// update the snpashot no-matter what, as it would mess up with the next action // update the snapshot no-matter what, as it would mess up with the next action
switch (action) { switch (action) {
// both immediately and never update the snapshot, unlike eventually // both immediately and never update the snapshot, unlike eventually
case CaptureUpdateAction.IMMEDIATELY: case CaptureUpdateAction.IMMEDIATELY:
@ -332,6 +320,27 @@ export class Store {
} }
} }
private processMacroAction(
elements: SceneElementsMap | undefined,
appState: AppState | ObservedAppState | undefined,
) {
const macroAction = this.getScheduledMacroAction();
const nextSnapshot = this.maybeCloneSnapshot(
macroAction,
elements,
appState,
);
if (!nextSnapshot) {
// don't continue if there is not change detected
return;
}
// execute a single scheduled "macro" function
// similar to macro tasks, there can be only one within a single commit
this.executeAction(macroAction, nextSnapshot);
}
/** /**
* Returns the scheduled macro action. * Returns the scheduled macro action.
*/ */
@ -747,7 +756,7 @@ export class StoreSnapshot {
return; return;
} }
this._lastChangedElementsHash = changedAppStateHash; this._lastChangedAppStateHash = changedAppStateHash;
return didAppStateChange; return didAppStateChange;
} }
@ -827,6 +836,7 @@ export class StoreSnapshot {
} }
for (const [id, changedElement] of changedElements) { for (const [id, changedElement] of changedElements) {
// TODO: consider just creating new instance, once we can ensure that all reference properties on every element are immutable
clonedElements.set(id, deepCopyElement(changedElement)); clonedElements.set(id, deepCopyElement(changedElement));
} }