refactor(ivy): move directive, component and pipe factories to ngFactoryFn (#31953)

Reworks the compiler to output the factories for directives, components and pipes under a new static field called `ngFactoryFn`, instead of the usual `factory` property in their respective defs. This should eventually allow us to inject any kind of decorated class (e.g. a pipe).

**Note:** these changes are the first part of the refactor and they don't include injectables. I decided to leave injectables for a follow-up PR, because there's some more cases we need to handle when it comes to their factories. Furthermore, directives, components and pipes make up most of the compiler output tests that need to be refactored and it'll make follow-up PRs easier to review if the tests are cleaned up now.

This is part of the larger refactor for FW-1468.

PR Close #31953
This commit is contained in:
Kristiyan Kostadinov 2019-08-12 09:26:20 +03:00 committed by atscott
parent 14feb56139
commit c885178d5f
71 changed files with 894 additions and 675 deletions

View File

@ -12,7 +12,7 @@
"master": { "master": {
"uncompressed": { "uncompressed": {
"runtime": 1440, "runtime": 1440,
"main": 13411, "main": 13266,
"polyfills": 45340 "polyfills": 45340
} }
} }

View File

@ -17,6 +17,9 @@ function noop() {}
export class TreeFunction { export class TreeFunction {
data: TreeNode = emptyTree; data: TreeNode = emptyTree;
/** @nocollapse */
static ngFactoryDef = () => new TreeFunction;
/** @nocollapse */ /** @nocollapse */
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: TreeFunction, type: TreeFunction,
@ -27,7 +30,6 @@ export class TreeFunction {
// bit of a hack // bit of a hack
TreeTpl(rf, ctx.data); TreeTpl(rf, ctx.data);
}, },
factory: () => new TreeFunction,
inputs: {data: 'data'} inputs: {data: 'data'}
}); });
} }

View File

@ -29,5 +29,5 @@ export {ViewportScroller, NullViewportScroller as ɵNullViewportScroller} from '
export {NgClassImplProvider__POST_R3__ as ɵNgClassImplProvider__POST_R3__, NgClassR2Impl as ɵNgClassR2Impl, NgClassImpl as ɵNgClassImpl} from './directives/ng_class_impl'; export {NgClassImplProvider__POST_R3__ as ɵNgClassImplProvider__POST_R3__, NgClassR2Impl as ɵNgClassR2Impl, NgClassImpl as ɵNgClassImpl} from './directives/ng_class_impl';
export {NgStyleImplProvider__POST_R3__ as ɵNgStyleImplProvider__POST_R3__, NgStyleR2Impl as ɵNgStyleR2Impl, NgStyleImpl as ɵNgStyleImpl} from './directives/ng_style_impl'; export {NgStyleImplProvider__POST_R3__ as ɵNgStyleImplProvider__POST_R3__, NgStyleR2Impl as ɵNgStyleR2Impl, NgStyleImpl as ɵNgStyleImpl} from './directives/ng_style_impl';
export {ngStyleDirectiveDef__POST_R3__ as ɵngStyleDirectiveDef__POST_R3__} from './directives/ng_style'; export {ngStyleDirectiveDef__POST_R3__ as ɵngStyleDirectiveDef__POST_R3__, ngStyleFactoryDef__POST_R3__ as ɵngStyleFactoryDef__POST_R3__} from './directives/ng_style';
export {ngClassDirectiveDef__POST_R3__ as ɵngClassDirectiveDef__POST_R3__} from './directives/ng_class'; export {ngClassDirectiveDef__POST_R3__ as ɵngClassDirectiveDef__POST_R3__, ngClassFactoryDef__POST_R3__ as ɵngClassFactoryDef__POST_R3__} from './directives/ng_class';

View File

