@angular/core 16.0.0 → 16.1.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/esm2022/src/application_ref.mjs +60 -55
  2. package/esm2022/src/compiler/compiler_facade_interface.mjs +1 -1
  3. package/esm2022/src/di/injectable.mjs +2 -1
  4. package/esm2022/src/di/metadata.mjs +6 -5
  5. package/esm2022/src/di/metadata_attr.mjs +2 -1
  6. package/esm2022/src/errors.mjs +1 -1
  7. package/esm2022/src/hydration/annotate.mjs +1 -1
  8. package/esm2022/src/hydration/api.mjs +2 -2
  9. package/esm2022/src/hydration/skip_hydration.mjs +12 -1
  10. package/esm2022/src/hydration/utils.mjs +9 -3
  11. package/esm2022/src/linker/element_ref.mjs +1 -1
  12. package/esm2022/src/linker/template_ref.mjs +6 -3
  13. package/esm2022/src/linker/view_container_ref.mjs +16 -6
  14. package/esm2022/src/metadata/di.mjs +5 -4
  15. package/esm2022/src/metadata/directives.mjs +7 -7
  16. package/esm2022/src/metadata/ng_module.mjs +2 -1
  17. package/esm2022/src/render/api.mjs +1 -1
  18. package/esm2022/src/render3/component.mjs +4 -1
  19. package/esm2022/src/render3/component_ref.mjs +14 -3
  20. package/esm2022/src/render3/definition.mjs +9 -3
  21. package/esm2022/src/render3/di.mjs +2 -2
  22. package/esm2022/src/render3/hooks.mjs +3 -3
  23. package/esm2022/src/render3/instructions/change_detection.mjs +37 -53
  24. package/esm2022/src/render3/instructions/element_validation.mjs +2 -2
  25. package/esm2022/src/render3/instructions/shared.mjs +15 -4
  26. package/esm2022/src/render3/interfaces/definition.mjs +1 -1
  27. package/esm2022/src/render3/interfaces/document.mjs +6 -4
  28. package/esm2022/src/render3/interfaces/node.mjs +1 -1
  29. package/esm2022/src/render3/interfaces/public_definitions.mjs +1 -1
  30. package/esm2022/src/render3/interfaces/view.mjs +1 -1
  31. package/esm2022/src/render3/jit/directive.mjs +2 -1
  32. package/esm2022/src/render3/node_manipulation.mjs +7 -1
  33. package/esm2022/src/transfer_state.mjs +8 -7
  34. package/esm2022/src/util/assert.mjs +2 -5
  35. package/esm2022/src/version.mjs +1 -1
  36. package/esm2022/testing/src/logger.mjs +3 -3
  37. package/esm2022/testing/src/test_bed.mjs +4 -4
  38. package/fesm2022/core.mjs +252 -192
  39. package/fesm2022/core.mjs.map +1 -1
  40. package/fesm2022/rxjs-interop.mjs +1 -1
  41. package/fesm2022/rxjs-interop.mjs.map +1 -1
  42. package/fesm2022/testing.mjs +179 -130
  43. package/fesm2022/testing.mjs.map +1 -1
  44. package/index.d.ts +54 -35
  45. package/package.json +1 -1
  46. package/rxjs-interop/index.d.ts +1 -1
  47. package/schematics/migrations/guard-and-resolve-interfaces/bundle.js +13 -13
  48. package/schematics/migrations/remove-module-id/bundle.js +14 -14
  49. package/schematics/ng-generate/standalone-migration/bundle.js +614 -411
  50. package/schematics/ng-generate/standalone-migration/bundle.js.map +4 -4
  51. package/testing/index.d.ts +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v16.0.0
2
+ * @license Angular v16.1.0-next.0
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -941,10 +941,7 @@ function throwError(msg, actual, expected, comparison) {
941
941
  (comparison == null ? '' : ` [Expected=> ${expected} ${comparison} ${actual} <=Actual]`));
942
942
  }
