@angular/core 15.0.0-next.4 → 15.0.0-next.6

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 (47) hide show
  1. package/esm2020/src/application_ref.mjs +1 -1
  2. package/esm2020/src/core_private_export.mjs +2 -1
  3. package/esm2020/src/di/index.mjs +2 -2
  4. package/esm2020/src/di/injectable.mjs +1 -1
  5. package/esm2020/src/di/injection_token.mjs +6 -3
  6. package/esm2020/src/di/interface/defs.mjs +1 -1
  7. package/esm2020/src/di/interface/provider.mjs +4 -2
  8. package/esm2020/src/di/provider_collection.mjs +30 -4
  9. package/esm2020/src/di/r3_injector.mjs +4 -6
  10. package/esm2020/src/errors.mjs +1 -1
  11. package/esm2020/src/metadata/directives.mjs +1 -1
  12. package/esm2020/src/metadata/ng_module.mjs +1 -1
  13. package/esm2020/src/render3/component_ref.mjs +20 -10
  14. package/esm2020/src/render3/errors_di.mjs +9 -3
  15. package/esm2020/src/render3/features/host_directives_feature.mjs +101 -9
  16. package/esm2020/src/render3/features/ng_onchanges_feature.mjs +4 -2
  17. package/esm2020/src/render3/instructions/shared.mjs +70 -34
  18. package/esm2020/src/render3/interfaces/definition.mjs +1 -1
  19. package/esm2020/src/render3/jit/directive.mjs +2 -6
  20. package/esm2020/src/render3/jit/module.mjs +2 -2
  21. package/esm2020/src/render3/ng_module_ref.mjs +1 -1
  22. package/esm2020/src/version.mjs +1 -1
  23. package/esm2020/testing/src/logger.mjs +3 -3
  24. package/esm2020/testing/src/ng_zone_mock.mjs +3 -3
  25. package/esm2020/testing/src/test_bed_compiler.mjs +29 -11
  26. package/fesm2015/core.mjs +243 -69
  27. package/fesm2015/core.mjs.map +1 -1
  28. package/fesm2015/testing.mjs +269 -73
  29. package/fesm2015/testing.mjs.map +1 -1
  30. package/fesm2020/core.mjs +243 -69
  31. package/fesm2020/core.mjs.map +1 -1
  32. package/fesm2020/testing.mjs +269 -73
  33. package/fesm2020/testing.mjs.map +1 -1
  34. package/index.d.ts +103 -32
  35. package/package.json +2 -2
  36. package/schematics/migrations/relative-link-resolution/index.d.ts +10 -0
  37. package/schematics/migrations/relative-link-resolution/index.js +68 -0
  38. package/schematics/migrations/relative-link-resolution/util.d.ts +20 -0
  39. package/schematics/migrations/relative-link-resolution/util.js +82 -0
  40. package/schematics/migrations/router-link-with-href/index.d.ts +10 -0
  41. package/schematics/migrations/router-link-with-href/index.js +70 -0
  42. package/schematics/migrations/router-link-with-href/util.d.ts +19 -0
  43. package/schematics/migrations/router-link-with-href/util.js +111 -0
  44. package/schematics/migrations.json +10 -0
  45. package/schematics/utils/typescript/imports.d.ts +10 -0
  46. package/schematics/utils/typescript/imports.js +17 -2
  47. package/testing/index.d.ts +1 -1
