refactor(compiler-cli): implement ɵɵngDeclarePipe() (#40803)

This commit implements creating of `ɵɵngDeclarePipe()` calls in partial
compilation, and processing of those calls in the linker and JIT compiler.

See #40677

PR Close #40803
This commit is contained in:
Pete Bacon Darwin
2021-02-12 09:00:16 -08:00
committed by Joey Perrott
parent 6425a6d543
commit 9cb43fb507
26 changed files with 265 additions and 46 deletions
+35 -6
View File
@@ -23,10 +23,10 @@ export interface R3PartialDeclaration {
}
/**
* This interface describes the shape of the object that partial directive declarations are compiled
* into. This serves only as documentation, as conformance of this interface is not enforced during
* the generation of the partial declaration, nor when the linker applies full compilation from the
* partial declaration.
* Describes the shape of the object that the `ɵɵngDeclareDirective() function accepts.
*
* This interface serves primarily as documentation, as conformance to this interface is not
* enforced during linking.
*/
export interface R3DeclareDirectiveMetadata extends R3PartialDeclaration {
/**
@@ -114,8 +114,10 @@ export interface R3DeclareDirectiveMetadata extends R3PartialDeclaration {
}
/**
* An extension of `R3DeclareDirectiveMetadata` that declares the shape of a partial declaration of
* a component.
* Describes the shape of the object that the `ɵɵngDeclareComponent()` function accepts.
*
* This interface serves primarily as documentation, as conformance to this interface is not
* enforced during linking.
*/
export interface R3DeclareComponentMetadata extends R3DeclareDirectiveMetadata {
/**
@@ -261,3 +263,30 @@ export interface R3DeclareQueryMetadata {
*/
static?: boolean;
}
/**
* Describes the shape of the object that the `ɵɵngDeclarePipe()` function accepts.
*
* This interface serves primarily as documentation, as conformance to this interface is not
* enforced during linking.
*/
export interface R3DeclarePipeMetadata extends R3PartialDeclaration {
/**
* Reference to the pipe class itself.
*/
type: o.Expression;
/**
* The name to use in templates to refer to this pipe.
*/
name: string;
/**
* Whether this pipe is "pure".
*
* A pure pipe's `transform()` method is only invoked when its input arguments change.
*
* Default: true.
*/
pure?: boolean;
}
@@ -0,0 +1,50 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import * as o from '../../output/output_ast';
import {Identifiers as R3} from '../r3_identifiers';
import {createPipeType, R3PipeMetadata} from '../r3_pipe_compiler';
import {R3PipeDef} from '../view/api';
import {DefinitionMap} from '../view/util';
import {R3DeclarePipeMetadata} from './api';
/**
* Compile a Pipe declaration defined by the `R3PipeMetadata`.
*/
export function compileDeclarePipeFromMetadata(meta: R3PipeMetadata): R3PipeDef {
const definitionMap = createPipeDefinitionMap(meta);
const expression = o.importExpr(R3.declarePipe).callFn([definitionMap.toLiteralMap()]);
const type = createPipeType(meta);
return {expression, type};
}
/**
* Gathers the declaration fields for a Pipe into a `DefinitionMap`. This allows for reusing
* this logic for components, as they extend the Pipe metadata.
*/
export function createPipeDefinitionMap(meta: R3PipeMetadata):
DefinitionMap<R3DeclarePipeMetadata> {
const definitionMap = new DefinitionMap<R3DeclarePipeMetadata>();
definitionMap.set('version', o.literal('0.0.0-PLACEHOLDER'));
definitionMap.set('ngImport', o.importExpr(R3.core));
// e.g. `type: MyPipe`
definitionMap.set('type', meta.internalType);
// e.g. `name: "myPipe"`
definitionMap.set('name', o.literal(meta.pipeName));
if (meta.pure === false) {
// e.g. `pure: false`
definitionMap.set('pure', o.literal(meta.pure));
}
return definitionMap;
}
@@ -294,6 +294,7 @@ export class Identifiers {
static PipeDefWithMeta: o.ExternalReference = {name: 'ɵɵPipeDefWithMeta', moduleName: CORE};
static definePipe: o.ExternalReference = {name: 'ɵɵdefinePipe', moduleName: CORE};
static declarePipe: o.ExternalReference = {name: 'ɵɵngDeclarePipe', moduleName: CORE};
static queryRefresh: o.ExternalReference = {name: 'ɵɵqueryRefresh', moduleName: CORE};
static viewQuery: o.ExternalReference = {name: 'ɵɵviewQuery', moduleName: CORE};
@@ -15,6 +15,7 @@ import {error, OutputContext} from '../util';
import {compileFactoryFunction, dependenciesFromGlobalMetadata, R3DependencyMetadata, R3FactoryTarget} from './r3_factory';
import {Identifiers as R3} from './r3_identifiers';
import {R3Reference, typeWithParameters, wrapReference} from './util';
import {R3PipeDef} from './view/api';
export interface R3PipeMetadata {
/**
@@ -57,7 +58,7 @@ export interface R3PipeMetadata {
pure: boolean;
}
export function compilePipeFromMetadata(metadata: R3PipeMetadata) {
export function compilePipeFromMetadata(metadata: R3PipeMetadata): R3PipeDef {
const definitionMapValues: {key: string, quoted: boolean, value: o.Expression}[] = [];
// e.g. `name: 'myPipe'`
@@ -70,12 +71,16 @@ export function compilePipeFromMetadata(metadata: R3PipeMetadata) {
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.PipeDefWithMeta, [
const type = createPipeType(metadata);
return {expression, type};
}
export function createPipeType(metadata: R3PipeMetadata): o.Type {
return new o.ExpressionType(o.importExpr(R3.PipeDefWithMeta, [
typeWithParameters(metadata.type.type, metadata.typeArgumentCount),
new o.ExpressionType(new o.LiteralExpr(metadata.pipeName)),
]));
return {expression, type};
}
/**
@@ -349,6 +349,14 @@ export interface R3ComponentDef {
type: o.Type;
}
/**
* Output of render3 pipe compilation.
*/
export interface R3PipeDef {
expression: o.Expression;
type: o.Type;
}
/**
* Mappings indicating how the class interacts with its
* host element (host bindings, listeners, etc).