Skip to content

Weak collections: read-only clear, explicit WeakReference tracking, reentrant clear, and stale counts (#1497) - #1503

Merged
ctrlaltca merged 2 commits into
pradosoft:masterfrom
belisoful:weak-collections-readonly-clear
Nov 9, 2026
Merged

ctrlaltca merged 2 commits into
pradosoft:masterfrom
belisoful:weak-collections-readonly-clear

Conversation

@belisoful

Copy link
Copy Markdown
Member

Part of #1497. Found by the second Collections path audit.

  • Read-only TWeakMap: clear() had no read-only check, so clear() and copyFrom() emptied a read-only map, and copyFrom(['b' => 2]) emptied it and then threw. It now throws map_readonly like TMap and leaves the map unchanged.
  • Explicit WeakReference: TWeakList and TWeakMap tracked the reference, which the collection holds strongly, so a collected referent was never scrubbed. A reference to a TEventHandler also drove TWeakList's handler count to -1 on removal. Add and remove now track the referent.
  • Reentrant clear(): all three collections crashed when a destructor removed another entry during the clear. Each now re-reads its live state on every pass and ends empty.
  • Read-only TWeakCallableCollection: turning DiscardInvalid on threw list_readonly, against its documentation. It now removes collected entries as TWeakList and TWeakMap do.
  • Stale counts: clear() resets the handler count, and removing a dead handler with DiscardInvalid false now decrements it.
  • Failed inserts: TWeakList and TWeakCallableCollection track an item after the insert succeeds, so a failed insert leaves no bookkeeping.

Behavior to review:

  • A read-only TWeakList with DiscardInvalid on that holds only collected entries now clears without error, as TWeakMap does; it scrubs first and then has nothing to remove. It used to throw list_readonly.
  • A WeakReference to a TEventHandler is treated as a plain weak object: the handler itself is tracked, and it is not counted as an event handler.

Not changed: if a destructor calls remove() on an entry clear() has already removed, TWeakList and TWeakCallableCollection still throw list_item_inexistent out of clear(), because swallowing it would hide real errors. The trait docblock records this. detachEventHandler() catches it and returns false.

26 regression tests, passing with and without Xdebug develop mode. Those tests and #1498 pass together.

@ctrlaltca
ctrlaltca merged commit a1eabe4 into pradosoft:master Nov 9, 2026
16 of 18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants