refactor(ivy): align compiler with runtime (#22921)

Remove `containerRefreshStart` and `containerRefreshEnd` instruction
from the output.

Generate directives as a list in `componentDef` rather than inline into
instructions. This is consistent in making selector resolution runtime
so that translation of templates can follow locality.

PR Close #22921
This commit is contained in:
Miško Hevery 2018-03-29 12:58:41 -07:00 committed by Alex Rickabaugh
parent 5266ffe04a
commit 60065935be
32 changed files with 402 additions and 348 deletions

View File

@ -81,7 +81,7 @@ export class TreeComponent {
}, },
factory: () => new TreeComponent, factory: () => new TreeComponent,
inputs: {data: 'data'}, inputs: {data: 'data'},
directiveDefs: () => [TreeComponent.ngComponentDef] directives: () => [TreeComponent]
}); });
} }

View File

@ -33,10 +33,6 @@ export class Identifiers {
static containerEnd: o.ExternalReference = {name: 'ɵc', moduleName: CORE}; static containerEnd: o.ExternalReference = {name: 'ɵc', moduleName: CORE};
static containerRefreshStart: o.ExternalReference = {name: 'ɵcR', moduleName: CORE};
static containerRefreshEnd: o.ExternalReference = {name: 'ɵcr', moduleName: CORE};
static directiveCreate: o.ExternalReference = {name: 'ɵD', moduleName: CORE}; static directiveCreate: o.ExternalReference = {name: 'ɵD', moduleName: CORE};
static text: o.ExternalReference = {name: 'ɵT', moduleName: CORE}; static text: o.ExternalReference = {name: 'ɵT', moduleName: CORE};

View File

@ -120,6 +120,23 @@ export function compileComponent(
addDependencyToComponent(outputCtx, summary, pipeSet, pipeExps); addDependencyToComponent(outputCtx, summary, pipeSet, pipeExps);
} }
const directiveExps: o.Expression[] = [];
const directiveMap = new Set<string>();
/**
* This function gets called every time a directive dependency needs to be added to the template.
* Its job is to remove duplicates from the list. (Only have single dependency no matter how many
* times the dependency is used.)
*/
function addDirectiveDependency(ast: DirectiveAst) {
const importExpr = outputCtx.importExpr(ast.directive.type.reference) as o.ExternalExpr;
const uniqueKey = importExpr.value.moduleName + ':' + importExpr.value.name;
if (!directiveMap.has(uniqueKey)) {
directiveMap.add(uniqueKey);
directiveExps.push(importExpr);
}
}
const field = (key: string, value: o.Expression | null) => { const field = (key: string, value: o.Expression | null) => {
if (value) { if (value) {
definitionMapValues.push({key, value, quoted: false}); definitionMapValues.push({key, value, quoted: false});
@ -162,10 +179,13 @@ export function compileComponent(
new TemplateDefinitionBuilder( new TemplateDefinitionBuilder(
outputCtx, outputCtx.constantPool, reflector, CONTEXT_NAME, ROOT_SCOPE.nestedScope(), 0, outputCtx, outputCtx.constantPool, reflector, CONTEXT_NAME, ROOT_SCOPE.nestedScope(), 0,
component.template !.ngContentSelectors, templateTypeName, templateName, pipeMap, component.template !.ngContentSelectors, templateTypeName, templateName, pipeMap,
component.viewQueries, addPipeDependency) component.viewQueries, addDirectiveDependency, addPipeDependency)
.buildTemplateFunction(template, []); .buildTemplateFunction(template, []);
field('template', templateFunctionExpression); field('template', templateFunctionExpression);
if (directiveExps.length) {
field('directives', o.literalArr(directiveExps));
}
// e.g. `pipes: [MyPipe]` // e.g. `pipes: [MyPipe]`
if (pipeExps.length) { if (pipeExps.length) {
@ -373,6 +393,7 @@ class TemplateDefinitionBuilder implements TemplateAstVisitor, LocalResolver {
private bindingScope: BindingScope, private level = 0, private ngContentSelectors: string[], private bindingScope: BindingScope, private level = 0, private ngContentSelectors: string[],
private contextName: string|null, private templateName: string|null, private contextName: string|null, private templateName: string|null,
private pipes: Map<string, CompilePipeSummary>, private viewQueries: CompileQueryMetadata[], private pipes: Map<string, CompilePipeSummary>, private viewQueries: CompileQueryMetadata[],
private addDirectiveDependency: (ast: DirectiveAst) => void,
private addPipeDependency: (summary: CompilePipeSummary) => void) { private addPipeDependency: (summary: CompilePipeSummary) => void) {
this._valueConverter = new ValueConverter( this._valueConverter = new ValueConverter(
outputCtx, () => this.allocateDataSlot(), (name, localName, slot, value) => { outputCtx, () => this.allocateDataSlot(), (name, localName, slot, value) => {
@ -504,23 +525,9 @@ class TemplateDefinitionBuilder implements TemplateAstVisitor, LocalResolver {
this.instruction(this._creationMode, ast.sourceSpan, R3.projection, ...parameters); this.instruction(this._creationMode, ast.sourceSpan, R3.projection, ...parameters);
} }
private _computeDirectivesArray(directives: DirectiveAst[]) {
const directiveExpressions: o.Expression[] =
directives.filter(directive => !directive.directive.isComponent).map(directive => {
this.allocateDataSlot(); // Allocate space for the directive
return this.typeReference(directive.directive.type.reference);
});
return directiveExpressions.length ?
this.constantPool.getConstLiteral(
o.literalArr(directiveExpressions), /* forceShared */ true) :
o.literal(null, o.INFERRED_TYPE);
;
}
// TemplateAstVisitor // TemplateAstVisitor
visitElement(element: ElementAst) { visitElement(element: ElementAst) {
const elementIndex = this.allocateDataSlot(); const elementIndex = this.allocateDataSlot();
let componentIndex: number|undefined = undefined;
const referenceDataSlots = new Map<string, number>(); const referenceDataSlots = new Map<string, number>();
const wasInI18nSection = this._inI18nSection; const wasInI18nSection = this._inI18nSection;
@ -563,13 +570,11 @@ class TemplateDefinitionBuilder implements TemplateAstVisitor, LocalResolver {
const nullNode = o.literal(null, o.INFERRED_TYPE); const nullNode = o.literal(null, o.INFERRED_TYPE);
const parameters: o.Expression[] = [o.literal(elementIndex)]; const parameters: o.Expression[] = [o.literal(elementIndex)];
// Add component type or element tag
if (component) { if (component) {
parameters.push(this.typeReference(component.directive.type.reference)); this.addDirectiveDependency(component);
componentIndex = this.allocateDataSlot();
} else {
parameters.push(o.literal(element.name));
} }
element.directives.forEach(this.addDirectiveDependency);
parameters.push(o.literal(element.name));
// Add the attributes // Add the attributes
const i18nMessages: o.Statement[] = []; const i18nMessages: o.Statement[] = [];
@ -598,10 +603,6 @@ class TemplateDefinitionBuilder implements TemplateAstVisitor, LocalResolver {
parameters.push(attrArg); parameters.push(attrArg);
// Add directives array
const directivesArray = this._computeDirectivesArray(element.directives);
parameters.push(directivesArray);
if (element.references && element.references.length > 0) { if (element.references && element.references.length > 0) {
const references = const references =
flatten(element.references.map(reference => { flatten(element.references.map(reference => {
@ -621,16 +622,12 @@ class TemplateDefinitionBuilder implements TemplateAstVisitor, LocalResolver {
parameters.push(nullNode); parameters.push(nullNode);
} }
// Remove trailing null nodes as they are implied.
while (o.isNull(parameters[parameters.length - 1])) {
parameters.pop();
}
// Generate the instruction create element instruction // Generate the instruction create element instruction
if (i18nMessages.length > 0) { if (i18nMessages.length > 0) {
this._creationMode.push(...i18nMessages); this._creationMode.push(...i18nMessages);
} }
this.instruction(this._creationMode, element.sourceSpan, R3.createElement, ...parameters); this.instruction(
this._creationMode, element.sourceSpan, R3.createElement, ...trimTrailingNulls(parameters));
const implicit = o.variable(this.contextParameter); const implicit = o.variable(this.contextParameter);
@ -725,28 +722,41 @@ class TemplateDefinitionBuilder implements TemplateAstVisitor, LocalResolver {
contextName ? `${contextName}_Template_${templateIndex}` : `Template_${templateIndex}`; contextName ? `${contextName}_Template_${templateIndex}` : `Template_${templateIndex}`;
const templateContext = `ctx${this.level}`; const templateContext = `ctx${this.level}`;
const directivesArray = this._computeDirectivesArray(ast.directives); const parameters: o.Expression[] = [o.variable(templateName), o.literal(null, o.INFERRED_TYPE)];
const attributeNames: o.Expression[] = [];
ast.directives.forEach((directiveAst: DirectiveAst) => {
this.addDirectiveDependency(directiveAst);
CssSelector.parse(directiveAst.directive.selector !).forEach(selector => {
selector.attrs.forEach((value) => {
// Convert '' (falsy) strings into `null`. This is needed because we want
// to communicate to runtime that these attributes are present for
// selector matching, but should not actually be added to the DOM.
// attributeNames.push(o.literal(value ? value : null));
// TODO(misko): make the above comment true, for now just write to DOM because
// the runtime selectors have not been updated.
attributeNames.push(o.literal(value));
});
});
});
if (attributeNames.length) {
parameters.push(
this.constantPool.getConstLiteral(o.literalArr(attributeNames), /* forcedShared */ true));
}
// e.g. C(1, C1Template) // e.g. C(1, C1Template)
this.instruction( this.instruction(
this._creationMode, ast.sourceSpan, R3.containerCreate, o.literal(templateIndex), this._creationMode, ast.sourceSpan, R3.containerCreate, o.literal(templateIndex),
directivesArray, o.variable(templateName)); ...trimTrailingNulls(parameters));
// e.g. Cr(1)
this.instruction(
this._refreshMode, ast.sourceSpan, R3.containerRefreshStart, o.literal(templateIndex));
// Generate directives // Generate directives
this._visitDirectives(ast.directives, o.variable(this.contextParameter), templateIndex); this._visitDirectives(ast.directives, o.variable(this.contextParameter), templateIndex);
// e.g. cr();
this.instruction(this._refreshMode, ast.sourceSpan, R3.containerRefreshEnd);
// Create the template function // Create the template function
const templateVisitor = new TemplateDefinitionBuilder( const templateVisitor = new TemplateDefinitionBuilder(
this.outputCtx, this.constantPool, this.reflector, templateContext, this.outputCtx, this.constantPool, this.reflector, templateContext,
this.bindingScope.nestedScope(), this.level + 1, this.ngContentSelectors, contextName, this.bindingScope.nestedScope(), this.level + 1, this.ngContentSelectors, contextName,
templateName, this.pipes, [], this.addPipeDependency); templateName, this.pipes, [], this.addDirectiveDependency, this.addPipeDependency);
const templateFunctionExpr = templateVisitor.buildTemplateFunction(ast.children, ast.variables); const templateFunctionExpr = templateVisitor.buildTemplateFunction(ast.children, ast.variables);
this._postfix.push(templateFunctionExpr.toDeclStmt(templateName, null)); this._postfix.push(templateFunctionExpr.toDeclStmt(templateName, null));
} }
@ -811,8 +821,6 @@ class TemplateDefinitionBuilder implements TemplateAstVisitor, LocalResolver {
statements.push(o.importExpr(reference, null, span).callFn(params, span).toStmt()); statements.push(o.importExpr(reference, null, span).callFn(params, span).toStmt());
} }
private typeReference(type: any): o.Expression { return this.outputCtx.importExpr(type); }
private definitionOf(type: any, kind: DefinitionKind): o.Expression { private definitionOf(type: any, kind: DefinitionKind): o.Expression {
return this.constantPool.getDefinition(type, kind, this.outputCtx); return this.constantPool.getDefinition(type, kind, this.outputCtx);
} }
@ -923,6 +931,16 @@ export function createFactory(
type.reference.name ? `${type.reference.name}_Factory` : null); type.reference.name ? `${type.reference.name}_Factory` : null);
} }
/**
* Remove trailing null nodes as they are implied.
*/
function trimTrailingNulls(parameters: o.Expression[]): o.Expression[] {
while (o.isNull(parameters[parameters.length - 1])) {
parameters.pop();
}
return parameters;
}
type HostBindings = { type HostBindings = {
[key: string]: string [key: string]: string
}; };

View File

@ -28,6 +28,17 @@ const _SELECTOR_REGEXP = new RegExp(
export class CssSelector { export class CssSelector {
element: string|null = null; element: string|null = null;
classNames: string[] = []; classNames: string[] = [];
/**
* The selectors are encoded in pairs where:
* - even locations are attribute names
* - odd locations are attribute values.
*
* Example:
* Selector: `[key1=value1][key2]` would parse to:
* ```
* ['key1', 'value1', 'key2', '']
* ```
*/
attrs: string[] = []; attrs: string[] = [];
notSelectors: CssSelector[] = []; notSelectors: CssSelector[] = [];

View File

@ -113,7 +113,6 @@ describe('compiler compliance', () => {
// MyComponent definition should be: // MyComponent definition should be:
const MyComponentDefinition = ` const MyComponentDefinition = `
const $c1$ = ['some-directive', '']; const $c1$ = ['some-directive', ''];
const $c2$ = [SomeDirective];
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
@ -121,11 +120,12 @@ describe('compiler compliance', () => {
factory: function MyComponent_Factory() { return new MyComponent(); }, factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) { template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
if (cm) { if (cm) {
$r3$.ɵE(0, ChildComponent, IDENT, IDENT); $r3$.ɵE(0, 'child', $c1$);
$r3$.ɵe(); $r3$.ɵe();
$r3$.ɵT(3, '!'); $r3$.ɵT(1, '!');
} }
} },
directives: [ChildComponent, SomeDirective]
}); });
`; `;
@ -249,7 +249,7 @@ describe('compiler compliance', () => {
});`; });`;
const MyComponentDefinition = ` const MyComponentDefinition = `
const $c1$ = ['foo', '']; const $c1$ = ['foo', ''];
const $c2$ = [IfDirective]; const $c2$ = ['if', ''];
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
@ -257,13 +257,11 @@ describe('compiler compliance', () => {
factory: function MyComponent_Factory() { return new MyComponent(); }, factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) { template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
if (cm) { if (cm) {
$r3$.ɵE(0, 'ul', null, null, $c1$); $r3$.ɵE(0, 'ul', null, $c1$);
$r3$.ɵC(2, $c2$, MyComponent_IfDirective_Template_2); $r3$.ɵC(2, MyComponent_IfDirective_Template_2, null, $c2$);
$r3$.ɵe(); $r3$.ɵe();
} }
const $foo$ = $r3$.ɵld(1); const $foo$ = $r3$.ɵld(1);
$r3$.ɵcR(2);
$r3$.ɵcr();
function MyComponent_IfDirective_Template_2(ctx0: IDENT, cm: IDENT) { function MyComponent_IfDirective_Template_2(ctx0: IDENT, cm: IDENT) {
if (cm) { if (cm) {
@ -273,7 +271,8 @@ describe('compiler compliance', () => {
} }
$r3$.ɵt(1, $r3$.ɵi2('', ctx.salutation, ' ', $foo$, '')); $r3$.ɵt(1, $r3$.ɵi2('', ctx.salutation, ' ', $foo$, ''));
} }
} },
directives: [IfDirective]
});`; });`;
const result = compile(files, angularFiles); const result = compile(files, angularFiles);
@ -327,11 +326,12 @@ describe('compiler compliance', () => {
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) { template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) { if (cm) {
$r3$.ɵE(0, MyComp); $r3$.ɵE(0, 'my-comp');
$r3$.ɵe(); $r3$.ɵe();
} }
$r3$.ɵp(0, 'names', $r3$.ɵb($r3$.ɵf1($e0_ff$, ctx.customName))); $r3$.ɵp(0, 'names', $r3$.ɵb($r3$.ɵf1($e0_ff$, ctx.customName)));
} },
directives: [MyComp]
}); });
`; `;
@ -403,13 +403,14 @@ describe('compiler compliance', () => {
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) { template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) { if (cm) {
$r3$.ɵE(0, MyComp); $r3$.ɵE(0, 'my-comp');
$r3$.ɵe(); $r3$.ɵe();
} }
$r3$.ɵp( $r3$.ɵp(
0, 'names', 0, 'names',
$r3$.ɵb($r3$.ɵfV($e0_ff$, ctx.n0, ctx.n1, ctx.n2, ctx.n3, ctx.n4, ctx.n5, ctx.n6, ctx.n7, ctx.n8))); $r3$.ɵb($r3$.ɵfV($e0_ff$, ctx.n0, ctx.n1, ctx.n2, ctx.n3, ctx.n4, ctx.n5, ctx.n6, ctx.n7, ctx.n8)));
} },
directives: [MyComp]
}); });
`; `;
@ -461,11 +462,12 @@ describe('compiler compliance', () => {
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) { template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) { if (cm) {
$r3$.ɵE(0, ObjectComp); $r3$.ɵE(0, 'object-comp');
$r3$.ɵe(); $r3$.ɵe();
} }
$r3$.ɵp(0, 'config', $r3$.ɵb($r3$.ɵf1($e0_ff$, ctx.name))); $r3$.ɵp(0, 'config', $r3$.ɵb($r3$.ɵf1($e0_ff$, ctx.name)));
} },
directives: [ObjectComp]
}); });
`; `;
@ -523,14 +525,15 @@ describe('compiler compliance', () => {
factory: function MyApp_Factory() { return new MyApp(); }, factory: function MyApp_Factory() { return new MyApp(); },
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) { template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
if (cm) { if (cm) {
$r3$.ɵE(0, NestedComp); $r3$.ɵE(0, 'nested-comp');
$r3$.ɵe(); $r3$.ɵe();
} }
$r3$.ɵp( $r3$.ɵp(
0, 'config', 0, 'config',
$r3$.ɵb($r3$.ɵf2( $r3$.ɵb($r3$.ɵf2(
$e0_ff_2$, ctx.name, $r3$.ɵf1($e0_ff_1$, $r3$.ɵf1($e0_ff$, ctx.duration))))); $e0_ff_2$, ctx.name, $r3$.ɵf1($e0_ff_1$, $r3$.ɵf1($e0_ff$, ctx.duration)))));
} },
directives: [NestedComp]
}); });
`; `;
@ -655,7 +658,6 @@ describe('compiler compliance', () => {
const ViewQueryComponentDefinition = ` const ViewQueryComponentDefinition = `
const $e0_attrs$ = ['someDir','']; const $e0_attrs$ = ['someDir',''];
const $e1_dirs$ = [SomeDirective];
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: ViewQueryComponent, type: ViewQueryComponent,
@ -665,11 +667,12 @@ describe('compiler compliance', () => {
var $tmp$: $any$; var $tmp$: $any$;
if (cm) { if (cm) {
$r3$.ɵQ(0, SomeDirective, true); $r3$.ɵQ(0, SomeDirective, true);
$r3$.ɵE(1, 'div', $e0_attrs$, $e1_dirs$); $r3$.ɵE(1, 'div', $e0_attrs$);
$r3$.ɵe(); $r3$.ɵe();
} }
($r3$.ɵqR(($tmp$ = $r3$.ɵld(0))) && (ctx.someDir = $tmp$.first)); ($r3$.ɵqR(($tmp$ = $r3$.ɵld(0))) && (ctx.someDir = $tmp$.first));
} },
directives:[SomeDirective]
});`; });`;
const result = compile(files, angularFiles); const result = compile(files, angularFiles);
@ -851,7 +854,7 @@ describe('compiler compliance', () => {
factory: function MyComponent_Factory() { return new MyComponent(); }, factory: function MyComponent_Factory() { return new MyComponent(); },
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) { template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
if (cm) { if (cm) {
$r3$.ɵE(0, 'input', null, null, $c1$); $r3$.ɵE(0, 'input', null, $c1$);
$r3$.ɵe(); $r3$.ɵe();
$r3$.ɵT(2); $r3$.ɵT(2);
} }
@ -929,14 +932,15 @@ describe('compiler compliance', () => {
factory: function SimpleLayout_Factory() { return new SimpleLayout(); }, factory: function SimpleLayout_Factory() { return new SimpleLayout(); },
template: function SimpleLayout_Template(ctx: IDENT, cm: IDENT) { template: function SimpleLayout_Template(ctx: IDENT, cm: IDENT) {
if (cm) { if (cm) {
$r3$.ɵE(0, LifecycleComp); $r3$.ɵE(0, 'lifecycle-comp');
$r3$.ɵe(); $r3$.ɵe();
$r3$.ɵE(2, LifecycleComp); $r3$.ɵE(1, 'lifecycle-comp');
$r3$.ɵe(); $r3$.ɵe();
} }
$r3$.ɵp(0, 'name', $r3$.ɵb(ctx.name1)); $r3$.ɵp(0, 'name', $r3$.ɵb(ctx.name1));
$r3$.ɵp(2, 'name', $r3$.ɵb(ctx.name2)); $r3$.ɵp(1, 'name', $r3$.ɵb(ctx.name2));
} },
directives: [LifecycleComp]
});`; });`;
const result = compile(files, angularFiles); const result = compile(files, angularFiles);
@ -1039,7 +1043,7 @@ describe('compiler compliance', () => {
`; `;
const MyComponentDefinition = ` const MyComponentDefinition = `
const $c1$ = [ForOfDirective]; const $_c0$ = ['forOf',''];
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
@ -1048,12 +1052,10 @@ describe('compiler compliance', () => {
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) { template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
if (cm) { if (cm) {
$r3$.ɵE(0, 'ul'); $r3$.ɵE(0, 'ul');
$r3$.ɵC(1, $c1$, MyComponent_ForOfDirective_Template_1); $r3$.ɵC(1, MyComponent_ForOfDirective_Template_1, null, $_c0$);
$r3$.ɵe(); $r3$.ɵe();
} }
$r3$.ɵp(1, 'forOf', $r3$.ɵb(ctx.items)); $r3$.ɵp(1, 'forOf', $r3$.ɵb(ctx.items));
$r3$.ɵcR(1);
$r3$.ɵcr();
function MyComponent_ForOfDirective_Template_1(ctx0: IDENT, cm: IDENT) { function MyComponent_ForOfDirective_Template_1(ctx0: IDENT, cm: IDENT) {
if (cm) { if (cm) {
@ -1064,7 +1066,8 @@ describe('compiler compliance', () => {
const $item$ = ctx0.$implicit; const $item$ = ctx0.$implicit;
$r3$.ɵt(1, $r3$.ɵi1('', $item$.name, '')); $r3$.ɵt(1, $r3$.ɵi1('', $item$.name, ''));
} }
} },
directives: [ForOfDirective]
}); });
`; `;
@ -1114,7 +1117,7 @@ describe('compiler compliance', () => {
}; };
const MyComponentDefinition = ` const MyComponentDefinition = `
const $c1$ = [ForOfDirective]; const $c1$ = ['forOf', ''];
static ngComponentDef = $r3$.ɵdefineComponent({ static ngComponentDef = $r3$.ɵdefineComponent({
type: MyComponent, type: MyComponent,
@ -1123,12 +1126,10 @@ describe('compiler compliance', () => {
template: function MyComponent_Template(ctx: IDENT, cm: IDENT) { template: function MyComponent_Template(ctx: IDENT, cm: IDENT) {
if (cm) { if (cm) {
$r3$.ɵE(0, 'ul'); $r3$.ɵE(0, 'ul');
$r3$.ɵC(1, $c1$, MyComponent_ForOfDirective_Template_1); $r3$.ɵC(1, MyComponent_ForOfDirective_Template_1, null, $c1$);
$r3$.ɵe(); $r3$.ɵe();
} }
$r3$.ɵp(1, 'forOf', $r3$.ɵb(ctx.items)); $r3$.ɵp(1, 'forOf', $r3$.ɵb(ctx.items));
$r3$.ɵcR(1);
$r3$.ɵcr();
function MyComponent_ForOfDirective_Template_1(ctx0: IDENT, cm: IDENT) { function MyComponent_ForOfDirective_Template_1(ctx0: IDENT, cm: IDENT) {
if (cm) { if (cm) {
@ -1137,15 +1138,13 @@ describe('compiler compliance', () => {
$r3$.ɵT(2); $r3$.ɵT(2);
$r3$.ɵe(); $r3$.ɵe();
$r3$.ɵE(3, 'ul'); $r3$.ɵE(3, 'ul');
$r3$.ɵC(4, $c1$, MyComponent_ForOfDirective_ForOfDirective_Template_4); $r3$.ɵC(4, MyComponent_ForOfDirective_ForOfDirective_Template_4, null, $c1$);
$r3$.ɵe(); $r3$.ɵe();
$r3$.ɵe(); $r3$.ɵe();
} }
const $item$ = ctx0.$implicit; const $item$ = ctx0.$implicit;
$r3$.ɵp(4, 'forOf', $r3$.ɵb(IDENT.infos)); $r3$.ɵp(4, 'forOf', $r3$.ɵb(IDENT.infos));
$r3$.ɵt(2, $r3$.ɵi1('', IDENT.name, '')); $r3$.ɵt(2, $r3$.ɵi1('', IDENT.name, ''));
$r3$.ɵcR(4);
$r3$.ɵcr();
function MyComponent_ForOfDirective_ForOfDirective_Template_4( function MyComponent_ForOfDirective_ForOfDirective_Template_4(
ctx1: IDENT, cm: IDENT) { ctx1: IDENT, cm: IDENT) {
@ -1158,7 +1157,8 @@ describe('compiler compliance', () => {
$r3$.ɵt(1, $r3$.ɵi2(' ', $item$.name, ': ', $info$.description, ' ')); $r3$.ɵt(1, $r3$.ɵi2(' ', $item$.name, ': ', $info$.description, ' '));
} }
} }
} },
directives: [ForOfDirective]
});`; });`;
const result = compile(files, angularFiles); const result = compile(files, angularFiles);

View File

@ -14,6 +14,7 @@ export {
detectChanges as ɵdetectChanges, detectChanges as ɵdetectChanges,
renderComponent as ɵrenderComponent, renderComponent as ɵrenderComponent,
ComponentType as ɵComponentType, ComponentType as ɵComponentType,
DirectiveType as ɵDirectiveType,
directiveInject as ɵdirectiveInject, directiveInject as ɵdirectiveInject,
injectTemplateRef as ɵinjectTemplateRef, injectTemplateRef as ɵinjectTemplateRef,
injectViewContainerRef as ɵinjectViewContainerRef, injectViewContainerRef as ɵinjectViewContainerRef,
@ -73,6 +74,9 @@ export {
st as ɵst, st as ɵst,
ld as ɵld, ld as ɵld,
Pp as ɵPp, Pp as ɵPp,
ComponentDef as ɵComponentDef,
DirectiveDef as ɵDirectiveDef,
PipeDef as ɵPipeDef,
} from './render3/index'; } from './render3/index';
export { export {
bypassSanitizationTrustHtml as ɵbypassSanitizationTrustHtml, bypassSanitizationTrustHtml as ɵbypassSanitizationTrustHtml,

View File

@ -62,5 +62,6 @@ export function assertComponentType(
} }
function throwError(msg: string): never { function throwError(msg: string): never {
debugger; // Left intentionally for better debugger experience.
throw new Error(`ASSERTION ERROR: ${msg}`); throw new Error(`ASSERTION ERROR: ${msg}`);
} }

View File

@ -16,7 +16,7 @@ import {Type} from '../type';
import {resolveRendererType2} from '../view/util'; import {resolveRendererType2} from '../view/util';
import {diPublic} from './di'; import {diPublic} from './di';
import {ComponentDef, ComponentDefFeature, ComponentTemplate, DirectiveDef, DirectiveDefFeature, DirectiveDefListOrFactory, PipeDef, PipeDefListOrFactory} from './interfaces/definition'; import {ComponentDef, ComponentDefFeature, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFeature, DirectiveDefListOrFactory, DirectiveType, DirectiveTypesOrFactory, PipeDef, PipeType, PipeTypesOrFactory} from './interfaces/definition';
import {CssSelectorList, SelectorFlags} from './interfaces/projection'; import {CssSelectorList, SelectorFlags} from './interfaces/projection';
@ -153,7 +153,7 @@ export function defineComponent<T>(componentDefinition: {
* The property is either an array of `DirectiveDef`s or a function which returns the array of * The property is either an array of `DirectiveDef`s or a function which returns the array of
* `DirectiveDef`s. The function is necessary to be able to support forward declarations. * `DirectiveDef`s. The function is necessary to be able to support forward declarations.
*/ */
directiveDefs?: DirectiveDefListOrFactory | null; directives?: DirectiveTypesOrFactory | null;
/** /**
* Registry of pipes that may be found in this component's view. * Registry of pipes that may be found in this component's view.
@ -161,9 +161,11 @@ export function defineComponent<T>(componentDefinition: {
* The property is either an array of `PipeDefs`s or a function which returns the array of * The property is either an array of `PipeDefs`s or a function which returns the array of
* `PipeDefs`s. The function is necessary to be able to support forward declarations. * `PipeDefs`s. The function is necessary to be able to support forward declarations.
*/ */
pipeDefs?: PipeDefListOrFactory | null; pipes?: PipeTypesOrFactory | null;
}): ComponentDef<T> { }): ComponentDef<T> {
const type = componentDefinition.type; const type = componentDefinition.type;
const pipeTypes = componentDefinition.pipes !;
const directiveTypes = componentDefinition.directives !;
const def = <ComponentDef<any>>{ const def = <ComponentDef<any>>{
type: type, type: type,
diPublic: null, diPublic: null,
@ -183,8 +185,13 @@ export function defineComponent<T>(componentDefinition: {
afterViewChecked: type.prototype.ngAfterViewChecked || null, afterViewChecked: type.prototype.ngAfterViewChecked || null,
onDestroy: type.prototype.ngOnDestroy || null, onDestroy: type.prototype.ngOnDestroy || null,
onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush, onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush,
directiveDefs: componentDefinition.directiveDefs || null, directiveDefs: directiveTypes ?
pipeDefs: componentDefinition.pipeDefs || null, () => (typeof directiveTypes === 'function' ? directiveTypes() : directiveTypes)
.map(extractDirectiveDef) :
null,
pipeDefs: pipeTypes ?
() => (typeof pipeTypes === 'function' ? pipeTypes() : pipeTypes).map(extractPipeDef) :
null,
selectors: componentDefinition.selectors selectors: componentDefinition.selectors
}; };
const feature = componentDefinition.features; const feature = componentDefinition.features;
@ -192,6 +199,24 @@ export function defineComponent<T>(componentDefinition: {
return def; return def;
} }
export function extractDirectiveDef(type: DirectiveType<any>& ComponentType<any>):
DirectiveDef<any>|ComponentDef<any> {
const def = type.ngComponentDef || type.ngDirectiveDef;
if (ngDevMode && !def) {
throw new Error(`'${type.name}' is neither 'ComponentType' or 'DirectiveType'.`);
}
return def;
}
export function extractPipeDef(type: PipeType<any>): PipeDef<any> {
const def = type.ngPipeDef;
if (ngDevMode && !def) {
throw new Error(`'${type.name}' is not a 'PipeType'.`);
}
return def;
}
const PRIVATE_PREFIX = '__ngOnChanges_'; const PRIVATE_PREFIX = '__ngOnChanges_';

View File

@ -9,7 +9,7 @@
import {LifecycleHooksFeature, createComponentRef, getHostElement, getRenderedText, renderComponent, whenRendered} from './component'; import {LifecycleHooksFeature, createComponentRef, getHostElement, getRenderedText, renderComponent, whenRendered} from './component';
import {NgOnChangesFeature, PublicFeature, defineComponent, defineDirective, definePipe} from './definition'; import {NgOnChangesFeature, PublicFeature, defineComponent, defineDirective, definePipe} from './definition';
import {InjectFlags} from './di'; import {InjectFlags} from './di';
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveType} from './interfaces/definition'; import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefFlags, DirectiveType, PipeDef} from './interfaces/definition';
export {InjectFlags, QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF, directiveInject, injectAttribute, injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from './di'; export {InjectFlags, QUERY_READ_CONTAINER_REF, QUERY_READ_ELEMENT_REF, QUERY_READ_FROM_NODE, QUERY_READ_TEMPLATE_REF, directiveInject, injectAttribute, injectChangeDetectorRef, injectElementRef, injectTemplateRef, injectViewContainerRef} from './di';
export {CssSelectorList} from './interfaces/projection'; export {CssSelectorList} from './interfaces/projection';
@ -111,6 +111,7 @@ export {
DirectiveType, DirectiveType,
NgOnChangesFeature, NgOnChangesFeature,
PublicFeature, PublicFeature,
PipeDef,
LifecycleHooksFeature, LifecycleHooksFeature,
defineComponent, defineComponent,
defineDirective, defineDirective,

View File

@ -400,7 +400,8 @@ function resetApplicationState() {
* @param context to pass into the template. * @param context to pass into the template.
* @param providedRendererFactory renderer factory to use * @param providedRendererFactory renderer factory to use
* @param host The host element node to use * @param host The host element node to use
* @param defs Any directive or pipe defs that should be used for matching * @param directives Directive defs that should be used for matching
* @param pipes Pipe defs that should be used for matching
*/ */
export function renderTemplate<T>( export function renderTemplate<T>(
hostNode: RElement, template: ComponentTemplate<T>, context: T, hostNode: RElement, template: ComponentTemplate<T>, context: T,

View File

@ -223,6 +223,12 @@ export type DirectiveDefListOrFactory = (() => DirectiveDefList) | DirectiveDefL
export type DirectiveDefList = (DirectiveDef<any>| ComponentDef<any>)[]; export type DirectiveDefList = (DirectiveDef<any>| ComponentDef<any>)[];
export type DirectiveTypesOrFactory = (() => DirectiveTypeList) | DirectiveTypeList;
export type DirectiveTypeList =
(DirectiveDef<any>| ComponentDef<any>|
Type<any>/* Type as workaround for: Microsoft/TypeScript/issues/4881 */)[];
/** /**
* Type used for PipeDefs on component definition. * Type used for PipeDefs on component definition.
* *
@ -232,6 +238,12 @@ export type PipeDefListOrFactory = (() => PipeDefList) | PipeDefList;
export type PipeDefList = PipeDef<any>[]; export type PipeDefList = PipeDef<any>[];
export type PipeTypesOrFactory = (() => DirectiveTypeList) | DirectiveTypeList;
export type PipeTypeList =
(PipeDef<any>| Type<any>/* Type as workaround for: Microsoft/TypeScript/issues/4881 */)[];
// Note: This hack is necessary so we don't erroneously get a circular dependency // Note: This hack is necessary so we don't erroneously get a circular dependency
// failure based on types. // failure based on types.
export const unusedValueExportToPlacateAjd = 1; export const unusedValueExportToPlacateAjd = 1;

View File

@ -133,7 +133,7 @@ describe('change detection', () => {
} }
elementProperty(0, 'name', bind(ctx.name)); elementProperty(0, 'name', bind(ctx.name));
}, },
directiveDefs: () => [MyComponent.ngComponentDef] directives: () => [MyComponent]
}); });
} }
@ -203,7 +203,7 @@ describe('change detection', () => {
{ listener('click', () => noop()); } { listener('click', () => noop()); }
elementEnd(); elementEnd();
} }
}, [MyComponent.ngComponentDef]); }, [MyComponent]);
const buttonParent = renderComponent(ButtonParent); const buttonParent = renderComponent(ButtonParent);
expect(getRenderedText(buttonParent)).toEqual('1 - Nancy'); expect(getRenderedText(buttonParent)).toEqual('1 - Nancy');
@ -234,7 +234,7 @@ describe('change detection', () => {
} }
textBinding(0, interpolation1('', ctx.doCheckCount, ' - ')); textBinding(0, interpolation1('', ctx.doCheckCount, ' - '));
}, },
directiveDefs: () => [MyComponent.ngComponentDef], directives: () => [MyComponent],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}); });
} }
@ -244,7 +244,7 @@ describe('change detection', () => {
elementStart(0, 'button-parent'); elementStart(0, 'button-parent');
elementEnd(); elementEnd();
} }
}, [ButtonParent.ngComponentDef]); }, [ButtonParent]);
const myButtonApp = renderComponent(MyButtonApp); const myButtonApp = renderComponent(MyButtonApp);
expect(parent !.doCheckCount).toEqual(1); expect(parent !.doCheckCount).toEqual(1);
@ -318,7 +318,7 @@ describe('change detection', () => {
} }
textBinding(0, interpolation1('', ctx.doCheckCount, ' - ')); textBinding(0, interpolation1('', ctx.doCheckCount, ' - '));
}, },
directiveDefs: () => [MyComp.ngComponentDef] directives: () => [MyComp]
}); });
} }
@ -393,7 +393,7 @@ describe('change detection', () => {
elementStart(0, 'my-comp', ['dir', '']); elementStart(0, 'my-comp', ['dir', '']);
elementEnd(); elementEnd();
} }
}, [MyComp.ngComponentDef, Dir.ngDirectiveDef]); }, [MyComp, Dir]);
const app = renderComponent(MyApp); const app = renderComponent(MyApp);
expect(getRenderedText(app)).toEqual('Nancy'); expect(getRenderedText(app)).toEqual('Nancy');
@ -415,7 +415,7 @@ describe('change detection', () => {
elementEnd(); elementEnd();
} }
textBinding(1, bind(ctx.value)); textBinding(1, bind(ctx.value));
}, [Dir.ngDirectiveDef]); }, [Dir]);
const app = renderComponent(MyApp); const app = renderComponent(MyApp);
app.value = 'Frank'; app.value = 'Frank';
@ -462,7 +462,7 @@ describe('change detection', () => {
} }
containerRefreshEnd(); containerRefreshEnd();
}, },
directiveDefs: [Dir.ngDirectiveDef] directives: [Dir]
}); });
} }
@ -551,7 +551,7 @@ describe('change detection', () => {
elementEnd(); elementEnd();
} }
}, },
directiveDefs: () => [DetachedComp.ngComponentDef] directives: () => [DetachedComp]
}); });
} }
@ -682,7 +682,7 @@ describe('change detection', () => {
elementEnd(); elementEnd();
} }
elementProperty(0, 'value', bind(ctx.value)); elementProperty(0, 'value', bind(ctx.value));
}, [OnPushComp.ngComponentDef]); }, [OnPushComp]);
const app = renderComponent(OnPushApp); const app = renderComponent(OnPushApp);
app.value = 'one'; app.value = 'one';
@ -749,7 +749,7 @@ describe('change detection', () => {
} }
textBinding(0, interpolation1('', ctx.value, ' - ')); textBinding(0, interpolation1('', ctx.value, ' - '));
}, },
directiveDefs: () => [OnPushComp.ngComponentDef], directives: () => [OnPushComp],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}); });
} }
@ -828,7 +828,7 @@ describe('change detection', () => {
} }
containerRefreshEnd(); containerRefreshEnd();
}, },
directiveDefs: () => [OnPushComp.ngComponentDef], directives: () => [OnPushComp],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}); });
} }
@ -907,7 +907,7 @@ describe('change detection', () => {
} }
textBinding(0, interpolation1('', ctx.value, ' - ')); textBinding(0, interpolation1('', ctx.value, ' - '));
}, },
directiveDefs: () => [NoChangesComp.ngComponentDef] directives: () => [NoChangesComp]
}); });
} }

