LearnNewsExamplesServices
Frontmatter
id11701
titlecollection.Base: isItem() treats null as an item
stateClosed
labels
bugaicore
assigneesneo-gpt
createdAtMay 21, 2026, 12:19 AM
updatedAtMay 21, 2026, 7:59 AM
githubUrlhttps://github.com/neomjs/neo/issues/11701
authorneo-gpt
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMay 21, 2026, 7:59 AM

collection.Base: isItem() treats null as an item

neo-gpt
neo-gpt commented on May 21, 2026, 12:19 AM

Context

Operator review on 2026-05-21 surfaced a small but real Neo.collection.Base edge case while discussing the current isItem() implementation:

isItem(value) {
    // We can not use Neo.isObject() || Neo.isRecord(), since collections can store neo instances too.
    return typeof value === 'object'
}

The broad typeof value === 'object' predicate correctly preserves the post-#5954 behavior for Neo instances, but it also classifies null as an item because JavaScript reports typeof null === 'object'.

The Problem

Neo.collection.Base#isItem(null) currently returns true. Callers such as splice() use isItem(item) ? me.getKey(item) : item when removing keyed entries. A null remove entry therefore routes into getKey(null), which can throw a TypeError instead of treating null as a non-item key/value or gracefully no-oping through the map lookup.

This is the same failure class surfaced during recent graph-cleanup work: a null-like value entering a collection removal path should not be promoted into object/item handling.

The Architectural Reality

  • src/collection/Base.mjs:1294 defines isItem(value) as typeof value === 'object'.
  • src/collection/Base.mjs:1483 uses isItem(item) during splice() removal to decide whether to call getKey(item).
  • Historical closed issue #5954 intentionally broadened isItem() because collections can store Neo instances, so this ticket must preserve broad object-like support.
  • Historical closed issue #5391 introduced the item-recognition helper for record/object handling. This ticket is not a reversion to Neo.isObject() / Neo.isRecord().
  • Historical closed issue #9311 handled sorting null/undefined behavior, but not item/key classification.

The Fix

Update Neo.collection.Base#isItem(value) to explicitly exclude null while retaining broad object-like instance support:

return value !== null && typeof value === 'object'

Add focused unit coverage under test/playwright/unit/collection/Base.spec.mjs or an adjacent collection unit spec proving:

  • collection.isItem(null) returns false.
  • Existing object-like/Neo-instance item behavior is preserved.
  • Removing null through a keyed removal path does not call getKey(null) / does not throw.

Acceptance Criteria

  • Neo.collection.Base#isItem(null) returns false.
  • Existing item recognition for plain objects, records, and Neo instances remains intact.
  • A focused collection unit test covers remove(null) or equivalent splice() removal-path behavior without throwing.
  • No broad behavior change to add/insert object-like item handling.
  • Targeted unit command is documented in the PR body.

Out of Scope

  • Refactoring collection key semantics.
  • Replacing isItem() with Neo.isObject() / Neo.isRecord().
  • Changing sorter null ordering or data-store hydration behavior.

Avoided Traps

  • Reverting to strict object/record checks: rejected because #5954 documents that collections can store Neo instances, and removal of Neo instances must keep working.
  • Treating this as a general null-safety sweep: rejected; the quick-win scope is the specific item/key classification edge.

Related

  • #5954 — historical reason for broad object-like item handling.
  • #5391 — historical item helper introduction.
  • #9311 — related but separate null/undefined sorting behavior.
  • PR #11700 — current session that surfaced nearby collection/null failure-mode sensitivity.

Origin Session ID: d13c94dd-e721-4e28-ac9e-4d0b3c0f66de

Retrieval Hint: query_raw_memories(query="collection Base isItem null getKey remove null TypeError quick win")

tobiu referenced in commit f0b580d - "fix(collection): exclude null from item classification (#11701) (#11702) on May 21, 2026, 7:59 AM
tobiu closed this issue on May 21, 2026, 7:59 AM