@angular/core 15.0.0-next.2 → 15.0.0-next.3

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/esm2020/src/debug/debug_node.mjs +1 -1
  2. package/esm2020/src/render3/component_ref.mjs +2 -2
  3. package/esm2020/src/render3/context_discovery.mjs +12 -9
  4. package/esm2020/src/render3/definition.mjs +3 -2
  5. package/esm2020/src/render3/features/host_directives_feature.mjs +36 -13
  6. package/esm2020/src/render3/instructions/element.mjs +1 -1
  7. package/esm2020/src/render3/instructions/listener.mjs +2 -4
  8. package/esm2020/src/render3/instructions/lview_debug.mjs +9 -9
  9. package/esm2020/src/render3/instructions/projection.mjs +1 -1
  10. package/esm2020/src/render3/instructions/shared.mjs +60 -25
  11. package/esm2020/src/render3/instructions/styling.mjs +2 -2
  12. package/esm2020/src/render3/interfaces/definition.mjs +1 -1
  13. package/esm2020/src/render3/interfaces/node.mjs +3 -3
  14. package/esm2020/src/render3/interfaces/type_checks.mjs +3 -3
  15. package/esm2020/src/render3/jit/directive.mjs +7 -2
  16. package/esm2020/src/render3/node_manipulation.mjs +6 -5
  17. package/esm2020/src/render3/node_manipulation_i18n.mjs +2 -2
  18. package/esm2020/src/version.mjs +1 -1
  19. package/esm2020/testing/src/logger.mjs +3 -3
  20. package/esm2020/testing/src/ng_zone_mock.mjs +3 -3
  21. package/fesm2015/core.mjs +137 -73
  22. package/fesm2015/core.mjs.map +1 -1
  23. package/fesm2015/testing.mjs +129 -71
  24. package/fesm2015/testing.mjs.map +1 -1
  25. package/fesm2020/core.mjs +136 -72
  26. package/fesm2020/core.mjs.map +1 -1
  27. package/fesm2020/testing.mjs +129 -70
  28. package/fesm2020/testing.mjs.map +1 -1
  29. package/index.d.ts +41 -29
  30. package/package.json +1 -1
  31. package/testing/index.d.ts +1 -1
package/fesm2015/core.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v15.0.0-next.2
2
+ * @license Angular v15.0.0-next.3
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -931,7 +931,8 @@ function ɵɵdefineComponent(componentDefinition) {
931
931
  setInput: null,
932
932
  schemas: componentDefinition.schemas || null,
933
933
  tView: null,
934
- applyHostDirectives: null,
934
+ findHostDirectiveDefs: null,
935
+ hostDirectives: null,
935
936
  };
936
937
  const dependencies = componentDefinition.dependencies;
937
938
  const feature = componentDefinition.features;
@@ -1265,10 +1266,10 @@ function isLContainer(value) {
1265
1266
  return Array.isArray(value) && value[TYPE] === true;
1266
1267
  }
1267
1268
  function isContentQueryHost(tNode) {
1268
- return (tNode.flags & 8 /* TNodeFlags.hasContentQuery */) !== 0;
1269
+ return (tNode.flags & 4 /* TNodeFlags.hasContentQuery */) !== 0;
1269
1270
  }
1270
1271
  function isComponentHost(tNode) {
1271
- return (tNode.flags & 2 /* TNodeFlags.isComponentHost */) === 2 /* TNodeFlags.isComponentHost */;
1272
+ return tNode.componentOffset > -1;
1272
1273
  }
