@angular/core 18.1.0-next.1 → 18.1.0-next.2

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 (31) hide show
  1. package/esm2022/src/core.mjs +1 -1
  2. package/esm2022/src/event_emitter.mjs +20 -11
  3. package/esm2022/src/pending_tasks.mjs +15 -20
  4. package/esm2022/src/render3/after_render_hooks.mjs +67 -132
  5. package/esm2022/src/render3/component_ref.mjs +1 -1
  6. package/esm2022/src/render3/instructions/change_detection.mjs +27 -24
  7. package/esm2022/src/render3/reactive_lview_consumer.mjs +56 -3
  8. package/esm2022/src/version.mjs +1 -1
  9. package/esm2022/testing/src/logger.mjs +3 -3
  10. package/fesm2022/core.mjs +344 -349
  11. package/fesm2022/core.mjs.map +1 -1
  12. package/fesm2022/primitives/event-dispatch.mjs +1 -1
  13. package/fesm2022/primitives/signals.mjs +1 -1
  14. package/fesm2022/rxjs-interop.mjs +1 -1
  15. package/fesm2022/testing.mjs +1 -1
  16. package/index.d.ts +212 -28
  17. package/package.json +1 -1
  18. package/primitives/event-dispatch/index.d.ts +1 -1
  19. package/primitives/signals/index.d.ts +1 -1
  20. package/rxjs-interop/index.d.ts +1 -1
  21. package/schematics/migrations/after-render-phase/bundle.js +602 -0
  22. package/schematics/migrations/after-render-phase/bundle.js.map +7 -0
  23. package/schematics/migrations/http-providers/bundle.js +15 -15
  24. package/schematics/migrations/invalid-two-way-bindings/bundle.js +158 -158
  25. package/schematics/migrations/invalid-two-way-bindings/bundle.js.map +1 -1
  26. package/schematics/migrations.json +5 -0
  27. package/schematics/ng-generate/control-flow-migration/bundle.js +166 -166
  28. package/schematics/ng-generate/control-flow-migration/bundle.js.map +1 -1
  29. package/schematics/ng-generate/standalone-migration/bundle.js +483 -1096
  30. package/schematics/ng-generate/standalone-migration/bundle.js.map +4 -4
  31. package/testing/index.d.ts +1 -1
package/fesm2022/core.mjs CHANGED
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @license Angular v18.1.0-next.1
2
+ * @license Angular v18.1.0-next.2
3
3
  * (c) 2010-2024 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import { SIGNAL_NODE as SIGNAL_NODE$1, signalSetFn as signalSetFn$1, producerAccessed as producerAccessed$1, SIGNAL as SIGNAL$1, getActiveConsumer as getActiveConsumer$1, setActiveConsumer as setActiveConsumer$1, consumerDestroy as consumerDestroy$1, REACTIVE_NODE as REACTIVE_NODE$1, consumerBeforeComputation as consumerBeforeComputation$1, consumerAfterComputation as consumerAfterComputation$1, consumerPollProducersForChange as consumerPollProducersForChange$1, createSignal as createSignal$1, signalUpdateFn as signalUpdateFn$1, createComputed as createComputed$1, setThrowInvalidWriteToSignalError as setThrowInvalidWriteToSignalError$1, createWatch as createWatch$1 } from '@angular/core/primitives/signals';
8
- import { Subject, Subscription, BehaviorSubject } from 'rxjs';
8
+ import { BehaviorSubject, Subject, Subscription } from 'rxjs';
9
9
  import { map, first } from 'rxjs/operators';
10
10
  import * as Attributes from '@angular/core/primitives/event-dispatch';
11
11
  import { EventContract, EventContractContainer, EventDispatcher, registerDispatcher, isSupportedEvent, isCaptureEvent } from '@angular/core/primitives/event-dispatch';
@@ -6917,15 +6917,102 @@ function unwrapElementRef(value) {
6917
6917
  return value instanceof ElementRef ? value.nativeElement : value;
6918
6918
  }
6919
6919
 
6920
+ /**
6921
+ * Internal implementation of the pending tasks service.
6922
+ */
6923
+ class PendingTasks {
6924
+ constructor() {
6925
+ this.taskId = 0;
6926
+ this.pendingTasks = new Set();
6927
+ this.hasPendingTasks = new BehaviorSubject(false);
6928
+ }
6929
+ get _hasPendingTasks() {
6930
+ return this.hasPendingTasks.value;
6931
+ }
6932
+ add() {
6933
+ if (!this._hasPendingTasks) {
6934
+ this.hasPendingTasks.next(true);
6935
+ }
6936
+ const taskId = this.taskId++;
6937
+ this.pendingTasks.add(taskId);
6938
+ return taskId;
6939
+ }
6940
+ remove(taskId) {
6941
+ this.pendingTasks.delete(taskId);
6942
+ if (this.pendingTasks.size === 0 && this._hasPendingTasks) {
6943
+ this.hasPendingTasks.next(false);
6944
+ }
6945
+ }
6946
+ ngOnDestroy() {
6947
+ this.pendingTasks.clear();
6948
+ if (this._hasPendingTasks) {
6949
+ this.hasPendingTasks.next(false);
6950
+ }
6951
+ }
6952
+ /** @nocollapse */
6953
+ static { this.ɵprov = ɵɵdefineInjectable({
6954
+ token: PendingTasks,
6955
+ providedIn: 'root',
6956
+ factory: () => new PendingTasks(),
6957
+ }); }
6958
+ }
6959
+ /**
6960
+ * Experimental service that keeps track of pending tasks contributing to the stableness of Angular
6961
+ * application. While several existing Angular services (ex.: `HttpClient`) will internally manage
6962
+ * tasks influencing stability, this API gives control over stability to library and application
6963
+ * developers for specific cases not covered by Angular internals.
6964
+ *
6965
+ * The concept of stability comes into play in several important scenarios:
6966
+ * - SSR process needs to wait for the application stability before serializing and sending rendered
6967
+ * HTML;
6968
+ * - tests might want to delay assertions until the application becomes stable;
6969
+ *
6970
+ * @usageNotes
6971
+ * ```typescript
6972
+ * const pendingTasks = inject(ExperimentalPendingTasks);
6973
+ * const taskCleanup = pendingTasks.add();
6974
+ * // do work that should block application's stability and then:
6975
+ * taskCleanup();
6976
+ * ```
6977
+ *
6978
+ * This API is experimental. Neither the shape, nor the underlying behavior is stable and can change
6979
+ * in patch versions. We will iterate on the exact API based on the feedback and our understanding
6980
+ * of the problem and solution space.
6981
+ *
6982
+ * @publicApi
6983
+ * @experimental
6984
+ */
6985
+ class ExperimentalPendingTasks {
6986
+ constructor() {
6987
+ this.internalPendingTasks = inject(PendingTasks);
6988
+ }
6989
+ /**
6990
+ * Adds a new task that should block application's stability.
6991
+ * @returns A cleanup function that removes a task when called.
6992
+ */
6993
+ add() {
6994
+ const taskId = this.internalPendingTasks.add();
6995
+ return () => this.internalPendingTasks.remove(taskId);
6996
+ }
6997
+ /** @nocollapse */
6998
+ static { this.ɵprov = ɵɵdefineInjectable({
6999
+ token: ExperimentalPendingTasks,
7000
+ providedIn: 'root',
7001
+ factory: () => new ExperimentalPendingTasks(),
7002
+ }); }
7003
+ }
7004
+
6920
7005
  class EventEmitter_ extends Subject {
6921
7006
  constructor(isAsync = false) {
6922
7007
  super();
6923
7008
  this.destroyRef = undefined;
7009
+ this.pendingTasks = undefined;
6924
7010
  this.__isAsync = isAsync;
6925
- // Attempt to retrieve a `DestroyRef` optionally.
6926
- // For backwards compatibility reasons, this cannot be required
7011
+ // Attempt to retrieve a `DestroyRef` and `PendingTasks` optionally.
7012
+ // For backwards compatibility reasons, this cannot be required.
6927
7013
  if (isInInjectionContext()) {
6928
7014
  this.destroyRef = inject(DestroyRef, { optional: true }) ?? undefined;
7015
+ this.pendingTasks = inject(PendingTasks, { optional: true }) ?? undefined;
6929
7016
  }
6930
7017
  }
6931
7018
  emit(value) {
@@ -6948,12 +7035,12 @@ class EventEmitter_ extends Subject {
6948
7035
  completeFn = observer.complete?.bind(observer);
6949
7036
  }
6950
7037
  if (this.__isAsync) {
6951
- errorFn = _wrapInTimeout(errorFn);
7038
+ errorFn = this.wrapInTimeout(errorFn);
6952
7039
  if (nextFn) {
6953
- nextFn = _wrapInTimeout(nextFn);
7040
+ nextFn = this.wrapInTimeout(nextFn);
6954
7041
  }
6955
7042
  if (completeFn) {
6956
- completeFn = _wrapInTimeout(completeFn);
7043
+ completeFn = this.wrapInTimeout(completeFn);
6957
7044
  }
6958
7045
  }
6959
7046
  const sink = super.subscribe({ next: nextFn, error: errorFn, complete: completeFn });
@@ -6962,11 +7049,17 @@ class EventEmitter_ extends Subject {
6962
7049
  }
6963
7050
  return sink;
6964
7051
  }
6965
- }
6966
- function _wrapInTimeout(fn) {
6967
- return (value) => {
6968
- setTimeout(fn, undefined, value);
6969
- };
7052
+ wrapInTimeout(fn) {
7053
+ return (value) => {
7054
+ const taskId = this.pendingTasks?.add();
7055
+ setTimeout(() => {
7056
+ fn(value);
7057
+ if (taskId !== undefined) {
7058
+ this.pendingTasks?.remove(taskId);
7059
+ }
7060
+ });
7061
+ };
7062
+ }
6970
7063
  }
