@@ -274,22 +274,34 @@ class NativeScriptRenderer implements Renderer2 {
274274 if ( NativeScriptDebug . enabled ) {
275275 NativeScriptDebug . rendererLog ( `NativeScriptRenderer.selectRootElement: ${ selectorOrNode } ` ) ;
276276 }
277+ // Angular 21+ reads `rootElement.tagName.toLowerCase()` after this call
278+ // (`locateHostElement`) to reject `<script>` hosts. Guarantee every return
279+ // path produces a View with a non-empty string `tagName`; otherwise the
280+ // bootstrap throws `Cannot read properties of undefined (reading 'toLowerCase')`.
281+ const ensureTagName = ( view : any , fallback : string ) => {
282+ if ( view && typeof view . tagName !== 'string' ) {
283+ try {
284+ view . tagName = view . nodeName || fallback || 'view' ;
285+ } catch { }
286+ }
287+ return view ;
288+ } ;
277289 if ( selectorOrNode instanceof View ) {
278- return selectorOrNode ;
290+ return ensureTagName ( selectorOrNode , '' ) ;
279291 }
280292 if ( selectorOrNode && selectorOrNode [ 0 ] === '#' ) {
281293 const result = getViewById ( this . rootView , selectorOrNode . slice ( 1 ) ) ;
282- return ( result || this . rootView ) as View ;
294+ return ensureTagName ( ( result || this . rootView ) as View , selectorOrNode ) ;
283295 }
284296 if ( typeof selectorOrNode === 'string' ) {
285297 const view = this . viewUtil . createView ( selectorOrNode ) ;
286298 if ( getFirstNativeLikeView ( view ) === view ) {
287299 // view is nativelike!
288300 this . appendChild ( this . rootView , view ) ;
289- return view ;
301+ return ensureTagName ( view , selectorOrNode ) ;
290302 }
291303 }
292- return this . rootView ;
304+ return ensureTagName ( this . rootView , '' ) ;
293305 }
294306 parentNode ( node : NgView ) {
295307 if ( NativeScriptDebug . enabled ) {
0 commit comments