feat(ivy): support pipe compilation from local metadata (#24703)

This updates the r3_pipe_compiler to not depend on global analysis,
and to produce ngPipeDef instructions in the same way that the other
compilers do. It's a precursor to JIT and AOT implementations of
@Pipe compilation.

PR Close #24703
This commit is contained in:
Alex Rickabaugh
2018-06-26 10:43:06 -07:00
committed by Miško Hevery
parent ffbacdf4ac
commit dbdcfed2bd
11 changed files with 78 additions and 43 deletions

View File

@ -12,55 +12,84 @@ import {DefinitionKind} from '../constant_pool';
import * as o from '../output/output_ast';
import {OutputContext, error} from '../util';
import {compileFactoryFunction, dependenciesFromGlobalMetadata} from './r3_factory';
import {R3DependencyMetadata, compileFactoryFunction, dependenciesFromGlobalMetadata} from './r3_factory';
import {Identifiers as R3} from './r3_identifiers';
export interface R3PipeMetadata {
name: string;
type: o.Expression;
pipeName: string;
deps: R3DependencyMetadata[];
pure: boolean;
}
/**
* Write a pipe definition to the output context.
*/
export function compilePipe(
outputCtx: OutputContext, pipe: CompilePipeMetadata, reflector: CompileReflector) {
export interface R3PipeDef {
expression: o.Expression;
type: o.Type;
}
export function compilePipeFromMetadata(metadata: R3PipeMetadata) {
const definitionMapValues: {key: string, quoted: boolean, value: o.Expression}[] = [];
// e.g. `name: 'myPipe'`
definitionMapValues.push({key: 'name', value: o.literal(pipe.name), quoted: false});
definitionMapValues.push({key: 'name', value: o.literal(metadata.pipeName), quoted: false});
// e.g. `type: MyPipe`
definitionMapValues.push(
{key: 'type', value: outputCtx.importExpr(pipe.type.reference), quoted: false});
definitionMapValues.push({key: 'type', value: metadata.type, quoted: false});
// e.g. `factory: function MyPipe_Factory() { return new MyPipe(); }`
const deps = dependenciesFromGlobalMetadata(pipe.type, outputCtx, reflector);
const templateFactory = compileFactoryFunction({
name: identifierName(pipe.type) !,
fnOrClass: outputCtx.importExpr(pipe.type.reference), deps,
name: metadata.name,
fnOrClass: metadata.type,
deps: metadata.deps,
useNew: true,
injectFn: R3.directiveInject,
});
definitionMapValues.push({key: 'factory', value: templateFactory, quoted: false});
// e.g. `pure: true`
if (pipe.pure) {
definitionMapValues.push({key: 'pure', value: o.literal(true), quoted: false});
definitionMapValues.push({key: 'pure', value: o.literal(metadata.pure), quoted: false});
const expression = o.importExpr(R3.definePipe).callFn([o.literalMap(definitionMapValues)]);
const type = new o.ExpressionType(o.importExpr(R3.PipeDef, [
new o.ExpressionType(metadata.type),
new o.ExpressionType(new o.LiteralExpr(metadata.pipeName)),
]));
return {expression, type};
}
/**
* Write a pipe definition to the output context.
*/
export function compilePipeFromRender2(
outputCtx: OutputContext, pipe: CompilePipeMetadata, reflector: CompileReflector) {
const definitionMapValues: {key: string, quoted: boolean, value: o.Expression}[] = [];
const name = identifierName(pipe.type);
if (!name) {
return error(`Cannot resolve the name of ${pipe.type}`);
}
const className = identifierName(pipe.type) !;
className || error(`Cannot resolve the name of ${pipe.type}`);
const metadata: R3PipeMetadata = {
name,
pipeName: pipe.name,
type: outputCtx.importExpr(pipe.type.reference),
deps: dependenciesFromGlobalMetadata(pipe.type, outputCtx, reflector),
pure: pipe.pure,
};
const res = compilePipeFromMetadata(metadata);
const definitionField = outputCtx.constantPool.propertyNameOf(DefinitionKind.Pipe);
const definitionFunction =
o.importExpr(R3.definePipe).callFn([o.literalMap(definitionMapValues)]);
outputCtx.statements.push(new o.ClassStmt(
/* name */ className,
/* name */ name,
/* parent */ null,
/* fields */[new o.ClassField(
/* name */ definitionField,
/* type */ o.INFERRED_TYPE,
/* modifiers */[o.StmtModifier.Static],
/* initializer */ definitionFunction)],
/* initializer */ res.expression)],
/* getters */[],
/* constructorMethod */ new o.ClassMethod(null, [], []),
/* methods */[]));
}
}