@angular/core 10.2.0 → 10.2.4

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.
package/fesm2015/core.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v10.2.0
2
+ * @license Angular v10.2.4
3
3
  * (c) 2010-2020 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -2095,6 +2095,182 @@ function assertNodeInjector(lView, injectorIndex) {
2095
2095
  assertNumber(lView[injectorIndex + 8 /* PARENT */], 'injectorIndex should point to parent injector');
2096
2096
  }
2097
2097
 
2098
+ /**
2099
+ * @license
2100
+ * Copyright Google LLC All Rights Reserved.
2101
+ *
2102
+ * Use of this source code is governed by an MIT-style license that can be
2103
+ * found in the LICENSE file at https://angular.io/license
2104
+ */
2105
+ /**
2106
+ * Used for stringify render output in Ivy.
2107
+ * Important! This function is very performance-sensitive and we should
2108
+ * be extra careful not to introduce megamorphic reads in it.
2109
+ */
2110
+ function renderStringify(value) {
2111
+ if (typeof value === 'string')
2112
+ return value;
2113
+ if (value == null)
2114
+ return '';
2115
+ return '' + value;
2116
+ }
2117
+ /**
2118
+ * Used to stringify a value so that it can be displayed in an error message.
2119
+ * Important! This function contains a megamorphic read and should only be
2120
+ * used for error messages.
2121
+ */
2122
+ function stringifyForError(value) {
2123
+ if (typeof value === 'function')
2124
+ return value.name || value.toString();
2125
+ if (typeof value === 'object' && value != null && typeof value.type === 'function') {
2126
+ return value.type.name || value.type.toString();
2127
+ }
2128
+ return renderStringify(value);
2129
+ }
2130
+ const ɵ0$2 = () => (typeof requestAnimationFrame !== 'undefined' &&
2131
+ requestAnimationFrame || // browser only
2132
+ setTimeout // everything else
2133
+ )
2134
+ .bind(_global);
2135
+ const defaultScheduler = (ɵ0$2)();
2136
+ /**
2137
+ *
2138
+ * @codeGenApi
2139
+ */
2140
+ function ɵɵresolveWindow(element) {
2141
+ return { name: 'window', target: element.ownerDocument.defaultView };
2142
+ }
2143
+ /**
2144
+ *
2145
+ * @codeGenApi
2146
+ */
2147
+ function ɵɵresolveDocument(element) {
2148
+ return { name: 'document', target: element.ownerDocument };
2149
+ }
2150
+ /**
2151
+ *
2152
+ * @codeGenApi
2153
+ */
2154
+ function ɵɵresolveBody(element) {
2155
+ return { name: 'body', target: element.ownerDocument.body };
2156
+ }
2157
+ /**
2158
+ * The special delimiter we use to separate property names, prefixes, and suffixes
2159
+ * in property binding metadata. See storeBindingMetadata().
2160
+ *
2161
+ * We intentionally use the Unicode "REPLACEMENT CHARACTER" (U+FFFD) as a delimiter
2162
+ * because it is a very uncommon character that is unlikely to be part of a user's
2163
+ * property names or interpolation strings. If it is in fact used in a property
2164
+ * binding, DebugElement.properties will not return the correct value for that
2165
+ * binding. However, there should be no runtime effect for real applications.
2166
+ *
2167
+ * This character is typically rendered as a question mark inside of a diamond.
2168
+ * See https://en.wikipedia.org/wiki/Specials_(Unicode_block)
2169
+ *
2170
+ */
2171
+ const INTERPOLATION_DELIMITER = `�`;
2172
+ /**
2173
+ * Unwrap a value which might be behind a closure (for forward declaration reasons).
2174
+ */
2175
+ function maybeUnwrapFn(value) {
2176
+ if (value instanceof Function) {
2177
+ return value();
2178
+ }
2179
+ else {
2180
+ return value;
2181
+ }
2182
+ }
2183
+
2184
+ /** Called when directives inject each other (creating a circular dependency) */
2185
+ function throwCyclicDependencyError(token, path) {
2186
+ const depPath = path ? `. Dependency path: ${path.join(' > ')} > ${token}` : '';
2187
+ throw new Error(`Circular dependency in DI detected for ${token}${depPath}`);
2188
+ }
2189
+ /** Called when there are multiple component selectors that match a given node */
2190
+ function throwMultipleComponentError(tNode) {
2191
+ throw new Error(`Multiple components match node with tagname ${tNode.tagName}`);
2192
+ }
2193
+ function throwMixedMultiProviderError() {
2194
+ throw new Error(`Cannot mix multi providers and regular providers`);
2195
+ }
2196
+ function throwInvalidProviderError(ngModuleType, providers, provider) {
2197
+ let ngModuleDetail = '';
2198
+ if (ngModuleType && providers) {
2199
+ const providerDetail = providers.map(v => v == provider ? '?' + provider + '?' : '...');
2200
+ ngModuleDetail =
2201
+ ` - only instances of Provider and Type are allowed, got: [${providerDetail.join(', ')}]`;
2202
+ }
2203
+ throw new Error(`Invalid provider for the NgModule '${stringify(ngModuleType)}'` + ngModuleDetail);
2204
+ }
2205
+ /** Throws an ExpressionChangedAfterChecked error if checkNoChanges mode is on. */
2206
+ function throwErrorIfNoChangesMode(creationMode, oldValue, currValue, propName) {
2207
+ const field = propName ? ` for '${propName}'` : '';
2208
+ let msg = `ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value${field}: '${oldValue}'. Current value: '${currValue}'.`;
2209
+ if (creationMode) {
2210
+ msg +=
2211
+ ` It seems like the view has been created after its parent and its children have been dirty checked.` +
2212
+ ` Has it been created in a change detection hook?`;
2213
+ }
2214
+ // TODO: include debug context, see `viewDebugError` function in
2215
+ // `packages/core/src/view/errors.ts` for reference.
2216
+ throw new Error(msg);
2217
+ }
2218
+ function constructDetailsForInterpolation(lView, rootIndex, expressionIndex, meta, changedValue) {
2219
+ const [propName, prefix, ...chunks] = meta.split(INTERPOLATION_DELIMITER);
2220
+ let oldValue = prefix, newValue = prefix;
2221
+ for (let i = 0; i < chunks.length; i++) {
2222
+ const slotIdx = rootIndex + i;
2223
+ oldValue += `${lView[slotIdx]}${chunks[i]}`;
2224
+ newValue += `${slotIdx === expressionIndex ? changedValue : lView[slotIdx]}${chunks[i]}`;
2225
+ }
2226
+ return { propName, oldValue, newValue };
2227
+ }
2228
+ /**
2229
+ * Constructs an object that contains details for the ExpressionChangedAfterItHasBeenCheckedError:
2230
+ * - property name (for property bindings or interpolations)
2231
+ * - old and new values, enriched using information from metadata
2232
+ *
2233
+ * More information on the metadata storage format can be found in `storePropertyBindingMetadata`
2234
+ * function description.
2235
+ */
2236
+ function getExpressionChangedErrorDetails(lView, bindingIndex, oldValue, newValue) {
2237
+ const tData = lView[TVIEW].data;
2238
+ const metadata = tData[bindingIndex];
2239
+ if (typeof metadata === 'string') {
2240
+ // metadata for property interpolation
2241
+ if (metadata.indexOf(INTERPOLATION_DELIMITER) > -1) {
2242
+ return constructDetailsForInterpolation(lView, bindingIndex, bindingIndex, metadata, newValue);
2243
+ }
2244
+ // metadata for property binding
2245
+ return { propName: metadata, oldValue, newValue };
2246
+ }
2247
+ // metadata is not available for this expression, check if this expression is a part of the
2248
+ // property interpolation by going from the current binding index left and look for a string that
2249
+ // contains INTERPOLATION_DELIMITER, the layout in tView.data for this case will look like this:
2250
+ // [..., 'id�Prefix � and � suffix', null, null, null, ...]
2251
+ if (metadata === null) {
2252
+ let idx = bindingIndex - 1;
2253
+ while (typeof tData[idx] !== 'string' && tData[idx + 1] === null) {
2254
+ idx--;
2255
+ }
2256
+ const meta = tData[idx];
2257
+ if (typeof meta === 'string') {
2258
+ const matches = meta.match(new RegExp(INTERPOLATION_DELIMITER, 'g'));
2259
+ // first interpolation delimiter separates property name from interpolation parts (in case of
2260
+ // property interpolations), so we subtract one from total number of found delimiters
2261
+ if (matches && (matches.length - 1) > bindingIndex - idx) {
2262
+ return constructDetailsForInterpolation(lView, idx, bindingIndex, meta, newValue);
2263
+ }
2264
+ }
2265
+ }
2266
+ return { propName: undefined, oldValue, newValue };
2267
+ }
2268
+ /** Throws an error when a token is not found in DI. */
2269
+ function throwProviderNotFoundError(token, injectorName) {
2270
+ const injectorDetails = injectorName ? ` in ${injectorName}` : '';
2271
+ throw new Error(`No provider for ${stringifyForError(token)} found${injectorDetails}`);
2272
+ }
2273
+
2098
2274
  /**
2099
2275
  * @license
2100
2276
  * Copyright Google LLC All Rights Reserved.
@@ -2309,11 +2485,11 @@ var RendererStyleFlags3;
2309
2485
  function isProceduralRenderer(renderer) {
2310
2486
  return !!(renderer.listen);
2311
2487
  }
2312
- const ɵ0$2 = (hostElement, rendererType) => {
2488
+ const ɵ0$3 = (hostElement, rendererType) => {
2313
2489
  return getDocument();
2314
2490
  };
2315
2491
  const domRendererFactory3 = {
2316
- createRenderer: ɵ0$2
2492
+ createRenderer: ɵ0$3
2317
2493
  };
2318
2494
  // Note: This hack is necessary so we don't erroneously get a circular dependency
2319
2495
  // failure based on types.
@@ -3581,92 +3757,6 @@ function getParentInjectorView(location, startView) {
3581
3757
  return parentView;
3582
3758
  }
3583
3759
 
3584
- /**
3585
- * @license
3586
- * Copyright Google LLC All Rights Reserved.
3587
- *
3588
- * Use of this source code is governed by an MIT-style license that can be
3589
- * found in the LICENSE file at https://angular.io/license
3590
- */
3591
- /**
3592
- * Used for stringify render output in Ivy.
3593
- * Important! This function is very performance-sensitive and we should
3594
- * be extra careful not to introduce megamorphic reads in it.
3595
- */
3596
- function renderStringify(value) {
3597
- if (typeof value === 'string')
3598
- return value;
3599
- if (value == null)
3600
- return '';
3601
- return '' + value;
3602
- }
3603
- /**
3604
- * Used to stringify a value so that it can be displayed in an error message.
3605
- * Important! This function contains a megamorphic read and should only be
3606
- * used for error messages.
3607
- */
3608
- function stringifyForError(value) {
3609
- if (typeof value === 'function')
3610
- return value.name || value.toString();
3611
- if (typeof value === 'object' && value != null && typeof value.type === 'function') {
3612
- return value.type.name || value.type.toString();
3613
- }
3614
- return renderStringify(value);
3615
- }
3616
- const ɵ0$3 = () => (typeof requestAnimationFrame !== 'undefined' &&
3617
- requestAnimationFrame || // browser only
3618
- setTimeout // everything else
3619
- )
3620
- .bind(_global);
3621
- const defaultScheduler = (ɵ0$3)();
3622
- /**
3623
- *
3624
- * @codeGenApi
3625
- */
3626
- function ɵɵresolveWindow(element) {
3627
- return { name: 'window', target: element.ownerDocument.defaultView };
3628
- }
3629
- /**
3630
- *
3631
- * @codeGenApi
3632
- */
3633
- function ɵɵresolveDocument(element) {
3634
- return { name: 'document', target: element.ownerDocument };
3635
- }
3636
- /**
3637
- *
3638
- * @codeGenApi
3639
- */
3640
- function ɵɵresolveBody(element) {
3641
- return { name: 'body', target: element.ownerDocument.body };
3642
- }
3643
- /**
3644
- * The special delimiter we use to separate property names, prefixes, and suffixes
3645
- * in property binding metadata. See storeBindingMetadata().
3646
- *
3647
- * We intentionally use the Unicode "REPLACEMENT CHARACTER" (U+FFFD) as a delimiter
3648
- * because it is a very uncommon character that is unlikely to be part of a user's
3649
- * property names or interpolation strings. If it is in fact used in a property
3650
- * binding, DebugElement.properties will not return the correct value for that
3651
- * binding. However, there should be no runtime effect for real applications.
3652
- *
3653
- * This character is typically rendered as a question mark inside of a diamond.
3654
- * See https://en.wikipedia.org/wiki/Specials_(Unicode_block)
3655
- *
3656
- */
3657
- const INTERPOLATION_DELIMITER = `�`;
3658
- /**
3659
- * Unwrap a value which might be behind a closure (for forward declaration reasons).
3660
- */
3661
- function maybeUnwrapFn(value) {
3662
- if (value instanceof Function) {
3663
- return value();
3664
- }
3665
- else {
3666
- return value;
3667
- }
3668
- }
3669
-
3670
3760
  /**
3671
3761
  * @license
3672
3762
  * Copyright Google LLC All Rights Reserved.
@@ -3991,7 +4081,7 @@ function getOrCreateInjectable(tNode, lView, token, flags = InjectFlags.Default,
3991
4081
  try {
3992
4082
  const value = bloomHash();
3993
4083
  if (value == null && !(flags & InjectFlags.Optional)) {
3994
- throw new Error(`No provider for ${stringifyForError(token)}!`);
4084
+ throwProviderNotFoundError(token);
3995
4085
  }
3996
4086
  else {
3997
4087
  return value;
@@ -4090,7 +4180,7 @@ function getOrCreateInjectable(tNode, lView, token, flags = InjectFlags.Default,
4090
4180
  return notFoundValue;
4091
4181
  }
4092
4182
  else {
4093
- throw new Error(`NodeInjector: NOT_FOUND [${stringifyForError(token)}]`);
4183
+ throwProviderNotFoundError(token, 'NodeInjector');
4094
4184
  }
4095
4185
  }
4096
4186
  const NOT_FOUND = {};
@@ -4174,7 +4264,7 @@ function getNodeInjectable(lView, tView, index, tNode) {
4174
4264
  if (isFactory(value)) {
4175
4265
  const factory = value;
4176
4266
  if (factory.resolving) {
4177
- throw new Error(`Circular dep for ${stringifyForError(tData[index])}`);
4267
+ throwCyclicDependencyError(stringifyForError(tData[index]));
4178
4268
  }
4179
4269
  const previousIncludeViewProviders = setIncludeViewProviders(factory.canSeeViewProviders);
4180
4270
  factory.resolving = true;
@@ -4610,6 +4700,11 @@ function enableProdMode() {
4610
4700
  if (_runModeLocked) {
4611
4701
  throw new Error('Cannot enable prod mode after platform setup.');
4612
4702
  }
4703
+ // The below check is there so when ngDevMode is set via terser
4704
+ // `global['ngDevMode'] = false;` is also dropped.
4705
+ if (typeof ngDevMode === undefined || !!ngDevMode) {
4706
+ _global['ngDevMode'] = false;
4707
+ }
4613
4708
  _devMode = false;
4614
4709
  }
4615
4710
 
@@ -5239,6 +5334,42 @@ function getSanitizer() {
5239
5334
  return lView && lView[SANITIZER];
5240
5335
  }
5241
5336
 
5337
+ /**
5338
+ * @license
5339
+ * Copyright Google LLC All Rights Reserved.
5340
+ *
5341
+ * Use of this source code is governed by an MIT-style license that can be
5342
+ * found in the LICENSE file at https://angular.io/license
5343
+ */
5344
+ const END_COMMENT = /-->/g;
5345
+ const END_COMMENT_ESCAPED = '-\u200B-\u200B>';
5346
+ /**
5347
+ * Escape the content of the strings so that it can be safely inserted into a comment node.
5348
+ *
5349
+ * The issue is that HTML does not specify any way to escape comment end text inside the comment.
5350
+ * `<!-- The way you close a comment is with "-->". -->`. Above the `"-->"` is meant to be text not
5351
+ * an end to the comment. This can be created programmatically through DOM APIs.
5352
+ *
5353
+ * ```
5354
+ * div.innerHTML = div.innerHTML
5355
+ * ```
5356
+ *
5357
+ * One would expect that the above code would be safe to do, but it turns out that because comment
5358
+ * text is not escaped, the comment may contain text which will prematurely close the comment
5359
+ * opening up the application for XSS attack. (In SSR we programmatically create comment nodes which
5360
+ * may contain such text and expect them to be safe.)
5361
+ *
5362
+ * This function escapes the comment text by looking for the closing char sequence `-->` and replace
5363
+ * it with `-_-_>` where the `_` is a zero width space `\u200B`. The result is that if a comment
5364
+ * contains `-->` text it will render normally but it will not cause the HTML parser to close the
5365
+ * comment.
5366
+ *
5367
+ * @param value text to make safe for comment node by escaping the comment close character sequence
5368
+ */
5369
+ function escapeCommentText(value) {
5370
+ return value.replace(END_COMMENT, END_COMMENT_ESCAPED);
5371
+ }
5372
+
5242
5373
  /**
5243
5374
  * @license
5244
5375
  * Copyright Google LLC All Rights Reserved.
@@ -5591,90 +5722,6 @@ function discoverLocalRefs(lView, nodeIndex) {
5591
5722
  return null;
5592
5723
  }
5593
5724
 
5594
- /** Called when directives inject each other (creating a circular dependency) */
5595
- function throwCyclicDependencyError(token) {
5596
- throw new Error(`Cannot instantiate cyclic dependency! ${token}`);
5597
- }
5598
- /** Called when there are multiple component selectors that match a given node */
5599
- function throwMultipleComponentError(tNode) {
5600
- throw new Error(`Multiple components match node with tagname ${tNode.tagName}`);
5601
- }
5602
- function throwMixedMultiProviderError() {
5603
- throw new Error(`Cannot mix multi providers and regular providers`);
5604
- }
5605
- function throwInvalidProviderError(ngModuleType, providers, provider) {
5606
- let ngModuleDetail = '';
5607
- if (ngModuleType && providers) {
5608
- const providerDetail = providers.map(v => v == provider ? '?' + provider + '?' : '...');
5609
- ngModuleDetail =
5610
- ` - only instances of Provider and Type are allowed, got: [${providerDetail.join(', ')}]`;
5611
- }
5612
- throw new Error(`Invalid provider for the NgModule '${stringify(ngModuleType)}'` + ngModuleDetail);
5613
- }
5614
- /** Throws an ExpressionChangedAfterChecked error if checkNoChanges mode is on. */
5615
- function throwErrorIfNoChangesMode(creationMode, oldValue, currValue, propName) {
5616
- const field = propName ? ` for '${propName}'` : '';
5617
- let msg = `ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value${field}: '${oldValue}'. Current value: '${currValue}'.`;
5618
- if (creationMode) {
5619
- msg +=
5620
- ` It seems like the view has been created after its parent and its children have been dirty checked.` +
5621
- ` Has it been created in a change detection hook?`;
5622
- }
5623
- // TODO: include debug context, see `viewDebugError` function in
5624
- // `packages/core/src/view/errors.ts` for reference.
5625
- throw new Error(msg);
5626
- }
5627
- function constructDetailsForInterpolation(lView, rootIndex, expressionIndex, meta, changedValue) {
5628
- const [propName, prefix, ...chunks] = meta.split(INTERPOLATION_DELIMITER);
5629
- let oldValue = prefix, newValue = prefix;
5630
- for (let i = 0; i < chunks.length; i++) {
5631
- const slotIdx = rootIndex + i;
5632
- oldValue += `${lView[slotIdx]}${chunks[i]}`;
5633
- newValue += `${slotIdx === expressionIndex ? changedValue : lView[slotIdx]}${chunks[i]}`;
5634
- }
5635
- return { propName, oldValue, newValue };
5636
- }
5637
- /**
5638
- * Constructs an object that contains details for the ExpressionChangedAfterItHasBeenCheckedError:
5639
- * - property name (for property bindings or interpolations)
5640
- * - old and new values, enriched using information from metadata
5641
- *
5642
- * More information on the metadata storage format can be found in `storePropertyBindingMetadata`
5643
- * function description.
5644
- */
5645
- function getExpressionChangedErrorDetails(lView, bindingIndex, oldValue, newValue) {
5646
- const tData = lView[TVIEW].data;
5647
- const metadata = tData[bindingIndex];
5648
- if (typeof metadata === 'string') {
5649
- // metadata for property interpolation
5650
- if (metadata.indexOf(INTERPOLATION_DELIMITER) > -1) {
5651
- return constructDetailsForInterpolation(lView, bindingIndex, bindingIndex, metadata, newValue);
5652
- }
5653
- // metadata for property binding
5654
- return { propName: metadata, oldValue, newValue };
5655
- }
5656
- // metadata is not available for this expression, check if this expression is a part of the
5657
- // property interpolation by going from the current binding index left and look for a string that
5658
- // contains INTERPOLATION_DELIMITER, the layout in tView.data for this case will look like this:
5659
- // [..., 'id�Prefix � and � suffix', null, null, null, ...]
5660
- if (metadata === null) {
5661
- let idx = bindingIndex - 1;
5662
- while (typeof tData[idx] !== 'string' && tData[idx + 1] === null) {
5663
- idx--;
5664
- }
5665
- const meta = tData[idx];
5666
- if (typeof meta === 'string') {
5667
- const matches = meta.match(new RegExp(INTERPOLATION_DELIMITER, 'g'));
5668
- // first interpolation delimiter separates property name from interpolation parts (in case of
5669
- // property interpolations), so we subtract one from total number of found delimiters
5670
- if (matches && (matches.length - 1) > bindingIndex - idx) {
5671
- return constructDetailsForInterpolation(lView, idx, bindingIndex, meta, newValue);
5672
- }
5673
- }
5674
- }
5675
- return { propName: undefined, oldValue, newValue };
5676
- }
5677
-
5678
5725
  /**
5679
5726
  * @license
5680
5727
  * Copyright Google LLC All Rights Reserved.
@@ -7761,7 +7808,7 @@ function generatePropertyAliases(inputAliasMap, directiveDefIdx, propStore) {
7761
7808
  return propStore;
7762
7809
  }
7763
7810
  /**
7764
- * Initializes data structures required to work with directive outputs and outputs.
7811
+ * Initializes data structures required to work with directive inputs and outputs.
7765
7812
  * Initialization is done for all directives matched on a given TNode.
7766
7813
  */
