@@ -187,12 +187,7 @@ function _removeDecorators(refactor: TypeScriptFileRefactor) {
187187}
188188
189189
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 ) {
196191 // Calculate the base path.
197192 const basePath = path . normalize ( plugin . basePath ) ;
198193 const genDir = path . normalize ( plugin . genDir ) ;
@@ -202,44 +197,20 @@ function _replaceBootstrap(plugin: AotPlugin, refactor: TypeScriptFileRefactor)
202197 const relativeEntryModulePath = path . relative ( basePath , entryModuleFileName ) ;
203198 const fullEntryModulePath = path . resolve ( genDir , relativeEntryModulePath ) ;
204199 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+ }
217202
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- } ) ;
229203
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 ] ) ;
241212
242- calls . forEach ( call => {
213+ platforms . forEach ( call => {
243214 const platform = changeMap [ ( call . expression as ts . Identifier ) . text ] ;
244215
245216 // Replace with mapped replacement
@@ -248,14 +219,70 @@ function _replaceBootstrap(plugin: AotPlugin, refactor: TypeScriptFileRefactor)
248219 // Add the appropriate import
249220 refactor . insertImport ( platform . name , platform . importLocation ) ;
250221 } ) ;
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+
251251
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 ) ) ;
256272 } ) ;
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+ }
257284
258- refactor . insertImport ( entryModule . className + 'NgFactory' , ngFactoryPath ) ;
285+ _replaceEntryModule ( plugin , refactor ) ;
259286}
260287
261288export function removeModuleIdOnlyForTesting ( refactor : TypeScriptFileRefactor ) {
@@ -410,7 +437,7 @@ export function ngcLoader(this: LoaderContext & { _compilation: any }) {
410437 if ( ! plugin . skipCodeGeneration ) {
411438 return Promise . resolve ( )
412439 . then ( ( ) => _removeDecorators ( refactor ) )
413- . then ( ( ) => _replaceBootstrap ( plugin , refactor ) ) ;
440+ . then ( ( ) => _refactorBootstrap ( plugin , refactor ) ) ;
414441 } else {
415442 return Promise . resolve ( )
416443 . then ( ( ) => _replaceResources ( refactor ) )
0 commit comments