@@ -1,10 +1,10 @@
1
1
  /**
2
- * @license Angular v15.0.0-next.4
2
+ * @license Angular v15.0.0-next.6
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
6
6
 
7
- import { getDebugNode as getDebugNode$1, RendererFactory2 as RendererFactory2$1, InjectionToken as InjectionToken$1, ɵstringify, ɵReflectionCapabilities, Directive, Component, Pipe, NgModule, ɵgetInjectableDef, resolveForwardRef as resolveForwardRef$1, ɵNG_COMP_DEF, ɵRender3NgModuleRef, ApplicationInitStatus, LOCALE_ID as LOCALE_ID$1, ɵDEFAULT_LOCALE_ID, ɵsetLocaleId, ɵRender3ComponentFactory, ɵcompileComponent, ɵNG_DIR_DEF, ɵcompileDirective, ɵNG_PIPE_DEF, ɵcompilePipe, ɵNG_MOD_DEF, ɵtransitiveScopesFor, ɵpatchComponentDefWithScope, ɵNG_INJ_DEF, ɵcompileNgModuleDefs, NgZone, Compiler, COMPILER_OPTIONS, ɵNgModuleFactory, ModuleWithComponentFactories, ɵconvertToBitFlags, Injector as Injector$1, InjectFlags as InjectFlags$1, ɵsetAllowDuplicateNgModuleIdsForTest, ɵresetCompiledComponents, ɵsetUnknownElementStrictMode as ɵsetUnknownElementStrictMode$1, ɵsetUnknownPropertyStrictMode as ɵsetUnknownPropertyStrictMode$1, ɵgetUnknownElementStrictMode as ɵgetUnknownElementStrictMode$1, ɵgetUnknownPropertyStrictMode as ɵgetUnknownPropertyStrictMode$1, ɵflushModuleScopingQueueAsMuchAsPossible } from '@angular/core';
7
+ import { getDebugNode as getDebugNode$1, RendererFactory2 as RendererFactory2$1, InjectionToken as InjectionToken$1, ɵstringify, ɵReflectionCapabilities, Directive, Component, Pipe, NgModule, ɵgetInjectableDef, resolveForwardRef as resolveForwardRef$1, ɵNG_COMP_DEF, ɵRender3NgModuleRef, ApplicationInitStatus, LOCALE_ID as LOCALE_ID$1, ɵDEFAULT_LOCALE_ID, ɵsetLocaleId, ɵRender3ComponentFactory, ɵcompileComponent, ɵNG_DIR_DEF, ɵcompileDirective, ɵNG_PIPE_DEF, ɵcompilePipe, ɵNG_MOD_DEF, ɵtransitiveScopesFor, ɵpatchComponentDefWithScope, ɵNG_INJ_DEF, ɵcompileNgModuleDefs, NgZone, Compiler, COMPILER_OPTIONS, ɵNgModuleFactory, ɵisEnvironmentProviders, ModuleWithComponentFactories, ɵconvertToBitFlags, Injector as Injector$1, InjectFlags as InjectFlags$1, ɵsetAllowDuplicateNgModuleIdsForTest, ɵresetCompiledComponents, ɵsetUnknownElementStrictMode as ɵsetUnknownElementStrictMode$1, ɵsetUnknownPropertyStrictMode as ɵsetUnknownPropertyStrictMode$1, ɵgetUnknownElementStrictMode as ɵgetUnknownElementStrictMode$1, ɵgetUnknownPropertyStrictMode as ɵgetUnknownPropertyStrictMode$1, ɵflushModuleScopingQueueAsMuchAsPossible } from '@angular/core';
8
8
  import { ResourceLoader } from '@angular/compiler';
9
9
  import { Subject, Subscription } from 'rxjs';
10
10
 
@@ -1886,6 +1886,17 @@ function initNgDevMode() {
1886
1886
  return false;
1887
1887
  }
1888
1888
 
1889
+ /**
1890
+ * @license
1891
+ * Copyright Google LLC All Rights Reserved.
1892
+ *
1893
+ * Use of this source code is governed by an MIT-style license that can be
1894
+ * found in the LICENSE file at https://angular.io/license
1895
+ */
1896
+ function isEnvironmentProviders(value) {
1897
+ return value && !!value.ɵproviders;
1898
+ }
1899
+
1889
1900
  /**
1890
1901
  * @license
1891
1902
  * Copyright Google LLC All Rights Reserved.
@@ -1942,8 +1953,13 @@ function throwInvalidProviderError(ngModuleType, providers, provider) {
1942
1953
  const providerDetail = providers.map(v => v == provider ? '?' + provider + '?' : '...');
1943
1954
  throw new Error(`Invalid provider for the NgModule '${stringify(ngModuleType)}' - only instances of Provider and Type are allowed, got: [${providerDetail.join(', ')}]`);
1944
1955
  }
1945
- else if (provider.ɵproviders) {
1946
- throw new RuntimeError(207 /* RuntimeErrorCode.PROVIDER_IN_WRONG_CONTEXT */, `Invalid providers from 'importProvidersFrom' present in a non-environment injector. 'importProvidersFrom' can't be used for component providers.`);
1956
+ else if (isEnvironmentProviders(provider)) {
1957
+ if (provider.ɵfromNgModule) {
1958
+ throw new RuntimeError(207 /* RuntimeErrorCode.PROVIDER_IN_WRONG_CONTEXT */, `Invalid providers from 'importProvidersFrom' present in a non-environment injector. 'importProvidersFrom' can't be used for component providers.`);
1959
+ }
1960
+ else {
1961
+ throw new RuntimeError(207 /* RuntimeErrorCode.PROVIDER_IN_WRONG_CONTEXT */, `Invalid providers present in a non-environment injector. 'EnvironmentProviders' can't be used for component providers.`);
1962
+ }
1947
1963
  }
1948
1964
  else {
1949
1965
  throw new Error('Invalid provider');
@@ -3170,11 +3186,12 @@ function rememberChangeHistoryAndInvokeOnChangesHook() {
3170
3186
  }
3171
3187
  }
