Skip to content

Complete Dock 12.0.0.2 -> 12.1.0.2 upgrade: migrate legacy $id/$ref layouts that break the new reference handling #1348

Description

@JoshuaRowePhantom

Summary

The Dock.* pins are held at 12.0.0.2 because upgrading to 12.1.0.2 breaks deserialization of already-persisted ("legacy") dock layouts. Dock 12.1.0.2 (upstream PR danipen/Dock #1107 "Fix Owner reference-cycle handling across all serializers") widened the System.Text.Json $id/$ref reference-tracking scope so it no longer resets per-list. Legacy layouts written by 12.0.0.2 contain massively duplicated $id values (a per-list-isolated-scope artifact — the very bloat from #1335/#1334), which the 12.1.0.2 deserializer rejects. Impact: we cannot take the Dock upgrade (and its native #1107 reference-cycle fix that supersedes our #1335 workaround) until legacy persisted layouts are migrated. This is also a real user-facing MIGRATION risk: any user's already-persisted 12.0.0.2 layout would fail to load after the upgrade, not just the test fixture.

Root Cause

Affected Files

File Role
features\Directory.Packages.props (:17-21) Pins all five Dock.* at 12.0.0.2 (only CPM file under features\; no submodule variant) — to move to 12.1.0.2
features\Phantom.Workspaces\ViewModels\DockLayoutCanonicalizer.cs (:42-52,60-61,68-83,86-113) Preserve options, legacy-format detection, legacy DockSerializer deserialize path — migration pre-pass goes here
features\Phantom.Workspaces\ViewModels\WorkspaceDockTypeInfoResolver.cs (:128-157,144-157,195-208) Custom resolver ($type + $id/$ref ordering) — candidate for simplification once #1107 native handling is trusted
features\Phantom.Workspaces\ViewModels\MainWindowViewModel.cs (:2840 write, :3583/:3600 read) Persistence load/save call sites
features\Phantom.Workspaces.Tests\WorkspaceDockPersistenceTests.cs (:132-150) Failing test + Expected-Tests home
features\Phantom.Workspaces.Tests\Fixtures\dock-layout-1334.json Legacy bloated fixture with duplicate $ids

Design / Fix (ordered options)

  1. PRIMARY — legacy-layout migration pre-pass in DockLayoutCanonicalizer.Deserialize before the legacy DockSerializer.Deserialize call (:81): run a JSON-level transform that either (a) STRIPS all $id/$ref metadata from legacy-format JSON (only 3 $refs total — negligible sharing lost; Dock rebuilds from $type + inline objects), or (b) RENUMBERS $ids to be globally unique and rewrites the 3 $ref targets. Pure JSON transform, no Dock-internals dependency. Crucially this also unblocks any USER's already-persisted 12.0.0.2 layout on upgrade, not just the fixture.
  2. Regenerate the fixture under the current preserve write path (SerializeCanonical) as a secondary safety net so the test also covers the new persisted format; keep the legacy fixture behind a dedicated migration test.
  3. Bump the pins in Directory.Packages.props:17-21 to 12.1.0.2 for all five Dock.* together (never a partial subset — Bump Dock.Avalonia and Dock.Avalonia.Themes.Fluent #1339 only moved 2 of 5, which desyncs the set).
  4. Follow-up cleanup (after 1 lands): PR Crash: ObservableCollection reentrancy opening a tab — remove dock->Tabs order back-sync (Tabs order must be independent of dock) #1107 fixes the upstream per-list-isolation/Owner-cycle problem natively, so the heal/dedupe + ApplySerializationOrder machinery in WorkspaceDockTypeInfoResolver (and possibly CreatePreserveOptions) MAY be simplified toward Dock.Serializer.SystemTextJson's own serializer. Do NOT remove the heal/dedupe wholesale — it is still needed to reduce already-bloated persisted graphs (Dock-layout persistence leak: ActiveDockable/DefaultDockable/FocusedDockable and orphan floating Windows are inline-cloned every save (DockSerializer bypasses ReferenceHandler.Preserve), compounding to 100+ WorkspaceDocument instances for 11 tabs #1335). Note this simplification alone does NOT fix Review, validate, and merge all open Dependabot dependency-update PRs #1346 because the failing input is a pre-existing legacy file — option 1 is still required.
  5. When implementing, check whether Dock.Serializer.SystemTextJson 12.1.0.2 exposes a ctor/option to opt out of the new reference tracking (possible temporary escape hatch, not the long-term fix).

Verification: after migration + pin bump, WorkspaceDockPersistence_LoadRealLayout1334_HealsTo11Docs passes under 12.1.0.2; full dock persistence/tab-switch/layout suites green incl. stability run.

Expected Tests

Follow WorkspaceDockPersistenceTests convention Subject_Scenario_ExpectedOutcome (existing examples at :65,:93,:112,:135).

Test Name Class What It Verifies
WorkspaceDockPersistence_LoadLegacyLayoutWithDuplicateIds_MigratesAndHealsTo11Docs WorkspaceDockPersistenceTests The legacy dock-layout-1334.json (105× $id="1") deserializes under Dock 12.1.0.2 via the migration pre-pass and still heals to 11 docs
WorkspaceDockPersistence_Dock1210Upgrade_DeserializesLegacyFixtureWithoutIdConflict WorkspaceDockPersistenceTests Deserializing a legacy duplicate-$id layout does not throw the '$id' ... conflicts with an existing identifier error
DockLayoutCanonicalizer_LegacyJsonWithDuplicateIds_StripsOrRenumbersReferenceMetadata WorkspaceDockPersistenceTests (or a canonicalizer-focused test class) The migration pre-pass produces JSON with globally-unique (or absent) $ids and intact $ref targets

Related issues

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't workingdiagnosedRoot cause identifiedneeds-slow-testsRequires full test suite including slow Git tests at checkinnext-upverified-locallyImplementation has been verified locally

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions