LearnNewsExamplesServices
Frontmatter
id8574
titleAllow subclasses to override config descriptors in Neo.setupClass
stateClosed
labels
enhancementarchitecturecore
assigneestobiu
createdAtJan 12, 2026, 3:39 AM
updatedAtJan 12, 2026, 3:42 AM
githubUrlhttps://github.com/neomjs/neo/issues/8574
authortobiu
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJan 12, 2026, 3:42 AM

Allow subclasses to override config descriptors in Neo.setupClass

Closed v11.20.0 enhancementarchitecturecore
tobiu
tobiu commented on Jan 12, 2026, 3:39 AM

Neo.setupClass currently 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 use clone: 'deep' because the parent's descriptor takes precedence.

Proposed Change: Modify the merge logic in Neo.setupClass to 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 with clone: 'deep' active).

tobiu added the enhancement label on Jan 12, 2026, 3:39 AM
tobiu added the architecture label on Jan 12, 2026, 3:39 AM
tobiu added the core label on Jan 12, 2026, 3:39 AM
tobiu referenced in commit 038cf49 - "fix: Allow subclasses to override config descriptors in Neo.setupClass (#8574)" on Jan 12, 2026, 3:40 AM
tobiu
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:

  1. Core: Updated Neo.setupClass to allow subclasses to override config descriptors (merge strategy: last-defined wins for same key). This ensures clone: 'deep' defined in subclasses is respected even if parent defined clone: 'shallow'.
  2. Shared Containers: Added clone: 'deep' to the items descriptor in Shared.Container.mjs and PageContainer.mjs. This forces Neo.createConfig to deep-clone the shared static item definitions before assigning them to the instance, isolating them from mutation by beforeSetItems or parseItemConfigs.
  3. Recursion: mergeFrom implementation in parseItemConfigs is recursive and handles Object maps correctly.
  4. Verification: test/playwright/unit/core/ConfigMerging.spec.mjs now 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