fix(ivy): ngcc - compute potential d.ts files from .js files (#31411)
If a package delcares a class internally on an NgModule, ngcc needs to be able to add a public export to this class's type. Previously, if the typing file for the declared is not imported from the typings entry-point file, then ngcc cannot find it. Now we try to guess the .d.ts files from the equivalent .js files. PR Close #31411
This commit is contained in:

committed by
Jason Aden

parent
e6f1b04cd5
commit
83b19bf1a2
@ -154,7 +154,8 @@ export function mainNgcc(
|
||||
// the property as processed even if its underlying format has been built already.
|
||||
if (!compiledFormats.has(formatPath) && (compileAllFormats || isFirstFormat)) {
|
||||
const bundle = makeEntryPointBundle(
|
||||
fileSystem, entryPoint, formatPath, isCore, property, format, processDts, pathMappings);
|
||||
fileSystem, entryPoint, formatPath, isCore, property, format, processDts, pathMappings,
|
||||
true);
|
||||
if (bundle) {
|
||||
logger.info(`Compiling ${entryPoint.name} : ${property} as ${format}`);
|
||||
const transformedFiles = transformer.transform(bundle);
|
||||
|
@ -32,9 +32,11 @@ export interface BundleProgram {
|
||||
*/
|
||||
export function makeBundleProgram(
|
||||
fs: FileSystem, isCore: boolean, path: AbsoluteFsPath, r3FileName: string,
|
||||
options: ts.CompilerOptions, host: ts.CompilerHost): BundleProgram {
|
||||
options: ts.CompilerOptions, host: ts.CompilerHost,
|
||||
additionalFiles: AbsoluteFsPath[] = []): BundleProgram {
|
||||
const r3SymbolsPath = isCore ? findR3SymbolsPath(fs, dirname(path), r3FileName) : null;
|
||||
const rootPaths = r3SymbolsPath ? [path, r3SymbolsPath] : [path];
|
||||
let rootPaths =
|
||||
r3SymbolsPath ? [path, r3SymbolsPath, ...additionalFiles] : [path, ...additionalFiles];
|
||||
|
||||
const originalGetExpandoInitializer = patchTsGetExpandoInitializer();
|
||||
const program = ts.createProgram(rootPaths, options, host);
|
||||
|
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import * as ts from 'typescript';
|
||||
import {AbsoluteFsPath, FileSystem, absoluteFrom, resolve} from '../../../src/ngtsc/file_system';
|
||||
import {AbsoluteFsPath, FileSystem, absoluteFrom} from '../../../src/ngtsc/file_system';
|
||||
import {NgtscCompilerHost} from '../../../src/ngtsc/file_system/src/compiler_host';
|
||||
import {PathMappings} from '../utils';
|
||||
import {BundleProgram, makeBundleProgram} from './bundle_program';
|
||||
@ -30,17 +30,21 @@ export interface EntryPointBundle {
|
||||
|
||||
/**
|
||||
* Get an object that describes a formatted bundle for an entry-point.
|
||||
* @param entryPointPath The path to the entry-point that contains the bundle.
|
||||
* @param fs The current file-system being used.
|
||||
* @param entryPoint The entry-point that contains the bundle.
|
||||
* @param formatPath The path to the source files for this bundle.
|
||||
* @param typingsPath The path to the typings files if we should transform them with this bundle.
|
||||
* @param isCore This entry point is the Angular core package.
|
||||
* @param formatProperty The property in the package.json that holds the formatPath.
|
||||
* @param format The underlying format of the bundle.
|
||||
* @param transformDts Whether to transform the typings along with this bundle.
|
||||
* @param pathMappings An optional set of mappings to use when compiling files.
|
||||
* @param mirrorDtsFromSrc If true then the `dts` program will contain additional files that
|
||||
* were guessed by mapping the `src` files to `dts` files.
|
||||
*/
|
||||
export function makeEntryPointBundle(
|
||||
fs: FileSystem, entryPoint: EntryPoint, formatPath: string, isCore: boolean,
|
||||
formatProperty: EntryPointJsonProperty, format: EntryPointFormat, transformDts: boolean,
|
||||
pathMappings?: PathMappings): EntryPointBundle|null {
|
||||
pathMappings?: PathMappings, mirrorDtsFromSrc: boolean = false): EntryPointBundle|null {
|
||||
// Create the TS program and necessary helpers.
|
||||
const options: ts.CompilerOptions = {
|
||||
allowJs: true,
|
||||
@ -53,13 +57,35 @@ export function makeEntryPointBundle(
|
||||
const rootDirs = [absoluteFrom(entryPoint.path)];
|
||||
|
||||
// Create the bundle programs, as necessary.
|
||||
const src = makeBundleProgram(
|
||||
fs, isCore, resolve(entryPoint.path, formatPath), 'r3_symbols.js', options, srcHost);
|
||||
const dts = transformDts ? makeBundleProgram(
|
||||
fs, isCore, resolve(entryPoint.path, entryPoint.typings),
|
||||
'r3_symbols.d.ts', options, dtsHost) :
|
||||
null;
|
||||
const absFormatPath = fs.resolve(entryPoint.path, formatPath);
|
||||
const typingsPath = fs.resolve(entryPoint.path, entryPoint.typings);
|
||||
const src = makeBundleProgram(fs, isCore, absFormatPath, 'r3_symbols.js', options, srcHost);
|
||||
const additionalDtsFiles = transformDts && mirrorDtsFromSrc ?
|
||||
computePotentialDtsFilesFromJsFiles(fs, src.program, absFormatPath, typingsPath) :
|
||||
[];
|
||||
const dts = transformDts ?
|
||||
makeBundleProgram(
|
||||
fs, isCore, typingsPath, 'r3_symbols.d.ts', options, dtsHost, additionalDtsFiles) :
|
||||
null;
|
||||
const isFlatCore = isCore && src.r3SymbolsFile === null;
|
||||
|
||||
return {entryPoint, format, formatProperty, rootDirs, isCore, isFlatCore, src, dts};
|
||||
}
|
||||
|
||||
function computePotentialDtsFilesFromJsFiles(
|
||||
fs: FileSystem, srcProgram: ts.Program, formatPath: AbsoluteFsPath,
|
||||
typingsPath: AbsoluteFsPath) {
|
||||
const relativePath = fs.relative(fs.dirname(formatPath), fs.dirname(typingsPath));
|
||||
const additionalFiles: AbsoluteFsPath[] = [];
|
||||
for (const sf of srcProgram.getSourceFiles()) {
|
||||
if (!sf.fileName.endsWith('.js')) {
|
||||
continue;
|
||||
}
|
||||
const dtsPath = fs.resolve(
|
||||
fs.dirname(sf.fileName), relativePath, fs.basename(sf.fileName, '.js') + '.d.ts');
|
||||
if (fs.exists(dtsPath)) {
|
||||
additionalFiles.push(dtsPath);
|
||||
}
|
||||
}
|
||||
return additionalFiles;
|
||||
}
|
Reference in New Issue
Block a user