Commit 8c82106
fix(core): markDirty() should only mark flags when really scheduling tick. (#39316)
Close #39296
Fix an issue that `markDirty()` will not trigger change detection.
The case is for example we have the following component.
```
export class AppComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit() {
this.router.events
.pipe(filter((e) => e instanceof NavigationEnd))
.subscribe(() => ɵmarkDirty(this));
}
}
export class CounterComponent implements OnInit, OnDestroy {
ngOnInit() {
this.countSubject.pipe(takeUntil(this.destroy)).subscribe((count) => {
this.count = count;
ɵmarkDirty(this);
});
}
```
Then the app navigate from `AppComponent` to `CounterComponent`,
so there are 2 `markDirty()` call at in a row.
The `1st` call is from `AppComponent` when router changed, the
`2nd` call is from `CounterComponent.ngOnInit()`.
And the `markDirty()->scheduleTick()` code look like this
```
function scheduleTick(rootContext, flags) {
const nothingScheduled = rootContext.flags === 0 /* Empty */;
rootContext.flags |= flags;
if (nothingScheduled && rootContext.clean == _CLEAN_PROMISE) {
rootContext.schedule(() => {
...
if (rootContext.flags & RootContextFlags.DetectChanges)
rootContext.flags &= ~RootContextFlags.DetectChanges;
tickContext();
rootContext.clean = _CLEAN_PROMISE;
...
});
```
So in this case, the `1st` markDirty() will
1. set rootContext.flags = 1
2. before `tickContext()`, reset rootContext.flags = 0
3. inside `tickContext()`, it will call `CounterComponent.ngOnint()`,
so the `2nd` markDirty() is called.
4. and the `2nd` scheduleTick is called, `nothingScheduled` is true,
but rootContext.clean is not `_CLEAN_PROMISE` yet, since the `1st` markDirty tick
is still running.
5. So nowhere will reset the `rootContext.flags`.
6. then in the future, any other `markDirty()` call will not trigger the tick, since
`nothingScheduled` is always false.
So `nothingScheduled` means no tick is scheduled, `rootContext.clean === _CLEAN_PROMISE`
means no tick is running.
So we should set the flags to `rootContext` only when `no tick is scheudled or running`.
PR Close #393161 parent fb96c3d commit 8c82106Copy full SHA for 8c82106
File tree
Expand file treeCollapse file tree
2 files changed
+104
-5
lines changedOpen diff view settings
Filter options
- packages/core
- src/render3/instructions
- test/render3
Expand file treeCollapse file tree
2 files changed
+104
-5
lines changedOpen diff view settings
Collapse file
packages/core/src/render3/instructions/shared.ts
Copy file name to clipboardExpand all lines: packages/core/src/render3/instructions/shared.ts+3-2Lines changed: 3 additions & 2 deletions
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| ||
1863 | 1863 | |
1864 | 1864 | |
1865 | 1865 | |
1866 | | - |
1867 | | - |
1868 | 1866 | |
| 1867 | + |
| 1868 | + |
| 1869 | + |
1869 | 1870 | |
1870 | 1871 | |
1871 | 1872 | |
|
Collapse file
packages/core/test/render3/change_detection_spec.ts
Copy file name to clipboardExpand all lines: packages/core/test/render3/change_detection_spec.ts+101-3Lines changed: 101 additions & 3 deletions
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| ||
8 | 8 | |
9 | 9 | |
10 | 10 | |
11 | | - |
| 11 | + |
12 | 12 | |
13 | | - |
14 | | - |
| 13 | + |
| 14 | + |
15 | 15 | |
16 | 16 | |
17 | 17 | |
18 | 18 | |
| 19 | + |
19 | 20 | |
20 | 21 | |
21 | 22 | |
22 | 23 | |
| 24 | + |
23 | 25 | |
24 | 26 | |
25 | 27 | |
| ||
48 | 50 | |
49 | 51 | |
50 | 52 | |
| 53 | + |
| 54 | + |
| 55 | + |
| 56 | + |
| 57 | + |
| 58 | + |
| 59 | + |
| 60 | + |
| 61 | + |
| 62 | + |
| 63 | + |
| 64 | + |
| 65 | + |
| 66 | + |
| 67 | + |
| 68 | + |
| 69 | + |
| 70 | + |
| 71 | + |
| 72 | + |
| 73 | + |
| 74 | + |
| 75 | + |
| 76 | + |
| 77 | + |
| 78 | + |
| 79 | + |
| 80 | + |
| 81 | + |
| 82 | + |
| 83 | + |
| 84 | + |
| 85 | + |
| 86 | + |
| 87 | + |
| 88 | + |
| 89 | + |
| 90 | + |
| 91 | + |
| 92 | + |
| 93 | + |
| 94 | + |
| 95 | + |
| 96 | + |
| 97 | + |
| 98 | + |
| 99 | + |
| 100 | + |
| 101 | + |
| 102 | + |
| 103 | + |
| 104 | + |
| 105 | + |
| 106 | + |
| 107 | + |
| 108 | + |
| 109 | + |
| 110 | + |
| 111 | + |
| 112 | + |
| 113 | + |
| 114 | + |
| 115 | + |
| 116 | + |
| 117 | + |
| 118 | + |
| 119 | + |
| 120 | + |
| 121 | + |
| 122 | + |
| 123 | + |
| 124 | + |
| 125 | + |
| 126 | + |
| 127 | + |
| 128 | + |
| 129 | + |
| 130 | + |
51 | 131 | |
52 | 132 | |
53 | 133 | |
| ||
66 | 146 | |
67 | 147 | |
68 | 148 | |
| 149 | + |
| 150 | + |
| 151 | + |
| 152 | + |
| 153 | + |
| 154 | + |
| 155 | + |
| 156 | + |
| 157 | + |
| 158 | + |
| 159 | + |
| 160 | + |
| 161 | + |
| 162 | + |
| 163 | + |
| 164 | + |
| 165 | + |
| 166 | + |
69 | 167 | |
70 | 168 | |
71 | 169 | |
|
0 commit comments