View File

@ -46,7 +46,7 @@ describe('@angular/common integration', () => {
textBinding(1, bind(row.$implicit)); textBinding(1, bind(row.$implicit));
} }
}, },
directiveDefs: () => [NgForOf.ngDirectiveDef] directives: () => [NgForOf]
}); });
} }

View File

@ -88,7 +88,7 @@ describe('content projection', () => {
$r3$.ɵe(); $r3$.ɵe();
} }
}, },
directiveDefs: () => [SimpleComponent.ngComponentDef] directives: () => [SimpleComponent]
}); });
} }
}); });

View File

@ -56,7 +56,7 @@ describe('injection', () => {
$r3$.ɵe(); $r3$.ɵe();
} }
}, },
directiveDefs: () => [MyComp.ngComponentDef] directives: () => [MyComp]
}); });
} }
@ -101,7 +101,7 @@ describe('injection', () => {
$r3$.ɵe(); $r3$.ɵe();
} }
}, },
directiveDefs: () => [MyComp.ngComponentDef] directives: () => [MyComp]
}); });
} }
const e0_attrs = ['title', 'WORKS']; const e0_attrs = ['title', 'WORKS'];

View File

@ -113,7 +113,7 @@ describe('component with a container', () => {
elementProperty(0, 'items', bind(ctx.items)); elementProperty(0, 'items', bind(ctx.items));
} }
const defs = [WrapperComponent.ngComponentDef]; const defs = [WrapperComponent];
it('should re-render on input change', () => { it('should re-render on input change', () => {
const ctx: {items: string[]} = {items: ['a']}; const ctx: {items: string[]} = {items: ['a']};
@ -139,7 +139,7 @@ describe('encapsulation', () => {
} }
}, },
factory: () => new WrapperComponent, factory: () => new WrapperComponent,
directiveDefs: () => [EncapsulatedComponent.ngComponentDef] directives: () => [EncapsulatedComponent]
}); });
} }
@ -157,7 +157,7 @@ describe('encapsulation', () => {
factory: () => new EncapsulatedComponent, factory: () => new EncapsulatedComponent,
rendererType: rendererType:
createRendererType2({encapsulation: ViewEncapsulation.Emulated, styles: [], data: {}}), createRendererType2({encapsulation: ViewEncapsulation.Emulated, styles: [], data: {}}),
directiveDefs: () => [LeafComponent.ngComponentDef] directives: () => [LeafComponent]
}); });
} }
@ -204,7 +204,7 @@ describe('encapsulation', () => {
factory: () => new WrapperComponentWith, factory: () => new WrapperComponentWith,
rendererType: rendererType:
createRendererType2({encapsulation: ViewEncapsulation.Emulated, styles: [], data: {}}), createRendererType2({encapsulation: ViewEncapsulation.Emulated, styles: [], data: {}}),
directiveDefs: () => [LeafComponentwith.ngComponentDef] directives: () => [LeafComponentwith]
}); });
} }

View File

@ -37,7 +37,7 @@ describe('content projection', () => {
{ text(1, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)).toEqual('<child><div>content</div></child>'); expect(toHtml(parent)).toEqual('<child><div>content</div></child>');
@ -56,7 +56,7 @@ describe('content projection', () => {
{ text(1, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)).toEqual('<child>content</child>'); expect(toHtml(parent)).toEqual('<child>content</child>');
@ -78,7 +78,7 @@ describe('content projection', () => {
{ projection(2, 0); } { projection(2, 0); }
elementEnd(); elementEnd();
} }
}, [GrandChild.ngComponentDef]); }, [GrandChild]);
const Parent = createComponent('parent', function(ctx: any, cm: boolean) { const Parent = createComponent('parent', function(ctx: any, cm: boolean) {
if (cm) { if (cm) {
elementStart(0, 'child'); elementStart(0, 'child');
@ -90,7 +90,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)) expect(toHtml(parent))
@ -129,7 +129,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef, ProjectedComp.ngComponentDef]); }, [Child, ProjectedComp]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)) expect(toHtml(parent))
@ -165,7 +165,7 @@ describe('content projection', () => {
} }
} }
containerRefreshEnd(); containerRefreshEnd();
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)).toEqual('<child><div>()</div></child>'); expect(toHtml(parent)).toEqual('<child><div>()</div></child>');
@ -200,7 +200,7 @@ describe('content projection', () => {
} }
} }
containerRefreshEnd(); containerRefreshEnd();
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)).toEqual('<child></child>'); expect(toHtml(parent)).toEqual('<child></child>');
@ -248,7 +248,7 @@ describe('content projection', () => {
} }
} }
containerRefreshEnd(); containerRefreshEnd();
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)).toEqual('<child><div>(else)</div></child>'); expect(toHtml(parent)).toEqual('<child><div>(else)</div></child>');
@ -305,7 +305,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)).toEqual('<child><div><span>content</span></div></child>'); expect(toHtml(parent)).toEqual('<child><div><span>content</span></div></child>');
@ -357,7 +357,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)).toEqual('<child><div>content</div></child>'); expect(toHtml(parent)).toEqual('<child><div>content</div></child>');
@ -411,7 +411,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)).toEqual('<child><div>before-content-after</div></child>'); expect(toHtml(parent)).toEqual('<child><div>before-content-after</div></child>');
@ -447,7 +447,7 @@ describe('content projection', () => {
{ text(1, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)).toEqual('<child><div></div><span>content</span></child>'); expect(toHtml(parent)).toEqual('<child><div></div><span>content</span></child>');
@ -504,7 +504,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)).toEqual('<child>content<div></div></child>'); expect(toHtml(parent)).toEqual('<child>content<div></div></child>');
@ -554,7 +554,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)) expect(toHtml(parent))
@ -604,7 +604,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)) expect(toHtml(parent))
@ -654,7 +654,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)) expect(toHtml(parent))
@ -700,7 +700,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)) expect(toHtml(parent))
@ -745,7 +745,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)) expect(toHtml(parent))
@ -791,7 +791,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)) expect(toHtml(parent))
@ -838,7 +838,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [GrandChild.ngComponentDef]); }, [GrandChild]);
/** /**
* <child> * <child>
@ -857,7 +857,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)) expect(toHtml(parent))
@ -902,7 +902,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Card.ngComponentDef]); }, [Card]);
/** /**
* <card-with-title> * <card-with-title>
@ -915,7 +915,7 @@ describe('content projection', () => {
{ text(1, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
}, [CardWithTitle.ngComponentDef]); }, [CardWithTitle]);
const app = renderComponent(App); const app = renderComponent(App);
expect(toHtml(app)) expect(toHtml(app))
@ -961,7 +961,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Card.ngComponentDef]); }, [Card]);
/** /**
* <card-with-title> * <card-with-title>
@ -974,7 +974,7 @@ describe('content projection', () => {
{ text(1, 'content'); } { text(1, 'content'); }
elementEnd(); elementEnd();
} }
}, [CardWithTitle.ngComponentDef]); }, [CardWithTitle]);
const app = renderComponent(App); const app = renderComponent(App);
expect(toHtml(app)) expect(toHtml(app))
@ -1013,7 +1013,7 @@ describe('content projection', () => {
} }
elementEnd(); elementEnd();
} }
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)).toEqual('<child><div>should project</div></child>'); expect(toHtml(parent)).toEqual('<child><div>should project</div></child>');
@ -1058,7 +1058,7 @@ describe('content projection', () => {
} }
} }
containerRefreshEnd(); containerRefreshEnd();
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Parent); const parent = renderComponent(Parent);
expect(toHtml(parent)).toEqual('<child><span><div>content</div></span></child>'); expect(toHtml(parent)).toEqual('<child><span><div>content</div></span></child>');
}); });

View File

@ -588,7 +588,7 @@ describe('JS control flow', () => {
} }
containerRefreshEnd(); containerRefreshEnd();
}, },
directiveDefs: () => [Comp.ngComponentDef] directives: () => [Comp]
}); });
} }
@ -651,7 +651,7 @@ describe('JS control flow', () => {
} }
containerRefreshEnd(); containerRefreshEnd();
}, },
directiveDefs: () => [Comp.ngComponentDef] directives: () => [Comp]
}); });
} }

View File

@ -43,8 +43,7 @@ describe('di', () => {
textBinding(2, bind(tmp.value)); textBinding(2, bind(tmp.value));
} }
expect(renderToHtml(Template, {}, [Directive.ngDirectiveDef])) expect(renderToHtml(Template, {}, [Directive])).toEqual('<div dir="">Created</div>');
.toEqual('<div dir="">Created</div>');
}); });
}); });
@ -100,8 +99,7 @@ describe('di', () => {
textBinding(3, bind(tmp.value)); textBinding(3, bind(tmp.value));
} }
const defs = const defs = [DirectiveA, DirectiveB, DirectiveC];
[DirectiveA.ngDirectiveDef, DirectiveB.ngDirectiveDef, DirectiveC.ngDirectiveDef];
expect(renderToHtml(Template, {}, defs)) expect(renderToHtml(Template, {}, defs))
.toEqual('<div dira=""><span dirb="" dirc="">AB</span></div>'); .toEqual('<div dira=""><span dirb="" dirc="">AB</span></div>');
}); });
@ -153,7 +151,7 @@ describe('di', () => {
textBinding(3, interpolation2('', tmp2.value, '-', tmp1.value, '')); textBinding(3, interpolation2('', tmp2.value, '-', tmp1.value, ''));
} }
const defs = [Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef]; const defs = [Directive, DirectiveSameInstance];
expect(renderToHtml(Template, {}, defs)) expect(renderToHtml(Template, {}, defs))
.toEqual('<div dir="" dirsame="">ElementRef-true</div>'); .toEqual('<div dir="" dirsame="">ElementRef-true</div>');
}); });
@ -204,7 +202,7 @@ describe('di', () => {
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, '')); textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, ''));
} }
const defs = [Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef]; const defs = [Directive, DirectiveSameInstance];
expect(renderToHtml(Template, {}, defs)).toEqual('TemplateRef-true'); expect(renderToHtml(Template, {}, defs)).toEqual('TemplateRef-true');
}); });
}); });
@ -256,7 +254,7 @@ describe('di', () => {
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, '')); textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, ''));
} }
const defs = [Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef]; const defs = [Directive, DirectiveSameInstance];
expect(renderToHtml(Template, {}, defs)) expect(renderToHtml(Template, {}, defs))
.toEqual('<div dir="" dirsame="">ViewContainerRef-true</div>'); .toEqual('<div dir="" dirsame="">ViewContainerRef-true</div>');
}); });
@ -327,10 +325,7 @@ describe('di', () => {
} }
const defs = [ const directives = [MyComp, Directive, DirectiveSameInstance, IfDirective];
MyComp.ngComponentDef, Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef,
IfDirective.ngDirectiveDef
];
it('should inject current component ChangeDetectorRef into directives on components', () => { it('should inject current component ChangeDetectorRef into directives on components', () => {
/** <my-comp dir dirSameInstance #dir="dir"></my-comp> {{ dir.value }} */ /** <my-comp dir dirSameInstance #dir="dir"></my-comp> {{ dir.value }} */
@ -342,7 +337,7 @@ describe('di', () => {
} }
const tmp = load(1) as any; const tmp = load(1) as any;
textBinding(2, bind(tmp.value)); textBinding(2, bind(tmp.value));
}, defs); }, directives);
const app = renderComponent(MyApp); const app = renderComponent(MyApp);
// ChangeDetectorRef is the token, ViewRef has historically been the constructor // ChangeDetectorRef is the token, ViewRef has historically been the constructor
@ -372,7 +367,7 @@ describe('di', () => {
const tmp = load(1) as any; const tmp = load(1) as any;
textBinding(2, bind(tmp.value)); textBinding(2, bind(tmp.value));
}, },
directiveDefs: defs directives: directives
}); });
} }
@ -411,7 +406,7 @@ describe('di', () => {
const tmp = load(2) as any; const tmp = load(2) as any;
textBinding(3, bind(tmp.value)); textBinding(3, bind(tmp.value));
}, },
directiveDefs: defs directives: directives
}); });
} }
@ -458,7 +453,7 @@ describe('di', () => {
} }
containerRefreshEnd(); containerRefreshEnd();
}, },
directiveDefs: defs directives: directives
}); });
} }
@ -498,7 +493,7 @@ describe('di', () => {
textBinding(2, bind(tmp.value)); textBinding(2, bind(tmp.value));
} }
}, },
directiveDefs: defs directives: directives
}); });
} }
@ -675,10 +670,7 @@ describe('di', () => {
containerRefreshEnd(); containerRefreshEnd();
} }
const defs = [ const defs = [ChildDirective, Child2Directive, ParentDirective];
ChildDirective.ngDirectiveDef, Child2Directive.ngDirectiveDef,
ParentDirective.ngDirectiveDef
];
expect(renderToHtml(Template, {}, defs)) expect(renderToHtml(Template, {}, defs))
.toEqual('<div parentdir=""><span child2dir="" childdir="">Directive-true</span></div>'); .toEqual('<div parentdir=""><span child2dir="" childdir="">Directive-true</span></div>');
}); });

View File

@ -38,7 +38,7 @@ describe('directive', () => {
} }
} }
const defs = [Directive.ngDirectiveDef]; const defs = [Directive];
expect(renderToHtml(Template, {}, defs)).toEqual('<span class="foo" dir=""></span>'); expect(renderToHtml(Template, {}, defs)).toEqual('<span class="foo" dir=""></span>');
directiveInstance !.klass = 'bar'; directiveInstance !.klass = 'bar';
expect(renderToHtml(Template, {}, defs)).toEqual('<span class="bar" dir=""></span>'); expect(renderToHtml(Template, {}, defs)).toEqual('<span class="bar" dir=""></span>');

View File

@ -52,7 +52,7 @@ describe('exports', () => {
}); });
} }
expect(renderToHtml(Template, {}, [MyComponent.ngComponentDef])).toEqual('<comp></comp>Nancy'); expect(renderToHtml(Template, {}, [MyComponent])).toEqual('<comp></comp>Nancy');
}); });
it('should support component instance fed into directive', () => { it('should support component instance fed into directive', () => {
@ -80,7 +80,7 @@ describe('exports', () => {
}); });
} }
const defs = [MyComponent.ngComponentDef, MyDir.ngDirectiveDef]; const defs = [MyComponent, MyDir];
/** <comp #myComp></comp> <div [myDir]="myComp"></div> */ /** <comp #myComp></comp> <div [myDir]="myComp"></div> */
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
@ -121,8 +121,7 @@ describe('exports', () => {
}); });
} }
expect(renderToHtml(Template, {}, [SomeDir.ngDirectiveDef])) expect(renderToHtml(Template, {}, [SomeDir])).toEqual('<div somedir=""></div>Drew');
.toEqual('<div somedir=""></div>Drew');
}); });
it('should throw if export name is not found', () => { it('should throw if export name is not found', () => {
@ -247,7 +246,7 @@ describe('exports', () => {
elementProperty(0, 'myDir', bind(tmp)); elementProperty(0, 'myDir', bind(tmp));
} }
renderToHtml(Template, {}, [MyComponent.ngComponentDef, MyDir.ngDirectiveDef]); renderToHtml(Template, {}, [MyComponent, MyDir]);
expect(myDir !.myDir).toEqual(myComponent !); expect(myDir !.myDir).toEqual(myComponent !);
}); });
@ -283,7 +282,7 @@ describe('exports', () => {
factory: () => new MyComponent factory: () => new MyComponent
}); });
} }
expect(renderToHtml(Template, {}, [MyComponent.ngComponentDef])) expect(renderToHtml(Template, {}, [MyComponent]))
.toEqual('oneNancy<comp></comp><input value="one">'); .toEqual('oneNancy<comp></comp><input value="one">');
}); });

View File

