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,
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 containerRefreshStart: o.ExternalReference = {name: 'ɵcR', moduleName: CORE};
static containerRefreshEnd: o.ExternalReference = {name: 'ɵcr', moduleName: CORE};
static directiveCreate: o.ExternalReference = {name: 'ɵD', moduleName: CORE};
static text: o.ExternalReference = {name: 'ɵT', moduleName: CORE};

View File

@ -120,6 +120,23 @@ export function compileComponent(
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) => {
if (value) {
definitionMapValues.push({key, value, quoted: false});
@ -162,10 +179,13 @@ export function compileComponent(
new TemplateDefinitionBuilder(
outputCtx, outputCtx.constantPool, reflector, CONTEXT_NAME, ROOT_SCOPE.nestedScope(), 0,
component.template !.ngContentSelectors, templateTypeName, templateName, pipeMap,
component.viewQueries, addPipeDependency)
component.viewQueries, addDirectiveDependency, addPipeDependency)
.buildTemplateFunction(template, []);
field('template', templateFunctionExpression);
if (directiveExps.length) {
field('directives', o.literalArr(directiveExps));
}
// e.g. `pipes: [MyPipe]`
if (pipeExps.length) {
@ -373,6 +393,7 @@ class TemplateDefinitionBuilder implements TemplateAstVisitor, LocalResolver {
private bindingScope: BindingScope, private level = 0, private ngContentSelectors: string[],
private contextName: string|null, private templateName: string|null,
private pipes: Map<string, CompilePipeSummary>, private viewQueries: CompileQueryMetadata[],
private addDirectiveDependency: (ast: DirectiveAst) => void,
private addPipeDependency: (summary: CompilePipeSummary) => void) {
this._valueConverter = new ValueConverter(
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);
}
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
visitElement(element: ElementAst) {
const elementIndex = this.allocateDataSlot();
let componentIndex: number|undefined = undefined;
const referenceDataSlots = new Map<string, number>();
const wasInI18nSection = this._inI18nSection;
@ -563,13 +570,11 @@ class TemplateDefinitionBuilder implements TemplateAstVisitor, LocalResolver {
const nullNode = o.literal(null, o.INFERRED_TYPE);
const parameters: o.Expression[] = [o.literal(elementIndex)];
// Add component type or element tag
if (component) {
parameters.push(this.typeReference(component.directive.type.reference));
componentIndex = this.allocateDataSlot();
} else {
parameters.push(o.literal(element.name));
this.addDirectiveDependency(component);
}
element.directives.forEach(this.addDirectiveDependency);
parameters.push(o.literal(element.name));
// Add the attributes
const i18nMessages: o.Statement[] = [];
@ -598,10 +603,6 @@ class TemplateDefinitionBuilder implements TemplateAstVisitor, LocalResolver {
parameters.push(attrArg);
// Add directives array
const directivesArray = this._computeDirectivesArray(element.directives);
parameters.push(directivesArray);
if (element.references && element.references.length > 0) {
const references =
flatten(element.references.map(reference => {
@ -621,16 +622,12 @@ class TemplateDefinitionBuilder implements TemplateAstVisitor, LocalResolver {
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
if (i18nMessages.length > 0) {
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);
@ -725,28 +722,41 @@ class TemplateDefinitionBuilder implements TemplateAstVisitor, LocalResolver {
contextName ? `${contextName}_Template_${templateIndex}` : `Template_${templateIndex}`;
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)
this.instruction(
this._creationMode, ast.sourceSpan, R3.containerCreate, o.literal(templateIndex),
directivesArray, o.variable(templateName));
// e.g. Cr(1)
this.instruction(
this._refreshMode, ast.sourceSpan, R3.containerRefreshStart, o.literal(templateIndex));
...trimTrailingNulls(parameters));
// Generate directives
this._visitDirectives(ast.directives, o.variable(this.contextParameter), templateIndex);
// e.g. cr();
this.instruction(this._refreshMode, ast.sourceSpan, R3.containerRefreshEnd);
// Create the template function
const templateVisitor = new TemplateDefinitionBuilder(
this.outputCtx, this.constantPool, this.reflector, templateContext,
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);
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());
}
private typeReference(type: any): o.Expression { return this.outputCtx.importExpr(type); }
private definitionOf(type: any, kind: DefinitionKind): o.Expression {
return this.constantPool.getDefinition(type, kind, this.outputCtx);
}
@ -923,6 +931,16 @@ export function createFactory(
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 = {
[key: string]: string
};

View File

@ -28,6 +28,17 @@ const _SELECTOR_REGEXP = new RegExp(
export class CssSelector {
element: string|null = null;
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[] = [];
notSelectors: CssSelector[] = [];

View File

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

View File

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

View File

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

View File

@ -16,7 +16,7 @@ import {Type} from '../type';
import {resolveRendererType2} from '../view/util';
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';
@ -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
* `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.
@ -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
* `PipeDefs`s. The function is necessary to be able to support forward declarations.
*/
pipeDefs?: PipeDefListOrFactory | null;
pipes?: PipeTypesOrFactory | null;
}): ComponentDef<T> {
const type = componentDefinition.type;
const pipeTypes = componentDefinition.pipes !;
const directiveTypes = componentDefinition.directives !;
const def = <ComponentDef<any>>{
type: type,
diPublic: null,
@ -183,8 +185,13 @@ export function defineComponent<T>(componentDefinition: {
afterViewChecked: type.prototype.ngAfterViewChecked || null,
onDestroy: type.prototype.ngOnDestroy || null,
onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush,
directiveDefs: componentDefinition.directiveDefs || null,
pipeDefs: componentDefinition.pipeDefs || null,
directiveDefs: directiveTypes ?
() => (typeof directiveTypes === 'function' ? directiveTypes() : directiveTypes)
.map(extractDirectiveDef) :
null,
pipeDefs: pipeTypes ?
() => (typeof pipeTypes === 'function' ? pipeTypes() : pipeTypes).map(extractPipeDef) :
null,
selectors: componentDefinition.selectors
};
const feature = componentDefinition.features;
@ -192,6 +199,24 @@ export function defineComponent<T>(componentDefinition: {
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_';

View File

@ -9,7 +9,7 @@
import {LifecycleHooksFeature, createComponentRef, getHostElement, getRenderedText, renderComponent, whenRendered} from './component';
import {NgOnChangesFeature, PublicFeature, defineComponent, defineDirective, definePipe} from './definition';
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 {CssSelectorList} from './interfaces/projection';
@ -111,6 +111,7 @@ export {
DirectiveType,
NgOnChangesFeature,
PublicFeature,
PipeDef,
LifecycleHooksFeature,
defineComponent,
defineDirective,

View File

@ -400,7 +400,8 @@ function resetApplicationState() {
* @param context to pass into the template.
* @param providedRendererFactory renderer factory 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>(
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 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.
*
@ -232,6 +238,12 @@ export type PipeDefListOrFactory = (() => PipeDefList) | PipeDefList;
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
// failure based on types.
export const unusedValueExportToPlacateAjd = 1;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -43,8 +43,7 @@ describe('di', () => {
textBinding(2, bind(tmp.value));
}
expect(renderToHtml(Template, {}, [Directive.ngDirectiveDef]))
.toEqual('<div dir="">Created</div>');
expect(renderToHtml(Template, {}, [Directive])).toEqual('<div dir="">Created</div>');
});
});
@ -100,8 +99,7 @@ describe('di', () => {
textBinding(3, bind(tmp.value));
}
const defs =
[DirectiveA.ngDirectiveDef, DirectiveB.ngDirectiveDef, DirectiveC.ngDirectiveDef];
const defs = [DirectiveA, DirectiveB, DirectiveC];
expect(renderToHtml(Template, {}, defs))
.toEqual('<div dira=""><span dirb="" dirc="">AB</span></div>');
});
@ -153,7 +151,7 @@ describe('di', () => {
textBinding(3, interpolation2('', tmp2.value, '-', tmp1.value, ''));
}
const defs = [Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef];
const defs = [Directive, DirectiveSameInstance];
expect(renderToHtml(Template, {}, defs))
.toEqual('<div dir="" dirsame="">ElementRef-true</div>');
});
@ -204,7 +202,7 @@ describe('di', () => {
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, ''));
}
const defs = [Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef];
const defs = [Directive, DirectiveSameInstance];
expect(renderToHtml(Template, {}, defs)).toEqual('TemplateRef-true');
});
});
@ -256,7 +254,7 @@ describe('di', () => {
textBinding(3, interpolation2('', tmp1.value, '-', tmp2.value, ''));
}
const defs = [Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef];
const defs = [Directive, DirectiveSameInstance];
expect(renderToHtml(Template, {}, defs))
.toEqual('<div dir="" dirsame="">ViewContainerRef-true</div>');
});
@ -327,10 +325,7 @@ describe('di', () => {
}
const defs = [
MyComp.ngComponentDef, Directive.ngDirectiveDef, DirectiveSameInstance.ngDirectiveDef,
IfDirective.ngDirectiveDef
];
const directives = [MyComp, Directive, DirectiveSameInstance, IfDirective];
it('should inject current component ChangeDetectorRef into directives on components', () => {
/** <my-comp dir dirSameInstance #dir="dir"></my-comp> {{ dir.value }} */
@ -342,7 +337,7 @@ describe('di', () => {
}
const tmp = load(1) as any;
textBinding(2, bind(tmp.value));
}, defs);
}, directives);
const app = renderComponent(MyApp);
// ChangeDetectorRef is the token, ViewRef has historically been the constructor
@ -372,7 +367,7 @@ describe('di', () => {
const tmp = load(1) as any;
textBinding(2, bind(tmp.value));
},
directiveDefs: defs
directives: directives
});
}
@ -411,7 +406,7 @@ describe('di', () => {
const tmp = load(2) as any;
textBinding(3, bind(tmp.value));
},
directiveDefs: defs
directives: directives
});
}
@ -458,7 +453,7 @@ describe('di', () => {
}
containerRefreshEnd();
},
directiveDefs: defs
directives: directives
});
}
@ -498,7 +493,7 @@ describe('di', () => {
textBinding(2, bind(tmp.value));
}
},
directiveDefs: defs
directives: directives
});
}
@ -675,10 +670,7 @@ describe('di', () => {
containerRefreshEnd();
}
const defs = [
ChildDirective.ngDirectiveDef, Child2Directive.ngDirectiveDef,
ParentDirective.ngDirectiveDef
];
const defs = [ChildDirective, Child2Directive, ParentDirective];
expect(renderToHtml(Template, {}, defs))
.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>');
directiveInstance !.klass = 'bar';
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', () => {
@ -80,7 +80,7 @@ describe('exports', () => {
});
}
const defs = [MyComponent.ngComponentDef, MyDir.ngDirectiveDef];
const defs = [MyComponent, MyDir];
/** <comp #myComp></comp> <div [myDir]="myComp"></div> */
function Template(ctx: any, cm: boolean) {
@ -121,8 +121,7 @@ describe('exports', () => {
});
}
expect(renderToHtml(Template, {}, [SomeDir.ngDirectiveDef]))
.toEqual('<div somedir=""></div>Drew');
expect(renderToHtml(Template, {}, [SomeDir])).toEqual('<div somedir=""></div>Drew');
});
it('should throw if export name is not found', () => {
@ -247,7 +246,7 @@ describe('exports', () => {
elementProperty(0, 'myDir', bind(tmp));
}
renderToHtml(Template, {}, [MyComponent.ngComponentDef, MyDir.ngDirectiveDef]);
renderToHtml(Template, {}, [MyComponent, MyDir]);
expect(myDir !.myDir).toEqual(myComponent !);
});
@ -283,7 +282,7 @@ describe('exports', () => {
factory: () => new MyComponent
});
}
expect(renderToHtml(Template, {}, [MyComponent.ngComponentDef]))
expect(renderToHtml(Template, {}, [MyComponent]))
.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', () => {
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>');
cmptInstance !.title = 'two';
expect(renderToHtml(Template, {}, defs)).toEqual('<todo title="two">two</todo>');
@ -314,8 +314,7 @@ describe('render3 integration test', () => {
}
}
expect(renderToHtml(Template, null, [MyComp.ngComponentDef]))
.toEqual('<comp><p>Bess</p></comp>');
expect(renderToHtml(Template, null, [MyComp])).toEqual('<comp><p>Bess</p></comp>');
});
it('should support a component with sub-views', () => {
@ -360,7 +359,7 @@ describe('render3 integration test', () => {
elementProperty(0, 'condition', bind(ctx.condition));
}
const defs = [MyComp.ngComponentDef];
const defs = [MyComp];
expect(renderToHtml(Template, {condition: true}, defs))
.toEqual('<comp><div>text</div></comp>');
expect(renderToHtml(Template, {condition: false}, defs)).toEqual('<comp></comp>');
@ -488,7 +487,7 @@ describe('render3 integration test', () => {
projectedTree: {beforeLabel: 'p'},
afterTree: {afterLabel: 'z'}
};
const defs = [ChildComponent.ngComponentDef];
const defs = [ChildComponent];
expect(renderToHtml(parentTemplate, ctx, defs)).toEqual('<child>apz</child>');
ctx.projectedTree = {subTrees: [{}, {}, {subTrees: [{}, {}]}, {}]};
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))
.toEqual(`<div aria-label="some label" hostbindingdir=""></div>`);

View File

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

View File

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

View File

@ -30,7 +30,7 @@ describe('pipe', () => {
person = new Person();
});
const defs = () => [CountingPipe.ngPipeDef, MultiArgPipe.ngPipeDef, CountingImpurePipe.ngPipeDef];
const pipes = () => [CountingPipe, MultiArgPipe, CountingImpurePipe];
it('should support interpolation', () => {
function Template(person: Person, cm: boolean) {
@ -42,7 +42,7 @@ describe('pipe', () => {
}
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', () => {
@ -52,7 +52,7 @@ describe('pipe', () => {
pipe(1, 'randomPipeName');
}
textBinding(0, interpolation1('', pipeBind1(1, ctx.value), ''));
}, [], defs);
}, [], pipes);
expect(() => {
const fixture = new ComponentFixture(App);
@ -96,7 +96,7 @@ describe('pipe', () => {
elementProperty(0, 'elprop', bind(pipeBind1(1, ctx)));
directive = loadDirective(0);
}
renderToHtml(Template, 'a', [MyDir.ngDirectiveDef], [DoublePipe.ngPipeDef]);
renderToHtml(Template, 'a', [MyDir], [DoublePipe]);
expect(directive !.dirProp).toEqual('aa');
});
@ -111,7 +111,7 @@ describe('pipe', () => {
}
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', () => {
@ -126,7 +126,7 @@ describe('pipe', () => {
}
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', () => {
@ -150,11 +150,11 @@ describe('pipe', () => {
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']);
renderLog.clear();
renderToHtml(Template, person, null, defs, rendererFactory2);
renderToHtml(Template, person, null, pipes, rendererFactory2);
expect(renderLog.log).toEqual([]);
});
@ -170,18 +170,18 @@ describe('pipe', () => {
// change from undefined -> null
person.name = null;
expect(renderToHtml(Template, person, null, defs)).toEqual('null state:0');
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, pipes)).toEqual('null state:0');
// change from null -> some value
person.name = 'bob';
expect(renderToHtml(Template, person, null, defs)).toEqual('bob state:1');
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, pipes)).toEqual('bob state:1');
// change from some value -> some other value
person.name = 'bart';
expect(renderToHtml(Template, person, null, defs)).toEqual('bart state:2');
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, pipes)).toEqual('bart state:2');
});
});
@ -196,8 +196,8 @@ describe('pipe', () => {
}
person.name = 'bob';
expect(renderToHtml(Template, person, null, defs)).toEqual('bob state:0');
expect(renderToHtml(Template, person, null, defs)).toEqual('bob state:1');
expect(renderToHtml(Template, person, null, pipes)).toEqual('bob state:0');
expect(renderToHtml(Template, person, null, pipes)).toEqual('bob state:1');
});
it('should not cache impure pipes', () => {
@ -234,7 +234,7 @@ describe('pipe', () => {
}
const pipeInstances: CountingImpurePipe[] = [];
renderToHtml(Template, {}, null, defs, rendererFactory2);
renderToHtml(Template, {}, null, pipes, rendererFactory2);
expect(pipeInstances.length).toEqual(4);
expect(pipeInstances[0]).toBeAnInstanceOf(CountingImpurePipe);
expect(pipeInstances[1]).toBeAnInstanceOf(CountingImpurePipe);
@ -281,23 +281,23 @@ describe('pipe', () => {
}
containerRefreshEnd();
}
const defs = [PipeWithOnDestroy.ngPipeDef];
const pipes = [PipeWithOnDestroy];
person.age = 25;
renderToHtml(Template, person, null, defs);
renderToHtml(Template, person, null, pipes);
person.age = 15;
renderToHtml(Template, person, null, defs);
renderToHtml(Template, person, null, pipes);
expect(log).toEqual(['pipeWithOnDestroy - ngOnDestroy']);
log = [];
person.age = 30;
renderToHtml(Template, person, null, defs);
renderToHtml(Template, person, null, pipes);
expect(log).toEqual([]);
log = [];
person.age = 10;
renderToHtml(Template, person, null, defs);
renderToHtml(Template, person, null, pipes);
expect(log).toEqual(['pipeWithOnDestroy - ngOnDestroy']);
});
});

View File

@ -139,10 +139,7 @@ describe('elementProperty', () => {
}
const deps = [
MyButton.ngDirectiveDef, OtherDir.ngDirectiveDef, OtherDisabledDir.ngDirectiveDef,
IdDir.ngDirectiveDef
];
const deps = [MyButton, OtherDir, OtherDisabledDir, IdDir];
it('should check input properties before setting (directives)', () => {
@ -223,7 +220,7 @@ describe('elementProperty', () => {
elementProperty(0, 'id', bind(ctx.id));
}
const deps = [Comp.ngComponentDef];
const deps = [Comp];
expect(renderToHtml(Template, {id: 1}, deps)).toEqual(`<comp></comp>`);
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', () => {
@ -539,7 +536,7 @@ describe('elementProperty', () => {
textBinding(2, bind(tmp.role));
},
factory: () => new Comp(),
directiveDefs: () => [MyDir.ngDirectiveDef]
directives: () => [MyDir]
});
}
@ -565,7 +562,7 @@ describe('elementProperty', () => {
containerRefreshEnd();
}
expect(renderToHtml(Template, {}, [Comp.ngComponentDef]))
expect(renderToHtml(Template, {}, [Comp]))
.toEqual(
`<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', () => {
const e0_ff = (v: any) => ['Nancy', v, 'Bess'];
@ -39,15 +39,15 @@ describe('array literals', () => {
elementProperty(0, 'names', bind(pureFunction1(e0_ff, ctx.customName)));
}
renderToHtml(Template, {customName: 'Carson'}, defs);
renderToHtml(Template, {customName: 'Carson'}, directives);
const firstArray = myComp !.names;
expect(firstArray).toEqual(['Nancy', 'Carson', 'Bess']);
renderToHtml(Template, {customName: 'Carson'}, defs);
renderToHtml(Template, {customName: 'Carson'}, directives);
expect(myComp !.names).toEqual(['Nancy', 'Carson', 'Bess']);
expect(firstArray).toBe(myComp !.names);
renderToHtml(Template, {customName: 'Hannah'}, defs);
renderToHtml(Template, {customName: 'Hannah'}, directives);
expect(myComp !.names).toEqual(['Nancy', 'Hannah', 'Bess']);
// 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
// setting the property to ensure it's not 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']);
});
@ -92,7 +92,7 @@ describe('array literals', () => {
elementProperty(0, 'names2', bind(pureFunction1(e0_ff_1, ctx.customName2)));
}
const defs = [ManyPropComp.ngComponentDef];
const defs = [ManyPropComp];
renderToHtml(Template, {customName: 'Carson', customName2: 'George'}, defs);
expect(manyPropComp !.names1).toEqual(['Nancy', 'Carson']);
expect(manyPropComp !.names2).toEqual(['George']);
@ -128,7 +128,7 @@ describe('array literals', () => {
}
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 secondArray = myComps[1].names;
expect(firstArray).toEqual(['NANCY', 'Bess']);
expect(secondArray).toEqual(['NANCY', 'Bess']);
expect(firstArray).not.toBe(secondArray);
renderToHtml(Template, {}, [ParentComp.ngComponentDef]);
renderToHtml(Template, {}, [ParentComp]);
expect(firstArray).toEqual(['NANCY', 'Bess']);
expect(secondArray).toEqual(['NANCY', 'Bess']);
expect(firstArray).toBe(myComps[0].names);
@ -167,25 +167,25 @@ describe('array literals', () => {
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;
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(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(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']);
// The property should not be set if the exp value is the same, so artificially
// setting the property to ensure it's not 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']);
});
@ -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])));
}
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(f4Comp !.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(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(f4Comp !.names).toEqual(['a', 'b', 'c', 'd', '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(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(f4Comp !.names).toEqual(['a', 'b', 'c', 'd', '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'];
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>
@ -293,12 +293,12 @@ describe('array literals', () => {
'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([
'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([
'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', () => {
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>>(1)) && (ctx.query1 = tmp as QueryList<any>);
}, [Child.ngComponentDef]);
}, [Child]);
const parent = renderComponent(Cmp);
expect((parent.query0 as QueryList<any>).toArray()).toEqual([child1]);
@ -99,7 +99,7 @@ describe('query', () => {
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngDirectiveDef]);
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>);
@ -128,7 +128,7 @@ describe('query', () => {
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngDirectiveDef, OtherChild.ngDirectiveDef]);
}, [Child, OtherChild]);
const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>);
@ -153,7 +153,7 @@ describe('query', () => {
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngDirectiveDef, OtherChild.ngDirectiveDef]);
}, [Child, OtherChild]);
const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>);
@ -422,7 +422,7 @@ describe('query', () => {
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngComponentDef]);
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>);
@ -457,7 +457,7 @@ describe('query', () => {
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngComponentDef]);
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>);
@ -485,7 +485,7 @@ describe('query', () => {
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngDirectiveDef]);
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>);
@ -516,7 +516,7 @@ describe('query', () => {
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child1.ngDirectiveDef, Child2.ngDirectiveDef]);
}, [Child1, Child2]);
const cmptInstance = renderComponent(Cmpt);
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>>(1)) && (ctx.barQuery = tmp as QueryList<any>);
}, [Child.ngDirectiveDef]);
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
@ -578,7 +578,7 @@ describe('query', () => {
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngDirectiveDef]);
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>);
@ -605,7 +605,7 @@ describe('query', () => {
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngDirectiveDef]);
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>);
@ -631,7 +631,7 @@ describe('query', () => {
elementEnd();
}
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}, [Child.ngDirectiveDef]);
}, [Child]);
const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>);

