6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
8
8
9
- import { AnimationAnimateMetadata , AnimationEntryMetadata , AnimationGroupMetadata , AnimationKeyframesSequenceMetadata , AnimationMetadata , AnimationStateDeclarationMetadata , AnimationStateMetadata , AnimationStateTransitionMetadata , AnimationStyleMetadata , AnimationWithStepsMetadata , Attribute , ChangeDetectionStrategy , Component , Directive , Host , Inject , Injectable , ModuleWithProviders , Optional , Provider , Query , SchemaMetadata , Self , SkipSelf , Type , resolveForwardRef } from '@angular/core' ;
9
+ import { AnimationAnimateMetadata , AnimationEntryMetadata , AnimationGroupMetadata , AnimationKeyframesSequenceMetadata , AnimationMetadata , AnimationStateDeclarationMetadata , AnimationStateMetadata , AnimationStateTransitionMetadata , AnimationStyleMetadata , AnimationWithStepsMetadata , Attribute , ChangeDetectionStrategy , Component , Directive , Host , Inject , Injectable , ModuleWithProviders , OpaqueToken , Optional , Provider , Query , SchemaMetadata , Self , SkipSelf , Type , resolveForwardRef } from '@angular/core' ;
10
10
11
11
import { StaticSymbol } from './aot/static_symbol' ;
12
12
import { assertArrayOfStrings , assertInterpolationSymbols } from './assertions' ;
@@ -25,7 +25,8 @@ import {SummaryResolver} from './summary_resolver';
25
25
import { getUrlScheme } from './url_resolver' ;
26
26
import { MODULE_SUFFIX , SyncAsyncResult , ValueTransformer , visitValue } from './util' ;
27
27
28
-
28
+ export type ErrorCollector = ( error : any , type ?: any ) => void ;
29
+ export const ERROR_COLLECTOR_TOKEN = new OpaqueToken ( 'ErrorCollector' ) ;
29
30
30
31
// Design notes:
31
32
// - don't lazily create metadata:
@@ -47,7 +48,8 @@ export class CompileMetadataResolver {
47
48
private _pipeResolver : PipeResolver , private _summaryResolver : SummaryResolver ,
48
49
private _schemaRegistry : ElementSchemaRegistry ,
49
50
private _directiveNormalizer : DirectiveNormalizer ,
50
- private _reflector : ReflectorReader = reflector ) { }
51
+ private _reflector : ReflectorReader = reflector ,
52
+ @Optional ( ) @Inject ( ERROR_COLLECTOR_TOKEN ) private _errorCollector ?: ErrorCollector ) { }
51
53
52
54
clearCacheFor ( type : Type < any > ) {
53
55
const dirMeta = this . _directiveCache . get ( type ) ;
@@ -182,7 +184,8 @@ export class CompileMetadataResolver {
182
184
return null ;
183
185
} else {
184
186
if ( isSync ) {
185
- throw new ComponentStillLoadingError ( directiveType ) ;
187
+ this . _reportError ( new ComponentStillLoadingError ( directiveType ) , directiveType ) ;
188
+ return null ;
186
189
}
187
190
return templateMeta . asyncResult . then ( createDirectiveMetadata ) ;
188
191
}
@@ -234,7 +237,7 @@ export class CompileMetadataResolver {
234
237
if ( dirMeta . viewProviders ) {
235
238
viewProviders = this . _getProvidersMetadata (
236
239
dirMeta . viewProviders , entryComponentMetadata ,
237
- `viewProviders for "${ stringify ( directiveType ) } "` ) ;
240
+ `viewProviders for "${ stringify ( directiveType ) } "` , [ ] , directiveType ) ;
238
241
}
239
242
if ( dirMeta . entryComponents ) {
240
243
entryComponentMetadata = flattenAndDedupeArray ( dirMeta . entryComponents )
@@ -247,14 +250,18 @@ export class CompileMetadataResolver {
247
250
} else {
248
251
// Directive
249
252
if ( ! selector ) {
250
- throw new Error ( `Directive ${ stringify ( directiveType ) } has no selector, please add it!` ) ;
253
+ this . _reportError (
254
+ new Error ( `Directive ${ stringify ( directiveType ) } has no selector, please add it!` ) ,
255
+ directiveType ) ;
256
+ selector = 'error' ;
251
257
}
252
258
}
253
259
254
260
let providers : cpl . CompileProviderMetadata [ ] = [ ] ;
255
261
if ( isPresent ( dirMeta . providers ) ) {
256
262
providers = this . _getProvidersMetadata (
257
- dirMeta . providers , entryComponentMetadata , `providers for "${ stringify ( directiveType ) } "` ) ;
263
+ dirMeta . providers , entryComponentMetadata , `providers for "${ stringify ( directiveType ) } "` ,
264
+ [ ] , directiveType ) ;
258
265
}
259
266
let queries : cpl . CompileQueryMetadata [ ] = [ ] ;
260
267
let viewQueries : cpl . CompileQueryMetadata [ ] = [ ] ;
@@ -289,8 +296,10 @@ export class CompileMetadataResolver {
289
296
getDirectiveMetadata ( directiveType : any ) : cpl . CompileDirectiveMetadata {
290
297
const dirMeta = this . _directiveCache . get ( directiveType ) ;
291
298
if ( ! dirMeta ) {
292
- throw new Error (
293
- `Illegal state: getDirectiveMetadata can only be called after loadNgModuleMetadata for a module that declares it. Directive ${ stringify ( directiveType ) } .` ) ;
299
+ this . _reportError (
300
+ new Error (
301
+ `Illegal state: getDirectiveMetadata can only be called after loadNgModuleMetadata for a module that declares it. Directive ${ stringify ( directiveType ) } .` ) ,
302
+ directiveType ) ;
294
303
}
295
304
return dirMeta ;
296
305
}
@@ -299,8 +308,10 @@ export class CompileMetadataResolver {
299
308
const dirSummary =
300
309
< cpl . CompileDirectiveSummary > this . _loadSummary ( dirType , cpl . CompileSummaryKind . Directive ) ;
301
310
if ( ! dirSummary ) {
302
- throw new Error (
303
- `Illegal state: Could not load the summary for directive ${ stringify ( dirType ) } .` ) ;
311
+ this . _reportError (
312
+ new Error (
313
+ `Illegal state: Could not load the summary for directive ${ stringify ( dirType ) } .` ) ,
314
+ dirType ) ;
304
315
}
305
316
return dirSummary ;
306
317
}
@@ -372,29 +383,38 @@ export class CompileMetadataResolver {
372
383
if ( moduleWithProviders . providers ) {
373
384
providers . push ( ...this . _getProvidersMetadata (
374
385
moduleWithProviders . providers , entryComponents ,
375
- `provider for the NgModule '${ stringify ( importedModuleType ) } '` ) ) ;
386
+ `provider for the NgModule '${ stringify ( importedModuleType ) } '` , [ ] , importedType ) ) ;
376
387
}
377
388
}
378
389
379
390
if ( importedModuleType ) {
380
391
const importedModuleSummary = this . getNgModuleSummary ( importedModuleType ) ;
381
392
if ( ! importedModuleSummary ) {
382
- throw new Error (
383
- `Unexpected ${ this . _getTypeDescriptor ( importedType ) } '${ stringify ( importedType ) } ' imported by the module '${ stringify ( moduleType ) } '` ) ;
393
+ this . _reportError (
394
+ new Error (
395
+ `Unexpected ${ this . _getTypeDescriptor ( importedType ) } '${ stringify ( importedType ) } ' imported by the module '${ stringify ( moduleType ) } '` ) ,
396
+ moduleType ) ;
397
+ return ;
384
398
}
385
399
importedModules . push ( importedModuleSummary ) ;
386
400
} else {
387
- throw new Error (
388
- `Unexpected value '${ stringify ( importedType ) } ' imported by the module '${ stringify ( moduleType ) } '` ) ;
401
+ this . _reportError (
402
+ new Error (
403
+ `Unexpected value '${ stringify ( importedType ) } ' imported by the module '${ stringify ( moduleType ) } '` ) ,
404
+ moduleType ) ;
405
+ return ;
389
406
}
390
407
} ) ;
391
408
}
392
409
393
410
if ( meta . exports ) {
394
411
flattenAndDedupeArray ( meta . exports ) . forEach ( ( exportedType ) => {
395
412
if ( ! isValidType ( exportedType ) ) {
396
- throw new Error (
397
- `Unexpected value '${ stringify ( exportedType ) } ' exported by the module '${ stringify ( moduleType ) } '` ) ;
413
+ this . _reportError (
414
+ new Error (
415
+ `Unexpected value '${ stringify ( exportedType ) } ' exported by the module '${ stringify ( moduleType ) } '` ) ,
416
+ moduleType ) ;
417
+ return ;
398
418
}
399
419
const exportedModuleSummary = this . getNgModuleSummary ( exportedType ) ;
400
420
if ( exportedModuleSummary ) {
@@ -411,8 +431,11 @@ export class CompileMetadataResolver {
411
431
if ( meta . declarations ) {
412
432
flattenAndDedupeArray ( meta . declarations ) . forEach ( ( declaredType ) => {
413
433
if ( ! isValidType ( declaredType ) ) {
414
- throw new Error (
415
- `Unexpected value '${ stringify ( declaredType ) } ' declared by the module '${ stringify ( moduleType ) } '` ) ;
434
+ this . _reportError (
435
+ new Error (
436
+ `Unexpected value '${ stringify ( declaredType ) } ' declared by the module '${ stringify ( moduleType ) } '` ) ,
437
+ moduleType ) ;
438
+ return ;
416
439
}
417
440
const declaredIdentifier = this . _getIdentifierMetadata ( declaredType ) ;
418
441
if ( this . _directiveResolver . isDirective ( declaredType ) ) {
@@ -425,8 +448,11 @@ export class CompileMetadataResolver {
425
448
declaredPipes . push ( declaredIdentifier ) ;
426
449
this . _addTypeToModule ( declaredType , moduleType ) ;
427
450
} else {
428
- throw new Error (
429
- `Unexpected ${ this . _getTypeDescriptor ( declaredType ) } '${ stringify ( declaredType ) } ' declared by the module '${ stringify ( moduleType ) } '` ) ;
451
+ this . _reportError (
452
+ new Error (
453
+ `Unexpected ${ this . _getTypeDescriptor ( declaredType ) } '${ stringify ( declaredType ) } ' declared by the module '${ stringify ( moduleType ) } '` ) ,
454
+ moduleType ) ;
455
+ return ;
430
456
}
431
457
} ) ;
432
458
}
@@ -441,16 +467,19 @@ export class CompileMetadataResolver {
441
467
exportedPipes . push ( exportedId ) ;
442
468
transitiveModule . addExportedPipe ( exportedId ) ;
443
469
} else {
444
- throw new Error (
445
- `Can't export ${ this . _getTypeDescriptor ( exportedId . reference ) } ${ stringify ( exportedId . reference ) } from ${ stringify ( moduleType ) } as it was neither declared nor imported!` ) ;
470
+ this . _reportError (
471
+ new Error (
472
+ `Can't export ${ this . _getTypeDescriptor ( exportedId . reference ) } ${ stringify ( exportedId . reference ) } from ${ stringify ( moduleType ) } as it was neither declared nor imported!` ) ,
473
+ moduleType ) ;
446
474
}
447
475
} ) ;
448
476
449
477
// The providers of the module have to go last
450
478
// so that they overwrite any other provider we already added.
451
479
if ( meta . providers ) {
452
480
providers . push ( ...this . _getProvidersMetadata (
453
- meta . providers , entryComponents , `provider for the NgModule '${ stringify ( moduleType ) } '` ) ) ;
481
+ meta . providers , entryComponents , `provider for the NgModule '${ stringify ( moduleType ) } '` ,
482
+ [ ] , moduleType ) ) ;
454
483
}
455
484
456
485
if ( meta . entryComponents ) {
@@ -459,14 +488,16 @@ export class CompileMetadataResolver {
459
488
}
460
489
461
490
if ( meta . bootstrap ) {
462
- const typeMetadata = flattenAndDedupeArray ( meta . bootstrap ) . map ( type => {
491
+ flattenAndDedupeArray ( meta . bootstrap ) . forEach ( type => {
463
492
if ( ! isValidType ( type ) ) {
464
- throw new Error (
465
- `Unexpected value '${ stringify ( type ) } ' used in the bootstrap property of module '${ stringify ( moduleType ) } '` ) ;
493
+ this . _reportError (
494
+ new Error (
495
+ `Unexpected value '${ stringify ( type ) } ' used in the bootstrap property of module '${ stringify ( moduleType ) } '` ) ,
496
+ moduleType ) ;
497
+ return ;
466
498
}
467
- return this . _getTypeMetadata ( type ) ;
499
+ bootstrapComponents . push ( this . _getTypeMetadata ( type ) ) ;
468
500
} ) ;
469
- bootstrapComponents . push ( ...typeMetadata ) ;
470
501
}
471
502
472
503
entryComponents . push ( ...bootstrapComponents ) ;
@@ -522,10 +553,12 @@ export class CompileMetadataResolver {
522
553
private _addTypeToModule ( type : Type < any > , moduleType : Type < any > ) {
523
554
const oldModule = this . _ngModuleOfTypes . get ( type ) ;
524
555
if ( oldModule && oldModule !== moduleType ) {
525
- throw new Error (
526
- `Type ${ stringify ( type ) } is part of the declarations of 2 modules: ${ stringify ( oldModule ) } and ${ stringify ( moduleType ) } ! ` +
527
- `Please consider moving ${ stringify ( type ) } to a higher module that imports ${ stringify ( oldModule ) } and ${ stringify ( moduleType ) } . ` +
528
- `You can also create a new NgModule that exports and includes ${ stringify ( type ) } then import that NgModule in ${ stringify ( oldModule ) } and ${ stringify ( moduleType ) } .` ) ;
556
+ this . _reportError (
557
+ new Error (
558
+ `Type ${ stringify ( type ) } is part of the declarations of 2 modules: ${ stringify ( oldModule ) } and ${ stringify ( moduleType ) } ! ` +
559
+ `Please consider moving ${ stringify ( type ) } to a higher module that imports ${ stringify ( oldModule ) } and ${ stringify ( moduleType ) } . ` +
560
+ `You can also create a new NgModule that exports and includes ${ stringify ( type ) } then import that NgModule in ${ stringify ( oldModule ) } and ${ stringify ( moduleType ) } .` ) ,
561
+ moduleType ) ;
529
562
}
530
563
this . _ngModuleOfTypes . set ( type , moduleType ) ;
531
564
}
@@ -596,8 +629,10 @@ export class CompileMetadataResolver {
596
629
getPipeMetadata ( pipeType : any ) : cpl . CompilePipeMetadata {
597
630
const pipeMeta = this . _pipeCache . get ( pipeType ) ;
598
631
if ( ! pipeMeta ) {
599
- throw new Error (
600
- `Illegal state: getPipeMetadata can only be called after loadNgModuleMetadata for a module that declares it. Pipe ${ stringify ( pipeType ) } .` ) ;
632
+ this . _reportError (
633
+ new Error (
634
+ `Illegal state: getPipeMetadata can only be called after loadNgModuleMetadata for a module that declares it. Pipe ${ stringify ( pipeType ) } .` ) ,
635
+ pipeType ) ;
601
636
}
602
637
return pipeMeta ;
603
638
}
@@ -606,7 +641,9 @@ export class CompileMetadataResolver {
606
641
const pipeSummary =
607
642
< cpl . CompilePipeSummary > this . _loadSummary ( pipeType , cpl . CompileSummaryKind . Pipe ) ;
608
643
if ( ! pipeSummary ) {
609
- throw new Error ( `Illegal state: Could not load the summary for pipe ${ stringify ( pipeType ) } .` ) ;
644
+ this . _reportError (
645
+ new Error ( `Illegal state: Could not load the summary for pipe ${ stringify ( pipeType ) } .` ) ,
646
+ pipeType ) ;
610
647
}
611
648
return pipeSummary ;
612
649
}
@@ -686,8 +723,9 @@ export class CompileMetadataResolver {
686
723
if ( hasUnknownDeps ) {
687
724
const depsTokens =
688
725
dependenciesMetadata . map ( ( dep ) => dep ? stringify ( dep . token ) : '?' ) . join ( ', ' ) ;
689
- throw new Error (
690
- `Can't resolve all parameters for ${ stringify ( typeOrFunc ) } : (${ depsTokens } ).` ) ;
726
+ this . _reportError (
727
+ new Error ( `Can't resolve all parameters for ${ stringify ( typeOrFunc ) } : (${ depsTokens } ).` ) ,
728
+ typeOrFunc ) ;
691
729
}
692
730
693
731
return dependenciesMetadata ;
@@ -706,8 +744,8 @@ export class CompileMetadataResolver {
706
744
707
745
private _getProvidersMetadata (
708
746
providers : Provider [ ] , targetEntryComponents : cpl . CompileIdentifierMetadata [ ] ,
709
- debugInfo ?: string ,
710
- compileProviders : cpl . CompileProviderMetadata [ ] = [ ] ) : cpl . CompileProviderMetadata [ ] {
747
+ debugInfo ?: string , compileProviders : cpl . CompileProviderMetadata [ ] = [ ] ,
748
+ type ?: any ) : cpl . CompileProviderMetadata [ ] {
711
749
providers . forEach ( ( provider : any , providerIdx : number ) => {
712
750
if ( Array . isArray ( provider ) ) {
713
751
this . _getProvidersMetadata ( provider , targetEntryComponents , debugInfo , compileProviders ) ;
@@ -733,11 +771,13 @@ export class CompileMetadataResolver {
733
771
} ,
734
772
[ ] ) )
735
773
. join ( ', ' ) ;
736
- throw new Error (
737
- `Invalid ${ debugInfo ? debugInfo : 'provider' } - only instances of Provider and Type are allowed, got: [${ providersInfo } ]` ) ;
774
+ this . _reportError (
775
+ new Error (
776
+ `Invalid ${ debugInfo ? debugInfo : 'provider' } - only instances of Provider and Type are allowed, got: [${ providersInfo } ]` ) ,
777
+ type ) ;
738
778
}
739
779
if ( providerMeta . token === resolveIdentifier ( Identifiers . ANALYZE_FOR_ENTRY_COMPONENTS ) ) {
740
- targetEntryComponents . push ( ...this . _getEntryComponentsFromProvider ( providerMeta ) ) ;
780
+ targetEntryComponents . push ( ...this . _getEntryComponentsFromProvider ( providerMeta , type ) ) ;
741
781
} else {
742
782
compileProviders . push ( this . getProviderMetadata ( providerMeta ) ) ;
743
783
}
@@ -746,17 +786,21 @@ export class CompileMetadataResolver {
746
786
return compileProviders ;
747
787
}
748
788
749
- private _getEntryComponentsFromProvider ( provider : cpl . ProviderMeta ) :
789
+ private _getEntryComponentsFromProvider ( provider : cpl . ProviderMeta , type ?: any ) :
750
790
cpl . CompileIdentifierMetadata [ ] {
751
791
const components : cpl . CompileIdentifierMetadata [ ] = [ ] ;
752
792
const collectedIdentifiers : cpl . CompileIdentifierMetadata [ ] = [ ] ;
753
793
754
794
if ( provider . useFactory || provider . useExisting || provider . useClass ) {
755
- throw new Error ( `The ANALYZE_FOR_ENTRY_COMPONENTS token only supports useValue!` ) ;
795
+ this . _reportError (
796
+ new Error ( `The ANALYZE_FOR_ENTRY_COMPONENTS token only supports useValue!` ) , type ) ;
797
+ return [ ] ;
756
798
}
757
799
758
800
if ( ! provider . multi ) {
759
- throw new Error ( `The ANALYZE_FOR_ENTRY_COMPONENTS token only supports 'multi = true'!` ) ;
801
+ this . _reportError (
802
+ new Error ( `The ANALYZE_FOR_ENTRY_COMPONENTS token only supports 'multi = true'!` ) , type ) ;
803
+ return [ ] ;
760
804
}
761
805
762
806
extractIdentifiers ( provider . useValue , collectedIdentifiers ) ;
@@ -822,8 +866,10 @@ export class CompileMetadataResolver {
822
866
this . _queryVarBindings ( q . selector ) . map ( varName => this . _getTokenMetadata ( varName ) ) ;
823
867
} else {
824
868
if ( ! q . selector ) {
825
- throw new Error (
826
- `Can't construct a query for the property "${ propertyName } " of "${ stringify ( typeOrFunc ) } " since the query selector wasn't defined.` ) ;
869
+ this . _reportError (
870
+ new Error (
871
+ `Can't construct a query for the property "${ propertyName } " of "${ stringify ( typeOrFunc ) } " since the query selector wasn't defined.` ) ,
872
+ typeOrFunc ) ;
827
873
}
828
874
selectors = [ this . _getTokenMetadata ( q . selector ) ] ;
829
875
}
@@ -835,6 +881,17 @@ export class CompileMetadataResolver {
835
881
read : q . read ? this . _getTokenMetadata ( q . read ) : null
836
882
} ;
837
883
}
884
+
885
+ private _reportError ( error : any , type ?: any , otherType ?: any ) {
886
+ if ( this . _errorCollector ) {
887
+ this . _errorCollector ( error , type ) ;
888
+ if ( otherType ) {
889
+ this . _errorCollector ( error , otherType ) ;
890
+ }
891
+ } else {
892
+ throw error ;
893
+ }
894
+ }
838
895
}
839
896
840
897
function flattenArray ( tree : any [ ] , out : Array < any > = [ ] ) : Array < any > {
0 commit comments