6971
7064
  /**
6972
7065
  * @publicApi
@@ -12895,6 +12988,59 @@ const REACTIVE_LVIEW_CONSUMER_NODE = {
12895
12988
  this.lView[REACTIVE_TEMPLATE_CONSUMER] = this;
12896
12989
  },
12897
12990
  };
12991
+ /**
12992
+ * Creates a temporary consumer for use with `LView`s that should not have consumers.
12993
+ * If the LView already has a consumer, returns the existing one instead.
12994
+ *
12995
+ * This is necessary because some APIs may cause change detection directly on an LView
12996
+ * that we do not want to have a consumer (Embedded views today). As a result, there
12997
+ * would be no active consumer from running change detection on its host component
12998
+ * and any signals in the LView template would be untracked. Instead, we create
12999
+ * this temporary consumer that marks the first parent that _should_ have a consumer
13000
+ * for refresh. Once change detection runs as part of that refresh, we throw away
13001
+ * this consumer because its signals will then be tracked by the parent's consumer.
13002
+ */
13003
+ function getOrCreateTemporaryConsumer(lView) {
13004
+ const consumer = lView[REACTIVE_TEMPLATE_CONSUMER] ?? Object.create(TEMPORARY_CONSUMER_NODE);
13005
+ consumer.lView = lView;
13006
+ return consumer;
13007
+ }
13008
+ const TEMPORARY_CONSUMER_NODE = {
13009
+ ...REACTIVE_NODE$1,
13010
+ consumerIsAlwaysLive: true,
13011
+ consumerMarkedDirty: (node) => {
13012
+ let parent = getLViewParent(node.lView);
13013
+ while (parent && !viewShouldHaveReactiveConsumer(parent[TVIEW])) {
13014
+ parent = getLViewParent(parent);
13015
+ }
13016
+ if (!parent) {
13017
+ // If we can't find an appropriate parent that should have a consumer, we
13018
+ // don't have a way of appropriately refreshing this LView as part of application synchronization.
13019
+ return;
13020
+ }
13021
+ markViewForRefresh(parent);
13022
+ },
13023
+ consumerOnSignalRead() {
13024
+ this.lView[REACTIVE_TEMPLATE_CONSUMER] = this;
13025
+ },
13026
+ };
13027
+ /**
13028
+ * Indicates if the view should get its own reactive consumer node.
13029
+ *
13030
+ * In the current design, all embedded views share a consumer with the component view. This allows
13031
+ * us to refresh at the component level rather than at a per-view level. In addition, root views get
13032
+ * their own reactive node because root component will have a host view that executes the
13033
+ * component's host bindings. This needs to be tracked in a consumer as well.
13034
+ *
13035
+ * To get a more granular change detection than per-component, all we would just need to update the
13036
+ * condition here so that a given view gets a reactive consumer which can become dirty independently
13037
+ * from its parent component. For example embedded views for signal components could be created with
13038
+ * a new type "SignalEmbeddedView" and the condition here wouldn't even need updating in order to
13039
+ * get granular per-view change detection for signal components.
13040
+ */
13041
+ function viewShouldHaveReactiveConsumer(tView) {
13042
+ return tView.type !== 2 /* TViewType.Embedded */;
13043
+ }
12898
13044
 
12899
13045
  /**
12900
13046
  * The maximum number of times the change detection traversal will rerun before throwing an error.
@@ -12993,11 +13139,29 @@ function refreshView(tView, lView, templateFn, context) {
12993
13139
  // - We might already be in a reactive context if this is an embedded view of the host.
12994
13140
  // - We might be descending into a view that needs a consumer.
12995
13141
  enterView(lView);
13142
+ let returnConsumerToPool = true;
12996
13143
  let prevConsumer = null;
12997
13144
  let currentConsumer = null;
12998
- if (!isInCheckNoChangesPass && viewShouldHaveReactiveConsumer(tView)) {
12999
- currentConsumer = getOrBorrowReactiveLViewConsumer(lView);
13000
- prevConsumer = consumerBeforeComputation$1(currentConsumer);
13145
+ if (!isInCheckNoChangesPass) {
13146
+ if (viewShouldHaveReactiveConsumer(tView)) {
13147
+ currentConsumer = getOrBorrowReactiveLViewConsumer(lView);
13148
+ prevConsumer = consumerBeforeComputation$1(currentConsumer);
13149
+ }
13150
+ else if (getActiveConsumer$1() === null) {
13151
+ // If the current view should not have a reactive consumer but we don't have an active consumer,
13152
+ // we still need to create a temporary consumer to track any signal reads in this template.
13153
+ // This is a rare case that can happen with `viewContainerRef.createEmbeddedView(...).detectChanges()`.
13154
+ // This temporary consumer marks the first parent that _should_ have a consumer for refresh.
13155
+ // Once that refresh happens, the signals will be tracked in the parent consumer and we can destroy
13156
+ // the temporary one.
13157
+ returnConsumerToPool = false;
13158
+ currentConsumer = getOrCreateTemporaryConsumer(lView);
13159
+ prevConsumer = consumerBeforeComputation$1(currentConsumer);
13160
+ }
13161
+ else if (lView[REACTIVE_TEMPLATE_CONSUMER]) {
13162
+ consumerDestroy$1(lView[REACTIVE_TEMPLATE_CONSUMER]);
13163
+ lView[REACTIVE_TEMPLATE_CONSUMER] = null;
13164
+ }
13001
13165
  }
13002
13166
  try {
13003
13167
  resetPreOrderHookFlags(lView);
@@ -13123,28 +13287,13 @@ function refreshView(tView, lView, templateFn, context) {
13123
13287
  finally {
13124
13288
  if (currentConsumer !== null) {
13125
13289
  consumerAfterComputation$1(currentConsumer, prevConsumer);
13126
- maybeReturnReactiveLViewConsumer(currentConsumer);
13290
+ if (returnConsumerToPool) {
13291
+ maybeReturnReactiveLViewConsumer(currentConsumer);
13292
+ }
13127
13293
  }
13128
13294
  leaveView();
13129
13295
  }
13130
13296
  }
13131
- /**
13132
- * Indicates if the view should get its own reactive consumer node.
13133
- *
13134
- * In the current design, all embedded views share a consumer with the component view. This allows
13135
- * us to refresh at the component level rather than at a per-view level. In addition, root views get
13136
- * their own reactive node because root component will have a host view that executes the
13137
- * component's host bindings. This needs to be tracked in a consumer as well.
13138
- *
13139
- * To get a more granular change detection than per-component, all we would just need to update the
13140
- * condition here so that a given view gets a reactive consumer which can become dirty independently
13141
- * from its parent component. For example embedded views for signal components could be created with
13142
- * a new type "SignalEmbeddedView" and the condition here wouldn't even need updating in order to
13143
- * get granular per-view change detection for signal components.
13144
- */
13145
- function viewShouldHaveReactiveConsumer(tView) {
13146
- return tView.type !== 2 /* TViewType.Embedded */;
13147
- }
13148
13297
  /**
13149
13298
  * Goes over embedded views (ones created through ViewContainerRef APIs) and refreshes
13150
13299
  * them by executing an associated template function.
@@ -15881,15 +16030,17 @@ function getNgZone(ngZoneToUse = 'zone.js', options) {
15881
16030
  * manual DOM access, ensuring the best experience for the end users of your application
15882
16031
  * or library.
15883
16032
  *
15884
- * @developerPreview
16033
+ * @deprecated Specify the phase for your callback to run in by passing a spec-object as the first
16034
+ * parameter to `afterRender` or `afterNextRender` insetad of a function.
15885
16035
  */
