@@ -296,18 +296,27 @@ export class NewTreeBuilder implements TreeBuilder {
296296 }
297297
298298 closeElement ( ) : Nullable < ModifierInstance [ ] > {
299- // Check if we are closing a shadow DOM section. Shadow roots (and document
300- // fragments) have nodeType 11 (DOCUMENT_FRAGMENT_NODE), whereas regular
301- // elements have nodeType 1 (ELEMENT_NODE).
302- //
303- // When we detect a shadow root as the current element, we need to pop the
304- // block we pushed in flushElement (instead of using willCloseElement which
305- // decrements the parent block's nesting counter).
306- //
307- // Note: this.element is typed as SimpleElement (nodeType 1), but at runtime
308- // it may be a ShadowRoot (nodeType 11) that was stored during flushElement's
309- // shadow DOM handling. We use an explicit nodeType check to detect this case.
310299 if ( isShadowRootOrDocumentFragment ( this . element ) ) {
300+ // A ShadowRoot (or DocumentFragment) is used as the rendering target for
301+ // declarative shadow DOM (`<template shadowrootmode="...">`) and
302+ // `{{#in-element}}` calls.
303+ //
304+ // Unlike a regular element, a shadow root:
305+ // 1. Has nodeType 11 (DOCUMENT_FRAGMENT_NODE) instead of 1 (ELEMENT_NODE)
306+ // 2. Must always be attached to a host element — it cannot exist as a
307+ // free-standing node — so its content must not be tracked in the
308+ // parent block's bounds (the host element is the visible boundary).
309+ //
310+ // Because of (2), `flushElement` pushed an extra *remote* block (isRemote=true)
311+ // for the shadow root content so that its nodes are excluded from the
312+ // enclosing block's first/last node tracking. We must pop that extra
313+ // block here rather than calling `willCloseElement()`, which would
314+ // incorrectly decrement the parent block's element-nesting counter.
315+ //
316+ // Note: `this.element` is typed as SimpleElement (nodeType 1), but at
317+ // runtime it may hold a ShadowRoot (nodeType 11) placed there during
318+ // `flushElement`'s shadow DOM handling. The explicit nodeType check in
319+ // `isShadowRootOrDocumentFragment` detects this case.
311320 this . popBlock ( ) ;
312321 this . popElement ( ) ;
313322 return this . popModifiers ( ) ;
0 commit comments