refactor(ivy): remove pipe references from the template (#23032)
PR Close #23032
This commit is contained in:
parent
5a86f7144f
commit
e2e80ec61c
|
@ -133,8 +133,9 @@ export function renderComponent<T>(
|
||||||
clean: CLEAN_PROMISE,
|
clean: CLEAN_PROMISE,
|
||||||
};
|
};
|
||||||
const rootView = createLView(
|
const rootView = createLView(
|
||||||
-1, rendererFactory.createRenderer(hostNode, componentDef.rendererType), createTView(null),
|
-1, rendererFactory.createRenderer(hostNode, componentDef.rendererType),
|
||||||
null, rootContext, componentDef.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways);
|
createTView(null, null), null, rootContext,
|
||||||
|
componentDef.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways);
|
||||||
|
|
||||||
const oldView = enterView(rootView, null !);
|
const oldView = enterView(rootView, null !);
|
||||||
let elementNode: LElementNode;
|
let elementNode: LElementNode;
|
||||||
|
|
|
@ -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} from './interfaces/definition';
|
import {ComponentDef, ComponentDefFeature, ComponentTemplate, DirectiveDef, DirectiveDefFeature, DirectiveDefListOrFactory, PipeDef, PipeDefListOrFactory} from './interfaces/definition';
|
||||||
import {CssSelector} from './interfaces/projection';
|
import {CssSelector} from './interfaces/projection';
|
||||||
|
|
||||||
|
|
||||||
|
@ -154,6 +154,14 @@ export function defineComponent<T>(componentDefinition: {
|
||||||
* `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;
|
directiveDefs?: DirectiveDefListOrFactory | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registry of pipes that may be found in this component's view.
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
}): ComponentDef<T> {
|
}): ComponentDef<T> {
|
||||||
const type = componentDefinition.type;
|
const type = componentDefinition.type;
|
||||||
const def = <ComponentDef<any>>{
|
const def = <ComponentDef<any>>{
|
||||||
|
@ -176,6 +184,7 @@ export function defineComponent<T>(componentDefinition: {
|
||||||
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: componentDefinition.directiveDefs || null,
|
||||||
|
pipeDefs: componentDefinition.pipeDefs || null,
|
||||||
selector: componentDefinition.selector
|
selector: componentDefinition.selector
|
||||||
};
|
};
|
||||||
const feature = componentDefinition.features;
|
const feature = componentDefinition.features;
|
||||||
|
@ -380,15 +389,25 @@ export const defineDirective = defineComponent as any as<T>(directiveDefinition:
|
||||||
* });
|
* });
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
* @param type Pipe class reference. Needed to extract pipe lifecycle hooks.
|
* @param pipeDef Pipe definition generated by the compiler
|
||||||
* @param factory A factory for creating a pipe instance.
|
|
||||||
* @param pure Whether the pipe is pure.
|
|
||||||
*/
|
*/
|
||||||
export function definePipe<T>(
|
export function definePipe<T>(pipeDef: {
|
||||||
{type, factory, pure}: {type: Type<T>, factory: () => T, pure?: boolean}): PipeDef<T> {
|
/** Name of the pipe. Used for matching pipes in template to pipe defs. */
|
||||||
|
name: string,
|
||||||
|
|
||||||
|
/** Pipe class reference. Needed to extract pipe lifecycle hooks. */
|
||||||
|
type: Type<T>,
|
||||||
|
|
||||||
|
/** A factory for creating a pipe instance. */
|
||||||
|
factory: () => T,
|
||||||
|
|
||||||
|
/** Whether the pipe is pure. */
|
||||||
|
pure?: boolean
|
||||||
|
}): PipeDef<T> {
|
||||||
return <PipeDef<T>>{
|
return <PipeDef<T>>{
|
||||||
n: factory,
|
name: pipeDef.name,
|
||||||
pure: pure !== false,
|
n: pipeDef.factory,
|
||||||
onDestroy: type.prototype.ngOnDestroy || null
|
pure: pipeDef.pure !== false,
|
||||||
|
onDestroy: pipeDef.type.prototype.ngOnDestroy || null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {LContainerNode, LElementNode, LNode, LNodeType, TNodeFlags, LProjectionN
|
||||||
import {assertNodeType} from './node_assert';
|
import {assertNodeType} from './node_assert';
|
||||||
import {appendChild, insertChild, insertView, appendProjectedNode, removeView, canInsertNativeNode} from './node_manipulation';
|
import {appendChild, insertChild, insertView, appendProjectedNode, removeView, canInsertNativeNode} from './node_manipulation';
|
||||||
import {isNodeMatchingSelector, matchingSelectorIndex} from './node_selector_matcher';
|
import {isNodeMatchingSelector, matchingSelectorIndex} from './node_selector_matcher';
|
||||||
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefList, DirectiveDefListOrFactory, DirectiveType} from './interfaces/definition';
|
import {ComponentDef, ComponentTemplate, ComponentType, DirectiveDef, DirectiveDefList, DirectiveDefListOrFactory, DirectiveType, PipeDef, PipeDefListOrFactory} from './interfaces/definition';
|
||||||
import {RElement, RText, Renderer3, RendererFactory3, ProceduralRenderer3, ObjectOrientedRenderer3, RendererStyleFlags3, isProceduralRenderer} from './interfaces/renderer';
|
import {RElement, RText, Renderer3, RendererFactory3, ProceduralRenderer3, ObjectOrientedRenderer3, RendererStyleFlags3, isProceduralRenderer} from './interfaces/renderer';
|
||||||
import {isDifferent, stringify} from './util';
|
import {isDifferent, stringify} from './util';
|
||||||
import {executeHooks, queueLifecycleHooks, queueInitHooks, executeInitHooks} from './hooks';
|
import {executeHooks, queueLifecycleHooks, queueInitHooks, executeInitHooks} from './hooks';
|
||||||
|
@ -400,20 +400,22 @@ 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 directiveRegistry Any directive defs that should be used to match nodes to directives
|
* @param defs Any directive or 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,
|
||||||
providedRendererFactory: RendererFactory3, host: LElementNode | null,
|
providedRendererFactory: RendererFactory3, host: LElementNode | null,
|
||||||
directiveRegistry: DirectiveDefListOrFactory | null = null): LElementNode {
|
directives?: DirectiveDefListOrFactory | null,
|
||||||
|
pipes?: PipeDefListOrFactory | null): LElementNode {
|
||||||
if (host == null) {
|
if (host == null) {
|
||||||
resetApplicationState();
|
resetApplicationState();
|
||||||
rendererFactory = providedRendererFactory;
|
rendererFactory = providedRendererFactory;
|
||||||
|
const tView = getOrCreateTView(template, directives || null, pipes || null);
|
||||||
host = createLNode(
|
host = createLNode(
|
||||||
null, LNodeType.Element, hostNode,
|
null, LNodeType.Element, hostNode,
|
||||||
createLView(
|
createLView(
|
||||||
-1, providedRendererFactory.createRenderer(null, null),
|
-1, providedRendererFactory.createRenderer(null, null), tView, null, {},
|
||||||
getOrCreateTView(template, directiveRegistry), null, {}, LViewFlags.CheckAlways));
|
LViewFlags.CheckAlways));
|
||||||
}
|
}
|
||||||
const hostView = host.data !;
|
const hostView = host.data !;
|
||||||
ngDevMode && assertNotNull(hostView, 'Host node should have an LView defined in host.data.');
|
ngDevMode && assertNotNull(hostView, 'Host node should have an LView defined in host.data.');
|
||||||
|
@ -432,9 +434,11 @@ export function renderEmbeddedTemplate<T>(
|
||||||
let cm: boolean = false;
|
let cm: boolean = false;
|
||||||
if (viewNode == null) {
|
if (viewNode == null) {
|
||||||
// TODO: revisit setting currentView when re-writing view containers
|
// TODO: revisit setting currentView when re-writing view containers
|
||||||
|
const directives = currentView && currentView.tView.directiveRegistry;
|
||||||
|
const pipes = currentView && currentView.tView.pipeRegistry;
|
||||||
|
|
||||||
const view = createLView(
|
const view = createLView(
|
||||||
-1, renderer, createTView(currentView && currentView.tView.directiveRegistry), template,
|
-1, renderer, createTView(directives, pipes), template, context, LViewFlags.CheckAlways);
|
||||||
context, LViewFlags.CheckAlways);
|
|
||||||
viewNode = createLNode(null, LNodeType.View, null, view);
|
viewNode = createLNode(null, LNodeType.View, null, view);
|
||||||
cm = true;
|
cm = true;
|
||||||
}
|
}
|
||||||
|
@ -655,15 +659,20 @@ function saveResolvedLocalsInData(): void {
|
||||||
* if it doesn't already exist.
|
* if it doesn't already exist.
|
||||||
*
|
*
|
||||||
* @param template The template from which to get static data
|
* @param template The template from which to get static data
|
||||||
|
* @param directives Directive defs that should be saved on TView
|
||||||
|
* @param pipes Pipe defs that should be saved on TView
|
||||||
* @returns TView
|
* @returns TView
|
||||||
*/
|
*/
|
||||||
function getOrCreateTView(
|
function getOrCreateTView(
|
||||||
template: ComponentTemplate<any>, defs: DirectiveDefListOrFactory | null): TView {
|
template: ComponentTemplate<any>, directives: DirectiveDefListOrFactory | null,
|
||||||
return template.ngPrivateData || (template.ngPrivateData = createTView(defs) as never);
|
pipes: PipeDefListOrFactory | null): TView {
|
||||||
|
return template.ngPrivateData ||
|
||||||
|
(template.ngPrivateData = createTView(directives, pipes) as never);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates a TView instance */
|
/** Creates a TView instance */
|
||||||
export function createTView(defs: DirectiveDefListOrFactory | null): TView {
|
export function createTView(
|
||||||
|
defs: DirectiveDefListOrFactory | null, pipes: PipeDefListOrFactory | null): TView {
|
||||||
return {
|
return {
|
||||||
data: [],
|
data: [],
|
||||||
directives: null,
|
directives: null,
|
||||||
|
@ -678,7 +687,8 @@ export function createTView(defs: DirectiveDefListOrFactory | null): TView {
|
||||||
pipeDestroyHooks: null,
|
pipeDestroyHooks: null,
|
||||||
hostBindings: null,
|
hostBindings: null,
|
||||||
components: null,
|
components: null,
|
||||||
directiveRegistry: typeof defs === 'function' ? defs() : defs
|
directiveRegistry: typeof defs === 'function' ? defs() : defs,
|
||||||
|
pipeRegistry: typeof pipes === 'function' ? pipes() : pipes
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -740,7 +750,7 @@ export function hostElement(
|
||||||
const node = createLNode(
|
const node = createLNode(
|
||||||
0, LNodeType.Element, rNode,
|
0, LNodeType.Element, rNode,
|
||||||
createLView(
|
createLView(
|
||||||
-1, renderer, getOrCreateTView(def.template, def.directiveDefs), null, null,
|
-1, renderer, getOrCreateTView(def.template, def.directiveDefs, def.pipeDefs), null, null,
|
||||||
def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways));
|
def.onPush ? LViewFlags.Dirty : LViewFlags.CheckAlways));
|
||||||
|
|
||||||
if (firstTemplatePass) {
|
if (firstTemplatePass) {
|
||||||
|
@ -1170,7 +1180,7 @@ export function directiveCreate<T>(
|
||||||
|
|
||||||
function addComponentLogic<T>(
|
function addComponentLogic<T>(
|
||||||
index: number, elementIndex: number, instance: T, def: ComponentDef<any>): void {
|
index: number, elementIndex: number, instance: T, def: ComponentDef<any>): void {
|
||||||
const tView = getOrCreateTView(def.template, def.directiveDefs);
|
const tView = getOrCreateTView(def.template, def.directiveDefs, def.pipeDefs);
|
||||||
|
|
||||||
// Only component views should be added to the view tree directly. Embedded views are
|
// Only component views should be added to the view tree directly. Embedded views are
|
||||||
// accessed through their containers because they may be removed / re-added later.
|
// accessed through their containers because they may be removed / re-added later.
|
||||||
|
@ -1476,7 +1486,8 @@ function getOrCreateEmbeddedTView(viewIndex: number, parent: LContainerNode): TV
|
||||||
ngDevMode && assertNodeType(parent, LNodeType.Container);
|
ngDevMode && assertNodeType(parent, LNodeType.Container);
|
||||||
const tContainer = (parent !.tNode as TContainerNode).data;
|
const tContainer = (parent !.tNode as TContainerNode).data;
|
||||||
if (viewIndex >= tContainer.length || tContainer[viewIndex] == null) {
|
if (viewIndex >= tContainer.length || tContainer[viewIndex] == null) {
|
||||||
tContainer[viewIndex] = createTView(currentView.tView.directiveRegistry);
|
const tView = currentView.tView;
|
||||||
|
tContainer[viewIndex] = createTView(tView.directiveRegistry, tView.pipeRegistry);
|
||||||
}
|
}
|
||||||
return tContainer[viewIndex];
|
return tContainer[viewIndex];
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,6 +161,14 @@ export interface ComponentDef<T> extends DirectiveDef<T> {
|
||||||
* `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;
|
directiveDefs: DirectiveDefListOrFactory|null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registry of pipes that may be found in this view.
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -176,6 +184,13 @@ export interface ComponentDef<T> extends DirectiveDef<T> {
|
||||||
* See: {@link definePipe}
|
* See: {@link definePipe}
|
||||||
*/
|
*/
|
||||||
export interface PipeDef<T> {
|
export interface PipeDef<T> {
|
||||||
|
/**
|
||||||
|
* Pipe name.
|
||||||
|
*
|
||||||
|
* Used to resolve pipe in templates.
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* factory function used to create a new directive instance.
|
* factory function used to create a new directive instance.
|
||||||
*
|
*
|
||||||
|
@ -208,6 +223,15 @@ export type DirectiveDefListOrFactory = (() => DirectiveDefList) | DirectiveDefL
|
||||||
|
|
||||||
export type DirectiveDefList = (DirectiveDef<any>| ComponentDef<any>)[];
|
export type DirectiveDefList = (DirectiveDef<any>| ComponentDef<any>)[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type used for PipeDefs on component definition.
|
||||||
|
*
|
||||||
|
* The function is necessary to be able to support forward declarations.
|
||||||
|
*/
|
||||||
|
export type PipeDefListOrFactory = (() => PipeDefList) | PipeDefList;
|
||||||
|
|
||||||
|
export type PipeDefList = PipeDef<any>[];
|
||||||
|
|
||||||
// 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;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {LContainer} from './container';
|
import {LContainer} from './container';
|
||||||
import {ComponentDef, ComponentTemplate, DirectiveDef, DirectiveDefList, PipeDef} from './definition';
|
import {ComponentTemplate, DirectiveDefList, PipeDef, PipeDefList} from './definition';
|
||||||
import {LElementNode, LViewNode, TNode} from './node';
|
import {LElementNode, LViewNode, TNode} from './node';
|
||||||
import {LQueries} from './query';
|
import {LQueries} from './query';
|
||||||
import {Renderer3} from './renderer';
|
import {Renderer3} from './renderer';
|
||||||
|
@ -245,6 +245,17 @@ export interface TView {
|
||||||
*/
|
*/
|
||||||
directiveRegistry: DirectiveDefList|null;
|
directiveRegistry: DirectiveDefList|null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Full registry of pipes that may be found in this view.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* It's necessary to keep a copy of the full def list on the TView so it's possible
|
||||||
|
* to render template functions without a host component.
|
||||||
|
*/
|
||||||
|
pipeRegistry: PipeDefList|null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of ngOnInit and ngDoCheck hooks that should be executed for this view in
|
* Array of ngOnInit and ngDoCheck hooks that should be executed for this view in
|
||||||
* creation mode.
|
* creation mode.
|
||||||
|
|
|
@ -9,10 +9,9 @@
|
||||||
import {PipeTransform} from '../change_detection/pipe_transform';
|
import {PipeTransform} from '../change_detection/pipe_transform';
|
||||||
|
|
||||||
import {getTView, load, store} from './instructions';
|
import {getTView, load, store} from './instructions';
|
||||||
import {PipeDef} from './interfaces/definition';
|
import {PipeDef, PipeDefList} from './interfaces/definition';
|
||||||
import {pureFunction1, pureFunction2, pureFunction3, pureFunction4, pureFunctionV} from './pure_function';
|
import {pureFunction1, pureFunction2, pureFunction3, pureFunction4, pureFunctionV} from './pure_function';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a pipe.
|
* Create a pipe.
|
||||||
*
|
*
|
||||||
|
@ -21,19 +20,45 @@ import {pureFunction1, pureFunction2, pureFunction3, pureFunction4, pureFunction
|
||||||
* @param firstInstance (optional) The first instance of the pipe that can be reused for pure pipes.
|
* @param firstInstance (optional) The first instance of the pipe that can be reused for pure pipes.
|
||||||
* @returns T the instance of the pipe.
|
* @returns T the instance of the pipe.
|
||||||
*/
|
*/
|
||||||
export function pipe<T>(index: number, pipeDef: PipeDef<T>, firstInstance?: T): T {
|
export function pipe(index: number, pipeName: string, firstInstance?: any): any {
|
||||||
const tView = getTView();
|
const tView = getTView();
|
||||||
|
let pipeDef: PipeDef<any>;
|
||||||
|
|
||||||
if (tView.firstTemplatePass) {
|
if (tView.firstTemplatePass) {
|
||||||
|
pipeDef = getPipeDef(pipeName, tView.pipeRegistry);
|
||||||
tView.data[index] = pipeDef;
|
tView.data[index] = pipeDef;
|
||||||
if (pipeDef.onDestroy) {
|
if (pipeDef.onDestroy) {
|
||||||
(tView.pipeDestroyHooks || (tView.pipeDestroyHooks = [])).push(index, pipeDef.onDestroy);
|
(tView.pipeDestroyHooks || (tView.pipeDestroyHooks = [])).push(index, pipeDef.onDestroy);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
pipeDef = tView.data[index] as PipeDef<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pipeInstance = pipeDef.pure && firstInstance ? firstInstance : pipeDef.n();
|
const pipeInstance = pipeDef.pure && firstInstance ? firstInstance : pipeDef.n();
|
||||||
store(index, pipeInstance);
|
store(index, pipeInstance);
|
||||||
return pipeInstance;
|
return pipeInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches the pipe registry for a pipe with the given name. If one is found,
|
||||||
|
* returns the pipe. Otherwise, an error is thrown because the pipe cannot be resolved.
|
||||||
|
*
|
||||||
|
* @param name Name of pipe to resolve
|
||||||
|
* @param registry Full list of available pipes
|
||||||
|
* @returns Matching PipeDef
|
||||||
|
*/
|
||||||
|
function getPipeDef(name: string, registry: PipeDefList | null): PipeDef<any> {
|
||||||
|
if (registry) {
|
||||||
|
for (let i = 0; i < registry.length; i++) {
|
||||||
|
const pipeDef = registry[i];
|
||||||
|
if (name === pipeDef.name) {
|
||||||
|
return pipeDef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(`Pipe with name '${name}' not found!`);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invokes a pipe with 1 arguments.
|
* Invokes a pipe with 1 arguments.
|
||||||
*
|
*
|
||||||
|
|
|
@ -38,6 +38,7 @@ describe('pipes', () => {
|
||||||
|
|
||||||
// NORMATIVE
|
// NORMATIVE
|
||||||
static ngPipeDef = $r3$.ɵdefinePipe({
|
static ngPipeDef = $r3$.ɵdefinePipe({
|
||||||
|
name: 'myPipe',
|
||||||
type: MyPipe,
|
type: MyPipe,
|
||||||
factory: function MyPipe_Factory() { return new MyPipe(); },
|
factory: function MyPipe_Factory() { return new MyPipe(); },
|
||||||
pure: false,
|
pure: false,
|
||||||
|
@ -57,6 +58,7 @@ describe('pipes', () => {
|
||||||
|
|
||||||
// NORMATIVE
|
// NORMATIVE
|
||||||
static ngPipeDef = $r3$.ɵdefinePipe({
|
static ngPipeDef = $r3$.ɵdefinePipe({
|
||||||
|
name: 'myPurePipe',
|
||||||
type: MyPurePipe,
|
type: MyPurePipe,
|
||||||
factory: function MyPurePipe_Factory() { return new MyPurePipe(); },
|
factory: function MyPurePipe_Factory() { return new MyPurePipe(); },
|
||||||
pure: true,
|
pure: true,
|
||||||
|
@ -64,11 +66,6 @@ describe('pipes', () => {
|
||||||
// /NORMATIVE
|
// /NORMATIVE
|
||||||
}
|
}
|
||||||
|
|
||||||
// NORMATIVE
|
|
||||||
const $MyPurePipe_ngPipeDef$ = MyPurePipe.ngPipeDef;
|
|
||||||
const $MyPipe_ngPipeDef$ = MyPipe.ngPipeDef;
|
|
||||||
// /NORMATIVE
|
|
||||||
|
|
||||||
it('should render pipes', () => {
|
it('should render pipes', () => {
|
||||||
type $MyApp$ = MyApp;
|
type $MyApp$ = MyApp;
|
||||||
myPipeTransformCalls = 0;
|
myPipeTransformCalls = 0;
|
||||||
|
@ -87,8 +84,8 @@ describe('pipes', () => {
|
||||||
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
template: function MyApp_Template(ctx: $MyApp$, cm: $boolean$) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
$r3$.ɵT(0);
|
$r3$.ɵT(0);
|
||||||
$r3$.ɵPp(1, $MyPipe_ngPipeDef$);
|
$r3$.ɵPp(1, 'myPipe');
|
||||||
$r3$.ɵPp(2, $MyPurePipe_ngPipeDef$);
|
$r3$.ɵPp(2, 'myPurePipe');
|
||||||
}
|
}
|
||||||
$r3$.ɵt(0, $r3$.ɵi1('', $r3$.ɵpb2(1, $r3$.ɵpb2(2, ctx.name, ctx.size), ctx.size), ''));
|
$r3$.ɵt(0, $r3$.ɵi1('', $r3$.ɵpb2(1, $r3$.ɵpb2(2, ctx.name, ctx.size), ctx.size), ''));
|
||||||
}
|
}
|
||||||
|
@ -96,6 +93,10 @@ describe('pipes', () => {
|
||||||
// /NORMATIVE
|
// /NORMATIVE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NON-NORMATIVE
|
||||||
|
MyApp.ngComponentDef.pipeDefs = () => [MyPurePipe.ngPipeDef, MyPipe.ngPipeDef];
|
||||||
|
// /NON-NORMATIVE
|
||||||
|
|
||||||
let myApp: MyApp = renderComponent(MyApp);
|
let myApp: MyApp = renderComponent(MyApp);
|
||||||
expect(toHtml(containerEl)).toEqual('World!');
|
expect(toHtml(containerEl)).toEqual('World!');
|
||||||
expect(myPurePipeTransformCalls).toEqual(1);
|
expect(myPurePipeTransformCalls).toEqual(1);
|
||||||
|
@ -115,7 +116,6 @@ describe('pipes', () => {
|
||||||
|
|
||||||
it('should render many pipes and forward the first instance (pure or impure pipe)', () => {
|
it('should render many pipes and forward the first instance (pure or impure pipe)', () => {
|
||||||
type $MyApp$ = MyApp;
|
type $MyApp$ = MyApp;
|
||||||
type $MyPurePipe$ = MyPurePipe;
|
|
||||||
myPipeTransformCalls = 0;
|
myPipeTransformCalls = 0;
|
||||||
myPurePipeTransformCalls = 0;
|
myPurePipeTransformCalls = 0;
|
||||||
|
|
||||||
|
@ -155,12 +155,12 @@ describe('pipes', () => {
|
||||||
selector: [[['my-app'], null]],
|
selector: [[['my-app'], null]],
|
||||||
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$) {
|
||||||
let $pi$: $MyPurePipe$;
|
let $pi$: $any$;
|
||||||
if (cm) {
|
if (cm) {
|
||||||
$r3$.ɵT(0);
|
$r3$.ɵT(0);
|
||||||
$pi$ = $r3$.ɵPp(1, $MyPurePipe_ngPipeDef$);
|
$pi$ = $r3$.ɵPp(1, 'myPurePipe');
|
||||||
$r3$.ɵT(2);
|
$r3$.ɵT(2);
|
||||||
$r3$.ɵPp(3, $MyPurePipe_ngPipeDef$, $pi$);
|
$r3$.ɵPp(3, 'myPurePipe', $pi$);
|
||||||
$r3$.ɵC(4, C4, '', ['oneTimeIf', '']);
|
$r3$.ɵC(4, C4, '', ['oneTimeIf', '']);
|
||||||
}
|
}
|
||||||
$r3$.ɵt(0, $r3$.ɵi1('', $r3$.ɵpb2(1, ctx.name, ctx.size), ''));
|
$r3$.ɵt(0, $r3$.ɵi1('', $r3$.ɵpb2(1, ctx.name, ctx.size), ''));
|
||||||
|
@ -173,7 +173,7 @@ describe('pipes', () => {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
$r3$.ɵE(0, 'div');
|
$r3$.ɵE(0, 'div');
|
||||||
$r3$.ɵT(1);
|
$r3$.ɵT(1);
|
||||||
$r3$.ɵPp(2, $MyPurePipe_ngPipeDef$, $pi$);
|
$r3$.ɵPp(2, 'myPurePipe', $pi$);
|
||||||
$r3$.ɵe();
|
$r3$.ɵe();
|
||||||
}
|
}
|
||||||
$r3$.ɵt(1, $r3$.ɵi1('', $r3$.ɵpb2(2, ctx.name, ctx.size), ''));
|
$r3$.ɵt(1, $r3$.ɵi1('', $r3$.ɵpb2(2, ctx.name, ctx.size), ''));
|
||||||
|
@ -185,6 +185,7 @@ describe('pipes', () => {
|
||||||
|
|
||||||
// NON-NORMATIVE
|
// NON-NORMATIVE
|
||||||
MyApp.ngComponentDef.directiveDefs = [OneTimeIf.ngDirectiveDef];
|
MyApp.ngComponentDef.directiveDefs = [OneTimeIf.ngDirectiveDef];
|
||||||
|
MyApp.ngComponentDef.pipeDefs = [MyPurePipe.ngPipeDef];
|
||||||
// /NON-NORMATIVE
|
// /NON-NORMATIVE
|
||||||
|
|
||||||
let myApp: MyApp = renderComponent(MyApp);
|
let myApp: MyApp = renderComponent(MyApp);
|
||||||
|
|
|
@ -691,7 +691,7 @@ describe('di', () => {
|
||||||
describe('getOrCreateNodeInjector', () => {
|
describe('getOrCreateNodeInjector', () => {
|
||||||
it('should handle initial undefined state', () => {
|
it('should handle initial undefined state', () => {
|
||||||
const contentView =
|
const contentView =
|
||||||
createLView(-1, null !, createTView(null), null, null, LViewFlags.CheckAlways);
|
createLView(-1, null !, createTView(null, null), null, null, LViewFlags.CheckAlways);
|
||||||
const oldView = enterView(contentView, null !);
|
const oldView = enterView(contentView, null !);
|
||||||
try {
|
try {
|
||||||
const parent = createLNode(0, LNodeType.Element, null, null);
|
const parent = createLNode(0, LNodeType.Element, null, null);
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {bind, container, containerRefreshEnd, containerRefreshStart, elementEnd,
|
||||||
import {pipe, pipeBind1, pipeBind3, pipeBind4, pipeBindV} from '../../src/render3/pipe';
|
import {pipe, pipeBind1, pipeBind3, pipeBind4, pipeBindV} from '../../src/render3/pipe';
|
||||||
|
|
||||||
import {RenderLog, getRendererFactory2, patchLoggingRenderer2} from './imported_renderer2';
|
import {RenderLog, getRendererFactory2, patchLoggingRenderer2} from './imported_renderer2';
|
||||||
import {renderToHtml} from './render_util';
|
import {ComponentFixture, createComponent, renderToHtml} from './render_util';
|
||||||
|
|
||||||
|
|
||||||
let log: string[] = [];
|
let log: string[] = [];
|
||||||
|
@ -30,16 +30,33 @@ describe('pipe', () => {
|
||||||
person = new Person();
|
person = new Person();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const defs = () => [CountingPipe.ngPipeDef, MultiArgPipe.ngPipeDef, CountingImpurePipe.ngPipeDef];
|
||||||
|
|
||||||
it('should support interpolation', () => {
|
it('should support interpolation', () => {
|
||||||
function Template(person: Person, cm: boolean) {
|
function Template(person: Person, cm: boolean) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
text(0);
|
text(0);
|
||||||
pipe(1, CountingPipe.ngPipeDef);
|
pipe(1, 'countingPipe');
|
||||||
}
|
}
|
||||||
textBinding(0, interpolation1('', pipeBind1(1, person.name), ''));
|
textBinding(0, interpolation1('', pipeBind1(1, person.name), ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
person.init('bob', null);
|
person.init('bob', null);
|
||||||
expect(renderToHtml(Template, person)).toEqual('bob state:0');
|
expect(renderToHtml(Template, person, null, defs)).toEqual('bob state:0');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if pipe is not found', () => {
|
||||||
|
const App = createComponent('app', function(ctx: any, cm: boolean) {
|
||||||
|
if (cm) {
|
||||||
|
text(0);
|
||||||
|
pipe(1, 'randomPipeName');
|
||||||
|
}
|
||||||
|
textBinding(0, interpolation1('', pipeBind1(1, ctx.value), ''));
|
||||||
|
}, [], defs);
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
const fixture = new ComponentFixture(App);
|
||||||
|
}).toThrowError(/Pipe with name 'randomPipeName' not found!/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support bindings', () => {
|
it('should support bindings', () => {
|
||||||
|
@ -64,6 +81,7 @@ describe('pipe', () => {
|
||||||
transform(value: any) { return `${value}${value}`; }
|
transform(value: any) { return `${value}${value}`; }
|
||||||
|
|
||||||
static ngPipeDef = definePipe({
|
static ngPipeDef = definePipe({
|
||||||
|
name: 'double',
|
||||||
type: DoublePipe,
|
type: DoublePipe,
|
||||||
factory: function DoublePipe_Factory() { return new DoublePipe(); },
|
factory: function DoublePipe_Factory() { return new DoublePipe(); },
|
||||||
});
|
});
|
||||||
|
@ -72,13 +90,13 @@ describe('pipe', () => {
|
||||||
function Template(ctx: string, cm: boolean) {
|
function Template(ctx: string, cm: boolean) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'div', ['myDir', '']);
|
elementStart(0, 'div', ['myDir', '']);
|
||||||
pipe(1, DoublePipe.ngPipeDef);
|
pipe(1, 'double');
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
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]);
|
renderToHtml(Template, 'a', [MyDir.ngDirectiveDef], [DoublePipe.ngPipeDef]);
|
||||||
expect(directive !.dirProp).toEqual('aa');
|
expect(directive !.dirProp).toEqual('aa');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -86,27 +104,29 @@ describe('pipe', () => {
|
||||||
function Template(person: Person, cm: boolean) {
|
function Template(person: Person, cm: boolean) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
text(0);
|
text(0);
|
||||||
pipe(1, MultiArgPipe.ngPipeDef);
|
pipe(1, 'multiArgPipe');
|
||||||
}
|
}
|
||||||
textBinding(
|
textBinding(
|
||||||
0, interpolation1('', pipeBind3(1, person.name, 'one', person.address !.city), ''));
|
0, interpolation1('', pipeBind3(1, person.name, 'one', person.address !.city), ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
person.init('value', new Address('two'));
|
person.init('value', new Address('two'));
|
||||||
expect(renderToHtml(Template, person)).toEqual('value one two default');
|
expect(renderToHtml(Template, person, null, defs)).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', () => {
|
||||||
function Template(person: Person, cm: boolean) {
|
function Template(person: Person, cm: boolean) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
text(0);
|
text(0);
|
||||||
pipe(1, MultiArgPipe.ngPipeDef);
|
pipe(1, 'multiArgPipe');
|
||||||
pipe(2, MultiArgPipe.ngPipeDef);
|
pipe(2, 'multiArgPipe');
|
||||||
}
|
}
|
||||||
textBinding(
|
textBinding(
|
||||||
0, interpolation1('', pipeBind4(2, pipeBindV(1, [person.name, 'a', 'b']), 0, 1, 2), ''));
|
0, interpolation1('', pipeBind4(2, pipeBindV(1, [person.name, 'a', 'b']), 0, 1, 2), ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
person.init('value', null);
|
person.init('value', null);
|
||||||
expect(renderToHtml(Template, person)).toEqual('value a b default 0 1 2');
|
expect(renderToHtml(Template, person, null, defs)).toEqual('value a b default 0 1 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should do nothing when no change', () => {
|
it('should do nothing when no change', () => {
|
||||||
|
@ -115,6 +135,7 @@ describe('pipe', () => {
|
||||||
transform(value: any) { return value; }
|
transform(value: any) { return value; }
|
||||||
|
|
||||||
static ngPipeDef = definePipe({
|
static ngPipeDef = definePipe({
|
||||||
|
name: 'identityPipe',
|
||||||
type: IdentityPipe,
|
type: IdentityPipe,
|
||||||
factory: function IdentityPipe_Factory() { return new IdentityPipe(); },
|
factory: function IdentityPipe_Factory() { return new IdentityPipe(); },
|
||||||
});
|
});
|
||||||
|
@ -123,16 +144,17 @@ describe('pipe', () => {
|
||||||
function Template(person: Person, cm: boolean) {
|
function Template(person: Person, cm: boolean) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'div');
|
elementStart(0, 'div');
|
||||||
pipe(1, IdentityPipe.ngPipeDef);
|
pipe(1, 'identityPipe');
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
elementProperty(0, 'someProp', bind(pipeBind1(1, 'Megatron')));
|
elementProperty(0, 'someProp', bind(pipeBind1(1, 'Megatron')));
|
||||||
}
|
}
|
||||||
renderToHtml(Template, person, [], rendererFactory2);
|
|
||||||
|
renderToHtml(Template, person, null, [IdentityPipe.ngPipeDef], rendererFactory2);
|
||||||
expect(renderLog.log).toEqual(['someProp=Megatron']);
|
expect(renderLog.log).toEqual(['someProp=Megatron']);
|
||||||
|
|
||||||
renderLog.clear();
|
renderLog.clear();
|
||||||
renderToHtml(Template, person, [], rendererFactory2);
|
renderToHtml(Template, person, null, defs, rendererFactory2);
|
||||||
expect(renderLog.log).toEqual([]);
|
expect(renderLog.log).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -141,36 +163,36 @@ describe('pipe', () => {
|
||||||
function Template(person: Person, cm: boolean) {
|
function Template(person: Person, cm: boolean) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
text(0);
|
text(0);
|
||||||
pipe(1, CountingPipe.ngPipeDef);
|
pipe(1, 'countingPipe');
|
||||||
}
|
}
|
||||||
textBinding(0, interpolation1('', pipeBind1(1, person.name), ''));
|
textBinding(0, interpolation1('', pipeBind1(1, person.name), ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
// change from undefined -> null
|
// change from undefined -> null
|
||||||
person.name = null;
|
person.name = null;
|
||||||
expect(renderToHtml(Template, person)).toEqual('null state:0');
|
expect(renderToHtml(Template, person, null, defs)).toEqual('null state:0');
|
||||||
expect(renderToHtml(Template, person)).toEqual('null state:0');
|
expect(renderToHtml(Template, person, null, defs)).toEqual('null state:0');
|
||||||
|
|
||||||
// change from null -> some value
|
// change from null -> some value
|
||||||
person.name = 'bob';
|
person.name = 'bob';
|
||||||
expect(renderToHtml(Template, person)).toEqual('bob state:1');
|
expect(renderToHtml(Template, person, null, defs)).toEqual('bob state:1');
|
||||||
expect(renderToHtml(Template, person)).toEqual('bob state:1');
|
expect(renderToHtml(Template, person, null, defs)).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)).toEqual('bart state:2');
|
expect(renderToHtml(Template, person, null, defs)).toEqual('bart state:2');
|
||||||
expect(renderToHtml(Template, person)).toEqual('bart state:2');
|
expect(renderToHtml(Template, person, null, defs)).toEqual('bart state:2');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should cache pure pipes', () => {
|
it('should cache pure pipes', () => {
|
||||||
function Template(ctx: any, cm: boolean) {
|
function Template(ctx: any, cm: boolean) {
|
||||||
let pipeInstance;
|
let pipeInstance: any;
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'div');
|
elementStart(0, 'div');
|
||||||
pipeInstance = pipe(1, CountingPipe.ngPipeDef);
|
pipeInstance = pipe(1, 'countingPipe');
|
||||||
elementEnd();
|
elementEnd();
|
||||||
elementStart(2, 'div');
|
elementStart(2, 'div');
|
||||||
pipe(3, CountingPipe.ngPipeDef, pipeInstance);
|
pipe(3, 'countingPipe', pipeInstance);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
container(4);
|
container(4);
|
||||||
}
|
}
|
||||||
|
@ -184,7 +206,7 @@ describe('pipe', () => {
|
||||||
{
|
{
|
||||||
if (cm1) {
|
if (cm1) {
|
||||||
elementStart(0, 'div');
|
elementStart(0, 'div');
|
||||||
pipe(1, CountingPipe.ngPipeDef, pipeInstance);
|
pipe(1, 'countingPipe', pipeInstance);
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
elementProperty(0, 'someProp', bind(pipeBind1(1, true)));
|
elementProperty(0, 'someProp', bind(pipeBind1(1, true)));
|
||||||
|
@ -195,8 +217,9 @@ describe('pipe', () => {
|
||||||
}
|
}
|
||||||
containerRefreshEnd();
|
containerRefreshEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
const pipeInstances: CountingPipe[] = [];
|
const pipeInstances: CountingPipe[] = [];
|
||||||
renderToHtml(Template, {}, [], rendererFactory2);
|
renderToHtml(Template, {}, null, defs, rendererFactory2);
|
||||||
expect(pipeInstances.length).toEqual(4);
|
expect(pipeInstances.length).toEqual(4);
|
||||||
expect(pipeInstances[0]).toBeAnInstanceOf(CountingPipe);
|
expect(pipeInstances[0]).toBeAnInstanceOf(CountingPipe);
|
||||||
expect(pipeInstances[1]).toBe(pipeInstances[0]);
|
expect(pipeInstances[1]).toBe(pipeInstances[0]);
|
||||||
|
@ -210,24 +233,24 @@ describe('pipe', () => {
|
||||||
function Template(person: Person, cm: boolean) {
|
function Template(person: Person, cm: boolean) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
text(0);
|
text(0);
|
||||||
pipe(1, CountingImpurePipe.ngPipeDef);
|
pipe(1, 'countingImpurePipe');
|
||||||
}
|
}
|
||||||
textBinding(0, interpolation1('', pipeBind1(1, person.name), ''));
|
textBinding(0, interpolation1('', pipeBind1(1, person.name), ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
person.name = 'bob';
|
person.name = 'bob';
|
||||||
expect(renderToHtml(Template, person)).toEqual('bob state:0');
|
expect(renderToHtml(Template, person, null, defs)).toEqual('bob state:0');
|
||||||
expect(renderToHtml(Template, person)).toEqual('bob state:1');
|
expect(renderToHtml(Template, person, null, defs)).toEqual('bob state:1');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not cache impure pipes', () => {
|
it('should not cache impure pipes', () => {
|
||||||
function Template(ctx: any, cm: boolean) {
|
function Template(ctx: any, cm: boolean) {
|
||||||
if (cm) {
|
if (cm) {
|
||||||
elementStart(0, 'div');
|
elementStart(0, 'div');
|
||||||
pipe(1, CountingImpurePipe.ngPipeDef);
|
pipe(1, 'countingImpurePipe');
|
||||||
elementEnd();
|
elementEnd();
|
||||||
elementStart(2, 'div');
|
elementStart(2, 'div');
|
||||||
pipe(3, CountingImpurePipe.ngPipeDef);
|
pipe(3, 'countingImpurePipe');
|
||||||
elementEnd();
|
elementEnd();
|
||||||
container(4);
|
container(4);
|
||||||
}
|
}
|
||||||
|
@ -241,7 +264,7 @@ describe('pipe', () => {
|
||||||
{
|
{
|
||||||
if (cm1) {
|
if (cm1) {
|
||||||
elementStart(0, 'div');
|
elementStart(0, 'div');
|
||||||
pipe(1, CountingImpurePipe.ngPipeDef);
|
pipe(1, 'countingImpurePipe');
|
||||||
elementEnd();
|
elementEnd();
|
||||||
}
|
}
|
||||||
elementProperty(0, 'someProp', bind(pipeBind1(1, true)));
|
elementProperty(0, 'someProp', bind(pipeBind1(1, true)));
|
||||||
|
@ -252,8 +275,9 @@ describe('pipe', () => {
|
||||||
}
|
}
|
||||||
containerRefreshEnd();
|
containerRefreshEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
const pipeInstances: CountingImpurePipe[] = [];
|
const pipeInstances: CountingImpurePipe[] = [];
|
||||||
renderToHtml(Template, {}, [], rendererFactory2);
|
renderToHtml(Template, {}, null, defs, 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);
|
||||||
|
@ -273,6 +297,7 @@ describe('pipe', () => {
|
||||||
transform(value: any): any { return null; }
|
transform(value: any): any { return null; }
|
||||||
|
|
||||||
static ngPipeDef = definePipe({
|
static ngPipeDef = definePipe({
|
||||||
|
name: 'pipeWithOnDestroy',
|
||||||
type: PipeWithOnDestroy,
|
type: PipeWithOnDestroy,
|
||||||
factory: function PipeWithOnDestroy_Factory() { return new PipeWithOnDestroy(); },
|
factory: function PipeWithOnDestroy_Factory() { return new PipeWithOnDestroy(); },
|
||||||
});
|
});
|
||||||
|
@ -290,7 +315,7 @@ describe('pipe', () => {
|
||||||
{
|
{
|
||||||
if (cm1) {
|
if (cm1) {
|
||||||
text(0);
|
text(0);
|
||||||
pipe(1, PipeWithOnDestroy.ngPipeDef);
|
pipe(1, 'pipeWithOnDestroy');
|
||||||
}
|
}
|
||||||
textBinding(0, interpolation1('', pipeBind1(1, person.age), ''));
|
textBinding(0, interpolation1('', pipeBind1(1, person.age), ''));
|
||||||
}
|
}
|
||||||
|
@ -299,21 +324,23 @@ describe('pipe', () => {
|
||||||
}
|
}
|
||||||
containerRefreshEnd();
|
containerRefreshEnd();
|
||||||
}
|
}
|
||||||
|
const defs = [PipeWithOnDestroy.ngPipeDef];
|
||||||
|
|
||||||
person.age = 25;
|
person.age = 25;
|
||||||
renderToHtml(Template, person);
|
renderToHtml(Template, person, null, defs);
|
||||||
|
|
||||||
person.age = 15;
|
person.age = 15;
|
||||||
renderToHtml(Template, person);
|
renderToHtml(Template, person, null, defs);
|
||||||
expect(log).toEqual(['pipeWithOnDestroy - ngOnDestroy']);
|
expect(log).toEqual(['pipeWithOnDestroy - ngOnDestroy']);
|
||||||
|
|
||||||
log = [];
|
log = [];
|
||||||
person.age = 30;
|
person.age = 30;
|
||||||
renderToHtml(Template, person);
|
renderToHtml(Template, person, null, defs);
|
||||||
expect(log).toEqual([]);
|
expect(log).toEqual([]);
|
||||||
|
|
||||||
log = [];
|
log = [];
|
||||||
person.age = 10;
|
person.age = 10;
|
||||||
renderToHtml(Template, person);
|
renderToHtml(Template, person, null, defs);
|
||||||
expect(log).toEqual(['pipeWithOnDestroy - ngOnDestroy']);
|
expect(log).toEqual(['pipeWithOnDestroy - ngOnDestroy']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -327,6 +354,7 @@ class CountingPipe implements PipeTransform {
|
||||||
transform(value: any) { return `${value} state:${this.state++}`; }
|
transform(value: any) { return `${value} state:${this.state++}`; }
|
||||||
|
|
||||||
static ngPipeDef = definePipe({
|
static ngPipeDef = definePipe({
|
||||||
|
name: 'countingPipe',
|
||||||
type: CountingPipe,
|
type: CountingPipe,
|
||||||
factory: function CountingPipe_Factory() { return new CountingPipe(); },
|
factory: function CountingPipe_Factory() { return new CountingPipe(); },
|
||||||
});
|
});
|
||||||
|
@ -339,6 +367,7 @@ class CountingImpurePipe implements PipeTransform {
|
||||||
transform(value: any) { return `${value} state:${this.state++}`; }
|
transform(value: any) { return `${value} state:${this.state++}`; }
|
||||||
|
|
||||||
static ngPipeDef = definePipe({
|
static ngPipeDef = definePipe({
|
||||||
|
name: 'countingImpurePipe',
|
||||||
type: CountingImpurePipe,
|
type: CountingImpurePipe,
|
||||||
factory: function CountingImpurePipe_Factory() { return new CountingImpurePipe(); },
|
factory: function CountingImpurePipe_Factory() { return new CountingImpurePipe(); },
|
||||||
pure: false,
|
pure: false,
|
||||||
|
@ -352,6 +381,7 @@ class MultiArgPipe implements PipeTransform {
|
||||||
}
|
}
|
||||||
|
|
||||||
static ngPipeDef = definePipe({
|
static ngPipeDef = definePipe({
|
||||||
|
name: 'multiArgPipe',
|
||||||
type: MultiArgPipe,
|
type: MultiArgPipe,
|
||||||
factory: function MultiArgPipe_Factory() { return new MultiArgPipe(); },
|
factory: function MultiArgPipe_Factory() { return new MultiArgPipe(); },
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {stringifyElement} from '@angular/platform-browser/testing/src/browser_ut
|
||||||
import {CreateComponentOptions} from '../../src/render3/component';
|
import {CreateComponentOptions} from '../../src/render3/component';
|
||||||
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 {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';
|
||||||
|
|
||||||
|
@ -151,10 +152,11 @@ export function resetDOM() {
|
||||||
* @deprecated use `TemplateFixture` or `ComponentFixture`
|
* @deprecated use `TemplateFixture` or `ComponentFixture`
|
||||||
*/
|
*/
|
||||||
export function renderToHtml(
|
export function renderToHtml(
|
||||||
template: ComponentTemplate<any>, ctx: any, defs?: any[],
|
template: ComponentTemplate<any>, ctx: any, directives?: DirectiveDefListOrFactory | null,
|
||||||
providedRendererFactory?: RendererFactory3 | null) {
|
pipes?: PipeDefListOrFactory | null, providedRendererFactory?: RendererFactory3 | null) {
|
||||||
host = renderTemplate(
|
host = renderTemplate(
|
||||||
containerEl, template, ctx, providedRendererFactory || testRendererFactory, host, defs);
|
containerEl, template, ctx, providedRendererFactory || testRendererFactory, host,
|
||||||
|
directives || null, pipes || null);
|
||||||
return toHtml(containerEl);
|
return toHtml(containerEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,8 +191,8 @@ export function toHtml<T>(componentOrElement: T | RElement): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createComponent(
|
export function createComponent(
|
||||||
name: string, template: ComponentTemplate<any>,
|
name: string, template: ComponentTemplate<any>, directives: DirectiveDefListOrFactory = [],
|
||||||
defs: (ComponentDef<any>| DirectiveDef<any>)[] = []): ComponentType<any> {
|
pipes: PipeDefListOrFactory = []): ComponentType<any> {
|
||||||
return class Component {
|
return class Component {
|
||||||
value: any;
|
value: any;
|
||||||
static ngComponentDef = defineComponent({
|
static ngComponentDef = defineComponent({
|
||||||
|
@ -199,7 +201,8 @@ export function createComponent(
|
||||||
factory: () => new Component,
|
factory: () => new Component,
|
||||||
template: template,
|
template: template,
|
||||||
features: [PublicFeature],
|
features: [PublicFeature],
|
||||||
directiveDefs: () => defs
|
directiveDefs: directives,
|
||||||
|
pipeDefs: pipes
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ describe('renderer factory lifecycle', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should work with a template', () => {
|
it('should work with a template', () => {
|
||||||
renderToHtml(Template, {}, [], rendererFactory);
|
renderToHtml(Template, {}, null, null, rendererFactory);
|
||||||
expect(logs).toEqual(['create', 'begin', 'function', 'end']);
|
expect(logs).toEqual(['create', 'begin', 'function', 'end']);
|
||||||
|
|
||||||
logs = [];
|
logs = [];
|
||||||
|
@ -97,7 +97,7 @@ 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, rendererFactory);
|
renderToHtml(TemplateWithComponent, {}, defs, null, rendererFactory);
|
||||||
expect(logs).toEqual(
|
expect(logs).toEqual(
|
||||||
['create', 'begin', 'function_with_component', 'create', 'component', 'end']);
|
['create', 'begin', 'function_with_component', 'create', 'component', 'end']);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue