@angular/core 14.1.0-next.0 → 14.1.0-next.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/esm2020/src/application_ref.mjs +31 -35
  2. package/esm2020/src/change_detection/differs/default_iterable_differ.mjs +3 -5
  3. package/esm2020/src/change_detection/differs/default_keyvalue_differ.mjs +3 -5
  4. package/esm2020/src/change_detection/differs/iterable_differs.mjs +3 -5
  5. package/esm2020/src/change_detection/differs/keyvalue_differs.mjs +2 -5
  6. package/esm2020/src/di/injector_compatibility.mjs +6 -16
  7. package/esm2020/src/di/jit/util.mjs +3 -2
  8. package/esm2020/src/di/reflective_key.mjs +3 -2
  9. package/esm2020/src/errors.mjs +1 -1
  10. package/esm2020/src/i18n/locale_data_api.mjs +3 -2
  11. package/esm2020/src/render3/component.mjs +3 -2
  12. package/esm2020/src/render3/features/inherit_definition_feature.mjs +3 -5
  13. package/esm2020/src/render3/interfaces/renderer.mjs +10 -1
  14. package/esm2020/src/render3/jit/directive.mjs +20 -3
  15. package/esm2020/src/render3/jit/module.mjs +2 -1
  16. package/esm2020/src/render3/ng_module_ref.mjs +10 -2
  17. package/esm2020/src/render3/view_ref.mjs +3 -5
  18. package/esm2020/src/sanitization/sanitization.mjs +4 -9
  19. package/esm2020/src/version.mjs +1 -1
  20. package/esm2020/src/zone/ng_zone.mjs +5 -4
  21. package/esm2020/testing/src/logger.mjs +3 -3
  22. package/esm2020/testing/src/ng_zone_mock.mjs +3 -3
  23. package/esm2020/testing/src/r3_test_bed_compiler.mjs +30 -25
  24. package/fesm2015/core.mjs +96 -91
  25. package/fesm2015/core.mjs.map +1 -1
  26. package/fesm2015/testing.mjs +131 -126
  27. package/fesm2015/testing.mjs.map +1 -1
  28. package/fesm2020/core.mjs +96 -91
  29. package/fesm2020/core.mjs.map +1 -1
  30. package/fesm2020/testing.mjs +131 -126
  31. package/fesm2020/testing.mjs.map +1 -1
  32. package/index.d.ts +15 -7
  33. package/package.json +1 -1
  34. package/testing/index.d.ts +1 -1
  35. package/schematics/utils/schematics_prompt.d.ts +0 -17
  36. package/schematics/utils/schematics_prompt.js +0 -45
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v14.1.0-next.0
2
+ * @license Angular v14.1.0-next.3
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -862,6 +862,68 @@ const NG_INJ_DEF = getClosureSafeProperty({ ɵinj: getClosureSafeProperty });
862
862
  const NG_INJECTABLE_DEF = getClosureSafeProperty({ ngInjectableDef: getClosureSafeProperty });
863
863
  const NG_INJECTOR_DEF = getClosureSafeProperty({ ngInjectorDef: getClosureSafeProperty });
864
864
 
