fix(ivy): ensure renderer begin/end methods are only called during change detection (#28192)
In VE the renderer.begin() and renderer.end() methods are only called when CD is called on an element. This patch ensures that Ivy does the same thing. Jira issue: FW-945 PR Close #28192
This commit is contained in:
parent
1f7d3b9a57
commit
896cf35afb
|
@ -169,8 +169,6 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
|
||||||
let component: T;
|
let component: T;
|
||||||
let tElementNode: TElementNode;
|
let tElementNode: TElementNode;
|
||||||
try {
|
try {
|
||||||
if (rendererFactory.begin) rendererFactory.begin();
|
|
||||||
|
|
||||||
const componentView = createRootComponentView(
|
const componentView = createRootComponentView(
|
||||||
hostRNode, this.componentDef, rootLView, rendererFactory, renderer);
|
hostRNode, this.componentDef, rootLView, rendererFactory, renderer);
|
||||||
|
|
||||||
|
@ -216,7 +214,6 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
|
||||||
refreshDescendantViews(rootLView);
|
refreshDescendantViews(rootLView);
|
||||||
} finally {
|
} finally {
|
||||||
leaveView(oldLView);
|
leaveView(oldLView);
|
||||||
if (rendererFactory.end) rendererFactory.end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const componentRef = new ComponentRef(
|
const componentRef = new ComponentRef(
|
||||||
|
|
|
@ -395,12 +395,13 @@ function renderComponentOrTemplate<T>(
|
||||||
const rendererFactory = hostView[RENDERER_FACTORY];
|
const rendererFactory = hostView[RENDERER_FACTORY];
|
||||||
const oldView = enterView(hostView, hostView[HOST_NODE]);
|
const oldView = enterView(hostView, hostView[HOST_NODE]);
|
||||||
const normalExecutionPath = !getCheckNoChangesMode();
|
const normalExecutionPath = !getCheckNoChangesMode();
|
||||||
|
const creationModeIsActive = isCreationMode(hostView);
|
||||||
try {
|
try {
|
||||||
if (normalExecutionPath && rendererFactory.begin) {
|
if (normalExecutionPath && !creationModeIsActive && rendererFactory.begin) {
|
||||||
rendererFactory.begin();
|
rendererFactory.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCreationMode(hostView)) {
|
if (creationModeIsActive) {
|
||||||
// creation mode pass
|
// creation mode pass
|
||||||
if (templateFn) {
|
if (templateFn) {
|
||||||
namespaceHTML();
|
namespaceHTML();
|
||||||
|
@ -415,7 +416,7 @@ function renderComponentOrTemplate<T>(
|
||||||
templateFn && templateFn(RenderFlags.Update, context !);
|
templateFn && templateFn(RenderFlags.Update, context !);
|
||||||
refreshDescendantViews(hostView);
|
refreshDescendantViews(hostView);
|
||||||
} finally {
|
} finally {
|
||||||
if (normalExecutionPath && rendererFactory.end) {
|
if (normalExecutionPath && !creationModeIsActive && rendererFactory.end) {
|
||||||
rendererFactory.end();
|
rendererFactory.end();
|
||||||
}
|
}
|
||||||
leaveView(oldView);
|
leaveView(oldView);
|
||||||
|
|
|
@ -803,58 +803,56 @@ import {HostListener} from '../../src/metadata/directives';
|
||||||
expect(player.element.style.height).toEqual('444px');
|
expect(player.element.style.height).toEqual('444px');
|
||||||
});
|
});
|
||||||
|
|
||||||
fixmeIvy(
|
it('should find newly inserted items in the component via :enter', () => {
|
||||||
'FW-945 - Ivy createComponent calls CD while VE waits for CD to be explicitly called')
|
@Component({
|
||||||
.it('should find newly inserted items in the component via :enter', () => {
|
selector: 'ani-cmp',
|
||||||
@Component({
|
template: `
|
||||||
selector: 'ani-cmp',
|
|
||||||
template: `
|
|
||||||
<div @myAnimation>
|
<div @myAnimation>
|
||||||
<div *ngFor="let item of items" class="child">
|
<div *ngFor="let item of items" class="child">
|
||||||
{{ item }}
|
{{ item }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
animations: [trigger(
|
animations: [trigger(
|
||||||
'myAnimation',
|
'myAnimation',
|
||||||
[
|
[
|
||||||
transition(
|
transition(
|
||||||
':enter',
|
':enter',
|
||||||
[
|
[
|
||||||
query(
|
query(
|
||||||
':enter',
|
':enter',
|
||||||
[
|
[
|
||||||
style({opacity: 0}),
|
style({opacity: 0}),
|
||||||
animate(1000, style({opacity: .5})),
|
animate(1000, style({opacity: .5})),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
])]
|
])]
|
||||||
})
|
})
|
||||||
class Cmp {
|
class Cmp {
|
||||||
public items: any[] = [0, 1, 2];
|
public items: any[] = [0, 1, 2];
|
||||||
}
|
}
|
||||||
|
|
||||||
TestBed.configureTestingModule({declarations: [Cmp]});
|
TestBed.configureTestingModule({declarations: [Cmp]});
|
||||||
|
|
||||||
const engine = TestBed.get(ɵAnimationEngine);
|
const engine = TestBed.get(ɵAnimationEngine);
|
||||||
const fixture = TestBed.createComponent(Cmp);
|
const fixture = TestBed.createComponent(Cmp);
|
||||||
const cmp = fixture.componentInstance;
|
const cmp = fixture.componentInstance;
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
engine.flush();
|
engine.flush();
|
||||||
|
|
||||||
const players = getLog();
|
const players = getLog();
|
||||||
expect(players.length).toEqual(3);
|
expect(players.length).toEqual(3);
|
||||||
|
|
||||||
const [p1, p2, p3] = players;
|
const [p1, p2, p3] = players;
|
||||||
expect(p1.element.innerText.trim()).toEqual('0');
|
expect(p1.element.innerText.trim()).toEqual('0');
|
||||||
expect(p2.element.innerText.trim()).toEqual('1');
|
expect(p2.element.innerText.trim()).toEqual('1');
|
||||||
expect(p3.element.innerText.trim()).toEqual('2');
|
expect(p3.element.innerText.trim()).toEqual('2');
|
||||||
|
|
||||||
players.forEach(p => {
|
players.forEach(p => {
|
||||||
expect(p.keyframes).toEqual([{opacity: '0', offset: 0}, {opacity: '0.5', offset: 1}]);
|
expect(p.keyframes).toEqual([{opacity: '0', offset: 0}, {opacity: '0.5', offset: 1}]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should cleanup :enter and :leave artifacts from nodes when any animation sequences fail to be built',
|
it('should cleanup :enter and :leave artifacts from nodes when any animation sequences fail to be built',
|
||||||
() => {
|
() => {
|
||||||
|
|
|
@ -105,7 +105,7 @@ describe('renderer factory lifecycle', () => {
|
||||||
|
|
||||||
it('should work with a template', () => {
|
it('should work with a template', () => {
|
||||||
renderToHtml(Template, {}, 1, 0, null, null, rendererFactory);
|
renderToHtml(Template, {}, 1, 0, null, null, rendererFactory);
|
||||||
expect(logs).toEqual(['create', 'begin', 'function create', 'function update', 'end']);
|
expect(logs).toEqual(['create', 'function create', 'function update']);
|
||||||
|
|
||||||
logs = [];
|
logs = [];
|
||||||
renderToHtml(Template, {});
|
renderToHtml(Template, {});
|
||||||
|
@ -115,8 +115,8 @@ describe('renderer factory lifecycle', () => {
|
||||||
it('should work with a template which contains a component', () => {
|
it('should work with a template which contains a component', () => {
|
||||||
renderToHtml(TemplateWithComponent, {}, 2, 0, directives, null, rendererFactory);
|
renderToHtml(TemplateWithComponent, {}, 2, 0, directives, null, rendererFactory);
|
||||||
expect(logs).toEqual([
|
expect(logs).toEqual([
|
||||||
'create', 'begin', 'function_with_component create', 'create', 'component create',
|
'create', 'function_with_component create', 'create', 'component create',
|
||||||
'function_with_component update', 'component update', 'end'
|
'function_with_component update', 'component update'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
logs = [];
|
logs = [];
|
||||||
|
|
Loading…
Reference in New Issue