@ -194,7 +194,7 @@ describe('render3 integration test', () => {
}); });
} }
const defs = [TodoComponent.ngComponentDef]; const defs = [TodoComponent];
it('should support a basic component template', () => { it('should support a basic component template', () => {
function Template(ctx: any, cm: boolean) { function Template(ctx: any, cm: boolean) {
@ -267,7 +267,7 @@ describe('render3 integration test', () => {
} }
} }
const defs = [TodoComponentHostBinding.ngComponentDef]; const defs = [TodoComponentHostBinding];
expect(renderToHtml(Template, {}, defs)).toEqual('<todo title="one">one</todo>'); expect(renderToHtml(Template, {}, defs)).toEqual('<todo title="one">one</todo>');
cmptInstance !.title = 'two'; cmptInstance !.title = 'two';
expect(renderToHtml(Template, {}, defs)).toEqual('<todo title="two">two</todo>'); expect(renderToHtml(Template, {}, defs)).toEqual('<todo title="two">two</todo>');
@ -314,8 +314,7 @@ describe('render3 integration test', () => {
} }
} }
expect(renderToHtml(Template, null, [MyComp.ngComponentDef])) expect(renderToHtml(Template, null, [MyComp])).toEqual('<comp><p>Bess</p></comp>');
.toEqual('<comp><p>Bess</p></comp>');
}); });
it('should support a component with sub-views', () => { it('should support a component with sub-views', () => {
@ -360,7 +359,7 @@ describe('render3 integration test', () => {
elementProperty(0, 'condition', bind(ctx.condition)); elementProperty(0, 'condition', bind(ctx.condition));
} }
const defs = [MyComp.ngComponentDef]; const defs = [MyComp];
expect(renderToHtml(Template, {condition: true}, defs)) expect(renderToHtml(Template, {condition: true}, defs))
.toEqual('<comp><div>text</div></comp>'); .toEqual('<comp><div>text</div></comp>');
expect(renderToHtml(Template, {condition: false}, defs)).toEqual('<comp></comp>'); expect(renderToHtml(Template, {condition: false}, defs)).toEqual('<comp></comp>');
@ -488,7 +487,7 @@ describe('render3 integration test', () => {
projectedTree: {beforeLabel: 'p'}, projectedTree: {beforeLabel: 'p'},
afterTree: {afterLabel: 'z'} afterTree: {afterLabel: 'z'}
}; };
const defs = [ChildComponent.ngComponentDef]; const defs = [ChildComponent];
expect(renderToHtml(parentTemplate, ctx, defs)).toEqual('<child>apz</child>'); expect(renderToHtml(parentTemplate, ctx, defs)).toEqual('<child>apz</child>');
ctx.projectedTree = {subTrees: [{}, {}, {subTrees: [{}, {}]}, {}]}; ctx.projectedTree = {subTrees: [{}, {}, {subTrees: [{}, {}]}, {}]};
ctx.beforeTree.subTrees !.push({afterLabel: 'b'}); ctx.beforeTree.subTrees !.push({afterLabel: 'b'});
@ -658,7 +657,7 @@ describe('render3 integration test', () => {
} }
} }
const defs = [HostBindingDir.ngDirectiveDef]; const defs = [HostBindingDir];
expect(renderToHtml(Template, {}, defs)) expect(renderToHtml(Template, {}, defs))
.toEqual(`<div aria-label="some label" hostbindingdir=""></div>`); .toEqual(`<div aria-label="some label" hostbindingdir=""></div>`);

View File

@ -37,7 +37,7 @@ describe('lifecycles', () => {
elementEnd(); elementEnd();
} }
}); });
let Parent = createOnInitComponent('parent', getParentTemplate('comp'), [Comp.ngComponentDef]); let Parent = createOnInitComponent('parent', getParentTemplate('comp'), [Comp]);
let ProjectedComp = createOnInitComponent('projected', (ctx: any, cm: boolean) => { let ProjectedComp = createOnInitComponent('projected', (ctx: any, cm: boolean) => {
if (cm) { if (cm) {
text(0, 'content'); text(0, 'content');
@ -45,7 +45,7 @@ describe('lifecycles', () => {
}); });
function createOnInitComponent( function createOnInitComponent(
name: string, template: ComponentTemplate<any>, defs: any[] = []) { name: string, template: ComponentTemplate<any>, directives: any[] = []) {
return class Component { return class Component {
val: string = ''; val: string = '';
ngOnInit() { events.push(`${name}${this.val}`); } ngOnInit() { events.push(`${name}${this.val}`); }
@ -55,7 +55,7 @@ describe('lifecycles', () => {
selectors: [[name]], selectors: [[name]],
factory: () => new Component(), factory: () => new Component(),
inputs: {val: 'val'}, template, inputs: {val: 'val'}, template,
directiveDefs: defs directives: directives
}); });
}; };
} }
@ -67,10 +67,7 @@ describe('lifecycles', () => {
{type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()}); {type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()});
} }
const defs = [ const directives = [Comp, Parent, ProjectedComp, Directive];
Comp.ngComponentDef, Parent.ngComponentDef, ProjectedComp.ngComponentDef,
Directive.ngDirectiveDef
];
it('should call onInit method after inputs are set in creation mode (and not in update mode)', it('should call onInit method after inputs are set in creation mode (and not in update mode)',
() => { () => {
@ -83,10 +80,10 @@ describe('lifecycles', () => {
elementProperty(0, 'val', bind(ctx.val)); elementProperty(0, 'val', bind(ctx.val));
} }
renderToHtml(Template, {val: '1'}, defs); renderToHtml(Template, {val: '1'}, directives);
expect(events).toEqual(['comp1']); expect(events).toEqual(['comp1']);
renderToHtml(Template, {val: '2'}, defs); renderToHtml(Template, {val: '2'}, directives);
expect(events).toEqual(['comp1']); expect(events).toEqual(['comp1']);
}); });
@ -112,7 +109,7 @@ describe('lifecycles', () => {
} }
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['parent', 'comp']); expect(events).toEqual(['parent', 'comp']);
}); });
@ -135,7 +132,7 @@ describe('lifecycles', () => {
elementProperty(1, 'val', 2); elementProperty(1, 'val', 2);
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['parent1', 'parent2', 'comp1', 'comp2']); expect(events).toEqual(['parent1', 'parent2', 'comp1', 'comp2']);
}); });
@ -164,13 +161,13 @@ describe('lifecycles', () => {
containerRefreshEnd(); containerRefreshEnd();
} }
renderToHtml(Template, {condition: true}, defs); renderToHtml(Template, {condition: true}, directives);
expect(events).toEqual(['comp']); expect(events).toEqual(['comp']);
renderToHtml(Template, {condition: false}, defs); renderToHtml(Template, {condition: false}, directives);
expect(events).toEqual(['comp']); expect(events).toEqual(['comp']);
renderToHtml(Template, {condition: true}, defs); renderToHtml(Template, {condition: true}, directives);
expect(events).toEqual(['comp', 'comp']); expect(events).toEqual(['comp', 'comp']);
}); });
@ -188,7 +185,7 @@ describe('lifecycles', () => {
} }
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['comp', 'projected']); expect(events).toEqual(['comp', 'projected']);
}); });
@ -216,7 +213,7 @@ describe('lifecycles', () => {
elementProperty(3, 'val', 2); elementProperty(3, 'val', 2);
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['comp1', 'projected1', 'comp2', 'projected2']); expect(events).toEqual(['comp1', 'projected1', 'comp2', 'projected2']);
}); });
@ -229,10 +226,10 @@ describe('lifecycles', () => {
} }
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['comp', 'dir']); expect(events).toEqual(['comp', 'dir']);
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['comp', 'dir']); expect(events).toEqual(['comp', 'dir']);
}); });
@ -246,10 +243,10 @@ describe('lifecycles', () => {
} }
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['dir']); expect(events).toEqual(['dir']);
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['dir']); expect(events).toEqual(['dir']);
}); });
@ -286,7 +283,7 @@ describe('lifecycles', () => {
containerRefreshEnd(); containerRefreshEnd();
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
// onInit is called top to bottom, so top level comps (1 and 5) are called // onInit is called top to bottom, so top level comps (1 and 5) are called
// before the comps inside the for loop's embedded view (2, 3, and 4) // before the comps inside the for loop's embedded view (2, 3, and 4)
@ -326,7 +323,7 @@ describe('lifecycles', () => {
containerRefreshEnd(); containerRefreshEnd();
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
// onInit is called top to bottom, so top level comps (1 and 5) are called // onInit is called top to bottom, so top level comps (1 and 5) are called
// before the comps inside the for loop's embedded view (2, 3, and 4) // before the comps inside the for loop's embedded view (2, 3, and 4)
@ -348,10 +345,10 @@ describe('lifecycles', () => {
}); });
let Comp = createDoCheckComponent('comp', (ctx: any, cm: boolean) => {}); let Comp = createDoCheckComponent('comp', (ctx: any, cm: boolean) => {});
let Parent = createDoCheckComponent('parent', getParentTemplate('comp'), [Comp.ngComponentDef]); let Parent = createDoCheckComponent('parent', getParentTemplate('comp'), [Comp]);
function createDoCheckComponent( function createDoCheckComponent(
name: string, template: ComponentTemplate<any>, defs: any[] = []) { name: string, template: ComponentTemplate<any>, directives: any[] = []) {
return class Component { return class Component {
ngDoCheck() { ngDoCheck() {
events.push(name); events.push(name);
@ -364,7 +361,7 @@ describe('lifecycles', () => {
type: Component, type: Component,
selectors: [[name]], selectors: [[name]],
factory: () => new Component(), template, factory: () => new Component(), template,
directiveDefs: defs directives: directives
}); });
}; };
} }
@ -376,7 +373,7 @@ describe('lifecycles', () => {
{type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()}); {type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()});
} }
const defs = [Comp.ngComponentDef, Parent.ngComponentDef, Directive.ngDirectiveDef]; const directives = [Comp, Parent, Directive];
it('should call doCheck on every refresh', () => { it('should call doCheck on every refresh', () => {
/** <comp></comp> */ /** <comp></comp> */
@ -387,10 +384,10 @@ describe('lifecycles', () => {
} }
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['comp']); expect(events).toEqual(['comp']);
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['comp', 'comp']); expect(events).toEqual(['comp', 'comp']);
}); });
@ -416,7 +413,7 @@ describe('lifecycles', () => {
} }
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['parent', 'comp']); expect(events).toEqual(['parent', 'comp']);
}); });
@ -429,10 +426,10 @@ describe('lifecycles', () => {
} }
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(allEvents).toEqual(['init comp', 'check comp']); expect(allEvents).toEqual(['init comp', 'check comp']);
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(allEvents).toEqual(['init comp', 'check comp', 'check comp']); expect(allEvents).toEqual(['init comp', 'check comp', 'check comp']);
}); });
@ -445,10 +442,10 @@ describe('lifecycles', () => {
} }
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['comp', 'dir']); expect(events).toEqual(['comp', 'dir']);
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['comp', 'dir', 'comp', 'dir']); expect(events).toEqual(['comp', 'dir', 'comp', 'dir']);
}); });
@ -462,10 +459,10 @@ describe('lifecycles', () => {
} }
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['dir']); expect(events).toEqual(['dir']);
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['dir', 'dir']); expect(events).toEqual(['dir', 'dir']);
}); });
@ -495,7 +492,7 @@ describe('lifecycles', () => {
elementEnd(); elementEnd();
} }
elementProperty(1, 'val', bind(ctx.val)); elementProperty(1, 'val', bind(ctx.val));
}, [Comp.ngComponentDef]); }, [Comp]);
let ProjectedComp = createAfterContentInitComp('projected', (ctx: any, cm: boolean) => { let ProjectedComp = createAfterContentInitComp('projected', (ctx: any, cm: boolean) => {
if (cm) { if (cm) {
@ -505,7 +502,7 @@ describe('lifecycles', () => {
}); });
function createAfterContentInitComp( function createAfterContentInitComp(
name: string, template: ComponentTemplate<any>, defs: any[] = []) { name: string, template: ComponentTemplate<any>, directives: any[] = []) {
return class Component { return class Component {
val: string = ''; val: string = '';
ngAfterContentInit() { ngAfterContentInit() {
@ -520,7 +517,7 @@ describe('lifecycles', () => {
factory: () => new Component(), factory: () => new Component(),
inputs: {val: 'val'}, inputs: {val: 'val'},
template: template, template: template,
directiveDefs: defs directives: directives
}); });
}; };
} }
@ -560,10 +557,7 @@ describe('lifecycles', () => {
containerRefreshEnd(); containerRefreshEnd();
} }
const defs = [ const directives = [Comp, Parent, ProjectedComp, Directive];
Comp.ngComponentDef, Parent.ngComponentDef, ProjectedComp.ngComponentDef,
Directive.ngDirectiveDef
];
it('should be called only in creation mode', () => { it('should be called only in creation mode', () => {
/** <comp>content</comp> */ /** <comp>content</comp> */
@ -575,10 +569,10 @@ describe('lifecycles', () => {
} }
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['comp']); expect(events).toEqual(['comp']);
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['comp']); expect(events).toEqual(['comp']);
}); });
@ -615,13 +609,13 @@ describe('lifecycles', () => {
containerRefreshEnd(); containerRefreshEnd();
} }
renderToHtml(Template, {condition: true}, defs); renderToHtml(Template, {condition: true}, directives);
expect(events).toEqual(['comp']); expect(events).toEqual(['comp']);
renderToHtml(Template, {condition: false}, defs); renderToHtml(Template, {condition: false}, directives);
expect(events).toEqual(['comp']); expect(events).toEqual(['comp']);
renderToHtml(Template, {condition: true}, defs); renderToHtml(Template, {condition: true}, directives);
expect(events).toEqual(['comp', 'comp']); expect(events).toEqual(['comp', 'comp']);
}); });
@ -639,7 +633,7 @@ describe('lifecycles', () => {
} }
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['parent', 'comp']); expect(events).toEqual(['parent', 'comp']);
}); });
@ -663,7 +657,7 @@ describe('lifecycles', () => {
elementProperty(2, 'val', 2); elementProperty(2, 'val', 2);
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['parent1', 'parent2', 'comp1', 'comp2']); expect(events).toEqual(['parent1', 'parent2', 'comp1', 'comp2']);
}); });
@ -690,7 +684,7 @@ describe('lifecycles', () => {
} }
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['projected', 'parent', 'comp']); expect(events).toEqual(['projected', 'parent', 'comp']);
}); });
@ -731,7 +725,7 @@ describe('lifecycles', () => {
elementProperty(4, 'val', 2); elementProperty(4, 'val', 2);
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['projected1', 'parent1', 'projected2', 'parent2', 'comp1', 'comp2']); expect(events).toEqual(['projected1', 'parent1', 'projected2', 'parent2', 'comp1', 'comp2']);
}); });
@ -770,7 +764,7 @@ describe('lifecycles', () => {
containerRefreshEnd(); containerRefreshEnd();
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['comp2', 'comp3', 'comp1', 'comp4']); expect(events).toEqual(['comp2', 'comp3', 'comp1', 'comp4']);
}); });
@ -783,7 +777,7 @@ describe('lifecycles', () => {
* <parent [val]="4">content</parent> * <parent [val]="4">content</parent>
*/ */
renderToHtml(ForLoopWithChildrenTemplate, {}, defs); renderToHtml(ForLoopWithChildrenTemplate, {}, directives);
expect(events).toEqual( expect(events).toEqual(
['parent2', 'comp2', 'parent3', 'comp3', 'parent1', 'parent4', 'comp1', 'comp4']); ['parent2', 'comp2', 'parent3', 'comp3', 'parent1', 'parent4', 'comp1', 'comp4']);
}); });
@ -800,10 +794,10 @@ describe('lifecycles', () => {
} }
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(allEvents).toEqual(['comp init', 'comp check']); expect(allEvents).toEqual(['comp init', 'comp check']);
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(allEvents).toEqual(['comp init', 'comp check', 'comp check']); expect(allEvents).toEqual(['comp init', 'comp check', 'comp check']);
}); });
@ -829,7 +823,7 @@ describe('lifecycles', () => {
} }
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['comp', 'init', 'check']); expect(events).toEqual(['comp', 'init', 'check']);
}); });
@ -842,7 +836,7 @@ describe('lifecycles', () => {
} }
} }
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, directives);
expect(events).toEqual(['init', 'check']); expect(events).toEqual(['init', 'check']);
}); });
}); });
@ -865,8 +859,7 @@ describe('lifecycles', () => {
elementEnd(); elementEnd();
} }
}); });
let Parent = let Parent = createAfterViewInitComponent('parent', getParentTemplate('comp'), [Comp]);
createAfterViewInitComponent('parent', getParentTemplate('comp'), [Comp.ngComponentDef]);
let ProjectedComp = createAfterViewInitComponent('projected', (ctx: any, cm: boolean) => { let ProjectedComp = createAfterViewInitComponent('projected', (ctx: any, cm: boolean) => {
if (cm) { if (cm) {
@ -875,7 +868,7 @@ describe('lifecycles', () => {
}); });
function createAfterViewInitComponent( function createAfterViewInitComponent(
name: string, template: ComponentTemplate<any>, defs: any[] = []) { name: string, template: ComponentTemplate<any>, directives: any[] = []) {
return class Component { return class Component {
val: string = ''; val: string = '';
ngAfterViewInit() { ngAfterViewInit() {
@ -890,7 +883,7 @@ describe('lifecycles', () => {
factory: () => new Component(), factory: () => new Component(),
inputs: {val: 'val'}, inputs: {val: 'val'},
template: template, template: template,
directiveDefs: defs directives: directives
}); });
}; };
} }
@ -903,10 +896,7 @@ describe('lifecycles', () => {
{type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()}); {type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()});
} }
const defs = [ const defs = [Comp, Parent, ProjectedComp, Directive];
Comp.ngComponentDef, Parent.ngComponentDef, ProjectedComp.ngComponentDef,
Directive.ngDirectiveDef
];
it('should be called on init and not in update mode', () => { it('should be called on init and not in update mode', () => {
/** <comp></comp> */ /** <comp></comp> */
@ -1079,7 +1069,7 @@ describe('lifecycles', () => {
} }
elementProperty(0, 'val', bind(ctx.val)); elementProperty(0, 'val', bind(ctx.val));
elementProperty(1, 'val', bind(ctx.val)); elementProperty(1, 'val', bind(ctx.val));
}, [Comp.ngComponentDef, ProjectedComp.ngComponentDef]); }, [Comp, ProjectedComp]);
/** /**
* <parent [val]="1"></parent> * <parent [val]="1"></parent>
@ -1096,7 +1086,7 @@ describe('lifecycles', () => {
elementProperty(1, 'val', 2); elementProperty(1, 'val', 2);
} }
renderToHtml(Template, {}, [ParentComp.ngComponentDef]); renderToHtml(Template, {}, [ParentComp]);
expect(events).toEqual(['projected1', 'comp1', 'projected2', 'comp2', 'parent1', 'parent2']); expect(events).toEqual(['projected1', 'comp1', 'projected2', 'comp2', 'parent1', 'parent2']);
}); });
@ -1302,11 +1292,10 @@ describe('lifecycles', () => {
projection(1, 0); projection(1, 0);
} }
}); });
let Parent = let Parent = createOnDestroyComponent('parent', getParentTemplate('comp'), [Comp]);
createOnDestroyComponent('parent', getParentTemplate('comp'), [Comp.ngComponentDef]);
function createOnDestroyComponent( function createOnDestroyComponent(
name: string, template: ComponentTemplate<any>, defs: any[] = []) { name: string, template: ComponentTemplate<any>, directives: any[] = []) {
return class Component { return class Component {
val: string = ''; val: string = '';
ngOnDestroy() { events.push(`${name}${this.val}`); } ngOnDestroy() { events.push(`${name}${this.val}`); }
@ -1317,7 +1306,7 @@ describe('lifecycles', () => {
factory: () => new Component(), factory: () => new Component(),
inputs: {val: 'val'}, inputs: {val: 'val'},
template: template, template: template,
directiveDefs: defs directives: directives
}); });
}; };
} }
@ -1327,7 +1316,7 @@ describe('lifecycles', () => {
elementStart(0, 'parent'); elementStart(0, 'parent');
elementEnd(); elementEnd();
} }
}, [Parent.ngComponentDef]); }, [Parent]);
const ProjectedComp = createOnDestroyComponent('projected', (ctx: any, cm: boolean) => {}); const ProjectedComp = createOnDestroyComponent('projected', (ctx: any, cm: boolean) => {});
@ -1338,10 +1327,7 @@ describe('lifecycles', () => {
{type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()}); {type: Directive, selectors: [['', 'dir', '']], factory: () => new Directive()});
} }
const defs = [ const defs = [Comp, Parent, Grandparent, ProjectedComp, Directive];
Comp.ngComponentDef, Parent.ngComponentDef, Grandparent.ngComponentDef,
ProjectedComp.ngComponentDef, Directive.ngDirectiveDef
];
it('should call destroy when view is removed', () => { it('should call destroy when view is removed', () => {
/** /**
@ -1808,7 +1794,7 @@ describe('lifecycles', () => {
} }
elementProperty(0, 'val1', bind(ctx.a)); elementProperty(0, 'val1', bind(ctx.a));
elementProperty(0, 'publicName', bind(ctx.b)); elementProperty(0, 'publicName', bind(ctx.b));
}, [Comp.ngComponentDef]); }, [Comp]);
const ProjectedComp = createOnChangesComponent('projected', (ctx: any, cm: boolean) => { const ProjectedComp = createOnChangesComponent('projected', (ctx: any, cm: boolean) => {
if (cm) { if (cm) {
text(0, 'content'); text(0, 'content');
@ -1817,7 +1803,7 @@ describe('lifecycles', () => {
function createOnChangesComponent( function createOnChangesComponent(
name: string, template: ComponentTemplate<any>, defs: any[] = []) { name: string, template: ComponentTemplate<any>, directives: any[] = []) {
return class Component { return class Component {
// @Input() val1: string; // @Input() val1: string;
// @Input('publicName') val2: string; // @Input('publicName') val2: string;
@ -1834,7 +1820,7 @@ describe('lifecycles', () => {
factory: () => new Component(), factory: () => new Component(),
features: [NgOnChangesFeature({b: 'val2'})], features: [NgOnChangesFeature({b: 'val2'})],
inputs: {a: 'val1', b: 'publicName'}, template, inputs: {a: 'val1', b: 'publicName'}, template,
directiveDefs: defs directives: directives
}); });
}; };
} }
@ -1858,10 +1844,7 @@ describe('lifecycles', () => {
}); });
} }
const defs = [ const defs = [Comp, Parent, Directive, ProjectedComp];
Comp.ngComponentDef, Parent.ngComponentDef, Directive.ngDirectiveDef,
ProjectedComp.ngComponentDef
];
it('should call onChanges method after inputs are set in creation and update mode', () => { it('should call onChanges method after inputs are set in creation and update mode', () => {
/** <comp [val1]="val1" [publicName]="val2"></comp> */ /** <comp [val1]="val1" [publicName]="val2"></comp> */
@ -2190,7 +2173,7 @@ describe('lifecycles', () => {
beforeEach(() => { events = []; }); beforeEach(() => { events = []; });
function createAllHooksComponent( function createAllHooksComponent(
name: string, template: ComponentTemplate<any>, defs: any[] = []) { name: string, template: ComponentTemplate<any>, directives: any[] = []) {
return class Component { return class Component {
val: string = ''; val: string = '';
@ -2211,7 +2194,7 @@ describe('lifecycles', () => {
factory: () => new Component(), factory: () => new Component(),
inputs: {val: 'val'}, template, inputs: {val: 'val'}, template,
features: [NgOnChangesFeature()], features: [NgOnChangesFeature()],
directiveDefs: defs directives: directives
}); });
}; };
} }
@ -2235,7 +2218,7 @@ describe('lifecycles', () => {
elementProperty(1, 'val', 2); elementProperty(1, 'val', 2);
} }
const defs = [Comp.ngComponentDef]; const defs = [Comp];
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, defs);
expect(events).toEqual([ expect(events).toEqual([
'changes comp1', 'init comp1', 'check comp1', 'changes comp2', 'init comp2', 'check comp2', 'changes comp1', 'init comp1', 'check comp1', 'changes comp2', 'init comp2', 'check comp2',
@ -2261,7 +2244,7 @@ describe('lifecycles', () => {
elementEnd(); elementEnd();
} }
elementProperty(0, 'val', bind(ctx.val)); elementProperty(0, 'val', bind(ctx.val));
}, [Comp.ngComponentDef]); }, [Comp]);
/** /**
* <parent [val]="1"></parent> * <parent [val]="1"></parent>
@ -2278,7 +2261,7 @@ describe('lifecycles', () => {
elementProperty(1, 'val', 2); elementProperty(1, 'val', 2);
} }
const defs = [Parent.ngComponentDef]; const defs = [Parent];
renderToHtml(Template, {}, defs); renderToHtml(Template, {}, defs);
expect(events).toEqual([ expect(events).toEqual([
'changes parent1', 'init parent1', 'check parent1', 'changes parent1', 'init parent1', 'check parent1',

View File

@ -252,7 +252,7 @@ describe('event listeners', () => {
} }
} }
renderToHtml(Template, {}, [HostListenerDir.ngDirectiveDef]); renderToHtml(Template, {}, [HostListenerDir]);
const button = containerEl.querySelector('button') !; const button = containerEl.querySelector('button') !;
button.click(); button.click();
expect(events).toEqual(['click!']); expect(events).toEqual(['click!']);
@ -350,7 +350,7 @@ describe('event listeners', () => {
} }
const ctx = {showing: true}; const ctx = {showing: true};
renderToHtml(Template, ctx, [MyComp.ngComponentDef]); renderToHtml(Template, ctx, [MyComp]);
const buttons = containerEl.querySelectorAll('button') !; const buttons = containerEl.querySelectorAll('button') !;
buttons[0].click(); buttons[0].click();
@ -361,7 +361,7 @@ describe('event listeners', () => {
// the child view listener should be removed when the parent view is removed // the child view listener should be removed when the parent view is removed
ctx.showing = false; ctx.showing = false;
renderToHtml(Template, ctx, [MyComp.ngComponentDef]); renderToHtml(Template, ctx, [MyComp]);
buttons[0].click(); buttons[0].click();
buttons[1].click(); buttons[1].click();
expect(comps[0] !.counter).toEqual(1); expect(comps[0] !.counter).toEqual(1);

View File

@ -69,10 +69,7 @@ describe('outputs', () => {
} }
const deps = [ const deps = [ButtonToggle, OtherDir, DestroyComp, MyButton];
ButtonToggle.ngComponentDef, OtherDir.ngDirectiveDef, DestroyComp.ngComponentDef,
MyButton.ngDirectiveDef
];
it('should call component output function when event is emitted', () => { it('should call component output function when event is emitted', () => {
/** <button-toggle (change)="onChange()"></button-toggle> */ /** <button-toggle (change)="onChange()"></button-toggle> */
@ -374,7 +371,7 @@ describe('outputs', () => {
} }
let counter = 0; let counter = 0;
const deps = [ButtonToggle.ngComponentDef, OtherChangeDir.ngDirectiveDef]; const deps = [ButtonToggle, OtherChangeDir];
renderToHtml(Template, {counter, onChange: () => counter++, change: true}, deps); renderToHtml(Template, {counter, onChange: () => counter++, change: true}, deps);
expect(otherDir !.change).toEqual(true); expect(otherDir !.change).toEqual(true);

View File

@ -30,7 +30,7 @@ describe('pipe', () => {
person = new Person(); person = new Person();
}); });
const defs = () => [CountingPipe.ngPipeDef, MultiArgPipe.ngPipeDef, CountingImpurePipe.ngPipeDef]; const pipes = () => [CountingPipe, MultiArgPipe, CountingImpurePipe];
it('should support interpolation', () => { it('should support interpolation', () => {
function Template(person: Person, cm: boolean) { function Template(person: Person, cm: boolean) {
@ -42,7 +42,7 @@ describe('pipe', () => {
} }
person.init('bob', null); person.init('bob', null);
expect(renderToHtml(Template, person, null, defs)).toEqual('bob state:0'); expect(renderToHtml(Template, person, null, pipes)).toEqual('bob state:0');
}); });
it('should throw if pipe is not found', () => { it('should throw if pipe is not found', () => {
@ -52,7 +52,7 @@ describe('pipe', () => {
pipe(1, 'randomPipeName'); pipe(1, 'randomPipeName');
} }
textBinding(0, interpolation1('', pipeBind1(1, ctx.value), '')); textBinding(0, interpolation1('', pipeBind1(1, ctx.value), ''));
}, [], defs); }, [], pipes);
expect(() => { expect(() => {
const fixture = new ComponentFixture(App); const fixture = new ComponentFixture(App);
@ -96,7 +96,7 @@ describe('pipe', () => {
elementProperty(0, 'elprop', bind(pipeBind1(1, ctx))); elementProperty(0, 'elprop', bind(pipeBind1(1, ctx)));
directive = loadDirective(0); directive = loadDirective(0);
} }
renderToHtml(Template, 'a', [MyDir.ngDirectiveDef], [DoublePipe.ngPipeDef]); renderToHtml(Template, 'a', [MyDir], [DoublePipe]);
expect(directive !.dirProp).toEqual('aa'); expect(directive !.dirProp).toEqual('aa');
}); });
@ -111,7 +111,7 @@ describe('pipe', () => {
} }
person.init('value', new Address('two')); person.init('value', new Address('two'));
expect(renderToHtml(Template, person, null, defs)).toEqual('value one two default'); expect(renderToHtml(Template, person, null, pipes)).toEqual('value one two default');
}); });
it('should support calling pipes with different number of arguments', () => { it('should support calling pipes with different number of arguments', () => {
@ -126,7 +126,7 @@ describe('pipe', () => {
} }
person.init('value', null); person.init('value', null);
expect(renderToHtml(Template, person, null, defs)).toEqual('value a b default 0 1 2'); expect(renderToHtml(Template, person, null, pipes)).toEqual('value a b default 0 1 2');
}); });
it('should do nothing when no change', () => { it('should do nothing when no change', () => {
@ -150,11 +150,11 @@ describe('pipe', () => {
elementProperty(0, 'someProp', bind(pipeBind1(1, 'Megatron'))); elementProperty(0, 'someProp', bind(pipeBind1(1, 'Megatron')));
} }
renderToHtml(Template, person, null, [IdentityPipe.ngPipeDef], rendererFactory2); renderToHtml(Template, person, null, [IdentityPipe], rendererFactory2);
expect(renderLog.log).toEqual(['someProp=Megatron']); expect(renderLog.log).toEqual(['someProp=Megatron']);
renderLog.clear(); renderLog.clear();
renderToHtml(Template, person, null, defs, rendererFactory2); renderToHtml(Template, person, null, pipes, rendererFactory2);
expect(renderLog.log).toEqual([]); expect(renderLog.log).toEqual([]);
}); });
@ -170,18 +170,18 @@ describe('pipe', () => {
// change from undefined -> null // change from undefined -> null
person.name = null; person.name = null;
expect(renderToHtml(Template, person, null, defs)).toEqual('null state:0'); expect(renderToHtml(Template, person, null, pipes)).toEqual('null state:0');
expect(renderToHtml(Template, person, null, defs)).toEqual('null state:0'); expect(renderToHtml(Template, person, null, pipes)).toEqual('null state:0');
// change from null -> some value // change from null -> some value
person.name = 'bob'; person.name = 'bob';
expect(renderToHtml(Template, person, null, defs)).toEqual('bob state:1'); expect(renderToHtml(Template, person, null, pipes)).toEqual('bob state:1');
expect(renderToHtml(Template, person, null, defs)).toEqual('bob state:1'); expect(renderToHtml(Template, person, null, pipes)).toEqual('bob state:1');
// change from some value -> some other value // change from some value -> some other value
person.name = 'bart'; person.name = 'bart';
expect(renderToHtml(Template, person, null, defs)).toEqual('bart state:2'); expect(renderToHtml(Template, person, null, pipes)).toEqual('bart state:2');
expect(renderToHtml(Template, person, null, defs)).toEqual('bart state:2'); expect(renderToHtml(Template, person, null, pipes)).toEqual('bart state:2');
}); });
}); });
@ -196,8 +196,8 @@ describe('pipe', () => {
} }
person.name = 'bob'; person.name = 'bob';
expect(renderToHtml(Template, person, null, defs)).toEqual('bob state:0'); expect(renderToHtml(Template, person, null, pipes)).toEqual('bob state:0');
expect(renderToHtml(Template, person, null, defs)).toEqual('bob state:1'); expect(renderToHtml(Template, person, null, pipes)).toEqual('bob state:1');
}); });
it('should not cache impure pipes', () => { it('should not cache impure pipes', () => {
@ -234,7 +234,7 @@ describe('pipe', () => {
} }
const pipeInstances: CountingImpurePipe[] = []; const pipeInstances: CountingImpurePipe[] = [];
renderToHtml(Template, {}, null, defs, rendererFactory2); renderToHtml(Template, {}, null, pipes, rendererFactory2);
expect(pipeInstances.length).toEqual(4); expect(pipeInstances.length).toEqual(4);
expect(pipeInstances[0]).toBeAnInstanceOf(CountingImpurePipe); expect(pipeInstances[0]).toBeAnInstanceOf(CountingImpurePipe);
expect(pipeInstances[1]).toBeAnInstanceOf(CountingImpurePipe); expect(pipeInstances[1]).toBeAnInstanceOf(CountingImpurePipe);
@ -281,23 +281,23 @@ describe('pipe', () => {
} }
containerRefreshEnd(); containerRefreshEnd();
} }
const defs = [PipeWithOnDestroy.ngPipeDef]; const pipes = [PipeWithOnDestroy];
person.age = 25; person.age = 25;
renderToHtml(Template, person, null, defs); renderToHtml(Template, person, null, pipes);
person.age = 15; person.age = 15;
renderToHtml(Template, person, null, defs); renderToHtml(Template, person, null, pipes);
expect(log).toEqual(['pipeWithOnDestroy - ngOnDestroy']); expect(log).toEqual(['pipeWithOnDestroy - ngOnDestroy']);
log = []; log = [];
person.age = 30; person.age = 30;
renderToHtml(Template, person, null, defs); renderToHtml(Template, person, null, pipes);
expect(log).toEqual([]); expect(log).toEqual([]);
log = []; log = [];
person.age = 10; person.age = 10;
renderToHtml(Template, person, null, defs); renderToHtml(Template, person, null, pipes);
expect(log).toEqual(['pipeWithOnDestroy - ngOnDestroy']); expect(log).toEqual(['pipeWithOnDestroy - ngOnDestroy']);
}); });
}); });

