@@ -10,7 +10,9 @@ let nextPendingDynamicRootComponentIdentifier = 0;
1010type ComponentParameters = object | null | undefined ;
1111
1212let manager : DotNet . DotNetObject | undefined ;
13+ let currentRendererId : number | undefined ;
1314let jsComponentParametersByIdentifier : JSComponentParametersByIdentifier ;
15+ let hasInitializedJsComponents = false ;
1416
1517// These are the public APIs at Blazor.rootComponents.*
1618export const RootComponentsFunctions = {
@@ -116,28 +118,38 @@ class DynamicRootComponent {
116118
117119// Called by the framework
118120export function enableJSRootComponents (
121+ rendererId : number ,
119122 managerInstance : DotNet . DotNetObject ,
120123 jsComponentParameters : JSComponentParametersByIdentifier ,
121124 jsComponentInitializers : JSComponentIdentifiersByInitializer
122125) : void {
123- if ( manager ) {
124- // This will only happen in very nonstandard cases where someone has multiple hosts .
125- // It's up to the developer to ensure that only one of them enables dynamic root components.
126+ if ( manager && currentRendererId !== rendererId ) {
127+ // A different renderer type (e.g., Server vs WebAssembly) is trying to enable JS root components .
128+ // This is a multi-host scenario which is not supported for dynamic root components.
126129 throw new Error ( 'Dynamic root components have already been enabled.' ) ;
127130 }
128131
132+ // When the same renderer type re-enables (e.g., circuit restart or new circuit on same page),
133+ // accept the new manager. The old manager's DotNetObjectReference is no longer valid anyway
134+ // because the old circuit is gone. We don't dispose the old manager - doing so would cause
135+ // JSDisconnectedException because the circuit that created it no longer exists.
136+ currentRendererId = rendererId ;
129137 manager = managerInstance ;
130138 jsComponentParametersByIdentifier = jsComponentParameters ;
131139
132- // Call the registered initializers. This is an arbitrary subset of the JS component types that are registered
133- // on the .NET side - just those of them that require some JS-side initialization (e.g., to register them
134- // as custom elements).
135- for ( const [ initializerIdentifier , componentIdentifiers ] of Object . entries ( jsComponentInitializers ) ) {
136- const initializerFunc = DotNet . findJSFunction ( initializerIdentifier , 0 ) as JSComponentInitializerCallback ;
137- for ( const componentIdentifier of componentIdentifiers ) {
138- const parameters = jsComponentParameters [ componentIdentifier ] ;
139- initializerFunc ( componentIdentifier , parameters ) ;
140+ if ( ! hasInitializedJsComponents ) {
141+ // Call the registered initializers. This is an arbitrary subset of the JS component types that are registered
142+ // on the .NET side - just those of them that require some JS-side initialization (e.g., to register them
143+ // as custom elements).
144+ for ( const [ initializerIdentifier , componentIdentifiers ] of Object . entries ( jsComponentInitializers ) ) {
145+ const initializerFunc = DotNet . findJSFunction ( initializerIdentifier , 0 ) as JSComponentInitializerCallback ;
146+ for ( const componentIdentifier of componentIdentifiers ) {
147+ const parameters = jsComponentParameters [ componentIdentifier ] ;
148+ initializerFunc ( componentIdentifier , parameters ) ;
149+ }
140150 }
151+
152+ hasInitializedJsComponents = true ;
141153 }
142154}
143155
0 commit comments