[Blazor] Generate component metadata for Native AOT - #68299
Draft
javiercn wants to merge 17 commits into
Draft
Conversation
javiercn
force-pushed
the
javiercn-component-metadata-aot
branch
from
August 9, 2026 11:47
a0b2f1b to
73ba69c
Compare
javiercn
force-pushed
the
javiercn-component-metadata-aot
branch
from
August 9, 2026 12:36
73ba69c to
cdc58e7
Compare
javiercn
force-pushed
the
javiercn-component-metadata-aot
branch
from
August 9, 2026 19:26
cdc58e7 to
1afdfb0
Compare
javiercn
force-pushed
the
javiercn-component-metadata-aot
branch
from
August 9, 2026 21:47
c98e962 to
eba8437
Compare
Member
Author
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). 3 pipeline(s) were filtered out due to trigger conditions. |
…pe info Route component activation, injection, parameters, cascades, and persistent members through a shared reflection-backed type-info model. Keep the descriptor implementation internal until generated metadata is introduced. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Verify reflection-backed activation, injection, ordinary parameters, cascading parameters, and persistent members before generated metadata is introduced. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Carry component type info through route discovery, route cache identity, endpoint metadata, and page descriptors. Preserve dynamically accessed type flow and include the donor's final route-table annotation fix. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Delete the assembly-scan builder graph now that route and endpoint discovery resolve component type info directly. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Cover route-table metadata, endpoint discovery, hot reload, and page descriptor propagation using normalized component type info with reflection fallback. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Carry resolved component type info through initial markers, dynamic root operations, resumed circuits, renderer attachment, and parameter deserialization. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Cover metadata-aware root component deserialization, renderer attachment, dynamic operations, circuit persistence, and Server service registration. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Expose component, parameter, and injectable descriptors when the existing metadata context first carries Components. Generate application component factories, attributes, accessors, and diagnostics, then resolve generated type info before the default reflection fallback without adding framework provider machinery. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Cover component activation metadata, parameters, cascading and persistent members, injection, inherited metadata, accessibility diagnostics, unique contexts, and runtime registration while preserving lower-layer JSON, JS, and binding contexts. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Wire the E2E manifest task, add the native-capable source-generated harness and targets, and introduce runnable JIT feature applications with metadata registration and browser fixtures. Native testing remains available to later layers but is not enabled here. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Drive activation, injection, parameters, cascades, binding graphs, JS dispatch, JSON composition, custom events, persistence, Session, protected storage, dynamic roots, and endpoint metadata through the JIT feature application. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep a dedicated JIT witness for undescribed components, JS-invokable methods, and JSON payloads using the default reflection fallbacks. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Route ComponentBase parameter assignment through renderer-scoped type info and add the compatibility-preserving reflection switch infrastructure and fail-fast branches required when a later layer disables reflection. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Resolve Session and TempData component getters from component parameter descriptors first, preserving reflection fallback compatibility and eliminating their independent reflection caches. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Cover cascading state, activation, injection, resolver ordering and caches, ParameterView, persistent members, generated render modes, activator substitution, and reflection-disabled fail-fast behavior. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Verify descriptor precedence, reflection compatibility, reflection-disabled failure, and Session and TempData subscription parity. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Verify persistent-state serializer closure, JSON resolver composition, typed JS serialization contracts, and generated parameter bridges for DynamicallyAccessedMembers annotations. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
javiercn
force-pushed
the
javiercn-component-metadata-aot
branch
from
August 11, 2026 10:50
eba8437 to
103b080
Compare
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.
Overview
This is layer 4 of 6 for #68332, stacked on #68297. It gives component activation, member access, routing/discovery, and Server root operations one shared
ComponentTypeInfomodel, then teaches the application metadata generator to produce that model at compile time. The governing constraint is generated first, reflection last: registered metadata avoids reflection, while applications without metadata continue to work unchanged; framework-owned descriptor providers and strict reflection disablement remain in later stack layers.Design
The new experimental contract describes a component as executable metadata rather than as reflected members:
ComponentParameterDescriptorcarries the declared type, role attribute, generated getter/setter delegates, and an optional closed persistent-state serializer factory.ComponentInjectableDescriptoris separate because injection has different semantics: service type, keyed[Inject]metadata, and a setter, but no getter or unmatched-value behavior. The open metadata bag carries route, layout, render-mode, endpoint, and future attributes without expanding the public API for each feature.The existing application metadata context gains one capability and keeps the lower-layer JSON, JS-invokable, and bindable contracts:
Two decisions preserve compatibility:
true. This layer defines generated-only resolver/failure semantics; the final strict layer is responsible for setting the switch tofalse.Framework assemblies are intentionally skipped by the application collector. The next stack layer supplies owner-authored framework descriptors and factories; this PR only establishes the resolver/merge contract they consume.
Implementation
A renderer creates one resolver chain and gives it to activation, property injection, parameter binding, cascading state, persistence, discovery, and root operations. The source-generated resolver is first; the composite caches type/name/assembly lookups, can fill a missing generated construction factory from a later resolver, and invalidates caches for hot reload. If both generated and reflection resolvers exist, hot reload disables stale generated descriptors and continues through reflection.
The generator walks referenced application types with private metadata imported because Razor-generated
@injectproperties and render-mode attributes are not visible under Roslyn's default import mode. It preserves most-derived member semantics, reconstructs component attributes, and rejects the whole component if any required member cannot be reached.Generated parameter descriptors cover ordinary, cascading/query/session/TempData, and persistent parameters. Their deltas are only the reconstructed attribute and optional serializer/accessor bridge:
Runtime entry points retain renderer-scoped type info instead of rediscovering members.
ComponentBasebinds through the renderer;ComponentFactoryuses descriptor render modes, activation, and injection; Session and TempData share descriptor-first value access instead of maintaining independent reflection caches.Discovery is the assembly-enumeration equivalence class. Routing and endpoint discovery enumerate
ComponentTypeInfo, route-cache identity includes the resolver, and endpoint metadata is the descriptor metadata minusRouteAttribute. Layout and render-mode consumers read the same metadata bag, so the old assembly/component/page builder graph is removed.Server roots are the lifetime equivalence class. Initial marker deserialization resolves and stores
ComponentTypeInfo; dynamic add/update operations pass that object into the renderer; resumed circuits retain(typeInfo, parameters)rather than discarding metadata and resolving byTypeagain.PR4's feature application and browser scenarios now consume the Native AOT Components.Testing harness from main (#68289) and the shared MSTest/MTP infrastructure from #67083. The upstream harness owns publish/source-generation plumbing; this PR contributes only its application,
ServerFactoryfixture/routing integration, and component-metadata scenarios. The separateJitDefaultcategory proves undescribed component, JS method, and JSON payload fallbacks remain compatible.Outcome
ComponentTypeInfoDynamicallyAccessedMembersbridgesStack note: this PR depends on #68297. Framework-owned component descriptor providers are added by the next stack layer; strict reflection-disabled Native AOT proof follows after that.