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:

committed by
Miško Hevery

parent
ffbacdf4ac
commit
dbdcfed2bd
@ -23,7 +23,7 @@ import {OutputEmitter} from '../output/abstract_emitter';
|
||||
import * as o from '../output/output_ast';
|
||||
import {ParseError} from '../parse_util';
|
||||
import {compileNgModuleFromRender2 as compileR3Module} from '../render3/r3_module_compiler';
|
||||
import {compilePipe as compileR3Pipe} from '../render3/r3_pipe_compiler';
|
||||
import {compilePipeFromRender2 as compileR3Pipe} from '../render3/r3_pipe_compiler';
|
||||
import {htmlAstToRender3Ast} from '../render3/r3_template_transform';
|
||||
import {compileComponentFromRender2 as compileR3Component, compileDirectiveFromRender2 as compileR3Directive} from '../render3/view/compiler';
|
||||
import {DomElementSchemaRegistry} from '../schema/dom_element_schema_registry';
|
||||
|
@ -84,6 +84,7 @@ export * from './render3/view/api';
|
||||
export {jitExpression} from './render3/r3_jit';
|
||||
export {R3DependencyMetadata, R3FactoryMetadata, R3ResolvedDependencyType} from './render3/r3_factory';
|
||||
export {compileInjector, compileNgModule, R3InjectorMetadata, R3NgModuleMetadata} from './render3/r3_module_compiler';
|
||||
export {compilePipeFromMetadata, R3PipeMetadata} from './render3/r3_pipe_compiler';
|
||||
export {makeBindingParser, parseTemplate} from './render3/view/template';
|
||||
export {compileComponentFromMetadata, compileDirectiveFromMetadata, parseHostBindings} from './render3/view/compiler';
|
||||
// This file only reexports content of the `src` folder. Keep it that way.
|
@ -131,6 +131,8 @@ export class Identifiers {
|
||||
|
||||
static defineNgModule: o.ExternalReference = {name: 'ɵdefineNgModule', moduleName: CORE};
|
||||
|
||||
static PipeDef: o.ExternalReference = {name: 'ɵPipeDef', moduleName: CORE};
|
||||
|
||||
static definePipe: o.ExternalReference = {name: 'ɵdefinePipe', moduleName: CORE};
|
||||
|
||||
static query: o.ExternalReference = {name: 'ɵQ', moduleName: CORE};
|
||||
|
@ -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 */[]));
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import {ConstantPool} from '../../src/constant_pool';
|
||||
import * as html from '../../src/ml_parser/ast';
|
||||
import {removeWhitespaces} from '../../src/ml_parser/html_whitespaces';
|
||||
import * as o from '../../src/output/output_ast';
|
||||
import {compilePipe} from '../../src/render3/r3_pipe_compiler';
|
||||
import {compilePipeFromRender2} from '../../src/render3/r3_pipe_compiler';
|
||||
import {htmlAstToRender3Ast} from '../../src/render3/r3_template_transform';
|
||||
import {compileComponentFromRender2, compileDirectiveFromRender2} from '../../src/render3/view/compiler';
|
||||
import {BindingParser} from '../../src/template_parser/binding_parser';
|
||||
@ -320,7 +320,7 @@ export function compile(
|
||||
} else if (resolver.isPipe(pipeOrDirective)) {
|
||||
const metadata = resolver.getPipeMetadata(pipeOrDirective);
|
||||
if (metadata) {
|
||||
compilePipe(outputCtx, metadata, reflector);
|
||||
compilePipeFromRender2(outputCtx, metadata, reflector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1072,7 +1072,7 @@ describe('compiler compliance', () => {
|
||||
it('should render pipes', () => {
|
||||
const MyPipeDefinition = `
|
||||
static ngPipeDef = $r3$.ɵdefinePipe(
|
||||
{name: 'myPipe', type: MyPipe, factory: function MyPipe_Factory() { return new MyPipe(); }});
|
||||
{name: 'myPipe', type: MyPipe, factory: function MyPipe_Factory() { return new MyPipe(); }, pure: false});
|
||||
`;
|
||||
|
||||
const MyPurePipeDefinition = `
|
||||
|
Reference in New Issue
Block a user