1273
1274
  function isDirectiveHost(tNode) {
1274
1275
  return (tNode.flags & 1 /* TNodeFlags.isDirectiveHost */) === 1 /* TNodeFlags.isDirectiveHost */;
@@ -2678,7 +2679,7 @@ const unusedValueExportToPlacateAjd$5 = 1;
2678
2679
  * @param tNode
2679
2680
  */
2680
2681
  function hasClassInput(tNode) {
2681
- return (tNode.flags & 16 /* TNodeFlags.hasClassInput */) !== 0;
2682
+ return (tNode.flags & 8 /* TNodeFlags.hasClassInput */) !== 0;
2682
2683
  }
2683
2684
  /**
2684
2685
  * Returns `true` if the `TNode` has a directive which has `@Input()` for `style` binding.
@@ -2702,7 +2703,7 @@ function hasClassInput(tNode) {
2702
2703
  * @param tNode
2703
2704
  */
2704
2705
  function hasStyleInput(tNode) {
2705
- return (tNode.flags & 32 /* TNodeFlags.hasStyleInput */) !== 0;
2706
+ return (tNode.flags & 16 /* TNodeFlags.hasStyleInput */) !== 0;
2706
2707
  }
2707
2708
 
2708
2709
  /**
@@ -7235,7 +7236,7 @@ class Version {
7235
7236
  /**
7236
7237
  * @publicApi
7237
7238
  */
7238
- const VERSION = new Version('15.0.0-next.2');
7239
+ const VERSION = new Version('15.0.0-next.3');
7239
7240
 
7240
7241
  /**
7241
7242
  * @license
@@ -8055,18 +8056,21 @@ function findViaDirective(lView, directiveInstance) {
8055
8056
  */
8056
8057
  function getDirectivesAtNodeIndex(nodeIndex, lView, includeComponents) {
8057
8058
  const tNode = lView[TVIEW].data[nodeIndex];
8058
- let directiveStartIndex = tNode.directiveStart;
8059
- if (directiveStartIndex == 0)
8059
+ if (tNode.directiveStart === 0)
8060
8060
  return EMPTY_ARRAY;
8061
- const directiveEndIndex = tNode.directiveEnd;
8062
- if (!includeComponents && tNode.flags & 2 /* TNodeFlags.isComponentHost */)
8063
- directiveStartIndex++;
8064
- return lView.slice(directiveStartIndex, directiveEndIndex);
8061
+ const results = [];
8062
+ for (let i = tNode.directiveStart; i < tNode.directiveEnd; i++) {
8063
+ const directiveInstance = lView[i];
8064
+ if (!isComponentInstance(directiveInstance) || includeComponents) {
8065
+ results.push(directiveInstance);
8066
+ }
8067
+ }
8068
+ return results;
8065
8069
  }
8066
8070
  function getComponentAtNodeIndex(nodeIndex, lView) {
8067
8071
  const tNode = lView[TVIEW].data[nodeIndex];
8068
- let directiveStartIndex = tNode.directiveStart;
8069
- return tNode.flags & 2 /* TNodeFlags.isComponentHost */ ? lView[directiveStartIndex] : null;
8072
+ const { directiveStart, componentOffset } = tNode;
8073
+ return componentOffset > -1 ? lView[directiveStart + componentOffset] : null;
8070
8074
  }
8071
8075
  /**
8072
8076
  * Returns a map of local references (local reference name => element or directive instance) that
@@ -8869,9 +8873,10 @@ function getClosestRElement(tView, tNode, lView) {
8869
8873
  }
8870
8874
  else {
8871
8875
  ngDevMode && assertTNodeType(parentTNode, 3 /* TNodeType.AnyRNode */ | 4 /* TNodeType.Container */);
