(lView: LView, source: NotificationSource)
| 24 | * @returns the root LView |
| 25 | */ |
| 26 | export function markViewDirty(lView: LView, source: NotificationSource): LView | null { |
| 27 | const dirtyBitsToUse = isRefreshingViews() |
| 28 | ? // When we are actively refreshing views, we only use the `Dirty` bit to mark a view |
| 29 | // for check. This bit is ignored in ChangeDetectionMode.Targeted, which is used to |
| 30 | // synchronously rerun change detection on a specific set of views (those which have |
| 31 | // the `RefreshView` flag and those with dirty signal consumers). `LViewFlags.Dirty` |
| 32 | // does not support re-entrant change detection on its own. |
| 33 | LViewFlags.Dirty |
| 34 | : // When we are not actively refreshing a view tree, it is absolutely |
| 35 | // valid to update state and mark views dirty. We use the `RefreshView` flag in this |
| 36 | // case to allow synchronously rerunning change detection. This applies today to |
| 37 | // afterRender hooks as well as animation listeners which execute after detecting |
| 38 | // changes in a view when the render factory flushes. |
| 39 | LViewFlags.RefreshView | LViewFlags.Dirty; |
| 40 | lView[ENVIRONMENT].changeDetectionScheduler?.notify(source); |
| 41 | while (lView) { |
| 42 | lView[FLAGS] |= dirtyBitsToUse; |
| 43 | const parent = getLViewParent(lView); |
| 44 | // Stop traversing up as soon as you find a root view that wasn't attached to any container |
| 45 | if (isRootView(lView) && !parent) { |
| 46 | return lView; |
| 47 | } |
| 48 | // continue otherwise |
| 49 | lView = parent!; |
| 50 | } |
| 51 | return null; |
| 52 | } |
no test coverage detected
searching dependent graphs…