diff --git a/modules/@angular/core/test/animation/animation_integration_spec.ts b/modules/@angular/core/test/animation/animation_integration_spec.ts
index a83eed562e2517..955ba9258e091d 100644
--- a/modules/@angular/core/test/animation/animation_integration_spec.ts
+++ b/modules/@angular/core/test/animation/animation_integration_spec.ts
@@ -25,6 +25,7 @@ import {AnimationPlayer, NoOpAnimationPlayer} from '../../src/animation/animatio
import {AnimationStyles} from '../../src/animation/animation_styles';
import {AnimationTransitionEvent} from '../../src/animation/animation_transition_event';
import {AUTO_STYLE, animate, group, keyframes, sequence, state, style, transition, trigger} from '../../src/animation/metadata';
+import {Input} from '../../src/core';
import {isPresent} from '../../src/facade/lang';
import {TestBed, fakeAsync, flushMicrotasks} from '../../testing';
import {MockAnimationPlayer} from '../../testing/mock_animation_player';
@@ -2243,38 +2244,52 @@ function declareTests({useJit}: {useJit: boolean}) {
});
describe('error handling', () => {
- it('should recover if an animation driver or player throws an error during an animation',
+ if (!getDOM().supportsWebAnimation()) return;
+
+ it('should not throw an error when an animation exists within projected content that is not bound to the DOM',
fakeAsync(() => {
TestBed.configureTestingModule({
- declarations: [DummyIfCmp],
- providers: [{provide: AnimationDriver, useClass: ErroneousAnimationDriver}],
+ declarations: [DummyIfCmp, DummyLoadingCmp],
+ providers: [{provide: AnimationDriver, useClass: WebAnimationsDriver}],
imports: [CommonModule]
});
TestBed.overrideComponent(DummyIfCmp, {
set: {
template: `
-
+
+ world
+
`,
animations: [trigger('myAnimation', [transition(
'* => *',
[
- animate(1000, style({transform: 'noooooo'})),
+ style({opacity: 0}),
+ animate(1000, style({opacity: 1})),
])])]
}
});
+ TestBed.overrideComponent(
+ DummyLoadingCmp, {set: {template: `hello `}});
const fixture = TestBed.createComponent(DummyIfCmp);
const cmp = fixture.componentInstance;
- let started = false;
- let done = false;
- cmp.callback1 = (event: AnimationTransitionEvent) => started = true;
- cmp.callback2 = (event: AnimationTransitionEvent) => done = true;
+ const container = fixture.nativeElement;
+ let animationCalls = 0;
+ cmp.callback = () => animationCalls++;
+
+ cmp.exp = false;
+ fixture.detectChanges();
+ flushMicrotasks();
+
+ expect(animationCalls).toBe(1);
+ expect(getDOM().getText(container).trim()).toEqual('hello');
+
cmp.exp = true;
fixture.detectChanges();
flushMicrotasks();
- expect(started).toBe(true);
- expect(done).toBe(true);
+ expect(animationCalls).toBe(2);
+ expect(getDOM().getText(container).trim()).toMatch(/hello[\s\r\n]+world/m);
}));
});
@@ -2460,6 +2475,9 @@ class DummyIfCmp {
class DummyLoadingCmp {
exp: any = false;
callback = () => {};
+
+ @Input('exp2')
+ exp2: any = false;
}
@Component({
@@ -2571,11 +2589,3 @@ class ExtendedWebAnimationsDriver extends WebAnimationsDriver {
return player;
}
}
-
-class ErroneousAnimationDriver extends MockAnimationDriver {
- animate(
- element: any, startingStyles: AnimationStyles, keyframes: AnimationKeyframe[],
- duration: number, delay: number, easing: string): WebAnimationsPlayer {
- throw new Error();
- }
-}
diff --git a/modules/@angular/platform-browser/src/dom/dom_renderer.ts b/modules/@angular/platform-browser/src/dom/dom_renderer.ts
index 608d6a0e3002fe..68de6d4d9d951b 100644
--- a/modules/@angular/platform-browser/src/dom/dom_renderer.ts
+++ b/modules/@angular/platform-browser/src/dom/dom_renderer.ts
@@ -262,12 +262,11 @@ export class DomRenderer implements Renderer {
element: any, startingStyles: AnimationStyles, keyframes: AnimationKeyframe[],
duration: number, delay: number, easing: string,
previousPlayers: AnimationPlayer[] = []): AnimationPlayer {
- try {
+ if (this._rootRenderer.document.body.contains(element)) {
return this._animationDriver.animate(
element, startingStyles, keyframes, duration, delay, easing, previousPlayers);
- } catch (e) {
- return new NoOpAnimationPlayer();
}
+ return new NoOpAnimationPlayer();
}
}
diff --git a/modules/@angular/platform-server/src/private_import_core.ts b/modules/@angular/platform-server/src/private_import_core.ts
index 772db2a59cb206..465952850e4983 100644
--- a/modules/@angular/platform-server/src/private_import_core.ts
+++ b/modules/@angular/platform-server/src/private_import_core.ts
@@ -21,5 +21,3 @@ export type RenderDebugInfo = typeof r._RenderDebugInfo;
export const RenderDebugInfo: typeof r.RenderDebugInfo = r.RenderDebugInfo;
export type DebugDomRootRenderer = typeof r._DebugDomRootRenderer;
export const DebugDomRootRenderer: typeof r.DebugDomRootRenderer = r.DebugDomRootRenderer;
-export type NoOpAnimationPlayer = typeof r._NoOpAnimationPlayer;
-export const NoOpAnimationPlayer: typeof r.NoOpAnimationPlayer = r.NoOpAnimationPlayer;
diff --git a/modules/@angular/platform-server/src/server_renderer.ts b/modules/@angular/platform-server/src/server_renderer.ts
index e59b9765081d08..5a09ff65c43ce0 100644
--- a/modules/@angular/platform-server/src/server_renderer.ts
+++ b/modules/@angular/platform-server/src/server_renderer.ts
@@ -10,7 +10,7 @@ import {APP_ID, Inject, Injectable, NgZone, RenderComponentType, Renderer, RootR
import {AnimationDriver, DOCUMENT} from '@angular/platform-browser';
import {isBlank, isPresent, stringify} from './facade/lang';
-import {AnimationKeyframe, AnimationPlayer, AnimationStyles, NoOpAnimationPlayer, RenderDebugInfo} from './private_import_core';
+import {AnimationKeyframe, AnimationPlayer, AnimationStyles, RenderDebugInfo} from './private_import_core';
import {NAMESPACE_URIS, SharedStylesHost, flattenStyles, getDOM, isNamespaced, shimContentAttribute, shimHostAttribute, splitNamespace} from './private_import_platform-browser';
const TEMPLATE_COMMENT_TEXT = 'template bindings={}';
@@ -208,12 +208,8 @@ export class ServerRenderer implements Renderer {
element: any, startingStyles: AnimationStyles, keyframes: AnimationKeyframe[],
duration: number, delay: number, easing: string,
previousPlayers: AnimationPlayer[] = []): AnimationPlayer {
- try {
- return this._animationDriver.animate(
- element, startingStyles, keyframes, duration, delay, easing, previousPlayers);
- } catch (e) {
- return new NoOpAnimationPlayer();
- }
+ return this._animationDriver.animate(
+ element, startingStyles, keyframes, duration, delay, easing, previousPlayers);
}
}
diff --git a/modules/@angular/platform-webworker/test/web_workers/worker/renderer_animation_integration_spec.ts b/modules/@angular/platform-webworker/test/web_workers/worker/renderer_animation_integration_spec.ts
index 418c4977136724..f0507b15e125df 100644
--- a/modules/@angular/platform-webworker/test/web_workers/worker/renderer_animation_integration_spec.ts
+++ b/modules/@angular/platform-webworker/test/web_workers/worker/renderer_animation_integration_spec.ts
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {AUTO_STYLE, AnimationTransitionEvent, Component, Injector, animate, state, style, transition, trigger} from '@angular/core';
+import {AUTO_STYLE, AnimationTransitionEvent, Component, Injector, ViewChild, animate, state, style, transition, trigger} from '@angular/core';
import {DebugDomRootRenderer} from '@angular/core/src/debug/debug_renderer';
import {RootRenderer} from '@angular/core/src/render/api';
import {TestBed, fakeAsync, flushMicrotasks} from '@angular/core/testing';
@@ -84,7 +84,7 @@ export function main() {
workerRenderStore = new RenderStore();
TestBed.configureTestingModule({
- declarations: [AnimationCmp, MultiAnimationCmp],
+ declarations: [AnimationCmp, MultiAnimationCmp, ContainerAnimationCmp],
providers: [
Serializer, {provide: RenderStore, useValue: workerRenderStore}, {
provide: RootRenderer,
@@ -231,10 +231,9 @@ export function main() {
return (event: AnimationTransitionEvent) => { log[phaseName] = event; };
}
- const f1 = TestBed.createComponent(AnimationCmp);
- const f2 = TestBed.createComponent(AnimationCmp);
- const cmp1 = f1.componentInstance;
- const cmp2 = f2.componentInstance;
+ const fixture = TestBed.createComponent(ContainerAnimationCmp);
+ const cmp1 = fixture.componentInstance.compOne;
+ const cmp2 = fixture.componentInstance.compTwo;
const cmp1Log: {[phaseName: string]: AnimationTransitionEvent} = {};
const cmp2Log: {[phaseName: string]: AnimationTransitionEvent} = {};
@@ -246,8 +245,7 @@ export function main() {
cmp1.state = 'off';
cmp2.state = 'on';
- f1.detectChanges();
- f2.detectChanges();
+ fixture.detectChanges();
flushMicrotasks();
uiDriver.log.shift()['player'].finish();
@@ -316,6 +314,18 @@ export function main() {
});
}
+@Component({
+ selector: 'container-comp',
+ template: `
+
+
+ `
+})
+class ContainerAnimationCmp {
+ @ViewChild('one') public compOne: AnimationCmp;
+
+ @ViewChild('two') public compTwo: AnimationCmp;
+}
@Component({
selector: 'my-comp',