Frontmatter
| id | 8574 |
| title | Allow subclasses to override config descriptors in Neo.setupClass |
| state | Closed |
| labels | enhancementarchitecturecore |
| assignees | tobiu |
| createdAt | Jan 12, 2026, 3:39 AM |
| updatedAt | Jan 12, 2026, 3:42 AM |
| githubUrl | https://github.com/neomjs/neo/issues/8574 |
| author | tobiu |
| commentsCount | 1 |
| parentIssue | null |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Jan 12, 2026, 3:42 AM |
Allow subclasses to override config descriptors in Neo.setupClass

tobiu
Jan 12, 2026, 3:41 AM
Input from Gemini 3 Pro:
✦ I have resolved the Prototype Pollution issue and verified it with unit tests.
Fix:
- Core: Updated
Neo.setupClassto allow subclasses to override config descriptors (merge strategy: last-defined wins for same key). This ensuresclone: 'deep'defined in subclasses is respected even if parent definedclone: 'shallow'.- Shared Containers: Added
clone: 'deep'to theitemsdescriptor inShared.Container.mjsandPageContainer.mjs. This forcesNeo.createConfigto deep-clone the shared static item definitions before assigning them to the instance, isolating them from mutation bybeforeSetItemsorparseItemConfigs.- Recursion:
mergeFromimplementation inparseItemConfigsis recursive and handles Object maps correctly.- Verification:
test/playwright/unit/core/ConfigMerging.spec.mjsnow passes all 4 tests, including strict pollution checks and nested object scenarios.This ensures that "switching views" (creating new instances) no longer results in cross-contamination of configuration state (e.g. empty toolbar or wrong tree config).
Closing as completed.
tobiu assigned to @tobiu on Jan 12, 2026, 3:41 AM
tobiu closed this issue on Jan 12, 2026, 3:42 AM
Neo.setupClasscurrently employs a "first-defined wins" strategy for merging configuration descriptors (configDescriptors). This prevents subclasses from overriding descriptors defined in parent classes.Problem: If a parent class (e.g.,
Neo.container.Base) defines a reactive config with a descriptor (e.g.,clone: 'shallow'), a subclass cannot override this to useclone: 'deep'because the parent's descriptor takes precedence.Proposed Change: Modify the merge logic in
Neo.setupClassto use a "last-defined wins" (or merge) strategy. If a subclass defines a descriptor for an existing key, it should be merged into the accumulated descriptor object, allowing overrides.Impact: This enables subclasses to refine configuration behaviors (like cloning strategies) without redefining the property entirely or being blocked by the base class.
Verified: Verified via
test/playwright/unit/core/ConfigMerging.spec.mjs(Prototype Pollution tests pass withclone: 'deep'active).