fix(ngcc): do not collect private declarations from external packages (#34811)

Previously, while trying to build an `NgccReflectionHost`'s
`privateDtsDeclarationMap`, `computePrivateDtsDeclarationMap()` would
try to collect exported declarations from all source files of the
program (i.e. without checking whether they were within the target
package, as happens for declarations in `.d.ts` files).

Most of the time, that would not be a problem, because external packages
would be represented as `.d.ts` files in the program. But when an
external package had no typings, the JS files would be used instead. As
a result, the `ReflectionHost` would try to (unnecessarilly) parse the
file in order to extract exported declarations, which in turn would be
harmless in most cases.

There are certain cases, though, where the `ReflectionHost` would throw
an error, because it cannot parse the external package's JS file. This
could happen, for example, in `UmdReflectionHost`, which expects the
file to contain exactly one statement. See #34544 for more details on a
real-world failure.

This commit fixes the issue by ensuring that
`computePrivateDtsDeclarationMap()` will only collect exported
declarations from files within the target package.

Jira issue: [FW-1794](https://angular-team.atlassian.net/browse/FW-1794)

Fixes #34544

PR Close #34811
This commit is contained in:
George Kalpakas
2020-01-15 21:54:36 +02:00
committed by Andrew Kushnir
parent ba2bf82540
commit 5b42084912
10 changed files with 76 additions and 16 deletions

View File

@ -50,7 +50,7 @@ export const CONSTRUCTOR_PARAMS = 'ctorParameters' as ts.__String;
*/
export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements NgccReflectionHost {
/**
* A mapping from source declarations typings declarations, which are both publicly exported.
* A mapping from source declarations to typings declarations, which are both publicly exported.
*
* There should be one entry for every public export visible from the root file of the source
* tree. Note that by definition the key and value declarations will not be in the same TS
@ -1573,14 +1573,14 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
Map<ts.Declaration, ts.Declaration> {
const declarationMap = new Map<ts.Declaration, ts.Declaration>();
const dtsDeclarationMap = new Map<string, ts.Declaration>();
const dtsFiles = getNonRootFiles(dts);
const typeChecker = dts.program.getTypeChecker();
const dtsFiles = getNonRootPackageFiles(dts);
for (const dtsFile of dtsFiles) {
if (isWithinPackage(dts.package, dtsFile)) {
this.collectDtsExportedDeclarations(dtsDeclarationMap, dtsFile, typeChecker);
}
this.collectDtsExportedDeclarations(dtsDeclarationMap, dtsFile, typeChecker);
}
const srcFiles = getNonRootFiles(src);
const srcFiles = getNonRootPackageFiles(src);
for (const srcFile of srcFiles) {
this.collectSrcExportedDeclarations(declarationMap, dtsDeclarationMap, srcFile);
}
@ -2070,7 +2070,8 @@ function getRootFileOrFail(bundle: BundleProgram): ts.SourceFile {
return rootFile;
}
function getNonRootFiles(bundle: BundleProgram): ts.SourceFile[] {
function getNonRootPackageFiles(bundle: BundleProgram): ts.SourceFile[] {
const rootFile = bundle.program.getSourceFile(bundle.path);
return bundle.program.getSourceFiles().filter(f => f !== rootFile);
return bundle.program.getSourceFiles().filter(
f => (f !== rootFile) && isWithinPackage(bundle.package, f));
}