@angular/core 16.0.0-rc.1 → 16.0.0-rc.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.
package/fesm2022/core.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v16.0.0-rc.1
2
+ * @license Angular v16.0.0-rc.2
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -9963,7 +9963,7 @@ class Version {
9963
9963
  /**
9964
9964
  * @publicApi
9965
9965
  */
9966
- const VERSION = new Version('16.0.0-rc.1');
9966
+ const VERSION = new Version('16.0.0-rc.2');
9967
9967
 
9968
9968
  // This default value is when checking the hierarchy for a token.
9969
9969
  //
@@ -10111,12 +10111,11 @@ function isInSkipHydrationBlock(tNode) {
10111
10111
  return false;
10112
10112
  }
10113
10113
 
10114
- const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
10115
10114
  /**
10116
10115
  * Internal token that specifies whether DOM reuse logic
10117
10116
  * during hydration is enabled.
10118
10117
  */
10119
- const IS_HYDRATION_DOM_REUSE_ENABLED = new InjectionToken(NG_DEV_MODE$1 ? 'IS_HYDRATION_DOM_REUSE_ENABLED' : '');
10118
+ const IS_HYDRATION_DOM_REUSE_ENABLED = new InjectionToken((typeof ngDevMode === 'undefined' || !!ngDevMode) ? 'IS_HYDRATION_DOM_REUSE_ENABLED' : '');
10120
10119
  // By default (in client rendering mode), we remove all the contents
10121
10120
  // of the host element and render an application after that.
10122
10121
  const PRESERVE_HOST_CONTENT_DEFAULT = false;
@@ -10124,7 +10123,7 @@ const PRESERVE_HOST_CONTENT_DEFAULT = false;
10124
10123
  * Internal token that indicates whether host element content should be
10125
10124
  * retained during the bootstrap.
10126
10125
  */
10127
- const PRESERVE_HOST_CONTENT = new InjectionToken(NG_DEV_MODE$1 ? 'PRESERVE_HOST_CONTENT' : '', {
10126
+ const PRESERVE_HOST_CONTENT = new InjectionToken((typeof ngDevMode === 'undefined' || !!ngDevMode) ? 'PRESERVE_HOST_CONTENT' : '', {
10128
10127
  providedIn: 'root',
10129
10128
  factory: () => PRESERVE_HOST_CONTENT_DEFAULT,
10130
10129
  });
@@ -10282,7 +10281,6 @@ function getExpressionChangedErrorDetails(lView, bindingIndex, oldValue, newValu
10282
10281
  return { propName: undefined, oldValue, newValue };
10283
10282
  }
10284
10283
 
10285
- const NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;
10286
10284
  class ReactiveLViewConsumer extends ReactiveNode {
10287
10285
  constructor() {
10288
10286
  super(...arguments);
@@ -10290,11 +10288,12 @@ class ReactiveLViewConsumer extends ReactiveNode {
10290
10288
  this._lView = null;
10291
10289
  }
10292
10290
  set lView(lView) {
10293
- NG_DEV_MODE && assertEqual(this._lView, null, 'Consumer already associated with a view.');
10291
+ (typeof ngDevMode === 'undefined' || ngDevMode) &&
10292
+ assertEqual(this._lView, null, 'Consumer already associated with a view.');
10294
10293
  this._lView = lView;
10295
10294
  }
10296
10295
  onConsumerDependencyMayHaveChanged() {
10297
- NG_DEV_MODE &&
10296
+ (typeof ngDevMode === 'undefined' || ngDevMode) &&
10298
10297
  assertDefined(this._lView, 'Updating a signal during template or host binding execution is not allowed.');
10299
10298
  markViewDirty(this._lView);
10300
10299
  }
@@ -10712,8 +10711,9 @@ function processHostBindingOpCodes(tView, lView) {
10712
10711
  }
10713
10712
  }
10714
10713
  finally {
10715
- lView[REACTIVE_HOST_BINDING_CONSUMER] === null &&
10714
+ if (lView[REACTIVE_HOST_BINDING_CONSUMER] === null) {
10716
10715
  commitLViewConsumerIfHasProducers(lView, REACTIVE_HOST_BINDING_CONSUMER);
10716
+ }
10717
10717
  setSelectedIndex(-1);
10718
10718
  }
10719
10719
  }
@@ -10768,7 +10768,6 @@ function createLView(parentLView, tView, context, flags, host, tHostNode, enviro
10768
10768
  lView[ID] = getUniqueLViewId();
10769
10769
  lView[HYDRATION] = hydrationInfo;
10770
10770
  lView[EMBEDDED_VIEW_INJECTOR] = embeddedViewInjector;
10771
- lView[REACTIVE_TEMPLATE_CONSUMER] = null;
10772
10771
  ngDevMode &&
10773
10772
  assertEqual(tView.type == 2 /* TViewType.Embedded */ ? parentLView !== null : true, true, 'Embedded views must have parentLView');
10774
10773
  lView[DECLARATION_COMPONENT_VIEW] =
@@ -11066,10 +11065,21 @@ function executeTemplate(tView, lView, templateFn, rf, context) {
11066
11065
  }
11067
11066
  const preHookType = isUpdatePhase ? 2 /* ProfilerEvent.TemplateUpdateStart */ : 0 /* ProfilerEvent.TemplateCreateStart */;
11068
11067
  profiler(preHookType, context);
11069
- consumer.runInContext(templateFn, rf, context);
11068
+ if (isUpdatePhase) {
11069
+ consumer.runInContext(templateFn, rf, context);
11070
+ }
11071
+ else {
11072
+ const prevConsumer = setActiveConsumer(null);
11073
+ try {
11074
+ templateFn(rf, context);
11075
+ }
11076
+ finally {
11077
+ setActiveConsumer(prevConsumer);
11078
+ }
11079
+ }
11070
11080
  }
11071
11081
  finally {
11072
- if (lView[REACTIVE_TEMPLATE_CONSUMER] === null) {
11082
+ if (isUpdatePhase && lView[REACTIVE_TEMPLATE_CONSUMER] === null) {
11073
11083
  commitLViewConsumerIfHasProducers(lView, REACTIVE_TEMPLATE_CONSUMER);
11074
11084
  }
11075
11085
  setSelectedIndex(prevSelectedIndex);
@@ -11082,14 +11092,20 @@ function executeTemplate(tView, lView, templateFn, rf, context) {
11082
11092
  //////////////////////////
11083
11093
  function executeContentQueries(tView, tNode, lView) {
11084
11094
  if (isContentQueryHost(tNode)) {
11085
- const start = tNode.directiveStart;
11086
- const end = tNode.directiveEnd;
11087
- for (let directiveIndex = start; directiveIndex < end; directiveIndex++) {
11088
- const def = tView.data[directiveIndex];
11089
- if (def.contentQueries) {
11090
- def.contentQueries(1 /* RenderFlags.Create */, lView[directiveIndex], directiveIndex);
11095
+ const prevConsumer = setActiveConsumer(null);
11096
+ try {
11097
+ const start = tNode.directiveStart;
11098
+ const end = tNode.directiveEnd;
11099
+ for (let directiveIndex = start; directiveIndex < end; directiveIndex++) {
11100
+ const def = tView.data[directiveIndex];
11101
+ if (def.contentQueries) {
11102
+ def.contentQueries(1 /* RenderFlags.Create */, lView[directiveIndex], directiveIndex);
11103
+ }
11091
11104
  }
11092
11105
  }
11106
+ finally {
11107
+ setActiveConsumer(prevConsumer);
11108
+ }
11093
11109
  }
11094
11110
  }
11095
11111
  /**
@@ -11908,17 +11924,11 @@ function setElementAttribute(renderer, element, namespace, tagName, name, value,
11908
11924
  function setInputsFromAttrs(lView, directiveIndex, instance, def, tNode, initialInputData) {
11909
11925
  const initialInputs = initialInputData[directiveIndex];
11910
11926
  if (initialInputs !== null) {
11911
- const setInput = def.setInput;
11912
11927
  for (let i = 0; i < initialInputs.length;) {
11913
11928
  const publicName = initialInputs[i++];
11914
11929
  const privateName = initialInputs[i++];
11915
11930
  const value = initialInputs[i++];
11916
- if (setInput !== null) {
11917
- def.setInput(instance, value, publicName, privateName);
11918
- }
11919
- else {
11920
- instance[privateName] = value;
11921
- }
11931
+ writeToDirectiveInput(def, instance, publicName, privateName, value);
11922
11932
  if (ngDevMode) {
11923
11933
  const nativeElement = getNativeByTNode(tNode, lView);
11924
11934
  setNgReflectProperty(lView, nativeElement, tNode.type, privateName, value);
@@ -11926,6 +11936,20 @@ function setInputsFromAttrs(lView, directiveIndex, instance, def, tNode, initial
11926
11936
  }
11927
11937
  }
11928
11938
  }
11939
+ function writeToDirectiveInput(def, instance, publicName, privateName, value) {
11940
+ const prevConsumer = setActiveConsumer(null);
11941
+ try {
11942
+ if (def.setInput !== null) {
11943
+ def.setInput(instance, value, publicName, privateName);
11944
+ }
11945
+ else {
11946
+ instance[privateName] = value;
11947
+ }
11948
+ }
11949
+ finally {
11950
+ setActiveConsumer(prevConsumer);
11951
+ }
11952
+ }
11929
11953
  /**
11930
11954
  * Generates initialInputData for a node and stores it in the template's static storage
11931
11955
  * so subsequent template invocations don't have to recalculate it.
@@ -12220,7 +12244,13 @@ function checkNoChangesInternal(tView, lView, context, notifyErrorHandler = true
12220
12244
  function executeViewQueryFn(flags, viewQueryFn, component) {
12221
12245
  ngDevMode && assertDefined(viewQueryFn, 'View queries function to execute must be defined.');
12222
12246
  setCurrentQueryIndex(0);
12223
- viewQueryFn(flags, component);
12247
+ const prevConsumer = setActiveConsumer(null);
12248
+ try {
12249
+ viewQueryFn(flags, component);
12250
+ }
12251
+ finally {
12252
+ setActiveConsumer(prevConsumer);
12253
+ }
12224
12254
  }
12225
12255
  ///////////////////////////////
12226
12256
  //// Bindings & interpolations
@@ -12308,12 +12338,7 @@ function setInputsForProperty(tView, lView, inputs, publicName, value) {
12308
12338
  const instance = lView[index];
12309
12339
  ngDevMode && assertIndexInRange(lView, index);
12310
12340
  const def = tView.data[index];
12311
- if (def.setInput !== null) {
12312
- def.setInput(instance, value, publicName, privateName);
12313
- }
12314
- else {
12315
- instance[privateName] = value;
12316
- }
12341
+ writeToDirectiveInput(def, instance, publicName, privateName, value);
12317
12342
  }
12318
12343
  }
12319
12344
  /**
@@ -12371,7 +12396,7 @@ class EffectManager {
12371
12396
  this.queue = new Map();
12372
12397
  }
12373
12398
  create(effectFn, destroyRef, allowSignalWrites) {
12374
- const zone = Zone.current;
12399
+ const zone = (typeof Zone === 'undefined') ? null : Zone.current;
12375
12400
  const watch = new Watch(effectFn, (watch) => {
12376
12401
  if (!this.all.has(watch)) {
12377
12402
  return;
@@ -12399,7 +12424,12 @@ class EffectManager {
12399
12424
  }
12400
12425
  for (const [watch, zone] of this.queue) {
12401
12426
  this.queue.delete(watch);
12402
- zone.run(() => watch.run());
12427
+ if (zone) {
12428
+ zone.run(() => watch.run());
12429
+ }
12430
+ else {
12431
+ watch.run();
12432
+ }
12403
12433
  }
12404
12434
  }
12405
12435
  get isQueueEmpty() {
@@ -12481,6 +12511,21 @@ function collectNativeNodes(tView, lView, tNode, result, isProjection = false) {
12481
12511
  collectNativeNodes(lViewInAContainer[TVIEW], lViewInAContainer, lViewFirstChildTNode, result);
12482
12512
  }
12483
12513
  }
12514
+ // When an LContainer is created, the anchor (comment) node is:
12515
+ // - (1) either reused in case of an ElementContainer (<ng-container>)
12516
+ // - (2) or a new comment node is created
12517
+ // In the first case, the anchor comment node would be added to the final
12518
+ // list by the code above (`result.push(unwrapRNode(lNode))`), but the second
12519
+ // case requires extra handling: the anchor node needs to be added to the
12520
+ // final list manually. See additional information in the `createAnchorNode`
12521
+ // function in the `view_container_ref.ts`.
12522
+ //
12523
+ // In the first case, the same reference would be stored in the `NATIVE`
12524
+ // and `HOST` slots in an LContainer. Otherwise, this is the second case and
12525
+ // we should add an element to the final list.
12526
+ if (lNode[NATIVE] !== lNode[HOST]) {
12527
+ result.push(lNode[NATIVE]);
12528
+ }
12484
12529
  }
12485
12530
  const tNodeType = tNode.type;
12486
12531
  if (tNodeType & 8 /* TNodeType.ElementContainer */) {
@@ -14748,10 +14793,10 @@ function locateRNodeByPath(path, lView) {
14748
14793
  const [referenceNode, ...navigationInstructions] = decompressNodeLocation(path);
14749
14794
  let ref;
14750
14795
  if (referenceNode === REFERENCE_NODE_HOST) {
14751
- ref = lView[0];
14796
+ ref = lView[DECLARATION_COMPONENT_VIEW][HOST];
14752
14797
  }
14753
14798
  else if (referenceNode === REFERENCE_NODE_BODY) {
14754
- ref = ɵɵresolveBody(lView[0]);
14799
+ ref = ɵɵresolveBody(lView[DECLARATION_COMPONENT_VIEW][HOST]);
14755
14800
  }
14756
14801
  else {
14757
14802
  const parentElementId = Number(referenceNode);
@@ -14795,6 +14840,7 @@ function navigateBetween(start, finish) {
14795
14840
  }
14796
14841
  /**
14797
14842
  * Calculates a path between 2 sibling nodes (generates a number of `NextSibling` navigations).
14843
+ * Returns `null` if no such path exists between the given nodes.
14798
14844
  */
14799
14845
  function navigateBetweenSiblings(start, finish) {
14800
14846
  const nav = [];
@@ -14802,7 +14848,10 @@ function navigateBetweenSiblings(start, finish) {
14802
14848
  for (node = start; node != null && node !== finish; node = node.nextSibling) {
14803
14849
  nav.push(NodeNavigationStep.NextSibling);
14804
14850
  }
14805
- return node === null ? [] : nav;
14851
+ // If the `node` becomes `null` or `undefined` at the end, that means that we
14852
+ // didn't find the `end` node, thus return `null` (which would trigger serialization
14853
+ // error to be produced).
14854
+ return node == null ? null : nav;
14806
14855
  }
14807
14856
  /**
14808
14857
  * Calculates a path between 2 nodes in terms of `nextSibling` and `firstChild`
@@ -14825,10 +14874,11 @@ function calcPathForNode(tNode, lView) {
14825
14874
  let parentIndex;
14826
14875
  let parentRNode;
14827
14876
  let referenceNodeName;
14828
- if (parentTNode === null) {
14829
- // No parent TNode - use host element as a reference node.
14877
+ if (parentTNode === null || !(parentTNode.type & 3 /* TNodeType.AnyRNode */)) {
14878
+ // If there is no parent TNode or a parent TNode does not represent an RNode
14879
+ // (i.e. not a DOM node), use component host element as a reference node.
14830
14880
  parentIndex = referenceNodeName = REFERENCE_NODE_HOST;
14831
- parentRNode = lView[HOST];
14881
+ parentRNode = lView[DECLARATION_COMPONENT_VIEW][HOST];
14832
14882
  }
14833
14883
  else {
14834
14884
  // Use parent TNode as a reference node.
@@ -14880,7 +14930,7 @@ function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, t
14880
14930
  const hydrationInfo = lView[HYDRATION];
14881
14931
  if (hydrationInfo) {
14882
14932
  const noOffsetIndex = index - HEADER_OFFSET;
14883
- ssrId = (hydrationInfo && hydrationInfo.data[TEMPLATES]?.[noOffsetIndex]) ?? null;
14933
+ ssrId = hydrationInfo.data[TEMPLATES]?.[noOffsetIndex] ?? null;
14884
14934
  }
14885
14935
  // TODO(pk): refactor getOrCreateTNode to have the "create" only version
14886
14936
  const tNode = getOrCreateTNode(tView, index, 4 /* TNodeType.Container */, tagName || null, getConstant(tViewConsts, attrsIndex));
@@ -16997,7 +17047,7 @@ function styleStringParser(keyValueArray, text) {
16997
17047
  * @codeGenApi
16998
17048
  */
16999
17049
  function ɵɵclassMap(classes) {
17000
- checkStylingMap(keyValueArraySet, classStringParser, classes, true);
17050
+ checkStylingMap(classKeyValueArraySet, classStringParser, classes, true);
17001
17051
  }
17002
17052
  /**
17003
17053
  * Parse text as class and add values to KeyValueArray.
@@ -17439,6 +17489,26 @@ function toStylingKeyValueArray(keyValueArraySet, stringParser, value) {
17439
17489
  function styleKeyValueArraySet(keyValueArray, key, value) {
17440
17490
  keyValueArraySet(keyValueArray, key, unwrapSafeValue(value));
17441
17491
  }
17492
+ /**
17493
+ * Class-binding-specific function for setting the `value` for a `key`.
17494
+ *
17495
+ * See: `keyValueArraySet` for details
17496
+ *
17497
+ * @param keyValueArray KeyValueArray to add to.
17498
+ * @param key Style key to add.
17499
+ * @param value The value to set.
17500
+ */
17501
+ function classKeyValueArraySet(keyValueArray, key, value) {
17502
+ // We use `classList.add` to eventually add the CSS classes to the DOM node. Any value passed into
17503
+ // `add` is stringified and added to the `class` attribute, e.g. even null, undefined or numbers
17504
+ // will be added. Stringify the key here so that our internal data structure matches the value in
17505
+ // the DOM. The only exceptions are empty strings and strings that contain spaces for which
17506
+ // the browser throws an error. We ignore such values, because the error is somewhat cryptic.
17507
+ const stringKey = String(key);
17508
+ if (stringKey !== '' && !stringKey.includes(' ')) {
17509
+ keyValueArraySet(keyValueArray, stringKey, value);
17510
+ }
17511
+ }
17442
17512
  /**
17443
17513
  * Update map based styling.
17444
17514
  *
@@ -20168,11 +20238,10 @@ const MARKER = `�`;
20168
20238
  const SUBTEMPLATE_REGEXP = /�\/?\*(\d+:\d+)�/gi;
20169
20239
  const PH_REGEXP = /�(\/?[#*]\d+):?\d*�/gi;
20170
20240
  /**
20171
- * Angular Dart introduced &ngsp; as a placeholder for non-removable space, see:
20172
- * https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart#L25-L32
20173
- * In Angular Dart &ngsp; is converted to the 0xE500 PUA (Private Use Areas) unicode character
20174
- * and later on replaced by a space. We are re-implementing the same idea here, since translations
20175
- * might contain this special character.
20241
+ * Angular uses the special entity &ngsp; as a placeholder for non-removable space.
20242
+ * It's replaced by the 0xE500 PUA (Private Use Areas) unicode character and later on replaced by a
20243
+ * space.
20244
+ * We are re-implementing the same idea since translations might contain this special character.
20176
20245
  */
20177
20246
  const NGSP_UNICODE_REGEXP = /\uE500/g;
20178
20247
  function replaceNgsp(value) {
@@ -29509,7 +29578,10 @@ function serializeLView(lView, context) {
29509
29578
  // live DOM has exactly the same state as it was before serialization.
29510
29579
  if (tNode.type & 1 /* TNodeType.Text */) {
29511
29580
  const rNode = unwrapRNode(lView[i]);
29512
- if (rNode.textContent?.replace(/\s/gm, '') === '') {
29581
+ // Collect this node as required special annotation only when its
29582
+ // contents is empty. Otherwise, such text node would be present on
29583
+ // the client after server-side rendering and no special handling needed.
29584
+ if (rNode.textContent === '') {
29513
29585
  context.corruptedTextNodes.set(rNode, "ngetn" /* TextNodeMarker.EmptyNode */);
29514
29586
  }
29515
29587
  else if (rNode.nextSibling?.nodeType === Node.TEXT_NODE) {
@@ -29750,7 +29822,7 @@ function withDomHydration() {
29750
29822
  // hydration annotations. Otherwise, keep hydration disabled.
29751
29823
  const transferState = inject(TransferState, { optional: true });
29752
29824
  isEnabled = !!transferState?.get(NGH_DATA_KEY, null);
29753
- if (!isEnabled) {
29825
+ if (!isEnabled && (typeof ngDevMode !== 'undefined' && ngDevMode)) {
29754
29826
  const console = inject(Console);
29755
29827
  const message = formatRuntimeError(-505 /* RuntimeErrorCode.MISSING_HYDRATION_ANNOTATIONS */, 'Angular hydration was requested on the client, but there was no ' +
29756
29828
  'serialized information present in the server response, ' +