fix(upgrade): upgrade Directive facade should not return different instance from constructor (#27660)

In ngUpgrade (dynamic) we create a dynamic Angular `Directive` that wraps AngularJS components
that are being upgraded. The constructor of this `Directive` class returns a different instance
than `this`. It is this instance that actually contains the life-cycle hook handlers.

This would break in ivy, since the methods on the prototype of the original class are wired up,
rather than the instance methods. This results in hooks like `ngOnInit` not being called.

This commit refactors the code to extend the inner class that was being returned so that the
prototype chain is correct for both ViewEngine and ivy.

This change resolves a number of failing ivy tests, but also exposes other failures that were
masked by this issue. The tests have been updated accordingly.

(FW-812)

PR Close #27660
This commit is contained in:
Pete Bacon Darwin 2018-12-13 18:07:24 +00:00 committed by Miško Hevery
parent 3444aee5da
commit c986d3dcf4
2 changed files with 1075 additions and 1146 deletions

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Directive, DoCheck, ElementRef, EventEmitter, Inject, Injector, OnChanges, OnInit, SimpleChange, SimpleChanges, Type} from '@angular/core';
import {Directive, DoCheck, ElementRef, EventEmitter, Inject, Injector, OnChanges, OnDestroy, OnInit, SimpleChange, SimpleChanges, Type} from '@angular/core';
import * as angular from '../common/angular1';
import {$SCOPE} from '../common/constants';
@ -46,23 +46,14 @@ export class UpgradeNg1ComponentAdapterBuilder {
const directive = {selector: selector, inputs: this.inputsRename, outputs: this.outputsRename};
@Directive({jit: true, ...directive})
class MyClass {
// TODO(issue/24571): remove '!'.
directive !: angular.IDirective;
class MyClass extends UpgradeNg1ComponentAdapter implements OnInit, OnChanges, DoCheck,
OnDestroy {
constructor(
@Inject($SCOPE) scope: angular.IScope, injector: Injector, elementRef: ElementRef) {
const helper = new UpgradeHelper(injector, name, elementRef, this.directive);
return new UpgradeNg1ComponentAdapter(
helper, scope, self.template, self.inputs, self.outputs, self.propertyOutputs,
self.checkProperties, self.propertyMap) as any;
}
ngOnInit() { /* needs to be here for ng2 to properly detect it */
}
ngOnChanges() { /* needs to be here for ng2 to properly detect it */
}
ngDoCheck() { /* needs to be here for ng2 to properly detect it */
}
ngOnDestroy() { /* needs to be here for ng2 to properly detect it */
super(
new UpgradeHelper(injector, name, elementRef, self.directive || undefined), scope,
self.template, self.inputs, self.outputs, self.propertyOutputs, self.checkProperties,
self.propertyMap) as any;
}
}
this.type = MyClass;
@ -149,7 +140,7 @@ class UpgradeNg1ComponentAdapter implements OnInit, OnChanges, DoCheck {
private controllerInstance: IControllerInstance|null = null;
destinationObj: IBindingDestination|null = null;
checkLastValues: any[] = [];
private directive: angular.IDirective;
directive: angular.IDirective;
element: Element;
$element: any = null;
componentScope: angular.IScope;

View File

@ -56,8 +56,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-714: ng1 projected content is not being rendered')
.it('should instantiate ng1 in ng2 template and project content', async(() => {
it('should instantiate ng1 in ng2 template and project content', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
@ -76,10 +75,7 @@ withEachNg1Version(() => {
}
ng1Module.directive('ng1', () => {
return {
transclude: true,
template: '{{ "ng1" }}(<ng-transclude></ng-transclude>)'
};
return {transclude: true, template: '{{ "ng1" }}(<ng-transclude></ng-transclude>)'};
});
ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2));
@ -657,8 +653,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-713: ngDestroy not being called when downgraded ng2 component is destroyed')
.it('should properly run cleanup with multiple levels of nesting', async(() => {
it('should properly run cleanup with multiple levels of nesting', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
let destroyed = false;
@ -1035,8 +1030,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-724: upgraded ng1 components are not being rendered')
.it('should support `&` bindings', fakeAsync(() => {
it('should support `&` bindings', fakeAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
// Define `ng1Component`
@ -1059,8 +1053,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
const ng1Module = angular.module('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -1294,8 +1287,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-724: upgraded ng1 components are not being rendered')
.it('should support templateUrl fetched from $httpBackend', async(() => {
it('should support templateUrl fetched from $httpBackend', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
ng1Module.value(
@ -1324,8 +1316,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-724: upgraded ng1 components are not being rendered')
.it('should support templateUrl as a function', async(() => {
it('should support templateUrl as a function', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
ng1Module.value(
@ -1406,8 +1397,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-724: upgraded ng1 components are not being rendered')
.it('should support templateUrl fetched from $templateCache', async(() => {
it('should support templateUrl fetched from $templateCache', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
ng1Module.run(($templateCache: any) => $templateCache.put('url.html', 'WORKS'));
@ -1434,8 +1424,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-724: upgraded ng1 components are not being rendered')
.it('should support controller with controllerAs', async(() => {
it('should support controller with controllerAs', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
@ -1449,13 +1438,11 @@ withEachNg1Version(() => {
scope: any; hasElement: string; $element: any; isClass: any;
constructor($scope: any, $element: any) {
this.verifyIAmAClass();
this.scope =
$scope.$parent.$parent == $scope.$root ? 'scope' : 'wrong-scope';
this.scope = $scope.$parent.$parent == $scope.$root ? 'scope' : 'wrong-scope';
this.hasElement = $element[0].nodeName;
this.$element = $element;
} verifyIAmAClass() { this.isClass = 'isClass'; } isPublished() {
return this.$element.controller('ng1') == this ? 'published' :
'not-published';
return this.$element.controller('ng1') == this ? 'published' : 'not-published';
}
}
};
@ -1476,8 +1463,7 @@ withEachNg1Version(() => {
ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2));
const element = html(`<div><ng2></ng2></div>`);
adapter.bootstrap(element, ['ng1']).ready((ref) => {
expect(multiTrim(document.body.textContent))
.toEqual('scope; isClass; NG1; published');
expect(multiTrim(document.body.textContent)).toEqual('scope; isClass; NG1; published');
ref.dispose();
});
}));
@ -1552,8 +1538,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-724: upgraded ng1 components are not being rendered')
.it('should support single require in linking fn', async(() => {
it('should support single require in linking fn', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
@ -1594,8 +1579,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-724: upgraded ng1 components are not being rendered')
.it('should support array require in linking fn', async(() => {
it('should support array require in linking fn', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
@ -1640,9 +1624,7 @@ withEachNg1Version(() => {
}));
describe('with life-cycle hooks', () => {
fixmeIvy(
'FW-812: Life-cycle hooks not correctly wired up for components that return a different instance from their constructor')
.it('should call `$onInit()` on controller', async(() => {
it('should call `$onInit()` on controller', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const $onInitSpyA = jasmine.createSpy('$onInitA');
const $onInitSpyB = jasmine.createSpy('$onInitB');
@ -1733,9 +1715,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy(
'FW-812: Life-cycle hooks not correctly wired up for components that return a different instance from their constructor')
.it('should call `$doCheck()` on controller', async(() => {
it('should call `$doCheck()` on controller', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const $doCheckSpyA = jasmine.createSpy('$doCheckA');
const $doCheckSpyB = jasmine.createSpy('$doCheckB');
@ -1844,9 +1824,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy(
'FW-812: Life-cycle hooks not correctly wired up for components that return a different instance from their constructor')
.it('should call `$postLink()` on controller', async(() => {
it('should call `$postLink()` on controller', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const $postLinkSpyA = jasmine.createSpy('$postLinkA');
const $postLinkSpyB = jasmine.createSpy('$postLinkB');
@ -1863,8 +1841,7 @@ withEachNg1Version(() => {
controllerAs: '$ctrl',
controller: class {$postLink() { $postLinkSpyA(); }}
}))
.directive(
'ng1B', () => ({
.directive('ng1B', () => ({
template: '',
scope: {},
bindToController: false,
@ -1939,7 +1916,7 @@ withEachNg1Version(() => {
}));
fixmeIvy(
'FW-812: Life-cycle hooks not correctly wired up for components that return a different instance from their constructor')
'FW-844: Directive input bindings cannot be assigned after the `@Directive` decorator has been compiled')
.it('should call `$onChanges()` on binding destination', fakeAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const $onChangesControllerSpyA = jasmine.createSpy('$onChangesControllerA');
@ -2035,7 +2012,7 @@ withEachNg1Version(() => {
}));
fixmeIvy(
'FW-812: Life-cycle hooks not correctly wired up for components that return a different instance from their constructor')
'FW-843: destroy hooks are not registered on upgraded ng1 components contained in ng2 component templates under ivy')
.it('should call `$onDestroy()` on controller', fakeAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const $onDestroySpyA = jasmine.createSpy('$onDestroyA');
@ -2127,9 +2104,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy(
'FW-812: Life-cycle hooks not correctly wired up for components that return a different instance from their constructor')
.it('should not call `$onDestroy()` on scope', fakeAsync(() => {
it('should not call `$onDestroy()` on scope', fakeAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const $onDestroySpy = jasmine.createSpy('$onDestroy');
let ng2ComponentInstance: Ng2Component;
@ -2159,8 +2134,7 @@ withEachNg1Version(() => {
bindToController: true,
controllerAs: '$ctrl',
controller: function($scope: angular.IScope) {
Object.getPrototypeOf($scope).$onDestroy =
$onDestroySpy;
Object.getPrototypeOf($scope).$onDestroy = $onDestroySpy;
}
}))
.directive('ng1B', () => ({
@ -2212,14 +2186,12 @@ withEachNg1Version(() => {
});
describe('destroying the upgraded component', () => {
fixmeIvy('FW-713: ngDestroy not being called when downgraded ng2 component is destroyed')
.it('should destroy `componentScope`', fakeAsync(() => {
it('should destroy `componentScope`', fakeAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const scopeDestroyListener = jasmine.createSpy('scopeDestroyListener');
let ng2ComponentInstance: Ng2Component;
@Component(
{selector: 'ng2', template: '<div *ngIf="!ng2Destroy"><ng1></ng1></div>'})
@Component({selector: 'ng2', template: '<div *ngIf="!ng2Destroy"><ng1></ng1></div>'})
class Ng2Component {
ng2Destroy: boolean = false;
constructor() { ng2ComponentInstance = this; }
@ -2259,15 +2231,13 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-713: ngDestroy not being called when downgraded ng2 component is destroyed')
.it('should emit `$destroy` on `$element` and descendants', fakeAsync(() => {
it('should emit `$destroy` on `$element` and descendants', fakeAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const elementDestroyListener = jasmine.createSpy('elementDestroyListener');
const descendantDestroyListener = jasmine.createSpy('descendantDestroyListener');
let ng2ComponentInstance: Ng2Component;
@Component(
{selector: 'ng2', template: '<div *ngIf="!ng2Destroy"><ng1></ng1></div>'})
@Component({selector: 'ng2', template: '<div *ngIf="!ng2Destroy"><ng1></ng1></div>'})
class Ng2Component {
ng2Destroy: boolean = false;
constructor() { ng2ComponentInstance = this; }
@ -2315,8 +2285,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-713: ngDestroy not being called when downgraded ng2 component is destroyed')
.it('should clear data on `$element` and descendants', fakeAsync(() => {
it('should clear data on `$element` and descendants', fakeAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
let ng1ComponentElement: angular.IAugmentedJQuery;
let ng2ComponentAInstance: Ng2ComponentA;
@ -2353,8 +2322,7 @@ withEachNg1Version(() => {
// Define `Ng2Module`
@NgModule({
declarations:
[adapter.upgradeNg1Component('ng1'), Ng2ComponentA, Ng2ComponentB],
declarations: [adapter.upgradeNg1Component('ng1'), Ng2ComponentA, Ng2ComponentB],
entryComponents: [Ng2ComponentA],
imports: [BrowserModule]
})
@ -2381,8 +2349,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-713: ngDestroy not being called when downgraded ng2 component is destroyed')
.it('should clear dom listeners on `$element` and descendants`', fakeAsync(() => {
it('should clear dom listeners on `$element` and descendants`', fakeAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const elementClickListener = jasmine.createSpy('elementClickListener');
const descendantClickListener = jasmine.createSpy('descendantClickListener');
@ -2421,8 +2388,7 @@ withEachNg1Version(() => {
// Define `Ng2Module`
@NgModule({
declarations:
[adapter.upgradeNg1Component('ng1'), Ng2ComponentA, Ng2ComponentB],
declarations: [adapter.upgradeNg1Component('ng1'), Ng2ComponentA, Ng2ComponentB],
entryComponents: [Ng2ComponentA],
imports: [BrowserModule]
})
@ -2453,9 +2419,7 @@ withEachNg1Version(() => {
});
describe('linking', () => {
fixmeIvy(
'FW-812: Life-cycle hooks not correctly wired up for components that return a different instance from their constructor')
.it('should run the pre-linking after instantiating the controller', async(() => {
it('should run the pre-linking after instantiating the controller', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const log: string[] = [];
@ -2472,8 +2436,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module =
angular.module('ng1', [])
const ng1Module = angular.module('ng1', [])
.directive('ng1', () => ng1Directive)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2493,9 +2456,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy(
'FW-812: Life-cycle hooks not correctly wired up for components that return a different instance from their constructor')
.it('should run the pre-linking function before linking', async(() => {
it('should run the pre-linking function before linking', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const log: string[] = [];
@ -2513,8 +2474,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module =
angular.module('ng1', [])
const ng1Module = angular.module('ng1', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2536,9 +2496,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy(
'FW-812: Life-cycle hooks not correctly wired up for components that return a different instance from their constructor')
.it('should run the post-linking function after linking (link: object)', async(() => {
it('should run the post-linking function after linking (link: object)', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const log: string[] = [];
@ -2556,8 +2514,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module =
angular.module('ng1', [])
const ng1Module = angular.module('ng1', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2579,9 +2536,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy(
'FW-812: Life-cycle hooks not correctly wired up for components that return a different instance from their constructor')
.it('should run the post-linking function after linking (link: function)', async(() => {
it('should run the post-linking function after linking (link: function)', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const log: string[] = [];
@ -2599,8 +2554,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module =
angular.module('ng1', [])
const ng1Module = angular.module('ng1', [])
.directive('ng1A', () => ng1DirectiveA)
.directive('ng1B', () => ng1DirectiveB)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2622,9 +2576,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy(
'FW-812: Life-cycle hooks not correctly wired up for components that return a different instance from their constructor')
.it('should run the post-linking function before `$postLink`', async(() => {
it('should run the post-linking function before `$postLink`', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const log: string[] = [];
@ -2641,8 +2593,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module =
angular.module('ng1', [])
const ng1Module = angular.module('ng1', [])
.directive('ng1', () => ng1Directive)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2727,8 +2678,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-714: ng1 projected content is not being rendered')
.it('should support single-slot transclusion with fallback content', async(() => {
it('should support single-slot transclusion with fallback content', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
let ng1ControllerInstances: any[] = [];
let ng2ComponentInstance: Ng2Component;
@ -2761,8 +2711,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
const ng1Module = angular.module('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2790,8 +2739,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-714: ng1 projected content is not being rendered')
.it('should support multi-slot transclusion', async(() => {
it('should support multi-slot transclusion', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
let ng2ComponentInstance: Ng2Component;
@ -2822,8 +2770,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
const ng1Module = angular.module('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2852,20 +2799,17 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-714: ng1 projected content is not being rendered')
.it('should support default slot (with fallback content)', async(() => {
it('should support default slot (with fallback content)', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
let ng1ControllerInstances: any[] = [];
let ng2ComponentInstance: Ng2Component;
// Define `ng1Component`
const ng1Component: angular.IComponent = {
template:
'ng1(default(<div ng-transclude="">fallback-{{ $ctrl.value }}</div>))',
template: 'ng1(default(<div ng-transclude="">fallback-{{ $ctrl.value }}</div>))',
transclude: {slotX: 'contentX', slotY: 'contentY'},
controller: class {
value = 'ng1'; constructor() { ng1ControllerInstances.push(this); }
}
controller:
class {value = 'ng1'; constructor() { ng1ControllerInstances.push(this); }}
};
// Define `Ng2Component`
@ -2900,8 +2844,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
const ng1Module = angular.module('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -2933,8 +2876,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-714: ng1 projected content is not being rendered')
.it('should support optional transclusion slots (with fallback content)', async(() => {
it('should support optional transclusion slots (with fallback content)', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
let ng1ControllerInstances: any[] = [];
let ng2ComponentInstance: Ng2Component;
@ -2968,8 +2910,7 @@ withEachNg1Version(() => {
}
// Define `ng1Module`
const ng1Module =
angular.module('ng1Module', [])
const ng1Module = angular.module('ng1Module', [])
.component('ng1', ng1Component)
.directive('ng2', adapter.downgradeNg2Component(Ng2Component));
@ -3002,8 +2943,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy('FW-714: ng1 projected content is not being rendered')
.it('should throw if a non-optional slot is not filled', async(() => {
it('should throw if a non-optional slot is not filled', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
let errorMessage: string;
@ -3114,7 +3054,7 @@ withEachNg1Version(() => {
});
fixmeIvy(
'FW-812: Life-cycle hooks not correctly wired up for components that return a different instance from their constructor')
'FW-844: Directive input bindings cannot be assigned after the `@Directive` decorator has been compiled')
.it('should bind input properties (<) of components', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);
@ -3148,9 +3088,7 @@ withEachNg1Version(() => {
});
}));
fixmeIvy(
'FW-812: Life-cycle hooks not correctly wired up for components that return a different instance from their constructor')
.it('should support ng2 > ng1 > ng2', async(() => {
it('should support ng2 > ng1 > ng2', async(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module('ng1', []);