865
+ /**
866
+ * @license
867
+ * Copyright Google LLC All Rights Reserved.
868
+ *
869
+ * Use of this source code is governed by an MIT-style license that can be
870
+ * found in the LICENSE file at https://angular.io/license
871
+ */
872
+ /**
873
+ * Base URL for the error details page.
874
+ *
875
+ * Keep the files below in full sync:
876
+ * - packages/compiler-cli/src/ngtsc/diagnostics/src/error_details_base_url.ts
877
+ * - packages/core/src/error_details_base_url.ts
878
+ */
879
+ const ERROR_DETAILS_PAGE_BASE_URL = 'https://angular.io/errors';
880
+
881
+ /**
882
+ * @license
883
+ * Copyright Google LLC All Rights Reserved.
884
+ *
885
+ * Use of this source code is governed by an MIT-style license that can be
886
+ * found in the LICENSE file at https://angular.io/license
887
+ */
888
+ /**
889
+ * Class that represents a runtime error.
890
+ * Formats and outputs the error message in a consistent way.
891
+ *
892
+ * Example:
893
+ * ```
894
+ * throw new RuntimeError(
895
+ * RuntimeErrorCode.INJECTOR_ALREADY_DESTROYED,
896
+ * ngDevMode && 'Injector has already been destroyed.');
897
+ * ```
898
+ *
899
+ * Note: the `message` argument contains a descriptive error message as a string in development
900
+ * mode (when the `ngDevMode` is defined). In production mode (after tree-shaking pass), the
901
+ * `message` argument becomes `false`, thus we account for it in the typings and the runtime logic.
902
+ */
903
+ class RuntimeError extends Error {
904
+ constructor(code, message) {
905
+ super(formatRuntimeError(code, message));
906
+ this.code = code;
907
+ }
908
+ }
909
+ /**
910
+ * Called to format a runtime error.
911
+ * See additional info on the `message` argument type in the `RuntimeError` class description.
912
+ */
913
+ function formatRuntimeError(code, message) {
914
+ // Error code might be a negative number, which is a special marker that instructs the logic to
915
+ // generate a link to the error details page on angular.io.
916
+ const fullCode = `NG0${Math.abs(code)}`;
917
+ let errorMessage = `${fullCode}${message ? ': ' + message.trim() : ''}`;
918
+ if (ngDevMode && code < 0) {
919
+ const addPeriodSeparator = !errorMessage.match(/[.,;!?]$/);
920
+ const separator = addPeriodSeparator ? '.' : '';
921
+ errorMessage =
922
+ `${errorMessage}${separator} Find more at ${ERROR_DETAILS_PAGE_BASE_URL}/${fullCode}`;
923
+ }
924
+ return errorMessage;
925
+ }
926
+
865
927
  /**
866
928
  * @license
867
929
  * Copyright Google LLC All Rights Reserved.
@@ -1790,68 +1852,6 @@ function initNgDevMode() {
1790
1852
  return false;
1791
1853
  }
1792
1854
 
1793
- /**
1794
- * @license
1795
- * Copyright Google LLC All Rights Reserved.
1796
- *
1797
- * Use of this source code is governed by an MIT-style license that can be
1798
- * found in the LICENSE file at https://angular.io/license
1799
- */
1800
- /**
1801
- * Base URL for the error details page.
1802
- *
1803
- * Keep the files below in full sync:
1804
- * - packages/compiler-cli/src/ngtsc/diagnostics/src/error_details_base_url.ts
1805
- * - packages/core/src/error_details_base_url.ts
1806
- */
1807
- const ERROR_DETAILS_PAGE_BASE_URL = 'https://angular.io/errors';
1808
-
1809
- /**
1810
- * @license
1811
- * Copyright Google LLC All Rights Reserved.
1812
- *
1813
- * Use of this source code is governed by an MIT-style license that can be
1814
- * found in the LICENSE file at https://angular.io/license
1815
- */
1816
- /**
1817
- * Class that represents a runtime error.
1818
- * Formats and outputs the error message in a consistent way.
1819
- *
1820
- * Example:
1821
- * ```
1822
- * throw new RuntimeError(
1823
- * RuntimeErrorCode.INJECTOR_ALREADY_DESTROYED,
1824
- * ngDevMode && 'Injector has already been destroyed.');
1825
- * ```
1826
- *
1827
- * Note: the `message` argument contains a descriptive error message as a string in development
1828
- * mode (when the `ngDevMode` is defined). In production mode (after tree-shaking pass), the
1829
- * `message` argument becomes `false`, thus we account for it in the typings and the runtime logic.
1830
- */
1831
- class RuntimeError extends Error {
1832
- constructor(code, message) {
1833
- super(formatRuntimeError(code, message));
1834
- this.code = code;
1835
- }
1836
- }
1837
- /**
1838
- * Called to format a runtime error.
1839
- * See additional info on the `message` argument type in the `RuntimeError` class description.
1840
- */
1841
- function formatRuntimeError(code, message) {
1842
- // Error code might be a negative number, which is a special marker that instructs the logic to
1843
- // generate a link to the error details page on angular.io.
1844
- const fullCode = `NG0${Math.abs(code)}`;
1845
- let errorMessage = `${fullCode}${message ? ': ' + message.trim() : ''}`;
1846
- if (ngDevMode && code < 0) {
1847
- const addPeriodSeparator = !errorMessage.match(/[.,;!?]$/);
1848
- const separator = addPeriodSeparator ? '.' : '';
1849
- errorMessage =
1850
- `${errorMessage}${separator} Find more at ${ERROR_DETAILS_PAGE_BASE_URL}/${fullCode}`;
1851
- }
1852
- return errorMessage;
1853
- }
1854
-
1855
1855
  /**
1856
1856
  * @license
1857
1857
  * Copyright Google LLC All Rights Reserved.
@@ -2045,10 +2045,8 @@ function setCurrentInjector(injector) {
2045
2045
  }
2046
2046
  function injectInjectorOnly(token, flags = InjectFlags.Default) {
2047
2047
  if (_currentInjector === undefined) {
2048
- const errorMessage = (typeof ngDevMode === 'undefined' || ngDevMode) ?
2049
- `inject() must be called from an injection context (a constructor, a factory function or a field initializer)` :
2050
- '';
2051
- throw new RuntimeError(-203 /* RuntimeErrorCode.MISSING_INJECTION_CONTEXT */, errorMessage);
2048
+ throw new RuntimeError(-203 /* RuntimeErrorCode.MISSING_INJECTION_CONTEXT */, ngDevMode &&
2049
+ `inject() must be called from an injection context (a constructor, a factory function or a field initializer)`);
2052
2050
  }
