fix(ivy): process nested animation metadata (#32818)
In View Engine, animation metadata could occur in nested arrays which would be flattened in the compiler. When compiling a component for Ivy however, the compiler no longer statically evaluates a component's animation metadata and is therefore unable to flatten it statically. This resulted in an issue to find animations at runtime, as the metadata was incorrectly registered with the animation engine. Although it would be possible to statically evaluate the animation metadata in ngtsc, doing so would prevent reusable animations exported from libraries from being usable as ngtsc's partial evaluator is unable to read values inside libraries. This is unlike ngc's usage of static symbols represented in a library's `.metadata.json`, which explains how the View Engine compiler is able to flatten the animation metadata statically. As an alternative solution, the metadata flattening is now done in the runtime during the registration of the animation metadata with the animation engine. Fixes #32794 PR Close #32818
This commit is contained in:
@ -12,6 +12,12 @@ import {Injectable, NgZone, Renderer2, RendererFactory2, RendererStyleFlags2, Re
|
||||
const ANIMATION_PREFIX = '@';
|
||||
const DISABLE_ANIMATIONS_FLAG = '@.disabled';
|
||||
|
||||
// Define a recursive type to allow for nested arrays of `AnimationTriggerMetadata`. Note that an
|
||||
// interface declaration is used as TypeScript prior to 3.7 does not support recursive type
|
||||
// references, see https://github.com/microsoft/TypeScript/pull/33050 for details.
|
||||
type NestedAnimationTriggerMetadata = AnimationTriggerMetadata | RecursiveAnimationTriggerMetadata;
|
||||
interface RecursiveAnimationTriggerMetadata extends Array<NestedAnimationTriggerMetadata> {}
|
||||
|
||||
@Injectable()
|
||||
export class AnimationRendererFactory implements RendererFactory2 {
|
||||
private _currentId: number = 0;
|
||||
@ -55,10 +61,17 @@ export class AnimationRendererFactory implements RendererFactory2 {
|
||||
this._currentId++;
|
||||
|
||||
this.engine.register(namespaceId, hostElement);
|
||||
const animationTriggers = type.data['animation'] as AnimationTriggerMetadata[];
|
||||
animationTriggers.forEach(
|
||||
trigger => this.engine.registerTrigger(
|
||||
componentId, namespaceId, hostElement, trigger.name, trigger));
|
||||
|
||||
const registerTrigger = (trigger: NestedAnimationTriggerMetadata) => {
|
||||
if (Array.isArray(trigger)) {
|
||||
trigger.forEach(registerTrigger);
|
||||
} else {
|
||||
this.engine.registerTrigger(componentId, namespaceId, hostElement, trigger.name, trigger);
|
||||
}
|
||||
};
|
||||
const animationTriggers = type.data['animation'] as NestedAnimationTriggerMetadata[];
|
||||
animationTriggers.forEach(registerTrigger);
|
||||
|
||||
return new AnimationRenderer(this, namespaceId, delegate, this.engine);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user