@angular/core 16.0.0-next.2 → 16.0.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 (51) hide show
  1. package/esm2020/src/application_ref.mjs +95 -87
  2. package/esm2020/src/application_tokens.mjs +27 -21
  3. package/esm2020/src/compiler/compiler_facade_interface.mjs +1 -1
  4. package/esm2020/src/core_private_export.mjs +2 -3
  5. package/esm2020/src/di/contextual.mjs +37 -0
  6. package/esm2020/src/di/index.mjs +2 -1
  7. package/esm2020/src/di/r3_injector.mjs +1 -1
  8. package/esm2020/src/errors.mjs +1 -1
  9. package/esm2020/src/hydration/annotate.mjs +136 -5
  10. package/esm2020/src/hydration/api.mjs +9 -1
  11. package/esm2020/src/hydration/cleanup.mjs +50 -0
  12. package/esm2020/src/hydration/error_handling.mjs +11 -3
  13. package/esm2020/src/hydration/interfaces.mjs +9 -2
  14. package/esm2020/src/hydration/node_lookup_utils.mjs +22 -14
  15. package/esm2020/src/hydration/skip_hydration.mjs +16 -1
  16. package/esm2020/src/hydration/utils.mjs +82 -7
  17. package/esm2020/src/hydration/views.mjs +80 -0
  18. package/esm2020/src/linker/template_ref.mjs +17 -2
  19. package/esm2020/src/linker/view_container_ref.mjs +110 -35
  20. package/esm2020/src/render3/component_ref.mjs +2 -2
  21. package/esm2020/src/render3/definition.mjs +114 -45
  22. package/esm2020/src/render3/instructions/element.mjs +18 -8
  23. package/esm2020/src/render3/instructions/element_container.mjs +12 -13
  24. package/esm2020/src/render3/instructions/shared.mjs +53 -16
  25. package/esm2020/src/render3/instructions/template.mjs +57 -6
  26. package/esm2020/src/render3/instructions/text.mjs +1 -1
  27. package/esm2020/src/render3/interfaces/container.mjs +3 -2
  28. package/esm2020/src/render3/interfaces/type_checks.mjs +2 -2
  29. package/esm2020/src/render3/interfaces/view.mjs +1 -1
  30. package/esm2020/src/render3/jit/module.mjs +3 -2
  31. package/esm2020/src/render3/ng_module_ref.mjs +9 -5
  32. package/esm2020/src/render3/util/discovery_utils.mjs +3 -2
  33. package/esm2020/src/util/ng_dev_mode.mjs +2 -1
  34. package/esm2020/src/version.mjs +1 -1
  35. package/esm2020/src/zone/ng_zone.mjs +62 -1
  36. package/esm2020/testing/src/logger.mjs +3 -3
  37. package/esm2020/testing/src/ng_zone_mock.mjs +3 -3
  38. package/esm2020/testing/src/test_bed_compiler.mjs +4 -4
  39. package/fesm2015/core.mjs +2354 -1657
  40. package/fesm2015/core.mjs.map +1 -1
  41. package/fesm2015/testing.mjs +1910 -1415
  42. package/fesm2015/testing.mjs.map +1 -1
  43. package/fesm2020/core.mjs +2288 -1581
  44. package/fesm2020/core.mjs.map +1 -1
  45. package/fesm2020/testing.mjs +5085 -4581
  46. package/fesm2020/testing.mjs.map +1 -1
  47. package/index.d.ts +370 -400
  48. package/package.json +1 -1
  49. package/schematics/ng-generate/standalone-migration/bundle.js +198 -99
  50. package/schematics/ng-generate/standalone-migration/bundle.js.map +3 -3
  51. package/testing/index.d.ts +1 -1
package/fesm2015/core.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v16.0.0-next.2
2
+ * @license Angular v16.0.0-next.3
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -557,6 +557,7 @@ function ngDevModeResetPerfCounters() {
557
557
  rendererCreateComment: 0,
558
558
  hydratedNodes: 0,
559
559
  hydratedComponents: 0,
560
+ dehydratedViewsRemoved: 0,
560
561
  };
561
562
  // Make sure to refer to ngDevMode as ['ngDevMode'] for closure.
562
563
  const allowNgDevModeTrue = locationString.indexOf('ngDevMode=false') === -1;
