Fix dispose() context.read assertion in blender_lines_panel.dart #28

Closed
opened 2026-08-12 12:42:37 +00:00 by ImBenji · 1 comment
Owner

Same anti-pattern that #16 fixed in lib/widgets/lines_panel_v2.dart has reappeared in lib/pages/blender/blender_lines_panel.dart, which is now the active editor under Blender Mode.

dispose() calls a commit helper that calls context.read() directly, guarded only by mounted (which doesn't prevent "Looking up a deactivated widget's ancestor is unsafe"):

  • _ActiveLineNameField.dispose() (~line 444) -> _commit() (line 457) -> context.read
    • another State's dispose() (~line 601) -> _commitWidth()/_commitPadding() -> _update() (line 663) -> context.read
      Fix the same way #16 was fixed: cache the dependency earlier (initState/didChangeDependencies) instead of looking it up in dispose.

Acceptance: no assertion when rapidly opening/closing the panel or switching tools.

Same anti-pattern that #16 fixed in lib/widgets/lines_panel_v2.dart has reappeared in lib/pages/blender/blender_lines_panel.dart, which is now the active editor under Blender Mode. dispose() calls a commit helper that calls context.read<MapDataProvider>() directly, guarded only by `mounted` (which doesn't prevent "Looking up a deactivated widget's ancestor is unsafe"): - _ActiveLineNameField.dispose() (~line 444) -> _commit() (line 457) -> context.read - - another State's dispose() (~line 601) -> _commitWidth()/_commitPadding() -> _update() (line 663) -> context.read Fix the same way #16 was fixed: cache the dependency earlier (initState/didChangeDependencies) instead of looking it up in dispose. Acceptance: no assertion when rapidly opening/closing the panel or switching tools.
ImBenji added the bugarea:ui/ux labels 2026-08-12 12:42:37 +00:00
ImBenji added this to the Arcs & Angles project 2026-08-12 12:42:37 +00:00
Author
Owner

Fixed on development (2026-09-05, uncommitted at time of writing).

Both State classes now hold MapDataProvider and CommandEngine from didChangeDependencies instead of reaching for context.read, same fix #16 used. The if (!mounted) return guards came out with it: mounted is still TRUE inside dispose (it only goes false on unmount afterwards), so it never guarded the assertion, and it was silently DROPPING the pending edit on the way past.

Fixing this exposed the same bug one layer down. _commitWidth reaches CommandEngine.commitTransactionAsSingleCommand, which captures the document through EditorCoreState._captureDocumentJson, and _mapData there was also an on-demand context.read getter. So the assertion just moved from the panel to editor_core.dart:331. All seven provider getters on EditorCoreState now come from a cached _cacheProviders(), called from initState and didChangeDependencies.

Guarded by test/blender_lines_panel_dispose_test.dart, which reproduces the exact "Looking up a deactivated widget's ancestor is unsafe" failure on the old code and also asserts the pending edit actually lands rather than being swallowed. Third time this pattern has shipped, hence a test rather than a fourth fix.

Fixed on development (2026-09-05, uncommitted at time of writing). Both State classes now hold MapDataProvider and CommandEngine from didChangeDependencies instead of reaching for context.read, same fix #16 used. The `if (!mounted) return` guards came out with it: mounted is still TRUE inside dispose (it only goes false on unmount afterwards), so it never guarded the assertion, and it was silently DROPPING the pending edit on the way past. Fixing this exposed the same bug one layer down. _commitWidth reaches CommandEngine.commitTransactionAsSingleCommand, which captures the document through EditorCoreState._captureDocumentJson, and _mapData there was also an on-demand context.read getter. So the assertion just moved from the panel to editor_core.dart:331. All seven provider getters on EditorCoreState now come from a cached _cacheProviders(), called from initState and didChangeDependencies. Guarded by test/blender_lines_panel_dispose_test.dart, which reproduces the exact "Looking up a deactivated widget's ancestor is unsafe" failure on the old code and also asserts the pending edit actually lands rather than being swallowed. Third time this pattern has shipped, hence a test rather than a fourth fix.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: IMBENJI.NET/Metro-Map-Maker#28