Frontmatter
| id | 9363 |
| title | Chrome Window Learn funktionale Komponenten |
| state | Closed |
| labels | bug |
| assignees | tobiu |
| createdAt | Mar 6, 2026, 10:39 AM |
| updatedAt | Mar 15, 2026, 2:42 PM |
| githubUrl | https://github.com/neomjs/neo/issues/9363 |
| author | kmunk-klarso |
| commentsCount | 4 |
| parentIssue | null |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Mar 15, 2026, 2:42 PM |
Chrome Window Learn funktionale Komponenten


Input from Gemini 3.1 Pro:
✦ ### AI Session Post-Mortem & Implementation Strategy
During the session investigating the live preview failures for functional components, we identified two distinct issues. Due to context bloat from excessive testing, we are documenting the findings here to continue cleanly in a fresh session.
1. The Executor Parsing Flaw (Resolved conceptually)
The
NeoExecutorwas failing to parseexport default MainView;because its regex expected a class or variable declaration (export default class...).The Agreed Solution (Hybrid Approach): Instead of relying on brittle regex to extract the
classNamestring to resolve the module viaNeo.ns(), we will modifyexecute()to intercept the explicit export:
- Update
exportRegexto^(\s*)export\s+(?:default\s+)?(.*)- Replace
export default MainView;withmodule = MainView;directly in the sandbox string.- This safely captures the exported module.
- Crucially: We must keep the legacy
classNameextraction as a fallback for the 50-100 classic live preview examples that do not use anexportstatement (e.g.MainView = Neo.setupClass(MainView);).2. The OOP Rendering Crash (The root cause of
includeserror)Even with the executor fixed, the functional component crashes with:
TypeError: Cannot read properties of undefined (reading 'includes')insideNeoArray.add().The Context:
createVdom(config) { return { ntype: 'container', // Creates an OOP Container layout: {ntype: 'vbox', align: 'start'}, // Creates an OOP Flexbox layout items: [...] } }The Bug:
FunctionalBase.mjs -> processVdomForComponentsdetectsntype: 'container'and instantiates a classic OOP container, passing the raw VDOM object as its configuration.- The OOP Container initializes its
vboxlayout (Flexbox.mjs).Flexbox.applyRenderAttributes()reads{wrapperCls} = container;and tries to add classes to it usingNeoArray.add(wrapperCls, prefix + 'container');.- Because the raw VDOM object provided by
createVdomdid not explicitly define aclsarray, the dynamically instantiated OOP Container somehow ends up withwrapperClsbeingundefined(instead of falling back to the class's default empty array).Next Steps for Fresh Session:
- Implement the Hybrid Executor fix in
src/code/executor/Neo.mjs.- Investigate exactly why an OOP component instantiated via
Neo.ntype(vdomTree)loses its defaultwrapperClsarray if thevdomTreeomits it, while standardNeo.createcalls seemingly do not. The fix likely belongs in how configs/vdom are merged during instantiation withinprocessVdomForComponentsorcore/Base.mjs, not by hackingNeoArray.

Input from Gemini 3.1 Pro:
✦ Correction to the Post-Mortem (Rendering Crash):
My previous assessment of the
includescrash was flawed.When the functional component returns:
{ ntype: 'container', layout: {ntype: 'vbox'}, items: [...] }
processVdomForComponentsintercepts this and correctly instantiates a pure OOPContainer, passing this exact object as its configuration. From that point on, the OOP Container manages its own layout (Flexbox) and its own children (items-> OOPButton). The layout operations happen entirely within the standard OOP scope.If
wrapperClsisundefinedwhenFlexbox.applyRenderAttributes()runs, the bug is not because the functional component "forgot to provide a cls array in the VDOM". The bug is that something about this specific initialization pathway (Neo.ntype()being called with this specific configuration shape byprocessVdomForComponents) causes the resulting OOP Container to fail to initialize its own defaultvdomstructure properly.The next session should investigate how config merging and VDOM initialization differ when an OOP component is created dynamically via
FunctionalBaseversus a standard application startup.

Input from Gemini 3.1 Pro:
✦ I have completed the fixes for the functional component live preview edge cases.
- Guide Examples Updated: The examples in
learn/gettingstarted/DescribingTheUI.mdwere corrected to use a wrapper node (cn) instead of returning an OOP component (ntype: 'container') directly as the root of the functional component. This avoids the component ID clashing and preserves the functional component's own VDOM root correctly.- Missing Component Import: Changed the non-existent
Calendarimport in the interop example to useDateSelector, ensuring it works perfectly in live preview.- Unit Test Added: Created a rigorous Playwright unit test (
test/playwright/unit/functional/DuplicateIdBug.spec.mjs) that replicates the exact Live Preview teardown and re-creation flow, confirming the ID bug is resolved and ensuring no future regressions.All changes have been successfully committed and pushed to the repository.

Input from Gemini 3.1 Pro:
✦ Architectural Root Cause Analysis:
To clarify the exact nature of this bug: The core issue stemmed from a structural anti-pattern in the original examples. The functional components were returning a pure OOP component (e.g.,
ntype: 'container') directly as their absolute root node, without wrapping it in a standard HTML node (like an implicitdiv).Using a functional component purely as a passthrough to an OOP component is architecturally pointless, as the functional component lacks its own distinct DOM root. When the framework's
processVdomForComponentsmethod intercepted this, it replaced the functional component's entire rootvdomwith acreateVdomReference()pointer to the inner OOP component.During the aggressive re-render cycle triggered by Live Preview, this caused
Helper.mjsto crash during diffing, as the functional component'sidandvnodestructure completely mismatched the newly generated OOP container reference. By adjusting the examples to correctly wrap the OOP components in a standardcnarray, the functional component maintains its own isolated root, fully resolving the ID collision and diffing errors.