* NOTE: for performance reasons, the possible actions are inlined within the function instead of * being passed as an argument.
( action: WalkTNodeTreeAction, renderer: Renderer, injector: Injector, parent: RElement | null, lNodeToHandle: RNode | LContainer | LView, tNode: TNode, beforeNode?: RNode | null, parentLView?: LView, )
| 108 | * being passed as an argument. |
| 109 | */ |
| 110 | function applyToElementOrContainer( |
| 111 | action: WalkTNodeTreeAction, |
| 112 | renderer: Renderer, |
| 113 | injector: Injector, |
| 114 | parent: RElement | null, |
| 115 | lNodeToHandle: RNode | LContainer | LView, |
| 116 | tNode: TNode, |
| 117 | beforeNode?: RNode | null, |
| 118 | parentLView?: LView, |
| 119 | ) { |
| 120 | // If this slot was allocated for a text node dynamically created by i18n, the text node itself |
| 121 | // won't be created until i18nApply() in the update block, so this node should be skipped. |
| 122 | // For more info, see "ICU expressions should work inside an ngTemplateOutlet inside an ngFor" |
| 123 | // in `i18n_spec.ts`. |
| 124 | if (lNodeToHandle != null) { |
| 125 | let lContainer: LContainer | undefined; |
| 126 | let isComponent = false; |
| 127 | // We are expecting an RNode, but in the case of a component or LContainer the `RNode` is |
| 128 | // wrapped in an array which needs to be unwrapped. We need to know if it is a component and if |
| 129 | // it has LContainer so that we can process all of those cases appropriately. |
| 130 | if (isLContainer(lNodeToHandle)) { |
| 131 | lContainer = lNodeToHandle; |
| 132 | } else if (isLView(lNodeToHandle)) { |
| 133 | isComponent = true; |
| 134 | ngDevMode && assertDefined(lNodeToHandle[HOST], 'HOST must be defined for a component LView'); |
| 135 | lNodeToHandle = lNodeToHandle[HOST]!; |
| 136 | } |
| 137 | const rNode: RNode = unwrapRNode(lNodeToHandle); |
| 138 | if (action === WalkTNodeTreeAction.Create && parent !== null) { |
| 139 | maybeQueueEnterAnimation(parentLView, parent, tNode, injector); |
| 140 | if (beforeNode == null) { |
| 141 | nativeAppendChild(renderer, parent, rNode); |
| 142 | } else { |
| 143 | nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true); |
| 144 | } |
| 145 | } else if (action === WalkTNodeTreeAction.Insert && parent !== null) { |
| 146 | maybeQueueEnterAnimation(parentLView, parent, tNode, injector); |
| 147 | nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true); |
| 148 | cancelLeavingNodes(tNode, rNode as HTMLElement, parentLView); |
| 149 | } else if (action === WalkTNodeTreeAction.Detach) { |
| 150 | if (parentLView?.[ANIMATIONS]?.leave?.has(tNode.index)) { |
| 151 | trackLeavingNodes(tNode, rNode as HTMLElement, parentLView); |
| 152 | } |
| 153 | reusedNodes.delete(rNode as HTMLElement); |
| 154 | runLeaveAnimationsWithCallback( |
| 155 | parentLView, |
| 156 | tNode, |
| 157 | injector, |
| 158 | (nodeHasLeaveAnimations: boolean) => { |
| 159 | if (reusedNodes.has(rNode as HTMLElement)) { |
| 160 | reusedNodes.delete(rNode as HTMLElement); |
| 161 | return; |
| 162 | } |
| 163 | // the nodeHasLeaveAnimations indicates to the renderer that the element needs to |
| 164 | // be removed synchronously and sets the requireSynchronousElementRemoval flag in |
| 165 | // the renderer. |
| 166 | nativeRemoveNode(renderer, rNode, isComponent, nodeHasLeaveAnimations); |
| 167 | }, |
no test coverage detected
searching dependent graphs…