@ -32,7 +32,6 @@ export const ngClassDirectiveDef__PRE_R3__ = undefined;
export const ngClassDirectiveDef__POST_R3__ = ɵɵdefineDirective({ export const ngClassDirectiveDef__POST_R3__ = ɵɵdefineDirective({
type: function() {} as any, type: function() {} as any,
selectors: null as any, selectors: null as any,
factory: () => {},
hostBindings: function(rf: ɵRenderFlags, ctx: any, elIndex: number) { hostBindings: function(rf: ɵRenderFlags, ctx: any, elIndex: number) {
if (rf & ɵRenderFlags.Create) { if (rf & ɵRenderFlags.Create) {
ɵɵallocHostVars(1); ɵɵallocHostVars(1);
@ -47,6 +46,10 @@ export const ngClassDirectiveDef__POST_R3__ = ɵɵdefineDirective({
export const ngClassDirectiveDef = ngClassDirectiveDef__PRE_R3__; export const ngClassDirectiveDef = ngClassDirectiveDef__PRE_R3__;
export const ngClassFactoryDef__PRE_R3__ = undefined;
export const ngClassFactoryDef__POST_R3__ = function() {};
export const ngClassFactoryDef = ngClassFactoryDef__PRE_R3__;
/** /**
* Serves as the base non-VE container for NgClass. * Serves as the base non-VE container for NgClass.
* *
@ -63,6 +66,7 @@ export const ngClassDirectiveDef = ngClassDirectiveDef__PRE_R3__;
*/ */
export class NgClassBase { export class NgClassBase {
static ngDirectiveDef: any = ngClassDirectiveDef; static ngDirectiveDef: any = ngClassDirectiveDef;
static ngFactoryDef: any = ngClassFactoryDef;
constructor(protected _delegate: NgClassImpl) {} constructor(protected _delegate: NgClassImpl) {}

View File

@ -25,6 +25,7 @@ import {NgStyleImpl, NgStyleImplProvider} from './ng_style_impl';
// used when the VE is present // used when the VE is present
export const ngStyleDirectiveDef__PRE_R3__ = undefined; export const ngStyleDirectiveDef__PRE_R3__ = undefined;
export const ngStyleFactoryDef__PRE_R3__ = undefined;
// used when the VE is not present (note the directive will // used when the VE is not present (note the directive will
// never be instantiated normally because it is apart of a // never be instantiated normally because it is apart of a
@ -32,7 +33,6 @@ export const ngStyleDirectiveDef__PRE_R3__ = undefined;
export const ngStyleDirectiveDef__POST_R3__ = ɵɵdefineDirective({ export const ngStyleDirectiveDef__POST_R3__ = ɵɵdefineDirective({
type: function() {} as any, type: function() {} as any,
selectors: null as any, selectors: null as any,
factory: () => {},
hostBindings: function(rf: ɵRenderFlags, ctx: any, elIndex: number) { hostBindings: function(rf: ɵRenderFlags, ctx: any, elIndex: number) {
if (rf & ɵRenderFlags.Create) { if (rf & ɵRenderFlags.Create) {
ɵɵstyling(); ɵɵstyling();
@ -44,7 +44,10 @@ export const ngStyleDirectiveDef__POST_R3__ = ɵɵdefineDirective({
} }
}); });
export const ngStyleFactoryDef__POST_R3__ = function() {};
export const ngStyleDirectiveDef = ngStyleDirectiveDef__PRE_R3__; export const ngStyleDirectiveDef = ngStyleDirectiveDef__PRE_R3__;
export const ngStyleFactoryDef = ngStyleDirectiveDef__PRE_R3__;
/** /**
* Serves as the base non-VE container for NgStyle. * Serves as the base non-VE container for NgStyle.
@ -62,6 +65,7 @@ export const ngStyleDirectiveDef = ngStyleDirectiveDef__PRE_R3__;
*/ */
export class NgStyleBase { export class NgStyleBase {
static ngDirectiveDef: any = ngStyleDirectiveDef; static ngDirectiveDef: any = ngStyleDirectiveDef;
static ngFactory: any = ngStyleFactoryDef;
constructor(protected _delegate: NgStyleImpl) {} constructor(protected _delegate: NgStyleImpl) {}

View File

@ -119,7 +119,7 @@ runInEachFileSystem(() => {
const typingsFile = result.find(f => f.path === _('/typings/file.d.ts')) !; const typingsFile = result.find(f => f.path === _('/typings/file.d.ts')) !;
expect(typingsFile.contents) expect(typingsFile.contents)
.toContain( .toContain(
'foo(x: number): number;\n static ngDirectiveDef: ɵngcc0.ɵɵDirectiveDefWithMeta'); 'foo(x: number): number;\n static ngFactoryDef: ɵngcc0.ɵɵFactoryDef<A>;\n static ngDirectiveDef: ɵngcc0.ɵɵDirectiveDefWithMeta');
}); });
it('should render imports into typings files', () => { it('should render imports into typings files', () => {

View File

@ -188,8 +188,8 @@ runInEachFileSystem(() => {
decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses); decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses);
const addDefinitionsSpy = testFormatter.addDefinitions as jasmine.Spy; const addDefinitionsSpy = testFormatter.addDefinitions as jasmine.Spy;
expect(addDefinitionsSpy.calls.first().args[2]) expect(addDefinitionsSpy.calls.first().args[2])
.toEqual( .toEqual(`A.ngFactoryDef = function A_Factory(t) { return new (t || A)(); };
`A.ngComponentDef = ɵngcc0.ɵɵdefineComponent({ type: A, selectors: [["a"]], factory: function A_Factory(t) { return new (t || A)(); }, consts: 1, vars: 1, template: function A_Template(rf, ctx) { if (rf & 1) { A.ngComponentDef = ɵngcc0.ɵɵdefineComponent({ type: A, selectors: [["a"]], consts: 1, vars: 1, template: function A_Template(rf, ctx) { if (rf & 1) {
ɵngcc0.ɵɵtext(0); ɵngcc0.ɵɵtext(0);
} if (rf & 2) { } if (rf & 2) {
ɵngcc0.ɵɵtextInterpolate(ctx.person.name); ɵngcc0.ɵɵtextInterpolate(ctx.person.name);
@ -227,9 +227,10 @@ runInEachFileSystem(() => {
name: 'A', name: 'A',
decorators: [jasmine.objectContaining({name: 'Directive'})] decorators: [jasmine.objectContaining({name: 'Directive'})]
})); }));
expect(addDefinitionsSpy.calls.first().args[2]) expect(addDefinitionsSpy.calls.first().args[2])
.toEqual( .toEqual(`A.ngFactoryDef = function A_Factory(t) { return new (t || A)(); };
`A.ngDirectiveDef = ɵngcc0.ɵɵdefineDirective({ type: A, selectors: [["", "a", ""]], factory: function A_Factory(t) { return new (t || A)(); } }); A.ngDirectiveDef = ɵngcc0.ɵɵdefineDirective({ type: A, selectors: [["", "a", ""]] });
/*@__PURE__*/ ɵngcc0.ɵsetClassMetadata(A, [{ /*@__PURE__*/ ɵngcc0.ɵsetClassMetadata(A, [{
type: Directive, type: Directive,
args: [{ selector: '[a]' }] args: [{ selector: '[a]' }]

View File

@ -26,6 +26,7 @@ import {tsSourceMapBug29300Fixed} from '../../util/src/ts_source_map_bug_29300';
import {ResourceLoader} from './api'; import {ResourceLoader} from './api';
import {extractDirectiveMetadata, parseFieldArrayValue} from './directive'; import {extractDirectiveMetadata, parseFieldArrayValue} from './directive';
import {compileNgFactoryDefField} from './factory';
import {generateSetClassMetadataCall} from './metadata'; import {generateSetClassMetadataCall} from './metadata';
import {findAngularDecorator, isAngularCoreReference, isExpressionForwardReference, readBaseClass, unwrapExpression} from './util'; import {findAngularDecorator, isAngularCoreReference, isExpressionForwardReference, readBaseClass, unwrapExpression} from './util';
@ -517,18 +518,21 @@ export class ComponentDecoratorHandler implements
} }
compile(node: ClassDeclaration, analysis: ComponentHandlerData, pool: ConstantPool): compile(node: ClassDeclaration, analysis: ComponentHandlerData, pool: ConstantPool):
CompileResult { CompileResult[] {
const res = compileComponentFromMetadata(analysis.meta, pool, makeBindingParser()); const meta = analysis.meta;
const res = compileComponentFromMetadata(meta, pool, makeBindingParser());
const statements = res.statements; const factoryRes = compileNgFactoryDefField(meta);
if (analysis.metadataStmt !== null) { if (analysis.metadataStmt !== null) {
statements.push(analysis.metadataStmt); factoryRes.statements.push(analysis.metadataStmt);
} }
return { return [
name: 'ngComponentDef', factoryRes, {
initializer: res.expression, statements, name: 'ngComponentDef',
type: res.type, initializer: res.expression,
}; statements: [],
type: res.type,
}
];
} }
private _resolveLiteral(decorator: Decorator): ts.ObjectLiteralExpression { private _resolveLiteral(decorator: Decorator): ts.ObjectLiteralExpression {
@ -822,4 +826,4 @@ export interface ParsedTemplate {
interface PreanalyzedTemplate extends ParsedTemplate { interface PreanalyzedTemplate extends ParsedTemplate {
parseTemplate: (options?: ParseTemplateOptions) => ParsedTemplate; parseTemplate: (options?: ParseTemplateOptions) => ParsedTemplate;
} }

View File

@ -17,6 +17,7 @@ import {DynamicValue, EnumValue, PartialEvaluator} from '../../partial_evaluator
import {ClassDeclaration, ClassMember, ClassMemberKind, Decorator, ReflectionHost, filterToMembersWithDecorator, reflectObjectLiteral} from '../../reflection'; import {ClassDeclaration, ClassMember, ClassMemberKind, Decorator, ReflectionHost, filterToMembersWithDecorator, reflectObjectLiteral} from '../../reflection';
import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence} from '../../transform'; import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence} from '../../transform';
import {compileNgFactoryDefField} from './factory';
import {generateSetClassMetadataCall} from './metadata'; import {generateSetClassMetadataCall} from './metadata';
import {findAngularDecorator, getValidConstructorDependencies, readBaseClass, unwrapExpression, unwrapForwardRef} from './util'; import {findAngularDecorator, getValidConstructorDependencies, readBaseClass, unwrapExpression, unwrapForwardRef} from './util';
@ -90,18 +91,21 @@ export class DirectiveDecoratorHandler implements
} }
compile(node: ClassDeclaration, analysis: DirectiveHandlerData, pool: ConstantPool): compile(node: ClassDeclaration, analysis: DirectiveHandlerData, pool: ConstantPool):
CompileResult { CompileResult[] {
const res = compileDirectiveFromMetadata(analysis.meta, pool, makeBindingParser()); const meta = analysis.meta;
const statements = res.statements; const res = compileDirectiveFromMetadata(meta, pool, makeBindingParser());
const factoryRes = compileNgFactoryDefField(meta);
if (analysis.metadataStmt !== null) { if (analysis.metadataStmt !== null) {
statements.push(analysis.metadataStmt); factoryRes.statements.push(analysis.metadataStmt);
} }
return { return [
name: 'ngDirectiveDef', factoryRes, {
initializer: res.expression, name: 'ngDirectiveDef',
statements: statements, initializer: res.expression,
type: res.type, statements: [],
}; type: res.type,
}
];
} }
} }

View File

@ -0,0 +1,21 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* 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
*/
import {R3FactoryDefMetadata, compileFactoryFromMetadata} from '@angular/compiler';
import {CompileResult} from '../../transform';
export function compileNgFactoryDefField(metadata: R3FactoryDefMetadata): CompileResult {
const res = compileFactoryFromMetadata(metadata);
return {
name: 'ngFactoryDef',
initializer: res.factory,
statements: res.statements,
type: res.type
};
}

View File

@ -16,6 +16,7 @@ import {PartialEvaluator} from '../../partial_evaluator';
import {ClassDeclaration, Decorator, ReflectionHost, reflectObjectLiteral} from '../../reflection'; import {ClassDeclaration, Decorator, ReflectionHost, reflectObjectLiteral} from '../../reflection';
import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence} from '../../transform'; import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence} from '../../transform';
import {compileNgFactoryDefField} from './factory';
import {generateSetClassMetadataCall} from './metadata'; import {generateSetClassMetadataCall} from './metadata';
import {findAngularDecorator, getValidConstructorDependencies, unwrapExpression} from './util'; import {findAngularDecorator, getValidConstructorDependencies, unwrapExpression} from './util';
@ -105,16 +106,20 @@ export class PipeDecoratorHandler implements DecoratorHandler<PipeHandlerData, D
}; };
} }
compile(node: ClassDeclaration, analysis: PipeHandlerData): CompileResult { compile(node: ClassDeclaration, analysis: PipeHandlerData): CompileResult[] {
const res = compilePipeFromMetadata(analysis.meta); const meta = analysis.meta;
const statements = res.statements; const res = compilePipeFromMetadata(meta);
const factoryRes = compileNgFactoryDefField({...meta, isPipe: true});
if (analysis.metadataStmt !== null) { if (analysis.metadataStmt !== null) {
statements.push(analysis.metadataStmt); factoryRes.statements.push(analysis.metadataStmt);
} }
return { return [
name: 'ngPipeDef', factoryRes, {
initializer: res.expression, statements, name: 'ngPipeDef',
type: res.type, initializer: res.expression,
}; statements: [],
type: res.type,
}
];
} }
} }

View File

@ -26,6 +26,7 @@ const R3_DEF_NAME_PATTERN = [
'ngInjectorDef', 'ngInjectorDef',
'ngModuleDef', 'ngModuleDef',
'ngPipeDef', 'ngPipeDef',
'ngFactoryDef',
].join('|'); ].join('|');
// Pattern matching `Identifier.property` where property is a Render3 property. // Pattern matching `Identifier.property` where property is a Render3 property.

View File

@ -44,7 +44,7 @@ describe('compiler compliance', () => {
// The factory should look like this: // The factory should look like this:
const factory = const factory =
'factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }'; 'MyComponent.ngFactoryDef = function MyComponent_Factory(t) { return new (t || MyComponent)(); }';
// The template should look like this (where IDENT is a wild card for an identifier): // The template should look like this (where IDENT is a wild card for an identifier):
const template = ` const template = `
@ -94,7 +94,7 @@ describe('compiler compliance', () => {
// The factory should look like this: // The factory should look like this:
const factory = const factory =
'factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }'; 'MyComponent.ngFactoryDef = function MyComponent_Factory(t) { return new (t || MyComponent)(); }';
// The template should look like this (where IDENT is a wild card for an identifier): // The template should look like this (where IDENT is a wild card for an identifier):
const template = ` const template = `
@ -142,7 +142,7 @@ describe('compiler compliance', () => {
// The factory should look like this: // The factory should look like this:
const factory = const factory =
'factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }'; 'MyComponent.ngFactoryDef = function MyComponent_Factory(t) { return new (t || MyComponent)(); }';
// The template should look like this (where IDENT is a wild card for an identifier): // The template should look like this (where IDENT is a wild card for an identifier):
const template = ` const template = `
@ -190,7 +190,7 @@ describe('compiler compliance', () => {
// The factory should look like this: // The factory should look like this:
const factory = const factory =
'factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }'; 'MyComponent.ngFactoryDef = function MyComponent_Factory(t) { return new (t || MyComponent)(); }';
// The template should look like this (where IDENT is a wild card for an identifier): // The template should look like this (where IDENT is a wild card for an identifier):
const template = ` const template = `
@ -306,7 +306,7 @@ describe('compiler compliance', () => {
}; };
const factory = const factory =
'factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }'; 'MyComponent.ngFactoryDef = function MyComponent_Factory(t) { return new (t || MyComponent)(); }';
const template = ` const template = `
const $e0_attrs$ = [${AttributeMarker.Bindings}, "id"]; const $e0_attrs$ = [${AttributeMarker.Bindings}, "id"];
@ -361,7 +361,7 @@ describe('compiler compliance', () => {
/////////////// ///////////////
const factory = const factory =
'factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }'; 'MyComponent.ngFactoryDef = function MyComponent_Factory(t) { return new (t || MyComponent)(); }';
const template = ` const template = `
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
if (rf & 1) { if (rf & 1) {
@ -476,12 +476,9 @@ describe('compiler compliance', () => {
}; };
const factory = const factory =
'factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }'; 'MyComponent.ngFactoryDef = function MyComponent_Factory(t) { return new (t || MyComponent)(); }';
const template = ` const template = `
MyComponent.ngComponentDef = i0.ɵɵdefineComponent({type:MyComponent,selectors:[["my-component"]], MyComponent.ngComponentDef = i0.ɵɵdefineComponent({type:MyComponent,selectors:[["my-component"]],
factory: function MyComponent_Factory(t){
return new (t || MyComponent)();
},
consts: 1, consts: 1,
vars: 2, vars: 2,
template: function MyComponent_Template(rf,ctx){ template: function MyComponent_Template(rf,ctx){
@ -536,7 +533,6 @@ describe('compiler compliance', () => {
ChildComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ ChildComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: ChildComponent, type: ChildComponent,
selectors: [["child"]], selectors: [["child"]],
factory: function ChildComponent_Factory(t) { return new (t || ChildComponent)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function ChildComponent_Template(rf, ctx) { template: function ChildComponent_Template(rf, ctx) {
@ -547,15 +543,20 @@ describe('compiler compliance', () => {
encapsulation: 2 encapsulation: 2
});`; });`;
const ChildComponentFactory =
`ChildComponent.ngFactoryDef = function ChildComponent_Factory(t) { return new (t || ChildComponent)(); };`;
// SomeDirective definition should be: // SomeDirective definition should be:
const SomeDirectiveDefinition = ` const SomeDirectiveDefinition = `
SomeDirective.ngDirectiveDef = $r3$.ɵɵdefineDirective({ SomeDirective.ngDirectiveDef = $r3$.ɵɵdefineDirective({
type: SomeDirective, type: SomeDirective,
selectors: [["", "some-directive", ""]], selectors: [["", "some-directive", ""]]
factory: function SomeDirective_Factory(t) {return new (t || SomeDirective)(); }
}); });
`; `;
const SomeDirectiveFactory =
`SomeDirective.ngFactoryDef = function SomeDirective_Factory(t) {return new (t || SomeDirective)(); };`;
// MyComponent definition should be: // MyComponent definition should be:
const MyComponentDefinition = ` const MyComponentDefinition = `
const $c1$ = ["some-directive", ""]; const $c1$ = ["some-directive", ""];
@ -563,7 +564,6 @@ describe('compiler compliance', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 2, consts: 2,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -577,13 +577,18 @@ describe('compiler compliance', () => {
}); });
`; `;
const MyComponentFactory =
`MyComponent.ngFactoryDef = function MyComponent_Factory(t) { return new (t || MyComponent)(); };`;
const result = compile(files, angularFiles); const result = compile(files, angularFiles);
const source = result.source; const source = result.source;
expectEmit(source, ChildComponentDefinition, 'Incorrect ChildComponent.ngComponentDef'); expectEmit(source, ChildComponentDefinition, 'Incorrect ChildComponent.ngComponentDef');
expectEmit(source, ChildComponentFactory, 'Incorrect ChildComponent.ngFactoryDef');
expectEmit(source, SomeDirectiveDefinition, 'Incorrect SomeDirective.ngDirectiveDef'); expectEmit(source, SomeDirectiveDefinition, 'Incorrect SomeDirective.ngDirectiveDef');
expectEmit(source, SomeDirectiveFactory, 'Incorrect SomeDirective.ngFactoryDef');
expectEmit(source, MyComponentDefinition, 'Incorrect MyComponentDefinition.ngComponentDef'); expectEmit(source, MyComponentDefinition, 'Incorrect MyComponentDefinition.ngComponentDef');
expectEmit(source, MyComponentFactory, 'Incorrect MyComponentDefinition.ngFactoryDef');
}); });
it('should support complex selectors', () => { it('should support complex selectors', () => {
@ -608,25 +613,31 @@ describe('compiler compliance', () => {
const SomeDirectiveDefinition = ` const SomeDirectiveDefinition = `
SomeDirective.ngDirectiveDef = $r3$.ɵɵdefineDirective({ SomeDirective.ngDirectiveDef = $r3$.ɵɵdefineDirective({
type: SomeDirective, type: SomeDirective,
selectors: [["div", "some-directive", "", 8, "foo", 3, "title", "", 9, "baz"]], selectors: [["div", "some-directive", "", 8, "foo", 3, "title", "", 9, "baz"]]
factory: function SomeDirective_Factory(t) {return new (t || SomeDirective)(); }
}); });
`; `;
const SomeDirectiveFactory =
`SomeDirective.ngFactoryDef = function SomeDirective_Factory(t) {return new (t || SomeDirective)(); };`;
// OtherDirective definition should be: // OtherDirective definition should be:
const OtherDirectiveDefinition = ` const OtherDirectiveDefinition = `
OtherDirective.ngDirectiveDef = $r3$.ɵɵdefineDirective({ OtherDirective.ngDirectiveDef = $r3$.ɵɵdefineDirective({
type: OtherDirective, type: OtherDirective,
selectors: [["", 5, "span", "title", "", 9, "baz"]], selectors: [["", 5, "span", "title", "", 9, "baz"]]
factory: function OtherDirective_Factory(t) {return new (t || OtherDirective)(); }
}); });
`; `;
const OtherDirectiveFactory =
`OtherDirective.ngFactoryDef = function OtherDirective_Factory(t) {return new (t || OtherDirective)(); };`;
const result = compile(files, angularFiles); const result = compile(files, angularFiles);
const source = result.source; const source = result.source;
expectEmit(source, SomeDirectiveDefinition, 'Incorrect SomeDirective.ngDirectiveDef'); expectEmit(source, SomeDirectiveDefinition, 'Incorrect SomeDirective.ngDirectiveDef');
expectEmit(source, SomeDirectiveFactory, 'Incorrect SomeDirective.ngFactoryDef');
expectEmit(source, OtherDirectiveDefinition, 'Incorrect OtherDirective.ngDirectiveDef'); expectEmit(source, OtherDirectiveDefinition, 'Incorrect OtherDirective.ngDirectiveDef');
expectEmit(source, OtherDirectiveFactory, 'Incorrect OtherDirective.ngFactoryDef');
}); });
it('should support components without selector', () => { it('should support components without selector', () => {
@ -650,7 +661,6 @@ describe('compiler compliance', () => {
EmptyOutletComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ EmptyOutletComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: EmptyOutletComponent, type: EmptyOutletComponent,
selectors: [["ng-component"]], selectors: [["ng-component"]],
factory: function EmptyOutletComponent_Factory(t) { return new (t || EmptyOutletComponent)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function EmptyOutletComponent_Template(rf, ctx) { template: function EmptyOutletComponent_Template(rf, ctx) {
@ -662,11 +672,16 @@ describe('compiler compliance', () => {
}); });
`; `;
const EmptyOutletComponentFactory =
`EmptyOutletComponent.ngFactoryDef = function EmptyOutletComponent_Factory(t) { return new (t || EmptyOutletComponent)(); };`;
const result = compile(files, angularFiles); const result = compile(files, angularFiles);
const source = result.source; const source = result.source;
expectEmit( expectEmit(
source, EmptyOutletComponentDefinition, 'Incorrect EmptyOutletComponent.ngComponentDef'); source, EmptyOutletComponentDefinition, 'Incorrect EmptyOutletComponent.ngComponentDef');
expectEmit(
source, EmptyOutletComponentFactory, 'Incorrect EmptyOutletComponent.ngFactoryDef');
}); });
it('should not treat ElementRef, ViewContainerRef, or ChangeDetectorRef specially when injecting', it('should not treat ElementRef, ViewContainerRef, or ChangeDetectorRef specially when injecting',
@ -695,21 +710,23 @@ describe('compiler compliance', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) {
return new (t || MyComponent)(
$r3$.ɵɵdirectiveInject($i$.ElementRef), $r3$.ɵɵdirectiveInject($i$.ViewContainerRef),
$r3$.ɵɵdirectiveInject($i$.ChangeDetectorRef));
},
consts: 0, consts: 0,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, ctx) {}, template: function MyComponent_Template(rf, ctx) {},
encapsulation: 2 encapsulation: 2
});`; });`;
const MyComponentFactory = `MyComponent.ngFactoryDef = function MyComponent_Factory(t) {
return new (t || MyComponent)(
$r3$.ɵɵdirectiveInject($i$.ElementRef), $r3$.ɵɵdirectiveInject($i$.ViewContainerRef),
$r3$.ɵɵdirectiveInject($i$.ChangeDetectorRef));
};`;
const result = compile(files, angularFiles); const result = compile(files, angularFiles);
const source = result.source; const source = result.source;
expectEmit(source, MyComponentDefinition, 'Incorrect MyComponent.ngComponentDef'); expectEmit(source, MyComponentDefinition, 'Incorrect MyComponent.ngComponentDef');
expectEmit(source, MyComponentFactory, 'Incorrect MyComponent.ngFactoryDef');
}); });
it('should support structural directives', () => { it('should support structural directives', () => {
@ -740,9 +757,11 @@ describe('compiler compliance', () => {
const IfDirectiveDefinition = ` const IfDirectiveDefinition = `
IfDirective.ngDirectiveDef = $r3$.ɵɵdefineDirective({ IfDirective.ngDirectiveDef = $r3$.ɵɵdefineDirective({
type: IfDirective, type: IfDirective,
selectors: [["", "if", ""]], selectors: [["", "if", ""]]
factory: function IfDirective_Factory(t) { return new (t || IfDirective)($r3$.ɵɵdirectiveInject($i$.TemplateRef)); }
});`; });`;
const IfDirectiveFactory =
`IfDirective.ngFactoryDef = function IfDirective_Factory(t) { return new (t || IfDirective)($r3$.ɵɵdirectiveInject($i$.TemplateRef)); };`;
const MyComponentDefinition = ` const MyComponentDefinition = `
const $c1$ = ["foo", ""]; const $c1$ = ["foo", ""];
const $c2$ = [${AttributeMarker.Template}, "if"]; const $c2$ = [${AttributeMarker.Template}, "if"];
@ -763,7 +782,6 @@ describe('compiler compliance', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 3, consts: 3,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -777,11 +795,16 @@ describe('compiler compliance', () => {
encapsulation: 2 encapsulation: 2
});`; });`;
const MyComponentFactory =
`MyComponent.ngFactoryDef = function MyComponent_Factory(t) { return new (t || MyComponent)(); };`;
const result = compile(files, angularFiles); const result = compile(files, angularFiles);
const source = result.source; const source = result.source;
expectEmit(source, IfDirectiveDefinition, 'Incorrect IfDirective.ngDirectiveDef'); expectEmit(source, IfDirectiveDefinition, 'Incorrect IfDirective.ngDirectiveDef');
expectEmit(source, IfDirectiveFactory, 'Incorrect IfDirective.ngFactoryDef');
expectEmit(source, MyComponentDefinition, 'Incorrect MyComponent.ngComponentDef'); expectEmit(source, MyComponentDefinition, 'Incorrect MyComponent.ngComponentDef');
expectEmit(source, MyComponentFactory, 'Incorrect MyComponent.ngFactoryDef');
}); });
describe('value composition', () => { describe('value composition', () => {
@ -826,7 +849,6 @@ describe('compiler compliance', () => {
MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({ MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [["my-app"]], selectors: [["my-app"]],
factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 3, vars: 3,
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
@ -908,7 +930,6 @@ describe('compiler compliance', () => {
MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({ MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [["my-app"]], selectors: [["my-app"]],
factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 11, vars: 11,
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
@ -971,7 +992,6 @@ describe('compiler compliance', () => {
MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({ MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [["my-app"]], selectors: [["my-app"]],
factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 3, vars: 3,
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
@ -1039,7 +1059,6 @@ describe('compiler compliance', () => {
MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({ MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [["my-app"]], selectors: [["my-app"]],
factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 1, consts: 1,
vars: 8, vars: 8,
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
@ -1100,7 +1119,6 @@ describe('compiler compliance', () => {
SimpleComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ SimpleComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: SimpleComponent, type: SimpleComponent,
selectors: [["simple"]], selectors: [["simple"]],
factory: function SimpleComponent_Factory(t) { return new (t || SimpleComponent)(); },
ngContentSelectors: $c0$, ngContentSelectors: $c0$,
consts: 2, consts: 2,
vars: 0, vars: 0,
@ -1123,7 +1141,6 @@ describe('compiler compliance', () => {
ComplexComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ ComplexComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: ComplexComponent, type: ComplexComponent,
selectors: [["complex"]], selectors: [["complex"]],
factory: function ComplexComponent_Factory(t) { return new (t || ComplexComponent)(); },
ngContentSelectors: _c4, ngContentSelectors: _c4,
consts: 4, consts: 4,
vars: 0, vars: 0,
@ -1179,7 +1196,6 @@ describe('compiler compliance', () => {
Cmp.ngComponentDef = $r3$.ɵɵdefineComponent({ Cmp.ngComponentDef = $r3$.ɵɵdefineComponent({
type: Cmp, type: Cmp,
selectors: [["ng-component"]], selectors: [["ng-component"]],
factory: function Cmp_Factory(t) { return new (t || Cmp)(); },
ngContentSelectors: $c1$, ngContentSelectors: $c1$,
consts: 3, consts: 3,
vars: 0, vars: 0,
@ -1368,9 +1384,6 @@ describe('compiler compliance', () => {
MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({ MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [["my-app"]], selectors: [["my-app"]],
factory: function MyApp_Factory(t) {
return new(t || MyApp)();
},
consts: 2, consts: 2,
vars: 0, vars: 0,
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
@ -1423,9 +1436,6 @@ describe('compiler compliance', () => {
MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({ MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [["my-app"]], selectors: [["my-app"]],
factory: function MyApp_Factory(t) {
return new(t || MyApp)();
},
consts: 2, consts: 2,
vars: 0, vars: 0,
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
@ -1489,7 +1499,6 @@ describe('compiler compliance', () => {
ViewQueryComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ ViewQueryComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: ViewQueryComponent, type: ViewQueryComponent,
selectors: [["view-query-component"]], selectors: [["view-query-component"]],
factory: function ViewQueryComponent_Factory(t) { return new (t || ViewQueryComponent)(); },
viewQuery: function ViewQueryComponent_Query(rf, ctx) { viewQuery: function ViewQueryComponent_Query(rf, ctx) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵɵviewQuery(SomeDirective, true); $r3$.ɵɵviewQuery(SomeDirective, true);
@ -1600,7 +1609,6 @@ describe('compiler compliance', () => {
ViewQueryComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ ViewQueryComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: ViewQueryComponent, type: ViewQueryComponent,
selectors: [["view-query-component"]], selectors: [["view-query-component"]],
factory: function ViewQueryComponent_Factory(t) { return new (t || ViewQueryComponent)(); },
viewQuery: function ViewQueryComponent_Query(rf, ctx) { viewQuery: function ViewQueryComponent_Query(rf, ctx) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵɵstaticViewQuery(SomeDirective, true); $r3$.ɵɵstaticViewQuery(SomeDirective, true);
@ -1727,9 +1735,6 @@ describe('compiler compliance', () => {
ContentQueryComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ ContentQueryComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: ContentQueryComponent, type: ContentQueryComponent,
selectors: [["content-query-component"]], selectors: [["content-query-component"]],
factory: function ContentQueryComponent_Factory(t) {
return new (t || ContentQueryComponent)();
},
contentQueries: function ContentQueryComponent_ContentQueries(rf, ctx, dirIndex) { contentQueries: function ContentQueryComponent_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵɵcontentQuery(dirIndex, SomeDirective, true); $r3$.ɵɵcontentQuery(dirIndex, SomeDirective, true);
@ -1849,9 +1854,6 @@ describe('compiler compliance', () => {
ContentQueryComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ ContentQueryComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: ContentQueryComponent, type: ContentQueryComponent,
selectors: [["content-query-component"]], selectors: [["content-query-component"]],
factory: function ContentQueryComponent_Factory(t) {
return new (t || ContentQueryComponent)();
},
contentQueries: function ContentQueryComponent_ContentQueries(rf, ctx, dirIndex) { contentQueries: function ContentQueryComponent_ContentQueries(rf, ctx, dirIndex) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵɵstaticContentQuery(dirIndex, SomeDirective, true); $r3$.ɵɵstaticContentQuery(dirIndex, SomeDirective, true);
@ -1988,19 +1990,25 @@ describe('compiler compliance', () => {
MyPipe.ngPipeDef = $r3$.ɵɵdefinePipe({ MyPipe.ngPipeDef = $r3$.ɵɵdefinePipe({
name: "myPipe", name: "myPipe",
type: MyPipe, type: MyPipe,
factory: function MyPipe_Factory(t) { return new (t || MyPipe)(); },
pure: false pure: false
}); });
`; `;
const MyPipengFactoryDef = `
MyPipe.ngFactoryDef = function MyPipe_Factory(t) { return new (t || MyPipe)(); };
`;
const MyPurePipeDefinition = ` const MyPurePipeDefinition = `
MyPurePipe.ngPipeDef = $r3$.ɵɵdefinePipe({ MyPurePipe.ngPipeDef = $r3$.ɵɵdefinePipe({
name: "myPurePipe", name: "myPurePipe",
type: MyPurePipe, type: MyPurePipe,
factory: function MyPurePipe_Factory(t) { return new (t || MyPurePipe)(); },
pure: true pure: true
});`; });`;
const MyPurePipengFactoryDef = `
MyPurePipe.ngFactoryDef = function MyPurePipe_Factory(t) { return new (t || MyPurePipe)(); };
`;
const MyAppDefinition = ` const MyAppDefinition = `
const $c0$ = function ($a0$) { const $c0$ = function ($a0$) {
return [$a0$, 1, 2, 3, 4, 5]; return [$a0$, 1, 2, 3, 4, 5];
@ -2009,7 +2017,6 @@ describe('compiler compliance', () => {
MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({ MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [["my-app"]], selectors: [["my-app"]],
factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 7, consts: 7,
vars: 20, vars: 20,
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
@ -2037,7 +2044,9 @@ describe('compiler compliance', () => {
const source = result.source; const source = result.source;
expectEmit(source, MyPipeDefinition, 'Invalid pipe definition'); expectEmit(source, MyPipeDefinition, 'Invalid pipe definition');
expectEmit(source, MyPipengFactoryDef, 'Invalid pipe factory function');
expectEmit(source, MyPurePipeDefinition, 'Invalid pure pipe definition'); expectEmit(source, MyPurePipeDefinition, 'Invalid pure pipe definition');
expectEmit(source, MyPurePipengFactoryDef, 'Invalid pure pipe factory function');
expectEmit(source, MyAppDefinition, 'Invalid MyApp definition'); expectEmit(source, MyAppDefinition, 'Invalid MyApp definition');
}); });
@ -2075,7 +2084,6 @@ describe('compiler compliance', () => {
MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({ MyApp.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [["my-app"]], selectors: [["my-app"]],
factory: function MyApp_Factory(t) { return new (t || MyApp)(); },
consts: 6, consts: 6,
vars: 27, vars: 27,
template: function MyApp_Template(rf, ctx) { template: function MyApp_Template(rf, ctx) {
@ -2148,24 +2156,32 @@ describe('compiler compliance', () => {
MyPipe.ngPipeDef = $r3$.ɵɵdefinePipe({ MyPipe.ngPipeDef = $r3$.ɵɵdefinePipe({
name: "myPipe", name: "myPipe",
type: MyPipe, type: MyPipe,
factory: function MyPipe_Factory(t) { return new (t || MyPipe)($r3$.ɵɵinjectPipeChangeDetectorRef()); },
pure: true pure: true
}); });
`; `;
const MyPipeFactory = `
MyPipe.ngFactoryDef = function MyPipe_Factory(t) { return new (t || MyPipe)($r3$.ɵɵinjectPipeChangeDetectorRef()); };
`;
const MyOtherPipeDefinition = ` const MyOtherPipeDefinition = `
MyOtherPipe.ngPipeDef = $r3$.ɵɵdefinePipe({ MyOtherPipe.ngPipeDef = $r3$.ɵɵdefinePipe({
name: "myOtherPipe", name: "myOtherPipe",
type: MyOtherPipe, type: MyOtherPipe,
factory: function MyOtherPipe_Factory(t) { return new (t || MyOtherPipe)($r3$.ɵɵinjectPipeChangeDetectorRef(8)); },
pure: true pure: true
});`; });`;
const MyOtherPipeFactory = `
MyOtherPipe.ngFactoryDef = function MyOtherPipe_Factory(t) { return new (t || MyOtherPipe)($r3$.ɵɵinjectPipeChangeDetectorRef(8)); };
`;
const result = compile(files, angularFiles); const result = compile(files, angularFiles);
const source = result.source; const source = result.source;
expectEmit(source, MyPipeDefinition, 'Invalid pipe definition'); expectEmit(source, MyPipeDefinition, 'Invalid pipe definition');
expectEmit(source, MyPipeFactory, 'Invalid pipe factory function');
expectEmit(source, MyOtherPipeDefinition, 'Invalid alternate pipe definition'); expectEmit(source, MyOtherPipeDefinition, 'Invalid alternate pipe definition');
expectEmit(source, MyOtherPipeFactory, 'Invalid alternate pipe factory function');
}); });
}); });
@ -2191,7 +2207,6 @@ describe('compiler compliance', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 3, consts: 3,
vars: 1, vars: 1,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -2288,7 +2303,6 @@ describe('compiler compliance', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 6, consts: 6,
vars: 1, vars: 1,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -2434,7 +2448,6 @@ describe('compiler compliance', () => {
LifecycleComp.ngComponentDef = $r3$.ɵɵdefineComponent({ LifecycleComp.ngComponentDef = $r3$.ɵɵdefineComponent({
type: LifecycleComp, type: LifecycleComp,
selectors: [["lifecycle-comp"]], selectors: [["lifecycle-comp"]],
factory: function LifecycleComp_Factory(t) { return new (t || LifecycleComp)(); },
inputs: {nameMin: ["name", "nameMin"]}, inputs: {nameMin: ["name", "nameMin"]},
features: [$r3$.ɵɵNgOnChangesFeature()], features: [$r3$.ɵɵNgOnChangesFeature()],
consts: 0, consts: 0,
@ -2447,7 +2460,6 @@ describe('compiler compliance', () => {
SimpleLayout.ngComponentDef = $r3$.ɵɵdefineComponent({ SimpleLayout.ngComponentDef = $r3$.ɵɵdefineComponent({
type: SimpleLayout, type: SimpleLayout,
selectors: [["simple-layout"]], selectors: [["simple-layout"]],
factory: function SimpleLayout_Factory(t) { return new (t || SimpleLayout)(); },
consts: 2, consts: 2,
vars: 2, vars: 2,
template: function SimpleLayout_Template(rf, ctx) { template: function SimpleLayout_Template(rf, ctx) {
@ -2556,14 +2568,16 @@ describe('compiler compliance', () => {
ForOfDirective.ngDirectiveDef = $r3$.ɵɵdefineDirective({ ForOfDirective.ngDirectiveDef = $r3$.ɵɵdefineDirective({
type: ForOfDirective, type: ForOfDirective,
selectors: [["", "forOf", ""]], selectors: [["", "forOf", ""]],
factory: function ForOfDirective_Factory(t) {
return new (t || ForOfDirective)($r3$.ɵɵdirectiveInject(ViewContainerRef), $r3$.ɵɵdirectiveInject(TemplateRef));
},
features: [$r3$.ɵɵNgOnChangesFeature()], features: [$r3$.ɵɵNgOnChangesFeature()],
inputs: {forOf: "forOf"} inputs: {forOf: "forOf"}
}); });
`; `;
const ForDirectiveFactory =
`ForOfDirective.ngFactoryDef = function ForOfDirective_Factory(t) {
return new (t || ForOfDirective)($r3$.ɵɵdirectiveInject(ViewContainerRef), $r3$.ɵɵdirectiveInject(TemplateRef));
};`;
const MyComponentDefinition = ` const MyComponentDefinition = `
const $t1_attrs$ = [${AttributeMarker.Template}, "for", "forOf"]; const $t1_attrs$ = [${AttributeMarker.Template}, "for", "forOf"];
function MyComponent__svg_g_1_Template(rf, ctx) { function MyComponent__svg_g_1_Template(rf, ctx) {
@ -2578,7 +2592,6 @@ describe('compiler compliance', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 2, consts: 2,
vars: 1, vars: 1,
template: function MyComponent_Template(rf, ctx){ template: function MyComponent_Template(rf, ctx){
@ -2603,6 +2616,7 @@ describe('compiler compliance', () => {
// TODO(benlesh): Enforce this when the directives are specified // TODO(benlesh): Enforce this when the directives are specified
// expectEmit(source, ForDirectiveDefinition, 'Invalid directive definition'); // expectEmit(source, ForDirectiveDefinition, 'Invalid directive definition');
// expectEmit(source, ForDirectiveFactory, 'Invalid directive factory');
expectEmit(source, MyComponentDefinition, 'Invalid component definition'); expectEmit(source, MyComponentDefinition, 'Invalid component definition');
}); });
@ -2635,14 +2649,17 @@ describe('compiler compliance', () => {
ForOfDirective.ngDirectiveDef = $r3$.ɵɵdefineDirective({ ForOfDirective.ngDirectiveDef = $r3$.ɵɵdefineDirective({
type: ForOfDirective, type: ForOfDirective,
selectors: [["", "forOf", ""]], selectors: [["", "forOf", ""]],
factory: function ForOfDirective_Factory(t) {
return new (t || ForOfDirective)($r3$.ɵɵdirectiveInject(ViewContainerRef), $r3$.ɵɵdirectiveInject(TemplateRef));
},
features: [$r3$.ɵɵNgOnChangesFeature()], features: [$r3$.ɵɵNgOnChangesFeature()],
inputs: {forOf: "forOf"} inputs: {forOf: "forOf"}
}); });
`; `;
const ForDirectiveFactory = `
ForOfDirective.ngFactoryDef = function ForOfDirective_Factory(t) {
return new (t || ForOfDirective)($r3$.ɵɵdirectiveInject(ViewContainerRef), $r3$.ɵɵdirectiveInject(TemplateRef));
};
`;
const MyComponentDefinition = ` const MyComponentDefinition = `
const $t1_attrs$ = [${AttributeMarker.Template}, "for", "forOf"]; const $t1_attrs$ = [${AttributeMarker.Template}, "for", "forOf"];
function MyComponent_li_1_Template(rf, ctx) { function MyComponent_li_1_Template(rf, ctx) {
@ -2661,7 +2678,6 @@ describe('compiler compliance', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 2, consts: 2,
vars: 1, vars: 1,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -2685,6 +2701,7 @@ describe('compiler compliance', () => {
// TODO(chuckj): Enforce this when the directives are specified // TODO(chuckj): Enforce this when the directives are specified
// expectEmit(source, ForDirectiveDefinition, 'Invalid directive definition'); // expectEmit(source, ForDirectiveDefinition, 'Invalid directive definition');
// expectEmit(source, ForDirectiveFactory, 'Invalid directive factory');
expectEmit(source, MyComponentDefinition, 'Invalid component definition'); expectEmit(source, MyComponentDefinition, 'Invalid component definition');
}); });
@ -2765,7 +2782,6 @@ describe('compiler compliance', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 2, consts: 2,
vars: 1, vars: 1,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -2883,7 +2899,6 @@ describe('compiler compliance', () => {
SomeDirective.ngDirectiveDef = $r3$.ɵɵdefineDirective({ SomeDirective.ngDirectiveDef = $r3$.ɵɵdefineDirective({
type: SomeDirective, type: SomeDirective,
selectors: [["", "some-directive", ""]], selectors: [["", "some-directive", ""]],
factory: function SomeDirective_Factory(t) {return new (t || SomeDirective)(); },
exportAs: ["someDir", "otherDir"] exportAs: ["someDir", "otherDir"]
}); });
`; `;

View File

@ -671,7 +671,6 @@ describe('compiler compliance: bindings', () => {
HostBindingDir.ngDirectiveDef = $r3$.ɵɵdefineDirective({ HostBindingDir.ngDirectiveDef = $r3$.ɵɵdefineDirective({
type: HostBindingDir, type: HostBindingDir,
selectors: [["", "hostBindingDir", ""]], selectors: [["", "hostBindingDir", ""]],
factory: function HostBindingDir_Factory(t) { return new (t || HostBindingDir)(); },
hostBindings: function HostBindingDir_HostBindings(rf, ctx, elIndex) { hostBindings: function HostBindingDir_HostBindings(rf, ctx, elIndex) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵɵallocHostVars(1); $r3$.ɵɵallocHostVars(1);
@ -718,7 +717,6 @@ describe('compiler compliance: bindings', () => {
HostBindingComp.ngComponentDef = $r3$.ɵɵdefineComponent({ HostBindingComp.ngComponentDef = $r3$.ɵɵdefineComponent({
type: HostBindingComp, type: HostBindingComp,
selectors: [["host-binding-comp"]], selectors: [["host-binding-comp"]],
factory: function HostBindingComp_Factory(t) { return new (t || HostBindingComp)(); },
hostBindings: function HostBindingComp_HostBindings(rf, ctx, elIndex) { hostBindings: function HostBindingComp_HostBindings(rf, ctx, elIndex) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵɵallocHostVars(3); $r3$.ɵɵallocHostVars(3);
@ -766,7 +764,6 @@ describe('compiler compliance: bindings', () => {
HostAttributeDir.ngDirectiveDef = $r3$.ɵɵdefineDirective({ HostAttributeDir.ngDirectiveDef = $r3$.ɵɵdefineDirective({
type: HostAttributeDir, type: HostAttributeDir,
selectors: [["", "hostAttributeDir", ""]], selectors: [["", "hostAttributeDir", ""]],
factory: function HostAttributeDir_Factory(t) { return new (t || HostAttributeDir)(); },
hostBindings: function HostAttributeDir_HostBindings(rf, ctx, elIndex) { hostBindings: function HostAttributeDir_HostBindings(rf, ctx, elIndex) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵɵallocHostVars(1); $r3$.ɵɵallocHostVars(1);
@ -811,7 +808,6 @@ describe('compiler compliance: bindings', () => {
HostAttributeDir.ngDirectiveDef = $r3$.ɵɵdefineDirective({ HostAttributeDir.ngDirectiveDef = $r3$.ɵɵdefineDirective({
type: HostAttributeDir, type: HostAttributeDir,
selectors: [["", "hostAttributeDir", ""]], selectors: [["", "hostAttributeDir", ""]],
factory: function HostAttributeDir_Factory(t) { return new (t || HostAttributeDir)(); },
hostBindings: function HostAttributeDir_HostBindings(rf, ctx, elIndex) { hostBindings: function HostAttributeDir_HostBindings(rf, ctx, elIndex) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵɵelementHostAttrs($c0$); $r3$.ɵɵelementHostAttrs($c0$);
@ -869,7 +865,6 @@ describe('compiler compliance: bindings', () => {
HostAttributeComp.ngComponentDef = $r3$.ɵɵdefineComponent({ HostAttributeComp.ngComponentDef = $r3$.ɵɵdefineComponent({
type: HostAttributeComp, type: HostAttributeComp,
selectors: [["my-host-attribute-component"]], selectors: [["my-host-attribute-component"]],
factory: function HostAttributeComp_Factory(t) { return new (t || HostAttributeComp)(); },
hostBindings: function HostAttributeComp_HostBindings(rf, ctx, elIndex) { hostBindings: function HostAttributeComp_HostBindings(rf, ctx, elIndex) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵɵelementHostAttrs($c0$); $r3$.ɵɵelementHostAttrs($c0$);
@ -881,7 +876,6 @@ describe('compiler compliance: bindings', () => {
HostAttributeDir.ngDirectiveDef = $r3$.ɵɵdefineDirective({ HostAttributeDir.ngDirectiveDef = $r3$.ɵɵdefineDirective({
type: HostAttributeDir, type: HostAttributeDir,
selectors: [["", "hostAttributeDir", ""]], selectors: [["", "hostAttributeDir", ""]],
factory: function HostAttributeDir_Factory(t) { return new (t || HostAttributeDir)(); },
hostBindings: function HostAttributeDir_HostBindings(rf, ctx, elIndex) { hostBindings: function HostAttributeDir_HostBindings(rf, ctx, elIndex) {
if (rf & 1) { if (rf & 1) {
$r3$.ɵɵallocHostVars(2); $r3$.ɵɵallocHostVars(2);

View File

@ -48,7 +48,7 @@ describe('compiler compliance: dependency injection', () => {
}; };
const factory = ` const factory = `
factory: function MyComponent_Factory(t) { MyComponent.ngFactoryDef = function MyComponent_Factory(t) {
return new (t || MyComponent)( return new (t || MyComponent)(
$r3$.ɵɵinjectAttribute('name'), $r3$.ɵɵinjectAttribute('name'),
$r3$.ɵɵdirectiveInject(MyService), $r3$.ɵɵdirectiveInject(MyService),

View File

@ -41,7 +41,6 @@ describe('compiler compliance: directives', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -53,10 +52,15 @@ describe('compiler compliance: directives', () => {
}); });
`; `;
const MyComponentFactory = `
MyComponent.ngFactoryDef = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
`;
const result = compile(files, angularFiles); const result = compile(files, angularFiles);
const source = result.source; const source = result.source;
expectEmit(source, MyComponentDefinition, 'Incorrect ChildComponent.ngComponentDef'); expectEmit(source, MyComponentDefinition, 'Incorrect ChildComponent.ngComponentDef');
expectEmit(source, MyComponentFactory, 'Incorrect ChildComponent.ngFactoryDef');
}); });
it('should not match directives on i18n-prefixed attributes', () => { it('should not match directives on i18n-prefixed attributes', () => {
@ -87,7 +91,6 @@ describe('compiler compliance: directives', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -99,10 +102,15 @@ describe('compiler compliance: directives', () => {
}); });
`; `;
const MyComponentFactory = `
MyComponent.ngFactoryDef = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
`;
const result = compile(files, angularFiles); const result = compile(files, angularFiles);
const source = result.source; const source = result.source;
expectEmit(source, MyComponentDefinition, 'Incorrect ChildComponent.ngComponentDef'); expectEmit(source, MyComponentDefinition, 'Incorrect ChildComponent.ngComponentDef');
expectEmit(source, MyComponentFactory, 'Incorrect ChildComponent.ngFactoryDef');
}); });
it('should match directives on element bindings', () => { it('should match directives on element bindings', () => {

View File

@ -201,7 +201,6 @@ describe('compiler compliance: listen()', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 4, consts: 4,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -222,10 +221,15 @@ describe('compiler compliance: listen()', () => {
}); });
`; `;
const MyComponentFactory = `
MyComponent.ngFactoryDef = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
`;
const result = compile(files, angularFiles); const result = compile(files, angularFiles);
const source = result.source; const source = result.source;
expectEmit(source, MyComponentDefinition, 'Incorrect MyComponent.ngComponentDef'); expectEmit(source, MyComponentDefinition, 'Incorrect MyComponent.ngComponentDef');
expectEmit(source, MyComponentFactory, 'Incorrect MyComponent.ngFactoryDef');
}); });
}); });

View File

@ -144,10 +144,10 @@ describe('compiler compliance: providers', () => {
result.source, ` result.source, `
export class MyComponent { export class MyComponent {
} }
MyComponent.ngFactoryDef = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
MyComponent.ngComponentDef = i0.ɵɵdefineComponent({ MyComponent.ngComponentDef = i0.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); },
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {

View File

@ -131,9 +131,6 @@ describe('compiler compliance: styling', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors:[["my-component"]], selectors:[["my-component"]],
factory:function MyComponent_Factory(t){
return new (t || MyComponent)();
},
consts: 0, consts: 0,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, $ctx$) { template: function MyComponent_Template(rf, $ctx$) {
@ -173,9 +170,6 @@ describe('compiler compliance: styling', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors:[["my-component"]], selectors:[["my-component"]],
factory:function MyComponent_Factory(t){
return new (t || MyComponent)();
},
consts: 0, consts: 0,
vars: 0, vars: 0,
template: function MyComponent_Template(rf, $ctx$) { template: function MyComponent_Template(rf, $ctx$) {
@ -524,9 +518,6 @@ describe('compiler compliance: styling', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors:[["my-component"]], selectors:[["my-component"]],
factory:function MyComponent_Factory(t){
return new (t || MyComponent)();
},
consts: 1, consts: 1,
vars: 4, vars: 4,
template: function MyComponent_Template(rf, $ctx$) { template: function MyComponent_Template(rf, $ctx$) {
@ -577,9 +568,6 @@ describe('compiler compliance: styling', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [["my-component"]], selectors: [["my-component"]],
factory: function MyComponent_Factory(t) {
return new (t || MyComponent)();
},
consts: 1, consts: 1,
vars: 1, vars: 1,
template: function MyComponent_Template(rf, ctx) { template: function MyComponent_Template(rf, ctx) {
@ -736,9 +724,6 @@ describe('compiler compliance: styling', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors:[["my-component"]], selectors:[["my-component"]],
factory:function MyComponent_Factory(t){
return new (t || MyComponent)();
},
consts: 1, consts: 1,
vars: 4, vars: 4,
template: function MyComponent_Template(rf, $ctx$) { template: function MyComponent_Template(rf, $ctx$) {
@ -791,9 +776,6 @@ describe('compiler compliance: styling', () => {
MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({ MyComponent.ngComponentDef = $r3$.ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors:[["my-component"]], selectors:[["my-component"]],
factory:function MyComponent_Factory(t){
return new (t || MyComponent)();
},
consts: 1, consts: 1,
vars: 2, vars: 2,
template: function MyComponent_Template(rf, $ctx$) { template: function MyComponent_Template(rf, $ctx$) {

View File

@ -197,12 +197,14 @@ runInEachFileSystem(os => {
const jsContents = env.getContents('test.js'); const jsContents = env.getContents('test.js');
expect(jsContents).toContain('TestCmp.ngComponentDef = i0.ɵɵdefineComponent'); expect(jsContents).toContain('TestCmp.ngComponentDef = i0.ɵɵdefineComponent');
expect(jsContents).toContain('TestCmp.ngFactoryDef = function');
expect(jsContents).not.toContain('__decorate'); expect(jsContents).not.toContain('__decorate');
const dtsContents = env.getContents('test.d.ts'); const dtsContents = env.getContents('test.d.ts');
expect(dtsContents) expect(dtsContents)
.toContain( .toContain(
'static ngComponentDef: i0.ɵɵComponentDefWithMeta<TestCmp, "test-cmp", never, {}, {}, never>'); 'static ngComponentDef: i0.ɵɵComponentDefWithMeta<TestCmp, "test-cmp", never, {}, {}, never>');
expect(dtsContents).toContain('static ngFactoryDef: i0.ɵɵFactoryDef<TestCmp>');
}); });
it('should compile Components (dynamic inline template) without errors', () => { it('should compile Components (dynamic inline template) without errors', () => {
@ -220,12 +222,15 @@ runInEachFileSystem(os => {
const jsContents = env.getContents('test.js'); const jsContents = env.getContents('test.js');
expect(jsContents).toContain('TestCmp.ngComponentDef = i0.ɵɵdefineComponent'); expect(jsContents).toContain('TestCmp.ngComponentDef = i0.ɵɵdefineComponent');
expect(jsContents).toContain('TestCmp.ngFactoryDef = function');
expect(jsContents).not.toContain('__decorate'); expect(jsContents).not.toContain('__decorate');
const dtsContents = env.getContents('test.d.ts'); const dtsContents = env.getContents('test.d.ts');
expect(dtsContents) expect(dtsContents)
.toContain( .toContain(
'static ngComponentDef: i0.ɵɵComponentDefWithMeta<TestCmp, "test-cmp", never, {}, {}, never>'); 'static ngComponentDef: i0.ɵɵComponentDefWithMeta<TestCmp, "test-cmp", never, {}, {}, never>');
expect(dtsContents).toContain('static ngFactoryDef: i0.ɵɵFactoryDef<TestCmp>');
}); });
it('should compile Components (function call inline template) without errors', () => { it('should compile Components (function call inline template) without errors', () => {
@ -246,12 +251,14 @@ runInEachFileSystem(os => {
const jsContents = env.getContents('test.js'); const jsContents = env.getContents('test.js');
expect(jsContents).toContain('TestCmp.ngComponentDef = i0.ɵɵdefineComponent'); expect(jsContents).toContain('TestCmp.ngComponentDef = i0.ɵɵdefineComponent');
expect(jsContents).toContain('TestCmp.ngFactoryDef = function');
expect(jsContents).not.toContain('__decorate'); expect(jsContents).not.toContain('__decorate');
const dtsContents = env.getContents('test.d.ts'); const dtsContents = env.getContents('test.d.ts');
expect(dtsContents) expect(dtsContents)
.toContain( .toContain(
'static ngComponentDef: i0.ɵɵComponentDefWithMeta<TestCmp, "test-cmp", never, {}, {}, never>'); 'static ngComponentDef: i0.ɵɵComponentDefWithMeta<TestCmp, "test-cmp", never, {}, {}, never>');
expect(dtsContents).toContain('static ngFactoryDef: i0.ɵɵFactoryDef<TestCmp>');
}); });
it('should compile Components (external template) without errors', () => { it('should compile Components (external template) without errors', () => {
@ -880,10 +887,13 @@ runInEachFileSystem(os => {
expect(jsContents) expect(jsContents)
.toContain( .toContain(
'TestPipe.ngPipeDef = i0.ɵɵdefinePipe({ name: "test-pipe", type: TestPipe, ' + 'TestPipe.ngPipeDef = i0.ɵɵdefinePipe({ name: "test-pipe", type: TestPipe, pure: false })');
'factory: function TestPipe_Factory(t) { return new (t || TestPipe)(); }, pure: false })'); expect(jsContents)
.toContain(
'TestPipe.ngFactoryDef = function TestPipe_Factory(t) { return new (t || TestPipe)(); }');
expect(dtsContents) expect(dtsContents)
.toContain('static ngPipeDef: i0.ɵɵPipeDefWithMeta<TestPipe, "test-pipe">;'); .toContain('static ngPipeDef: i0.ɵɵPipeDefWithMeta<TestPipe, "test-pipe">;');
expect(dtsContents).toContain('static ngFactoryDef: i0.ɵɵFactoryDef<TestPipe>;');
}); });
it('should compile pure Pipes without errors', () => { it('should compile pure Pipes without errors', () => {
@ -903,10 +913,13 @@ runInEachFileSystem(os => {
expect(jsContents) expect(jsContents)
.toContain( .toContain(
'TestPipe.ngPipeDef = i0.ɵɵdefinePipe({ name: "test-pipe", type: TestPipe, ' + 'TestPipe.ngPipeDef = i0.ɵɵdefinePipe({ name: "test-pipe", type: TestPipe, pure: true })');
'factory: function TestPipe_Factory(t) { return new (t || TestPipe)(); }, pure: true })'); expect(jsContents)
.toContain(
'TestPipe.ngFactoryDef = function TestPipe_Factory(t) { return new (t || TestPipe)(); }');
expect(dtsContents) expect(dtsContents)
.toContain('static ngPipeDef: i0.ɵɵPipeDefWithMeta<TestPipe, "test-pipe">;'); .toContain('static ngPipeDef: i0.ɵɵPipeDefWithMeta<TestPipe, "test-pipe">;');
expect(dtsContents).toContain('static ngFactoryDef: i0.ɵɵFactoryDef<TestPipe>;');
}); });
it('should compile Pipes with dependencies', () => { it('should compile Pipes with dependencies', () => {
@ -947,6 +960,7 @@ runInEachFileSystem(os => {
const dtsContents = env.getContents('test.d.ts'); const dtsContents = env.getContents('test.d.ts');
expect(dtsContents) expect(dtsContents)
.toContain('static ngPipeDef: i0.ɵɵPipeDefWithMeta<TestPipe<any>, "test-pipe">;'); .toContain('static ngPipeDef: i0.ɵɵPipeDefWithMeta<TestPipe<any>, "test-pipe">;');
expect(dtsContents).toContain('static ngFactoryDef: i0.ɵɵFactoryDef<TestPipe<any>>;');
}); });
it('should include @Pipes in @NgModule scopes', () => { it('should include @Pipes in @NgModule scopes', () => {
@ -1615,7 +1629,7 @@ runInEachFileSystem(os => {
const jsContents = env.getContents('test.js'); const jsContents = env.getContents('test.js');
expect(jsContents) expect(jsContents)
.toContain( .toContain(
`factory: function FooCmp_Factory(t) { return new (t || FooCmp)(i0.ɵɵinjectAttribute("test"), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i0.Injector), i0.ɵɵdirectiveInject(i0.Renderer2), i0.ɵɵdirectiveInject(i0.TemplateRef), i0.ɵɵdirectiveInject(i0.ViewContainerRef)); }`); `FooCmp.ngFactoryDef = function FooCmp_Factory(t) { return new (t || FooCmp)(i0.ɵɵinjectAttribute("test"), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i0.Injector), i0.ɵɵdirectiveInject(i0.Renderer2), i0.ɵɵdirectiveInject(i0.TemplateRef), i0.ɵɵdirectiveInject(i0.ViewContainerRef)); }`);
}); });
it('should generate queries for components', () => { it('should generate queries for components', () => {

View File

@ -95,7 +95,7 @@ export {BoundAttribute as TmplAstBoundAttribute, BoundEvent as TmplAstBoundEvent
export * from './render3/view/t2_api'; export * from './render3/view/t2_api';
export * from './render3/view/t2_binder'; export * from './render3/view/t2_binder';
export {Identifiers as R3Identifiers} from './render3/r3_identifiers'; export {Identifiers as R3Identifiers} from './render3/r3_identifiers';
export {R3DependencyMetadata, R3FactoryMetadata, R3ResolvedDependencyType} from './render3/r3_factory'; export {R3DependencyMetadata, R3FactoryDefMetadata, R3ResolvedDependencyType, compileFactoryFromMetadata, R3FactoryMetadata} from './render3/r3_factory';
export {compileInjector, compileNgModule, R3InjectorMetadata, R3NgModuleMetadata} from './render3/r3_module_compiler'; export {compileInjector, compileNgModule, R3InjectorMetadata, R3NgModuleMetadata} from './render3/r3_module_compiler';
export {compilePipeFromMetadata, R3PipeMetadata} from './render3/r3_pipe_compiler'; export {compilePipeFromMetadata, R3PipeMetadata} from './render3/r3_pipe_compiler';
export {makeBindingParser, parseTemplate, ParseTemplateOptions} from './render3/view/template'; export {makeBindingParser, parseTemplate, ParseTemplateOptions} from './render3/view/template';
@ -106,4 +106,4 @@ export {publishFacade} from './jit_compiler_facade';
// This function call has a global side effects and publishes the compiler into global namespace for // This function call has a global side effects and publishes the compiler into global namespace for
// the late binding of the Compiler to the @angular/core for jit compilation. // the late binding of the Compiler to the @angular/core for jit compilation.
publishFacade(global); publishFacade(global);

View File

@ -39,6 +39,10 @@ export interface CompilerFacade {
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3ComponentMetadataFacade): any; angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3ComponentMetadataFacade): any;
compileBase(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3BaseMetadataFacade): compileBase(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3BaseMetadataFacade):
any; any;
compileFactory(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string,
meta: R3PipeMetadataFacade|R3DirectiveMetadataFacade|R3ComponentMetadataFacade,
isPipe?: boolean): any;
createParseSourceSpan(kind: string, typeName: string, sourceUrl: string): ParseSourceSpan; createParseSourceSpan(kind: string, typeName: string, sourceUrl: string): ParseSourceSpan;

View File

@ -37,6 +37,7 @@ export function compileInjectable(meta: R3InjectableMetadata): InjectableDef {
const factoryMeta = { const factoryMeta = {
name: meta.name, name: meta.name,
type: meta.type, type: meta.type,
typeArgumentCount: meta.typeArgumentCount,
deps: meta.ctorDeps, deps: meta.ctorDeps,
injectFn: Identifiers.inject, injectFn: Identifiers.inject,
}; };

View File

@ -15,7 +15,7 @@ import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from './ml_parser/int
import {DeclareVarStmt, Expression, LiteralExpr, Statement, StmtModifier, WrappedNodeExpr} from './output/output_ast'; import {DeclareVarStmt, Expression, LiteralExpr, Statement, StmtModifier, WrappedNodeExpr} from './output/output_ast';
import {JitEvaluator} from './output/output_jit'; import {JitEvaluator} from './output/output_jit';
import {ParseError, ParseSourceSpan, r3JitTypeSourceSpan} from './parse_util'; import {ParseError, ParseSourceSpan, r3JitTypeSourceSpan} from './parse_util';
import {R3DependencyMetadata, R3ResolvedDependencyType} from './render3/r3_factory'; import {R3DependencyMetadata, R3ResolvedDependencyType, compileFactoryFromMetadata} from './render3/r3_factory';
import {R3JitReflector} from './render3/r3_jit'; import {R3JitReflector} from './render3/r3_jit';
import {R3InjectorMetadata, R3NgModuleMetadata, compileInjector, compileNgModule} from './render3/r3_module_compiler'; import {R3InjectorMetadata, R3NgModuleMetadata, compileInjector, compileNgModule} from './render3/r3_module_compiler';
import {compilePipeFromMetadata} from './render3/r3_pipe_compiler'; import {compilePipeFromMetadata} from './render3/r3_pipe_compiler';
@ -35,15 +35,16 @@ export class CompilerFacadeImpl implements CompilerFacade {
compilePipe(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, facade: R3PipeMetadataFacade): compilePipe(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, facade: R3PipeMetadataFacade):
any { any {
const res = compilePipeFromMetadata({ const metadata = {
name: facade.name, name: facade.name,
type: new WrappedNodeExpr(facade.type), type: new WrappedNodeExpr(facade.type),
typeArgumentCount: facade.typeArgumentCount, typeArgumentCount: facade.typeArgumentCount,
deps: convertR3DependencyMetadataArray(facade.deps), deps: convertR3DependencyMetadataArray(facade.deps),
pipeName: facade.pipeName, pipeName: facade.pipeName,
pure: facade.pure, pure: facade.pure,
}); };
return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, res.statements); const res = compilePipeFromMetadata(metadata);
return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);
} }
compileInjectable( compileInjectable(
@ -105,8 +106,8 @@ export class CompilerFacadeImpl implements CompilerFacade {
const meta: R3DirectiveMetadata = convertDirectiveFacadeToMetadata(facade); const meta: R3DirectiveMetadata = convertDirectiveFacadeToMetadata(facade);
const res = compileDirectiveFromMetadata(meta, constantPool, bindingParser); const res = compileDirectiveFromMetadata(meta, constantPool, bindingParser);
const preStatements = [...constantPool.statements, ...res.statements]; return this.jitExpression(
return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, preStatements); res.expression, angularCoreEnv, sourceMapUrl, constantPool.statements);
} }
compileComponent( compileComponent(
@ -129,27 +130,41 @@ export class CompilerFacadeImpl implements CompilerFacade {
// Compile the component metadata, including template, into an expression. // Compile the component metadata, including template, into an expression.
// TODO(alxhub): implement inputs, outputs, queries, etc. // TODO(alxhub): implement inputs, outputs, queries, etc.
const metadata = {
...facade as R3ComponentMetadataFacadeNoPropAndWhitespace,
...convertDirectiveFacadeToMetadata(facade),
selector: facade.selector || this.elementSchemaRegistry.getDefaultComponentElementName(),
template,
wrapDirectivesAndPipesInClosure: false,
styles: facade.styles || [],
encapsulation: facade.encapsulation as any,
interpolation: interpolationConfig,
changeDetection: facade.changeDetection,
animations: facade.animations != null ? new WrappedNodeExpr(facade.animations) : null,
viewProviders: facade.viewProviders != null ? new WrappedNodeExpr(facade.viewProviders) :
null,
relativeContextFilePath: '',
i18nUseExternalIds: true,
};
const res = compileComponentFromMetadata( const res = compileComponentFromMetadata(
{ metadata, constantPool, makeBindingParser(interpolationConfig));
...facade as R3ComponentMetadataFacadeNoPropAndWhitespace, const jitExpressionSourceMap = `ng:///${facade.name}.js`;
...convertDirectiveFacadeToMetadata(facade),
selector: facade.selector || this.elementSchemaRegistry.getDefaultComponentElementName(),
template,
wrapDirectivesAndPipesInClosure: false,
styles: facade.styles || [],
encapsulation: facade.encapsulation as any,
interpolation: interpolationConfig,
changeDetection: facade.changeDetection,
animations: facade.animations != null ? new WrappedNodeExpr(facade.animations) : null,
viewProviders: facade.viewProviders != null ? new WrappedNodeExpr(facade.viewProviders) :
null,
relativeContextFilePath: '',
i18nUseExternalIds: true,
},
constantPool, makeBindingParser(interpolationConfig));
const preStatements = [...constantPool.statements, ...res.statements];
return this.jitExpression( return this.jitExpression(
res.expression, angularCoreEnv, `ng:///${facade.name}.js`, preStatements); res.expression, angularCoreEnv, jitExpressionSourceMap, constantPool.statements);
}
compileFactory(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string,
meta: R3PipeMetadataFacade|R3DirectiveMetadataFacade|R3ComponentMetadataFacade,
isPipe = false) {
const factoryRes = compileFactoryFromMetadata({
name: meta.name,
type: new WrappedNodeExpr(meta.type),
typeArgumentCount: meta.typeArgumentCount,
deps: convertR3DependencyMetadataArray(meta.deps), isPipe
});
return this.jitExpression(
factoryRes.factory, angularCoreEnv, sourceMapUrl, factoryRes.statements);
} }
compileBase(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, facade: R3BaseMetadataFacade): compileBase(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, facade: R3BaseMetadataFacade):

View File

@ -15,9 +15,11 @@ import * as o from '../output/output_ast';
import {Identifiers as R3} from '../render3/r3_identifiers'; import {Identifiers as R3} from '../render3/r3_identifiers';
import {OutputContext} from '../util'; import {OutputContext} from '../util';
import {typeWithParameters} from './util';
import {unsupported} from './view/util'; import {unsupported} from './view/util';
/** /**
* Metadata required by the factory generator to generate a `factory` function for a type. * Metadata required by the factory generator to generate a `factory` function for a type.
*/ */
@ -36,6 +38,9 @@ export interface R3ConstructorFactoryMetadata {
*/ */
type: o.Expression; type: o.Expression;
/** Number of arguments for the `type`. */
typeArgumentCount: number;
/** /**
* Regardless of whether `fnOrClass` is a constructor function or a user-defined factory, it * Regardless of whether `fnOrClass` is a constructor function or a user-defined factory, it
* may have 0 or more parameters, which will be injected according to the `R3DependencyMetadata` * may have 0 or more parameters, which will be injected according to the `R3DependencyMetadata`
@ -77,6 +82,14 @@ export interface R3ExpressionFactoryMetadata extends R3ConstructorFactoryMetadat
export type R3FactoryMetadata = R3ConstructorFactoryMetadata | R3DelegatedFactoryMetadata | export type R3FactoryMetadata = R3ConstructorFactoryMetadata | R3DelegatedFactoryMetadata |
R3DelegatedFnOrClassMetadata | R3ExpressionFactoryMetadata; R3DelegatedFnOrClassMetadata | R3ExpressionFactoryMetadata;
export interface R3FactoryDefMetadata {
name: string;
type: o.Expression;
typeArgumentCount: number;
deps: R3DependencyMetadata[]|null;
isPipe?: boolean;
}
/** /**
* Resolved type of a dependency. * Resolved type of a dependency.
* *
@ -140,11 +153,16 @@ export interface R3DependencyMetadata {
skipSelf: boolean; skipSelf: boolean;
} }
export interface R3FactoryFn {
factory: o.Expression;
statements: o.Statement[];
type: o.ExpressionType;
}
/** /**
* Construct a factory function expression for the given `R3FactoryMetadata`. * Construct a factory function expression for the given `R3FactoryMetadata`.
*/ */
export function compileFactoryFunction( export function compileFactoryFunction(meta: R3FactoryMetadata, isPipe = false): R3FactoryFn {
meta: R3FactoryMetadata, isPipe = false): {factory: o.Expression, statements: o.Statement[]} {
const t = o.variable('t'); const t = o.variable('t');
const statements: o.Statement[] = []; const statements: o.Statement[] = [];
@ -234,9 +252,27 @@ export function compileFactoryFunction(
[new o.FnParam('t', o.DYNAMIC_TYPE)], body, o.INFERRED_TYPE, undefined, [new o.FnParam('t', o.DYNAMIC_TYPE)], body, o.INFERRED_TYPE, undefined,
`${meta.name}_Factory`), `${meta.name}_Factory`),
statements, statements,
type: o.expressionType(
o.importExpr(R3.FactoryDef, [typeWithParameters(meta.type, meta.typeArgumentCount)]))
}; };
} }
/**
* Constructs the `ngFactoryDef` from directive/component/pipe metadata.
*/
export function compileFactoryFromMetadata(meta: R3FactoryDefMetadata): R3FactoryFn {
return compileFactoryFunction(
{
name: meta.name,
type: meta.type,
deps: meta.deps,
typeArgumentCount: meta.typeArgumentCount,
// TODO(crisbeto): this should be refactored once we start using it for injectables.
injectFn: R3.directiveInject,
},
meta.isPipe);
}
function injectDependencies( function injectDependencies(
deps: R3DependencyMetadata[], injectFn: o.ExternalReference, isPipe: boolean): o.Expression[] { deps: R3DependencyMetadata[], injectFn: o.ExternalReference, isPipe: boolean): o.Expression[] {
return deps.map(dep => compileInjectDependency(dep, injectFn, isPipe)); return deps.map(dep => compileInjectDependency(dep, injectFn, isPipe));

View File

@ -241,6 +241,11 @@ export class Identifiers {
moduleName: CORE, moduleName: CORE,
}; };
static FactoryDef: o.ExternalReference = {
name: 'ɵɵFactoryDef',
moduleName: CORE,
};
static defineDirective: o.ExternalReference = { static defineDirective: o.ExternalReference = {
name: 'ɵɵdefineDirective', name: 'ɵɵdefineDirective',
moduleName: CORE, moduleName: CORE,

View File

@ -207,6 +207,7 @@ export function compileInjector(meta: R3InjectorMetadata): R3InjectorDef {
const result = compileFactoryFunction({ const result = compileFactoryFunction({
name: meta.name, name: meta.name,
type: meta.type, type: meta.type,
typeArgumentCount: 0,
deps: meta.deps, deps: meta.deps,
injectFn: R3.inject, injectFn: R3.inject,
}); });

View File

@ -12,7 +12,7 @@ import {DefinitionKind} from '../constant_pool';
import * as o from '../output/output_ast'; import * as o from '../output/output_ast';
import {OutputContext, error} from '../util'; import {OutputContext, error} from '../util';
import {R3DependencyMetadata, compileFactoryFunction, dependenciesFromGlobalMetadata} from './r3_factory'; import {R3DependencyMetadata, compileFactoryFromMetadata, compileFactoryFunction, dependenciesFromGlobalMetadata} from './r3_factory';
import {Identifiers as R3} from './r3_identifiers'; import {Identifiers as R3} from './r3_identifiers';
import {typeWithParameters} from './util'; import {typeWithParameters} from './util';
@ -57,16 +57,6 @@ export function compilePipeFromMetadata(metadata: R3PipeMetadata) {
// e.g. `type: MyPipe` // e.g. `type: MyPipe`
definitionMapValues.push({key: 'type', value: metadata.type, quoted: false}); definitionMapValues.push({key: 'type', value: metadata.type, quoted: false});
const templateFactory = compileFactoryFunction(
{
name: metadata.name,
type: metadata.type,
deps: metadata.deps,
injectFn: R3.directiveInject,
},
true);
definitionMapValues.push({key: 'factory', value: templateFactory.factory, quoted: false});
// e.g. `pure: true` // e.g. `pure: true`
definitionMapValues.push({key: 'pure', value: o.literal(metadata.pure), quoted: false}); definitionMapValues.push({key: 'pure', value: o.literal(metadata.pure), quoted: false});
@ -75,7 +65,8 @@ export function compilePipeFromMetadata(metadata: R3PipeMetadata) {
typeWithParameters(metadata.type, metadata.typeArgumentCount), typeWithParameters(metadata.type, metadata.typeArgumentCount),
new o.ExpressionType(new o.LiteralExpr(metadata.pipeName)), new o.ExpressionType(new o.LiteralExpr(metadata.pipeName)),
])); ]));
return {expression, type, statements: templateFactory.statements};
return {expression, type};
} }
/** /**
@ -83,9 +74,8 @@ export function compilePipeFromMetadata(metadata: R3PipeMetadata) {
*/ */
export function compilePipeFromRender2( export function compilePipeFromRender2(
outputCtx: OutputContext, pipe: CompilePipeMetadata, reflector: CompileReflector) { outputCtx: OutputContext, pipe: CompilePipeMetadata, reflector: CompileReflector) {
const definitionMapValues: {key: string, quoted: boolean, value: o.Expression}[] = [];
const name = identifierName(pipe.type); const name = identifierName(pipe.type);
if (!name) { if (!name) {
return error(`Cannot resolve the name of ${pipe.type}`); return error(`Cannot resolve the name of ${pipe.type}`);
} }
@ -98,12 +88,22 @@ export function compilePipeFromRender2(
deps: dependenciesFromGlobalMetadata(pipe.type, outputCtx, reflector), deps: dependenciesFromGlobalMetadata(pipe.type, outputCtx, reflector),
pure: pipe.pure, pure: pipe.pure,
}; };
const res = compilePipeFromMetadata(metadata); const res = compilePipeFromMetadata(metadata);
const factoryRes = compileFactoryFromMetadata({...metadata, isPipe: true});
const definitionField = outputCtx.constantPool.propertyNameOf(DefinitionKind.Pipe); const definitionField = outputCtx.constantPool.propertyNameOf(DefinitionKind.Pipe);
const ngFactoryDefStatement = new o.ClassStmt(
outputCtx.statements.push(new o.ClassStmt( /* name */ name,
/* parent */ null,
/* fields */
[new o.ClassField(
/* name */ 'ngFactoryDef',
/* type */ o.INFERRED_TYPE,
/* modifiers */[o.StmtModifier.Static],
/* initializer */ factoryRes.factory)],
/* getters */[],
/* constructorMethod */ new o.ClassMethod(null, [], []),
/* methods */[]);
const pipeDefStatement = new o.ClassStmt(
/* name */ name, /* name */ name,
/* parent */ null, /* parent */ null,
/* fields */[new o.ClassField( /* fields */[new o.ClassField(
@ -113,5 +113,7 @@ export function compilePipeFromRender2(
/* initializer */ res.expression)], /* initializer */ res.expression)],
/* getters */[], /* getters */[],
/* constructorMethod */ new o.ClassMethod(null, [], []), /* constructorMethod */ new o.ClassMethod(null, [], []),
/* methods */[])); /* methods */[]);
outputCtx.statements.push(ngFactoryDefStatement, pipeDefStatement);
} }

View File

@ -237,7 +237,6 @@ export interface R3QueryMetadata {
export interface R3DirectiveDef { export interface R3DirectiveDef {
expression: o.Expression; expression: o.Expression;
type: o.Type; type: o.Type;
statements: o.Statement[];
} }
/** /**
@ -246,7 +245,6 @@ export interface R3DirectiveDef {
export interface R3ComponentDef { export interface R3ComponentDef {
expression: o.Expression; expression: o.Expression;
type: o.Type; type: o.Type;
statements: o.Statement[];
} }
/** /**

View File

@ -22,7 +22,7 @@ import {CONTENT_ATTR, HOST_ATTR} from '../../style_compiler';
import {BindingParser} from '../../template_parser/binding_parser'; import {BindingParser} from '../../template_parser/binding_parser';
import {OutputContext, error} from '../../util'; import {OutputContext, error} from '../../util';
import {BoundEvent} from '../r3_ast'; import {BoundEvent} from '../r3_ast';
import {compileFactoryFunction, dependenciesFromGlobalMetadata} from '../r3_factory'; import {compileFactoryFromMetadata, compileFactoryFunction, dependenciesFromGlobalMetadata} from '../r3_factory';
import {Identifiers as R3} from '../r3_identifiers'; import {Identifiers as R3} from '../r3_identifiers';
import {Render3ParseResult} from '../r3_template_transform'; import {Render3ParseResult} from '../r3_template_transform';
import {prepareSyntheticListenerFunctionName, prepareSyntheticPropertyName, typeWithParameters} from '../util'; import {prepareSyntheticListenerFunctionName, prepareSyntheticPropertyName, typeWithParameters} from '../util';
@ -44,7 +44,7 @@ function getStylingPrefix(name: string): string {
function baseDirectiveFields( function baseDirectiveFields(
meta: R3DirectiveMetadata, constantPool: ConstantPool, meta: R3DirectiveMetadata, constantPool: ConstantPool,
bindingParser: BindingParser): {definitionMap: DefinitionMap, statements: o.Statement[]} { bindingParser: BindingParser): DefinitionMap {
const definitionMap = new DefinitionMap(); const definitionMap = new DefinitionMap();
// e.g. `type: MyDirective` // e.g. `type: MyDirective`
@ -53,16 +53,6 @@ function baseDirectiveFields(
// e.g. `selectors: [['', 'someDir', '']]` // e.g. `selectors: [['', 'someDir', '']]`
definitionMap.set('selectors', createDirectiveSelector(meta.selector)); definitionMap.set('selectors', createDirectiveSelector(meta.selector));
// e.g. `factory: () => new MyApp(directiveInject(ElementRef))`
const result = compileFactoryFunction({
name: meta.name,
type: meta.type,
deps: meta.deps,
injectFn: R3.directiveInject,
});
definitionMap.set('factory', result.factory);
if (meta.queries.length > 0) { if (meta.queries.length > 0) {
// e.g. `contentQueries: (rf, ctx, dirIndex) => { ... } // e.g. `contentQueries: (rf, ctx, dirIndex) => { ... }
definitionMap.set( definitionMap.set(
@ -90,7 +80,7 @@ function baseDirectiveFields(
definitionMap.set('exportAs', o.literalArr(meta.exportAs.map(e => o.literal(e)))); definitionMap.set('exportAs', o.literalArr(meta.exportAs.map(e => o.literal(e))));
} }
return {definitionMap, statements: result.statements}; return definitionMap;
} }
/** /**
@ -128,12 +118,12 @@ function addFeatures(
export function compileDirectiveFromMetadata( export function compileDirectiveFromMetadata(
meta: R3DirectiveMetadata, constantPool: ConstantPool, meta: R3DirectiveMetadata, constantPool: ConstantPool,
bindingParser: BindingParser): R3DirectiveDef { bindingParser: BindingParser): R3DirectiveDef {
const {definitionMap, statements} = baseDirectiveFields(meta, constantPool, bindingParser); const definitionMap = baseDirectiveFields(meta, constantPool, bindingParser);
addFeatures(definitionMap, meta); addFeatures(definitionMap, meta);
const expression = o.importExpr(R3.defineDirective).callFn([definitionMap.toLiteralMap()]); const expression = o.importExpr(R3.defineDirective).callFn([definitionMap.toLiteralMap()]);
const type = createTypeForDef(meta, R3.DirectiveDefWithMeta); const type = createTypeForDef(meta, R3.DirectiveDefWithMeta);
return {expression, type, statements}; return {expression, type};
} }
export interface R3BaseRefMetaData { export interface R3BaseRefMetaData {
@ -197,7 +187,7 @@ export function compileBaseDefFromMetadata(
export function compileComponentFromMetadata( export function compileComponentFromMetadata(
meta: R3ComponentMetadata, constantPool: ConstantPool, meta: R3ComponentMetadata, constantPool: ConstantPool,
bindingParser: BindingParser): R3ComponentDef { bindingParser: BindingParser): R3ComponentDef {
const {definitionMap, statements} = baseDirectiveFields(meta, constantPool, bindingParser); const definitionMap = baseDirectiveFields(meta, constantPool, bindingParser);
addFeatures(definitionMap, meta); addFeatures(definitionMap, meta);
const selector = meta.selector && CssSelector.parse(meta.selector); const selector = meta.selector && CssSelector.parse(meta.selector);
@ -315,7 +305,7 @@ export function compileComponentFromMetadata(
const expression = o.importExpr(R3.defineComponent).callFn([definitionMap.toLiteralMap()]); const expression = o.importExpr(R3.defineComponent).callFn([definitionMap.toLiteralMap()]);
const type = createTypeForDef(meta, R3.ComponentDefWithMeta); const type = createTypeForDef(meta, R3.ComponentDefWithMeta);
return {expression, type, statements}; return {expression, type};
} }
/** /**
@ -335,12 +325,19 @@ export function compileDirectiveFromRender2(
const meta = directiveMetadataFromGlobalMetadata(directive, outputCtx, reflector); const meta = directiveMetadataFromGlobalMetadata(directive, outputCtx, reflector);
const res = compileDirectiveFromMetadata(meta, outputCtx.constantPool, bindingParser); const res = compileDirectiveFromMetadata(meta, outputCtx.constantPool, bindingParser);
const factoryRes = compileFactoryFromMetadata(meta);
// Create the partial class to be merged with the actual class. const ngFactoryDefStatement = new o.ClassStmt(
outputCtx.statements.push(new o.ClassStmt( name, null,
[new o.ClassField(
'ngFactoryDef', o.INFERRED_TYPE, [o.StmtModifier.Static], factoryRes.factory)],
[], new o.ClassMethod(null, [], []), []);
const directiveDefStatement = new o.ClassStmt(
name, null, name, null,
[new o.ClassField(definitionField, o.INFERRED_TYPE, [o.StmtModifier.Static], res.expression)], [new o.ClassField(definitionField, o.INFERRED_TYPE, [o.StmtModifier.Static], res.expression)],
[], new o.ClassMethod(null, [], []), [])); [], new o.ClassMethod(null, [], []), []);
// Create the partial class to be merged with the actual class.
outputCtx.statements.push(ngFactoryDefStatement, directiveDefStatement);
} }
/** /**
@ -381,12 +378,19 @@ export function compileComponentFromRender2(
i18nUseExternalIds: true, i18nUseExternalIds: true,
}; };
const res = compileComponentFromMetadata(meta, outputCtx.constantPool, bindingParser); const res = compileComponentFromMetadata(meta, outputCtx.constantPool, bindingParser);
const factoryRes = compileFactoryFromMetadata(meta);
// Create the partial class to be merged with the actual class. const ngFactoryDefStatement = new o.ClassStmt(
outputCtx.statements.push(new o.ClassStmt( name, null,
[new o.ClassField(
'ngFactoryDef', o.INFERRED_TYPE, [o.StmtModifier.Static], factoryRes.factory)],
[], new o.ClassMethod(null, [], []), []);
const componentDefStatement = new o.ClassStmt(
name, null, name, null,
[new o.ClassField(definitionField, o.INFERRED_TYPE, [o.StmtModifier.Static], res.expression)], [new o.ClassField(definitionField, o.INFERRED_TYPE, [o.StmtModifier.Static], res.expression)],
[], new o.ClassMethod(null, [], []), [])); [], new o.ClassMethod(null, [], []), []);
// Create the partial class to be merged with the actual class.
outputCtx.statements.push(ngFactoryDefStatement, componentDefStatement);
} }
/** /**

View File

@ -39,6 +39,10 @@ export interface CompilerFacade {
angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3ComponentMetadataFacade): any; angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3ComponentMetadataFacade): any;
compileBase(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3BaseMetadataFacade): compileBase(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, meta: R3BaseMetadataFacade):
any; any;
compileFactory(
angularCoreEnv: CoreEnvironment, sourceMapUrl: string,
meta: R3PipeMetadataFacade|R3DirectiveMetadataFacade|R3ComponentMetadataFacade,
isPipe?: boolean): any;
createParseSourceSpan(kind: string, typeName: string, sourceUrl: string): ParseSourceSpan; createParseSourceSpan(kind: string, typeName: string, sourceUrl: string): ParseSourceSpan;

View File

@ -156,6 +156,7 @@ export {
ɵɵBaseDef, ɵɵBaseDef,
ComponentDef as ɵComponentDef, ComponentDef as ɵComponentDef,
ɵɵComponentDefWithMeta, ɵɵComponentDefWithMeta,
ɵɵFactoryDef,
DirectiveDef as ɵDirectiveDef, DirectiveDef as ɵDirectiveDef,
ɵɵDirectiveDefWithMeta, ɵɵDirectiveDefWithMeta,
PipeDef as ɵPipeDef, PipeDef as ɵPipeDef,

View File

@ -10,6 +10,7 @@ import '../util/ng_dev_mode';
import {OnDestroy} from '../interface/lifecycle_hooks'; import {OnDestroy} from '../interface/lifecycle_hooks';
import {Type} from '../interface/type'; import {Type} from '../interface/type';
import {getFactoryDef} from '../render3/definition';
import {throwCyclicDependencyError, throwInvalidProviderError, throwMixedMultiProviderError} from '../render3/errors'; import {throwCyclicDependencyError, throwInvalidProviderError, throwMixedMultiProviderError} from '../render3/errors';
import {deepForEach, newArray} from '../util/array_utils'; import {deepForEach, newArray} from '../util/array_utils';
import {stringify} from '../util/stringify'; import {stringify} from '../util/stringify';
@ -398,8 +399,10 @@ export class R3Injector {
function injectableDefOrInjectorDefFactory(token: Type<any>| InjectionToken<any>): () => any { function injectableDefOrInjectorDefFactory(token: Type<any>| InjectionToken<any>): () => any {
// Most tokens will have an ngInjectableDef directly on them, which specifies a factory directly. // Most tokens will have an ngInjectableDef directly on them, which specifies a factory directly.
const injectableDef = getInjectableDef(token); const injectableDef = getInjectableDef(token);
if (injectableDef !== null) { const factory = injectableDef !== null ? injectableDef.factory : getFactoryDef(token);
return injectableDef.factory;
if (factory !== null) {
return factory;
} }
// If the token is an NgModule, it's also injectable but the factory is on its ngInjectorDef. // If the token is an NgModule, it's also injectable but the factory is on its ngInjectorDef.

View File

@ -7,6 +7,7 @@
*/ */
import '../util/ng_dev_mode'; import '../util/ng_dev_mode';
import {ChangeDetectionStrategy} from '../change_detection/constants'; import {ChangeDetectionStrategy} from '../change_detection/constants';
import {NG_INJECTABLE_DEF, ɵɵdefineInjectable} from '../di/interface/defs'; import {NG_INJECTABLE_DEF, ɵɵdefineInjectable} from '../di/interface/defs';
import {Mutable, Type} from '../interface/type'; import {Mutable, Type} from '../interface/type';
@ -15,8 +16,9 @@ import {SchemaMetadata} from '../metadata/schema';
import {ViewEncapsulation} from '../metadata/view'; import {ViewEncapsulation} from '../metadata/view';
import {noSideEffects} from '../util/closure'; import {noSideEffects} from '../util/closure';
import {stringify} from '../util/stringify'; import {stringify} from '../util/stringify';
import {EMPTY_ARRAY, EMPTY_OBJ} from './empty'; import {EMPTY_ARRAY, EMPTY_OBJ} from './empty';
import {NG_BASE_DEF, NG_COMPONENT_DEF, NG_DIRECTIVE_DEF, NG_LOCALE_ID_DEF, NG_MODULE_DEF, NG_PIPE_DEF} from './fields'; import {NG_BASE_DEF, NG_COMPONENT_DEF, NG_DIRECTIVE_DEF, NG_FACTORY_DEF, NG_LOCALE_ID_DEF, NG_MODULE_DEF, NG_PIPE_DEF} from './fields';
import {ComponentDef, ComponentDefFeature, ComponentTemplate, ComponentType, ContentQueriesFunction, DirectiveDef, DirectiveDefFeature, DirectiveType, DirectiveTypesOrFactory, FactoryFn, HostBindingsFunction, PipeDef, PipeType, PipeTypesOrFactory, ViewQueriesFunction, ɵɵBaseDef} from './interfaces/definition'; import {ComponentDef, ComponentDefFeature, ComponentTemplate, ComponentType, ContentQueriesFunction, DirectiveDef, DirectiveDefFeature, DirectiveType, DirectiveTypesOrFactory, FactoryFn, HostBindingsFunction, PipeDef, PipeType, PipeTypesOrFactory, ViewQueriesFunction, ɵɵBaseDef} from './interfaces/definition';
// while SelectorFlags is unused here, it's required so that types don't get resolved lazily // while SelectorFlags is unused here, it's required so that types don't get resolved lazily
// see: https://github.com/Microsoft/web-build-tools/issues/1050 // see: https://github.com/Microsoft/web-build-tools/issues/1050
@ -49,11 +51,6 @@ export function ɵɵdefineComponent<T>(componentDefinition: {
/** The selectors that will be used to match nodes to this component. */ /** The selectors that will be used to match nodes to this component. */
selectors: CssSelectorList; selectors: CssSelectorList;
/**
* Factory method used to create an instance of directive.
*/
factory: FactoryFn<T>;
/** /**
* The number of nodes, local refs, and pipes in this component template. * The number of nodes, local refs, and pipes in this component template.
* *
@ -251,7 +248,7 @@ export function ɵɵdefineComponent<T>(componentDefinition: {
providersResolver: null, providersResolver: null,
consts: componentDefinition.consts, consts: componentDefinition.consts,
vars: componentDefinition.vars, vars: componentDefinition.vars,
factory: componentDefinition.factory, factory: null,
template: componentDefinition.template || null !, template: componentDefinition.template || null !,
ngContentSelectors: componentDefinition.ngContentSelectors, ngContentSelectors: componentDefinition.ngContentSelectors,
hostBindings: componentDefinition.hostBindings || null, hostBindings: componentDefinition.hostBindings || null,
@ -300,15 +297,6 @@ export function ɵɵdefineComponent<T>(componentDefinition: {
def.pipeDefs = pipeTypes ? def.pipeDefs = pipeTypes ?
() => (typeof pipeTypes === 'function' ? pipeTypes() : pipeTypes).map(extractPipeDef) : () => (typeof pipeTypes === 'function' ? pipeTypes() : pipeTypes).map(extractPipeDef) :
null; null;
// Add ngInjectableDef so components are reachable through the module injector by default
// (unless it has already been set by the @Injectable decorator). This is mostly to
// support injecting components in tests. In real application code, components should
// be retrieved through the node injector, so this isn't a problem.
if (!type.hasOwnProperty(NG_INJECTABLE_DEF)) {
(type as any)[NG_INJECTABLE_DEF] =
ɵɵdefineInjectable<T>({token: type, factory: componentDefinition.factory as() => T});
}
}) as never; }) as never;
return def as never; return def as never;
@ -615,11 +603,6 @@ export const ɵɵdefineDirective = ɵɵdefineComponent as any as<T>(directiveDef
/** The selectors that will be used to match nodes to this directive. */ /** The selectors that will be used to match nodes to this directive. */
selectors: CssSelectorList; selectors: CssSelectorList;
/**
* Factory method used to create an instance of directive.
*/
factory: FactoryFn<T>;
/** /**
* A map of input names. * A map of input names.
* *
@ -731,15 +714,13 @@ export function ɵɵdefinePipe<T>(pipeDef: {
/** Pipe class reference. Needed to extract pipe lifecycle hooks. */ /** Pipe class reference. Needed to extract pipe lifecycle hooks. */
type: Type<T>, type: Type<T>,
/** A factory for creating a pipe instance. */
factory: FactoryFn<T>,
/** Whether the pipe is pure. */ /** Whether the pipe is pure. */
pure?: boolean pure?: boolean
}): never { }): never {
return (<PipeDef<T>>{ return (<PipeDef<T>>{
type: pipeDef.type,
name: pipeDef.name, name: pipeDef.name,
factory: pipeDef.factory, factory: null,
pure: pipeDef.pure !== false, pure: pipeDef.pure !== false,
onDestroy: pipeDef.type.prototype.ngOnDestroy || null onDestroy: pipeDef.type.prototype.ngOnDestroy || null
}) as never; }) as never;
@ -752,25 +733,35 @@ export function ɵɵdefinePipe<T>(pipeDef: {
*/ */
export function getComponentDef<T>(type: any): ComponentDef<T>|null { export function getComponentDef<T>(type: any): ComponentDef<T>|null {
return (type as any)[NG_COMPONENT_DEF] || null; return type[NG_COMPONENT_DEF] || null;
} }
export function getDirectiveDef<T>(type: any): DirectiveDef<T>|null { export function getDirectiveDef<T>(type: any): DirectiveDef<T>|null {
return (type as any)[NG_DIRECTIVE_DEF] || null; return type[NG_DIRECTIVE_DEF] || null;
} }
export function getPipeDef<T>(type: any): PipeDef<T>|null { export function getPipeDef<T>(type: any): PipeDef<T>|null {
return (type as any)[NG_PIPE_DEF] || null; return type[NG_PIPE_DEF] || null;
} }
export function getBaseDef<T>(type: any): ɵɵBaseDef<T>|null { export function getBaseDef<T>(type: any): ɵɵBaseDef<T>|null {
return (type as any)[NG_BASE_DEF] || null; return type[NG_BASE_DEF] || null;
}
export function getFactoryDef<T>(type: any, throwNotFound: true): FactoryFn<T>;
export function getFactoryDef<T>(type: any): FactoryFn<T>|null;
export function getFactoryDef<T>(type: any, throwNotFound?: boolean): FactoryFn<T>|null {
const factoryFn = type[NG_FACTORY_DEF] || null;
if (!factoryFn && throwNotFound === true && ngDevMode) {
throw new Error(`Type ${stringify(type)} does not have 'ngFactoryDef' property.`);
}
return factoryFn;
} }
export function getNgModuleDef<T>(type: any, throwNotFound: true): NgModuleDef<T>; export function getNgModuleDef<T>(type: any, throwNotFound: true): NgModuleDef<T>;
export function getNgModuleDef<T>(type: any): NgModuleDef<T>|null; export function getNgModuleDef<T>(type: any): NgModuleDef<T>|null;
export function getNgModuleDef<T>(type: any, throwNotFound?: boolean): NgModuleDef<T>|null { export function getNgModuleDef<T>(type: any, throwNotFound?: boolean): NgModuleDef<T>|null {
const ngModuleDef = (type as any)[NG_MODULE_DEF] || null; const ngModuleDef = type[NG_MODULE_DEF] || null;
if (!ngModuleDef && throwNotFound === true) { if (!ngModuleDef && throwNotFound === true) {
throw new Error(`Type ${stringify(type)} does not have 'ngModuleDef' property.`); throw new Error(`Type ${stringify(type)} does not have 'ngModuleDef' property.`);
} }

View File

@ -15,7 +15,7 @@ import {InjectFlags} from '../di/interface/injector';
import {Type} from '../interface/type'; import {Type} from '../interface/type';
import {assertDefined, assertEqual} from '../util/assert'; import {assertDefined, assertEqual} from '../util/assert';
import {getComponentDef, getDirectiveDef, getPipeDef} from './definition'; import {getFactoryDef} from './definition';
import {NG_ELEMENT_ID} from './fields'; import {NG_ELEMENT_ID} from './fields';
import {DirectiveDef, FactoryFn} from './interfaces/definition'; import {DirectiveDef, FactoryFn} from './interfaces/definition';
import {NO_PARENT_INJECTOR, NodeInjectorFactory, PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags, TNODE, isFactory} from './interfaces/injector'; import {NO_PARENT_INJECTOR, NodeInjectorFactory, PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags, TNODE, isFactory} from './interfaces/injector';
@ -642,12 +642,10 @@ export function ɵɵgetFactoryOf<T>(type: Type<any>): FactoryFn<T>|null {
}) as any; }) as any;
} }
const def = getComponentDef<T>(typeAny) || getDirectiveDef<T>(typeAny) || // TODO(crisbeto): unify injectable factories with getFactory.
getPipeDef<T>(typeAny) || getInjectableDef<T>(typeAny) || getInjectorDef<T>(typeAny); const def = getInjectableDef<T>(typeAny) || getInjectorDef<T>(typeAny);
if (!def || def.factory === undefined) { const factory = def && def.factory || getFactoryDef<T>(typeAny);
return null; return factory || null;
}
return def.factory;
} }
/** /**

View File

@ -14,6 +14,7 @@ export const NG_PIPE_DEF = getClosureSafeProperty({ngPipeDef: getClosureSafeProp
export const NG_MODULE_DEF = getClosureSafeProperty({ngModuleDef: getClosureSafeProperty}); export const NG_MODULE_DEF = getClosureSafeProperty({ngModuleDef: getClosureSafeProperty});
export const NG_LOCALE_ID_DEF = getClosureSafeProperty({ngLocaleIdDef: getClosureSafeProperty}); export const NG_LOCALE_ID_DEF = getClosureSafeProperty({ngLocaleIdDef: getClosureSafeProperty});
export const NG_BASE_DEF = getClosureSafeProperty({ngBaseDef: getClosureSafeProperty}); export const NG_BASE_DEF = getClosureSafeProperty({ngBaseDef: getClosureSafeProperty});
export const NG_FACTORY_DEF = getClosureSafeProperty({ngFactoryDef: getClosureSafeProperty});
/** /**
* If a directive is diPublic, bloomAdd sets a property on the type with this constant as * If a directive is diPublic, bloomAdd sets a property on the type with this constant as

View File

@ -10,11 +10,12 @@ import {ɵɵdefineBase, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineNgMo
import {ɵɵInheritDefinitionFeature} from './features/inherit_definition_feature'; import {ɵɵInheritDefinitionFeature} from './features/inherit_definition_feature';
import {ɵɵNgOnChangesFeature} from './features/ng_onchanges_feature'; import {ɵɵNgOnChangesFeature} from './features/ng_onchanges_feature';
import {ɵɵProvidersFeature} from './features/providers_feature'; import {ɵɵProvidersFeature} from './features/providers_feature';
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveType, PipeDef, ɵɵBaseDef, ɵɵComponentDefWithMeta, ɵɵDirectiveDefWithMeta, ɵɵPipeDefWithMeta} from './interfaces/definition'; import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveType, PipeDef, ɵɵBaseDef, ɵɵComponentDefWithMeta, ɵɵDirectiveDefWithMeta, ɵɵFactoryDef, ɵɵPipeDefWithMeta} from './interfaces/definition';
import {getComponent, getDirectives, getHostElement, getRenderedText} from './util/discovery_utils'; import {getComponent, getDirectives, getHostElement, getRenderedText} from './util/discovery_utils';
export {ComponentFactory, ComponentFactoryResolver, ComponentRef, injectComponentFactoryResolver} from './component_ref'; export {ComponentFactory, ComponentFactoryResolver, ComponentRef, injectComponentFactoryResolver} from './component_ref';
export {ɵɵgetFactoryOf, ɵɵgetInheritedFactory} from './di'; export {ɵɵgetFactoryOf, ɵɵgetInheritedFactory} from './di';
// clang-format off // clang-format off
export { export {
detectChanges, detectChanges,
@ -205,6 +206,7 @@ export {
ɵɵBaseDef, ɵɵBaseDef,
ComponentDef, ComponentDef,
ɵɵComponentDefWithMeta, ɵɵComponentDefWithMeta,
ɵɵFactoryDef,
ComponentTemplate, ComponentTemplate,
ComponentType, ComponentType,
DirectiveDef, DirectiveDef,

View File

@ -15,6 +15,7 @@ import {createNamedArrayType} from '../../util/named_array_type';
import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../../util/ng_reflect'; import {normalizeDebugBindingName, normalizeDebugBindingValue} from '../../util/ng_reflect';
import {assertFirstTemplatePass, assertLView} from '../assert'; import {assertFirstTemplatePass, assertLView} from '../assert';
import {attachPatchData, getComponentViewByInstance} from '../context_discovery'; import {attachPatchData, getComponentViewByInstance} from '../context_discovery';
import {getFactoryDef} from '../definition';
import {diPublicInInjector, getNodeInjectable, getOrCreateNodeInjectorForNode} from '../di'; import {diPublicInInjector, getNodeInjectable, getOrCreateNodeInjectorForNode} from '../di';
import {throwMultipleComponentError} from '../errors'; import {throwMultipleComponentError} from '../errors';
import {executeCheckHooks, executeInitAndCheckHooks, incrementInitPhaseFlags, registerPreOrderHooks} from '../hooks'; import {executeCheckHooks, executeInitAndCheckHooks, incrementInitPhaseFlags, registerPreOrderHooks} from '../hooks';
@ -1028,7 +1029,7 @@ export function instantiateRootComponent<T>(
if (tView.firstTemplatePass) { if (tView.firstTemplatePass) {
if (def.providersResolver) def.providersResolver(def); if (def.providersResolver) def.providersResolver(def);
generateExpandoInstructionBlock(tView, rootTNode, 1); generateExpandoInstructionBlock(tView, rootTNode, 1);
baseResolveDirective(tView, viewData, def, def.factory); baseResolveDirective(tView, viewData, def);
} }
const directive = const directive =
getNodeInjectable(tView.data, viewData, viewData.length - 1, rootTNode as TElementNode); getNodeInjectable(tView.data, viewData, viewData.length - 1, rootTNode as TElementNode);
@ -1072,7 +1073,7 @@ export function resolveDirectives(
const def = directives[i] as DirectiveDef<any>; const def = directives[i] as DirectiveDef<any>;
const directiveDefIdx = tView.data.length; const directiveDefIdx = tView.data.length;
baseResolveDirective(tView, lView, def, def.factory); baseResolveDirective(tView, lView, def);
saveNameToExportMap(tView.data !.length - 1, def, exportsMap); saveNameToExportMap(tView.data !.length - 1, def, exportsMap);
@ -1311,9 +1312,9 @@ export function initNodeFlags(tNode: TNode, index: number, numberOfDirectives: n
tNode.providerIndexes = index; tNode.providerIndexes = index;
} }
function baseResolveDirective<T>( function baseResolveDirective<T>(tView: TView, viewData: LView, def: DirectiveDef<T>) {
tView: TView, viewData: LView, def: DirectiveDef<T>, directiveFactory: FactoryFn<T>) {
tView.data.push(def); tView.data.push(def);
const directiveFactory = def.factory || (def.factory = getFactoryDef(def.type, true));
const nodeInjectorFactory = new NodeInjectorFactory(directiveFactory, isComponentDef(def), null); const nodeInjectorFactory = new NodeInjectorFactory(directiveFactory, isComponentDef(def), null);
tView.blueprint.push(nodeInjectorFactory); tView.blueprint.push(nodeInjectorFactory);
viewData.push(nodeInjectorFactory); viewData.push(nodeInjectorFactory);

View File

@ -76,7 +76,10 @@ export interface ComponentType<T> extends Type<T> { ngComponentDef: never; }
* A subclass of `Type` which has a static `ngDirectiveDef`:`DirectiveDef` field making it * A subclass of `Type` which has a static `ngDirectiveDef`:`DirectiveDef` field making it
* consumable for rendering. * consumable for rendering.
*/ */
export interface DirectiveType<T> extends Type<T> { ngDirectiveDef: never; } export interface DirectiveType<T> extends Type<T> {
ngDirectiveDef: never;
ngFactoryDef: () => T;
}
export const enum DirectiveDefFlags {ContentQuery = 0b10} export const enum DirectiveDefFlags {ContentQuery = 0b10}
@ -175,9 +178,10 @@ export interface DirectiveDef<T> extends ɵɵBaseDef<T> {
readonly exportAs: string[]|null; readonly exportAs: string[]|null;
/** /**
* Factory function used to create a new directive instance. * Factory function used to create a new directive instance. Will be null initially.
* Populated when the factory is first requested by directive instantiation logic.
*/ */
factory: FactoryFn<T>; factory: FactoryFn<T>|null;
/* The following are lifecycle hooks for this component */ /* The following are lifecycle hooks for this component */
onChanges: (() => void)|null; onChanges: (() => void)|null;
@ -207,6 +211,11 @@ export type ɵɵComponentDefWithMeta<
T, Selector extends String, ExportAs extends string[], InputMap extends{[key: string]: string}, T, Selector extends String, ExportAs extends string[], InputMap extends{[key: string]: string},
OutputMap extends{[key: string]: string}, QueryFields extends string[]> = ComponentDef<T>; OutputMap extends{[key: string]: string}, QueryFields extends string[]> = ComponentDef<T>;
/**
* @codeGenApi
*/
export type ɵɵFactoryDef<T> = () => T;
/** /**
* Runtime link information for Components. * Runtime link information for Components.
* *
@ -329,6 +338,9 @@ export interface ComponentDef<T> extends DirectiveDef<T> {
* See: {@link definePipe} * See: {@link definePipe}
*/ */
export interface PipeDef<T> { export interface PipeDef<T> {
/** Token representing the pipe. */
type: Type<T>;
/** /**
* Pipe name. * Pipe name.
* *
@ -337,9 +349,10 @@ export interface PipeDef<T> {
readonly name: string; readonly name: string;
/** /**
* Factory function used to create a new pipe instance. * Factory function used to create a new pipe instance. Will be null initially.
* Populated when the factory is first requested by pipe instantiation logic.
*/ */
factory: FactoryFn<T>; factory: FactoryFn<T>|null;
/** /**
* Whether or not the pipe is pure. * Whether or not the pipe is pure.

View File

@ -7,7 +7,7 @@
*/ */
import {R3DirectiveMetadataFacade, getCompilerFacade} from '../../compiler/compiler_facade'; import {R3DirectiveMetadataFacade, getCompilerFacade} from '../../compiler/compiler_facade';
import {R3BaseMetadataFacade, R3ComponentMetadataFacade, R3QueryMetadataFacade} from '../../compiler/compiler_facade_interface'; import {CompilerFacade, R3BaseMetadataFacade, R3ComponentMetadataFacade, R3QueryMetadataFacade} from '../../compiler/compiler_facade_interface';
import {resolveForwardRef} from '../../di/forward_ref'; import {resolveForwardRef} from '../../di/forward_ref';
import {compileInjectable} from '../../di/jit/injectable'; import {compileInjectable} from '../../di/jit/injectable';
import {getReflect, reflectDependencies} from '../../di/jit/util'; import {getReflect, reflectDependencies} from '../../di/jit/util';
@ -18,7 +18,7 @@ import {componentNeedsResolution, maybeQueueResolutionOfComponentResources} from
import {ViewEncapsulation} from '../../metadata/view'; import {ViewEncapsulation} from '../../metadata/view';
import {getBaseDef, getComponentDef, getDirectiveDef} from '../definition'; import {getBaseDef, getComponentDef, getDirectiveDef} from '../definition';
import {EMPTY_ARRAY, EMPTY_OBJ} from '../empty'; import {EMPTY_ARRAY, EMPTY_OBJ} from '../empty';
import {NG_BASE_DEF, NG_COMPONENT_DEF, NG_DIRECTIVE_DEF} from '../fields'; import {NG_BASE_DEF, NG_COMPONENT_DEF, NG_DIRECTIVE_DEF, NG_FACTORY_DEF} from '../fields';
import {ComponentType} from '../interfaces/definition'; import {ComponentType} from '../interfaces/definition';
import {stringifyForError} from '../util/misc_utils'; import {stringifyForError} from '../util/misc_utils';
@ -38,43 +38,31 @@ import {flushModuleScopingQueueAsMuchAsPossible, patchComponentDefWithScope, tra
*/ */
export function compileComponent(type: Type<any>, metadata: Component): void { export function compileComponent(type: Type<any>, metadata: Component): void {
let ngComponentDef: any = null; let ngComponentDef: any = null;
let ngFactoryDef: any = null;
// Metadata may have resources which need to be resolved. // Metadata may have resources which need to be resolved.
maybeQueueResolutionOfComponentResources(type, metadata); maybeQueueResolutionOfComponentResources(type, metadata);
Object.defineProperty(type, NG_FACTORY_DEF, {
get: () => {
if (ngFactoryDef === null) {
const compiler = getCompilerFacade();
const meta = getComponentMetadata(compiler, type, metadata);
ngFactoryDef = compiler.compileFactory(
angularCoreEnv, `ng:///${type.name}/ngFactory.js`, meta.metadata);
}
return ngFactoryDef;
},
// Make the property configurable in dev mode to allow overriding in tests
configurable: !!ngDevMode,
});
Object.defineProperty(type, NG_COMPONENT_DEF, { Object.defineProperty(type, NG_COMPONENT_DEF, {
get: () => { get: () => {
const compiler = getCompilerFacade();
if (ngComponentDef === null) { if (ngComponentDef === null) {
if (componentNeedsResolution(metadata)) { const compiler = getCompilerFacade();
const error = [`Component '${type.name}' is not resolved:`]; const meta = getComponentMetadata(compiler, type, metadata);
if (metadata.templateUrl) { ngComponentDef = compiler.compileComponent(angularCoreEnv, meta.templateUrl, meta.metadata);
error.push(` - templateUrl: ${metadata.templateUrl}`);
}
if (metadata.styleUrls && metadata.styleUrls.length) {
error.push(` - styleUrls: ${JSON.stringify(metadata.styleUrls)}`);
}
error.push(`Did you run and wait for 'resolveComponentResources()'?`);
throw new Error(error.join('\n'));
}
const templateUrl = metadata.templateUrl || `ng:///${type.name}/template.html`;
const meta: R3ComponentMetadataFacade = {
...directiveMetadata(type, metadata),
typeSourceSpan: compiler.createParseSourceSpan('Component', type.name, templateUrl),
template: metadata.template || '',
preserveWhitespaces: metadata.preserveWhitespaces || false,
styles: metadata.styles || EMPTY_ARRAY,
animations: metadata.animations,
directives: [],
changeDetection: metadata.changeDetection,
pipes: new Map(),
encapsulation: metadata.encapsulation || ViewEncapsulation.Emulated,
interpolation: metadata.interpolation,
viewProviders: metadata.viewProviders || null,
};
if (meta.usesInheritance) {
addBaseDefToUndecoratedParents(type);
}
ngComponentDef = compiler.compileComponent(angularCoreEnv, templateUrl, meta);
// When NgModule decorator executed, we enqueued the module definition such that // When NgModule decorator executed, we enqueued the module definition such that
// it would only dequeue and add itself as module scope to all of its declarations, // it would only dequeue and add itself as module scope to all of its declarations,
@ -98,13 +86,46 @@ export function compileComponent(type: Type<any>, metadata: Component): void {
configurable: !!ngDevMode, configurable: !!ngDevMode,
}); });
// Add ngInjectableDef so components are reachable through the module injector by default // Add ngInjectableDef so components are reachable through the module injector by default
// This is mostly to support injecting components in tests. In real application code, // This is mostly to support injecting components in tests. In real application code,
// components should be retrieved through the node injector, so this isn't a problem. // components should be retrieved through the node injector, so this isn't a problem.
compileInjectable(type); compileInjectable(type);
} }
function getComponentMetadata(compiler: CompilerFacade, type: Type<any>, metadata: Component) {
if (componentNeedsResolution(metadata)) {
const error = [`Component '${type.name}' is not resolved:`];
if (metadata.templateUrl) {
error.push(` - templateUrl: ${metadata.templateUrl}`);
}
if (metadata.styleUrls && metadata.styleUrls.length) {
error.push(` - styleUrls: ${JSON.stringify(metadata.styleUrls)}`);
}
error.push(`Did you run and wait for 'resolveComponentResources()'?`);
throw new Error(error.join('\n'));
}
const templateUrl = metadata.templateUrl || `ng:///${type.name}/template.html`;
const meta: R3ComponentMetadataFacade = {
...directiveMetadata(type, metadata),
typeSourceSpan: compiler.createParseSourceSpan('Component', type.name, templateUrl),
template: metadata.template || '',
preserveWhitespaces: metadata.preserveWhitespaces || false,
styles: metadata.styles || EMPTY_ARRAY,
animations: metadata.animations,
directives: [],
changeDetection: metadata.changeDetection,
pipes: new Map(),
encapsulation: metadata.encapsulation || ViewEncapsulation.Emulated,
interpolation: metadata.interpolation,
viewProviders: metadata.viewProviders || null,
};
if (meta.usesInheritance) {
addBaseDefToUndecoratedParents(type);
}
return {metadata: meta, templateUrl};
}
function hasSelectorScope<T>(component: Type<T>): component is Type<T>& function hasSelectorScope<T>(component: Type<T>): component is Type<T>&
{ngSelectorScope: Type<any>} { {ngSelectorScope: Type<any>} {
return (component as{ngSelectorScope?: any}).ngSelectorScope !== undefined; return (component as{ngSelectorScope?: any}).ngSelectorScope !== undefined;
@ -119,21 +140,33 @@ function hasSelectorScope<T>(component: Type<T>): component is Type<T>&
*/ */
export function compileDirective(type: Type<any>, directive: Directive | null): void { export function compileDirective(type: Type<any>, directive: Directive | null): void {
let ngDirectiveDef: any = null; let ngDirectiveDef: any = null;
Object.defineProperty(type, NG_DIRECTIVE_DEF, { let ngFactoryDef: any = null;
Object.defineProperty(type, NG_FACTORY_DEF, {
get: () => { get: () => {
if (ngDirectiveDef === null) { if (ngFactoryDef === null) {
const name = type && type.name;
const sourceMapUrl = `ng:///${name}/ngDirectiveDef.js`;
const compiler = getCompilerFacade();
// `directive` can be null in the case of abstract directives as a base class // `directive` can be null in the case of abstract directives as a base class
// that use `@Directive()` with no selector. In that case, pass empty object to the // that use `@Directive()` with no selector. In that case, pass empty object to the
// `directiveMetadata` function instead of null. // `directiveMetadata` function instead of null.
const facade = directiveMetadata(type as ComponentType<any>, directive || {}); const meta = getDirectiveMetadata(type, directive || {});
facade.typeSourceSpan = compiler.createParseSourceSpan('Directive', name, sourceMapUrl); ngFactoryDef = getCompilerFacade().compileFactory(
if (facade.usesInheritance) { angularCoreEnv, `ng:///${type.name}/ngFactory.js`, meta.metadata);
addBaseDefToUndecoratedParents(type); }
} return ngFactoryDef;
ngDirectiveDef = compiler.compileDirective(angularCoreEnv, sourceMapUrl, facade); },
// Make the property configurable in dev mode to allow overriding in tests
configurable: !!ngDevMode,
});
Object.defineProperty(type, NG_DIRECTIVE_DEF, {
get: () => {
if (ngDirectiveDef === null) {
// `directive` can be null in the case of abstract directives as a base class
// that use `@Directive()` with no selector. In that case, pass empty object to the
// `directiveMetadata` function instead of null.
const meta = getDirectiveMetadata(type, directive || {});
ngDirectiveDef =
getCompilerFacade().compileDirective(angularCoreEnv, meta.sourceMapUrl, meta.metadata);
} }
return ngDirectiveDef; return ngDirectiveDef;
}, },
@ -147,6 +180,18 @@ export function compileDirective(type: Type<any>, directive: Directive | null):
compileInjectable(type); compileInjectable(type);
} }
function getDirectiveMetadata(type: Type<any>, metadata: Directive) {
const name = type && type.name;
const sourceMapUrl = `ng:///${name}/ngDirectiveDef.js`;
const compiler = getCompilerFacade();
const facade = directiveMetadata(type as ComponentType<any>, metadata);
facade.typeSourceSpan = compiler.createParseSourceSpan('Directive', name, sourceMapUrl);
if (facade.usesInheritance) {
addBaseDefToUndecoratedParents(type);
}
return {metadata: facade, sourceMapUrl};
}
export function extendsDirectlyFromObject(type: Type<any>): boolean { export function extendsDirectlyFromObject(type: Type<any>): boolean {
return Object.getPrototypeOf(type.prototype) === Object.prototype; return Object.getPrototypeOf(type.prototype) === Object.prototype;
} }

View File

@ -10,25 +10,33 @@ import {getCompilerFacade} from '../../compiler/compiler_facade';
import {reflectDependencies} from '../../di/jit/util'; import {reflectDependencies} from '../../di/jit/util';
import {Type} from '../../interface/type'; import {Type} from '../../interface/type';
import {Pipe} from '../../metadata/directives'; import {Pipe} from '../../metadata/directives';
import {NG_PIPE_DEF} from '../fields'; import {NG_FACTORY_DEF, NG_PIPE_DEF} from '../fields';
import {angularCoreEnv} from './environment'; import {angularCoreEnv} from './environment';
export function compilePipe(type: Type<any>, meta: Pipe): void { export function compilePipe(type: Type<any>, meta: Pipe): void {
let ngPipeDef: any = null; let ngPipeDef: any = null;
let ngFactoryDef: any = null;
Object.defineProperty(type, NG_FACTORY_DEF, {
get: () => {
if (ngFactoryDef === null) {
const metadata = getPipeMetadata(type, meta);
ngFactoryDef = getCompilerFacade().compileFactory(
angularCoreEnv, `ng:///${metadata.name}/ngFactory.js`, metadata, true);
}
return ngFactoryDef;
},
// Make the property configurable in dev mode to allow overriding in tests
configurable: !!ngDevMode,
});
Object.defineProperty(type, NG_PIPE_DEF, { Object.defineProperty(type, NG_PIPE_DEF, {
get: () => { get: () => {
if (ngPipeDef === null) { if (ngPipeDef === null) {
const typeName = type.name; const metadata = getPipeMetadata(type, meta);
ngPipeDef = ngPipeDef = getCompilerFacade().compilePipe(
getCompilerFacade().compilePipe(angularCoreEnv, `ng:///${typeName}/ngPipeDef.js`, { angularCoreEnv, `ng:///${metadata.name}/ngPipeDef.js`, metadata);
type: type,
typeArgumentCount: 0,
name: typeName,
deps: reflectDependencies(type),
pipeName: meta.name,
pure: meta.pure !== undefined ? meta.pure : true
});
} }
return ngPipeDef; return ngPipeDef;
}, },
@ -36,3 +44,14 @@ export function compilePipe(type: Type<any>, meta: Pipe): void {
configurable: !!ngDevMode, configurable: !!ngDevMode,
}); });
} }
function getPipeMetadata(type: Type<any>, meta: Pipe) {
return {
type: type,
typeArgumentCount: 0,
name: type.name,
deps: reflectDependencies(type),
pipeName: meta.name,
pure: meta.pure !== undefined ? meta.pure : true
};
}

View File

@ -9,6 +9,7 @@
import {WrappedValue} from '../change_detection/change_detection_util'; import {WrappedValue} from '../change_detection/change_detection_util';
import {PipeTransform} from '../change_detection/pipe_transform'; import {PipeTransform} from '../change_detection/pipe_transform';
import {getFactoryDef} from './definition';
import {store} from './instructions/all'; import {store} from './instructions/all';
import {PipeDef, PipeDefList} from './interfaces/definition'; import {PipeDef, PipeDefList} from './interfaces/definition';
import {BINDING_INDEX, HEADER_OFFSET, TVIEW} from './interfaces/view'; import {BINDING_INDEX, HEADER_OFFSET, TVIEW} from './interfaces/view';
@ -43,7 +44,8 @@ export function ɵɵpipe(index: number, pipeName: string): any {
pipeDef = tView.data[adjustedIndex] as PipeDef<any>; pipeDef = tView.data[adjustedIndex] as PipeDef<any>;
} }
const pipeInstance = pipeDef.factory(); const pipeFactory = pipeDef.factory || (pipeDef.factory = getFactoryDef(pipeDef.type, true));
const pipeInstance = pipeFactory();
store(index, pipeInstance); store(index, pipeInstance);
return pipeInstance; return pipeInstance;
} }

View File

@ -81,7 +81,7 @@
"name": "NG_ELEMENT_ID" "name": "NG_ELEMENT_ID"
}, },
{ {
"name": "NG_INJECTABLE_DEF" "name": "NG_FACTORY_DEF"
}, },
{ {
"name": "NG_PIPE_DEF" "name": "NG_PIPE_DEF"
@ -311,6 +311,9 @@
{ {
"name": "getElementDepthCount" "name": "getElementDepthCount"
}, },
{
"name": "getFactoryDef"
},
{ {
"name": "getHostNative" "name": "getHostNative"
}, },
@ -674,9 +677,6 @@
{ {
"name": "ɵɵdefineComponent" "name": "ɵɵdefineComponent"
}, },
{
"name": "ɵɵdefineInjectable"
},
{ {
"name": "ɵɵdefineInjector" "name": "ɵɵdefineInjector"
}, },
@ -698,4 +698,4 @@
{ {
"name": "ɵɵtext" "name": "ɵɵtext"
} }
] ]

View File

@ -72,7 +72,7 @@
"name": "NG_ELEMENT_ID" "name": "NG_ELEMENT_ID"
}, },
{ {
"name": "NG_INJECTABLE_DEF" "name": "NG_FACTORY_DEF"
}, },
{ {
"name": "NG_PIPE_DEF" "name": "NG_PIPE_DEF"
@ -248,6 +248,9 @@
{ {
"name": "getDirectiveDef" "name": "getDirectiveDef"
}, },
{
"name": "getFactoryDef"
},
{ {
"name": "getHostNative" "name": "getHostNative"
}, },
@ -485,10 +488,7 @@
{ {
"name": "ɵɵdefineComponent" "name": "ɵɵdefineComponent"
}, },
{
"name": "ɵɵdefineInjectable"
},
{ {
"name": "ɵɵtext" "name": "ɵɵtext"
} }
] ]

View File

@ -26,6 +26,9 @@
{ {
"name": "NEW_LINE" "name": "NEW_LINE"
}, },
{
"name": "NG_FACTORY_DEF"
},
{ {
"name": "NG_INJECTABLE_DEF" "name": "NG_INJECTABLE_DEF"
}, },
@ -116,6 +119,9 @@
{ {
"name": "getClosureSafeProperty" "name": "getClosureSafeProperty"
}, },
{
"name": "getFactoryDef"
},
{ {
"name": "getInheritedInjectableDef" "name": "getInheritedInjectableDef"
}, },
@ -209,4 +215,4 @@
{ {
"name": "ɵɵinject" "name": "ɵɵinject"
} }
] ]

View File

@ -134,6 +134,9 @@
{ {
"name": "NG_ELEMENT_ID" "name": "NG_ELEMENT_ID"
}, },
{
"name": "NG_FACTORY_DEF"
},
{ {
"name": "NG_INJECTABLE_DEF" "name": "NG_INJECTABLE_DEF"
}, },
@ -758,6 +761,9 @@
{ {
"name": "getErrorLogger" "name": "getErrorLogger"
}, },
{
"name": "getFactoryDef"
},
{ {
"name": "getGuardMask" "name": "getGuardMask"
}, },
@ -1451,4 +1457,4 @@
{ {
"name": "ɵɵtextInterpolate1" "name": "ɵɵtextInterpolate1"
} }
] ]

View File

@ -33,6 +33,7 @@ describe('iv perf test', () => {
it(`${iteration}. create ${count} divs in Render3`, () => { it(`${iteration}. create ${count} divs in Render3`, () => {
class Component { class Component {
static ngFactoryDef = () => new Component;
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: Component, type: Component,
selectors: [['div']], selectors: [['div']],
@ -59,8 +60,7 @@ describe('iv perf test', () => {
} }
ɵɵcontainerRefreshEnd(); ɵɵcontainerRefreshEnd();
} }
}, }
factory: () => new Component
}); });
} }

View File

@ -25,10 +25,10 @@ describe('change detection', () => {
doCheckCount = 0; doCheckCount = 0;
ngDoCheck(): void { this.doCheckCount++; } ngDoCheck(): void { this.doCheckCount++; }
static ngFactoryDef = () => new MyComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-comp']], selectors: [['my-comp']],
factory: () => new MyComponent(),
consts: 2, consts: 2,
vars: 1, vars: 1,
template: (rf: RenderFlags, ctx: MyComponent) => { template: (rf: RenderFlags, ctx: MyComponent) => {
@ -101,10 +101,10 @@ describe('change detection', () => {
onClick() {} onClick() {}
static ngFactoryDef = () => comp = new MyComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-comp']], selectors: [['my-comp']],
factory: () => comp = new MyComponent(),
consts: 2, consts: 2,
vars: 2, vars: 2,
/** /**
@ -140,10 +140,10 @@ describe('change detection', () => {
onClick() {} onClick() {}
static ngFactoryDef = () => comp = new ManualComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ManualComponent, type: ManualComponent,
selectors: [['manual-comp']], selectors: [['manual-comp']],
factory: () => comp = new ManualComponent(),
consts: 2, consts: 2,
vars: 2, vars: 2,
/** /**
@ -177,10 +177,10 @@ describe('change detection', () => {
class ManualApp { class ManualApp {
name: string = 'Nancy'; name: string = 'Nancy';
static ngFactoryDef = () => new ManualApp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ManualApp, type: ManualApp,
selectors: [['manual-app']], selectors: [['manual-app']],
factory: () => new ManualApp(),
consts: 1, consts: 1,
vars: 1, vars: 1,
/** <manual-comp [name]="name"></manual-comp> */ /** <manual-comp [name]="name"></manual-comp> */
@ -233,10 +233,10 @@ describe('change detection', () => {
doCheckCount = 0; doCheckCount = 0;
ngDoCheck(): void { this.doCheckCount++; } ngDoCheck(): void { this.doCheckCount++; }
static ngFactoryDef = () => parent = new ButtonParent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ButtonParent, type: ButtonParent,
selectors: [['button-parent']], selectors: [['button-parent']],
factory: () => parent = new ButtonParent(),
consts: 2, consts: 2,
vars: 1, vars: 1,
/** {{ doCheckCount }} - <manual-comp></manual-comp> */ /** {{ doCheckCount }} - <manual-comp></manual-comp> */
@ -311,10 +311,10 @@ describe('change detection', () => {
return 'works'; return 'works';
} }
static ngFactoryDef = () => new MyComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-comp']], selectors: [['my-comp']],
factory: () => new MyComponent(),
consts: 1, consts: 1,
vars: 1, vars: 1,
template: (rf: RenderFlags, ctx: MyComponent) => { template: (rf: RenderFlags, ctx: MyComponent) => {

View File

@ -18,9 +18,6 @@ export const NgTemplateOutlet: DirectiveType<NgTemplateOutletDef> = NgTemplateOu
NgForOf.ngDirectiveDef = ɵɵdefineDirective({ NgForOf.ngDirectiveDef = ɵɵdefineDirective({
type: NgForOfDef, type: NgForOfDef,
selectors: [['', 'ngForOf', '']], selectors: [['', 'ngForOf', '']],
factory: () => new NgForOfDef(
ɵɵdirectiveInject(ViewContainerRef as any), ɵɵdirectiveInject(TemplateRef as any),
ɵɵdirectiveInject(IterableDiffers)),
inputs: { inputs: {
ngForOf: 'ngForOf', ngForOf: 'ngForOf',
ngForTrackBy: 'ngForTrackBy', ngForTrackBy: 'ngForTrackBy',
@ -28,19 +25,26 @@ NgForOf.ngDirectiveDef = ɵɵdefineDirective({
} }
}); });
(NgIf as any).ngDirectiveDef = ɵɵdefineDirective({ NgForOf.ngFactoryDef = () => new NgForOfDef(
ɵɵdirectiveInject(ViewContainerRef as any), ɵɵdirectiveInject(TemplateRef as any),
ɵɵdirectiveInject(IterableDiffers));
NgIf.ngDirectiveDef = ɵɵdefineDirective({
type: NgIfDef, type: NgIfDef,
selectors: [['', 'ngIf', '']], selectors: [['', 'ngIf', '']],
factory: () => new NgIfDef(
ɵɵdirectiveInject(ViewContainerRef as any), ɵɵdirectiveInject(TemplateRef as any)),
inputs: {ngIf: 'ngIf', ngIfThen: 'ngIfThen', ngIfElse: 'ngIfElse'} inputs: {ngIf: 'ngIf', ngIfThen: 'ngIfThen', ngIfElse: 'ngIfElse'}
}); });
(NgTemplateOutlet as any).ngDirectiveDef = ɵɵdefineDirective({ NgIf.ngFactoryDef = () =>
new NgIfDef(ɵɵdirectiveInject(ViewContainerRef as any), ɵɵdirectiveInject(TemplateRef as any));
NgTemplateOutlet.ngDirectiveDef = ɵɵdefineDirective({
type: NgTemplateOutletDef, type: NgTemplateOutletDef,
selectors: [['', 'ngTemplateOutlet', '']], selectors: [['', 'ngTemplateOutlet', '']],
factory: () => new NgTemplateOutletDef(ɵɵdirectiveInject(ViewContainerRef as any)),
features: [ɵɵNgOnChangesFeature()], features: [ɵɵNgOnChangesFeature()],
inputs: inputs:
{ngTemplateOutlet: 'ngTemplateOutlet', ngTemplateOutletContext: 'ngTemplateOutletContext'} {ngTemplateOutlet: 'ngTemplateOutlet', ngTemplateOutletContext: 'ngTemplateOutletContext'}
}); });
NgTemplateOutlet.ngFactoryDef = () =>
new NgTemplateOutletDef(ɵɵdirectiveInject(ViewContainerRef as any));

View File

@ -20,13 +20,13 @@ describe('ComponentFactory', () => {
describe('constructor()', () => { describe('constructor()', () => {
it('should correctly populate default properties', () => { it('should correctly populate default properties', () => {
class TestComponent { class TestComponent {
static ngFactoryDef = () => new TestComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: TestComponent, type: TestComponent,
selectors: [['test', 'foo'], ['bar']], selectors: [['test', 'foo'], ['bar']],
consts: 0, consts: 0,
vars: 0, vars: 0,
template: () => undefined, template: () => undefined,
factory: () => new TestComponent(),
}); });
} }
@ -41,6 +41,7 @@ describe('ComponentFactory', () => {
it('should correctly populate defined properties', () => { it('should correctly populate defined properties', () => {
class TestComponent { class TestComponent {
static ngFactoryDef = () => new TestComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: TestComponent, type: TestComponent,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@ -49,7 +50,6 @@ describe('ComponentFactory', () => {
vars: 0, vars: 0,
template: () => undefined, template: () => undefined,
ngContentSelectors: ['*', 'a', 'b'], ngContentSelectors: ['*', 'a', 'b'],
factory: () => new TestComponent(),
inputs: { inputs: {
in1: 'in1', in1: 'in1',
in2: ['input-attr-2', 'in2'], in2: ['input-attr-2', 'in2'],
@ -89,6 +89,7 @@ describe('ComponentFactory', () => {
createRenderer3Spy = spyOn(domRendererFactory3, 'createRenderer').and.callThrough(); createRenderer3Spy = spyOn(domRendererFactory3, 'createRenderer').and.callThrough();
class TestComponent { class TestComponent {
static ngFactoryDef = () => new TestComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: TestComponent, type: TestComponent,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@ -96,7 +97,6 @@ describe('ComponentFactory', () => {
consts: 0, consts: 0,
vars: 0, vars: 0,
template: () => undefined, template: () => undefined,
factory: () => new TestComponent(),
}); });
} }

View File

@ -21,6 +21,7 @@ describe('component', () => {
increment() { this.count++; } increment() { this.count++; }
static ngFactoryDef = () => new CounterComponent;
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: CounterComponent, type: CounterComponent,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@ -36,7 +37,6 @@ describe('component', () => {
ɵɵtextBinding(ctx.count); ɵɵtextBinding(ctx.count);
} }
}, },
factory: () => new CounterComponent,
inputs: {count: 'count'}, inputs: {count: 'count'},
}); });
} }
@ -72,11 +72,11 @@ describe('component', () => {
} }
class MyComponent { class MyComponent {
constructor(public myService: MyService) {} constructor(public myService: MyService) {}
static ngFactoryDef = () => new MyComponent(ɵɵdirectiveInject(MyService));
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
selectors: [['my-component']], selectors: [['my-component']],
factory: () => new MyComponent(ɵɵdirectiveInject(MyService)),
consts: 1, consts: 1,
vars: 1, vars: 1,
template: function(fs: RenderFlags, ctx: MyComponent) { template: function(fs: RenderFlags, ctx: MyComponent) {
@ -117,10 +117,10 @@ describe('component', () => {
// @Input // @Input
name = ''; name = '';
static ngFactoryDef = () => new Comp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: Comp, type: Comp,
selectors: [['comp']], selectors: [['comp']],
factory: () => new Comp(),
consts: 1, consts: 1,
vars: 1, vars: 1,
template: (rf: RenderFlags, ctx: Comp) => { template: (rf: RenderFlags, ctx: Comp) => {
@ -172,15 +172,17 @@ it('should not invoke renderer destroy method for embedded views', () => {
class Comp { class Comp {
visible = true; visible = true;
static ngFactoryDef =
() => {
comp = new Comp();
return comp;
}
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: Comp, type: Comp,
selectors: [['comp']], selectors: [['comp']],
consts: 3, consts: 3,
vars: 1, vars: 1,
factory: () => {
comp = new Comp();
return comp;
},
directives: [NgIf], directives: [NgIf],
/** /**
* <div>Root view</div> * <div>Root view</div>
@ -248,6 +250,7 @@ describe('component with a container', () => {
class WrapperComponent { class WrapperComponent {
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
items !: string[]; items !: string[];
static ngFactoryDef = () => new WrapperComponent;
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: WrapperComponent, type: WrapperComponent,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@ -268,7 +271,6 @@ describe('component with a container', () => {
ɵɵcontainerRefreshEnd(); ɵɵcontainerRefreshEnd();
} }
}, },
factory: () => new WrapperComponent,
inputs: {items: 'items'} inputs: {items: 'items'}
}); });
} }
@ -326,11 +328,11 @@ describe('recursive components', () => {
ngOnDestroy() { events.push('destroy' + this.data.value); } ngOnDestroy() { events.push('destroy' + this.data.value); }
static ngFactoryDef = () => new TreeComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: TreeComponent, type: TreeComponent,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
selectors: [['tree-comp']], selectors: [['tree-comp']],
factory: () => new TreeComponent(),
consts: 3, consts: 3,
vars: 1, vars: 1,
template: (rf: RenderFlags, ctx: TreeComponent) => { template: (rf: RenderFlags, ctx: TreeComponent) => {
@ -393,11 +395,11 @@ describe('recursive components', () => {
ngOnDestroy() { events.push('destroy' + this.data.value); } ngOnDestroy() { events.push('destroy' + this.data.value); }
static ngFactoryDef = () => new NgIfTree();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: NgIfTree, type: NgIfTree,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
selectors: [['ng-if-tree']], selectors: [['ng-if-tree']],
factory: () => new NgIfTree(),
consts: 3, consts: 3,
vars: 3, vars: 3,
template: (rf: RenderFlags, ctx: NgIfTree) => { template: (rf: RenderFlags, ctx: NgIfTree) => {
@ -543,6 +545,7 @@ describe('recursive components', () => {
class TestInputsComponent { class TestInputsComponent {
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
minifiedName !: string; minifiedName !: string;
static ngFactoryDef = () => new TestInputsComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: TestInputsComponent, type: TestInputsComponent,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@ -550,7 +553,6 @@ describe('recursive components', () => {
inputs: {minifiedName: 'unminifiedName'}, inputs: {minifiedName: 'unminifiedName'},
consts: 0, consts: 0,
vars: 0, vars: 0,
factory: () => new TestInputsComponent(),
template: function(rf: RenderFlags, ctx: TestInputsComponent): void { template: function(rf: RenderFlags, ctx: TestInputsComponent): void {
// Template not needed for this test // Template not needed for this test
} }

View File

@ -692,15 +692,17 @@ describe('JS control flow', () => {
// Intentionally duplicating the templates in test below so we are // Intentionally duplicating the templates in test below so we are
// testing the behavior on firstTemplatePass for each of these tests // testing the behavior on firstTemplatePass for each of these tests
class Comp { class Comp {
static ngFactoryDef =
() => {
log.push('comp!');
return new Comp();
}
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: Comp, type: Comp,
selectors: [['comp']], selectors: [['comp']],
consts: 0, consts: 0,
vars: 0, vars: 0,
factory: () => {
log.push('comp!');
return new Comp();
},
template: function(rf: RenderFlags, ctx: Comp) {} template: function(rf: RenderFlags, ctx: Comp) {}
}); });
} }
@ -709,10 +711,10 @@ describe('JS control flow', () => {
condition = true; condition = true;
condition2 = true; condition2 = true;
static ngFactoryDef = () => new App();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: App, type: App,
selectors: [['app']], selectors: [['app']],
factory: () => new App(),
consts: 3, consts: 3,
vars: 0, vars: 0,
template: function(rf: RenderFlags, ctx: any) { template: function(rf: RenderFlags, ctx: any) {
@ -760,15 +762,17 @@ describe('JS control flow', () => {
// Intentionally duplicating the templates from above so we are // Intentionally duplicating the templates from above so we are
// testing the behavior on firstTemplatePass for each of these tests // testing the behavior on firstTemplatePass for each of these tests
class Comp { class Comp {
static ngFactoryDef =
() => {
log.push('comp!');
return new Comp();
}
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: Comp, type: Comp,
selectors: [['comp']], selectors: [['comp']],
consts: 0, consts: 0,
vars: 0, vars: 0,
factory: () => {
log.push('comp!');
return new Comp();
},
template: function(rf: RenderFlags, ctx: Comp) {} template: function(rf: RenderFlags, ctx: Comp) {}
}); });
} }
@ -777,10 +781,10 @@ describe('JS control flow', () => {
condition = false; condition = false;
condition2 = true; condition2 = true;
static ngFactoryDef = () => new App();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: App, type: App,
selectors: [['app']], selectors: [['app']],
factory: () => new App(),
consts: 3, consts: 3,
vars: 0, vars: 0,
template: function(rf: RenderFlags, ctx: any) { template: function(rf: RenderFlags, ctx: any) {

View File

@ -15,12 +15,12 @@ import {ComponentFixture} from './render_util';
describe('Debug Representation', () => { describe('Debug Representation', () => {
it('should generate a human readable version', () => { it('should generate a human readable version', () => {
class MyComponent { class MyComponent {
static ngFactoryDef = () => new MyComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-comp']], selectors: [['my-comp']],
vars: 0, vars: 0,
consts: 2, consts: 2,
factory: () => new MyComponent(),
template: function(rf: RenderFlags, ctx: MyComponent) { template: function(rf: RenderFlags, ctx: MyComponent) {
if (rf == RenderFlags.Create) { if (rf == RenderFlags.Create) {
ɵɵelementStart(0, 'div', ['id', '123']); ɵɵelementStart(0, 'div', ['id', '123']);

View File

@ -31,12 +31,9 @@ describe('di', () => {
value = 'DirB'; value = 'DirB';
constructor() { log.push(this.value); } constructor() { log.push(this.value); }
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => new DirB();
selectors: [['', 'dirB', '']], static ngDirectiveDef =
type: DirB, ɵɵdefineDirective({selectors: [['', 'dirB', '']], type: DirB, inputs: {value: 'value'}});
factory: () => new DirB(),
inputs: {value: 'value'}
});
} }
beforeEach(() => log = []); beforeEach(() => log = []);
@ -49,11 +46,8 @@ describe('di', () => {
class DirA { class DirA {
constructor(dir: DirB) { log.push(`DirA (dep: ${dir.value})`); } constructor(dir: DirB) { log.push(`DirA (dep: ${dir.value})`); }
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => new DirA(ɵɵdirectiveInject(DirB));
selectors: [['', 'dirA', '']], static ngDirectiveDef = ɵɵdefineDirective({selectors: [['', 'dirA', '']], type: DirA});
type: DirA,
factory: () => new DirA(ɵɵdirectiveInject(DirB))
});
} }
/** /**
@ -92,13 +86,11 @@ describe('di', () => {
this.injector = vcr.injector; this.injector = vcr.injector;
} }
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => new DirA(
type: DirA, ɵɵdirectiveInject(DirB), ɵɵdirectiveInject(ViewContainerRef as any))
selectors: [['', 'dirA', '']],
factory: static ngDirectiveDef =
() => new DirA(ɵɵdirectiveInject(DirB), ɵɵdirectiveInject(ViewContainerRef as any)), ɵɵdefineDirective({type: DirA, selectors: [['', 'dirA', '']], exportAs: ['dirA']});
exportAs: ['dirA']
});
} }
/** /**
@ -171,12 +163,9 @@ describe('di', () => {
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
value !: string; value !: string;
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => new DirB();
type: DirB, static ngDirectiveDef =
selectors: [['', 'dirB', '']], ɵɵdefineDirective({type: DirB, selectors: [['', 'dirB', '']], inputs: {value: 'dirB'}});
factory: () => new DirB(),
inputs: {value: 'dirB'}
});
} }
describe('Optional', () => { describe('Optional', () => {
@ -185,11 +174,13 @@ describe('di', () => {
class DirA { class DirA {
constructor(@Optional() public dirB: DirB|null) {} constructor(@Optional() public dirB: DirB|null) {}
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef =
type: DirA, () => {
selectors: [['', 'dirA', '']], dirA = new DirA(ɵɵdirectiveInject(DirB, InjectFlags.Optional));
factory: () => dirA = new DirA(ɵɵdirectiveInject(DirB, InjectFlags.Optional)) return dirA;
}); }
static ngDirectiveDef = ɵɵdefineDirective({type: DirA, selectors: [['', 'dirA', '']]});
} }
beforeEach(() => dirA = null); beforeEach(() => dirA = null);
@ -214,11 +205,8 @@ describe('di', () => {
class DirA { class DirA {
constructor(@Self() public dirB: DirB) {} constructor(@Self() public dirB: DirB) {}
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => dirA = new DirA(ɵɵdirectiveInject(DirB, InjectFlags.Self));
type: DirA, static ngDirectiveDef = ɵɵdefineDirective({type: DirA, selectors: [['', 'dirA', '']]});
selectors: [['', 'dirA', '']],
factory: () => dirA = new DirA(ɵɵdirectiveInject(DirB, InjectFlags.Self))
});
} }
const DirC = createDirective('dirC'); const DirC = createDirective('dirC');
@ -251,11 +239,8 @@ describe('di', () => {
class DirA { class DirA {
constructor(@Host() public dirB: DirB) {} constructor(@Host() public dirB: DirB) {}
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => dirA = new DirA(ɵɵdirectiveInject(DirB, InjectFlags.Host));
type: DirA, static ngDirectiveDef = ɵɵdefineDirective({type: DirA, selectors: [['', 'dirA', '']]});
selectors: [['', 'dirA', '']],
factory: () => dirA = new DirA(ɵɵdirectiveInject(DirB, InjectFlags.Host))
});
} }
/** /**
@ -319,10 +304,10 @@ describe('di', () => {
class MyComp { class MyComp {
constructor(public cdr: ChangeDetectorRef) {} constructor(public cdr: ChangeDetectorRef) {}
static ngFactoryDef = () => comp = new MyComp(ɵɵdirectiveInject(ChangeDetectorRef as any));
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: MyComp, type: MyComp,
selectors: [['my-comp']], selectors: [['my-comp']],
factory: () => comp = new MyComp(ɵɵdirectiveInject(ChangeDetectorRef as any)),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function(rf: RenderFlags, ctx: MyComp) { template: function(rf: RenderFlags, ctx: MyComp) {
@ -339,23 +324,24 @@ describe('di', () => {
constructor(public cdr: ChangeDetectorRef) { this.value = (cdr.constructor as any).name; } constructor(public cdr: ChangeDetectorRef) { this.value = (cdr.constructor as any).name; }
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef =
type: Directive, () => {
selectors: [['', 'dir', '']], dir = new Directive(ɵɵdirectiveInject(ChangeDetectorRef as any));
factory: () => dir = new Directive(ɵɵdirectiveInject(ChangeDetectorRef as any)), return dir;
exportAs: ['dir'] }
});
static ngDirectiveDef =
ɵɵdefineDirective({type: Directive, selectors: [['', 'dir', '']], exportAs: ['dir']});
} }
class DirectiveSameInstance { class DirectiveSameInstance {
constructor(public cdr: ChangeDetectorRef) {} constructor(public cdr: ChangeDetectorRef) {}
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => dirSameInstance =
type: DirectiveSameInstance, new DirectiveSameInstance(ɵɵdirectiveInject(ChangeDetectorRef as any))
selectors: [['', 'dirSame', '']],
factory: () => dirSameInstance = static ngDirectiveDef = ɵɵdefineDirective(
new DirectiveSameInstance(ɵɵdirectiveInject(ChangeDetectorRef as any)) {type: DirectiveSameInstance, selectors: [['', 'dirSame', '']]});
});
} }
const directives = [MyComp, Directive, DirectiveSameInstance]; const directives = [MyComp, Directive, DirectiveSameInstance];
@ -371,10 +357,10 @@ describe('di', () => {
constructor(public cdr: ChangeDetectorRef) {} constructor(public cdr: ChangeDetectorRef) {}
static ngFactoryDef = () => new MyApp(ɵɵdirectiveInject(ChangeDetectorRef as any));
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: MyApp, type: MyApp,
selectors: [['my-app']], selectors: [['my-app']],
factory: () => new MyApp(ɵɵdirectiveInject(ChangeDetectorRef as any)),
consts: 1, consts: 1,
vars: 0, vars: 0,
/** /**
@ -426,10 +412,10 @@ describe('di', () => {
class MyComp { class MyComp {
constructor(public renderer: Renderer2) {} constructor(public renderer: Renderer2) {}
static ngFactoryDef = () => new MyComp(ɵɵdirectiveInject(Renderer2 as any));
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: MyComp, type: MyComp,
selectors: [['my-comp']], selectors: [['my-comp']],
factory: () => new MyComp(ɵɵdirectiveInject(Renderer2 as any)),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function(rf: RenderFlags, ctx: MyComp) { template: function(rf: RenderFlags, ctx: MyComp) {
@ -537,24 +523,22 @@ describe('di', () => {
class ChildDirective { class ChildDirective {
value: string; value: string;
constructor(public parent: any) { this.value = (parent.constructor as any).name; } constructor(public parent: any) { this.value = (parent.constructor as any).name; }
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => new ChildDirective(ɵɵdirectiveInject(ParentDirective));
type: ChildDirective, static ngDirectiveDef = ɵɵdefineDirective(
selectors: [['', 'childDir', '']], {type: ChildDirective, selectors: [['', 'childDir', '']], exportAs: ['childDir']});
factory: () => new ChildDirective(ɵɵdirectiveInject(ParentDirective)),
exportAs: ['childDir']
});
} }
class Child2Directive { class Child2Directive {
value: boolean; value: boolean;
constructor(parent: any, child: ChildDirective) { this.value = parent === child.parent; } constructor(parent: any, child: ChildDirective) { this.value = parent === child.parent; }
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => new Child2Directive(
selectors: [['', 'child2Dir', '']], ɵɵdirectiveInject(ParentDirective), ɵɵdirectiveInject(ChildDirective))
type: Child2Directive,
factory: () => new Child2Directive( static ngDirectiveDef = ɵɵdefineDirective({
ɵɵdirectiveInject(ParentDirective), ɵɵdirectiveInject(ChildDirective)), selectors: [['', 'child2Dir', '']],
exportAs: ['child2Dir'] type: Child2Directive,
}); exportAs: ['child2Dir']
});
} }
/** /**

View File

@ -272,10 +272,10 @@ describe('instructions', () => {
class NestedLoops { class NestedLoops {
rows = [['a', 'b'], ['A', 'B'], ['a', 'b'], ['A', 'B']]; rows = [['a', 'b'], ['A', 'B'], ['a', 'b'], ['A', 'B']];
static ngFactoryDef = function ToDoAppComponent_Factory() { return new NestedLoops(); };
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: NestedLoops, type: NestedLoops,
selectors: [['nested-loops']], selectors: [['nested-loops']],
factory: function ToDoAppComponent_Factory() { return new NestedLoops(); },
consts: 1, consts: 1,
vars: 1, vars: 1,
template: function ToDoAppComponent_Template(rf: RenderFlags, ctx: NestedLoops) { template: function ToDoAppComponent_Template(rf: RenderFlags, ctx: NestedLoops) {

View File

@ -117,6 +117,8 @@ describe('render3 integration test', () => {
beforeTree !: Tree; beforeTree !: Tree;
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
afterTree !: Tree; afterTree !: Tree;
static ngFactoryDef = () => new ChildComponent;
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
selectors: [['child']], selectors: [['child']],
type: ChildComponent, type: ChildComponent,
@ -147,7 +149,6 @@ describe('render3 integration test', () => {
ɵɵcontainerRefreshEnd(); ɵɵcontainerRefreshEnd();
} }
}, },
factory: () => new ChildComponent,
inputs: {beforeTree: 'beforeTree', afterTree: 'afterTree'} inputs: {beforeTree: 'beforeTree', afterTree: 'afterTree'}
}); });
} }
@ -200,6 +201,7 @@ describe('render3 integration test', () => {
describe('component styles', () => { describe('component styles', () => {
it('should pass in the component styles directly into the underlying renderer', () => { it('should pass in the component styles directly into the underlying renderer', () => {
class StyledComp { class StyledComp {
static ngFactoryDef = () => new StyledComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: StyledComp, type: StyledComp,
styles: ['div { color: red; }'], styles: ['div { color: red; }'],
@ -207,7 +209,6 @@ describe('component styles', () => {
vars: 0, vars: 0,
encapsulation: 100, encapsulation: 100,
selectors: [['foo']], selectors: [['foo']],
factory: () => new StyledComp(),
template: (rf: RenderFlags, ctx: StyledComp) => { template: (rf: RenderFlags, ctx: StyledComp) => {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
ɵɵelement(0, 'div'); ɵɵelement(0, 'div');
@ -228,6 +229,7 @@ describe('component animations', () => {
const animB = {name: 'b'}; const animB = {name: 'b'};
class AnimComp { class AnimComp {
static ngFactoryDef = () => new AnimComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: AnimComp, type: AnimComp,
consts: 0, consts: 0,
@ -239,7 +241,6 @@ describe('component animations', () => {
], ],
}, },
selectors: [['foo']], selectors: [['foo']],
factory: () => new AnimComp(),
template: (rf: RenderFlags, ctx: AnimComp) => {} template: (rf: RenderFlags, ctx: AnimComp) => {}
}); });
} }
@ -255,6 +256,7 @@ describe('component animations', () => {
it('should include animations in the renderType data array even if the array is empty', () => { it('should include animations in the renderType data array even if the array is empty', () => {
class AnimComp { class AnimComp {
static ngFactoryDef = () => new AnimComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: AnimComp, type: AnimComp,
consts: 0, consts: 0,
@ -263,7 +265,6 @@ describe('component animations', () => {
animation: [], animation: [],
}, },
selectors: [['foo']], selectors: [['foo']],
factory: () => new AnimComp(),
template: (rf: RenderFlags, ctx: AnimComp) => {} template: (rf: RenderFlags, ctx: AnimComp) => {}
}); });
} }
@ -275,12 +276,12 @@ describe('component animations', () => {
it('should allow [@trigger] bindings to be picked up by the underlying renderer', () => { it('should allow [@trigger] bindings to be picked up by the underlying renderer', () => {
class AnimComp { class AnimComp {
static ngFactoryDef = () => new AnimComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: AnimComp, type: AnimComp,
consts: 1, consts: 1,
vars: 1, vars: 1,
selectors: [['foo']], selectors: [['foo']],
factory: () => new AnimComp(),
template: (rf: RenderFlags, ctx: AnimComp) => { template: (rf: RenderFlags, ctx: AnimComp) => {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
ɵɵelement(0, 'div', [AttributeMarker.Bindings, '@fooAnimation']); ɵɵelement(0, 'div', [AttributeMarker.Bindings, '@fooAnimation']);
@ -312,12 +313,12 @@ describe('component animations', () => {
it('should allow creation-level [@trigger] properties to be picked up by the underlying renderer', it('should allow creation-level [@trigger] properties to be picked up by the underlying renderer',
() => { () => {
class AnimComp { class AnimComp {
static ngFactoryDef = () => new AnimComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: AnimComp, type: AnimComp,
consts: 1, consts: 1,
vars: 1, vars: 1,
selectors: [['foo']], selectors: [['foo']],
factory: () => new AnimComp(),
template: (rf: RenderFlags, ctx: AnimComp) => { template: (rf: RenderFlags, ctx: AnimComp) => {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
ɵɵelement(0, 'div', ['@fooAnimation', '']); ɵɵelement(0, 'div', ['@fooAnimation', '']);
@ -345,9 +346,9 @@ describe('component animations', () => {
// it('should allow host binding animations to be picked up and rendered', () => { // it('should allow host binding animations to be picked up and rendered', () => {
// class ChildCompWithAnim { // class ChildCompWithAnim {
// static ngFactoryDef = () => new ChildCompWithAnim();
// static ngDirectiveDef = ɵɵdefineDirective({ // static ngDirectiveDef = ɵɵdefineDirective({
// type: ChildCompWithAnim, // type: ChildCompWithAnim,
// factory: () => new ChildCompWithAnim(),
// selectors: [['child-comp-with-anim']], // selectors: [['child-comp-with-anim']],
// hostBindings: function(rf: RenderFlags, ctx: any, elementIndex: number): void { // hostBindings: function(rf: RenderFlags, ctx: any, elementIndex: number): void {
// if (rf & RenderFlags.Update) { // if (rf & RenderFlags.Update) {
@ -360,12 +361,12 @@ describe('component animations', () => {
// } // }
// class ParentComp { // class ParentComp {
// static ngFactoryDef = () => new ParentComp();
// static ngComponentDef = ɵɵdefineComponent({ // static ngComponentDef = ɵɵdefineComponent({
// type: ParentComp, // type: ParentComp,
// consts: 1, // consts: 1,
// vars: 1, // vars: 1,
// selectors: [['foo']], // selectors: [['foo']],
// factory: () => new ParentComp(),
// template: (rf: RenderFlags, ctx: ParentComp) => { // template: (rf: RenderFlags, ctx: ParentComp) => {
// if (rf & RenderFlags.Create) { // if (rf & RenderFlags.Create) {
// ɵɵelement(0, 'child-comp-with-anim'); // ɵɵelement(0, 'child-comp-with-anim');
@ -390,10 +391,10 @@ describe('component animations', () => {
describe('element discovery', () => { describe('element discovery', () => {
it('should only monkey-patch immediate child nodes in a component', () => { it('should only monkey-patch immediate child nodes in a component', () => {
class StructuredComp { class StructuredComp {
static ngFactoryDef = () => new StructuredComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: StructuredComp, type: StructuredComp,
selectors: [['structured-comp']], selectors: [['structured-comp']],
factory: () => new StructuredComp(),
consts: 2, consts: 2,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: StructuredComp) => { template: (rf: RenderFlags, ctx: StructuredComp) => {
@ -422,10 +423,10 @@ describe('element discovery', () => {
it('should only monkey-patch immediate child nodes in a sub component', () => { it('should only monkey-patch immediate child nodes in a sub component', () => {
class ChildComp { class ChildComp {
static ngFactoryDef = () => new ChildComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ChildComp, type: ChildComp,
selectors: [['child-comp']], selectors: [['child-comp']],
factory: () => new ChildComp(),
consts: 3, consts: 3,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: ChildComp) => { template: (rf: RenderFlags, ctx: ChildComp) => {
@ -439,11 +440,11 @@ describe('element discovery', () => {
} }
class ParentComp { class ParentComp {
static ngFactoryDef = () => new ParentComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ParentComp, type: ParentComp,
selectors: [['parent-comp']], selectors: [['parent-comp']],
directives: [ChildComp], directives: [ChildComp],
factory: () => new ParentComp(),
consts: 2, consts: 2,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: ParentComp) => { template: (rf: RenderFlags, ctx: ParentComp) => {
@ -472,11 +473,11 @@ describe('element discovery', () => {
it('should only monkey-patch immediate child nodes in an embedded template container', () => { it('should only monkey-patch immediate child nodes in an embedded template container', () => {
class StructuredComp { class StructuredComp {
static ngFactoryDef = () => new StructuredComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: StructuredComp, type: StructuredComp,
selectors: [['structured-comp']], selectors: [['structured-comp']],
directives: [NgIf], directives: [NgIf],
factory: () => new StructuredComp(),
consts: 2, consts: 2,
vars: 1, vars: 1,
template: (rf: RenderFlags, ctx: StructuredComp) => { template: (rf: RenderFlags, ctx: StructuredComp) => {
@ -521,11 +522,11 @@ describe('element discovery', () => {
it('should return a context object from a given dom node', () => { it('should return a context object from a given dom node', () => {
class StructuredComp { class StructuredComp {
static ngFactoryDef = () => new StructuredComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: StructuredComp, type: StructuredComp,
selectors: [['structured-comp']], selectors: [['structured-comp']],
directives: [NgIf], directives: [NgIf],
factory: () => new StructuredComp(),
consts: 2, consts: 2,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: StructuredComp) => { template: (rf: RenderFlags, ctx: StructuredComp) => {
@ -559,10 +560,10 @@ describe('element discovery', () => {
it('should cache the element context on a element was pre-emptively monkey-patched', () => { it('should cache the element context on a element was pre-emptively monkey-patched', () => {
class StructuredComp { class StructuredComp {
static ngFactoryDef = () => new StructuredComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: StructuredComp, type: StructuredComp,
selectors: [['structured-comp']], selectors: [['structured-comp']],
factory: () => new StructuredComp(),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: StructuredComp) => { template: (rf: RenderFlags, ctx: StructuredComp) => {
@ -591,10 +592,10 @@ describe('element discovery', () => {
it('should cache the element context on an intermediate element that isn\'t pre-emptively monkey-patched', it('should cache the element context on an intermediate element that isn\'t pre-emptively monkey-patched',
() => { () => {
class StructuredComp { class StructuredComp {
static ngFactoryDef = () => new StructuredComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: StructuredComp, type: StructuredComp,
selectors: [['structured-comp']], selectors: [['structured-comp']],
factory: () => new StructuredComp(),
consts: 2, consts: 2,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: StructuredComp) => { template: (rf: RenderFlags, ctx: StructuredComp) => {
@ -624,10 +625,10 @@ describe('element discovery', () => {
it('should be able to pull in element context data even if the element is decorated using styling', it('should be able to pull in element context data even if the element is decorated using styling',
() => { () => {
class StructuredComp { class StructuredComp {
static ngFactoryDef = () => new StructuredComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: StructuredComp, type: StructuredComp,
selectors: [['structured-comp']], selectors: [['structured-comp']],
factory: () => new StructuredComp(),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: StructuredComp) => { template: (rf: RenderFlags, ctx: StructuredComp) => {
@ -677,10 +678,10 @@ describe('element discovery', () => {
</section> </section>
*/ */
class ProjectorComp { class ProjectorComp {
static ngFactoryDef = () => new ProjectorComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ProjectorComp, type: ProjectorComp,
selectors: [['projector-comp']], selectors: [['projector-comp']],
factory: () => new ProjectorComp(),
consts: 4, consts: 4,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: ProjectorComp) => { template: (rf: RenderFlags, ctx: ProjectorComp) => {
@ -700,11 +701,11 @@ describe('element discovery', () => {
} }
class ParentComp { class ParentComp {
static ngFactoryDef = () => new ParentComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ParentComp, type: ParentComp,
selectors: [['parent-comp']], selectors: [['parent-comp']],
directives: [ProjectorComp], directives: [ProjectorComp],
factory: () => new ParentComp(),
consts: 5, consts: 5,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: ParentComp) => { template: (rf: RenderFlags, ctx: ParentComp) => {
@ -774,10 +775,10 @@ describe('element discovery', () => {
it('should return `null` when an element context is retrieved that is a DOM node that was not created by Angular', it('should return `null` when an element context is retrieved that is a DOM node that was not created by Angular',
() => { () => {
class StructuredComp { class StructuredComp {
static ngFactoryDef = () => new StructuredComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: StructuredComp, type: StructuredComp,
selectors: [['structured-comp']], selectors: [['structured-comp']],
factory: () => new StructuredComp(),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: StructuredComp) => { template: (rf: RenderFlags, ctx: StructuredComp) => {
@ -801,10 +802,10 @@ describe('element discovery', () => {
it('should by default monkey-patch the bootstrap component with context details', () => { it('should by default monkey-patch the bootstrap component with context details', () => {
class StructuredComp { class StructuredComp {
static ngFactoryDef = () => new StructuredComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: StructuredComp, type: StructuredComp,
selectors: [['structured-comp']], selectors: [['structured-comp']],
factory: () => new StructuredComp(),
consts: 0, consts: 0,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: StructuredComp) => {} template: (rf: RenderFlags, ctx: StructuredComp) => {}
@ -840,35 +841,29 @@ describe('element discovery', () => {
let myDir3Instance: MyDir2|null = null; let myDir3Instance: MyDir2|null = null;
class MyDir1 { class MyDir1 {
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => myDir1Instance = new MyDir1();
type: MyDir1, static ngDirectiveDef =
selectors: [['', 'my-dir-1', '']], ɵɵdefineDirective({type: MyDir1, selectors: [['', 'my-dir-1', '']]});
factory: () => myDir1Instance = new MyDir1()
});
} }
class MyDir2 { class MyDir2 {
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => myDir2Instance = new MyDir2();
type: MyDir2, static ngDirectiveDef =
selectors: [['', 'my-dir-2', '']], ɵɵdefineDirective({type: MyDir2, selectors: [['', 'my-dir-2', '']]});
factory: () => myDir2Instance = new MyDir2()
});
} }
class MyDir3 { class MyDir3 {
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => myDir3Instance = new MyDir2();
type: MyDir3, static ngDirectiveDef =
selectors: [['', 'my-dir-3', '']], ɵɵdefineDirective({type: MyDir3, selectors: [['', 'my-dir-3', '']]});
factory: () => myDir3Instance = new MyDir2()
});
} }
class StructuredComp { class StructuredComp {
static ngFactoryDef = () => new StructuredComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: StructuredComp, type: StructuredComp,
selectors: [['structured-comp']], selectors: [['structured-comp']],
directives: [MyDir1, MyDir2, MyDir3], directives: [MyDir1, MyDir2, MyDir3],
factory: () => new StructuredComp(),
consts: 2, consts: 2,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: StructuredComp) => { template: (rf: RenderFlags, ctx: StructuredComp) => {
@ -929,26 +924,22 @@ describe('element discovery', () => {
let childComponentInstance: ChildComp|null = null; let childComponentInstance: ChildComp|null = null;
class MyDir1 { class MyDir1 {
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => myDir1Instance = new MyDir1();
type: MyDir1, static ngDirectiveDef =
selectors: [['', 'my-dir-1', '']], ɵɵdefineDirective({type: MyDir1, selectors: [['', 'my-dir-1', '']]});
factory: () => myDir1Instance = new MyDir1()
});
} }
class MyDir2 { class MyDir2 {
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => myDir2Instance = new MyDir2();
type: MyDir2, static ngDirectiveDef =
selectors: [['', 'my-dir-2', '']], ɵɵdefineDirective({type: MyDir2, selectors: [['', 'my-dir-2', '']]});
factory: () => myDir2Instance = new MyDir2()
});
} }
class ChildComp { class ChildComp {
static ngFactoryDef = () => childComponentInstance = new ChildComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ChildComp, type: ChildComp,
selectors: [['child-comp']], selectors: [['child-comp']],
factory: () => childComponentInstance = new ChildComp(),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: ChildComp) => { template: (rf: RenderFlags, ctx: ChildComp) => {
@ -960,11 +951,11 @@ describe('element discovery', () => {
} }
class ParentComp { class ParentComp {
static ngFactoryDef = () => new ParentComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ParentComp, type: ParentComp,
selectors: [['parent-comp']], selectors: [['parent-comp']],
directives: [ChildComp, MyDir1, MyDir2], directives: [ChildComp, MyDir1, MyDir2],
factory: () => new ParentComp(),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: ParentComp) => { template: (rf: RenderFlags, ctx: ParentComp) => {
@ -1022,10 +1013,10 @@ describe('element discovery', () => {
it('should monkey-patch sub components with the view data and then replace them with the context result once a lookup occurs', it('should monkey-patch sub components with the view data and then replace them with the context result once a lookup occurs',
() => { () => {
class ChildComp { class ChildComp {
static ngFactoryDef = () => new ChildComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ChildComp, type: ChildComp,
selectors: [['child-comp']], selectors: [['child-comp']],
factory: () => new ChildComp(),
consts: 3, consts: 3,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: ChildComp) => { template: (rf: RenderFlags, ctx: ChildComp) => {
@ -1039,11 +1030,11 @@ describe('element discovery', () => {
} }
class ParentComp { class ParentComp {
static ngFactoryDef = () => new ParentComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ParentComp, type: ParentComp,
selectors: [['parent-comp']], selectors: [['parent-comp']],
directives: [ChildComp], directives: [ChildComp],
factory: () => new ParentComp(),
consts: 2, consts: 2,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: ParentComp) => { template: (rf: RenderFlags, ctx: ParentComp) => {
@ -1083,10 +1074,10 @@ describe('element discovery', () => {
describe('sanitization', () => { describe('sanitization', () => {
it('should sanitize data using the provided sanitization interface', () => { it('should sanitize data using the provided sanitization interface', () => {
class SanitizationComp { class SanitizationComp {
static ngFactoryDef = () => new SanitizationComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: SanitizationComp, type: SanitizationComp,
selectors: [['sanitize-this']], selectors: [['sanitize-this']],
factory: () => new SanitizationComp(),
consts: 1, consts: 1,
vars: 1, vars: 1,
template: (rf: RenderFlags, ctx: SanitizationComp) => { template: (rf: RenderFlags, ctx: SanitizationComp) => {
@ -1126,10 +1117,10 @@ describe('sanitization', () => {
// @HostBinding() // @HostBinding()
cite: any = 'http://cite-dir-value'; cite: any = 'http://cite-dir-value';
static ngFactoryDef = () => hostBindingDir = new UnsafeUrlHostBindingDir();
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: UnsafeUrlHostBindingDir, type: UnsafeUrlHostBindingDir,
selectors: [['', 'unsafeUrlHostBindingDir', '']], selectors: [['', 'unsafeUrlHostBindingDir', '']],
factory: () => hostBindingDir = new UnsafeUrlHostBindingDir(),
hostBindings: (rf: RenderFlags, ctx: any, elementIndex: number) => { hostBindings: (rf: RenderFlags, ctx: any, elementIndex: number) => {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
ɵɵallocHostVars(1); ɵɵallocHostVars(1);
@ -1143,10 +1134,10 @@ describe('sanitization', () => {
} }
class SimpleComp { class SimpleComp {
static ngFactoryDef = () => new SimpleComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: SimpleComp, type: SimpleComp,
selectors: [['sanitize-this']], selectors: [['sanitize-this']],
factory: () => new SimpleComp(),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: SimpleComp) => { template: (rf: RenderFlags, ctx: SimpleComp) => {

View File

@ -15,7 +15,7 @@ import {ivyEnabled} from '@angular/core/src/ivy_switch';
import {ContentChild, ContentChildren, ViewChild, ViewChildren} from '@angular/core/src/metadata/di'; import {ContentChild, ContentChildren, ViewChild, ViewChildren} from '@angular/core/src/metadata/di';
import {Component, Directive, HostBinding, HostListener, Input, Output, Pipe} from '@angular/core/src/metadata/directives'; import {Component, Directive, HostBinding, HostListener, Input, Output, Pipe} from '@angular/core/src/metadata/directives';
import {NgModule, NgModuleDef} from '@angular/core/src/metadata/ng_module'; import {NgModule, NgModuleDef} from '@angular/core/src/metadata/ng_module';
import {ComponentDef, PipeDef} from '@angular/core/src/render3/interfaces/definition'; import {ComponentDef, FactoryFn, PipeDef} from '@angular/core/src/render3/interfaces/definition';
ivyEnabled && describe('render3 jit', () => { ivyEnabled && describe('render3 jit', () => {
@ -34,7 +34,7 @@ ivyEnabled && describe('render3 jit', () => {
const SomeCmpAny = SomeCmp as any; const SomeCmpAny = SomeCmp as any;
expect(SomeCmpAny.ngComponentDef).toBeDefined(); expect(SomeCmpAny.ngComponentDef).toBeDefined();
expect(SomeCmpAny.ngComponentDef.factory() instanceof SomeCmp).toBe(true); expect(SomeCmpAny.ngFactoryDef() instanceof SomeCmp).toBe(true);
}); });
it('compiles an injectable with a type provider', () => { it('compiles an injectable with a type provider', () => {
@ -242,9 +242,10 @@ ivyEnabled && describe('render3 jit', () => {
} }
const pipeDef = (P as any).ngPipeDef as PipeDef<P>; const pipeDef = (P as any).ngPipeDef as PipeDef<P>;
const pipeFactory = (P as any).ngFactoryDef as FactoryFn<P>;
expect(pipeDef.name).toBe('test-pipe'); expect(pipeDef.name).toBe('test-pipe');
expect(pipeDef.pure).toBe(false, 'pipe should not be pure'); expect(pipeDef.pure).toBe(false, 'pipe should not be pure');
expect(pipeDef.factory() instanceof P) expect(pipeFactory() instanceof P)
.toBe(true, 'factory() should create an instance of the pipe'); .toBe(true, 'factory() should create an instance of the pipe');
}); });

View File

@ -18,6 +18,7 @@ const INTERFACE_EXCEPTIONS = new Set<string>([
'ɵɵInjectorDef', 'ɵɵInjectorDef',
'ɵɵNgModuleDefWithMeta', 'ɵɵNgModuleDefWithMeta',
'ɵɵPipeDefWithMeta', 'ɵɵPipeDefWithMeta',
'ɵɵFactoryDef',
]); ]);
describe('r3 jit environment', () => { describe('r3 jit environment', () => {

View File

@ -56,12 +56,12 @@ describe('lifecycles', () => {
events.push(`${name}${this.val}`); events.push(`${name}${this.val}`);
} }
static ngFactoryDef = () => new Component();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: Component, type: Component,
selectors: [[name]], selectors: [[name]],
consts: consts, consts: consts,
vars: vars, vars: vars,
factory: () => new Component(),
inputs: {val: 'val'}, template, inputs: {val: 'val'}, template,
directives: directives directives: directives
}); });
@ -71,8 +71,8 @@ describe('lifecycles', () => {
class Directive { class Directive {
ngOnInit() { events.push('dir'); } ngOnInit() { events.push('dir'); }
static ngDirectiveDef = ɵɵdefineDirective( static ngFactoryDef = () => new Directive();
{type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()}); static ngDirectiveDef = ɵɵdefineDirective({type: Directive, selectors: [['', 'dir', '']]});
} }
const directives = [Comp, Parent, ProjectedComp, Directive, NgIf]; const directives = [Comp, Parent, ProjectedComp, Directive, NgIf];

View File

@ -27,6 +27,13 @@ describe('event listeners', () => {
onClick() { this.counter++; } onClick() { this.counter++; }
static ngFactoryDef =
() => {
let comp = new MyComp();
comps.push(comp);
return comp;
}
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: MyComp, type: MyComp,
selectors: [['comp']], selectors: [['comp']],
@ -42,11 +49,6 @@ describe('event listeners', () => {
} }
ɵɵelementEnd(); ɵɵelementEnd();
} }
},
factory: () => {
let comp = new MyComp();
comps.push(comp);
return comp;
} }
}); });
} }
@ -58,6 +60,13 @@ describe('event listeners', () => {
/* @HostListener('body:click') */ /* @HostListener('body:click') */
onBodyClick() { events.push('component - body:click'); } onBodyClick() { events.push('component - body:click'); }
static ngFactoryDef =
() => {
let comp = new MyCompWithGlobalListeners();
comps.push(comp);
return comp;
}
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: MyCompWithGlobalListeners, type: MyCompWithGlobalListeners,
selectors: [['comp']], selectors: [['comp']],
@ -68,11 +77,6 @@ describe('event listeners', () => {
ɵɵtext(0, 'Some text'); ɵɵtext(0, 'Some text');
} }
}, },
factory: () => {
let comp = new MyCompWithGlobalListeners();
comps.push(comp);
return comp;
},
hostBindings: function HostListenerDir_HostBindings( hostBindings: function HostListenerDir_HostBindings(
rf: RenderFlags, ctx: any, elIndex: number) { rf: RenderFlags, ctx: any, elIndex: number) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
@ -94,10 +98,12 @@ describe('event listeners', () => {
/* @HostListener('body:click') */ /* @HostListener('body:click') */
onBodyClick() { events.push('directive - body:click'); } onBodyClick() { events.push('directive - body:click'); }
static ngFactoryDef = function HostListenerDir_Factory() {
return new GlobalHostListenerDir();
};
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: GlobalHostListenerDir, type: GlobalHostListenerDir,
selectors: [['', 'hostListenerDir', '']], selectors: [['', 'hostListenerDir', '']],
factory: function HostListenerDir_Factory() { return new GlobalHostListenerDir(); },
hostBindings: function HostListenerDir_HostBindings( hostBindings: function HostListenerDir_HostBindings(
rf: RenderFlags, ctx: any, elIndex: number) { rf: RenderFlags, ctx: any, elIndex: number) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
@ -128,10 +134,10 @@ describe('event listeners', () => {
return this.handlerReturnValue; return this.handlerReturnValue;
} }
static ngFactoryDef = () => new PreventDefaultComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: PreventDefaultComp, type: PreventDefaultComp,
selectors: [['prevent-default-comp']], selectors: [['prevent-default-comp']],
factory: () => new PreventDefaultComp(),
consts: 2, consts: 2,
vars: 0, vars: 0,
/** <button (click)="onClick($event)">Click</button> */ /** <button (click)="onClick($event)">Click</button> */
@ -319,10 +325,10 @@ describe('event listeners', () => {
onClick() { this.counter++; } onClick() { this.counter++; }
static ngFactoryDef = () => new AppComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: AppComp, type: AppComp,
selectors: [['app-comp']], selectors: [['app-comp']],
factory: () => new AppComp(),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function(rf: RenderFlags, ctx: any) { template: function(rf: RenderFlags, ctx: any) {
@ -380,10 +386,10 @@ describe('event listeners', () => {
onClick(index: number) { this.counters[index]++; } onClick(index: number) { this.counters[index]++; }
static ngFactoryDef = () => new AppComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: AppComp, type: AppComp,
selectors: [['app-comp']], selectors: [['app-comp']],
factory: () => new AppComp(),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function(rf: RenderFlags, ctx: any) { template: function(rf: RenderFlags, ctx: any) {
@ -444,10 +450,10 @@ describe('event listeners', () => {
onClick(index: number) { this.counters[index]++; } onClick(index: number) { this.counters[index]++; }
static ngFactoryDef = () => new AppComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: AppComp, type: AppComp,
selectors: [['app-comp']], selectors: [['app-comp']],
factory: () => new AppComp(),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: function(rf: RenderFlags, ctx: any) { template: function(rf: RenderFlags, ctx: any) {
@ -523,6 +529,7 @@ describe('event listeners', () => {
/* @HostListener('click') */ /* @HostListener('click') */
onClick() { events.push('click!'); } onClick() { events.push('click!'); }
static ngFactoryDef = () => { return new MyComp(); };
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: MyComp, type: MyComp,
selectors: [['comp']], selectors: [['comp']],
@ -533,7 +540,6 @@ describe('event listeners', () => {
ɵɵtext(0, 'Some text'); ɵɵtext(0, 'Some text');
} }
}, },
factory: () => { return new MyComp(); },
hostBindings: function HostListenerDir_HostBindings( hostBindings: function HostListenerDir_HostBindings(
rf: RenderFlags, ctx: any, elIndex: number) { rf: RenderFlags, ctx: any, elIndex: number) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
@ -574,10 +580,10 @@ describe('event listeners', () => {
/* @HostListener('click') */ /* @HostListener('click') */
onClick() { events.push('click!'); } onClick() { events.push('click!'); }
static ngFactoryDef = function HostListenerDir_Factory() { return new HostListenerDir(); };
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: HostListenerDir, type: HostListenerDir,
selectors: [['', 'hostListenerDir', '']], selectors: [['', 'hostListenerDir', '']],
factory: function HostListenerDir_Factory() { return new HostListenerDir(); },
hostBindings: function HostListenerDir_HostBindings( hostBindings: function HostListenerDir_HostBindings(
rf: RenderFlags, ctx: any, elIndex: number) { rf: RenderFlags, ctx: any, elIndex: number) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
@ -626,6 +632,7 @@ describe('event listeners', () => {
onClick(a: any, b: any) { this.counter += a + b; } onClick(a: any, b: any) { this.counter += a + b; }
static ngFactoryDef = () => new MyComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: MyComp, type: MyComp,
selectors: [['comp']], selectors: [['comp']],
@ -641,8 +648,7 @@ describe('event listeners', () => {
} }
ɵɵelementEnd(); ɵɵelementEnd();
} }
}, }
factory: () => new MyComp()
}); });
} }
@ -907,10 +913,10 @@ describe('event listeners', () => {
onClick(comp: any) { this.comp = comp; } onClick(comp: any) { this.comp = comp; }
static ngFactoryDef = () => new App();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: App, type: App,
selectors: [['app']], selectors: [['app']],
factory: () => new App(),
consts: 3, consts: 3,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: App) => { template: (rf: RenderFlags, ctx: App) => {

View File

@ -21,13 +21,13 @@ describe('outputs', () => {
change = new EventEmitter(); change = new EventEmitter();
resetStream = new EventEmitter(); resetStream = new EventEmitter();
static ngFactoryDef = () => buttonToggle = new ButtonToggle();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ButtonToggle, type: ButtonToggle,
selectors: [['button-toggle']], selectors: [['button-toggle']],
template: function(rf: RenderFlags, ctx: any) {}, template: function(rf: RenderFlags, ctx: any) {},
consts: 0, consts: 0,
vars: 0, vars: 0,
factory: () => buttonToggle = new ButtonToggle(),
outputs: {change: 'change', resetStream: 'reset'} outputs: {change: 'change', resetStream: 'reset'}
}); });
} }
@ -37,12 +37,9 @@ describe('outputs', () => {
class OtherDir { class OtherDir {
changeStream = new EventEmitter(); changeStream = new EventEmitter();
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => otherDir = new OtherDir;
type: OtherDir, static ngDirectiveDef = ɵɵdefineDirective(
selectors: [['', 'otherDir', '']], {type: OtherDir, selectors: [['', 'otherDir', '']], outputs: {changeStream: 'change'}});
factory: () => otherDir = new OtherDir,
outputs: {changeStream: 'change'}
});
} }

View File

@ -29,12 +29,8 @@ describe('pipe', () => {
class WrappingPipe implements PipeTransform { class WrappingPipe implements PipeTransform {
transform(value: any) { return new WrappedValue('Bar'); } transform(value: any) { return new WrappedValue('Bar'); }
static ngPipeDef = ɵɵdefinePipe({ static ngFactoryDef = function WrappingPipe_Factory() { return new WrappingPipe(); };
name: 'wrappingPipe', static ngPipeDef = ɵɵdefinePipe({name: 'wrappingPipe', type: WrappingPipe, pure: false});
type: WrappingPipe,
factory: function WrappingPipe_Factory() { return new WrappingPipe(); },
pure: false
});
} }
function createTemplate() { function createTemplate() {

View File

@ -866,10 +866,12 @@ describe('providers', () => {
class Repeated { class Repeated {
constructor(private s: String, private n: Number) {} constructor(private s: String, private n: Number) {}
static ngFactoryDef =
() => { return new Repeated(ɵɵdirectiveInject(String), ɵɵdirectiveInject(Number)); }
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: Repeated, type: Repeated,
selectors: [['repeated']], selectors: [['repeated']],
factory: () => new Repeated(ɵɵdirectiveInject(String), ɵɵdirectiveInject(Number)),
consts: 2, consts: 2,
vars: 2, vars: 2,
template: function(fs: RenderFlags, ctx: Repeated) { template: function(fs: RenderFlags, ctx: Repeated) {
@ -898,10 +900,10 @@ describe('providers', () => {
[{provide: String, useValue: 'foo'}, {provide: Number, useValue: 2, multi: true}], [{provide: String, useValue: 'foo'}, {provide: Number, useValue: 2, multi: true}],
}) })
class ComponentWithProviders { class ComponentWithProviders {
static ngFactoryDef = () => new ComponentWithProviders();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ComponentWithProviders, type: ComponentWithProviders,
selectors: [['component-with-providers']], selectors: [['component-with-providers']],
factory: () => new ComponentWithProviders(),
consts: 2, consts: 2,
vars: 0, vars: 0,
template: function(fs: RenderFlags, ctx: ComponentWithProviders) { template: function(fs: RenderFlags, ctx: ComponentWithProviders) {
@ -951,10 +953,12 @@ describe('providers', () => {
class Repeated { class Repeated {
constructor(private s: String, private n: Number) {} constructor(private s: String, private n: Number) {}
static ngFactoryDef =
() => { return new Repeated(ɵɵdirectiveInject(String), ɵɵdirectiveInject(Number)); }
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: Repeated, type: Repeated,
selectors: [['repeated']], selectors: [['repeated']],
factory: () => new Repeated(ɵɵdirectiveInject(String), ɵɵdirectiveInject(Number)),
consts: 2, consts: 2,
vars: 2, vars: 2,
template: function(fs: RenderFlags, ctx: Repeated) { template: function(fs: RenderFlags, ctx: Repeated) {
@ -986,10 +990,10 @@ describe('providers', () => {
viewProviders: [{provide: toString, useValue: 'foo'}], viewProviders: [{provide: toString, useValue: 'foo'}],
}) })
class ComponentWithProviders { class ComponentWithProviders {
static ngFactoryDef = () => new ComponentWithProviders();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ComponentWithProviders, type: ComponentWithProviders,
selectors: [['component-with-providers']], selectors: [['component-with-providers']],
factory: () => new ComponentWithProviders(),
consts: 2, consts: 2,
vars: 0, vars: 0,
template: function(fs: RenderFlags, ctx: ComponentWithProviders) { template: function(fs: RenderFlags, ctx: ComponentWithProviders) {
@ -1035,10 +1039,10 @@ describe('providers', () => {
class EmbeddedComponent { class EmbeddedComponent {
constructor(private s: String) {} constructor(private s: String) {}
static ngFactoryDef = () => new EmbeddedComponent(ɵɵdirectiveInject(String));
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: EmbeddedComponent, type: EmbeddedComponent,
selectors: [['embedded-cmp']], selectors: [['embedded-cmp']],
factory: () => new EmbeddedComponent(ɵɵdirectiveInject(String)),
consts: 1, consts: 1,
vars: 1, vars: 1,
template: (rf: RenderFlags, cmp: EmbeddedComponent) => { template: (rf: RenderFlags, cmp: EmbeddedComponent) => {
@ -1057,22 +1061,23 @@ describe('providers', () => {
class HostComponent { class HostComponent {
constructor(public vcref: ViewContainerRef, public cfr: ComponentFactoryResolver) {} constructor(public vcref: ViewContainerRef, public cfr: ComponentFactoryResolver) {}
static ngComponentDef = ɵɵdefineComponent({ static ngFactoryDef = () => hostComponent = new HostComponent(
type: HostComponent, ɵɵdirectiveInject(ViewContainerRef as any), injectComponentFactoryResolver())
selectors: [['host-cmp']],
factory: () => hostComponent = new HostComponent( static ngComponentDef = ɵɵdefineComponent({
ɵɵdirectiveInject(ViewContainerRef as any), injectComponentFactoryResolver()), type: HostComponent,
consts: 1, selectors: [['host-cmp']],
vars: 0, consts: 1,
template: (rf: RenderFlags, cmp: HostComponent) => { vars: 0,
if (rf & RenderFlags.Create) { template: (rf: RenderFlags, cmp: HostComponent) => {
ɵɵtext(0, 'foo'); if (rf & RenderFlags.Create) {
} ɵɵtext(0, 'foo');
}, }
features: [ },
ɵɵProvidersFeature([{provide: String, useValue: 'From host component'}]), features: [
], ɵɵProvidersFeature([{provide: String, useValue: 'From host component'}]),
}); ],
});
} }
@Component({ @Component({
@ -1082,10 +1087,10 @@ describe('providers', () => {
class AppComponent { class AppComponent {
constructor() {} constructor() {}
static ngFactoryDef = () => new AppComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: AppComponent, type: AppComponent,
selectors: [['app-cmp']], selectors: [['app-cmp']],
factory: () => new AppComponent(),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: (rf: RenderFlags, cmp: AppComponent) => { template: (rf: RenderFlags, cmp: AppComponent) => {
@ -1244,10 +1249,10 @@ describe('providers', () => {
class MyComponent { class MyComponent {
constructor() {} constructor() {}
static ngFactoryDef = () => new MyComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-cmp']], selectors: [['my-cmp']],
factory: () => new MyComponent(),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: (rf: RenderFlags, cmp: MyComponent) => { template: (rf: RenderFlags, cmp: MyComponent) => {
@ -1271,10 +1276,10 @@ describe('providers', () => {
class AppComponent { class AppComponent {
constructor() {} constructor() {}
static ngFactoryDef = () => new AppComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: AppComponent, type: AppComponent,
selectors: [['app-cmp']], selectors: [['app-cmp']],
factory: () => new AppComponent(),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: (rf: RenderFlags, cmp: AppComponent) => { template: (rf: RenderFlags, cmp: AppComponent) => {
@ -1334,10 +1339,12 @@ describe('providers', () => {
class MyComponent { class MyComponent {
constructor(foo: InjectableWithLifeCycleHooks) {} constructor(foo: InjectableWithLifeCycleHooks) {}
static ngFactoryDef =
() => { return new MyComponent(ɵɵdirectiveInject(InjectableWithLifeCycleHooks)); }
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: MyComponent, type: MyComponent,
selectors: [['my-comp']], selectors: [['my-comp']],
factory: () => new MyComponent(ɵɵdirectiveInject(InjectableWithLifeCycleHooks)),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: MyComponent) => { template: (rf: RenderFlags, ctx: MyComponent) => {
@ -1361,10 +1368,10 @@ describe('providers', () => {
class App { class App {
public condition = true; public condition = true;
static ngFactoryDef = () => new App();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: App, type: App,
selectors: [['app-cmp']], selectors: [['app-cmp']],
factory: () => new App(),
consts: 2, consts: 2,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: App) => { template: (rf: RenderFlags, ctx: App) => {
@ -1436,40 +1443,40 @@ function expectProvidersScenario(defs: {
} }
class ViewChildComponent { class ViewChildComponent {
static ngFactoryDef = () => testComponentInjection(defs.viewChild, new ViewChildComponent());
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ViewChildComponent, type: ViewChildComponent,
selectors: [['view-child']], selectors: [['view-child']],
consts: 1, consts: 1,
vars: 0, vars: 0,
factory: () => testComponentInjection(defs.viewChild, new ViewChildComponent()),
template: function(fs: RenderFlags, ctx: ViewChildComponent) { template: function(fs: RenderFlags, ctx: ViewChildComponent) {
if (fs & RenderFlags.Create) { if (fs & RenderFlags.Create) {
ɵɵtext(0, 'view-child'); ɵɵtext(0, 'view-child');
} }
}, },
features: defs.viewChild && features: defs.viewChild &&
[ [ɵɵProvidersFeature(defs.viewChild.providers || [], defs.viewChild.viewProviders || [])]
ɵɵProvidersFeature(defs.viewChild.providers || [], defs.viewChild.viewProviders || []),
],
}); });
} }
class ViewChildDirective { class ViewChildDirective {
static ngFactoryDef = () => testDirectiveInjection(defs.viewChild, new ViewChildDirective());
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: ViewChildDirective, type: ViewChildDirective,
selectors: [['view-child']], selectors: [['view-child']],
factory: () => testDirectiveInjection(defs.viewChild, new ViewChildDirective()),
features: defs.viewChild && [ɵɵProvidersFeature(defs.viewChild.directiveProviders || [])], features: defs.viewChild && [ɵɵProvidersFeature(defs.viewChild.directiveProviders || [])],
}); });
} }
class ContentChildComponent { class ContentChildComponent {
static ngFactoryDef =
() => { return testComponentInjection(defs.contentChild, new ContentChildComponent()); }
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ContentChildComponent, type: ContentChildComponent,
selectors: [['content-child']], selectors: [['content-child']],
consts: 1, consts: 1,
vars: 0, vars: 0,
factory: () => testComponentInjection(defs.contentChild, new ContentChildComponent()),
template: function(fs: RenderFlags, ctx: ParentComponent) { template: function(fs: RenderFlags, ctx: ParentComponent) {
if (fs & RenderFlags.Create) { if (fs & RenderFlags.Create) {
ɵɵtext(0, 'content-child'); ɵɵtext(0, 'content-child');
@ -1482,10 +1489,12 @@ function expectProvidersScenario(defs: {
} }
class ContentChildDirective { class ContentChildDirective {
static ngFactoryDef =
() => { return testDirectiveInjection(defs.contentChild, new ContentChildDirective()); }
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: ContentChildDirective, type: ContentChildDirective,
selectors: [['content-child']], selectors: [['content-child']],
factory: () => testDirectiveInjection(defs.contentChild, new ContentChildDirective()),
features: features:
defs.contentChild && [ɵɵProvidersFeature(defs.contentChild.directiveProviders || [])], defs.contentChild && [ɵɵProvidersFeature(defs.contentChild.directiveProviders || [])],
}); });
@ -1493,12 +1502,12 @@ function expectProvidersScenario(defs: {
class ParentComponent { class ParentComponent {
static ngFactoryDef = () => testComponentInjection(defs.parent, new ParentComponent());
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ParentComponent, type: ParentComponent,
selectors: [['parent']], selectors: [['parent']],
consts: 1, consts: 1,
vars: 0, vars: 0,
factory: () => testComponentInjection(defs.parent, new ParentComponent()),
template: function(fs: RenderFlags, ctx: ParentComponent) { template: function(fs: RenderFlags, ctx: ParentComponent) {
if (fs & RenderFlags.Create) { if (fs & RenderFlags.Create) {
ɵɵelement(0, 'view-child'); ɵɵelement(0, 'view-child');
@ -1511,31 +1520,31 @@ function expectProvidersScenario(defs: {
} }
class ParentDirective { class ParentDirective {
static ngFactoryDef = () => testDirectiveInjection(defs.parent, new ParentDirective());
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: ParentDirective, type: ParentDirective,
selectors: [['parent']], selectors: [['parent']],
factory: () => testDirectiveInjection(defs.parent, new ParentDirective()),
features: defs.parent && [ɵɵProvidersFeature(defs.parent.directiveProviders || [])], features: defs.parent && [ɵɵProvidersFeature(defs.parent.directiveProviders || [])],
}); });
} }
class ParentDirective2 { class ParentDirective2 {
static ngFactoryDef = () => testDirectiveInjection(defs.parent, new ParentDirective2());
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: ParentDirective2, type: ParentDirective2,
selectors: [['parent']], selectors: [['parent']],
factory: () => testDirectiveInjection(defs.parent, new ParentDirective2()),
features: defs.parent && [ɵɵProvidersFeature(defs.parent.directive2Providers || [])], features: defs.parent && [ɵɵProvidersFeature(defs.parent.directive2Providers || [])],
}); });
} }
class App { class App {
static ngFactoryDef = () => testComponentInjection(defs.app, new App());
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: App, type: App,
selectors: [['app']], selectors: [['app']],
consts: 2, consts: 2,
vars: 0, vars: 0,
factory: () => testComponentInjection(defs.app, new App()),
template: function(fs: RenderFlags, ctx: App) { template: function(fs: RenderFlags, ctx: App) {
if (fs & RenderFlags.Create) { if (fs & RenderFlags.Create) {
ɵɵelementStart(0, 'parent'); ɵɵelementStart(0, 'parent');

View File

@ -19,10 +19,10 @@ describe('object literals', () => {
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
config !: {[key: string]: any}; config !: {[key: string]: any};
static ngFactoryDef = function ObjectComp_Factory() { return objectComp = new ObjectComp(); };
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ObjectComp, type: ObjectComp,
selectors: [['object-comp']], selectors: [['object-comp']],
factory: function ObjectComp_Factory() { return objectComp = new ObjectComp(); },
consts: 0, consts: 0,
vars: 1, vars: 1,
template: function ObjectComp_Template() {}, template: function ObjectComp_Template() {},

View File

@ -217,12 +217,12 @@ describe('query', () => {
class MyDirective { class MyDirective {
constructor(public service: Service) {} constructor(public service: Service) {}
static ngFactoryDef = function MyDirective_Factory() {
return directive = new MyDirective(ɵɵdirectiveInject(Service));
};
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: MyDirective, type: MyDirective,
selectors: [['', 'myDir', '']], selectors: [['', 'myDir', '']],
factory: function MyDirective_Factory() {
return directive = new MyDirective(ɵɵdirectiveInject(Service));
},
features: [ɵɵProvidersFeature([Service, {provide: Alias, useExisting: Service}])], features: [ɵɵProvidersFeature([Service, {provide: Alias, useExisting: Service}])],
}); });
} }
@ -245,12 +245,12 @@ describe('query', () => {
service?: Service; service?: Service;
alias?: Alias; alias?: Alias;
static ngFactoryDef = function App_Factory() { return new App(); };
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: App, type: App,
selectors: [['app']], selectors: [['app']],
consts: 1, consts: 1,
vars: 0, vars: 0,
factory: function App_Factory() { return new App(); },
template: function App_Template(rf: RenderFlags, ctx: App) { template: function App_Template(rf: RenderFlags, ctx: App) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
ɵɵelement(0, 'div', ['myDir']); ɵɵelement(0, 'div', ['myDir']);
@ -290,12 +290,12 @@ describe('query', () => {
class App { class App {
service?: Service; service?: Service;
static ngFactoryDef = function App_Factory() { return new App(); };
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: App, type: App,
selectors: [['app']], selectors: [['app']],
consts: 1, consts: 1,
vars: 0, vars: 0,
factory: function App_Factory() { return new App(); },
template: function App_Template(rf: RenderFlags, ctx: App) { template: function App_Template(rf: RenderFlags, ctx: App) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
ɵɵelement(0, 'div', ['myDir']); ɵɵelement(0, 'div', ['myDir']);
@ -833,10 +833,10 @@ describe('query', () => {
let childInstance: Child; let childInstance: Child;
class Child { class Child {
static ngFactoryDef = () => childInstance = new Child();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: Child, type: Child,
selectors: [['child']], selectors: [['child']],
factory: () => childInstance = new Child(),
consts: 0, consts: 0,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: Child) => {}, template: (rf: RenderFlags, ctx: Child) => {},
@ -1406,13 +1406,13 @@ describe('query', () => {
this.vcr.createEmbeddedView(this.temp); this.vcr.createEmbeddedView(this.temp);
} }
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => new SomeDir(
type: SomeDir, ɵɵdirectiveInject(ViewContainerRef as any), ɵɵdirectiveInject(TemplateRef as any))
selectors: [['', 'someDir', '']],
factory: static ngDirectiveDef = ɵɵdefineDirective({
() => new SomeDir( type: SomeDir,
ɵɵdirectiveInject(ViewContainerRef as any), ɵɵdirectiveInject(TemplateRef as any)) selectors: [['', 'someDir', '']],
}); });
} }
function AppComponent_Template_1(rf: RenderFlags, ctx: any) { function AppComponent_Template_1(rf: RenderFlags, ctx: any) {
@ -1467,10 +1467,10 @@ describe('query', () => {
this.contentCheckedQuerySnapshot = this.foos ? this.foos.length : 0; this.contentCheckedQuerySnapshot = this.foos ? this.foos.length : 0;
} }
static ngFactoryDef = () => withContentInstance = new WithContentDirective();
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: WithContentDirective, type: WithContentDirective,
selectors: [['', 'with-content', '']], selectors: [['', 'with-content', '']],
factory: () => withContentInstance = new WithContentDirective(),
contentQueries: (rf: RenderFlags, ctx: any, dirIndex: number) => { contentQueries: (rf: RenderFlags, ctx: any, dirIndex: number) => {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
ɵɵcontentQuery(dirIndex, ['foo'], true); ɵɵcontentQuery(dirIndex, ['foo'], true);
@ -1655,11 +1655,11 @@ describe('query', () => {
it('should report results to appropriate queries where deep content queries are nested', () => { it('should report results to appropriate queries where deep content queries are nested', () => {
class QueryDirective { class QueryDirective {
fooBars: any; fooBars: any;
static ngFactoryDef = () => new QueryDirective();
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: QueryDirective, type: QueryDirective,
selectors: [['', 'query', '']], selectors: [['', 'query', '']],
exportAs: ['query'], exportAs: ['query'],
factory: () => new QueryDirective(),
contentQueries: (rf: RenderFlags, ctx: any, dirIndex: number) => { contentQueries: (rf: RenderFlags, ctx: any, dirIndex: number) => {
// @ContentChildren('foo, bar, baz', {descendants: true}) // @ContentChildren('foo, bar, baz', {descendants: true})
// fooBars: QueryList<ElementRef>; // fooBars: QueryList<ElementRef>;
@ -1720,11 +1720,11 @@ describe('query', () => {
class QueryDirective { class QueryDirective {
fooBars: any; fooBars: any;
static ngFactoryDef = () => new QueryDirective();
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: QueryDirective, type: QueryDirective,
selectors: [['', 'query', '']], selectors: [['', 'query', '']],
exportAs: ['query'], exportAs: ['query'],
factory: () => new QueryDirective(),
contentQueries: (rf: RenderFlags, ctx: any, dirIndex: number) => { contentQueries: (rf: RenderFlags, ctx: any, dirIndex: number) => {
// @ContentChildren('foo', {descendants: true}) // @ContentChildren('foo', {descendants: true})
// fooBars: QueryList<ElementRef>; // fooBars: QueryList<ElementRef>;
@ -1777,11 +1777,11 @@ describe('query', () => {
class QueryDirective { class QueryDirective {
fooBars: any; fooBars: any;
static ngFactoryDef = () => new QueryDirective();
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: QueryDirective, type: QueryDirective,
selectors: [['', 'query', '']], selectors: [['', 'query', '']],
exportAs: ['query'], exportAs: ['query'],
factory: () => new QueryDirective(),
contentQueries: (rf: RenderFlags, ctx: any, dirIndex: number) => { contentQueries: (rf: RenderFlags, ctx: any, dirIndex: number) => {
// @ContentChildren('foo', {descendants: true}) // @ContentChildren('foo', {descendants: true})
// fooBars: QueryList<ElementRef>; // fooBars: QueryList<ElementRef>;
@ -1838,11 +1838,11 @@ describe('query', () => {
() => { () => {
class ShallowQueryDirective { class ShallowQueryDirective {
foos: any; foos: any;
static ngFactoryDef = () => new ShallowQueryDirective();
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: ShallowQueryDirective, type: ShallowQueryDirective,
selectors: [['', 'shallow-query', '']], selectors: [['', 'shallow-query', '']],
exportAs: ['shallow-query'], exportAs: ['shallow-query'],
factory: () => new ShallowQueryDirective(),
contentQueries: (rf: RenderFlags, ctx: any, dirIndex: number) => { contentQueries: (rf: RenderFlags, ctx: any, dirIndex: number) => {
// @ContentChildren('foo', {descendants: false}) // @ContentChildren('foo', {descendants: false})
// foos: QueryList<ElementRef>; // foos: QueryList<ElementRef>;
@ -1859,11 +1859,11 @@ describe('query', () => {
class DeepQueryDirective { class DeepQueryDirective {
foos: any; foos: any;
static ngFactoryDef = () => new DeepQueryDirective();
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: DeepQueryDirective, type: DeepQueryDirective,
selectors: [['', 'deep-query', '']], selectors: [['', 'deep-query', '']],
exportAs: ['deep-query'], exportAs: ['deep-query'],
factory: () => new DeepQueryDirective(),
contentQueries: (rf: RenderFlags, ctx: any, dirIndex: number) => { contentQueries: (rf: RenderFlags, ctx: any, dirIndex: number) => {
// @ContentChildren('foo', {descendants: true}) // @ContentChildren('foo', {descendants: true})
// foos: QueryList<ElementRef>; // foos: QueryList<ElementRef>;
@ -1922,12 +1922,9 @@ describe('query', () => {
class TextDirective { class TextDirective {
value !: string; value !: string;
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => new TextDirective();
type: TextDirective, static ngDirectiveDef = ɵɵdefineDirective(
selectors: [['', 'text', '']], {type: TextDirective, selectors: [['', 'text', '']], inputs: {value: 'text'}});
factory: () => new TextDirective(),
inputs: {value: 'text'}
});
} }
it('should register content matches from top to bottom', () => { it('should register content matches from top to bottom', () => {
@ -1937,10 +1934,10 @@ describe('query', () => {
// @ContentChildren(TextDirective) // @ContentChildren(TextDirective)
texts !: QueryList<TextDirective>; texts !: QueryList<TextDirective>;
static ngFactoryDef = () => contentQueryDirective = new ContentQueryDirective();
static ngComponentDef = ɵɵdefineDirective({ static ngComponentDef = ɵɵdefineDirective({
type: ContentQueryDirective, type: ContentQueryDirective,
selectors: [['', 'content-query', '']], selectors: [['', 'content-query', '']],
factory: () => contentQueryDirective = new ContentQueryDirective(),
contentQueries: (rf: RenderFlags, ctx: any, dirIndex: number) => { contentQueries: (rf: RenderFlags, ctx: any, dirIndex: number) => {
// @ContentChildren(TextDirective, {descendants: true}) // @ContentChildren(TextDirective, {descendants: true})
// texts: QueryList<TextDirective>; // texts: QueryList<TextDirective>;
@ -2005,10 +2002,10 @@ describe('query', () => {
// @ViewChildren(TextDirective) // @ViewChildren(TextDirective)
texts !: QueryList<TextDirective>; texts !: QueryList<TextDirective>;
static ngFactoryDef = () => new ViewQueryComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: ViewQueryComponent, type: ViewQueryComponent,
selectors: [['view-query']], selectors: [['view-query']],
factory: () => new ViewQueryComponent(),
template: function(rf: RenderFlags, ctx: ViewQueryComponent) { template: function(rf: RenderFlags, ctx: ViewQueryComponent) {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
ɵɵelement(0, 'span', ['text', 'A']); ɵɵelement(0, 'span', ['text', 'A']);

View File

@ -260,7 +260,6 @@ export function renderTemplate<T>(
selectView(hostLView, null); // SUSPECT! why do we need to enter the View? selectView(hostLView, null); // SUSPECT! why do we need to enter the View?
const def: ComponentDef<any> = ɵɵdefineComponent({ const def: ComponentDef<any> = ɵɵdefineComponent({
factory: () => null,
selectors: [], selectors: [],
type: Object, type: Object,
template: templateFn, template: templateFn,
@ -369,12 +368,12 @@ export function createComponent(
viewProviders: Provider[] = [], hostBindings?: HostBindingsFunction<any>): ComponentType<any> { viewProviders: Provider[] = [], hostBindings?: HostBindingsFunction<any>): ComponentType<any> {
return class Component { return class Component {
value: any; value: any;
static ngFactoryDef = () => new Component;
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: Component, type: Component,
selectors: [[name]], selectors: [[name]],
consts: consts, consts: consts,
vars: vars, vars: vars,
factory: () => new Component,
template: template, template: template,
viewQuery: viewQuery, viewQuery: viewQuery,
directives: directives, hostBindings, directives: directives, hostBindings,
@ -388,10 +387,10 @@ export function createComponent(
export function createDirective( export function createDirective(
name: string, {exportAs}: {exportAs?: string[]} = {}): DirectiveType<any> { name: string, {exportAs}: {exportAs?: string[]} = {}): DirectiveType<any> {
return class Directive { return class Directive {
static ngFactoryDef = () => new Directive();
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: Directive, type: Directive,
selectors: [['', name, '']], selectors: [['', name, '']],
factory: () => new Directive(),
exportAs: exportAs, exportAs: exportAs,
}); });
}; };

View File

@ -26,6 +26,7 @@ describe('renderer factory lifecycle', () => {
rendererFactory.end = () => logs.push('end'); rendererFactory.end = () => logs.push('end');
class SomeComponent { class SomeComponent {
static ngFactoryDef = () => new SomeComponent;
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: SomeComponent, type: SomeComponent,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@ -40,12 +41,12 @@ describe('renderer factory lifecycle', () => {
if (rf & RenderFlags.Update) { if (rf & RenderFlags.Update) {
logs.push('component update'); logs.push('component update');
} }
}, }
factory: () => new SomeComponent
}); });
} }
class SomeComponentWhichThrows { class SomeComponentWhichThrows {
static ngFactoryDef = () => new SomeComponentWhichThrows;
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: SomeComponentWhichThrows, type: SomeComponentWhichThrows,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@ -54,8 +55,7 @@ describe('renderer factory lifecycle', () => {
vars: 0, vars: 0,
template: function(rf: RenderFlags, ctx: SomeComponentWhichThrows) { template: function(rf: RenderFlags, ctx: SomeComponentWhichThrows) {
throw(new Error('SomeComponentWhichThrows threw')); throw(new Error('SomeComponentWhichThrows threw'));
}, }
factory: () => new SomeComponentWhichThrows
}); });
} }
@ -150,6 +150,7 @@ describe('Renderer2 destruction hooks', () => {
it('should call renderer.destroy for each component destroyed', () => { it('should call renderer.destroy for each component destroyed', () => {
class SimpleComponent { class SimpleComponent {
static ngFactoryDef = () => new SimpleComponent;
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: SimpleComponent, type: SimpleComponent,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
@ -161,7 +162,6 @@ describe('Renderer2 destruction hooks', () => {
ɵɵelement(0, 'span'); ɵɵelement(0, 'span');
} }
}, },
factory: () => new SimpleComponent,
}); });
} }

View File

@ -29,14 +29,14 @@ describe('ViewContainerRef', () => {
beforeEach(() => directiveInstance = null); beforeEach(() => directiveInstance = null);
class DirectiveWithVCRef { class DirectiveWithVCRef {
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => directiveInstance = new DirectiveWithVCRef(
type: DirectiveWithVCRef, ɵɵdirectiveInject(ViewContainerRef as any), injectComponentFactoryResolver())
selectors: [['', 'vcref', '']],
factory: () => directiveInstance = new DirectiveWithVCRef(
ɵɵdirectiveInject(ViewContainerRef as any), injectComponentFactoryResolver()), static ngDirectiveDef = ɵɵdefineDirective({
inputs: {tplRef: 'tplRef', name: 'name'} type: DirectiveWithVCRef,
}); selectors: [['', 'vcref', '']],
inputs: {tplRef: 'tplRef', name: 'name'}
});
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
tplRef !: TemplateRef<{}>; tplRef !: TemplateRef<{}>;
@ -57,18 +57,20 @@ describe('ViewContainerRef', () => {
let directiveInstances: TestDirective[] = []; let directiveInstances: TestDirective[] = [];
class TestDirective { class TestDirective {
static ngFactoryDef =
() => {
const instance = new TestDirective(
ɵɵdirectiveInject(ViewContainerRef as any),
ɵɵdirectiveInject(TemplateRef as any));
directiveInstances.push(instance);
return instance;
}
static ngDirectiveDef = ɵɵdefineDirective({ static ngDirectiveDef = ɵɵdefineDirective({
type: TestDirective, type: TestDirective,
selectors: [['', 'testdir', '']], selectors: [['', 'testdir', '']],
factory: () => {
const instance = new TestDirective(
ɵɵdirectiveInject(ViewContainerRef as any),
ɵɵdirectiveInject(TemplateRef as any));
directiveInstances.push(instance);
return instance;
}
}); });
constructor(private _vcRef: ViewContainerRef, private _tplRef: TemplateRef<{}>) {} constructor(private _vcRef: ViewContainerRef, private _tplRef: TemplateRef<{}>) {}
@ -99,11 +101,11 @@ describe('ViewContainerRef', () => {
class TestComponent { class TestComponent {
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
testDir !: TestDirective; testDir !: TestDirective;
static ngFactoryDef = () => new TestComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: TestComponent, type: TestComponent,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
selectors: [['test-cmp']], selectors: [['test-cmp']],
factory: () => new TestComponent(),
consts: 4, consts: 4,
vars: 0, vars: 0,
template: (rf: RenderFlags, cmp: TestComponent) => { template: (rf: RenderFlags, cmp: TestComponent) => {
@ -134,13 +136,11 @@ describe('ViewContainerRef', () => {
let directiveInstance: TestDirective; let directiveInstance: TestDirective;
class TestDirective { class TestDirective {
static ngDirectiveDef = ɵɵdefineDirective({ static ngFactoryDef = () => directiveInstance = new TestDirective(
type: TestDirective, ɵɵdirectiveInject(ViewContainerRef as any), ɵɵdirectiveInject(TemplateRef as any))
selectors: [['', 'testdir', '']],
factory: () => directiveInstance = new TestDirective( static ngDirectiveDef =
ɵɵdirectiveInject(ViewContainerRef as any), ɵɵdefineDirective({type: TestDirective, selectors: [['', 'testdir', '']]});
ɵɵdirectiveInject(TemplateRef as any))
});
constructor(private _vcRef: ViewContainerRef, private _tplRef: TemplateRef<{}>) {} constructor(private _vcRef: ViewContainerRef, private _tplRef: TemplateRef<{}>) {}
@ -172,13 +172,13 @@ describe('ViewContainerRef', () => {
condition = false; condition = false;
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
testDir !: TestDirective; testDir !: TestDirective;
static ngFactoryDef = () => new TestComponent();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: TestComponent, type: TestComponent,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
selectors: [['test-cmp']], selectors: [['test-cmp']],
consts: 4, consts: 4,
vars: 0, vars: 0,
factory: () => new TestComponent(),
template: (rf: RenderFlags, cmp: TestComponent) => { template: (rf: RenderFlags, cmp: TestComponent) => {
if (rf & RenderFlags.Create) { if (rf & RenderFlags.Create) {
ɵɵtext(0, 'before|'); ɵɵtext(0, 'before|');
@ -239,12 +239,15 @@ describe('ViewContainerRef', () => {
class AppComp { class AppComp {
constructor(public vcr: ViewContainerRef, public cfr: ComponentFactoryResolver) {} constructor(public vcr: ViewContainerRef, public cfr: ComponentFactoryResolver) {}
static ngFactoryDef =
() => {
return new AppComp(
ɵɵdirectiveInject(ViewContainerRef as any), injectComponentFactoryResolver());
}
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: AppComp, type: AppComp,
selectors: [['app-comp']], selectors: [['app-comp']],
factory:
() => new AppComp(
ɵɵdirectiveInject(ViewContainerRef as any), injectComponentFactoryResolver()),
consts: 0, consts: 0,
vars: 0, vars: 0,
template: (rf: RenderFlags, cmp: AppComp) => {} template: (rf: RenderFlags, cmp: AppComp) => {}
@ -256,10 +259,11 @@ describe('ViewContainerRef', () => {
ngDoCheck() { this.doCheckCount++; } ngDoCheck() { this.doCheckCount++; }
static ngFactoryDef = () => dynamicComp = new DynamicComp();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: DynamicComp, type: DynamicComp,
selectors: [['dynamic-comp']], selectors: [['dynamic-comp']],
factory: () => dynamicComp = new DynamicComp(),
consts: 0, consts: 0,
vars: 0, vars: 0,
template: (rf: RenderFlags, cmp: DynamicComp) => {} template: (rf: RenderFlags, cmp: DynamicComp) => {}
@ -355,15 +359,16 @@ describe('ViewContainerRef', () => {
@Component({selector: 'app', template: ''}) @Component({selector: 'app', template: ''})
class AppCmpt { class AppCmpt {
static ngComponentDef = ɵɵdefineComponent({ static ngFactoryDef = () =>
type: AppCmpt, new AppCmpt(ɵɵdirectiveInject(ViewContainerRef as any), injectComponentFactoryResolver())
selectors: [['app']],
factory: () => new AppCmpt( static ngComponentDef = ɵɵdefineComponent({
ɵɵdirectiveInject(ViewContainerRef as any), injectComponentFactoryResolver()), type: AppCmpt,
consts: 0, selectors: [['app']],
vars: 0, consts: 0,
template: (rf: RenderFlags, cmp: AppCmpt) => {} vars: 0,
}); template: (rf: RenderFlags, cmp: AppCmpt) => {}
});
constructor(private _vcRef: ViewContainerRef, private _cfResolver: ComponentFactoryResolver) { constructor(private _vcRef: ViewContainerRef, private _cfResolver: ComponentFactoryResolver) {
} }
@ -424,10 +429,10 @@ describe('ViewContainerRef', () => {
// @ViewChildren('foo') // @ViewChildren('foo')
foo !: QueryList<any>; foo !: QueryList<any>;
static ngFactoryDef = () => dynamicComp = new DynamicCompWithViewQueries();
static ngComponentDef = ɵɵdefineComponent({ static ngComponentDef = ɵɵdefineComponent({
type: DynamicCompWithViewQueries, type: DynamicCompWithViewQueries,
selectors: [['dynamic-cmpt-with-view-queries']], selectors: [['dynamic-cmpt-with-view-queries']],
factory: () => dynamicComp = new DynamicCompWithViewQueries(),
consts: 2, consts: 2,
vars: 0, vars: 0,
template: (rf: RenderFlags, ctx: DynamicCompWithViewQueries) => { template: (rf: RenderFlags, ctx: DynamicCompWithViewQueries) => {
@ -468,27 +473,28 @@ describe('ViewContainerRef', () => {
ngOnDestroy() { this.viewRef.destroy(); } ngOnDestroy() { this.viewRef.destroy(); }
static ngComponentDef = ɵɵdefineComponent({ // We want the ViewRef, so we rely on the knowledge that `ViewRef` is actually given
type: CompWithListenerThatDestroysItself, // when injecting `ChangeDetectorRef`.
selectors: [['comp-with-listener-and-on-destroy']], static ngFactoryDef = () =>
consts: 2, new CompWithListenerThatDestroysItself(ɵɵdirectiveInject(ChangeDetectorRef as any))
vars: 0,
/** <button (click)="onClick()"> Click me </button> */ static ngComponentDef = ɵɵdefineComponent({
template: function CompTemplate(rf: RenderFlags, ctx: any) { type: CompWithListenerThatDestroysItself,
if (rf & RenderFlags.Create) { selectors: [['comp-with-listener-and-on-destroy']],
ɵɵelementStart(0, 'button'); consts: 2,
{ vars: 0,
ɵɵlistener('click', function() { return ctx.onClick(); }); /** <button (click)="onClick()"> Click me </button> */
ɵɵtext(1, 'Click me'); template: function CompTemplate(rf: RenderFlags, ctx: any) {
} if (rf & RenderFlags.Create) {
ɵɵelementEnd(); ɵɵelementStart(0, 'button');
} {
}, ɵɵlistener('click', function() { return ctx.onClick(); });
// We want the ViewRef, so we rely on the knowledge that `ViewRef` is actually given ɵɵtext(1, 'Click me');
// when injecting `ChangeDetectorRef`. }
factory: () => new CompWithListenerThatDestroysItself( ɵɵelementEnd();
ɵɵdirectiveInject(ChangeDetectorRef as any)), }
}); },
});
} }

View File

@ -503,10 +503,10 @@ describe('TestBed', () => {
*/ */
const getAOTCompiledComponent = () => { const getAOTCompiledComponent = () => {
class ComponentClass { class ComponentClass {
static ngFactoryDef = () => new ComponentClass();
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
type: ComponentClass, type: ComponentClass,
selectors: [['comp']], selectors: [['comp']],
factory: () => new ComponentClass(),
consts: 1, consts: 1,
vars: 0, vars: 0,
template: (rf: any, ctx: any) => { template: (rf: any, ctx: any) => {

View File

@ -225,6 +225,7 @@ export declare class NgClassBase {
[key: string]: any; [key: string]: any;
} | null; } | null;
static ngDirectiveDef: any; static ngDirectiveDef: any;
static ngFactoryDef: any;
} }
export declare class NgComponentOutlet implements OnChanges, OnDestroy { export declare class NgComponentOutlet implements OnChanges, OnDestroy {
@ -309,6 +310,7 @@ export declare class NgStyleBase {
[key: string]: any; [key: string]: any;
} | null; } | null;
static ngDirectiveDef: any; static ngDirectiveDef: any;
static ngFactory: any;
} }
export declare class NgSwitch { export declare class NgSwitch {

View File

@ -771,7 +771,6 @@ export declare function ɵɵdefineBase<T>(baseDefinition: {
export declare function ɵɵdefineComponent<T>(componentDefinition: { export declare function ɵɵdefineComponent<T>(componentDefinition: {
type: Type<T>; type: Type<T>;
selectors: CssSelectorList; selectors: CssSelectorList;
factory: FactoryFn<T>;
consts: number; consts: number;
vars: number; vars: number;
inputs?: { inputs?: {
@ -801,7 +800,6 @@ export declare function ɵɵdefineComponent<T>(componentDefinition: {
export declare const ɵɵdefineDirective: <T>(directiveDefinition: { export declare const ɵɵdefineDirective: <T>(directiveDefinition: {
type: Type<T>; type: Type<T>;
selectors: (string | SelectorFlags)[][]; selectors: (string | SelectorFlags)[][];
factory: FactoryFn<T>;
inputs?: { [P in keyof T]?: string | [string, string] | undefined; } | undefined; inputs?: { [P in keyof T]?: string | [string, string] | undefined; } | undefined;
outputs?: { [P in keyof T]?: string | undefined; } | undefined; outputs?: { [P in keyof T]?: string | undefined; } | undefined;
features?: DirectiveDefFeature[] | undefined; features?: DirectiveDefFeature[] | undefined;
@ -836,7 +834,6 @@ export declare function ɵɵdefineNgModule<T>(def: {
export declare function ɵɵdefinePipe<T>(pipeDef: { export declare function ɵɵdefinePipe<T>(pipeDef: {
name: string; name: string;
type: Type<T>; type: Type<T>;
factory: FactoryFn<T>;
pure?: boolean; pure?: boolean;
}): never; }): never;
@ -871,6 +868,8 @@ export declare function ɵɵembeddedViewStart(viewBlockId: number, consts: numbe
export declare function ɵɵenableBindings(): void; export declare function ɵɵenableBindings(): void;
export declare type ɵɵFactoryDef<T> = () => T;
export declare function ɵɵgetCurrentView(): OpaqueViewState; export declare function ɵɵgetCurrentView(): OpaqueViewState;
export declare function ɵɵgetFactoryOf<T>(type: Type<any>): FactoryFn<T> | null; export declare function ɵɵgetFactoryOf<T>(type: Type<any>): FactoryFn<T> | null;