Skip to content

BUGFIX: Prevent infinite recursion in form element node label - #160

Open
signalwerk wants to merge 1 commit into
neos:mainfrom
signalwerk:bugfix/recursive-form-element-label
Open

signalwerk wants to merge 1 commit into
neos:mainfrom
signalwerk:bugfix/recursive-form-element-label

Conversation

@signalwerk

Copy link
Copy Markdown

Problem

Neos.Form.Builder:FormElement falls back to Neos.Node.label(node) when neither identifier nor label is set:

label: "${node.properties.identifier || node.properties.label || ((Neos.Node.label(node) || node.nodeTypeName) + ' (' + node.name + ')')}"

On Neos 9 that helper delegates to DelegatingNodeLabelRenderer, which looks up the node type's own label configuration and evaluates this very expression again — unbounded recursion until PHP aborts with Maximum call stack size … reached. Infinite recursion?. (The renderer guards against this for label.generatorClass, but not for the expression case.)

StaticText and Section set 'Neos.Form.Builder:IdentifierMixin': false, so any of them without an explicit label triggers it. Since the content tree renders a label for every node of the selected document, POST /neos/ui-services/flow-query fatals — a stack overflow, so no error page either — and the Neos UI content tree keeps spinning. The document cannot be edited at all.

Fix

Drop the self-referential call and inline the fallback the core itself uses for node types without a label expression (the anonymous generator in DelegatingNodeLabelRenderer::getDelegatedGenerator()):

label: "${node.properties.identifier || node.properties.label || (node.nodeTypeName.value + (node.name ? ' (' + node.name.value + ')' : ''))}"

This also repairs the concatenation itself: on Neos 9 node.nodeTypeName and node.name are value objects, and node.name is null for non-autocreated nodes.

Verified on Neos 9.1.5 / form-builder 3.0.5: labels for a document containing a form render again, elements that do have an identifier or a label are unchanged.

Note

This patch was written by an LLM (Claude), then verified against a Neos 9.1.5 installation. Please feel free to change the fallback, the comment or the wording if you prefer something else — the point is only to break the recursion.

The label expression of `Neos.Form.Builder:FormElement` fell back to
`Neos.Node.label(node)`. On Neos 9 that helper delegates to
`DelegatingNodeLabelRenderer`, which evaluates the node type's own label
expression again - so the expression calls itself until PHP aborts with
"Maximum call stack size reached. Infinite recursion?".

Every form element without an identifier and without a label is
affected; `StaticText` and `Section` disable the `IdentifierMixin`. As
the content tree renders a label for every node of a document, the
`/neos/ui-services/flow-query` request fatals and the Neos UI content
tree keeps spinning, leaving the document uneditable.

Use the fallback the core renders for node types without a label
expression instead: the node type name, plus the node name in
parentheses when the node has one.

@bwaidelich bwaidelich left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants