fix(ivy): init hooks being re-run if an exception is throw (#28024)
Fixes Ivy running the init hooks if an exception is thrown in one of them. These changes fix FW-830. PR Close #28024
This commit is contained in:
parent
3bafc002ae
commit
a6ba789599
@ -319,11 +319,14 @@ export function leaveView(newView: LView): void {
|
|||||||
if (isCreationMode(lView)) {
|
if (isCreationMode(lView)) {
|
||||||
lView[FLAGS] &= ~LViewFlags.CreationMode;
|
lView[FLAGS] &= ~LViewFlags.CreationMode;
|
||||||
} else {
|
} else {
|
||||||
executeHooks(lView, tView.viewHooks, tView.viewCheckHooks, checkNoChangesMode);
|
try {
|
||||||
// Views are clean and in update mode after being checked, so these bits are cleared
|
executeHooks(lView, tView.viewHooks, tView.viewCheckHooks, checkNoChangesMode);
|
||||||
lView[FLAGS] &= ~(LViewFlags.Dirty | LViewFlags.FirstLViewPass);
|
} finally {
|
||||||
lView[FLAGS] |= LViewFlags.RunInit;
|
// Views are clean and in update mode after being checked, so these bits are cleared
|
||||||
lView[BINDING_INDEX] = tView.bindingStartIndex;
|
lView[FLAGS] &= ~(LViewFlags.Dirty | LViewFlags.FirstLViewPass);
|
||||||
|
lView[FLAGS] |= LViewFlags.RunInit;
|
||||||
|
lView[BINDING_INDEX] = tView.bindingStartIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
enterView(newView, null);
|
enterView(newView, null);
|
||||||
}
|
}
|
||||||
|
@ -1022,33 +1022,31 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [
|
|||||||
expect(directiveLog.filter(['ngAfterViewInit'])).toEqual([]);
|
expect(directiveLog.filter(['ngAfterViewInit'])).toEqual([]);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
fixmeIvy(
|
it('should not call ngAfterViewInit again if it throws', fakeAsync(() => {
|
||||||
'FW-830: Exception thrown in ngAfterViewInit triggers ngAfterViewInit re-execution')
|
const ctx =
|
||||||
.it('should not call ngAfterViewInit again if it throws', fakeAsync(() => {
|
createCompFixture('<div testDirective="dir" throwOn="ngAfterViewInit"></div>');
|
||||||
const ctx = createCompFixture(
|
|
||||||
'<div testDirective="dir" throwOn="ngAfterViewInit"></div>');
|
|
||||||
|
|
||||||
let errored = false;
|
let errored = false;
|
||||||
// First pass fails, but ngAfterViewInit should be called.
|
// First pass fails, but ngAfterViewInit should be called.
|
||||||
try {
|
try {
|
||||||
ctx.detectChanges(false);
|
ctx.detectChanges(false);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
errored = true;
|
errored = true;
|
||||||
}
|
}
|
||||||
expect(errored).toBe(true);
|
expect(errored).toBe(true);
|
||||||
|
|
||||||
expect(directiveLog.filter(['ngAfterViewInit'])).toEqual(['dir.ngAfterViewInit']);
|
expect(directiveLog.filter(['ngAfterViewInit'])).toEqual(['dir.ngAfterViewInit']);
|
||||||
directiveLog.clear();
|
directiveLog.clear();
|
||||||
|
|
||||||
// Second change detection also fails, but this time ngAfterViewInit should not be
|
// Second change detection also fails, but this time ngAfterViewInit should not be
|
||||||
// called.
|
// called.
|
||||||
try {
|
try {
|
||||||
ctx.detectChanges(false);
|
ctx.detectChanges(false);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error('Second detectChanges() should not have run detection.');
|
throw new Error('Second detectChanges() should not have run detection.');
|
||||||
}
|
}
|
||||||
expect(directiveLog.filter(['ngAfterViewInit'])).toEqual([]);
|
expect(directiveLog.filter(['ngAfterViewInit'])).toEqual([]);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('ngAfterViewChecked', () => {
|
describe('ngAfterViewChecked', () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user