7767
7814
  function initializeInputAndOutputAliases(tView, tNode) {
@@ -7891,7 +7938,7 @@ function setNgReflectProperty(lView, element, type, attrName, value) {
7891
7938
  }
7892
7939
  }
7893
7940
  else {
7894
- const textContent = `bindings=${JSON.stringify({ [attrName]: debugValue }, null, 2)}`;
7941
+ const textContent = escapeCommentText(`bindings=${JSON.stringify({ [attrName]: debugValue }, null, 2)}`);
7895
7942
  if (isProceduralRenderer(renderer)) {
7896
7943
  renderer.setValue(element, textContent);
7897
7944
  }
@@ -8610,8 +8657,10 @@ function markViewDirty(lView) {
8610
8657
  */
8611
8658
  function scheduleTick(rootContext, flags) {
8612
8659
  const nothingScheduled = rootContext.flags === 0 /* Empty */;
8613
- rootContext.flags |= flags;
8614
8660
  if (nothingScheduled && rootContext.clean == _CLEAN_PROMISE) {
8661
+ // https://github.com/angular/angular/issues/39296
8662
+ // should only attach the flags when really scheduling a tick
8663
+ rootContext.flags |= flags;
8615
8664
  let res;
8616
8665
  rootContext.clean = new Promise((r) => res = r);
8617
8666
  rootContext.scheduler(() => {
@@ -11186,7 +11235,8 @@ class R3Injector {
11186
11235
  // Check for circular dependencies.
11187
11236
  if (ngDevMode && parents.indexOf(defType) !== -1) {
11188
11237
  const defName = stringify(defType);
11189
- throw new Error(`Circular dependency in DI detected for type ${defName}. Dependency path: ${parents.map(defType => stringify(defType)).join(' > ')} > ${defName}.`);
11238
+ const path = parents.map(stringify);
11239
+ throwCyclicDependencyError(defName, path);
11190
11240
  }
11191
11241
  // Check for multiple imports of the same module
11192
11242
  const isDuplicate = dedupStack.indexOf(defType) !== -1;
@@ -13373,7 +13423,7 @@ function publishGlobalUtil(name, fn) {
13373
13423
  * found in the LICENSE file at https://angular.io/license
13374
13424
  */
13375
13425
  const ɵ0$b = (token, notFoundValue) => {
13376
- throw new Error('NullInjector: Not found: ' + stringifyForError(token));
13426
+ throwProviderNotFoundError(token, 'NullInjector');
13377
13427
  };
13378
13428
  // TODO: A hack to not pull in the NullInjector from @angular/core.
13379
13429
  const NULL_INJECTOR$1 = {
@@ -21059,7 +21109,7 @@ class Version {
21059
21109
  /**
21060
21110
  * @publicApi
21061
21111
  */
21062
- const VERSION = new Version('10.2.0');
21112
+ const VERSION = new Version('10.2.4');
21063
21113
 
21064
21114
  /**
21065
21115
  * @license
@@ -24177,18 +24227,25 @@ function assertSameOrNotExisting(id, type, incoming) {
24177
24227
  }
24178
24228
  }
24179
24229
  function registerNgModuleType(ngModuleType) {
24180
- if (ngModuleType.ɵmod.id !== null) {
24181
- const id = ngModuleType.ɵmod.id;
24182
- const existing = modules.get(id);
24183
- assertSameOrNotExisting(id, existing, ngModuleType);
24184
- modules.set(id, ngModuleType);
24185
- }
24186
- let imports = ngModuleType.ɵmod.imports;
24187
- if (imports instanceof Function) {
24188
- imports = imports();
24189
- }
24190
- if (imports) {
24191
- imports.forEach(i => registerNgModuleType(i));
24230
+ const visited = new Set();
24231
+ recurse(ngModuleType);
24232
+ function recurse(ngModuleType) {
24233
+ // The imports array of an NgModule must refer to other NgModules,
24234
+ // so an error is thrown if no module definition is available.
24235
+ const def = getNgModuleDef(ngModuleType, /* throwNotFound */ true);
24236
+ const id = def.id;
24237
+ if (id !== null) {
24238
+ const existing = modules.get(id);
24239
+ assertSameOrNotExisting(id, existing, ngModuleType);
24240
+ modules.set(id, ngModuleType);
24241
+ }
24242
+ const imports = maybeUnwrapFn(def.imports);
24243
+ for (const i of imports) {
24244
+ if (!visited.has(i)) {
24245
+ visited.add(i);
24246
+ recurse(i);
24247
+ }
24248
+ }
24192
24249
  }
24193
24250
  }
24194
24251
  function clearModulesForTest() {
@@ -25571,7 +25628,7 @@ function ɵɵtemplateRefExtractor(tNode, currentView) {
25571
25628
  function ɵɵinjectPipeChangeDetectorRef(flags = InjectFlags.Default) {
25572
25629
  const value = injectChangeDetectorRef(true);
25573
25630
  if (value == null && !(flags & InjectFlags.Optional)) {
25574
- throw new Error(`No provider for ChangeDetectorRef!`);
25631
+ throwProviderNotFoundError('ChangeDetectorRef');
25575
25632
  }
25576
25633
  else {
25577
25634
  return value;
@@ -31294,7 +31351,7 @@ function debugCheckAndUpdateNode(view, nodeDef, argStyle, givenValues) {
31294
31351
  const el = asElementData(view, elDef.nodeIndex).renderElement;
31295
31352
  if (!elDef.element.name) {
31296
31353
  // a comment.
31297
- view.renderer.setValue(el, `bindings=${JSON.stringify(bindingValues, null, 2)}`);
31354
+ view.renderer.setValue(el, escapeCommentText(`bindings=${JSON.stringify(bindingValues, null, 2)}`));
31298
31355
  }
31299
31356
  else {
31300
31357
  // a regular element.
@@ -31544,7 +31601,7 @@ class DebugRenderer2 {
31544
31601
  return el;
31545
31602
  }
31546
31603
  createComment(value) {
31547
- const comment = this.delegate.createComment(value);
31604
+ const comment = this.delegate.createComment(escapeCommentText(value));
31548
31605
  const debugCtx = this.createDebugContext(comment);
31549
31606
  if (debugCtx) {
31550
31607
  indexDebugNode(new DebugNode__PRE_R3__(comment, null, debugCtx));
@@ -31761,7 +31818,7 @@ class NgModuleFactory_ extends NgModuleFactory {
31761
31818
  * Use of this source code is governed by an MIT-style license that can be
31762
31819
  * found in the LICENSE file at https://angular.io/license
31763
31820
  */
31764
- if (ngDevMode) {
31821
+ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
31765
31822
  // This helper is to give a reasonable error message to people upgrading to v9 that have not yet
31766
31823
  // installed `@angular/localize` in their app.
31767
31824
  // tslint:disable-next-line: no-toplevel-property-access