View File

@ -139,10 +139,7 @@ describe('elementProperty', () => {
} }
const deps = [ const deps = [MyButton, OtherDir, OtherDisabledDir, IdDir];
MyButton.ngDirectiveDef, OtherDir.ngDirectiveDef, OtherDisabledDir.ngDirectiveDef,
IdDir.ngDirectiveDef
];
it('should check input properties before setting (directives)', () => { it('should check input properties before setting (directives)', () => {
@ -223,7 +220,7 @@ describe('elementProperty', () => {
elementProperty(0, 'id', bind(ctx.id)); elementProperty(0, 'id', bind(ctx.id));
} }
const deps = [Comp.ngComponentDef]; const deps = [Comp];
expect(renderToHtml(Template, {id: 1}, deps)).toEqual(`<comp></comp>`); expect(renderToHtml(Template, {id: 1}, deps)).toEqual(`<comp></comp>`);
expect(comp !.id).toEqual(1); expect(comp !.id).toEqual(1);
@ -365,7 +362,7 @@ describe('elementProperty', () => {
}); });
} }
const deps = [MyDir.ngDirectiveDef, MyDirB.ngDirectiveDef]; const deps = [MyDir, MyDirB];
it('should set input property based on attribute if existing', () => { it('should set input property based on attribute if existing', () => {
@ -539,7 +536,7 @@ describe('elementProperty', () => {
textBinding(2, bind(tmp.role)); textBinding(2, bind(tmp.role));
}, },
factory: () => new Comp(), factory: () => new Comp(),
directiveDefs: () => [MyDir.ngDirectiveDef] directives: () => [MyDir]
}); });
} }
@ -565,7 +562,7 @@ describe('elementProperty', () => {
containerRefreshEnd(); containerRefreshEnd();
} }
expect(renderToHtml(Template, {}, [Comp.ngComponentDef])) expect(renderToHtml(Template, {}, [Comp]))
.toEqual( .toEqual(
`<comp><div mydir="" role="button"></div>button</comp><comp><div mydir="" role="button"></div>button</comp>`); `<comp><div mydir="" role="button"></div>button</comp><comp><div mydir="" role="button"></div>button</comp>`);
}); });