@@ -938,355 +939,1040 @@ const NG_ELEMENT_ID = getClosureSafeProperty({ __NG_ELEMENT_ID__: getClosureSafe
938
939
  */
939
940
  const NG_ENV_ID = getClosureSafeProperty({ __NG_ENV_ID__: getClosureSafeProperty });
940
941
 
941
- /** Counter used to generate unique IDs for component definitions. */
942
- let componentDefCount = 0;
943
942
  /**
944
- * Create a component definition object.
945
- *
946
- *
947
- * # Example
948
- * ```
949
- * class MyDirective {
950
- * // Generated by Angular Template Compiler
951
- * // [Symbol] syntax will not be supported by TypeScript until v2.7
952
- * static ɵcmp = defineComponent({
953
- * ...
954
- * });
955
- * }
956
- * ```
957
- * @codeGenApi
958
- */
959
- function ɵɵdefineComponent(componentDefinition) {
960
- return noSideEffects(() => {
961
- // Initialize ngDevMode. This must be the first statement in ɵɵdefineComponent.
962
- // See the `initNgDevMode` docstring for more information.
963
- (typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode();
964
- const type = componentDefinition.type;
965
- const standalone = componentDefinition.standalone === true;
966
- const declaredInputs = {};
967
- const def = {
968
- type: type,
969
- providersResolver: null,
970
- decls: componentDefinition.decls,
971
- vars: componentDefinition.vars,
972
- factory: null,
973
- template: componentDefinition.template || null,
974
- consts: componentDefinition.consts || null,
975
- ngContentSelectors: componentDefinition.ngContentSelectors,
976
- hostBindings: componentDefinition.hostBindings || null,
977
- hostVars: componentDefinition.hostVars || 0,
978
- hostAttrs: componentDefinition.hostAttrs || null,
979
- contentQueries: componentDefinition.contentQueries || null,
980
- declaredInputs: declaredInputs,
981
- inputs: null,
982
- outputs: null,
983
- exportAs: componentDefinition.exportAs || null,
984
- onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush,
985
- directiveDefs: null,
986
- pipeDefs: null,
987
- standalone,
988
- dependencies: standalone && componentDefinition.dependencies || null,
989
- getStandaloneInjector: null,
990
- selectors: componentDefinition.selectors || EMPTY_ARRAY,
991
- viewQuery: componentDefinition.viewQuery || null,
992
- features: componentDefinition.features || null,
993
- data: componentDefinition.data || {},
994
- encapsulation: componentDefinition.encapsulation || ViewEncapsulation$1.Emulated,
995
- id: `c${componentDefCount++}`,
996
- styles: componentDefinition.styles || EMPTY_ARRAY,
997
- _: null,
998
- setInput: null,
999
- schemas: componentDefinition.schemas || null,
1000
- tView: null,
1001
- findHostDirectiveDefs: null,
1002
- hostDirectives: null,
1003
- };
1004
- const dependencies = componentDefinition.dependencies;
1005
- const feature = componentDefinition.features;
1006
- def.inputs = invertObject(componentDefinition.inputs, declaredInputs),
1007
- def.outputs = invertObject(componentDefinition.outputs),
1008
- feature && feature.forEach((fn) => fn(def));
1009
- def.directiveDefs = dependencies ?
1010
- (() => (typeof dependencies === 'function' ? dependencies() : dependencies)
1011
- .map(extractDirectiveDef)
1012
- .filter(nonNull)) :
1013
- null;
1014
- def.pipeDefs = dependencies ?
1015
- (() => (typeof dependencies === 'function' ? dependencies() : dependencies)
1016
- .map(getPipeDef$1)
1017
- .filter(nonNull)) :
1018
- null;
1019
- return def;
1020
- });
1021
- }
1022
- /**
1023
- * Generated next to NgModules to monkey-patch directive and pipe references onto a component's
1024
- * definition, when generating a direct reference in the component file would otherwise create an
1025
- * import cycle.
1026
- *
1027
- * See [this explanation](https://hackmd.io/Odw80D0pR6yfsOjg_7XCJg?view) for more details.
1028
- *
1029
- * @codeGenApi
1030
- */
1031
- function ɵɵsetComponentScope(type, directives, pipes) {
1032
- const def = type.ɵcmp;
1033
- def.directiveDefs = () => (typeof directives === 'function' ? directives() : directives).map(extractDirectiveDef);
1034
- def.pipeDefs = () => (typeof pipes === 'function' ? pipes() : pipes).map(getPipeDef$1);
1035
- }
1036
- function extractDirectiveDef(type) {
1037
- return getComponentDef(type) || getDirectiveDef(type);
1038
- }
1039
- function nonNull(value) {
1040
- return value !== null;
1041
- }
1042
- /**
1043
- * @codeGenApi
1044
- */
1045
- function ɵɵdefineNgModule(def) {
1046
- return noSideEffects(() => {
1047
- const res = {
1048
- type: def.type,
1049
- bootstrap: def.bootstrap || EMPTY_ARRAY,
1050
- declarations: def.declarations || EMPTY_ARRAY,
1051
- imports: def.imports || EMPTY_ARRAY,
1052
- exports: def.exports || EMPTY_ARRAY,
1053
- transitiveCompileScopes: null,
1054
- schemas: def.schemas || null,
1055
- id: def.id || null,
1056
- };
1057
- return res;
1058
- });
1059
- }
1060
- /**
1061
- * Adds the module metadata that is necessary to compute the module's transitive scope to an
1062
- * existing module definition.
943
+ * Returns an index of `classToSearch` in `className` taking token boundaries into account.
1063
944
  *
1064
- * Scope metadata of modules is not used in production builds, so calls to this function can be
1065
- * marked pure to tree-shake it from the bundle, allowing for all referenced declarations
1066
- * to become eligible for tree-shaking as well.
945
+ * `classIndexOf('AB A', 'A', 0)` will be 3 (not 0 since `AB!==A`)
1067
946
  *
1068
- * @codeGenApi
947
+ * @param className A string containing classes (whitespace separated)
948
+ * @param classToSearch A class name to locate
949
+ * @param startingIndex Starting location of search
950
+ * @returns an index of the located class (or -1 if not found)
1069
951
  */
1070
- function ɵɵsetNgModuleScope(type, scope) {
1071
- return noSideEffects(() => {
1072
- const ngModuleDef = getNgModuleDef(type, true);
1073
- ngModuleDef.declarations = scope.declarations || EMPTY_ARRAY;
1074
- ngModuleDef.imports = scope.imports || EMPTY_ARRAY;
1075
- ngModuleDef.exports = scope.exports || EMPTY_ARRAY;
1076
- });
952
+ function classIndexOf(className, classToSearch, startingIndex) {
953
+ ngDevMode && assertNotEqual(classToSearch, '', 'can not look for "" string.');
954
+ let end = className.length;
955
+ while (true) {
956
+ const foundIndex = className.indexOf(classToSearch, startingIndex);
957
+ if (foundIndex === -1)
958
+ return foundIndex;
959
+ if (foundIndex === 0 || className.charCodeAt(foundIndex - 1) <= 32 /* CharCode.SPACE */) {
960
+ // Ensure that it has leading whitespace
961
+ const length = classToSearch.length;
962
+ if (foundIndex + length === end ||
963
+ className.charCodeAt(foundIndex + length) <= 32 /* CharCode.SPACE */) {
964
+ // Ensure that it has trailing whitespace
965
+ return foundIndex;
966
+ }
967
+ }
968
+ // False positive, keep searching from where we left off.
969
+ startingIndex = foundIndex + 1;
970
+ }
1077
971
  }
972
+
1078
973
  /**
1079
- * Inverts an inputs or outputs lookup such that the keys, which were the
1080
- * minified keys, are part of the values, and the values are parsed so that
1081
- * the publicName of the property is the new key
1082
- *
1083
- * e.g. for
1084
- *
1085
- * ```
1086
- * class Comp {
1087
- * @Input()
1088
- * propName1: string;
1089
- *
1090
- * @Input('publicName2')
1091
- * declaredPropName2: number;
1092
- * }
1093
- * ```
1094
- *
1095
- * will be serialized as
1096
- *
1097
- * ```
1098
- * {
1099
- * propName1: 'propName1',
1100
- * declaredPropName2: ['publicName2', 'declaredPropName2'],
1101
- * }
1102
- * ```
1103
- *
1104
- * which is than translated by the minifier as:
974
+ * Assigns all attribute values to the provided element via the inferred renderer.
1105
975
  *
1106
- * ```
1107
- * {
1108
- * minifiedPropName1: 'propName1',
1109
- * minifiedPropName2: ['publicName2', 'declaredPropName2'],
1110
- * }
1111
- * ```
976
+ * This function accepts two forms of attribute entries:
1112
977
  *
1113
- * becomes: (public name => minifiedName)
978
+ * default: (key, value):
979
+ * attrs = [key1, value1, key2, value2]
1114
980
  *
1115
- * ```
1116
- * {
1117
- * 'propName1': 'minifiedPropName1',
1118
- * 'publicName2': 'minifiedPropName2',
1119
- * }
1120
- * ```
981
+ * namespaced: (NAMESPACE_MARKER, uri, name, value)
982
+ * attrs = [NAMESPACE_MARKER, uri, name, value, NAMESPACE_MARKER, uri, name, value]
1121
983
  *
1122
- * Optionally the function can take `secondary` which will result in: (public name => declared name)
984
+ * The `attrs` array can contain a mix of both the default and namespaced entries.
985
+ * The "default" values are set without a marker, but if the function comes across
986
+ * a marker value then it will attempt to set a namespaced value. If the marker is
987
+ * not of a namespaced value then the function will quit and return the index value
988
+ * where it stopped during the iteration of the attrs array.
1123
989
  *
1124
- * ```
1125
- * {
1126
- * 'propName1': 'propName1',
1127
- * 'publicName2': 'declaredPropName2',
1128
- * }
1129
- * ```
990
+ * See [AttributeMarker] to understand what the namespace marker value is.
1130
991
  *
1131
-
992
+ * Note that this instruction does not support assigning style and class values to
993
+ * an element. See `elementStart` and `elementHostAttrs` to learn how styling values
994
+ * are applied to an element.
995
+ * @param renderer The renderer to be used
996
+ * @param native The element that the attributes will be assigned to
997
+ * @param attrs The attribute array of values that will be assigned to the element
998
+ * @returns the index value that was last accessed in the attributes array
1132
999
  */
1133
- function invertObject(obj, secondary) {
1134
- if (obj == null)
1135
- return EMPTY_OBJ;
1136
- const newLookup = {};
1137
- for (const minifiedKey in obj) {
1138
- if (obj.hasOwnProperty(minifiedKey)) {
1139
- let publicName = obj[minifiedKey];
1140
- let declaredName = publicName;
1141
- if (Array.isArray(publicName)) {
1142
- declaredName = publicName[1];
1143
- publicName = publicName[0];
1000
+ function setUpAttributes(renderer, native, attrs) {
1001
+ let i = 0;
1002
+ while (i < attrs.length) {
1003
+ const value = attrs[i];
1004
+ if (typeof value === 'number') {
1005
+ // only namespaces are supported. Other value types (such as style/class
1006
+ // entries) are not supported in this function.
1007
+ if (value !== 0 /* AttributeMarker.NamespaceURI */) {
1008
+ break;
1144
1009
  }
1145
- newLookup[publicName] = minifiedKey;
1146
- if (secondary) {
1147
- (secondary[publicName] = declaredName);
1010
+ // we just landed on the marker value ... therefore
1011
+ // we should skip to the next entry
1012
+ i++;
1013
+ const namespaceURI = attrs[i++];
1014
+ const attrName = attrs[i++];
1015
+ const attrVal = attrs[i++];
1016
+ ngDevMode && ngDevMode.rendererSetAttribute++;
1017
+ renderer.setAttribute(native, attrName, attrVal, namespaceURI);
1018
+ }
1019
+ else {
1020
+ // attrName is string;
1021
+ const attrName = value;
1022
+ const attrVal = attrs[++i];
1023
+ // Standard attributes
1024
+ ngDevMode && ngDevMode.rendererSetAttribute++;
1025
+ if (isAnimationProp(attrName)) {
1026
+ renderer.setProperty(native, attrName, attrVal);
1027
+ }
1028
+ else {
1029
+ renderer.setAttribute(native, attrName, attrVal);
1148
1030
  }
1031
+ i++;
1149
1032
  }
1150
1033
  }
1151
- return newLookup;
1034
+ // another piece of code may iterate over the same attributes array. Therefore
1035
+ // it may be helpful to return the exact spot where the attributes array exited
1036
+ // whether by running into an unsupported marker or if all the static values were
1037
+ // iterated over.
1038
+ return i;
1152
1039
  }
1153
1040
  /**
1154
- * Create a directive definition object.
1155
- *
1156
- * # Example
1157
- * ```ts
1158
- * class MyDirective {
1159
- * // Generated by Angular Template Compiler
1160
- * // [Symbol] syntax will not be supported by TypeScript until v2.7
1161
- * static ɵdir = ɵɵdefineDirective({
1162
- * ...
1163
- * });
1164
- * }
1165
- * ```
1166
- *
1167
- * @codeGenApi
1041
+ * Test whether the given value is a marker that indicates that the following
1042
+ * attribute values in a `TAttributes` array are only the names of attributes,
1043
+ * and not name-value pairs.
1044
+ * @param marker The attribute marker to test.
1045
+ * @returns true if the marker is a "name-only" marker (e.g. `Bindings`, `Template` or `I18n`).
1168
1046
  */
1169
- const ɵɵdefineDirective = ɵɵdefineComponent;
1047
+ function isNameOnlyAttributeMarker(marker) {
1048
+ return marker === 3 /* AttributeMarker.Bindings */ || marker === 4 /* AttributeMarker.Template */ ||
1049
+ marker === 6 /* AttributeMarker.I18n */;
1050
+ }
1051
+ function isAnimationProp(name) {
1052
+ // Perf note: accessing charCodeAt to check for the first character of a string is faster as
1053
+ // compared to accessing a character at index 0 (ex. name[0]). The main reason for this is that
1054
+ // charCodeAt doesn't allocate memory to return a substring.
1055
+ return name.charCodeAt(0) === 64 /* CharCode.AT_SIGN */;
1056
+ }
1170
1057
  /**
1171
- * Create a pipe definition object.
1058
+ * Merges `src` `TAttributes` into `dst` `TAttributes` removing any duplicates in the process.
1172
1059
  *
1173
- * # Example
1174
- * ```
1175
- * class MyPipe implements PipeTransform {
1176
- * // Generated by Angular Template Compiler
1177
- * static ɵpipe = definePipe({
1178
- * ...
1179
- * });
1180
- * }
1181
- * ```
1182
- * @param pipeDef Pipe definition generated by the compiler
1060
+ * This merge function keeps the order of attrs same.
1183
1061
  *
1184
- * @codeGenApi
1185
- */
1186
- function ɵɵdefinePipe(pipeDef) {
1187
- return {
1188
- type: pipeDef.type,
1189
- name: pipeDef.name,
1190
- factory: null,
1191
- pure: pipeDef.pure !== false,
1192
- standalone: pipeDef.standalone === true,
1193
- onDestroy: pipeDef.type.prototype.ngOnDestroy || null
1194
- };
1195
- }
1196
- /**
1197
- * The following getter methods retrieve the definition from the type. Currently the retrieval
1198
- * honors inheritance, but in the future we may change the rule to require that definitions are
1199
- * explicit. This would require some sort of migration strategy.
1062
+ * @param dst Location of where the merged `TAttributes` should end up.
1063
+ * @param src `TAttributes` which should be appended to `dst`
1200
1064
  */
1201
- function getComponentDef(type) {
1202
- return type[NG_COMP_DEF] || null;
1203
- }
1204
- function getDirectiveDef(type) {
1205
- return type[NG_DIR_DEF] || null;
1206
- }
1207
- function getPipeDef$1(type) {
1208
- return type[NG_PIPE_DEF] || null;
1065
+ function mergeHostAttrs(dst, src) {
1066
+ if (src === null || src.length === 0) {
1067
+ // do nothing
1068
+ }
1069
+ else if (dst === null || dst.length === 0) {
1070
+ // We have source, but dst is empty, just make a copy.
1071
+ dst = src.slice();
1072
+ }
1073
+ else {
1074
+ let srcMarker = -1 /* AttributeMarker.ImplicitAttributes */;
1075
+ for (let i = 0; i < src.length; i++) {
1076
+ const item = src[i];
1077
+ if (typeof item === 'number') {
1078
+ srcMarker = item;
1079
+ }
1080
+ else {
1081
+ if (srcMarker === 0 /* AttributeMarker.NamespaceURI */) {
1082
+ // Case where we need to consume `key1`, `key2`, `value` items.
1083
+ }
1084
+ else if (srcMarker === -1 /* AttributeMarker.ImplicitAttributes */ ||
1085
+ srcMarker === 2 /* AttributeMarker.Styles */) {
1086
+ // Case where we have to consume `key1` and `value` only.
1087
+ mergeHostAttribute(dst, srcMarker, item, null, src[++i]);
1088
+ }
1089
+ else {
1090
+ // Case where we have to consume `key1` only.
1091
+ mergeHostAttribute(dst, srcMarker, item, null, null);
1092
+ }
1093
+ }
1094
+ }
1095
+ }
1096
+ return dst;
1209
1097
  }
1210
1098
  /**
1211
- * Checks whether a given Component, Directive or Pipe is marked as standalone.
1212
- * This will return false if passed anything other than a Component, Directive, or Pipe class
1213
- * See this guide for additional information: https://angular.io/guide/standalone-components
1099
+ * Append `key`/`value` to existing `TAttributes` taking region marker and duplicates into account.
1214
1100
  *
1215
- * @param type A reference to a Component, Directive or Pipe.
1216
- * @publicApi
1101
+ * @param dst `TAttributes` to append to.
1102
+ * @param marker Region where the `key`/`value` should be added.
1103
+ * @param key1 Key to add to `TAttributes`
1104
+ * @param key2 Key to add to `TAttributes` (in case of `AttributeMarker.NamespaceURI`)
1105
+ * @param value Value to add or to overwrite to `TAttributes` Only used if `marker` is not Class.
1217
1106
  */
1218
- function isStandalone(type) {
1219
- const def = getComponentDef(type) || getDirectiveDef(type) || getPipeDef$1(type);
1220
- return def !== null ? def.standalone : false;
1221
- }
1222
- function getNgModuleDef(type, throwNotFound) {
1223
- const ngModuleDef = type[NG_MOD_DEF] || null;
1224
- if (!ngModuleDef && throwNotFound === true) {
1225
- throw new Error(`Type ${stringify(type)} does not have 'ɵmod' property.`);
1107
+ function mergeHostAttribute(dst, marker, key1, key2, value) {
1108
+ let i = 0;
1109
+ // Assume that new markers will be inserted at the end.
1110
+ let markerInsertPosition = dst.length;
1111
+ // scan until correct type.
1112
+ if (marker === -1 /* AttributeMarker.ImplicitAttributes */) {
1113
+ markerInsertPosition = -1;
1114
+ }
1115
+ else {
1116
+ while (i < dst.length) {
1117
+ const dstValue = dst[i++];
1118
+ if (typeof dstValue === 'number') {
1119
+ if (dstValue === marker) {
1120
+ markerInsertPosition = -1;
1121
+ break;
1122
+ }
1123
+ else if (dstValue > marker) {
1124
+ // We need to save this as we want the markers to be inserted in specific order.
1125
+ markerInsertPosition = i - 1;
1126
+ break;
1127
+ }
1128
+ }
1129
+ }
1130
+ }
1131
+ // search until you find place of insertion
1132
+ while (i < dst.length) {
1133
+ const item = dst[i];
1134
+ if (typeof item === 'number') {
1135
+ // since `i` started as the index after the marker, we did not find it if we are at the next
1136
+ // marker
1137
+ break;
1138
+ }
1139
+ else if (item === key1) {
1140
+ // We already have same token
1141
+ if (key2 === null) {
1142
+ if (value !== null) {
1143
+ dst[i + 1] = value;
1144
+ }
1145
+ return;
1146
+ }
1147
+ else if (key2 === dst[i + 1]) {
1148
+ dst[i + 2] = value;
1149
+ return;
1150
+ }
1151
+ }
1152
+ // Increment counter.
1153
+ i++;
1154
+ if (key2 !== null)
1155
+ i++;
1156
+ if (value !== null)
1157
+ i++;
1158
+ }
1159
+ // insert at location.
1160
+ if (markerInsertPosition !== -1) {
1161
+ dst.splice(markerInsertPosition, 0, marker);
1162
+ i = markerInsertPosition + 1;
1163
+ }
1164
+ dst.splice(i++, 0, key1);
1165
+ if (key2 !== null) {
1166
+ dst.splice(i++, 0, key2);
1167
+ }
1168
+ if (value !== null) {
1169
+ dst.splice(i++, 0, value);
1226
1170
  }
1227
- return ngModuleDef;
1228
1171
  }
1229
1172
 
1173
+ const NG_TEMPLATE_SELECTOR = 'ng-template';
1230
1174
  /**
1231
- * Special location which allows easy identification of type. If we have an array which was
1232
- * retrieved from the `LView` and that array has `true` at `TYPE` location, we know it is
1233
- * `LContainer`.
1175
+ * Search the `TAttributes` to see if it contains `cssClassToMatch` (case insensitive)
1176
+ *
1177
+ * @param attrs `TAttributes` to search through.
1178
+ * @param cssClassToMatch class to match (lowercase)
1179
+ * @param isProjectionMode Whether or not class matching should look into the attribute `class` in
1180
+ * addition to the `AttributeMarker.Classes`.
1234
1181
  */
1235
- const TYPE = 1;
1182
+ function isCssClassMatching(attrs, cssClassToMatch, isProjectionMode) {
1183
+ // TODO(misko): The fact that this function needs to know about `isProjectionMode` seems suspect.
1184
+ // It is strange to me that sometimes the class information comes in form of `class` attribute
1185
+ // and sometimes in form of `AttributeMarker.Classes`. Some investigation is needed to determine
1186
+ // if that is the right behavior.
1187
+ ngDevMode &&
1188
+ assertEqual(cssClassToMatch, cssClassToMatch.toLowerCase(), 'Class name expected to be lowercase.');
1189
+ let i = 0;
1190
+ while (i < attrs.length) {
1191
+ let item = attrs[i++];
1192
+ if (isProjectionMode && item === 'class') {
1193
+ item = attrs[i];
1194
+ if (classIndexOf(item.toLowerCase(), cssClassToMatch, 0) !== -1) {
1195
+ return true;
1196
+ }
1197
+ }
1198
+ else if (item === 1 /* AttributeMarker.Classes */) {
1199
+ // We found the classes section. Start searching for the class.
1200
+ while (i < attrs.length && typeof (item = attrs[i++]) == 'string') {
1201
+ // while we have strings
1202
+ if (item.toLowerCase() === cssClassToMatch)
1203
+ return true;
1204
+ }
1205
+ return false;
1206
+ }
1207
+ }
1208
+ return false;
1209
+ }
1236
1210
  /**
1237
- * Below are constants for LContainer indices to help us look up LContainer members
1238
- * without having to remember the specific indices.
1239
- * Uglify will inline these when minifying so there shouldn't be a cost.
1211
+ * Checks whether the `tNode` represents an inline template (e.g. `*ngFor`).
1212
+ *
1213
+ * @param tNode current TNode
1240
1214
  */
1215
+ function isInlineTemplate(tNode) {
1216
+ return tNode.type === 4 /* TNodeType.Container */ && tNode.value !== NG_TEMPLATE_SELECTOR;
1217
+ }
1241
1218
  /**
1242
- * Flag to signify that this `LContainer` may have transplanted views which need to be change
1243
- * detected. (see: `LView[DECLARATION_COMPONENT_VIEW])`.
1219
+ * Function that checks whether a given tNode matches tag-based selector and has a valid type.
1244
1220
  *
1245
- * This flag, once set, is never unset for the `LContainer`. This means that when unset we can skip
1246
- * a lot of work in `refreshEmbeddedViews`. But when set we still need to verify
1247
- * that the `MOVED_VIEWS` are transplanted and on-push.
1221
+ * Matching can be performed in 2 modes: projection mode (when we project nodes) and regular
1222
+ * directive matching mode:
1223
+ * - in the "directive matching" mode we do _not_ take TContainer's tagName into account if it is
1224
+ * different from NG_TEMPLATE_SELECTOR (value different from NG_TEMPLATE_SELECTOR indicates that a
1225
+ * tag name was extracted from * syntax so we would match the same directive twice);
1226
+ * - in the "projection" mode, we use a tag name potentially extracted from the * syntax processing
1227
+ * (applicable to TNodeType.Container only).
1248
1228
  */
1249
- const HAS_TRANSPLANTED_VIEWS = 2;
1250
- // PARENT, NEXT, TRANSPLANTED_VIEWS_TO_REFRESH are indices 3, 4, and 5
1251
- // As we already have these constants in LView, we don't need to re-create them.
1252
- // T_HOST is index 6
1253
- // We already have this constants in LView, we don't need to re-create it.
1254
- const NATIVE = 7;
1255
- const VIEW_REFS = 8;
1256
- const MOVED_VIEWS = 9;
1229
+ function hasTagAndTypeMatch(tNode, currentSelector, isProjectionMode) {
1230
+ const tagNameToCompare = tNode.type === 4 /* TNodeType.Container */ && !isProjectionMode ? NG_TEMPLATE_SELECTOR : tNode.value;
1231
+ return currentSelector === tagNameToCompare;
1232
+ }
1257
1233
  /**
1258
- * Size of LContainer's header. Represents the index after which all views in the
1259
- * container will be inserted. We need to keep a record of current views so we know
1260
- * which views are already in the DOM (and don't need to be re-added) and so we can
1261
- * remove views from the DOM when they are no longer required.
1234
+ * A utility function to match an Ivy node static data against a simple CSS selector
1235
+ *
1236
+ * @param node static data of the node to match
1237
+ * @param selector The selector to try matching against the node.
1238
+ * @param isProjectionMode if `true` we are matching for content projection, otherwise we are doing
1239
+ * directive matching.
1240
+ * @returns true if node matches the selector.
1262
1241
  */
1263
- const CONTAINER_HEADER_OFFSET = 10;
1264
- // Note: This hack is necessary so we don't erroneously get a circular dependency
1265
- // failure based on types.
1266
- const unusedValueExportToPlacateAjd$4 = 1;
1267
-
1268
- // Below are constants for LView indices to help us look up LView members
1269
- // without having to remember the specific indices.
1270
- // Uglify will inline these when minifying so there shouldn't be a cost.
1271
- const HOST = 0;
1272
- const TVIEW = 1;
1273
- const FLAGS = 2;
1274
- const PARENT = 3;
1275
- const NEXT = 4;
1276
- const TRANSPLANTED_VIEWS_TO_REFRESH = 5;
1277
- const T_HOST = 6;
1278
- const CLEANUP = 7;
1279
- const CONTEXT = 8;
1280
- const INJECTOR$1 = 9;
1281
- const RENDERER_FACTORY = 10;
1282
- const RENDERER = 11;
1283
- const SANITIZER = 12;
1284
- const CHILD_HEAD = 13;
1285
- const CHILD_TAIL = 14;
1286
- // FIXME(misko): Investigate if the three declarations aren't all same thing.
1287
- const DECLARATION_VIEW = 15;
1288
- const DECLARATION_COMPONENT_VIEW = 16;
1289
- const DECLARATION_LCONTAINER = 17;
1242
+ function isNodeMatchingSelector(tNode, selector, isProjectionMode) {
1243
+ ngDevMode && assertDefined(selector[0], 'Selector should have a tag name');
1244
+ let mode = 4 /* SelectorFlags.ELEMENT */;
1245
+ const nodeAttrs = tNode.attrs || [];
1246
+ // Find the index of first attribute that has no value, only a name.
1247
+ const nameOnlyMarkerIdx = getNameOnlyMarkerIndex(nodeAttrs);
1248
+ // When processing ":not" selectors, we skip to the next ":not" if the
1249
+ // current one doesn't match
1250
+ let skipToNextSelector = false;
1251
+ for (let i = 0; i < selector.length; i++) {
1252
+ const current = selector[i];
1253
+ if (typeof current === 'number') {
1254
+ // If we finish processing a :not selector and it hasn't failed, return false
1255
+ if (!skipToNextSelector && !isPositive(mode) && !isPositive(current)) {
1256
+ return false;
1257
+ }
1258
+ // If we are skipping to the next :not() and this mode flag is positive,
1259
+ // it's a part of the current :not() selector, and we should keep skipping
1260
+ if (skipToNextSelector && isPositive(current))
1261
+ continue;
1262
+ skipToNextSelector = false;
1263
+ mode = current | (mode & 1 /* SelectorFlags.NOT */);
1264
+ continue;
1265
+ }
1266
+ if (skipToNextSelector)
1267
+ continue;
1268
+ if (mode & 4 /* SelectorFlags.ELEMENT */) {
1269
+ mode = 2 /* SelectorFlags.ATTRIBUTE */ | mode & 1 /* SelectorFlags.NOT */;
1270
+ if (current !== '' && !hasTagAndTypeMatch(tNode, current, isProjectionMode) ||
1271
+ current === '' && selector.length === 1) {
1272
+ if (isPositive(mode))
1273
+ return false;
1274
+ skipToNextSelector = true;
1275
+ }
1276
+ }
1277
+ else {
1278
+ const selectorAttrValue = mode & 8 /* SelectorFlags.CLASS */ ? current : selector[++i];
1279
+ // special case for matching against classes when a tNode has been instantiated with
1280
+ // class and style values as separate attribute values (e.g. ['title', CLASS, 'foo'])
1281
+ if ((mode & 8 /* SelectorFlags.CLASS */) && tNode.attrs !== null) {
1282
+ if (!isCssClassMatching(tNode.attrs, selectorAttrValue, isProjectionMode)) {
1283
+ if (isPositive(mode))
1284
+ return false;
1285
+ skipToNextSelector = true;
1286
+ }
1287
+ continue;
1288
+ }
1289
+ const attrName = (mode & 8 /* SelectorFlags.CLASS */) ? 'class' : current;
1290
+ const attrIndexInNode = findAttrIndexInNode(attrName, nodeAttrs, isInlineTemplate(tNode), isProjectionMode);
1291
+ if (attrIndexInNode === -1) {
1292
+ if (isPositive(mode))
1293
+ return false;
1294
+ skipToNextSelector = true;
1295
+ continue;
1296
+ }
1297
+ if (selectorAttrValue !== '') {
1298
+ let nodeAttrValue;
1299
+ if (attrIndexInNode > nameOnlyMarkerIdx) {
1300
+ nodeAttrValue = '';
1301
+ }
1302
+ else {
1303
+ ngDevMode &&
1304
+ assertNotEqual(nodeAttrs[attrIndexInNode], 0 /* AttributeMarker.NamespaceURI */, 'We do not match directives on namespaced attributes');
1305
+ // we lowercase the attribute value to be able to match
1306
+ // selectors without case-sensitivity
1307
+ // (selectors are already in lowercase when generated)
1308
+ nodeAttrValue = nodeAttrs[attrIndexInNode + 1].toLowerCase();
1309
+ }
1310
+ const compareAgainstClassName = mode & 8 /* SelectorFlags.CLASS */ ? nodeAttrValue : null;
1311
+ if (compareAgainstClassName &&
1312
+ classIndexOf(compareAgainstClassName, selectorAttrValue, 0) !== -1 ||
1313
+ mode & 2 /* SelectorFlags.ATTRIBUTE */ && selectorAttrValue !== nodeAttrValue) {
1314
+ if (isPositive(mode))
1315
+ return false;
1316
+ skipToNextSelector = true;
1317
+ }
1318
+ }
1319
+ }
1320
+ }
1321
+ return isPositive(mode) || skipToNextSelector;
1322
+ }
1323
+ function isPositive(mode) {
1324
+ return (mode & 1 /* SelectorFlags.NOT */) === 0;
1325
+ }
1326
+ /**
1327
+ * Examines the attribute's definition array for a node to find the index of the
1328
+ * attribute that matches the given `name`.
1329
+ *
1330
+ * NOTE: This will not match namespaced attributes.
1331
+ *
1332
+ * Attribute matching depends upon `isInlineTemplate` and `isProjectionMode`.
1333
+ * The following table summarizes which types of attributes we attempt to match:
1334
+ *
1335
+ * ===========================================================================================================
1336
+ * Modes | Normal Attributes | Bindings Attributes | Template Attributes | I18n
1337
+ * Attributes
1338
+ * ===========================================================================================================
1339
+ * Inline + Projection | YES | YES | NO | YES
1340
+ * -----------------------------------------------------------------------------------------------------------
1341
+ * Inline + Directive | NO | NO | YES | NO
1342
+ * -----------------------------------------------------------------------------------------------------------
1343
+ * Non-inline + Projection | YES | YES | NO | YES
1344
+ * -----------------------------------------------------------------------------------------------------------
1345
+ * Non-inline + Directive | YES | YES | NO | YES
1346
+ * ===========================================================================================================
1347
+ *
1348
+ * @param name the name of the attribute to find
1349
+ * @param attrs the attribute array to examine
1350
+ * @param isInlineTemplate true if the node being matched is an inline template (e.g. `*ngFor`)
1351
+ * rather than a manually expanded template node (e.g `<ng-template>`).
1352
+ * @param isProjectionMode true if we are matching against content projection otherwise we are
1353
+ * matching against directives.
1354
+ */
1355
+ function findAttrIndexInNode(name, attrs, isInlineTemplate, isProjectionMode) {
1356
+ if (attrs === null)
1357
+ return -1;
1358
+ let i = 0;
1359
+ if (isProjectionMode || !isInlineTemplate) {
1360
+ let bindingsMode = false;
1361
+ while (i < attrs.length) {
1362
+ const maybeAttrName = attrs[i];
1363
+ if (maybeAttrName === name) {
1364
+ return i;
1365
+ }
1366
+ else if (maybeAttrName === 3 /* AttributeMarker.Bindings */ || maybeAttrName === 6 /* AttributeMarker.I18n */) {
1367
+ bindingsMode = true;
1368
+ }
1369
+ else if (maybeAttrName === 1 /* AttributeMarker.Classes */ || maybeAttrName === 2 /* AttributeMarker.Styles */) {
1370
+ let value = attrs[++i];
1371
+ // We should skip classes here because we have a separate mechanism for
1372
+ // matching classes in projection mode.
1373
+ while (typeof value === 'string') {
1374
+ value = attrs[++i];
1375
+ }
1376
+ continue;
1377
+ }
1378
+ else if (maybeAttrName === 4 /* AttributeMarker.Template */) {
1379
+ // We do not care about Template attributes in this scenario.
1380
+ break;
1381
+ }
1382
+ else if (maybeAttrName === 0 /* AttributeMarker.NamespaceURI */) {
1383
+ // Skip the whole namespaced attribute and value. This is by design.
1384
+ i += 4;
1385
+ continue;
1386
+ }
1387
+ // In binding mode there are only names, rather than name-value pairs.
1388
+ i += bindingsMode ? 1 : 2;
1389
+ }
1390
+ // We did not match the attribute
1391
+ return -1;
1392
+ }
1393
+ else {
1394
+ return matchTemplateAttribute(attrs, name);
1395
+ }
1396
+ }
1397
+ function isNodeMatchingSelectorList(tNode, selector, isProjectionMode = false) {
1398
+ for (let i = 0; i < selector.length; i++) {
1399
+ if (isNodeMatchingSelector(tNode, selector[i], isProjectionMode)) {
1400
+ return true;
1401
+ }
1402
+ }
1403
+ return false;
1404
+ }
1405
+ function getProjectAsAttrValue(tNode) {
1406
+ const nodeAttrs = tNode.attrs;
1407
+ if (nodeAttrs != null) {
1408
+ const ngProjectAsAttrIdx = nodeAttrs.indexOf(5 /* AttributeMarker.ProjectAs */);
1409
+ // only check for ngProjectAs in attribute names, don't accidentally match attribute's value
1410
+ // (attribute names are stored at even indexes)
1411
+ if ((ngProjectAsAttrIdx & 1) === 0) {
1412
+ return nodeAttrs[ngProjectAsAttrIdx + 1];
1413
+ }
1414
+ }
1415
+ return null;
1416
+ }
1417
+ function getNameOnlyMarkerIndex(nodeAttrs) {
1418
+ for (let i = 0; i < nodeAttrs.length; i++) {
1419
+ const nodeAttr = nodeAttrs[i];
1420
+ if (isNameOnlyAttributeMarker(nodeAttr)) {
1421
+ return i;
1422
+ }
1423
+ }
1424
+ return nodeAttrs.length;
1425
+ }
1426
+ function matchTemplateAttribute(attrs, name) {
1427
+ let i = attrs.indexOf(4 /* AttributeMarker.Template */);
1428
+ if (i > -1) {
1429
+ i++;
1430
+ while (i < attrs.length) {
1431
+ const attr = attrs[i];
1432
+ // Return in case we checked all template attrs and are switching to the next section in the
1433
+ // attrs array (that starts with a number that represents an attribute marker).
1434
+ if (typeof attr === 'number')
1435
+ return -1;
1436
+ if (attr === name)
1437
+ return i;
1438
+ i++;
1439
+ }
1440
+ }
1441
+ return -1;
1442
+ }
1443
+ /**
1444
+ * Checks whether a selector is inside a CssSelectorList
1445
+ * @param selector Selector to be checked.
1446
+ * @param list List in which to look for the selector.
1447
+ */
1448
+ function isSelectorInSelectorList(selector, list) {
1449
+ selectorListLoop: for (let i = 0; i < list.length; i++) {
1450
+ const currentSelectorInList = list[i];
1451
+ if (selector.length !== currentSelectorInList.length) {
1452
+ continue;
1453
+ }
1454
+ for (let j = 0; j < selector.length; j++) {
1455
+ if (selector[j] !== currentSelectorInList[j]) {
1456
+ continue selectorListLoop;
1457
+ }
1458
+ }
1459
+ return true;
1460
+ }
1461
+ return false;
1462
+ }
1463
+ function maybeWrapInNotSelector(isNegativeMode, chunk) {
1464
+ return isNegativeMode ? ':not(' + chunk.trim() + ')' : chunk;
1465
+ }
1466
+ function stringifyCSSSelector(selector) {
1467
+ let result = selector[0];
1468
+ let i = 1;
1469
+ let mode = 2 /* SelectorFlags.ATTRIBUTE */;
1470
+ let currentChunk = '';
1471
+ let isNegativeMode = false;
1472
+ while (i < selector.length) {
1473
+ let valueOrMarker = selector[i];
1474
+ if (typeof valueOrMarker === 'string') {
1475
+ if (mode & 2 /* SelectorFlags.ATTRIBUTE */) {
1476
+ const attrValue = selector[++i];
1477
+ currentChunk +=
1478
+ '[' + valueOrMarker + (attrValue.length > 0 ? '="' + attrValue + '"' : '') + ']';
1479
+ }
1480
+ else if (mode & 8 /* SelectorFlags.CLASS */) {
1481
+ currentChunk += '.' + valueOrMarker;
1482
+ }
1483
+ else if (mode & 4 /* SelectorFlags.ELEMENT */) {
1484
+ currentChunk += ' ' + valueOrMarker;
1485
+ }
1486
+ }
1487
+ else {
1488
+ //
1489
+ // Append current chunk to the final result in case we come across SelectorFlag, which
1490
+ // indicates that the previous section of a selector is over. We need to accumulate content
1491
+ // between flags to make sure we wrap the chunk later in :not() selector if needed, e.g.
1492
+ // ```
1493
+ // ['', Flags.CLASS, '.classA', Flags.CLASS | Flags.NOT, '.classB', '.classC']
1494
+ // ```
1495
+ // should be transformed to `.classA :not(.classB .classC)`.
1496
+ //
1497
+ // Note: for negative selector part, we accumulate content between flags until we find the
1498
+ // next negative flag. This is needed to support a case where `:not()` rule contains more than
1499
+ // one chunk, e.g. the following selector:
1500
+ // ```
1501
+ // ['', Flags.ELEMENT | Flags.NOT, 'p', Flags.CLASS, 'foo', Flags.CLASS | Flags.NOT, 'bar']
1502
+ // ```
1503
+ // should be stringified to `:not(p.foo) :not(.bar)`
1504
+ //
1505
+ if (currentChunk !== '' && !isPositive(valueOrMarker)) {
1506
+ result += maybeWrapInNotSelector(isNegativeMode, currentChunk);
1507
+ currentChunk = '';
1508
+ }
1509
+ mode = valueOrMarker;
1510
+ // According to CssSelector spec, once we come across `SelectorFlags.NOT` flag, the negative
1511
+ // mode is maintained for remaining chunks of a selector.
1512
+ isNegativeMode = isNegativeMode || !isPositive(mode);
1513
+ }
1514
+ i++;
1515
+ }
1516
+ if (currentChunk !== '') {
1517
+ result += maybeWrapInNotSelector(isNegativeMode, currentChunk);
1518
+ }
1519
+ return result;
1520
+ }
1521
+ /**
1522
+ * Generates string representation of CSS selector in parsed form.
1523
+ *
1524
+ * ComponentDef and DirectiveDef are generated with the selector in parsed form to avoid doing
1525
+ * additional parsing at runtime (for example, for directive matching). However in some cases (for
1526
+ * example, while bootstrapping a component), a string version of the selector is required to query
1527
+ * for the host element on the page. This function takes the parsed form of a selector and returns
1528
+ * its string representation.
1529
+ *
1530
+ * @param selectorList selector in parsed form
1531
+ * @returns string representation of a given selector
1532
+ */
1533
+ function stringifyCSSSelectorList(selectorList) {
1534
+ return selectorList.map(stringifyCSSSelector).join(',');
1535
+ }
1536
+ /**
1537
+ * Extracts attributes and classes information from a given CSS selector.
1538
+ *
1539
+ * This function is used while creating a component dynamically. In this case, the host element
1540
+ * (that is created dynamically) should contain attributes and classes specified in component's CSS
1541
+ * selector.
1542
+ *
1543
+ * @param selector CSS selector in parsed form (in a form of array)
1544
+ * @returns object with `attrs` and `classes` fields that contain extracted information
1545
+ */
1546
+ function extractAttrsAndClassesFromSelector(selector) {
1547
+ const attrs = [];
1548
+ const classes = [];
1549
+ let i = 1;
1550
+ let mode = 2 /* SelectorFlags.ATTRIBUTE */;
1551
+ while (i < selector.length) {
1552
+ let valueOrMarker = selector[i];
1553
+ if (typeof valueOrMarker === 'string') {
1554
+ if (mode === 2 /* SelectorFlags.ATTRIBUTE */) {
1555
+ if (valueOrMarker !== '') {
1556
+ attrs.push(valueOrMarker, selector[++i]);
1557
+ }
1558
+ }
1559
+ else if (mode === 8 /* SelectorFlags.CLASS */) {
1560
+ classes.push(valueOrMarker);
1561
+ }
1562
+ }
1563
+ else {
1564
+ // According to CssSelector spec, once we come across `SelectorFlags.NOT` flag, the negative
1565
+ // mode is maintained for remaining chunks of a selector. Since attributes and classes are
1566
+ // extracted only for "positive" part of the selector, we can stop here.
1567
+ if (!isPositive(mode))
1568
+ break;
1569
+ mode = valueOrMarker;
1570
+ }
1571
+ i++;
1572
+ }
1573
+ return { attrs, classes };
1574
+ }
1575
+
1576
+ /**
1577
+ * Create a component definition object.
1578
+ *
1579
+ *
1580
+ * # Example
1581
+ * ```
1582
+ * class MyComponent {
1583
+ * // Generated by Angular Template Compiler
1584
+ * // [Symbol] syntax will not be supported by TypeScript until v2.7
1585
+ * static ɵcmp = defineComponent({
1586
+ * ...
1587
+ * });
1588
+ * }
1589
+ * ```
1590
+ * @codeGenApi
1591
+ */
1592
+ function ɵɵdefineComponent(componentDefinition) {
1593
+ return noSideEffects(() => {
1594
+ // Initialize ngDevMode. This must be the first statement in ɵɵdefineComponent.
1595
+ // See the `initNgDevMode` docstring for more information.
1596
+ (typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode();
1597
+ const baseDef = getNgDirectiveDef(componentDefinition);
1598
+ const def = Object.assign(Object.assign({}, baseDef), { decls: componentDefinition.decls, vars: componentDefinition.vars, template: componentDefinition.template, consts: componentDefinition.consts || null, ngContentSelectors: componentDefinition.ngContentSelectors, onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush, directiveDefs: null, pipeDefs: null, dependencies: baseDef.standalone && componentDefinition.dependencies || null, getStandaloneInjector: null, data: componentDefinition.data || {}, encapsulation: componentDefinition.encapsulation || ViewEncapsulation$1.Emulated, styles: componentDefinition.styles || EMPTY_ARRAY, _: null, schemas: componentDefinition.schemas || null, tView: null, id: '' });
1599
+ initFeatures(def);
1600
+ const dependencies = componentDefinition.dependencies;
1601
+ def.directiveDefs = extractDefListOrFactory(dependencies, /* pipeDef */ false);
1602
+ def.pipeDefs = extractDefListOrFactory(dependencies, /* pipeDef */ true);
1603
+ def.id = getComponentId(def);
1604
+ return def;
1605
+ });
1606
+ }
1607
+ /**
1608
+ * Generated next to NgModules to monkey-patch directive and pipe references onto a component's
1609
+ * definition, when generating a direct reference in the component file would otherwise create an
1610
+ * import cycle.
1611
+ *
1612
+ * See [this explanation](https://hackmd.io/Odw80D0pR6yfsOjg_7XCJg?view) for more details.
1613
+ *
1614
+ * @codeGenApi
1615
+ */
1616
+ function ɵɵsetComponentScope(type, directives, pipes) {
1617
+ const def = type.ɵcmp;
1618
+ def.directiveDefs = extractDefListOrFactory(directives, /* pipeDef */ false);
1619
+ def.pipeDefs = extractDefListOrFactory(pipes, /* pipeDef */ true);
1620
+ }
1621
+ function extractDirectiveDef(type) {
1622
+ return getComponentDef(type) || getDirectiveDef(type);
1623
+ }
1624
+ function nonNull(value) {
1625
+ return value !== null;
1626
+ }
1627
+ /**
1628
+ * @codeGenApi
1629
+ */
1630
+ function ɵɵdefineNgModule(def) {
1631
+ return noSideEffects(() => {
1632
+ const res = {
1633
+ type: def.type,
1634
+ bootstrap: def.bootstrap || EMPTY_ARRAY,
1635
+ declarations: def.declarations || EMPTY_ARRAY,
1636
+ imports: def.imports || EMPTY_ARRAY,
1637
+ exports: def.exports || EMPTY_ARRAY,
1638
+ transitiveCompileScopes: null,
1639
+ schemas: def.schemas || null,
1640
+ id: def.id || null,
1641
+ };
1642
+ return res;
1643
+ });
1644
+ }
1645
+ /**
1646
+ * Adds the module metadata that is necessary to compute the module's transitive scope to an
1647
+ * existing module definition.
1648
+ *
1649
+ * Scope metadata of modules is not used in production builds, so calls to this function can be
1650
+ * marked pure to tree-shake it from the bundle, allowing for all referenced declarations
1651
+ * to become eligible for tree-shaking as well.
1652
+ *
1653
+ * @codeGenApi
1654
+ */
1655
+ function ɵɵsetNgModuleScope(type, scope) {
1656
+ return noSideEffects(() => {
1657
+ const ngModuleDef = getNgModuleDef(type, true);
1658
+ ngModuleDef.declarations = scope.declarations || EMPTY_ARRAY;
1659
+ ngModuleDef.imports = scope.imports || EMPTY_ARRAY;
1660
+ ngModuleDef.exports = scope.exports || EMPTY_ARRAY;
1661
+ });
1662
+ }
1663
+ /**
1664
+ * Inverts an inputs or outputs lookup such that the keys, which were the
1665
+ * minified keys, are part of the values, and the values are parsed so that
1666
+ * the publicName of the property is the new key
1667
+ *
1668
+ * e.g. for
1669
+ *
1670
+ * ```
1671
+ * class Comp {
1672
+ * @Input()
1673
+ * propName1: string;
1674
+ *
1675
+ * @Input('publicName2')
1676
+ * declaredPropName2: number;
1677
+ * }
1678
+ * ```
1679
+ *
1680
+ * will be serialized as
1681
+ *
1682
+ * ```
1683
+ * {
1684
+ * propName1: 'propName1',
1685
+ * declaredPropName2: ['publicName2', 'declaredPropName2'],
1686
+ * }
1687
+ * ```
1688
+ *
1689
+ * which is than translated by the minifier as:
1690
+ *
1691
+ * ```
1692
+ * {
1693
+ * minifiedPropName1: 'propName1',
1694
+ * minifiedPropName2: ['publicName2', 'declaredPropName2'],
1695
+ * }
1696
+ * ```
1697
+ *
1698
+ * becomes: (public name => minifiedName)
1699
+ *
1700
+ * ```
1701
+ * {
1702
+ * 'propName1': 'minifiedPropName1',
1703
+ * 'publicName2': 'minifiedPropName2',
1704
+ * }
1705
+ * ```
1706
+ *
1707
+ * Optionally the function can take `secondary` which will result in: (public name => declared name)
1708
+ *
1709
+ * ```
1710
+ * {
1711
+ * 'propName1': 'propName1',
1712
+ * 'publicName2': 'declaredPropName2',
1713
+ * }
1714
+ * ```
1715
+ *
1716
+
1717
+ */
1718
+ function invertObject(obj, secondary) {
1719
+ if (obj == null)
1720
+ return EMPTY_OBJ;
1721
+ const newLookup = {};
1722
+ for (const minifiedKey in obj) {
1723
+ if (obj.hasOwnProperty(minifiedKey)) {
1724
+ let publicName = obj[minifiedKey];
1725
+ let declaredName = publicName;
1726
+ if (Array.isArray(publicName)) {
1727
+ declaredName = publicName[1];
1728
+ publicName = publicName[0];
1729
+ }
1730
+ newLookup[publicName] = minifiedKey;
1731
+ if (secondary) {
1732
+ (secondary[publicName] = declaredName);
1733
+ }
1734
+ }
1735
+ }
1736
+ return newLookup;
1737
+ }
1738
+ /**
1739
+ * Create a directive definition object.
1740
+ *
1741
+ * # Example
1742
+ * ```ts
1743
+ * class MyDirective {
1744
+ * // Generated by Angular Template Compiler
1745
+ * // [Symbol] syntax will not be supported by TypeScript until v2.7
1746
+ * static ɵdir = ɵɵdefineDirective({
1747
+ * ...
1748
+ * });
1749
+ * }
1750
+ * ```
1751
+ *
1752
+ * @codeGenApi
1753
+ */
1754
+ function ɵɵdefineDirective(directiveDefinition) {
1755
+ return noSideEffects(() => {
1756
+ const def = getNgDirectiveDef(directiveDefinition);
1757
+ initFeatures(def);
1758
+ return def;
1759
+ });
1760
+ }
1761
+ /**
1762
+ * Create a pipe definition object.
1763
+ *
1764
+ * # Example
1765
+ * ```
1766
+ * class MyPipe implements PipeTransform {
1767
+ * // Generated by Angular Template Compiler
1768
+ * static ɵpipe = definePipe({
1769
+ * ...
1770
+ * });
1771
+ * }
1772
+ * ```
1773
+ * @param pipeDef Pipe definition generated by the compiler
1774
+ *
1775
+ * @codeGenApi
1776
+ */
1777
+ function ɵɵdefinePipe(pipeDef) {
1778
+ return {
1779
+ type: pipeDef.type,
1780
+ name: pipeDef.name,
1781
+ factory: null,
1782
+ pure: pipeDef.pure !== false,
1783
+ standalone: pipeDef.standalone === true,
1784
+ onDestroy: pipeDef.type.prototype.ngOnDestroy || null
1785
+ };
1786
+ }
1787
+ /**
1788
+ * The following getter methods retrieve the definition from the type. Currently the retrieval
1789
+ * honors inheritance, but in the future we may change the rule to require that definitions are
1790
+ * explicit. This would require some sort of migration strategy.
1791
+ */
1792
+ function getComponentDef(type) {
1793
+ return type[NG_COMP_DEF] || null;
1794
+ }
1795
+ function getDirectiveDef(type) {
1796
+ return type[NG_DIR_DEF] || null;
1797
+ }
1798
+ function getPipeDef$1(type) {
1799
+ return type[NG_PIPE_DEF] || null;
1800
+ }
1801
+ /**
1802
+ * Checks whether a given Component, Directive or Pipe is marked as standalone.
1803
+ * This will return false if passed anything other than a Component, Directive, or Pipe class
1804
+ * See this guide for additional information: https://angular.io/guide/standalone-components
1805
+ *
1806
+ * @param type A reference to a Component, Directive or Pipe.
1807
+ * @publicApi
1808
+ */
1809
+ function isStandalone(type) {
1810
+ const def = getComponentDef(type) || getDirectiveDef(type) || getPipeDef$1(type);
1811
+ return def !== null ? def.standalone : false;
1812
+ }
1813
+ function getNgModuleDef(type, throwNotFound) {
1814
+ const ngModuleDef = type[NG_MOD_DEF] || null;
1815
+ if (!ngModuleDef && throwNotFound === true) {
1816
+ throw new Error(`Type ${stringify(type)} does not have 'ɵmod' property.`);
1817
+ }
1818
+ return ngModuleDef;
1819
+ }
1820
+ function getNgDirectiveDef(directiveDefinition) {
1821
+ const declaredInputs = {};
1822
+ return {
1823
+ type: directiveDefinition.type,
1824
+ providersResolver: null,
1825
+ factory: null,
1826
+ hostBindings: directiveDefinition.hostBindings || null,
1827
+ hostVars: directiveDefinition.hostVars || 0,
1828
+ hostAttrs: directiveDefinition.hostAttrs || null,
1829
+ contentQueries: directiveDefinition.contentQueries || null,
1830
+ declaredInputs,
1831
+ exportAs: directiveDefinition.exportAs || null,
1832
+ standalone: directiveDefinition.standalone === true,
1833
+ selectors: directiveDefinition.selectors || EMPTY_ARRAY,
1834
+ viewQuery: directiveDefinition.viewQuery || null,
1835
+ features: directiveDefinition.features || null,
1836
+ setInput: null,
1837
+ findHostDirectiveDefs: null,
1838
+ hostDirectives: null,
1839
+ inputs: invertObject(directiveDefinition.inputs, declaredInputs),
1840
+ outputs: invertObject(directiveDefinition.outputs),
1841
+ };
1842
+ }
1843
+ function initFeatures(definition) {
1844
+ var _a;
1845
+ (_a = definition.features) === null || _a === void 0 ? void 0 : _a.forEach((fn) => fn(definition));
1846
+ }
1847
+ function extractDefListOrFactory(dependencies, pipeDef) {
1848
+ if (!dependencies) {
1849
+ return null;
1850
+ }
1851
+ const defExtractor = pipeDef ? getPipeDef$1 : extractDirectiveDef;
1852
+ return () => (typeof dependencies === 'function' ? dependencies() : dependencies)
1853
+ .map(dep => defExtractor(dep))
1854
+ .filter(nonNull);
1855
+ }
1856
+ /**
1857
+ * A map that contains the generated component IDs and type.
1858
+ */
1859
+ const GENERATED_COMP_IDS = new Map();
1860
+ /**
1861
+ * A method can returns a component ID from the component definition using a variant of DJB2 hash
1862
+ * algorithm.
1863
+ */
1864
+ function getComponentId(componentDef) {
1865
+ let hash = 0;
1866
+ // We cannot rely solely on the component selector as the same selector can be used in different
1867
+ // modules.
1868
+ //
1869
+ // `componentDef.style` is not used, due to it causing inconsistencies. Ex: when server
1870
+ // component styles has no sourcemaps and browsers do.
1871
+ //
1872
+ // Example:
1873
+ // https://github.com/angular/components/blob/d9f82c8f95309e77a6d82fd574c65871e91354c2/src/material/core/option/option.ts#L248
1874
+ // https://github.com/angular/components/blob/285f46dc2b4c5b127d356cb7c4714b221f03ce50/src/material/legacy-core/option/option.ts#L32
1875
+ const hashSelectors = [
1876
+ componentDef.selectors,
1877
+ componentDef.ngContentSelectors,
1878
+ componentDef.hostVars,
1879
+ componentDef.hostAttrs,
1880
+ componentDef.consts,
1881
+ componentDef.vars,
1882
+ componentDef.decls,
1883
+ componentDef.encapsulation,
1884
+ componentDef.standalone,
1885
+ // We cannot use 'componentDef.type.name' as the name of the symbol will change and will not
1886
+ // match in the server and browser bundles.
1887
+ Object.getOwnPropertyNames(componentDef.type.prototype),
1888
+ !!componentDef.contentQueries,
1889
+ !!componentDef.viewQuery,
1890
+ ].join('|');
1891
+ for (const char of hashSelectors) {
1892
+ hash = Math.imul(31, hash) + char.charCodeAt(0) << 0;
1893
+ }
1894
+ // Force positive number hash.
1895
+ // 2147483647 = equivalent of Integer.MAX_VALUE.
1896
+ hash += 2147483647 + 1;
1897
+ const compId = 'c' + hash;
1898
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
1899
+ if (GENERATED_COMP_IDS.has(compId)) {
1900
+ const previousCompDefType = GENERATED_COMP_IDS.get(compId);
1901
+ if (previousCompDefType !== componentDef.type) {
1902
+ // TODO: use `formatRuntimeError` to have an error code and we can later on create an error
1903
+ // guide to explain this further.
1904
+ console.warn(`Component ID generation collision detected. Components '${previousCompDefType.name}' and '${componentDef.type.name}' with selector '${stringifyCSSSelectorList(componentDef
1905
+ .selectors)}' generated the same component ID. To fix this, you can change the selector of one of those components or add an extra host attribute to force a different ID.`);
1906
+ }
1907
+ }
1908
+ else {
1909
+ GENERATED_COMP_IDS.set(compId, componentDef.type);
1910
+ }
1911
+ }
1912
+ return compId;
1913
+ }
1914
+
1915
+ /**
1916
+ * Special location which allows easy identification of type. If we have an array which was
1917
+ * retrieved from the `LView` and that array has `true` at `TYPE` location, we know it is
1918
+ * `LContainer`.
1919
+ */
1920
+ const TYPE = 1;
1921
+ /**
1922
+ * Below are constants for LContainer indices to help us look up LContainer members
1923
+ * without having to remember the specific indices.
1924
+ * Uglify will inline these when minifying so there shouldn't be a cost.
1925
+ */
1926
+ /**
1927
+ * Flag to signify that this `LContainer` may have transplanted views which need to be change
1928
+ * detected. (see: `LView[DECLARATION_COMPONENT_VIEW])`.
1929
+ *
1930
+ * This flag, once set, is never unset for the `LContainer`. This means that when unset we can skip
1931
+ * a lot of work in `refreshEmbeddedViews`. But when set we still need to verify
1932
+ * that the `MOVED_VIEWS` are transplanted and on-push.
1933
+ */
1934
+ const HAS_TRANSPLANTED_VIEWS = 2;
1935
+ // PARENT, NEXT, TRANSPLANTED_VIEWS_TO_REFRESH are indices 3, 4, and 5
1936
+ // As we already have these constants in LView, we don't need to re-create them.
1937
+ // T_HOST is index 6
1938
+ // We already have this constants in LView, we don't need to re-create it.
1939
+ const NATIVE = 7;
1940
+ const VIEW_REFS = 8;
1941
+ const MOVED_VIEWS = 9;
1942
+ const DEHYDRATED_VIEWS = 10;
1943
+ /**
1944
+ * Size of LContainer's header. Represents the index after which all views in the
1945
+ * container will be inserted. We need to keep a record of current views so we know
1946
+ * which views are already in the DOM (and don't need to be re-added) and so we can
1947
+ * remove views from the DOM when they are no longer required.
1948
+ */
1949
+ const CONTAINER_HEADER_OFFSET = 11;
1950
+ // Note: This hack is necessary so we don't erroneously get a circular dependency
1951
+ // failure based on types.
1952
+ const unusedValueExportToPlacateAjd$4 = 1;
1953
+
1954
+ // Below are constants for LView indices to help us look up LView members
1955
+ // without having to remember the specific indices.
1956
+ // Uglify will inline these when minifying so there shouldn't be a cost.
1957
+ const HOST = 0;
1958
+ const TVIEW = 1;
1959
+ const FLAGS = 2;
1960
+ const PARENT = 3;
1961
+ const NEXT = 4;
1962
+ const TRANSPLANTED_VIEWS_TO_REFRESH = 5;
1963
+ const T_HOST = 6;
1964
+ const CLEANUP = 7;
1965
+ const CONTEXT = 8;
1966
+ const INJECTOR$1 = 9;
1967
+ const RENDERER_FACTORY = 10;
1968
+ const RENDERER = 11;
1969
+ const SANITIZER = 12;
1970
+ const CHILD_HEAD = 13;
1971
+ const CHILD_TAIL = 14;
1972
+ // FIXME(misko): Investigate if the three declarations aren't all same thing.
1973
+ const DECLARATION_VIEW = 15;
1974
+ const DECLARATION_COMPONENT_VIEW = 16;
1975
+ const DECLARATION_LCONTAINER = 17;
1290
1976
  const PREORDER_HOOK_FLAGS = 18;
1291
1977
  const QUERIES = 19;
1292
1978
  const ID = 20;
@@ -1329,7 +2015,7 @@ function isDirectiveHost(tNode) {
1329
2015
  return (tNode.flags & 1 /* TNodeFlags.isDirectiveHost */) === 1 /* TNodeFlags.isDirectiveHost */;
1330
2016
  }
1331
2017
  function isComponentDef(def) {
1332
- return def.template !== null;
2018
+ return !!def.template;
1333
2019
  }
1334
2020
  function isRootView(target) {
1335
2021
  return (target[FLAGS] & 256 /* LViewFlags.IsRoot */) !== 0;
@@ -1786,7 +2472,7 @@ function getBindingsEnabled() {
1786
2472
  * Returns true if currently inside a skip hydration block.
1787
2473
  * @returns boolean
1788
2474
  */
1789
- function isInSkipHydrationBlock() {
2475
+ function isInSkipHydrationBlock$1() {
1790
2476
  return instructionState.skipHydrationRootTNode !== null;
1791
2477
  }
1792
2478
  /**
@@ -2669,265 +3355,65 @@ const unusedValueExportToPlacateAjd$1 = 1;
2669
3355
  * ```
2670
3356
  * <div my-dir [class]="exp"></div>
2671
3357
  * ```
2672
- * and
2673
- * ```
2674
- * @Directive({
2675
- * })
2676
- * class MyDirective {
2677
- * @Input()
2678
- * class: string;
2679
- * }
2680
- * ```
2681
- *
2682
- * In the above case it is necessary to write the reconciled styling information into the
2683
- * directive's input.
2684
- *
2685
- * @param tNode
2686
- */
2687
- function hasClassInput(tNode) {
2688
- return (tNode.flags & 8 /* TNodeFlags.hasClassInput */) !== 0;
2689
- }
2690
- /**
2691
- * Returns `true` if the `TNode` has a directive which has `@Input()` for `style` binding.
2692
- *
2693
- * ```
2694
- * <div my-dir [style]="exp"></div>
2695
- * ```
2696
- * and
2697
- * ```
2698
- * @Directive({
2699
- * })
2700
- * class MyDirective {
2701
- * @Input()
2702
- * class: string;
2703
- * }
2704
- * ```
2705
- *
2706
- * In the above case it is necessary to write the reconciled styling information into the
2707
- * directive's input.
2708
- *
2709
- * @param tNode
2710
- */
2711
- function hasStyleInput(tNode) {
2712
- return (tNode.flags & 16 /* TNodeFlags.hasStyleInput */) !== 0;
2713
- }
2714
-
2715
- function assertTNodeType(tNode, expectedTypes, message) {
2716
- assertDefined(tNode, 'should be called with a TNode');
2717
- if ((tNode.type & expectedTypes) === 0) {
2718
- throwError(message ||
2719
- `Expected [${toTNodeTypeAsString(expectedTypes)}] but got ${toTNodeTypeAsString(tNode.type)}.`);
2720
- }
2721
- }
2722
- function assertPureTNodeType(type) {
2723
- if (!(type === 2 /* TNodeType.Element */ || //
2724
- type === 1 /* TNodeType.Text */ || //
2725
- type === 4 /* TNodeType.Container */ || //
2726
- type === 8 /* TNodeType.ElementContainer */ || //
2727
- type === 32 /* TNodeType.Icu */ || //
2728
- type === 16 /* TNodeType.Projection */ || //
2729
- type === 64 /* TNodeType.Placeholder */)) {
2730
- throwError(`Expected TNodeType to have only a single type selected, but got ${toTNodeTypeAsString(type)}.`);
2731
- }
2732
- }
2733
-
2734
- /**
2735
- * Assigns all attribute values to the provided element via the inferred renderer.
2736
- *
2737
- * This function accepts two forms of attribute entries:
2738
- *
2739
- * default: (key, value):
2740
- * attrs = [key1, value1, key2, value2]
2741
- *
2742
- * namespaced: (NAMESPACE_MARKER, uri, name, value)
2743
- * attrs = [NAMESPACE_MARKER, uri, name, value, NAMESPACE_MARKER, uri, name, value]
2744
- *
2745
- * The `attrs` array can contain a mix of both the default and namespaced entries.
2746
- * The "default" values are set without a marker, but if the function comes across
2747
- * a marker value then it will attempt to set a namespaced value. If the marker is
2748
- * not of a namespaced value then the function will quit and return the index value
2749
- * where it stopped during the iteration of the attrs array.
2750
- *
2751
- * See [AttributeMarker] to understand what the namespace marker value is.
2752
- *
2753
- * Note that this instruction does not support assigning style and class values to
2754
- * an element. See `elementStart` and `elementHostAttrs` to learn how styling values
2755
- * are applied to an element.
2756
- * @param renderer The renderer to be used
2757
- * @param native The element that the attributes will be assigned to
2758
- * @param attrs The attribute array of values that will be assigned to the element
2759
- * @returns the index value that was last accessed in the attributes array
2760
- */
2761
- function setUpAttributes(renderer, native, attrs) {
2762
- let i = 0;
2763
- while (i < attrs.length) {
2764
- const value = attrs[i];
2765
- if (typeof value === 'number') {
2766
- // only namespaces are supported. Other value types (such as style/class
2767
- // entries) are not supported in this function.
2768
- if (value !== 0 /* AttributeMarker.NamespaceURI */) {
2769
- break;
2770
- }
2771
- // we just landed on the marker value ... therefore
2772
- // we should skip to the next entry
2773
- i++;
2774
- const namespaceURI = attrs[i++];
2775
- const attrName = attrs[i++];
2776
- const attrVal = attrs[i++];
2777
- ngDevMode && ngDevMode.rendererSetAttribute++;
2778
- renderer.setAttribute(native, attrName, attrVal, namespaceURI);
2779
- }
2780
- else {
2781
- // attrName is string;
2782
- const attrName = value;
2783
- const attrVal = attrs[++i];
2784
- // Standard attributes
2785
- ngDevMode && ngDevMode.rendererSetAttribute++;
2786
- if (isAnimationProp(attrName)) {
2787
- renderer.setProperty(native, attrName, attrVal);
2788
- }
2789
- else {
2790
- renderer.setAttribute(native, attrName, attrVal);
2791
- }
2792
- i++;
2793
- }
2794
- }
2795
- // another piece of code may iterate over the same attributes array. Therefore
2796
- // it may be helpful to return the exact spot where the attributes array exited
2797
- // whether by running into an unsupported marker or if all the static values were
2798
- // iterated over.
2799
- return i;
2800
- }
2801
- /**
2802
- * Test whether the given value is a marker that indicates that the following
2803
- * attribute values in a `TAttributes` array are only the names of attributes,
2804
- * and not name-value pairs.
2805
- * @param marker The attribute marker to test.
2806
- * @returns true if the marker is a "name-only" marker (e.g. `Bindings`, `Template` or `I18n`).
2807
- */
2808
- function isNameOnlyAttributeMarker(marker) {
2809
- return marker === 3 /* AttributeMarker.Bindings */ || marker === 4 /* AttributeMarker.Template */ ||
2810
- marker === 6 /* AttributeMarker.I18n */;
2811
- }
2812
- function isAnimationProp(name) {
2813
- // Perf note: accessing charCodeAt to check for the first character of a string is faster as
2814
- // compared to accessing a character at index 0 (ex. name[0]). The main reason for this is that
2815
- // charCodeAt doesn't allocate memory to return a substring.
2816
- return name.charCodeAt(0) === 64 /* CharCode.AT_SIGN */;
2817
- }
2818
- /**
2819
- * Merges `src` `TAttributes` into `dst` `TAttributes` removing any duplicates in the process.
2820
- *
2821
- * This merge function keeps the order of attrs same.
2822
- *
2823
- * @param dst Location of where the merged `TAttributes` should end up.
2824
- * @param src `TAttributes` which should be appended to `dst`
2825
- */
2826
- function mergeHostAttrs(dst, src) {
2827
- if (src === null || src.length === 0) {
2828
- // do nothing
2829
- }
2830
- else if (dst === null || dst.length === 0) {
2831
- // We have source, but dst is empty, just make a copy.
2832
- dst = src.slice();
2833
- }
2834
- else {
2835
- let srcMarker = -1 /* AttributeMarker.ImplicitAttributes */;
2836
- for (let i = 0; i < src.length; i++) {
2837
- const item = src[i];
2838
- if (typeof item === 'number') {
2839
- srcMarker = item;
2840
- }
2841
- else {
2842
- if (srcMarker === 0 /* AttributeMarker.NamespaceURI */) {
2843
- // Case where we need to consume `key1`, `key2`, `value` items.
2844
- }
2845
- else if (srcMarker === -1 /* AttributeMarker.ImplicitAttributes */ ||
2846
- srcMarker === 2 /* AttributeMarker.Styles */) {
2847
- // Case where we have to consume `key1` and `value` only.
2848
- mergeHostAttribute(dst, srcMarker, item, null, src[++i]);
2849
- }
2850
- else {
2851
- // Case where we have to consume `key1` only.
2852
- mergeHostAttribute(dst, srcMarker, item, null, null);
2853
- }
2854
- }
2855
- }
2856
- }
2857
- return dst;
3358
+ * and
3359
+ * ```
3360
+ * @Directive({
3361
+ * })
3362
+ * class MyDirective {
3363
+ * @Input()
3364
+ * class: string;
3365
+ * }
3366
+ * ```
3367
+ *
3368
+ * In the above case it is necessary to write the reconciled styling information into the
3369
+ * directive's input.
3370
+ *
3371
+ * @param tNode
3372
+ */
3373
+ function hasClassInput(tNode) {
3374
+ return (tNode.flags & 8 /* TNodeFlags.hasClassInput */) !== 0;
2858
3375
  }
2859
3376
  /**
2860
- * Append `key`/`value` to existing `TAttributes` taking region marker and duplicates into account.
3377
+ * Returns `true` if the `TNode` has a directive which has `@Input()` for `style` binding.
2861
3378
  *
2862
- * @param dst `TAttributes` to append to.
2863
- * @param marker Region where the `key`/`value` should be added.
2864
- * @param key1 Key to add to `TAttributes`
2865
- * @param key2 Key to add to `TAttributes` (in case of `AttributeMarker.NamespaceURI`)
2866
- * @param value Value to add or to overwrite to `TAttributes` Only used if `marker` is not Class.
3379
+ * ```
3380
+ * <div my-dir [style]="exp"></div>
3381
+ * ```
3382
+ * and
3383
+ * ```
3384
+ * @Directive({
3385
+ * })
3386
+ * class MyDirective {
3387
+ * @Input()
3388
+ * class: string;
3389
+ * }
3390
+ * ```
3391
+ *
3392
+ * In the above case it is necessary to write the reconciled styling information into the
3393
+ * directive's input.
3394
+ *
3395
+ * @param tNode
2867
3396
  */
2868
- function mergeHostAttribute(dst, marker, key1, key2, value) {
2869
- let i = 0;
2870
- // Assume that new markers will be inserted at the end.
2871
- let markerInsertPosition = dst.length;
2872
- // scan until correct type.
2873
- if (marker === -1 /* AttributeMarker.ImplicitAttributes */) {
2874
- markerInsertPosition = -1;
2875
- }
2876
- else {
2877
- while (i < dst.length) {
2878
- const dstValue = dst[i++];
2879
- if (typeof dstValue === 'number') {
2880
- if (dstValue === marker) {
2881
- markerInsertPosition = -1;
2882
- break;
2883
- }
2884
- else if (dstValue > marker) {
2885
- // We need to save this as we want the markers to be inserted in specific order.
2886
- markerInsertPosition = i - 1;
2887
- break;
2888
- }
2889
- }
2890
- }
2891
- }
2892
- // search until you find place of insertion
2893
- while (i < dst.length) {
2894
- const item = dst[i];
2895
- if (typeof item === 'number') {
2896
- // since `i` started as the index after the marker, we did not find it if we are at the next
2897
- // marker
2898
- break;
2899
- }
2900
- else if (item === key1) {
2901
- // We already have same token
2902
- if (key2 === null) {
2903
- if (value !== null) {
2904
- dst[i + 1] = value;
2905
- }
2906
- return;
2907
- }
2908
- else if (key2 === dst[i + 1]) {
2909
- dst[i + 2] = value;
2910
- return;
2911
- }
2912
- }
2913
- // Increment counter.
2914
- i++;
2915
- if (key2 !== null)
2916
- i++;
2917
- if (value !== null)
2918
- i++;
2919
- }
2920
- // insert at location.
2921
- if (markerInsertPosition !== -1) {
2922
- dst.splice(markerInsertPosition, 0, marker);
2923
- i = markerInsertPosition + 1;
2924
- }
2925
- dst.splice(i++, 0, key1);
2926
- if (key2 !== null) {
2927
- dst.splice(i++, 0, key2);
3397
+ function hasStyleInput(tNode) {
3398
+ return (tNode.flags & 16 /* TNodeFlags.hasStyleInput */) !== 0;
3399
+ }
3400
+
3401
+ function assertTNodeType(tNode, expectedTypes, message) {
3402
+ assertDefined(tNode, 'should be called with a TNode');
3403
+ if ((tNode.type & expectedTypes) === 0) {
3404
+ throwError(message ||
3405
+ `Expected [${toTNodeTypeAsString(expectedTypes)}] but got ${toTNodeTypeAsString(tNode.type)}.`);
2928
3406
  }
2929
- if (value !== null) {
2930
- dst.splice(i++, 0, value);
3407
+ }
3408
+ function assertPureTNodeType(type) {
3409
+ if (!(type === 2 /* TNodeType.Element */ || //
3410
+ type === 1 /* TNodeType.Text */ || //
3411
+ type === 4 /* TNodeType.Container */ || //
3412
+ type === 8 /* TNodeType.ElementContainer */ || //
3413
+ type === 32 /* TNodeType.Icu */ || //
3414
+ type === 16 /* TNodeType.Projection */ || //
3415
+ type === 64 /* TNodeType.Placeholder */)) {
3416
+ throwError(`Expected TNodeType to have only a single type selected, but got ${toTNodeTypeAsString(type)}.`);
2931
3417
  }
2932
3418
  }
2933
3419
 
@@ -8232,35 +8718,41 @@ function forEachSingleProvider(providers, fn) {
8232
8718
  }
8233
8719
 
8234
8720
  /**
8235
- * A [DI token](guide/glossary#di-token "DI token definition") representing a unique string ID, used
8721
+ * A [DI token](guide/glossary#di-token "DI token definition") representing a string ID, used
8236
8722
  * primarily for prefixing application attributes and CSS styles when
8237
8723
  * {@link ViewEncapsulation#Emulated ViewEncapsulation.Emulated} is being used.
8238
8724
  *
8239
- * BY default, the value is randomly generated and assigned to the application by Angular.
8240
- * To provide a custom ID value, use a DI provider <!-- TODO: provider --> to configure
8241
- * the root {@link Injector} that uses this token.
8725
+ * The token is needed in cases when multiple applications are bootstrapped on a page
8726
+ * (for example, using `bootstrapApplication` calls). In this case, ensure that those applications
8727
+ * have different `APP_ID` value setup. For example:
8728
+ *
8729
+ * ```
8730
+ * bootstrapApplication(ComponentA, {
8731
+ * providers: [
8732
+ * { provide: APP_ID, useValue: 'app-a' },
8733
+ * // ... other providers ...
8734
+ * ]
8735
+ * });
8736
+ *
8737
+ * bootstrapApplication(ComponentB, {
8738
+ * providers: [
8739
+ * { provide: APP_ID, useValue: 'app-b' },
8740
+ * // ... other providers ...
8741
+ * ]
8742
+ * });
8743
+ * ```
8744
+ *
8745
+ * By default, when there is only one application bootstrapped, you don't need to provide the
8746
+ * `APP_ID` token (the `ng` will be used as an app ID).
8242
8747
  *
8243
8748
  * @publicApi
8244
8749
  */
8245
8750
  const APP_ID = new InjectionToken('AppId', {
8246
8751
  providedIn: 'root',
8247
- factory: _appIdRandomProviderFactory,
8752
+ factory: () => DEFAULT_APP_ID,
8248
8753
  });
8249
- function _appIdRandomProviderFactory() {
8250
- return `${_randomChar()}${_randomChar()}${_randomChar()}`;
8251
- }
8252
- /**
8253
- * Providers that generate a random `APP_ID_TOKEN`.
8254
- * @publicApi
8255
- */
8256
- const APP_ID_RANDOM_PROVIDER = {
8257
- provide: APP_ID,
8258
- useFactory: _appIdRandomProviderFactory,
8259
- deps: [],
8260
- };
8261
- function _randomChar() {
8262
- return String.fromCharCode(97 + Math.floor(Math.random() * 25));
8263
- }
8754
+ /** Default value of the `APP_ID` token. */
8755
+ const DEFAULT_APP_ID = 'ng';
8264
8756
  /**
8265
8757
  * A function that is executed when a platform is initialized.
8266
8758
  * @publicApi
@@ -8431,8 +8923,15 @@ function retrieveTransferredState(doc, appId) {
8431
8923
  return initialState;
8432
8924
  }
8433
8925
 
8434
- /* Represents a key in NghDom that holds information about <ng-container>s. */
8926
+ /**
8927
+ * Keys within serialized view data structure to represent various
8928
+ * parts. See the `SerializedView` interface below for additional information.
8929
+ */
8435
8930
  const ELEMENT_CONTAINERS = 'e';
8931
+ const TEMPLATES = 't';
8932
+ const CONTAINERS = 'c';
8933
+ const NUM_ROOT_NODES = 'r';
8934
+ const TEMPLATE_ID = 'i'; // as it's also an "id"
8436
8935
 
8437
8936
  /**
8438
8937
  * The name of the key used in the TransferState collection,
@@ -8492,932 +8991,576 @@ function retrieveHydrationInfoImpl(rNode, injector) {
8492
8991
  // template instructions.
8493
8992
  ngDevMode && markRNodeAsClaimedByHydration(rNode, /* checkIfAlreadyClaimed */ false);
8494
8993
  ngDevMode && ngDevMode.hydratedComponents++;
8495
- return dehydratedView;
8496
- }
8497
- /**
8498
- * Sets the implementation for the `retrieveNghInfo` function.
8499
- */
8500
- function enableRetrieveHydrationInfoImpl() {
8501
- _retrieveHydrationInfoImpl = retrieveHydrationInfoImpl;
8502
- }
8503
- /**
8504
- * Retrieves hydration info by reading the value from the `ngh` attribute
8505
- * and accessing a corresponding slot in TransferState storage.
8506
- */
8507
- function retrieveHydrationInfo(rNode, injector) {
8508
- return _retrieveHydrationInfoImpl(rNode, injector);
8509
- }
8510
- /**
8511
- * Retrieves an instance of a component LView from a given ViewRef.
8512
- * Returns an instance of a component LView or `null` in case of an embedded view.
8513
- */
8514
- function getComponentLViewForHydration(viewRef) {
8515
- // Reading an internal field from `ViewRef` instance.
8516
- let lView = viewRef._lView;
8517
- const tView = lView[TVIEW];
8518
- // A registered ViewRef might represent an instance of an
8519
- // embedded view, in which case we do not need to annotate it.
8520
- if (tView.type === 2 /* TViewType.Embedded */) {
8521
- return null;
8522
- }
8523
- // Check if it's a root view and if so, retrieve component's
8524
- // LView from the first slot after the header.
8525
- if (isRootView(lView)) {
8526
- lView = lView[HEADER_OFFSET];
8527
- }
8528
- return lView;
8529
- }
8530
- /**
8531
- * Marks a node as "claimed" by hydration process.
8532
- * This is needed to make assessments in tests whether
8533
- * the hydration process handled all nodes.
8534
- */
8535
- function markRNodeAsClaimedByHydration(node, checkIfAlreadyClaimed = true) {
8536
- if (!ngDevMode) {
8537
- throw new Error('Calling `markRNodeAsClaimedByHydration` in prod mode ' +
8538
- 'is not supported and likely a mistake.');
8539
- }
8540
- if (checkIfAlreadyClaimed && isRNodeClaimedForHydration(node)) {
8541
- throw new Error('Trying to claim a node, which was claimed already.');
8542
- }
8543
- node.__claimed = true;
8544
- ngDevMode.hydratedNodes++;
8545
- }
8546
- function isRNodeClaimedForHydration(node) {
8547
- return !!node.__claimed;
8548
- }
8549
- function storeNgContainerInfo(hydrationInfo, index, firstChild) {
8550
- var _a;
8551
- (_a = hydrationInfo.ngContainers) !== null && _a !== void 0 ? _a : (hydrationInfo.ngContainers = {});
8552
- hydrationInfo.ngContainers[index] = { firstChild };
8553
- }
8554
- function getNgContainerSize(hydrationInfo, index) {
8555
- var _a, _b;
8556
- return (_b = (_a = hydrationInfo.data[ELEMENT_CONTAINERS]) === null || _a === void 0 ? void 0 : _a[index]) !== null && _b !== void 0 ? _b : null;
8557
- }
8558
-
8559
- /**
8560
- * Represents a component created by a `ComponentFactory`.
8561
- * Provides access to the component instance and related objects,
8562
- * and provides the means of destroying the instance.
8563
- *
8564
- * @publicApi
8565
- */
8566
- class ComponentRef$1 {
8567
- }
8568
- /**
8569
- * Base class for a factory that can create a component dynamically.
8570
- * Instantiate a factory for a given type of component with `resolveComponentFactory()`.
8571
- * Use the resulting `ComponentFactory.create()` method to create a component of that type.
8572
- *
8573
- * @see [Dynamic Components](guide/dynamic-component-loader)
8574
- *
8575
- * @publicApi
8576
- *
8577
- * @deprecated Angular no longer requires Component factories. Please use other APIs where
8578
- * Component class can be used directly.
8579
- */
8580
- class ComponentFactory$1 {
8581
- }
8582
-
8583
- function noComponentFactoryError(component) {
8584
- const error = Error(`No component factory found for ${stringify(component)}. Did you add it to @NgModule.entryComponents?`);
8585
- error[ERROR_COMPONENT] = component;
8586
- return error;
8587
- }
8588
- const ERROR_COMPONENT = 'ngComponent';
8589
- function getComponent$1(error) {
8590
- return error[ERROR_COMPONENT];
8591
- }
8592
- class _NullComponentFactoryResolver {
8593
- resolveComponentFactory(component) {
8594
- throw noComponentFactoryError(component);
8595
- }
8596
- }
8597
- /**
8598
- * A simple registry that maps `Components` to generated `ComponentFactory` classes
8599
- * that can be used to create instances of components.
8600
- * Use to obtain the factory for a given component type,
8601
- * then use the factory's `create()` method to create a component of that type.
8602
- *
8603
- * Note: since v13, dynamic component creation via
8604
- * [`ViewContainerRef.createComponent`](api/core/ViewContainerRef#createComponent)
8605
- * does **not** require resolving component factory: component class can be used directly.
8606
- *
8607
- * @publicApi
8608
- *
8609
- * @deprecated Angular no longer requires Component factories. Please use other APIs where
8610
- * Component class can be used directly.
8611
- */
8612
- class ComponentFactoryResolver$1 {
8994
+ return dehydratedView;
8613
8995
  }
8614
- ComponentFactoryResolver$1.NULL = ( /* @__PURE__ */new _NullComponentFactoryResolver());
8615
-
8616
8996
  /**
8617
- * Creates an ElementRef from the most recent node.
8618
- *
8619
- * @returns The ElementRef instance to use
8997
+ * Sets the implementation for the `retrieveHydrationInfo` function.
8620
8998
  */
8621
- function injectElementRef() {
8622
- return createElementRef(getCurrentTNode(), getLView());
8999
+ function enableRetrieveHydrationInfoImpl() {
9000
+ _retrieveHydrationInfoImpl = retrieveHydrationInfoImpl;
8623
9001
  }
8624
9002
  /**
8625
- * Creates an ElementRef given a node.
8626
- *
8627
- * @param tNode The node for which you'd like an ElementRef
8628
- * @param lView The view to which the node belongs
8629
- * @returns The ElementRef instance to use
9003
+ * Retrieves hydration info by reading the value from the `ngh` attribute
9004
+ * and accessing a corresponding slot in TransferState storage.
8630
9005
  */
8631
- function createElementRef(tNode, lView) {
8632
- return new ElementRef(getNativeByTNode(tNode, lView));
9006
+ function retrieveHydrationInfo(rNode, injector) {
9007
+ return _retrieveHydrationInfoImpl(rNode, injector);
8633
9008
  }
8634
9009
  /**
8635
- * A wrapper around a native element inside of a View.
8636
- *
8637
- * An `ElementRef` is backed by a render-specific element. In the browser, this is usually a DOM
8638
- * element.
8639
- *
8640
- * @security Permitting direct access to the DOM can make your application more vulnerable to
8641
- * XSS attacks. Carefully review any use of `ElementRef` in your code. For more detail, see the
8642
- * [Security Guide](https://g.co/ng/security).
8643
- *
8644
- * @publicApi
9010
+ * Retrieves an instance of a component LView from a given ViewRef.
9011
+ * Returns an instance of a component LView or `null` in case of an embedded view.
8645
9012
  */
8646
- // Note: We don't expose things like `Injector`, `ViewContainer`, ... here,
8647
- // i.e. users have to ask for what they need. With that, we can build better analysis tools
8648
- // and could do better codegen in the future.
8649
- class ElementRef {
8650
- constructor(nativeElement) {
8651
- this.nativeElement = nativeElement;
9013
+ function getComponentLViewForHydration(viewRef) {
9014
+ // Reading an internal field from `ViewRef` instance.
9015
+ let lView = viewRef._lView;
9016
+ const tView = lView[TVIEW];
9017
+ // A registered ViewRef might represent an instance of an
9018
+ // embedded view, in which case we do not need to annotate it.
9019
+ if (tView.type === 2 /* TViewType.Embedded */) {
9020
+ return null;
9021
+ }
9022
+ // Check if it's a root view and if so, retrieve component's
9023
+ // LView from the first slot after the header.
9024
+ if (isRootView(lView)) {
9025
+ lView = lView[HEADER_OFFSET];
8652
9026
  }
9027
+ return lView;
8653
9028
  }
8654
- /**
8655
- * @internal
8656
- * @nocollapse
8657
- */
8658
- ElementRef.__NG_ELEMENT_ID__ = injectElementRef;
8659
- /**
8660
- * Unwraps `ElementRef` and return the `nativeElement`.
8661
- *
8662
- * @param value value to unwrap
8663
- * @returns `nativeElement` if `ElementRef` otherwise returns value as is.
8664
- */
8665
- function unwrapElementRef(value) {
8666
- return value instanceof ElementRef ? value.nativeElement : value;
9029
+ function getTextNodeContent(node) {
9030
+ var _a;
9031
+ return (_a = node.textContent) === null || _a === void 0 ? void 0 : _a.replace(/\s/gm, '');
8667
9032
  }
8668
-
8669
9033
  /**
8670
- * Creates and initializes a custom renderer that implements the `Renderer2` base class.
9034
+ * Restores text nodes and separators into the DOM that were lost during SSR
9035
+ * serialization. The hydration process replaces empty text nodes and text
9036
+ * nodes that are immediately adjacent to other text nodes with comment nodes
9037
+ * that this method filters on to restore those missing nodes that the
9038
+ * hydration process is expecting to be present.
8671
9039
  *
8672
- * @publicApi
9040
+ * @param node The app's root HTML Element
8673
9041
  */
8674
- class RendererFactory2 {
9042
+ function processTextNodeMarkersBeforeHydration(node) {
9043
+ const doc = getDocument();
9044
+ const commentNodesIterator = doc.createNodeIterator(node, NodeFilter.SHOW_COMMENT, {
9045
+ acceptNode(node) {
9046
+ const content = getTextNodeContent(node);
9047
+ const isTextNodeMarker = content === "ngetn" /* TextNodeMarker.EmptyNode */ || content === "ngtns" /* TextNodeMarker.Separator */;
9048
+ return isTextNodeMarker ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
9049
+ }
9050
+ });
9051
+ let currentNode;
9052
+ // We cannot modify the DOM while using the commentIterator,
9053
+ // because it throws off the iterator state.
9054
+ // So we collect all marker nodes first and then follow up with
9055
+ // applying the changes to the DOM: either inserting an empty node
9056
+ // or just removing the marker if it was used as a separator.
9057
+ const nodes = [];
9058
+ while (currentNode = commentNodesIterator.nextNode()) {
9059
+ nodes.push(currentNode);
9060
+ }
9061
+ for (const node of nodes) {
9062
+ if (node.textContent === "ngetn" /* TextNodeMarker.EmptyNode */) {
9063
+ node.replaceWith(doc.createTextNode(''));
9064
+ }
9065
+ else {
9066
+ node.remove();
9067
+ }
9068
+ }
8675
9069
  }
8676
9070
  /**
8677
- * Extend this base class to implement custom rendering. By default, Angular
8678
- * renders a template into DOM. You can use custom rendering to intercept
8679
- * rendering calls, or to render to something other than DOM.
8680
- *
8681
- * Create your custom renderer using `RendererFactory2`.
8682
- *
8683
- * Use a custom renderer to bypass Angular's templating and
8684
- * make custom UI changes that can't be expressed declaratively.
8685
- * For example if you need to set a property or an attribute whose name is
8686
- * not statically known, use the `setProperty()` or
8687
- * `setAttribute()` method.
8688
- *
8689
- * @publicApi
9071
+ * Marks a node as "claimed" by hydration process.
9072
+ * This is needed to make assessments in tests whether
9073
+ * the hydration process handled all nodes.
8690
9074
  */
8691
- class Renderer2 {
9075
+ function markRNodeAsClaimedByHydration(node, checkIfAlreadyClaimed = true) {
9076
+ if (!ngDevMode) {
9077
+ throw new Error('Calling `markRNodeAsClaimedByHydration` in prod mode ' +
9078
+ 'is not supported and likely a mistake.');
9079
+ }
9080
+ if (checkIfAlreadyClaimed && isRNodeClaimedForHydration(node)) {
9081
+ throw new Error('Trying to claim a node, which was claimed already.');
9082
+ }
9083
+ node.__claimed = true;
9084
+ ngDevMode.hydratedNodes++;
8692
9085
  }
8693
- /**
8694
- * @internal
8695
- * @nocollapse
8696
- */
8697
- Renderer2.__NG_ELEMENT_ID__ = () => injectRenderer2();
8698
- /** Injects a Renderer2 for the current component. */
8699
- function injectRenderer2() {
8700
- // We need the Renderer to be based on the component that it's being injected into, however since
8701
- // DI happens before we've entered its view, `getLView` will return the parent view instead.
8702
- const lView = getLView();
8703
- const tNode = getCurrentTNode();
8704
- const nodeAtIndex = getComponentLViewByIndex(tNode.index, lView);
8705
- return (isLView(nodeAtIndex) ? nodeAtIndex : lView)[RENDERER];
9086
+ function isRNodeClaimedForHydration(node) {
9087
+ return !!node.__claimed;
9088
+ }
9089
+ function setSegmentHead(hydrationInfo, index, node) {
9090
+ var _a;
9091
+ (_a = hydrationInfo.segmentHeads) !== null && _a !== void 0 ? _a : (hydrationInfo.segmentHeads = {});
9092
+ hydrationInfo.segmentHeads[index] = node;
9093
+ }
9094
+ function getSegmentHead(hydrationInfo, index) {
9095
+ var _a, _b;
9096
+ return (_b = (_a = hydrationInfo.segmentHeads) === null || _a === void 0 ? void 0 : _a[index]) !== null && _b !== void 0 ? _b : null;
8706
9097
  }
8707
-
8708
9098
  /**
8709
- * Sanitizer is used by the views to sanitize potentially dangerous values.
8710
- *
8711
- * @publicApi
9099
+ * Returns the size of an <ng-container>, using either the information
9100
+ * serialized in `ELEMENT_CONTAINERS` (element container size) or by
9101
+ * computing the sum of root nodes in all dehydrated views in a given
9102
+ * container (in case this `<ng-container>` was also used as a view
9103
+ * container host node, e.g. <ng-container *ngIf>).
8712
9104
  */
8713
- class Sanitizer {
9105
+ function getNgContainerSize(hydrationInfo, index) {
9106
+ var _a, _b, _c;
9107
+ const data = hydrationInfo.data;
9108
+ let size = (_b = (_a = data[ELEMENT_CONTAINERS]) === null || _a === void 0 ? void 0 : _a[index]) !== null && _b !== void 0 ? _b : null;
9109
+ // If there is no serialized information available in the `ELEMENT_CONTAINERS` slot,
9110
+ // check if we have info about view containers at this location (e.g.
9111
+ // `<ng-container *ngIf>`) and use container size as a number of root nodes in this
9112
+ // element container.
9113
+ if (size === null && ((_c = data[CONTAINERS]) === null || _c === void 0 ? void 0 : _c[index])) {
9114
+ size = calcSerializedContainerSize(hydrationInfo, index);
9115
+ }
9116
+ return size;
9117
+ }
9118
+ function getSerializedContainerViews(hydrationInfo, index) {
9119
+ var _a, _b;
9120
+ return (_b = (_a = hydrationInfo.data[CONTAINERS]) === null || _a === void 0 ? void 0 : _a[index]) !== null && _b !== void 0 ? _b : null;
8714
9121
  }
8715
- /** @nocollapse */
8716
- Sanitizer.ɵprov = ɵɵdefineInjectable({
8717
- token: Sanitizer,
8718
- providedIn: 'root',
8719
- factory: () => null,
8720
- });
8721
-
8722
9122
  /**
8723
- * @description Represents the version of Angular
8724
- *
8725
- * @publicApi
9123
+ * Computes the size of a serialized container (the number of root nodes)
9124
+ * by calculating the sum of root nodes in all dehydrated views in this container.
8726
9125
  */
8727
- class Version {
8728
- constructor(full) {
8729
- this.full = full;
8730
- this.major = full.split('.')[0];
8731
- this.minor = full.split('.')[1];
8732
- this.patch = full.split('.').slice(2).join('.');
9126
+ function calcSerializedContainerSize(hydrationInfo, index) {
9127
+ var _a;
9128
+ const views = (_a = getSerializedContainerViews(hydrationInfo, index)) !== null && _a !== void 0 ? _a : [];
9129
+ let numNodes = 0;
9130
+ for (let view of views) {
9131
+ numNodes += view[NUM_ROOT_NODES];
8733
9132
  }
9133
+ return numNodes;
8734
9134
  }
9135
+
8735
9136
  /**
9137
+ * Represents a component created by a `ComponentFactory`.
9138
+ * Provides access to the component instance and related objects,
9139
+ * and provides the means of destroying the instance.
9140
+ *
8736
9141
  * @publicApi
8737
9142
  */
8738
- const VERSION = new Version('16.0.0-next.2');
8739
-
8740
- // This default value is when checking the hierarchy for a token.
8741
- //
8742
- // It means both:
8743
- // - the token is not provided by the current injector,
8744
- // - only the element injectors should be checked (ie do not check module injectors
8745
- //
8746
- // mod1
8747
- // /
8748
- // el1 mod2
8749
- // \ /
8750
- // el2
8751
- //
8752
- // When requesting el2.injector.get(token), we should check in the following order and return the
8753
- // first found value:
8754
- // - el2.injector.get(token, default)
8755
- // - el1.injector.get(token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) -> do not check the module
8756
- // - mod2.injector.get(token, default)
8757
- const NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR = {};
8758
-
8759
- const ERROR_ORIGINAL_ERROR = 'ngOriginalError';
8760
- function wrappedError(message, originalError) {
8761
- const msg = `${message} caused by: ${originalError instanceof Error ? originalError.message : originalError}`;
8762
- const error = Error(msg);
8763
- error[ERROR_ORIGINAL_ERROR] = originalError;
8764
- return error;
8765
- }
8766
- function getOriginalError(error) {
8767
- return error[ERROR_ORIGINAL_ERROR];
9143
+ class ComponentRef$1 {
8768
9144
  }
8769
-
8770
9145
  /**
8771
- * Provides a hook for centralized exception handling.
8772
- *
8773
- * The default implementation of `ErrorHandler` prints error messages to the `console`. To
8774
- * intercept error handling, write a custom exception handler that replaces this default as
8775
- * appropriate for your app.
8776
- *
8777
- * @usageNotes
8778
- * ### Example
8779
- *
8780
- * ```
8781
- * class MyErrorHandler implements ErrorHandler {
8782
- * handleError(error) {
8783
- * // do something with the exception
8784
- * }
8785
- * }
9146
+ * Base class for a factory that can create a component dynamically.
9147
+ * Instantiate a factory for a given type of component with `resolveComponentFactory()`.
9148
+ * Use the resulting `ComponentFactory.create()` method to create a component of that type.
8786
9149
  *
8787
- * @NgModule({
8788
- * providers: [{provide: ErrorHandler, useClass: MyErrorHandler}]
8789
- * })
8790
- * class MyModule {}
8791
- * ```
9150
+ * @see [Dynamic Components](guide/dynamic-component-loader)
8792
9151
  *
8793
9152
  * @publicApi
9153
+ *
9154
+ * @deprecated Angular no longer requires Component factories. Please use other APIs where
9155
+ * Component class can be used directly.
8794
9156
  */
8795
- class ErrorHandler {
8796
- constructor() {
8797
- /**
8798
- * @internal
8799
- */
8800
- this._console = console;
8801
- }
8802
- handleError(error) {
8803
- const originalError = this._findOriginalError(error);
8804
- this._console.error('ERROR', error);
8805
- if (originalError) {
8806
- this._console.error('ORIGINAL ERROR', originalError);
8807
- }
8808
- }
8809
- /** @internal */
8810
- _findOriginalError(error) {
8811
- let e = error && getOriginalError(error);
8812
- while (e && getOriginalError(e)) {
8813
- e = getOriginalError(e);
8814
- }
8815
- return e || null;
8816
- }
9157
+ class ComponentFactory$1 {
8817
9158
  }
8818
9159
 
8819
- const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
8820
- /**
8821
- * Internal token that specifies whether hydration is enabled.
8822
- */
8823
- const IS_HYDRATION_FEATURE_ENABLED = new InjectionToken(NG_DEV_MODE$1 ? 'IS_HYDRATION_FEATURE_ENABLED' : '');
8824
- // By default (in client rendering mode), we remove all the contents
8825
- // of the host element and render an application after that.
8826
- const PRESERVE_HOST_CONTENT_DEFAULT = false;
8827
- /**
8828
- * Internal token that indicates whether host element content should be
8829
- * retained during the bootstrap.
8830
- */
8831
- const PRESERVE_HOST_CONTENT = new InjectionToken(NG_DEV_MODE$1 ? 'PRESERVE_HOST_CONTENT' : '', {
8832
- providedIn: 'root',
8833
- factory: () => PRESERVE_HOST_CONTENT_DEFAULT,
8834
- });
8835
-
8836
- function normalizeDebugBindingName(name) {
8837
- // Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
8838
- name = camelCaseToDashCase(name.replace(/[$@]/g, '_'));
8839
- return `ng-reflect-${name}`;
9160
+ function noComponentFactoryError(component) {
9161
+ const error = Error(`No component factory found for ${stringify(component)}. Did you add it to @NgModule.entryComponents?`);
9162
+ error[ERROR_COMPONENT] = component;
9163
+ return error;
8840
9164
  }
8841
- const CAMEL_CASE_REGEXP = /([A-Z])/g;
8842
- function camelCaseToDashCase(input) {
8843
- return input.replace(CAMEL_CASE_REGEXP, (...m) => '-' + m[1].toLowerCase());
9165
+ const ERROR_COMPONENT = 'ngComponent';
9166
+ function getComponent$1(error) {
9167
+ return error[ERROR_COMPONENT];
8844
9168
  }
8845
- function normalizeDebugBindingValue(value) {
8846
- try {
8847
- // Limit the size of the value as otherwise the DOM just gets polluted.
8848
- return value != null ? value.toString().slice(0, 30) : value;
8849
- }
8850
- catch (e) {
8851
- return '[ERROR] Exception while trying to serialize the value';
9169
+ class _NullComponentFactoryResolver {
9170
+ resolveComponentFactory(component) {
9171
+ throw noComponentFactoryError(component);
8852
9172
  }
8853
9173
  }
8854
-
8855
9174
  /**
9175
+ * A simple registry that maps `Components` to generated `ComponentFactory` classes
9176
+ * that can be used to create instances of components.
9177
+ * Use to obtain the factory for a given component type,
9178
+ * then use the factory's `create()` method to create a component of that type.
8856
9179
  *
8857
- * @codeGenApi
9180
+ * Note: since v13, dynamic component creation via
9181
+ * [`ViewContainerRef.createComponent`](api/core/ViewContainerRef#createComponent)
9182
+ * does **not** require resolving component factory: component class can be used directly.
9183
+ *
9184
+ * @publicApi
9185
+ *
9186
+ * @deprecated Angular no longer requires Component factories. Please use other APIs where
9187
+ * Component class can be used directly.
8858
9188
  */
8859
- function ɵɵresolveWindow(element) {
8860
- return element.ownerDocument.defaultView;
9189
+ class ComponentFactoryResolver$1 {
8861
9190
  }
9191
+ ComponentFactoryResolver$1.NULL = ( /* @__PURE__ */new _NullComponentFactoryResolver());
9192
+
8862
9193
  /**
9194
+ * Creates an ElementRef from the most recent node.
8863
9195
  *
8864
- * @codeGenApi
9196
+ * @returns The ElementRef instance to use
8865
9197
  */
8866
- function ɵɵresolveDocument(element) {
8867
- return element.ownerDocument;
9198
+ function injectElementRef() {
9199
+ return createElementRef(getCurrentTNode(), getLView());
8868
9200
  }
8869
9201
  /**
9202
+ * Creates an ElementRef given a node.
8870
9203
  *
8871
- * @codeGenApi
9204
+ * @param tNode The node for which you'd like an ElementRef
9205
+ * @param lView The view to which the node belongs
9206
+ * @returns The ElementRef instance to use
8872
9207
  */
8873
- function ɵɵresolveBody(element) {
8874
- return element.ownerDocument.body;
9208
+ function createElementRef(tNode, lView) {
9209
+ return new ElementRef(getNativeByTNode(tNode, lView));
8875
9210
  }
8876
9211
  /**
8877
- * The special delimiter we use to separate property names, prefixes, and suffixes
8878
- * in property binding metadata. See storeBindingMetadata().
9212
+ * A wrapper around a native element inside of a View.
8879
9213
  *
8880
- * We intentionally use the Unicode "REPLACEMENT CHARACTER" (U+FFFD) as a delimiter
8881
- * because it is a very uncommon character that is unlikely to be part of a user's
8882
- * property names or interpolation strings. If it is in fact used in a property
8883
- * binding, DebugElement.properties will not return the correct value for that
8884
- * binding. However, there should be no runtime effect for real applications.
9214
+ * An `ElementRef` is backed by a render-specific element. In the browser, this is usually a DOM
9215
+ * element.
8885
9216
  *
8886
- * This character is typically rendered as a question mark inside of a diamond.
8887
- * See https://en.wikipedia.org/wiki/Specials_(Unicode_block)
9217
+ * @security Permitting direct access to the DOM can make your application more vulnerable to
9218
+ * XSS attacks. Carefully review any use of `ElementRef` in your code. For more detail, see the
9219
+ * [Security Guide](https://g.co/ng/security).
8888
9220
  *
9221
+ * @publicApi
8889
9222
  */
8890
- const INTERPOLATION_DELIMITER = `�`;
8891
- /**
8892
- * Unwrap a value which might be behind a closure (for forward declaration reasons).
8893
- */
8894
- function maybeUnwrapFn(value) {
8895
- if (value instanceof Function) {
8896
- return value();
8897
- }
8898
- else {
8899
- return value;
8900
- }
8901
- }
8902
-
8903
- /** Verifies that a given type is a Standalone Component. */
8904
- function assertStandaloneComponentType(type) {
8905
- assertComponentDef(type);
8906
- const componentDef = getComponentDef(type);
8907
- if (!componentDef.standalone) {
8908
- throw new RuntimeError(907 /* RuntimeErrorCode.TYPE_IS_NOT_STANDALONE */, `The ${stringifyForError(type)} component is not marked as standalone, ` +
8909
- `but Angular expects to have a standalone component here. ` +
8910
- `Please make sure the ${stringifyForError(type)} component has ` +
8911
- `the \`standalone: true\` flag in the decorator.`);
8912
- }
8913
- }
8914
- /** Verifies whether a given type is a component */
8915
- function assertComponentDef(type) {
8916
- if (!getComponentDef(type)) {
8917
- throw new RuntimeError(906 /* RuntimeErrorCode.MISSING_GENERATED_DEF */, `The ${stringifyForError(type)} is not an Angular component, ` +
8918
- `make sure it has the \`@Component\` decorator.`);
8919
- }
8920
- }
8921
- /** Called when there are multiple component selectors that match a given node */
8922
- function throwMultipleComponentError(tNode, first, second) {
8923
- throw new RuntimeError(-300 /* RuntimeErrorCode.MULTIPLE_COMPONENTS_MATCH */, `Multiple components match node with tagname ${tNode.value}: ` +
8924
- `${stringifyForError(first)} and ` +
8925
- `${stringifyForError(second)}`);
8926
- }
8927
- /** Throws an ExpressionChangedAfterChecked error if checkNoChanges mode is on. */
8928
- function throwErrorIfNoChangesMode(creationMode, oldValue, currValue, propName) {
8929
- const field = propName ? ` for '${propName}'` : '';
8930
- let msg = `ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value${field}: '${oldValue}'. Current value: '${currValue}'.`;
8931
- if (creationMode) {
8932
- msg +=
8933
- ` It seems like the view has been created after its parent and its children have been dirty checked.` +
8934
- ` Has it been created in a change detection hook?`;
8935
- }
8936
- throw new RuntimeError(-100 /* RuntimeErrorCode.EXPRESSION_CHANGED_AFTER_CHECKED */, msg);
8937
- }
8938
- function constructDetailsForInterpolation(lView, rootIndex, expressionIndex, meta, changedValue) {
8939
- const [propName, prefix, ...chunks] = meta.split(INTERPOLATION_DELIMITER);
8940
- let oldValue = prefix, newValue = prefix;
8941
- for (let i = 0; i < chunks.length; i++) {
8942
- const slotIdx = rootIndex + i;
8943
- oldValue += `${lView[slotIdx]}${chunks[i]}`;
8944
- newValue += `${slotIdx === expressionIndex ? changedValue : lView[slotIdx]}${chunks[i]}`;
9223
+ // Note: We don't expose things like `Injector`, `ViewContainer`, ... here,
9224
+ // i.e. users have to ask for what they need. With that, we can build better analysis tools
9225
+ // and could do better codegen in the future.
9226
+ class ElementRef {
9227
+ constructor(nativeElement) {
9228
+ this.nativeElement = nativeElement;
8945
9229
  }
8946
- return { propName, oldValue, newValue };
8947
9230
  }
8948
9231
  /**
8949
- * Constructs an object that contains details for the ExpressionChangedAfterItHasBeenCheckedError:
8950
- * - property name (for property bindings or interpolations)
8951
- * - old and new values, enriched using information from metadata
9232
+ * @internal
9233
+ * @nocollapse
9234
+ */
9235
+ ElementRef.__NG_ELEMENT_ID__ = injectElementRef;
9236
+ /**
9237
+ * Unwraps `ElementRef` and return the `nativeElement`.
8952
9238
  *
8953
- * More information on the metadata storage format can be found in `storePropertyBindingMetadata`
8954
- * function description.
9239
+ * @param value value to unwrap
9240
+ * @returns `nativeElement` if `ElementRef` otherwise returns value as is.
8955
9241
  */
8956
- function getExpressionChangedErrorDetails(lView, bindingIndex, oldValue, newValue) {
8957
- const tData = lView[TVIEW].data;
8958
- const metadata = tData[bindingIndex];
8959
- if (typeof metadata === 'string') {
8960
- // metadata for property interpolation
8961
- if (metadata.indexOf(INTERPOLATION_DELIMITER) > -1) {
8962
- return constructDetailsForInterpolation(lView, bindingIndex, bindingIndex, metadata, newValue);
8963
- }
8964
- // metadata for property binding
8965
- return { propName: metadata, oldValue, newValue };
8966
- }
8967
- // metadata is not available for this expression, check if this expression is a part of the
8968
- // property interpolation by going from the current binding index left and look for a string that
8969
- // contains INTERPOLATION_DELIMITER, the layout in tView.data for this case will look like this:
8970
- // [..., 'id�Prefix � and � suffix', null, null, null, ...]
8971
- if (metadata === null) {
8972
- let idx = bindingIndex - 1;
8973
- while (typeof tData[idx] !== 'string' && tData[idx + 1] === null) {
8974
- idx--;
8975
- }
8976
- const meta = tData[idx];
8977
- if (typeof meta === 'string') {
8978
- const matches = meta.match(new RegExp(INTERPOLATION_DELIMITER, 'g'));
8979
- // first interpolation delimiter separates property name from interpolation parts (in case of
8980
- // property interpolations), so we subtract one from total number of found delimiters
8981
- if (matches && (matches.length - 1) > bindingIndex - idx) {
8982
- return constructDetailsForInterpolation(lView, idx, bindingIndex, meta, newValue);
8983
- }
8984
- }
8985
- }
8986
- return { propName: undefined, oldValue, newValue };
9242
+ function unwrapElementRef(value) {
9243
+ return value instanceof ElementRef ? value.nativeElement : value;
8987
9244
  }
8988
9245
 
8989
9246
  /**
8990
- * Returns an index of `classToSearch` in `className` taking token boundaries into account.
8991
- *
8992
- * `classIndexOf('AB A', 'A', 0)` will be 3 (not 0 since `AB!==A`)
9247
+ * Creates and initializes a custom renderer that implements the `Renderer2` base class.
8993
9248
  *
8994
- * @param className A string containing classes (whitespace separated)
8995
- * @param classToSearch A class name to locate
8996
- * @param startingIndex Starting location of search
8997
- * @returns an index of the located class (or -1 if not found)
9249
+ * @publicApi
8998
9250
  */
8999
- function classIndexOf(className, classToSearch, startingIndex) {
9000
- ngDevMode && assertNotEqual(classToSearch, '', 'can not look for "" string.');
9001
- let end = className.length;
9002
- while (true) {
9003
- const foundIndex = className.indexOf(classToSearch, startingIndex);
9004
- if (foundIndex === -1)
9005
- return foundIndex;
9006
- if (foundIndex === 0 || className.charCodeAt(foundIndex - 1) <= 32 /* CharCode.SPACE */) {
9007
- // Ensure that it has leading whitespace
9008
- const length = classToSearch.length;
9009
- if (foundIndex + length === end ||
9010
- className.charCodeAt(foundIndex + length) <= 32 /* CharCode.SPACE */) {
9011
- // Ensure that it has trailing whitespace
9012
- return foundIndex;
9013
- }
9014
- }
9015
- // False positive, keep searching from where we left off.
9016
- startingIndex = foundIndex + 1;
9017
- }
9251
+ class RendererFactory2 {
9018
9252
  }
9019
-
9020
- const NG_TEMPLATE_SELECTOR = 'ng-template';
9021
9253
  /**
9022
- * Search the `TAttributes` to see if it contains `cssClassToMatch` (case insensitive)
9254
+ * Extend this base class to implement custom rendering. By default, Angular
9255
+ * renders a template into DOM. You can use custom rendering to intercept
9256
+ * rendering calls, or to render to something other than DOM.
9023
9257
  *
9024
- * @param attrs `TAttributes` to search through.
9025
- * @param cssClassToMatch class to match (lowercase)
9026
- * @param isProjectionMode Whether or not class matching should look into the attribute `class` in
9027
- * addition to the `AttributeMarker.Classes`.
9258
+ * Create your custom renderer using `RendererFactory2`.
9259
+ *
9260
+ * Use a custom renderer to bypass Angular's templating and
9261
+ * make custom UI changes that can't be expressed declaratively.
9262
+ * For example if you need to set a property or an attribute whose name is
9263
+ * not statically known, use the `setProperty()` or
9264
+ * `setAttribute()` method.
9265
+ *
9266
+ * @publicApi
9028
9267
  */
9029
- function isCssClassMatching(attrs, cssClassToMatch, isProjectionMode) {
9030
- // TODO(misko): The fact that this function needs to know about `isProjectionMode` seems suspect.
9031
- // It is strange to me that sometimes the class information comes in form of `class` attribute
9032
- // and sometimes in form of `AttributeMarker.Classes`. Some investigation is needed to determine
9033
- // if that is the right behavior.
9034
- ngDevMode &&
9035
- assertEqual(cssClassToMatch, cssClassToMatch.toLowerCase(), 'Class name expected to be lowercase.');
9036
- let i = 0;
9037
- while (i < attrs.length) {
9038
- let item = attrs[i++];
9039
- if (isProjectionMode && item === 'class') {
9040
- item = attrs[i];
9041
- if (classIndexOf(item.toLowerCase(), cssClassToMatch, 0) !== -1) {
9042
- return true;
9043
- }
9044
- }
9045
- else if (item === 1 /* AttributeMarker.Classes */) {
9046
- // We found the classes section. Start searching for the class.
9047
- while (i < attrs.length && typeof (item = attrs[i++]) == 'string') {
9048
- // while we have strings
9049
- if (item.toLowerCase() === cssClassToMatch)
9050
- return true;
9051
- }
9052
- return false;
9053
- }
9054
- }
9055
- return false;
9268
+ class Renderer2 {
9269
+ }
9270
+ /**
9271
+ * @internal
9272
+ * @nocollapse
9273
+ */
9274
+ Renderer2.__NG_ELEMENT_ID__ = () => injectRenderer2();
9275
+ /** Injects a Renderer2 for the current component. */
9276
+ function injectRenderer2() {
9277
+ // We need the Renderer to be based on the component that it's being injected into, however since
9278
+ // DI happens before we've entered its view, `getLView` will return the parent view instead.
9279
+ const lView = getLView();
9280
+ const tNode = getCurrentTNode();
9281
+ const nodeAtIndex = getComponentLViewByIndex(tNode.index, lView);
9282
+ return (isLView(nodeAtIndex) ? nodeAtIndex : lView)[RENDERER];
9056
9283
  }
9284
+
9057
9285
  /**
9058
- * Checks whether the `tNode` represents an inline template (e.g. `*ngFor`).
9286
+ * Sanitizer is used by the views to sanitize potentially dangerous values.
9059
9287
  *
9060
- * @param tNode current TNode
9288
+ * @publicApi
9061
9289
  */
9062
- function isInlineTemplate(tNode) {
9063
- return tNode.type === 4 /* TNodeType.Container */ && tNode.value !== NG_TEMPLATE_SELECTOR;
9290
+ class Sanitizer {
9064
9291
  }
9292
+ /** @nocollapse */
9293
+ Sanitizer.ɵprov = ɵɵdefineInjectable({
9294
+ token: Sanitizer,
9295
+ providedIn: 'root',
9296
+ factory: () => null,
9297
+ });
9298
+
9065
9299
  /**
9066
- * Function that checks whether a given tNode matches tag-based selector and has a valid type.
9300
+ * @description Represents the version of Angular
9067
9301
  *
9068
- * Matching can be performed in 2 modes: projection mode (when we project nodes) and regular
9069
- * directive matching mode:
9070
- * - in the "directive matching" mode we do _not_ take TContainer's tagName into account if it is
9071
- * different from NG_TEMPLATE_SELECTOR (value different from NG_TEMPLATE_SELECTOR indicates that a
9072
- * tag name was extracted from * syntax so we would match the same directive twice);
9073
- * - in the "projection" mode, we use a tag name potentially extracted from the * syntax processing
9074
- * (applicable to TNodeType.Container only).
9302
+ * @publicApi
9075
9303
  */
9076
- function hasTagAndTypeMatch(tNode, currentSelector, isProjectionMode) {
9077
- const tagNameToCompare = tNode.type === 4 /* TNodeType.Container */ && !isProjectionMode ? NG_TEMPLATE_SELECTOR : tNode.value;
9078
- return currentSelector === tagNameToCompare;
9304
+ class Version {
9305
+ constructor(full) {
9306
+ this.full = full;
9307
+ this.major = full.split('.')[0];
9308
+ this.minor = full.split('.')[1];
9309
+ this.patch = full.split('.').slice(2).join('.');
9310
+ }
9079
9311
  }
9080
9312
  /**
9081
- * A utility function to match an Ivy node static data against a simple CSS selector
9082
- *
9083
- * @param node static data of the node to match
9084
- * @param selector The selector to try matching against the node.
9085
- * @param isProjectionMode if `true` we are matching for content projection, otherwise we are doing
9086
- * directive matching.
9087
- * @returns true if node matches the selector.
9313
+ * @publicApi
9088
9314
  */
9089
- function isNodeMatchingSelector(tNode, selector, isProjectionMode) {
9090
- ngDevMode && assertDefined(selector[0], 'Selector should have a tag name');
9091
- let mode = 4 /* SelectorFlags.ELEMENT */;
9092
- const nodeAttrs = tNode.attrs || [];
9093
- // Find the index of first attribute that has no value, only a name.
9094
- const nameOnlyMarkerIdx = getNameOnlyMarkerIndex(nodeAttrs);
9095
- // When processing ":not" selectors, we skip to the next ":not" if the
9096
- // current one doesn't match
9097
- let skipToNextSelector = false;
9098
- for (let i = 0; i < selector.length; i++) {
9099
- const current = selector[i];
9100
- if (typeof current === 'number') {
9101
- // If we finish processing a :not selector and it hasn't failed, return false
9102
- if (!skipToNextSelector && !isPositive(mode) && !isPositive(current)) {
9103
- return false;
9104
- }
9105
- // If we are skipping to the next :not() and this mode flag is positive,
9106
- // it's a part of the current :not() selector, and we should keep skipping
9107
- if (skipToNextSelector && isPositive(current))
9108
- continue;
9109
- skipToNextSelector = false;
9110
- mode = current | (mode & 1 /* SelectorFlags.NOT */);
9111
- continue;
9112
- }
9113
- if (skipToNextSelector)
9114
- continue;
9115
- if (mode & 4 /* SelectorFlags.ELEMENT */) {
9116
- mode = 2 /* SelectorFlags.ATTRIBUTE */ | mode & 1 /* SelectorFlags.NOT */;
9117
- if (current !== '' && !hasTagAndTypeMatch(tNode, current, isProjectionMode) ||
9118
- current === '' && selector.length === 1) {
9119
- if (isPositive(mode))
9120
- return false;
9121
- skipToNextSelector = true;
9122
- }
9123
- }
9124
- else {
9125
- const selectorAttrValue = mode & 8 /* SelectorFlags.CLASS */ ? current : selector[++i];
9126
- // special case for matching against classes when a tNode has been instantiated with
9127
- // class and style values as separate attribute values (e.g. ['title', CLASS, 'foo'])
9128
- if ((mode & 8 /* SelectorFlags.CLASS */) && tNode.attrs !== null) {
9129
- if (!isCssClassMatching(tNode.attrs, selectorAttrValue, isProjectionMode)) {
9130
- if (isPositive(mode))
9131
- return false;
9132
- skipToNextSelector = true;
9133
- }
9134
- continue;
9135
- }
9136
- const attrName = (mode & 8 /* SelectorFlags.CLASS */) ? 'class' : current;
9137
- const attrIndexInNode = findAttrIndexInNode(attrName, nodeAttrs, isInlineTemplate(tNode), isProjectionMode);
9138
- if (attrIndexInNode === -1) {
9139
- if (isPositive(mode))
9140
- return false;
9141
- skipToNextSelector = true;
9142
- continue;
9143
- }
9144
- if (selectorAttrValue !== '') {
9145
- let nodeAttrValue;
9146
- if (attrIndexInNode > nameOnlyMarkerIdx) {
9147
- nodeAttrValue = '';
9148
- }
9149
- else {
9150
- ngDevMode &&
9151
- assertNotEqual(nodeAttrs[attrIndexInNode], 0 /* AttributeMarker.NamespaceURI */, 'We do not match directives on namespaced attributes');
9152
- // we lowercase the attribute value to be able to match
9153
- // selectors without case-sensitivity
9154
- // (selectors are already in lowercase when generated)
9155
- nodeAttrValue = nodeAttrs[attrIndexInNode + 1].toLowerCase();
9156
- }
9157
- const compareAgainstClassName = mode & 8 /* SelectorFlags.CLASS */ ? nodeAttrValue : null;
9158
- if (compareAgainstClassName &&
9159
- classIndexOf(compareAgainstClassName, selectorAttrValue, 0) !== -1 ||
9160
- mode & 2 /* SelectorFlags.ATTRIBUTE */ && selectorAttrValue !== nodeAttrValue) {
9161
- if (isPositive(mode))
9162
- return false;
9163
- skipToNextSelector = true;
9164
- }
9165
- }
9166
- }
9167
- }
9168
- return isPositive(mode) || skipToNextSelector;
9315
+ const VERSION = new Version('16.0.0-next.3');
9316
+
9317
+ // This default value is when checking the hierarchy for a token.
9318
+ //
9319
+ // It means both:
9320
+ // - the token is not provided by the current injector,
9321
+ // - only the element injectors should be checked (ie do not check module injectors
9322
+ //
9323
+ // mod1
9324
+ // /
9325
+ // el1 mod2
9326
+ // \ /
9327
+ // el2
9328
+ //
9329
+ // When requesting el2.injector.get(token), we should check in the following order and return the
9330
+ // first found value:
9331
+ // - el2.injector.get(token, default)
9332
+ // - el1.injector.get(token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) -> do not check the module
9333
+ // - mod2.injector.get(token, default)
9334
+ const NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR = {};
9335
+
9336
+ const ERROR_ORIGINAL_ERROR = 'ngOriginalError';
9337
+ function wrappedError(message, originalError) {
9338
+ const msg = `${message} caused by: ${originalError instanceof Error ? originalError.message : originalError}`;
9339
+ const error = Error(msg);
9340
+ error[ERROR_ORIGINAL_ERROR] = originalError;
9341
+ return error;
9169
9342
  }
9170
- function isPositive(mode) {
9171
- return (mode & 1 /* SelectorFlags.NOT */) === 0;
9343
+ function getOriginalError(error) {
9344
+ return error[ERROR_ORIGINAL_ERROR];
9172
9345
  }
9346
+
9173
9347
  /**
9174
- * Examines the attribute's definition array for a node to find the index of the
9175
- * attribute that matches the given `name`.
9176
- *
9177
- * NOTE: This will not match namespaced attributes.
9178
- *
9179
- * Attribute matching depends upon `isInlineTemplate` and `isProjectionMode`.
9180
- * The following table summarizes which types of attributes we attempt to match:
9348
+ * Provides a hook for centralized exception handling.
9181
9349
  *
9182
- * ===========================================================================================================
9183
- * Modes | Normal Attributes | Bindings Attributes | Template Attributes | I18n
9184
- * Attributes
9185
- * ===========================================================================================================
9186
- * Inline + Projection | YES | YES | NO | YES
9187
- * -----------------------------------------------------------------------------------------------------------
9188
- * Inline + Directive | NO | NO | YES | NO
9189
- * -----------------------------------------------------------------------------------------------------------
9190
- * Non-inline + Projection | YES | YES | NO | YES
9191
- * -----------------------------------------------------------------------------------------------------------
9192
- * Non-inline + Directive | YES | YES | NO | YES
9193
- * ===========================================================================================================
9350
+ * The default implementation of `ErrorHandler` prints error messages to the `console`. To
9351
+ * intercept error handling, write a custom exception handler that replaces this default as
9352
+ * appropriate for your app.
9194
9353
  *
9195
- * @param name the name of the attribute to find
9196
- * @param attrs the attribute array to examine
9197
- * @param isInlineTemplate true if the node being matched is an inline template (e.g. `*ngFor`)
9198
- * rather than a manually expanded template node (e.g `<ng-template>`).
9199
- * @param isProjectionMode true if we are matching against content projection otherwise we are
9200
- * matching against directives.
9201
- */
9202
- function findAttrIndexInNode(name, attrs, isInlineTemplate, isProjectionMode) {
9203
- if (attrs === null)
9204
- return -1;
9205
- let i = 0;
9206
- if (isProjectionMode || !isInlineTemplate) {
9207
- let bindingsMode = false;
9208
- while (i < attrs.length) {
9209
- const maybeAttrName = attrs[i];
9210
- if (maybeAttrName === name) {
9211
- return i;
9212
- }
9213
- else if (maybeAttrName === 3 /* AttributeMarker.Bindings */ || maybeAttrName === 6 /* AttributeMarker.I18n */) {
9214
- bindingsMode = true;
9215
- }
9216
- else if (maybeAttrName === 1 /* AttributeMarker.Classes */ || maybeAttrName === 2 /* AttributeMarker.Styles */) {
9217
- let value = attrs[++i];
9218
- // We should skip classes here because we have a separate mechanism for
9219
- // matching classes in projection mode.
9220
- while (typeof value === 'string') {
9221
- value = attrs[++i];
9222
- }
9223
- continue;
9224
- }
9225
- else if (maybeAttrName === 4 /* AttributeMarker.Template */) {
9226
- // We do not care about Template attributes in this scenario.
9227
- break;
9228
- }
9229
- else if (maybeAttrName === 0 /* AttributeMarker.NamespaceURI */) {
9230
- // Skip the whole namespaced attribute and value. This is by design.
9231
- i += 4;
9232
- continue;
9233
- }
9234
- // In binding mode there are only names, rather than name-value pairs.
9235
- i += bindingsMode ? 1 : 2;
9236
- }
9237
- // We did not match the attribute
9238
- return -1;
9239
- }
9240
- else {
9241
- return matchTemplateAttribute(attrs, name);
9242
- }
9243
- }
9244
- function isNodeMatchingSelectorList(tNode, selector, isProjectionMode = false) {
9245
- for (let i = 0; i < selector.length; i++) {
9246
- if (isNodeMatchingSelector(tNode, selector[i], isProjectionMode)) {
9247
- return true;
9248
- }
9249
- }
9250
- return false;
9251
- }
9252
- function getProjectAsAttrValue(tNode) {
9253
- const nodeAttrs = tNode.attrs;
9254
- if (nodeAttrs != null) {
9255
- const ngProjectAsAttrIdx = nodeAttrs.indexOf(5 /* AttributeMarker.ProjectAs */);
9256
- // only check for ngProjectAs in attribute names, don't accidentally match attribute's value
9257
- // (attribute names are stored at even indexes)
9258
- if ((ngProjectAsAttrIdx & 1) === 0) {
9259
- return nodeAttrs[ngProjectAsAttrIdx + 1];
9260
- }
9354
+ * @usageNotes
9355
+ * ### Example
9356
+ *
9357
+ * ```
9358
+ * class MyErrorHandler implements ErrorHandler {
9359
+ * handleError(error) {
9360
+ * // do something with the exception
9361
+ * }
9362
+ * }
9363
+ *
9364
+ * @NgModule({
9365
+ * providers: [{provide: ErrorHandler, useClass: MyErrorHandler}]
9366
+ * })
9367
+ * class MyModule {}
9368
+ * ```
9369
+ *
9370
+ * @publicApi
9371
+ */
9372
+ class ErrorHandler {
9373
+ constructor() {
9374
+ /**
9375
+ * @internal
9376
+ */
9377
+ this._console = console;
9261
9378
  }
9262
- return null;
9263
- }
9264
- function getNameOnlyMarkerIndex(nodeAttrs) {
9265
- for (let i = 0; i < nodeAttrs.length; i++) {
9266
- const nodeAttr = nodeAttrs[i];
9267
- if (isNameOnlyAttributeMarker(nodeAttr)) {
9268
- return i;
9379
+ handleError(error) {
9380
+ const originalError = this._findOriginalError(error);
9381
+ this._console.error('ERROR', error);
9382
+ if (originalError) {
9383
+ this._console.error('ORIGINAL ERROR', originalError);
9269
9384
  }
9270
9385
  }
9271
- return nodeAttrs.length;
9272
- }
9273
- function matchTemplateAttribute(attrs, name) {
9274
- let i = attrs.indexOf(4 /* AttributeMarker.Template */);
9275
- if (i > -1) {
9276
- i++;
9277
- while (i < attrs.length) {
9278
- const attr = attrs[i];
9279
- // Return in case we checked all template attrs and are switching to the next section in the
9280
- // attrs array (that starts with a number that represents an attribute marker).
9281
- if (typeof attr === 'number')
9282
- return -1;
9283
- if (attr === name)
9284
- return i;
9285
- i++;
9386
+ /** @internal */
9387
+ _findOriginalError(error) {
9388
+ let e = error && getOriginalError(error);
9389
+ while (e && getOriginalError(e)) {
9390
+ e = getOriginalError(e);
9286
9391
  }
9392
+ return e || null;
9287
9393
  }
9288
- return -1;
9289
9394
  }
9395
+
9396
+ const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
9290
9397
  /**
9291
- * Checks whether a selector is inside a CssSelectorList
9292
- * @param selector Selector to be checked.
9293
- * @param list List in which to look for the selector.
9398
+ * Internal token that specifies whether hydration is enabled.
9294
9399
  */
9295
- function isSelectorInSelectorList(selector, list) {
9296
- selectorListLoop: for (let i = 0; i < list.length; i++) {
9297
- const currentSelectorInList = list[i];
9298
- if (selector.length !== currentSelectorInList.length) {
9299
- continue;
9300
- }
9301
- for (let j = 0; j < selector.length; j++) {
9302
- if (selector[j] !== currentSelectorInList[j]) {
9303
- continue selectorListLoop;
9304
- }
9305
- }
9306
- return true;
9307
- }
9308
- return false;
9400
+ const IS_HYDRATION_FEATURE_ENABLED = new InjectionToken(NG_DEV_MODE$1 ? 'IS_HYDRATION_FEATURE_ENABLED' : '');
9401
+ // By default (in client rendering mode), we remove all the contents
9402
+ // of the host element and render an application after that.
9403
+ const PRESERVE_HOST_CONTENT_DEFAULT = false;
9404
+ /**
9405
+ * Internal token that indicates whether host element content should be
9406
+ * retained during the bootstrap.
9407
+ */
9408
+ const PRESERVE_HOST_CONTENT = new InjectionToken(NG_DEV_MODE$1 ? 'PRESERVE_HOST_CONTENT' : '', {
9409
+ providedIn: 'root',
9410
+ factory: () => PRESERVE_HOST_CONTENT_DEFAULT,
9411
+ });
9412
+
9413
+ function normalizeDebugBindingName(name) {
9414
+ // Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
9415
+ name = camelCaseToDashCase(name.replace(/[$@]/g, '_'));
9416
+ return `ng-reflect-${name}`;
9309
9417
  }
9310
- function maybeWrapInNotSelector(isNegativeMode, chunk) {
9311
- return isNegativeMode ? ':not(' + chunk.trim() + ')' : chunk;
9418
+ const CAMEL_CASE_REGEXP = /([A-Z])/g;
9419
+ function camelCaseToDashCase(input) {
9420
+ return input.replace(CAMEL_CASE_REGEXP, (...m) => '-' + m[1].toLowerCase());
9312
9421
  }
9313
- function stringifyCSSSelector(selector) {
9314
- let result = selector[0];
9315
- let i = 1;
9316
- let mode = 2 /* SelectorFlags.ATTRIBUTE */;
9317
- let currentChunk = '';
9318
- let isNegativeMode = false;
9319
- while (i < selector.length) {
9320
- let valueOrMarker = selector[i];
9321
- if (typeof valueOrMarker === 'string') {
9322
- if (mode & 2 /* SelectorFlags.ATTRIBUTE */) {
9323
- const attrValue = selector[++i];
9324
- currentChunk +=
9325
- '[' + valueOrMarker + (attrValue.length > 0 ? '="' + attrValue + '"' : '') + ']';
9326
- }
9327
- else if (mode & 8 /* SelectorFlags.CLASS */) {
9328
- currentChunk += '.' + valueOrMarker;
9329
- }
9330
- else if (mode & 4 /* SelectorFlags.ELEMENT */) {
9331
- currentChunk += ' ' + valueOrMarker;
9332
- }
9333
- }
9334
- else {
9335
- //
9336
- // Append current chunk to the final result in case we come across SelectorFlag, which
9337
- // indicates that the previous section of a selector is over. We need to accumulate content
9338
- // between flags to make sure we wrap the chunk later in :not() selector if needed, e.g.
9339
- // ```
9340
- // ['', Flags.CLASS, '.classA', Flags.CLASS | Flags.NOT, '.classB', '.classC']
9341
- // ```
9342
- // should be transformed to `.classA :not(.classB .classC)`.
9343
- //
9344
- // Note: for negative selector part, we accumulate content between flags until we find the
9345
- // next negative flag. This is needed to support a case where `:not()` rule contains more than
9346
- // one chunk, e.g. the following selector:
9347
- // ```
9348
- // ['', Flags.ELEMENT | Flags.NOT, 'p', Flags.CLASS, 'foo', Flags.CLASS | Flags.NOT, 'bar']
9349
- // ```
9350
- // should be stringified to `:not(p.foo) :not(.bar)`
9351
- //
9352
- if (currentChunk !== '' && !isPositive(valueOrMarker)) {
9353
- result += maybeWrapInNotSelector(isNegativeMode, currentChunk);
9354
- currentChunk = '';
9355
- }
9356
- mode = valueOrMarker;
9357
- // According to CssSelector spec, once we come across `SelectorFlags.NOT` flag, the negative
9358
- // mode is maintained for remaining chunks of a selector.
9359
- isNegativeMode = isNegativeMode || !isPositive(mode);
9360
- }
9361
- i++;
9422
+ function normalizeDebugBindingValue(value) {
9423
+ try {
9424
+ // Limit the size of the value as otherwise the DOM just gets polluted.
9425
+ return value != null ? value.toString().slice(0, 30) : value;
9362
9426
  }
9363
- if (currentChunk !== '') {
9364
- result += maybeWrapInNotSelector(isNegativeMode, currentChunk);
9427
+ catch (e) {
9428
+ return '[ERROR] Exception while trying to serialize the value';
9365
9429
  }
9366
- return result;
9367
9430
  }
9431
+
9368
9432
  /**
9369
- * Generates string representation of CSS selector in parsed form.
9370
9433
  *
9371
- * ComponentDef and DirectiveDef are generated with the selector in parsed form to avoid doing
9372
- * additional parsing at runtime (for example, for directive matching). However in some cases (for
9373
- * example, while bootstrapping a component), a string version of the selector is required to query
9374
- * for the host element on the page. This function takes the parsed form of a selector and returns
9375
- * its string representation.
9434
+ * @codeGenApi
9435
+ */
9436
+ function ɵɵresolveWindow(element) {
9437
+ return element.ownerDocument.defaultView;
9438
+ }
9439
+ /**
9376
9440
  *
9377
- * @param selectorList selector in parsed form
9378
- * @returns string representation of a given selector
9441
+ * @codeGenApi
9379
9442
  */
9380
- function stringifyCSSSelectorList(selectorList) {
9381
- return selectorList.map(stringifyCSSSelector).join(',');
9443
+ function ɵɵresolveDocument(element) {
9444
+ return element.ownerDocument;
9382
9445
  }
9383
9446
  /**
9384
- * Extracts attributes and classes information from a given CSS selector.
9385
9447
  *
9386
- * This function is used while creating a component dynamically. In this case, the host element
9387
- * (that is created dynamically) should contain attributes and classes specified in component's CSS
9388
- * selector.
9448
+ * @codeGenApi
9449
+ */
9450
+ function ɵɵresolveBody(element) {
9451
+ return element.ownerDocument.body;
9452
+ }
9453
+ /**
9454
+ * The special delimiter we use to separate property names, prefixes, and suffixes
9455
+ * in property binding metadata. See storeBindingMetadata().
9456
+ *
9457
+ * We intentionally use the Unicode "REPLACEMENT CHARACTER" (U+FFFD) as a delimiter
9458
+ * because it is a very uncommon character that is unlikely to be part of a user's
9459
+ * property names or interpolation strings. If it is in fact used in a property
9460
+ * binding, DebugElement.properties will not return the correct value for that
9461
+ * binding. However, there should be no runtime effect for real applications.
9462
+ *
9463
+ * This character is typically rendered as a question mark inside of a diamond.
9464
+ * See https://en.wikipedia.org/wiki/Specials_(Unicode_block)
9465
+ *
9466
+ */
9467
+ const INTERPOLATION_DELIMITER = `�`;
9468
+ /**
9469
+ * Unwrap a value which might be behind a closure (for forward declaration reasons).
9470
+ */
9471
+ function maybeUnwrapFn(value) {
9472
+ if (value instanceof Function) {
9473
+ return value();
9474
+ }
9475
+ else {
9476
+ return value;
9477
+ }
9478
+ }
9479
+
9480
+ /** Verifies that a given type is a Standalone Component. */
9481
+ function assertStandaloneComponentType(type) {
9482
+ assertComponentDef(type);
9483
+ const componentDef = getComponentDef(type);
9484
+ if (!componentDef.standalone) {
9485
+ throw new RuntimeError(907 /* RuntimeErrorCode.TYPE_IS_NOT_STANDALONE */, `The ${stringifyForError(type)} component is not marked as standalone, ` +
9486
+ `but Angular expects to have a standalone component here. ` +
9487
+ `Please make sure the ${stringifyForError(type)} component has ` +
9488
+ `the \`standalone: true\` flag in the decorator.`);
9489
+ }
9490
+ }
9491
+ /** Verifies whether a given type is a component */
9492
+ function assertComponentDef(type) {
9493
+ if (!getComponentDef(type)) {
9494
+ throw new RuntimeError(906 /* RuntimeErrorCode.MISSING_GENERATED_DEF */, `The ${stringifyForError(type)} is not an Angular component, ` +
9495
+ `make sure it has the \`@Component\` decorator.`);
9496
+ }
9497
+ }
9498
+ /** Called when there are multiple component selectors that match a given node */
9499
+ function throwMultipleComponentError(tNode, first, second) {
9500
+ throw new RuntimeError(-300 /* RuntimeErrorCode.MULTIPLE_COMPONENTS_MATCH */, `Multiple components match node with tagname ${tNode.value}: ` +
9501
+ `${stringifyForError(first)} and ` +
9502
+ `${stringifyForError(second)}`);
9503
+ }
9504
+ /** Throws an ExpressionChangedAfterChecked error if checkNoChanges mode is on. */
9505
+ function throwErrorIfNoChangesMode(creationMode, oldValue, currValue, propName) {
9506
+ const field = propName ? ` for '${propName}'` : '';
9507
+ let msg = `ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value${field}: '${oldValue}'. Current value: '${currValue}'.`;
9508
+ if (creationMode) {
9509
+ msg +=
9510
+ ` It seems like the view has been created after its parent and its children have been dirty checked.` +
9511
+ ` Has it been created in a change detection hook?`;
9512
+ }
9513
+ throw new RuntimeError(-100 /* RuntimeErrorCode.EXPRESSION_CHANGED_AFTER_CHECKED */, msg);
9514
+ }
9515
+ function constructDetailsForInterpolation(lView, rootIndex, expressionIndex, meta, changedValue) {
9516
+ const [propName, prefix, ...chunks] = meta.split(INTERPOLATION_DELIMITER);
9517
+ let oldValue = prefix, newValue = prefix;
9518
+ for (let i = 0; i < chunks.length; i++) {
9519
+ const slotIdx = rootIndex + i;
9520
+ oldValue += `${lView[slotIdx]}${chunks[i]}`;
9521
+ newValue += `${slotIdx === expressionIndex ? changedValue : lView[slotIdx]}${chunks[i]}`;
9522
+ }
9523
+ return { propName, oldValue, newValue };
9524
+ }
9525
+ /**
9526
+ * Constructs an object that contains details for the ExpressionChangedAfterItHasBeenCheckedError:
9527
+ * - property name (for property bindings or interpolations)
9528
+ * - old and new values, enriched using information from metadata
9389
9529
  *
9390
- * @param selector CSS selector in parsed form (in a form of array)
9391
- * @returns object with `attrs` and `classes` fields that contain extracted information
9530
+ * More information on the metadata storage format can be found in `storePropertyBindingMetadata`
9531
+ * function description.
9392
9532
  */
9393
- function extractAttrsAndClassesFromSelector(selector) {
9394
- const attrs = [];
9395
- const classes = [];
9396
- let i = 1;
9397
- let mode = 2 /* SelectorFlags.ATTRIBUTE */;
9398
- while (i < selector.length) {
9399
- let valueOrMarker = selector[i];
9400
- if (typeof valueOrMarker === 'string') {
9401
- if (mode === 2 /* SelectorFlags.ATTRIBUTE */) {
9402
- if (valueOrMarker !== '') {
9403
- attrs.push(valueOrMarker, selector[++i]);
9404
- }
9405
- }
9406
- else if (mode === 8 /* SelectorFlags.CLASS */) {
9407
- classes.push(valueOrMarker);
9408
- }
9533
+ function getExpressionChangedErrorDetails(lView, bindingIndex, oldValue, newValue) {
9534
+ const tData = lView[TVIEW].data;
9535
+ const metadata = tData[bindingIndex];
9536
+ if (typeof metadata === 'string') {
9537
+ // metadata for property interpolation
9538
+ if (metadata.indexOf(INTERPOLATION_DELIMITER) > -1) {
9539
+ return constructDetailsForInterpolation(lView, bindingIndex, bindingIndex, metadata, newValue);
9409
9540
  }
9410
- else {
9411
- // According to CssSelector spec, once we come across `SelectorFlags.NOT` flag, the negative
9412
- // mode is maintained for remaining chunks of a selector. Since attributes and classes are
9413
- // extracted only for "positive" part of the selector, we can stop here.
9414
- if (!isPositive(mode))
9415
- break;
9416
- mode = valueOrMarker;
9541
+ // metadata for property binding
9542
+ return { propName: metadata, oldValue, newValue };
9543
+ }
9544
+ // metadata is not available for this expression, check if this expression is a part of the
9545
+ // property interpolation by going from the current binding index left and look for a string that
9546
+ // contains INTERPOLATION_DELIMITER, the layout in tView.data for this case will look like this:
9547
+ // [..., 'id�Prefix � and � suffix', null, null, null, ...]
9548
+ if (metadata === null) {
9549
+ let idx = bindingIndex - 1;
9550
+ while (typeof tData[idx] !== 'string' && tData[idx + 1] === null) {
9551
+ idx--;
9552
+ }
9553
+ const meta = tData[idx];
9554
+ if (typeof meta === 'string') {
9555
+ const matches = meta.match(new RegExp(INTERPOLATION_DELIMITER, 'g'));
9556
+ // first interpolation delimiter separates property name from interpolation parts (in case of
9557
+ // property interpolations), so we subtract one from total number of found delimiters
9558
+ if (matches && (matches.length - 1) > bindingIndex - idx) {
9559
+ return constructDetailsForInterpolation(lView, idx, bindingIndex, meta, newValue);
9560
+ }
9417
9561
  }
9418
- i++;
9419
9562
  }
9420
- return { attrs, classes };
9563
+ return { propName: undefined, oldValue, newValue };
9421
9564
  }
9422
9565
 
9423
9566
  /** A special value which designates that a value has not changed. */
@@ -9476,6 +9619,33 @@ function selectIndexInternal(tView, lView, index, checkNoChangesMode) {
9476
9619
  setSelectedIndex(index);
9477
9620
  }
9478
9621
 
9622
+ /**
9623
+ * Runs the given function in the context of the given `Injector`.
9624
+ *
9625
+ * Within the function's stack frame, `inject` can be used to inject dependencies from the given
9626
+ * `Injector`. Note that `inject` is only usable synchronously, and cannot be used in any
9627
+ * asynchronous callbacks or after any `await` points.
9628
+ *
9629
+ * @param injector the injector which will satisfy calls to `inject` while `fn` is executing
9630
+ * @param fn the closure to be run in the context of `injector`
9631
+ * @returns the return value of the function, if any
9632
+ * @publicApi
9633
+ */
9634
+ function runInInjectionContext(injector, fn) {
9635
+ if (injector instanceof R3Injector) {
9636
+ injector.assertNotDestroyed();
9637
+ }
9638
+ const prevInjector = setCurrentInjector(injector);
9639
+ const previousInjectImplementation = setInjectImplementation(undefined);
9640
+ try {
9641
+ return fn();
9642
+ }
9643
+ finally {
9644
+ setCurrentInjector(prevInjector);
9645
+ setInjectImplementation(previousInjectImplementation);
9646
+ }
9647
+ }
9648
+
9479
9649
  /**
9480
9650
  * A mapping of the @angular/core API surface used in generated expressions to the actual symbols.
9481
9651
  *
@@ -10915,7 +11085,7 @@ function getOrCreateComponentTView(def) {
10915
11085
  // Declaration node here is null since this function is called when we dynamically create a
10916
11086
  // component and hence there is no declaration.
10917
11087
  const declTNode = null;
10918
- return def.tView = createTView(1 /* TViewType.Component */, declTNode, def.template, def.decls, def.vars, def.directiveDefs, def.pipeDefs, def.viewQuery, def.schemas, def.consts);
11088
+ return def.tView = createTView(1 /* TViewType.Component */, declTNode, def.template, def.decls, def.vars, def.directiveDefs, def.pipeDefs, def.viewQuery, def.schemas, def.consts, def.id);
10919
11089
  }
10920
11090
  return tView;
10921
11091
  }
@@ -10932,7 +11102,7 @@ function getOrCreateComponentTView(def) {
10932
11102
  * @param schemas Schemas for this view
10933
11103
  * @param consts Constants for this view
10934
11104
  */
10935
- function createTView(type, declTNode, templateFn, decls, vars, directives, pipes, viewQuery, schemas, constsOrFactory) {
11105
+ function createTView(type, declTNode, templateFn, decls, vars, directives, pipes, viewQuery, schemas, constsOrFactory, ssrId) {
10936
11106
  ngDevMode && ngDevMode.tView++;
10937
11107
  const bindingStartIndex = HEADER_OFFSET + decls;
10938
11108
  // This length does not yet contain host bindings from child directives because at this point,
@@ -10971,7 +11141,8 @@ function createTView(type, declTNode, templateFn, decls, vars, directives, pipes
10971
11141
  firstChild: null,
10972
11142
  schemas: schemas,
10973
11143
  consts: consts,
10974
- incompleteFirstPass: false
11144
+ incompleteFirstPass: false,
11145
+ ssrId,
10975
11146
  };
10976
11147
  if (ngDevMode) {
10977
11148
  // For performance reasons it is important that the tView retains the same shape during runtime.
@@ -10991,23 +11162,58 @@ function createViewBlueprint(bindingStartIndex, initialViewLength) {
10991
11162
  /**
10992
11163
  * Locates the host native element, used for bootstrapping existing nodes into rendering pipeline.
10993
11164
  *
10994
- * @param rendererFactory Factory function to create renderer instance.
11165
+ * @param renderer the renderer used to locate the element.
10995
11166
  * @param elementOrSelector Render element or CSS selector to locate the element.
10996
11167
  * @param encapsulation View Encapsulation defined for component that requests host element.
10997
11168
  * @param injector Root view injector instance.
10998
11169
  */
10999
11170
  function locateHostElement(renderer, elementOrSelector, encapsulation, injector) {
11000
11171
  // Note: we use default value for the `PRESERVE_HOST_CONTENT` here even though it's a
11001
- // tree-shakable one (providedIn:'root'). This code path can be triggered during dynamic component
11002
- // creation (after calling ViewContainerRef.createComponent) when an injector instance can be
11003
- // provided. The injector instance might be disconnected from the main DI tree, thus the
11004
- // `PRESERVE_HOST_CONTENT` woild not be able to instantiate. In this case, the default value will
11005
- // be used.
11172
+ // tree-shakable one (providedIn:'root'). This code path can be triggered during dynamic
11173
+ // component creation (after calling ViewContainerRef.createComponent) when an injector
11174
+ // instance can be provided. The injector instance might be disconnected from the main DI
11175
+ // tree, thus the `PRESERVE_HOST_CONTENT` woild not be able to instantiate. In this case, the
11176
+ // default value will be used.
11006
11177
  const preserveHostContent = injector.get(PRESERVE_HOST_CONTENT, PRESERVE_HOST_CONTENT_DEFAULT);
11007
11178
  // When using native Shadow DOM, do not clear host element to allow native slot
11008
11179
  // projection.
11009
11180
  const preserveContent = preserveHostContent || encapsulation === ViewEncapsulation$1.ShadowDom;
11010
- return renderer.selectRootElement(elementOrSelector, preserveContent);
11181
+ const rootElement = renderer.selectRootElement(elementOrSelector, preserveContent);
11182
+ applyRootElementTransform(rootElement);
11183
+ return rootElement;
11184
+ }
11185
+ /**
11186
+ * Applies any root element transformations that are needed. If hydration is enabled,
11187
+ * this will process corrupted text nodes.
11188
+ *
11189
+ * @param rootElement the app root HTML Element
11190
+ */
11191
+ function applyRootElementTransform(rootElement) {
11192
+ _applyRootElementTransformImpl(rootElement);
11193
+ }
11194
+ /**
11195
+ * Reference to a function that applies transformations to the root HTML element
11196
+ * of an app. When hydration is enabled, this processes any corrupt text nodes
11197
+ * so they are properly hydratable on the client.
11198
+ *
11199
+ * @param rootElement the app root HTML Element
11200
+ */
11201
+ let _applyRootElementTransformImpl = (rootElement) => null;
11202
+ /**
11203
+ * Processes text node markers before hydration begins. This replaces any special comment
11204
+ * nodes that were added prior to serialization are swapped out to restore proper text
11205
+ * nodes before hydration.
11206
+ *
11207
+ * @param rootElement the app root HTML Element
11208
+ */
11209
+ function applyRootElementTransformImpl(rootElement) {
11210
+ processTextNodeMarkersBeforeHydration(rootElement);
11211
+ }
11212
+ /**
11213
+ * Sets the implementation for the `applyRootElementTransform` function.
11214
+ */
11215
+ function enableApplyRootElementTransformImpl() {
11216
+ _applyRootElementTransformImpl = applyRootElementTransformImpl;
11011
11217
  }
11012
11218
  /**
11013
11219
  * Saves context for this cleanup function in LView.cleanupInstances.
@@ -11019,9 +11225,9 @@ function locateHostElement(renderer, elementOrSelector, encapsulation, injector)
11019
11225
  function storeCleanupWithContext(tView, lView, context, cleanupFn) {
11020
11226
  const lCleanup = getOrCreateLViewCleanup(lView);
11021
11227
  // Historically the `storeCleanupWithContext` was used to register both framework-level and
11022
- // user-defined cleanup callbacks, but over time those two types of cleanups were separated. This
11023
- // dev mode checks assures that user-level cleanup callbacks are _not_ stored in data structures
11024
- // reserved for framework-specific hooks.
11228
+ // user-defined cleanup callbacks, but over time those two types of cleanups were separated.
11229
+ // This dev mode checks assures that user-level cleanup callbacks are _not_ stored in data
11230
+ // structures reserved for framework-specific hooks.
11025
11231
  ngDevMode &&
11026
11232
  assertDefined(context, 'Cleanup context is mandatory when registering framework-level destroy hooks');
11027
11233
  lCleanup.push(context);
@@ -11740,7 +11946,8 @@ function createLContainer(hostNative, currentView, native, tNode) {
11740
11946
  tNode,
11741
11947
  native,
11742
11948
  null,
11743
- null, // moved views
11949
+ null,
11950
+ null, // dehydrated views
11744
11951
  ];
11745
11952
  ngDevMode &&
11746
11953
  assertEqual(lContainer.length, CONTAINER_HEADER_OFFSET, 'Should allocate correct number of slots for LContainer header.');
@@ -12562,7 +12769,7 @@ class ComponentFactory extends ComponentFactory$1 {
12562
12769
  const rootFlags = this.componentDef.onPush ? 32 /* LViewFlags.Dirty */ | 256 /* LViewFlags.IsRoot */ :
12563
12770
  16 /* LViewFlags.CheckAlways */ | 256 /* LViewFlags.IsRoot */;
12564
12771
  // Create the root view. Uses empty TView and ContentTemplate.
12565
- const rootTView = createTView(0 /* TViewType.Root */, null, null, 1, 0, null, null, null, null, null);
12772
+ const rootTView = createTView(0 /* TViewType.Root */, null, null, 1, 0, null, null, null, null, null, null);
12566
12773
  const rootLView = createLView(null, rootTView, null, rootFlags, null, null, rendererFactory, hostRenderer, sanitizer, rootViewInjector, null, null);
12567
12774
  // rootView is the parent when bootstrapping
12568
12775
  // TODO(misko): it looks like we are entering view here but we don't really need to as
@@ -13847,92 +14054,15 @@ function detectChanges(component) {
13847
14054
  detectChangesInternal(view[TVIEW], view, component);
13848
14055
  }
13849
14056
 
13850
- function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) {
13851
- ngDevMode && assertFirstCreatePass(tView);
13852
- ngDevMode && ngDevMode.firstCreatePass++;
13853
- const tViewConsts = tView.consts;
13854
- // TODO(pk): refactor getOrCreateTNode to have the "create" only version
13855
- const tNode = getOrCreateTNode(tView, index, 4 /* TNodeType.Container */, tagName || null, getConstant(tViewConsts, attrsIndex));
13856
- resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
13857
- registerPostOrderHooks(tView, tNode);
13858
- const embeddedTView = tNode.tView = createTView(2 /* TViewType.Embedded */, tNode, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry, null, tView.schemas, tViewConsts);
13859
- if (tView.queries !== null) {
13860
- tView.queries.template(tView, tNode);
13861
- embeddedTView.queries = tView.queries.embeddedTView(tNode);
13862
- }
13863
- return tNode;
13864
- }
13865
- /**
13866
- * Creates an LContainer for an ng-template (dynamically-inserted view), e.g.
13867
- *
13868
- * <ng-template #foo>
13869
- * <div></div>
13870
- * </ng-template>
13871
- *
13872
- * @param index The index of the container in the data array
13873
- * @param templateFn Inline template
13874
- * @param decls The number of nodes, local refs, and pipes for this template
13875
- * @param vars The number of bindings for this template
13876
- * @param tagName The name of the container element, if applicable
13877
- * @param attrsIndex Index of template attributes in the `consts` array.
13878
- * @param localRefs Index of the local references in the `consts` array.
13879
- * @param localRefExtractor A function which extracts local-refs values from the template.
13880
- * Defaults to the current element associated with the local-ref.
13881
- *
13882
- * @codeGenApi
13883
- */
13884
- function ɵɵtemplate(index, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex, localRefExtractor) {
13885
- const lView = getLView();
13886
- const tView = getTView();
13887
- const adjustedIndex = index + HEADER_OFFSET;
13888
- const tNode = tView.firstCreatePass ? templateFirstCreatePass(adjustedIndex, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) :
13889
- tView.data[adjustedIndex];
13890
- setCurrentTNode(tNode, false);
13891
- const comment = lView[RENDERER].createComment(ngDevMode ? 'container' : '');
13892
- appendChild(tView, lView, comment, tNode);
13893
- attachPatchData(comment, lView);
13894
- addToViewTree(lView, lView[adjustedIndex] = createLContainer(comment, lView, comment, tNode));
13895
- if (isDirectiveHost(tNode)) {
13896
- createDirectivesInstances(tView, lView, tNode);
13897
- }
13898
- if (localRefsIndex != null) {
13899
- saveResolvedLocalsInData(lView, tNode, localRefExtractor);
13900
- }
13901
- }
13902
-
13903
- /** Store a value in the `data` at a given `index`. */
13904
- function store(tView, lView, index, value) {
13905
- // We don't store any static data for local variables, so the first time
13906
- // we see the template, we should store as null to avoid a sparse array
13907
- if (index >= tView.data.length) {
13908
- tView.data[index] = null;
13909
- tView.blueprint[index] = null;
13910
- }
13911
- lView[index] = value;
13912
- }
13913
- /**
13914
- * Retrieves a local reference from the current contextViewData.
13915
- *
13916
- * If the reference to retrieve is in a parent view, this instruction is used in conjunction
13917
- * with a nextContext() call, which walks up the tree and updates the contextViewData instance.
13918
- *
13919
- * @param index The index of the local ref in contextViewData.
13920
- *
13921
- * @codeGenApi
13922
- */
13923
- function ɵɵreference(index) {
13924
- const contextLView = getContextLView();
13925
- return load(contextLView, HEADER_OFFSET + index);
13926
- }
13927
-
13928
14057
  /**
13929
14058
  * Verifies whether a given node matches an expected criteria,
13930
14059
  * based on internal data structure state.
13931
14060
  */
13932
14061
  function validateMatchingNode(node, nodeType, tagName, lView, tNode) {
14062
+ validateNodeExists(node);
13933
14063
  if (node.nodeType !== nodeType ||
13934
- (node.nodeType === Node.ELEMENT_NODE &&
13935
- node.tagName.toLowerCase() !== (tagName === null || tagName === void 0 ? void 0 : tagName.toLowerCase()))) {
14064
+ node.nodeType === Node.ELEMENT_NODE &&
14065
+ node.tagName.toLowerCase() !== (tagName === null || tagName === void 0 ? void 0 : tagName.toLowerCase())) {
13936
14066
  // TODO: improve error message and use RuntimeError instead.
13937
14067
  throw new Error(`Unexpected node found during hydration.`);
13938
14068
  }
@@ -13941,27 +14071,24 @@ function validateMatchingNode(node, nodeType, tagName, lView, tNode) {
13941
14071
  * Verifies whether next sibling node exists.
13942
14072
  */
13943
14073
  function validateSiblingNodeExists(node) {
14074
+ validateNodeExists(node);
13944
14075
  if (!node.nextSibling) {
13945
14076
  // TODO: improve error message and use RuntimeError instead.
13946
14077
  throw new Error(`Unexpected state: insufficient number of sibling nodes.`);
13947
14078
  }
13948
14079
  }
14080
+ function validateNodeExists(node) {
14081
+ if (!node) {
14082
+ // TODO: improve error message and use RuntimeError instead.
14083
+ throw new Error(`Hydration expected an element to be present at this location.`);
14084
+ }
14085
+ }
13949
14086
 
13950
14087
  /** Whether current TNode is a first node in an <ng-container>. */
13951
14088
  function isFirstElementInNgContainer(tNode) {
13952
14089
  var _a;
13953
14090
  return !tNode.prev && ((_a = tNode.parent) === null || _a === void 0 ? void 0 : _a.type) === 8 /* TNodeType.ElementContainer */;
13954
14091
  }
13955
- /** Returns first element from a DOM segment that corresponds to this <ng-container>. */
13956
- function getDehydratedNgContainer(hydrationInfo, tContainerNode) {
13957
- var _a;
13958
- const noOffsetIndex = tContainerNode.index - HEADER_OFFSET;
13959
- const ngContainer = (_a = hydrationInfo.ngContainers) === null || _a === void 0 ? void 0 : _a[noOffsetIndex];
13960
- ngDevMode &&
13961
- assertDefined(ngContainer, 'Unexpected state: no hydration info available for a given TNode, ' +
13962
- 'which represents an element container.');
13963
- return ngContainer;
13964
- }
13965
14092
  /**
13966
14093
  * Locate a node in DOM tree that corresponds to a given TNode.
13967
14094
  *
@@ -13972,7 +14099,7 @@ function getDehydratedNgContainer(hydrationInfo, tContainerNode) {
13972
14099
  * @returns an RNode that represents a given tNode
13973
14100
  */
13974
14101
  function locateNextRNode(hydrationInfo, tView, lView, tNode) {
13975
- var _a, _b;
14102
+ var _a;
13976
14103
  let native = null;
13977
14104
  if (tView.firstChild === tNode) {
13978
14105
  // We create a first node in this view, so we use a reference
@@ -13986,32 +14113,174 @@ function locateNextRNode(hydrationInfo, tView, lView, tNode) {
13986
14113
  ngDevMode &&
13987
14114
  assertDefined(previousTNode, 'Unexpected state: current TNode does not have a connection ' +
13988
14115
  'to the previous node or a parent node.');
13989
- const previousRElement = getNativeByTNode(previousTNode, lView);
13990
14116
  if (isFirstElementInNgContainer(tNode)) {
13991
- const ngContainer = getDehydratedNgContainer(hydrationInfo, tNode.parent);
13992
- native = (_b = ngContainer.firstChild) !== null && _b !== void 0 ? _b : null;
14117
+ const noOffsetParentIndex = tNode.parent.index - HEADER_OFFSET;
14118
+ native = getSegmentHead(hydrationInfo, noOffsetParentIndex);
13993
14119
  }
13994
14120
  else {
14121
+ let previousRElement = getNativeByTNode(previousTNode, lView);
13995
14122
  if (previousTNodeParent) {
13996
14123
  native = previousRElement.firstChild;
13997
14124
  }
13998
14125
  else {
13999
- native = previousRElement.nextSibling;
14126
+ // If the previous node is an element, but it also has container info,
14127
+ // this means that we are processing a node like `<div #vcrTarget>`, which is
14128
+ // represented in the DOM as `<div></div>...<!--container-->`.
14129
+ // In this case, there are nodes *after* this element and we need to skip
14130
+ // all of them to reach an element that we are looking for.
14131
+ const noOffsetPrevSiblingIndex = previousTNode.index - HEADER_OFFSET;
14132
+ const segmentHead = getSegmentHead(hydrationInfo, noOffsetPrevSiblingIndex);
14133
+ if (previousTNode.type === 2 /* TNodeType.Element */ && segmentHead) {
14134
+ const numRootNodesToSkip = calcSerializedContainerSize(hydrationInfo, noOffsetPrevSiblingIndex);
14135
+ // `+1` stands for an anchor comment node after all the views in this container.
14136
+ const nodesToSkip = numRootNodesToSkip + 1;
14137
+ // First node after this segment.
14138
+ native = siblingAfter(nodesToSkip, segmentHead);
14139
+ }
14140
+ else {
14141
+ native = previousRElement.nextSibling;
14142
+ }
14000
14143
  }
14001
14144
  }
14002
14145
  }
14003
- return native;
14146
+ return native;
14147
+ }
14148
+ /**
14149
+ * Skips over a specified number of nodes and returns the next sibling node after that.
14150
+ */
14151
+ function siblingAfter(skip, from) {
14152
+ let currentNode = from;
14153
+ for (let i = 0; i < skip; i++) {
14154
+ ngDevMode && validateSiblingNodeExists(currentNode);
14155
+ currentNode = currentNode.nextSibling;
14156
+ }
14157
+ return currentNode;
14158
+ }
14159
+
14160
+ function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) {
14161
+ var _a, _b;
14162
+ ngDevMode && assertFirstCreatePass(tView);
14163
+ ngDevMode && ngDevMode.firstCreatePass++;
14164
+ const tViewConsts = tView.consts;
14165
+ let ssrId = null;
14166
+ const hydrationInfo = lView[HYDRATION];
14167
+ if (hydrationInfo) {
14168
+ const noOffsetIndex = index - HEADER_OFFSET;
14169
+ ssrId = (_b = (hydrationInfo && ((_a = hydrationInfo.data[TEMPLATES]) === null || _a === void 0 ? void 0 : _a[noOffsetIndex]))) !== null && _b !== void 0 ? _b : null;
14170
+ }
14171
+ // TODO(pk): refactor getOrCreateTNode to have the "create" only version
14172
+ const tNode = getOrCreateTNode(tView, index, 4 /* TNodeType.Container */, tagName || null, getConstant(tViewConsts, attrsIndex));
14173
+ resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
14174
+ registerPostOrderHooks(tView, tNode);
14175
+ const embeddedTView = tNode.tView = createTView(2 /* TViewType.Embedded */, tNode, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry, null, tView.schemas, tViewConsts, ssrId);
14176
+ if (tView.queries !== null) {
14177
+ tView.queries.template(tView, tNode);
14178
+ embeddedTView.queries = tView.queries.embeddedTView(tNode);
14179
+ }
14180
+ return tNode;
14181
+ }
14182
+ /**
14183
+ * Creates an LContainer for an ng-template (dynamically-inserted view), e.g.
14184
+ *
14185
+ * <ng-template #foo>
14186
+ * <div></div>
14187
+ * </ng-template>
14188
+ *
14189
+ * @param index The index of the container in the data array
14190
+ * @param templateFn Inline template
14191
+ * @param decls The number of nodes, local refs, and pipes for this template
14192
+ * @param vars The number of bindings for this template
14193
+ * @param tagName The name of the container element, if applicable
14194
+ * @param attrsIndex Index of template attributes in the `consts` array.
14195
+ * @param localRefs Index of the local references in the `consts` array.
14196
+ * @param localRefExtractor A function which extracts local-refs values from the template.
14197
+ * Defaults to the current element associated with the local-ref.
14198
+ *
14199
+ * @codeGenApi
14200
+ */
14201
+ function ɵɵtemplate(index, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex, localRefExtractor) {
14202
+ const lView = getLView();
14203
+ const tView = getTView();
14204
+ const adjustedIndex = index + HEADER_OFFSET;
14205
+ const tNode = tView.firstCreatePass ? templateFirstCreatePass(adjustedIndex, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) :
14206
+ tView.data[adjustedIndex];
14207
+ setCurrentTNode(tNode, false);
14208
+ const comment = _locateOrCreateContainerAnchor(tView, lView, tNode, index);
14209
+ if (wasLastNodeCreated()) {
14210
+ appendChild(tView, lView, comment, tNode);
14211
+ }
14212
+ attachPatchData(comment, lView);
14213
+ addToViewTree(lView, lView[adjustedIndex] = createLContainer(comment, lView, comment, tNode));
14214
+ if (isDirectiveHost(tNode)) {
14215
+ createDirectivesInstances(tView, lView, tNode);
14216
+ }
14217
+ if (localRefsIndex != null) {
14218
+ saveResolvedLocalsInData(lView, tNode, localRefExtractor);
14219
+ }
14220
+ }
14221
+ let _locateOrCreateContainerAnchor = createContainerAnchorImpl;
14222
+ /**
14223
+ * Regular creation mode for LContainers and their anchor (comment) nodes.
14224
+ */
14225
+ function createContainerAnchorImpl(tView, lView, tNode, index) {
14226
+ lastNodeWasCreated(true);
14227
+ return lView[RENDERER].createComment(ngDevMode ? 'container' : '');
14228
+ }
14229
+ /**
14230
+ * Enables hydration code path (to lookup existing elements in DOM)
14231
+ * in addition to the regular creation mode for LContainers and their
14232
+ * anchor (comment) nodes.
14233
+ */
14234
+ function locateOrCreateContainerAnchorImpl(tView, lView, tNode, index) {
14235
+ const hydrationInfo = lView[HYDRATION];
14236
+ const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
14237
+ lastNodeWasCreated(isNodeCreationMode);
14238
+ // Regular creation mode.
14239
+ if (isNodeCreationMode) {
14240
+ return createContainerAnchorImpl(tView, lView, tNode, index);
14241
+ }
14242
+ // Hydration mode, looking up existing elements in DOM.
14243
+ const currentRNode = locateNextRNode(hydrationInfo, tView, lView, tNode);
14244
+ ngDevMode && validateNodeExists(currentRNode);
14245
+ const viewContainerSize = calcSerializedContainerSize(hydrationInfo, index);
14246
+ // If this container is non-empty, store the first node as a segment head,
14247
+ // otherwise, this node is an anchor and segment head doesn't exist (thus `null`).
14248
+ const segmentHead = viewContainerSize > 0 ? currentRNode : null;
14249
+ setSegmentHead(hydrationInfo, index, segmentHead);
14250
+ const comment = siblingAfter(viewContainerSize, currentRNode);
14251
+ if (ngDevMode) {
14252
+ validateMatchingNode(comment, Node.COMMENT_NODE, null, lView, tNode);
14253
+ markRNodeAsClaimedByHydration(comment);
14254
+ }
14255
+ return comment;
14256
+ }
14257
+ function enableLocateOrCreateContainerAnchorImpl() {
14258
+ _locateOrCreateContainerAnchor = locateOrCreateContainerAnchorImpl;
14259
+ }
14260
+
14261
+ /** Store a value in the `data` at a given `index`. */
14262
+ function store(tView, lView, index, value) {
14263
+ // We don't store any static data for local variables, so the first time
14264
+ // we see the template, we should store as null to avoid a sparse array
14265
+ if (index >= tView.data.length) {
14266
+ tView.data[index] = null;
14267
+ tView.blueprint[index] = null;
14268
+ }
14269
+ lView[index] = value;
14004
14270
  }
14005
14271
  /**
14006
- * Skips over a specified number of nodes and returns the next sibling node after that.
14272
+ * Retrieves a local reference from the current contextViewData.
14273
+ *
14274
+ * If the reference to retrieve is in a parent view, this instruction is used in conjunction
14275
+ * with a nextContext() call, which walks up the tree and updates the contextViewData instance.
14276
+ *
14277
+ * @param index The index of the local ref in contextViewData.
14278
+ *
14279
+ * @codeGenApi
14007
14280
  */
14008
- function siblingAfter(skip, from) {
14009
- let currentNode = from;
14010
- for (let i = 0; i < skip; i++) {
14011
- ngDevMode && validateSiblingNodeExists(currentNode);
14012
- currentNode = currentNode.nextSibling;
14013
- }
14014
- return currentNode;
14281
+ function ɵɵreference(index) {
14282
+ const contextLView = getContextLView();
14283
+ return load(contextLView, HEADER_OFFSET + index);
14015
14284
  }
14016
14285
 
14017
14286
  /**
@@ -14040,6 +14309,21 @@ function hasNgSkipHydrationAttr(tNode) {
14040
14309
  }
14041
14310
  return false;
14042
14311
  }
14312
+ /**
14313
+ * Helper function that determines if a given node is within a skip hydration block
14314
+ * by navigating up the TNode tree to see if any parent nodes have skip hydration
14315
+ * attribute.
14316
+ */
14317
+ function isInSkipHydrationBlock(tNode) {
14318
+ let currentTNode = tNode.parent;
14319
+ while (currentTNode) {
14320
+ if (hasNgSkipHydrationAttr(currentTNode)) {
14321
+ return true;
14322
+ }
14323
+ currentTNode = currentTNode.parent;
14324
+ }
14325
+ return false;
14326
+ }
14043
14327
 
14044
14328
  /**
14045
14329
  * Update a property on a selected element.
@@ -14125,7 +14409,7 @@ function ɵɵelementStart(index, name, attrsIndex, localRefsIndex) {
14125
14409
  const tNode = tView.firstCreatePass ?
14126
14410
  elementStartFirstCreatePass(adjustedIndex, tView, lView, name, attrsIndex, localRefsIndex) :
14127
14411
  tView.data[adjustedIndex];
14128
- const native = _locateOrCreateElementNode(tView, lView, tNode, renderer, name);
14412
+ const native = _locateOrCreateElementNode(tView, lView, tNode, renderer, name, index);
14129
14413
  lView[adjustedIndex] = native;
14130
14414
  const hasDirectives = isDirectiveHost(tNode);
14131
14415
  if (ngDevMode && tView.firstCreatePass) {
@@ -14208,7 +14492,7 @@ function ɵɵelement(index, name, attrsIndex, localRefsIndex) {
14208
14492
  ɵɵelementEnd();
14209
14493
  return ɵɵelement;
14210
14494
  }
14211
- let _locateOrCreateElementNode = (tView, lView, tNode, renderer, name) => {
14495
+ let _locateOrCreateElementNode = (tView, lView, tNode, renderer, name, index) => {
14212
14496
  lastNodeWasCreated(true);
14213
14497
  return createElementNode(renderer, name, getNamespace$1());
14214
14498
  };
@@ -14216,9 +14500,9 @@ let _locateOrCreateElementNode = (tView, lView, tNode, renderer, name) => {
14216
14500
  * Enables hydration code path (to lookup existing elements in DOM)
14217
14501
  * in addition to the regular creation mode of element nodes.
14218
14502
  */
14219
- function locateOrCreateElementNodeImpl(tView, lView, tNode, renderer, name) {
14503
+ function locateOrCreateElementNodeImpl(tView, lView, tNode, renderer, name, index) {
14220
14504
  const hydrationInfo = lView[HYDRATION];
14221
- const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock();
14505
+ const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
14222
14506
  lastNodeWasCreated(isNodeCreationMode);
14223
14507
  // Regular creation mode.
14224
14508
  if (isNodeCreationMode) {
@@ -14226,9 +14510,19 @@ function locateOrCreateElementNodeImpl(tView, lView, tNode, renderer, name) {
14226
14510
  }
14227
14511
  // Hydration mode, looking up an existing element in DOM.
14228
14512
  const native = locateNextRNode(hydrationInfo, tView, lView, tNode);
14229
- ngDevMode &&
14230
- validateMatchingNode(native, Node.ELEMENT_NODE, name, lView, tNode);
14513
+ ngDevMode && validateMatchingNode(native, Node.ELEMENT_NODE, name, lView, tNode);
14231
14514
  ngDevMode && markRNodeAsClaimedByHydration(native);
14515
+ // This element might also be an anchor of a view container.
14516
+ if (getSerializedContainerViews(hydrationInfo, index)) {
14517
+ // Important note: this element acts as an anchor, but it's **not** a part
14518
+ // of the embedded view, so we start the segment **after** this element, taking
14519
+ // a reference to the next sibling. For example, the following template:
14520
+ // `<div #vcrTarget>` is represented in the DOM as `<div></div>...<!--container-->`,
14521
+ // so while processing a `<div>` instruction, point to the next sibling as a
14522
+ // start of a segment.
14523
+ ngDevMode && validateNodeExists(native.nextSibling);
14524
+ setSegmentHead(hydrationInfo, index, native.nextSibling);
14525
+ }
14232
14526
  // Checks if the skip hydration attribute is present during hydration so we know to
14233
14527
  // skip attempting to hydrate this block.
14234
14528
  if (hydrationInfo && hasNgSkipHydrationAttr(tNode)) {
@@ -14356,7 +14650,7 @@ let _locateOrCreateElementContainerNode = (tView, lView, tNode, index) => {
14356
14650
  function locateOrCreateElementContainerNode(tView, lView, tNode, index) {
14357
14651
  let comment;
14358
14652
  const hydrationInfo = lView[HYDRATION];
14359
- const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock();
14653
+ const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
14360
14654
  lastNodeWasCreated(isNodeCreationMode);
14361
14655
  // Regular creation mode.
14362
14656
  if (isNodeCreationMode) {
@@ -14364,21 +14658,20 @@ function locateOrCreateElementContainerNode(tView, lView, tNode, index) {
14364
14658
  }
14365
14659
  // Hydration mode, looking up existing elements in DOM.
14366
14660
  const currentRNode = locateNextRNode(hydrationInfo, tView, lView, tNode);
14661
+ ngDevMode && validateNodeExists(currentRNode);
14367
14662
  const ngContainerSize = getNgContainerSize(hydrationInfo, index);
14368
14663
  ngDevMode &&
14369
14664
  assertNumber(ngContainerSize, 'Unexpected state: hydrating an <ng-container>, ' +
14370
14665
  'but no hydration info is available.');
14371
- if (ngContainerSize > 0) {
14372
- storeNgContainerInfo(hydrationInfo, index, currentRNode);
14373
- comment = siblingAfter(ngContainerSize, currentRNode);
14374
- }
14375
- else {
14376
- // If <ng-container> has no nodes,
14377
- // the current node is an anchor (comment) node.
14378
- comment = currentRNode;
14666
+ // If this container is non-empty, store the first node as a segment head,
14667
+ // otherwise, this node is an anchor and segment head doesn't exist (thus `null`).
14668
+ const segmentHead = ngContainerSize > 0 ? currentRNode : null;
14669
+ setSegmentHead(hydrationInfo, index, segmentHead);
14670
+ comment = siblingAfter(ngContainerSize, currentRNode);
14671
+ if (ngDevMode) {
14672
+ validateMatchingNode(comment, Node.COMMENT_NODE, null, lView, tNode);
14673
+ markRNodeAsClaimedByHydration(comment);
14379
14674
  }
14380
- ngDevMode && validateMatchingNode(comment, Node.COMMENT_NODE, null, lView, tNode);
14381
- ngDevMode && markRNodeAsClaimedByHydration(comment);
14382
14675
  return comment;
14383
14676
  }
14384
14677
  function enableLocateOrCreateElementContainerNodeImpl() {
@@ -16736,7 +17029,7 @@ let _locateOrCreateTextNode = (tView, lView, tNode, value) => {
16736
17029
  */
16737
17030
  function locateOrCreateTextNodeImpl(tView, lView, tNode, value) {
16738
17031
  const hydrationInfo = lView[HYDRATION];
16739
- const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock();
17032
+ const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
16740
17033
  lastNodeWasCreated(isNodeCreationMode);
16741
17034
  // Regular creation mode.
16742
17035
  if (isNodeCreationMode) {
@@ -20404,7 +20697,7 @@ class NgModuleFactory$1 {
20404
20697
  * @publicApi
20405
20698
  */
20406
20699
  function createNgModule(ngModule, parentInjector) {
20407
- return new NgModuleRef(ngModule, parentInjector !== null && parentInjector !== void 0 ? parentInjector : null);
20700
+ return new NgModuleRef(ngModule, parentInjector !== null && parentInjector !== void 0 ? parentInjector : null, []);
20408
20701
  }
20409
20702
  /**
20410
20703
  * The `createNgModule` function alias for backwards-compatibility.
@@ -20414,7 +20707,7 @@ function createNgModule(ngModule, parentInjector) {
20414
20707
  */
20415
20708
  const createNgModuleRef = createNgModule;
20416
20709
  class NgModuleRef extends NgModuleRef$1 {
20417
- constructor(ngModuleType, _parent) {
20710
+ constructor(ngModuleType, _parent, additionalProviders) {
20418
20711
  super();
20419
20712
  this._parent = _parent;
20420
20713
  // tslint:disable-next-line:require-internal-with-underscore
@@ -20435,7 +20728,8 @@ class NgModuleRef extends NgModuleRef$1 {
20435
20728
  { provide: NgModuleRef$1, useValue: this }, {
20436
20729
  provide: ComponentFactoryResolver$1,
20437
20730
  useValue: this.componentFactoryResolver
20438
- }
20731
+ },
20732
+ ...additionalProviders
20439
20733
  ], stringify(ngModuleType), new Set(['environment']));
20440
20734
  // We need to resolve the injector types separately from the injector creation, because
20441
20735
  // the module might be trying to use this ref in its constructor for DI which will cause a
@@ -20464,9 +20758,12 @@ class NgModuleFactory extends NgModuleFactory$1 {
20464
20758
  this.moduleType = moduleType;
20465
20759
  }
20466
20760
  create(parentInjector) {
20467
- return new NgModuleRef(this.moduleType, parentInjector);
20761
+ return new NgModuleRef(this.moduleType, parentInjector, []);
20468
20762
  }
20469
20763
  }
20764
+ function createNgModuleRefWithProviders(moduleType, parentInjector, additionalProviders) {
20765
+ return new NgModuleRef(moduleType, parentInjector, additionalProviders);
20766
+ }
20470
20767
  class EnvironmentNgModuleRefAdapter extends NgModuleRef$1 {
20471
20768
  constructor(providers, parent, source) {
20472
20769
  super();
@@ -20914,7 +21211,8 @@ function sortListeners(a, b) {
20914
21211
  * See call site for more info.
20915
21212
  */
20916
21213
  function isDirectiveDefHack(obj) {
20917
- return obj.type !== undefined && obj.template !== undefined && obj.declaredInputs !== undefined;
21214
+ return obj.type !== undefined && obj.declaredInputs !== undefined &&
21215
+ obj.findHostDirectiveDefs !== undefined;
20918
21216
  }
20919
21217
  /**
20920
21218
  * Retrieve the component `LView` from component/element.
@@ -21752,9 +22050,25 @@ const R3TemplateRef = class TemplateRef extends ViewEngineTemplateRef {
21752
22050
  this._declarationTContainer = _declarationTContainer;
21753
22051
  this.elementRef = elementRef;
21754
22052
  }
22053
+ /**
22054
+ * Returns an `ssrId` associated with a TView, which was used to
22055
+ * create this instance of the `TemplateRef`.
22056
+ *
22057
+ * @internal
22058
+ */
22059
+ get ssrId() {
22060
+ var _a;
22061
+ return ((_a = this._declarationTContainer.tView) === null || _a === void 0 ? void 0 : _a.ssrId) || null;
22062
+ }
21755
22063
  createEmbeddedView(context, injector) {
22064
+ return this.createEmbeddedViewImpl(context, injector, null);
22065
+ }
22066
+ /**
22067
+ * @internal
22068
+ */
22069
+ createEmbeddedViewImpl(context, injector, hydrationInfo) {
21756
22070
  const embeddedTView = this._declarationTContainer.tView;
21757
- const embeddedLView = createLView(this._declarationLView, embeddedTView, context, 16 /* LViewFlags.CheckAlways */, null, embeddedTView.declTNode, null, null, null, null, injector || null, null);
22071
+ const embeddedLView = createLView(this._declarationLView, embeddedTView, context, 16 /* LViewFlags.CheckAlways */, null, embeddedTView.declTNode, null, null, null, null, injector || null, hydrationInfo || null);
21758
22072
  const declarationLContainer = this._declarationLView[this._declarationTContainer.index];
21759
22073
  ngDevMode && assertLContainer(declarationLContainer);
21760
22074
  embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;
@@ -21789,6 +22103,114 @@ function createTemplateRef(hostTNode, hostLView) {
21789
22103
  return null;
21790
22104
  }
21791
22105
 
22106
+ /**
22107
+ * Removes all dehydrated views from a given LContainer:
22108
+ * both in internal data structure, as well as removing
22109
+ * corresponding DOM nodes that belong to that dehydrated view.
22110
+ */
22111
+ function removeDehydratedViews(lContainer) {
22112
+ var _a;
22113
+ const views = (_a = lContainer[DEHYDRATED_VIEWS]) !== null && _a !== void 0 ? _a : [];
22114
+ const parentLView = lContainer[PARENT];
22115
+ const renderer = parentLView[RENDERER];
22116
+ for (const view of views) {
22117
+ removeDehydratedView(view, renderer);
22118
+ ngDevMode && ngDevMode.dehydratedViewsRemoved++;
22119
+ }
22120
+ // Reset the value to an empty array to indicate that no
22121
+ // further processing of dehydrated views is needed for
22122
+ // this view container (i.e. do not trigger the lookup process
22123
+ // once again in case a `ViewContainerRef` is created later).
22124
+ lContainer[DEHYDRATED_VIEWS] = EMPTY_ARRAY;
22125
+ }
22126
+ /**
22127
+ * Helper function to remove all nodes from a dehydrated view.
22128
+ */
22129
+ function removeDehydratedView(dehydratedView, renderer) {
22130
+ let nodesRemoved = 0;
22131
+ let currentRNode = dehydratedView.firstChild;
22132
+ if (currentRNode) {
22133
+ const numNodes = dehydratedView.data[NUM_ROOT_NODES];
22134
+ while (nodesRemoved < numNodes) {
22135
+ ngDevMode && validateSiblingNodeExists(currentRNode);
22136
+ const nextSibling = currentRNode.nextSibling;
22137
+ nativeRemoveNode(renderer, currentRNode, false);
22138
+ currentRNode = nextSibling;
22139
+ nodesRemoved++;
22140
+ }
22141
+ }
22142
+ }
22143
+
22144
+ /**
22145
+ * Given a current DOM node and a serialized information about the views
22146
+ * in a container, walks over the DOM structure, collecting the list of
22147
+ * dehydrated views.
22148
+ */
22149
+ function locateDehydratedViewsInContainer(currentRNode, serializedViews) {
22150
+ const dehydratedViews = [];
22151
+ for (const serializedView of serializedViews) {
22152
+ const view = {
22153
+ data: serializedView,
22154
+ firstChild: null,
22155
+ };
22156
+ if (serializedView[NUM_ROOT_NODES] > 0) {
22157
+ // Keep reference to the first node in this view,
22158
+ // so it can be accessed while invoking template instructions.
22159
+ view.firstChild = currentRNode;
22160
+ // Move over to the next node after this view, which can
22161
+ // either be a first node of the next view or an anchor comment
22162
+ // node after the last view in a container.
22163
+ currentRNode = siblingAfter(serializedView[NUM_ROOT_NODES], currentRNode);
22164
+ }
22165
+ dehydratedViews.push(view);
22166
+ }
22167
+ return [currentRNode, dehydratedViews];
22168
+ }
22169
+ /**
22170
+ * Reference to a function that searches for a matching dehydrated views
22171
+ * stored on a given lContainer.
22172
+ * Returns `null` by default, when hydration is not enabled.
22173
+ */
22174
+ let _findMatchingDehydratedViewImpl = (lContainer, template) => null;
22175
+ /**
22176
+ * Retrieves the next dehydrated view from the LContainer and verifies that
22177
+ * it matches a given template id (from the TView that was used to create this
22178
+ * instance of a view). If the id doesn't match, that means that we are in an
22179
+ * unexpected state and can not complete the reconciliation process. Thus,
22180
+ * all dehydrated views from this LContainer are removed (including corresponding
22181
+ * DOM nodes) and the rendering is performed as if there were no dehydrated views
22182
+ * in this container.
22183
+ */
22184
+ function findMatchingDehydratedViewImpl(lContainer, template) {
22185
+ var _a;
22186
+ const views = (_a = lContainer[DEHYDRATED_VIEWS]) !== null && _a !== void 0 ? _a : [];
22187
+ if (!template || views.length === 0) {
22188
+ return null;
22189
+ }
22190
+ const view = views[0];
22191
+ // Verify whether the first dehydrated view in the container matches
22192
+ // the template id passed to this function (that originated from a TView
22193
+ // that was used to create an instance of an embedded or component views.
22194
+ if (view.data[TEMPLATE_ID] === template) {
22195
+ // If the template id matches - extract the first view and return it.
22196
+ return views.shift();
22197
+ }
22198
+ else {
22199
+ // Otherwise, we are at the state when reconciliation can not be completed,
22200
+ // thus we remove all dehydrated views within this container (remove them
22201
+ // from internal data structures as well as delete associated elements from
22202
+ // the DOM tree).
22203
+ removeDehydratedViews(lContainer);
22204
+ return null;
22205
+ }
22206
+ }
22207
+ function enableFindMatchingDehydratedViewImpl() {
22208
+ _findMatchingDehydratedViewImpl = findMatchingDehydratedViewImpl;
22209
+ }
22210
+ function findMatchingDehydratedView(lContainer, template) {
22211
+ return _findMatchingDehydratedViewImpl(lContainer, template);
22212
+ }
22213
+
21792
22214
  /**
21793
22215
  * Represents a container where one or more views can be attached to a component.
21794
22216
  *
@@ -21873,11 +22295,13 @@ const R3ViewContainerRef = class ViewContainerRef extends VE_ViewContainerRef {
21873
22295
  index = indexOrOptions.index;
21874
22296
  injector = indexOrOptions.injector;
21875
22297
  }
21876
- const viewRef = templateRef.createEmbeddedView(context || {}, injector);
21877
- this.insert(viewRef, index);
22298
+ const hydrationInfo = findMatchingDehydratedView(this._lContainer, templateRef.ssrId);
22299
+ const viewRef = templateRef.createEmbeddedViewImpl(context || {}, injector, hydrationInfo);
22300
+ this.insertImpl(viewRef, index, !!hydrationInfo);
21878
22301
  return viewRef;
21879
22302
  }
21880
22303
  createComponent(componentFactoryOrType, indexOrOptions, injector, projectableNodes, environmentInjector) {
22304
+ var _a, _b, _c;
21881
22305
  const isComponentFactory = componentFactoryOrType && !isType(componentFactoryOrType);
21882
22306
  let index;
21883
22307
  // This function supports 2 signatures and we need to handle options correctly for both:
@@ -21944,11 +22368,17 @@ const R3ViewContainerRef = class ViewContainerRef extends VE_ViewContainerRef {
21944
22368
  environmentInjector = result;
21945
22369
  }
21946
22370
  }
21947
- const componentRef = componentFactory.create(contextInjector, projectableNodes, undefined, environmentInjector);
21948
- this.insert(componentRef.hostView, index);
22371
+ const componentDef = getComponentDef((_a = componentFactory.componentType) !== null && _a !== void 0 ? _a : {});
22372
+ const dehydratedView = findMatchingDehydratedView(this._lContainer, (_b = componentDef === null || componentDef === void 0 ? void 0 : componentDef.id) !== null && _b !== void 0 ? _b : null);
22373
+ const rNode = (_c = dehydratedView === null || dehydratedView === void 0 ? void 0 : dehydratedView.firstChild) !== null && _c !== void 0 ? _c : null;
22374
+ const componentRef = componentFactory.create(contextInjector, projectableNodes, rNode, environmentInjector);
22375
+ this.insertImpl(componentRef.hostView, index, !!dehydratedView);
21949
22376
  return componentRef;
21950
22377
  }
21951
22378
  insert(viewRef, index) {
22379
+ return this.insertImpl(viewRef, index, false);
22380
+ }
22381
+ insertImpl(viewRef, index, skipDomInsertion) {
21952
22382
  const lView = viewRef._lView;
21953
22383
  const tView = lView[TVIEW];
21954
22384
  if (ngDevMode && viewRef.destroyed) {
@@ -21979,11 +22409,13 @@ const R3ViewContainerRef = class ViewContainerRef extends VE_ViewContainerRef {
21979
22409
  const lContainer = this._lContainer;
21980
22410
  insertView(tView, lView, lContainer, adjustedIdx);
21981
22411
  // Physical operation of adding the DOM nodes.
21982
- const beforeNode = getBeforeNodeForView(adjustedIdx, lContainer);
21983
- const renderer = lView[RENDERER];
21984
- const parentRNode = nativeParentNode(renderer, lContainer[NATIVE]);
21985
- if (parentRNode !== null) {
21986
- addViewToContainer(tView, lContainer[T_HOST], renderer, lView, parentRNode, beforeNode);
22412
+ if (!skipDomInsertion) {
22413
+ const beforeNode = getBeforeNodeForView(adjustedIdx, lContainer);
22414
+ const renderer = lView[RENDERER];
22415
+ const parentRNode = nativeParentNode(renderer, lContainer[NATIVE]);
22416
+ if (parentRNode !== null) {
22417
+ addViewToContainer(tView, lContainer[T_HOST], renderer, lView, parentRNode, beforeNode);
22418
+ }
21987
22419
  }
21988
22420
  viewRef.attachToViewContainerRef();
21989
22421
  addToArray(getOrCreateViewRefs(lContainer), adjustedIdx, viewRef);
@@ -22040,8 +22472,6 @@ function getOrCreateViewRefs(lContainer) {
22040
22472
  /**
22041
22473
  * Creates a ViewContainerRef and stores it on the injector.
22042
22474
  *
22043
- * @param ViewContainerRefToken The ViewContainerRef type
22044
- * @param ElementRefToken The ElementRef type
22045
22475
  * @param hostTNode The node that is requesting a ViewContainerRef
22046
22476
  * @param hostLView The view to which the node belongs
22047
22477
  * @returns The ViewContainerRef instance to use
@@ -22055,31 +22485,95 @@ function createContainerRef(hostTNode, hostLView) {
22055
22485
  lContainer = slotValue;
22056
22486
  }
22057
22487
  else {
22058
- let commentNode;
22059
- // If the host is an element container, the native host element is guaranteed to be a
22060
- // comment and we can reuse that comment as anchor element for the new LContainer.
22061
- // The comment node in question is already part of the DOM structure so we don't need to append
22062
- // it again.
22063
- if (hostTNode.type & 8 /* TNodeType.ElementContainer */) {
22064
- commentNode = unwrapRNode(slotValue);
22065
- }
22066
- else {
22067
- // If the host is a regular element, we have to insert a comment node manually which will
22068
- // be used as an anchor when inserting elements. In this specific case we use low-level DOM
22069
- // manipulation to insert it.
22070
- const renderer = hostLView[RENDERER];
22071
- ngDevMode && ngDevMode.rendererCreateComment++;
22072
- commentNode = renderer.createComment(ngDevMode ? 'container' : '');
22073
- const hostNative = getNativeByTNode(hostTNode, hostLView);
22074
- const parentOfHostNative = nativeParentNode(renderer, hostNative);
22075
- nativeInsertBefore(renderer, parentOfHostNative, commentNode, nativeNextSibling(renderer, hostNative), false);
22076
- }
22077
- hostLView[hostTNode.index] = lContainer =
22078
- createLContainer(slotValue, hostLView, commentNode, hostTNode);
22488
+ // An LContainer anchor can not be `null`, but we set it here temporarily
22489
+ // and update to the actual value later in this function (see
22490
+ // `_locateOrCreateAnchorNode`).
22491
+ lContainer = createLContainer(slotValue, hostLView, null, hostTNode);
22492
+ hostLView[hostTNode.index] = lContainer;
22079
22493
  addToViewTree(hostLView, lContainer);
22080
22494
  }
22495
+ _locateOrCreateAnchorNode(lContainer, hostLView, hostTNode, slotValue);
22081
22496
  return new R3ViewContainerRef(lContainer, hostTNode, hostLView);
22082
22497
  }
22498
+ /**
22499
+ * Creates and inserts a comment node that acts as an anchor for a view container.
22500
+ *
22501
+ * If the host is a regular element, we have to insert a comment node manually which will
22502
+ * be used as an anchor when inserting elements. In this specific case we use low-level DOM
22503
+ * manipulation to insert it.
22504
+ */
22505
+ function insertAnchorNode(hostLView, hostTNode) {
22506
+ const renderer = hostLView[RENDERER];
22507
+ ngDevMode && ngDevMode.rendererCreateComment++;
22508
+ const commentNode = renderer.createComment(ngDevMode ? 'container' : '');
22509
+ const hostNative = getNativeByTNode(hostTNode, hostLView);
22510
+ const parentOfHostNative = nativeParentNode(renderer, hostNative);
22511
+ nativeInsertBefore(renderer, parentOfHostNative, commentNode, nativeNextSibling(renderer, hostNative), false);
22512
+ return commentNode;
22513
+ }
22514
+ let _locateOrCreateAnchorNode = createAnchorNode;
22515
+ /**
22516
+ * Regular creation mode: an anchor is created and
22517
+ * assigned to the `lContainer[NATIVE]` slot.
22518
+ */
22519
+ function createAnchorNode(lContainer, hostLView, hostTNode, slotValue) {
22520
+ // We already have a native element (anchor) set, return.
22521
+ if (lContainer[NATIVE])
22522
+ return;
22523
+ let commentNode;
22524
+ // If the host is an element container, the native host element is guaranteed to be a
22525
+ // comment and we can reuse that comment as anchor element for the new LContainer.
22526
+ // The comment node in question is already part of the DOM structure so we don't need to append
22527
+ // it again.
22528
+ if (hostTNode.type & 8 /* TNodeType.ElementContainer */) {
22529
+ commentNode = unwrapRNode(slotValue);
22530
+ }
22531
+ else {
22532
+ commentNode = insertAnchorNode(hostLView, hostTNode);
22533
+ }
22534
+ lContainer[NATIVE] = commentNode;
22535
+ }
22536
+ /**
22537
+ * Hydration logic that looks up:
22538
+ * - an anchor node in the DOM and stores the node in `lContainer[NATIVE]`
22539
+ * - all dehydrated views in this container and puts them into `lContainer[DEHYDRATED_VIEWS]`
22540
+ */
22541
+ function locateOrCreateAnchorNode(lContainer, hostLView, hostTNode, slotValue) {
22542
+ var _a;
22543
+ // We already have a native element (anchor) set and the process
22544
+ // of finding dehydrated views happened (so the `lContainer[DEHYDRATED_VIEWS]`
22545
+ // is not null), exit early.
22546
+ if (lContainer[NATIVE] && lContainer[DEHYDRATED_VIEWS])
22547
+ return;
22548
+ const hydrationInfo = hostLView[HYDRATION];
22549
+ const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock(hostTNode);
22550
+ // Regular creation mode.
22551
+ if (isNodeCreationMode) {
22552
+ return createAnchorNode(lContainer, hostLView, hostTNode, slotValue);
22553
+ }
22554
+ // Hydration mode, looking up an anchor node and dehydrated views in DOM.
22555
+ const index = hostTNode.index - HEADER_OFFSET;
22556
+ const currentRNode = getSegmentHead(hydrationInfo, index);
22557
+ const serializedViews = (_a = hydrationInfo.data[CONTAINERS]) === null || _a === void 0 ? void 0 : _a[index];
22558
+ ngDevMode &&
22559
+ assertDefined(serializedViews, 'Unexpected state: no hydration info available for a given TNode, ' +
22560
+ 'which represents a view container.');
22561
+ const [commentNode, dehydratedViews] = locateDehydratedViewsInContainer(currentRNode, serializedViews);
22562
+ if (ngDevMode) {
22563
+ validateMatchingNode(commentNode, Node.COMMENT_NODE, null, hostLView, hostTNode);
22564
+ // Do not throw in case this node is already claimed (thus `false` as a second
22565
+ // argument). If this container is created based on an `<ng-template>`, the comment
22566
+ // node would be already claimed from the `template` instruction. If an element acts
22567
+ // as an anchor (e.g. <div #vcRef>), a separate comment node would be created/located,
22568
+ // so we need to claim it here.
22569
+ markRNodeAsClaimedByHydration(commentNode, false);
22570
+ }
22571
+ lContainer[NATIVE] = commentNode;
22572
+ lContainer[DEHYDRATED_VIEWS] = dehydratedViews;
22573
+ }
22574
+ function enableLocateOrCreateContainerRefImpl() {
22575
+ _locateOrCreateAnchorNode = locateOrCreateAnchorNode;
22576
+ }
22083
22577
 
22084
22578
  class LQuery_ {
22085
22579
  constructor(queryList) {
@@ -23080,6 +23574,7 @@ function resetCompiledComponents() {
23080
23574
  ownerNgModule = new WeakMap();
23081
23575
  verifiedNgModule = new WeakMap();
23082
23576
  moduleQueue.length = 0;
23577
+ GENERATED_COMP_IDS.clear();
23083
23578
  }
23084
23579
  /**
23085
23580
  * Computes the combined declarations of explicit declarations, as well as declarations inherited by
@@ -24839,6 +25334,63 @@ class NoopNgZone {
24839
25334
  return fn.apply(applyThis, applyArgs);
24840
25335
  }
24841
25336
  }
25337
+ /**
25338
+ * Token used to drive ApplicationRef.isStable
25339
+ *
25340
+ * TODO: This should be moved entirely to NgZone (as a breaking change) so it can be tree-shakeable
25341
+ * for `NoopNgZone` which is always just an `Observable` of `true`. Additionally, we should consider
25342
+ * whether the property on `NgZone` should be `Observable` or `Signal`.
25343
+ */
25344
+ const ZONE_IS_STABLE_OBSERVABLE = new InjectionToken(ngDevMode ? 'isStable Observable' : '', {
25345
+ providedIn: 'root',
25346
+ // TODO(atscott): Replace this with a suitable default like `new
25347
+ // BehaviorSubject(true).asObservable`. Again, long term this won't exist on ApplicationRef at
25348
+ // all but until we can remove it, we need a default value zoneless.
25349
+ factory: isStableFactory,
25350
+ });
25351
+ function isStableFactory() {
25352
+ const zone = inject(NgZone);
25353
+ let _stable = true;
25354
+ const isCurrentlyStable = new Observable((observer) => {
25355
+ _stable = zone.isStable && !zone.hasPendingMacrotasks && !zone.hasPendingMicrotasks;
25356
+ zone.runOutsideAngular(() => {
25357
+ observer.next(_stable);
25358
+ observer.complete();
25359
+ });
25360
+ });
25361
+ const isStable = new Observable((observer) => {
25362
+ // Create the subscription to onStable outside the Angular Zone so that
25363
+ // the callback is run outside the Angular Zone.
25364
+ let stableSub;
25365
+ zone.runOutsideAngular(() => {
25366
+ stableSub = zone.onStable.subscribe(() => {
25367
+ NgZone.assertNotInAngularZone();
25368
+ // Check whether there are no pending macro/micro tasks in the next tick
25369
+ // to allow for NgZone to update the state.
25370
+ scheduleMicroTask(() => {
25371
+ if (!_stable && !zone.hasPendingMacrotasks && !zone.hasPendingMicrotasks) {
25372
+ _stable = true;
25373
+ observer.next(true);
25374
+ }
25375
+ });
25376
+ });
25377
+ });
25378
+ const unstableSub = zone.onUnstable.subscribe(() => {
25379
+ NgZone.assertInAngularZone();
25380
+ if (_stable) {
25381
+ _stable = false;
25382
+ zone.runOutsideAngular(() => {
25383
+ observer.next(false);
25384
+ });
25385
+ }
25386
+ });
25387
+ return () => {
25388
+ stableSub.unsubscribe();
25389
+ unstableSub.unsubscribe();
25390
+ };
25391
+ });
25392
+ return merge$1(isCurrentlyStable, isStable.pipe(share()));
25393
+ }
24842
25394
 
24843
25395
  /**
24844
25396
  * Internal injection token that can used to access an instance of a Testability class.
@@ -25283,13 +25835,13 @@ function internalCreateApplication(config) {
25283
25835
  // Create root application injector based on a set of providers configured at the platform
25284
25836
  // bootstrap level as well as providers passed to the bootstrap call by a user.
25285
25837
  const allAppProviders = [
25286
- { provide: NgZone, useValue: ngZone },
25838
+ provideNgZoneChangeDetection(ngZone),
25287
25839
  ...(appProviders || []),
25288
25840
  ];
25289
25841
  const envInjector = createEnvironmentInjector(allAppProviders, platformInjector, 'Environment Injector');
25290
25842
  const exceptionHandler = envInjector.get(ErrorHandler, null);
25291
25843
  if (NG_DEV_MODE && !exceptionHandler) {
25292
- throw new RuntimeError(402 /* RuntimeErrorCode.ERROR_HANDLER_NOT_FOUND */, 'No `ErrorHandler` found in the Dependency Injection tree.');
25844
+ throw new RuntimeError(402 /* RuntimeErrorCode.MISSING_REQUIRED_INJECTABLE_IN_BOOTSTRAP */, 'No `ErrorHandler` found in the Dependency Injection tree.');
25293
25845
  }
25294
25846
  let onErrorSubscription;
25295
25847
  ngZone.runOutsideAngular(() => {
@@ -25433,17 +25985,15 @@ class PlatformRef {
25433
25985
  // So we create a mini parent injector that just contains the new NgZone and
25434
25986
  // pass that as parent to the NgModuleFactory.
25435
25987
  const ngZone = getNgZone(options === null || options === void 0 ? void 0 : options.ngZone, getNgZoneOptions(options));
25436
- const providers = [{ provide: NgZone, useValue: ngZone }];
25437
25988
  // Note: Create ngZoneInjector within ngZone.run so that all of the instantiated services are
25438
25989
  // created within the Angular zone
25439
25990
  // Do not try to replace ngZone.run with ApplicationRef#run because ApplicationRef would then be
25440
25991
  // created outside of the Angular zone.
25441
25992
  return ngZone.run(() => {
25442
- const ngZoneInjector = Injector.create({ providers: providers, parent: this.injector, name: moduleFactory.moduleType.name });
25443
- const moduleRef = moduleFactory.create(ngZoneInjector);
25993
+ const moduleRef = createNgModuleRefWithProviders(moduleFactory.moduleType, this.injector, provideNgZoneChangeDetection(ngZone));
25444
25994
  const exceptionHandler = moduleRef.injector.get(ErrorHandler, null);
25445
- if (!exceptionHandler) {
25446
- throw new RuntimeError(402 /* RuntimeErrorCode.ERROR_HANDLER_NOT_FOUND */, ngDevMode && 'No ErrorHandler. Is platform module (BrowserModule) included?');
25995
+ if (NG_DEV_MODE && exceptionHandler === null) {
25996
+ throw new RuntimeError(402 /* RuntimeErrorCode.MISSING_REQUIRED_INJECTABLE_IN_BOOTSTRAP */, 'No ErrorHandler. Is platform module (BrowserModule) included?');
25447
25997
  }
25448
25998
  ngZone.runOutsideAngular(() => {
25449
25999
  const subscription = ngZone.onError.subscribe({
@@ -25599,7 +26149,6 @@ function optionsReducer(dst, objs) {
25599
26149
  * A reference to an Angular application running on a page.
25600
26150
  *
25601
26151
  * @usageNotes
25602
- *
25603
26152
  * {@a is-stable-examples}
25604
26153
  * ### isStable examples and caveats
25605
26154
  *
@@ -25689,31 +26238,15 @@ function optionsReducer(dst, objs) {
25689
26238
  * @publicApi
25690
26239
  */
25691
26240
  class ApplicationRef {
25692
- /**
25693
- * Indicates whether this instance was destroyed.
25694
- */
25695
- get destroyed() {
25696
- return this._destroyed;
25697
- }
25698
- /**
25699
- * The `EnvironmentInjector` used to create this application.
25700
- */
25701
- get injector() {
25702
- return this._injector;
25703
- }
25704
- /** @internal */
25705
- constructor(_zone, _injector, _exceptionHandler) {
25706
- this._zone = _zone;
25707
- this._injector = _injector;
25708
- this._exceptionHandler = _exceptionHandler;
26241
+ constructor() {
25709
26242
  /** @internal */
25710
26243
  this._bootstrapListeners = [];
25711
26244
  this._runningTick = false;
25712
- this._stable = true;
25713
26245
  this._destroyed = false;
25714
26246
  this._destroyListeners = [];
25715
26247
  /** @internal */
25716
26248
  this._views = [];
26249
+ this.internalErrorHandler = inject(INTERNAL_APPLICATION_ERROR_HANDLER);
25717
26250
  /**
25718
26251
  * Get a list of component types registered to this application.
25719
26252
  * This list is populated even before the component is created.
@@ -25723,54 +26256,23 @@ class ApplicationRef {
25723
26256
  * Get a list of components registered to this application.
25724
26257
  */
25725
26258
  this.components = [];
25726
- this._onMicrotaskEmptySubscription = this._zone.onMicrotaskEmpty.subscribe({
25727
- next: () => {
25728
- this._zone.run(() => {
25729
- this.tick();
25730
- });
25731
- }
25732
- });
25733
- const isCurrentlyStable = new Observable((observer) => {
25734
- this._stable = this._zone.isStable && !this._zone.hasPendingMacrotasks &&
25735
- !this._zone.hasPendingMicrotasks;
25736
- this._zone.runOutsideAngular(() => {
25737
- observer.next(this._stable);
25738
- observer.complete();
25739
- });
25740
- });
25741
- const isStable = new Observable((observer) => {
25742
- // Create the subscription to onStable outside the Angular Zone so that
25743
- // the callback is run outside the Angular Zone.
25744
- let stableSub;
25745
- this._zone.runOutsideAngular(() => {
25746
- stableSub = this._zone.onStable.subscribe(() => {
25747
- NgZone.assertNotInAngularZone();
25748
- // Check whether there are no pending macro/micro tasks in the next tick
25749
- // to allow for NgZone to update the state.
25750
- scheduleMicroTask(() => {
25751
- if (!this._stable && !this._zone.hasPendingMacrotasks &&
25752
- !this._zone.hasPendingMicrotasks) {
25753
- this._stable = true;
25754
- observer.next(true);
25755
- }
25756
- });
25757
- });
25758
- });
25759
- const unstableSub = this._zone.onUnstable.subscribe(() => {
25760
- NgZone.assertInAngularZone();
25761
- if (this._stable) {
25762
- this._stable = false;
25763
- this._zone.runOutsideAngular(() => {
25764
- observer.next(false);
25765
- });
25766
- }
25767
- });
25768
- return () => {
25769
- stableSub.unsubscribe();
25770
- unstableSub.unsubscribe();
25771
- };
25772
- });
25773
- this.isStable = merge$1(isCurrentlyStable, isStable.pipe(share()));
26259
+ /**
26260
+ * Returns an Observable that indicates when the application is stable or unstable.
26261
+ */
26262
+ this.isStable = inject(ZONE_IS_STABLE_OBSERVABLE);
26263
+ this._injector = inject(EnvironmentInjector);
26264
+ }
26265
+ /**
26266
+ * Indicates whether this instance was destroyed.
26267
+ */
26268
+ get destroyed() {
26269
+ return this._destroyed;
26270
+ }
26271
+ /**
26272
+ * The `EnvironmentInjector` used to create this application.
26273
+ */
26274
+ get injector() {
26275
+ return this._injector;
25774
26276
  }
25775
26277
  /**
25776
26278
  * Bootstrap a component onto the element identified by its selector or, optionally, to a
@@ -25876,7 +26378,7 @@ class ApplicationRef {
25876
26378
  }
25877
26379
  catch (e) {
25878
26380
  // Attention: Don't rethrow as it could cancel subscriptions to Observables!
25879
- this._zone.runOutsideAngular(() => this._exceptionHandler.handleError(e));
26381
+ this.internalErrorHandler(e);
25880
26382
  }
25881
26383
  finally {
25882
26384
  this._runningTick = false;
@@ -25926,7 +26428,6 @@ class ApplicationRef {
25926
26428
  this._destroyListeners.forEach(listener => listener());
25927
26429
  // Destroy all registered views.
25928
26430
  this._views.slice().forEach((view) => view.destroy());
25929
- this._onMicrotaskEmptySubscription.unsubscribe();
25930
26431
  }
25931
26432
  finally {
25932
26433
  // Indicate that this instance is destroyed.
@@ -25979,13 +26480,13 @@ class ApplicationRef {
25979
26480
  }
25980
26481
  }
25981
26482
  }
25982
- ApplicationRef.ɵfac = function ApplicationRef_Factory(t) { return new (t || ApplicationRef)(ɵɵinject(NgZone), ɵɵinject(EnvironmentInjector), ɵɵinject(ErrorHandler)); };
26483
+ ApplicationRef.ɵfac = function ApplicationRef_Factory(t) { return new (t || ApplicationRef)(); };
25983
26484
  ApplicationRef.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: ApplicationRef, factory: ApplicationRef.ɵfac, providedIn: 'root' });
25984
26485
  (function () {
25985
26486
  (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationRef, [{
25986
26487
  type: Injectable,
25987
26488
  args: [{ providedIn: 'root' }]
25988
- }], function () { return [{ type: NgZone }, { type: EnvironmentInjector }, { type: ErrorHandler }]; }, null);
26489
+ }], null, null);
25989
26490
  })();
25990
26491
  function remove(list, el) {
25991
26492
  const index = list.indexOf(el);
@@ -26001,6 +26502,72 @@ function _lastDefined(args) {
26001
26502
  }
26002
26503
  return undefined;
26003
26504
  }
26505
+ /**
26506
+ * `InjectionToken` used to configure how to call the `ErrorHandler`.
26507
+ *
26508
+ * `NgZone` is provided by default today so the default (and only) implementation for this
26509
+ * is calling `ErrorHandler.handleError` outside of the Angular zone.
26510
+ */
26511
+ const INTERNAL_APPLICATION_ERROR_HANDLER = new InjectionToken(NG_DEV_MODE ? 'internal error handler' : '', {
26512
+ providedIn: 'root',
26513
+ factory: () => {
26514
+ const userErrorHandler = inject(ErrorHandler);
26515
+ return userErrorHandler.handleError.bind(undefined);
26516
+ }
26517
+ });
26518
+ function ngZoneApplicationErrorHandlerFactory() {
26519
+ const zone = inject(NgZone);
26520
+ const userErrorHandler = inject(ErrorHandler);
26521
+ return (e) => zone.runOutsideAngular(() => userErrorHandler.handleError(e));
26522
+ }
26523
+ class NgZoneChangeDetectionScheduler {
26524
+ constructor() {
26525
+ this.zone = inject(NgZone);
26526
+ this.applicationRef = inject(ApplicationRef);
26527
+ }
26528
+ initialize() {
26529
+ if (this._onMicrotaskEmptySubscription) {
26530
+ return;
26531
+ }
26532
+ this._onMicrotaskEmptySubscription = this.zone.onMicrotaskEmpty.subscribe({
26533
+ next: () => {
26534
+ this.zone.run(() => {
26535
+ this.applicationRef.tick();
26536
+ });
26537
+ }
26538
+ });
26539
+ }
26540
+ ngOnDestroy() {
26541
+ var _a;
26542
+ (_a = this._onMicrotaskEmptySubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
26543
+ }
26544
+ }
26545
+ NgZoneChangeDetectionScheduler.ɵfac = function NgZoneChangeDetectionScheduler_Factory(t) { return new (t || NgZoneChangeDetectionScheduler)(); };
26546
+ NgZoneChangeDetectionScheduler.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: NgZoneChangeDetectionScheduler, factory: NgZoneChangeDetectionScheduler.ɵfac, providedIn: 'root' });
26547
+ (function () {
26548
+ (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(NgZoneChangeDetectionScheduler, [{
26549
+ type: Injectable,
26550
+ args: [{ providedIn: 'root' }]
26551
+ }], null, null);
26552
+ })();
26553
+ function provideNgZoneChangeDetection(ngZone) {
26554
+ return [
26555
+ { provide: NgZone, useValue: ngZone },
26556
+ {
26557
+ provide: ENVIRONMENT_INITIALIZER,
26558
+ multi: true,
26559
+ useFactory: () => {
26560
+ const ngZoneChangeDetectionScheduler = inject(NgZoneChangeDetectionScheduler, { optional: true });
26561
+ if (NG_DEV_MODE && ngZoneChangeDetectionScheduler === null) {
26562
+ throw new RuntimeError(402 /* RuntimeErrorCode.MISSING_REQUIRED_INJECTABLE_IN_BOOTSTRAP */, 'No NgZoneChangeDetectionScheduler found in the Dependency Injection tree.');
26563
+ }
26564
+ return () => ngZoneChangeDetectionScheduler.initialize();
26565
+ },
26566
+ },
26567
+ { provide: INTERNAL_APPLICATION_ERROR_HANDLER, useFactory: ngZoneApplicationErrorHandlerFactory },
26568
+ { provide: ZONE_IS_STABLE_OBSERVABLE, useFactory: isStableFactory },
26569
+ ];
26570
+ }
26004
26571
 
26005
26572
  /**
26006
26573
  * Returns whether Angular is in development mode.
@@ -27921,6 +28488,25 @@ class SerializedViewCollection {
27921
28488
  return this.views;
27922
28489
  }
27923
28490
  }
28491
+ /**
28492
+ * Global counter that is used to generate a unique id for TViews
28493
+ * during the serialization process.
28494
+ */
28495
+ let tViewSsrId = 0;
28496
+ /**
28497
+ * Generates a unique id for a given TView and returns this id.
28498
+ * The id is also stored on this instance of a TView and reused in
28499
+ * subsequent calls.
28500
+ *
28501
+ * This id is needed to uniquely identify and pick up dehydrated views
28502
+ * at runtime.
28503
+ */
28504
+ function getSsrId(tView) {
28505
+ if (!tView.ssrId) {
28506
+ tView.ssrId = `t${tViewSsrId++}`;
28507
+ }
28508
+ return tView.ssrId;
28509
+ }
27924
28510
  /**
27925
28511
  * Computes the number of root nodes in a given view
27926
28512
  * (or child nodes in a given container if a tNode is provided).
@@ -27939,6 +28525,7 @@ function calcNumRootNodes(tView, lView, tNode) {
27939
28525
  */
27940
28526
  function annotateForHydration(appRef, doc) {
27941
28527
  const serializedViewCollection = new SerializedViewCollection();
28528
+ const corruptedTextNodes = new Map();
27942
28529
  const viewRefs = appRef._views;
27943
28530
  for (const viewRef of viewRefs) {
27944
28531
  const lView = getComponentLViewForHydration(viewRef);
@@ -27949,8 +28536,10 @@ function annotateForHydration(appRef, doc) {
27949
28536
  if (hostElement) {
27950
28537
  const context = {
27951
28538
  serializedViewCollection,
28539
+ corruptedTextNodes,
27952
28540
  };
27953
28541
  annotateHostElementForHydration(hostElement, lView, context);
28542
+ insertCorruptedTextNodeMarkers(corruptedTextNodes, doc);
27954
28543
  }
27955
28544
  }
27956
28545
  }
@@ -27960,6 +28549,41 @@ function annotateForHydration(appRef, doc) {
27960
28549
  transferState.set(NGH_DATA_KEY, allSerializedViews);
27961
28550
  }
27962
28551
  }
28552
+ /**
28553
+ * Serializes the lContainer data into a list of SerializedView objects,
28554
+ * that represent views within this lContainer.
28555
+ *
28556
+ * @param lContainer the lContainer we are serializing
28557
+ * @param context the hydration context
28558
+ * @returns an array of the `SerializedView` objects
28559
+ */
28560
+ function serializeLContainer(lContainer, context) {
28561
+ const views = [];
28562
+ for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
28563
+ let childLView = lContainer[i];
28564
+ // If this is a root view, get an LView for the underlying component,
28565
+ // because it contains information about the view to serialize.
28566
+ if (isRootView(childLView)) {
28567
+ childLView = childLView[HEADER_OFFSET];
28568
+ }
28569
+ const childTView = childLView[TVIEW];
28570
+ let template;
28571
+ let numRootNodes = 0;
28572
+ if (childTView.type === 1 /* TViewType.Component */) {
28573
+ template = childTView.ssrId;
28574
+ // This is a component view, thus it has only 1 root node: the component
28575
+ // host node itself (other nodes would be inside that host node).
28576
+ numRootNodes = 1;
28577
+ }
28578
+ else {
28579
+ template = getSsrId(childTView);
28580
+ numRootNodes = calcNumRootNodes(childTView, childLView, childTView.firstChild);
28581
+ }
28582
+ const view = Object.assign({ [TEMPLATE_ID]: template, [NUM_ROOT_NODES]: numRootNodes }, serializeLView(lContainer[i], context));
28583
+ views.push(view);
28584
+ }
28585
+ return views;
28586
+ }
27963
28587
  /**
27964
28588
  * Serializes the lView data into a SerializedView object that will later be added
27965
28589
  * to the TransferState storage and referenced using the `ngh` attribute on a host
@@ -27970,7 +28594,7 @@ function annotateForHydration(appRef, doc) {
27970
28594
  * @returns the `SerializedView` object containing the data to be added to the host node
27971
28595
  */
27972
28596
  function serializeLView(lView, context) {
27973
- var _a;
28597
+ var _a, _b, _c, _d, _e;
27974
28598
  const ngh = {};
27975
28599
  const tView = lView[TVIEW];
27976
28600
  // Iterate over DOM element references in an LView.
@@ -27985,8 +28609,26 @@ function serializeLView(lView, context) {
27985
28609
  continue;
27986
28610
  }
27987
28611
  if (isLContainer(lView[i])) {
27988
- // TODO: serialization of LContainers will be added
27989
- // in followup PRs.
28612
+ // Serialize information about a template.
28613
+ const embeddedTView = tNode.tView;
28614
+ if (embeddedTView !== null) {
28615
+ (_a = ngh[TEMPLATES]) !== null && _a !== void 0 ? _a : (ngh[TEMPLATES] = {});
28616
+ ngh[TEMPLATES][noOffsetIndex] = getSsrId(embeddedTView);
28617
+ }
28618
+ // Serialize views within this LContainer.
28619
+ const hostNode = lView[i][HOST]; // host node of this container
28620
+ // LView[i][HOST] can be of 2 different types:
28621
+ // - either a DOM node
28622
+ // - or an array that represents an LView of a component
28623
+ if (Array.isArray(hostNode)) {
28624
+ // This is a component, serialize info about it.
28625
+ const targetNode = unwrapRNode(hostNode);
28626
+ if (!targetNode.hasAttribute(SKIP_HYDRATION_ATTR_NAME)) {
28627
+ annotateHostElementForHydration(targetNode, hostNode, context);
28628
+ }
28629
+ }
28630
+ (_b = ngh[CONTAINERS]) !== null && _b !== void 0 ? _b : (ngh[CONTAINERS] = {});
28631
+ ngh[CONTAINERS][noOffsetIndex] = serializeLContainer(lView[i], context);
27990
28632
  }
27991
28633
  else if (Array.isArray(lView[i])) {
27992
28634
  // This is a component, annotate the host node with an `ngh` attribute.
@@ -28001,9 +28643,46 @@ function serializeLView(lView, context) {
28001
28643
  // An <ng-container> is represented by the number of
28002
28644
  // top-level nodes. This information is needed to skip over
28003
28645
  // those nodes to reach a corresponding anchor node (comment node).
28004
- (_a = ngh[ELEMENT_CONTAINERS]) !== null && _a !== void 0 ? _a : (ngh[ELEMENT_CONTAINERS] = {});
28646
+ (_c = ngh[ELEMENT_CONTAINERS]) !== null && _c !== void 0 ? _c : (ngh[ELEMENT_CONTAINERS] = {});
28005
28647
  ngh[ELEMENT_CONTAINERS][noOffsetIndex] = calcNumRootNodes(tView, lView, tNode.child);
28006
28648
  }
28649
+ else {
28650
+ // Handle cases where text nodes can be lost after DOM serialization:
28651
+ // 1. When there is an *empty text node* in DOM: in this case, this
28652
+ // node would not make it into the serialized string and as a result,
28653
+ // this node wouldn't be created in a browser. This would result in
28654
+ // a mismatch during the hydration, where the runtime logic would expect
28655
+ // a text node to be present in live DOM, but no text node would exist.
28656
+ // Example: `<span>{{ name }}</span>` when the `name` is an empty string.
28657
+ // This would result in `<span></span>` string after serialization and
28658
+ // in a browser only the `span` element would be created. To resolve that,
28659
+ // an extra comment node is appended in place of an empty text node and
28660
+ // that special comment node is replaced with an empty text node *before*
28661
+ // hydration.
28662
+ // 2. When there are 2 consecutive text nodes present in the DOM.
28663
+ // Example: `<div>Hello <ng-container *ngIf="true">world</ng-container></div>`.
28664
+ // In this scenario, the live DOM would look like this:
28665
+ // <div>#text('Hello ') #text('world') #comment('container')</div>
28666
+ // Serialized string would look like this: `<div>Hello world<!--container--></div>`.
28667
+ // The live DOM in a browser after that would be:
28668
+ // <div>#text('Hello world') #comment('container')</div>
28669
+ // Notice how 2 text nodes are now "merged" into one. This would cause hydration
28670
+ // logic to fail, since it'd expect 2 text nodes being present, not one.
28671
+ // To fix this, we insert a special comment node in between those text nodes, so
28672
+ // serialized representation is: `<div>Hello <!--ngtns-->world<!--container--></div>`.
28673
+ // This forces browser to create 2 text nodes separated by a comment node.
28674
+ // Before running a hydration process, this special comment node is removed, so the
28675
+ // live DOM has exactly the same state as it was before serialization.
28676
+ if (tNode.type & 1 /* TNodeType.Text */) {
28677
+ const rNode = unwrapRNode(lView[i]);
28678
+ if (((_d = rNode.textContent) === null || _d === void 0 ? void 0 : _d.replace(/\s/gm, '')) === '') {
28679
+ context.corruptedTextNodes.set(rNode, "ngetn" /* TextNodeMarker.EmptyNode */);
28680
+ }
28681
+ else if (((_e = rNode.nextSibling) === null || _e === void 0 ? void 0 : _e.nodeType) === Node.TEXT_NODE) {
28682
+ context.corruptedTextNodes.set(rNode, "ngtns" /* TextNodeMarker.Separator */);
28683
+ }
28684
+ }
28685
+ }
28007
28686
  }
28008
28687
  }
28009
28688
  return ngh;
@@ -28021,6 +28700,20 @@ function annotateHostElementForHydration(element, lView, context) {
28021
28700
  const renderer = lView[RENDERER];
28022
28701
  renderer.setAttribute(element, NGH_ATTR_NAME, index.toString());
28023
28702
  }
28703
+ /**
28704
+ * Physically inserts the comment nodes to ensure empty text nodes and adjacent
28705
+ * text node separators are preserved after server serialization of the DOM.
28706
+ * These get swapped back for empty text nodes or separators once hydration happens
28707
+ * on the client.
28708
+ *
28709
+ * @param corruptedTextNodes The Map of text nodes to be replaced with comments
28710
+ * @param doc The document
28711
+ */
28712
+ function insertCorruptedTextNodeMarkers(corruptedTextNodes, doc) {
28713
+ for (const [textNode, marker] of corruptedTextNodes) {
28714
+ textNode.after(doc.createComment(marker));
28715
+ }
28716
+ }
28024
28717
 
28025
28718
  /**
28026
28719
  * Indicates whether the hydration-related code was added,
@@ -28045,6 +28738,10 @@ function enableHydrationRuntimeSupport() {
28045
28738
  enableLocateOrCreateElementNodeImpl();
28046
28739
  enableLocateOrCreateTextNodeImpl();
28047
28740
  enableLocateOrCreateElementContainerNodeImpl();
28741
+ enableLocateOrCreateContainerAnchorImpl();
28742
+ enableLocateOrCreateContainerRefImpl();
28743
+ enableFindMatchingDehydratedViewImpl();
28744
+ enableApplyRootElementTransformImpl();
28048
28745
  }
28049
28746
  }
28050
28747
  /**
@@ -28884,5 +29581,5 @@ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
28884
29581
  * Generated bundle index. Do not edit.
28885
29582
  */
28886
29583
 
28887
- export { ANALYZE_FOR_ENTRY_COMPONENTS, ANIMATION_MODULE_TYPE, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, ApplicationInitStatus, ApplicationModule, ApplicationRef, Attribute, COMPILER_OPTIONS, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Compiler, CompilerFactory, Component, ComponentFactory$1 as ComponentFactory, ComponentFactoryResolver$1 as ComponentFactoryResolver, ComponentRef$1 as ComponentRef, ContentChild, ContentChildren, DEFAULT_CURRENCY_CODE, DebugElement, DebugEventListener, DebugNode, DefaultIterableDiffer, DestroyRef, Directive, ENVIRONMENT_INITIALIZER, ElementRef, EmbeddedViewRef, EnvironmentInjector, ErrorHandler, EventEmitter, Host, HostBinding, HostListener, INJECTOR, Inject, InjectFlags, Injectable, InjectionToken, Injector, Input, IterableDiffers, KeyValueDiffers, LOCALE_ID, MissingTranslationStrategy, ModuleWithComponentFactories, NO_ERRORS_SCHEMA, NgModule, NgModuleFactory$1 as NgModuleFactory, NgModuleRef$1 as NgModuleRef, NgProbeToken, NgZone, Optional, Output, PACKAGE_ROOT_URL, PLATFORM_ID, PLATFORM_INITIALIZER, Pipe, PlatformRef, Query, QueryList, ReflectiveInjector, ReflectiveKey, Renderer2, RendererFactory2, RendererStyleFlags2, ResolvedReflectiveFactory, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, Type, VERSION, Version, ViewChild, ViewChildren, ViewContainerRef, ViewEncapsulation$1 as ViewEncapsulation, ViewRef, asNativeElements, assertPlatform, computed, createComponent, createEnvironmentInjector, createNgModule, createNgModuleRef, createPlatform, createPlatformFactory, defineInjectable, destroyPlatform, effect, enableProdMode, forwardRef, getDebugNode, getModuleFactory, getNgModuleById, getPlatform, importProvidersFrom, inject, isDevMode, isSignal, isStandalone, makeEnvironmentProviders, mergeApplicationConfig, platformCore, reflectComponentType, resolveForwardRef, setTestabilityGetter, signal, untracked, ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS, APP_ID_RANDOM_PROVIDER as ɵAPP_ID_RANDOM_PROVIDER, ComponentFactory$1 as ɵComponentFactory, Console as ɵConsole, DEFAULT_LOCALE_ID as ɵDEFAULT_LOCALE_ID, INJECTOR_SCOPE as ɵINJECTOR_SCOPE, IS_HYDRATION_FEATURE_ENABLED as ɵIS_HYDRATION_FEATURE_ENABLED, LContext as ɵLContext, LifecycleHooksFeature as ɵLifecycleHooksFeature, LocaleDataIndex as ɵLocaleDataIndex, NG_COMP_DEF as ɵNG_COMP_DEF, NG_DIR_DEF as ɵNG_DIR_DEF, NG_ELEMENT_ID as ɵNG_ELEMENT_ID, NG_INJ_DEF as ɵNG_INJ_DEF, NG_MOD_DEF as ɵNG_MOD_DEF, NG_PIPE_DEF as ɵNG_PIPE_DEF, NG_PROV_DEF as ɵNG_PROV_DEF, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, NO_CHANGE as ɵNO_CHANGE, NgModuleFactory as ɵNgModuleFactory, NoopNgZone as ɵNoopNgZone, ReflectionCapabilities as ɵReflectionCapabilities, ComponentFactory as ɵRender3ComponentFactory, ComponentRef as ɵRender3ComponentRef, NgModuleRef as ɵRender3NgModuleRef, RuntimeError as ɵRuntimeError, TESTABILITY as ɵTESTABILITY, TESTABILITY_GETTER as ɵTESTABILITY_GETTER, TransferState as ɵTransferState, ViewRef$1 as ɵViewRef, XSS_SECURITY_URL as ɵXSS_SECURITY_URL, _sanitizeHtml as ɵ_sanitizeHtml, _sanitizeUrl as ɵ_sanitizeUrl, allowSanitizationBypassAndThrow as ɵallowSanitizationBypassAndThrow, annotateForHydration as ɵannotateForHydration, bypassSanitizationTrustHtml as ɵbypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl as ɵbypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript as ɵbypassSanitizationTrustScript, bypassSanitizationTrustStyle as ɵbypassSanitizationTrustStyle, bypassSanitizationTrustUrl as ɵbypassSanitizationTrustUrl, clearResolutionOfComponentResourcesQueue as ɵclearResolutionOfComponentResourcesQueue, coerceToBoolean as ɵcoerceToBoolean, compileComponent as ɵcompileComponent, compileDirective as ɵcompileDirective, compileNgModule as ɵcompileNgModule, compileNgModuleDefs as ɵcompileNgModuleDefs, compileNgModuleFactory as ɵcompileNgModuleFactory, compilePipe as ɵcompilePipe, convertToBitFlags as ɵconvertToBitFlags, createInjector as ɵcreateInjector, defaultIterableDiffers as ɵdefaultIterableDiffers, defaultKeyValueDiffers as ɵdefaultKeyValueDiffers, detectChanges as ɵdetectChanges, devModeEqual as ɵdevModeEqual, escapeTransferStateContent as ɵescapeTransferStateContent, findLocaleData as ɵfindLocaleData, flushModuleScopingQueueAsMuchAsPossible as ɵflushModuleScopingQueueAsMuchAsPossible, formatRuntimeError as ɵformatRuntimeError, getComponentDef as ɵgetComponentDef, getDebugNode as ɵgetDebugNode, getDirectives as ɵgetDirectives, getHostElement as ɵgetHostElement, getInjectableDef as ɵgetInjectableDef, getLContext as ɵgetLContext, getLocaleCurrencyCode as ɵgetLocaleCurrencyCode, getLocalePluralCase as ɵgetLocalePluralCase, getSanitizationBypassType as ɵgetSanitizationBypassType, ɵgetUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode, _global as ɵglobal, injectChangeDetectorRef as ɵinjectChangeDetectorRef, internalCreateApplication as ɵinternalCreateApplication, isBoundToModule as ɵisBoundToModule, isEnvironmentProviders as ɵisEnvironmentProviders, isInjectable as ɵisInjectable, isNgModule as ɵisNgModule, isPromise as ɵisPromise, isSubscribable as ɵisSubscribable, makeDecorator as ɵmakeDecorator, makeStateKey as ɵmakeStateKey, noSideEffects as ɵnoSideEffects, patchComponentDefWithScope as ɵpatchComponentDefWithScope, provideHydrationSupport as ɵprovideHydrationSupport, publishDefaultGlobalUtils$1 as ɵpublishDefaultGlobalUtils, publishGlobalUtil as ɵpublishGlobalUtil, registerLocaleData as ɵregisterLocaleData, resetCompiledComponents as ɵresetCompiledComponents, resetJitOptions as ɵresetJitOptions, resolveComponentResources as ɵresolveComponentResources, setAllowDuplicateNgModuleIdsForTest as ɵsetAllowDuplicateNgModuleIdsForTest, setClassMetadata as ɵsetClassMetadata, setCurrentInjector as ɵsetCurrentInjector, setDocument as ɵsetDocument, setLocaleId as ɵsetLocaleId, ɵsetUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode, store as ɵstore, stringify as ɵstringify, transitiveScopesFor as ɵtransitiveScopesFor, unescapeTransferStateContent as ɵunescapeTransferStateContent, unregisterAllLocaleData as ɵunregisterLocaleData, unwrapSafeValue as ɵunwrapSafeValue, ɵɵCopyDefinitionFeature, FactoryTarget as ɵɵFactoryTarget, ɵɵHostDirectivesFeature, ɵɵInheritDefinitionFeature, ɵɵNgOnChangesFeature, ɵɵProvidersFeature, ɵɵStandaloneFeature, ɵɵadvance, ɵɵattribute, ɵɵattributeInterpolate1, ɵɵattributeInterpolate2, ɵɵattributeInterpolate3, ɵɵattributeInterpolate4, ɵɵattributeInterpolate5, ɵɵattributeInterpolate6, ɵɵattributeInterpolate7, ɵɵattributeInterpolate8, ɵɵattributeInterpolateV, ɵɵclassMap, ɵɵclassMapInterpolate1, ɵɵclassMapInterpolate2, ɵɵclassMapInterpolate3, ɵɵclassMapInterpolate4, ɵɵclassMapInterpolate5, ɵɵclassMapInterpolate6, ɵɵclassMapInterpolate7, ɵɵclassMapInterpolate8, ɵɵclassMapInterpolateV, ɵɵclassProp, ɵɵcontentQuery, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵdefineNgModule, ɵɵdefinePipe, ɵɵdirectiveInject, ɵɵdisableBindings, ɵɵelement, ɵɵelementContainer, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementStart, ɵɵenableBindings, ɵɵgetCurrentView, ɵɵgetInheritedFactory, ɵɵhostProperty, ɵɵi18n, ɵɵi18nApply, ɵɵi18nAttributes, ɵɵi18nEnd, ɵɵi18nExp, ɵɵi18nPostprocess, ɵɵi18nStart, ɵɵinject, ɵɵinjectAttribute, ɵɵinvalidFactory, ɵɵinvalidFactoryDep, ɵɵlistener, ɵɵloadQuery, ɵɵnamespaceHTML, ɵɵnamespaceMathML, ɵɵnamespaceSVG, ɵɵnextContext, ɵɵngDeclareClassMetadata, ɵɵngDeclareComponent, ɵɵngDeclareDirective, ɵɵngDeclareFactory, ɵɵngDeclareInjectable, ɵɵngDeclareInjector, ɵɵngDeclareNgModule, ɵɵngDeclarePipe, ɵɵpipe, ɵɵpipeBind1, ɵɵpipeBind2, ɵɵpipeBind3, ɵɵpipeBind4, ɵɵpipeBindV, ɵɵprojection, ɵɵprojectionDef, ɵɵproperty, ɵɵpropertyInterpolate, ɵɵpropertyInterpolate1, ɵɵpropertyInterpolate2, ɵɵpropertyInterpolate3, ɵɵpropertyInterpolate4, ɵɵpropertyInterpolate5, ɵɵpropertyInterpolate6, ɵɵpropertyInterpolate7, ɵɵpropertyInterpolate8, ɵɵpropertyInterpolateV, ɵɵpureFunction0, ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunction5, ɵɵpureFunction6, ɵɵpureFunction7, ɵɵpureFunction8, ɵɵpureFunctionV, ɵɵqueryRefresh, ɵɵreference, registerNgModuleType as ɵɵregisterNgModuleType, ɵɵresetView, ɵɵresolveBody, ɵɵresolveDocument, ɵɵresolveWindow, ɵɵrestoreView, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl, ɵɵsetComponentScope, ɵɵsetNgModuleScope, ɵɵstyleMap, ɵɵstyleMapInterpolate1, ɵɵstyleMapInterpolate2, ɵɵstyleMapInterpolate3, ɵɵstyleMapInterpolate4, ɵɵstyleMapInterpolate5, ɵɵstyleMapInterpolate6, ɵɵstyleMapInterpolate7, ɵɵstyleMapInterpolate8, ɵɵstyleMapInterpolateV, ɵɵstyleProp, ɵɵstylePropInterpolate1, ɵɵstylePropInterpolate2, ɵɵstylePropInterpolate3, ɵɵstylePropInterpolate4, ɵɵstylePropInterpolate5, ɵɵstylePropInterpolate6, ɵɵstylePropInterpolate7, ɵɵstylePropInterpolate8, ɵɵstylePropInterpolateV, ɵɵsyntheticHostListener, ɵɵsyntheticHostProperty, ɵɵtemplate, ɵɵtemplateRefExtractor, ɵɵtext, ɵɵtextInterpolate, ɵɵtextInterpolate1, ɵɵtextInterpolate2, ɵɵtextInterpolate3, ɵɵtextInterpolate4, ɵɵtextInterpolate5, ɵɵtextInterpolate6, ɵɵtextInterpolate7, ɵɵtextInterpolate8, ɵɵtextInterpolateV, ɵɵtrustConstantHtml, ɵɵtrustConstantResourceUrl, ɵɵvalidateIframeAttribute, ɵɵviewQuery };
29584
+ export { ANALYZE_FOR_ENTRY_COMPONENTS, ANIMATION_MODULE_TYPE, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, ApplicationInitStatus, ApplicationModule, ApplicationRef, Attribute, COMPILER_OPTIONS, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Compiler, CompilerFactory, Component, ComponentFactory$1 as ComponentFactory, ComponentFactoryResolver$1 as ComponentFactoryResolver, ComponentRef$1 as ComponentRef, ContentChild, ContentChildren, DEFAULT_CURRENCY_CODE, DebugElement, DebugEventListener, DebugNode, DefaultIterableDiffer, DestroyRef, Directive, ENVIRONMENT_INITIALIZER, ElementRef, EmbeddedViewRef, EnvironmentInjector, ErrorHandler, EventEmitter, Host, HostBinding, HostListener, INJECTOR, Inject, InjectFlags, Injectable, InjectionToken, Injector, Input, IterableDiffers, KeyValueDiffers, LOCALE_ID, MissingTranslationStrategy, ModuleWithComponentFactories, NO_ERRORS_SCHEMA, NgModule, NgModuleFactory$1 as NgModuleFactory, NgModuleRef$1 as NgModuleRef, NgProbeToken, NgZone, Optional, Output, PACKAGE_ROOT_URL, PLATFORM_ID, PLATFORM_INITIALIZER, Pipe, PlatformRef, Query, QueryList, ReflectiveInjector, ReflectiveKey, Renderer2, RendererFactory2, RendererStyleFlags2, ResolvedReflectiveFactory, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, Type, VERSION, Version, ViewChild, ViewChildren, ViewContainerRef, ViewEncapsulation$1 as ViewEncapsulation, ViewRef, asNativeElements, assertPlatform, computed, createComponent, createEnvironmentInjector, createNgModule, createNgModuleRef, createPlatform, createPlatformFactory, defineInjectable, destroyPlatform, effect, enableProdMode, forwardRef, getDebugNode, getModuleFactory, getNgModuleById, getPlatform, importProvidersFrom, inject, isDevMode, isSignal, isStandalone, makeEnvironmentProviders, mergeApplicationConfig, platformCore, reflectComponentType, resolveForwardRef, runInInjectionContext, setTestabilityGetter, signal, untracked, ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS, ComponentFactory$1 as ɵComponentFactory, Console as ɵConsole, DEFAULT_LOCALE_ID as ɵDEFAULT_LOCALE_ID, INJECTOR_SCOPE as ɵINJECTOR_SCOPE, IS_HYDRATION_FEATURE_ENABLED as ɵIS_HYDRATION_FEATURE_ENABLED, LContext as ɵLContext, LifecycleHooksFeature as ɵLifecycleHooksFeature, LocaleDataIndex as ɵLocaleDataIndex, NG_COMP_DEF as ɵNG_COMP_DEF, NG_DIR_DEF as ɵNG_DIR_DEF, NG_ELEMENT_ID as ɵNG_ELEMENT_ID, NG_INJ_DEF as ɵNG_INJ_DEF, NG_MOD_DEF as ɵNG_MOD_DEF, NG_PIPE_DEF as ɵNG_PIPE_DEF, NG_PROV_DEF as ɵNG_PROV_DEF, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, NO_CHANGE as ɵNO_CHANGE, NgModuleFactory as ɵNgModuleFactory, NoopNgZone as ɵNoopNgZone, ReflectionCapabilities as ɵReflectionCapabilities, ComponentFactory as ɵRender3ComponentFactory, ComponentRef as ɵRender3ComponentRef, NgModuleRef as ɵRender3NgModuleRef, RuntimeError as ɵRuntimeError, TESTABILITY as ɵTESTABILITY, TESTABILITY_GETTER as ɵTESTABILITY_GETTER, TransferState as ɵTransferState, ViewRef$1 as ɵViewRef, XSS_SECURITY_URL as ɵXSS_SECURITY_URL, _sanitizeHtml as ɵ_sanitizeHtml, _sanitizeUrl as ɵ_sanitizeUrl, allowSanitizationBypassAndThrow as ɵallowSanitizationBypassAndThrow, annotateForHydration as ɵannotateForHydration, bypassSanitizationTrustHtml as ɵbypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl as ɵbypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript as ɵbypassSanitizationTrustScript, bypassSanitizationTrustStyle as ɵbypassSanitizationTrustStyle, bypassSanitizationTrustUrl as ɵbypassSanitizationTrustUrl, clearResolutionOfComponentResourcesQueue as ɵclearResolutionOfComponentResourcesQueue, coerceToBoolean as ɵcoerceToBoolean, compileComponent as ɵcompileComponent, compileDirective as ɵcompileDirective, compileNgModule as ɵcompileNgModule, compileNgModuleDefs as ɵcompileNgModuleDefs, compileNgModuleFactory as ɵcompileNgModuleFactory, compilePipe as ɵcompilePipe, convertToBitFlags as ɵconvertToBitFlags, createInjector as ɵcreateInjector, defaultIterableDiffers as ɵdefaultIterableDiffers, defaultKeyValueDiffers as ɵdefaultKeyValueDiffers, detectChanges as ɵdetectChanges, devModeEqual as ɵdevModeEqual, escapeTransferStateContent as ɵescapeTransferStateContent, findLocaleData as ɵfindLocaleData, flushModuleScopingQueueAsMuchAsPossible as ɵflushModuleScopingQueueAsMuchAsPossible, formatRuntimeError as ɵformatRuntimeError, getComponentDef as ɵgetComponentDef, getDebugNode as ɵgetDebugNode, getDirectives as ɵgetDirectives, getHostElement as ɵgetHostElement, getInjectableDef as ɵgetInjectableDef, getLContext as ɵgetLContext, getLocaleCurrencyCode as ɵgetLocaleCurrencyCode, getLocalePluralCase as ɵgetLocalePluralCase, getSanitizationBypassType as ɵgetSanitizationBypassType, ɵgetUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode, _global as ɵglobal, injectChangeDetectorRef as ɵinjectChangeDetectorRef, internalCreateApplication as ɵinternalCreateApplication, isBoundToModule as ɵisBoundToModule, isEnvironmentProviders as ɵisEnvironmentProviders, isInjectable as ɵisInjectable, isNgModule as ɵisNgModule, isPromise as ɵisPromise, isSubscribable as ɵisSubscribable, makeDecorator as ɵmakeDecorator, makeStateKey as ɵmakeStateKey, noSideEffects as ɵnoSideEffects, patchComponentDefWithScope as ɵpatchComponentDefWithScope, provideHydrationSupport as ɵprovideHydrationSupport, provideNgZoneChangeDetection as ɵprovideNgZoneChangeDetection, publishDefaultGlobalUtils$1 as ɵpublishDefaultGlobalUtils, publishGlobalUtil as ɵpublishGlobalUtil, registerLocaleData as ɵregisterLocaleData, resetCompiledComponents as ɵresetCompiledComponents, resetJitOptions as ɵresetJitOptions, resolveComponentResources as ɵresolveComponentResources, setAllowDuplicateNgModuleIdsForTest as ɵsetAllowDuplicateNgModuleIdsForTest, setClassMetadata as ɵsetClassMetadata, setCurrentInjector as ɵsetCurrentInjector, setDocument as ɵsetDocument, setLocaleId as ɵsetLocaleId, ɵsetUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode, store as ɵstore, stringify as ɵstringify, transitiveScopesFor as ɵtransitiveScopesFor, unescapeTransferStateContent as ɵunescapeTransferStateContent, unregisterAllLocaleData as ɵunregisterLocaleData, unwrapSafeValue as ɵunwrapSafeValue, ɵɵCopyDefinitionFeature, FactoryTarget as ɵɵFactoryTarget, ɵɵHostDirectivesFeature, ɵɵInheritDefinitionFeature, ɵɵNgOnChangesFeature, ɵɵProvidersFeature, ɵɵStandaloneFeature, ɵɵadvance, ɵɵattribute, ɵɵattributeInterpolate1, ɵɵattributeInterpolate2, ɵɵattributeInterpolate3, ɵɵattributeInterpolate4, ɵɵattributeInterpolate5, ɵɵattributeInterpolate6, ɵɵattributeInterpolate7, ɵɵattributeInterpolate8, ɵɵattributeInterpolateV, ɵɵclassMap, ɵɵclassMapInterpolate1, ɵɵclassMapInterpolate2, ɵɵclassMapInterpolate3, ɵɵclassMapInterpolate4, ɵɵclassMapInterpolate5, ɵɵclassMapInterpolate6, ɵɵclassMapInterpolate7, ɵɵclassMapInterpolate8, ɵɵclassMapInterpolateV, ɵɵclassProp, ɵɵcontentQuery, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵdefineNgModule, ɵɵdefinePipe, ɵɵdirectiveInject, ɵɵdisableBindings, ɵɵelement, ɵɵelementContainer, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementStart, ɵɵenableBindings, ɵɵgetCurrentView, ɵɵgetInheritedFactory, ɵɵhostProperty, ɵɵi18n, ɵɵi18nApply, ɵɵi18nAttributes, ɵɵi18nEnd, ɵɵi18nExp, ɵɵi18nPostprocess, ɵɵi18nStart, ɵɵinject, ɵɵinjectAttribute, ɵɵinvalidFactory, ɵɵinvalidFactoryDep, ɵɵlistener, ɵɵloadQuery, ɵɵnamespaceHTML, ɵɵnamespaceMathML, ɵɵnamespaceSVG, ɵɵnextContext, ɵɵngDeclareClassMetadata, ɵɵngDeclareComponent, ɵɵngDeclareDirective, ɵɵngDeclareFactory, ɵɵngDeclareInjectable, ɵɵngDeclareInjector, ɵɵngDeclareNgModule, ɵɵngDeclarePipe, ɵɵpipe, ɵɵpipeBind1, ɵɵpipeBind2, ɵɵpipeBind3, ɵɵpipeBind4, ɵɵpipeBindV, ɵɵprojection, ɵɵprojectionDef, ɵɵproperty, ɵɵpropertyInterpolate, ɵɵpropertyInterpolate1, ɵɵpropertyInterpolate2, ɵɵpropertyInterpolate3, ɵɵpropertyInterpolate4, ɵɵpropertyInterpolate5, ɵɵpropertyInterpolate6, ɵɵpropertyInterpolate7, ɵɵpropertyInterpolate8, ɵɵpropertyInterpolateV, ɵɵpureFunction0, ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunction5, ɵɵpureFunction6, ɵɵpureFunction7, ɵɵpureFunction8, ɵɵpureFunctionV, ɵɵqueryRefresh, ɵɵreference, registerNgModuleType as ɵɵregisterNgModuleType, ɵɵresetView, ɵɵresolveBody, ɵɵresolveDocument, ɵɵresolveWindow, ɵɵrestoreView, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl, ɵɵsetComponentScope, ɵɵsetNgModuleScope, ɵɵstyleMap, ɵɵstyleMapInterpolate1, ɵɵstyleMapInterpolate2, ɵɵstyleMapInterpolate3, ɵɵstyleMapInterpolate4, ɵɵstyleMapInterpolate5, ɵɵstyleMapInterpolate6, ɵɵstyleMapInterpolate7, ɵɵstyleMapInterpolate8, ɵɵstyleMapInterpolateV, ɵɵstyleProp, ɵɵstylePropInterpolate1, ɵɵstylePropInterpolate2, ɵɵstylePropInterpolate3, ɵɵstylePropInterpolate4, ɵɵstylePropInterpolate5, ɵɵstylePropInterpolate6, ɵɵstylePropInterpolate7, ɵɵstylePropInterpolate8, ɵɵstylePropInterpolateV, ɵɵsyntheticHostListener, ɵɵsyntheticHostProperty, ɵɵtemplate, ɵɵtemplateRefExtractor, ɵɵtext, ɵɵtextInterpolate, ɵɵtextInterpolate1, ɵɵtextInterpolate2, ɵɵtextInterpolate3, ɵɵtextInterpolate4, ɵɵtextInterpolate5, ɵɵtextInterpolate6, ɵɵtextInterpolate7, ɵɵtextInterpolate8, ɵɵtextInterpolateV, ɵɵtrustConstantHtml, ɵɵtrustConstantResourceUrl, ɵɵvalidateIframeAttribute, ɵɵviewQuery };
28888
29585
  //# sourceMappingURL=core.mjs.map