From 3077c9a1f89c5bd75fb96c16ea08440bb2160661 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Tue, 6 Aug 2019 00:53:38 +0300 Subject: [PATCH] refactor(ivy): ngcc - make `EntryPointJsonProperty`-related types and checks a little more strict (#32052) PR Close #32052 --- .../src/dependencies/dependency_resolver.ts | 18 +++++----- packages/compiler-cli/ngcc/src/main.ts | 33 ++++++++++++++++--- .../ngcc/src/packages/build_marker.ts | 4 +-- .../ngcc/src/packages/entry_point.ts | 5 +-- .../ngcc/test/integration/ngcc_spec.ts | 11 +++++++ 5 files changed, 54 insertions(+), 17 deletions(-) diff --git a/packages/compiler-cli/ngcc/src/dependencies/dependency_resolver.ts b/packages/compiler-cli/ngcc/src/dependencies/dependency_resolver.ts index e2c404c9c2..8267201044 100644 --- a/packages/compiler-cli/ngcc/src/dependencies/dependency_resolver.ts +++ b/packages/compiler-cli/ngcc/src/dependencies/dependency_resolver.ts @@ -9,7 +9,7 @@ import {DepGraph} from 'dependency-graph'; import {AbsoluteFsPath, FileSystem, resolve} from '../../../src/ngtsc/file_system'; import {Logger} from '../logging/logger'; -import {EntryPoint, EntryPointFormat, EntryPointJsonProperty, getEntryPointFormat} from '../packages/entry_point'; +import {EntryPoint, EntryPointFormat, EntryPointJsonProperty, SUPPORTED_FORMAT_PROPERTIES, getEntryPointFormat} from '../packages/entry_point'; import {DependencyHost, DependencyInfo} from './dependency_host'; const builtinNodeJsModules = new Set(require('module').builtinModules); @@ -177,16 +177,16 @@ export class DependencyResolver { private getEntryPointFormatInfo(entryPoint: EntryPoint): {format: EntryPointFormat, path: AbsoluteFsPath} { - const properties = Object.keys(entryPoint.packageJson); - for (let i = 0; i < properties.length; i++) { - const property = properties[i] as EntryPointJsonProperty; - const format = getEntryPointFormat(this.fs, entryPoint, property); + for (const property of SUPPORTED_FORMAT_PROPERTIES) { + const formatPath = entryPoint.packageJson[property]; + if (formatPath === undefined) continue; - if (format === 'esm2015' || format === 'esm5' || format === 'umd' || format === 'commonjs') { - const formatPath = entryPoint.packageJson[property] !; - return {format, path: resolve(entryPoint.path, formatPath)}; - } + const format = getEntryPointFormat(this.fs, entryPoint, property); + if (format === undefined) continue; + + return {format, path: resolve(entryPoint.path, formatPath)}; } + throw new Error( `There is no appropriate source code format in '${entryPoint.path}' entry-point.`); } diff --git a/packages/compiler-cli/ngcc/src/main.ts b/packages/compiler-cli/ngcc/src/main.ts index 2b78f893b0..5a5c97acea 100644 --- a/packages/compiler-cli/ngcc/src/main.ts +++ b/packages/compiler-cli/ngcc/src/main.ts @@ -82,6 +82,8 @@ export function mainNgcc( {basePath, targetEntryPointPath, propertiesToConsider = SUPPORTED_FORMAT_PROPERTIES, compileAllFormats = true, createNewEntryPointFormats = false, logger = new ConsoleLogger(LogLevel.info), pathMappings}: NgccOptions): void { + const supportedPropertiesToConsider = ensureSupportedProperties(propertiesToConsider); + const fileSystem = getFileSystem(); const transformer = new Transformer(fileSystem, logger); const moduleResolver = new ModuleResolver(fileSystem, pathMappings); @@ -99,7 +101,7 @@ export function mainNgcc( const fileWriter = getFileWriter(fileSystem, createNewEntryPointFormats); const entryPoints = getEntryPoints( fileSystem, config, logger, resolver, absBasePath, targetEntryPointPath, pathMappings, - propertiesToConsider, compileAllFormats); + supportedPropertiesToConsider, compileAllFormats); for (const entryPoint of entryPoints) { // Are we compiling the Angular core? const isCore = entryPoint.name === '@angular/core'; @@ -111,7 +113,7 @@ export function mainNgcc( let processDts = !hasBeenProcessed(entryPointPackageJson, 'typings'); - for (const property of propertiesToConsider as EntryPointJsonProperty[]) { + for (const property of supportedPropertiesToConsider) { // If we only need one format processed and we already have one, exit the loop. if (!compileAllFormats && (compiledFormats.size > 0)) break; @@ -139,7 +141,8 @@ export function mainNgcc( fileWriter.writeBundle(entryPoint, bundle, transformedFiles); compiledFormats.add(formatPath); - const propsToMarkAsProcessed = pathToPropsMap.get(formatPath) !; + const propsToMarkAsProcessed: (EntryPointJsonProperty | 'typings')[] = + pathToPropsMap.get(formatPath) !; if (processDts) { propsToMarkAsProcessed.push('typings'); processDts = false; @@ -152,11 +155,33 @@ export function mainNgcc( if (compiledFormats.size === 0) { throw new Error( - `Failed to compile any formats for entry-point at (${entryPoint.path}). Tried ${propertiesToConsider}.`); + `Failed to compile any formats for entry-point at (${entryPoint.path}). Tried ${supportedPropertiesToConsider}.`); } } } +function ensureSupportedProperties(properties: string[]): EntryPointJsonProperty[] { + // Short-circuit the case where `properties` has fallen back to the default value: + // `SUPPORTED_FORMAT_PROPERTIES` + if (properties === SUPPORTED_FORMAT_PROPERTIES) return SUPPORTED_FORMAT_PROPERTIES; + + const supportedProperties: EntryPointJsonProperty[] = []; + + for (const prop of properties as EntryPointJsonProperty[]) { + if (SUPPORTED_FORMAT_PROPERTIES.indexOf(prop) !== -1) { + supportedProperties.push(prop); + } + } + + if (supportedProperties.length === 0) { + throw new Error( + `No supported format property to consider among [${properties.join(', ')}]. ` + + `Supported properties: ${SUPPORTED_FORMAT_PROPERTIES.join(', ')}`); + } + + return supportedProperties; +} + function getFileWriter(fs: FileSystem, createNewEntryPointFormats: boolean): FileWriter { return createNewEntryPointFormats ? new NewEntryPointFileWriter(fs) : new InPlaceFileWriter(fs); } diff --git a/packages/compiler-cli/ngcc/src/packages/build_marker.ts b/packages/compiler-cli/ngcc/src/packages/build_marker.ts index 628ace6fd0..4cc43207e3 100644 --- a/packages/compiler-cli/ngcc/src/packages/build_marker.ts +++ b/packages/compiler-cli/ngcc/src/packages/build_marker.ts @@ -23,7 +23,7 @@ export const NGCC_VERSION = '0.0.0-PLACEHOLDER'; * @throws Error if the entry-point has already been processed with a different ngcc version. */ export function hasBeenProcessed( - packageJson: EntryPointPackageJson, format: EntryPointJsonProperty): boolean { + packageJson: EntryPointPackageJson, format: EntryPointJsonProperty | 'typings'): boolean { if (!packageJson.__processed_by_ivy_ngcc__) { return false; } @@ -49,7 +49,7 @@ export function hasBeenProcessed( */ export function markAsProcessed( fs: FileSystem, packageJson: EntryPointPackageJson, packageJsonPath: AbsoluteFsPath, - properties: EntryPointJsonProperty[]) { + properties: (EntryPointJsonProperty | 'typings')[]) { const processed = packageJson.__processed_by_ivy_ngcc__ || (packageJson.__processed_by_ivy_ngcc__ = {}); diff --git a/packages/compiler-cli/ngcc/src/packages/entry_point.ts b/packages/compiler-cli/ngcc/src/packages/entry_point.ts index 10b6785fc0..a173a59472 100644 --- a/packages/compiler-cli/ngcc/src/packages/entry_point.ts +++ b/packages/compiler-cli/ngcc/src/packages/entry_point.ts @@ -58,7 +58,7 @@ export interface EntryPointPackageJson extends PackageJsonFormatProperties { __processed_by_ivy_ngcc__?: {[key: string]: string}; } -export type EntryPointJsonProperty = keyof(PackageJsonFormatProperties); +export type EntryPointJsonProperty = Exclude; // We need to keep the elements of this const and the `EntryPointJsonProperty` type in sync. export const SUPPORTED_FORMAT_PROPERTIES: EntryPointJsonProperty[] = ['fesm2015', 'fesm5', 'es2015', 'esm2015', 'esm5', 'main', 'module']; @@ -122,7 +122,8 @@ export function getEntryPointInfo( * @returns An entry-point format or `undefined` if none match the given property. */ export function getEntryPointFormat( - fs: FileSystem, entryPoint: EntryPoint, property: string): EntryPointFormat|undefined { + fs: FileSystem, entryPoint: EntryPoint, property: EntryPointJsonProperty): EntryPointFormat| + undefined { switch (property) { case 'fesm2015': return 'esm2015'; diff --git a/packages/compiler-cli/ngcc/test/integration/ngcc_spec.ts b/packages/compiler-cli/ngcc/test/integration/ngcc_spec.ts index 18827a89fd..d70c17872e 100644 --- a/packages/compiler-cli/ngcc/test/integration/ngcc_spec.ts +++ b/packages/compiler-cli/ngcc/test/integration/ngcc_spec.ts @@ -200,6 +200,17 @@ runInEachFileSystem(() => { describe('with propertiesToConsider', () => { + it('should complain if none of the properties in the `propertiesToConsider` list is supported', + () => { + const propertiesToConsider = ['es1337', 'fesm42']; + const errorMessage = + 'No supported format property to consider among [es1337, fesm42]. Supported ' + + 'properties: fesm2015, fesm5, es2015, esm2015, esm5, main, module'; + + expect(() => mainNgcc({basePath: '/node_modules', propertiesToConsider})) + .toThrowError(errorMessage); + }); + it('should only compile the entry-point formats given in the `propertiesToConsider` list', () => { mainNgcc({