View File

@ -25,7 +25,7 @@ describe('array literals', () => {
}); });
} }
const defs = [MyComp.ngComponentDef]; const directives = [MyComp];
it('should support an array literal with a binding', () => { it('should support an array literal with a binding', () => {
const e0_ff = (v: any) => ['Nancy', v, 'Bess']; const e0_ff = (v: any) => ['Nancy', v, 'Bess'];
@ -39,15 +39,15 @@ describe('array literals', () => {
elementProperty(0, 'names', bind(pureFunction1(e0_ff, ctx.customName))); elementProperty(0, 'names', bind(pureFunction1(e0_ff, ctx.customName)));
} }
renderToHtml(Template, {customName: 'Carson'}, defs); renderToHtml(Template, {customName: 'Carson'}, directives);
const firstArray = myComp !.names; const firstArray = myComp !.names;
expect(firstArray).toEqual(['Nancy', 'Carson', 'Bess']); expect(firstArray).toEqual(['Nancy', 'Carson', 'Bess']);
renderToHtml(Template, {customName: 'Carson'}, defs); renderToHtml(Template, {customName: 'Carson'}, directives);
expect(myComp !.names).toEqual(['Nancy', 'Carson', 'Bess']); expect(myComp !.names).toEqual(['Nancy', 'Carson', 'Bess']);
expect(firstArray).toBe(myComp !.names); expect(firstArray).toBe(myComp !.names);
renderToHtml(Template, {customName: 'Hannah'}, defs); renderToHtml(Template, {customName: 'Hannah'}, directives);
expect(myComp !.names).toEqual(['Nancy', 'Hannah', 'Bess']); expect(myComp !.names).toEqual(['Nancy', 'Hannah', 'Bess']);
// Identity must change if binding changes // Identity must change if binding changes
@ -56,7 +56,7 @@ describe('array literals', () => {
// The property should not be set if the exp value is the same, so artificially // The property should not be set if the exp value is the same, so artificially
// setting the property to ensure it's not overwritten. // setting the property to ensure it's not overwritten.
myComp !.names = ['should not be overwritten']; myComp !.names = ['should not be overwritten'];
renderToHtml(Template, {customName: 'Hannah'}, defs); renderToHtml(Template, {customName: 'Hannah'}, directives);
expect(myComp !.names).toEqual(['should not be overwritten']); expect(myComp !.names).toEqual(['should not be overwritten']);
}); });
@ -92,7 +92,7 @@ describe('array literals', () => {
elementProperty(0, 'names2', bind(pureFunction1(e0_ff_1, ctx.customName2))); elementProperty(0, 'names2', bind(pureFunction1(e0_ff_1, ctx.customName2)));
} }
const defs = [ManyPropComp.ngComponentDef]; const defs = [ManyPropComp];
renderToHtml(Template, {customName: 'Carson', customName2: 'George'}, defs); renderToHtml(Template, {customName: 'Carson', customName2: 'George'}, defs);
expect(manyPropComp !.names1).toEqual(['Nancy', 'Carson']); expect(manyPropComp !.names1).toEqual(['Nancy', 'Carson']);
expect(manyPropComp !.names2).toEqual(['George']); expect(manyPropComp !.names2).toEqual(['George']);
@ -128,7 +128,7 @@ describe('array literals', () => {
} }
elementProperty(0, 'names', bind(ctx.someFn(pureFunction1(e0_ff, ctx.customName)))); elementProperty(0, 'names', bind(ctx.someFn(pureFunction1(e0_ff, ctx.customName))));
}, },
directiveDefs: defs directives: directives
}); });
} }
@ -141,14 +141,14 @@ describe('array literals', () => {
} }
} }
renderToHtml(Template, {}, [ParentComp.ngComponentDef]); renderToHtml(Template, {}, [ParentComp]);
const firstArray = myComps[0].names; const firstArray = myComps[0].names;
const secondArray = myComps[1].names; const secondArray = myComps[1].names;
expect(firstArray).toEqual(['NANCY', 'Bess']); expect(firstArray).toEqual(['NANCY', 'Bess']);
expect(secondArray).toEqual(['NANCY', 'Bess']); expect(secondArray).toEqual(['NANCY', 'Bess']);
expect(firstArray).not.toBe(secondArray); expect(firstArray).not.toBe(secondArray);
renderToHtml(Template, {}, [ParentComp.ngComponentDef]); renderToHtml(Template, {}, [ParentComp]);
expect(firstArray).toEqual(['NANCY', 'Bess']); expect(firstArray).toEqual(['NANCY', 'Bess']);
expect(secondArray).toEqual(['NANCY', 'Bess']); expect(secondArray).toEqual(['NANCY', 'Bess']);
expect(firstArray).toBe(myComps[0].names); expect(firstArray).toBe(myComps[0].names);
@ -167,25 +167,25 @@ describe('array literals', () => {
elementProperty(0, 'names', bind(pureFunction2(e0_ff, ctx.customName, ctx.customName2))); elementProperty(0, 'names', bind(pureFunction2(e0_ff, ctx.customName, ctx.customName2)));
} }
renderToHtml(Template, {customName: 'Carson', customName2: 'Hannah'}, defs); renderToHtml(Template, {customName: 'Carson', customName2: 'Hannah'}, directives);
const firstArray = myComp !.names; const firstArray = myComp !.names;
expect(firstArray).toEqual(['Nancy', 'Carson', 'Bess', 'Hannah']); expect(firstArray).toEqual(['Nancy', 'Carson', 'Bess', 'Hannah']);
renderToHtml(Template, {customName: 'Carson', customName2: 'Hannah'}, defs); renderToHtml(Template, {customName: 'Carson', customName2: 'Hannah'}, directives);
expect(myComp !.names).toEqual(['Nancy', 'Carson', 'Bess', 'Hannah']); expect(myComp !.names).toEqual(['Nancy', 'Carson', 'Bess', 'Hannah']);
expect(firstArray).toBe(myComp !.names); expect(firstArray).toBe(myComp !.names);
renderToHtml(Template, {customName: 'George', customName2: 'Hannah'}, defs); renderToHtml(Template, {customName: 'George', customName2: 'Hannah'}, directives);
expect(myComp !.names).toEqual(['Nancy', 'George', 'Bess', 'Hannah']); expect(myComp !.names).toEqual(['Nancy', 'George', 'Bess', 'Hannah']);
expect(firstArray).not.toBe(myComp !.names); expect(firstArray).not.toBe(myComp !.names);
renderToHtml(Template, {customName: 'Frank', customName2: 'Ned'}, defs); renderToHtml(Template, {customName: 'Frank', customName2: 'Ned'}, directives);
expect(myComp !.names).toEqual(['Nancy', 'Frank', 'Bess', 'Ned']); expect(myComp !.names).toEqual(['Nancy', 'Frank', 'Bess', 'Ned']);
// The property should not be set if the exp value is the same, so artificially // The property should not be set if the exp value is the same, so artificially
// setting the property to ensure it's not overwritten. // setting the property to ensure it's not overwritten.
myComp !.names = ['should not be overwritten']; myComp !.names = ['should not be overwritten'];
renderToHtml(Template, {customName: 'Frank', customName2: 'Ned'}, defs); renderToHtml(Template, {customName: 'Frank', customName2: 'Ned'}, directives);
expect(myComp !.names).toEqual(['should not be overwritten']); expect(myComp !.names).toEqual(['should not be overwritten']);
}); });
@ -243,7 +243,7 @@ describe('array literals', () => {
5, 'names', bind(pureFunction8(e10_ff, c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]))); 5, 'names', bind(pureFunction8(e10_ff, c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7])));
} }
renderToHtml(Template, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], defs); renderToHtml(Template, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], directives);
expect(f3Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']); expect(f3Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
expect(f4Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']); expect(f4Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
expect(f5Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']); expect(f5Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
@ -251,7 +251,7 @@ describe('array literals', () => {
expect(f7Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']); expect(f7Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
expect(f8Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']); expect(f8Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']);
renderToHtml(Template, ['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1', 'i1'], defs); renderToHtml(Template, ['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1', 'i1'], directives);
expect(f3Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f1', 'g1', 'h1']); expect(f3Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f1', 'g1', 'h1']);
expect(f4Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e1', 'f1', 'g1', 'h1']); expect(f4Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e1', 'f1', 'g1', 'h1']);
expect(f5Comp !.names).toEqual(['a', 'b', 'c', 'd1', 'e1', 'f1', 'g1', 'h1']); expect(f5Comp !.names).toEqual(['a', 'b', 'c', 'd1', 'e1', 'f1', 'g1', 'h1']);
@ -259,7 +259,7 @@ describe('array literals', () => {
expect(f7Comp !.names).toEqual(['a', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1']); expect(f7Comp !.names).toEqual(['a', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1']);
expect(f8Comp !.names).toEqual(['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1']); expect(f8Comp !.names).toEqual(['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1']);
renderToHtml(Template, ['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h2', 'i1'], defs); renderToHtml(Template, ['a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h2', 'i1'], directives);
expect(f3Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f1', 'g1', 'h2']); expect(f3Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e', 'f1', 'g1', 'h2']);
expect(f4Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e1', 'f1', 'g1', 'h2']); expect(f4Comp !.names).toEqual(['a', 'b', 'c', 'd', 'e1', 'f1', 'g1', 'h2']);
expect(f5Comp !.names).toEqual(['a', 'b', 'c', 'd1', 'e1', 'f1', 'g1', 'h2']); expect(f5Comp !.names).toEqual(['a', 'b', 'c', 'd1', 'e1', 'f1', 'g1', 'h2']);
@ -274,7 +274,7 @@ describe('array literals', () => {
v8: any) => ['start', v0, v1, v2, v3, v4, v5, v6, v7, v8, 'end']; v8: any) => ['start', v0, v1, v2, v3, v4, v5, v6, v7, v8, 'end'];
const e0_ff_1 = (v: any) => { return {name: v}; }; const e0_ff_1 = (v: any) => { return {name: v}; };
renderToHtml(Template, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], defs); renderToHtml(Template, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], directives);
/** /**
* <my-comp [names]="['start', v0, v1, v2, v3, {name: v4}, v5, v6, v7, v8, 'end']"> * <my-comp [names]="['start', v0, v1, v2, v3, {name: v4}, v5, v6, v7, v8, 'end']">
* </my-comp> * </my-comp>
@ -293,12 +293,12 @@ describe('array literals', () => {
'start', 'a', 'b', 'c', 'd', {name: 'e'}, 'f', 'g', 'h', 'i', 'end' 'start', 'a', 'b', 'c', 'd', {name: 'e'}, 'f', 'g', 'h', 'i', 'end'
]); ]);
renderToHtml(Template, ['a1', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], defs); renderToHtml(Template, ['a1', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'], directives);
expect(myComp !.names).toEqual([ expect(myComp !.names).toEqual([
'start', 'a1', 'b', 'c', 'd', {name: 'e'}, 'f', 'g', 'h', 'i', 'end' 'start', 'a1', 'b', 'c', 'd', {name: 'e'}, 'f', 'g', 'h', 'i', 'end'
]); ]);
renderToHtml(Template, ['a1', 'b', 'c', 'd', 'e5', 'f', 'g', 'h', 'i'], defs); renderToHtml(Template, ['a1', 'b', 'c', 'd', 'e5', 'f', 'g', 'h', 'i'], directives);
expect(myComp !.names).toEqual([ expect(myComp !.names).toEqual([
'start', 'a1', 'b', 'c', 'd', {name: 'e5'}, 'f', 'g', 'h', 'i', 'end' 'start', 'a1', 'b', 'c', 'd', {name: 'e5'}, 'f', 'g', 'h', 'i', 'end'
]); ]);
@ -320,7 +320,7 @@ describe('object literals', () => {
}); });
} }
const defs = [ObjectComp.ngComponentDef]; const defs = [ObjectComp];
it('should support an object literal', () => { it('should support an object literal', () => {
const e0_ff = (v: any) => { return {duration: 500, animation: v}; }; const e0_ff = (v: any) => { return {duration: 500, animation: v}; };

View File

@ -73,7 +73,7 @@ describe('query', () => {
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query0 = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query0 = tmp as QueryList<any>);
queryRefresh(tmp = load<QueryList<any>>(1)) && (ctx.query1 = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(1)) && (ctx.query1 = tmp as QueryList<any>);
}, [Child.ngComponentDef]); }, [Child]);
const parent = renderComponent(Cmp); const parent = renderComponent(Cmp);
expect((parent.query0 as QueryList<any>).toArray()).toEqual([child1]); expect((parent.query0 as QueryList<any>).toArray()).toEqual([child1]);
@ -99,7 +99,7 @@ describe('query', () => {
elementEnd(); elementEnd();
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngDirectiveDef]); }, [Child]);
const cmptInstance = renderComponent(Cmpt); const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>); const qList = (cmptInstance.query as QueryList<any>);
@ -128,7 +128,7 @@ describe('query', () => {
elementEnd(); elementEnd();
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngDirectiveDef, OtherChild.ngDirectiveDef]); }, [Child, OtherChild]);
const cmptInstance = renderComponent(Cmpt); const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>); const qList = (cmptInstance.query as QueryList<any>);
@ -153,7 +153,7 @@ describe('query', () => {
elementEnd(); elementEnd();
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngDirectiveDef, OtherChild.ngDirectiveDef]); }, [Child, OtherChild]);
const cmptInstance = renderComponent(Cmpt); const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>); const qList = (cmptInstance.query as QueryList<any>);
@ -422,7 +422,7 @@ describe('query', () => {
elementEnd(); elementEnd();
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngComponentDef]); }, [Child]);
const cmptInstance = renderComponent(Cmpt); const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>); const qList = (cmptInstance.query as QueryList<any>);
@ -457,7 +457,7 @@ describe('query', () => {
elementEnd(); elementEnd();
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngComponentDef]); }, [Child]);
const cmptInstance = renderComponent(Cmpt); const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>); const qList = (cmptInstance.query as QueryList<any>);
@ -485,7 +485,7 @@ describe('query', () => {
elementEnd(); elementEnd();
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngDirectiveDef]); }, [Child]);
const cmptInstance = renderComponent(Cmpt); const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>); const qList = (cmptInstance.query as QueryList<any>);
@ -516,7 +516,7 @@ describe('query', () => {
elementEnd(); elementEnd();
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child1.ngDirectiveDef, Child2.ngDirectiveDef]); }, [Child1, Child2]);
const cmptInstance = renderComponent(Cmpt); const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>); const qList = (cmptInstance.query as QueryList<any>);
@ -547,7 +547,7 @@ describe('query', () => {
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.fooQuery = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.fooQuery = tmp as QueryList<any>);
queryRefresh(tmp = load<QueryList<any>>(1)) && (ctx.barQuery = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(1)) && (ctx.barQuery = tmp as QueryList<any>);
}, [Child.ngDirectiveDef]); }, [Child]);
const cmptInstance = renderComponent(Cmpt); const cmptInstance = renderComponent(Cmpt);
@ -578,7 +578,7 @@ describe('query', () => {
elementEnd(); elementEnd();
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngDirectiveDef]); }, [Child]);
const cmptInstance = renderComponent(Cmpt); const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>); const qList = (cmptInstance.query as QueryList<any>);
@ -605,7 +605,7 @@ describe('query', () => {
elementEnd(); elementEnd();
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngDirectiveDef]); }, [Child]);
const cmptInstance = renderComponent(Cmpt); const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>); const qList = (cmptInstance.query as QueryList<any>);
@ -631,7 +631,7 @@ describe('query', () => {
elementEnd(); elementEnd();
} }
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>); queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngDirectiveDef]); }, [Child]);
const cmptInstance = renderComponent(Cmpt); const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>); const qList = (cmptInstance.query as QueryList<any>);

View File

@ -9,11 +9,13 @@
import {stringifyElement} from '@angular/platform-browser/testing/src/browser_util'; import {stringifyElement} from '@angular/platform-browser/testing/src/browser_util';
import {CreateComponentOptions} from '../../src/render3/component'; import {CreateComponentOptions} from '../../src/render3/component';
import {extractDirectiveDef, extractPipeDef} from '../../src/render3/definition';
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveType, PublicFeature, defineComponent, defineDirective, renderComponent as _renderComponent, tick} from '../../src/render3/index'; import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveType, PublicFeature, defineComponent, defineDirective, renderComponent as _renderComponent, tick} from '../../src/render3/index';
import {NG_HOST_SYMBOL, renderTemplate} from '../../src/render3/instructions'; import {NG_HOST_SYMBOL, renderTemplate} from '../../src/render3/instructions';
import {DirectiveDefListOrFactory, PipeDefListOrFactory} from '../../src/render3/interfaces/definition'; import {DirectiveDefList, DirectiveDefListOrFactory, DirectiveTypesOrFactory, PipeDef, PipeDefList, PipeDefListOrFactory, PipeTypesOrFactory} from '../../src/render3/interfaces/definition';
import {LElementNode} from '../../src/render3/interfaces/node'; import {LElementNode} from '../../src/render3/interfaces/node';
import {RElement, RText, Renderer3, RendererFactory3, domRendererFactory3} from '../../src/render3/interfaces/renderer'; import {RElement, RText, Renderer3, RendererFactory3, domRendererFactory3} from '../../src/render3/interfaces/renderer';
import {Type} from '../../src/type';
import {getRendererFactory2} from './imported_renderer2'; import {getRendererFactory2} from './imported_renderer2';
@ -152,14 +154,30 @@ export function resetDOM() {
* @deprecated use `TemplateFixture` or `ComponentFixture` * @deprecated use `TemplateFixture` or `ComponentFixture`
*/ */
export function renderToHtml( export function renderToHtml(
template: ComponentTemplate<any>, ctx: any, directives?: DirectiveDefListOrFactory | null, template: ComponentTemplate<any>, ctx: any, directives?: DirectiveTypesOrFactory | null,
pipes?: PipeDefListOrFactory | null, providedRendererFactory?: RendererFactory3 | null) { pipes?: PipeTypesOrFactory | null, providedRendererFactory?: RendererFactory3 | null) {
host = renderTemplate( host = renderTemplate(
containerEl, template, ctx, providedRendererFactory || testRendererFactory, host, containerEl, template, ctx, providedRendererFactory || testRendererFactory, host,
directives || null, pipes || null); toDefs(directives, extractDirectiveDef), toDefs(pipes, extractPipeDef));
return toHtml(containerEl); return toHtml(containerEl);
} }
function toDefs(
types: DirectiveTypesOrFactory | undefined | null,
mapFn: (type: Type<any>) => DirectiveDef<any>): DirectiveDefList|null;
function toDefs(
types: PipeTypesOrFactory | undefined | null,
mapFn: (type: Type<any>) => PipeDef<any>): PipeDefList|null;
function toDefs(
types: PipeTypesOrFactory | DirectiveTypesOrFactory | undefined | null,
mapFn: (type: Type<any>) => PipeDef<any>| DirectiveDef<any>): any {
if (!types) return null;
if (typeof types == 'function') {
types = types();
}
return types.map(mapFn);
}
beforeEach(resetDOM); beforeEach(resetDOM);
/** /**
@ -191,8 +209,8 @@ export function toHtml<T>(componentOrElement: T | RElement): string {
} }
export function createComponent( export function createComponent(
name: string, template: ComponentTemplate<any>, directives: DirectiveDefListOrFactory = [], name: string, template: ComponentTemplate<any>, directives: DirectiveTypesOrFactory = [],
pipes: PipeDefListOrFactory = []): ComponentType<any> { pipes: PipeTypesOrFactory = []): ComponentType<any> {
return class Component { return class Component {
value: any; value: any;
static ngComponentDef = defineComponent({ static ngComponentDef = defineComponent({
@ -201,8 +219,8 @@ export function createComponent(
factory: () => new Component, factory: () => new Component,
template: template, template: template,
features: [PublicFeature], features: [PublicFeature],
directiveDefs: directives, directives: directives,
pipeDefs: pipes pipes: pipes
}); });
}; };
} }

View File

@ -60,7 +60,7 @@ describe('renderer factory lifecycle', () => {
} }
} }
const defs = [SomeComponent.ngComponentDef, SomeComponentWhichThrows.ngComponentDef]; const directives = [SomeComponent, SomeComponentWhichThrows];
function TemplateWithComponent(ctx: any, cm: boolean) { function TemplateWithComponent(ctx: any, cm: boolean) {
logs.push('function_with_component'); logs.push('function_with_component');
@ -97,12 +97,12 @@ describe('renderer factory lifecycle', () => {
}); });
it('should work with a template which contains a component', () => { it('should work with a template which contains a component', () => {
renderToHtml(TemplateWithComponent, {}, defs, null, rendererFactory); renderToHtml(TemplateWithComponent, {}, directives, null, rendererFactory);
expect(logs).toEqual( expect(logs).toEqual(
['create', 'begin', 'function_with_component', 'create', 'component', 'end']); ['create', 'begin', 'function_with_component', 'create', 'component', 'end']);
logs = []; logs = [];
renderToHtml(TemplateWithComponent, {}, defs); renderToHtml(TemplateWithComponent, {}, directives);
expect(logs).toEqual(['begin', 'function_with_component', 'component', 'end']); expect(logs).toEqual(['begin', 'function_with_component', 'component', 'end']);
}); });

View File

@ -44,7 +44,7 @@ describe('ViewContainerRef', () => {
cmp.testDir = loadDirective<TestDirective>(0); cmp.testDir = loadDirective<TestDirective>(0);
containerRefreshEnd(); containerRefreshEnd();
}, },
directiveDefs: [TestDirective.ngDirectiveDef] directives: [TestDirective]
}); });
} }