8872
- if (parentTNode.flags & 2 /* TNodeFlags.isComponentHost */) {
8876
+ const { componentOffset } = parentTNode;
8877
+ if (componentOffset > -1) {
8873
8878
  ngDevMode && assertTNodeForLView(parentTNode, lView);
8874
- const encapsulation = tView.data[parentTNode.directiveStart].encapsulation;
8879
+ const { encapsulation } = tView.data[parentTNode.directiveStart + componentOffset];
8875
8880
  // We've got a parent which is an element in the current view. We just need to verify if the
8876
8881
  // parent element is not a component. Component's content nodes are not inserted immediately
8877
8882
  // because they will be projected, and so doing insert at this point would be wasteful.
@@ -9104,10 +9109,10 @@ function applyNodes(renderer, action, tNode, lView, parentRElement, beforeNode,
9104
9109
  if (isProjection) {
9105
9110
  if (action === 0 /* WalkTNodeTreeAction.Create */) {
9106
9111
  rawSlotValue && attachPatchData(unwrapRNode(rawSlotValue), lView);
9107
- tNode.flags |= 4 /* TNodeFlags.isProjected */;
9112
+ tNode.flags |= 2 /* TNodeFlags.isProjected */;
9108
9113
  }
9109
9114
  }
9110
- if ((tNode.flags & 64 /* TNodeFlags.isDetached */) !== 64 /* TNodeFlags.isDetached */) {
9115
+ if ((tNode.flags & 32 /* TNodeFlags.isDetached */) !== 32 /* TNodeFlags.isDetached */) {
9111
9116
  if (tNodeType & 8 /* TNodeType.ElementContainer */) {
9112
9117
  applyNodes(renderer, action, tNode.child, lView, parentRElement, beforeNode, false);
9113
9118
  applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
@@ -11162,6 +11167,7 @@ class TNode {
11162
11167
  index, //
11163
11168
  insertBeforeIndex, //
11164
11169
  injectorIndex, //
11170
+ componentOffset, //
11165
11171
  directiveStart, //
11166
11172
  directiveEnd, //
11167
11173
  directiveStylingLast, //
@@ -11194,6 +11200,7 @@ class TNode {
11194
11200
  this.index = index;
11195
11201
  this.insertBeforeIndex = insertBeforeIndex;
11196
11202
  this.injectorIndex = injectorIndex;
11203
+ this.componentOffset = componentOffset;
11197
11204
  this.directiveStart = directiveStart;
11198
11205
  this.directiveEnd = directiveEnd;
11199
11206
  this.directiveStylingLast = directiveStylingLast;
@@ -11271,21 +11278,19 @@ class TNode {
11271
11278
  }
11272
11279
  get flags_() {
11273
11280
  const flags = [];
11274
- if (this.flags & 16 /* TNodeFlags.hasClassInput */)
11281
+ if (this.flags & 8 /* TNodeFlags.hasClassInput */)
11275
11282
  flags.push('TNodeFlags.hasClassInput');
11276
- if (this.flags & 8 /* TNodeFlags.hasContentQuery */)
11283
+ if (this.flags & 4 /* TNodeFlags.hasContentQuery */)
11277
11284
  flags.push('TNodeFlags.hasContentQuery');
11278
- if (this.flags & 32 /* TNodeFlags.hasStyleInput */)
11285
+ if (this.flags & 16 /* TNodeFlags.hasStyleInput */)
11279
11286
  flags.push('TNodeFlags.hasStyleInput');
11280
- if (this.flags & 128 /* TNodeFlags.hasHostBindings */)
11287
+ if (this.flags & 64 /* TNodeFlags.hasHostBindings */)
11281
11288
  flags.push('TNodeFlags.hasHostBindings');
11282
- if (this.flags & 2 /* TNodeFlags.isComponentHost */)
11283
- flags.push('TNodeFlags.isComponentHost');
11284
11289
  if (this.flags & 1 /* TNodeFlags.isDirectiveHost */)
11285
11290
  flags.push('TNodeFlags.isDirectiveHost');
11286
- if (this.flags & 64 /* TNodeFlags.isDetached */)
11291
+ if (this.flags & 32 /* TNodeFlags.isDetached */)
11287
11292
  flags.push('TNodeFlags.isDetached');
11288
- if (this.flags & 4 /* TNodeFlags.isProjected */)
11293
+ if (this.flags & 2 /* TNodeFlags.isProjected */)
11289
11294
  flags.push('TNodeFlags.isProjected');
11290
11295
  return flags.join('|');
11291
11296
  }
@@ -11795,7 +11800,7 @@ function getOrCreateTNode(tView, index, type, name, attrs) {
11795
11800
  // See `TNodeType.Placeholder` and `LFrame.inI18n` for more context.
11796
11801
  // If the `TNode` was not pre-declared than it means it was not mentioned which means it was
11797
11802
  // removed, so we mark it as detached.
11798
- tNode.flags |= 64 /* TNodeFlags.isDetached */;
11803
+ tNode.flags |= 32 /* TNodeFlags.isDetached */;
11799
11804
  }
11800
11805
  }
11801
11806
  else if (tNode.type & 64 /* TNodeType.Placeholder */) {
@@ -12099,7 +12104,7 @@ function createDirectivesInstances(tView, lView, tNode) {
12099
12104
  if (!getBindingsEnabled())
12100
12105
  return;
12101
12106
  instantiateAllDirectives(tView, lView, tNode, getNativeByTNode(tNode, lView));
12102
- if ((tNode.flags & 128 /* TNodeFlags.hasHostBindings */) === 128 /* TNodeFlags.hasHostBindings */) {
12107
+ if ((tNode.flags & 64 /* TNodeFlags.hasHostBindings */) === 64 /* TNodeFlags.hasHostBindings */) {
12103
12108
  invokeDirectivesHostBindings(tView, lView, tNode);
12104
12109
  }
12105
12110
  }
@@ -12299,6 +12304,7 @@ function createTNode(tView, tParent, type, index, value, attrs) {
12299
12304
  index, // index: number
12300
12305
  null, // insertBeforeIndex: null|-1|number|number[]
12301
12306
  injectorIndex, // injectorIndex: number
12307
+ -1, // componentOffset: number
12302
12308
  -1, // directiveStart: number
12303
12309
  -1, // directiveEnd: number
12304
12310
  -1, // directiveStylingLast: number
@@ -12334,6 +12340,7 @@ function createTNode(tView, tParent, type, index, value, attrs) {
12334
12340
  directiveStart: -1,
12335
12341
  directiveEnd: -1,
12336
12342
  directiveStylingLast: -1,
12343
+ componentOffset: -1,
12337
12344
  propertyBindings: null,
12338
12345
  flags: 0,
12339
12346
  providerIndexes: 0,
@@ -12397,24 +12404,23 @@ function initializeInputAndOutputAliases(tView, tNode) {
12397
12404
  let outputsStore = null;
12398
12405
  for (let i = start; i < end; i++) {
12399
12406
  const directiveDef = tViewData[i];
12400
- const directiveInputs = directiveDef.inputs;
12407
+ inputsStore = generatePropertyAliases(directiveDef.inputs, i, inputsStore);
12408
+ outputsStore = generatePropertyAliases(directiveDef.outputs, i, outputsStore);
12401
12409
  // Do not use unbound attributes as inputs to structural directives, since structural
12402
12410
  // directive inputs can only be set using microsyntax (e.g. `<div *dir="exp">`).
12403
12411
  // TODO(FW-1930): microsyntax expressions may also contain unbound/static attributes, which
12404
12412
  // should be set for inline templates.
12405
- const initialInputs = (tNodeAttrs !== null && !isInlineTemplate(tNode)) ?
12406
- generateInitialInputs(directiveInputs, tNodeAttrs) :
12413
+ const initialInputs = (inputsStore !== null && tNodeAttrs !== null && !isInlineTemplate(tNode)) ?
12414
+ generateInitialInputs(inputsStore, i, tNodeAttrs) :
12407
12415
  null;
12408
12416
  inputsFromAttrs.push(initialInputs);
12409
- inputsStore = generatePropertyAliases(directiveInputs, i, inputsStore);
12410
- outputsStore = generatePropertyAliases(directiveDef.outputs, i, outputsStore);
12411
12417
  }
12412
12418
  if (inputsStore !== null) {
12413
12419
  if (inputsStore.hasOwnProperty('class')) {
12414
- tNode.flags |= 16 /* TNodeFlags.hasClassInput */;
12420
+ tNode.flags |= 8 /* TNodeFlags.hasClassInput */;
12415
12421
  }
12416
12422
  if (inputsStore.hasOwnProperty('style')) {
12417
- tNode.flags |= 32 /* TNodeFlags.hasStyleInput */;
12423
+ tNode.flags |= 16 /* TNodeFlags.hasStyleInput */;
12418
12424
  }
12419
12425
  }
12420
12426
  tNode.initialInputs = inputsFromAttrs;
@@ -12535,7 +12541,7 @@ function instantiateRootComponent(tView, lView, def) {
12535
12541
  configureViewWithDirective(tView, rootTNode, lView, directiveIndex, def);
12536
12542
  initializeInputAndOutputAliases(tView, rootTNode);
12537
12543
  }
12538
- const directive = getNodeInjectable(lView, tView, rootTNode.directiveStart, rootTNode);
12544
+ const directive = getNodeInjectable(lView, tView, rootTNode.directiveStart + rootTNode.componentOffset, rootTNode);
12539
12545
  attachPatchData(directive, lView);
12540
12546
  const native = getNativeByTNode(rootTNode, lView);
12541
12547
  if (native) {
@@ -12552,7 +12558,10 @@ function resolveDirectives(tView, lView, tNode, localRefs) {
12552
12558
  ngDevMode && assertFirstCreatePass(tView);
12553
12559
  let hasDirectives = false;
12554
12560
  if (getBindingsEnabled()) {
12555
- const directiveDefs = findDirectiveDefMatches(tView, lView, tNode);
12561
+ const directiveDefsMatchedBySelectors = findDirectiveDefMatches(tView, lView, tNode);
12562
+ const directiveDefs = directiveDefsMatchedBySelectors ?
12563
+ findHostDirectiveDefs$1(directiveDefsMatchedBySelectors, tView, lView, tNode) :
12564
+ null;
12556
12565
  const exportsMap = localRefs === null ? null : { '': -1 };
12557
12566
  if (directiveDefs !== null) {
12558
12567
  hasDirectives = true;
@@ -12581,9 +12590,9 @@ function resolveDirectives(tView, lView, tNode, localRefs) {
12581
12590
  configureViewWithDirective(tView, tNode, lView, directiveIdx, def);
12582
12591
  saveNameToExportMap(directiveIdx, def, exportsMap);
12583
12592
  if (def.contentQueries !== null)
12584
- tNode.flags |= 8 /* TNodeFlags.hasContentQuery */;
12593
+ tNode.flags |= 4 /* TNodeFlags.hasContentQuery */;
12585
12594
  if (def.hostBindings !== null || def.hostAttrs !== null || def.hostVars !== 0)
12586
- tNode.flags |= 128 /* TNodeFlags.hasHostBindings */;
12595
+ tNode.flags |= 64 /* TNodeFlags.hasHostBindings */;
12587
12596
  const lifeCycleHooks = def.type.prototype;
12588
12597
  // Only push a node index into the preOrderHooks array if this is the first
12589
12598
  // pre-order hook found on this node.
@@ -12722,7 +12731,6 @@ function invokeHostBindingsInCreationMode(def, directive) {
12722
12731
  * If a component is matched (at most one), it is returned in first position in the array.
12723
12732
  */
12724
12733
  function findDirectiveDefMatches(tView, viewData, tNode) {
12725
- var _a;
12726
12734
  ngDevMode && assertFirstCreatePass(tView);
12727
12735
  ngDevMode && assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ | 12 /* TNodeType.AnyContainer */);
12728
12736
  const registry = tView.directiveRegistry;
@@ -12737,20 +12745,19 @@ function findDirectiveDefMatches(tView, viewData, tNode) {
12737
12745
  if (ngDevMode) {
12738
12746
  assertTNodeType(tNode, 2 /* TNodeType.Element */, `"${tNode.value}" tags cannot be used as component hosts. ` +
12739
12747
  `Please use a different tag to activate the ${stringify(def.type)} component.`);
12740
- if (tNode.flags & 2 /* TNodeFlags.isComponentHost */) {
12748
+ if (isComponentHost(tNode)) {
12741
12749
  // If another component has been matched previously, it's the first element in the
12742
12750
  // `matches` array, see how we store components/directives in `matches` below.
12743
12751
  throwMultipleComponentError(tNode, matches[0].type, def.type);
12744
12752
  }
12745
12753
  }
12746
- markAsComponentHost(tView, tNode);
12754
+ markAsComponentHost(tView, tNode, 0);
12747
12755
  // The component is always stored first with directives after.
12748
12756
  matches.unshift(def);
12749
12757
  }
12750
12758
  else {
12751
12759
  matches.push(def);
12752
12760
  }
12753
- (_a = def.applyHostDirectives) === null || _a === void 0 ? void 0 : _a.call(def, tView, viewData, tNode, matches);
12754
12761
  }
12755
12762
  }
12756
12763
  }
@@ -12758,15 +12765,36 @@ function findDirectiveDefMatches(tView, viewData, tNode) {
12758
12765
  }
12759
12766
  /**
12760
12767
  * Marks a given TNode as a component's host. This consists of:
12761
- * - setting appropriate TNode flags;
12768
+ * - setting the component offset on the TNode.
12762
12769
  * - storing index of component's host element so it will be queued for view refresh during CD.
12763
12770
  */
12764
- function markAsComponentHost(tView, hostTNode) {
12771
+ function markAsComponentHost(tView, hostTNode, componentOffset) {
12765
12772
  ngDevMode && assertFirstCreatePass(tView);
12766
- hostTNode.flags |= 2 /* TNodeFlags.isComponentHost */;
12773
+ ngDevMode && assertGreaterThan(componentOffset, -1, 'componentOffset must be great than -1');
12774
+ hostTNode.componentOffset = componentOffset;
12767
12775
  (tView.components || (tView.components = ngDevMode ? new TViewComponents() : []))
12768
12776
  .push(hostTNode.index);
12769
12777
  }
12778
+ /**
12779
+ * Given an array of directives that were matched by their selectors, this function
12780
+ * produces a new array that also includes any host directives that have to be applied.
12781
+ * @param selectorMatches Directives matched in a template based on their selectors.
12782
+ * @param tView Current TView.
12783
+ * @param lView Current LView.
12784
+ * @param tNode Current TNode that is being matched.
12785
+ */
12786
+ function findHostDirectiveDefs$1(selectorMatches, tView, lView, tNode) {
12787
+ const matches = [];
12788
+ for (const def of selectorMatches) {
12789
+ if (def.findHostDirectiveDefs === null) {
12790
+ matches.push(def);
12791
+ }
12792
+ else {
12793
+ def.findHostDirectiveDefs(matches, def, tView, lView, tNode);
12794
+ }
12795
+ }
12796
+ return matches;
12797
+ }
12770
12798
  /** Caches local names and their matching directive indices for query and template lookups. */
12771
12799
  function cacheMatchingLocalNames(tNode, localRefs, exportsMap) {
12772
12800
  if (localRefs) {
@@ -12909,10 +12937,11 @@ function setInputsFromAttrs(lView, directiveIndex, instance, def, tNode, initial
12909
12937
  *
12910
12938
  * <my-component name="Bess"></my-component>
12911
12939
  *
12912
- * @param inputs The list of inputs from the directive def
12913
- * @param attrs The static attrs on this node
12940
+ * @param inputs Input alias map that was generated from the directive def inputs.
12941
+ * @param directiveIndex Index of the directive that is currently being processed.
12942
+ * @param attrs Static attrs on this node.
12914
12943
  */
12915
- function generateInitialInputs(inputs, attrs) {
12944
+ function generateInitialInputs(inputs, directiveIndex, attrs) {
12916
12945
  let inputsToStore = null;
12917
12946
  let i = 0;
12918
12947
  while (i < attrs.length) {
@@ -12933,7 +12962,17 @@ function generateInitialInputs(inputs, attrs) {
12933
12962
  if (inputs.hasOwnProperty(attrName)) {
12934
12963
  if (inputsToStore === null)
12935
12964
  inputsToStore = [];
12936
- inputsToStore.push(attrName, inputs[attrName], attrs[i + 1]);
12965
+ // Find the input's public name from the input store. Note that we can be found easier
12966
+ // through the directive def, but we want to do it using the inputs store so that it can
12967
+ // account for host directive aliases.
12968
+ const inputConfig = inputs[attrName];
12969
+ for (let j = 0; j < inputConfig.length; j += 2) {
12970
+ if (inputConfig[j] === directiveIndex) {
12971
+ inputsToStore.push(attrName, inputConfig[j + 1], attrs[i + 1]);
12972
+ // A directive can't have multiple inputs with the same name so we can break here.
12973
+ break;
12974
+ }
12975
+ }
12937
12976
  }
12938
12977
  i += 2;
12939
12978
  }
@@ -13966,7 +14005,7 @@ function createRootComponentView(rNode, def, rootView, rendererFactory, hostRend
13966
14005
  const componentView = createLView(rootView, getOrCreateComponentTView(def), null, def.onPush ? 32 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, rootView[index], tNode, rendererFactory, viewRenderer, sanitizer || null, null, null);
13967
14006
  if (tView.firstCreatePass) {
13968
14007
  diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, rootView), tView, def.type);
13969
- markAsComponentHost(tView, tNode);
14008
+ markAsComponentHost(tView, tNode, 0);
13970
14009
  initTNodeFlags(tNode, rootView.length, 1);
13971
14010
  }
13972
14011
  addToViewTree(rootView, componentView);
@@ -14263,6 +14302,13 @@ function ɵɵCopyDefinitionFeature(definition) {
14263
14302
  }
14264
14303
  }
14265
14304
 
14305
+ /**
14306
+ * @license
14307
+ * Copyright Google LLC All Rights Reserved.
14308
+ *
14309
+ * Use of this source code is governed by an MIT-style license that can be
14310
+ * found in the LICENSE file at https://angular.io/license
14311
+ */
14266
14312
  /**
14267
14313
  * This feature add the host directives behavior to a directive definition by patching a
14268
14314
  * function onto it. The expectation is that the runtime will invoke the function during
@@ -14284,29 +14330,43 @@ function ɵɵCopyDefinitionFeature(definition) {
14284
14330
  * @codeGenApi
14285
14331
  */
14286
14332
  function ɵɵHostDirectivesFeature(rawHostDirectives) {
14287
- const unwrappedHostDirectives = Array.isArray(rawHostDirectives) ? rawHostDirectives : rawHostDirectives();
14288
- const hostDirectives = unwrappedHostDirectives.map(dir => typeof dir === 'function' ? { directive: dir, inputs: EMPTY_OBJ, outputs: EMPTY_OBJ } : {
14289
- directive: dir.directive,
14290
- inputs: bindingArrayToMap(dir.inputs),
14291
- outputs: bindingArrayToMap(dir.outputs)
14292
- });
14293
14333
  return (definition) => {
14294
- // TODO(crisbeto): implement host directive matching logic.
14295
- definition.applyHostDirectives =
14296
- (tView, viewData, tNode, matches) => { };
14334
+ definition.findHostDirectiveDefs = findHostDirectiveDefs;
14335
+ definition.hostDirectives =
14336
+ (Array.isArray(rawHostDirectives) ? rawHostDirectives : rawHostDirectives()).map(dir => {
14337
+ return typeof dir === 'function' ?
14338
+ { directive: resolveForwardRef(dir), inputs: EMPTY_OBJ, outputs: EMPTY_OBJ } :
14339
+ {
14340
+ directive: resolveForwardRef(dir.directive),
14341
+ inputs: bindingArrayToMap(dir.inputs),
14342
+ outputs: bindingArrayToMap(dir.outputs)
14343
+ };
14344
+ });
14297
14345
  };
14298
14346
  }
14347
+ function findHostDirectiveDefs(matches, def, tView, lView, tNode) {
14348
+ if (def.hostDirectives !== null) {
14349
+ for (const hostDirectiveConfig of def.hostDirectives) {
14350
+ const hostDirectiveDef = getDirectiveDef(hostDirectiveConfig.directive);
14351
+ // TODO(crisbeto): assert that the def exists.
14352
+ // Host directives execute before the host so that its host bindings can be overwritten.
14353
+ findHostDirectiveDefs(matches, hostDirectiveDef, tView, lView, tNode);
14354
+ }
14355
+ }
14356
+ // Push the def itself at the end since it needs to execute after the host directives.
14357
+ matches.push(def);
14358
+ }
14299
14359
  /**
14300
14360
  * Converts an array in the form of `['publicName', 'alias', 'otherPublicName', 'otherAlias']` into
14301
14361
  * a map in the form of `{publicName: 'alias', otherPublicName: 'otherAlias'}`.
14302
14362
  */
14303
14363
  function bindingArrayToMap(bindings) {
14304
- if (!bindings || bindings.length === 0) {
14364
+ if (bindings === undefined || bindings.length === 0) {
14305
14365
  return EMPTY_OBJ;
14306
14366
  }
14307
14367
  const result = {};
14308
- for (let i = 1; i < bindings.length; i += 2) {
14309
- result[bindings[i - 1]] = bindings[i];
14368
+ for (let i = 0; i < bindings.length; i += 2) {
14369
+ result[bindings[i]] = bindings[i + 1];
14310
14370
  }
14311
14371
  return result;
14312
14372
  }
@@ -15265,7 +15325,7 @@ function ɵɵelementStart(index, name, attrsIndex, localRefsIndex) {
15265
15325
  if (styles !== null) {
15266
15326
  writeDirectStyle(renderer, native, styles);
15267
15327
  }
15268
- if ((tNode.flags & 64 /* TNodeFlags.isDetached */) !== 64 /* TNodeFlags.isDetached */) {
15328
+ if ((tNode.flags & 32 /* TNodeFlags.isDetached */) !== 32 /* TNodeFlags.isDetached */) {
15269
15329
  // In the i18n case, the translation may have removed this element, so only add it if it is not
15270
15330
  // detached. See `TNodeType.Placeholder` and `LFrame.inI18n` for more context.
15271
15331
  appendChild(tView, lView, native, tNode);
@@ -15703,9 +15763,7 @@ function wrapListener(tNode, lView, context, listenerFn, wrapWithPreventDefault)
15703
15763
  }
15704
15764
  // In order to be backwards compatible with View Engine, events on component host nodes
15705
15765
  // must also mark the component view itself dirty (i.e. the view that it owns).
15706
- const startView = tNode.flags & 2 /* TNodeFlags.isComponentHost */ ?
15707
- getComponentLViewByIndex(tNode.index, lView) :
15708
- lView;
15766
+ const startView = tNode.componentOffset > -1 ? getComponentLViewByIndex(tNode.index, lView) : lView;
15709
15767
  markViewDirty(startView);
15710
15768
  let result = executeListenerWithErrorHandling(lView, context, listenerFn, e);
15711
15769
  // A just-invoked listener function might have coalesced listeners so we need to check for
@@ -15862,7 +15920,7 @@ function ɵɵprojection(nodeIndex, selectorIndex = 0, attrs) {
15862
15920
  tProjectionNode.projection = selectorIndex;
15863
15921
  // `<ng-content>` has no content
15864
15922
  setCurrentTNodeAsNotParent();
15865
- if ((tProjectionNode.flags & 64 /* TNodeFlags.isDetached */) !== 64 /* TNodeFlags.isDetached */) {
15923
+ if ((tProjectionNode.flags & 32 /* TNodeFlags.isDetached */) !== 32 /* TNodeFlags.isDetached */) {
15866
15924
  // re-distribution of projectable nodes is stored on a component's view level
15867
15925
  applyProjection(tView, lView, tProjectionNode);
15868
15926
  }
@@ -17776,7 +17834,7 @@ function normalizeSuffix(value, suffix) {
17776
17834
  * @param isClassBased `true` if `class` (`false` if `style`)
17777
17835
  */
17778
17836
  function hasStylingInputShadow(tNode, isClassBased) {
17779
- return (tNode.flags & (isClassBased ? 16 /* TNodeFlags.hasClassInput */ : 32 /* TNodeFlags.hasStyleInput */)) !== 0;
17837
+ return (tNode.flags & (isClassBased ? 8 /* TNodeFlags.hasClassInput */ : 16 /* TNodeFlags.hasStyleInput */)) !== 0;
17780
17838
  }
17781
17839
 
17782
17840
  /**
@@ -19468,7 +19526,7 @@ function processI18nInsertBefore(renderer, childTNode, lView, childRNode, parent
19468
19526
  anchorRNode = i18nParent;
19469
19527
  i18nParent = parentRElement;
19470
19528
  }
19471
- if (i18nParent !== null && (childTNode.flags & 2 /* TNodeFlags.isComponentHost */) === 0) {
19529
+ if (i18nParent !== null && childTNode.componentOffset === -1) {
19472
19530
  for (let i = 1; i < tNodeInsertBeforeIndex.length; i++) {
19473
19531
  // No need to `unwrapRNode` because all of the indexes point to i18n text nodes.
19474
19532
  // see `assertDomNode` below.
@@ -24939,6 +24997,7 @@ function extendsDirectlyFromObject(type) {
24939
24997
  * `Component`).
24940
24998
  */
24941
24999
  function directiveMetadata(type, metadata) {
25000
+ var _a;
24942
25001
  // Reflect inputs and outputs.
24943
25002
  const reflect = getReflect();
24944
25003
  const propMetadata = reflect.ownPropMetadata(type);
@@ -24958,7 +25017,12 @@ function directiveMetadata(type, metadata) {
24958
25017
  providers: metadata.providers || null,
24959
25018
  viewQueries: extractQueriesMetadata(type, propMetadata, isViewQuery),
24960
25019
  isStandalone: !!metadata.standalone,
24961
- hostDirectives: null,
25020
+ hostDirectives:
25021
+ // TODO(crisbeto): remove the `as any` usage here and down in the `map` call once
25022
+ // host directives are exposed in the public API.
25023
+ ((_a = metadata
25024
+ .hostDirectives) === null || _a === void 0 ? void 0 : _a.map((directive) => typeof directive === 'function' ? { directive } : directive)) ||
25025
+ null
24962
25026
  };
24963
25027
  }
24964
25028
  /**
@@ -28225,7 +28289,7 @@ function _queryNodeChildren(tNode, lView, predicate, matches, elementsOnly, root
28225
28289
  if (rootNativeNode !== nativeNode) {
28226
28290
  // To determine the next node to be processed, we need to use the next or the projectionNext
28227
28291
  // link, depending on whether the current node has been projected.
28228
- const nextTNode = (tNode.flags & 4 /* TNodeFlags.isProjected */) ? tNode.projectionNext : tNode.next;
28292
+ const nextTNode = (tNode.flags & 2 /* TNodeFlags.isProjected */) ? tNode.projectionNext : tNode.next;
28229
28293
  if (nextTNode) {
28230
28294
  _queryNodeChildren(nextTNode, lView, predicate, matches, elementsOnly, rootNativeNode);
28231
28295
  }