@angular/core 17.0.3 → 17.0.5

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 (32) hide show
  1. package/esm2022/src/application_init.mjs +2 -2
  2. package/esm2022/src/defer/instructions.mjs +3 -2
  3. package/esm2022/src/defer/utils.mjs +2 -2
  4. package/esm2022/src/image_performance_warning.mjs +14 -3
  5. package/esm2022/src/render3/features/host_directives_feature.mjs +20 -13
  6. package/esm2022/src/render3/instructions/change_detection.mjs +4 -5
  7. package/esm2022/src/render3/instructions/control_flow.mjs +9 -11
  8. package/esm2022/src/render3/util/view_utils.mjs +11 -12
  9. package/esm2022/src/version.mjs +1 -1
  10. package/esm2022/testing/src/logger.mjs +3 -3
  11. package/esm2022/testing/src/test_bed.mjs +3 -3
  12. package/esm2022/testing/src/test_bed_compiler.mjs +19 -10
  13. package/fesm2022/core.mjs +56 -41
  14. package/fesm2022/core.mjs.map +1 -1
  15. package/fesm2022/primitives/signals.mjs +1 -1
  16. package/fesm2022/rxjs-interop.mjs +1 -1
  17. package/fesm2022/testing.mjs +21 -12
  18. package/fesm2022/testing.mjs.map +1 -1
  19. package/index.d.ts +4 -7
  20. package/package.json +1 -1
  21. package/primitives/signals/index.d.ts +1 -1
  22. package/rxjs-interop/index.d.ts +1 -1
  23. package/schematics/migrations/block-template-entities/bundle.js +506 -364
  24. package/schematics/migrations/block-template-entities/bundle.js.map +4 -4
  25. package/schematics/migrations/compiler-options/bundle.js +13 -13
  26. package/schematics/migrations/transfer-state/bundle.js +13 -13
  27. package/schematics/ng-generate/control-flow-migration/bundle.js +855 -517
  28. package/schematics/ng-generate/control-flow-migration/bundle.js.map +4 -4
  29. package/schematics/ng-generate/control-flow-migration/schema.json +6 -0
  30. package/schematics/ng-generate/standalone-migration/bundle.js +818 -623
  31. package/schematics/ng-generate/standalone-migration/bundle.js.map +4 -4
  32. package/testing/index.d.ts +1 -1
package/fesm2022/core.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v17.0.3
2
+ * @license Angular v17.0.5
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -2722,20 +2722,19 @@ function walkUpViews(nestingLevel, currentView) {
2722
2722
  }
2723
2723
  return currentView;
2724
2724
  }
2725
+ function requiresRefreshOrTraversal(lView) {
2726
+ return lView[FLAGS] & (1024 /* LViewFlags.RefreshView */ | 8192 /* LViewFlags.HasChildViewsToRefresh */) ||
2727
+ lView[REACTIVE_TEMPLATE_CONSUMER]?.dirty;
2728
+ }
2725
2729
  /**
2726
- * Updates the `DESCENDANT_VIEWS_TO_REFRESH` counter on the parents of the `LView` as well as the
2727
- * parents above that whose
2728
- * 1. counter goes from 0 to 1, indicating that there is a new child that has a view to refresh
2729
- * or
2730
- * 2. counter goes from 1 to 0, indicating there are no more descendant views to refresh
2731
- * When attaching/re-attaching an `LView` to the change detection tree, we need to ensure that the
2732
- * views above it are traversed during change detection if this one is marked for refresh or has
2733
- * some child or descendant that needs to be refreshed.
2730
+ * Updates the `HasChildViewsToRefresh` flag on the parents of the `LView` as well as the
2731
+ * parents above.
2734
2732
  */
