@angular/core 19.2.0-rc.0 → 19.2.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.
- package/fesm2022/core.mjs +461 -269
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/primitives/event-dispatch.mjs +1 -1
- package/fesm2022/primitives/signals.mjs +1 -1
- package/fesm2022/rxjs-interop.mjs +1 -1
- package/fesm2022/testing.mjs +696 -5
- package/fesm2022/testing.mjs.map +1 -1
- package/index.d.ts +195 -19
- package/package.json +1 -1
- package/primitives/event-dispatch/index.d.ts +1 -1
- package/primitives/signals/index.d.ts +1 -1
- package/rxjs-interop/index.d.ts +1 -1
- package/schematics/bundles/{apply_import_manager-a930fcf1.js → apply_import_manager-a4e62ded.js} +2 -2
- package/schematics/bundles/checker-2eecc677.js +2 -2
- package/schematics/bundles/cleanup-unused-imports.js +4 -4
- package/schematics/bundles/{compiler_host-c280a924.js → compiler_host-f313eac9.js} +1 -1
- package/schematics/bundles/control-flow-migration.js +2 -2
- package/schematics/bundles/explicit-standalone-flag.js +4 -4
- package/schematics/bundles/{imports-abe29092.js → imports-31a38653.js} +1 -1
- package/schematics/bundles/index-3891dd55.js +2 -2
- package/schematics/bundles/{index-24a2ad1e.js → index-afc3f749.js} +2 -2
- package/schematics/bundles/inject-migration.js +6 -6
- package/schematics/bundles/{leading_space-d190b83b.js → leading_space-6e7a8ec6.js} +1 -1
- package/schematics/bundles/{migrate_ts_type_references-71b3a951.js → migrate_ts_type_references-1abf1f5f.js} +4 -4
- package/schematics/bundles/{ng_decorators-e699c081.js → ng_decorators-6878e227.js} +2 -2
- package/schematics/bundles/{nodes-a535b2be.js → nodes-ffdce442.js} +1 -1
- package/schematics/bundles/output-migration.js +5 -5
- package/schematics/bundles/pending-tasks.js +4 -4
- package/schematics/bundles/program-24da9092.js +10 -10
- package/schematics/bundles/{project_paths-b073c4d6.js → project_paths-64bc3947.js} +1 -1
- package/schematics/bundles/{project_tsconfig_paths-e9ccccbf.js → project_tsconfig_paths-6c9cde78.js} +1 -1
- package/schematics/bundles/{property_name-7c8433f5.js → property_name-42030525.js} +1 -1
- package/schematics/bundles/provide-initializer.js +4 -4
- package/schematics/bundles/route-lazy-loading.js +4 -4
- package/schematics/bundles/self-closing-tags-migration.js +6 -6
- package/schematics/bundles/signal-input-migration.js +7 -7
- package/schematics/bundles/signal-queries-migration.js +7 -7
- package/schematics/bundles/signals.js +7 -7
- package/schematics/bundles/standalone-migration.js +6 -6
- package/testing/index.d.ts +297 -1
package/fesm2022/core.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v19.2.0
|
|
2
|
+
* @license Angular v19.2.0
|
|
3
3
|
* (c) 2010-2024 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -967,8 +967,9 @@ function stringifyTypeFromDebugInfo(debugInfo) {
|
|
|
967
967
|
|
|
968
968
|
/** Called when directives inject each other (creating a circular dependency) */
|
|
969
969
|
function throwCyclicDependencyError(token, path) {
|
|
970
|
-
|
|
971
|
-
|
|
970
|
+
throw new RuntimeError(-200 /* RuntimeErrorCode.CYCLIC_DI_DEPENDENCY */, ngDevMode
|
|
971
|
+
? `Circular dependency in DI detected for ${token}${path ? `. Dependency path: ${path.join(' > ')} > ${token}` : ''}`
|
|
972
|
+
: token);
|
|
972
973
|
}
|
|
973
974
|
function throwMixedMultiProviderError() {
|
|
974
975
|
throw new Error(`Cannot mix multi providers and regular providers`);
|
|
@@ -7106,23 +7107,6 @@ function unwrapElementRef(value) {
|
|
|
7106
7107
|
return value instanceof ElementRef ? value.nativeElement : value;
|
|
7107
7108
|
}
|
|
7108
7109
|
|
|
7109
|
-
const markedFeatures = new Set();
|
|
7110
|
-
// tslint:disable:ban
|
|
7111
|
-
/**
|
|
7112
|
-
* A guarded `performance.mark` for feature marking.
|
|
7113
|
-
*
|
|
7114
|
-
* This method exists because while all supported browser and node.js version supported by Angular
|
|
7115
|
-
* support performance.mark API. This is not the case for other environments such as JSDOM and
|
|
7116
|
-
* Cloudflare workers.
|
|
7117
|
-
*/
|
|
7118
|
-
function performanceMarkFeature(feature) {
|
|
7119
|
-
if (markedFeatures.has(feature)) {
|
|
7120
|
-
return;
|
|
7121
|
-
}
|
|
7122
|
-
markedFeatures.add(feature);
|
|
7123
|
-
performance?.mark?.('mark_feature_usage', { detail: { feature } });
|
|
7124
|
-
}
|
|
7125
|
-
|
|
7126
7110
|
/**
|
|
7127
7111
|
* Checks if the given `value` is a reactive `Signal`.
|
|
7128
7112
|
*/
|
|
@@ -7145,7 +7129,6 @@ function ɵunwrapWritableSignal(value) {
|
|
|
7145
7129
|
* Create a `Signal` that can be set or updated directly.
|
|
7146
7130
|
*/
|
|
7147
7131
|
function signal(initialValue, options) {
|
|
7148
|
-
performanceMarkFeature('NgSignals');
|
|
7149
7132
|
const signalFn = createSignal$1(initialValue);
|
|
7150
7133
|
const node = signalFn[SIGNAL$1];
|
|
7151
7134
|
if (options?.equal) {
|
|
@@ -8625,6 +8608,23 @@ var TracingAction;
|
|
|
8625
8608
|
*/
|
|
8626
8609
|
const TracingService = new InjectionToken(ngDevMode ? 'TracingService' : '');
|
|
8627
8610
|
|
|
8611
|
+
const markedFeatures = new Set();
|
|
8612
|
+
// tslint:disable:ban
|
|
8613
|
+
/**
|
|
8614
|
+
* A guarded `performance.mark` for feature marking.
|
|
8615
|
+
*
|
|
8616
|
+
* This method exists because while all supported browser and node.js version supported by Angular
|
|
8617
|
+
* support performance.mark API. This is not the case for other environments such as JSDOM and
|
|
8618
|
+
* Cloudflare workers.
|
|
8619
|
+
*/
|
|
8620
|
+
function performanceMarkFeature(feature) {
|
|
8621
|
+
if (markedFeatures.has(feature)) {
|
|
8622
|
+
return;
|
|
8623
|
+
}
|
|
8624
|
+
markedFeatures.add(feature);
|
|
8625
|
+
performance?.mark?.('mark_feature_usage', { detail: { feature } });
|
|
8626
|
+
}
|
|
8627
|
+
|
|
8628
8628
|
/**
|
|
8629
8629
|
* Asserts that the current stack frame is not within a reactive context. Useful
|
|
8630
8630
|
* to disallow certain code from running inside a reactive context (see {@link toSignal}).
|
|
@@ -12559,15 +12559,6 @@ function executeTemplate(tView, lView, templateFn, rf, context) {
|
|
|
12559
12559
|
profiler(postHookType, context);
|
|
12560
12560
|
}
|
|
12561
12561
|
}
|
|
12562
|
-
/**
|
|
12563
|
-
* Creates directive instances.
|
|
12564
|
-
*/
|
|
12565
|
-
function createDirectivesInstancesInInstruction(tView, lView, tNode) {
|
|
12566
|
-
if (!getBindingsEnabled())
|
|
12567
|
-
return;
|
|
12568
|
-
attachPatchData(getNativeByTNode(tNode, lView), lView);
|
|
12569
|
-
createDirectivesInstances(tView, lView, tNode);
|
|
12570
|
-
}
|
|
12571
12562
|
/**
|
|
12572
12563
|
* Creates directive instances.
|
|
12573
12564
|
*/
|
|
@@ -12685,17 +12676,15 @@ function mapPropName(name) {
|
|
|
12685
12676
|
}
|
|
12686
12677
|
function elementPropertyInternal(tView, tNode, lView, propName, value, renderer, sanitizer, nativeOnly) {
|
|
12687
12678
|
ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
|
|
12688
|
-
|
|
12689
|
-
|
|
12690
|
-
|
|
12691
|
-
|
|
12692
|
-
|
|
12693
|
-
|
|
12694
|
-
if (ngDevMode) {
|
|
12695
|
-
setNgReflectProperties(lView, tView, tNode, dataValue, value);
|
|
12679
|
+
if (!nativeOnly) {
|
|
12680
|
+
const hasSetInput = setAllInputsForProperty(tNode, tView, lView, propName, value);
|
|
12681
|
+
if (hasSetInput) {
|
|
12682
|
+
isComponentHost(tNode) && markDirtyIfOnPush(lView, tNode.index);
|
|
12683
|
+
ngDevMode && setNgReflectProperties(lView, tView, tNode, propName, value);
|
|
12684
|
+
return; // Stop propcessing if we've matched at least one input.
|
|
12696
12685
|
}
|
|
12697
12686
|
}
|
|
12698
|
-
|
|
12687
|
+
if (tNode.type & 3 /* TNodeType.AnyRNode */) {
|
|
12699
12688
|
const element = getNativeByTNode(tNode, lView);
|
|
12700
12689
|
propName = mapPropName(propName);
|
|
12701
12690
|
if (ngDevMode) {
|
|
@@ -12744,14 +12733,25 @@ function setNgReflectProperty(lView, tNode, attrName, value) {
|
|
|
12744
12733
|
renderer.setValue(element, textContent);
|
|
12745
12734
|
}
|
|
12746
12735
|
}
|
|
12747
|
-
function setNgReflectProperties(lView, tView, tNode,
|
|
12748
|
-
if (tNode.type & (3 /* TNodeType.AnyRNode */ | 4 /* TNodeType.Container */)) {
|
|
12749
|
-
|
|
12750
|
-
|
|
12751
|
-
|
|
12752
|
-
|
|
12736
|
+
function setNgReflectProperties(lView, tView, tNode, publicName, value) {
|
|
12737
|
+
if (!(tNode.type & (3 /* TNodeType.AnyRNode */ | 4 /* TNodeType.Container */))) {
|
|
12738
|
+
return;
|
|
12739
|
+
}
|
|
12740
|
+
const inputConfig = tNode.inputs?.[publicName];
|
|
12741
|
+
const hostInputConfig = tNode.hostDirectiveInputs?.[publicName];
|
|
12742
|
+
if (hostInputConfig) {
|
|
12743
|
+
for (let i = 0; i < hostInputConfig.length; i += 2) {
|
|
12744
|
+
const index = hostInputConfig[i];
|
|
12745
|
+
const publicName = hostInputConfig[i + 1];
|
|
12746
|
+
const def = tView.data[index];
|
|
12747
|
+
setNgReflectProperty(lView, tNode, def.inputs[publicName][0], value);
|
|
12748
|
+
}
|
|
12749
|
+
}
|
|
12750
|
+
// Note: we set the private name of the input as the reflected property, not the public one.
|
|
12751
|
+
if (inputConfig) {
|
|
12752
|
+
for (const index of inputConfig) {
|
|
12753
12753
|
const def = tView.data[index];
|
|
12754
|
-
setNgReflectProperty(lView, tNode, def.inputs[
|
|
12754
|
+
setNgReflectProperty(lView, tNode, def.inputs[publicName][0], value);
|
|
12755
12755
|
}
|
|
12756
12756
|
}
|
|
12757
12757
|
}
|
|
@@ -12920,7 +12920,7 @@ function storePropertyBindingMetadata(tData, tNode, propertyName, bindingIndex,
|
|
|
12920
12920
|
// Since we don't have a concept of the "first update pass" we need to check for presence of the
|
|
12921
12921
|
// binding meta-data to decide if one should be stored (or if was stored already).
|
|
12922
12922
|
if (tData[bindingIndex] === null) {
|
|
12923
|
-
if (tNode.inputs
|
|
12923
|
+
if (!tNode.inputs?.[propertyName] && !tNode.hostDirectiveInputs?.[propertyName]) {
|
|
12924
12924
|
const propBindingIdxs = tNode.propertyBindings || (tNode.propertyBindings = []);
|
|
12925
12925
|
propBindingIdxs.push(bindingIndex);
|
|
12926
12926
|
let bindingMetadata = propertyName;
|
|
@@ -12955,23 +12955,88 @@ function handleError(lView, error) {
|
|
|
12955
12955
|
errorHandler && errorHandler.handleError(error);
|
|
12956
12956
|
}
|
|
12957
12957
|
/**
|
|
12958
|
-
* Set
|
|
12958
|
+
* Set all directive inputs with the specific public name on the node.
|
|
12959
12959
|
*
|
|
12960
|
-
* @param
|
|
12961
|
-
* @param
|
|
12962
|
-
* @param
|
|
12963
|
-
*
|
|
12960
|
+
* @param tNode TNode on which the input is being set.
|
|
12961
|
+
* @param tView Current TView
|
|
12962
|
+
* @param lView `LView` which contains the directives.
|
|
12963
|
+
* @param publicName Public name of the input being set.
|
|
12964
|
+
* @param value Value to set.
|
|
12965
|
+
*/
|
|
12966
|
+
function setAllInputsForProperty(tNode, tView, lView, publicName, value) {
|
|
12967
|
+
const inputs = tNode.inputs?.[publicName];
|
|
12968
|
+
const hostDirectiveInputs = tNode.hostDirectiveInputs?.[publicName];
|
|
12969
|
+
let hasMatch = false;
|
|
12970
|
+
if (hostDirectiveInputs) {
|
|
12971
|
+
for (let i = 0; i < hostDirectiveInputs.length; i += 2) {
|
|
12972
|
+
const index = hostDirectiveInputs[i];
|
|
12973
|
+
ngDevMode && assertIndexInRange(lView, index);
|
|
12974
|
+
const publicName = hostDirectiveInputs[i + 1];
|
|
12975
|
+
const def = tView.data[index];
|
|
12976
|
+
writeToDirectiveInput(def, lView[index], publicName, value);
|
|
12977
|
+
hasMatch = true;
|
|
12978
|
+
}
|
|
12979
|
+
}
|
|
12980
|
+
if (inputs) {
|
|
12981
|
+
for (const index of inputs) {
|
|
12982
|
+
ngDevMode && assertIndexInRange(lView, index);
|
|
12983
|
+
const instance = lView[index];
|
|
12984
|
+
const def = tView.data[index];
|
|
12985
|
+
writeToDirectiveInput(def, instance, publicName, value);
|
|
12986
|
+
hasMatch = true;
|
|
12987
|
+
}
|
|
12988
|
+
}
|
|
12989
|
+
return hasMatch;
|
|
12990
|
+
}
|
|
12991
|
+
/**
|
|
12992
|
+
* Sets an input value only on a specific directive and its host directives.
|
|
12993
|
+
* @param tNode TNode on which the input is being set.
|
|
12994
|
+
* @param tView Current TView
|
|
12995
|
+
* @param lView `LView` which contains the directives.
|
|
12996
|
+
* @param target Directive on which to set the input.
|
|
12997
|
+
* @param publicName Public name of the input being set.
|
|
12964
12998
|
* @param value Value to set.
|
|
12965
12999
|
*/
|
|
12966
|
-
function
|
|
12967
|
-
|
|
12968
|
-
|
|
12969
|
-
|
|
12970
|
-
|
|
12971
|
-
|
|
12972
|
-
|
|
12973
|
-
|
|
13000
|
+
function setDirectiveInput(tNode, tView, lView, target, publicName, value) {
|
|
13001
|
+
let hostIndex = null;
|
|
13002
|
+
let hostDirectivesStart = null;
|
|
13003
|
+
let hostDirectivesEnd = null;
|
|
13004
|
+
let hasSet = false;
|
|
13005
|
+
if (ngDevMode && !tNode.directiveToIndex?.has(target.type)) {
|
|
13006
|
+
throw new Error(`Node does not have a directive with type ${target.type.name}`);
|
|
13007
|
+
}
|
|
13008
|
+
const data = tNode.directiveToIndex.get(target.type);
|
|
13009
|
+
if (typeof data === 'number') {
|
|
13010
|
+
hostIndex = data;
|
|
13011
|
+
}
|
|
13012
|
+
else {
|
|
13013
|
+
[hostIndex, hostDirectivesStart, hostDirectivesEnd] = data;
|
|
13014
|
+
}
|
|
13015
|
+
if (hostDirectivesStart !== null &&
|
|
13016
|
+
hostDirectivesEnd !== null &&
|
|
13017
|
+
tNode.hostDirectiveInputs?.hasOwnProperty(publicName)) {
|
|
13018
|
+
const hostDirectiveInputs = tNode.hostDirectiveInputs[publicName];
|
|
13019
|
+
for (let i = 0; i < hostDirectiveInputs.length; i += 2) {
|
|
13020
|
+
const index = hostDirectiveInputs[i];
|
|
13021
|
+
if (index >= hostDirectivesStart && index <= hostDirectivesEnd) {
|
|
13022
|
+
ngDevMode && assertIndexInRange(lView, index);
|
|
13023
|
+
const def = tView.data[index];
|
|
13024
|
+
const hostDirectivePublicName = hostDirectiveInputs[i + 1];
|
|
13025
|
+
writeToDirectiveInput(def, lView[index], hostDirectivePublicName, value);
|
|
13026
|
+
hasSet = true;
|
|
13027
|
+
}
|
|
13028
|
+
else if (index > hostDirectivesEnd) {
|
|
13029
|
+
// Directives here are in ascending order so we can stop looking once we're past the range.
|
|
13030
|
+
break;
|
|
13031
|
+
}
|
|
13032
|
+
}
|
|
13033
|
+
}
|
|
13034
|
+
if (hostIndex !== null) {
|
|
13035
|
+
ngDevMode && assertIndexInRange(lView, hostIndex);
|
|
13036
|
+
writeToDirectiveInput(target, lView[hostIndex], publicName, value);
|
|
13037
|
+
hasSet = true;
|
|
12974
13038
|
}
|
|
13039
|
+
return hasSet;
|
|
12975
13040
|
}
|
|
12976
13041
|
|
|
12977
13042
|
function renderComponent(hostLView, componentHostIdx) {
|
|
@@ -15624,9 +15689,12 @@ function createTNode(tView, tParent, type, index, value, attrs) {
|
|
|
15624
15689
|
attrs: attrs,
|
|
15625
15690
|
mergedAttrs: null,
|
|
15626
15691
|
localNames: null,
|
|
15627
|
-
initialInputs:
|
|
15692
|
+
initialInputs: null,
|
|
15628
15693
|
inputs: null,
|
|
15694
|
+
hostDirectiveInputs: null,
|
|
15629
15695
|
outputs: null,
|
|
15696
|
+
hostDirectiveOutputs: null,
|
|
15697
|
+
directiveToIndex: null,
|
|
15630
15698
|
tView: null,
|
|
15631
15699
|
next: null,
|
|
15632
15700
|
prev: null,
|
|
@@ -15934,7 +16002,7 @@ function createIcuIterator(tIcu, lView) {
|
|
|
15934
16002
|
* - the `b` char which indicates that the lookup should start from the `document.body`
|
|
15935
16003
|
* - the `h` char to start lookup from the component host node (`lView[HOST]`)
|
|
15936
16004
|
*/
|
|
15937
|
-
const REF_EXTRACTOR_REGEXP = new RegExp(`^(\\d+)*(${REFERENCE_NODE_BODY}|${REFERENCE_NODE_HOST})*(.*)`);
|
|
16005
|
+
const REF_EXTRACTOR_REGEXP = /* @__PURE__ */ new RegExp(`^(\\d+)*(${REFERENCE_NODE_BODY}|${REFERENCE_NODE_HOST})*(.*)`);
|
|
15938
16006
|
/**
|
|
15939
16007
|
* Helper function that takes a reference node location and a set of navigation steps
|
|
15940
16008
|
* (from the reference node) to a target node and outputs a string that represents
|
|
@@ -16814,6 +16882,18 @@ function removeDehydratedViews(lContainer) {
|
|
|
16814
16882
|
// once again in case a `ViewContainerRef` is created later).
|
|
16815
16883
|
lContainer[DEHYDRATED_VIEWS] = retainedViews;
|
|
16816
16884
|
}
|
|
16885
|
+
function removeDehydratedViewList(deferBlock) {
|
|
16886
|
+
const { lContainer } = deferBlock;
|
|
16887
|
+
const dehydratedViews = lContainer[DEHYDRATED_VIEWS];
|
|
16888
|
+
if (dehydratedViews === null)
|
|
16889
|
+
return;
|
|
16890
|
+
const parentLView = lContainer[PARENT];
|
|
16891
|
+
const renderer = parentLView[RENDERER];
|
|
16892
|
+
for (const view of dehydratedViews) {
|
|
16893
|
+
removeDehydratedView(view, renderer);
|
|
16894
|
+
ngDevMode && ngDevMode.dehydratedViewsRemoved++;
|
|
16895
|
+
}
|
|
16896
|
+
}
|
|
16817
16897
|
/**
|
|
16818
16898
|
* Helper function to remove all nodes from a dehydrated view.
|
|
16819
16899
|
*/
|
|
@@ -17453,14 +17533,22 @@ function ɵɵinvalidFactory() {
|
|
|
17453
17533
|
* Resolve the matched directives on a node.
|
|
17454
17534
|
*/
|
|
17455
17535
|
function resolveDirectives(tView, lView, tNode, localRefs, directiveMatcher) {
|
|
17456
|
-
// Please make sure to have explicit type for `exportsMap`. Inferred type triggers bug in
|
|
17457
|
-
// tsickle.
|
|
17536
|
+
// Please make sure to have explicit type for `exportsMap`. Inferred type triggers bug in tsickle.
|
|
17458
17537
|
ngDevMode && assertFirstCreatePass(tView);
|
|
17459
17538
|
const exportsMap = localRefs === null ? null : { '': -1 };
|
|
17460
17539
|
const matchedDirectiveDefs = directiveMatcher(tView, tNode);
|
|
17461
17540
|
if (matchedDirectiveDefs !== null) {
|
|
17462
|
-
|
|
17463
|
-
|
|
17541
|
+
let directiveDefs;
|
|
17542
|
+
let hostDirectiveDefs = null;
|
|
17543
|
+
let hostDirectiveRanges = null;
|
|
17544
|
+
const hostDirectiveResolution = resolveHostDirectives(matchedDirectiveDefs);
|
|
17545
|
+
if (hostDirectiveResolution === null) {
|
|
17546
|
+
directiveDefs = matchedDirectiveDefs;
|
|
17547
|
+
}
|
|
17548
|
+
else {
|
|
17549
|
+
[directiveDefs, hostDirectiveDefs, hostDirectiveRanges] = hostDirectiveResolution;
|
|
17550
|
+
}
|
|
17551
|
+
initializeDirectives(tView, lView, tNode, directiveDefs, exportsMap, hostDirectiveDefs, hostDirectiveRanges);
|
|
17464
17552
|
}
|
|
17465
17553
|
if (exportsMap !== null && localRefs !== null) {
|
|
17466
17554
|
cacheMatchingLocalNames(tNode, localRefs, exportsMap);
|
|
@@ -17479,40 +17567,63 @@ function cacheMatchingLocalNames(tNode, localRefs, exportsMap) {
|
|
|
17479
17567
|
localNames.push(localRefs[i], index);
|
|
17480
17568
|
}
|
|
17481
17569
|
}
|
|
17482
|
-
function resolveHostDirectives(
|
|
17483
|
-
|
|
17570
|
+
function resolveHostDirectives(matches) {
|
|
17571
|
+
let componentDef = null;
|
|
17572
|
+
let hasHostDirectives = false;
|
|
17573
|
+
for (let i = 0; i < matches.length; i++) {
|
|
17574
|
+
const def = matches[i];
|
|
17575
|
+
if (i === 0 && isComponentDef(def)) {
|
|
17576
|
+
componentDef = def;
|
|
17577
|
+
}
|
|
17578
|
+
if (def.findHostDirectiveDefs !== null) {
|
|
17579
|
+
hasHostDirectives = true;
|
|
17580
|
+
break;
|
|
17581
|
+
}
|
|
17582
|
+
}
|
|
17583
|
+
if (!hasHostDirectives) {
|
|
17584
|
+
return null;
|
|
17585
|
+
}
|
|
17586
|
+
let allDirectiveDefs = null;
|
|
17484
17587
|
let hostDirectiveDefs = null;
|
|
17588
|
+
let hostDirectiveRanges = null;
|
|
17589
|
+
// Components are inserted at the front of the matches array so that their lifecycle
|
|
17590
|
+
// hooks run before any directive lifecycle hooks. This appears to be for ViewEngine
|
|
17591
|
+
// compatibility. This logic doesn't make sense with host directives, because it
|
|
17592
|
+
// would allow the host directives to undo any overrides the host may have made.
|
|
17593
|
+
// To handle this case, the host directives of components are inserted at the beginning
|
|
17594
|
+
// of the array, followed by the component. As such, the insertion order is as follows:
|
|
17595
|
+
// 1. Host directives belonging to the selector-matched component.
|
|
17596
|
+
// 2. Selector-matched component.
|
|
17597
|
+
// 3. Host directives belonging to selector-matched directives.
|
|
17598
|
+
// 4. Selector-matched dir
|
|
17485
17599
|
for (const def of matches) {
|
|
17486
17600
|
if (def.findHostDirectiveDefs !== null) {
|
|
17487
|
-
|
|
17601
|
+
allDirectiveDefs ??= [];
|
|
17488
17602
|
hostDirectiveDefs ??= new Map();
|
|
17489
|
-
|
|
17490
|
-
|
|
17491
|
-
// compatibility. This logic doesn't make sense with host directives, because it
|
|
17492
|
-
// would allow the host directives to undo any overrides the host may have made.
|
|
17493
|
-
// To handle this case, the host directives of components are inserted at the beginning
|
|
17494
|
-
// of the array, followed by the component. As such, the insertion order is as follows:
|
|
17495
|
-
// 1. Host directives belonging to the selector-matched component.
|
|
17496
|
-
// 2. Selector-matched component.
|
|
17497
|
-
// 3. Host directives belonging to selector-matched directives.
|
|
17498
|
-
// 4. Selector-matched directives.
|
|
17499
|
-
def.findHostDirectiveDefs(def, allDirectiveDefs, hostDirectiveDefs);
|
|
17603
|
+
hostDirectiveRanges ??= new Map();
|
|
17604
|
+
resolveHostDirectivesForDef(def, allDirectiveDefs, hostDirectiveRanges, hostDirectiveDefs);
|
|
17500
17605
|
}
|
|
17501
|
-
|
|
17606
|
+
// Component definition needs to be pushed early to maintain the correct ordering.
|
|
17607
|
+
if (def === componentDef) {
|
|
17608
|
+
allDirectiveDefs ??= [];
|
|
17502
17609
|
allDirectiveDefs.push(def);
|
|
17503
|
-
markAsComponentHost(tView, tNode, allDirectiveDefs.length - 1);
|
|
17504
17610
|
}
|
|
17505
17611
|
}
|
|
17506
|
-
if (
|
|
17507
|
-
allDirectiveDefs.push(...matches.slice(1));
|
|
17508
|
-
|
|
17509
|
-
|
|
17510
|
-
allDirectiveDefs.push(...matches);
|
|
17511
|
-
}
|
|
17512
|
-
if (ngDevMode) {
|
|
17513
|
-
assertNoDuplicateDirectives(allDirectiveDefs);
|
|
17612
|
+
if (allDirectiveDefs !== null) {
|
|
17613
|
+
allDirectiveDefs.push(...(componentDef === null ? matches : matches.slice(1)));
|
|
17614
|
+
ngDevMode && assertNoDuplicateDirectives(allDirectiveDefs);
|
|
17615
|
+
return [allDirectiveDefs, hostDirectiveDefs, hostDirectiveRanges];
|
|
17514
17616
|
}
|
|
17515
|
-
return
|
|
17617
|
+
return null;
|
|
17618
|
+
}
|
|
17619
|
+
function resolveHostDirectivesForDef(def, allDirectiveDefs, hostDirectiveRanges, hostDirectiveDefs) {
|
|
17620
|
+
ngDevMode && assertDefined(def.findHostDirectiveDefs, 'Expected host directive resolve function');
|
|
17621
|
+
const start = allDirectiveDefs.length;
|
|
17622
|
+
// TODO(pk): probably could return matches instead of taking in an array to fill in?
|
|
17623
|
+
def.findHostDirectiveDefs(def, allDirectiveDefs, hostDirectiveDefs);
|
|
17624
|
+
// Note that these indexes are within the offset by `directiveStart`. We can't do the
|
|
17625
|
+
// offsetting here, because `directiveStart` hasn't been initialized on the TNode yet.
|
|
17626
|
+
hostDirectiveRanges.set(def, [start, allDirectiveDefs.length - 1]);
|
|
17516
17627
|
}
|
|
17517
17628
|
/**
|
|
17518
17629
|
* Marks a given TNode as a component's host. This consists of:
|
|
@@ -17526,37 +17637,62 @@ function markAsComponentHost(tView, hostTNode, componentOffset) {
|
|
|
17526
17637
|
(tView.components ??= []).push(hostTNode.index);
|
|
17527
17638
|
}
|
|
17528
17639
|
/** Initializes the data structures necessary for a list of directives to be instantiated. */
|
|
17529
|
-
function initializeDirectives(tView, lView, tNode, directives, exportsMap, hostDirectiveDefs) {
|
|
17640
|
+
function initializeDirectives(tView, lView, tNode, directives, exportsMap, hostDirectiveDefs, hostDirectiveRanges) {
|
|
17530
17641
|
ngDevMode && assertFirstCreatePass(tView);
|
|
17642
|
+
const directivesLength = directives.length;
|
|
17643
|
+
let hasSeenComponent = false;
|
|
17531
17644
|
// Publishes the directive types to DI so they can be injected. Needs to
|
|
17532
17645
|
// happen in a separate pass before the TNode flags have been initialized.
|
|
17533
|
-
for (let i = 0; i <
|
|
17534
|
-
|
|
17646
|
+
for (let i = 0; i < directivesLength; i++) {
|
|
17647
|
+
const def = directives[i];
|
|
17648
|
+
if (!hasSeenComponent && isComponentDef(def)) {
|
|
17649
|
+
hasSeenComponent = true;
|
|
17650
|
+
markAsComponentHost(tView, tNode, i);
|
|
17651
|
+
}
|
|
17652
|
+
diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, lView), tView, def.type);
|
|
17535
17653
|
}
|
|
17536
|
-
initTNodeFlags(tNode, tView.data.length,
|
|
17654
|
+
initTNodeFlags(tNode, tView.data.length, directivesLength);
|
|
17537
17655
|
// When the same token is provided by several directives on the same node, some rules apply in
|
|
17538
17656
|
// the viewEngine:
|
|
17539
17657
|
// - viewProviders have priority over providers
|
|
17540
17658
|
// - the last directive in NgModule.declarations has priority over the previous one
|
|
17541
17659
|
// So to match these rules, the order in which providers are added in the arrays is very
|
|
17542
17660
|
// important.
|
|
17543
|
-
for (let i = 0; i <
|
|
17661
|
+
for (let i = 0; i < directivesLength; i++) {
|
|
17544
17662
|
const def = directives[i];
|
|
17545
17663
|
if (def.providersResolver)
|
|
17546
17664
|
def.providersResolver(def);
|
|
17547
17665
|
}
|
|
17548
17666
|
let preOrderHooksFound = false;
|
|
17549
17667
|
let preOrderCheckHooksFound = false;
|
|
17550
|
-
let directiveIdx = allocExpando(tView, lView,
|
|
17668
|
+
let directiveIdx = allocExpando(tView, lView, directivesLength, null);
|
|
17551
17669
|
ngDevMode &&
|
|
17552
17670
|
assertSame(directiveIdx, tNode.directiveStart, 'TNode.directiveStart should point to just allocated space');
|
|
17553
|
-
|
|
17671
|
+
// If there's at least one directive, we'll have to track it so initialize the map.
|
|
17672
|
+
if (directivesLength > 0) {
|
|
17673
|
+
tNode.directiveToIndex = new Map();
|
|
17674
|
+
}
|
|
17675
|
+
for (let i = 0; i < directivesLength; i++) {
|
|
17554
17676
|
const def = directives[i];
|
|
17555
17677
|
// Merge the attrs in the order of matches. This assumes that the first directive is the
|
|
17556
17678
|
// component itself, so that the component has the least priority.
|
|
17557
17679
|
tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, def.hostAttrs);
|
|
17558
17680
|
configureViewWithDirective(tView, tNode, lView, directiveIdx, def);
|
|
17559
17681
|
saveNameToExportMap(directiveIdx, def, exportsMap);
|
|
17682
|
+
// If a directive has host directives, we need to track both its index and the range within
|
|
17683
|
+
// the host directives are declared. Host directives are not tracked, but should be resolved
|
|
17684
|
+
// by looking up the host and getting its indexes from there.
|
|
17685
|
+
if (hostDirectiveRanges !== null && hostDirectiveRanges.has(def)) {
|
|
17686
|
+
const [start, end] = hostDirectiveRanges.get(def);
|
|
17687
|
+
tNode.directiveToIndex.set(def.type, [
|
|
17688
|
+
directiveIdx,
|
|
17689
|
+
start + tNode.directiveStart,
|
|
17690
|
+
end + tNode.directiveStart,
|
|
17691
|
+
]);
|
|
17692
|
+
}
|
|
17693
|
+
else if (hostDirectiveDefs === null || !hostDirectiveDefs.has(def)) {
|
|
17694
|
+
tNode.directiveToIndex.set(def.type, directiveIdx);
|
|
17695
|
+
}
|
|
17560
17696
|
if (def.contentQueries !== null)
|
|
17561
17697
|
tNode.flags |= 4 /* TNodeFlags.hasContentQuery */;
|
|
17562
17698
|
if (def.hostBindings !== null || def.hostAttrs !== null || def.hostVars !== 0)
|
|
@@ -17584,87 +17720,84 @@ function initializeDirectives(tView, lView, tNode, directives, exportsMap, hostD
|
|
|
17584
17720
|
* Initializes data structures required to work with directive inputs and outputs.
|
|
17585
17721
|
* Initialization is done for all directives matched on a given TNode.
|
|
17586
17722
|
*/
|
|
17587
|
-
function initializeInputAndOutputAliases(tView, tNode,
|
|
17723
|
+
function initializeInputAndOutputAliases(tView, tNode, hostDirectiveDefs) {
|
|
17588
17724
|
ngDevMode && assertFirstCreatePass(tView);
|
|
17589
|
-
|
|
17590
|
-
|
|
17591
|
-
|
|
17592
|
-
|
|
17593
|
-
|
|
17594
|
-
|
|
17595
|
-
let outputsStore = null;
|
|
17596
|
-
for (let directiveIndex = start; directiveIndex < end; directiveIndex++) {
|
|
17597
|
-
const directiveDef = tViewData[directiveIndex];
|
|
17598
|
-
const aliasData = hostDirectiveDefinitionMap
|
|
17599
|
-
? hostDirectiveDefinitionMap.get(directiveDef)
|
|
17600
|
-
: null;
|
|
17601
|
-
const aliasedInputs = aliasData ? aliasData.inputs : null;
|
|
17602
|
-
const aliasedOutputs = aliasData ? aliasData.outputs : null;
|
|
17603
|
-
inputsStore = captureNodeBindings(0 /* CaptureNodeBindingMode.Inputs */, directiveDef.inputs, directiveIndex, inputsStore, aliasedInputs);
|
|
17604
|
-
outputsStore = captureNodeBindings(1 /* CaptureNodeBindingMode.Outputs */, directiveDef.outputs, directiveIndex, outputsStore, aliasedOutputs);
|
|
17605
|
-
// Do not use unbound attributes as inputs to structural directives, since structural
|
|
17606
|
-
// directive inputs can only be set using microsyntax (e.g. `<div *dir="exp">`).
|
|
17607
|
-
const initialInputs = inputsStore !== null && tNodeAttrs !== null && !isInlineTemplate(tNode)
|
|
17608
|
-
? generateInitialInputs(inputsStore, directiveIndex, tNodeAttrs)
|
|
17609
|
-
: null;
|
|
17610
|
-
inputsFromAttrs.push(initialInputs);
|
|
17611
|
-
}
|
|
17612
|
-
if (inputsStore !== null) {
|
|
17613
|
-
if (inputsStore.hasOwnProperty('class')) {
|
|
17614
|
-
tNode.flags |= 8 /* TNodeFlags.hasClassInput */;
|
|
17725
|
+
for (let index = tNode.directiveStart; index < tNode.directiveEnd; index++) {
|
|
17726
|
+
const directiveDef = tView.data[index];
|
|
17727
|
+
if (hostDirectiveDefs === null || !hostDirectiveDefs.has(directiveDef)) {
|
|
17728
|
+
setupSelectorMatchedInputsOrOutputs(0 /* BindingType.Inputs */, tNode, directiveDef, index);
|
|
17729
|
+
setupSelectorMatchedInputsOrOutputs(1 /* BindingType.Outputs */, tNode, directiveDef, index);
|
|
17730
|
+
setupInitialInputs(tNode, index, false);
|
|
17615
17731
|
}
|
|
17616
|
-
|
|
17617
|
-
|
|
17732
|
+
else {
|
|
17733
|
+
const hostDirectiveDef = hostDirectiveDefs.get(directiveDef);
|
|
17734
|
+
setupHostDirectiveInputsOrOutputs(0 /* BindingType.Inputs */, tNode, hostDirectiveDef, index);
|
|
17735
|
+
setupHostDirectiveInputsOrOutputs(1 /* BindingType.Outputs */, tNode, hostDirectiveDef, index);
|
|
17736
|
+
setupInitialInputs(tNode, index, true);
|
|
17618
17737
|
}
|
|
17619
17738
|
}
|
|
17620
|
-
tNode.initialInputs = inputsFromAttrs;
|
|
17621
|
-
tNode.inputs = inputsStore;
|
|
17622
|
-
tNode.outputs = outputsStore;
|
|
17623
17739
|
}
|
|
17624
|
-
|
|
17625
|
-
|
|
17626
|
-
|
|
17627
|
-
|
|
17628
|
-
|
|
17629
|
-
|
|
17630
|
-
|
|
17631
|
-
|
|
17632
|
-
|
|
17633
|
-
|
|
17634
|
-
|
|
17635
|
-
|
|
17636
|
-
|
|
17637
|
-
|
|
17638
|
-
|
|
17639
|
-
|
|
17640
|
-
let finalPublicName = publicName;
|
|
17641
|
-
if (hostDirectiveAliasMap !== null) {
|
|
17642
|
-
// If there is no mapping, it's not part of the allowlist and this input/output
|
|
17643
|
-
// is not captured and should be ignored.
|
|
17644
|
-
if (!hostDirectiveAliasMap.hasOwnProperty(publicName)) {
|
|
17645
|
-
continue;
|
|
17740
|
+
/**
|
|
17741
|
+
* Sets up the input/output bindings for a directive that was matched in the template through its
|
|
17742
|
+
* selector. This method is called repeatedly to build up all of the available inputs on a node.
|
|
17743
|
+
*
|
|
17744
|
+
* @param mode Whether inputs or outputs are being contructed.
|
|
17745
|
+
* @param tNode Node on which the bindings are being set up.
|
|
17746
|
+
* @param def Directive definition for which the bindings are being set up.
|
|
17747
|
+
* @param directiveIndex Index at which the directive instance will be stored in the LView.
|
|
17748
|
+
*/
|
|
17749
|
+
function setupSelectorMatchedInputsOrOutputs(mode, tNode, def, directiveIndex) {
|
|
17750
|
+
const aliasMap = mode === 0 /* BindingType.Inputs */ ? def.inputs : def.outputs;
|
|
17751
|
+
for (const publicName in aliasMap) {
|
|
17752
|
+
if (aliasMap.hasOwnProperty(publicName)) {
|
|
17753
|
+
let bindings;
|
|
17754
|
+
if (mode === 0 /* BindingType.Inputs */) {
|
|
17755
|
+
bindings = tNode.inputs ??= {};
|
|
17646
17756
|
}
|
|
17647
|
-
|
|
17648
|
-
|
|
17649
|
-
|
|
17650
|
-
|
|
17757
|
+
else {
|
|
17758
|
+
bindings = tNode.outputs ??= {};
|
|
17759
|
+
}
|
|
17760
|
+
bindings[publicName] ??= [];
|
|
17761
|
+
bindings[publicName].push(directiveIndex);
|
|
17762
|
+
setShadowStylingInputFlags(tNode, publicName);
|
|
17651
17763
|
}
|
|
17652
|
-
|
|
17653
|
-
|
|
17764
|
+
}
|
|
17765
|
+
}
|
|
17766
|
+
/**
|
|
17767
|
+
* Sets up input/output bindings that were defined through host directives on a specific node.
|
|
17768
|
+
* @param mode Whether inputs or outputs are being contructed.
|
|
17769
|
+
* @param tNode Node on which the bindings are being set up.
|
|
17770
|
+
* @param config Host directive definition that is being set up.
|
|
17771
|
+
* @param directiveIndex Index at which the directive instance will be stored in the LView.
|
|
17772
|
+
*/
|
|
17773
|
+
function setupHostDirectiveInputsOrOutputs(mode, tNode, config, directiveIndex) {
|
|
17774
|
+
const aliasMap = mode === 0 /* BindingType.Inputs */ ? config.inputs : config.outputs;
|
|
17775
|
+
for (const initialName in aliasMap) {
|
|
17776
|
+
if (aliasMap.hasOwnProperty(initialName)) {
|
|
17777
|
+
const publicName = aliasMap[initialName];
|
|
17778
|
+
let bindings;
|
|
17779
|
+
if (mode === 0 /* BindingType.Inputs */) {
|
|
17780
|
+
bindings = tNode.hostDirectiveInputs ??= {};
|
|
17781
|
+
}
|
|
17782
|
+
else {
|
|
17783
|
+
bindings = tNode.hostDirectiveOutputs ??= {};
|
|
17784
|
+
}
|
|
17785
|
+
bindings[publicName] ??= [];
|
|
17786
|
+
bindings[publicName].push(directiveIndex, initialName);
|
|
17787
|
+
setShadowStylingInputFlags(tNode, publicName);
|
|
17654
17788
|
}
|
|
17655
17789
|
}
|
|
17656
|
-
return bindingsResult;
|
|
17657
17790
|
}
|
|
17658
|
-
function
|
|
17659
|
-
if (
|
|
17660
|
-
|
|
17791
|
+
function setShadowStylingInputFlags(tNode, publicName) {
|
|
17792
|
+
if (publicName === 'class') {
|
|
17793
|
+
tNode.flags |= 8 /* TNodeFlags.hasClassInput */;
|
|
17661
17794
|
}
|
|
17662
|
-
else {
|
|
17663
|
-
|
|
17795
|
+
else if (publicName === 'style') {
|
|
17796
|
+
tNode.flags |= 16 /* TNodeFlags.hasStyleInput */;
|
|
17664
17797
|
}
|
|
17665
17798
|
}
|
|
17666
17799
|
/**
|
|
17667
|
-
*
|
|
17800
|
+
* Sets up the initialInputData for a node and stores it in the template's static storage
|
|
17668
17801
|
* so subsequent template invocations don't have to recalculate it.
|
|
17669
17802
|
*
|
|
17670
17803
|
* initialInputData is an array containing values that need to be set as input properties
|
|
@@ -17674,11 +17807,21 @@ function addPropertyBinding(bindings, directiveIndex, publicName, lookupName) {
|
|
|
17674
17807
|
*
|
|
17675
17808
|
* <my-component name="Bess"></my-component>
|
|
17676
17809
|
*
|
|
17677
|
-
* @param
|
|
17810
|
+
* @param tNode TNode on which to set up the initial inputs.
|
|
17678
17811
|
* @param directiveIndex Index of the directive that is currently being processed.
|
|
17679
|
-
* @param attrs Static attrs on this node.
|
|
17680
17812
|
*/
|
|
17681
|
-
function
|
|
17813
|
+
function setupInitialInputs(tNode, directiveIndex, isHostDirective) {
|
|
17814
|
+
const { attrs, inputs, hostDirectiveInputs } = tNode;
|
|
17815
|
+
if (attrs === null ||
|
|
17816
|
+
(!isHostDirective && inputs === null) ||
|
|
17817
|
+
(isHostDirective && hostDirectiveInputs === null) ||
|
|
17818
|
+
// Do not use unbound attributes as inputs to structural directives, since structural
|
|
17819
|
+
// directive inputs can only be set using microsyntax (e.g. `<div *dir="exp">`).
|
|
17820
|
+
isInlineTemplate(tNode)) {
|
|
17821
|
+
tNode.initialInputs ??= [];
|
|
17822
|
+
tNode.initialInputs.push(null);
|
|
17823
|
+
return;
|
|
17824
|
+
}
|
|
17682
17825
|
let inputsToStore = null;
|
|
17683
17826
|
let i = 0;
|
|
17684
17827
|
while (i < attrs.length) {
|
|
@@ -17693,26 +17836,38 @@ function generateInitialInputs(inputs, directiveIndex, attrs) {
|
|
|
17693
17836
|
i += 2;
|
|
17694
17837
|
continue;
|
|
17695
17838
|
}
|
|
17696
|
-
|
|
17697
|
-
|
|
17839
|
+
else if (typeof attrName === 'number') {
|
|
17840
|
+
// If we hit any other attribute markers, we're done anyway. None of those are valid inputs.
|
|
17698
17841
|
break;
|
|
17699
|
-
|
|
17842
|
+
}
|
|
17843
|
+
if (!isHostDirective && inputs.hasOwnProperty(attrName)) {
|
|
17700
17844
|
// Find the input's public name from the input store. Note that we can be found easier
|
|
17701
17845
|
// through the directive def, but we want to do it using the inputs store so that it can
|
|
17702
17846
|
// account for host directive aliases.
|
|
17703
17847
|
const inputConfig = inputs[attrName];
|
|
17704
|
-
for (
|
|
17705
|
-
if (
|
|
17848
|
+
for (const index of inputConfig) {
|
|
17849
|
+
if (index === directiveIndex) {
|
|
17706
17850
|
inputsToStore ??= [];
|
|
17707
|
-
inputsToStore.push(
|
|
17851
|
+
inputsToStore.push(attrName, attrs[i + 1]);
|
|
17708
17852
|
// A directive can't have multiple inputs with the same name so we can break here.
|
|
17709
17853
|
break;
|
|
17710
17854
|
}
|
|
17711
17855
|
}
|
|
17712
17856
|
}
|
|
17857
|
+
else if (isHostDirective && hostDirectiveInputs.hasOwnProperty(attrName)) {
|
|
17858
|
+
const config = hostDirectiveInputs[attrName];
|
|
17859
|
+
for (let j = 0; j < config.length; j += 2) {
|
|
17860
|
+
if (config[j] === directiveIndex) {
|
|
17861
|
+
inputsToStore ??= [];
|
|
17862
|
+
inputsToStore.push(config[j + 1], attrs[i + 1]);
|
|
17863
|
+
break;
|
|
17864
|
+
}
|
|
17865
|
+
}
|
|
17866
|
+
}
|
|
17713
17867
|
i += 2;
|
|
17714
17868
|
}
|
|
17715
|
-
|
|
17869
|
+
tNode.initialInputs ??= [];
|
|
17870
|
+
tNode.initialInputs.push(inputsToStore);
|
|
17716
17871
|
}
|
|
17717
17872
|
/**
|
|
17718
17873
|
* Setup directive for instantiation.
|
|
@@ -17972,7 +18127,7 @@ class ComponentFactory extends ComponentFactory$1 {
|
|
|
17972
18127
|
const cmpDef = this.componentDef;
|
|
17973
18128
|
ngDevMode && verifyNotAnOrphanComponent(cmpDef);
|
|
17974
18129
|
const tAttributes = rootSelectorOrNode
|
|
17975
|
-
? ['ng-version', '19.2.0
|
|
18130
|
+
? ['ng-version', '19.2.0']
|
|
17976
18131
|
: // Extract attributes and classes from the first selector only to match VE behavior.
|
|
17977
18132
|
extractAttrsAndClassesFromSelector(this.componentDef.selectors[0]);
|
|
17978
18133
|
// Create the root view. Uses empty TView and ContentTemplate.
|
|
@@ -18061,29 +18216,24 @@ class ComponentRef extends ComponentRef$1 {
|
|
|
18061
18216
|
this.componentType = componentType;
|
|
18062
18217
|
}
|
|
18063
18218
|
setInput(name, value) {
|
|
18064
|
-
const
|
|
18065
|
-
|
|
18066
|
-
if
|
|
18067
|
-
|
|
18068
|
-
|
|
18069
|
-
|
|
18070
|
-
|
|
18071
|
-
Object.is(this.previousInputValues.get(name), value)) {
|
|
18072
|
-
return;
|
|
18073
|
-
}
|
|
18074
|
-
const lView = this._rootLView;
|
|
18075
|
-
setInputsForProperty(lView[TVIEW], lView, dataValue, name, value);
|
|
18076
|
-
this.previousInputValues.set(name, value);
|
|
18077
|
-
const childComponentLView = getComponentLViewByIndex(this._tNode.index, lView);
|
|
18078
|
-
markViewDirty(childComponentLView, 1 /* NotificationSource.SetInput */);
|
|
18219
|
+
const tNode = this._tNode;
|
|
18220
|
+
this.previousInputValues ??= new Map();
|
|
18221
|
+
// Do not set the input if it is the same as the last value
|
|
18222
|
+
// This behavior matches `bindingUpdated` when binding inputs in templates.
|
|
18223
|
+
if (this.previousInputValues.has(name) &&
|
|
18224
|
+
Object.is(this.previousInputValues.get(name), value)) {
|
|
18225
|
+
return;
|
|
18079
18226
|
}
|
|
18080
|
-
|
|
18081
|
-
|
|
18082
|
-
|
|
18083
|
-
|
|
18084
|
-
|
|
18085
|
-
|
|
18086
|
-
|
|
18227
|
+
const lView = this._rootLView;
|
|
18228
|
+
const hasSetInput = setAllInputsForProperty(tNode, lView[TVIEW], lView, name, value);
|
|
18229
|
+
this.previousInputValues.set(name, value);
|
|
18230
|
+
const childComponentLView = getComponentLViewByIndex(tNode.index, lView);
|
|
18231
|
+
markViewDirty(childComponentLView, 1 /* NotificationSource.SetInput */);
|
|
18232
|
+
if (ngDevMode && !hasSetInput) {
|
|
18233
|
+
const cmpNameForError = stringifyForError(this.componentType);
|
|
18234
|
+
let message = `Can't set value of the '${name}' input on the '${cmpNameForError}' component. `;
|
|
18235
|
+
message += `Make sure that the '${name}' property is annotated with @Input() or a mapped @Input('${name}') exists.`;
|
|
18236
|
+
reportUnknownPropertyError(message);
|
|
18087
18237
|
}
|
|
18088
18238
|
}
|
|
18089
18239
|
get injector() {
|
|
@@ -20705,7 +20855,7 @@ function declareTemplate(declarationLView, declarationTView, index, templateFn,
|
|
|
20705
20855
|
// In client-only mode, this function is a noop.
|
|
20706
20856
|
populateDehydratedViewsInLContainer(lContainer, tNode, declarationLView);
|
|
20707
20857
|
if (isDirectiveHost(tNode)) {
|
|
20708
|
-
|
|
20858
|
+
createDirectivesInstances(declarationTView, declarationLView, tNode);
|
|
20709
20859
|
}
|
|
20710
20860
|
if (localRefsIndex != null) {
|
|
20711
20861
|
saveResolvedLocalsInData(declarationLView, tNode, localRefExtractor);
|
|
@@ -21240,8 +21390,9 @@ function renderDeferBlockState(newState, tNode, lContainer, skipTimerScheduling
|
|
|
21240
21390
|
}
|
|
21241
21391
|
}
|
|
21242
21392
|
function findMatchingDehydratedViewForDeferBlock(lContainer, lDetails) {
|
|
21243
|
-
|
|
21244
|
-
|
|
21393
|
+
const dehydratedViewIx = lContainer[DEHYDRATED_VIEWS]?.findIndex((view) => view.data[DEFER_BLOCK_STATE$1] === lDetails[DEFER_BLOCK_STATE]) ?? -1;
|
|
21394
|
+
const dehydratedView = dehydratedViewIx > -1 ? lContainer[DEHYDRATED_VIEWS][dehydratedViewIx] : null;
|
|
21395
|
+
return { dehydratedView, dehydratedViewIx };
|
|
21245
21396
|
}
|
|
21246
21397
|
/**
|
|
21247
21398
|
* Applies changes to the DOM to reflect a given state.
|
|
@@ -21273,21 +21424,23 @@ function applyDeferBlockState(newState, lDetails, lContainer, tNode, hostLView)
|
|
|
21273
21424
|
injector = createDeferBlockInjector(hostLView[INJECTOR], tDetails, providers);
|
|
21274
21425
|
}
|
|
21275
21426
|
}
|
|
21276
|
-
const dehydratedView = findMatchingDehydratedViewForDeferBlock(lContainer, lDetails);
|
|
21277
|
-
// Erase dehydrated view info, so that it's not removed later
|
|
21278
|
-
// by post-hydration cleanup process.
|
|
21279
|
-
lContainer[DEHYDRATED_VIEWS] = null;
|
|
21427
|
+
const { dehydratedView, dehydratedViewIx } = findMatchingDehydratedViewForDeferBlock(lContainer, lDetails);
|
|
21280
21428
|
const embeddedLView = createAndRenderEmbeddedLView(hostLView, activeBlockTNode, null, {
|
|
21281
21429
|
injector,
|
|
21282
21430
|
dehydratedView,
|
|
21283
21431
|
});
|
|
21284
21432
|
addLViewToLContainer(lContainer, embeddedLView, viewIndex, shouldAddViewToDom(activeBlockTNode, dehydratedView));
|
|
21285
21433
|
markViewDirty(embeddedLView, 2 /* NotificationSource.DeferBlockStateUpdate */);
|
|
21286
|
-
|
|
21287
|
-
|
|
21288
|
-
|
|
21289
|
-
|
|
21290
|
-
|
|
21434
|
+
if (dehydratedViewIx > -1) {
|
|
21435
|
+
// Erase dehydrated view info in a given LContainer, so that the view is not
|
|
21436
|
+
// removed later by post-hydration cleanup process (which iterates over all
|
|
21437
|
+
// dehydrated views in component tree). This clears only the dehydrated view
|
|
21438
|
+
// that was found for this render, which in most cases will be the only view.
|
|
21439
|
+
// In the case that there was control flow that changed, there may be either
|
|
21440
|
+
// more than one or the views would not match up due to the server rendered
|
|
21441
|
+
// content being a different branch of the control flow.
|
|
21442
|
+
lContainer[DEHYDRATED_VIEWS]?.splice(dehydratedViewIx, 1);
|
|
21443
|
+
}
|
|
21291
21444
|
if ((newState === DeferBlockState.Complete || newState === DeferBlockState.Error) &&
|
|
21292
21445
|
Array.isArray(lDetails[ON_COMPLETE_FNS])) {
|
|
21293
21446
|
for (const callback of lDetails[ON_COMPLETE_FNS]) {
|
|
@@ -24136,16 +24289,36 @@ async function triggerHydrationFromBlockName(injector, blockName, replayQueuedEv
|
|
|
24136
24289
|
await parentBlockPromise;
|
|
24137
24290
|
}
|
|
24138
24291
|
// Actually do the triggering and hydration of the queue of blocks
|
|
24139
|
-
for (
|
|
24140
|
-
|
|
24141
|
-
|
|
24142
|
-
|
|
24143
|
-
|
|
24144
|
-
|
|
24145
|
-
|
|
24146
|
-
|
|
24147
|
-
|
|
24148
|
-
|
|
24292
|
+
for (let blockQueueIdx = 0; blockQueueIdx < hydrationQueue.length; blockQueueIdx++) {
|
|
24293
|
+
const dehydratedBlockId = hydrationQueue[blockQueueIdx];
|
|
24294
|
+
const dehydratedDeferBlock = dehydratedBlockRegistry.get(dehydratedBlockId);
|
|
24295
|
+
if (dehydratedDeferBlock != null) {
|
|
24296
|
+
// trigger the block resources and await next render for hydration. This should result
|
|
24297
|
+
// in the next block ɵɵdefer instruction being called and that block being added to the dehydrated registry.
|
|
24298
|
+
await triggerResourceLoadingForHydration(dehydratedDeferBlock);
|
|
24299
|
+
await nextRender(injector);
|
|
24300
|
+
// if the content has changed since server rendering, we need to check for the expected block
|
|
24301
|
+
// being in the registry or if errors occurred. In that case, we need to clean up the remaining expected
|
|
24302
|
+
// content that won't be rendered or fetched.
|
|
24303
|
+
if (deferBlockHasErrored(dehydratedDeferBlock)) {
|
|
24304
|
+
// Either the expected block has not yet had its ɵɵdefer instruction called or the block errored out when fetching
|
|
24305
|
+
// resources. In the former case, either we're hydrating too soon or the client and server differ. In both cases,
|
|
24306
|
+
// we need to clean up child content and promises.
|
|
24307
|
+
removeDehydratedViewList(dehydratedDeferBlock);
|
|
24308
|
+
cleanupRemainingHydrationQueue(hydrationQueue.slice(blockQueueIdx), dehydratedBlockRegistry);
|
|
24309
|
+
break;
|
|
24310
|
+
}
|
|
24311
|
+
// The defer block has not errored and we've finished fetching resources and rendering.
|
|
24312
|
+
// At this point it is safe to resolve the hydration promise.
|
|
24313
|
+
blocksBeingHydrated.get(dehydratedBlockId).resolve();
|
|
24314
|
+
}
|
|
24315
|
+
else {
|
|
24316
|
+
// The expected block has not yet had its ɵɵdefer instruction called. This is likely due to content changing between
|
|
24317
|
+
// client and server. We need to clean up the dehydrated DOM in the container since it no longer is valid.
|
|
24318
|
+
cleanupParentContainer(blockQueueIdx, hydrationQueue, dehydratedBlockRegistry);
|
|
24319
|
+
cleanupRemainingHydrationQueue(hydrationQueue.slice(blockQueueIdx), dehydratedBlockRegistry);
|
|
24320
|
+
break;
|
|
24321
|
+
}
|
|
24149
24322
|
}
|
|
24150
24323
|
// Await hydration completion for the requested block.
|
|
24151
24324
|
await blocksBeingHydrated.get(blockName)?.promise;
|
|
@@ -24158,6 +24331,33 @@ async function triggerHydrationFromBlockName(injector, blockName, replayQueuedEv
|
|
|
24158
24331
|
// Cleanup after hydration of all affected defer blocks.
|
|
24159
24332
|
cleanupHydratedDeferBlocks(dehydratedBlockRegistry.get(blockName), hydrationQueue, dehydratedBlockRegistry, injector.get(ApplicationRef));
|
|
24160
24333
|
}
|
|
24334
|
+
function deferBlockHasErrored(deferBlock) {
|
|
24335
|
+
return (getLDeferBlockDetails(deferBlock.lView, deferBlock.tNode)[DEFER_BLOCK_STATE] ===
|
|
24336
|
+
DeferBlockState.Error);
|
|
24337
|
+
}
|
|
24338
|
+
/**
|
|
24339
|
+
* Clean up the parent container of a block where content changed between server and client.
|
|
24340
|
+
* The parent of a block going through `triggerHydrationFromBlockName` will contain the
|
|
24341
|
+
* dehydrated content that needs to be cleaned up. So we have to do the clean up from that location
|
|
24342
|
+
* in the tree.
|
|
24343
|
+
*/
|
|
24344
|
+
function cleanupParentContainer(currentBlockIdx, hydrationQueue, dehydratedBlockRegistry) {
|
|
24345
|
+
// If a parent block exists, it's in the hydration queue in front of the current block.
|
|
24346
|
+
const parentDeferBlockIdx = currentBlockIdx - 1;
|
|
24347
|
+
const parentDeferBlock = parentDeferBlockIdx > -1
|
|
24348
|
+
? dehydratedBlockRegistry.get(hydrationQueue[parentDeferBlockIdx])
|
|
24349
|
+
: null;
|
|
24350
|
+
if (parentDeferBlock) {
|
|
24351
|
+
cleanupLContainer(parentDeferBlock.lContainer);
|
|
24352
|
+
}
|
|
24353
|
+
}
|
|
24354
|
+
function cleanupRemainingHydrationQueue(hydrationQueue, dehydratedBlockRegistry) {
|
|
24355
|
+
const blocksBeingHydrated = dehydratedBlockRegistry.hydrating;
|
|
24356
|
+
for (const dehydratedBlockId in hydrationQueue) {
|
|
24357
|
+
blocksBeingHydrated.get(dehydratedBlockId)?.reject();
|
|
24358
|
+
}
|
|
24359
|
+
dehydratedBlockRegistry.cleanup(hydrationQueue);
|
|
24360
|
+
}
|
|
24161
24361
|
/**
|
|
24162
24362
|
* Generates a new promise for every defer block in the hydrating queue
|
|
24163
24363
|
*/
|
|
@@ -24170,18 +24370,8 @@ function populateHydratingStateForQueue(registry, queue) {
|
|
|
24170
24370
|
function nextRender(injector) {
|
|
24171
24371
|
return new Promise((resolveFn) => afterNextRender(resolveFn, { injector }));
|
|
24172
24372
|
}
|
|
24173
|
-
async function triggerResourceLoadingForHydration(
|
|
24174
|
-
const
|
|
24175
|
-
// Since we trigger hydration for nested defer blocks in a sequence (parent -> child),
|
|
24176
|
-
// there is a chance that a defer block may not be present at hydration time. For example,
|
|
24177
|
-
// when a nested block was in an `@if` condition, which has changed.
|
|
24178
|
-
if (deferBlock === null) {
|
|
24179
|
-
// TODO(incremental-hydration): handle the cleanup for cases when
|
|
24180
|
-
// defer block is no longer present during hydration (e.g. `@if` condition
|
|
24181
|
-
// has changed during hydration/rendering).
|
|
24182
|
-
return;
|
|
24183
|
-
}
|
|
24184
|
-
const { tNode, lView } = deferBlock;
|
|
24373
|
+
async function triggerResourceLoadingForHydration(dehydratedBlock) {
|
|
24374
|
+
const { tNode, lView } = dehydratedBlock;
|
|
24185
24375
|
const lDetails = getLDeferBlockDetails(lView, tNode);
|
|
24186
24376
|
return new Promise((resolve) => {
|
|
24187
24377
|
onDeferBlockCompletion(lDetails, resolve);
|
|
@@ -26234,10 +26424,8 @@ function ɵɵproperty(propName, value, sanitizer) {
|
|
|
26234
26424
|
* directive input.
|
|
26235
26425
|
*/
|
|
26236
26426
|
function setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isClassBased) {
|
|
26237
|
-
const inputs = tNode.inputs;
|
|
26238
|
-
const property = isClassBased ? 'class' : 'style';
|
|
26239
26427
|
// We support both 'class' and `className` hence the fallback.
|
|
26240
|
-
|
|
26428
|
+
setAllInputsForProperty(tNode, tView, lView, isClassBased ? 'class' : 'style', value);
|
|
26241
26429
|
}
|
|
26242
26430
|
|
|
26243
26431
|
/**
|
|
@@ -28061,12 +28249,12 @@ function ɵɵelementStart(index, name, attrsIndex, localRefsIndex) {
|
|
|
28061
28249
|
// any immediate children of a component or template container must be pre-emptively
|
|
28062
28250
|
// monkey-patched with the component view data so that the element can be inspected
|
|
28063
28251
|
// later on using any element discovery utility methods (see `element_discovery.ts`)
|
|
28064
|
-
if (getElementDepthCount() === 0) {
|
|
28252
|
+
if (getElementDepthCount() === 0 || hasDirectives) {
|
|
28065
28253
|
attachPatchData(native, lView);
|
|
28066
28254
|
}
|
|
28067
28255
|
increaseElementDepthCount();
|
|
28068
28256
|
if (hasDirectives) {
|
|
28069
|
-
|
|
28257
|
+
createDirectivesInstances(tView, lView, tNode);
|
|
28070
28258
|
executeContentQueries(tView, tNode, lView);
|
|
28071
28259
|
}
|
|
28072
28260
|
if (localRefsIndex !== null) {
|
|
@@ -28238,7 +28426,7 @@ function ɵɵelementContainerStart(index, attrsIndex, localRefsIndex) {
|
|
|
28238
28426
|
}
|
|
28239
28427
|
attachPatchData(comment, lView);
|
|
28240
28428
|
if (isDirectiveHost(tNode)) {
|
|
28241
|
-
|
|
28429
|
+
createDirectivesInstances(tView, lView, tNode);
|
|
28242
28430
|
executeContentQueries(tView, tNode, lView);
|
|
28243
28431
|
}
|
|
28244
28432
|
if (localRefsIndex != null) {
|
|
@@ -30293,7 +30481,7 @@ function findExistingListener(tView, lView, eventName, tNodeIdx) {
|
|
|
30293
30481
|
function listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn, eventTargetResolver) {
|
|
30294
30482
|
const isTNodeDirectiveHost = isDirectiveHost(tNode);
|
|
30295
30483
|
const firstCreatePass = tView.firstCreatePass;
|
|
30296
|
-
const tCleanup = firstCreatePass
|
|
30484
|
+
const tCleanup = firstCreatePass ? getOrCreateTViewCleanup(tView) : null;
|
|
30297
30485
|
const context = lView[CONTEXT];
|
|
30298
30486
|
// When the ɵɵlistener instruction was generated and is executed we know that there is either a
|
|
30299
30487
|
// native listener or a directive output on this element. As such we we know that we will have to
|
|
@@ -30358,29 +30546,37 @@ function listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn,
|
|
|
30358
30546
|
// ancestors are marked dirty when an event occurs.
|
|
30359
30547
|
listenerFn = wrapListener(tNode, lView, context, listenerFn);
|
|
30360
30548
|
}
|
|
30361
|
-
|
|
30362
|
-
|
|
30363
|
-
|
|
30364
|
-
|
|
30365
|
-
|
|
30366
|
-
|
|
30367
|
-
|
|
30368
|
-
|
|
30369
|
-
|
|
30370
|
-
|
|
30371
|
-
|
|
30372
|
-
|
|
30373
|
-
|
|
30374
|
-
throw new Error(`@Output ${minifiedName} not initialized in '${directiveInstance.constructor.name}'.`);
|
|
30375
|
-
}
|
|
30376
|
-
const subscription = output.subscribe(listenerFn);
|
|
30377
|
-
const idx = lCleanup.length;
|
|
30378
|
-
lCleanup.push(listenerFn, subscription);
|
|
30379
|
-
tCleanup && tCleanup.push(eventName, tNode.index, idx, -(idx + 1));
|
|
30549
|
+
if (processOutputs) {
|
|
30550
|
+
const outputConfig = tNode.outputs?.[eventName];
|
|
30551
|
+
const hostDirectiveOutputConfig = tNode.hostDirectiveOutputs?.[eventName];
|
|
30552
|
+
if (hostDirectiveOutputConfig && hostDirectiveOutputConfig.length) {
|
|
30553
|
+
for (let i = 0; i < hostDirectiveOutputConfig.length; i += 2) {
|
|
30554
|
+
const index = hostDirectiveOutputConfig[i];
|
|
30555
|
+
const lookupName = hostDirectiveOutputConfig[i + 1];
|
|
30556
|
+
listenToOutput(tNode, tView, lView, index, lookupName, eventName, listenerFn, lCleanup, tCleanup);
|
|
30557
|
+
}
|
|
30558
|
+
}
|
|
30559
|
+
if (outputConfig && outputConfig.length) {
|
|
30560
|
+
for (const index of outputConfig) {
|
|
30561
|
+
listenToOutput(tNode, tView, lView, index, eventName, eventName, listenerFn, lCleanup, tCleanup);
|
|
30380
30562
|
}
|
|
30381
30563
|
}
|
|
30382
30564
|
}
|
|
30383
30565
|
}
|
|
30566
|
+
function listenToOutput(tNode, tView, lView, index, lookupName, eventName, listenerFn, lCleanup, tCleanup) {
|
|
30567
|
+
ngDevMode && assertIndexInRange(lView, index);
|
|
30568
|
+
const instance = lView[index];
|
|
30569
|
+
const def = tView.data[index];
|
|
30570
|
+
const propertyName = def.outputs[lookupName];
|
|
30571
|
+
const output = instance[propertyName];
|
|
30572
|
+
if (ngDevMode && !isOutputSubscribable(output)) {
|
|
30573
|
+
throw new Error(`@Output ${propertyName} not initialized in '${instance.constructor.name}'.`);
|
|
30574
|
+
}
|
|
30575
|
+
const subscription = output.subscribe(listenerFn);
|
|
30576
|
+
const idx = lCleanup.length;
|
|
30577
|
+
lCleanup.push(listenerFn, subscription);
|
|
30578
|
+
tCleanup && tCleanup.push(eventName, tNode.index, idx, -(idx + 1));
|
|
30579
|
+
}
|
|
30384
30580
|
function executeListenerWithErrorHandling(lView, context, listenerFn, e) {
|
|
30385
30581
|
const prevConsumer = setActiveConsumer$1(null);
|
|
30386
30582
|
try {
|
|
@@ -33544,11 +33740,12 @@ function executeWithInvalidateFallback(importMeta, id, callback) {
|
|
|
33544
33740
|
callback();
|
|
33545
33741
|
}
|
|
33546
33742
|
catch (e) {
|
|
33547
|
-
const
|
|
33743
|
+
const error = e;
|
|
33548
33744
|
// If we have all the necessary information and APIs to send off the invalidation
|
|
33549
33745
|
// request, send it before rethrowing so the dev server can decide what to do.
|
|
33550
|
-
if (id !== null &&
|
|
33551
|
-
|
|
33746
|
+
if (id !== null && error.message) {
|
|
33747
|
+
const toLog = error.message + (error.stack ? '\n' + error.stack : '');
|
|
33748
|
+
importMeta?.hot?.send?.('angular:invalidate', { id, message: toLog, error: true });
|
|
33552
33749
|
}
|
|
33553
33750
|
// Throw the error in case the page doesn't get refreshed.
|
|
33554
33751
|
throw e;
|
|
@@ -34978,7 +35175,7 @@ class Version {
|
|
|
34978
35175
|
/**
|
|
34979
35176
|
* @publicApi
|
|
34980
35177
|
*/
|
|
34981
|
-
const VERSION = new Version('19.2.0
|
|
35178
|
+
const VERSION = new Version('19.2.0');
|
|
34982
35179
|
|
|
34983
35180
|
/**
|
|
34984
35181
|
* Combination of NgModuleFactory and ComponentFactories.
|
|
@@ -35812,10 +36009,9 @@ class ImagePerformanceWarning {
|
|
|
35812
36009
|
window = null;
|
|
35813
36010
|
observer = null;
|
|
35814
36011
|
options = inject(IMAGE_CONFIG);
|
|
35815
|
-
isBrowser = inject(PLATFORM_ID) === 'browser';
|
|
35816
36012
|
lcpImageUrl;
|
|
35817
36013
|
start() {
|
|
35818
|
-
if (
|
|
36014
|
+
if ((typeof ngServerMode !== 'undefined' && ngServerMode) ||
|
|
35819
36015
|
typeof PerformanceObserver === 'undefined' ||
|
|
35820
36016
|
(this.options?.disableImageSizeWarning && this.options?.disableImageLazyLoadWarning)) {
|
|
35821
36017
|
return;
|
|
@@ -35823,7 +36019,7 @@ class ImagePerformanceWarning {
|
|
|
35823
36019
|
this.observer = this.initPerformanceObserver();
|
|
35824
36020
|
const doc = getDocument();
|
|
35825
36021
|
const win = doc.defaultView;
|
|
35826
|
-
if (
|
|
36022
|
+
if (win) {
|
|
35827
36023
|
this.window = win;
|
|
35828
36024
|
// Wait to avoid race conditions where LCP image triggers
|
|
35829
36025
|
// load event before it's recorded by the performance observer
|
|
@@ -40428,7 +40624,6 @@ function untracked(nonReactiveReadsFn) {
|
|
|
40428
40624
|
* Create a computed `Signal` which derives a reactive value from an expression.
|
|
40429
40625
|
*/
|
|
40430
40626
|
function computed(computation, options) {
|
|
40431
|
-
performanceMarkFeature('NgSignals');
|
|
40432
40627
|
const getter = createComputed$1(computation);
|
|
40433
40628
|
if (options?.equal) {
|
|
40434
40629
|
getter[SIGNAL$1].equal = options.equal;
|
|
@@ -40526,7 +40721,6 @@ function effect$1() { }
|
|
|
40526
40721
|
* Create a global `Effect` for the given reactive function.
|
|
40527
40722
|
*/
|
|
40528
40723
|
function microtaskEffect(effectFn, options) {
|
|
40529
|
-
performanceMarkFeature('NgSignals');
|
|
40530
40724
|
ngDevMode &&
|
|
40531
40725
|
assertNotInReactiveContext(effect$1, 'Call `effect` outside of a reactive context. For example, schedule the ' +
|
|
40532
40726
|
'effect inside the component constructor.');
|
|
@@ -40599,7 +40793,6 @@ function effect(effectFn, options) {
|
|
|
40599
40793
|
}
|
|
40600
40794
|
return microtaskEffect(effectFn, options);
|
|
40601
40795
|
}
|
|
40602
|
-
performanceMarkFeature('NgSignals');
|
|
40603
40796
|
ngDevMode &&
|
|
40604
40797
|
assertNotInReactiveContext(effect, 'Call `effect` outside of a reactive context. For example, schedule the ' +
|
|
40605
40798
|
'effect inside the component constructor.');
|
|
@@ -40796,7 +40989,6 @@ var ResourceStatus;
|
|
|
40796
40989
|
|
|
40797
40990
|
const identityFn = (v) => v;
|
|
40798
40991
|
function linkedSignal(optionsOrComputation, options) {
|
|
40799
|
-
performanceMarkFeature('NgSignals');
|
|
40800
40992
|
if (typeof optionsOrComputation === 'function') {
|
|
40801
40993
|
const getter = createLinkedSignal$1(optionsOrComputation, (identityFn), options?.equal);
|
|
40802
40994
|
return upgradeLinkedSignalGetter(getter);
|