fix(ivy): throw a descriptive error when trying to insert / move destroyed view (#27289)

PR Close #27289
This commit is contained in:
Pawel Kozlowski 2018-11-27 14:38:01 +01:00 committed by Jason Aden
parent d0e8020506
commit 0487fbe236
3 changed files with 39 additions and 36 deletions

View File

@ -265,6 +265,7 @@ export class ComponentRef<T> extends viewEngine_ComponentRef<T> {
ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed'); ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
this.destroyCbs !.forEach(fn => fn()); this.destroyCbs !.forEach(fn => fn());
this.destroyCbs = null; this.destroyCbs = null;
this.hostView.destroy();
} }
onDestroy(callback: () => void): void { onDestroy(callback: () => void): void {
ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed'); ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');

View File

@ -265,6 +265,9 @@ export function createContainerRef(
} }
move(viewRef: viewEngine_ViewRef, newIndex: number): viewEngine_ViewRef { move(viewRef: viewEngine_ViewRef, newIndex: number): viewEngine_ViewRef {
if (viewRef.destroyed) {
throw new Error('Cannot move a destroyed View in a ViewContainer!');
}
const index = this.indexOf(viewRef); const index = this.indexOf(viewRef);
this.detach(index); this.detach(index);
this.insert(viewRef, this._adjustIndex(newIndex)); this.insert(viewRef, this._adjustIndex(newIndex));

View File

@ -995,17 +995,18 @@ function declareTests(config?: {useJit: boolean}) {
expect(dir.receivedArgs).toEqual(['one', undefined]); expect(dir.receivedArgs).toEqual(['one', undefined]);
}); });
fixmeIvy('unknown') && it('should not allow pipes in hostListeners', () => { fixmeIvy('FW-742: Pipes in host listeners should throw a descriptive error') &&
@Directive({selector: '[host-listener]', host: {'(click)': 'doIt() | somePipe'}}) it('should not allow pipes in hostListeners', () => {
class DirectiveWithHostListener { @Directive({selector: '[host-listener]', host: {'(click)': 'doIt() | somePipe'}})
} class DirectiveWithHostListener {
}
TestBed.configureTestingModule({declarations: [MyComp, DirectiveWithHostListener]}); TestBed.configureTestingModule({declarations: [MyComp, DirectiveWithHostListener]});
const template = '<div host-listener></div>'; const template = '<div host-listener></div>';
TestBed.overrideComponent(MyComp, {set: {template}}); TestBed.overrideComponent(MyComp, {set: {template}});
expect(() => TestBed.createComponent(MyComp)) expect(() => TestBed.createComponent(MyComp))
.toThrowError(/Cannot have a pipe in an action expression/); .toThrowError(/Cannot have a pipe in an action expression/);
}); });
@ -1238,37 +1239,35 @@ function declareTests(config?: {useJit: boolean}) {
}); });
describe('.insert', () => { describe('.insert', () => {
fixmeIvy('unknown') && it('should throw with destroyed views', async(() => {
it('should throw with destroyed views', async(() => { const fixture = TestBed.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]})
const fixture = TestBed.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]}) .createComponent(MyComp);
.createComponent(MyComp); const tc = fixture.debugElement.children[0].children[0];
const tc = fixture.debugElement.children[0].children[0]; const dynamicVp: DynamicViewport = tc.injector.get(DynamicViewport);
const dynamicVp: DynamicViewport = tc.injector.get(DynamicViewport); const ref = dynamicVp.create();
const ref = dynamicVp.create(); fixture.detectChanges();
fixture.detectChanges();
ref.destroy(); ref.destroy();
expect(() => { expect(() => {
dynamicVp.insert(ref.hostView); dynamicVp.insert(ref.hostView);
}).toThrowError('Cannot insert a destroyed View in a ViewContainer!'); }).toThrowError('Cannot insert a destroyed View in a ViewContainer!');
})); }));
}); });
describe('.move', () => { describe('.move', () => {
fixmeIvy('unknown') && it('should throw with destroyed views', async(() => {
it('should throw with destroyed views', async(() => { const fixture = TestBed.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]})
const fixture = TestBed.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]}) .createComponent(MyComp);
.createComponent(MyComp); const tc = fixture.debugElement.children[0].children[0];
const tc = fixture.debugElement.children[0].children[0]; const dynamicVp: DynamicViewport = tc.injector.get(DynamicViewport);
const dynamicVp: DynamicViewport = tc.injector.get(DynamicViewport); const ref = dynamicVp.create();
const ref = dynamicVp.create(); fixture.detectChanges();
fixture.detectChanges();
ref.destroy(); ref.destroy();
expect(() => { expect(() => {
dynamicVp.move(ref.hostView, 1); dynamicVp.move(ref.hostView, 1);
}).toThrowError('Cannot move a destroyed View in a ViewContainer!'); }).toThrowError('Cannot move a destroyed View in a ViewContainer!');
})); }));
}); });
}); });