From 46aa0a1cf689e98ee37c9be488431fe48b3608a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matias=20Niemel=C3=A4?= Date: Thu, 30 Nov 2017 11:52:35 -0800 Subject: [PATCH] fix(animations): properly recover and cleanup DOM when CD failures occur (#20719) Closes #19093 PR Close #20719 --- packages/core/src/view/refs.ts | 9 ++-- .../animation/animation_integration_spec.ts | 46 +++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/packages/core/src/view/refs.ts b/packages/core/src/view/refs.ts index e72f3c8588..5359a46ce7 100644 --- a/packages/core/src/view/refs.ts +++ b/packages/core/src/view/refs.ts @@ -255,9 +255,12 @@ export class ViewRef_ implements EmbeddedViewRef, InternalViewRef { if (fs.begin) { fs.begin(); } - Services.checkAndUpdateView(this._view); - if (fs.end) { - fs.end(); + try { + Services.checkAndUpdateView(this._view); + } finally { + if (fs.end) { + fs.end(); + } } } checkNoChanges(): void { Services.checkNoChangesView(this._view); } diff --git a/packages/core/test/animation/animation_integration_spec.ts b/packages/core/test/animation/animation_integration_spec.ts index e01d6065b5..16ddc0d838 100644 --- a/packages/core/test/animation/animation_integration_spec.ts +++ b/packages/core/test/animation/animation_integration_spec.ts @@ -3348,6 +3348,52 @@ export function main() { expect(() => { TestBed.createComponent(Cmp); }).not.toThrowError(); }); + it('should continue to clean up DOM-related animation artificats even if a compiler-level error is thrown midway', + () => { + @Component({ + selector: 'if-cmp', + animations: [ + trigger( + 'foo', + [ + transition('* => something', []), + ]), + ], + template: ` + value = {{ foo[bar] }} +
+
1
+
2
+
3
+
+ `, + }) + class Cmp { + exp: any = false; + + @ViewChild('contents') public contents: any; + } + + TestBed.configureTestingModule({declarations: [Cmp]}); + + const engine = TestBed.get(ɵAnimationEngine); + const fixture = TestBed.createComponent(Cmp); + + const runCD = () => fixture.detectChanges(); + const cmp = fixture.componentInstance; + + cmp.exp = true; + expect(runCD).toThrow(); + + const contents = cmp.contents.nativeElement; + expect(contents.innerText.replace(/\s+/gm, '')).toEqual('123'); + + cmp.exp = false; + expect(runCD).toThrow(); + + expect(contents.innerText.trim()).toEqual(''); + }); + describe('errors for not using the animation module', () => { beforeEach(() => { TestBed.configureTestingModule({