@angular/core 14.0.0 → 14.0.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 (40) hide show
  1. package/esm2020/src/application_ref.mjs +10 -24
  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 +4 -9
  7. package/esm2020/src/di/provider_collection.mjs +1 -1
  8. package/esm2020/src/error_handler.mjs +4 -7
  9. package/esm2020/src/errors.mjs +6 -3
  10. package/esm2020/src/render3/component.mjs +9 -9
  11. package/esm2020/src/render3/definition.mjs +4 -4
  12. package/esm2020/src/render3/features/inherit_definition_feature.mjs +3 -5
  13. package/esm2020/src/render3/features/standalone_feature.mjs +4 -4
  14. package/esm2020/src/render3/instructions/all.mjs +2 -2
  15. package/esm2020/src/render3/instructions/element.mjs +3 -79
  16. package/esm2020/src/render3/instructions/element_validation.mjs +264 -0
  17. package/esm2020/src/render3/instructions/shared.mjs +7 -184
  18. package/esm2020/src/render3/interfaces/definition.mjs +1 -1
  19. package/esm2020/src/render3/jit/directive.mjs +20 -3
  20. package/esm2020/src/render3/jit/module.mjs +3 -2
  21. package/esm2020/src/render3/pipe.mjs +20 -6
  22. package/esm2020/src/render3/state.mjs +1 -3
  23. package/esm2020/src/render3/view_ref.mjs +3 -5
  24. package/esm2020/src/sanitization/sanitization.mjs +4 -9
  25. package/esm2020/src/util/errors.mjs +1 -8
  26. package/esm2020/src/version.mjs +1 -1
  27. package/esm2020/testing/src/logger.mjs +3 -3
  28. package/esm2020/testing/src/ng_zone_mock.mjs +3 -3
  29. package/esm2020/testing/src/r3_test_bed_compiler.mjs +30 -25
  30. package/fesm2015/core.mjs +636 -644
  31. package/fesm2015/core.mjs.map +1 -1
  32. package/fesm2015/testing.mjs +633 -630
  33. package/fesm2015/testing.mjs.map +1 -1
  34. package/fesm2020/core.mjs +637 -645
  35. package/fesm2020/core.mjs.map +1 -1
  36. package/fesm2020/testing.mjs +634 -631
  37. package/fesm2020/testing.mjs.map +1 -1
  38. package/index.d.ts +7 -6
  39. package/package.json +1 -1
  40. package/testing/index.d.ts +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v14.0.0
2
+ * @license Angular v14.0.3
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -1842,9 +1842,12 @@ function formatRuntimeError(code, message) {
1842
1842
  // Error code might be a negative number, which is a special marker that instructs the logic to
1843
1843
  // generate a link to the error details page on angular.io.
1844
1844
  const fullCode = `NG0${Math.abs(code)}`;
1845
- let errorMessage = `${fullCode}${message ? ': ' + message : ''}`;
1845
+ let errorMessage = `${fullCode}${message ? ': ' + message.trim() : ''}`;
1846
1846
  if (ngDevMode && code < 0) {
1847
- errorMessage = `${errorMessage}. Find more at ${ERROR_DETAILS_PAGE_BASE_URL}/${fullCode}`;
1847
+ const addPeriodSeparator = !errorMessage.match(/[.,;!?]$/);
1848
+ const separator = addPeriodSeparator ? '.' : '';
1849
+ errorMessage =
1850
+ `${errorMessage}${separator} Find more at ${ERROR_DETAILS_PAGE_BASE_URL}/${fullCode}`;
1848
1851
  }
1849
1852
  return errorMessage;
1850
1853
  }
@@ -2042,10 +2045,8 @@ function setCurrentInjector(injector) {
2042
2045
  }