2735
2733
  function updateAncestorTraversalFlagsOnAttach(lView) {
2736
- if (lView[FLAGS] & (1024 /* LViewFlags.RefreshView */ | 8192 /* LViewFlags.HasChildViewsToRefresh */)) {
2737
- markAncestorsForTraversal(lView);
2734
+ if (!requiresRefreshOrTraversal(lView)) {
2735
+ return;
2738
2736
  }
2737
+ markAncestorsForTraversal(lView);
2739
2738
  }
2740
2739
  /**
2741
2740
  * Ensures views above the given `lView` are traversed during change detection even when they are
@@ -10428,7 +10427,7 @@ class Version {
10428
10427
  /**
10429
10428
  * @publicApi
10430
10429
  */
10431
- const VERSION = new Version('17.0.3');
10430
+ const VERSION = new Version('17.0.5');
10432
10431
 
10433
10432
  // This default value is when checking the hierarchy for a token.
10434
10433
  //
@@ -13335,8 +13334,7 @@ function detectChangesInViewWhileDirty(lView) {
13335
13334
  // descendants views that need to be refreshed due to re-dirtying during the change detection
13336
13335
  // run, detect changes on the view again. We run change detection in `Targeted` mode to only
13337
13336
  // refresh views with the `RefreshView` flag.
13338
- while (lView[FLAGS] & (1024 /* LViewFlags.RefreshView */ | 8192 /* LViewFlags.HasChildViewsToRefresh */) ||
13339
- lView[REACTIVE_TEMPLATE_CONSUMER]?.dirty) {
13337
+ while (requiresRefreshOrTraversal(lView)) {
13340
13338
  if (retries === MAXIMUM_REFRESH_RERUNS) {
13341
13339
  throw new RuntimeError(103 /* RuntimeErrorCode.INFINITE_CHANGE_DETECTION */, ngDevMode &&
13342
13340
  'Infinite change detection while trying to refresh views. ' +
@@ -13584,7 +13582,7 @@ function detectChangesInViewIfAttached(lView, mode) {
13584
13582
  *
13585
13583
  * The view is refreshed if:
13586
13584
  * - If the view is CheckAlways or Dirty and ChangeDetectionMode is `Global`
13587
- * - If the view has the `RefreshTransplantedView` flag
13585
+ * - If the view has the `RefreshView` flag
13588
13586
  *
13589
13587
  * The view is not refreshed, but descendants are traversed in `ChangeDetectionMode.Targeted` if the
13590
13588
  * view HasChildViewsToRefresh flag is set.
@@ -15986,19 +15984,26 @@ function ɵɵCopyDefinitionFeature(definition) {
15986
15984
  * @codeGenApi
15987
15985
  */
15988
15986
  function ɵɵHostDirectivesFeature(rawHostDirectives) {
15989
- return (definition) => {
15990
- definition.findHostDirectiveDefs = findHostDirectiveDefs;
15991
- definition.hostDirectives =
15992
- (Array.isArray(rawHostDirectives) ? rawHostDirectives : rawHostDirectives()).map(dir => {
15993
- return typeof dir === 'function' ?
15994
- { directive: resolveForwardRef(dir), inputs: EMPTY_OBJ, outputs: EMPTY_OBJ } :
15995
- {
15996
- directive: resolveForwardRef(dir.directive),
15997
- inputs: bindingArrayToMap(dir.inputs),
15998
- outputs: bindingArrayToMap(dir.outputs)
15999
- };
16000
- });
15987
+ const feature = (definition) => {
15988
+ const resolved = (Array.isArray(rawHostDirectives) ? rawHostDirectives : rawHostDirectives()).map(dir => {
15989
+ return typeof dir === 'function' ?
15990
+ { directive: resolveForwardRef(dir), inputs: EMPTY_OBJ, outputs: EMPTY_OBJ } :
15991
+ {
15992
+ directive: resolveForwardRef(dir.directive),
15993
+ inputs: bindingArrayToMap(dir.inputs),
15994
+ outputs: bindingArrayToMap(dir.outputs)
15995
+ };
15996
+ });
15997
+ if (definition.hostDirectives === null) {
15998
+ definition.findHostDirectiveDefs = findHostDirectiveDefs;
15999
+ definition.hostDirectives = resolved;
16000
+ }
16001
+ else {
16002
+ definition.hostDirectives.unshift(...resolved);
16003
+ }
16001
16004
  };
16005
+ feature.ngInherit = true;
16006
+ return feature;
16002
16007
  }
16003
16008
  function findHostDirectiveDefs(currentDef, matchedDefs, hostDirectiveDefs) {
16004
16009
  if (currentDef.hostDirectives !== null) {
@@ -20335,7 +20340,7 @@ function ɵɵconditional(containerIndex, matchingTemplateIndex, value) {
20335
20340
  // Index -1 is a special case where none of the conditions evaluates to
20336
20341
  // a truthy value and as the consequence we've got no view to show.
20337
20342
  if (matchingTemplateIndex !== -1) {
20338
- const templateTNode = getExistingTNode(hostLView[TVIEW], matchingTemplateIndex);
20343
+ const templateTNode = getExistingTNode(hostLView[TVIEW], HEADER_OFFSET + matchingTemplateIndex);
20339
20344
  const dehydratedView = findMatchingDehydratedView(lContainer, templateTNode.tView.ssrId);
20340
20345
  const embeddedLView = createAndRenderEmbeddedLView(hostLView, templateTNode, value, { dehydratedView });
20341
20346
  addLViewToLContainer(lContainer, embeddedLView, viewInContainerIdx, shouldAddViewToDom(templateTNode, dehydratedView));
@@ -20493,21 +20498,19 @@ class LiveCollectionLContainerImpl extends LiveCollection {
20493
20498
  * The repeater instruction does update-time diffing of a provided collection (against the
20494
20499
  * collection seen previously) and maps changes in the collection to views structure (by adding,
20495
20500
  * removing or moving views as needed).
20496
- * @param metadataSlotIdx - index in data where we can find an instance of RepeaterMetadata with
20497
- * additional information (ex. differ) needed to process collection diffing and view
20498
- * manipulation
20499
20501
  * @param collection - the collection instance to be checked for changes
20500
20502
  * @codeGenApi
20501
20503
  */
20502
- function ɵɵrepeater(metadataSlotIdx, collection) {
20504
+ function ɵɵrepeater(collection) {
20503
20505
  const prevConsumer = setActiveConsumer$1(null);
20506
+ const metadataSlotIdx = getSelectedIndex();
20504
20507
  try {
20505
20508
  const hostLView = getLView();
20506
20509
  const hostTView = hostLView[TVIEW];
20507
- const metadata = hostLView[HEADER_OFFSET + metadataSlotIdx];
20510
+ const metadata = hostLView[metadataSlotIdx];
20508
20511
  if (metadata.liveCollection === undefined) {
20509
20512
  const containerIndex = metadataSlotIdx + 1;
20510
- const lContainer = getLContainer(hostLView, HEADER_OFFSET + containerIndex);
20513
+ const lContainer = getLContainer(hostLView, containerIndex);
20511
20514
  const itemTemplateTNode = getExistingTNode(hostTView, containerIndex);
20512
20515
  metadata.liveCollection =
20513
20516
  new LiveCollectionLContainerImpl(lContainer, hostLView, itemTemplateTNode);
@@ -20525,7 +20528,7 @@ function ɵɵrepeater(metadataSlotIdx, collection) {
20525
20528
  const isCollectionEmpty = liveCollection.length === 0;
20526
20529
  if (bindingUpdated(hostLView, bindingIndex, isCollectionEmpty)) {
20527
20530
  const emptyTemplateIndex = metadataSlotIdx + 2;
20528
- const lContainerForEmpty = getLContainer(hostLView, HEADER_OFFSET + emptyTemplateIndex);
20531
+ const lContainerForEmpty = getLContainer(hostLView, emptyTemplateIndex);
20529
20532
  if (isCollectionEmpty) {
20530
20533
  const emptyTemplateTNode = getExistingTNode(hostTView, emptyTemplateIndex);
20531
20534
  const dehydratedView = findMatchingDehydratedView(lContainerForEmpty, emptyTemplateTNode.tView.ssrId);
@@ -20558,7 +20561,7 @@ function getExistingLViewFromLContainer(lContainer, index) {
20558
20561
  return existingLView;
20559
20562
  }
20560
20563
  function getExistingTNode(tView, index) {
20561
- const tNode = getTNode(tView, index + HEADER_OFFSET);
20564
+ const tNode = getTNode(tView, index);
20562
20565
  ngDevMode && assertTNode(tNode);
20563
20566
  return tNode;
20564
20567
  }
@@ -20782,7 +20785,7 @@ function assertDeferredDependenciesLoaded(tDetails) {
20782
20785
  * that a primary template exists. All the other template options are optional.
20783
20786
  */
20784
20787
  function isTDeferBlockDetails(value) {
20785
- return (typeof value === 'object') &&
20788
+ return value !== null && (typeof value === 'object') &&
20786
20789
  (typeof value.primaryTmplIndex === 'number');
20787
20790
  }
20788
20791
 
@@ -21836,10 +21839,11 @@ function triggerResourceLoading(tDetails, lView, tNode) {
21836
21839
  }
21837
21840
  }
21838
21841
  // The `dependenciesFn` might be `null` when all dependencies within
21839
- // a given defer block were eagerly references elsewhere in a file,
21842
+ // a given defer block were eagerly referenced elsewhere in a file,
21840
21843
  // thus no dynamic `import()`s were produced.
21841
21844
  if (!dependenciesFn) {
21842
21845
  tDetails.loadingPromise = Promise.resolve().then(() => {
21846
+ tDetails.loadingPromise = null;
21843
21847
  tDetails.loadingState = DeferDependenciesLoadingState.COMPLETE;
21844
21848
  });
21845
21849
  return;
@@ -30004,7 +30008,7 @@ const ITS_JUST_ANGULAR = true;
30004
30008
  * provideHttpClient(),
30005
30009
  * {
30006
30010
  * provide: APP_INITIALIZER,
30007
- * useFactory: initializeApp,
30011
+ * useFactory: initializeAppFactory,
30008
30012
  * multi: true,
30009
30013
  * deps: [HttpClient],
30010
30014
  * },
@@ -30289,7 +30293,8 @@ class ImagePerformanceWarning {
30289
30293
  return;
30290
30294
  }
30291
30295
  this.observer = this.initPerformanceObserver();
30292
- const win = getDocument().defaultView;
30296
+ const doc = getDocument();
30297
+ const win = doc.defaultView;
30293
30298
  if (typeof win !== 'undefined') {
30294
30299
  this.window = win;
30295
30300
  // Wait to avoid race conditions where LCP image triggers
@@ -30300,7 +30305,17 @@ class ImagePerformanceWarning {
30300
30305
  // Angular doesn't have to run change detection whenever any asynchronous tasks are invoked in
30301
30306
  // the scope of this functionality.
30302
30307
  this.ngZone.runOutsideAngular(() => {
30303
- this.window?.addEventListener('load', waitToScan);
30308
+ // Consider the case when the application is created and destroyed multiple times.
30309
+ // Typically, applications are created instantly once the page is loaded, and the
30310
+ // `window.load` listener is always triggered. However, the `window.load` event will never
30311
+ // be fired if the page is loaded, and the application is created later. Checking for
30312
+ // `readyState` is the easiest way to determine whether the page has been loaded or not.
30313
+ if (doc.readyState === 'complete') {
30314
+ waitToScan();
30315
+ }
30316
+ else {
30317
+ this.window?.addEventListener('load', waitToScan, { once: true });
30318
+ }
30304
30319
  });
30305
30320
  }
30306
30321
  }