Skip to content

Commit 0afd9c5

Browse files
arturovtthePunderWoman
authored andcommitted
refactor(core): swap dev/prod error handling order in injector for tree-shaking (#63354)
In production builds, `ngDevMode` is replaced with `false`, so the guard compiles to `return;`. However, bundlers like ESBuild still keep the remaining statements after the return as unreachable code instead of removing them. This leaves behind unnecessary dead code in the output. Technically, the body is unreachable. But to prove that, the bundler must be 100% certain that: - `return` cannot be removed by some transform - there's no later transformation that changes control flow As thus, it's always conservative. This also allows dropping `assertDefined`, which was previously referenced only inside `prependTokenToDependencyPath`. With the function now fully inlined and dev-only, `assertDefined` is also eliminated from production builds, further reducing bundle size. PR Close #63354
1 parent 444fd01 commit 0afd9c5

File tree

8 files changed

+15
-46
lines changed

8 files changed

+15
-46
lines changed

packages/core/src/di/r3_injector.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ import {setActiveConsumer} from '@angular/core/primitives/signals';
7979
import {
8080
Injector as PrimitivesInjector,
8181
InjectionToken as PrimitivesInjectionToken,
82-
NOT_FOUND,
8382
NotFound,
8483
isNotFound,
8584
} from '@angular/core/primitives/di';
@@ -392,18 +391,23 @@ export class R3Injector extends EnvironmentInjector implements PrimitivesInjecto
392391
errorCode === RuntimeErrorCode.CYCLIC_DI_DEPENDENCY ||
393392
errorCode === RuntimeErrorCode.PROVIDER_NOT_FOUND
394393
) {
395-
if (!ngDevMode) {
396-
throw new RuntimeError(errorCode, null);
397-
}
398-
399-
prependTokenToDependencyPath(error, token);
394+
// Note: we use `if (ngDevMode) { ... }` instead of an early return.
395+
// ESBuild is conservative about removing dead code that follows `return;`
396+
// inside a function body, so the block may remain in the bundle.
397+
// Using a conditional ensures the dev-only logic is reliably tree-shaken
398+
// in production builds.
399+
if (ngDevMode) {
400+
prependTokenToDependencyPath(error, token);
400401

401-
if (previousInjector) {
402-
// We still have a parent injector, keep throwing
403-
throw error;
402+
if (previousInjector) {
403+
// We still have a parent injector, keep throwing
404+
throw error;
405+
} else {
406+
// Format & throw the final error message when we don't have any previous injector
407+
throw augmentRuntimeError(error, this.source);
408+
}
404409
} else {
405-
// Format & throw the final error message when we don't have any previous injector
406-
throw augmentRuntimeError(error, this.source);
410+
throw new RuntimeError(errorCode, null);
407411
}
408412
} else {
409413
throw error;

packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -415,10 +415,8 @@
415415
"applyView",
416416
"areAnimationSupported",
417417
"arrRemove",
418-
"assertDefined",
419418
"assertNotDestroyed",
420419
"attachPatchData",
421-
"augmentRuntimeError",
422420
"balancePreviousStylesIntoKeyframes",
423421
"balanceProperties",
424422
"baseElement",
@@ -551,7 +549,6 @@
551549
"flattenStyles",
552550
"forEachSingleProvider",
553551
"forkInnerZoneWithAngularBehavior",
554-
"formatErrorMessage",
555552
"formatRuntimeError",
556553
"formatRuntimeErrorCode",
557554
"forwardRef",
@@ -808,7 +805,6 @@
808805
"parseTriggerCallbackName",
809806
"performanceMarkFeature",
810807
"pipeFromArray",
811-
"prependTokenToDependencyPath",
812808
"processCleanups",
813809
"processHostBindingOpCodes",
814810
"processInjectorTypesWithProviders",
@@ -909,7 +905,6 @@
909905
"stringifyForError",
910906
"style",
911907
"syncViewWithBlueprint",
912-
"throwError",
913908
"throwInvalidWriteToSignalErrorFn",
914909
"throwProviderNotFoundError",
915910
"timeoutProvider",

packages/core/test/bundling/defer/bundle.golden_symbols.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,8 @@
358358
"applyView",
359359
"areAnimationSupported",
360360
"arrRemove",
361-
"assertDefined",
362361
"assertNotDestroyed",
363362
"attachPatchData",
364-
"augmentRuntimeError",
365363
"bind",
366364
"bindingUpdated",
367365
"bloomAdd",
@@ -469,7 +467,6 @@
469467
"findMatchingDehydratedViewForDeferBlock",
470468
"forEachSingleProvider",
471469
"forkInnerZoneWithAngularBehavior",
472-
"formatErrorMessage",
473470
"formatRuntimeError",
474471
"formatRuntimeErrorCode",
475472
"forwardRef",
@@ -683,7 +680,6 @@
683680
"performanceMarkFeature",
684681
"pipeFromArray",
685682
"populateDehydratedViewsInLContainer",
686-
"prependTokenToDependencyPath",
687683
"processCleanups",
688684
"processHostBindingOpCodes",
689685
"processInjectorTypesWithProviders",
@@ -776,7 +772,6 @@
776772
"stringifyForError",
777773
"syncViewWithBlueprint",
778774
"templateCreate",
779-
"throwError",
780775
"throwInvalidWriteToSignalErrorFn",
781776
"throwProviderNotFoundError",
782777
"timeoutProvider",

packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -451,11 +451,9 @@
451451
"arrayInsert2",
452452
"assertAllValuesPresent",
453453
"assertControlPresent",
454-
"assertDefined",
455454
"assertNotDestroyed",
456455
"assertPlatform",
457456
"attachPatchData",
458-
"augmentRuntimeError",
459457
"baseElement",
460458
"bind",
461459
"bindingUpdated",
@@ -611,7 +609,6 @@
611609
"formArrayNameProvider",
612610
"formDirectiveProvider",
613611
"formGroupNameProvider",
614-
"formatErrorMessage",
615612
"formatRuntimeError",
616613
"formatRuntimeErrorCode",
617614
"forwardRef",
@@ -930,7 +927,6 @@
930927
"populateDehydratedViewsInLContainer",
931928
"postProducerCreatedFn",
932929
"postSignalSetFn",
933-
"prependTokenToDependencyPath",
934930
"process",
935931
"processCleanups",
936932
"processHostBindingOpCodes",
@@ -1073,7 +1069,6 @@
10731069
"syncPendingControls",
10741070
"syncViewWithBlueprint",
10751071
"templateCreate",
1076-
"throwError",
10771072
"throwInvalidWriteToSignalError",
10781073
"throwInvalidWriteToSignalErrorFn",
10791074
"throwProviderNotFoundError",

packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -453,11 +453,9 @@
453453
"arrayInsert2",
454454
"assertAllValuesPresent",
455455
"assertControlPresent",
456-
"assertDefined",
457456
"assertNotDestroyed",
458457
"assertPlatform",
459458
"attachPatchData",
460-
"augmentRuntimeError",
461459
"baseElement",
462460
"bind",
463461
"bindingUpdated",
@@ -610,7 +608,6 @@
610608
"forkJoin",
611609
"formControlBinding",
612610
"formDirectiveProvider",
613-
"formatErrorMessage",
614611
"formatRuntimeError",
615612
"formatRuntimeErrorCode",
616613
"forwardRef",
@@ -926,7 +923,6 @@
926923
"populateDehydratedViewsInLContainer",
927924
"postProducerCreatedFn",
928925
"postSignalSetFn",
929-
"prependTokenToDependencyPath",
930926
"process",
931927
"processCleanups",
932928
"processHostBindingOpCodes",
@@ -1070,7 +1066,6 @@
10701066
"syncPendingControls",
10711067
"syncViewWithBlueprint",
10721068
"templateCreate",
1073-
"throwError",
10741069
"throwInvalidWriteToSignalError",
10751070
"throwInvalidWriteToSignalErrorFn",
10761071
"throwProviderNotFoundError",

packages/core/test/bundling/hydration/bundle.golden_symbols.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -356,10 +356,8 @@
356356
"applyView",
357357
"areAnimationSupported",
358358
"arrRemove",
359-
"assertDefined",
360359
"assertNotDestroyed",
361360
"attachPatchData",
362-
"augmentRuntimeError",
363361
"baseElement",
364362
"bind",
365363
"bloomAdd",
@@ -488,7 +486,6 @@
488486
"findMatchingDehydratedViewImpl",
489487
"forEachSingleProvider",
490488
"forkInnerZoneWithAngularBehavior",
491-
"formatErrorMessage",
492489
"formatRuntimeError",
493490
"formatRuntimeErrorCode",
494491
"forwardRef",
@@ -723,7 +720,6 @@
723720
"pipeFromArray",
724721
"popScheduler",
725722
"populateDehydratedViewsInLContainerImpl",
726-
"prependTokenToDependencyPath",
727723
"process",
728724
"processCleanups",
729725
"processHostBindingOpCodes",
@@ -828,7 +824,6 @@
828824
"stringifyForError",
829825
"subscribeOn",
830826
"syncViewWithBlueprint",
831-
"throwError",
832827
"throwInvalidWriteToSignalErrorFn",
833828
"throwProviderNotFoundError",
834829
"timeoutProvider",

packages/core/test/bundling/router/bundle.golden_symbols.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -526,10 +526,8 @@
526526
"argsArgArrayOrObject",
527527
"arrRemove",
528528
"arrayEquals",
529-
"assertDefined",
530529
"assertNotDestroyed",
531530
"attachPatchData",
532-
"augmentRuntimeError",
533531
"baseElement",
534532
"bind",
535533
"bindingUpdated",
@@ -725,7 +723,6 @@
725723
"flattenRouteTree",
726724
"forEachSingleProvider",
727725
"forkInnerZoneWithAngularBehavior",
728-
"formatErrorMessage",
729726
"formatRuntimeError",
730727
"formatRuntimeErrorCode",
731728
"forwardRef",
@@ -1061,7 +1058,6 @@
10611058
"postProducerCreatedFn",
10621059
"postSignalSetFn",
10631060
"prefixedWith",
1064-
"prependTokenToDependencyPath",
10651061
"prioritizedGuardValue",
10661062
"process",
10671063
"processCleanups",
@@ -1226,7 +1222,6 @@
12261222
"tap",
12271223
"textBindingInternal",
12281224
"throwError",
1229-
"throwError2",
12301225
"throwIfEmpty",
12311226
"throwInvalidWriteToSignalError",
12321227
"throwInvalidWriteToSignalErrorFn",

packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,8 @@
294294
"applyView",
295295
"areAnimationSupported",
296296
"arrRemove",
297-
"assertDefined",
298297
"assertNotDestroyed",
299298
"attachPatchData",
300-
"augmentRuntimeError",
301299
"baseElement",
302300
"bind",
303301
"bloomAdd",
@@ -397,7 +395,6 @@
397395
"finalizeConsumerAfterComputation",
398396
"forEachSingleProvider",
399397
"forkInnerZoneWithAngularBehavior",
400-
"formatErrorMessage",
401398
"formatRuntimeError",
402399
"formatRuntimeErrorCode",
403400
"forwardRef",
@@ -579,7 +576,6 @@
579576
"parseCookieValue",
580577
"performanceMarkFeature",
581578
"pipeFromArray",
582-
"prependTokenToDependencyPath",
583579
"processCleanups",
584580
"processHostBindingOpCodes",
585581
"processInjectorTypesWithProviders",
@@ -663,7 +659,6 @@
663659
"stringifyCSSSelectorList",
664660
"stringifyForError",
665661
"syncViewWithBlueprint",
666-
"throwError",
667662
"throwInvalidWriteToSignalErrorFn",
668663
"throwProviderNotFoundError",
669664
"timeoutProvider",

0 commit comments

Comments
 (0)