You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
After the react-doctor 0.9.3 cleanup (17 findings → 100/100), apps/mobile/doctor.config.ts still contains 3 documented exceptions that mask real work. These are not the screen-refactor exceptions tracked in #147 — they are:
no-create-object-url-without-revoke ×4 — blob URLs that are the live expo-audio web playback source
Each exception is justified with evidence, but the goal is to eliminate them with real fixes, not keep them forever.
1. no-create-object-url-without-revoke ×4
File
Line
Context
src/hooks/use-track-download.ts
143
Web cache-validation path creates a blob URL for immediate playback
src/store/download-manager-store.ts
131
Cache hit path
src/store/download-manager-store.ts
151
Fallback path (no Cache Storage / no reader)
src/store/download-manager-store.ts
177
Normal download path
Why it is flagged: react-doctor only proves same-scope revocation (URL.revokeObjectURL syntactically in the same function as URL.createObjectURL).
Why the naive fix is wrong: On web these blob URLs ARE the audio source passed to expo-audio. Revoking in the creation scope kills playback immediately.
What was already done: lifecycle-correct revocation is implemented and behavior-preserving:
download-manager-store.ts: webObjectUrlRegistry (module-level map) registers URLs at all 3 creation sites; revoked in cancel (completed entries) and _failDownload.
use-track-download.ts: ownedWebObjectUrlRef — the hook owns the URL and revokes it on replacement, clear, and unmount cleanup.
Path to a real fix (pick one):
(a) Watch react-doctor/deslop for same-scope registry pattern support (revocation via a tracked registry proved from a single ownership point) and drop the exception when provable.
(b) Redesign web playback to avoid long-lived blob URLs (e.g. revoke-and-recreate on track switch is already handled; a future approach could stream/cache differently), then delete the exception.
(c) If neither lands, accept and keep the documented exception (current state).
Reality:DeviceService.getPlatformDeviceId is imported and used by src/storage/app-storage.ts:3,28 and app-storage.web.ts.
Root cause: deslop resolves platform-split files (.ts / .web.ts) inconsistently — it associates the import with the .web.ts variant and counts zero importers for device-service.ts. Same false-positive family already ignored for config-cache and translation-cache (pre-existing team decision).
Path to a real fix:
(a) Verify whether newer deslop/react-doctor releases resolve platform-split correctly; drop the exception when proven.
(b) Restructure so the analyzer can see the reference (e.g. a single non-split module re-exporting both platform implementations) — measure whether this reduces analyzer confusion without hurting Metro platform resolution.
(c) If it remains an analyzer limitation, keep the documented exception (current state).
File: src/app/(tabs)/explore.tsx:101 (+ the same pattern in experiences.tsx, track-detail-view.tsx, trip-detail-view.tsx, track-map.tsx)
Flagged:(BuildHIR::lowerStatement) Handle TryStatement with a finalizer ("finally") clause — a known React Compiler limitation.
Current state: the exception predates this cleanup (team decision, already documented in doctor.config.ts); the rule name changed from react-compiler to react-hooks-js/todo between 0.5.x and 0.9.x and the override was updated to match.
Important: the finally block is not decorative — it guarantees setLoading(false) on both success and rejection (no-loading-flag-reset-outside-finally fix depends on it).
react-doctor 0.9.3 (repo-pinned, bun run doctor): 100/100, No issues found with the documented exceptions.
70 Jest suites / 508 tests pass; tsc --noEmit clean; prettier clean on touched files.
Related cleanup work (this PR set): useMemo removed in use-instructions-audio.ts (compiler-managed), effect cleanups added to use-purchase.ts/use-track-download.ts, only-export-components fixed via icon-utils.ts + tw/factory.ts, finally fix in explore.tsx, cancelled-flag in use-purchase.ts.
Acceptance Criteria
Each of the 3 exception groups is either (a) resolved with a real code fix and its doctor.config.ts override removed, or (b) closed as an analyzer/upstream limitation with a link to the upstream issue.
bun run doctor stays at No issues found (or the removed exception is provably gone from the output).
All tests + typecheck remain green after any change.
Pre-flight Checks
Problem Description
After the react-doctor 0.9.3 cleanup (
17 findings → 100/100),apps/mobile/doctor.config.tsstill contains 3 documented exceptions that mask real work. These are not the screen-refactor exceptions tracked in #147 — they are:no-create-object-url-without-revoke×4 — blob URLs that are the live expo-audio web playback sourcedeslop/unused-export—DeviceService(platform-split false positive)react-hooks-js/todo— React Compilertry/finallylimitation (overlaps with chore(code-health): eliminate React Doctor exceptions from doctor.config.ts #147, detailed below)Each exception is justified with evidence, but the goal is to eliminate them with real fixes, not keep them forever.
1.
no-create-object-url-without-revoke×4src/hooks/use-track-download.tssrc/store/download-manager-store.tssrc/store/download-manager-store.tssrc/store/download-manager-store.tsWhy it is flagged: react-doctor only proves same-scope revocation (
URL.revokeObjectURLsyntactically in the same function asURL.createObjectURL).Why the naive fix is wrong: On web these blob URLs ARE the audio source passed to
expo-audio. Revoking in the creation scope kills playback immediately.What was already done: lifecycle-correct revocation is implemented and behavior-preserving:
download-manager-store.ts:webObjectUrlRegistry(module-level map) registers URLs at all 3 creation sites; revoked incancel(completed entries) and_failDownload.use-track-download.ts:ownedWebObjectUrlRef— the hook owns the URL and revokes it on replacement, clear, and unmount cleanup.Path to a real fix (pick one):
2.
deslop/unused-export—DeviceServicesrc/services/device-service.ts:7(alsodevice-service.web.ts)DeviceService.getPlatformDeviceIdis imported and used bysrc/storage/app-storage.ts:3,28andapp-storage.web.ts..ts/.web.ts) inconsistently — it associates the import with the.web.tsvariant and counts zero importers fordevice-service.ts. Same false-positive family already ignored forconfig-cacheandtranslation-cache(pre-existing team decision).Path to a real fix:
3.
react-hooks-js/todo— React Compilertry/finallysrc/app/(tabs)/explore.tsx:101(+ the same pattern inexperiences.tsx,track-detail-view.tsx,trip-detail-view.tsx,track-map.tsx)(BuildHIR::lowerStatement) Handle TryStatement with a finalizer ("finally") clause— a known React Compiler limitation.doctor.config.ts); the rule name changed fromreact-compilertoreact-hooks-js/todobetween 0.5.x and 0.9.x and the override was updated to match.finallyblock is not decorative — it guaranteessetLoading(false)on both success and rejection (no-loading-flag-reset-outside-finallyfix depends on it).react-compilerexception; track resolution there and remove thereact-hooks-js/todoentry from the override when the compiler supports it.Path to a real fix:
TryStatementwith finalizer (upstream), then delete the exception.try/finally(e.g..then/.catchchains or a dedicated data-fetching hook per chore(code-health): eliminate React Doctor exceptions from doctor.config.ts #147) — only if the team accepts the style change; thefinallyreset semantics must be preserved.Verification & Current State
react-doctor0.9.3 (repo-pinned,bun run doctor): 100/100, No issues found with the documented exceptions.tsc --noEmitclean; prettier clean on touched files.useMemoremoved inuse-instructions-audio.ts(compiler-managed), effect cleanups added touse-purchase.ts/use-track-download.ts,only-export-componentsfixed viaicon-utils.ts+tw/factory.ts,finallyfix inexplore.tsx,cancelled-flag inuse-purchase.ts.Acceptance Criteria
doctor.config.tsoverride removed, or (b) closed as an analyzer/upstream limitation with a link to the upstream issue.bun run doctorstays atNo issues found(or the removed exception is provably gone from the output).Affected Area
Code quality / linting —
apps/mobile/doctor.config.ts,src/hooks/use-track-download.ts,src/store/download-manager-store.ts,src/services/device-service.ts