@@ -102,58 +102,67 @@ export function mainNgcc(
102102 const entryPoints = getEntryPoints (
103103 fileSystem , config , logger , resolver , absBasePath , targetEntryPointPath , pathMappings ,
104104 supportedPropertiesToConsider , compileAllFormats ) ;
105+
105106 for ( const entryPoint of entryPoints ) {
106107 // Are we compiling the Angular core?
107108 const isCore = entryPoint . name === '@angular/core' ;
108109
109- const compiledFormats = new Set < string > ( ) ;
110110 const entryPointPackageJson = entryPoint . packageJson ;
111111 const entryPointPackageJsonPath = fileSystem . resolve ( entryPoint . path , 'package.json' ) ;
112- const pathToPropsMap = getFormatPathToPropertiesMap ( entryPointPackageJson ) ;
112+ const { propertiesToProcess, propertyToPropertiesToMarkAsProcessed} =
113+ getPropertiesToProcessAndMarkAsProcessed (
114+ entryPointPackageJson , supportedPropertiesToConsider ) ;
113115
116+ let hasAnyProcessedFormat = false ;
114117 let processDts = ! hasBeenProcessed ( entryPointPackageJson , 'typings' ) ;
115118
116- for ( const property of supportedPropertiesToConsider ) {
119+ for ( const property of propertiesToProcess ) {
117120 // If we only need one format processed and we already have one, exit the loop.
118- if ( ! compileAllFormats && ( compiledFormats . size > 0 ) ) break ;
121+ if ( ! compileAllFormats && hasAnyProcessedFormat ) break ;
119122
120123 const formatPath = entryPointPackageJson [ property ] ;
121124 const format = getEntryPointFormat ( fileSystem , entryPoint , property ) ;
122125
123- // No format then this property is not supposed to be compiled.
124- if ( ! formatPath || ! format ) continue ;
126+ // All properties listed in `propertiesToProcess` are guaranteed to point to a format-path
127+ // (i.e. they exist in `entryPointPackageJson`). Furthermore, they are also guaranteed to be
128+ // among `SUPPORTED_FORMAT_PROPERTIES`.
129+ // Based on the above, `formatPath` should always be defined and `getEntryPointFormat()`
130+ // should always return a format here (and not `undefined`).
131+ if ( ! formatPath || ! format ) {
132+ // This should never happen.
133+ throw new Error (
134+ `Invariant violated: No format-path or format for ${ entryPoint . path } : ${ property } ` +
135+ `(formatPath: ${ formatPath } | format: ${ format } )` ) ;
136+ }
125137
126138 // The `formatPath` which the property maps to is already processed - nothing to do.
127139 if ( hasBeenProcessed ( entryPointPackageJson , property ) ) {
128- compiledFormats . add ( formatPath ) ;
140+ hasAnyProcessedFormat = true ;
129141 logger . debug ( `Skipping ${ entryPoint . name } : ${ property } (already compiled).` ) ;
130142 continue ;
131143 }
132144
145+ const bundle = makeEntryPointBundle (
146+ fileSystem , entryPoint , formatPath , isCore , property , format , processDts , pathMappings ,
147+ true ) ;
133148
134- if ( ! compiledFormats . has ( formatPath ) ) {
135- const bundle = makeEntryPointBundle (
136- fileSystem , entryPoint , formatPath , isCore , property , format , processDts , pathMappings ,
137- true ) ;
138-
139- logger . info ( `Compiling ${ entryPoint . name } : ${ property } as ${ format } ` ) ;
140- const transformedFiles = transformer . transform ( bundle ) ;
141- fileWriter . writeBundle ( entryPoint , bundle , transformedFiles ) ;
142- compiledFormats . add ( formatPath ) ;
143-
144- const propsToMarkAsProcessed : ( EntryPointJsonProperty | 'typings' ) [ ] =
145- pathToPropsMap . get ( formatPath ) ! ;
146- if ( processDts ) {
147- propsToMarkAsProcessed . push ( 'typings' ) ;
148- processDts = false ;
149- }
149+ logger . info ( `Compiling ${ entryPoint . name } : ${ property } as ${ format } ` ) ;
150+ const transformedFiles = transformer . transform ( bundle ) ;
151+ fileWriter . writeBundle ( entryPoint , bundle , transformedFiles ) ;
152+ hasAnyProcessedFormat = true ;
150153
151- markAsProcessed (
152- fileSystem , entryPointPackageJson , entryPointPackageJsonPath , propsToMarkAsProcessed ) ;
154+ const propsToMarkAsProcessed : ( EntryPointJsonProperty | 'typings' ) [ ] =
155+ propertyToPropertiesToMarkAsProcessed . get ( property ) ! ;
156+ if ( processDts ) {
157+ propsToMarkAsProcessed . push ( 'typings' ) ;
158+ processDts = false ;
153159 }
160+
161+ markAsProcessed (
162+ fileSystem , entryPointPackageJson , entryPointPackageJsonPath , propsToMarkAsProcessed ) ;
154163 }
155164
156- if ( compiledFormats . size === 0 ) {
165+ if ( ! hasAnyProcessedFormat ) {
157166 throw new Error (
158167 `Failed to compile any formats for entry-point at (${ entryPoint . path } ). Tried ${ supportedPropertiesToConsider } .` ) ;
159168 }
@@ -288,19 +297,59 @@ function logInvalidEntryPoints(logger: Logger, invalidEntryPoints: InvalidEntryP
288297 } ) ;
289298}
290299
291- function getFormatPathToPropertiesMap ( packageJson : EntryPointPackageJson ) :
292- Map < string , EntryPointJsonProperty [ ] > {
293- const map = new Map < string , EntryPointJsonProperty [ ] > ( ) ;
300+ /**
301+ * This function computes and returns the following:
302+ * - `propertiesToProcess`: An (ordered) list of properties that exist and need to be processed,
303+ * based on the specified `propertiesToConsider`, the properties in `package.json` and their
304+ * corresponding format-paths. NOTE: Only one property per format-path needs to be processed.
305+ * - `propertyToPropertiesToMarkAsProcessed`: A mapping from each property in `propertiesToProcess`
306+ * to the list of other properties in `package.json` that need to be marked as processed as soon
307+ * as of the former being processed.
308+ */
309+ function getPropertiesToProcessAndMarkAsProcessed (
310+ packageJson : EntryPointPackageJson , propertiesToConsider : EntryPointJsonProperty [ ] ) : {
311+ propertiesToProcess : EntryPointJsonProperty [ ] ;
312+ propertyToPropertiesToMarkAsProcessed : Map < EntryPointJsonProperty , EntryPointJsonProperty [ ] > ;
313+ } {
314+ const formatPathsToConsider = new Set < string > ( ) ;
315+
316+ const propertiesToProcess : EntryPointJsonProperty [ ] = [ ] ;
317+ for ( const prop of propertiesToConsider ) {
318+ // Ignore properties that are not in `package.json`.
319+ if ( ! packageJson . hasOwnProperty ( prop ) ) continue ;
320+
321+ const formatPath = packageJson [ prop ] ! ;
322+
323+ // Ignore properties that map to the same format-path as a preceding property.
324+ if ( formatPathsToConsider . has ( formatPath ) ) continue ;
325+
326+ // Process this property, because it is the first one to map to this format-path.
327+ formatPathsToConsider . add ( formatPath ) ;
328+ propertiesToProcess . push ( prop ) ;
329+ }
294330
331+ const formatPathToProperties : { [ formatPath : string ] : EntryPointJsonProperty [ ] } = { } ;
295332 for ( const prop of SUPPORTED_FORMAT_PROPERTIES ) {
296- const formatPath = packageJson [ prop ] ;
297- if ( formatPath ) {
298- if ( ! map . has ( formatPath ) ) {
299- map . set ( formatPath , [ ] ) ;
300- }
301- map . get ( formatPath ) ! . push ( prop ) ;
302- }
333+ // Ignore properties that are not in `package.json`.
334+ if ( ! packageJson . hasOwnProperty ( prop ) ) continue ;
335+
336+ const formatPath = packageJson [ prop ] ! ;
337+
338+ // Ignore properties that do not map to a format-path that will be considered.
339+ if ( ! formatPathsToConsider . has ( formatPath ) ) continue ;
340+
341+ // Add this property to the map.
342+ const list = formatPathToProperties [ formatPath ] || ( formatPathToProperties [ formatPath ] = [ ] ) ;
343+ list . push ( prop ) ;
344+ }
345+
346+ const propertyToPropertiesToMarkAsProcessed =
347+ new Map < EntryPointJsonProperty , EntryPointJsonProperty [ ] > ( ) ;
348+ for ( const prop of propertiesToConsider ) {
349+ const formatPath = packageJson [ prop ] ! ;
350+ const propertiesToMarkAsProcessed = formatPathToProperties [ formatPath ] ;
351+ propertyToPropertiesToMarkAsProcessed . set ( prop , propertiesToMarkAsProcessed ) ;
303352 }
304353
305- return map ;
354+ return { propertiesToProcess , propertyToPropertiesToMarkAsProcessed } ;
306355}
0 commit comments