15886
16036
  var AfterRenderPhase;
15887
16037
  (function (AfterRenderPhase) {
15888
16038
  /**
15889
16039
  * Use `AfterRenderPhase.EarlyRead` for callbacks that only need to **read** from the
15890
16040
  * DOM before a subsequent `AfterRenderPhase.Write` callback, for example to perform
15891
- * custom layout that the browser doesn't natively support. **Never** use this phase
15892
- * for callbacks that can write to the DOM or when `AfterRenderPhase.Read` is adequate.
16041
+ * custom layout that the browser doesn't natively support. Prefer the
16042
+ * `AfterRenderPhase.EarlyRead` phase if reading can wait until after the write phase.
16043
+ * **Never** write to the DOM in this phase.
15893
16044
  *
15894
16045
  * <div class="alert is-important">
15895
16046
  *
@@ -15901,25 +16052,25 @@ var AfterRenderPhase;
15901
16052
  AfterRenderPhase[AfterRenderPhase["EarlyRead"] = 0] = "EarlyRead";
15902
16053
  /**
15903
16054
  * Use `AfterRenderPhase.Write` for callbacks that only **write** to the DOM. **Never**
15904
- * use this phase for callbacks that can read from the DOM.
16055
+ * read from the DOM in this phase.
15905
16056
  */
15906
16057
  AfterRenderPhase[AfterRenderPhase["Write"] = 1] = "Write";
15907
16058
  /**
15908
16059
  * Use `AfterRenderPhase.MixedReadWrite` for callbacks that read from or write to the
15909
- * DOM, that haven't been refactored to use a different phase. **Never** use this phase
15910
- * for callbacks that can use a different phase instead.
16060
+ * DOM, that haven't been refactored to use a different phase. **Never** use this phase if
16061
+ * it is possible to divide the work among the other phases instead.
15911
16062
  *
15912
16063
  * <div class="alert is-critical">
15913
16064
  *
15914
16065
  * Using this value can **significantly** degrade performance.
15915
- * Instead, prefer refactoring into multiple callbacks using a more specific phase.
16066
+ * Instead, prefer dividing work into the appropriate phase callbacks.
15916
16067
  *
15917
16068
  * </div>
15918
16069
  */
15919
16070
  AfterRenderPhase[AfterRenderPhase["MixedReadWrite"] = 2] = "MixedReadWrite";
15920
16071
  /**
15921
16072
  * Use `AfterRenderPhase.Read` for callbacks that only **read** from the DOM. **Never**
15922
- * use this phase for callbacks that can write to the DOM.
16073
+ * write to the DOM in this phase.
15923
16074
  */
15924
16075
  AfterRenderPhase[AfterRenderPhase["Read"] = 3] = "Read";
15925
16076
  })(AfterRenderPhase || (AfterRenderPhase = {}));
@@ -15951,55 +16102,7 @@ function internalAfterNextRender(callback, options) {
15951
16102
  const afterRenderEventManager = injector.get(AfterRenderEventManager);
15952
16103
  afterRenderEventManager.internalCallbacks.push(callback);
15953
16104
  }