943
943
  function assertDomNode(node) {
944
- // If we're in a worker, `Node` will not be defined.
945
- if (!(typeof Node !== 'undefined' && node instanceof Node) &&
946
- !(typeof node === 'object' && node != null &&
947
- node.constructor.name === 'WebWorkerRenderNode')) {
944
+ if (!(node instanceof Node)) {
948
945
  throwError(`The provided value must be an instance of a DOM Node but got ${stringify(node)}`);
949
946
  }
950
947
  }
@@ -2042,6 +2039,7 @@ function formatError(text, obj, injectorErrorName, source = null) {
2042
2039
  /**
2043
2040
  * Inject decorator and metadata.
2044
2041
  *
2042
+ * @Annotation
2045
2043
  * @publicApi
2046
2044
  */
2047
2045
  const Inject = attachInjectFlag(
@@ -2051,7 +2049,7 @@ makeParamDecorator('Inject', (token) => ({ token })), -1 /* DecoratorFlags.Injec
2051
2049
  /**
2052
2050
  * Optional decorator and metadata.
2053
2051
  *
2054
-
2052
+ * @Annotation
2055
2053
  * @publicApi
2056
2054
  */
2057
2055
  const Optional =
@@ -2061,7 +2059,7 @@ attachInjectFlag(makeParamDecorator('Optional'), 8 /* InternalInjectFlags.Option
2061
2059
  /**
2062
2060
  * Self decorator and metadata.
2063
2061
  *
2064
-
2062
+ * @Annotation
2065
2063
  * @publicApi
2066
2064
  */
2067
2065
  const Self =
@@ -2071,7 +2069,7 @@ attachInjectFlag(makeParamDecorator('Self'), 2 /* InternalInjectFlags.Self */);
2071
2069
  /**
2072
2070
  * `SkipSelf` decorator and metadata.
2073
2071
  *
2074
-
2072
+ * @Annotation
2075
2073
  * @publicApi
2076
2074
  */
2077
2075
  const SkipSelf =
@@ -2081,7 +2079,7 @@ attachInjectFlag(makeParamDecorator('SkipSelf'), 4 /* InternalInjectFlags.SkipSe
2081
2079
  /**
2082
2080
  * Host decorator and metadata.
2083
2081
  *
2084
-
2082
+ * @Annotation
2085
2083
  * @publicApi
2086
2084
  */
2087
2085
  const Host =
@@ -2873,6 +2871,7 @@ function ɵɵdefineComponent(componentDefinition) {
2873
2871
  pipeDefs: null,
2874
2872
  dependencies: baseDef.standalone && componentDefinition.dependencies || null,
2875
2873
  getStandaloneInjector: null,
2874
+ signals: componentDefinition.signals ?? false,
2876
2875
  data: componentDefinition.data || {},
2877
2876
  encapsulation: componentDefinition.encapsulation || ViewEncapsulation.Emulated,
2878
2877
  styles: componentDefinition.styles || EMPTY_ARRAY,
@@ -3115,6 +3114,7 @@ function getNgDirectiveDef(directiveDefinition) {
3115
3114
  declaredInputs,
3116
3115
  exportAs: directiveDefinition.exportAs || null,
3117
3116
  standalone: directiveDefinition.standalone === true,
3117
+ signals: directiveDefinition.signals === true,
3118
3118
  selectors: directiveDefinition.selectors || EMPTY_ARRAY,
3119
3119
  viewQuery: directiveDefinition.viewQuery || null,
3120
3120
  features: directiveDefinition.features || null,
@@ -3156,7 +3156,7 @@ function getComponentId(componentDef) {
3156
3156
  // Example:
3157
3157
  // https://github.com/angular/components/blob/d9f82c8f95309e77a6d82fd574c65871e91354c2/src/material/core/option/option.ts#L248
3158
3158
  // https://github.com/angular/components/blob/285f46dc2b4c5b127d356cb7c4714b221f03ce50/src/material/legacy-core/option/option.ts#L32
3159
- const hashSelectors = [
3159
+ const hashSelectors = JSON.stringify([
3160
3160
  componentDef.selectors,
3161
3161
  componentDef.ngContentSelectors,
3162
3162
  componentDef.hostVars,
@@ -3166,12 +3166,16 @@ function getComponentId(componentDef) {
3166
3166
  componentDef.decls,
3167
3167
  componentDef.encapsulation,
3168
3168
  componentDef.standalone,
3169
+ componentDef.signals,
3170
+ componentDef.exportAs,
3171
+ componentDef.inputs,
3172
+ componentDef.outputs,
3169
3173
  // We cannot use 'componentDef.type.name' as the name of the symbol will change and will not
3170
3174
  // match in the server and browser bundles.
3171
3175
  Object.getOwnPropertyNames(componentDef.type.prototype),
3172
3176
  !!componentDef.contentQueries,
3173
3177
  !!componentDef.viewQuery,
3174
- ].join('|');
3178
+ ]);
3175
3179
  for (const char of hashSelectors) {
3176
3180
  hash = Math.imul(31, hash) + char.charCodeAt(0) << 0;
3177
3181
  }
@@ -5004,7 +5008,7 @@ function incrementInitPhaseFlags(lView, initPhase) {
5004
5008
  assertNotEqual(initPhase, 3 /* InitPhaseState.InitPhaseCompleted */, 'Init hooks phase should not be incremented after all init hooks have been run.');
5005
5009
  let flags = lView[FLAGS];
5006
5010
  if ((flags & 3 /* LViewFlags.InitPhaseStateMask */) === initPhase) {
5007
- flags &= 4095 /* LViewFlags.IndexWithinInitPhaseReset */;
5011
+ flags &= 8191 /* LViewFlags.IndexWithinInitPhaseReset */;
5008
5012
  flags += 1 /* LViewFlags.InitPhaseStateIncrementer */;
5009
5013
  lView[FLAGS] = flags;
5010
5014
  }
@@ -5085,12 +5089,12 @@ function callHook(currentView, initPhase, arr, i) {
5085
5089
  const directiveIndex = isInitHook ? -arr[i] : arr[i];
5086
5090
  const directive = currentView[directiveIndex];
5087
5091
  if (isInitHook) {
5088
- const indexWithintInitPhase = currentView[FLAGS] >> 12 /* LViewFlags.IndexWithinInitPhaseShift */;
5092
+ const indexWithintInitPhase = currentView[FLAGS] >> 13 /* LViewFlags.IndexWithinInitPhaseShift */;
5089
5093
  // The init phase state must be always checked here as it may have been recursively updated.
5090
5094
  if (indexWithintInitPhase <
5091
5095
  (currentView[PREORDER_HOOK_FLAGS] >> 16 /* PreOrderHookFlags.NumberOfInitHooksCalledShift */) &&
5092
5096
  (currentView[FLAGS] & 3 /* LViewFlags.InitPhaseStateMask */) === initPhase) {
5093
- currentView[FLAGS] += 4096 /* LViewFlags.IndexWithinInitPhaseIncrementer */;
5097
+ currentView[FLAGS] += 8192 /* LViewFlags.IndexWithinInitPhaseIncrementer */;
5094
5098
  callHookInternal(directive, hook);
5095
5099
  }
5096
5100
  }
@@ -5991,7 +5995,7 @@ function ɵɵgetInheritedFactory(type) {
5991
5995
  // (no Angular decorator on the superclass) or there is no constructor at all
5992
5996
  // in the inheritance chain. Since the two cases cannot be distinguished, the
5993
5997
  // latter has to be assumed.
5994
- return t => new t();
5998
+ return (t) => new t();
5995
5999
  });
5996
6000
  }
5997
6001
  function getFactoryOf(type) {
@@ -6083,6 +6087,7 @@ function ɵɵinjectAttribute(attrNameToInject) {
6083
6087
  /**
6084
6088
  * Attribute decorator and metadata.
6085
6089
  *
6090
+ * @Annotation
6086
6091
  * @publicApi
6087
6092
  */
6088
6093
  const Attribute = makeParamDecorator('Attribute', (attributeName) => ({ attributeName, __NG_ELEMENT_ID__: () => ɵɵinjectAttribute(attributeName) }));
@@ -6383,7 +6388,7 @@ function isPropertyValid(element, propName, tagName, schemas) {
6383
6388
  if (schemas === null)
6384
6389
  return true;
6385
6390
  // The property is considered valid if the element matches the schema, it exists on the element,
6386
- // or it is synthetic, and we are in a browser context (web worker nodes should be skipped).
6391
+ // or it is synthetic.
6387
6392
  if (matchingSchemas(schemas, tagName) || propName in element || isAnimationProp(propName)) {
6388
6393
  return true;
6389
6394
  }
@@ -6525,6 +6530,59 @@ function matchingSchemas(schemas, tagName) {
6525
6530
  return false;
6526
6531
  }
6527
6532
 
6533
+ /**
6534
+ * The name of an attribute that can be added to the hydration boundary node
6535
+ * (component host node) to disable hydration for the content within that boundary.
6536
+ */
6537
+ const SKIP_HYDRATION_ATTR_NAME = 'ngSkipHydration';
6538
+ /**
6539
+ * Helper function to check if a given node has the 'ngSkipHydration' attribute
6540
+ */
6541
+ function hasNgSkipHydrationAttr(tNode) {
6542
+ const SKIP_HYDRATION_ATTR_NAME_LOWER_CASE = SKIP_HYDRATION_ATTR_NAME.toLowerCase();
6543
+ const attrs = tNode.mergedAttrs;
6544
+ if (attrs === null)
6545
+ return false;
6546
+ // only ever look at the attribute name and skip the values
6547
+ for (let i = 0; i < attrs.length; i += 2) {
6548
+ const value = attrs[i];
6549
+ // This is a marker, which means that the static attributes section is over,
6550
+ // so we can exit early.
6551
+ if (typeof value === 'number')
6552
+ return false;
6553
+ if (typeof value === 'string' && value.toLowerCase() === SKIP_HYDRATION_ATTR_NAME_LOWER_CASE) {
6554
+ return true;
6555
+ }
6556
+ }
6557
+ return false;
6558
+ }
6559
+ /**
6560
+ * Checks whether a TNode has a flag to indicate that it's a part of
6561
+ * a skip hydration block.
6562
+ */
6563
+ function hasInSkipHydrationBlockFlag(tNode) {
6564
+ return (tNode.flags & 128 /* TNodeFlags.inSkipHydrationBlock */) === 128 /* TNodeFlags.inSkipHydrationBlock */;
6565
+ }
6566
+ /**
6567
+ * Helper function that determines if a given node is within a skip hydration block
6568
+ * by navigating up the TNode tree to see if any parent nodes have skip hydration
6569
+ * attribute.
6570
+ *
6571
+ * TODO(akushnir): this function should contain the logic of `hasInSkipHydrationBlockFlag`,
6572
+ * there is no need to traverse parent nodes when we have a TNode flag (which would also
6573
+ * make this lookup O(1)).
6574
+ */
6575
+ function isInSkipHydrationBlock(tNode) {
6576
+ let currentTNode = tNode.parent;
6577
+ while (currentTNode) {
6578
+ if (hasNgSkipHydrationAttr(currentTNode)) {
6579
+ return true;
6580
+ }
6581
+ currentTNode = currentTNode.parent;
6582
+ }
6583
+ return false;
6584
+ }
6585
+
6528
6586
  /**
6529
6587
  * Flags for renderer-specific style modifiers.
6530
6588
  * @publicApi
@@ -7824,6 +7882,11 @@ function applyProjectionRecursive(renderer, action, lView, tProjectionNode, pare
7824
7882
  else {
7825
7883
  let nodeToProject = nodeToProjectOrRNodes;
7826
7884
  const projectedComponentLView = componentLView[PARENT];
7885
+ // If a parent <ng-content> is located within a skip hydration block,
7886
+ // annotate an actual node that is being projected with the same flag too.
7887
+ if (hasInSkipHydrationBlockFlag(tProjectionNode)) {
7888
+ nodeToProject.flags |= 128 /* TNodeFlags.inSkipHydrationBlock */;
7889
+ }
7827
7890
  applyNodes(renderer, action, nodeToProject, projectedComponentLView, parentRElement, beforeNode, true);
7828
7891
  }
7829
7892
  }
@@ -8124,7 +8187,7 @@ function ɵɵvalidateIframeAttribute(attrValue, tagName, attrName) {
8124
8187
  * When running ivy outside of a browser environment, it is necessary to call `setDocument()` to
8125
8188
  * tell ivy what the global `document` is.
8126
8189
  *
8127
- * Angular does this for us in each of the standard platforms (`Browser`, `Server`, and `WebWorker`)
8190
+ * Angular does this for us in each of the standard platforms (`Browser` and `Server`)
8128
8191
  * by calling `setDocument()` when providing the `DOCUMENT` token.
8129
8192
  */
8130
8193
  let DOCUMENT = undefined;
@@ -8151,12 +8214,13 @@ function getDocument() {
8151
8214
  else if (typeof document !== 'undefined') {
8152
8215
  return document;
8153
8216
  }
8217
+ throw new RuntimeError(210 /* RuntimeErrorCode.MISSING_DOCUMENT */, (typeof ngDevMode === 'undefined' || ngDevMode) &&
8218
+ `The document object is not available in this context. Make sure the DOCUMENT injection token is provided.`);
8154
8219
  // No "document" can be found. This should only happen if we are running ivy outside Angular and
8155
8220
  // the current platform is not a browser. Since this is not a supported scenario at the moment
8156
8221
  // this should not happen in Angular apps.
8157
8222
  // Once we support running ivy outside of Angular we will need to publish `setDocument()` as a
8158
- // public API. Meanwhile we just return `undefined` and let the application fail.
8159
- return undefined;
8223
+ // public API.
8160
8224
  }
8161
8225
 
8162
8226
  /**
@@ -9862,7 +9926,9 @@ function makeStateKey(key) {
9862
9926
  }
9863
9927
  function initTransferState() {
9864
9928
  const transferState = new TransferState();
9865
- transferState.store = retrieveTransferredState(getDocument(), inject$1(APP_ID));
9929
+ if (inject$1(PLATFORM_ID) === 'browser') {
9930
+ transferState.store = retrieveTransferredState(getDocument(), inject$1(APP_ID));
9931
+ }
9866
9932
  return transferState;
9867
9933
  }
9868
9934
  /**
@@ -9951,17 +10017,16 @@ function retrieveTransferredState(doc, appId) {
9951
10017
  // Locate the script tag with the JSON data transferred from the server.
9952
10018
  // The id of the script tag is set to the Angular appId + 'state'.
9953
10019
  const script = doc.getElementById(appId + '-state');
9954
- let initialState = {};
9955
- if (script && script.textContent) {
10020
+ if (script?.textContent) {
9956
10021
  try {
9957
10022
  // Avoid using any here as it triggers lint errors in google3 (any is not allowed).
9958
- initialState = JSON.parse(unescapeTransferStateContent(script.textContent));
10023
+ return JSON.parse(unescapeTransferStateContent(script.textContent));
9959
10024
  }
9960
10025
  catch (e) {
9961
10026
  console.warn('Exception while restoring TransferState for app ' + appId, e);
9962
10027
  }
9963
10028
  }
9964
- return initialState;
10029
+ return {};
9965
10030
  }
9966
10031
 
9967
10032
  /** Encodes that the node lookup should start from the host node of this component. */
@@ -10080,6 +10145,12 @@ function getComponentLViewForHydration(viewRef) {
10080
10145
  if (isRootView(lView)) {
10081
10146
  lView = lView[HEADER_OFFSET];
10082
10147
  }
10148
+ // If a `ViewContainerRef` was injected in a component class, this resulted
10149
+ // in an LContainer creation at that location. In this case, the component
10150
+ // LView is in the LContainer's `HOST` slot.
10151
+ if (isLContainer(lView)) {
10152
+ lView = lView[HOST];
10153
+ }
10083
10154
  return lView;
10084
10155
  }
10085
10156
  function getTextNodeContent(node) {
@@ -10375,7 +10446,7 @@ class Version {
10375
10446
  /**
10376
10447
  * @publicApi
10377
10448
  */
10378
- const VERSION = new Version('16.0.0');
10449
+ const VERSION = new Version('16.1.0-next.0');
10379
10450
 
10380
10451
  // This default value is when checking the hierarchy for a token.
10381
10452
  //
@@ -10481,48 +10552,6 @@ class ErrorHandler {
10481
10552
  }
10482
10553
  }
10483
10554
 
10484
- /**
10485
- * The name of an attribute that can be added to the hydration boundary node
10486
- * (component host node) to disable hydration for the content within that boundary.
10487
- */
10488
- const SKIP_HYDRATION_ATTR_NAME = 'ngSkipHydration';
10489
- /**
10490
- * Helper function to check if a given node has the 'ngSkipHydration' attribute
10491
- */
10492
- function hasNgSkipHydrationAttr(tNode) {
10493
- const SKIP_HYDRATION_ATTR_NAME_LOWER_CASE = SKIP_HYDRATION_ATTR_NAME.toLowerCase();
10494
- const attrs = tNode.mergedAttrs;
10495
- if (attrs === null)
10496
- return false;
10497
- // only ever look at the attribute name and skip the values
10498
- for (let i = 0; i < attrs.length; i += 2) {
10499
- const value = attrs[i];
10500
- // This is a marker, which means that the static attributes section is over,
10501
- // so we can exit early.
10502
- if (typeof value === 'number')
10503
- return false;
10504
- if (typeof value === 'string' && value.toLowerCase() === SKIP_HYDRATION_ATTR_NAME_LOWER_CASE) {
10505
- return true;
10506
- }
10507
- }
10508
- return false;
10509
- }
10510
- /**
10511
- * Helper function that determines if a given node is within a skip hydration block
10512
- * by navigating up the TNode tree to see if any parent nodes have skip hydration
10513
- * attribute.
10514
- */
10515
- function isInSkipHydrationBlock(tNode) {
10516
- let currentTNode = tNode.parent;
10517
- while (currentTNode) {
10518
- if (hasNgSkipHydrationAttr(currentTNode)) {
10519
- return true;
10520
- }
10521
- currentTNode = currentTNode.parent;
10522
- }
10523
- return false;
10524
- }
10525
-
10526
10555
  /**
10527
10556
  * Internal token that specifies whether DOM reuse logic
10528
10557
  * during hydration is enabled.
@@ -10912,6 +10941,7 @@ function getInjectableMetadata(type, srcMeta) {
10912
10941
  /**
10913
10942
  * Injectable decorator and metadata.
10914
10943
  *
10944
+ * @Annotation
10915
10945
  * @publicApi
10916
10946
  */
10917
10947
  const Injectable = makeDecorator('Injectable', undefined, undefined, undefined, (type, meta) => compileInjectable(type, meta));
@@ -11468,6 +11498,10 @@ function createTNode(tView, tParent, type, index, value, attrs) {
11468
11498
  ngDevMode && ngDevMode.tNode++;
11469
11499
  ngDevMode && tParent && assertTNodeForTView(tParent, tView);
11470
11500
  let injectorIndex = tParent ? tParent.injectorIndex : -1;
11501
+ let flags = 0;
11502
+ if (isInSkipHydrationBlock$1()) {
11503
+ flags |= 128 /* TNodeFlags.inSkipHydrationBlock */;
11504
+ }
11471
11505
  const tNode = {
11472
11506
  type,
11473
11507
  index,
@@ -11478,7 +11512,7 @@ function createTNode(tView, tParent, type, index, value, attrs) {
11478
11512
  directiveStylingLast: -1,
11479
11513
  componentOffset: -1,
11480
11514
  propertyBindings: null,
11481
- flags: 0,
11515
+ flags,
11482
11516
  providerIndexes: 0,
11483
11517
  value: value,
11484
11518
  attrs: attrs,
@@ -12030,7 +12064,14 @@ function addComponentLogic(lView, hostTNode, def) {
12030
12064
  // Only component views should be added to the view tree directly. Embedded views are
12031
12065
  // accessed through their containers because they may be removed / re-added later.
12032
12066
  const rendererFactory = lView[ENVIRONMENT].rendererFactory;
12033
- const componentView = addToViewTree(lView, createLView(lView, tView, null, def.onPush ? 64 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, native, hostTNode, null, rendererFactory.createRenderer(native, def), null, null, null));
12067
+ let lViewFlags = 16 /* LViewFlags.CheckAlways */;
12068
+ if (def.signals) {
12069
+ lViewFlags = 4096 /* LViewFlags.SignalView */;
12070
+ }
12071
+ else if (def.onPush) {
12072
+ lViewFlags = 64 /* LViewFlags.Dirty */;
12073
+ }
12074
+ const componentView = addToViewTree(lView, createLView(lView, tView, null, lViewFlags, native, hostTNode, null, rendererFactory.createRenderer(native, def), null, null, null));
12034
12075
  // Component view will always be created before any injected LContainers,
12035
12076
  // so this is a regular element, wrap it with the component view
12036
12077
  lView[hostTNode.index] = componentView;
@@ -12740,7 +12781,7 @@ function refreshView(tView, lView, templateFn, context) {
12740
12781
  // insertion points. This is needed to avoid the situation where the template is defined in this
12741
12782
  // `LView` but its declaration appears after the insertion component.
12742
12783
  markTransplantedViewsForRefresh(lView);
12743
- refreshEmbeddedViews(lView);
12784
+ detectChangesInEmbeddedViews(lView, 2 /* ChangeDetectionMode.BugToForceRefreshAndIgnoreViewFlags */);
12744
12785
  // Content query results must be refreshed before content hooks are called.
12745
12786
  if (tView.contentQueries !== null) {
12746
12787
  refreshContentQueries(tView, lView);
@@ -12766,7 +12807,7 @@ function refreshView(tView, lView, templateFn, context) {
12766
12807
  // Refresh child component views.
12767
12808
  const components = tView.components;
12768
12809
  if (components !== null) {
12769
- refreshChildComponents(lView, components);
12810
+ detectChangesInChildComponents(lView, components, 0 /* ChangeDetectionMode.Global */);
12770
12811
  }
12771
12812
  // View queries must execute after refreshing child components because a template in this view
12772
12813
  // could be inserted in a child component. If the view query executes before child component
@@ -12820,15 +12861,11 @@ function refreshView(tView, lView, templateFn, context) {
12820
12861
  * Goes over embedded views (ones created through ViewContainerRef APIs) and refreshes
12821
12862
  * them by executing an associated template function.
12822
12863
  */
12823
- function refreshEmbeddedViews(lView) {
12864
+ function detectChangesInEmbeddedViews(lView, mode) {
12824
12865
  for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
12825
12866
  for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
12826
12867
  const embeddedLView = lContainer[i];
12827
- const embeddedTView = embeddedLView[TVIEW];
12828
- ngDevMode && assertDefined(embeddedTView, 'TView must be allocated');
12829
- if (viewAttachedToChangeDetector(embeddedLView)) {
12830
- refreshView(embeddedTView, embeddedLView, embeddedTView.template, embeddedLView[CONTEXT]);
12831
- }
12868
+ detectChangesInView(embeddedLView, mode);
12832
12869
  }
12833
12870
  }
12834
12871
  }
@@ -12852,65 +12889,53 @@ function markTransplantedViewsForRefresh(lView) {
12852
12889
  }
12853
12890
  }
12854
12891
  /**
12855
- * Refreshes components by entering the component view and processing its bindings, queries, etc.
12892
+ * Detects changes in a component by entering the component view and processing its bindings,
12893
+ * queries, etc. if it is CheckAlways, OnPush and Dirty, etc.
12856
12894
  *
12857
12895
  * @param componentHostIdx Element index in LView[] (adjusted for HEADER_OFFSET)
12858
12896
  */
12859
- function refreshComponent(hostLView, componentHostIdx) {
12897
+ function detectChangesInComponent(hostLView, componentHostIdx, mode) {
12860
12898
  ngDevMode && assertEqual(isCreationMode(hostLView), false, 'Should be run in update mode');
12861
12899
  const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
12862
- // Only attached components that are CheckAlways or OnPush and dirty should be refreshed
12863
- if (viewAttachedToChangeDetector(componentView)) {
12864
- const tView = componentView[TVIEW];
12865
- if (componentView[FLAGS] & (16 /* LViewFlags.CheckAlways */ | 64 /* LViewFlags.Dirty */)) {
12866
- refreshView(tView, componentView, tView.template, componentView[CONTEXT]);
12867
- }
12868
- else if (componentView[DESCENDANT_VIEWS_TO_REFRESH] > 0) {
12869
- // Only attached components that are CheckAlways or OnPush and dirty should be refreshed
12870
- refreshContainsDirtyView(componentView);
12871
- }
12872
- }
12900
+ detectChangesInView(componentView, mode);
12873
12901
  }
12874
12902
  /**
12875
- * Refreshes all transplanted views marked with `LViewFlags.RefreshTransplantedView` that are
12876
- * children or descendants of the given lView.
12903
+ * Visits a view as part of change detection traversal.
12904
+ *
12905
+ * - If the view is detached, no additional traversal happens.
12906
+ *
12907
+ * The view is refreshed if:
12908
+ * - If the view is CheckAlways or Dirty and ChangeDetectionMode is `Global`
12909
+ * - If the view has the `RefreshTransplantedView` flag
12910
+ *
12911
+ * The view is not refreshed, but descendants are traversed in `ChangeDetectionMode.Targeted` if the
12912
+ * view has a non-zero TRANSPLANTED_VIEWS_TO_REFRESH counter.
12877
12913
  *
12878
- * @param lView The lView which contains descendant transplanted views that need to be refreshed.
12879
12914
  */
12880
- function refreshContainsDirtyView(lView) {
12881
- for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
12882
- for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
12883
- const embeddedLView = lContainer[i];
12884
- if (viewAttachedToChangeDetector(embeddedLView)) {
12885
- if (embeddedLView[FLAGS] & 1024 /* LViewFlags.RefreshView */) {
12886
- const embeddedTView = embeddedLView[TVIEW];
12887
- ngDevMode && assertDefined(embeddedTView, 'TView must be allocated');
12888
- refreshView(embeddedTView, embeddedLView, embeddedTView.template, embeddedLView[CONTEXT]);
12889
- }
12890
- else if (embeddedLView[DESCENDANT_VIEWS_TO_REFRESH] > 0) {
12891
- refreshContainsDirtyView(embeddedLView);
12892
- }
12893
- }
12894
- }
12915
+ function detectChangesInView(lView, mode) {
12916
+ if (!viewAttachedToChangeDetector(lView)) {
12917
+ return;
12895
12918
  }
12896
12919
  const tView = lView[TVIEW];
12897
- // Refresh child component views.
12898
- const components = tView.components;
12899
- if (components !== null) {
12900
- for (let i = 0; i < components.length; i++) {
12901
- const componentView = getComponentLViewByIndex(components[i], lView);
12902
- // Only attached components that are CheckAlways or OnPush and dirty should be refreshed
12903
- if (viewAttachedToChangeDetector(componentView) &&
12904
- componentView[DESCENDANT_VIEWS_TO_REFRESH] > 0) {
12905
- refreshContainsDirtyView(componentView);
12906
- }
12920
+ if ((lView[FLAGS] & (16 /* LViewFlags.CheckAlways */ | 64 /* LViewFlags.Dirty */) &&
12921
+ mode === 0 /* ChangeDetectionMode.Global */) ||
12922
+ lView[FLAGS] & 1024 /* LViewFlags.RefreshView */ ||
12923
+ mode === 2 /* ChangeDetectionMode.BugToForceRefreshAndIgnoreViewFlags */) {
12924
+ refreshView(tView, lView, tView.template, lView[CONTEXT]);
12925
+ }
12926
+ else if (lView[DESCENDANT_VIEWS_TO_REFRESH] > 0) {
12927
+ detectChangesInEmbeddedViews(lView, 1 /* ChangeDetectionMode.Targeted */);
12928
+ const tView = lView[TVIEW];
12929
+ const components = tView.components;
12930
+ if (components !== null) {
12931
+ detectChangesInChildComponents(lView, components, 1 /* ChangeDetectionMode.Targeted */);
12907
12932
  }
12908
12933
  }
12909
12934
  }
12910
12935
  /** Refreshes child components in the current view (update mode). */
12911
- function refreshChildComponents(hostLView, components) {
12936
+ function detectChangesInChildComponents(hostLView, components, mode) {
12912
12937
  for (let i = 0; i < components.length; i++) {
12913
- refreshComponent(hostLView, components[i]);
12938
+ detectChangesInComponent(hostLView, components[i], mode);
12914
12939
  }
12915
12940
  }
12916
12941
 
@@ -13310,8 +13335,12 @@ class ComponentFactory extends ComponentFactory$1 {
13310
13335
  const hostRNode = rootSelectorOrNode ?
13311
13336
  locateHostElement(hostRenderer, rootSelectorOrNode, this.componentDef.encapsulation, rootViewInjector) :
13312
13337
  createElementNode(hostRenderer, elementName, getNamespace(elementName));
13313
- const rootFlags = this.componentDef.onPush ? 64 /* LViewFlags.Dirty */ | 512 /* LViewFlags.IsRoot */ :
13338
+ // Signal components use the granular "RefreshView" for change detection
13339
+ const signalFlags = (4096 /* LViewFlags.SignalView */ | 512 /* LViewFlags.IsRoot */);
13340
+ // Non-signal components use the traditional "CheckAlways or OnPush/Dirty" change detection
13341
+ const nonSignalFlags = this.componentDef.onPush ? 64 /* LViewFlags.Dirty */ | 512 /* LViewFlags.IsRoot */ :
13314
13342
  16 /* LViewFlags.CheckAlways */ | 512 /* LViewFlags.IsRoot */;
13343
+ const rootFlags = this.componentDef.signals ? signalFlags : nonSignalFlags;
13315
13344
  // Create the root view. Uses empty TView and ContentTemplate.
13316
13345
  const rootTView = createTView(0 /* TViewType.Root */, null, null, 1, 0, null, null, null, null, null, null);
13317
13346
  const rootLView = createLView(null, rootTView, null, rootFlags, null, null, environment, hostRenderer, rootViewInjector, null, null);
@@ -13454,7 +13483,14 @@ function createRootComponentView(tNode, hostRNode, rootComponentDef, rootDirecti
13454
13483
  hydrationInfo = retrieveHydrationInfo(hostRNode, rootView[INJECTOR$1]);
13455
13484
  }
13456
13485
  const viewRenderer = environment.rendererFactory.createRenderer(hostRNode, rootComponentDef);
13457
- const componentView = createLView(rootView, getOrCreateComponentTView(rootComponentDef), null, rootComponentDef.onPush ? 64 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, rootView[tNode.index], tNode, environment, viewRenderer, null, null, hydrationInfo);
13486
+ let lViewFlags = 16 /* LViewFlags.CheckAlways */;
13487
+ if (rootComponentDef.signals) {
13488
+ lViewFlags = 4096 /* LViewFlags.SignalView */;
13489
+ }
13490
+ else if (rootComponentDef.onPush) {
13491
+ lViewFlags = 64 /* LViewFlags.Dirty */;
13492
+ }
13493
+ const componentView = createLView(rootView, getOrCreateComponentTView(rootComponentDef), null, lViewFlags, rootView[tNode.index], tNode, environment, viewRenderer, null, null, hydrationInfo);
13458
13494
  if (tView.firstCreatePass) {
13459
13495
  markAsComponentHost(tView, tNode, rootDirectives.length - 1);
13460
13496
  }
@@ -23191,8 +23227,11 @@ const R3TemplateRef = class TemplateRef extends ViewEngineTemplateRef {
23191
23227
  * @internal
23192
23228
  */
23193
23229
  createEmbeddedViewImpl(context, injector, hydrationInfo) {
23230
+ // Embedded views follow the change detection strategy of the view they're declared in.
23231
+ const isSignalView = this._declarationLView[FLAGS] & 4096 /* LViewFlags.SignalView */;
23232
+ const viewFlags = isSignalView ? 4096 /* LViewFlags.SignalView */ : 16 /* LViewFlags.CheckAlways */;
23194
23233
  const embeddedTView = this._declarationTContainer.tView;
23195
- const embeddedLView = createLView(this._declarationLView, embeddedTView, context, 16 /* LViewFlags.CheckAlways */, null, embeddedTView.declTNode, null, null, null, injector || null, hydrationInfo || null);
23234
+ const embeddedLView = createLView(this._declarationLView, embeddedTView, context, viewFlags, null, embeddedTView.declTNode, null, null, null, injector || null, hydrationInfo || null);
23196
23235
  const declarationLContainer = this._declarationLView[this._declarationTContainer.index];
23197
23236
  ngDevMode && assertLContainer(declarationLContainer);
23198
23237
  embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;
@@ -23466,7 +23505,11 @@ const R3ViewContainerRef = class ViewContainerRef extends VE_ViewContainerRef {
23466
23505
  }
23467
23506
  const hydrationInfo = findMatchingDehydratedView(this._lContainer, templateRef.ssrId);
23468
23507
  const viewRef = templateRef.createEmbeddedViewImpl(context || {}, injector, hydrationInfo);
23469
- this.insertImpl(viewRef, index, !!hydrationInfo);
23508
+ // If there is a matching dehydrated view, but the host TNode is located in the skip
23509
+ // hydration block, this means that the content was detached (as a part of the skip
23510
+ // hydration logic) and it needs to be appended into the DOM.
23511
+ const skipDomInsertion = !!hydrationInfo && !hasInSkipHydrationBlockFlag(this._hostTNode);
23512
+ this.insertImpl(viewRef, index, skipDomInsertion);
23470
23513
  return viewRef;
23471
23514
  }
23472
23515
  createComponent(componentFactoryOrType, indexOrOptions, injector, projectableNodes, environmentInjector) {
@@ -23540,7 +23583,11 @@ const R3ViewContainerRef = class ViewContainerRef extends VE_ViewContainerRef {
23540
23583
  const dehydratedView = findMatchingDehydratedView(this._lContainer, componentDef?.id ?? null);
23541
23584
  const rNode = dehydratedView?.firstChild ?? null;
23542
23585
  const componentRef = componentFactory.create(contextInjector, projectableNodes, rNode, environmentInjector);
23543
- this.insertImpl(componentRef.hostView, index, !!dehydratedView);
23586
+ // If there is a matching dehydrated view, but the host TNode is located in the skip
23587
+ // hydration block, this means that the content was detached (as a part of the skip
23588
+ // hydration logic) and it needs to be appended into the DOM.
23589
+ const skipDomInsertion = !!dehydratedView && !hasInSkipHydrationBlockFlag(this._hostTNode);
23590
+ this.insertImpl(componentRef.hostView, index, skipDomInsertion);
23544
23591
  return componentRef;
23545
23592
  }
23546
23593
  insert(viewRef, index) {
@@ -23714,8 +23761,10 @@ function locateOrCreateAnchorNode(lContainer, hostLView, hostTNode, slotValue) {
23714
23761
  return;
23715
23762
  const hydrationInfo = hostLView[HYDRATION];
23716
23763
  const noOffsetIndex = hostTNode.index - HEADER_OFFSET;
23717
- const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock(hostTNode) ||
23718
- isDisconnectedNode(hydrationInfo, noOffsetIndex);
23764
+ // TODO(akushnir): this should really be a single condition, refactor the code
23765
+ // to use `hasInSkipHydrationBlockFlag` logic inside `isInSkipHydrationBlock`.
23766
+ const skipHydration = isInSkipHydrationBlock(hostTNode) || hasInSkipHydrationBlockFlag(hostTNode);
23767
+ const isNodeCreationMode = !hydrationInfo || skipHydration || isDisconnectedNode(hydrationInfo, noOffsetIndex);
23719
23768
  // Regular creation mode.
23720
23769
  if (isNodeCreationMode) {
23721
23770
  return createAnchorNode(lContainer, hostLView, hostTNode, slotValue);
@@ -26127,7 +26176,7 @@ class TestBedImpl {
26127
26176
  }
26128
26177
  configureCompiler(config) {
26129
26178
  if (config.useJit != null) {
26130
- throw new Error('the Render3 compiler JiT mode is not configurable !');
26179
+ throw new Error('JIT compiler is not configurable via TestBed APIs.');
26131
26180
  }
26132
26181
  if (config.providers !== undefined) {
26133
26182
  this.compiler.setCompilerProviders(config.providers);
@@ -26135,7 +26184,7 @@ class TestBedImpl {
26135
26184
  return this;
26136
26185
  }
26137
26186
  configureTestingModule(moduleDef) {
26138
- this.assertNotInstantiated('R3TestBed.configureTestingModule', 'configure the test module');
26187
+ this.assertNotInstantiated('TestBed.configureTestingModule', 'configure the test module');
26139
26188
  // Trigger module scoping queue flush before executing other TestBed operations in a test.
26140
26189
  // This is needed for the first test invocation to ensure that globally declared modules have
26141
26190
  // their components scoped properly. See the `checkGlobalCompilationFinished` function
@@ -26189,7 +26238,7 @@ class TestBedImpl {
26189
26238
  return this;
26190
26239
  }
26191
26240
  overrideTemplateUsingTestingModule(component, template) {
26192
- this.assertNotInstantiated('R3TestBed.overrideTemplateUsingTestingModule', 'Cannot override template when the test module has already been instantiated');
26241
+ this.assertNotInstantiated('TestBed.overrideTemplateUsingTestingModule', 'Cannot override template when the test module has already been instantiated');
26193
26242
  this.compiler.overrideTemplateUsingTestingModule(component, template);
26194
26243
  return this;
26195
26244
  }