From fca73dd344fb3d37cbfe4a6bf25296e496fdaa84 Mon Sep 17 00:00:00 2001 From: Wilhelm Behncke Date: Mon, 20 May 2024 17:44:18 +0200 Subject: [PATCH] BUGFIX: Remove race condition in `watchNodeInformationChanges` It may happen that `fetchAdditionalNodeMetadata` adds metadata for a node that has since been removed from the store. The occurance of such "zombie" nodes leads to problems, because they may lack crucial properties like `children` that are treated as always- present by other mechanisms throughout the UI. This became apparent after https://github.com/neos/neos-ui/pull/3756. The CR.Nodes.MERGE action now takes care of preventing zombie nodes from entering the store. --- packages/neos-ui-redux-store/src/CR/Nodes/index.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/neos-ui-redux-store/src/CR/Nodes/index.ts b/packages/neos-ui-redux-store/src/CR/Nodes/index.ts index 97618f7d74..759e3387f8 100644 --- a/packages/neos-ui-redux-store/src/CR/Nodes/index.ts +++ b/packages/neos-ui-redux-store/src/CR/Nodes/index.ts @@ -450,10 +450,16 @@ export const reducer = (state: State = defaultState, action: InitAction | EditPr if (!newNode) { throw new Error('This error should never be thrown, it\'s a way to fool TypeScript'); } - const mergedNode = defaultsDeep({}, newNode, draft.byContextPath[contextPath]); - // Force overwrite of children + const oldNode = state.byContextPath[contextPath]; + const mergedNode = defaultsDeep({}, newNode, oldNode); if (newNode.children !== undefined) { + // Force overwrite of children mergedNode.children = newNode.children; + } else if (!oldNode) { + // newNode only adds meta info, but oldNode is gone from the store. + // In order to avoid zombie nodes occupying the store, we'll leave + // the node alone in this case. + return; } // Force overwrite of matchesCurrentDimensions if (newNode.matchesCurrentDimensions !== undefined) {