15954
- /**
15955
- * Register a callback to be invoked each time the application
15956
- * finishes rendering.
15957
- *
15958
- * <div class="alert is-critical">
15959
- *
15960
- * You should always explicitly specify a non-default [phase](api/core/AfterRenderPhase), or you
15961
- * risk significant performance degradation.
15962
- *
15963
- * </div>
15964
- *
15965
- * Note that the callback will run
15966
- * - in the order it was registered
15967
- * - once per render
15968
- * - on browser platforms only
15969
- *
15970
- * <div class="alert is-important">
15971
- *
15972
- * Components are not guaranteed to be [hydrated](guide/hydration) before the callback runs.
15973
- * You must use caution when directly reading or writing the DOM and layout.
15974
- *
15975
- * </div>
15976
- *
15977
- * @param callback A callback function to register
15978
- *
15979
- * @usageNotes
15980
- *
15981
- * Use `afterRender` to read or write the DOM after each render.
15982
- *
15983
- * ### Example
15984
- * ```ts
15985
- * @Component({
15986
- * selector: 'my-cmp',
15987
- * template: `<span #content>{{ ... }}</span>`,
15988
- * })
15989
- * export class MyComponent {
15990
- * @ViewChild('content') contentRef: ElementRef;
15991
- *
15992
- * constructor() {
15993
- * afterRender(() => {
15994
- * console.log('content height: ' + this.contentRef.nativeElement.scrollHeight);
15995
- * }, {phase: AfterRenderPhase.Read});
15996
- * }
15997
- * }
15998
- * ```
15999
- *
16000
- * @developerPreview
16001
- */
16002
- function afterRender(callback, options) {
16105
+ function afterRender(callbackOrSpec, options) {
16003
16106
  ngDevMode &&
16004
16107
  assertNotInReactiveContext(afterRender, 'Call `afterRender` outside of a reactive context. For example, schedule the render ' +
16005
16108
  'callback inside the component constructor`.');
@@ -16009,101 +16112,80 @@ function afterRender(callback, options) {
16009
16112
  return NOOP_AFTER_RENDER_REF;
16010
16113
  }
16011
16114
  performanceMarkFeature('NgAfterRender');
16012
- const afterRenderEventManager = injector.get(AfterRenderEventManager);
16013
- // Lazily initialize the handler implementation, if necessary. This is so that it can be
16014
- // tree-shaken if `afterRender` and `afterNextRender` aren't used.
16015
- const callbackHandler = (afterRenderEventManager.handler ??=
16016
- new AfterRenderCallbackHandlerImpl());
16017
- const phase = options?.phase ?? AfterRenderPhase.MixedReadWrite;
16018
- const destroy = () => {
16019
- callbackHandler.unregister(instance);
16020
- unregisterFn();
16021
- };
16022
- const unregisterFn = injector.get(DestroyRef).onDestroy(destroy);
16023
- const instance = runInInjectionContext(injector, () => new AfterRenderCallback(phase, callback));
16024
- callbackHandler.register(instance);
16025
- return { destroy };
16115
+ return afterRenderImpl(callbackOrSpec, injector,
16116
+ /* once */ false, options?.phase ?? AfterRenderPhase.MixedReadWrite);
16026
16117
  }
16027
- /**
16028
- * Register a callback to be invoked the next time the application
16029
- * finishes rendering.
16030
- *
16031
- * <div class="alert is-critical">
16032
- *
16033
- * You should always explicitly specify a non-default [phase](api/core/AfterRenderPhase), or you
16034
- * risk significant performance degradation.
16035
- *
16036
- * </div>
16037
- *
16038
- * Note that the callback will run
16039
- * - in the order it was registered
16040
- * - on browser platforms only
16041
- *
16042
- * <div class="alert is-important">
16043
- *
16044
- * Components are not guaranteed to be [hydrated](guide/hydration) before the callback runs.
16045
- * You must use caution when directly reading or writing the DOM and layout.
16046
- *
16047
- * </div>
16048
- *
16049
- * @param callback A callback function to register
16050
- *
16051
- * @usageNotes
16052
- *
16053
- * Use `afterNextRender` to read or write the DOM once,
16054
- * for example to initialize a non-Angular library.
16055
- *
16056
- * ### Example
16057
- * ```ts
16058
- * @Component({
16059
- * selector: 'my-chart-cmp',
16060
- * template: `<div #chart>{{ ... }}</div>`,
16061
- * })
16062
- * export class MyChartCmp {
16063
- * @ViewChild('chart') chartRef: ElementRef;
16064
- * chart: MyChart|null;
16065
- *
16066
- * constructor() {
16067
- * afterNextRender(() => {
16068
- * this.chart = new MyChart(this.chartRef.nativeElement);
16069
- * }, {phase: AfterRenderPhase.Write});
16070
- * }
16071
- * }
16072
- * ```
16073
- *
16074
- * @developerPreview
16075
- */
16076
- function afterNextRender(callback, options) {
16118
+ function afterNextRender(callbackOrSpec, options) {
16077
16119
  !options && assertInInjectionContext(afterNextRender);
16078
16120
  const injector = options?.injector ?? inject(Injector);
16079
16121
  if (!isPlatformBrowser(injector)) {
16080
16122
  return NOOP_AFTER_RENDER_REF;
16081
16123
  }
16082
16124
  performanceMarkFeature('NgAfterNextRender');
16125
+ return afterRenderImpl(callbackOrSpec, injector,
16126
+ /* once */ true, options?.phase ?? AfterRenderPhase.MixedReadWrite);
16127
+ }
16128
+ function getSpec(callbackOrSpec, phase) {
16129
+ if (callbackOrSpec instanceof Function) {
16130
+ switch (phase) {
16131
+ case AfterRenderPhase.EarlyRead:
16132
+ return { earlyRead: callbackOrSpec };
16133
+ case AfterRenderPhase.Write:
16134
+ return { write: callbackOrSpec };
16135
+ case AfterRenderPhase.MixedReadWrite:
16136
+ return { mixedReadWrite: callbackOrSpec };
16137
+ case AfterRenderPhase.Read:
16138
+ return { read: callbackOrSpec };
16139
+ }
16140
+ }
16141
+ return callbackOrSpec;
16142
+ }
16143
+ /**
16144
+ * Shared implementation for `afterRender` and `afterNextRender`.
16145
+ */
16146
+ function afterRenderImpl(callbackOrSpec, injector, once, phase) {
16147
+ const spec = getSpec(callbackOrSpec, phase);
16083
16148
  const afterRenderEventManager = injector.get(AfterRenderEventManager);
16084
16149
  // Lazily initialize the handler implementation, if necessary. This is so that it can be
16085
16150
  // tree-shaken if `afterRender` and `afterNextRender` aren't used.
16086
16151
  const callbackHandler = (afterRenderEventManager.handler ??=
16087
16152
  new AfterRenderCallbackHandlerImpl());
16088
- const phase = options?.phase ?? AfterRenderPhase.MixedReadWrite;
16153
+ const pipelinedArgs = [];
16154
+ const instances = [];
16089
16155
  const destroy = () => {
16090
- callbackHandler.unregister(instance);
16156
+ for (const instance of instances) {
16157
+ callbackHandler.unregister(instance);
16158
+ }
16091
16159
  unregisterFn();
16092
16160
  };
16093
16161
  const unregisterFn = injector.get(DestroyRef).onDestroy(destroy);
16094
- const instance = runInInjectionContext(injector, () => new AfterRenderCallback(phase, () => {
16095
- destroy();
16096
- callback();
16097
- }));
16098
- callbackHandler.register(instance);
16162
+ const registerCallback = (phase, phaseCallback) => {
16163
+ if (!phaseCallback) {
16164
+ return;
16165
+ }
16166
+ const callback = once
16167
+ ? (...args) => {
16168
+ destroy();
16169
+ phaseCallback(...args);
16170
+ }
16171
+ : phaseCallback;
16172
+ const instance = runInInjectionContext(injector, () => new AfterRenderCallback(phase, pipelinedArgs, callback));
16173
+ callbackHandler.register(instance);
16174
+ instances.push(instance);
16175
+ };
16176
+ registerCallback(AfterRenderPhase.EarlyRead, spec.earlyRead);
16177
+ registerCallback(AfterRenderPhase.Write, spec.write);
16178
+ registerCallback(AfterRenderPhase.MixedReadWrite, spec.mixedReadWrite);
16179
+ registerCallback(AfterRenderPhase.Read, spec.read);
16099
16180
  return { destroy };
16100
16181
  }
16101
16182
  /**
16102
16183
  * A wrapper around a function to be used as an after render callback.
16103
16184
  */
16104
16185
  class AfterRenderCallback {
16105
- constructor(phase, callbackFn) {
16186
+ constructor(phase, pipelinedArgs, callbackFn) {
16106
16187
  this.phase = phase;
16188
+ this.pipelinedArgs = pipelinedArgs;
16107
16189
  this.callbackFn = callbackFn;
16108
16190
  this.zone = inject(NgZone);
16109
16191
  this.errorHandler = inject(ErrorHandler, { optional: true });
@@ -16112,7 +16194,9 @@ class AfterRenderCallback {
16112
16194
  }
16113
16195
  invoke() {
16114
16196
  try {
16115
- this.zone.runOutsideAngular(this.callbackFn);
16197
+ const result = this.zone.runOutsideAngular(() => this.callbackFn.apply(null, this.pipelinedArgs));
16198
+ // Clear out the args and add the result which will be passed to the next phase.
16199
+ this.pipelinedArgs.splice(0, this.pipelinedArgs.length, result);
16116
16200
  }
16117
16201
  catch (err) {
16118
16202
  this.errorHandler?.handleError(err);
@@ -16906,7 +16990,7 @@ function createRootComponent(componentView, rootComponentDef, rootDirectives, ho
16906
16990
  function setRootNodeAttributes(hostRenderer, componentDef, hostRNode, rootSelectorOrNode) {
16907
16991
  if (rootSelectorOrNode) {
16908
16992
  // The placeholder will be replaced with the actual version at build time.
16909
- setUpAttributes(hostRenderer, hostRNode, ['ng-version', '18.1.0-next.1']);
16993
+ setUpAttributes(hostRenderer, hostRNode, ['ng-version', '18.1.0-next.2']);
16910
16994
  }
16911
16995
  else {
16912
16996
  // If host element is created as a part of this function call (i.e. `rootSelectorOrNode`
@@ -19048,190 +19132,6 @@ class CachedInjectorService {
19048
19132
  }); }
19049
19133
  }
19050
19134
 
19051
- /**
19052
- * The name of a field that Angular monkey-patches onto a component
19053
- * class to store a function that loads defer-loadable dependencies
19054
- * and applies metadata to a class.
19055
- */
19056
- const ASYNC_COMPONENT_METADATA_FN = '__ngAsyncComponentMetadataFn__';
19057
- /**
19058
- * If a given component has unresolved async metadata - returns a reference
19059
- * to a function that applies component metadata after resolving defer-loadable
19060
- * dependencies. Otherwise - this function returns `null`.
19061
- */
19062
- function getAsyncClassMetadataFn(type) {
19063
- const componentClass = type; // cast to `any`, so that we can read a monkey-patched field
19064
- return componentClass[ASYNC_COMPONENT_METADATA_FN] ?? null;
19065
- }
19066
- /**
19067
- * Handles the process of applying metadata info to a component class in case
19068
- * component template has defer blocks (thus some dependencies became deferrable).
19069
- *
19070
- * @param type Component class where metadata should be added
19071
- * @param dependencyLoaderFn Function that loads dependencies
19072
- * @param metadataSetterFn Function that forms a scope in which the `setClassMetadata` is invoked
19073
- */
19074
- function setClassMetadataAsync(type, dependencyLoaderFn, metadataSetterFn) {
19075
- const componentClass = type; // cast to `any`, so that we can monkey-patch it
19076
- componentClass[ASYNC_COMPONENT_METADATA_FN] = () => Promise.all(dependencyLoaderFn()).then((dependencies) => {
19077
- metadataSetterFn(...dependencies);
19078
- // Metadata is now set, reset field value to indicate that this component
19079
- // can by used/compiled synchronously.
19080
- componentClass[ASYNC_COMPONENT_METADATA_FN] = null;
19081
- return dependencies;
19082
- });
19083
- return componentClass[ASYNC_COMPONENT_METADATA_FN];
19084
- }
19085
- /**
19086
- * Adds decorator, constructor, and property metadata to a given type via static metadata fields
19087
- * on the type.
19088
- *
19089
- * These metadata fields can later be read with Angular's `ReflectionCapabilities` API.
19090
- *
19091
- * Calls to `setClassMetadata` can be guarded by ngDevMode, resulting in the metadata assignments
19092
- * being tree-shaken away during production builds.
19093
- */
19094
- function setClassMetadata(type, decorators, ctorParameters, propDecorators) {
19095
- return noSideEffects(() => {
19096
- const clazz = type;
19097
- if (decorators !== null) {
19098
- if (clazz.hasOwnProperty('decorators') && clazz.decorators !== undefined) {
19099
- clazz.decorators.push(...decorators);
19100
- }
19101
- else {
19102
- clazz.decorators = decorators;
19103
- }
19104
- }
19105
- if (ctorParameters !== null) {
19106
- // Rather than merging, clobber the existing parameters. If other projects exist which
19107
- // use tsickle-style annotations and reflect over them in the same way, this could
19108
- // cause issues, but that is vanishingly unlikely.
19109
- clazz.ctorParameters = ctorParameters;
19110
- }
19111
- if (propDecorators !== null) {
19112
- // The property decorator objects are merged as it is possible different fields have
19113
- // different decorator types. Decorators on individual fields are not merged, as it's
19114
- // also incredibly unlikely that a field will be decorated both with an Angular
19115
- // decorator and a non-Angular decorator that's also been downleveled.
19116
- if (clazz.hasOwnProperty('propDecorators') && clazz.propDecorators !== undefined) {
19117
- clazz.propDecorators = { ...clazz.propDecorators, ...propDecorators };
19118
- }
19119
- else {
19120
- clazz.propDecorators = propDecorators;
19121
- }
19122
- }
19123
- });
19124
- }
19125
-
19126
- /*
19127
- * This file exists to support compilation of @angular/core in Ivy mode.
19128
- *
19129
- * When the Angular compiler processes a compilation unit, it normally writes imports to
19130
- * @angular/core. When compiling the core package itself this strategy isn't usable. Instead, the
19131
- * compiler writes imports to this file.
19132
- *
19133
- * Only a subset of such imports are supported - core is not allowed to declare components or pipes.
19134
- * A check in ngtsc's `R3SymbolsImportRewriter` validates this condition. The rewriter is only used
19135
- * when compiling @angular/core and is responsible for translating an external name (prefixed with
19136
- * ɵ) to the internal symbol name as exported below.
19137
- *
19138
- * The below symbols are used for @Injectable and @NgModule compilation.
19139
- */
19140
- /**
19141
- * The existence of this constant (in this particular file) informs the Angular compiler that the
19142
- * current program is actually @angular/core, which needs to be compiled specially.
19143
- */
19144
- const ITS_JUST_ANGULAR = true;
19145
-
19146
- /**
19147
- * Internal implementation of the pending tasks service.
19148
- */
19149
- class PendingTasks {
19150
- constructor() {
19151
- this.taskId = 0;
19152
- this.pendingTasks = new Set();
19153
- this.hasPendingTasks = new BehaviorSubject(false);
19154
- }
19155
- get _hasPendingTasks() {
19156
- return this.hasPendingTasks.value;
19157
- }
19158
- add() {
19159
- if (!this._hasPendingTasks) {
19160
- this.hasPendingTasks.next(true);
19161
- }
19162
- const taskId = this.taskId++;
19163
- this.pendingTasks.add(taskId);
19164
- return taskId;
19165
- }
19166
- remove(taskId) {
19167
- this.pendingTasks.delete(taskId);
19168
- if (this.pendingTasks.size === 0 && this._hasPendingTasks) {
19169
- this.hasPendingTasks.next(false);
19170
- }
19171
- }
19172
- ngOnDestroy() {
19173
- this.pendingTasks.clear();
19174
- if (this._hasPendingTasks) {
19175
- this.hasPendingTasks.next(false);
19176
- }
19177
- }
19178
- static { this.ɵfac = function PendingTasks_Factory(t) { return new (t || PendingTasks)(); }; }
19179
- static { this.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: PendingTasks, factory: PendingTasks.ɵfac, providedIn: 'root' }); }
19180
- }
19181
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PendingTasks, [{
19182
- type: Injectable,
19183
- args: [{
19184
- providedIn: 'root',
19185
- }]
19186
- }], null, null); })();
19187
- /**
19188
- * Experimental service that keeps track of pending tasks contributing to the stableness of Angular
19189
- * application. While several existing Angular services (ex.: `HttpClient`) will internally manage
19190
- * tasks influencing stability, this API gives control over stability to library and application
19191
- * developers for specific cases not covered by Angular internals.
19192
- *
19193
- * The concept of stability comes into play in several important scenarios:
19194
- * - SSR process needs to wait for the application stability before serializing and sending rendered
19195
- * HTML;
19196
- * - tests might want to delay assertions until the application becomes stable;
19197
- *
19198
- * @usageNotes
19199
- * ```typescript
19200
- * const pendingTasks = inject(ExperimentalPendingTasks);
19201
- * const taskCleanup = pendingTasks.add();
19202
- * // do work that should block application's stability and then:
19203
- * taskCleanup();
19204
- * ```
19205
- *
19206
- * This API is experimental. Neither the shape, nor the underlying behavior is stable and can change
19207
- * in patch versions. We will iterate on the exact API based on the feedback and our understanding
19208
- * of the problem and solution space.
19209
- *
19210
- * @publicApi
19211
- * @experimental
19212
- */
19213
- class ExperimentalPendingTasks {
19214
- constructor() {
19215
- this.internalPendingTasks = inject(PendingTasks);
19216
- }
19217
- /**
19218
- * Adds a new task that should block application's stability.
19219
- * @returns A cleanup function that removes a task when called.
19220
- */
19221
- add() {
19222
- const taskId = this.internalPendingTasks.add();
19223
- return () => this.internalPendingTasks.remove(taskId);
19224
- }
19225
- static { this.ɵfac = function ExperimentalPendingTasks_Factory(t) { return new (t || ExperimentalPendingTasks)(); }; }
19226
- static { this.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: ExperimentalPendingTasks, factory: ExperimentalPendingTasks.ɵfac, providedIn: 'root' }); }
19227
- }
19228
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ExperimentalPendingTasks, [{
19229
- type: Injectable,
19230
- args: [{
19231
- providedIn: 'root',
19232
- }]
19233
- }], null, null); })();
19234
-
19235
19135
  function isIterable(obj) {
19236
19136
  return obj !== null && typeof obj === 'object' && obj[Symbol.iterator] !== undefined;
19237
19137
  }
