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-11 14:42:10 +00:00
committed by Joey Perrott
parent 6425a6d543
commit 9cb43fb507
26 changed files with 265 additions and 46 deletions
@@ -14,10 +14,12 @@ import {LinkerEnvironment} from '../linker_environment';
import {PartialComponentLinkerVersion1} from './partial_component_linker_1';
import {PartialDirectiveLinkerVersion1} from './partial_directive_linker_1';
import {PartialLinker} from './partial_linker';
import {PartialPipeLinkerVersion1} from './partial_pipe_linker_1';
export const ɵɵngDeclareDirective = 'ɵɵngDeclareDirective';
export const ɵɵngDeclareComponent = 'ɵɵngDeclareComponent';
export const declarationFunctions = [ɵɵngDeclareDirective, ɵɵngDeclareComponent];
export const ɵɵngDeclarePipe = 'ɵɵngDeclarePipe';
export const declarationFunctions = [ɵɵngDeclareDirective, ɵɵngDeclareComponent, ɵɵngDeclarePipe];
interface LinkerRange<TExpression> {
range: string;
@@ -81,6 +83,7 @@ export class PartialLinkerSelector<TStatement, TExpression> {
const partialComponentLinkerVersion1 = new PartialComponentLinkerVersion1(
environment, createGetSourceFile(sourceUrl, code, environment.sourceFileLoader), sourceUrl,
code);
const partialPipeLinkerVersion1 = new PartialPipeLinkerVersion1();
const linkers = new Map<string, LinkerRange<TExpression>[]>();
linkers.set(ɵɵngDeclareDirective, [
@@ -91,6 +94,10 @@ export class PartialLinkerSelector<TStatement, TExpression> {
{range: '0.0.0-PLACEHOLDER', linker: partialComponentLinkerVersion1},
{range: '>=11.1.0-next.1', linker: partialComponentLinkerVersion1},
]);
linkers.set(ɵɵngDeclarePipe, [
{range: '0.0.0-PLACEHOLDER', linker: partialPipeLinkerVersion1},
{range: '>=11.1.0-next.1', linker: partialPipeLinkerVersion1},
]);
return linkers;
}
}
@@ -0,0 +1,58 @@
/**
* @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 {compilePipeFromMetadata, ConstantPool, R3DeclarePipeMetadata, R3PartialDeclaration, R3PipeMetadata, R3Reference} from '@angular/compiler';
import * as o from '@angular/compiler/src/output/output_ast';
import {AstObject} from '../../ast/ast_value';
import {FatalLinkerError} from '../../fatal_linker_error';
import {PartialLinker} from './partial_linker';
/**
* A `PartialLinker` that is designed to process `ɵɵngDeclarePipe()` call expressions.
*/
export class PartialPipeLinkerVersion1<TExpression> implements PartialLinker<TExpression> {
constructor() {}
linkPartialDeclaration(
constantPool: ConstantPool,
metaObj: AstObject<R3PartialDeclaration, TExpression>): o.Expression {
const meta = toR3PipeMeta(metaObj);
const def = compilePipeFromMetadata(meta);
return def.expression;
}
}
/**
* Derives the `R3PipeMetadata` structure from the AST object.
*/
export function toR3PipeMeta<TExpression>(metaObj: AstObject<R3DeclarePipeMetadata, TExpression>):
R3PipeMetadata {
const typeExpr = metaObj.getValue('type');
const typeName = typeExpr.getSymbolName();
if (typeName === null) {
throw new FatalLinkerError(
typeExpr.expression, 'Unsupported type, its name could not be determined');
}
const pure = metaObj.has('pure') ? metaObj.getBoolean('pure') : true;
return {
name: typeName,
type: wrapReference(typeExpr.getOpaque()),
internalType: metaObj.getOpaque('type'),
typeArgumentCount: 0,
deps: null,
pipeName: metaObj.getString('name'),
pure,
};
}
function wrapReference<TExpression>(wrapped: o.WrappedNodeExpr<TExpression>): R3Reference {
return {value: wrapped, type: wrapped};
}
@@ -17,6 +17,7 @@ import {LinkerEnvironment} from '../../../src/file_linker/linker_environment';
import {PartialComponentLinkerVersion1} from '../../../src/file_linker/partial_linkers/partial_component_linker_1';
import {PartialDirectiveLinkerVersion1} from '../../../src/file_linker/partial_linkers/partial_directive_linker_1';
import {PartialLinkerSelector} from '../../../src/file_linker/partial_linkers/partial_linker_selector';
import {PartialPipeLinkerVersion1} from '../../../src/file_linker/partial_linkers/partial_pipe_linker_1';
describe('PartialLinkerSelector', () => {
const options: LinkerOptions = {
@@ -42,6 +43,7 @@ describe('PartialLinkerSelector', () => {
environment, fs.resolve('/some/path/to/file.js'), 'some file contents');
expect(selector.supportsDeclaration('ɵɵngDeclareDirective')).toBe(true);
expect(selector.supportsDeclaration('ɵɵngDeclareComponent')).toBe(true);
expect(selector.supportsDeclaration('ɵɵngDeclarePipe')).toBe(true);
expect(selector.supportsDeclaration('$foo')).toBe(false);
});
@@ -60,6 +62,8 @@ describe('PartialLinkerSelector', () => {
.toBeInstanceOf(PartialDirectiveLinkerVersion1);
expect(selector.getLinker('ɵɵngDeclareComponent', '0.0.0-PLACEHOLDER'))
.toBeInstanceOf(PartialComponentLinkerVersion1);
expect(selector.getLinker('ɵɵngDeclarePipe', '0.0.0-PLACEHOLDER'))
.toBeInstanceOf(PartialPipeLinkerVersion1);
});
it('should return the linker that matches the name and valid full version', () => {