Skip to content

fix(builder): keep the view locator's mappings and leave global state alone on a second build - #4490

Merged
glennawatson merged 2 commits into
mainfrom
fix/builder-viewlocator
Sep 26, 2026
Merged

glennawatson merged 2 commits into
mainfrom
fix/builder-viewlocator

Conversation

@glennawatson

Copy link
Copy Markdown
Contributor

Summary

ConfigureViewLocator configures the view locator the app resolves, and a second build leaves global state alone.

  • ConfigureViewLocator runs its action once, on the registered DefaultViewLocator. Mappings added with RegisterViews, WithViewModule or on a resolved locator are kept, and resolving IViewLocator twice returns the same instance. When no DefaultViewLocator is registered, a new one is configured and registered as the single IViewLocator.
  • Only the first Build()/BuildApp() in a process changes global state. A later build no longer replaces the global converter service, message bus, exception handler, suspension host or cache sizes, matching the Splat builder, which already skips that build's registrations.

Why

ConfigureViewLocator registered a factory that built a new locator on every resolve, and a second build half-applied.

  • Each resolve of IViewLocator produced a new DefaultViewLocator and reran the configure action, so views mapped with RegisterViews or WithViewModule resolved to null.
  • A second builder, even on its own resolver, had its registrations skipped by the Splat builder, yet still replaced BindingConverters.Current and MessageBus.Current, so the first builder's custom converters stopped resolving.

Closes #4486
Closes #4487

Breaking changes

None for an app that builds once.

  • If some other Splat AppBuilder builds before ReactiveUI's builder, ReactiveUI's builder no longer sets its static state or marks ReactiveUI as initialized. Its registrations were already skipped in that case.

How this was verified

Tests cover a single resolved locator instance that keeps RegisterViews mappings and runs the configure action once, and a second build that leaves the first build's converter service and message bus in place.

Notes for the reviewer

Two commits, one per fix.

Checklist

  • I have read the Contribute guide
  • The PR title follows Conventional Commits
  • Tests cover this change, or the summary says why they do not
  • New or changed public API has XML documentation

…ocator

ConfigureViewLocator registered IViewLocator as a transient factory, so every
resolve built a new DefaultViewLocator and reran the configure action. Mappings
added by RegisterViews or WithViewModule, or on a resolved locator, were lost.
The action now runs once on the registered DefaultViewLocator, or on a new one
registered as the single IViewLocator when none is registered.
Splat's AppBuilder applies only the first build in a process and skips the
registrations of later builds. ReactiveUIBuilder.Build still replaced the
global converter service, message bus, exception handler, suspension host and
cache sizes with the later builder's values. A later build now changes none
of them.
@sonarqubecloud

Copy link
Copy Markdown

@codecov

codecov Bot commented Sep 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.38%. Comparing base (37fa90a) to head (88624fc).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4490   +/-   ##
=======================================
  Coverage   93.37%   93.38%           
=======================================
  Files         168      168           
  Lines        6309     6317    +8     
  Branches      723      724    +1     
=======================================
+ Hits         5891     5899    +8     
  Misses        417      417           
  Partials        1        1           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@glennawatson
glennawatson merged commit edc6355 into main Sep 26, 2026
15 of 16 checks passed
@glennawatson
glennawatson deleted the fix/builder-viewlocator branch September 26, 2026 03:29
@github-actions

Copy link
Copy Markdown

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Oct 10, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

1 participant

⌂ 换网址