2053
2051
  else if (_currentInjector === null) {
2054
2052
  return injectRootLimpMode(token, undefined, flags);
@@ -2064,22 +2062,17 @@ function ɵɵinject(token, flags = InjectFlags.Default) {
2064
2062
  * Throws an error indicating that a factory function could not be generated by the compiler for a
2065
2063
  * particular class.
2066
2064
  *
2067
- * This instruction allows the actual error message to be optimized away when ngDevMode is turned
2068
- * off, saving bytes of generated code while still providing a good experience in dev mode.
2069
- *
2070
2065
  * The name of the class is not mentioned here, but will be in the generated factory function name
2071
2066
  * and thus in the stack trace.
2072
2067
  *
2073
2068
  * @codeGenApi
2074
2069
  */
2075
2070
  function ɵɵinvalidFactoryDep(index) {
2076
- const msg = ngDevMode ?
2071
+ throw new RuntimeError(202 /* RuntimeErrorCode.INVALID_FACTORY_DEPENDENCY */, ngDevMode &&
2077
2072
  `This constructor is not compatible with Angular Dependency Injection because its dependency at index ${index} of the parameter list is invalid.
2078
2073
  This can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.
2079
2074
 
2080
- Please check that 1) the type for the parameter at index ${index} is correct and 2) the correct Angular decorators are defined for this class and its ancestors.` :
2081
- 'invalid';
2082
- throw new Error(msg);
2075
+ Please check that 1) the type for the parameter at index ${index} is correct and 2) the correct Angular decorators are defined for this class and its ancestors.`);
2083
2076
  }
2084
2077
  /**
2085
2078
  * Injects a token from the currently active injector.
@@ -2154,10 +2147,7 @@ function injectArgs(types) {
2154
2147
  const arg = resolveForwardRef(types[i]);
2155
2148
  if (Array.isArray(arg)) {
2156
2149
  if (arg.length === 0) {
2157
- const errorMessage = (typeof ngDevMode === 'undefined' || ngDevMode) ?
2158
- 'Arguments array must have arguments.' :
2159
- '';
2160
- throw new RuntimeError(900 /* RuntimeErrorCode.INVALID_DIFFER_INPUT */, errorMessage);
2150
+ throw new RuntimeError(900 /* RuntimeErrorCode.INVALID_DIFFER_INPUT */, ngDevMode && 'Arguments array must have arguments.');
2161
2151
  }
2162
2152
  let type = undefined;
2163
2153
  let flags = InjectFlags.Default;
@@ -3271,8 +3261,17 @@ var RendererStyleFlags3;
3271
3261
  function isProceduralRenderer(renderer) {
3272
3262
  return !!(renderer.listen);
3273
3263
  }
3264
+ let renderer3Enabled = false;
3265
+ function enableRenderer3() {
3266
+ renderer3Enabled = true;
3267
+ }
3274
3268
  const domRendererFactory3 = {
3275
3269
  createRenderer: (hostElement, rendererType) => {
3270
+ if (!renderer3Enabled) {
3271
+ throw new Error(ngDevMode ?
3272
+ `Renderer3 is not supported. This problem is likely caused by some component in the hierarchy was constructed without a correct parent injector.` :
3273
+ 'Renderer3 disabled');
3274
+ }
3276
3275
  return getDocument();
3277
3276
  }
3278
3277
  };
@@ -5487,7 +5486,7 @@ function reflectDependency(dep) {
5487
5486
  }
5488
5487
  else if (param instanceof Attribute) {
5489
5488
  if (param.attributeName === undefined) {
5490
- throw new Error(`Attribute name must be defined.`);
5489
+ throw new RuntimeError(204 /* RuntimeErrorCode.INVALID_INJECTION_TOKEN */, ngDevMode && `Attribute name must be defined.`);
5491
5490
  }
5492
5491
  meta.attribute = param.attributeName;
5493
5492
  }
@@ -6489,10 +6488,8 @@ function ɵɵsanitizeResourceUrl(unsafeResourceUrl) {
6489
6488
  if (allowSanitizationBypassAndThrow(unsafeResourceUrl, "ResourceURL" /* BypassType.ResourceUrl */)) {
6490
6489
  return trustedScriptURLFromStringBypass(unwrapSafeValue(unsafeResourceUrl));
6491
6490
  }
6492
- const errorMessage = (typeof ngDevMode === 'undefined' || ngDevMode) ?
6493
- 'unsafe value used in a resource URL context (see https://g.co/ng/security#xss)' :
6494
- '';
6495
- throw new RuntimeError(904 /* RuntimeErrorCode.UNSAFE_VALUE_IN_RESOURCE_URL */, errorMessage);
6491
+ throw new RuntimeError(904 /* RuntimeErrorCode.UNSAFE_VALUE_IN_RESOURCE_URL */, ngDevMode &&
6492
+ 'unsafe value used in a resource URL context (see https://g.co/ng/security#xss)');
6496
6493
  }
6497
6494
  /**
6498
6495
  * A `script` sanitizer which only lets trusted javascript through.
@@ -6514,10 +6511,7 @@ function ɵɵsanitizeScript(unsafeScript) {
6514
6511
  if (allowSanitizationBypassAndThrow(unsafeScript, "Script" /* BypassType.Script */)) {
6515
6512
  return trustedScriptFromStringBypass(unwrapSafeValue(unsafeScript));
6516
6513
  }
6517
- const errorMessage = (typeof ngDevMode === 'undefined' || ngDevMode) ?
6518
- 'unsafe value used in a script context' :
6519
- '';
6520
- throw new RuntimeError(905 /* RuntimeErrorCode.UNSAFE_VALUE_IN_SCRIPT */, errorMessage);
6514
+ throw new RuntimeError(905 /* RuntimeErrorCode.UNSAFE_VALUE_IN_SCRIPT */, ngDevMode && 'unsafe value used in a script context');
6521
6515
  }
6522
6516
  /**
6523
6517
  * A template tag function for promoting the associated constant literal to a
@@ -10128,7 +10122,7 @@ class ReflectiveKey {
10128
10122
  this.token = token;
10129
10123
  this.id = id;
10130
10124
  if (!token) {
10131
- throw new Error('Token must be defined!');
10125
+ throw new RuntimeError(208 /* RuntimeErrorCode.MISSING_INJECTION_TOKEN */, ngDevMode && 'Token must be defined!');
10132
10126
  }
10133
10127
  this.displayName = stringify(this.token);
10134
10128
  }
@@ -14198,6 +14192,7 @@ const NULL_INJECTOR = {
14198
14192
  function renderComponent(componentType /* Type as workaround for: Microsoft/TypeScript/issues/4881 */, opts = {}) {
14199
14193
  ngDevMode && publishDefaultGlobalUtils();
14200
14194
  ngDevMode && assertComponentType(componentType);
14195
+ enableRenderer3();
14201
14196
  const rendererFactory = opts.rendererFactory || domRendererFactory3;
14202
14197
  const sanitizer = opts.sanitizer || null;
14203
14198
  const componentDef = getComponentDef$1(componentType);
@@ -14385,10 +14380,8 @@ function ɵɵInheritDefinitionFeature(definition) {
14385
14380
  }
14386
14381
  else {
14387
14382
  if (superType.ɵcmp) {
14388
- const errorMessage = (typeof ngDevMode === 'undefined' || ngDevMode) ?
14389
- `Directives cannot inherit Components. Directive ${stringifyForError(definition.type)} is attempting to extend component ${stringifyForError(superType)}` :
14390
- '';
14391
- throw new RuntimeError(903 /* RuntimeErrorCode.INVALID_INHERITANCE */, errorMessage);
14383
+ throw new RuntimeError(903 /* RuntimeErrorCode.INVALID_INHERITANCE */, ngDevMode &&
14384
+ `Directives cannot inherit Components. Directive ${stringifyForError(definition.type)} is attempting to extend component ${stringifyForError(superType)}`);
14392
14385
  }
14393
14386
  // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
14394
14387
  superDef = superType.ɵdir;
@@ -19509,7 +19502,7 @@ function findLocaleData(locale) {
19509
19502
  if (parentLocale === 'en') {
19510
19503
  return localeEn;
19511
19504
  }
19512
- throw new Error(`Missing locale data for the locale "${locale}".`);
19505
+ throw new RuntimeError(701 /* RuntimeErrorCode.MISSING_LOCALE_DATA */, ngDevMode && `Missing locale data for the locale "${locale}".`);
19513
19506
  }
19514
19507
  /**
19515
19508
  * Retrieves the default currency code for the given locale.
@@ -22085,7 +22078,7 @@ class Version {
22085
22078
  /**
22086
22079
  * @publicApi
22087
22080
  */
22088
- const VERSION = new Version('14.1.0-next.0');
22081
+ const VERSION = new Version('14.1.0-next.3');
22089
22082
 
22090
22083
  /**
22091
22084
  * @license
@@ -22423,8 +22416,7 @@ class ViewRef {
22423
22416
  }
22424
22417
  attachToViewContainerRef() {
22425
22418
  if (this._appRef) {
22426
- const errorMessage = ngDevMode ? 'This view is already attached directly to the ApplicationRef!' : '';
22427
- throw new RuntimeError(902 /* RuntimeErrorCode.VIEW_ALREADY_ATTACHED */, errorMessage);
22419
+ throw new RuntimeError(902 /* RuntimeErrorCode.VIEW_ALREADY_ATTACHED */, ngDevMode && 'This view is already attached directly to the ApplicationRef!');
22428
22420
  }
22429
22421
  this._attachedToViewContainer = true;
22430
22422
  }
@@ -22434,8 +22426,7 @@ class ViewRef {
22434
22426
  }
22435
22427
  attachToAppRef(appRef) {
22436
22428
  if (this._attachedToViewContainer) {
22437
- const errorMessage = ngDevMode ? 'This view is already attached to a ViewContainer!' : '';
22438
- throw new RuntimeError(902 /* RuntimeErrorCode.VIEW_ALREADY_ATTACHED */, errorMessage);
22429
+ throw new RuntimeError(902 /* RuntimeErrorCode.VIEW_ALREADY_ATTACHED */, ngDevMode && 'This view is already attached to a ViewContainer!');
22439
22430
  }
22440
22431
  this._appRef = appRef;
22441
22432
  }
@@ -22756,10 +22747,18 @@ class EnvironmentNgModuleRefAdapter extends NgModuleRef$1 {
22756
22747
  /**
22757
22748
  * Create a new environment injector.
22758
22749
  *
22750
+ * Learn more about environment injectors in
22751
+ * [this guide](guide/standalone-components#environment-injectors).
22752
+ *
22753
+ * @param providers An array of providers.
22754
+ * @param parent A parent environment injector.
22755
+ * @param debugName An optional name for this injector instance, which will be used in error
22756
+ * messages.
22757
+ *
22759
22758
  * @publicApi
22760
22759
  * @developerPreview
22761
22760
  */
22762
- function createEnvironmentInjector(providers, parent = null, debugName = null) {
22761
+ function createEnvironmentInjector(providers, parent, debugName = null) {
22763
22762
  const adapter = new EnvironmentNgModuleRefAdapter(providers, parent, debugName);
22764
22763
  return adapter.injector;
22765
22764
  }
@@ -24713,7 +24712,7 @@ function patchModuleCompilation() {
24713
24712
  function isModuleWithProviders$1(value) {
24714
24713
  return value.ngModule !== undefined;
24715
24714
  }
24716
- function isNgModule(value) {
24715
+ function isNgModule$1(value) {
24717
24716
  return !!getNgModuleDef(value);
24718
24717
  }
24719
24718
 
@@ -25102,6 +25101,7 @@ function setScopeOnDeclaredComponents(moduleType, ngModule) {
25102
25101
  const declarations = flatten$1(ngModule.declarations || EMPTY_ARRAY);
25103
25102
  const transitiveScopes = transitiveScopesFor(moduleType);
25104
25103
  declarations.forEach(declaration => {
25104
+ declaration = resolveForwardRef(declaration);
25105
25105
  if (declaration.hasOwnProperty(NG_COMP_DEF)) {
25106
25106
  // A `ɵcmp` field exists - go ahead and patch the component directly.
25107
25107
  const component = declaration;
@@ -25135,7 +25135,7 @@ function patchComponentDefWithScope(componentDef, transitiveScopes) {
25135
25135
  * (either a NgModule or a standalone component / directive / pipe).
25136
25136
  */
25137
25137
  function transitiveScopesFor(type) {
25138
- if (isNgModule(type)) {
25138
+ if (isNgModule$1(type)) {
25139
25139
  return transitiveScopesForNgModule(type);
25140
25140
  }
25141
25141
  else if (isStandalone(type)) {
@@ -25219,7 +25219,7 @@ function transitiveScopesForNgModule(moduleType) {
25219
25219
  const exportedType = exported;
25220
25220
  // Either the type is a module, a pipe, or a component/directive (which may not have a
25221
25221
  // ɵcmp as it might be compiled asynchronously).
25222
- if (isNgModule(exportedType)) {
25222
+ if (isNgModule$1(exportedType)) {
25223
25223
  // When this module exports another, the exported module's exported directives and pipes are
25224
25224
  // added to both the compilation and exported scopes of this module.
25225
25225
  const exportedScope = transitiveScopesFor(exportedType);
@@ -25526,7 +25526,7 @@ class R3TestBedCompiler {
25526
25526
  // module's provider list.
25527
25527
  this.providerOverridesByModule = new Map();
25528
25528
  this.providerOverridesByToken = new Map();
25529
- this.moduleProvidersOverridden = new Set();
25529
+ this.scopesWithOverriddenProviders = new Set();
25530
25530
  this.testModuleRef = null;
25531
25531
  class DynamicTestModule {
25532
25532
  }
@@ -25694,7 +25694,7 @@ class R3TestBedCompiler {
25694
25694
  this.queueTypesFromModulesArray([moduleType]);
25695
25695
  this.compileTypesSync();
25696
25696
  this.applyProviderOverrides();
25697
- this.applyProviderOverridesToModule(moduleType);
25697
+ this.applyProviderOverridesInScope(moduleType);
25698
25698
  this.applyTransitiveScopes();
25699
25699
  }
25700
25700
  /**
@@ -25704,7 +25704,7 @@ class R3TestBedCompiler {
25704
25704
  this.queueTypesFromModulesArray([moduleType]);
25705
25705
  await this.compileComponents();
25706
25706
  this.applyProviderOverrides();
25707
- this.applyProviderOverridesToModule(moduleType);
25707
+ this.applyProviderOverridesInScope(moduleType);
25708
25708
  this.applyTransitiveScopes();
25709
25709
  }
25710
25710
  /**
@@ -25805,50 +25805,52 @@ class R3TestBedCompiler {
25805
25805
  this.seenComponents.clear();
25806
25806
  this.seenDirectives.clear();
25807
25807
  }
25808
- applyProviderOverridesToModule(moduleType) {
25809
- if (this.moduleProvidersOverridden.has(moduleType)) {
25808
+ /**
25809
+ * Applies provider overrides to a given type (either an NgModule or a standalone component)
25810
+ * and all imported NgModules and standalone components recursively.
25811
+ */
25812
+ applyProviderOverridesInScope(type) {
25813
+ const hasScope = isStandaloneComponent(type) || isNgModule(type);
25814
+ // The function can be re-entered recursively while inspecting dependencies
25815
+ // of an NgModule or a standalone component. Exit early if we come across a
25816
+ // type that can not have a scope (directive or pipe) or the type is already
25817
+ // processed earlier.
25818
+ if (!hasScope || this.scopesWithOverriddenProviders.has(type)) {
25810
25819
  return;
25811
25820
  }
25812
- this.moduleProvidersOverridden.add(moduleType);
25821
+ this.scopesWithOverriddenProviders.add(type);
25813
25822
  // NOTE: the line below triggers JIT compilation of the module injector,
25814
25823
  // which also invokes verification of the NgModule semantics, which produces
25815
25824
  // detailed error messages. The fact that the code relies on this line being
25816
25825
  // present here is suspicious and should be refactored in a way that the line
25817
25826
  // below can be moved (for ex. after an early exit check below).
25818
- const injectorDef = moduleType[ɵNG_INJ_DEF];
25827
+ const injectorDef = type[ɵNG_INJ_DEF];
25819
25828
  // No provider overrides, exit early.
25820
25829
  if (this.providerOverridesByToken.size === 0)
25821
25830
  return;
25822
- if (isStandaloneComponent(moduleType)) {
25831
+ if (isStandaloneComponent(type)) {
25823
25832
  // Visit all component dependencies and override providers there.
25824
- const def = getComponentDef(moduleType);
25833
+ const def = getComponentDef(type);
25825
25834
  const dependencies = maybeUnwrapFn(def.dependencies ?? []);
25826
25835
  for (const dependency of dependencies) {
25827
- // Proceed with examining dependencies recursively
25828
- // when a dependency is a standalone component or an NgModule.
25829
- // In AOT, the `dependencies` might also contain regular (NgModule-based)
25830
- // Component, Directive and Pipes. Skip them here, they are handled in a
25831
- // different location (in the `configureTestingModule` function).
25832
- if (isStandaloneComponent(dependency) || hasNgModuleDef(dependency)) {
25833
- this.applyProviderOverridesToModule(dependency);
25834
- }
25836
+ this.applyProviderOverridesInScope(dependency);
25835
25837
  }
25836
25838
  }
25837
25839
  else {
25838
25840
  const providers = [
25839
25841
  ...injectorDef.providers,
25840
- ...(this.providerOverridesByModule.get(moduleType) || [])
25842
+ ...(this.providerOverridesByModule.get(type) || [])
25841
25843
  ];
25842
25844
  if (this.hasProviderOverrides(providers)) {
25843
- this.maybeStoreNgDef(ɵNG_INJ_DEF, moduleType);
25844
- this.storeFieldOfDefOnType(moduleType, ɵNG_INJ_DEF, 'providers');
25845
+ this.maybeStoreNgDef(ɵNG_INJ_DEF, type);
25846
+ this.storeFieldOfDefOnType(type, ɵNG_INJ_DEF, 'providers');
25845
25847
  injectorDef.providers = this.getOverriddenProviders(providers);
25846
25848
  }
25847
25849
  // Apply provider overrides to imported modules recursively
25848
- const moduleDef = moduleType[ɵNG_MOD_DEF];
25850
+ const moduleDef = type[ɵNG_MOD_DEF];
25849
25851
  const imports = maybeUnwrapFn(moduleDef.imports);
25850
25852
  for (const importedModule of imports) {
25851
- this.applyProviderOverridesToModule(importedModule);
25853
+ this.applyProviderOverridesInScope(importedModule);
25852
25854
  }
25853
25855
  // Also override the providers on any ModuleWithProviders imports since those don't appear in
25854
25856
  // the moduleDef.
@@ -26085,7 +26087,7 @@ class R3TestBedCompiler {
26085
26087
  });
26086
26088
  });
26087
26089
  this.initialNgDefs.clear();
26088
- this.moduleProvidersOverridden.clear();
26090
+ this.scopesWithOverriddenProviders.clear();
26089
26091
  this.restoreComponentResolutionQueue();
26090
26092
  // Restore the locale ID to the default value, this shouldn't be necessary but we never know
26091
26093
  ɵsetLocaleId(ɵDEFAULT_LOCALE_ID);
@@ -26112,7 +26114,7 @@ class R3TestBedCompiler {
26112
26114
  providers,
26113
26115
  }, /* allowDuplicateDeclarationsInRoot */ true);
26114
26116
  // clang-format on
26115
- this.applyProviderOverridesToModule(this.testModuleType);
26117
+ this.applyProviderOverridesInScope(this.testModuleType);
26116
26118
  }
26117
26119
  get injector() {
26118
26120
  if (this._injector !== null) {
@@ -26212,6 +26214,9 @@ function getComponentDef(value) {
26212
26214
  function hasNgModuleDef(value) {
26213
26215
  return value.hasOwnProperty('ɵmod');
26214
26216
  }
26217
+ function isNgModule(value) {
26218
+ return hasNgModuleDef(value);
26219
+ }
26215
26220
  function maybeUnwrapFn(maybeFn) {
26216
26221
  return maybeFn instanceof Function ? maybeFn() : maybeFn;
26217
26222
  }