@@ -187,12 +187,7 @@ function _removeDecorators(refactor: TypeScriptFileRefactor) {
187
187
}
188
188
189
189
190
- function _replaceBootstrap ( plugin : AotPlugin , refactor : TypeScriptFileRefactor ) {
191
- // If bootstrapModule can't be found, bail out early.
192
- if ( ! refactor . sourceMatch ( / \b b o o t s t r a p M o d u l e \b / ) ) {
193
- return ;
194
- }
195
-
190
+ function _getNgFactoryPath ( plugin : AotPlugin , refactor : TypeScriptFileRefactor ) {
196
191
// Calculate the base path.
197
192
const basePath = path . normalize ( plugin . basePath ) ;
198
193
const genDir = path . normalize ( plugin . genDir ) ;
@@ -202,44 +197,20 @@ function _replaceBootstrap(plugin: AotPlugin, refactor: TypeScriptFileRefactor)
202
197
const relativeEntryModulePath = path . relative ( basePath , entryModuleFileName ) ;
203
198
const fullEntryModulePath = path . resolve ( genDir , relativeEntryModulePath ) ;
204
199
const relativeNgFactoryPath = path . relative ( dirName , fullEntryModulePath ) ;
205
- const ngFactoryPath = './' + relativeNgFactoryPath . replace ( / \\ / g, '/' ) ;
206
-
207
- const allCalls = refactor . findAstNodes ( refactor . sourceFile ,
208
- ts . SyntaxKind . CallExpression , true ) as ts . CallExpression [ ] ;
209
-
210
- const bootstraps = allCalls
211
- . filter ( call => call . expression . kind == ts . SyntaxKind . PropertyAccessExpression )
212
- . map ( call => call . expression as ts . PropertyAccessExpression )
213
- . filter ( access => {
214
- return access . name . kind == ts . SyntaxKind . Identifier
215
- && access . name . text == 'bootstrapModule' ;
216
- } ) ;
200
+ return './' + relativeNgFactoryPath . replace ( / \\ / g, '/' ) ;
201
+ }
217
202
218
- const calls : ts . CallExpression [ ] = bootstraps
219
- . reduce ( ( previous , access ) => {
220
- const expressions
221
- = refactor . findAstNodes ( access , ts . SyntaxKind . CallExpression , true ) as ts . CallExpression [ ] ;
222
- return previous . concat ( expressions ) ;
223
- } , [ ] )
224
- . filter ( ( call : ts . CallExpression ) => call . expression . kind == ts . SyntaxKind . Identifier )
225
- . filter ( ( call : ts . CallExpression ) => {
226
- // Find if the expression matches one of the replacement targets
227
- return ! ! changeMap [ ( call . expression as ts . Identifier ) . text ] ;
228
- } ) ;
229
203
230
- if ( calls . length == 0 ) {
231
- // Didn't find any dynamic bootstrapping going on.
232
- return ;
233
- }
234
-
235
- // Create the changes we need.
236
- allCalls
237
- . filter ( call => bootstraps . some ( bs => bs == call . expression ) )
238
- . forEach ( ( call : ts . CallExpression ) => {
239
- refactor . replaceNode ( call . arguments [ 0 ] , entryModule . className + 'NgFactory' ) ;
240
- } ) ;
204
+ function _replacePlatform (
205
+ refactor : TypeScriptFileRefactor , bootstrapCall : ts . PropertyAccessExpression ) {
206
+ const platforms = ( refactor . findAstNodes ( bootstrapCall ,
207
+ ts . SyntaxKind . CallExpression , true ) as ts . CallExpression [ ] )
208
+ . filter ( call => {
209
+ return call . expression . kind == ts . SyntaxKind . Identifier ;
210
+ } )
211
+ . filter ( call => ! ! changeMap [ ( call . expression as ts . Identifier ) . text ] ) ;
241
212
242
- calls . forEach ( call => {
213
+ platforms . forEach ( call => {
243
214
const platform = changeMap [ ( call . expression as ts . Identifier ) . text ] ;
244
215
245
216
// Replace with mapped replacement
@@ -248,14 +219,70 @@ function _replaceBootstrap(plugin: AotPlugin, refactor: TypeScriptFileRefactor)
248
219
// Add the appropriate import
249
220
refactor . insertImport ( platform . name , platform . importLocation ) ;
250
221
} ) ;
222
+ }
223
+
224
+
225
+ function _replaceBootstrap ( refactor : TypeScriptFileRefactor , call : ts . CallExpression ) {
226
+ // If bootstrapModule can't be found, bail out early.
227
+ if ( ! call . getText ( ) . includes ( 'bootstrapModule' ) ) {
228
+ return ;
229
+ }
230
+
231
+ if ( call . expression . kind == ts . SyntaxKind . PropertyAccessExpression ) {
232
+ const access = call . expression as ts . PropertyAccessExpression ;
233
+
234
+ if ( access . name . text === 'bootstrapModule' ) {
235
+ _replacePlatform ( refactor , access ) ;
236
+ refactor . replaceNode ( access . name , 'bootstrapModuleFactory' ) ;
237
+ }
238
+ }
239
+ }
240
+
241
+
242
+ function _getCaller ( node : ts . Node ) : ts . CallExpression {
243
+ while ( node = node . parent ) {
244
+ if ( node . kind === ts . SyntaxKind . CallExpression ) {
245
+ return node as ts . CallExpression ;
246
+ }
247
+ }
248
+ return null ;
249
+ }
250
+
251
251
252
- bootstraps
253
- . forEach ( ( bs : ts . PropertyAccessExpression ) => {
254
- // This changes the call.
255
- refactor . replaceNode ( bs . name , 'bootstrapModuleFactory' ) ;
252
+ function _replaceEntryModule ( plugin : AotPlugin , refactor : TypeScriptFileRefactor ) {
253
+ const modules = refactor . findAstNodes ( refactor . sourceFile , ts . SyntaxKind . Identifier , true )
254
+ . filter ( identifier => identifier . getText ( ) === plugin . entryModule . className )
255
+ . filter ( identifier =>
256
+ identifier . parent . kind === ts . SyntaxKind . CallExpression ||
257
+ identifier . parent . kind === ts . SyntaxKind . PropertyAssignment )
258
+ . filter ( node => ! ! _getCaller ( node ) ) ;
259
+
260
+ if ( modules . length == 0 ) {
261
+ return ;
262
+ }
263
+
264
+ const factoryClassName = plugin . entryModule . className + 'NgFactory' ;
265
+
266
+ refactor . insertImport ( factoryClassName , _getNgFactoryPath ( plugin , refactor ) ) ;
267
+
268
+ modules
269
+ . forEach ( reference => {
270
+ refactor . replaceNode ( reference , factoryClassName ) ;
271
+ _replaceBootstrap ( refactor , _getCaller ( reference ) ) ;
256
272
} ) ;
273
+ }
274
+
275
+
276
+ function _refactorBootstrap ( plugin : AotPlugin , refactor : TypeScriptFileRefactor ) {
277
+ const genDir = path . normalize ( plugin . genDir ) ;
278
+ const dirName = path . normalize ( path . dirname ( refactor . fileName ) ) ;
279
+
280
+ // Bail if in the generated directory
281
+ if ( dirName . startsWith ( genDir ) ) {
282
+ return ;
283
+ }
257
284
258
- refactor . insertImport ( entryModule . className + 'NgFactory' , ngFactoryPath ) ;
285
+ _replaceEntryModule ( plugin , refactor ) ;
259
286
}
260
287
261
288
export function removeModuleIdOnlyForTesting ( refactor : TypeScriptFileRefactor ) {
@@ -410,7 +437,7 @@ export function ngcLoader(this: LoaderContext & { _compilation: any }) {
410
437
if ( ! plugin . skipCodeGeneration ) {
411
438
return Promise . resolve ( )
412
439
. then ( ( ) => _removeDecorators ( refactor ) )
413
- . then ( ( ) => _replaceBootstrap ( plugin , refactor ) ) ;
440
+ . then ( ( ) => _refactorBootstrap ( plugin , refactor ) ) ;
414
441
} else {
415
442
return Promise . resolve ( )
416
443
. then ( ( ) => _replaceResources ( refactor ) )
0 commit comments