2043
2046
  function injectInjectorOnly(token, flags = InjectFlags.Default) {
2044
2047
  if (_currentInjector === undefined) {
2045
- const errorMessage = (typeof ngDevMode === 'undefined' || ngDevMode) ?
2046
- `inject() must be called from an injection context (a constructor, a factory function or a field initializer)` :
2047
- '';
2048
- 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)`);
2049
2050
  }
2050
2051
  else if (_currentInjector === null) {
2051
2052
  return injectRootLimpMode(token, undefined, flags);
@@ -2151,10 +2152,7 @@ function injectArgs(types) {
2151
2152
  const arg = resolveForwardRef(types[i]);
2152
2153
  if (Array.isArray(arg)) {
2153
2154
  if (arg.length === 0) {
2154
- const errorMessage = (typeof ngDevMode === 'undefined' || ngDevMode) ?
2155
- 'Arguments array must have arguments.' :
2156
- '';
2157
- throw new RuntimeError(900 /* RuntimeErrorCode.INVALID_DIFFER_INPUT */, errorMessage);
2155
+ throw new RuntimeError(900 /* RuntimeErrorCode.INVALID_DIFFER_INPUT */, ngDevMode && 'Arguments array must have arguments.');
2158
2156
  }
2159
2157
  let type = undefined;
2160
2158
  let flags = InjectFlags.Default;
@@ -2470,7 +2468,8 @@ const NG_ELEMENT_ID = getClosureSafeProperty({ __NG_ELEMENT_ID__: getClosureSafe
2470
2468
  * Use of this source code is governed by an MIT-style license that can be
2471
2469
  * found in the LICENSE file at https://angular.io/license
2472
2470
  */
2473
- let _renderCompCount = 0;
2471
+ /** Counter used to generate unique IDs for component definitions. */
2472
+ let componentDefCount = 0;
2474
2473
  /**
2475
2474
  * Create a component definition object.
2476
2475
  *
@@ -2523,7 +2522,7 @@ function ɵɵdefineComponent(componentDefinition) {
2523
2522
  features: componentDefinition.features || null,
2524
2523
  data: componentDefinition.data || {},
2525
2524
  encapsulation: componentDefinition.encapsulation || ViewEncapsulation.Emulated,
2526
- id: 'c',
2525
+ id: `c${componentDefCount++}`,
2527
2526
  styles: componentDefinition.styles || EMPTY_ARRAY,
2528
2527
  _: null,
2529
2528
  setInput: null,
@@ -2532,7 +2531,6 @@ function ɵɵdefineComponent(componentDefinition) {
2532
2531
  };
2533
2532
  const dependencies = componentDefinition.dependencies;
2534
2533
  const feature = componentDefinition.features;
2535
- def.id += _renderCompCount++;
2536
2534
  def.inputs = invertObject(componentDefinition.inputs, declaredInputs),
2537
2535
  def.outputs = invertObject(componentDefinition.outputs),
2538
2536
  feature && feature.forEach((fn) => fn(def));
@@ -3546,7 +3544,6 @@ function getLView() {
3546
3544
  function getTView() {
3547
3545
  return instructionState.lFrame.tView;
3548
3546
  }
3549
- // TODO(crisbeto): revert the @noinline once Closure issue is resolved.
3550
3547
  /**
3551
3548
  * Restores `contextViewData` to the given OpaqueViewState instance.
3552
3549
  *
@@ -3558,7 +3555,6 @@ function getTView() {
3558
3555
  * @returns Context of the restored OpaqueViewState instance.
3559
3556
  *
3560
3557
  * @codeGenApi
3561
- * @noinline Disable inlining due to issue with Closure in listeners inside embedded views.
3562
3558
  */
3563
3559
  function ɵɵrestoreView(viewToRestore) {
3564
3560
  instructionState.lFrame.contextLView = viewToRestore;
@@ -6488,10 +6484,8 @@ function ɵɵsanitizeResourceUrl(unsafeResourceUrl) {
6488
6484
  if (allowSanitizationBypassAndThrow(unsafeResourceUrl, "ResourceURL" /* BypassType.ResourceUrl */)) {
6489
6485
  return trustedScriptURLFromStringBypass(unwrapSafeValue(unsafeResourceUrl));
6490
6486
  }
6491
- const errorMessage = (typeof ngDevMode === 'undefined' || ngDevMode) ?
6492
- 'unsafe value used in a resource URL context (see https://g.co/ng/security#xss)' :
6493
- '';
6494
- throw new RuntimeError(904 /* RuntimeErrorCode.UNSAFE_VALUE_IN_RESOURCE_URL */, errorMessage);
6487
+ throw new RuntimeError(904 /* RuntimeErrorCode.UNSAFE_VALUE_IN_RESOURCE_URL */, ngDevMode &&
6488
+ 'unsafe value used in a resource URL context (see https://g.co/ng/security#xss)');
6495
6489
  }
6496
6490
  /**
6497
6491
  * A `script` sanitizer which only lets trusted javascript through.
@@ -6513,10 +6507,7 @@ function ɵɵsanitizeScript(unsafeScript) {
6513
6507
  if (allowSanitizationBypassAndThrow(unsafeScript, "Script" /* BypassType.Script */)) {
6514
6508
  return trustedScriptFromStringBypass(unwrapSafeValue(unsafeScript));
6515
6509
  }
6516
- const errorMessage = (typeof ngDevMode === 'undefined' || ngDevMode) ?
6517
- 'unsafe value used in a script context' :
6518
- '';
6519
- throw new RuntimeError(905 /* RuntimeErrorCode.UNSAFE_VALUE_IN_SCRIPT */, errorMessage);
6510
+ throw new RuntimeError(905 /* RuntimeErrorCode.UNSAFE_VALUE_IN_SCRIPT */, ngDevMode && 'unsafe value used in a script context');
6520
6511
  }
6521
6512
  /**
6522
6513
  * A template tag function for promoting the associated constant literal to a
@@ -6623,6 +6614,155 @@ function getSanitizer() {
6623
6614
  return lView && lView[SANITIZER];
6624
6615
  }
6625
6616
 
6617
+ /**
6618
+ * @license
6619
+ * Copyright Google LLC All Rights Reserved.
6620
+ *
6621
+ * Use of this source code is governed by an MIT-style license that can be
6622
+ * found in the LICENSE file at https://angular.io/license
6623
+ */
6624
+ const ERROR_ORIGINAL_ERROR = 'ngOriginalError';
6625
+ function wrappedError(message, originalError) {
6626
+ const msg = `${message} caused by: ${originalError instanceof Error ? originalError.message : originalError}`;
6627
+ const error = Error(msg);
6628
+ error[ERROR_ORIGINAL_ERROR] = originalError;
6629
+ return error;
6630
+ }
6631
+ function getOriginalError(error) {
6632
+ return error[ERROR_ORIGINAL_ERROR];
6633
+ }
6634
+
6635
+ /**
6636
+ * @license
6637
+ * Copyright Google LLC All Rights Reserved.
6638
+ *
6639
+ * Use of this source code is governed by an MIT-style license that can be
6640
+ * found in the LICENSE file at https://angular.io/license
6641
+ */
6642
+ /**
6643
+ * Provides a hook for centralized exception handling.
6644
+ *
6645
+ * The default implementation of `ErrorHandler` prints error messages to the `console`. To
6646
+ * intercept error handling, write a custom exception handler that replaces this default as
6647
+ * appropriate for your app.
6648
+ *
6649
+ * @usageNotes
6650
+ * ### Example
6651
+ *
6652
+ * ```
6653
+ * class MyErrorHandler implements ErrorHandler {
6654
+ * handleError(error) {
6655
+ * // do something with the exception
6656
+ * }
6657
+ * }
6658
+ *
6659
+ * @NgModule({
6660
+ * providers: [{provide: ErrorHandler, useClass: MyErrorHandler}]
6661
+ * })
6662
+ * class MyModule {}
6663
+ * ```
6664
+ *
6665
+ * @publicApi
6666
+ */
6667
+ class ErrorHandler {
6668
+ constructor() {
6669
+ /**
6670
+ * @internal
6671
+ */
6672
+ this._console = console;
6673
+ }
6674
+ handleError(error) {
6675
+ const originalError = this._findOriginalError(error);
6676
+ this._console.error('ERROR', error);
6677
+ if (originalError) {
6678
+ this._console.error('ORIGINAL ERROR', originalError);
6679
+ }
6680
+ }
6681
+ /** @internal */
6682
+ _findOriginalError(error) {
6683
+ let e = error && getOriginalError(error);
6684
+ while (e && getOriginalError(e)) {
6685
+ e = getOriginalError(e);
6686
+ }
6687
+ return e || null;
6688
+ }
6689
+ }
6690
+
6691
+ /**
6692
+ * @license
6693
+ * Copyright Google LLC All Rights Reserved.
6694
+ *
6695
+ * Use of this source code is governed by an MIT-style license that can be
6696
+ * found in the LICENSE file at https://angular.io/license
6697
+ */
6698
+ /**
6699
+ * Disallowed strings in the comment.
6700
+ *
6701
+ * see: https://html.spec.whatwg.org/multipage/syntax.html#comments
6702
+ */
6703
+ const COMMENT_DISALLOWED = /^>|^->|<!--|-->|--!>|<!-$/g;
6704
+ /**
6705
+ * Delimiter in the disallowed strings which needs to be wrapped with zero with character.
6706
+ */
6707
+ const COMMENT_DELIMITER = /(<|>)/;
6708
+ const COMMENT_DELIMITER_ESCAPED = '\u200B$1\u200B';
6709
+ /**
6710
+ * Escape the content of comment strings so that it can be safely inserted into a comment node.
6711
+ *
6712
+ * The issue is that HTML does not specify any way to escape comment end text inside the comment.
6713
+ * Consider: `<!-- The way you close a comment is with ">", and "->" at the beginning or by "-->" or
6714
+ * "--!>" at the end. -->`. Above the `"-->"` is meant to be text not an end to the comment. This
6715
+ * can be created programmatically through DOM APIs. (`<!--` are also disallowed.)
6716
+ *
6717
+ * see: https://html.spec.whatwg.org/multipage/syntax.html#comments
6718
+ *
6719
+ * ```
6720
+ * div.innerHTML = div.innerHTML
6721
+ * ```
6722
+ *
6723
+ * One would expect that the above code would be safe to do, but it turns out that because comment
6724
+ * text is not escaped, the comment may contain text which will prematurely close the comment
6725
+ * opening up the application for XSS attack. (In SSR we programmatically create comment nodes which
6726
+ * may contain such text and expect them to be safe.)
6727
+ *
6728
+ * This function escapes the comment text by looking for comment delimiters (`<` and `>`) and
6729
+ * surrounding them with `_>_` where the `_` is a zero width space `\u200B`. The result is that if a
6730
+ * comment contains any of the comment start/end delimiters (such as `<!--`, `-->` or `--!>`) the
6731
+ * text it will render normally but it will not cause the HTML parser to close/open the comment.
6732
+ *
6733
+ * @param value text to make safe for comment node by escaping the comment open/close character
6734
+ * sequence.
6735
+ */
6736
+ function escapeCommentText(value) {
6737
+ return value.replace(COMMENT_DISALLOWED, (text) => text.replace(COMMENT_DELIMITER, COMMENT_DELIMITER_ESCAPED));
6738
+ }
6739
+
6740
+ /**
6741
+ * @license
6742
+ * Copyright Google LLC All Rights Reserved.
6743
+ *
6744
+ * Use of this source code is governed by an MIT-style license that can be
6745
+ * found in the LICENSE file at https://angular.io/license
6746
+ */
6747
+ function normalizeDebugBindingName(name) {
6748
+ // Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
6749
+ name = camelCaseToDashCase(name.replace(/[$@]/g, '_'));
6750
+ return `ng-reflect-${name}`;
6751
+ }
6752
+ const CAMEL_CASE_REGEXP = /([A-Z])/g;
6753
+ function camelCaseToDashCase(input) {
6754
+ return input.replace(CAMEL_CASE_REGEXP, (...m) => '-' + m[1].toLowerCase());
6755
+ }
6756
+ function normalizeDebugBindingValue(value) {
6757
+ try {
6758
+ // Limit the size of the value as otherwise the DOM just gets polluted.
6759
+ return value != null ? value.toString().slice(0, 30) : value;
6760
+ }
6761
+ catch (e) {
6762
+ return '[ERROR] Exception while trying to serialize the value';
6763
+ }
6764
+ }
6765
+
6626
6766
  /**
6627
6767
  * @license
6628
6768
  * Copyright Google LLC All Rights Reserved.
@@ -6977,217 +7117,27 @@ function getDirectivesAtNodeIndex(nodeIndex, lView, includeComponents) {
6977
7117
  directiveStartIndex++;
6978
7118
  return lView.slice(directiveStartIndex, directiveEndIndex);
6979
7119
  }
6980
- function getComponentAtNodeIndex(nodeIndex, lView) {
6981
- const tNode = lView[TVIEW].data[nodeIndex];
6982
- let directiveStartIndex = tNode.directiveStart;
6983
- return tNode.flags & 2 /* TNodeFlags.isComponentHost */ ? lView[directiveStartIndex] : null;
6984
- }
6985
- /**
6986
- * Returns a map of local references (local reference name => element or directive instance) that
6987
- * exist on a given element.
6988
- */
6989
- function discoverLocalRefs(lView, nodeIndex) {
6990
- const tNode = lView[TVIEW].data[nodeIndex];
6991
- if (tNode && tNode.localNames) {
6992
- const result = {};
6993
- let localIndex = tNode.index + 1;
6994
- for (let i = 0; i < tNode.localNames.length; i += 2) {
6995
- result[tNode.localNames[i]] = lView[localIndex];
6996
- localIndex++;
6997
- }
6998
- return result;
6999
- }
7000
- return null;
7001
- }
7002
-
7003
- /**
7004
- * @license
7005
- * Copyright Google LLC All Rights Reserved.
7006
- *
7007
- * Use of this source code is governed by an MIT-style license that can be
7008
- * found in the LICENSE file at https://angular.io/license
7009
- */
7010
- const ERROR_ORIGINAL_ERROR = 'ngOriginalError';
7011
- const ERROR_LOGGER = 'ngErrorLogger';
7012
- function wrappedError(message, originalError) {
7013
- const msg = `${message} caused by: ${originalError instanceof Error ? originalError.message : originalError}`;
7014
- const error = Error(msg);
7015
- error[ERROR_ORIGINAL_ERROR] = originalError;
7016
- return error;
7017
- }
7018
- function getOriginalError(error) {
7019
- return error[ERROR_ORIGINAL_ERROR];
7020
- }
7021
- function getErrorLogger(error) {
7022
- return error && error[ERROR_LOGGER] || defaultErrorLogger;
7023
- }
7024
- function defaultErrorLogger(console, ...values) {
7025
- console.error(...values);
7026
- }
7027
-
7028
- /**
7029
- * @license
7030
- * Copyright Google LLC All Rights Reserved.
7031
- *
7032
- * Use of this source code is governed by an MIT-style license that can be
7033
- * found in the LICENSE file at https://angular.io/license
7034
- */
7035
- /**
7036
- * Provides a hook for centralized exception handling.
7037
- *
7038
- * The default implementation of `ErrorHandler` prints error messages to the `console`. To
7039
- * intercept error handling, write a custom exception handler that replaces this default as
7040
- * appropriate for your app.
7041
- *
7042
- * @usageNotes
7043
- * ### Example
7044
- *
7045
- * ```
7046
- * class MyErrorHandler implements ErrorHandler {
7047
- * handleError(error) {
7048
- * // do something with the exception
7049
- * }
7050
- * }
7051
- *
7052
- * @NgModule({
7053
- * providers: [{provide: ErrorHandler, useClass: MyErrorHandler}]
7054
- * })
7055
- * class MyModule {}
7056
- * ```
7057
- *
7058
- * @publicApi
7059
- */
7060
- class ErrorHandler {
7061
- constructor() {
7062
- /**
7063
- * @internal
7064
- */
7065
- this._console = console;
7066
- }
7067
- handleError(error) {
7068
- const originalError = this._findOriginalError(error);
7069
- // Note: Browser consoles show the place from where console.error was called.
7070
- // We can use this to give users additional information about the error.
7071
- const errorLogger = getErrorLogger(error);
7072
- errorLogger(this._console, `ERROR`, error);
7073
- if (originalError) {
7074
- errorLogger(this._console, `ORIGINAL ERROR`, originalError);
7075
- }
7076
- }
7077
- /** @internal */
7078
- _findOriginalError(error) {
7079
- let e = error && getOriginalError(error);
7080
- while (e && getOriginalError(e)) {
7081
- e = getOriginalError(e);
7082
- }
7083
- return e || null;
7084
- }
7085
- }
7086
-
7087
- /**
7088
- * @license
7089
- * Copyright Google LLC All Rights Reserved.
7090
- *
7091
- * Use of this source code is governed by an MIT-style license that can be
7092
- * found in the LICENSE file at https://angular.io/license
7093
- */
7094
- /**
7095
- * Defines a schema that allows an NgModule to contain the following:
7096
- * - Non-Angular elements named with dash case (`-`).
7097
- * - Element properties named with dash case (`-`).
7098
- * Dash case is the naming convention for custom elements.
7099
- *
7100
- * @publicApi
7101
- */
7102
- const CUSTOM_ELEMENTS_SCHEMA = {
7103
- name: 'custom-elements'
7104
- };
7105
- /**
7106
- * Defines a schema that allows any property on any element.
7107
- *
7108
- * This schema allows you to ignore the errors related to any unknown elements or properties in a
7109
- * template. The usage of this schema is generally discouraged because it prevents useful validation
7110
- * and may hide real errors in your template. Consider using the `CUSTOM_ELEMENTS_SCHEMA` instead.
7111
- *
7112
- * @publicApi
7113
- */
7114
- const NO_ERRORS_SCHEMA = {
7115
- name: 'no-errors-schema'
7116
- };
7117
-
7118
- /**
7119
- * @license
7120
- * Copyright Google LLC All Rights Reserved.
7121
- *
7122
- * Use of this source code is governed by an MIT-style license that can be
7123
- * found in the LICENSE file at https://angular.io/license
7124
- */
7125
- /**
7126
- * Disallowed strings in the comment.
7127
- *
7128
- * see: https://html.spec.whatwg.org/multipage/syntax.html#comments
7129
- */
7130
- const COMMENT_DISALLOWED = /^>|^->|<!--|-->|--!>|<!-$/g;
7131
- /**
7132
- * Delimiter in the disallowed strings which needs to be wrapped with zero with character.
7133
- */
7134
- const COMMENT_DELIMITER = /(<|>)/;
7135
- const COMMENT_DELIMITER_ESCAPED = '\u200B$1\u200B';
7136
- /**
7137
- * Escape the content of comment strings so that it can be safely inserted into a comment node.
7138
- *
7139
- * The issue is that HTML does not specify any way to escape comment end text inside the comment.
7140
- * Consider: `<!-- The way you close a comment is with ">", and "->" at the beginning or by "-->" or
7141
- * "--!>" at the end. -->`. Above the `"-->"` is meant to be text not an end to the comment. This
7142
- * can be created programmatically through DOM APIs. (`<!--` are also disallowed.)
7143
- *
7144
- * see: https://html.spec.whatwg.org/multipage/syntax.html#comments
7145
- *
7146
- * ```
7147
- * div.innerHTML = div.innerHTML
7148
- * ```
7149
- *
7150
- * One would expect that the above code would be safe to do, but it turns out that because comment
7151
- * text is not escaped, the comment may contain text which will prematurely close the comment
7152
- * opening up the application for XSS attack. (In SSR we programmatically create comment nodes which
7153
- * may contain such text and expect them to be safe.)
7154
- *
7155
- * This function escapes the comment text by looking for comment delimiters (`<` and `>`) and
7156
- * surrounding them with `_>_` where the `_` is a zero width space `\u200B`. The result is that if a
7157
- * comment contains any of the comment start/end delimiters (such as `<!--`, `-->` or `--!>`) the
7158
- * text it will render normally but it will not cause the HTML parser to close/open the comment.
7159
- *
7160
- * @param value text to make safe for comment node by escaping the comment open/close character
7161
- * sequence.
7162
- */
7163
- function escapeCommentText(value) {
7164
- return value.replace(COMMENT_DISALLOWED, (text) => text.replace(COMMENT_DELIMITER, COMMENT_DELIMITER_ESCAPED));
7165
- }
7166
-
7120
+ function getComponentAtNodeIndex(nodeIndex, lView) {
7121
+ const tNode = lView[TVIEW].data[nodeIndex];
7122
+ let directiveStartIndex = tNode.directiveStart;
7123
+ return tNode.flags & 2 /* TNodeFlags.isComponentHost */ ? lView[directiveStartIndex] : null;
7124
+ }
7167
7125
  /**
7168
- * @license
7169
- * Copyright Google LLC All Rights Reserved.
7170
- *
7171
- * Use of this source code is governed by an MIT-style license that can be
7172
- * found in the LICENSE file at https://angular.io/license
7126
+ * Returns a map of local references (local reference name => element or directive instance) that
7127
+ * exist on a given element.
7173
7128
  */
7174
- function normalizeDebugBindingName(name) {
7175
- // Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
7176
- name = camelCaseToDashCase(name.replace(/[$@]/g, '_'));
7177
- return `ng-reflect-${name}`;
7178
- }
7179
- const CAMEL_CASE_REGEXP = /([A-Z])/g;
7180
- function camelCaseToDashCase(input) {
7181
- return input.replace(CAMEL_CASE_REGEXP, (...m) => '-' + m[1].toLowerCase());
7182
- }
7183
- function normalizeDebugBindingValue(value) {
7184
- try {
7185
- // Limit the size of the value as otherwise the DOM just gets polluted.
7186
- return value != null ? value.toString().slice(0, 30) : value;
7187
- }
7188
- catch (e) {
7189
- return '[ERROR] Exception while trying to serialize the value';
7129
+ function discoverLocalRefs(lView, nodeIndex) {
7130
+ const tNode = lView[TVIEW].data[nodeIndex];
7131
+ if (tNode && tNode.localNames) {
7132
+ const result = {};
7133
+ let localIndex = tNode.index + 1;
7134
+ for (let i = 0; i < tNode.localNames.length; i += 2) {
7135
+ result[tNode.localNames[i]] = lView[localIndex];
7136
+ localIndex++;
7137
+ }
7138
+ return result;
7190
7139
  }
7140
+ return null;
7191
7141
  }
7192
7142
 
7193
7143
  /**
@@ -10654,113 +10604,402 @@ class ReflectiveInjector_ {
10654
10604
  return this.objs[i];
10655
10605
  }
10656
10606
  }
10657
- return UNDEFINED;
10607
+ return UNDEFINED;
10608
+ }
10609
+ /** @internal */
10610
+ _throwOrNull(key, notFoundValue) {
10611
+ if (notFoundValue !== THROW_IF_NOT_FOUND) {
10612
+ return notFoundValue;
10613
+ }
10614
+ else {
10615
+ throw noProviderError(this, key);
10616
+ }
10617
+ }
10618
+ /** @internal */
10619
+ _getByKeySelf(key, notFoundValue) {
10620
+ const obj = this._getObjByKeyId(key.id);
10621
+ return (obj !== UNDEFINED) ? obj : this._throwOrNull(key, notFoundValue);
10622
+ }
10623
+ /** @internal */
10624
+ _getByKeyDefault(key, notFoundValue, visibility) {
10625
+ let inj;
10626
+ if (visibility instanceof SkipSelf) {
10627
+ inj = this.parent;
10628
+ }
10629
+ else {
10630
+ inj = this;
10631
+ }
10632
+ while (inj instanceof ReflectiveInjector_) {
10633
+ const inj_ = inj;
10634
+ const obj = inj_._getObjByKeyId(key.id);
10635
+ if (obj !== UNDEFINED)
10636
+ return obj;
10637
+ inj = inj_.parent;
10638
+ }
10639
+ if (inj !== null) {
10640
+ return inj.get(key.token, notFoundValue);
10641
+ }
10642
+ else {
10643
+ return this._throwOrNull(key, notFoundValue);
10644
+ }
10645
+ }
10646
+ get displayName() {
10647
+ const providers = _mapProviders(this, (b) => ' "' + b.key.displayName + '" ')
10648
+ .join(', ');
10649
+ return `ReflectiveInjector(providers: [${providers}])`;
10650
+ }
10651
+ toString() {
10652
+ return this.displayName;
10653
+ }
10654
+ }
10655
+ ReflectiveInjector_.INJECTOR_KEY = ( /* @__PURE__ */ReflectiveKey.get(Injector));
10656
+ function _mapProviders(injector, fn) {
10657
+ const res = [];
10658
+ for (let i = 0; i < injector._providers.length; ++i) {
10659
+ res[i] = fn(injector.getProviderAtIndex(i));
10660
+ }
10661
+ return res;
10662
+ }
10663
+
10664
+ /**
10665
+ * @license
10666
+ * Copyright Google LLC All Rights Reserved.
10667
+ *
10668
+ * Use of this source code is governed by an MIT-style license that can be
10669
+ * found in the LICENSE file at https://angular.io/license
10670
+ */
10671
+
10672
+ /**
10673
+ * @license
10674
+ * Copyright Google LLC All Rights Reserved.
10675
+ *
10676
+ * Use of this source code is governed by an MIT-style license that can be
10677
+ * found in the LICENSE file at https://angular.io/license
10678
+ */
10679
+
10680
+ /**
10681
+ * @license
10682
+ * Copyright Google LLC All Rights Reserved.
10683
+ *
10684
+ * Use of this source code is governed by an MIT-style license that can be
10685
+ * found in the LICENSE file at https://angular.io/license
10686
+ */
10687
+ function ɵɵdirectiveInject(token, flags = InjectFlags.Default) {
10688
+ const lView = getLView();
10689
+ // Fall back to inject() if view hasn't been created. This situation can happen in tests
10690
+ // if inject utilities are used before bootstrapping.
10691
+ if (lView === null) {
10692
+ // Verify that we will not get into infinite loop.
10693
+ ngDevMode && assertInjectImplementationNotEqual(ɵɵdirectiveInject);
10694
+ return ɵɵinject(token, flags);
10695
+ }
10696
+ const tNode = getCurrentTNode();
10697
+ return getOrCreateInjectable(tNode, lView, resolveForwardRef(token), flags);
10698
+ }
10699
+ /**
10700
+ * Throws an error indicating that a factory function could not be generated by the compiler for a
10701
+ * particular class.
10702
+ *
10703
+ * This instruction allows the actual error message to be optimized away when ngDevMode is turned
10704
+ * off, saving bytes of generated code while still providing a good experience in dev mode.
10705
+ *
10706
+ * The name of the class is not mentioned here, but will be in the generated factory function name
10707
+ * and thus in the stack trace.
10708
+ *
10709
+ * @codeGenApi
10710
+ */
10711
+ function ɵɵinvalidFactory() {
10712
+ const msg = ngDevMode ? `This constructor was not compatible with Dependency Injection.` : 'invalid';
10713
+ throw new Error(msg);
10714
+ }
10715
+
10716
+ /**
10717
+ * @license
10718
+ * Copyright Google LLC All Rights Reserved.
10719
+ *
10720
+ * Use of this source code is governed by an MIT-style license that can be
10721
+ * found in the LICENSE file at https://angular.io/license
10722
+ */
10723
+ /**
10724
+ * Defines a schema that allows an NgModule to contain the following:
10725
+ * - Non-Angular elements named with dash case (`-`).
10726
+ * - Element properties named with dash case (`-`).
10727
+ * Dash case is the naming convention for custom elements.
10728
+ *
10729
+ * @publicApi
10730
+ */
10731
+ const CUSTOM_ELEMENTS_SCHEMA = {
10732
+ name: 'custom-elements'
10733
+ };
10734
+ /**
10735
+ * Defines a schema that allows any property on any element.
10736
+ *
10737
+ * This schema allows you to ignore the errors related to any unknown elements or properties in a
10738
+ * template. The usage of this schema is generally discouraged because it prevents useful validation
10739
+ * and may hide real errors in your template. Consider using the `CUSTOM_ELEMENTS_SCHEMA` instead.
10740
+ *
10741
+ * @publicApi
10742
+ */
10743
+ const NO_ERRORS_SCHEMA = {
10744
+ name: 'no-errors-schema'
10745
+ };
10746
+
10747
+ /**
10748
+ * @license
10749
+ * Copyright Google LLC All Rights Reserved.
10750
+ *
10751
+ * Use of this source code is governed by an MIT-style license that can be
10752
+ * found in the LICENSE file at https://angular.io/license
10753
+ */
10754
+ let shouldThrowErrorOnUnknownElement = false;
10755
+ /**
10756
+ * Sets a strict mode for JIT-compiled components to throw an error on unknown elements,
10757
+ * instead of just logging the error.
10758
+ * (for AOT-compiled ones this check happens at build time).
10759
+ */
10760
+ function ɵsetUnknownElementStrictMode(shouldThrow) {
10761
+ shouldThrowErrorOnUnknownElement = shouldThrow;
10762
+ }
10763
+ /**
10764
+ * Gets the current value of the strict mode.
10765
+ */
10766
+ function ɵgetUnknownElementStrictMode() {
10767
+ return shouldThrowErrorOnUnknownElement;
10768
+ }
10769
+ let shouldThrowErrorOnUnknownProperty = false;
10770
+ /**
10771
+ * Sets a strict mode for JIT-compiled components to throw an error on unknown properties,
10772
+ * instead of just logging the error.
10773
+ * (for AOT-compiled ones this check happens at build time).
10774
+ */
10775
+ function ɵsetUnknownPropertyStrictMode(shouldThrow) {
10776
+ shouldThrowErrorOnUnknownProperty = shouldThrow;
10777
+ }
10778
+ /**
10779
+ * Gets the current value of the strict mode.
10780
+ */
10781
+ function ɵgetUnknownPropertyStrictMode() {
10782
+ return shouldThrowErrorOnUnknownProperty;
10783
+ }
10784
+ /**
10785
+ * Validates that the element is known at runtime and produces
10786
+ * an error if it's not the case.
10787
+ * This check is relevant for JIT-compiled components (for AOT-compiled
10788
+ * ones this check happens at build time).
10789
+ *
10790
+ * The element is considered known if either:
10791
+ * - it's a known HTML element
10792
+ * - it's a known custom element
10793
+ * - the element matches any directive
10794
+ * - the element is allowed by one of the schemas
10795
+ *
10796
+ * @param element Element to validate
10797
+ * @param lView An `LView` that represents a current component that is being rendered
10798
+ * @param tagName Name of the tag to check
10799
+ * @param schemas Array of schemas
10800
+ * @param hasDirectives Boolean indicating that the element matches any directive
10801
+ */
10802
+ function validateElementIsKnown(element, lView, tagName, schemas, hasDirectives) {
10803
+ // If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
10804
+ // mode where this check happens at compile time. In JIT mode, `schemas` is always present and
10805
+ // defined as an array (as an empty array in case `schemas` field is not defined) and we should
10806
+ // execute the check below.
10807
+ if (schemas === null)
10808
+ return;
10809
+ // If the element matches any directive, it's considered as valid.
10810
+ if (!hasDirectives && tagName !== null) {
10811
+ // The element is unknown if it's an instance of HTMLUnknownElement, or it isn't registered
10812
+ // as a custom element. Note that unknown elements with a dash in their name won't be instances
10813
+ // of HTMLUnknownElement in browsers that support web components.
10814
+ const isUnknown =
10815
+ // Note that we can't check for `typeof HTMLUnknownElement === 'function'`,
10816
+ // because while most browsers return 'function', IE returns 'object'.
10817
+ (typeof HTMLUnknownElement !== 'undefined' && HTMLUnknownElement &&
10818
+ element instanceof HTMLUnknownElement) ||
10819
+ (typeof customElements !== 'undefined' && tagName.indexOf('-') > -1 &&
10820
+ !customElements.get(tagName));
10821
+ if (isUnknown && !matchingSchemas(schemas, tagName)) {
10822
+ const isHostStandalone = isHostComponentStandalone(lView);
10823
+ const templateLocation = getTemplateLocationDetails(lView);
10824
+ const schemas = `'${isHostStandalone ? '@Component' : '@NgModule'}.schemas'`;
10825
+ let message = `'${tagName}' is not a known element${templateLocation}:\n`;
10826
+ message += `1. If '${tagName}' is an Angular component, then verify that it is ${isHostStandalone ? 'included in the \'@Component.imports\' of this component' :
10827
+ 'a part of an @NgModule where this component is declared'}.\n`;
10828
+ if (tagName && tagName.indexOf('-') > -1) {
10829
+ message +=
10830
+ `2. If '${tagName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the ${schemas} of this component to suppress this message.`;
10831
+ }
10832
+ else {
10833
+ message +=
10834
+ `2. To allow any element add 'NO_ERRORS_SCHEMA' to the ${schemas} of this component.`;
10835
+ }
10836
+ if (shouldThrowErrorOnUnknownElement) {
10837
+ throw new RuntimeError(304 /* RuntimeErrorCode.UNKNOWN_ELEMENT */, message);
10838
+ }
10839
+ else {
10840
+ console.error(formatRuntimeError(304 /* RuntimeErrorCode.UNKNOWN_ELEMENT */, message));
10841
+ }
10842
+ }
10658
10843
  }
10659
- /** @internal */
10660
- _throwOrNull(key, notFoundValue) {
10661
- if (notFoundValue !== THROW_IF_NOT_FOUND) {
10662
- return notFoundValue;
10663
- }
10664
- else {
10665
- throw noProviderError(this, key);
10666
- }
10844
+ }
10845
+ /**
10846
+ * Validates that the property of the element is known at runtime and returns
10847
+ * false if it's not the case.
10848
+ * This check is relevant for JIT-compiled components (for AOT-compiled
10849
+ * ones this check happens at build time).
10850
+ *
10851
+ * The property is considered known if either:
10852
+ * - it's a known property of the element
10853
+ * - the element is allowed by one of the schemas
10854
+ * - the property is used for animations
10855
+ *
10856
+ * @param element Element to validate
10857
+ * @param propName Name of the property to check
10858
+ * @param tagName Name of the tag hosting the property
10859
+ * @param schemas Array of schemas
10860
+ */
10861
+ function isPropertyValid(element, propName, tagName, schemas) {
10862
+ // If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
10863
+ // mode where this check happens at compile time. In JIT mode, `schemas` is always present and
10864
+ // defined as an array (as an empty array in case `schemas` field is not defined) and we should
10865
+ // execute the check below.
10866
+ if (schemas === null)
10867
+ return true;
10868
+ // The property is considered valid if the element matches the schema, it exists on the element,
10869
+ // or it is synthetic, and we are in a browser context (web worker nodes should be skipped).
10870
+ if (matchingSchemas(schemas, tagName) || propName in element || isAnimationProp(propName)) {
10871
+ return true;
10667
10872
  }
10668
- /** @internal */
10669
- _getByKeySelf(key, notFoundValue) {
10670
- const obj = this._getObjByKeyId(key.id);
10671
- return (obj !== UNDEFINED) ? obj : this._throwOrNull(key, notFoundValue);
10873
+ // Note: `typeof Node` returns 'function' in most browsers, but on IE it is 'object' so we
10874
+ // need to account for both here, while being careful with `typeof null` also returning 'object'.
10875
+ return typeof Node === 'undefined' || Node === null || !(element instanceof Node);
10876
+ }
10877
+ /**
10878
+ * Logs or throws an error that a property is not supported on an element.
10879
+ *
10880
+ * @param propName Name of the invalid property
10881
+ * @param tagName Name of the tag hosting the property
10882
+ * @param nodeType Type of the node hosting the property
10883
+ * @param lView An `LView` that represents a current component
10884
+ */
10885
+ function handleUnknownPropertyError(propName, tagName, nodeType, lView) {
10886
+ // Special-case a situation when a structural directive is applied to
10887
+ // an `<ng-template>` element, for example: `<ng-template *ngIf="true">`.
10888
+ // In this case the compiler generates the `ɵɵtemplate` instruction with
10889
+ // the `null` as the tagName. The directive matching logic at runtime relies
10890
+ // on this effect (see `isInlineTemplate`), thus using the 'ng-template' as
10891
+ // a default value of the `tNode.value` is not feasible at this moment.
10892
+ if (!tagName && nodeType === 4 /* TNodeType.Container */) {
10893
+ tagName = 'ng-template';
10672
10894
  }
10673
- /** @internal */
10674
- _getByKeyDefault(key, notFoundValue, visibility) {
10675
- let inj;
10676
- if (visibility instanceof SkipSelf) {
10677
- inj = this.parent;
10678
- }
10679
- else {
10680
- inj = this;
10681
- }
10682
- while (inj instanceof ReflectiveInjector_) {
10683
- const inj_ = inj;
10684
- const obj = inj_._getObjByKeyId(key.id);
10685
- if (obj !== UNDEFINED)
10686
- return obj;
10687
- inj = inj_.parent;
10688
- }
10689
- if (inj !== null) {
10690
- return inj.get(key.token, notFoundValue);
10895
+ const isHostStandalone = isHostComponentStandalone(lView);
10896
+ const templateLocation = getTemplateLocationDetails(lView);
10897
+ let message = `Can't bind to '${propName}' since it isn't a known property of '${tagName}'${templateLocation}.`;
10898
+ const schemas = `'${isHostStandalone ? '@Component' : '@NgModule'}.schemas'`;
10899
+ const importLocation = isHostStandalone ?
10900
+ 'included in the \'@Component.imports\' of this component' :
10901
+ 'a part of an @NgModule where this component is declared';
10902
+ if (KNOWN_CONTROL_FLOW_DIRECTIVES.has(propName)) {
10903
+ // Most likely this is a control flow directive (such as `*ngIf`) used in
10904
+ // a template, but the `CommonModule` is not imported.
10905
+ message += `\nIf the '${propName}' is an Angular control flow directive, ` +
10906
+ `please make sure that the 'CommonModule' is ${importLocation}.`;
10907
+ }
10908
+ else {
10909
+ // May be an Angular component, which is not imported/declared?
10910
+ message += `\n1. If '${tagName}' is an Angular component and it has the ` +
10911
+ `'${propName}' input, then verify that it is ${importLocation}.`;
10912
+ // May be a Web Component?
10913
+ if (tagName && tagName.indexOf('-') > -1) {
10914
+ message += `\n2. If '${tagName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' ` +
10915
+ `to the ${schemas} of this component to suppress this message.`;
10916
+ message += `\n3. To allow any property add 'NO_ERRORS_SCHEMA' to ` +
10917
+ `the ${schemas} of this component.`;
10691
10918
  }
10692
10919
  else {
10693
- return this._throwOrNull(key, notFoundValue);
10920
+ // If it's expected, the error can be suppressed by the `NO_ERRORS_SCHEMA` schema.
10921
+ message += `\n2. To allow any property add 'NO_ERRORS_SCHEMA' to ` +
10922
+ `the ${schemas} of this component.`;
10694
10923
  }
10695
10924
  }
10696
- get displayName() {
10697
- const providers = _mapProviders(this, (b) => ' "' + b.key.displayName + '" ')
10698
- .join(', ');
10699
- return `ReflectiveInjector(providers: [${providers}])`;
10700
- }
10701
- toString() {
10702
- return this.displayName;
10925
+ if (shouldThrowErrorOnUnknownProperty) {
10926
+ throw new RuntimeError(303 /* RuntimeErrorCode.UNKNOWN_BINDING */, message);
10703
10927
  }
10704
- }
10705
- ReflectiveInjector_.INJECTOR_KEY = ( /* @__PURE__ */ReflectiveKey.get(Injector));
10706
- function _mapProviders(injector, fn) {
10707
- const res = [];
10708
- for (let i = 0; i < injector._providers.length; ++i) {
10709
- res[i] = fn(injector.getProviderAtIndex(i));
10928
+ else {
10929
+ console.error(formatRuntimeError(303 /* RuntimeErrorCode.UNKNOWN_BINDING */, message));
10710
10930
  }
10711
- return res;
10712
10931
  }
10713
-
10714
10932
  /**
10715
- * @license
10716
- * Copyright Google LLC All Rights Reserved.
10933
+ * WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`)
10934
+ * and must **not** be used in production bundles. The function makes megamorphic reads, which might
10935
+ * be too slow for production mode and also it relies on the constructor function being available.
10717
10936
  *
10718
- * Use of this source code is governed by an MIT-style license that can be
10719
- * found in the LICENSE file at https://angular.io/license
10720
- */
10721
-
10722
- /**
10723
- * @license
10724
- * Copyright Google LLC All Rights Reserved.
10937
+ * Gets a reference to the host component def (where a current component is declared).
10725
10938
  *
10726
- * Use of this source code is governed by an MIT-style license that can be
10727
- * found in the LICENSE file at https://angular.io/license
10939
+ * @param lView An `LView` that represents a current component that is being rendered.
10728
10940
  */
10729
-
10941
+ function getDeclarationComponentDef(lView) {
10942
+ !ngDevMode && throwError('Must never be called in production mode');
10943
+ const declarationLView = lView[DECLARATION_COMPONENT_VIEW];
10944
+ const context = declarationLView[CONTEXT];
10945
+ // Unable to obtain a context.
10946
+ if (!context)
10947
+ return null;
10948
+ return context.constructor ? getComponentDef$1(context.constructor) : null;
10949
+ }
10730
10950
  /**
10731
- * @license
10732
- * Copyright Google LLC All Rights Reserved.
10951
+ * WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`)
10952
+ * and must **not** be used in production bundles. The function makes megamorphic reads, which might
10953
+ * be too slow for production mode.
10733
10954
  *
10734
- * Use of this source code is governed by an MIT-style license that can be
10735
- * found in the LICENSE file at https://angular.io/license
10955
+ * Checks if the current component is declared inside of a standalone component template.
10956
+ *
10957
+ * @param lView An `LView` that represents a current component that is being rendered.
10736
10958
  */
10737
- function ɵɵdirectiveInject(token, flags = InjectFlags.Default) {
10738
- const lView = getLView();
10739
- // Fall back to inject() if view hasn't been created. This situation can happen in tests
10740
- // if inject utilities are used before bootstrapping.
10741
- if (lView === null) {
10742
- // Verify that we will not get into infinite loop.
10743
- ngDevMode && assertInjectImplementationNotEqual(ɵɵdirectiveInject);
10744
- return ɵɵinject(token, flags);
10745
- }
10746
- const tNode = getCurrentTNode();
10747
- return getOrCreateInjectable(tNode, lView, resolveForwardRef(token), flags);
10959
+ function isHostComponentStandalone(lView) {
10960
+ !ngDevMode && throwError('Must never be called in production mode');
10961
+ const componentDef = getDeclarationComponentDef(lView);
10962
+ // Treat host component as non-standalone if we can't obtain the def.
10963
+ return !!componentDef?.standalone;
10748
10964
  }
10749
10965
  /**
10750
- * Throws an error indicating that a factory function could not be generated by the compiler for a
10751
- * particular class.
10752
- *
10753
- * This instruction allows the actual error message to be optimized away when ngDevMode is turned
10754
- * off, saving bytes of generated code while still providing a good experience in dev mode.
10966
+ * WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`)
10967
+ * and must **not** be used in production bundles. The function makes megamorphic reads, which might
10968
+ * be too slow for production mode.
10755
10969
  *
10756
- * The name of the class is not mentioned here, but will be in the generated factory function name
10757
- * and thus in the stack trace.
10970
+ * Constructs a string describing the location of the host component template. The function is used
10971
+ * in dev mode to produce error messages.
10758
10972
  *
10759
- * @codeGenApi
10973
+ * @param lView An `LView` that represents a current component that is being rendered.
10760
10974
  */
10761
- function ɵɵinvalidFactory() {
10762
- const msg = ngDevMode ? `This constructor was not compatible with Dependency Injection.` : 'invalid';
10763
- throw new Error(msg);
10975
+ function getTemplateLocationDetails(lView) {
10976
+ !ngDevMode && throwError('Must never be called in production mode');
10977
+ const hostComponentDef = getDeclarationComponentDef(lView);
10978
+ const componentClassName = hostComponentDef?.type?.name;
10979
+ return componentClassName ? ` (used in the '${componentClassName}' component template)` : '';
10980
+ }
10981
+ /**
10982
+ * The set of known control flow directives.
10983
+ * We use this set to produce a more precises error message with a note
10984
+ * that the `CommonModule` should also be included.
10985
+ */
10986
+ const KNOWN_CONTROL_FLOW_DIRECTIVES = new Set(['ngIf', 'ngFor', 'ngSwitch', 'ngSwitchCase', 'ngSwitchDefault']);
10987
+ /**
10988
+ * Returns true if the tag name is allowed by specified schemas.
10989
+ * @param schemas Array of schemas
10990
+ * @param tagName Name of the tag
10991
+ */
10992
+ function matchingSchemas(schemas, tagName) {
10993
+ if (schemas !== null) {
10994
+ for (let i = 0; i < schemas.length; i++) {
10995
+ const schema = schemas[i];
10996
+ if (schema === NO_ERRORS_SCHEMA ||
10997
+ schema === CUSTOM_ELEMENTS_SCHEMA && tagName && tagName.indexOf('-') > -1) {
10998
+ return true;
10999
+ }
11000
+ }
11001
+ }
11002
+ return false;
10764
11003
  }
10765
11004
 
10766
11005
  /**
@@ -11560,30 +11799,15 @@ class LContainerDebug {
11560
11799
  }
11561
11800
  get host() {
11562
11801
  return this._raw_lContainer[HOST];
11563
- }
11564
- get native() {
11565
- return this._raw_lContainer[NATIVE];
11566
- }
11567
- get next() {
11568
- return toDebug(this._raw_lContainer[NEXT]);
11569
- }
11570
- }
11571
-
11572
- let shouldThrowErrorOnUnknownProperty = false;
11573
- /**
11574
- * Sets a strict mode for JIT-compiled components to throw an error on unknown properties,
11575
- * instead of just logging the error.
11576
- * (for AOT-compiled ones this check happens at build time).
11577
- */
11578
- function ɵsetUnknownPropertyStrictMode(shouldThrow) {
11579
- shouldThrowErrorOnUnknownProperty = shouldThrow;
11580
- }
11581
- /**
11582
- * Gets the current value of the strict mode.
11583
- */
11584
- function ɵgetUnknownPropertyStrictMode() {
11585
- return shouldThrowErrorOnUnknownProperty;
11802
+ }
11803
+ get native() {
11804
+ return this._raw_lContainer[NATIVE];
11805
+ }
11806
+ get next() {
11807
+ return toDebug(this._raw_lContainer[NEXT]);
11808
+ }
11586
11809
  }
11810
+
11587
11811
  /**
11588
11812
  * A permanent marker promise which signifies that the current CD tree is
11589
11813
  * clean.
@@ -11742,55 +11966,6 @@ function createTNodeAtIndex(tView, index, type, name, attrs) {
11742
11966
  }
11743
11967
  return tNode;
11744
11968
  }
11745
- /**
11746
- * WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`)
11747
- * and must **not** be used in production bundles. The function makes megamorphic reads, which might
11748
- * be too slow for production mode and also it relies on the constructor function being available.
11749
- *
11750
- * Gets a reference to the host component def (where a current component is declared).
11751
- *
11752
- * @param lView An `LView` that represents a current component that is being rendered.
11753
- */
11754
- function getDeclarationComponentDef(lView) {
11755
- !ngDevMode && throwError('Must never be called in production mode');
11756
- const declarationLView = lView[DECLARATION_COMPONENT_VIEW];
11757
- const context = declarationLView[CONTEXT];
11758
- // Unable to obtain a context.
11759
- if (!context)
11760
- return null;
11761
- return context.constructor ? getComponentDef$1(context.constructor) : null;
11762
- }
11763
- /**
11764
- * WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`)
11765
- * and must **not** be used in production bundles. The function makes megamorphic reads, which might
11766
- * be too slow for production mode.
11767
- *
11768
- * Checks if the current component is declared inside of a standalone component template.
11769
- *
11770
- * @param lView An `LView` that represents a current component that is being rendered.
11771
- */
11772
- function isHostComponentStandalone(lView) {
11773
- !ngDevMode && throwError('Must never be called in production mode');
11774
- const componentDef = getDeclarationComponentDef(lView);
11775
- // Treat host component as non-standalone if we can't obtain the def.
11776
- return !!(componentDef?.standalone);
11777
- }
11778
- /**
11779
- * WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`)
11780
- * and must **not** be used in production bundles. The function makes megamorphic reads, which might
11781
- * be too slow for production mode.
11782
- *
11783
- * Constructs a string describing the location of the host component template. The function is used
11784
- * in dev mode to produce error messages.
11785
- *
11786
- * @param lView An `LView` that represents a current component that is being rendered.
11787
- */
11788
- function getTemplateLocationDetails(lView) {
11789
- !ngDevMode && throwError('Must never be called in production mode');
11790
- const hostComponentDef = getDeclarationComponentDef(lView);
11791
- const componentClassName = hostComponentDef?.type?.name;
11792
- return componentClassName ? ` (used in the '${componentClassName}' component template)` : '';
11793
- }
11794
11969
  /**
11795
11970
  * When elements are created dynamically after a view blueprint is created (e.g. through
11796
11971
  * i18nApply()), we need to adjust the blueprint for future
@@ -12457,10 +12632,8 @@ function elementPropertyInternal(tView, tNode, lView, propName, value, renderer,
12457
12632
  propName = mapPropName(propName);
12458
12633
  if (ngDevMode) {
12459
12634
  validateAgainstEventProperties(propName);
12460
- if (!validateProperty(element, tNode.value, propName, tView.schemas)) {
12461
- // Return here since we only log warnings for unknown properties.
12462
- handleUnknownPropertyError(propName, tNode, lView);
12463
- return;
12635
+ if (!isPropertyValid(element, propName, tNode.value, tView.schemas)) {
12636
+ handleUnknownPropertyError(propName, tNode.value, tNode.type, lView);
12464
12637
  }
12465
12638
  ngDevMode.rendererSetProperty++;
12466
12639
  }
@@ -12479,7 +12652,7 @@ function elementPropertyInternal(tView, tNode, lView, propName, value, renderer,
12479
12652
  // If the node is a container and the property didn't
12480
12653
  // match any of the inputs or schemas we should throw.
12481
12654
  if (ngDevMode && !matchingSchemas(tView.schemas, tNode.value)) {
12482
- handleUnknownPropertyError(propName, tNode, lView);
12655
+ handleUnknownPropertyError(propName, tNode.value, tNode.type, lView);
12483
12656
  }
12484
12657
  }
12485
12658
  }
@@ -12531,116 +12704,6 @@ function setNgReflectProperties(lView, element, type, dataValue, value) {
12531
12704
  }
12532
12705
  }
12533
12706
  }
12534
- /**
12535
- * Validates that the property of the element is known at runtime and returns
12536
- * false if it's not the case.
12537
- * This check is relevant for JIT-compiled components (for AOT-compiled
12538
- * ones this check happens at build time).
12539
- *
12540
- * The property is considered known if either:
12541
- * - it's a known property of the element
12542
- * - the element is allowed by one of the schemas
12543
- * - the property is used for animations
12544
- *
12545
- * @param element Element to validate
12546
- * @param tagName Name of the tag to check
12547
- * @param propName Name of the property to check
12548
- * @param schemas Array of schemas
12549
- */
12550
- function validateProperty(element, tagName, propName, schemas) {
12551
- // If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
12552
- // mode where this check happens at compile time. In JIT mode, `schemas` is always present and
12553
- // defined as an array (as an empty array in case `schemas` field is not defined) and we should
12554
- // execute the check below.
12555
- if (schemas === null)
12556
- return true;
12557
- // The property is considered valid if the element matches the schema, it exists on the element,
12558
- // or it is synthetic, and we are in a browser context (web worker nodes should be skipped).
12559
- if (matchingSchemas(schemas, tagName) || propName in element || isAnimationProp(propName)) {
12560
- return true;
12561
- }
12562
- // Note: `typeof Node` returns 'function' in most browsers, but on IE it is 'object' so we
12563
- // need to account for both here, while being careful with `typeof null` also returning 'object'.
12564
- return typeof Node === 'undefined' || Node === null || !(element instanceof Node);
12565
- }
12566
- /**
12567
- * Returns true if the tag name is allowed by specified schemas.
12568
- * @param schemas Array of schemas
12569
- * @param tagName Name of the tag
12570
- */
12571
- function matchingSchemas(schemas, tagName) {
12572
- if (schemas !== null) {
12573
- for (let i = 0; i < schemas.length; i++) {
12574
- const schema = schemas[i];
12575
- if (schema === NO_ERRORS_SCHEMA ||
12576
- schema === CUSTOM_ELEMENTS_SCHEMA && tagName && tagName.indexOf('-') > -1) {
12577
- return true;
12578
- }
12579
- }
12580
- }
12581
- return false;
12582
- }
12583
- /**
12584
- * The set of known control flow directives.
12585
- * We use this set to produce a more precises error message with a note
12586
- * that the `CommonModule` should also be included.
12587
- */
12588
- const KNOWN_CONTROL_FLOW_DIRECTIVES = new Set(['ngIf', 'ngFor', 'ngSwitch', 'ngSwitchCase', 'ngSwitchDefault']);
12589
- /**
12590
- * Logs or throws an error that a property is not supported on an element.
12591
- *
12592
- * @param propName Name of the invalid property.
12593
- * @param tNode A `TNode` that represents a current component that is being rendered.
12594
- * @param lView An `LView` that represents a current component that is being rendered.
12595
- */
12596
- function handleUnknownPropertyError(propName, tNode, lView) {
12597
- let tagName = tNode.value;
12598
- // Special-case a situation when a structural directive is applied to
12599
- // an `<ng-template>` element, for example: `<ng-template *ngIf="true">`.
12600
- // In this case the compiler generates the `ɵɵtemplate` instruction with
12601
- // the `null` as the tagName. The directive matching logic at runtime relies
12602
- // on this effect (see `isInlineTemplate`), thus using the 'ng-template' as
12603
- // a default value of the `tNode.value` is not feasible at this moment.
12604
- if (!tagName && tNode.type === 4 /* TNodeType.Container */) {
12605
- tagName = 'ng-template';
12606
- }
12607
- const isHostStandalone = isHostComponentStandalone(lView);
12608
- const templateLocation = getTemplateLocationDetails(lView);
12609
- let message = `Can't bind to '${propName}' since it isn't a known property of '${tagName}'${templateLocation}.`;
12610
- const schemas = `'${isHostStandalone ? '@Component' : '@NgModule'}.schemas'`;
12611
- const importLocation = isHostStandalone ?
12612
- 'included in the \'@Component.imports\' of this component' :
12613
- 'a part of an @NgModule where this component is declared';
12614
- if (KNOWN_CONTROL_FLOW_DIRECTIVES.has(propName)) {
12615
- // Most likely this is a control flow directive (such as `*ngIf`) used in
12616
- // a template, but the `CommonModule` is not imported.
12617
- message += `\nIf the '${propName}' is an Angular control flow directive, ` +
12618
- `please make sure that the 'CommonModule' is ${importLocation}.`;
12619
- }
12620
- else {
12621
- // May be an Angular component, which is not imported/declared?
12622
- message += `\n1. If '${tagName}' is an Angular component and it has the ` +
12623
- `'${propName}' input, then verify that it is ${importLocation}.`;
12624
- // May be a Web Component?
12625
- if (tagName && tagName.indexOf('-') > -1) {
12626
- message += `\n2. If '${tagName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' ` +
12627
- `to the ${schemas} of this component to suppress this message.`;
12628
- message += `\n3. To allow any property add 'NO_ERRORS_SCHEMA' to ` +
12629
- `the ${schemas} of this component.`;
12630
- }
12631
- else {
12632
- // If it's expected, the error can be suppressed by the `NO_ERRORS_SCHEMA` schema.
12633
- message += `\n2. To allow any property add 'NO_ERRORS_SCHEMA' to ` +
12634
- `the ${schemas} of this component.`;
12635
- }
12636
- }
12637
- if (shouldThrowErrorOnUnknownProperty) {
12638
- throw new RuntimeError(303 /* RuntimeErrorCode.UNKNOWN_BINDING */, message);
12639
- }
12640
- else {
12641
- console.error(formatRuntimeError(303 /* RuntimeErrorCode.UNKNOWN_BINDING */, message));
12642
- }
12643
- }
12644
12707
  /**
12645
12708
  * Instantiate a root component.
12646
12709
  */
@@ -14214,7 +14277,11 @@ function createRootComponent(componentView, componentDef, rootLView, rootContext
14214
14277
  const component = instantiateRootComponent(tView, rootLView, componentDef);
14215
14278
  rootContext.components.push(component);
14216
14279
  componentView[CONTEXT] = component;
14217
- hostFeatures && hostFeatures.forEach((feature) => feature(component, componentDef));
14280
+ if (hostFeatures !== null) {
14281
+ for (const feature of hostFeatures) {
14282
+ feature(component, componentDef);
14283
+ }
14284
+ }
14218
14285
  // We want to generate an empty QueryList for root content queries for backwards
14219
14286
  // compatibility with ViewEngine.
14220
14287
  if (componentDef.contentQueries) {
@@ -14255,13 +14322,10 @@ function createRootContext(scheduler, playerHandler) {
14255
14322
  * renderComponent(AppComponent, {hostFeatures: [LifecycleHooksFeature]});
14256
14323
  * ```
14257
14324
  */
14258
- function LifecycleHooksFeature(component, def) {
14259
- const lView = readPatchedLView(component);
14260
- ngDevMode && assertDefined(lView, 'LView is required');
14261
- const tView = lView[TVIEW];
14325
+ function LifecycleHooksFeature() {
14262
14326
  const tNode = getCurrentTNode();
14263
14327
  ngDevMode && assertDefined(tNode, 'TNode is required');
14264
- registerPostOrderHooks(tView, tNode);
14328
+ registerPostOrderHooks(getLView()[TVIEW], tNode);
14265
14329
  }
14266
14330
  /**
14267
14331
  * Wait on component until it is rendered.
@@ -14311,10 +14375,8 @@ function ɵɵInheritDefinitionFeature(definition) {
14311
14375
  }
14312
14376
  else {
14313
14377
  if (superType.ɵcmp) {
14314
- const errorMessage = (typeof ngDevMode === 'undefined' || ngDevMode) ?
14315
- `Directives cannot inherit Components. Directive ${stringifyForError(definition.type)} is attempting to extend component ${stringifyForError(superType)}` :
14316
- '';
14317
- throw new RuntimeError(903 /* RuntimeErrorCode.INVALID_INHERITANCE */, errorMessage);
14378
+ throw new RuntimeError(903 /* RuntimeErrorCode.INVALID_INHERITANCE */, ngDevMode &&
14379
+ `Directives cannot inherit Components. Directive ${stringifyForError(definition.type)} is attempting to extend component ${stringifyForError(superType)}`);
14318
14380
  }
14319
14381
  // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
14320
14382
  superDef = superType.ɵdir;
@@ -15396,21 +15458,6 @@ function setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isCla
15396
15458
  * Use of this source code is governed by an MIT-style license that can be
15397
15459
  * found in the LICENSE file at https://angular.io/license
15398
15460
  */
15399
- let shouldThrowErrorOnUnknownElement = false;
15400
- /**
15401
- * Sets a strict mode for JIT-compiled components to throw an error on unknown elements,
15402
- * instead of just logging the error.
15403
- * (for AOT-compiled ones this check happens at build time).
15404
- */
15405
- function ɵsetUnknownElementStrictMode(shouldThrow) {
15406
- shouldThrowErrorOnUnknownElement = shouldThrow;
15407
- }
15408
- /**
15409
- * Gets the current value of the strict mode.
15410
- */
15411
- function ɵgetUnknownElementStrictMode() {
15412
- return shouldThrowErrorOnUnknownElement;
15413
- }
15414
15461
  function elementStartFirstCreatePass(index, tView, lView, native, name, attrsIndex, localRefsIndex) {
15415
15462
  ngDevMode && assertFirstCreatePass(tView);
15416
15463
  ngDevMode && ngDevMode.firstCreatePass++;
@@ -15544,67 +15591,6 @@ function ɵɵelement(index, name, attrsIndex, localRefsIndex) {
15544
15591
  ɵɵelementEnd();
15545
15592
  return ɵɵelement;
15546
15593
  }
15547
- /**
15548
- * Validates that the element is known at runtime and produces
15549
- * an error if it's not the case.
15550
- * This check is relevant for JIT-compiled components (for AOT-compiled
15551
- * ones this check happens at build time).
15552
- *
15553
- * The element is considered known if either:
15554
- * - it's a known HTML element
15555
- * - it's a known custom element
15556
- * - the element matches any directive
15557
- * - the element is allowed by one of the schemas
15558
- *
15559
- * @param element Element to validate
15560
- * @param lView An `LView` that represents a current component that is being rendered.
15561
- * @param tagName Name of the tag to check
15562
- * @param schemas Array of schemas
15563
- * @param hasDirectives Boolean indicating that the element matches any directive
15564
- */
15565
- function validateElementIsKnown(element, lView, tagName, schemas, hasDirectives) {
15566
- // If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
15567
- // mode where this check happens at compile time. In JIT mode, `schemas` is always present and
15568
- // defined as an array (as an empty array in case `schemas` field is not defined) and we should
15569
- // execute the check below.
15570
- if (schemas === null)
15571
- return;
15572
- // If the element matches any directive, it's considered as valid.
15573
- if (!hasDirectives && tagName !== null) {
15574
- // The element is unknown if it's an instance of HTMLUnknownElement, or it isn't registered
15575
- // as a custom element. Note that unknown elements with a dash in their name won't be instances
15576
- // of HTMLUnknownElement in browsers that support web components.
15577
- const isUnknown =
15578
- // Note that we can't check for `typeof HTMLUnknownElement === 'function'`,
15579
- // because while most browsers return 'function', IE returns 'object'.
15580
- (typeof HTMLUnknownElement !== 'undefined' && HTMLUnknownElement &&
15581
- element instanceof HTMLUnknownElement) ||
15582
- (typeof customElements !== 'undefined' && tagName.indexOf('-') > -1 &&
15583
- !customElements.get(tagName));
15584
- if (isUnknown && !matchingSchemas(schemas, tagName)) {
15585
- const isHostStandalone = isHostComponentStandalone(lView);
15586
- const templateLocation = getTemplateLocationDetails(lView);
15587
- const schemas = `'${isHostStandalone ? '@Component' : '@NgModule'}.schemas'`;
15588
- let message = `'${tagName}' is not a known element${templateLocation}:\n`;
15589
- message += `1. If '${tagName}' is an Angular component, then verify that it is ${isHostStandalone ? 'included in the \'@Component.imports\' of this component' :
15590
- 'a part of an @NgModule where this component is declared'}.\n`;
15591
- if (tagName && tagName.indexOf('-') > -1) {
15592
- message +=
15593
- `2. If '${tagName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the ${schemas} of this component to suppress this message.`;
15594
- }
15595
- else {
15596
- message +=
15597
- `2. To allow any element add 'NO_ERRORS_SCHEMA' to the ${schemas} of this component.`;
15598
- }
15599
- if (shouldThrowErrorOnUnknownElement) {
15600
- throw new RuntimeError(304 /* RuntimeErrorCode.UNKNOWN_ELEMENT */, message);
15601
- }
15602
- else {
15603
- console.error(formatRuntimeError(304 /* RuntimeErrorCode.UNKNOWN_ELEMENT */, message));
15604
- }
15605
- }
15606
- }
15607
- }
15608
15594
 
15609
15595
  /**
15610
15596
  * @license
@@ -22087,7 +22073,7 @@ class Version {
22087
22073
  /**
22088
22074
  * @publicApi
22089
22075
  */
22090
- const VERSION = new Version('14.0.0');
22076
+ const VERSION = new Version('14.0.3');
22091
22077
 
22092
22078
  /**
22093
22079
  * @license
@@ -22425,8 +22411,7 @@ class ViewRef {
22425
22411
  }
22426
22412
  attachToViewContainerRef() {
22427
22413
  if (this._appRef) {
22428
- const errorMessage = ngDevMode ? 'This view is already attached directly to the ApplicationRef!' : '';
22429
- throw new RuntimeError(902 /* RuntimeErrorCode.VIEW_ALREADY_ATTACHED */, errorMessage);
22414
+ throw new RuntimeError(902 /* RuntimeErrorCode.VIEW_ALREADY_ATTACHED */, ngDevMode && 'This view is already attached directly to the ApplicationRef!');
22430
22415
  }
22431
22416
  this._attachedToViewContainer = true;
22432
22417
  }
@@ -22436,8 +22421,7 @@ class ViewRef {
22436
22421
  }
22437
22422
  attachToAppRef(appRef) {
22438
22423
  if (this._attachedToViewContainer) {
22439
- const errorMessage = ngDevMode ? 'This view is already attached to a ViewContainer!' : '';
22440
- throw new RuntimeError(902 /* RuntimeErrorCode.VIEW_ALREADY_ATTACHED */, errorMessage);
22424
+ throw new RuntimeError(902 /* RuntimeErrorCode.VIEW_ALREADY_ATTACHED */, ngDevMode && 'This view is already attached to a ViewContainer!');
22441
22425
  }
22442
22426
  this._appRef = appRef;
22443
22427
  }
@@ -22787,14 +22771,14 @@ class StandaloneService {
22787
22771
  if (!componentDef.standalone) {
22788
22772
  return null;
22789
22773
  }
22790
- if (!this.cachedInjectors.has(componentDef)) {
22774
+ if (!this.cachedInjectors.has(componentDef.id)) {
22791
22775
  const providers = internalImportProvidersFrom(false, componentDef.type);
22792
22776
  const standaloneInjector = providers.length > 0 ?
22793
22777
  createEnvironmentInjector([providers], this._injector, `Standalone[${componentDef.type.name}]`) :
22794
22778
  null;
22795
- this.cachedInjectors.set(componentDef, standaloneInjector);
22779
+ this.cachedInjectors.set(componentDef.id, standaloneInjector);
22796
22780
  }
22797
- return this.cachedInjectors.get(componentDef);
22781
+ return this.cachedInjectors.get(componentDef.id);
22798
22782
  }
22799
22783
  ngOnDestroy() {
22800
22784
  try {
@@ -23294,13 +23278,26 @@ function getPipeDef(name, registry) {
23294
23278
  }
23295
23279
  }
23296
23280
  if (ngDevMode) {
23297
- const lView = getLView();
23298
- const declarationLView = lView[DECLARATION_COMPONENT_VIEW];
23299
- const context = declarationLView[CONTEXT];
23300
- const component = context ? ` in the '${context.constructor.name}' component` : '';
23301
- throw new RuntimeError(-302 /* RuntimeErrorCode.PIPE_NOT_FOUND */, `The pipe '${name}' could not be found${component}!`);
23281
+ throw new RuntimeError(-302 /* RuntimeErrorCode.PIPE_NOT_FOUND */, getPipeNotFoundErrorMessage(name));
23302
23282
  }
23303
23283
  }
23284
+ /**
23285
+ * Generates a helpful error message for the user when a pipe is not found.
23286
+ *
23287
+ * @param name Name of the missing pipe
23288
+ * @returns The error message
23289
+ */
23290
+ function getPipeNotFoundErrorMessage(name) {
23291
+ const lView = getLView();
23292
+ const declarationLView = lView[DECLARATION_COMPONENT_VIEW];
23293
+ const context = declarationLView[CONTEXT];
23294
+ const hostIsStandalone = isHostComponentStandalone(lView);
23295
+ const componentInfoMessage = context ? ` in the '${context.constructor.name}' component` : '';
23296
+ const verifyMessage = `Verify that it is ${hostIsStandalone ? 'included in the \'@Component.imports\' of this component' :
23297
+ 'declared or imported in this module'}`;
23298
+ const errorMessage = `The pipe '${name}' could not be found${componentInfoMessage}. ${verifyMessage}`;
23299
+ return errorMessage;
23300
+ }
23304
23301
  /**
23305
23302
  * Invokes a pipe with 1 arguments.
23306
23303
  *
@@ -24702,7 +24699,7 @@ function patchModuleCompilation() {
24702
24699
  function isModuleWithProviders$1(value) {
24703
24700
  return value.ngModule !== undefined;
24704
24701
  }
24705
- function isNgModule(value) {
24702
+ function isNgModule$1(value) {
24706
24703
  return !!getNgModuleDef(value);
24707
24704
  }
24708
24705
 
@@ -25091,6 +25088,7 @@ function setScopeOnDeclaredComponents(moduleType, ngModule) {
25091
25088
  const declarations = flatten$1(ngModule.declarations || EMPTY_ARRAY);
25092
25089
  const transitiveScopes = transitiveScopesFor(moduleType);
25093
25090
  declarations.forEach(declaration => {
25091
+ declaration = resolveForwardRef(declaration);
25094
25092
  if (declaration.hasOwnProperty(NG_COMP_DEF)) {
25095
25093
  // A `ɵcmp` field exists - go ahead and patch the component directly.
25096
25094
  const component = declaration;
@@ -25121,10 +25119,10 @@ function patchComponentDefWithScope(componentDef, transitiveScopes) {
25121
25119
  }
25122
25120
  /**
25123
25121
  * Compute the pair of transitive scopes (compilation scope and exported scope) for a given type
25124
- * (eaither a NgModule or a standalone component / directive / pipe).
25122
+ * (either a NgModule or a standalone component / directive / pipe).
25125
25123
  */
25126
25124
  function transitiveScopesFor(type) {
25127
- if (isNgModule(type)) {
25125
+ if (isNgModule$1(type)) {
25128
25126
  return transitiveScopesForNgModule(type);
25129
25127
  }
25130
25128
  else if (isStandalone(type)) {
@@ -25208,7 +25206,7 @@ function transitiveScopesForNgModule(moduleType) {
25208
25206
  const exportedType = exported;
25209
25207
  // Either the type is a module, a pipe, or a component/directive (which may not have a
25210
25208
  // ɵcmp as it might be compiled asynchronously).
25211
- if (isNgModule(exportedType)) {
25209
+ if (isNgModule$1(exportedType)) {
25212
25210
  // When this module exports another, the exported module's exported directives and pipes are
25213
25211
  // added to both the compilation and exported scopes of this module.
25214
25212
  const exportedScope = transitiveScopesFor(exportedType);
@@ -25515,7 +25513,7 @@ class R3TestBedCompiler {
25515
25513
  // module's provider list.
25516
25514
  this.providerOverridesByModule = new Map();
25517
25515
  this.providerOverridesByToken = new Map();
25518
- this.moduleProvidersOverridden = new Set();
25516
+ this.scopesWithOverriddenProviders = new Set();
25519
25517
  this.testModuleRef = null;
25520
25518
  class DynamicTestModule {
25521
25519
  }
@@ -25683,7 +25681,7 @@ class R3TestBedCompiler {
25683
25681
  this.queueTypesFromModulesArray([moduleType]);
25684
25682
  this.compileTypesSync();
25685
25683
  this.applyProviderOverrides();
25686
- this.applyProviderOverridesToModule(moduleType);
25684
+ this.applyProviderOverridesInScope(moduleType);
25687
25685
  this.applyTransitiveScopes();
25688
25686
  }
25689
25687
  /**
@@ -25693,7 +25691,7 @@ class R3TestBedCompiler {
25693
25691
  this.queueTypesFromModulesArray([moduleType]);
25694
25692
  await this.compileComponents();
25695
25693
  this.applyProviderOverrides();
25696
- this.applyProviderOverridesToModule(moduleType);
25694
+ this.applyProviderOverridesInScope(moduleType);
25697
25695
  this.applyTransitiveScopes();
25698
25696
  }
25699
25697
  /**
@@ -25794,50 +25792,52 @@ class R3TestBedCompiler {
25794
25792
  this.seenComponents.clear();
25795
25793
  this.seenDirectives.clear();
25796
25794
  }
25797
- applyProviderOverridesToModule(moduleType) {
25798
- if (this.moduleProvidersOverridden.has(moduleType)) {
25795
+ /**
25796
+ * Applies provider overrides to a given type (either an NgModule or a standalone component)
25797
+ * and all imported NgModules and standalone components recursively.
25798
+ */
25799
+ applyProviderOverridesInScope(type) {
25800
+ const hasScope = isStandaloneComponent(type) || isNgModule(type);
25801
+ // The function can be re-entered recursively while inspecting dependencies
25802
+ // of an NgModule or a standalone component. Exit early if we come across a
25803
+ // type that can not have a scope (directive or pipe) or the type is already
25804
+ // processed earlier.
25805
+ if (!hasScope || this.scopesWithOverriddenProviders.has(type)) {
25799
25806
  return;
25800
25807
  }
25801
- this.moduleProvidersOverridden.add(moduleType);
25808
+ this.scopesWithOverriddenProviders.add(type);
25802
25809
  // NOTE: the line below triggers JIT compilation of the module injector,
25803
25810
  // which also invokes verification of the NgModule semantics, which produces
25804
25811
  // detailed error messages. The fact that the code relies on this line being
25805
25812
  // present here is suspicious and should be refactored in a way that the line
25806
25813
  // below can be moved (for ex. after an early exit check below).
25807
- const injectorDef = moduleType[ɵNG_INJ_DEF];
25814
+ const injectorDef = type[ɵNG_INJ_DEF];
25808
25815
  // No provider overrides, exit early.
25809
25816
  if (this.providerOverridesByToken.size === 0)
25810
25817
  return;
25811
- if (isStandaloneComponent(moduleType)) {
25818
+ if (isStandaloneComponent(type)) {
25812
25819
  // Visit all component dependencies and override providers there.
25813
- const def = getComponentDef(moduleType);
25820
+ const def = getComponentDef(type);
25814
25821
  const dependencies = maybeUnwrapFn(def.dependencies ?? []);
25815
25822
  for (const dependency of dependencies) {
25816
- // Proceed with examining dependencies recursively
25817
- // when a dependency is a standalone component or an NgModule.
25818
- // In AOT, the `dependencies` might also contain regular (NgModule-based)
25819
- // Component, Directive and Pipes. Skip them here, they are handled in a
25820
- // different location (in the `configureTestingModule` function).
25821
- if (isStandaloneComponent(dependency) || hasNgModuleDef(dependency)) {
25822
- this.applyProviderOverridesToModule(dependency);
25823
- }
25823
+ this.applyProviderOverridesInScope(dependency);
25824
25824
  }
25825
25825
  }
25826
25826
  else {
25827
25827
  const providers = [
25828
25828
  ...injectorDef.providers,
25829
- ...(this.providerOverridesByModule.get(moduleType) || [])
25829
+ ...(this.providerOverridesByModule.get(type) || [])
25830
25830
  ];
25831
25831
  if (this.hasProviderOverrides(providers)) {
25832
- this.maybeStoreNgDef(ɵNG_INJ_DEF, moduleType);
25833
- this.storeFieldOfDefOnType(moduleType, ɵNG_INJ_DEF, 'providers');
25832
+ this.maybeStoreNgDef(ɵNG_INJ_DEF, type);
25833
+ this.storeFieldOfDefOnType(type, ɵNG_INJ_DEF, 'providers');
25834
25834
  injectorDef.providers = this.getOverriddenProviders(providers);
25835
25835
  }
25836
25836
  // Apply provider overrides to imported modules recursively
25837
- const moduleDef = moduleType[ɵNG_MOD_DEF];
25837
+ const moduleDef = type[ɵNG_MOD_DEF];
25838
25838
  const imports = maybeUnwrapFn(moduleDef.imports);
25839
25839
  for (const importedModule of imports) {
25840
- this.applyProviderOverridesToModule(importedModule);
25840
+ this.applyProviderOverridesInScope(importedModule);
25841
25841
  }
25842
25842
  // Also override the providers on any ModuleWithProviders imports since those don't appear in
25843
25843
  // the moduleDef.
@@ -26074,7 +26074,7 @@ class R3TestBedCompiler {
26074
26074
  });
26075
26075
  });
26076
26076
  this.initialNgDefs.clear();
26077
- this.moduleProvidersOverridden.clear();
26077
+ this.scopesWithOverriddenProviders.clear();
26078
26078
  this.restoreComponentResolutionQueue();
26079
26079
  // Restore the locale ID to the default value, this shouldn't be necessary but we never know
26080
26080
  ɵsetLocaleId(ɵDEFAULT_LOCALE_ID);
@@ -26101,7 +26101,7 @@ class R3TestBedCompiler {
26101
26101
  providers,
26102
26102
  }, /* allowDuplicateDeclarationsInRoot */ true);
26103
26103
  // clang-format on
26104
- this.applyProviderOverridesToModule(this.testModuleType);
26104
+ this.applyProviderOverridesInScope(this.testModuleType);
26105
26105
  }
26106
26106
  get injector() {
26107
26107
  if (this._injector !== null) {
@@ -26201,6 +26201,9 @@ function getComponentDef(value) {
26201
26201
  function hasNgModuleDef(value) {
26202
26202
  return value.hasOwnProperty('ɵmod');
26203
26203
  }
26204
+ function isNgModule(value) {
26205
+ return hasNgModuleDef(value);
26206
+ }
26204
26207
  function maybeUnwrapFn(maybeFn) {
26205
26208
  return maybeFn instanceof Function ? maybeFn() : maybeFn;
26206
26209
  }