3172
3188
  function ngOnChangesSetInput(instance, value, publicName, privateName) {
3189
+ const declaredName = this.declaredInputs[publicName];
3190
+ ngDevMode && assertString(declaredName, 'Name of input in ngOnChanges has to be a string');
3173
3191
  const simpleChangesStore = getSimpleChangesStore(instance) ||
3174
3192
  setSimpleChangesStore(instance, { previous: EMPTY_OBJ, current: null });
3175
3193
  const current = simpleChangesStore.current || (simpleChangesStore.current = {});
3176
3194
  const previous = simpleChangesStore.previous;
3177
- const declaredName = this.declaredInputs[publicName];
3178
3195
  const previousChange = previous[declaredName];
3179
3196
  current[declaredName] = new SimpleChange(previousChange && previousChange.currentValue, value, previous === EMPTY_OBJ);
3180
3197
  instance[privateName] = value;
@@ -6639,8 +6656,11 @@ function getSanitizer() {
6639
6656
  * As you can see in the Tree-shakable InjectionToken example below.
6640
6657
  *
6641
6658
  * Additionally, if a `factory` is specified you can also specify the `providedIn` option, which
6642
- * overrides the above behavior and marks the token as belonging to a particular `@NgModule`. As
6643
- * mentioned above, `'root'` is the default value for `providedIn`.
6659
+ * overrides the above behavior and marks the token as belonging to a particular `@NgModule` (note:
6660
+ * this option is now deprecated). As mentioned above, `'root'` is the default value for
6661
+ * `providedIn`.
6662
+ *
6663
+ * The `providedIn: NgModule` and `providedIn: 'any'` options are deprecated.
6644
6664
  *
6645
6665
  * @usageNotes
6646
6666
  * ### Basic Examples
@@ -6771,6 +6791,15 @@ class NullInjector {
6771
6791
  * Use of this source code is governed by an MIT-style license that can be
6772
6792
  * found in the LICENSE file at https://angular.io/license
6773
6793
  */
6794
+ /**
6795
+ * Wrap an array of `Provider`s into `EnvironmentProviders`, preventing them from being accidentally
6796
+ * referenced in `@Component in a component injector.
6797
+ */
6798
+ function makeEnvironmentProviders(providers) {
6799
+ return {
6800
+ ɵproviders: providers,
6801
+ };
6802
+ }
6774
6803
  /**
6775
6804
  * Collects providers from all NgModules and standalone components, including transitively imported
6776
6805
  * ones.
@@ -6813,7 +6842,10 @@ class NullInjector {
6813
6842
  * @developerPreview
6814
6843
  */
6815
6844
  function importProvidersFrom(...sources) {
6816
- return { ɵproviders: internalImportProvidersFrom(true, sources) };
6845
+ return {
6846
+ ɵproviders: internalImportProvidersFrom(true, sources),
6847
+ ɵfromNgModule: true,
6848
+ };
6817
6849
  }
6818
6850
  function internalImportProvidersFrom(checkForStandaloneCmp, ...sources) {
6819
6851
  const providersOut = [];
@@ -6846,7 +6878,7 @@ function internalImportProvidersFrom(checkForStandaloneCmp, ...sources) {
6846
6878
  function processInjectorTypesWithProviders(typesWithProviders, providersOut) {
6847
6879
  for (let i = 0; i < typesWithProviders.length; i++) {
6848
6880
  const { ngModule, providers } = typesWithProviders[i];
6849
- deepForEach(providers, provider => {
6881
+ deepForEachProvider(providers, provider => {
6850
6882
  ngDevMode && validateProvider(provider, providers || EMPTY_ARRAY, ngModule);
6851
6883
  providersOut.push(provider);
6852
6884
  });
@@ -6963,7 +6995,7 @@ function walkProviderTree(container, providersOut, parents, dedup) {
6963
6995
  const defProviders = injDef.providers;
6964
6996
  if (defProviders != null && !isDuplicate) {
6965
6997
  const injectorType = container;
6966
- deepForEach(defProviders, provider => {
6998
+ deepForEachProvider(defProviders, provider => {
6967
6999
  ngDevMode && validateProvider(provider, defProviders, injectorType);
6968
7000
  providersOut.push(provider);
6969
7001
  });
@@ -6987,6 +7019,19 @@ function validateProvider(provider, providers, containerType) {
6987
7019
  throwInvalidProviderError(containerType, providers, provider);
6988
7020
  }
6989
7021
  }
7022
+ function deepForEachProvider(providers, fn) {
7023
+ for (let provider of providers) {
7024
+ if (isEnvironmentProviders(provider)) {
7025
+ provider = provider.ɵproviders;
7026
+ }
7027
+ if (Array.isArray(provider)) {
7028
+ deepForEachProvider(provider, fn);
7029
+ }
7030
+ else {
7031
+ fn(provider);
7032
+ }
7033
+ }
7034
+ }
6990
7035
  const USE_VALUE$1 = getClosureSafeProperty({ provide: String, useValue: getClosureSafeProperty });
6991
7036
  function isValueProvider(value) {
6992
7037
  return value !== null && typeof value == 'object' && USE_VALUE$1 in value;
@@ -7352,7 +7397,7 @@ function providerToRecord(provider) {
7352
7397
  */
7353
7398
  function providerToFactory(provider, ngModuleType, providers) {
7354
7399
  let factory = undefined;
7355
- if (ngDevMode && isImportedNgModuleProviders(provider)) {
7400
+ if (ngDevMode && isEnvironmentProviders(provider)) {
7356
7401
  throwInvalidProviderError(undefined, providers, provider);
7357
7402
  }
7358
7403
  if (isTypeProvider(provider)) {
@@ -7403,15 +7448,12 @@ function couldBeInjectableType(value) {
7403
7448
  return (typeof value === 'function') ||
7404
7449
  (typeof value === 'object' && value instanceof InjectionToken);
7405
7450
  }
7406
- function isImportedNgModuleProviders(provider) {
7407
- return !!provider.ɵproviders;
7408
- }
7409
7451
  function forEachSingleProvider(providers, fn) {
7410
7452
  for (const provider of providers) {
7411
7453
  if (Array.isArray(provider)) {
7412
7454
  forEachSingleProvider(provider, fn);
7413
7455
  }
7414
- else if (isImportedNgModuleProviders(provider)) {
7456
+ else if (provider && isEnvironmentProviders(provider)) {
7415
7457
  forEachSingleProvider(provider.ɵproviders, fn);
7416
7458
  }
7417
7459
  else {
@@ -7642,7 +7684,7 @@ class Version {
7642
7684
  /**
7643
7685
  * @publicApi
7644
7686
  */
7645
- const VERSION = new Version('15.0.0-next.4');
7687
+ const VERSION = new Version('15.0.0-next.6');
7646
7688
 
7647
7689
  /**
7648
7690
  * @license
@@ -12610,9 +12652,6 @@ function createViewBlueprint(bindingStartIndex, initialViewLength) {
12610
12652
  }
12611
12653
  return blueprint;
12612
12654
  }
12613
- function createError(text, token) {
12614
- return new Error(`Renderer: ${text} [${stringifyForError(token)}]`);
12615
- }
12616
12655
  /**
12617
12656
  * Locates the host native element, used for bootstrapping existing nodes into rendering pipeline.
12618
12657
  *
@@ -12736,26 +12775,49 @@ function createTNode(tView, tParent, type, index, value, attrs) {
12736
12775
  }
12737
12776
  return tNode;
12738
12777
  }
12739
- function generatePropertyAliases(inputAliasMap, directiveDefIdx, propStore) {
12740
- for (let publicName in inputAliasMap) {
12741
- if (inputAliasMap.hasOwnProperty(publicName)) {
12742
- propStore = propStore === null ? {} : propStore;
12743
- const internalName = inputAliasMap[publicName];
12744
- if (propStore.hasOwnProperty(publicName)) {
12745
- propStore[publicName].push(directiveDefIdx, internalName);
12778
+ /**
12779
+ * Generates the `PropertyAliases` data structure from the provided input/output mapping.
12780
+ * @param aliasMap Input/output mapping from the directive definition.
12781
+ * @param directiveIndex Index of the directive.
12782
+ * @param propertyAliases Object in which to store the results.
12783
+ * @param hostDirectiveAliasMap Object used to alias or filter out properties for host directives.
12784
+ * If the mapping is provided, it'll act as an allowlist, as well as a mapping of what public
12785
+ * name inputs/outputs should be exposed under.
12786
+ */
12787
+ function generatePropertyAliases(aliasMap, directiveIndex, propertyAliases, hostDirectiveAliasMap) {
12788
+ for (let publicName in aliasMap) {
12789
+ if (aliasMap.hasOwnProperty(publicName)) {
12790
+ propertyAliases = propertyAliases === null ? {} : propertyAliases;
12791
+ const internalName = aliasMap[publicName];
12792
+ // If there are no host directive mappings, we want to remap using the alias map from the
12793
+ // definition itself. If there is an alias map, it has two functions:
12794
+ // 1. It serves as an allowlist of bindings that are exposed by the host directives. Only the
12795
+ // ones inside the host directive map will be exposed on the host.
12796
+ // 2. The public name of the property is aliased using the host directive alias map, rather
12797
+ // than the alias map from the definition.
12798
+ if (hostDirectiveAliasMap === null) {
12799
+ addPropertyAlias(propertyAliases, directiveIndex, publicName, internalName);
12746
12800
  }
12747
- else {
12748
- (propStore[publicName] = [directiveDefIdx, internalName]);
12801
+ else if (hostDirectiveAliasMap.hasOwnProperty(publicName)) {
12802
+ addPropertyAlias(propertyAliases, directiveIndex, hostDirectiveAliasMap[publicName], internalName);
12749
12803
  }
12750
12804
  }
12751
12805
  }
12752
- return propStore;
12806
+ return propertyAliases;
12807
+ }
12808
+ function addPropertyAlias(propertyAliases, directiveIndex, publicName, internalName) {
12809
+ if (propertyAliases.hasOwnProperty(publicName)) {
12810
+ propertyAliases[publicName].push(directiveIndex, internalName);
12811
+ }
12812
+ else {
12813
+ propertyAliases[publicName] = [directiveIndex, internalName];
12814
+ }
12753
12815
  }
12754
12816
  /**
12755
12817
  * Initializes data structures required to work with directive inputs and outputs.
12756
12818
  * Initialization is done for all directives matched on a given TNode.
12757
12819
  */
12758
- function initializeInputAndOutputAliases(tView, tNode) {
12820
+ function initializeInputAndOutputAliases(tView, tNode, hostDirectiveDefinitionMap) {
12759
12821
  ngDevMode && assertFirstCreatePass(tView);
12760
12822
  const start = tNode.directiveStart;
12761
12823
  const end = tNode.directiveEnd;
@@ -12764,16 +12826,21 @@ function initializeInputAndOutputAliases(tView, tNode) {
12764
12826
  const inputsFromAttrs = ngDevMode ? new TNodeInitialInputs() : [];
12765
12827
  let inputsStore = null;
12766
12828
  let outputsStore = null;
12767
- for (let i = start; i < end; i++) {
12768
- const directiveDef = tViewData[i];
12769
- inputsStore = generatePropertyAliases(directiveDef.inputs, i, inputsStore);
12770
- outputsStore = generatePropertyAliases(directiveDef.outputs, i, outputsStore);
12829
+ for (let directiveIndex = start; directiveIndex < end; directiveIndex++) {
12830
+ const directiveDef = tViewData[directiveIndex];
12831
+ const aliasData = hostDirectiveDefinitionMap ? hostDirectiveDefinitionMap.get(directiveDef) : null;
12832
+ const aliasedInputs = aliasData ? aliasData.inputs : null;
12833
+ const aliasedOutputs = aliasData ? aliasData.outputs : null;
12834
+ inputsStore =
12835
+ generatePropertyAliases(directiveDef.inputs, directiveIndex, inputsStore, aliasedInputs);
12836
+ outputsStore =
12837
+ generatePropertyAliases(directiveDef.outputs, directiveIndex, outputsStore, aliasedOutputs);
12771
12838
  // Do not use unbound attributes as inputs to structural directives, since structural
12772
12839
  // directive inputs can only be set using microsyntax (e.g. `<div *dir="exp">`).
12773
12840
  // TODO(FW-1930): microsyntax expressions may also contain unbound/static attributes, which
12774
12841
  // should be set for inline templates.
12775
12842
  const initialInputs = (inputsStore !== null && tNodeAttrs !== null && !isInlineTemplate(tNode)) ?
12776
- generateInitialInputs(inputsStore, i, tNodeAttrs) :
12843
+ generateInitialInputs(inputsStore, directiveIndex, tNodeAttrs) :
12777
12844
  null;
12778
12845
  inputsFromAttrs.push(initialInputs);
12779
12846
  }
@@ -12898,16 +12965,19 @@ function resolveDirectives(tView, lView, tNode, localRefs) {
12898
12965
  ngDevMode && assertFirstCreatePass(tView);
12899
12966
  let hasDirectives = false;
12900
12967
  if (getBindingsEnabled()) {
12901
- const directiveDefs = findDirectiveDefMatches(tView, lView, tNode);
12902
12968
  const exportsMap = localRefs === null ? null : { '': -1 };
12969
+ const matchResult = findDirectiveDefMatches(tView, tNode);
12970
+ let directiveDefs;
12971
+ let hostDirectiveDefs;
12972
+ if (matchResult === null) {
12973
+ directiveDefs = hostDirectiveDefs = null;
12974
+ }
12975
+ else {
12976
+ [directiveDefs, hostDirectiveDefs] = matchResult;
12977
+ }
12903
12978
  if (directiveDefs !== null) {
12904
- // Publishes the directive types to DI so they can be injected. Needs to
12905
- // happen in a separate pass before the TNode flags have been initialized.
12906
- for (let i = 0; i < directiveDefs.length; i++) {
12907
- diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, lView), tView, directiveDefs[i].type);
12908
- }
12909
12979
  hasDirectives = true;
12910
- initializeDirectives(tView, lView, tNode, directiveDefs, exportsMap);
12980
+ initializeDirectives(tView, lView, tNode, directiveDefs, exportsMap, hostDirectiveDefs);
12911
12981
  }
12912
12982
  if (exportsMap)
12913
12983
  cacheMatchingLocalNames(tNode, localRefs, exportsMap);
@@ -12917,8 +12987,13 @@ function resolveDirectives(tView, lView, tNode, localRefs) {
12917
12987
  return hasDirectives;
12918
12988
  }
12919
12989
  /** Initializes the data structures necessary for a list of directives to be instantiated. */
12920
- function initializeDirectives(tView, lView, tNode, directives, exportsMap) {
12990
+ function initializeDirectives(tView, lView, tNode, directives, exportsMap, hostDirectiveDefs) {
12921
12991
  ngDevMode && assertFirstCreatePass(tView);
12992
+ // Publishes the directive types to DI so they can be injected. Needs to
12993
+ // happen in a separate pass before the TNode flags have been initialized.
12994
+ for (let i = 0; i < directives.length; i++) {
12995
+ diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, lView), tView, directives[i].type);
12996
+ }
12922
12997
  initTNodeFlags(tNode, tView.data.length, directives.length);
12923
12998
  // When the same token is provided by several directives on the same node, some rules apply in
12924
12999
  // the viewEngine:
@@ -12964,7 +13039,7 @@ function initializeDirectives(tView, lView, tNode, directives, exportsMap) {
12964
13039
  }
12965
13040
  directiveIdx++;
12966
13041
  }
12967
- initializeInputAndOutputAliases(tView, tNode);
13042
+ initializeInputAndOutputAliases(tView, tNode, hostDirectiveDefs);
12968
13043
  }
12969
13044
  /**
12970
13045
  * Add `hostBindings` to the `TView.hostBindingOpCodes`.
@@ -13076,11 +13151,12 @@ function invokeHostBindingsInCreationMode(def, directive) {
13076
13151
  * Matches the current node against all available selectors.
13077
13152
  * If a component is matched (at most one), it is returned in first position in the array.
13078
13153
  */
13079
- function findDirectiveDefMatches(tView, lView, tNode) {
13154
+ function findDirectiveDefMatches(tView, tNode) {
13080
13155
  ngDevMode && assertFirstCreatePass(tView);
13081
13156
  ngDevMode && assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ | 12 /* TNodeType.AnyContainer */);
13082
13157
  const registry = tView.directiveRegistry;
13083
13158
  let matches = null;
13159
+ let hostDirectiveDefs = null;
13084
13160
  if (registry) {
13085
13161
  for (let i = 0; i < registry.length; i++) {
13086
13162
  const def = registry[i];
@@ -13106,7 +13182,8 @@ function findDirectiveDefMatches(tView, lView, tNode) {
13106
13182
  // 4. Selector-matched directives.
13107
13183
  if (def.findHostDirectiveDefs !== null) {
13108
13184
  const hostDirectiveMatches = [];
13109
- def.findHostDirectiveDefs(hostDirectiveMatches, def, tView, lView, tNode);
13185
+ hostDirectiveDefs = hostDirectiveDefs || new Map();
13186
+ def.findHostDirectiveDefs(def, hostDirectiveMatches, hostDirectiveDefs);
13110
13187
  // Add all host directives declared on this component, followed by the component itself.
13111
13188
  // Host directives should execute first so the host has a chance to override changes
13112
13189
  // to the DOM made by them.
@@ -13124,13 +13201,14 @@ function findDirectiveDefMatches(tView, lView, tNode) {
13124
13201
  }
13125
13202
  else {
13126
13203
  // Append any host directives to the matches first.
13127
- def.findHostDirectiveDefs?.(matches, def, tView, lView, tNode);
13204
+ hostDirectiveDefs = hostDirectiveDefs || new Map();
13205
+ def.findHostDirectiveDefs?.(def, matches, hostDirectiveDefs);
13128
13206
  matches.push(def);
13129
13207
  }
13130
13208
  }
13131
13209
  }
13132
13210
  }
13133
- return matches;
13211
+ return matches === null ? null : [matches, hostDirectiveDefs];
13134
13212
  }
13135
13213
  /**
13136
13214
  * Marks a given TNode as a component's host. This consists of:
@@ -14211,15 +14289,26 @@ class ComponentFactory extends ComponentFactory$1 {
14211
14289
  let component;
14212
14290
  let tElementNode;
14213
14291
  try {
14214
- const rootDirectives = [this.componentDef];
14292
+ const rootComponentDef = this.componentDef;
14293
+ let rootDirectives;
14294
+ let hostDirectiveDefs = null;
14295
+ if (rootComponentDef.findHostDirectiveDefs) {
14296
+ rootDirectives = [];
14297
+ hostDirectiveDefs = new Map();
14298
+ rootComponentDef.findHostDirectiveDefs(rootComponentDef, rootDirectives, hostDirectiveDefs);
14299
+ rootDirectives.push(rootComponentDef);
14300
+ }
14301
+ else {
14302
+ rootDirectives = [rootComponentDef];
14303
+ }
14215
14304
  const hostTNode = createRootComponentTNode(rootLView, hostRNode);
14216
- const componentView = createRootComponentView(hostTNode, hostRNode, this.componentDef, rootDirectives, rootLView, rendererFactory, hostRenderer);
14305
+ const componentView = createRootComponentView(hostTNode, hostRNode, rootComponentDef, rootDirectives, rootLView, rendererFactory, hostRenderer);
14217
14306
  tElementNode = getTNode(rootTView, HEADER_OFFSET);
14218
14307
  // TODO(crisbeto): in practice `hostRNode` should always be defined, but there are some tests
14219
14308
  // where the renderer is mocked out and `undefined` is returned. We should update the tests so
14220
14309
  // that this check can be removed.
14221
14310
  if (hostRNode) {
14222
- setRootNodeAttributes(hostRenderer, this.componentDef, hostRNode, rootSelectorOrNode);
14311
+ setRootNodeAttributes(hostRenderer, rootComponentDef, hostRNode, rootSelectorOrNode);
14223
14312
  }
14224
14313
  if (projectableNodes !== undefined) {
14225
14314
  projectNodes(tElementNode, this.ngContentSelectors, projectableNodes);
@@ -14227,7 +14316,7 @@ class ComponentFactory extends ComponentFactory$1 {
14227
14316
  // TODO: should LifecycleHooksFeature and other host features be generated by the compiler and
14228
14317
  // executed here?
14229
14318
  // Angular 5 reference: https://stackblitz.com/edit/lifecycle-hooks-vcref
14230
- component = createRootComponent(componentView, this.componentDef, rootDirectives, rootLView, [LifecycleHooksFeature]);
14319
+ component = createRootComponent(componentView, rootComponentDef, rootDirectives, hostDirectiveDefs, rootLView, [LifecycleHooksFeature]);
14231
14320
  renderView(rootTView, rootLView, null);
14232
14321
  }
14233
14322
  finally {
@@ -14327,8 +14416,7 @@ function createRootComponentView(tNode, rNode, rootComponentDef, rootDirectives,
14327
14416
  const viewRenderer = rendererFactory.createRenderer(rNode, rootComponentDef);
14328
14417
  const componentView = createLView(rootView, getOrCreateComponentTView(rootComponentDef), null, rootComponentDef.onPush ? 32 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, rootView[tNode.index], tNode, rendererFactory, viewRenderer, sanitizer || null, null, null);
14329
14418
  if (tView.firstCreatePass) {
14330
- diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, rootView), tView, rootComponentDef.type);
14331
- markAsComponentHost(tView, tNode, 0);
14419
+ markAsComponentHost(tView, tNode, rootDirectives.length - 1);
14332
14420
  }
14333
14421
  addToViewTree(rootView, componentView);
14334
14422
  // Store component view at node index, with node as the HOST
@@ -14350,12 +14438,12 @@ function applyRootComponentStyling(rootDirectives, tNode, rNode, hostRenderer) {
14350
14438
  * Creates a root component and sets it up with features and host bindings.Shared by
14351
14439
  * renderComponent() and ViewContainerRef.createComponent().
14352
14440
  */
14353
- function createRootComponent(componentView, rootComponentDef, rootDirectives, rootLView, hostFeatures) {
14441
+ function createRootComponent(componentView, rootComponentDef, rootDirectives, hostDirectiveDefs, rootLView, hostFeatures) {
14354
14442
  const rootTNode = getCurrentTNode();
14355
14443
  ngDevMode && assertDefined(rootTNode, 'tNode should have been already created');
14356
14444
  const tView = rootLView[TVIEW];
14357
14445
  const native = getNativeByTNode(rootTNode, rootLView);
14358
- initializeDirectives(tView, rootLView, rootTNode, rootDirectives, null);
14446
+ initializeDirectives(tView, rootLView, rootTNode, rootDirectives, null, hostDirectiveDefs);
14359
14447
  for (let i = 0; i < rootDirectives.length; i++) {
14360
14448
  const directiveIndex = rootTNode.directiveStart + i;
14361
14449
  const directiveInstance = getNodeInjectable(rootLView, tView, directiveIndex, rootTNode);
@@ -14676,7 +14764,7 @@ function ɵɵCopyDefinitionFeature(definition) {
14676
14764
  * found in the LICENSE file at https://angular.io/license
14677
14765
  */
14678
14766
  /**
14679
- * This feature add the host directives behavior to a directive definition by patching a
14767
+ * This feature adds the host directives behavior to a directive definition by patching a
14680
14768
  * function onto it. The expectation is that the runtime will invoke the function during
14681
14769
  * directive matching.
14682
14770
  *
@@ -14710,14 +14798,20 @@ function ɵɵHostDirectivesFeature(rawHostDirectives) {
14710
14798
  });
14711
14799
  };
14712
14800
  }
14713
- function findHostDirectiveDefs(matches, def, tView, lView, tNode) {
14714
- if (def.hostDirectives !== null) {
14715
- for (const hostDirectiveConfig of def.hostDirectives) {
14801
+ function findHostDirectiveDefs(currentDef, matchedDefs, hostDirectiveDefs) {
14802
+ if (currentDef.hostDirectives !== null) {
14803
+ for (const hostDirectiveConfig of currentDef.hostDirectives) {
14716
14804
  const hostDirectiveDef = getDirectiveDef(hostDirectiveConfig.directive);
14717
- // TODO(crisbeto): assert that the def exists.
14805
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
14806
+ validateHostDirective(hostDirectiveConfig, hostDirectiveDef, matchedDefs);
14807
+ }
14808
+ // We need to patch the `declaredInputs` so that
14809
+ // `ngOnChanges` can map the properties correctly.
14810
+ patchDeclaredInputs(hostDirectiveDef.declaredInputs, hostDirectiveConfig.inputs);
14718
14811
  // Host directives execute before the host so that its host bindings can be overwritten.
14719
- findHostDirectiveDefs(matches, hostDirectiveDef, tView, lView, tNode);
14720
- matches.push(hostDirectiveDef);
14812
+ findHostDirectiveDefs(hostDirectiveDef, matchedDefs, hostDirectiveDefs);
14813
+ hostDirectiveDefs.set(hostDirectiveDef, hostDirectiveConfig);
14814
+ matchedDefs.push(hostDirectiveDef);
14721
14815
  }
14722
14816
  }
14723
14817
  }
@@ -14735,6 +14829,90 @@ function bindingArrayToMap(bindings) {
14735
14829
  }
14736
14830
  return result;
14737
14831
  }
14832
+ /**
14833
+ * `ngOnChanges` has some leftover legacy ViewEngine behavior where the keys inside the
14834
+ * `SimpleChanges` event refer to the *declared* name of the input, not its public name or its
14835
+ * minified name. E.g. in `@Input('alias') foo: string`, the name in the `SimpleChanges` object
14836
+ * will always be `foo`, and not `alias` or the minified name of `foo` in apps using property
14837
+ * minification.
14838
+ *
14839
+ * This is achieved through the `DirectiveDef.declaredInputs` map that is constructed when the
14840
+ * definition is declared. When a property is written to the directive instance, the
14841
+ * `NgOnChangesFeature` will try to remap the property name being written to using the
14842
+ * `declaredInputs`.
14843
+ *
14844
+ * Since the host directive input remapping happens during directive matching, `declaredInputs`
14845
+ * won't contain the new alias that the input is available under. This function addresses the
14846
+ * issue by patching the host directive aliases to the `declaredInputs`. There is *not* a risk of
14847
+ * this patching accidentally introducing new inputs to the host directive, because `declaredInputs`
14848
+ * is used *only* by the `NgOnChangesFeature` when determining what name is used in the
14849
+ * `SimpleChanges` object which won't be reached if an input doesn't exist.
14850
+ */
14851
+ function patchDeclaredInputs(declaredInputs, exposedInputs) {
14852
+ for (const publicName in exposedInputs) {
14853
+ if (exposedInputs.hasOwnProperty(publicName)) {
14854
+ const remappedPublicName = exposedInputs[publicName];
14855
+ const privateName = declaredInputs[publicName];
14856
+ // We *technically* shouldn't be able to hit this case because we can't have multiple
14857
+ // inputs on the same property and we have validations against conflicting aliases in
14858
+ // `validateMappings`. If we somehow did, it would lead to `ngOnChanges` being invoked
14859
+ // with the wrong name so we have a non-user-friendly assertion here just in case.
14860
+ if ((typeof ngDevMode === 'undefined' || ngDevMode) &&
14861
+ declaredInputs.hasOwnProperty(remappedPublicName)) {
14862
+ assertEqual(declaredInputs[remappedPublicName], declaredInputs[publicName], `Conflicting host directive input alias ${publicName}.`);
14863
+ }
14864
+ declaredInputs[remappedPublicName] = privateName;
14865
+ }
14866
+ }
14867
+ }
14868
+ /**
14869
+ * Verifies that the host directive has been configured correctly.
14870
+ * @param hostDirectiveConfig Host directive configuration object.
14871
+ * @param directiveDef Directive definition of the host directive.
14872
+ * @param matchedDefs Directives that have been matched so far.
14873
+ */
14874
+ function validateHostDirective(hostDirectiveConfig, directiveDef, matchedDefs) {
14875
+ // TODO(crisbeto): implement more of these checks in the compiler.
14876
+ const type = hostDirectiveConfig.directive;
14877
+ if (directiveDef === null) {
14878
+ if (getComponentDef$1(type) !== null) {
14879
+ throw new RuntimeError(310 /* RuntimeErrorCode.HOST_DIRECTIVE_COMPONENT */, `Host directive ${type.name} cannot be a component.`);
14880
+ }
14881
+ throw new RuntimeError(307 /* RuntimeErrorCode.HOST_DIRECTIVE_UNRESOLVABLE */, `Could not resolve metadata for host directive ${type.name}. ` +
14882
+ `Make sure that the ${type.name} class is annotated with an @Directive decorator.`);
14883
+ }
14884
+ if (!directiveDef.standalone) {
14885
+ throw new RuntimeError(308 /* RuntimeErrorCode.HOST_DIRECTIVE_NOT_STANDALONE */, `Host directive ${directiveDef.type.name} must be standalone.`);
14886
+ }
14887
+ if (matchedDefs.indexOf(directiveDef) > -1) {
14888
+ throw new RuntimeError(309 /* RuntimeErrorCode.DUPLICATE_DIRECTITVE */, `Directive ${directiveDef.type.name} matches multiple times on the same element. ` +
14889
+ `Directives can only match an element once.`);
14890
+ }
14891
+ validateMappings('input', directiveDef, hostDirectiveConfig.inputs);
14892
+ validateMappings('output', directiveDef, hostDirectiveConfig.outputs);
14893
+ }
14894
+ /**
14895
+ * Checks that the host directive inputs/outputs configuration is valid.
14896
+ * @param bindingType Kind of binding that is being validated. Used in the error message.
14897
+ * @param def Definition of the host directive that is being validated against.
14898
+ * @param hostDirectiveDefs Host directive mapping object that shold be validated.
14899
+ */
14900
+ function validateMappings(bindingType, def, hostDirectiveDefs) {
14901
+ const className = def.type.name;
14902
+ const bindings = bindingType === 'input' ? def.inputs : def.outputs;
14903
+ for (const publicName in hostDirectiveDefs) {
14904
+ if (hostDirectiveDefs.hasOwnProperty(publicName)) {
14905
+ if (!bindings.hasOwnProperty(publicName)) {
14906
+ throw new RuntimeError(311 /* RuntimeErrorCode.HOST_DIRECTIVE_UNDEFINED_BINDING */, `Directive ${className} does not have an ${bindingType} with a public name of ${publicName}.`);
14907
+ }
14908
+ const remappedPublicName = hostDirectiveDefs[publicName];
14909
+ if (bindings.hasOwnProperty(remappedPublicName) &&
14910
+ bindings[remappedPublicName] !== publicName) {
14911
+ throw new RuntimeError(312 /* RuntimeErrorCode.HOST_DIRECTIVE_CONFLICTING_ALIAS */, `Cannot alias ${bindingType} ${publicName} of host directive ${className} to ${remappedPublicName}, because it already has a different ${bindingType} with the same public name.`);
14912
+ }
14913
+ }
14914
+ }
14915
+ }
14738
14916
 
14739
14917
  /**
14740
14918
  * @license
@@ -24637,7 +24815,7 @@ function generateStandaloneInDeclarationsError(type, location) {
24637
24815
  function verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRoot, importingModule) {
24638
24816
  if (verifiedNgModule.get(moduleType))
24639
24817
  return;
24640
- // skip verifications of standalone components, directives and pipes
24818
+ // skip verifications of standalone components, directives, and pipes
24641
24819
  if (isStandalone(moduleType))
24642
24820
  return;
24643
24821
  verifiedNgModule.set(moduleType, true);
@@ -25899,17 +26077,17 @@ class TestBedCompiler {
25899
26077
  getProviderOverrides(providers) {
25900
26078
  if (!providers || !providers.length || this.providerOverridesByToken.size === 0)
25901
26079
  return [];
25902
- // There are two flattening operations here. The inner flatten() operates on the metadata's
25903
- // providers and applies a mapping function which retrieves overrides for each incoming
25904
- // provider. The outer flatten() then flattens the produced overrides array. If this is not
25905
- // done, the array can contain other empty arrays (e.g. `[[], []]`) which leak into the
26080
+ // There are two flattening operations here. The inner flattenProviders() operates on the
26081
+ // metadata's providers and applies a mapping function which retrieves overrides for each
26082
+ // incoming provider. The outer flatten() then flattens the produced overrides array. If this is
26083
+ // not done, the array can contain other empty arrays (e.g. `[[], []]`) which leak into the
25906
26084
  // providers array and contaminate any error messages that might be generated.
25907
- return flatten(flatten(providers, (provider) => this.getSingleProviderOverrides(provider) || []));
26085
+ return flatten(flattenProviders(providers, (provider) => this.getSingleProviderOverrides(provider) || []));
25908
26086
  }
25909
26087
  getOverriddenProviders(providers) {
25910
26088
  if (!providers || !providers.length || this.providerOverridesByToken.size === 0)
25911
26089
  return [];
25912
- const flattenedProviders = flatten(providers);
26090
+ const flattenedProviders = flattenProviders(providers);
25913
26091
  const overrides = this.getProviderOverrides(flattenedProviders);
25914
26092
  const overriddenProviders = [...flattenedProviders, ...overrides];
25915
26093
  const final = [];
@@ -25973,18 +26151,36 @@ function isNgModule(value) {
25973
26151
  function maybeUnwrapFn(maybeFn) {
25974
26152
  return maybeFn instanceof Function ? maybeFn() : maybeFn;
25975
26153
  }
25976
- function flatten(values, mapFn) {
26154
+ function flatten(values) {
25977
26155
  const out = [];
25978
26156
  values.forEach(value => {
25979
26157
  if (Array.isArray(value)) {
25980
- out.push(...flatten(value, mapFn));
26158
+ out.push(...flatten(value));
25981
26159
  }
25982
26160
  else {
25983
- out.push(mapFn ? mapFn(value) : value);
26161
+ out.push(value);
25984
26162
  }
25985
26163
  });
25986
26164
  return out;
25987
26165
  }
26166
+ function identityFn(value) {
26167
+ return value;
26168
+ }
26169
+ function flattenProviders(providers, mapFn = identityFn) {
26170
+ const out = [];
26171
+ for (let provider of providers) {
26172
+ if (ɵisEnvironmentProviders(provider)) {
26173
+ provider = provider.ɵproviders;
26174
+ }
26175
+ if (Array.isArray(provider)) {
26176
+ out.push(...flattenProviders(provider, mapFn));
26177
+ }
26178
+ else {
26179
+ out.push(mapFn(provider));
26180
+ }
26181
+ }
26182
+ return out;
26183
+ }
25988
26184
  function getProviderField(provider, field) {
25989
26185
  return provider && typeof provider === 'object' && provider[field];
25990
26186
  }