* Traverses all directive-hosting nodes in the `rootLView` hierarchy and builds a tree of * serialized element injectors. * * This function uses `walkLViewDirectives` to visit nodes in depth-first order and a stack * to reconstruct the hierarchical tree of injectors, handling both same-view and
(rootLView: LView)
| 94 | * @returns The root {@link SerializedInjector} object. |
| 95 | */ |
| 96 | function walkElementInjectors(rootLView: LView): SerializedInjector { |
| 97 | // Assert that we were given a root `LView` rather than a random component. |
| 98 | // A root component actually gets two `LView` objects, the "root `LView`" with |
| 99 | // `type === TViewType.Root` and then an `LView` for the component itself as a child. |
| 100 | if (rootLView[TVIEW].type !== TViewType.Root) { |
| 101 | throw new Error(`Expected a root LView but got type: \`${rootLView[TVIEW].type}\`.`); |
| 102 | } |
| 103 | |
| 104 | // Track the injectors we're currently processing. |
| 105 | const stack: Array<[TNode, LView, SerializedInjector]> = []; |
| 106 | |
| 107 | // By constraining `rootLView` to only accepting root `LView` objects, we don't have to |
| 108 | // process `rootLView` itself, knowing that it won't be a component or directive. |
| 109 | // We can just check its descendants. |
| 110 | for (const [tNode, lView] of walkLViewDirectives(rootLView)) { |
| 111 | const injector = new NodeInjector(tNode as TDirectiveHostNode, lView); |
| 112 | const serialized = serializeInjector(injector); |
| 113 | |
| 114 | // Look for our nearest ancestor in the stack. |
| 115 | while (stack.length > 0) { |
| 116 | const [lastTNode, lastLView, lastInjector] = stack[stack.length - 1]; |
| 117 | |
| 118 | const isDescendantInSameView = isTNodeDescendant(tNode, lastTNode); |
| 119 | const isDescendantInDifferentView = isLViewDescendantOfTNode(lView, lastLView, lastTNode); |
| 120 | if (isDescendantInSameView || isDescendantInDifferentView) { |
| 121 | // This injector is a child of the current last injector in the stack. |
| 122 | lastInjector.children.push(serialized); |
| 123 | break; |
| 124 | } else { |
| 125 | stack.pop(); |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | // Future injectors might be children of this one. |
| 130 | stack.push([tNode, lView, serialized]); |
| 131 | } |
| 132 | |
| 133 | // Since all component/directive LViews are descendants of the root LView, the first |
| 134 | // item on the stack must still remain and will be the root injector. |
| 135 | if (stack.length === 0) { |
| 136 | throw new Error(`Expected at least one component/directive in the root \`LView\`.`); |
| 137 | } |
| 138 | const [, , rootInjector] = stack[0]; |
| 139 | return rootInjector; |
| 140 | } |
| 141 | |
| 142 | /** |
| 143 | * Collects and serializes all environment injectors found in the hierarchy of the given |
no test coverage detected
searching dependent graphs…