fix(ngcc): correctly get config for sub-entry-points when primary entry-point is ignored (#37040)
Previously, when an entry-point was ignored via an ngcc config, ngcc would scan sub-directories for sub-entry-points, but would not use the correct `packagePath`. For example, if `@angular/common` was ignored, it would look at `@angular/common/http` but incorrectly use `.../@angular/common/http` as the `packagePath` (instead of `.../@angular/common`). As a result, it would not retrieve the correct ngcc config for the actual package. This commit fixes it by ensuring the correct `packagePath` is used, even if the primary entry-point corresponding to that path is ignored. In order to do this, a new return value for `getEntryPointInfo()` is added: `IGNORED_ENTRY_POINT`. This is used to differentiate between directories that correspond to no or an incompatible entry-point and those that correspond to an entry-point that could otherwise be valid but is explicitly ignored. Consumers of `getEntryPointInfo()` can then use this info to discard ignored entry-points, but still use the correct `packagePath` when scanning their sub-directories for secondary entry-points. PR Close #37040
This commit is contained in:

committed by
Misko Hevery

parent
a32579ae5b
commit
bf57776b59
@ -10,7 +10,7 @@ import {EntryPointWithDependencies} from '../dependencies/dependency_host';
|
||||
import {DependencyResolver, SortedEntryPointsInfo} from '../dependencies/dependency_resolver';
|
||||
import {Logger} from '../logging/logger';
|
||||
import {NgccConfiguration} from '../packages/configuration';
|
||||
import {getEntryPointInfo, INCOMPATIBLE_ENTRY_POINT, NO_ENTRY_POINT} from '../packages/entry_point';
|
||||
import {getEntryPointInfo, IGNORED_ENTRY_POINT, INCOMPATIBLE_ENTRY_POINT, isEntryPoint, NO_ENTRY_POINT} from '../packages/entry_point';
|
||||
import {EntryPointManifest} from '../packages/entry_point_manifest';
|
||||
import {PathMappings} from '../path_mappings';
|
||||
import {NGCC_DIRECTORY} from '../writing/new_entry_point_file_writer';
|
||||
@ -79,7 +79,9 @@ export class DirectoryWalkerEntryPointFinder implements EntryPointFinder {
|
||||
|
||||
const entryPoints: EntryPointWithDependencies[] = [];
|
||||
if (primaryEntryPoint !== NO_ENTRY_POINT) {
|
||||
entryPoints.push(this.resolver.getEntryPointWithDependencies(primaryEntryPoint));
|
||||
if (primaryEntryPoint !== IGNORED_ENTRY_POINT) {
|
||||
entryPoints.push(this.resolver.getEntryPointWithDependencies(primaryEntryPoint));
|
||||
}
|
||||
this.collectSecondaryEntryPoints(
|
||||
entryPoints, sourceDirectory, sourceDirectory, this.fs.readdir(sourceDirectory));
|
||||
|
||||
@ -148,14 +150,12 @@ export class DirectoryWalkerEntryPointFinder implements EntryPointFinder {
|
||||
}
|
||||
|
||||
// If the path is a JS file then strip its extension and see if we can match an
|
||||
// entry-point.
|
||||
// entry-point (even if it is an ignored one).
|
||||
const possibleEntryPointPath = isDirectory ? absolutePath : stripJsExtension(absolutePath);
|
||||
let isEntryPoint = false;
|
||||
const subEntryPoint =
|
||||
getEntryPointInfo(this.fs, this.config, this.logger, packagePath, possibleEntryPointPath);
|
||||
if (subEntryPoint !== NO_ENTRY_POINT && subEntryPoint !== INCOMPATIBLE_ENTRY_POINT) {
|
||||
if (isEntryPoint(subEntryPoint)) {
|
||||
entryPoints.push(this.resolver.getEntryPointWithDependencies(subEntryPoint));
|
||||
isEntryPoint = true;
|
||||
}
|
||||
|
||||
if (!isDirectory) {
|
||||
@ -163,9 +163,11 @@ export class DirectoryWalkerEntryPointFinder implements EntryPointFinder {
|
||||
continue;
|
||||
}
|
||||
|
||||
// This directory may contain entry-points of its own.
|
||||
// If not an entry-point itself, this directory may contain entry-points of its own.
|
||||
const canContainEntryPoints =
|
||||
subEntryPoint === NO_ENTRY_POINT || subEntryPoint === INCOMPATIBLE_ENTRY_POINT;
|
||||
const childPaths = this.fs.readdir(absolutePath);
|
||||
if (!isEntryPoint &&
|
||||
if (canContainEntryPoints &&
|
||||
childPaths.some(
|
||||
childPath => childPath.endsWith('.js') &&
|
||||
this.fs.stat(this.fs.resolve(absolutePath, childPath)).isFile())) {
|
||||
|
@ -11,7 +11,7 @@ import {EntryPointWithDependencies} from '../dependencies/dependency_host';
|
||||
import {DependencyResolver, SortedEntryPointsInfo} from '../dependencies/dependency_resolver';
|
||||
import {Logger} from '../logging/logger';
|
||||
import {NgccConfiguration} from '../packages/configuration';
|
||||
import {EntryPoint, getEntryPointInfo, INCOMPATIBLE_ENTRY_POINT, NO_ENTRY_POINT} from '../packages/entry_point';
|
||||
import {EntryPoint, getEntryPointInfo, isEntryPoint} from '../packages/entry_point';
|
||||
import {PathMappings} from '../path_mappings';
|
||||
|
||||
import {EntryPointFinder} from './interface';
|
||||
@ -61,10 +61,8 @@ export abstract class TracingEntryPointFinder implements EntryPointFinder {
|
||||
const packagePath = this.computePackagePath(entryPointPath);
|
||||
const entryPoint =
|
||||
getEntryPointInfo(this.fs, this.config, this.logger, packagePath, entryPointPath);
|
||||
if (entryPoint === NO_ENTRY_POINT || entryPoint === INCOMPATIBLE_ENTRY_POINT) {
|
||||
return null;
|
||||
}
|
||||
return entryPoint;
|
||||
|
||||
return isEntryPoint(entryPoint) ? entryPoint : null;
|
||||
}
|
||||
|
||||
private processNextPath(): void {
|
||||
|
@ -80,12 +80,16 @@ export const SUPPORTED_FORMAT_PROPERTIES: EntryPointJsonProperty[] =
|
||||
|
||||
|
||||
/**
|
||||
* The path does not represent an entry-point:
|
||||
* * there is no package.json at the path and there is no config to force an entry-point
|
||||
* * or the entrypoint is `ignored` by a config.
|
||||
* The path does not represent an entry-point, i.e. there is no package.json at the path and there
|
||||
* is no config to force an entry-point.
|
||||
*/
|
||||
export const NO_ENTRY_POINT = 'no-entry-point';
|
||||
|
||||
/**
|
||||
* The path represents an entry-point that is `ignored` by an ngcc config.
|
||||
*/
|
||||
export const IGNORED_ENTRY_POINT = 'ignored-entry-point';
|
||||
|
||||
/**
|
||||
* The path has a package.json, but it is not a valid entry-point for ngcc processing.
|
||||
*/
|
||||
@ -100,7 +104,8 @@ export const INCOMPATIBLE_ENTRY_POINT = 'incompatible-entry-point';
|
||||
* * INCOMPATIBLE_ENTRY_POINT - the path was a non-processable entry-point that should be searched
|
||||
* for sub-entry-points
|
||||
*/
|
||||
export type GetEntryPointResult = EntryPoint|typeof INCOMPATIBLE_ENTRY_POINT|typeof NO_ENTRY_POINT;
|
||||
export type GetEntryPointResult =
|
||||
EntryPoint|typeof IGNORED_ENTRY_POINT|typeof INCOMPATIBLE_ENTRY_POINT|typeof NO_ENTRY_POINT;
|
||||
|
||||
|
||||
/**
|
||||
@ -109,11 +114,12 @@ export type GetEntryPointResult = EntryPoint|typeof INCOMPATIBLE_ENTRY_POINT|typ
|
||||
* @param packagePath the absolute path to the containing npm package
|
||||
* @param entryPointPath the absolute path to the potential entry-point.
|
||||
* @returns
|
||||
* - An entry-point if it is valid.
|
||||
* - An entry-point if it is valid and not ignored.
|
||||
* - `NO_ENTRY_POINT` when there is no package.json at the path and there is no config to force an
|
||||
* entry-point or the entrypoint is `ignored`.
|
||||
* - `INCOMPATIBLE_ENTRY_POINT` there is a package.json but it is not a valid Angular compiled
|
||||
* entry-point.
|
||||
* entry-point,
|
||||
* - `IGNORED_ENTRY_POINT` when the entry-point is ignored by an ngcc config.
|
||||
* - `INCOMPATIBLE_ENTRY_POINT` when there is a package.json but it is not a valid Angular compiled
|
||||
* entry-point.
|
||||
*/
|
||||
export function getEntryPointInfo(
|
||||
fs: FileSystem, config: NgccConfiguration, logger: Logger, packagePath: AbsoluteFsPath,
|
||||
@ -131,7 +137,7 @@ export function getEntryPointInfo(
|
||||
|
||||
if (hasConfig && entryPointConfig.ignore === true) {
|
||||
// Explicitly ignored
|
||||
return NO_ENTRY_POINT;
|
||||
return IGNORED_ENTRY_POINT;
|
||||
}
|
||||
|
||||
const loadedEntryPointPackageJson = loadEntryPointPackage(fs, logger, packageJsonPath, hasConfig);
|
||||
@ -174,6 +180,11 @@ export function getEntryPointInfo(
|
||||
return entryPointInfo;
|
||||
}
|
||||
|
||||
export function isEntryPoint(result: GetEntryPointResult): result is EntryPoint {
|
||||
return result !== NO_ENTRY_POINT && result !== INCOMPATIBLE_ENTRY_POINT &&
|
||||
result !== IGNORED_ENTRY_POINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a package.json property into an entry-point format.
|
||||
*
|
||||
|
@ -13,7 +13,7 @@ import {Logger} from '../logging/logger';
|
||||
|
||||
import {NGCC_VERSION} from './build_marker';
|
||||
import {NgccConfiguration} from './configuration';
|
||||
import {getEntryPointInfo, INCOMPATIBLE_ENTRY_POINT, NO_ENTRY_POINT} from './entry_point';
|
||||
import {getEntryPointInfo, isEntryPoint} from './entry_point';
|
||||
|
||||
/**
|
||||
* Manages reading and writing a manifest file that contains a list of all the entry-points that
|
||||
@ -75,7 +75,7 @@ export class EntryPointManifest {
|
||||
const result = getEntryPointInfo(
|
||||
this.fs, this.config, this.logger, this.fs.resolve(basePath, packagePath),
|
||||
this.fs.resolve(basePath, entryPointPath));
|
||||
if (result === NO_ENTRY_POINT || result === INCOMPATIBLE_ENTRY_POINT) {
|
||||
if (!isEntryPoint(result)) {
|
||||
throw new Error(`The entry-point manifest at ${
|
||||
manifestPath} contained an invalid pair of package paths: [${packagePath}, ${
|
||||
entryPointPath}]`);
|
||||
|
Reference in New Issue
Block a user