fix(ivy): error if directive with synthetic property binding is on same node as directive that injects ViewContainerRef (#35343)
In the `loadRenderer` we make an assumption that the value will always be an `LView`, but if there's a directive on the same node which injects `ViewContainerRef` the `LView` will be wrapped in an `LContainer`. These changes add a call to unwrap the value before we try to read the value off of it. Fixes #35342. PR Close #35343
This commit is contained in:
parent
e8ea3be843
commit
d6bc63fa38
@ -36,7 +36,7 @@ import {NO_CHANGE} from '../tokens';
|
|||||||
import {isAnimationProp, mergeHostAttrs} from '../util/attrs_utils';
|
import {isAnimationProp, mergeHostAttrs} from '../util/attrs_utils';
|
||||||
import {INTERPOLATION_DELIMITER, renderStringify, stringifyForError} from '../util/misc_utils';
|
import {INTERPOLATION_DELIMITER, renderStringify, stringifyForError} from '../util/misc_utils';
|
||||||
import {getLViewParent} from '../util/view_traversal_utils';
|
import {getLViewParent} from '../util/view_traversal_utils';
|
||||||
import {getComponentLViewByIndex, getNativeByIndex, getNativeByTNode, getTNode, isCreationMode, readPatchedLView, resetPreOrderHookFlags, viewAttachedToChangeDetector} from '../util/view_utils';
|
import {getComponentLViewByIndex, getNativeByIndex, getNativeByTNode, getTNode, isCreationMode, readPatchedLView, resetPreOrderHookFlags, unwrapLView, viewAttachedToChangeDetector} from '../util/view_utils';
|
||||||
|
|
||||||
import {selectIndexInternal} from './advance';
|
import {selectIndexInternal} from './advance';
|
||||||
import {LCleanup, LViewBlueprint, MatchesArray, TCleanup, TNodeDebug, TNodeInitialInputs, TNodeLocalNames, TViewComponents, TViewConstructor, attachLContainerDebug, attachLViewDebug, cloneToLViewFromTViewBlueprint, cloneToTViewData} from './lview_debug';
|
import {LCleanup, LViewBlueprint, MatchesArray, TCleanup, TNodeDebug, TNodeInitialInputs, TNodeLocalNames, TViewComponents, TViewConstructor, attachLContainerDebug, attachLViewDebug, cloneToLViewFromTViewBlueprint, cloneToTViewData} from './lview_debug';
|
||||||
@ -1934,7 +1934,7 @@ function getTViewCleanup(tView: TView): any[] {
|
|||||||
* instead of the current renderer (see the componentSyntheticHost* instructions).
|
* instead of the current renderer (see the componentSyntheticHost* instructions).
|
||||||
*/
|
*/
|
||||||
export function loadComponentRenderer(tNode: TNode, lView: LView): Renderer3 {
|
export function loadComponentRenderer(tNode: TNode, lView: LView): Renderer3 {
|
||||||
const componentLView = lView[tNode.index] as LView;
|
const componentLView = unwrapLView(lView[tNode.index]) !;
|
||||||
return componentLView[RENDERER];
|
return componentLView[RENDERER];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,8 +5,9 @@
|
|||||||
* Use of this source code is governed by an MIT-style license that can be
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
import {state, style, trigger} from '@angular/animations';
|
||||||
import {CommonModule} from '@angular/common';
|
import {CommonModule} from '@angular/common';
|
||||||
import {Component, Directive, EventEmitter, Input, Output} from '@angular/core';
|
import {Component, Directive, EventEmitter, Input, Output, ViewContainerRef} from '@angular/core';
|
||||||
import {TestBed} from '@angular/core/testing';
|
import {TestBed} from '@angular/core/testing';
|
||||||
import {By, DomSanitizer, SafeUrl} from '@angular/platform-browser';
|
import {By, DomSanitizer, SafeUrl} from '@angular/platform-browser';
|
||||||
|
|
||||||
@ -598,4 +599,32 @@ describe('property bindings', () => {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not throw on synthetic property bindings when a directive on the same element injects ViewContainerRef',
|
||||||
|
() => {
|
||||||
|
@Component({
|
||||||
|
selector: 'my-comp',
|
||||||
|
template: '',
|
||||||
|
animations: [trigger('trigger', [state('void', style({opacity: 0}))])],
|
||||||
|
host: {'[@trigger]': '"void"'}
|
||||||
|
})
|
||||||
|
class MyComp {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Directive({selector: '[my-dir]'})
|
||||||
|
class MyDir {
|
||||||
|
constructor(public viewContainerRef: ViewContainerRef) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({template: '<my-comp my-dir></my-comp>'})
|
||||||
|
class App {
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [App, MyDir, MyComp]});
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
const fixture = TestBed.createComponent(App);
|
||||||
|
fixture.detectChanges();
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user