View File

@ -9,11 +9,13 @@
import {stringifyElement} from '@angular/platform-browser/testing/src/browser_util';
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 {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 {RElement, RText, Renderer3, RendererFactory3, domRendererFactory3} from '../../src/render3/interfaces/renderer';
import {Type} from '../../src/type';
import {getRendererFactory2} from './imported_renderer2';
@ -152,14 +154,30 @@ export function resetDOM() {
* @deprecated use `TemplateFixture` or `ComponentFixture`
*/
export function renderToHtml(
template: ComponentTemplate<any>, ctx: any, directives?: DirectiveDefListOrFactory | null,
pipes?: PipeDefListOrFactory | null, providedRendererFactory?: RendererFactory3 | null) {
template: ComponentTemplate<any>, ctx: any, directives?: DirectiveTypesOrFactory | null,
pipes?: PipeTypesOrFactory | null, providedRendererFactory?: RendererFactory3 | null) {
host = renderTemplate(
containerEl, template, ctx, providedRendererFactory || testRendererFactory, host,
directives || null, pipes || null);
toDefs(directives, extractDirectiveDef), toDefs(pipes, extractPipeDef));
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);
/**
@ -191,8 +209,8 @@ export function toHtml<T>(componentOrElement: T | RElement): string {
}
export function createComponent(
name: string, template: ComponentTemplate<any>, directives: DirectiveDefListOrFactory = [],
pipes: PipeDefListOrFactory = []): ComponentType<any> {
name: string, template: ComponentTemplate<any>, directives: DirectiveTypesOrFactory = [],
pipes: PipeTypesOrFactory = []): ComponentType<any> {
return class Component {
value: any;
static ngComponentDef = defineComponent({
@ -201,8 +219,8 @@ export function createComponent(
factory: () => new Component,
template: template,
features: [PublicFeature],
directiveDefs: directives,
pipeDefs: pipes
directives: directives,
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) {
logs.push('function_with_component');
@ -97,12 +97,12 @@ describe('renderer factory lifecycle', () => {
});
it('should work with a template which contains a component', () => {
renderToHtml(TemplateWithComponent, {}, defs, null, rendererFactory);
renderToHtml(TemplateWithComponent, {}, directives, null, rendererFactory);
expect(logs).toEqual(
['create', 'begin', 'function_with_component', 'create', 'component', 'end']);
logs = [];
renderToHtml(TemplateWithComponent, {}, defs);
renderToHtml(TemplateWithComponent, {}, directives);
expect(logs).toEqual(['begin', 'function_with_component', 'component', 'end']);
});

View File

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