Loads that join another load's read of the model file cannot evict it,
so the load that read it must. That eviction ran in the engine walk,
which stops when its caller cancels, so a damaged file could stay cached
while a joined load on another provider retried against it. The shared
load now evicts from its own failure handler, and the walk shares that
eviction.
Also pins the copy a load records to the moment it opens the file: a
test evicts the file after a load starts and checks that the damaged
replacement the load read is evicted before the retry.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Follow-up to #39. A load that joins another load's read of the model file cannot evict it, so the load that read the file has to. That eviction ran in the engine walk, which stops as soon as its caller cancels. If the caller that owned a corrupt read cancelled, nobody evicted the damaged file, and a joined load on another provider could retry against the same bytes and fail again.
The shared load now evicts a damaged copy from its own failure handler, which runs whether or not anyone is still waiting. The walk still awaits the eviction before its retry; it shares the one the load started, since the tracker evicts each copy once. A load without a recorded copy still never evicts.
Two tests are new. One cancels the only caller of a corrupt load, lets the load fail, and checks the file is evicted. The other evicts the file after a load starts but before it opens the file, has the load read a damaged replacement, and checks the retry does not see it. That pins the recorded copy to the file-open event rather than load creation. Each test fails against its own regression and passes otherwise. Root lint, typecheck, test (191 browser, 98 web) and build pass.
On the build of 1af41cf, the tree now on main at 813bf5d, I ran the remover in headless Chrome against a fresh origin: model download, WASM processing, an RGBA PNG with real transparency, download, reset and an unreadable-file error. I then overwrote the cached model with zeros of the same size and processed again. The damaged copy was evicted, downloaded fresh, and the photo processed. WebGPU and iPhone were not tested.
Created with Claude Opus 5.5 in Claude Code.
🤖 Generated with Claude Code