@@ -28858,6 +28758,81 @@ function maybeUnwrapModuleWithProviders(value) {
28858
28758
  return isModuleWithProviders(value) ? value.ngModule : value;
28859
28759
  }
28860
28760
 
28761
+ /**
28762
+ * The name of a field that Angular monkey-patches onto a component
28763
+ * class to store a function that loads defer-loadable dependencies
28764
+ * and applies metadata to a class.
28765
+ */
28766
+ const ASYNC_COMPONENT_METADATA_FN = '__ngAsyncComponentMetadataFn__';
28767
+ /**
28768
+ * If a given component has unresolved async metadata - returns a reference
28769
+ * to a function that applies component metadata after resolving defer-loadable
28770
+ * dependencies. Otherwise - this function returns `null`.
28771
+ */
28772
+ function getAsyncClassMetadataFn(type) {
28773
+ const componentClass = type; // cast to `any`, so that we can read a monkey-patched field
28774
+ return componentClass[ASYNC_COMPONENT_METADATA_FN] ?? null;
28775
+ }
28776
+ /**
28777
+ * Handles the process of applying metadata info to a component class in case
28778
+ * component template has defer blocks (thus some dependencies became deferrable).
28779
+ *
28780
+ * @param type Component class where metadata should be added
28781
+ * @param dependencyLoaderFn Function that loads dependencies
28782
+ * @param metadataSetterFn Function that forms a scope in which the `setClassMetadata` is invoked
28783
+ */
28784
+ function setClassMetadataAsync(type, dependencyLoaderFn, metadataSetterFn) {
28785
+ const componentClass = type; // cast to `any`, so that we can monkey-patch it
28786
+ componentClass[ASYNC_COMPONENT_METADATA_FN] = () => Promise.all(dependencyLoaderFn()).then((dependencies) => {
28787
+ metadataSetterFn(...dependencies);
28788
+ // Metadata is now set, reset field value to indicate that this component
28789
+ // can by used/compiled synchronously.
28790
+ componentClass[ASYNC_COMPONENT_METADATA_FN] = null;
28791
+ return dependencies;
28792
+ });
28793
+ return componentClass[ASYNC_COMPONENT_METADATA_FN];
28794
+ }
28795
+ /**
28796
+ * Adds decorator, constructor, and property metadata to a given type via static metadata fields
28797
+ * on the type.
28798
+ *
28799
+ * These metadata fields can later be read with Angular's `ReflectionCapabilities` API.
28800
+ *
28801
+ * Calls to `setClassMetadata` can be guarded by ngDevMode, resulting in the metadata assignments
28802
+ * being tree-shaken away during production builds.
28803
+ */
28804
+ function setClassMetadata(type, decorators, ctorParameters, propDecorators) {
28805
+ return noSideEffects(() => {
28806
+ const clazz = type;
28807
+ if (decorators !== null) {
28808
+ if (clazz.hasOwnProperty('decorators') && clazz.decorators !== undefined) {
28809
+ clazz.decorators.push(...decorators);
28810
+ }
28811
+ else {
28812
+ clazz.decorators = decorators;
28813
+ }
28814
+ }
28815
+ if (ctorParameters !== null) {
28816
+ // Rather than merging, clobber the existing parameters. If other projects exist which
28817
+ // use tsickle-style annotations and reflect over them in the same way, this could
28818
+ // cause issues, but that is vanishingly unlikely.
28819
+ clazz.ctorParameters = ctorParameters;
28820
+ }
28821
+ if (propDecorators !== null) {
28822
+ // The property decorator objects are merged as it is possible different fields have
28823
+ // different decorator types. Decorators on individual fields are not merged, as it's
28824
+ // also incredibly unlikely that a field will be decorated both with an Angular
28825
+ // decorator and a non-Angular decorator that's also been downleveled.
28826
+ if (clazz.hasOwnProperty('propDecorators') && clazz.propDecorators !== undefined) {
28827
+ clazz.propDecorators = { ...clazz.propDecorators, ...propDecorators };
28828
+ }
28829
+ else {
28830
+ clazz.propDecorators = propDecorators;
28831
+ }
28832
+ }
28833
+ });
28834
+ }
28835
+
28861
28836
  /**
28862
28837
  * Bindings for pure functions are stored after regular bindings.
28863
28838
  *
@@ -30815,7 +30790,27 @@ class Version {
30815
30790
  /**
30816
30791
  * @publicApi
30817
30792
  */
30818
- const VERSION = new Version('18.1.0-next.1');
30793
+ const VERSION = new Version('18.1.0-next.2');
30794
+
30795
+ /*
30796
+ * This file exists to support compilation of @angular/core in Ivy mode.
30797
+ *
30798
+ * When the Angular compiler processes a compilation unit, it normally writes imports to
30799
+ * @angular/core. When compiling the core package itself this strategy isn't usable. Instead, the
30800
+ * compiler writes imports to this file.
30801
+ *
30802
+ * Only a subset of such imports are supported - core is not allowed to declare components or pipes.
30803
+ * A check in ngtsc's `R3SymbolsImportRewriter` validates this condition. The rewriter is only used
30804
+ * when compiling @angular/core and is responsible for translating an external name (prefixed with
30805
+ * ɵ) to the internal symbol name as exported below.
30806
+ *
30807
+ * The below symbols are used for @Injectable and @NgModule compilation.
30808
+ */
30809
+ /**
30810
+ * The existence of this constant (in this particular file) informs the Angular compiler that the
30811
+ * current program is actually @angular/core, which needs to be compiled specially.
30812
+ */
30813
+ const ITS_JUST_ANGULAR = true;
30819
30814
 
30820
30815
  class Console {
30821
30816
  log(message) {