Skip to content

fix: evict mountedRoots on unmount; ManualTimers tests; PersistentStore host warn#265

Merged
zzal merged 1 commit into
mainfrom
fix/b13-hygiene
Jul 20, 2026
Merged

fix: evict mountedRoots on unmount; ManualTimers tests; PersistentStore host warn#265
zzal merged 1 commit into
mainfrom
fix/b13-hygiene

Conversation

@zzal

@zzal zzal commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Audit backlog B13 (Part-2/Part-6 Lows) — the hygiene items with behavior.

  • mountedRoots had no evict path. The driver's selector→root-node map was populated on mount/replaceMount but never cleaned: a root unmounted (Swiflow.unmount(into:)) and never remounted pinned its detached node forever, and the node stayed attached to the DOM. Fix: a new unmount(selector) driver op detaches the root and drops the entry, called from Renderer.teardown(); HMR teardown clears the map alongside nodes/listeners. Crucially, mountedRoots deliberately survives a bare destroyNode (the resync-batch ordering emits the old root's destroyNode before replaceMount, which needs the entry to detach the old node) — so the evict is an explicit unmount signal, not a destroyNode side effect. Two js-driver tests pin both halves.
  • SwiflowTiming had no direct testsManualTimers was covered only through ToastTests. New SwiflowTimingTests owns the process-global seam (.serialized) and pins schedule/advance/cancel/reset, the isolated deinit auto-cancel, due-order firing, in-body reschedule, and the 1e-9 FP-residue tolerance.
  • PersistentStore's host stub no-ops silently — the first host save now emits a one-time DEBUG swiflowWarn, so a test asserting persistence against the default registry (instead of injecting MemoryStorage) gets a signal instead of a silent pass/fail.

Deliberately deferred (documented in the commit): the @State/@Persisted didSet-prologue extraction (assertMacroExpansion pins byte-exact output; SwiftSyntax multiline interpolation flattens the nesting — not worth churning ~10 goldens for a stable 6-line block) and the callback @MainActor unification (a source-breaking public-API change that belongs in an intentional breaking batch, and is invisible on the wasm target).

Verification: js-driver 105 tests, 0 fail. Whole-package swift test: 1916 green. EmbeddedDriver.swift + 22 example copies regenerated.

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown

📦 Bundle size

Artifact Baseline This PR Δ
App.wasm 5.06 MB 5.23 MB +3.45%
App.wasm (gzip) 1.80 MB 1.87 MB +3.56%
JS runtime 54.5 KB 54.5 KB +0.00%
JS runtime (gzip) 11.3 KB 11.3 KB +0.00%
Total (gzip) 1.81 MB 1.88 MB +3.54%

✅ Within budget (≤5% growth allowed).

Baseline: Swift 6.3, WASM SDK 6.3-RELEASE, measured 2026-06-18.

…re host warn

Three B13 hygiene items from the modularization audit:

- The driver's mountedRoots map (selector→root node) had no evict path:
  a root unmounted and never remounted pinned its detached node forever,
  and the node stayed in the DOM. Swift's teardown now signals the driver
  via a new unmount(selector) op that detaches the root and drops the
  entry; HMR teardown clears the map alongside its two siblings.
  mountedRoots deliberately survives a bare destroyNode (replaceMount's
  resync ordering depends on it), so the evict is an explicit unmount
  signal, not a destroyNode side effect.
- SwiflowTiming had no direct tests — ManualTimers was exercised only
  through ToastTests. New SwiflowTimingTests owns the process-global
  seam (.serialized) and pins schedule/advance/cancel/reset, deinit
  auto-cancel, due-order, in-body reschedule, and the FP-residue tolerance.
- PersistentStore's host stub silently no-ops save/load; the first host
  save now emits a one-time DEBUG warn so a test asserting persistence
  against the default registry gets a signal instead of silence.

Two audit items deliberately deferred: the @State/@persisted didSet
prologue extraction (assertMacroExpansion pins byte-exact output and
SwiftSyntax multiline interpolation flattens the nesting — not worth
churning ~10 goldens for a stable 6-line block), and the callback
@mainactor unification (a source-breaking public-API change that belongs
in an intentional breaking batch, invisible on the wasm target).

js-driver: 105 tests. Whole-package swift test: 1916 green. EmbeddedDriver
+ example copies regenerated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@zzal
zzal force-pushed the fix/b13-hygiene branch from 3192535 to 1601170 Compare July 20, 2026 11:44
@zzal
zzal merged commit 3e5afea into main Jul 20, 2026
6 checks passed
@zzal
zzal deleted the fix/b13-hygiene branch July 20, 2026 11:49
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