Skip to content

fix(ios): hold ContentBlocker pending targets weakly, drop on failure#25

Merged
bnfy merged 1 commit into
mainfrom
claude/suspicious-austin-bb6a3d
Jul 10, 2026
Merged

fix(ios): hold ContentBlocker pending targets weakly, drop on failure#25
bnfy merged 1 commit into
mainfrom
claude/suspicious-austin-bb6a3d

Conversation

@bnfy

@bnfy bnfy commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes two latent lifetime defects in the iOS ContentBlocker ad-block queue (P3 #1 from the M5 final review):

  1. Strong refs + never drained on failurependingTargets held queued WKWebViews strongly and was never drained on a compile failure (or when WKContentRuleListStore.default() is nil, whose completion never fires), leaking them for the app's lifetime.
  2. Orphaned-tab reload — a tab closed during the ~cold-compile window was kept alive and then received a pointless add(ruleList) + reload() on its detached web view when the queue drained.

Changes

  • Hold pendingTargets as weak boxes; drainPending skips targets that deallocated while queued.
  • Clear the queue on terminal compile failure.
  • TabsManager.closeTab removes the closing tab's web view via ContentBlocker.cancelPending(for:) so it is neither reloaded nor retained.

Tests

  • Added FakeRuleListStore.failCompile() to model a terminal completed(false) (distinct from the existing defer-then-succeed).
  • New tests: compile-failure branch (not-ready, not-attached, not-retained), removed-before-drain, and deallocated-before-drain.
  • Full BlancTests suite: 81/81 green, including the real-WebKit integration test and TabsManagerTests.

Resolves P3 #1 and closes the P3 #5 compile-failure test-fidelity gap.

🤖 Generated with Claude Code

pendingTargets held queued WKWebViews strongly and was never drained on a
compile failure (or when WKContentRuleListStore.default() is nil, whose
completion never fires), leaking them for the app's lifetime. A tab closed
during the ~cold-compile window was likewise kept alive and then received a
pointless add-rules + reload() on its detached web view when the queue drained.

- Hold pendingTargets as weak boxes; drainPending skips deallocated targets.
- Clear the queue on terminal compile failure.
- TabsManager.closeTab removes the closing tab's web view via
  ContentBlocker.cancelPending(for:) so it is neither reloaded nor retained.

Adds tests for the compile-failure branch and the removed/deallocated-before-
drain paths, plus FakeRuleListStore.failCompile() to model a terminal
completed(false) (distinct from the existing defer-then-succeed).

Resolves P3 #1 and closes the P3 #5 test-fidelity gap from the M5 final review.
Full BlancTests suite: 81/81 green (incl. the WebKit integration test and
TabsManagerTests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@bnfy bnfy merged commit fdca645 into main Jul 10, 2026
6 checks passed
@bnfy bnfy deleted the claude/suspicious-austin-bb6a3d branch July 10, 2026 02:15
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.

1 participant