[Blazor] Make component serialization metadata-first - #68295
Draft
javiercn wants to merge 14 commits into
Draft
Conversation
Resolve framework-owned import map, resource, initializer, TempData, circuit, and persistence payloads through generated contracts. Behavior: changed: fixed framework payloads no longer require reflection metadata State: incomplete - ServerComponentJsonContext is completed by #2 Review hint: application-owned values are deliberately unchanged Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Generate the server and WebAssembly marker envelopes and route fixed render-fragment wire DTOs through JsonTypeInfo overloads. Application parameter values continue to use the reflection compatibility resolver. Behavior: changed: framework marker envelopes resolve without reflection State: complete Review hint: contracts stop at the application parameter-value boundary Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Make JSRuntime's reflection fallback explicit, serialize outbound object arrays through JsonTypeInfo, and compose Web renderer and converter-backed contracts before that fallback. Custom events now use the JsonTypeInfo overload. Behavior: changed: framework JS payloads resolve generated or converter-backed contracts first State: builds; focused coverage follows in #4 Review hint: no JS-invokable dispatch metadata is included Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Exercise reflection-disabled fixed payloads, generated-before-reflection ordering, converter-backed Web renderer arguments, and the corrected custom-event JsonTypeInfo path. Behavior: preserved State: complete for fixed framework serialization Review hint: remote tests prove behavior with STJ reflection disabled Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add the minimal RazorComponentsMetadataContext JSON surface and compose registered resolvers into provider-owned persistence, marker, Session, custom-event, Web renderer, and WebAssembly host options. Prerendered and updated WebAssembly markers now deserialize after provider creation through immutable host state. Behavior: changed: application contracts resolve before reflection without crossing service-provider boundaries State: builds; host-isolation coverage follows in #6 Review hint: resolver snapshots are instance-owned; no application resolver mutates a process static Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Verify resolver composition is additive, existing providers and serializers remain immutable, reflection-disabled marker values use only registered contracts, and WebAssembly host options snapshot each provider. Behavior: preserved State: complete for application JSON composition Review hint: each test builds distinct providers from one service collection to expose resolver leakage Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add generic SetAsync overloads and ProtectedBrowserStorageSerializer<T>, while JSON fallback uses the provider-scoped application contract snapshot and preserves shipped constructors. Behavior: changed: applications can provide typed protected-storage serializers or generated JSON contracts State: builds; API and runtime coverage follows in #8 Review hint: direct construction retains the shared compatibility options; DI instances are provider-isolated Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Cover provider-scoped JSON options, multiple contexts, custom typed serializers, runtime-type fallback, direct-construction compatibility, and failure behavior for protected browser storage. Behavior: preserved State: complete Review hint: the tests exercise both DI-created and shipped-constructor instances Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Generate the remaining initializer and prerender-state contracts, use explicit JsonTypeInfo overloads for JS component parameters, normalize Server renderer IDs to their integer wire shape, and correct the Endpoints linker substitution target. Behavior: changed: remaining framework-owned payloads no longer depend on reflection or enum wire conversion State: builds; linker descriptor coverage follows in #10 Review hint: these are the final serialization-owned hunks from the frozen donor audit Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Verify the embedded substitution descriptor targets the assembly that owns the HotReloadManager use so future moves cannot silently reintroduce the Forms assembly name. Behavior: preserved State: complete Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Create the provider-owned WebAssembly marker serializer on demand when a manually assembled renderer service provider does not register it, while normal hosts continue to reuse the DI singleton. Behavior: preserved: standalone renderer construction continues to emit WebAssembly markers State: complete Review hint: the fallback still snapshots resolver contexts from the current request provider Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Shared marker settings are linked into nullable-disabled projects, so establish their annotation context locally before declaring nullable application resolvers. Behavior: preserved State: complete Review hint: both files are shared source; the E2ETest compile gate is the regression witness Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Open
3 tasks
Resolve generated marker and cached render-fragment contracts through ServerComponentSerializationSettings so camelCase naming and null omission remain part of the wire protocol. Behavior: changed: emitted component comments again use lowercase protocol names and omit null-only fields State: complete Review hint: raw start/end marker assertions cover the browser parser contract; direct generated contexts remain only where no custom protocol options apply Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Materialize provider-deserialized SSR root mappings and insert them before manually configured roots, preserving historical startup precedence without restoring pre-provider deserialization. Behavior: changed: registered marker-backed roots start before manual mappings again State: complete Review hint: two registered and two manual mappings prove order is stable within and across both groups Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stack layer 1/6 for the Aspire Dashboard Native AOT work. This PR is intentionally limited to System.Text.Json and serialization contracts and targets
mainindependently.RazorComponentsMetadataContext.JsonTypeInfoResolversurface andAddComponentMetadata<TContext>()ProtectedBrowserStorageSerializer<T>Review focus
Please review only the STJ/serialization design in this layer: contract ownership, resolver ordering, provider/host isolation, marker protocol compatibility, WebAssembly registered-root startup ordering, and protected storage. JS-invokable descriptors, binding/component metadata, framework providers, and Native AOT E2E proof are intentionally deferred to later stack layers.
Validation
ClientRenderingMultpleComponentsTest.CanRenderMultipleRootComponents): passed in Debug JITeng/build.cmd: succeeded with 0 warnings/errorsServerComponentRenderingTest.CanRenderTextOnlyComponent): passedSource draft PR #68291 remains open and untouched.