fix(ngcc): fix compilation of ChangeDetectorRef in pipe constructors (#38892)

In #38666 we changed how ngcc deals with type expressions, where it
would now always emit the original type expression into the generated
code as a "local" type value reference instead of synthesizing new
imports using an "imported" type value reference. This was done as a fix
to properly deal with renamed symbols, however it turns out that the
compiler has special handling for certain imported symbols, e.g.
`ChangeDetectorRef` from `@angular/core`. The "local" type value
reference prevented this special logic from being hit, resulting in
incorrect compilation of pipe factories.

This commit fixes the issue by manually inspecting the import of the
type expression, in order to return an "imported" type value reference.
By manually inspecting the import we continue to handle renamed symbols.

Fixes #38883

PR Close #38892
This commit is contained in:
JoostK
2020-09-17 20:40:35 +02:00
committed by Misko Hevery
parent d795a00137
commit e4424863c2
7 changed files with 92 additions and 19 deletions

View File

@ -576,6 +576,35 @@ runInEachFileSystem(() => {
`TestClass.ɵprov = ɵngcc0.ɵɵdefineInjectable({`);
});
// https://github.com/angular/angular/issues/38883
it('should recognize ChangeDetectorRef as special symbol for pipes', () => {
compileIntoFlatEs2015Package('test-package', {
'/index.ts': `
import {ChangeDetectorRef, Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'myTestPipe'
})
export class TestClass implements PipeTransform {
constructor(cdr: ChangeDetectorRef) {}
transform(value: any) { return value; }
}
`,
});
mainNgcc({
basePath: '/node_modules',
targetEntryPointPath: 'test-package',
propertiesToConsider: ['esm2015'],
});
const jsContents = fs.readFile(_(`/node_modules/test-package/index.js`));
expect(jsContents)
.toContain(
`TestClass.ɵfac = function TestClass_Factory(t) { ` +
`return new (t || TestClass)(ɵngcc0.ɵɵinjectPipeChangeDetectorRef()); };`);
});
it('should use the correct type name in typings files when an export has a different name in source files',
() => {
// We need to make sure that changes to the typings files use the correct name

View File

@ -99,7 +99,14 @@ function compileIntoFlatPackage(
program.emit();
};
emit({declaration: true, module: options.module, target: options.target, lib: []});
emit({
declaration: true,
emitDecoratorMetadata: true,
moduleResolution: ts.ModuleResolutionKind.NodeJs,
module: options.module,
target: options.target,
lib: [],
});
// Copy over the JS and .d.ts files, and add a .metadata.json for each .d.ts file.
for (const file of rootNames) {
@ -152,7 +159,9 @@ export function compileIntoApf(
compileFs.ensureDir(compileFs.resolve('esm2015'));
emit({
declaration: true,
emitDecoratorMetadata: true,
outDir: './esm2015',
moduleResolution: ts.ModuleResolutionKind.NodeJs,
module: ts.ModuleKind.ESNext,
target: ts.ScriptTarget.ES2015,
lib: [],
@ -178,7 +187,9 @@ export function compileIntoApf(
compileFs.ensureDir(compileFs.resolve('esm5'));
emit({
declaration: false,
emitDecoratorMetadata: true,
outDir: './esm5',
moduleResolution: ts.ModuleResolutionKind.NodeJs,
module: ts.ModuleKind.ESNext,
target: ts.ScriptTarget.ES5,
lib: [],