Frontmatter
| id | 8472 |
| title | Implement Lazy VDOM Cloning in Component Base |
| state | Closed |
| labels | bugairefactoringcore |
| assignees | tobiu |
| createdAt | Jan 9, 2026, 5:25 PM |
| updatedAt | Jan 9, 2026, 5:33 PM |
| githubUrl | https://github.com/neomjs/neo/issues/8472 |
| author | tobiu |
| commentsCount | 1 |
| parentIssue | 8469 |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Jan 9, 2026, 5:33 PM |
Implement Lazy VDOM Cloning in Component Base
tobiu added parent issue #8469 on Jan 9, 2026, 5:26 PM
tobiu assigned to @tobiu on Jan 9, 2026, 5:32 PM

tobiu
Jan 9, 2026, 5:32 PM
Input from Gemini 3 Pro:
✦ I have implemented the lazy VDOM cloning mechanism in
src/component/Base.mjs.Changes:
- Modified the
vdomgetter to check forObject.hasOwn(this, '_vdom'). If missing, it immediately clones the prototype's_vdomto the instance.- This ensures that any early access to
this.vdom(e.g., inafterSetIdbeforeinitConfig) operates on a safe instance copy, preventing prototype pollution.Verification:
- Added a new regression test:
test/playwright/unit/component/Base_PrototypePollution.spec.mjs.- The test explicitly reproduces the "early access" pattern and verifies that subsequent instances do not inherit the mutated VDOM ID.
- Ran existing VDOM tests (
AutoId.spec.mjsandbutton/Base.spec.mjs) to ensure no regressions. All passed.Commit: 64cdb7694 (#8472)
tobiu closed this issue on Jan 9, 2026, 5:33 PM
tobiu cross-referenced by #8474 on Jan 9, 2026, 5:42 PM
Context:
Neo.core.Baseassigns an instance ID early in the constructor, triggeringafterSetId. InNeo.component.Base,afterSetIdcallsensureStableIds, which accessesthis.vdom. SinceinitConfig(andmergeConfig) has not yet run,this.vdomreturns the prototype's_vdomreference. Modifying this object (asensureStableIdsdoes) causes prototype pollution, affecting all subsequent instances of the class.Goal: Modify the
vdomgetter insrc/component/Base.mjsto implement lazy cloning.this._vdomis an own property (usingObject.hasOwn)._vdomonto the instance immediately.mergeConfigto respect this lazy initialization (avoid double cloning if already done).Verification: Add a regression test in
test/playwright/unit/component/Base_PrototypePollution.spec.mjsthat verifies: