diff --git a/packages/compiler-cli/ngcc/src/execution/analyze_entry_points.ts b/packages/compiler-cli/ngcc/src/execution/analyze_entry_points.ts new file mode 100644 index 0000000000..0a3643e4de --- /dev/null +++ b/packages/compiler-cli/ngcc/src/execution/analyze_entry_points.ts @@ -0,0 +1,172 @@ +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import {DepGraph} from 'dependency-graph'; + +import {FileSystem} from '../../../src/ngtsc/file_system'; +import {InvalidEntryPoint} from '../dependencies/dependency_resolver'; +import {EntryPointFinder} from '../entry_point_finder/interface'; +import {ParallelTaskQueue} from '../execution/tasks/queues/parallel_task_queue'; +import {SerialTaskQueue} from '../execution/tasks/queues/serial_task_queue'; +import {computeTaskDependencies} from '../execution/tasks/utils'; +import {Logger} from '../logging/logger'; +import {hasBeenProcessed} from '../packages/build_marker'; +import {EntryPoint, EntryPointJsonProperty, EntryPointPackageJson, SUPPORTED_FORMAT_PROPERTIES} from '../packages/entry_point'; +import {cleanOutdatedPackages} from '../writing/cleaning/package_cleaner'; + +import {AnalyzeEntryPointsFn} from './api'; +import {PartiallyOrderedTasks, TaskQueue} from './tasks/api'; + +/** + * Create the function for performing the analysis of the entry-points. + */ +export function getAnalyzeEntryPointsFn( + logger: Logger, finder: EntryPointFinder, fileSystem: FileSystem, + supportedPropertiesToConsider: EntryPointJsonProperty[], compileAllFormats: boolean, + propertiesToConsider: string[], inParallel: boolean): AnalyzeEntryPointsFn { + return () => { + logger.debug('Analyzing entry-points...'); + const startTime = Date.now(); + + let entryPointInfo = finder.findEntryPoints(); + const cleaned = cleanOutdatedPackages(fileSystem, entryPointInfo.entryPoints); + if (cleaned) { + // If we had to clean up one or more packages then we must read in the entry-points again. + entryPointInfo = finder.findEntryPoints(); + } + + const {entryPoints, invalidEntryPoints, graph} = entryPointInfo; + logInvalidEntryPoints(logger, invalidEntryPoints); + + const unprocessableEntryPointPaths: string[] = []; + // The tasks are partially ordered by virtue of the entry-points being partially ordered too. + const tasks: PartiallyOrderedTasks = [] as any; + + for (const entryPoint of entryPoints) { + const packageJson = entryPoint.packageJson; + const hasProcessedTypings = hasBeenProcessed(packageJson, 'typings'); + const {propertiesToProcess, equivalentPropertiesMap} = + getPropertiesToProcess(packageJson, supportedPropertiesToConsider, compileAllFormats); + let processDts = !hasProcessedTypings; + + if (propertiesToProcess.length === 0) { + // This entry-point is unprocessable (i.e. there is no format property that is of interest + // and can be processed). This will result in an error, but continue looping over + // entry-points in order to collect all unprocessable ones and display a more informative + // error. + unprocessableEntryPointPaths.push(entryPoint.path); + continue; + } + + for (const formatProperty of propertiesToProcess) { + if (hasBeenProcessed(entryPoint.packageJson, formatProperty)) { + // The format-path which the property maps to is already processed - nothing to do. + logger.debug(`Skipping ${entryPoint.name} : ${formatProperty} (already compiled).`); + continue; + } + + const formatPropertiesToMarkAsProcessed = equivalentPropertiesMap.get(formatProperty)!; + tasks.push({entryPoint, formatProperty, formatPropertiesToMarkAsProcessed, processDts}); + + // Only process typings for the first property (if not already processed). + processDts = false; + } + } + + // Check for entry-points for which we could not process any format at all. + if (unprocessableEntryPointPaths.length > 0) { + throw new Error( + 'Unable to process any formats for the following entry-points (tried ' + + `${propertiesToConsider.join(', ')}): ` + + unprocessableEntryPointPaths.map(path => `\n - ${path}`).join('')); + } + + const duration = Math.round((Date.now() - startTime) / 100) / 10; + logger.debug( + `Analyzed ${entryPoints.length} entry-points in ${duration}s. ` + + `(Total tasks: ${tasks.length})`); + + return getTaskQueue(logger, inParallel, tasks, graph); + }; +} + +function logInvalidEntryPoints(logger: Logger, invalidEntryPoints: InvalidEntryPoint[]): void { + invalidEntryPoints.forEach(invalidEntryPoint => { + logger.debug( + `Invalid entry-point ${invalidEntryPoint.entryPoint.path}.`, + `It is missing required dependencies:\n` + + invalidEntryPoint.missingDependencies.map(dep => ` - ${dep}`).join('\n')); + }); +} + +/** + * This function computes and returns the following: + * - `propertiesToProcess`: An (ordered) list of properties that exist and need to be processed, + * based on the provided `propertiesToConsider`, the properties in `package.json` and their + * corresponding format-paths. NOTE: Only one property per format-path needs to be processed. + * - `equivalentPropertiesMap`: A mapping from each property in `propertiesToProcess` to the list of + * other format properties in `package.json` that need to be marked as processed as soon as the + * former has been processed. + */ +function getPropertiesToProcess( + packageJson: EntryPointPackageJson, propertiesToConsider: EntryPointJsonProperty[], + compileAllFormats: boolean): { + propertiesToProcess: EntryPointJsonProperty[]; + equivalentPropertiesMap: Map; +} { + const formatPathsToConsider = new Set(); + + const propertiesToProcess: EntryPointJsonProperty[] = []; + for (const prop of propertiesToConsider) { + const formatPath = packageJson[prop]; + + // Ignore properties that are not defined in `package.json`. + if (typeof formatPath !== 'string') continue; + + // Ignore properties that map to the same format-path as a preceding property. + if (formatPathsToConsider.has(formatPath)) continue; + + // Process this property, because it is the first one to map to this format-path. + formatPathsToConsider.add(formatPath); + propertiesToProcess.push(prop); + + // If we only need one format processed, there is no need to process any more properties. + if (!compileAllFormats) break; + } + + const formatPathToProperties: {[formatPath: string]: EntryPointJsonProperty[]} = {}; + for (const prop of SUPPORTED_FORMAT_PROPERTIES) { + const formatPath = packageJson[prop]; + + // Ignore properties that are not defined in `package.json`. + if (typeof formatPath !== 'string') continue; + + // Ignore properties that do not map to a format-path that will be considered. + if (!formatPathsToConsider.has(formatPath)) continue; + + // Add this property to the map. + const list = formatPathToProperties[formatPath] || (formatPathToProperties[formatPath] = []); + list.push(prop); + } + + const equivalentPropertiesMap = new Map(); + for (const prop of propertiesToConsider) { + const formatPath = packageJson[prop]!; + const equivalentProperties = formatPathToProperties[formatPath]; + equivalentPropertiesMap.set(prop, equivalentProperties); + } + + return {propertiesToProcess, equivalentPropertiesMap}; +} + +function getTaskQueue( + logger: Logger, inParallel: boolean, tasks: PartiallyOrderedTasks, + graph: DepGraph): TaskQueue { + const dependencies = computeTaskDependencies(tasks, graph); + return inParallel ? new ParallelTaskQueue(logger, tasks, dependencies) : + new SerialTaskQueue(logger, tasks, dependencies); +} diff --git a/packages/compiler-cli/ngcc/src/execution/create_compile_function.ts b/packages/compiler-cli/ngcc/src/execution/create_compile_function.ts new file mode 100644 index 0000000000..38bf31fdfa --- /dev/null +++ b/packages/compiler-cli/ngcc/src/execution/create_compile_function.ts @@ -0,0 +1,92 @@ + +/** + * @license + * Copyright Google Inc. All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import * as ts from 'typescript'; + +import {replaceTsWithNgInErrors} from '../../../src/ngtsc/diagnostics'; +import {FileSystem} from '../../../src/ngtsc/file_system'; +import {ParsedConfiguration} from '../../../src/perform_compile'; +import {Logger} from '../logging/logger'; +import {getEntryPointFormat} from '../packages/entry_point'; +import {makeEntryPointBundle} from '../packages/entry_point_bundle'; +import {PathMappings} from '../utils'; +import {FileWriter} from '../writing/file_writer'; +import {InPlaceFileWriter} from '../writing/in_place_file_writer'; +import {NewEntryPointFileWriter} from '../writing/new_entry_point_file_writer'; +import {PackageJsonUpdater} from '../writing/package_json_updater'; + +import {CreateCompileFn} from './api'; +import {Task, TaskProcessingOutcome} from './tasks/api'; + +/** + * The function for creating the `compile()` function. + */ +export function getCreateCompileFn( + fileSystem: FileSystem, logger: Logger, pkgJsonUpdater: PackageJsonUpdater, + createNewEntryPointFormats: boolean, errorOnFailedEntryPoint: boolean, + enableI18nLegacyMessageIdFormat: boolean, tsConfig: ParsedConfiguration|null, + pathMappings: PathMappings|undefined): CreateCompileFn { + return onTaskCompleted => { + const fileWriter = getFileWriter( + fileSystem, logger, pkgJsonUpdater, createNewEntryPointFormats, errorOnFailedEntryPoint); + const {Transformer} = require('../packages/transformer'); + const transformer = new Transformer(fileSystem, logger, tsConfig); + + return (task: Task) => { + const {entryPoint, formatProperty, formatPropertiesToMarkAsProcessed, processDts} = task; + + const isCore = entryPoint.name === '@angular/core'; // Are we compiling the Angular core? + const packageJson = entryPoint.packageJson; + const formatPath = packageJson[formatProperty]; + const format = getEntryPointFormat(fileSystem, entryPoint, formatProperty); + + // All properties listed in `propertiesToProcess` are guaranteed to point to a format-path + // (i.e. they are defined in `entryPoint.packageJson`). Furthermore, they are also guaranteed + // to be among `SUPPORTED_FORMAT_PROPERTIES`. + // Based on the above, `formatPath` should always be defined and `getEntryPointFormat()` + // should always return a format here (and not `undefined`). + if (!formatPath || !format) { + // This should never happen. + throw new Error( + `Invariant violated: No format-path or format for ${entryPoint.path} : ` + + `${formatProperty} (formatPath: ${formatPath} | format: ${format})`); + } + + const bundle = makeEntryPointBundle( + fileSystem, entryPoint, formatPath, isCore, format, processDts, pathMappings, true, + enableI18nLegacyMessageIdFormat); + + logger.info(`Compiling ${entryPoint.name} : ${formatProperty} as ${format}`); + + const result = transformer.transform(bundle); + if (result.success) { + if (result.diagnostics.length > 0) { + logger.warn(replaceTsWithNgInErrors( + ts.formatDiagnosticsWithColorAndContext(result.diagnostics, bundle.src.host))); + } + fileWriter.writeBundle(bundle, result.transformedFiles, formatPropertiesToMarkAsProcessed); + + logger.debug(` Successfully compiled ${entryPoint.name} : ${formatProperty}`); + + onTaskCompleted(task, TaskProcessingOutcome.Processed, null); + } else { + const errors = replaceTsWithNgInErrors( + ts.formatDiagnosticsWithColorAndContext(result.diagnostics, bundle.src.host)); + onTaskCompleted(task, TaskProcessingOutcome.Failed, `compilation errors:\n${errors}`); + } + }; + }; +} + +function getFileWriter( + fs: FileSystem, logger: Logger, pkgJsonUpdater: PackageJsonUpdater, + createNewEntryPointFormats: boolean, errorOnFailedEntryPoint: boolean): FileWriter { + return createNewEntryPointFormats ? + new NewEntryPointFileWriter(fs, logger, errorOnFailedEntryPoint, pkgJsonUpdater) : + new InPlaceFileWriter(fs, logger, errorOnFailedEntryPoint); +} diff --git a/packages/compiler-cli/ngcc/src/main.ts b/packages/compiler-cli/ngcc/src/main.ts index 805645f66c..3647eced9b 100644 --- a/packages/compiler-cli/ngcc/src/main.ts +++ b/packages/compiler-cli/ngcc/src/main.ts @@ -8,17 +8,14 @@ /// -import {DepGraph} from 'dependency-graph'; import * as os from 'os'; -import * as ts from 'typescript'; import {readConfiguration} from '../..'; -import {replaceTsWithNgInErrors} from '../../src/ngtsc/diagnostics'; import {absoluteFrom, AbsoluteFsPath, dirname, FileSystem, getFileSystem, resolve} from '../../src/ngtsc/file_system'; import {AsyncNgccOptions, NgccOptions, SyncNgccOptions} from './command_line_options'; import {CommonJsDependencyHost} from './dependencies/commonjs_dependency_host'; -import {DependencyResolver, InvalidEntryPoint} from './dependencies/dependency_resolver'; +import {DependencyResolver} from './dependencies/dependency_resolver'; import {DtsDependencyHost} from './dependencies/dts_dependency_host'; import {EsmDependencyHost} from './dependencies/esm_dependency_host'; import {ModuleResolver} from './dependencies/module_resolver'; @@ -26,30 +23,23 @@ import {UmdDependencyHost} from './dependencies/umd_dependency_host'; import {DirectoryWalkerEntryPointFinder} from './entry_point_finder/directory_walker_entry_point_finder'; import {EntryPointFinder} from './entry_point_finder/interface'; import {TargetedEntryPointFinder} from './entry_point_finder/targeted_entry_point_finder'; -import {AnalyzeEntryPointsFn, CreateCompileFn, Executor} from './execution/api'; +import {getAnalyzeEntryPointsFn} from './execution/analyze_entry_points'; +import {Executor} from './execution/api'; import {ClusterExecutor} from './execution/cluster/executor'; import {ClusterPackageJsonUpdater} from './execution/cluster/package_json_updater'; +import {getCreateCompileFn} from './execution/create_compile_function'; import {SingleProcessExecutorAsync, SingleProcessExecutorSync} from './execution/single_process_executor'; -import {CreateTaskCompletedCallback, PartiallyOrderedTasks, Task, TaskProcessingOutcome, TaskQueue} from './execution/tasks/api'; +import {CreateTaskCompletedCallback, Task, TaskProcessingOutcome} from './execution/tasks/api'; import {composeTaskCompletedCallbacks, createLogErrorHandler, createMarkAsProcessedHandler, createThrowErrorHandler} from './execution/tasks/completion'; -import {ParallelTaskQueue} from './execution/tasks/queues/parallel_task_queue'; -import {SerialTaskQueue} from './execution/tasks/queues/serial_task_queue'; -import {computeTaskDependencies} from './execution/tasks/utils'; import {AsyncLocker} from './locking/async_locker'; import {LockFileWithChildProcess} from './locking/lock_file_with_child_process'; import {SyncLocker} from './locking/sync_locker'; import {ConsoleLogger} from './logging/console_logger'; import {Logger, LogLevel} from './logging/logger'; -import {hasBeenProcessed} from './packages/build_marker'; import {NgccConfiguration} from './packages/configuration'; -import {EntryPoint, EntryPointJsonProperty, EntryPointPackageJson, getEntryPointFormat, SUPPORTED_FORMAT_PROPERTIES} from './packages/entry_point'; -import {makeEntryPointBundle} from './packages/entry_point_bundle'; +import {EntryPointJsonProperty, SUPPORTED_FORMAT_PROPERTIES} from './packages/entry_point'; import {EntryPointManifest, InvalidatingEntryPointManifest} from './packages/entry_point_manifest'; import {PathMappings} from './utils'; -import {cleanOutdatedPackages} from './writing/cleaning/package_cleaner'; -import {FileWriter} from './writing/file_writer'; -import {InPlaceFileWriter} from './writing/in_place_file_writer'; -import {NewEntryPointFileWriter} from './writing/new_entry_point_file_writer'; import {DirectPackageJsonUpdater, PackageJsonUpdater} from './writing/package_json_updater'; /** @@ -126,123 +116,14 @@ export function mainNgcc({ // enforced manually. const pkgJsonUpdater = getPackageJsonUpdater(inParallel, fileSystem); - // The function for performing the analysis. - const analyzeEntryPoints: AnalyzeEntryPointsFn = () => { - logger.debug('Analyzing entry-points...'); - const startTime = Date.now(); - - let entryPointInfo = finder.findEntryPoints(); - const cleaned = cleanOutdatedPackages(fileSystem, entryPointInfo.entryPoints); - if (cleaned) { - // If we had to clean up one or more packages then we must read in the entry-points again. - entryPointInfo = finder.findEntryPoints(); - } - - const {entryPoints, invalidEntryPoints, graph} = entryPointInfo; - logInvalidEntryPoints(logger, invalidEntryPoints); - - const unprocessableEntryPointPaths: string[] = []; - // The tasks are partially ordered by virtue of the entry-points being partially ordered too. - const tasks: PartiallyOrderedTasks = [] as any; - - for (const entryPoint of entryPoints) { - const packageJson = entryPoint.packageJson; - const hasProcessedTypings = hasBeenProcessed(packageJson, 'typings'); - const {propertiesToProcess, equivalentPropertiesMap} = - getPropertiesToProcess(packageJson, supportedPropertiesToConsider, compileAllFormats); - let processDts = !hasProcessedTypings; - - if (propertiesToProcess.length === 0) { - // This entry-point is unprocessable (i.e. there is no format property that is of interest - // and can be processed). This will result in an error, but continue looping over - // entry-points in order to collect all unprocessable ones and display a more informative - // error. - unprocessableEntryPointPaths.push(entryPoint.path); - continue; - } - - for (const formatProperty of propertiesToProcess) { - if (hasBeenProcessed(entryPoint.packageJson, formatProperty)) { - // The format-path which the property maps to is already processed - nothing to do. - logger.debug(`Skipping ${entryPoint.name} : ${formatProperty} (already compiled).`); - continue; - } - - const formatPropertiesToMarkAsProcessed = equivalentPropertiesMap.get(formatProperty)!; - tasks.push({entryPoint, formatProperty, formatPropertiesToMarkAsProcessed, processDts}); - - // Only process typings for the first property (if not already processed). - processDts = false; - } - } - - // Check for entry-points for which we could not process any format at all. - if (unprocessableEntryPointPaths.length > 0) { - throw new Error( - 'Unable to process any formats for the following entry-points (tried ' + - `${propertiesToConsider.join(', ')}): ` + - unprocessableEntryPointPaths.map(path => `\n - ${path}`).join('')); - } - - const duration = Math.round((Date.now() - startTime) / 100) / 10; - logger.debug( - `Analyzed ${entryPoints.length} entry-points in ${duration}s. ` + - `(Total tasks: ${tasks.length})`); - - return getTaskQueue(logger, inParallel, tasks, graph); - }; + const analyzeEntryPoints = getAnalyzeEntryPointsFn( + logger, finder, fileSystem, supportedPropertiesToConsider, compileAllFormats, + propertiesToConsider, inParallel); // The function for creating the `compile()` function. - const createCompileFn: CreateCompileFn = onTaskCompleted => { - const fileWriter = getFileWriter( - fileSystem, logger, pkgJsonUpdater, createNewEntryPointFormats, errorOnFailedEntryPoint); - const {Transformer} = require('./packages/transformer'); - const transformer = new Transformer(fileSystem, logger, tsConfig); - - return (task: Task) => { - const {entryPoint, formatProperty, formatPropertiesToMarkAsProcessed, processDts} = task; - - const isCore = entryPoint.name === '@angular/core'; // Are we compiling the Angular core? - const packageJson = entryPoint.packageJson; - const formatPath = packageJson[formatProperty]; - const format = getEntryPointFormat(fileSystem, entryPoint, formatProperty); - - // All properties listed in `propertiesToProcess` are guaranteed to point to a format-path - // (i.e. they are defined in `entryPoint.packageJson`). Furthermore, they are also guaranteed - // to be among `SUPPORTED_FORMAT_PROPERTIES`. - // Based on the above, `formatPath` should always be defined and `getEntryPointFormat()` - // should always return a format here (and not `undefined`). - if (!formatPath || !format) { - // This should never happen. - throw new Error( - `Invariant violated: No format-path or format for ${entryPoint.path} : ` + - `${formatProperty} (formatPath: ${formatPath} | format: ${format})`); - } - - const bundle = makeEntryPointBundle( - fileSystem, entryPoint, formatPath, isCore, format, processDts, pathMappings, true, - enableI18nLegacyMessageIdFormat); - - logger.info(`Compiling ${entryPoint.name} : ${formatProperty} as ${format}`); - - const result = transformer.transform(bundle); - if (result.success) { - if (result.diagnostics.length > 0) { - logger.warn(replaceTsWithNgInErrors( - ts.formatDiagnosticsWithColorAndContext(result.diagnostics, bundle.src.host))); - } - fileWriter.writeBundle(bundle, result.transformedFiles, formatPropertiesToMarkAsProcessed); - - logger.debug(` Successfully compiled ${entryPoint.name} : ${formatProperty}`); - - onTaskCompleted(task, TaskProcessingOutcome.Processed, null); - } else { - const errors = replaceTsWithNgInErrors( - ts.formatDiagnosticsWithColorAndContext(result.diagnostics, bundle.src.host)); - onTaskCompleted(task, TaskProcessingOutcome.Failed, `compilation errors:\n${errors}`); - } - }; - }; + const createCompileFn = getCreateCompileFn( + fileSystem, logger, pkgJsonUpdater, createNewEntryPointFormats, errorOnFailedEntryPoint, + enableI18nLegacyMessageIdFormat, tsConfig, pathMappings); // The executor for actually planning and getting the work done. const createTaskCompletedCallback = @@ -280,22 +161,6 @@ function getPackageJsonUpdater(inParallel: boolean, fs: FileSystem): PackageJson return inParallel ? new ClusterPackageJsonUpdater(directPkgJsonUpdater) : directPkgJsonUpdater; } -function getFileWriter( - fs: FileSystem, logger: Logger, pkgJsonUpdater: PackageJsonUpdater, - createNewEntryPointFormats: boolean, errorOnFailedEntryPoint: boolean): FileWriter { - return createNewEntryPointFormats ? - new NewEntryPointFileWriter(fs, logger, errorOnFailedEntryPoint, pkgJsonUpdater) : - new InPlaceFileWriter(fs, logger, errorOnFailedEntryPoint); -} - -function getTaskQueue( - logger: Logger, inParallel: boolean, tasks: PartiallyOrderedTasks, - graph: DepGraph): TaskQueue { - const dependencies = computeTaskDependencies(tasks, graph); - return inParallel ? new ParallelTaskQueue(logger, tasks, dependencies) : - new SerialTaskQueue(logger, tasks, dependencies); -} - function getCreateTaskCompletedCallback( pkgJsonUpdater: PackageJsonUpdater, errorOnFailedEntryPoint: boolean, logger: Logger, fileSystem: FileSystem): CreateTaskCompletedCallback { @@ -361,72 +226,3 @@ function getEntryPointFinder( fs, config, logger, resolver, entryPointManifest, basePath, pathMappings); } } - -function logInvalidEntryPoints(logger: Logger, invalidEntryPoints: InvalidEntryPoint[]): void { - invalidEntryPoints.forEach(invalidEntryPoint => { - logger.debug( - `Invalid entry-point ${invalidEntryPoint.entryPoint.path}.`, - `It is missing required dependencies:\n` + - invalidEntryPoint.missingDependencies.map(dep => ` - ${dep}`).join('\n')); - }); -} - -/** - * This function computes and returns the following: - * - `propertiesToProcess`: An (ordered) list of properties that exist and need to be processed, - * based on the provided `propertiesToConsider`, the properties in `package.json` and their - * corresponding format-paths. NOTE: Only one property per format-path needs to be processed. - * - `equivalentPropertiesMap`: A mapping from each property in `propertiesToProcess` to the list of - * other format properties in `package.json` that need to be marked as processed as soon as the - * former has been processed. - */ -function getPropertiesToProcess( - packageJson: EntryPointPackageJson, propertiesToConsider: EntryPointJsonProperty[], - compileAllFormats: boolean): { - propertiesToProcess: EntryPointJsonProperty[]; - equivalentPropertiesMap: Map; -} { - const formatPathsToConsider = new Set(); - - const propertiesToProcess: EntryPointJsonProperty[] = []; - for (const prop of propertiesToConsider) { - const formatPath = packageJson[prop]; - - // Ignore properties that are not defined in `package.json`. - if (typeof formatPath !== 'string') continue; - - // Ignore properties that map to the same format-path as a preceding property. - if (formatPathsToConsider.has(formatPath)) continue; - - // Process this property, because it is the first one to map to this format-path. - formatPathsToConsider.add(formatPath); - propertiesToProcess.push(prop); - - // If we only need one format processed, there is no need to process any more properties. - if (!compileAllFormats) break; - } - - const formatPathToProperties: {[formatPath: string]: EntryPointJsonProperty[]} = {}; - for (const prop of SUPPORTED_FORMAT_PROPERTIES) { - const formatPath = packageJson[prop]; - - // Ignore properties that are not defined in `package.json`. - if (typeof formatPath !== 'string') continue; - - // Ignore properties that do not map to a format-path that will be considered. - if (!formatPathsToConsider.has(formatPath)) continue; - - // Add this property to the map. - const list = formatPathToProperties[formatPath] || (formatPathToProperties[formatPath] = []); - list.push(prop); - } - - const equivalentPropertiesMap = new Map(); - for (const prop of propertiesToConsider) { - const formatPath = packageJson[prop]!; - const equivalentProperties = formatPathToProperties[formatPath]; - equivalentPropertiesMap.set(prop, equivalentProperties); - } - - return {propertiesToProcess, equivalentPropertiesMap}; -}