@angular/core 17.0.0-next.7 → 17.0.0-next.8
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/esm2022/primitives/signals/index.mjs +15 -0
- package/esm2022/primitives/signals/src/computed.mjs +92 -0
- package/esm2022/primitives/signals/src/equality.mjs +14 -0
- package/esm2022/primitives/signals/src/errors.mjs +18 -0
- package/esm2022/primitives/signals/src/graph.mjs +291 -0
- package/esm2022/primitives/signals/src/signal.mjs +78 -0
- package/esm2022/primitives/signals/src/watch.mjs +82 -0
- package/esm2022/primitives/signals/src/weak_ref.mjs +11 -0
- package/esm2022/rxjs-interop/src/to_signal.mjs +45 -14
- package/esm2022/src/application_init.mjs +50 -2
- package/esm2022/src/application_ref.mjs +7 -2
- package/esm2022/src/application_tokens.mjs +16 -1
- package/esm2022/src/core_private_export.mjs +4 -4
- package/esm2022/src/core_reactivity_export_internal.mjs +6 -2
- package/esm2022/src/core_render3_private_export.mjs +2 -2
- package/esm2022/src/errors.mjs +1 -1
- package/esm2022/src/image_performance_warning.mjs +154 -0
- package/esm2022/src/linker/compiler.mjs +1 -1
- package/esm2022/src/metadata/directives.mjs +1 -1
- package/esm2022/src/render3/after_render_hooks.mjs +5 -1
- package/esm2022/src/render3/assert.mjs +16 -1
- package/esm2022/src/render3/component_ref.mjs +12 -3
- package/esm2022/src/render3/debug/framework_injector_profiler.mjs +33 -4
- package/esm2022/src/render3/debug/injector_profiler.mjs +1 -1
- package/esm2022/src/render3/debug/set_debug_info.mjs +20 -0
- package/esm2022/src/render3/definition.mjs +2 -1
- package/esm2022/src/render3/deps_tracker/api.mjs +1 -1
- package/esm2022/src/render3/deps_tracker/deps_tracker.mjs +13 -2
- package/esm2022/src/render3/features/host_directives_feature.mjs +3 -8
- package/esm2022/src/render3/hooks.mjs +5 -5
- package/esm2022/src/render3/index.mjs +3 -2
- package/esm2022/src/render3/instructions/change_detection.mjs +31 -14
- package/esm2022/src/render3/instructions/control_flow.mjs +21 -12
- package/esm2022/src/render3/instructions/defer.mjs +156 -22
- package/esm2022/src/render3/instructions/defer_events.mjs +13 -3
- package/esm2022/src/render3/instructions/shared.mjs +5 -4
- package/esm2022/src/render3/interfaces/container.mjs +5 -4
- package/esm2022/src/render3/interfaces/defer.mjs +13 -6
- package/esm2022/src/render3/interfaces/definition.mjs +1 -1
- package/esm2022/src/render3/interfaces/view.mjs +5 -4
- package/esm2022/src/render3/jit/environment.mjs +3 -1
- package/esm2022/src/render3/node_manipulation.mjs +4 -6
- package/esm2022/src/render3/reactive_lview_consumer.mjs +2 -2
- package/esm2022/src/render3/reactivity/api.mjs +15 -0
- package/esm2022/src/render3/reactivity/asserts.mjs +26 -0
- package/esm2022/src/render3/reactivity/computed.mjs +19 -0
- package/esm2022/src/render3/reactivity/effect.mjs +7 -6
- package/esm2022/src/render3/reactivity/signal.mjs +32 -0
- package/esm2022/src/render3/reactivity/untracked.mjs +24 -0
- package/esm2022/src/render3/util/injector_discovery_utils.mjs +43 -14
- package/esm2022/src/render3/util/stringify_utils.mjs +28 -1
- package/esm2022/src/render3/util/view_utils.mjs +41 -25
- package/esm2022/src/render3/view_ref.mjs +3 -2
- package/esm2022/src/util/stringify.mjs +16 -1
- package/esm2022/src/version.mjs +1 -1
- package/esm2022/testing/src/logger.mjs +3 -3
- package/fesm2022/core.mjs +1787 -1212
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/primitives/signals.mjs +539 -0
- package/fesm2022/primitives/signals.mjs.map +1 -0
- package/fesm2022/rxjs-interop.mjs +45 -14
- package/fesm2022/rxjs-interop.mjs.map +1 -1
- package/fesm2022/testing.mjs +1 -1
- package/index.d.ts +162 -163
- package/package.json +7 -1
- package/primitives/signals/index.d.ts +281 -0
- package/rxjs-interop/index.d.ts +15 -101
- package/schematics/collection.json +12 -2
- package/schematics/migrations/block-template-entities/bundle.js +485 -297
- package/schematics/migrations/block-template-entities/bundle.js.map +4 -4
- package/schematics/migrations/compiler-options/bundle.js +582 -0
- package/schematics/migrations/compiler-options/bundle.js.map +7 -0
- package/schematics/migrations/transfer-state/bundle.js +592 -0
- package/schematics/migrations/transfer-state/bundle.js.map +7 -0
- package/schematics/migrations.json +10 -0
- package/schematics/ng-generate/control-flow-migration/bundle.js +24097 -0
- package/schematics/ng-generate/control-flow-migration/bundle.js.map +7 -0
- package/schematics/ng-generate/control-flow-migration/schema.json +7 -0
- package/schematics/ng-generate/standalone-migration/bundle.js +1677 -1278
- package/schematics/ng-generate/standalone-migration/bundle.js.map +4 -4
- package/testing/index.d.ts +1 -1
- package/esm2022/src/signals/index.mjs +0 -16
- package/esm2022/src/signals/src/api.mjs +0 -39
- package/esm2022/src/signals/src/computed.mjs +0 -95
- package/esm2022/src/signals/src/errors.mjs +0 -18
- package/esm2022/src/signals/src/graph.mjs +0 -280
- package/esm2022/src/signals/src/signal.mjs +0 -92
- package/esm2022/src/signals/src/untracked.mjs +0 -26
- package/esm2022/src/signals/src/watch.mjs +0 -81
- package/esm2022/src/signals/src/weak_ref.mjs +0 -11
package/fesm2022/core.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v17.0.0-next.
|
|
2
|
+
* @license Angular v17.0.0-next.8
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { setActiveConsumer as setActiveConsumer$1, consumerDestroy as consumerDestroy$1, SIGNAL as SIGNAL$1, createComputed as createComputed$1, createSignal as createSignal$1, signalSetFn as signalSetFn$1, signalUpdateFn as signalUpdateFn$1, getActiveConsumer as getActiveConsumer$1, createWatch as createWatch$1, REACTIVE_NODE as REACTIVE_NODE$1, consumerBeforeComputation as consumerBeforeComputation$1, consumerAfterComputation as consumerAfterComputation$1, setThrowInvalidWriteToSignalError as setThrowInvalidWriteToSignalError$1 } from '@angular/core/primitives/signals';
|
|
7
8
|
import { Subject, Subscription, Observable, merge as merge$1, BehaviorSubject, of } from 'rxjs';
|
|
8
9
|
import { share, switchMap, distinctUntilChanged, first } from 'rxjs/operators';
|
|
9
10
|
|
|
@@ -65,6 +66,21 @@ function concatStringsWithSpace(before, after) {
|
|
|
65
66
|
(after === null ? '' : after) :
|
|
66
67
|
((after == null || after === '') ? before : before + ' ' + after);
|
|
67
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Ellipses the string in the middle when longer than the max length
|
|
71
|
+
*
|
|
72
|
+
* @param string
|
|
73
|
+
* @param maxLength of the output string
|
|
74
|
+
* @returns elispsed string with ... in the middle
|
|
75
|
+
*/
|
|
76
|
+
function truncateMiddle(str, maxLength = 100) {
|
|
77
|
+
if (!str || maxLength < 1 || str.length <= maxLength)
|
|
78
|
+
return str;
|
|
79
|
+
if (maxLength == 1)
|
|
80
|
+
return str.substring(0, 1) + '...';
|
|
81
|
+
const halfLimit = Math.round(maxLength / 2);
|
|
82
|
+
return str.substring(0, halfLimit) + '...' + str.substring(str.length - halfLimit);
|
|
83
|
+
}
|
|
68
84
|
|
|
69
85
|
const __forward_ref__ = getClosureSafeProperty({ __forward_ref__: getClosureSafeProperty });
|
|
70
86
|
/**
|
|
@@ -193,6 +209,28 @@ function formatRuntimeError(code, message) {
|
|
|
193
209
|
return errorMessage;
|
|
194
210
|
}
|
|
195
211
|
|
|
212
|
+
const NG_COMP_DEF = getClosureSafeProperty({ ɵcmp: getClosureSafeProperty });
|
|
213
|
+
const NG_DIR_DEF = getClosureSafeProperty({ ɵdir: getClosureSafeProperty });
|
|
214
|
+
const NG_PIPE_DEF = getClosureSafeProperty({ ɵpipe: getClosureSafeProperty });
|
|
215
|
+
const NG_MOD_DEF = getClosureSafeProperty({ ɵmod: getClosureSafeProperty });
|
|
216
|
+
const NG_FACTORY_DEF = getClosureSafeProperty({ ɵfac: getClosureSafeProperty });
|
|
217
|
+
/**
|
|
218
|
+
* If a directive is diPublic, bloomAdd sets a property on the type with this constant as
|
|
219
|
+
* the key and the directive's unique ID as the value. This allows us to map directives to their
|
|
220
|
+
* bloom filter bit for DI.
|
|
221
|
+
*/
|
|
222
|
+
// TODO(misko): This is wrong. The NG_ELEMENT_ID should never be minified.
|
|
223
|
+
const NG_ELEMENT_ID = getClosureSafeProperty({ __NG_ELEMENT_ID__: getClosureSafeProperty });
|
|
224
|
+
/**
|
|
225
|
+
* The `NG_ENV_ID` field on a DI token indicates special processing in the `EnvironmentInjector`:
|
|
226
|
+
* getting such tokens from the `EnvironmentInjector` will bypass the standard DI resolution
|
|
227
|
+
* strategy and instead will return implementation produced by the `NG_ENV_ID` factory function.
|
|
228
|
+
*
|
|
229
|
+
* This particular retrieval of DI tokens is mostly done to eliminate circular dependencies and
|
|
230
|
+
* improve tree-shaking.
|
|
231
|
+
*/
|
|
232
|
+
const NG_ENV_ID = getClosureSafeProperty({ __NG_ENV_ID__: getClosureSafeProperty });
|
|
233
|
+
|
|
196
234
|
/**
|
|
197
235
|
* Used for stringify render output in Ivy.
|
|
198
236
|
* Important! This function is very performance-sensitive and we should
|
|
@@ -210,6 +248,7 @@ function renderStringify(value) {
|
|
|
210
248
|
}
|
|
211
249
|
/**
|
|
212
250
|
* Used to stringify a value so that it can be displayed in an error message.
|
|
251
|
+
*
|
|
213
252
|
* Important! This function contains a megamorphic read and should only be
|
|
214
253
|
* used for error messages.
|
|
215
254
|
*/
|
|
@@ -221,6 +260,31 @@ function stringifyForError(value) {
|
|
|
221
260
|
}
|
|
222
261
|
return renderStringify(value);
|
|
223
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* Used to stringify a `Type` and including the file path and line number in which it is defined, if
|
|
265
|
+
* possible, for better debugging experience.
|
|
266
|
+
*
|
|
267
|
+
* Important! This function contains a megamorphic read and should only be used for error messages.
|
|
268
|
+
*/
|
|
269
|
+
function debugStringifyTypeForError(type) {
|
|
270
|
+
// TODO(pmvald): Do some refactoring so that we can use getComponentDef here without creating
|
|
271
|
+
// circular deps.
|
|
272
|
+
let componentDef = type[NG_COMP_DEF] || null;
|
|
273
|
+
if (componentDef !== null && componentDef.debugInfo) {
|
|
274
|
+
return stringifyTypeFromDebugInfo(componentDef.debugInfo);
|
|
275
|
+
}
|
|
276
|
+
return stringifyForError(type);
|
|
277
|
+
}
|
|
278
|
+
// TODO(pmvald): Do some refactoring so that we can use the type ClassDebugInfo for the param
|
|
279
|
+
// debugInfo here without creating circular deps.
|
|
280
|
+
function stringifyTypeFromDebugInfo(debugInfo) {
|
|
281
|
+
if (!debugInfo.filePath || !debugInfo.lineNumber) {
|
|
282
|
+
return debugInfo.className;
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
return `${debugInfo.className} (at ${debugInfo.filePath}:${debugInfo.lineNumber})`;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
224
288
|
|
|
225
289
|
/** Called when directives inject each other (creating a circular dependency) */
|
|
226
290
|
function throwCyclicDependencyError(token, path) {
|
|
@@ -1027,28 +1091,6 @@ if ((typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode()) {
|
|
|
1027
1091
|
Object.freeze(EMPTY_ARRAY);
|
|
1028
1092
|
}
|
|
1029
1093
|
|
|
1030
|
-
const NG_COMP_DEF = getClosureSafeProperty({ ɵcmp: getClosureSafeProperty });
|
|
1031
|
-
const NG_DIR_DEF = getClosureSafeProperty({ ɵdir: getClosureSafeProperty });
|
|
1032
|
-
const NG_PIPE_DEF = getClosureSafeProperty({ ɵpipe: getClosureSafeProperty });
|
|
1033
|
-
const NG_MOD_DEF = getClosureSafeProperty({ ɵmod: getClosureSafeProperty });
|
|
1034
|
-
const NG_FACTORY_DEF = getClosureSafeProperty({ ɵfac: getClosureSafeProperty });
|
|
1035
|
-
/**
|
|
1036
|
-
* If a directive is diPublic, bloomAdd sets a property on the type with this constant as
|
|
1037
|
-
* the key and the directive's unique ID as the value. This allows us to map directives to their
|
|
1038
|
-
* bloom filter bit for DI.
|
|
1039
|
-
*/
|
|
1040
|
-
// TODO(misko): This is wrong. The NG_ELEMENT_ID should never be minified.
|
|
1041
|
-
const NG_ELEMENT_ID = getClosureSafeProperty({ __NG_ELEMENT_ID__: getClosureSafeProperty });
|
|
1042
|
-
/**
|
|
1043
|
-
* The `NG_ENV_ID` field on a DI token indicates special processing in the `EnvironmentInjector`:
|
|
1044
|
-
* getting such tokens from the `EnvironmentInjector` will bypass the standard DI resolution
|
|
1045
|
-
* strategy and instead will return implementation produced by the `NG_ENV_ID` factory function.
|
|
1046
|
-
*
|
|
1047
|
-
* This particular retrieval of DI tokens is mostly done to eliminate circular dependencies and
|
|
1048
|
-
* improve tree-shaking.
|
|
1049
|
-
*/
|
|
1050
|
-
const NG_ENV_ID = getClosureSafeProperty({ __NG_ENV_ID__: getClosureSafeProperty });
|
|
1051
|
-
|
|
1052
1094
|
/**
|
|
1053
1095
|
* Returns an index of `classToSearch` in `className` taking token boundaries into account.
|
|
1054
1096
|
*
|
|
@@ -1951,6 +1993,7 @@ function getNgDirectiveDef(directiveDefinition) {
|
|
|
1951
1993
|
hostDirectives: null,
|
|
1952
1994
|
inputs: invertObject(directiveDefinition.inputs, declaredInputs),
|
|
1953
1995
|
outputs: invertObject(directiveDefinition.outputs),
|
|
1996
|
+
debugInfo: null,
|
|
1954
1997
|
};
|
|
1955
1998
|
}
|
|
1956
1999
|
function initFeatures(definition) {
|
|
@@ -2032,10 +2075,12 @@ function getComponentId(componentDef) {
|
|
|
2032
2075
|
const HOST = 0;
|
|
2033
2076
|
const TVIEW = 1;
|
|
2034
2077
|
const FLAGS = 2;
|
|
2078
|
+
// Shared with LContainer
|
|
2035
2079
|
const PARENT = 3;
|
|
2036
2080
|
const NEXT = 4;
|
|
2037
|
-
const
|
|
2038
|
-
|
|
2081
|
+
const T_HOST = 5;
|
|
2082
|
+
// End shared with LContainer
|
|
2083
|
+
const HYDRATION = 6;
|
|
2039
2084
|
const CLEANUP = 7;
|
|
2040
2085
|
const CONTEXT = 8;
|
|
2041
2086
|
const INJECTOR$1 = 9;
|
|
@@ -2052,7 +2097,6 @@ const QUERIES = 18;
|
|
|
2052
2097
|
const ID = 19;
|
|
2053
2098
|
const EMBEDDED_VIEW_INJECTOR = 20;
|
|
2054
2099
|
const ON_DESTROY_HOOKS = 21;
|
|
2055
|
-
const HYDRATION = 22;
|
|
2056
2100
|
const REACTIVE_TEMPLATE_CONSUMER = 23;
|
|
2057
2101
|
const REACTIVE_HOST_BINDING_CONSUMER = 24;
|
|
2058
2102
|
/**
|
|
@@ -2087,10 +2131,11 @@ const TYPE = 1;
|
|
|
2087
2131
|
* that the `MOVED_VIEWS` are transplanted and on-push.
|
|
2088
2132
|
*/
|
|
2089
2133
|
const HAS_TRANSPLANTED_VIEWS = 2;
|
|
2090
|
-
// PARENT
|
|
2134
|
+
// PARENT and NEXT are indices 3 and 4
|
|
2091
2135
|
// As we already have these constants in LView, we don't need to re-create them.
|
|
2092
|
-
// T_HOST is index
|
|
2136
|
+
// T_HOST is index 5
|
|
2093
2137
|
// We already have this constants in LView, we don't need to re-create it.
|
|
2138
|
+
const HAS_CHILD_VIEWS_TO_REFRESH = 6;
|
|
2094
2139
|
const NATIVE = 7;
|
|
2095
2140
|
const VIEW_REFS = 8;
|
|
2096
2141
|
const MOVED_VIEWS = 9;
|
|
@@ -2235,6 +2280,20 @@ function assertProjectionSlots(lView, errMessage) {
|
|
|
2235
2280
|
function assertParentView(lView, errMessage) {
|
|
2236
2281
|
assertDefined(lView, errMessage || 'Component views should always have a parent view (component\'s host view)');
|
|
2237
2282
|
}
|
|
2283
|
+
function assertNoDuplicateDirectives(directives) {
|
|
2284
|
+
// The array needs at least two elements in order to have duplicates.
|
|
2285
|
+
if (directives.length < 2) {
|
|
2286
|
+
return;
|
|
2287
|
+
}
|
|
2288
|
+
const seenDirectives = new Set();
|
|
2289
|
+
for (const current of directives) {
|
|
2290
|
+
if (seenDirectives.has(current)) {
|
|
2291
|
+
throw new RuntimeError(309 /* RuntimeErrorCode.DUPLICATE_DIRECTITVE */, `Directive ${current.type.name} matches multiple times on the same element. ` +
|
|
2292
|
+
`Directives can only match an element once.`);
|
|
2293
|
+
}
|
|
2294
|
+
seenDirectives.add(current);
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2238
2297
|
/**
|
|
2239
2298
|
* This is a basic sanity check that the `injectorIndex` seems to point to what looks like a
|
|
2240
2299
|
* NodeInjector data structure.
|
|
@@ -2265,906 +2324,345 @@ function getFactoryDef(type, throwNotFound) {
|
|
|
2265
2324
|
}
|
|
2266
2325
|
|
|
2267
2326
|
/**
|
|
2268
|
-
*
|
|
2327
|
+
* Represents a basic change from a previous to a new value for a single
|
|
2328
|
+
* property on a directive instance. Passed as a value in a
|
|
2329
|
+
* {@link SimpleChanges} object to the `ngOnChanges` hook.
|
|
2269
2330
|
*
|
|
2270
|
-
*
|
|
2331
|
+
* @see {@link OnChanges}
|
|
2332
|
+
*
|
|
2333
|
+
* @publicApi
|
|
2271
2334
|
*/
|
|
2272
|
-
|
|
2335
|
+
class SimpleChange {
|
|
2336
|
+
constructor(previousValue, currentValue, firstChange) {
|
|
2337
|
+
this.previousValue = previousValue;
|
|
2338
|
+
this.currentValue = currentValue;
|
|
2339
|
+
this.firstChange = firstChange;
|
|
2340
|
+
}
|
|
2341
|
+
/**
|
|
2342
|
+
* Check whether the new value is the first value assigned.
|
|
2343
|
+
*/
|
|
2344
|
+
isFirstChange() {
|
|
2345
|
+
return this.firstChange;
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2348
|
+
|
|
2273
2349
|
/**
|
|
2274
|
-
*
|
|
2350
|
+
* The NgOnChangesFeature decorates a component with support for the ngOnChanges
|
|
2351
|
+
* lifecycle hook, so it should be included in any component that implements
|
|
2352
|
+
* that hook.
|
|
2275
2353
|
*
|
|
2276
|
-
*
|
|
2354
|
+
* If the component or directive uses inheritance, the NgOnChangesFeature MUST
|
|
2355
|
+
* be included as a feature AFTER {@link InheritDefinitionFeature}, otherwise
|
|
2356
|
+
* inherited properties will not be propagated to the ngOnChanges lifecycle
|
|
2357
|
+
* hook.
|
|
2358
|
+
*
|
|
2359
|
+
* Example usage:
|
|
2360
|
+
*
|
|
2361
|
+
* ```
|
|
2362
|
+
* static ɵcmp = defineComponent({
|
|
2363
|
+
* ...
|
|
2364
|
+
* inputs: {name: 'publicName'},
|
|
2365
|
+
* features: [NgOnChangesFeature]
|
|
2366
|
+
* });
|
|
2367
|
+
* ```
|
|
2368
|
+
*
|
|
2369
|
+
* @codeGenApi
|
|
2277
2370
|
*/
|
|
2278
|
-
function
|
|
2279
|
-
return
|
|
2371
|
+
function ɵɵNgOnChangesFeature() {
|
|
2372
|
+
return NgOnChangesFeatureImpl;
|
|
2373
|
+
}
|
|
2374
|
+
function NgOnChangesFeatureImpl(definition) {
|
|
2375
|
+
if (definition.type.prototype.ngOnChanges) {
|
|
2376
|
+
definition.setInput = ngOnChangesSetInput;
|
|
2377
|
+
}
|
|
2378
|
+
return rememberChangeHistoryAndInvokeOnChangesHook;
|
|
2280
2379
|
}
|
|
2380
|
+
// This option ensures that the ngOnChanges lifecycle hook will be inherited
|
|
2381
|
+
// from superclasses (in InheritDefinitionFeature).
|
|
2382
|
+
/** @nocollapse */
|
|
2383
|
+
// tslint:disable-next-line:no-toplevel-property-access
|
|
2384
|
+
ɵɵNgOnChangesFeature.ngInherit = true;
|
|
2281
2385
|
/**
|
|
2282
|
-
*
|
|
2283
|
-
*
|
|
2386
|
+
* This is a synthetic lifecycle hook which gets inserted into `TView.preOrderHooks` to simulate
|
|
2387
|
+
* `ngOnChanges`.
|
|
2284
2388
|
*
|
|
2285
|
-
*
|
|
2286
|
-
*
|
|
2389
|
+
* The hook reads the `NgSimpleChangesStore` data from the component instance and if changes are
|
|
2390
|
+
* found it invokes `ngOnChanges` on the component instance.
|
|
2287
2391
|
*
|
|
2288
|
-
* @
|
|
2392
|
+
* @param this Component instance. Because this function gets inserted into `TView.preOrderHooks`,
|
|
2393
|
+
* it is guaranteed to be called with component instance.
|
|
2289
2394
|
*/
|
|
2290
|
-
function
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2395
|
+
function rememberChangeHistoryAndInvokeOnChangesHook() {
|
|
2396
|
+
const simpleChangesStore = getSimpleChangesStore(this);
|
|
2397
|
+
const current = simpleChangesStore?.current;
|
|
2398
|
+
if (current) {
|
|
2399
|
+
const previous = simpleChangesStore.previous;
|
|
2400
|
+
if (previous === EMPTY_OBJ) {
|
|
2401
|
+
simpleChangesStore.previous = current;
|
|
2402
|
+
}
|
|
2403
|
+
else {
|
|
2404
|
+
// New changes are copied to the previous store, so that we don't lose history for inputs
|
|
2405
|
+
// which were not changed this time
|
|
2406
|
+
for (let key in current) {
|
|
2407
|
+
previous[key] = current[key];
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
simpleChangesStore.current = null;
|
|
2411
|
+
this.ngOnChanges(current);
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2414
|
+
function ngOnChangesSetInput(instance, value, publicName, privateName) {
|
|
2415
|
+
const declaredName = this.declaredInputs[publicName];
|
|
2416
|
+
ngDevMode && assertString(declaredName, 'Name of input in ngOnChanges has to be a string');
|
|
2417
|
+
const simpleChangesStore = getSimpleChangesStore(instance) ||
|
|
2418
|
+
setSimpleChangesStore(instance, { previous: EMPTY_OBJ, current: null });
|
|
2419
|
+
const current = simpleChangesStore.current || (simpleChangesStore.current = {});
|
|
2420
|
+
const previous = simpleChangesStore.previous;
|
|
2421
|
+
const previousChange = previous[declaredName];
|
|
2422
|
+
current[declaredName] = new SimpleChange(previousChange && previousChange.currentValue, value, previous === EMPTY_OBJ);
|
|
2423
|
+
instance[privateName] = value;
|
|
2424
|
+
}
|
|
2425
|
+
const SIMPLE_CHANGES_STORE = '__ngSimpleChanges__';
|
|
2426
|
+
function getSimpleChangesStore(instance) {
|
|
2427
|
+
return instance[SIMPLE_CHANGES_STORE] || null;
|
|
2428
|
+
}
|
|
2429
|
+
function setSimpleChangesStore(instance, store) {
|
|
2430
|
+
return instance[SIMPLE_CHANGES_STORE] = store;
|
|
2297
2431
|
}
|
|
2298
2432
|
|
|
2299
|
-
|
|
2433
|
+
let profilerCallback = null;
|
|
2300
2434
|
/**
|
|
2301
|
-
*
|
|
2435
|
+
* Sets the callback function which will be invoked before and after performing certain actions at
|
|
2436
|
+
* runtime (for example, before and after running change detection).
|
|
2302
2437
|
*
|
|
2303
|
-
*
|
|
2438
|
+
* Warning: this function is *INTERNAL* and should not be relied upon in application's code.
|
|
2439
|
+
* The contract of the function might be changed in any release and/or the function can be removed
|
|
2440
|
+
* completely.
|
|
2441
|
+
*
|
|
2442
|
+
* @param profiler function provided by the caller or null value to disable profiling.
|
|
2304
2443
|
*/
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
function setActiveConsumer(consumer) {
|
|
2308
|
-
const prev = activeConsumer;
|
|
2309
|
-
activeConsumer = consumer;
|
|
2310
|
-
return prev;
|
|
2311
|
-
}
|
|
2312
|
-
function isInNotificationPhase() {
|
|
2313
|
-
return inNotificationPhase;
|
|
2314
|
-
}
|
|
2315
|
-
const REACTIVE_NODE = {
|
|
2316
|
-
version: 0,
|
|
2317
|
-
dirty: false,
|
|
2318
|
-
producerNode: undefined,
|
|
2319
|
-
producerLastReadVersion: undefined,
|
|
2320
|
-
producerIndexOfThis: undefined,
|
|
2321
|
-
nextProducerIndex: 0,
|
|
2322
|
-
liveConsumerNode: undefined,
|
|
2323
|
-
liveConsumerIndexOfThis: undefined,
|
|
2324
|
-
consumerAllowSignalWrites: false,
|
|
2325
|
-
consumerIsAlwaysLive: false,
|
|
2326
|
-
producerMustRecompute: () => false,
|
|
2327
|
-
producerRecomputeValue: () => { },
|
|
2328
|
-
consumerMarkedDirty: () => { },
|
|
2444
|
+
const setProfiler = (profiler) => {
|
|
2445
|
+
profilerCallback = profiler;
|
|
2329
2446
|
};
|
|
2330
2447
|
/**
|
|
2331
|
-
*
|
|
2448
|
+
* Profiler function which wraps user code executed by the runtime.
|
|
2449
|
+
*
|
|
2450
|
+
* @param event ProfilerEvent corresponding to the execution context
|
|
2451
|
+
* @param instance component instance
|
|
2452
|
+
* @param hookOrListener lifecycle hook function or output listener. The value depends on the
|
|
2453
|
+
* execution context
|
|
2454
|
+
* @returns
|
|
2332
2455
|
*/
|
|
2333
|
-
function
|
|
2334
|
-
if (
|
|
2335
|
-
|
|
2336
|
-
`Assertion error: signal read during notification phase` :
|
|
2337
|
-
'');
|
|
2338
|
-
}
|
|
2339
|
-
if (activeConsumer === null) {
|
|
2340
|
-
// Accessed outside of a reactive context, so nothing to record.
|
|
2341
|
-
return;
|
|
2342
|
-
}
|
|
2343
|
-
// This producer is the `idx`th dependency of `activeConsumer`.
|
|
2344
|
-
const idx = activeConsumer.nextProducerIndex++;
|
|
2345
|
-
assertConsumerNode(activeConsumer);
|
|
2346
|
-
if (idx < activeConsumer.producerNode.length && activeConsumer.producerNode[idx] !== node) {
|
|
2347
|
-
// There's been a change in producers since the last execution of `activeConsumer`.
|
|
2348
|
-
// `activeConsumer.producerNode[idx]` holds a stale dependency which will be be removed and
|
|
2349
|
-
// replaced with `this`.
|
|
2350
|
-
//
|
|
2351
|
-
// If `activeConsumer` isn't live, then this is a no-op, since we can replace the producer in
|
|
2352
|
-
// `activeConsumer.producerNode` directly. However, if `activeConsumer` is live, then we need
|
|
2353
|
-
// to remove it from the stale producer's `liveConsumer`s.
|
|
2354
|
-
if (consumerIsLive(activeConsumer)) {
|
|
2355
|
-
const staleProducer = activeConsumer.producerNode[idx];
|
|
2356
|
-
producerRemoveLiveConsumerAtIndex(staleProducer, activeConsumer.producerIndexOfThis[idx]);
|
|
2357
|
-
// At this point, the only record of `staleProducer` is the reference at
|
|
2358
|
-
// `activeConsumer.producerNode[idx]` which will be overwritten below.
|
|
2359
|
-
}
|
|
2360
|
-
}
|
|
2361
|
-
if (activeConsumer.producerNode[idx] !== node) {
|
|
2362
|
-
// We're a new dependency of the consumer (at `idx`).
|
|
2363
|
-
activeConsumer.producerNode[idx] = node;
|
|
2364
|
-
// If the active consumer is live, then add it as a live consumer. If not, then use 0 as a
|
|
2365
|
-
// placeholder value.
|
|
2366
|
-
activeConsumer.producerIndexOfThis[idx] =
|
|
2367
|
-
consumerIsLive(activeConsumer) ? producerAddLiveConsumer(node, activeConsumer, idx) : 0;
|
|
2456
|
+
const profiler = function (event, instance, hookOrListener) {
|
|
2457
|
+
if (profilerCallback != null /* both `null` and `undefined` */) {
|
|
2458
|
+
profilerCallback(event, instance, hookOrListener);
|
|
2368
2459
|
}
|
|
2369
|
-
|
|
2370
|
-
|
|
2460
|
+
};
|
|
2461
|
+
|
|
2462
|
+
const SVG_NAMESPACE = 'svg';
|
|
2463
|
+
const MATH_ML_NAMESPACE = 'math';
|
|
2464
|
+
|
|
2371
2465
|
/**
|
|
2372
|
-
*
|
|
2466
|
+
* For efficiency reasons we often put several different data types (`RNode`, `LView`, `LContainer`)
|
|
2467
|
+
* in same location in `LView`. This is because we don't want to pre-allocate space for it
|
|
2468
|
+
* because the storage is sparse. This file contains utilities for dealing with such data types.
|
|
2469
|
+
*
|
|
2470
|
+
* How do we know what is stored at a given location in `LView`.
|
|
2471
|
+
* - `Array.isArray(value) === false` => `RNode` (The normal storage value)
|
|
2472
|
+
* - `Array.isArray(value) === true` => then the `value[0]` represents the wrapped value.
|
|
2473
|
+
* - `typeof value[TYPE] === 'object'` => `LView`
|
|
2474
|
+
* - This happens when we have a component at a given location
|
|
2475
|
+
* - `typeof value[TYPE] === true` => `LContainer`
|
|
2476
|
+
* - This happens when we have `LContainer` binding at a given location.
|
|
2477
|
+
*
|
|
2478
|
+
*
|
|
2479
|
+
* NOTE: it is assumed that `Array.isArray` and `typeof` operations are very efficient.
|
|
2373
2480
|
*/
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
// None of our producers report a change since the last time they were read, so no
|
|
2382
|
-
// recomputation of our value is necessary, and we can consider ourselves clean.
|
|
2383
|
-
node.dirty = false;
|
|
2384
|
-
return;
|
|
2481
|
+
/**
|
|
2482
|
+
* Returns `RNode`.
|
|
2483
|
+
* @param value wrapped value of `RNode`, `LView`, `LContainer`
|
|
2484
|
+
*/
|
|
2485
|
+
function unwrapRNode(value) {
|
|
2486
|
+
while (Array.isArray(value)) {
|
|
2487
|
+
value = value[HOST];
|
|
2385
2488
|
}
|
|
2386
|
-
|
|
2387
|
-
// After recomputing the value, we're no longer dirty.
|
|
2388
|
-
node.dirty = false;
|
|
2489
|
+
return value;
|
|
2389
2490
|
}
|
|
2390
2491
|
/**
|
|
2391
|
-
*
|
|
2492
|
+
* Returns `LView` or `null` if not found.
|
|
2493
|
+
* @param value wrapped value of `RNode`, `LView`, `LContainer`
|
|
2392
2494
|
*/
|
|
2393
|
-
function
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
try {
|
|
2401
|
-
for (const consumer of node.liveConsumerNode) {
|
|
2402
|
-
if (!consumer.dirty) {
|
|
2403
|
-
consumerMarkDirty(consumer);
|
|
2404
|
-
}
|
|
2405
|
-
}
|
|
2406
|
-
}
|
|
2407
|
-
finally {
|
|
2408
|
-
inNotificationPhase = prev;
|
|
2495
|
+
function unwrapLView(value) {
|
|
2496
|
+
while (Array.isArray(value)) {
|
|
2497
|
+
// This check is same as `isLView()` but we don't call at as we don't want to call
|
|
2498
|
+
// `Array.isArray()` twice and give JITer more work for inlining.
|
|
2499
|
+
if (typeof value[TYPE] === 'object')
|
|
2500
|
+
return value;
|
|
2501
|
+
value = value[HOST];
|
|
2409
2502
|
}
|
|
2503
|
+
return null;
|
|
2410
2504
|
}
|
|
2411
2505
|
/**
|
|
2412
|
-
*
|
|
2413
|
-
*
|
|
2506
|
+
* Retrieves an element value from the provided `viewData`, by unwrapping
|
|
2507
|
+
* from any containers, component views, or style contexts.
|
|
2414
2508
|
*/
|
|
2415
|
-
function
|
|
2416
|
-
|
|
2509
|
+
function getNativeByIndex(index, lView) {
|
|
2510
|
+
ngDevMode && assertIndexInRange(lView, index);
|
|
2511
|
+
ngDevMode && assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Expected to be past HEADER_OFFSET');
|
|
2512
|
+
return unwrapRNode(lView[index]);
|
|
2417
2513
|
}
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2514
|
+
/**
|
|
2515
|
+
* Retrieve an `RNode` for a given `TNode` and `LView`.
|
|
2516
|
+
*
|
|
2517
|
+
* This function guarantees in dev mode to retrieve a non-null `RNode`.
|
|
2518
|
+
*
|
|
2519
|
+
* @param tNode
|
|
2520
|
+
* @param lView
|
|
2521
|
+
*/
|
|
2522
|
+
function getNativeByTNode(tNode, lView) {
|
|
2523
|
+
ngDevMode && assertTNodeForLView(tNode, lView);
|
|
2524
|
+
ngDevMode && assertIndexInRange(lView, tNode.index);
|
|
2525
|
+
const node = unwrapRNode(lView[tNode.index]);
|
|
2526
|
+
return node;
|
|
2422
2527
|
}
|
|
2423
2528
|
/**
|
|
2424
|
-
*
|
|
2529
|
+
* Retrieve an `RNode` or `null` for a given `TNode` and `LView`.
|
|
2425
2530
|
*
|
|
2426
|
-
*
|
|
2427
|
-
*
|
|
2531
|
+
* Some `TNode`s don't have associated `RNode`s. For example `Projection`
|
|
2532
|
+
*
|
|
2533
|
+
* @param tNode
|
|
2534
|
+
* @param lView
|
|
2428
2535
|
*/
|
|
2429
|
-
function
|
|
2430
|
-
|
|
2431
|
-
|
|
2536
|
+
function getNativeByTNodeOrNull(tNode, lView) {
|
|
2537
|
+
const index = tNode === null ? -1 : tNode.index;
|
|
2538
|
+
if (index !== -1) {
|
|
2539
|
+
ngDevMode && assertTNodeForLView(tNode, lView);
|
|
2540
|
+
const node = unwrapRNode(lView[index]);
|
|
2541
|
+
return node;
|
|
2542
|
+
}
|
|
2543
|
+
return null;
|
|
2544
|
+
}
|
|
2545
|
+
// fixme(misko): The return Type should be `TNode|null`
|
|
2546
|
+
function getTNode(tView, index) {
|
|
2547
|
+
ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode');
|
|
2548
|
+
ngDevMode && assertLessThan(index, tView.data.length, 'wrong index for TNode');
|
|
2549
|
+
const tNode = tView.data[index];
|
|
2550
|
+
ngDevMode && tNode !== null && assertTNode(tNode);
|
|
2551
|
+
return tNode;
|
|
2552
|
+
}
|
|
2553
|
+
/** Retrieves a value from any `LView` or `TData`. */
|
|
2554
|
+
function load(view, index) {
|
|
2555
|
+
ngDevMode && assertIndexInRange(view, index);
|
|
2556
|
+
return view[index];
|
|
2557
|
+
}
|
|
2558
|
+
function getComponentLViewByIndex(nodeIndex, hostView) {
|
|
2559
|
+
// Could be an LView or an LContainer. If LContainer, unwrap to find LView.
|
|
2560
|
+
ngDevMode && assertIndexInRange(hostView, nodeIndex);
|
|
2561
|
+
const slotValue = hostView[nodeIndex];
|
|
2562
|
+
const lView = isLView(slotValue) ? slotValue : slotValue[HOST];
|
|
2563
|
+
return lView;
|
|
2564
|
+
}
|
|
2565
|
+
/** Checks whether a given view is in creation mode */
|
|
2566
|
+
function isCreationMode(view) {
|
|
2567
|
+
return (view[FLAGS] & 4 /* LViewFlags.CreationMode */) === 4 /* LViewFlags.CreationMode */;
|
|
2432
2568
|
}
|
|
2433
2569
|
/**
|
|
2434
|
-
*
|
|
2570
|
+
* Returns a boolean for whether the view is attached to the change detection tree.
|
|
2435
2571
|
*
|
|
2436
|
-
*
|
|
2437
|
-
*
|
|
2572
|
+
* Note: This determines whether a view should be checked, not whether it's inserted
|
|
2573
|
+
* into a container. For that, you'll want `viewAttachedToContainer` below.
|
|
2438
2574
|
*/
|
|
2439
|
-
function
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2575
|
+
function viewAttachedToChangeDetector(view) {
|
|
2576
|
+
return (view[FLAGS] & 128 /* LViewFlags.Attached */) === 128 /* LViewFlags.Attached */;
|
|
2577
|
+
}
|
|
2578
|
+
/** Returns a boolean for whether the view is attached to a container. */
|
|
2579
|
+
function viewAttachedToContainer(view) {
|
|
2580
|
+
return isLContainer(view[PARENT]);
|
|
2581
|
+
}
|
|
2582
|
+
function getConstant(consts, index) {
|
|
2583
|
+
if (index === null || index === undefined)
|
|
2584
|
+
return null;
|
|
2585
|
+
ngDevMode && assertIndexInRange(consts, index);
|
|
2586
|
+
return consts[index];
|
|
2587
|
+
}
|
|
2588
|
+
/**
|
|
2589
|
+
* Resets the pre-order hook flags of the view.
|
|
2590
|
+
* @param lView the LView on which the flags are reset
|
|
2591
|
+
*/
|
|
2592
|
+
function resetPreOrderHookFlags(lView) {
|
|
2593
|
+
lView[PREORDER_HOOK_FLAGS] = 0;
|
|
2594
|
+
}
|
|
2595
|
+
/**
|
|
2596
|
+
* Adds the `RefreshView` flag from the lView and updates HAS_CHILD_VIEWS_TO_REFRESH flag of
|
|
2597
|
+
* parents.
|
|
2598
|
+
*/
|
|
2599
|
+
function markViewForRefresh(lView) {
|
|
2600
|
+
if (lView[FLAGS] & 1024 /* LViewFlags.RefreshView */) {
|
|
2443
2601
|
return;
|
|
2444
2602
|
}
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
for (let i = node.nextProducerIndex; i < node.producerNode.length; i++) {
|
|
2449
|
-
producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]);
|
|
2450
|
-
}
|
|
2451
|
-
}
|
|
2452
|
-
// Truncate the producer tracking arrays.
|
|
2453
|
-
// Perf note: this is essentially truncating the length to `node.nextProducerIndex`, but
|
|
2454
|
-
// benchmarking has shown that individual pop operations are faster.
|
|
2455
|
-
while (node.producerNode.length > node.nextProducerIndex) {
|
|
2456
|
-
node.producerNode.pop();
|
|
2457
|
-
node.producerLastReadVersion.pop();
|
|
2458
|
-
node.producerIndexOfThis.pop();
|
|
2603
|
+
lView[FLAGS] |= 1024 /* LViewFlags.RefreshView */;
|
|
2604
|
+
if (viewAttachedToChangeDetector(lView)) {
|
|
2605
|
+
markAncestorsForTraversal(lView);
|
|
2459
2606
|
}
|
|
2460
2607
|
}
|
|
2461
2608
|
/**
|
|
2462
|
-
*
|
|
2463
|
-
*
|
|
2609
|
+
* Walks up the LView hierarchy.
|
|
2610
|
+
* @param nestingLevel Number of times to walk up in hierarchy.
|
|
2611
|
+
* @param currentView View from which to start the lookup.
|
|
2464
2612
|
*/
|
|
2465
|
-
function
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
// First check the versions. A mismatch means that the producer's value is known to have
|
|
2472
|
-
// changed since the last time we read it.
|
|
2473
|
-
if (seenVersion !== producer.version) {
|
|
2474
|
-
return true;
|
|
2475
|
-
}
|
|
2476
|
-
// The producer's version is the same as the last time we read it, but it might itself be
|
|
2477
|
-
// stale. Force the producer to recompute its version (calculating a new value if necessary).
|
|
2478
|
-
producerUpdateValueVersion(producer);
|
|
2479
|
-
// Now when we do this check, `producer.version` is guaranteed to be up to date, so if the
|
|
2480
|
-
// versions still match then it has not changed since the last time we read it.
|
|
2481
|
-
if (seenVersion !== producer.version) {
|
|
2482
|
-
return true;
|
|
2483
|
-
}
|
|
2613
|
+
function walkUpViews(nestingLevel, currentView) {
|
|
2614
|
+
while (nestingLevel > 0) {
|
|
2615
|
+
ngDevMode &&
|
|
2616
|
+
assertDefined(currentView[DECLARATION_VIEW], 'Declaration view should be defined if nesting level is greater than 0.');
|
|
2617
|
+
currentView = currentView[DECLARATION_VIEW];
|
|
2618
|
+
nestingLevel--;
|
|
2484
2619
|
}
|
|
2485
|
-
return
|
|
2620
|
+
return currentView;
|
|
2486
2621
|
}
|
|
2487
2622
|
/**
|
|
2488
|
-
*
|
|
2623
|
+
* Updates the `DESCENDANT_VIEWS_TO_REFRESH` counter on the parents of the `LView` as well as the
|
|
2624
|
+
* parents above that whose
|
|
2625
|
+
* 1. counter goes from 0 to 1, indicating that there is a new child that has a view to refresh
|
|
2626
|
+
* or
|
|
2627
|
+
* 2. counter goes from 1 to 0, indicating there are no more descendant views to refresh
|
|
2628
|
+
* When attaching/re-attaching an `LView` to the change detection tree, we need to ensure that the
|
|
2629
|
+
* views above it are traversed during change detection if this one is marked for refresh or has
|
|
2630
|
+
* some child or descendant that needs to be refreshed.
|
|
2489
2631
|
*/
|
|
2490
|
-
function
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
// Drop all connections from the graph to this node.
|
|
2494
|
-
for (let i = 0; i < node.producerNode.length; i++) {
|
|
2495
|
-
producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]);
|
|
2496
|
-
}
|
|
2497
|
-
}
|
|
2498
|
-
// Truncate all the arrays to drop all connection from this node to the graph.
|
|
2499
|
-
node.producerNode.length = node.producerLastReadVersion.length = node.producerIndexOfThis.length =
|
|
2500
|
-
0;
|
|
2501
|
-
if (node.liveConsumerNode) {
|
|
2502
|
-
node.liveConsumerNode.length = node.liveConsumerIndexOfThis.length = 0;
|
|
2632
|
+
function updateAncestorTraversalFlagsOnAttach(lView) {
|
|
2633
|
+
if (lView[FLAGS] & (1024 /* LViewFlags.RefreshView */ | 8192 /* LViewFlags.HasChildViewsToRefresh */)) {
|
|
2634
|
+
markAncestorsForTraversal(lView);
|
|
2503
2635
|
}
|
|
2504
2636
|
}
|
|
2505
2637
|
/**
|
|
2506
|
-
*
|
|
2638
|
+
* Ensures views above the given `lView` are traversed during change detection even when they are
|
|
2639
|
+
* not dirty.
|
|
2507
2640
|
*
|
|
2508
|
-
*
|
|
2509
|
-
*
|
|
2641
|
+
* This is done by setting the `HAS_CHILD_VIEWS_TO_REFRESH` flag up to the root, stopping when the
|
|
2642
|
+
* flag is already `true` or the `lView` is detached.
|
|
2510
2643
|
*/
|
|
2511
|
-
function
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2644
|
+
function markAncestorsForTraversal(lView) {
|
|
2645
|
+
let parent = lView[PARENT];
|
|
2646
|
+
if (parent === null) {
|
|
2647
|
+
return;
|
|
2648
|
+
}
|
|
2649
|
+
while (parent !== null) {
|
|
2650
|
+
// We stop adding markers to the ancestors once we reach one that already has the marker. This
|
|
2651
|
+
// is to avoid needlessly traversing all the way to the root when the marker already exists.
|
|
2652
|
+
if ((isLContainer(parent) && parent[HAS_CHILD_VIEWS_TO_REFRESH] ||
|
|
2653
|
+
(isLView(parent) && parent[FLAGS] & 8192 /* LViewFlags.HasChildViewsToRefresh */))) {
|
|
2654
|
+
break;
|
|
2655
|
+
}
|
|
2656
|
+
if (isLContainer(parent)) {
|
|
2657
|
+
parent[HAS_CHILD_VIEWS_TO_REFRESH] = true;
|
|
2518
2658
|
}
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
function producerRemoveLiveConsumerAtIndex(node, idx) {
|
|
2527
|
-
assertProducerNode(node);
|
|
2528
|
-
assertConsumerNode(node);
|
|
2529
|
-
if (typeof ngDevMode !== 'undefined' && ngDevMode && idx >= node.liveConsumerNode.length) {
|
|
2530
|
-
throw new Error(`Assertion error: active consumer index ${idx} is out of bounds of ${node.liveConsumerNode.length} consumers)`);
|
|
2531
|
-
}
|
|
2532
|
-
if (node.liveConsumerNode.length === 1) {
|
|
2533
|
-
// When removing the last live consumer, we will no longer be live. We need to remove
|
|
2534
|
-
// ourselves from our producers' tracking (which may cause consumer-producers to lose
|
|
2535
|
-
// liveness as well).
|
|
2536
|
-
for (let i = 0; i < node.producerNode.length; i++) {
|
|
2537
|
-
producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]);
|
|
2538
|
-
}
|
|
2539
|
-
}
|
|
2540
|
-
// Move the last value of `liveConsumers` into `idx`. Note that if there's only a single
|
|
2541
|
-
// live consumer, this is a no-op.
|
|
2542
|
-
const lastIdx = node.liveConsumerNode.length - 1;
|
|
2543
|
-
node.liveConsumerNode[idx] = node.liveConsumerNode[lastIdx];
|
|
2544
|
-
node.liveConsumerIndexOfThis[idx] = node.liveConsumerIndexOfThis[lastIdx];
|
|
2545
|
-
// Truncate the array.
|
|
2546
|
-
node.liveConsumerNode.length--;
|
|
2547
|
-
node.liveConsumerIndexOfThis.length--;
|
|
2548
|
-
// If the index is still valid, then we need to fix the index pointer from the producer to this
|
|
2549
|
-
// consumer, and update it from `lastIdx` to `idx` (accounting for the move above).
|
|
2550
|
-
if (idx < node.liveConsumerNode.length) {
|
|
2551
|
-
const idxProducer = node.liveConsumerIndexOfThis[idx];
|
|
2552
|
-
const consumer = node.liveConsumerNode[idx];
|
|
2553
|
-
assertConsumerNode(consumer);
|
|
2554
|
-
consumer.producerIndexOfThis[idxProducer] = idx;
|
|
2555
|
-
}
|
|
2556
|
-
}
|
|
2557
|
-
function consumerIsLive(node) {
|
|
2558
|
-
return node.consumerIsAlwaysLive || (node?.liveConsumerNode?.length ?? 0) > 0;
|
|
2559
|
-
}
|
|
2560
|
-
function assertConsumerNode(node) {
|
|
2561
|
-
node.producerNode ??= [];
|
|
2562
|
-
node.producerIndexOfThis ??= [];
|
|
2563
|
-
node.producerLastReadVersion ??= [];
|
|
2564
|
-
}
|
|
2565
|
-
function assertProducerNode(node) {
|
|
2566
|
-
node.liveConsumerNode ??= [];
|
|
2567
|
-
node.liveConsumerIndexOfThis ??= [];
|
|
2568
|
-
}
|
|
2569
|
-
|
|
2570
|
-
/**
|
|
2571
|
-
* Create a computed `Signal` which derives a reactive value from an expression.
|
|
2572
|
-
*
|
|
2573
|
-
* @developerPreview
|
|
2574
|
-
*/
|
|
2575
|
-
function computed(computation, options) {
|
|
2576
|
-
const node = Object.create(COMPUTED_NODE);
|
|
2577
|
-
node.computation = computation;
|
|
2578
|
-
options?.equal && (node.equal = options.equal);
|
|
2579
|
-
const computed = () => {
|
|
2580
|
-
// Check if the value needs updating before returning it.
|
|
2581
|
-
producerUpdateValueVersion(node);
|
|
2582
|
-
// Record that someone looked at this signal.
|
|
2583
|
-
producerAccessed(node);
|
|
2584
|
-
if (node.value === ERRORED) {
|
|
2585
|
-
throw node.error;
|
|
2586
|
-
}
|
|
2587
|
-
return node.value;
|
|
2588
|
-
};
|
|
2589
|
-
computed[SIGNAL] = node;
|
|
2590
|
-
return computed;
|
|
2591
|
-
}
|
|
2592
|
-
/**
|
|
2593
|
-
* A dedicated symbol used before a computed value has been calculated for the first time.
|
|
2594
|
-
* Explicitly typed as `any` so we can use it as signal's value.
|
|
2595
|
-
*/
|
|
2596
|
-
const UNSET = /* @__PURE__ */ Symbol('UNSET');
|
|
2597
|
-
/**
|
|
2598
|
-
* A dedicated symbol used in place of a computed signal value to indicate that a given computation
|
|
2599
|
-
* is in progress. Used to detect cycles in computation chains.
|
|
2600
|
-
* Explicitly typed as `any` so we can use it as signal's value.
|
|
2601
|
-
*/
|
|
2602
|
-
const COMPUTING = /* @__PURE__ */ Symbol('COMPUTING');
|
|
2603
|
-
/**
|
|
2604
|
-
* A dedicated symbol used in place of a computed signal value to indicate that a given computation
|
|
2605
|
-
* failed. The thrown error is cached until the computation gets dirty again.
|
|
2606
|
-
* Explicitly typed as `any` so we can use it as signal's value.
|
|
2607
|
-
*/
|
|
2608
|
-
const ERRORED = /* @__PURE__ */ Symbol('ERRORED');
|
|
2609
|
-
// Note: Using an IIFE here to ensure that the spread assignment is not considered
|
|
2610
|
-
// a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
|
|
2611
|
-
// TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
|
|
2612
|
-
const COMPUTED_NODE = /* @__PURE__ */ (() => {
|
|
2613
|
-
return {
|
|
2614
|
-
...REACTIVE_NODE,
|
|
2615
|
-
value: UNSET,
|
|
2616
|
-
dirty: true,
|
|
2617
|
-
error: null,
|
|
2618
|
-
equal: defaultEquals,
|
|
2619
|
-
producerMustRecompute(node) {
|
|
2620
|
-
// Force a recomputation if there's no current value, or if the current value is in the
|
|
2621
|
-
// process of being calculated (which should throw an error).
|
|
2622
|
-
return node.value === UNSET || node.value === COMPUTING;
|
|
2623
|
-
},
|
|
2624
|
-
producerRecomputeValue(node) {
|
|
2625
|
-
if (node.value === COMPUTING) {
|
|
2626
|
-
// Our computation somehow led to a cyclic read of itself.
|
|
2627
|
-
throw new Error('Detected cycle in computations.');
|
|
2628
|
-
}
|
|
2629
|
-
const oldValue = node.value;
|
|
2630
|
-
node.value = COMPUTING;
|
|
2631
|
-
const prevConsumer = consumerBeforeComputation(node);
|
|
2632
|
-
let newValue;
|
|
2633
|
-
try {
|
|
2634
|
-
newValue = node.computation();
|
|
2635
|
-
}
|
|
2636
|
-
catch (err) {
|
|
2637
|
-
newValue = ERRORED;
|
|
2638
|
-
node.error = err;
|
|
2639
|
-
}
|
|
2640
|
-
finally {
|
|
2641
|
-
consumerAfterComputation(node, prevConsumer);
|
|
2642
|
-
}
|
|
2643
|
-
if (oldValue !== UNSET && oldValue !== ERRORED && newValue !== ERRORED &&
|
|
2644
|
-
node.equal(oldValue, newValue)) {
|
|
2645
|
-
// No change to `valueVersion` - old and new values are
|
|
2646
|
-
// semantically equivalent.
|
|
2647
|
-
node.value = oldValue;
|
|
2648
|
-
return;
|
|
2649
|
-
}
|
|
2650
|
-
node.value = newValue;
|
|
2651
|
-
node.version++;
|
|
2652
|
-
},
|
|
2653
|
-
};
|
|
2654
|
-
})();
|
|
2655
|
-
|
|
2656
|
-
function defaultThrowError() {
|
|
2657
|
-
throw new Error();
|
|
2658
|
-
}
|
|
2659
|
-
let throwInvalidWriteToSignalErrorFn = defaultThrowError;
|
|
2660
|
-
function throwInvalidWriteToSignalError() {
|
|
2661
|
-
throwInvalidWriteToSignalErrorFn();
|
|
2662
|
-
}
|
|
2663
|
-
function setThrowInvalidWriteToSignalError(fn) {
|
|
2664
|
-
throwInvalidWriteToSignalErrorFn = fn;
|
|
2665
|
-
}
|
|
2666
|
-
|
|
2667
|
-
/**
|
|
2668
|
-
* If set, called after `WritableSignal`s are updated.
|
|
2669
|
-
*
|
|
2670
|
-
* This hook can be used to achieve various effects, such as running effects synchronously as part
|
|
2671
|
-
* of setting a signal.
|
|
2672
|
-
*/
|
|
2673
|
-
let postSignalSetFn = null;
|
|
2674
|
-
/**
|
|
2675
|
-
* Create a `Signal` that can be set or updated directly.
|
|
2676
|
-
*
|
|
2677
|
-
* @developerPreview
|
|
2678
|
-
*/
|
|
2679
|
-
function signal(initialValue, options) {
|
|
2680
|
-
const node = Object.create(SIGNAL_NODE);
|
|
2681
|
-
node.value = initialValue;
|
|
2682
|
-
options?.equal && (node.equal = options.equal);
|
|
2683
|
-
function signalFn() {
|
|
2684
|
-
producerAccessed(node);
|
|
2685
|
-
return node.value;
|
|
2686
|
-
}
|
|
2687
|
-
signalFn.set = signalSetFn;
|
|
2688
|
-
signalFn.update = signalUpdateFn;
|
|
2689
|
-
signalFn.mutate = signalMutateFn;
|
|
2690
|
-
signalFn.asReadonly = signalAsReadonlyFn;
|
|
2691
|
-
signalFn[SIGNAL] = node;
|
|
2692
|
-
return signalFn;
|
|
2693
|
-
}
|
|
2694
|
-
function setPostSignalSetFn(fn) {
|
|
2695
|
-
const prev = postSignalSetFn;
|
|
2696
|
-
postSignalSetFn = fn;
|
|
2697
|
-
return prev;
|
|
2698
|
-
}
|
|
2699
|
-
// Note: Using an IIFE here to ensure that the spread assignment is not considered
|
|
2700
|
-
// a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
|
|
2701
|
-
// TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
|
|
2702
|
-
const SIGNAL_NODE = /* @__PURE__ */ (() => {
|
|
2703
|
-
return {
|
|
2704
|
-
...REACTIVE_NODE,
|
|
2705
|
-
equal: defaultEquals,
|
|
2706
|
-
readonlyFn: undefined,
|
|
2707
|
-
};
|
|
2708
|
-
})();
|
|
2709
|
-
function signalValueChanged(node) {
|
|
2710
|
-
node.version++;
|
|
2711
|
-
producerNotifyConsumers(node);
|
|
2712
|
-
postSignalSetFn?.();
|
|
2713
|
-
}
|
|
2714
|
-
function signalSetFn(newValue) {
|
|
2715
|
-
const node = this[SIGNAL];
|
|
2716
|
-
if (!producerUpdatesAllowed()) {
|
|
2717
|
-
throwInvalidWriteToSignalError();
|
|
2718
|
-
}
|
|
2719
|
-
if (!node.equal(node.value, newValue)) {
|
|
2720
|
-
node.value = newValue;
|
|
2721
|
-
signalValueChanged(node);
|
|
2722
|
-
}
|
|
2723
|
-
}
|
|
2724
|
-
function signalUpdateFn(updater) {
|
|
2725
|
-
if (!producerUpdatesAllowed()) {
|
|
2726
|
-
throwInvalidWriteToSignalError();
|
|
2727
|
-
}
|
|
2728
|
-
signalSetFn.call(this, updater(this[SIGNAL].value));
|
|
2729
|
-
}
|
|
2730
|
-
function signalMutateFn(mutator) {
|
|
2731
|
-
const node = this[SIGNAL];
|
|
2732
|
-
if (!producerUpdatesAllowed()) {
|
|
2733
|
-
throwInvalidWriteToSignalError();
|
|
2734
|
-
}
|
|
2735
|
-
// Mutate bypasses equality checks as it's by definition changing the value.
|
|
2736
|
-
mutator(node.value);
|
|
2737
|
-
signalValueChanged(node);
|
|
2738
|
-
}
|
|
2739
|
-
function signalAsReadonlyFn() {
|
|
2740
|
-
const node = this[SIGNAL];
|
|
2741
|
-
if (node.readonlyFn === undefined) {
|
|
2742
|
-
const readonlyFn = () => this();
|
|
2743
|
-
readonlyFn[SIGNAL] = node;
|
|
2744
|
-
node.readonlyFn = readonlyFn;
|
|
2745
|
-
}
|
|
2746
|
-
return node.readonlyFn;
|
|
2747
|
-
}
|
|
2748
|
-
|
|
2749
|
-
/**
|
|
2750
|
-
* Execute an arbitrary function in a non-reactive (non-tracking) context. The executed function
|
|
2751
|
-
* can, optionally, return a value.
|
|
2752
|
-
*
|
|
2753
|
-
* @developerPreview
|
|
2754
|
-
*/
|
|
2755
|
-
function untracked(nonReactiveReadsFn) {
|
|
2756
|
-
const prevConsumer = setActiveConsumer(null);
|
|
2757
|
-
// We are not trying to catch any particular errors here, just making sure that the consumers
|
|
2758
|
-
// stack is restored in case of errors.
|
|
2759
|
-
try {
|
|
2760
|
-
return nonReactiveReadsFn();
|
|
2761
|
-
}
|
|
2762
|
-
finally {
|
|
2763
|
-
setActiveConsumer(prevConsumer);
|
|
2764
|
-
}
|
|
2765
|
-
}
|
|
2766
|
-
|
|
2767
|
-
function watch(fn, schedule, allowSignalWrites) {
|
|
2768
|
-
const node = Object.create(WATCH_NODE);
|
|
2769
|
-
if (allowSignalWrites) {
|
|
2770
|
-
node.consumerAllowSignalWrites = true;
|
|
2771
|
-
}
|
|
2772
|
-
node.fn = fn;
|
|
2773
|
-
node.schedule = schedule;
|
|
2774
|
-
const registerOnCleanup = (cleanupFn) => {
|
|
2775
|
-
node.cleanupFn = cleanupFn;
|
|
2776
|
-
};
|
|
2777
|
-
function isWatchNodeDestroyed(node) {
|
|
2778
|
-
return node.fn === null && node.schedule === null;
|
|
2779
|
-
}
|
|
2780
|
-
function destroyWatchNode(node) {
|
|
2781
|
-
if (!isWatchNodeDestroyed(node)) {
|
|
2782
|
-
consumerDestroy(node); // disconnect watcher from the reactive graph
|
|
2783
|
-
node.cleanupFn();
|
|
2784
|
-
// nullify references to the integration functions to mark node as destroyed
|
|
2785
|
-
node.fn = null;
|
|
2786
|
-
node.schedule = null;
|
|
2787
|
-
node.cleanupFn = NOOP_CLEANUP_FN;
|
|
2788
|
-
}
|
|
2789
|
-
}
|
|
2790
|
-
const run = () => {
|
|
2791
|
-
if (node.fn === null) {
|
|
2792
|
-
// trying to run a destroyed watch is noop
|
|
2793
|
-
return;
|
|
2794
|
-
}
|
|
2795
|
-
if (isInNotificationPhase()) {
|
|
2796
|
-
throw new Error(`Schedulers cannot synchronously execute watches while scheduling.`);
|
|
2797
|
-
}
|
|
2798
|
-
node.dirty = false;
|
|
2799
|
-
if (node.hasRun && !consumerPollProducersForChange(node)) {
|
|
2800
|
-
return;
|
|
2801
|
-
}
|
|
2802
|
-
node.hasRun = true;
|
|
2803
|
-
const prevConsumer = consumerBeforeComputation(node);
|
|
2804
|
-
try {
|
|
2805
|
-
node.cleanupFn();
|
|
2806
|
-
node.cleanupFn = NOOP_CLEANUP_FN;
|
|
2807
|
-
node.fn(registerOnCleanup);
|
|
2808
|
-
}
|
|
2809
|
-
finally {
|
|
2810
|
-
consumerAfterComputation(node, prevConsumer);
|
|
2811
|
-
}
|
|
2812
|
-
};
|
|
2813
|
-
node.ref = {
|
|
2814
|
-
notify: () => consumerMarkDirty(node),
|
|
2815
|
-
run,
|
|
2816
|
-
cleanup: () => node.cleanupFn(),
|
|
2817
|
-
destroy: () => destroyWatchNode(node),
|
|
2818
|
-
};
|
|
2819
|
-
return node.ref;
|
|
2820
|
-
}
|
|
2821
|
-
const NOOP_CLEANUP_FN = () => { };
|
|
2822
|
-
// Note: Using an IIFE here to ensure that the spread assignment is not considered
|
|
2823
|
-
// a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
|
|
2824
|
-
// TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
|
|
2825
|
-
const WATCH_NODE = /* @__PURE__ */ (() => {
|
|
2826
|
-
return {
|
|
2827
|
-
...REACTIVE_NODE,
|
|
2828
|
-
consumerIsAlwaysLive: true,
|
|
2829
|
-
consumerAllowSignalWrites: false,
|
|
2830
|
-
consumerMarkedDirty: (node) => {
|
|
2831
|
-
if (node.schedule !== null) {
|
|
2832
|
-
node.schedule(node.ref);
|
|
2833
|
-
}
|
|
2834
|
-
},
|
|
2835
|
-
hasRun: false,
|
|
2836
|
-
cleanupFn: NOOP_CLEANUP_FN,
|
|
2837
|
-
};
|
|
2838
|
-
})();
|
|
2839
|
-
|
|
2840
|
-
function setAlternateWeakRefImpl(impl) {
|
|
2841
|
-
// TODO: remove this function
|
|
2842
|
-
}
|
|
2843
|
-
|
|
2844
|
-
/**
|
|
2845
|
-
* Represents a basic change from a previous to a new value for a single
|
|
2846
|
-
* property on a directive instance. Passed as a value in a
|
|
2847
|
-
* {@link SimpleChanges} object to the `ngOnChanges` hook.
|
|
2848
|
-
*
|
|
2849
|
-
* @see {@link OnChanges}
|
|
2850
|
-
*
|
|
2851
|
-
* @publicApi
|
|
2852
|
-
*/
|
|
2853
|
-
class SimpleChange {
|
|
2854
|
-
constructor(previousValue, currentValue, firstChange) {
|
|
2855
|
-
this.previousValue = previousValue;
|
|
2856
|
-
this.currentValue = currentValue;
|
|
2857
|
-
this.firstChange = firstChange;
|
|
2858
|
-
}
|
|
2859
|
-
/**
|
|
2860
|
-
* Check whether the new value is the first value assigned.
|
|
2861
|
-
*/
|
|
2862
|
-
isFirstChange() {
|
|
2863
|
-
return this.firstChange;
|
|
2864
|
-
}
|
|
2865
|
-
}
|
|
2866
|
-
|
|
2867
|
-
/**
|
|
2868
|
-
* The NgOnChangesFeature decorates a component with support for the ngOnChanges
|
|
2869
|
-
* lifecycle hook, so it should be included in any component that implements
|
|
2870
|
-
* that hook.
|
|
2871
|
-
*
|
|
2872
|
-
* If the component or directive uses inheritance, the NgOnChangesFeature MUST
|
|
2873
|
-
* be included as a feature AFTER {@link InheritDefinitionFeature}, otherwise
|
|
2874
|
-
* inherited properties will not be propagated to the ngOnChanges lifecycle
|
|
2875
|
-
* hook.
|
|
2876
|
-
*
|
|
2877
|
-
* Example usage:
|
|
2878
|
-
*
|
|
2879
|
-
* ```
|
|
2880
|
-
* static ɵcmp = defineComponent({
|
|
2881
|
-
* ...
|
|
2882
|
-
* inputs: {name: 'publicName'},
|
|
2883
|
-
* features: [NgOnChangesFeature]
|
|
2884
|
-
* });
|
|
2885
|
-
* ```
|
|
2886
|
-
*
|
|
2887
|
-
* @codeGenApi
|
|
2888
|
-
*/
|
|
2889
|
-
function ɵɵNgOnChangesFeature() {
|
|
2890
|
-
return NgOnChangesFeatureImpl;
|
|
2891
|
-
}
|
|
2892
|
-
function NgOnChangesFeatureImpl(definition) {
|
|
2893
|
-
if (definition.type.prototype.ngOnChanges) {
|
|
2894
|
-
definition.setInput = ngOnChangesSetInput;
|
|
2895
|
-
}
|
|
2896
|
-
return rememberChangeHistoryAndInvokeOnChangesHook;
|
|
2897
|
-
}
|
|
2898
|
-
// This option ensures that the ngOnChanges lifecycle hook will be inherited
|
|
2899
|
-
// from superclasses (in InheritDefinitionFeature).
|
|
2900
|
-
/** @nocollapse */
|
|
2901
|
-
// tslint:disable-next-line:no-toplevel-property-access
|
|
2902
|
-
ɵɵNgOnChangesFeature.ngInherit = true;
|
|
2903
|
-
/**
|
|
2904
|
-
* This is a synthetic lifecycle hook which gets inserted into `TView.preOrderHooks` to simulate
|
|
2905
|
-
* `ngOnChanges`.
|
|
2906
|
-
*
|
|
2907
|
-
* The hook reads the `NgSimpleChangesStore` data from the component instance and if changes are
|
|
2908
|
-
* found it invokes `ngOnChanges` on the component instance.
|
|
2909
|
-
*
|
|
2910
|
-
* @param this Component instance. Because this function gets inserted into `TView.preOrderHooks`,
|
|
2911
|
-
* it is guaranteed to be called with component instance.
|
|
2912
|
-
*/
|
|
2913
|
-
function rememberChangeHistoryAndInvokeOnChangesHook() {
|
|
2914
|
-
const simpleChangesStore = getSimpleChangesStore(this);
|
|
2915
|
-
const current = simpleChangesStore?.current;
|
|
2916
|
-
if (current) {
|
|
2917
|
-
const previous = simpleChangesStore.previous;
|
|
2918
|
-
if (previous === EMPTY_OBJ) {
|
|
2919
|
-
simpleChangesStore.previous = current;
|
|
2920
|
-
}
|
|
2921
|
-
else {
|
|
2922
|
-
// New changes are copied to the previous store, so that we don't lose history for inputs
|
|
2923
|
-
// which were not changed this time
|
|
2924
|
-
for (let key in current) {
|
|
2925
|
-
previous[key] = current[key];
|
|
2926
|
-
}
|
|
2927
|
-
}
|
|
2928
|
-
simpleChangesStore.current = null;
|
|
2929
|
-
this.ngOnChanges(current);
|
|
2930
|
-
}
|
|
2931
|
-
}
|
|
2932
|
-
function ngOnChangesSetInput(instance, value, publicName, privateName) {
|
|
2933
|
-
const declaredName = this.declaredInputs[publicName];
|
|
2934
|
-
ngDevMode && assertString(declaredName, 'Name of input in ngOnChanges has to be a string');
|
|
2935
|
-
const simpleChangesStore = getSimpleChangesStore(instance) ||
|
|
2936
|
-
setSimpleChangesStore(instance, { previous: EMPTY_OBJ, current: null });
|
|
2937
|
-
const current = simpleChangesStore.current || (simpleChangesStore.current = {});
|
|
2938
|
-
const previous = simpleChangesStore.previous;
|
|
2939
|
-
const previousChange = previous[declaredName];
|
|
2940
|
-
current[declaredName] = new SimpleChange(previousChange && previousChange.currentValue, value, previous === EMPTY_OBJ);
|
|
2941
|
-
instance[privateName] = value;
|
|
2942
|
-
}
|
|
2943
|
-
const SIMPLE_CHANGES_STORE = '__ngSimpleChanges__';
|
|
2944
|
-
function getSimpleChangesStore(instance) {
|
|
2945
|
-
return instance[SIMPLE_CHANGES_STORE] || null;
|
|
2946
|
-
}
|
|
2947
|
-
function setSimpleChangesStore(instance, store) {
|
|
2948
|
-
return instance[SIMPLE_CHANGES_STORE] = store;
|
|
2949
|
-
}
|
|
2950
|
-
|
|
2951
|
-
let profilerCallback = null;
|
|
2952
|
-
/**
|
|
2953
|
-
* Sets the callback function which will be invoked before and after performing certain actions at
|
|
2954
|
-
* runtime (for example, before and after running change detection).
|
|
2955
|
-
*
|
|
2956
|
-
* Warning: this function is *INTERNAL* and should not be relied upon in application's code.
|
|
2957
|
-
* The contract of the function might be changed in any release and/or the function can be removed
|
|
2958
|
-
* completely.
|
|
2959
|
-
*
|
|
2960
|
-
* @param profiler function provided by the caller or null value to disable profiling.
|
|
2961
|
-
*/
|
|
2962
|
-
const setProfiler = (profiler) => {
|
|
2963
|
-
profilerCallback = profiler;
|
|
2964
|
-
};
|
|
2965
|
-
/**
|
|
2966
|
-
* Profiler function which wraps user code executed by the runtime.
|
|
2967
|
-
*
|
|
2968
|
-
* @param event ProfilerEvent corresponding to the execution context
|
|
2969
|
-
* @param instance component instance
|
|
2970
|
-
* @param hookOrListener lifecycle hook function or output listener. The value depends on the
|
|
2971
|
-
* execution context
|
|
2972
|
-
* @returns
|
|
2973
|
-
*/
|
|
2974
|
-
const profiler = function (event, instance, hookOrListener) {
|
|
2975
|
-
if (profilerCallback != null /* both `null` and `undefined` */) {
|
|
2976
|
-
profilerCallback(event, instance, hookOrListener);
|
|
2977
|
-
}
|
|
2978
|
-
};
|
|
2979
|
-
|
|
2980
|
-
const SVG_NAMESPACE = 'svg';
|
|
2981
|
-
const MATH_ML_NAMESPACE = 'math';
|
|
2982
|
-
|
|
2983
|
-
/**
|
|
2984
|
-
* For efficiency reasons we often put several different data types (`RNode`, `LView`, `LContainer`)
|
|
2985
|
-
* in same location in `LView`. This is because we don't want to pre-allocate space for it
|
|
2986
|
-
* because the storage is sparse. This file contains utilities for dealing with such data types.
|
|
2987
|
-
*
|
|
2988
|
-
* How do we know what is stored at a given location in `LView`.
|
|
2989
|
-
* - `Array.isArray(value) === false` => `RNode` (The normal storage value)
|
|
2990
|
-
* - `Array.isArray(value) === true` => then the `value[0]` represents the wrapped value.
|
|
2991
|
-
* - `typeof value[TYPE] === 'object'` => `LView`
|
|
2992
|
-
* - This happens when we have a component at a given location
|
|
2993
|
-
* - `typeof value[TYPE] === true` => `LContainer`
|
|
2994
|
-
* - This happens when we have `LContainer` binding at a given location.
|
|
2995
|
-
*
|
|
2996
|
-
*
|
|
2997
|
-
* NOTE: it is assumed that `Array.isArray` and `typeof` operations are very efficient.
|
|
2998
|
-
*/
|
|
2999
|
-
/**
|
|
3000
|
-
* Returns `RNode`.
|
|
3001
|
-
* @param value wrapped value of `RNode`, `LView`, `LContainer`
|
|
3002
|
-
*/
|
|
3003
|
-
function unwrapRNode(value) {
|
|
3004
|
-
while (Array.isArray(value)) {
|
|
3005
|
-
value = value[HOST];
|
|
3006
|
-
}
|
|
3007
|
-
return value;
|
|
3008
|
-
}
|
|
3009
|
-
/**
|
|
3010
|
-
* Returns `LView` or `null` if not found.
|
|
3011
|
-
* @param value wrapped value of `RNode`, `LView`, `LContainer`
|
|
3012
|
-
*/
|
|
3013
|
-
function unwrapLView(value) {
|
|
3014
|
-
while (Array.isArray(value)) {
|
|
3015
|
-
// This check is same as `isLView()` but we don't call at as we don't want to call
|
|
3016
|
-
// `Array.isArray()` twice and give JITer more work for inlining.
|
|
3017
|
-
if (typeof value[TYPE] === 'object')
|
|
3018
|
-
return value;
|
|
3019
|
-
value = value[HOST];
|
|
3020
|
-
}
|
|
3021
|
-
return null;
|
|
3022
|
-
}
|
|
3023
|
-
/**
|
|
3024
|
-
* Retrieves an element value from the provided `viewData`, by unwrapping
|
|
3025
|
-
* from any containers, component views, or style contexts.
|
|
3026
|
-
*/
|
|
3027
|
-
function getNativeByIndex(index, lView) {
|
|
3028
|
-
ngDevMode && assertIndexInRange(lView, index);
|
|
3029
|
-
ngDevMode && assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Expected to be past HEADER_OFFSET');
|
|
3030
|
-
return unwrapRNode(lView[index]);
|
|
3031
|
-
}
|
|
3032
|
-
/**
|
|
3033
|
-
* Retrieve an `RNode` for a given `TNode` and `LView`.
|
|
3034
|
-
*
|
|
3035
|
-
* This function guarantees in dev mode to retrieve a non-null `RNode`.
|
|
3036
|
-
*
|
|
3037
|
-
* @param tNode
|
|
3038
|
-
* @param lView
|
|
3039
|
-
*/
|
|
3040
|
-
function getNativeByTNode(tNode, lView) {
|
|
3041
|
-
ngDevMode && assertTNodeForLView(tNode, lView);
|
|
3042
|
-
ngDevMode && assertIndexInRange(lView, tNode.index);
|
|
3043
|
-
const node = unwrapRNode(lView[tNode.index]);
|
|
3044
|
-
return node;
|
|
3045
|
-
}
|
|
3046
|
-
/**
|
|
3047
|
-
* Retrieve an `RNode` or `null` for a given `TNode` and `LView`.
|
|
3048
|
-
*
|
|
3049
|
-
* Some `TNode`s don't have associated `RNode`s. For example `Projection`
|
|
3050
|
-
*
|
|
3051
|
-
* @param tNode
|
|
3052
|
-
* @param lView
|
|
3053
|
-
*/
|
|
3054
|
-
function getNativeByTNodeOrNull(tNode, lView) {
|
|
3055
|
-
const index = tNode === null ? -1 : tNode.index;
|
|
3056
|
-
if (index !== -1) {
|
|
3057
|
-
ngDevMode && assertTNodeForLView(tNode, lView);
|
|
3058
|
-
const node = unwrapRNode(lView[index]);
|
|
3059
|
-
return node;
|
|
3060
|
-
}
|
|
3061
|
-
return null;
|
|
3062
|
-
}
|
|
3063
|
-
// fixme(misko): The return Type should be `TNode|null`
|
|
3064
|
-
function getTNode(tView, index) {
|
|
3065
|
-
ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode');
|
|
3066
|
-
ngDevMode && assertLessThan(index, tView.data.length, 'wrong index for TNode');
|
|
3067
|
-
const tNode = tView.data[index];
|
|
3068
|
-
ngDevMode && tNode !== null && assertTNode(tNode);
|
|
3069
|
-
return tNode;
|
|
3070
|
-
}
|
|
3071
|
-
/** Retrieves a value from any `LView` or `TData`. */
|
|
3072
|
-
function load(view, index) {
|
|
3073
|
-
ngDevMode && assertIndexInRange(view, index);
|
|
3074
|
-
return view[index];
|
|
3075
|
-
}
|
|
3076
|
-
function getComponentLViewByIndex(nodeIndex, hostView) {
|
|
3077
|
-
// Could be an LView or an LContainer. If LContainer, unwrap to find LView.
|
|
3078
|
-
ngDevMode && assertIndexInRange(hostView, nodeIndex);
|
|
3079
|
-
const slotValue = hostView[nodeIndex];
|
|
3080
|
-
const lView = isLView(slotValue) ? slotValue : slotValue[HOST];
|
|
3081
|
-
return lView;
|
|
3082
|
-
}
|
|
3083
|
-
/** Checks whether a given view is in creation mode */
|
|
3084
|
-
function isCreationMode(view) {
|
|
3085
|
-
return (view[FLAGS] & 4 /* LViewFlags.CreationMode */) === 4 /* LViewFlags.CreationMode */;
|
|
3086
|
-
}
|
|
3087
|
-
/**
|
|
3088
|
-
* Returns a boolean for whether the view is attached to the change detection tree.
|
|
3089
|
-
*
|
|
3090
|
-
* Note: This determines whether a view should be checked, not whether it's inserted
|
|
3091
|
-
* into a container. For that, you'll want `viewAttachedToContainer` below.
|
|
3092
|
-
*/
|
|
3093
|
-
function viewAttachedToChangeDetector(view) {
|
|
3094
|
-
return (view[FLAGS] & 128 /* LViewFlags.Attached */) === 128 /* LViewFlags.Attached */;
|
|
3095
|
-
}
|
|
3096
|
-
/** Returns a boolean for whether the view is attached to a container. */
|
|
3097
|
-
function viewAttachedToContainer(view) {
|
|
3098
|
-
return isLContainer(view[PARENT]);
|
|
3099
|
-
}
|
|
3100
|
-
function getConstant(consts, index) {
|
|
3101
|
-
if (index === null || index === undefined)
|
|
3102
|
-
return null;
|
|
3103
|
-
ngDevMode && assertIndexInRange(consts, index);
|
|
3104
|
-
return consts[index];
|
|
3105
|
-
}
|
|
3106
|
-
/**
|
|
3107
|
-
* Resets the pre-order hook flags of the view.
|
|
3108
|
-
* @param lView the LView on which the flags are reset
|
|
3109
|
-
*/
|
|
3110
|
-
function resetPreOrderHookFlags(lView) {
|
|
3111
|
-
lView[PREORDER_HOOK_FLAGS] = 0;
|
|
3112
|
-
}
|
|
3113
|
-
/**
|
|
3114
|
-
* Adds the `RefreshView` flag from the lView and updates DESCENDANT_VIEWS_TO_REFRESH counters of
|
|
3115
|
-
* parents.
|
|
3116
|
-
*/
|
|
3117
|
-
function markViewForRefresh(lView) {
|
|
3118
|
-
if ((lView[FLAGS] & 1024 /* LViewFlags.RefreshView */) === 0) {
|
|
3119
|
-
lView[FLAGS] |= 1024 /* LViewFlags.RefreshView */;
|
|
3120
|
-
updateViewsToRefresh(lView, 1);
|
|
3121
|
-
}
|
|
3122
|
-
}
|
|
3123
|
-
/**
|
|
3124
|
-
* Removes the `RefreshView` flag from the lView and updates DESCENDANT_VIEWS_TO_REFRESH counters of
|
|
3125
|
-
* parents.
|
|
3126
|
-
*/
|
|
3127
|
-
function clearViewRefreshFlag(lView) {
|
|
3128
|
-
if (lView[FLAGS] & 1024 /* LViewFlags.RefreshView */) {
|
|
3129
|
-
lView[FLAGS] &= ~1024 /* LViewFlags.RefreshView */;
|
|
3130
|
-
updateViewsToRefresh(lView, -1);
|
|
3131
|
-
}
|
|
3132
|
-
}
|
|
3133
|
-
/**
|
|
3134
|
-
* Walks up the LView hierarchy.
|
|
3135
|
-
* @param nestingLevel Number of times to walk up in hierarchy.
|
|
3136
|
-
* @param currentView View from which to start the lookup.
|
|
3137
|
-
*/
|
|
3138
|
-
function walkUpViews(nestingLevel, currentView) {
|
|
3139
|
-
while (nestingLevel > 0) {
|
|
3140
|
-
ngDevMode &&
|
|
3141
|
-
assertDefined(currentView[DECLARATION_VIEW], 'Declaration view should be defined if nesting level is greater than 0.');
|
|
3142
|
-
currentView = currentView[DECLARATION_VIEW];
|
|
3143
|
-
nestingLevel--;
|
|
3144
|
-
}
|
|
3145
|
-
return currentView;
|
|
3146
|
-
}
|
|
3147
|
-
/**
|
|
3148
|
-
* Updates the `DESCENDANT_VIEWS_TO_REFRESH` counter on the parents of the `LView` as well as the
|
|
3149
|
-
* parents above that whose
|
|
3150
|
-
* 1. counter goes from 0 to 1, indicating that there is a new child that has a view to refresh
|
|
3151
|
-
* or
|
|
3152
|
-
* 2. counter goes from 1 to 0, indicating there are no more descendant views to refresh
|
|
3153
|
-
*/
|
|
3154
|
-
function updateViewsToRefresh(lView, amount) {
|
|
3155
|
-
let parent = lView[PARENT];
|
|
3156
|
-
if (parent === null) {
|
|
3157
|
-
return;
|
|
3158
|
-
}
|
|
3159
|
-
parent[DESCENDANT_VIEWS_TO_REFRESH] += amount;
|
|
3160
|
-
let viewOrContainer = parent;
|
|
3161
|
-
parent = parent[PARENT];
|
|
3162
|
-
while (parent !== null &&
|
|
3163
|
-
((amount === 1 && viewOrContainer[DESCENDANT_VIEWS_TO_REFRESH] === 1) ||
|
|
3164
|
-
(amount === -1 && viewOrContainer[DESCENDANT_VIEWS_TO_REFRESH] === 0))) {
|
|
3165
|
-
parent[DESCENDANT_VIEWS_TO_REFRESH] += amount;
|
|
3166
|
-
viewOrContainer = parent;
|
|
3167
|
-
parent = parent[PARENT];
|
|
2659
|
+
else {
|
|
2660
|
+
parent[FLAGS] |= 8192 /* LViewFlags.HasChildViewsToRefresh */;
|
|
2661
|
+
if (!viewAttachedToChangeDetector(parent)) {
|
|
2662
|
+
break;
|
|
2663
|
+
}
|
|
2664
|
+
}
|
|
2665
|
+
parent = parent[PARENT];
|
|
3168
2666
|
}
|
|
3169
2667
|
}
|
|
3170
2668
|
/**
|
|
@@ -3863,7 +3361,7 @@ function incrementInitPhaseFlags(lView, initPhase) {
|
|
|
3863
3361
|
assertNotEqual(initPhase, 3 /* InitPhaseState.InitPhaseCompleted */, 'Init hooks phase should not be incremented after all init hooks have been run.');
|
|
3864
3362
|
let flags = lView[FLAGS];
|
|
3865
3363
|
if ((flags & 3 /* LViewFlags.InitPhaseStateMask */) === initPhase) {
|
|
3866
|
-
flags &=
|
|
3364
|
+
flags &= 16383 /* LViewFlags.IndexWithinInitPhaseReset */;
|
|
3867
3365
|
flags += 1 /* LViewFlags.InitPhaseStateIncrementer */;
|
|
3868
3366
|
lView[FLAGS] = flags;
|
|
3869
3367
|
}
|
|
@@ -3921,12 +3419,12 @@ function callHooks(currentView, arr, initPhase, currentNodeIndex) {
|
|
|
3921
3419
|
*/
|
|
3922
3420
|
function callHookInternal(directive, hook) {
|
|
3923
3421
|
profiler(4 /* ProfilerEvent.LifecycleHookStart */, directive, hook);
|
|
3924
|
-
const prevConsumer = setActiveConsumer(null);
|
|
3422
|
+
const prevConsumer = setActiveConsumer$1(null);
|
|
3925
3423
|
try {
|
|
3926
3424
|
hook.call(directive);
|
|
3927
3425
|
}
|
|
3928
3426
|
finally {
|
|
3929
|
-
setActiveConsumer(prevConsumer);
|
|
3427
|
+
setActiveConsumer$1(prevConsumer);
|
|
3930
3428
|
profiler(5 /* ProfilerEvent.LifecycleHookEnd */, directive, hook);
|
|
3931
3429
|
}
|
|
3932
3430
|
}
|
|
@@ -3944,12 +3442,12 @@ function callHook(currentView, initPhase, arr, i) {
|
|
|
3944
3442
|
const directiveIndex = isInitHook ? -arr[i] : arr[i];
|
|
3945
3443
|
const directive = currentView[directiveIndex];
|
|
3946
3444
|
if (isInitHook) {
|
|
3947
|
-
const indexWithintInitPhase = currentView[FLAGS] >>
|
|
3445
|
+
const indexWithintInitPhase = currentView[FLAGS] >> 14 /* LViewFlags.IndexWithinInitPhaseShift */;
|
|
3948
3446
|
// The init phase state must be always checked here as it may have been recursively updated.
|
|
3949
3447
|
if (indexWithintInitPhase <
|
|
3950
3448
|
(currentView[PREORDER_HOOK_FLAGS] >> 16 /* PreOrderHookFlags.NumberOfInitHooksCalledShift */) &&
|
|
3951
3449
|
(currentView[FLAGS] & 3 /* LViewFlags.InitPhaseStateMask */) === initPhase) {
|
|
3952
|
-
currentView[FLAGS] +=
|
|
3450
|
+
currentView[FLAGS] += 16384 /* LViewFlags.IndexWithinInitPhaseIncrementer */;
|
|
3953
3451
|
callHookInternal(directive, hook);
|
|
3954
3452
|
}
|
|
3955
3453
|
}
|
|
@@ -7261,6 +6759,21 @@ const ENABLED_SSR_FEATURES = new InjectionToken((typeof ngDevMode === 'undefined
|
|
|
7261
6759
|
providedIn: 'root',
|
|
7262
6760
|
factory: () => new Set(),
|
|
7263
6761
|
});
|
|
6762
|
+
const IMAGE_CONFIG_DEFAULTS = {
|
|
6763
|
+
breakpoints: [16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840],
|
|
6764
|
+
disableImageSizeWarning: false,
|
|
6765
|
+
disableImageLazyLoadWarning: false,
|
|
6766
|
+
};
|
|
6767
|
+
/**
|
|
6768
|
+
* Injection token that configures the image optimized image functionality.
|
|
6769
|
+
* See {@link ImageConfig} for additional information about parameters that
|
|
6770
|
+
* can be used.
|
|
6771
|
+
*
|
|
6772
|
+
* @see {@link NgOptimizedImage}
|
|
6773
|
+
* @see {@link ImageConfig}
|
|
6774
|
+
* @publicApi
|
|
6775
|
+
*/
|
|
6776
|
+
const IMAGE_CONFIG = new InjectionToken('ImageConfig', { providedIn: 'root', factory: () => IMAGE_CONFIG_DEFAULTS });
|
|
7264
6777
|
|
|
7265
6778
|
/**
|
|
7266
6779
|
*
|
|
@@ -7379,7 +6892,9 @@ class DepsTracker {
|
|
|
7379
6892
|
}
|
|
7380
6893
|
else {
|
|
7381
6894
|
if (!this.ownerNgModule.has(type)) {
|
|
7382
|
-
|
|
6895
|
+
// This component is orphan! No need to handle the error since the component rendering
|
|
6896
|
+
// pipeline (e.g., view_container_ref) will check for this error based on configs.
|
|
6897
|
+
return { dependencies: [] };
|
|
7383
6898
|
}
|
|
7384
6899
|
const scope = this.getNgModuleScope(this.ownerNgModule.get(type));
|
|
7385
6900
|
if (scope.compilation.isPoisoned) {
|
|
@@ -7552,6 +7067,15 @@ class DepsTracker {
|
|
|
7552
7067
|
}
|
|
7553
7068
|
return ans;
|
|
7554
7069
|
}
|
|
7070
|
+
/** @override */
|
|
7071
|
+
isOrphanComponent(cmp) {
|
|
7072
|
+
const def = getComponentDef(cmp);
|
|
7073
|
+
if (!def || def.standalone) {
|
|
7074
|
+
return false;
|
|
7075
|
+
}
|
|
7076
|
+
this.resolveNgModulesDecls();
|
|
7077
|
+
return !this.ownerNgModule.has(cmp);
|
|
7078
|
+
}
|
|
7555
7079
|
}
|
|
7556
7080
|
function addSet(sourceSet, targetSet) {
|
|
7557
7081
|
for (const m of sourceSet) {
|
|
@@ -8654,6 +8178,7 @@ function insertView(tView, lView, lContainer, index) {
|
|
|
8654
8178
|
if (lQueries !== null) {
|
|
8655
8179
|
lQueries.insertView(tView);
|
|
8656
8180
|
}
|
|
8181
|
+
updateAncestorTraversalFlagsOnAttach(lView);
|
|
8657
8182
|
// Sets the attached flag
|
|
8658
8183
|
lView[FLAGS] |= 128 /* LViewFlags.Attached */;
|
|
8659
8184
|
}
|
|
@@ -8692,9 +8217,6 @@ function detachMovedView(declarationContainer, lView) {
|
|
|
8692
8217
|
const declarationViewIndex = movedViews.indexOf(lView);
|
|
8693
8218
|
const insertionLContainer = lView[PARENT];
|
|
8694
8219
|
ngDevMode && assertLContainer(insertionLContainer);
|
|
8695
|
-
// If the view was marked for refresh but then detached before it was checked (where the flag
|
|
8696
|
-
// would be cleared and the counter decremented), we need to update the status here.
|
|
8697
|
-
clearViewRefreshFlag(lView);
|
|
8698
8220
|
movedViews.splice(declarationViewIndex, 1);
|
|
8699
8221
|
}
|
|
8700
8222
|
/**
|
|
@@ -8744,8 +8266,8 @@ function detachView(lContainer, removeIndex) {
|
|
|
8744
8266
|
function destroyLView(tView, lView) {
|
|
8745
8267
|
if (!(lView[FLAGS] & 256 /* LViewFlags.Destroyed */)) {
|
|
8746
8268
|
const renderer = lView[RENDERER];
|
|
8747
|
-
lView[REACTIVE_TEMPLATE_CONSUMER] && consumerDestroy(lView[REACTIVE_TEMPLATE_CONSUMER]);
|
|
8748
|
-
lView[REACTIVE_HOST_BINDING_CONSUMER] && consumerDestroy(lView[REACTIVE_HOST_BINDING_CONSUMER]);
|
|
8269
|
+
lView[REACTIVE_TEMPLATE_CONSUMER] && consumerDestroy$1(lView[REACTIVE_TEMPLATE_CONSUMER]);
|
|
8270
|
+
lView[REACTIVE_HOST_BINDING_CONSUMER] && consumerDestroy$1(lView[REACTIVE_HOST_BINDING_CONSUMER]);
|
|
8749
8271
|
if (renderer.destroyNode) {
|
|
8750
8272
|
applyView(tView, lView, renderer, 3 /* WalkTNodeTreeAction.Destroy */, null, null);
|
|
8751
8273
|
}
|
|
@@ -10907,7 +10429,7 @@ class Version {
|
|
|
10907
10429
|
/**
|
|
10908
10430
|
* @publicApi
|
|
10909
10431
|
*/
|
|
10910
|
-
const VERSION = new Version('17.0.0-next.
|
|
10432
|
+
const VERSION = new Version('17.0.0-next.8');
|
|
10911
10433
|
|
|
10912
10434
|
// This default value is when checking the hierarchy for a token.
|
|
10913
10435
|
//
|
|
@@ -10928,6 +10450,64 @@ const VERSION = new Version('17.0.0-next.7');
|
|
|
10928
10450
|
// - mod2.injector.get(token, default)
|
|
10929
10451
|
const NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR = {};
|
|
10930
10452
|
|
|
10453
|
+
/**
|
|
10454
|
+
* Checks if the given `value` is a reactive `Signal`.
|
|
10455
|
+
*/
|
|
10456
|
+
function isSignal(value) {
|
|
10457
|
+
return typeof value === 'function' && value[SIGNAL$1] !== undefined;
|
|
10458
|
+
}
|
|
10459
|
+
|
|
10460
|
+
/**
|
|
10461
|
+
* Create a computed `Signal` which derives a reactive value from an expression.
|
|
10462
|
+
*/
|
|
10463
|
+
function computed(computation, options) {
|
|
10464
|
+
const getter = createComputed$1(computation);
|
|
10465
|
+
if (options?.equal) {
|
|
10466
|
+
getter[SIGNAL$1].equal = options.equal;
|
|
10467
|
+
}
|
|
10468
|
+
return getter;
|
|
10469
|
+
}
|
|
10470
|
+
|
|
10471
|
+
/**
|
|
10472
|
+
* Create a `Signal` that can be set or updated directly.
|
|
10473
|
+
*/
|
|
10474
|
+
function signal(initialValue, options) {
|
|
10475
|
+
const signalFn = createSignal$1(initialValue);
|
|
10476
|
+
const node = signalFn[SIGNAL$1];
|
|
10477
|
+
if (options?.equal) {
|
|
10478
|
+
node.equal = options.equal;
|
|
10479
|
+
}
|
|
10480
|
+
signalFn.set = (newValue) => signalSetFn$1(node, newValue);
|
|
10481
|
+
signalFn.update = (updateFn) => signalUpdateFn$1(node, updateFn);
|
|
10482
|
+
signalFn.asReadonly = signalAsReadonlyFn.bind(signalFn);
|
|
10483
|
+
return signalFn;
|
|
10484
|
+
}
|
|
10485
|
+
function signalAsReadonlyFn() {
|
|
10486
|
+
const node = this[SIGNAL$1];
|
|
10487
|
+
if (node.readonlyFn === undefined) {
|
|
10488
|
+
const readonlyFn = () => this();
|
|
10489
|
+
readonlyFn[SIGNAL$1] = node;
|
|
10490
|
+
node.readonlyFn = readonlyFn;
|
|
10491
|
+
}
|
|
10492
|
+
return node.readonlyFn;
|
|
10493
|
+
}
|
|
10494
|
+
|
|
10495
|
+
/**
|
|
10496
|
+
* Execute an arbitrary function in a non-reactive (non-tracking) context. The executed function
|
|
10497
|
+
* can, optionally, return a value.
|
|
10498
|
+
*/
|
|
10499
|
+
function untracked(nonReactiveReadsFn) {
|
|
10500
|
+
const prevConsumer = setActiveConsumer$1(null);
|
|
10501
|
+
// We are not trying to catch any particular errors here, just making sure that the consumers
|
|
10502
|
+
// stack is restored in case of errors.
|
|
10503
|
+
try {
|
|
10504
|
+
return nonReactiveReadsFn();
|
|
10505
|
+
}
|
|
10506
|
+
finally {
|
|
10507
|
+
setActiveConsumer$1(prevConsumer);
|
|
10508
|
+
}
|
|
10509
|
+
}
|
|
10510
|
+
|
|
10931
10511
|
const ERROR_ORIGINAL_ERROR = 'ngOriginalError';
|
|
10932
10512
|
function wrappedError(message, originalError) {
|
|
10933
10513
|
const msg = `${message} caused by: ${originalError instanceof Error ? originalError.message : originalError}`;
|
|
@@ -11022,6 +10602,183 @@ function injectDestroyRef() {
|
|
|
11022
10602
|
return new NodeInjectorDestroyRef(getLView());
|
|
11023
10603
|
}
|
|
11024
10604
|
|
|
10605
|
+
/**
|
|
10606
|
+
* Asserts that the current stack frame is not within a reactive context. Useful
|
|
10607
|
+
* to disallow certain code from running inside a reactive context (see {@link toSignal}).
|
|
10608
|
+
*
|
|
10609
|
+
* @param debugFn a reference to the function making the assertion (used for the error message).
|
|
10610
|
+
*
|
|
10611
|
+
* @publicApi
|
|
10612
|
+
*/
|
|
10613
|
+
function assertNotInReactiveContext(debugFn, extraContext) {
|
|
10614
|
+
// Taking a `Function` instead of a string name here prevents the un-minified name of the function
|
|
10615
|
+
// from being retained in the bundle regardless of minification.
|
|
10616
|
+
if (getActiveConsumer$1() !== null) {
|
|
10617
|
+
throw new RuntimeError(-602 /* RuntimeErrorCode.ASSERTION_NOT_INSIDE_REACTIVE_CONTEXT */, ngDevMode &&
|
|
10618
|
+
`${debugFn.name}() cannot be called from within a reactive context.${extraContext ? ` ${extraContext}` : ''}`);
|
|
10619
|
+
}
|
|
10620
|
+
}
|
|
10621
|
+
|
|
10622
|
+
/**
|
|
10623
|
+
* Not public API, which guarantees `EffectScheduler` only ever comes from the application root
|
|
10624
|
+
* injector.
|
|
10625
|
+
*/
|
|
10626
|
+
const APP_EFFECT_SCHEDULER = new InjectionToken('', {
|
|
10627
|
+
providedIn: 'root',
|
|
10628
|
+
factory: () => inject(EffectScheduler),
|
|
10629
|
+
});
|
|
10630
|
+
/**
|
|
10631
|
+
* A scheduler which manages the execution of effects.
|
|
10632
|
+
*/
|
|
10633
|
+
class EffectScheduler {
|
|
10634
|
+
/** @nocollapse */
|
|
10635
|
+
static { this.ɵprov = ɵɵdefineInjectable({
|
|
10636
|
+
token: EffectScheduler,
|
|
10637
|
+
providedIn: 'root',
|
|
10638
|
+
factory: () => new ZoneAwareMicrotaskScheduler(),
|
|
10639
|
+
}); }
|
|
10640
|
+
}
|
|
10641
|
+
/**
|
|
10642
|
+
* An `EffectScheduler` which is capable of queueing scheduled effects per-zone, and flushing them
|
|
10643
|
+
* as an explicit operation.
|
|
10644
|
+
*/
|
|
10645
|
+
class ZoneAwareQueueingScheduler {
|
|
10646
|
+
constructor() {
|
|
10647
|
+
this.queuedEffectCount = 0;
|
|
10648
|
+
this.queues = new Map();
|
|
10649
|
+
}
|
|
10650
|
+
scheduleEffect(handle) {
|
|
10651
|
+
const zone = handle.creationZone;
|
|
10652
|
+
if (!this.queues.has(zone)) {
|
|
10653
|
+
this.queues.set(zone, new Set());
|
|
10654
|
+
}
|
|
10655
|
+
const queue = this.queues.get(zone);
|
|
10656
|
+
if (queue.has(handle)) {
|
|
10657
|
+
return;
|
|
10658
|
+
}
|
|
10659
|
+
this.queuedEffectCount++;
|
|
10660
|
+
queue.add(handle);
|
|
10661
|
+
}
|
|
10662
|
+
/**
|
|
10663
|
+
* Run all scheduled effects.
|
|
10664
|
+
*
|
|
10665
|
+
* Execution order of effects within the same zone is guaranteed to be FIFO, but there is no
|
|
10666
|
+
* ordering guarantee between effects scheduled in different zones.
|
|
10667
|
+
*/
|
|
10668
|
+
flush() {
|
|
10669
|
+
while (this.queuedEffectCount > 0) {
|
|
10670
|
+
for (const [zone, queue] of this.queues) {
|
|
10671
|
+
// `zone` here must be defined.
|
|
10672
|
+
if (zone === null) {
|
|
10673
|
+
this.flushQueue(queue);
|
|
10674
|
+
}
|
|
10675
|
+
else {
|
|
10676
|
+
zone.run(() => this.flushQueue(queue));
|
|
10677
|
+
}
|
|
10678
|
+
}
|
|
10679
|
+
}
|
|
10680
|
+
}
|
|
10681
|
+
flushQueue(queue) {
|
|
10682
|
+
for (const handle of queue) {
|
|
10683
|
+
queue.delete(handle);
|
|
10684
|
+
this.queuedEffectCount--;
|
|
10685
|
+
// TODO: what happens if this throws an error?
|
|
10686
|
+
handle.run();
|
|
10687
|
+
}
|
|
10688
|
+
}
|
|
10689
|
+
/** @nocollapse */
|
|
10690
|
+
static { this.ɵprov = ɵɵdefineInjectable({
|
|
10691
|
+
token: ZoneAwareQueueingScheduler,
|
|
10692
|
+
providedIn: 'root',
|
|
10693
|
+
factory: () => new ZoneAwareQueueingScheduler(),
|
|
10694
|
+
}); }
|
|
10695
|
+
}
|
|
10696
|
+
/**
|
|
10697
|
+
* A wrapper around `ZoneAwareQueueingScheduler` that schedules flushing via the microtask queue
|
|
10698
|
+
* when.
|
|
10699
|
+
*/
|
|
10700
|
+
class ZoneAwareMicrotaskScheduler {
|
|
10701
|
+
constructor() {
|
|
10702
|
+
this.hasQueuedFlush = false;
|
|
10703
|
+
this.delegate = new ZoneAwareQueueingScheduler();
|
|
10704
|
+
this.flushTask = () => {
|
|
10705
|
+
// Leave `hasQueuedFlush` as `true` so we don't queue another microtask if more effects are
|
|
10706
|
+
// scheduled during flushing. The flush of the `ZoneAwareQueueingScheduler` delegate is
|
|
10707
|
+
// guaranteed to empty the queue.
|
|
10708
|
+
this.delegate.flush();
|
|
10709
|
+
this.hasQueuedFlush = false;
|
|
10710
|
+
// This is a variable initialization, not a method.
|
|
10711
|
+
// tslint:disable-next-line:semicolon
|
|
10712
|
+
};
|
|
10713
|
+
}
|
|
10714
|
+
scheduleEffect(handle) {
|
|
10715
|
+
this.delegate.scheduleEffect(handle);
|
|
10716
|
+
if (!this.hasQueuedFlush) {
|
|
10717
|
+
queueMicrotask(this.flushTask);
|
|
10718
|
+
this.hasQueuedFlush = true;
|
|
10719
|
+
}
|
|
10720
|
+
}
|
|
10721
|
+
}
|
|
10722
|
+
/**
|
|
10723
|
+
* Core reactive node for an Angular effect.
|
|
10724
|
+
*
|
|
10725
|
+
* `EffectHandle` combines the reactive graph's `Watch` base node for effects with the framework's
|
|
10726
|
+
* scheduling abstraction (`EffectScheduler`) as well as automatic cleanup via `DestroyRef` if
|
|
10727
|
+
* available/requested.
|
|
10728
|
+
*/
|
|
10729
|
+
class EffectHandle {
|
|
10730
|
+
constructor(scheduler, effectFn, creationZone, destroyRef, errorHandler, allowSignalWrites) {
|
|
10731
|
+
this.scheduler = scheduler;
|
|
10732
|
+
this.effectFn = effectFn;
|
|
10733
|
+
this.creationZone = creationZone;
|
|
10734
|
+
this.errorHandler = errorHandler;
|
|
10735
|
+
this.watcher = createWatch$1((onCleanup) => this.runEffect(onCleanup), () => this.schedule(), allowSignalWrites);
|
|
10736
|
+
this.unregisterOnDestroy = destroyRef?.onDestroy(() => this.destroy());
|
|
10737
|
+
}
|
|
10738
|
+
runEffect(onCleanup) {
|
|
10739
|
+
try {
|
|
10740
|
+
this.effectFn(onCleanup);
|
|
10741
|
+
}
|
|
10742
|
+
catch (err) {
|
|
10743
|
+
this.errorHandler?.handleError(err);
|
|
10744
|
+
}
|
|
10745
|
+
}
|
|
10746
|
+
run() {
|
|
10747
|
+
this.watcher.run();
|
|
10748
|
+
}
|
|
10749
|
+
schedule() {
|
|
10750
|
+
this.scheduler.scheduleEffect(this);
|
|
10751
|
+
}
|
|
10752
|
+
notify() {
|
|
10753
|
+
this.watcher.notify();
|
|
10754
|
+
}
|
|
10755
|
+
destroy() {
|
|
10756
|
+
this.watcher.destroy();
|
|
10757
|
+
this.unregisterOnDestroy?.();
|
|
10758
|
+
// Note: if the effect is currently scheduled, it's not un-scheduled, and so the scheduler will
|
|
10759
|
+
// retain a reference to it. Attempting to execute it will be a no-op.
|
|
10760
|
+
}
|
|
10761
|
+
}
|
|
10762
|
+
/**
|
|
10763
|
+
* Create a global `Effect` for the given reactive function.
|
|
10764
|
+
*/
|
|
10765
|
+
function effect(effectFn, options) {
|
|
10766
|
+
ngDevMode &&
|
|
10767
|
+
assertNotInReactiveContext(effect, 'Call `effect` outside of a reactive context. For example, schedule the ' +
|
|
10768
|
+
'effect inside the component constructor.');
|
|
10769
|
+
!options?.injector && assertInInjectionContext(effect);
|
|
10770
|
+
const injector = options?.injector ?? inject(Injector);
|
|
10771
|
+
const errorHandler = injector.get(ErrorHandler, null, { optional: true });
|
|
10772
|
+
const destroyRef = options?.manualCleanup !== true ? injector.get(DestroyRef) : null;
|
|
10773
|
+
const handle = new EffectHandle(injector.get(APP_EFFECT_SCHEDULER), effectFn, (typeof Zone === 'undefined') ? null : Zone.current, destroyRef, errorHandler, options?.allowSignalWrites ?? false);
|
|
10774
|
+
// Effects start dirty.
|
|
10775
|
+
handle.notify();
|
|
10776
|
+
return handle;
|
|
10777
|
+
}
|
|
10778
|
+
|
|
10779
|
+
// clang-format off
|
|
10780
|
+
// clang-format on
|
|
10781
|
+
|
|
11025
10782
|
/// <reference types="rxjs" />
|
|
11026
10783
|
class EventEmitter_ extends Subject {
|
|
11027
10784
|
constructor(isAsync = false) {
|
|
@@ -11702,6 +11459,9 @@ var AfterRenderPhase;
|
|
|
11702
11459
|
* @developerPreview
|
|
11703
11460
|
*/
|
|
11704
11461
|
function afterRender(callback, options) {
|
|
11462
|
+
ngDevMode &&
|
|
11463
|
+
assertNotInReactiveContext(afterRender, 'Call `afterRender` outside of a reactive context. For example, schedule the render ' +
|
|
11464
|
+
'callback inside the component constructor`.');
|
|
11705
11465
|
!options && assertInInjectionContext(afterRender);
|
|
11706
11466
|
const injector = options?.injector ?? inject(Injector);
|
|
11707
11467
|
if (!isPlatformBrowser(injector)) {
|
|
@@ -12113,7 +11873,7 @@ function commitLViewConsumerIfHasProducers(lView, slot) {
|
|
|
12113
11873
|
currentConsumer = createLViewConsumer();
|
|
12114
11874
|
}
|
|
12115
11875
|
const REACTIVE_LVIEW_CONSUMER_NODE = {
|
|
12116
|
-
...REACTIVE_NODE,
|
|
11876
|
+
...REACTIVE_NODE$1,
|
|
12117
11877
|
consumerIsAlwaysLive: true,
|
|
12118
11878
|
consumerMarkedDirty: (node) => {
|
|
12119
11879
|
(typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
@@ -12245,13 +12005,13 @@ function processHostBindingOpCodes(tView, lView) {
|
|
|
12245
12005
|
const hostBindingFn = hostBindingOpCodes[++i];
|
|
12246
12006
|
setBindingRootForHostBindings(bindingRootIndx, directiveIdx);
|
|
12247
12007
|
consumer.dirty = false;
|
|
12248
|
-
const prevConsumer = consumerBeforeComputation(consumer);
|
|
12008
|
+
const prevConsumer = consumerBeforeComputation$1(consumer);
|
|
12249
12009
|
try {
|
|
12250
12010
|
const context = lView[directiveIdx];
|
|
12251
12011
|
hostBindingFn(2 /* RenderFlags.Update */, context);
|
|
12252
12012
|
}
|
|
12253
12013
|
finally {
|
|
12254
|
-
consumerAfterComputation(consumer, prevConsumer);
|
|
12014
|
+
consumerAfterComputation$1(consumer, prevConsumer);
|
|
12255
12015
|
}
|
|
12256
12016
|
}
|
|
12257
12017
|
}
|
|
@@ -12393,7 +12153,7 @@ function executeTemplate(tView, lView, templateFn, rf, context) {
|
|
|
12393
12153
|
const preHookType = isUpdatePhase ? 2 /* ProfilerEvent.TemplateUpdateStart */ : 0 /* ProfilerEvent.TemplateCreateStart */;
|
|
12394
12154
|
profiler(preHookType, context);
|
|
12395
12155
|
const effectiveConsumer = isUpdatePhase ? consumer : null;
|
|
12396
|
-
const prevConsumer = consumerBeforeComputation(effectiveConsumer);
|
|
12156
|
+
const prevConsumer = consumerBeforeComputation$1(effectiveConsumer);
|
|
12397
12157
|
try {
|
|
12398
12158
|
if (effectiveConsumer !== null) {
|
|
12399
12159
|
effectiveConsumer.dirty = false;
|
|
@@ -12401,7 +12161,7 @@ function executeTemplate(tView, lView, templateFn, rf, context) {
|
|
|
12401
12161
|
templateFn(rf, context);
|
|
12402
12162
|
}
|
|
12403
12163
|
finally {
|
|
12404
|
-
consumerAfterComputation(effectiveConsumer, prevConsumer);
|
|
12164
|
+
consumerAfterComputation$1(effectiveConsumer, prevConsumer);
|
|
12405
12165
|
}
|
|
12406
12166
|
}
|
|
12407
12167
|
finally {
|
|
@@ -12418,7 +12178,7 @@ function executeTemplate(tView, lView, templateFn, rf, context) {
|
|
|
12418
12178
|
//////////////////////////
|
|
12419
12179
|
function executeContentQueries(tView, tNode, lView) {
|
|
12420
12180
|
if (isContentQueryHost(tNode)) {
|
|
12421
|
-
const prevConsumer = setActiveConsumer(null);
|
|
12181
|
+
const prevConsumer = setActiveConsumer$1(null);
|
|
12422
12182
|
try {
|
|
12423
12183
|
const start = tNode.directiveStart;
|
|
12424
12184
|
const end = tNode.directiveEnd;
|
|
@@ -12430,7 +12190,7 @@ function executeContentQueries(tView, tNode, lView) {
|
|
|
12430
12190
|
}
|
|
12431
12191
|
}
|
|
12432
12192
|
finally {
|
|
12433
|
-
setActiveConsumer(prevConsumer);
|
|
12193
|
+
setActiveConsumer$1(prevConsumer);
|
|
12434
12194
|
}
|
|
12435
12195
|
}
|
|
12436
12196
|
}
|
|
@@ -13128,6 +12888,7 @@ function findDirectiveDefMatches(tView, tNode) {
|
|
|
13128
12888
|
}
|
|
13129
12889
|
}
|
|
13130
12890
|
}
|
|
12891
|
+
ngDevMode && matches !== null && assertNoDuplicateDirectives(matches);
|
|
13131
12892
|
return matches === null ? null : [matches, hostDirectiveDefs];
|
|
13132
12893
|
}
|
|
13133
12894
|
/**
|
|
@@ -13274,7 +13035,7 @@ function setInputsFromAttrs(lView, directiveIndex, instance, def, tNode, initial
|
|
|
13274
13035
|
}
|
|
13275
13036
|
}
|
|
13276
13037
|
function writeToDirectiveInput(def, instance, publicName, privateName, value) {
|
|
13277
|
-
const prevConsumer = setActiveConsumer(null);
|
|
13038
|
+
const prevConsumer = setActiveConsumer$1(null);
|
|
13278
13039
|
try {
|
|
13279
13040
|
const inputTransforms = def.inputTransforms;
|
|
13280
13041
|
if (inputTransforms !== null && inputTransforms.hasOwnProperty(privateName)) {
|
|
@@ -13288,7 +13049,7 @@ function writeToDirectiveInput(def, instance, publicName, privateName, value) {
|
|
|
13288
13049
|
}
|
|
13289
13050
|
}
|
|
13290
13051
|
finally {
|
|
13291
|
-
setActiveConsumer(prevConsumer);
|
|
13052
|
+
setActiveConsumer$1(prevConsumer);
|
|
13292
13053
|
}
|
|
13293
13054
|
}
|
|
13294
13055
|
/**
|
|
@@ -13364,8 +13125,8 @@ function createLContainer(hostNative, currentView, native, tNode) {
|
|
|
13364
13125
|
false,
|
|
13365
13126
|
currentView,
|
|
13366
13127
|
null,
|
|
13367
|
-
0,
|
|
13368
13128
|
tNode,
|
|
13129
|
+
false,
|
|
13369
13130
|
native,
|
|
13370
13131
|
null,
|
|
13371
13132
|
null,
|
|
@@ -13424,12 +13185,12 @@ function addToViewTree(lView, lViewOrLContainer) {
|
|
|
13424
13185
|
function executeViewQueryFn(flags, viewQueryFn, component) {
|
|
13425
13186
|
ngDevMode && assertDefined(viewQueryFn, 'View queries function to execute must be defined.');
|
|
13426
13187
|
setCurrentQueryIndex(0);
|
|
13427
|
-
const prevConsumer = setActiveConsumer(null);
|
|
13188
|
+
const prevConsumer = setActiveConsumer$1(null);
|
|
13428
13189
|
try {
|
|
13429
13190
|
viewQueryFn(flags, component);
|
|
13430
13191
|
}
|
|
13431
13192
|
finally {
|
|
13432
|
-
setActiveConsumer(prevConsumer);
|
|
13193
|
+
setActiveConsumer$1(prevConsumer);
|
|
13433
13194
|
}
|
|
13434
13195
|
}
|
|
13435
13196
|
///////////////////////////////
|
|
@@ -13919,7 +13680,15 @@ function refreshView(tView, lView, templateFn, context) {
|
|
|
13919
13680
|
if (!isInCheckNoChangesPass) {
|
|
13920
13681
|
lView[FLAGS] &= ~(64 /* LViewFlags.Dirty */ | 8 /* LViewFlags.FirstLViewPass */);
|
|
13921
13682
|
}
|
|
13922
|
-
|
|
13683
|
+
lView[FLAGS] &= ~1024 /* LViewFlags.RefreshView */;
|
|
13684
|
+
}
|
|
13685
|
+
catch (e) {
|
|
13686
|
+
// If refreshing a view causes an error, we need to remark the ancestors as needing traversal
|
|
13687
|
+
// because the error might have caused a situation where views below the current location are
|
|
13688
|
+
// dirty but will be unreachable because the "has dirty children" flag in the ancestors has been
|
|
13689
|
+
// cleared during change detection and we failed to run to completion.
|
|
13690
|
+
markAncestorsForTraversal(lView);
|
|
13691
|
+
throw e;
|
|
13923
13692
|
}
|
|
13924
13693
|
finally {
|
|
13925
13694
|
leaveView();
|
|
@@ -13931,9 +13700,10 @@ function refreshView(tView, lView, templateFn, context) {
|
|
|
13931
13700
|
*/
|
|
13932
13701
|
function detectChangesInEmbeddedViews(lView, mode) {
|
|
13933
13702
|
for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
|
|
13703
|
+
lContainer[HAS_CHILD_VIEWS_TO_REFRESH] = false;
|
|
13934
13704
|
for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
|
|
13935
13705
|
const embeddedLView = lContainer[i];
|
|
13936
|
-
|
|
13706
|
+
detectChangesInViewIfAttached(embeddedLView, mode);
|
|
13937
13707
|
}
|
|
13938
13708
|
}
|
|
13939
13709
|
}
|
|
@@ -13965,33 +13735,41 @@ function markTransplantedViewsForRefresh(lView) {
|
|
|
13965
13735
|
function detectChangesInComponent(hostLView, componentHostIdx, mode) {
|
|
13966
13736
|
ngDevMode && assertEqual(isCreationMode(hostLView), false, 'Should be run in update mode');
|
|
13967
13737
|
const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
|
|
13968
|
-
|
|
13738
|
+
detectChangesInViewIfAttached(componentView, mode);
|
|
13969
13739
|
}
|
|
13970
13740
|
/**
|
|
13971
13741
|
* Visits a view as part of change detection traversal.
|
|
13972
13742
|
*
|
|
13973
|
-
*
|
|
13743
|
+
* If the view is detached, no additional traversal happens.
|
|
13744
|
+
*/
|
|
13745
|
+
function detectChangesInViewIfAttached(lView, mode) {
|
|
13746
|
+
if (!viewAttachedToChangeDetector(lView)) {
|
|
13747
|
+
return;
|
|
13748
|
+
}
|
|
13749
|
+
detectChangesInView(lView, mode);
|
|
13750
|
+
}
|
|
13751
|
+
/**
|
|
13752
|
+
* Visits a view as part of change detection traversal.
|
|
13974
13753
|
*
|
|
13975
13754
|
* The view is refreshed if:
|
|
13976
13755
|
* - If the view is CheckAlways or Dirty and ChangeDetectionMode is `Global`
|
|
13977
13756
|
* - If the view has the `RefreshTransplantedView` flag
|
|
13978
13757
|
*
|
|
13979
13758
|
* The view is not refreshed, but descendants are traversed in `ChangeDetectionMode.Targeted` if the
|
|
13980
|
-
* view
|
|
13981
|
-
*
|
|
13759
|
+
* view HasChildViewsToRefresh flag is set.
|
|
13982
13760
|
*/
|
|
13983
13761
|
function detectChangesInView(lView, mode) {
|
|
13984
|
-
if (!viewAttachedToChangeDetector(lView)) {
|
|
13985
|
-
return;
|
|
13986
|
-
}
|
|
13987
13762
|
const tView = lView[TVIEW];
|
|
13988
13763
|
const flags = lView[FLAGS];
|
|
13764
|
+
// Flag cleared before change detection runs so that the view can be re-marked for traversal if
|
|
13765
|
+
// necessary.
|
|
13766
|
+
lView[FLAGS] &= ~8192 /* LViewFlags.HasChildViewsToRefresh */;
|
|
13989
13767
|
if ((flags & (16 /* LViewFlags.CheckAlways */ | 64 /* LViewFlags.Dirty */) &&
|
|
13990
13768
|
mode === 0 /* ChangeDetectionMode.Global */) ||
|
|
13991
13769
|
flags & 1024 /* LViewFlags.RefreshView */) {
|
|
13992
13770
|
refreshView(tView, lView, tView.template, lView[CONTEXT]);
|
|
13993
13771
|
}
|
|
13994
|
-
else if (
|
|
13772
|
+
else if (flags & 8192 /* LViewFlags.HasChildViewsToRefresh */) {
|
|
13995
13773
|
detectChangesInEmbeddedViews(lView, 1 /* ChangeDetectionMode.Targeted */);
|
|
13996
13774
|
const components = tView.components;
|
|
13997
13775
|
if (components !== null) {
|
|
@@ -14226,6 +14004,7 @@ class ViewRef$1 {
|
|
|
14226
14004
|
* ```
|
|
14227
14005
|
*/
|
|
14228
14006
|
reattach() {
|
|
14007
|
+
updateAncestorTraversalFlagsOnAttach(this._lView);
|
|
14229
14008
|
this._lView[FLAGS] |= 128 /* LViewFlags.Attached */;
|
|
14230
14009
|
}
|
|
14231
14010
|
/**
|
|
@@ -14392,6 +14171,13 @@ class ComponentFactory extends ComponentFactory$1 {
|
|
|
14392
14171
|
this.isBoundToModule = !!ngModule;
|
|
14393
14172
|
}
|
|
14394
14173
|
create(injector, projectableNodes, rootSelectorOrNode, environmentInjector) {
|
|
14174
|
+
// Check if the component is orphan
|
|
14175
|
+
if (ngDevMode && (typeof ngJitMode === 'undefined' || ngJitMode) &&
|
|
14176
|
+
this.componentDef.debugInfo?.forbidOrphanRendering) {
|
|
14177
|
+
if (depsTracker.isOrphanComponent(this.componentType)) {
|
|
14178
|
+
throw new RuntimeError(1001 /* RuntimeErrorCode.RUNTIME_DEPS_ORPHAN_COMPONENT */, `Orphan component found! Trying to render the component ${debugStringifyTypeForError(this.componentType)} without first loading the NgModule that declares it. It is recommended to make this component standalone in order to avoid this error. If this is not possible now, import the component's NgModule in the appropriate NgModule, or the standalone component in which you are trying to render this component. If this is a lazy import, load the NgModule lazily as well and use its module injector.`);
|
|
14179
|
+
}
|
|
14180
|
+
}
|
|
14395
14181
|
environmentInjector = environmentInjector || this.ngModule;
|
|
14396
14182
|
let realEnvironmentInjector = environmentInjector instanceof EnvironmentInjector ?
|
|
14397
14183
|
environmentInjector :
|
|
@@ -14454,6 +14240,7 @@ class ComponentFactory extends ComponentFactory$1 {
|
|
|
14454
14240
|
hostDirectiveDefs = new Map();
|
|
14455
14241
|
rootComponentDef.findHostDirectiveDefs(rootComponentDef, rootDirectives, hostDirectiveDefs);
|
|
14456
14242
|
rootDirectives.push(rootComponentDef);
|
|
14243
|
+
ngDevMode && assertNoDuplicateDirectives(rootDirectives);
|
|
14457
14244
|
}
|
|
14458
14245
|
else {
|
|
14459
14246
|
rootDirectives = [rootComponentDef];
|
|
@@ -14952,7 +14739,7 @@ function findHostDirectiveDefs(currentDef, matchedDefs, hostDirectiveDefs) {
|
|
|
14952
14739
|
for (const hostDirectiveConfig of currentDef.hostDirectives) {
|
|
14953
14740
|
const hostDirectiveDef = getDirectiveDef(hostDirectiveConfig.directive);
|
|
14954
14741
|
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
14955
|
-
validateHostDirective(hostDirectiveConfig, hostDirectiveDef
|
|
14742
|
+
validateHostDirective(hostDirectiveConfig, hostDirectiveDef);
|
|
14956
14743
|
}
|
|
14957
14744
|
// We need to patch the `declaredInputs` so that
|
|
14958
14745
|
// `ngOnChanges` can map the properties correctly.
|
|
@@ -15018,9 +14805,8 @@ function patchDeclaredInputs(declaredInputs, exposedInputs) {
|
|
|
15018
14805
|
* Verifies that the host directive has been configured correctly.
|
|
15019
14806
|
* @param hostDirectiveConfig Host directive configuration object.
|
|
15020
14807
|
* @param directiveDef Directive definition of the host directive.
|
|
15021
|
-
* @param matchedDefs Directives that have been matched so far.
|
|
15022
14808
|
*/
|
|
15023
|
-
function validateHostDirective(hostDirectiveConfig, directiveDef
|
|
14809
|
+
function validateHostDirective(hostDirectiveConfig, directiveDef) {
|
|
15024
14810
|
const type = hostDirectiveConfig.directive;
|
|
15025
14811
|
if (directiveDef === null) {
|
|
15026
14812
|
if (getComponentDef(type) !== null) {
|
|
@@ -15032,10 +14818,6 @@ function validateHostDirective(hostDirectiveConfig, directiveDef, matchedDefs) {
|
|
|
15032
14818
|
if (!directiveDef.standalone) {
|
|
15033
14819
|
throw new RuntimeError(308 /* RuntimeErrorCode.HOST_DIRECTIVE_NOT_STANDALONE */, `Host directive ${directiveDef.type.name} must be standalone.`);
|
|
15034
14820
|
}
|
|
15035
|
-
if (matchedDefs.indexOf(directiveDef) > -1) {
|
|
15036
|
-
throw new RuntimeError(309 /* RuntimeErrorCode.DUPLICATE_DIRECTITVE */, `Directive ${directiveDef.type.name} matches multiple times on the same element. ` +
|
|
15037
|
-
`Directives can only match an element once.`);
|
|
15038
|
-
}
|
|
15039
14821
|
validateMappings('input', directiveDef, hostDirectiveConfig.inputs);
|
|
15040
14822
|
validateMappings('output', directiveDef, hostDirectiveConfig.outputs);
|
|
15041
14823
|
}
|
|
@@ -19421,6 +19203,12 @@ class LiveCollectionLContainerImpl extends LiveCollection {
|
|
|
19421
19203
|
this.hostLView = hostLView;
|
|
19422
19204
|
this.templateTNode = templateTNode;
|
|
19423
19205
|
this.trackByFn = trackByFn;
|
|
19206
|
+
/**
|
|
19207
|
+
Property indicating if indexes in the repeater context need to be updated following the live
|
|
19208
|
+
collection changes. Index updates are necessary if and only if views are inserted / removed in
|
|
19209
|
+
the middle of LContainer. Adds and removals at the end don't require index updates.
|
|
19210
|
+
*/
|
|
19211
|
+
this.needsIndexUpdate = false;
|
|
19424
19212
|
}
|
|
19425
19213
|
get length() {
|
|
19426
19214
|
return this.lContainer.length - CONTAINER_HEADER_OFFSET;
|
|
@@ -19433,9 +19221,11 @@ class LiveCollectionLContainerImpl extends LiveCollection {
|
|
|
19433
19221
|
}
|
|
19434
19222
|
attach(index, lView) {
|
|
19435
19223
|
const dehydratedView = lView[HYDRATION];
|
|
19224
|
+
this.needsIndexUpdate ||= index !== this.length;
|
|
19436
19225
|
addLViewToLContainer(this.lContainer, lView, index, shouldAddViewToDom(this.templateTNode, dehydratedView));
|
|
19437
19226
|
}
|
|
19438
19227
|
detach(index) {
|
|
19228
|
+
this.needsIndexUpdate ||= index !== this.length - 1;
|
|
19439
19229
|
return detachExistingView(this.lContainer, index);
|
|
19440
19230
|
}
|
|
19441
19231
|
create(index, value) {
|
|
@@ -19449,6 +19239,13 @@ class LiveCollectionLContainerImpl extends LiveCollection {
|
|
|
19449
19239
|
updateValue(index, value) {
|
|
19450
19240
|
this.at(index)[CONTEXT].$implicit = value;
|
|
19451
19241
|
}
|
|
19242
|
+
updateIndexes() {
|
|
19243
|
+
if (this.needsIndexUpdate) {
|
|
19244
|
+
for (let i = 0; i < this.length; i++) {
|
|
19245
|
+
this.at(i)[CONTEXT].$index = i;
|
|
19246
|
+
}
|
|
19247
|
+
}
|
|
19248
|
+
}
|
|
19452
19249
|
}
|
|
19453
19250
|
/**
|
|
19454
19251
|
* The repeater instruction does update-time diffing of a provided collection (against the
|
|
@@ -19467,19 +19264,13 @@ function ɵɵrepeater(metadataSlotIdx, collection) {
|
|
|
19467
19264
|
const containerIndex = metadataSlotIdx + 1;
|
|
19468
19265
|
const lContainer = getLContainer(hostLView, HEADER_OFFSET + containerIndex);
|
|
19469
19266
|
const itemTemplateTNode = getExistingTNode(hostTView, containerIndex);
|
|
19470
|
-
|
|
19471
|
-
|
|
19472
|
-
//
|
|
19473
|
-
|
|
19474
|
-
for (let i = 0; i < lContainer.length - CONTAINER_HEADER_OFFSET; i++) {
|
|
19475
|
-
const lView = getExistingLViewFromLContainer(lContainer, i);
|
|
19476
|
-
lView[CONTEXT].$index = i;
|
|
19477
|
-
}
|
|
19267
|
+
const liveCollection = new LiveCollectionLContainerImpl(lContainer, hostLView, itemTemplateTNode, metadata.trackByFn);
|
|
19268
|
+
reconcile(liveCollection, collection, metadata.trackByFn);
|
|
19269
|
+
// moves in the container might caused context's index to get out of order, re-adjust if needed
|
|
19270
|
+
liveCollection.updateIndexes();
|
|
19478
19271
|
// handle empty blocks
|
|
19479
|
-
// PERF: maybe I could skip allocation of memory for the empty block? Isn't it the "fix" on the
|
|
19480
|
-
// compiler side that we've been discussing? Talk to K & D!
|
|
19481
|
-
const bindingIndex = nextBindingIndex();
|
|
19482
19272
|
if (metadata.hasEmptyBlock) {
|
|
19273
|
+
const bindingIndex = nextBindingIndex();
|
|
19483
19274
|
const isCollectionEmpty = lContainer.length - CONTAINER_HEADER_OFFSET === 0;
|
|
19484
19275
|
if (bindingUpdated(hostLView, bindingIndex, isCollectionEmpty)) {
|
|
19485
19276
|
const emptyTemplateIndex = metadataSlotIdx + 2;
|
|
@@ -19531,6 +19322,10 @@ var DeferDependenciesLoadingState;
|
|
|
19531
19322
|
/** Dependency loading has failed */
|
|
19532
19323
|
DeferDependenciesLoadingState[DeferDependenciesLoadingState["FAILED"] = 3] = "FAILED";
|
|
19533
19324
|
})(DeferDependenciesLoadingState || (DeferDependenciesLoadingState = {}));
|
|
19325
|
+
/** Slot index where `minimum` parameter value is stored. */
|
|
19326
|
+
const MINIMUM_SLOT = 0;
|
|
19327
|
+
/** Slot index where `after` parameter value is stored. */
|
|
19328
|
+
const LOADING_AFTER_SLOT = 1;
|
|
19534
19329
|
/**
|
|
19535
19330
|
* Describes the current state of this defer block instance.
|
|
19536
19331
|
*
|
|
@@ -19559,11 +19354,14 @@ var DeferBlockInternalState;
|
|
|
19559
19354
|
/** Initial state. Nothing is rendered yet. */
|
|
19560
19355
|
DeferBlockInternalState[DeferBlockInternalState["Initial"] = -1] = "Initial";
|
|
19561
19356
|
})(DeferBlockInternalState || (DeferBlockInternalState = {}));
|
|
19562
|
-
|
|
19563
|
-
*
|
|
19564
|
-
|
|
19565
|
-
|
|
19566
|
-
|
|
19357
|
+
const NEXT_DEFER_BLOCK_STATE = 0;
|
|
19358
|
+
// Note: it's *important* to keep the state in this slot, because this slot
|
|
19359
|
+
// is used by runtime logic to differentiate between LViews, LContainers and
|
|
19360
|
+
// other types (see `isLView` and `isLContainer` functions). In case of defer
|
|
19361
|
+
// blocks, this slot would always be a number.
|
|
19362
|
+
const DEFER_BLOCK_STATE = 1;
|
|
19363
|
+
const STATE_IS_FROZEN_UNTIL = 2;
|
|
19364
|
+
const LOADING_AFTER_CLEANUP_FN = 3;
|
|
19567
19365
|
/**
|
|
19568
19366
|
* Options for configuring defer blocks behavior.
|
|
19569
19367
|
* @publicApi
|
|
@@ -19600,6 +19398,8 @@ const hoverTriggers = new WeakMap();
|
|
|
19600
19398
|
const interactionTriggers = new WeakMap();
|
|
19601
19399
|
/** Names of the events considered as interaction events. */
|
|
19602
19400
|
const interactionEventNames = ['click', 'keydown'];
|
|
19401
|
+
/** Names of the events considered as hover events. */
|
|
19402
|
+
const hoverEventNames = ['mouseenter', 'focusin'];
|
|
19603
19403
|
/** Object keeping track of registered callbacks for a deferred block trigger. */
|
|
19604
19404
|
class DeferEventEntry {
|
|
19605
19405
|
constructor() {
|
|
@@ -19669,7 +19469,9 @@ function onHover(trigger, callback, injector) {
|
|
|
19669
19469
|
// Ensure that the handler runs in the NgZone since it gets
|
|
19670
19470
|
// registered in `afterRender` which runs outside.
|
|
19671
19471
|
injector.get(NgZone).run(() => {
|
|
19672
|
-
|
|
19472
|
+
for (const name of hoverEventNames) {
|
|
19473
|
+
trigger.addEventListener(name, entry.listener, eventListenerOptions);
|
|
19474
|
+
}
|
|
19673
19475
|
});
|
|
19674
19476
|
}
|
|
19675
19477
|
entry.callbacks.add(callback);
|
|
@@ -19677,7 +19479,9 @@ function onHover(trigger, callback, injector) {
|
|
|
19677
19479
|
const { callbacks, listener } = entry;
|
|
19678
19480
|
callbacks.delete(callback);
|
|
19679
19481
|
if (callbacks.size === 0) {
|
|
19680
|
-
|
|
19482
|
+
for (const name of hoverEventNames) {
|
|
19483
|
+
trigger.removeEventListener(name, listener, eventListenerOptions);
|
|
19484
|
+
}
|
|
19681
19485
|
hoverTriggers.delete(trigger);
|
|
19682
19486
|
}
|
|
19683
19487
|
};
|
|
@@ -19730,6 +19534,10 @@ class DeferIntersectionManager {
|
|
|
19730
19534
|
}
|
|
19731
19535
|
entry.callbacks.add(callback);
|
|
19732
19536
|
return () => {
|
|
19537
|
+
// It's possible that a different cleanup callback fully removed this element already.
|
|
19538
|
+
if (!this.viewportTriggers.has(trigger)) {
|
|
19539
|
+
return;
|
|
19540
|
+
}
|
|
19733
19541
|
entry.callbacks.delete(callback);
|
|
19734
19542
|
if (entry.callbacks.size === 0) {
|
|
19735
19543
|
this.intersectionObserver?.unobserve(trigger);
|
|
@@ -19757,6 +19565,33 @@ function shouldTriggerDeferBlock(injector) {
|
|
|
19757
19565
|
}
|
|
19758
19566
|
return isPlatformBrowser(injector);
|
|
19759
19567
|
}
|
|
19568
|
+
/**
|
|
19569
|
+
* Reference to the timer-based scheduler implementation of defer block state
|
|
19570
|
+
* rendering method. It's used to make timer-based scheduling tree-shakable.
|
|
19571
|
+
* If `minimum` or `after` parameters are used, compiler generates an extra
|
|
19572
|
+
* argument for the `ɵɵdefer` instruction, which references a timer-based
|
|
19573
|
+
* implementation.
|
|
19574
|
+
*/
|
|
19575
|
+
let applyDeferBlockStateWithSchedulingImpl = null;
|
|
19576
|
+
/**
|
|
19577
|
+
* Enables timer-related scheduling if `after` or `minimum` parameters are setup
|
|
19578
|
+
* on the `@loading` or `@placeholder` blocks.
|
|
19579
|
+
*/
|
|
19580
|
+
function ɵɵdeferEnableTimerScheduling(tView, tDetails, placeholderConfigIndex, loadingConfigIndex) {
|
|
19581
|
+
const tViewConsts = tView.consts;
|
|
19582
|
+
if (placeholderConfigIndex != null) {
|
|
19583
|
+
tDetails.placeholderBlockConfig =
|
|
19584
|
+
getConstant(tViewConsts, placeholderConfigIndex);
|
|
19585
|
+
}
|
|
19586
|
+
if (loadingConfigIndex != null) {
|
|
19587
|
+
tDetails.loadingBlockConfig =
|
|
19588
|
+
getConstant(tViewConsts, loadingConfigIndex);
|
|
19589
|
+
}
|
|
19590
|
+
// Enable implementation that supports timer-based scheduling.
|
|
19591
|
+
if (applyDeferBlockStateWithSchedulingImpl === null) {
|
|
19592
|
+
applyDeferBlockStateWithSchedulingImpl = applyDeferBlockStateWithScheduling;
|
|
19593
|
+
}
|
|
19594
|
+
}
|
|
19760
19595
|
/**
|
|
19761
19596
|
* Creates runtime data structures for defer blocks.
|
|
19762
19597
|
*
|
|
@@ -19770,32 +19605,30 @@ function shouldTriggerDeferBlock(injector) {
|
|
|
19770
19605
|
* block.
|
|
19771
19606
|
* @param placeholderConfigIndex Index in the constants array of the configuration of the
|
|
19772
19607
|
* placeholder block.
|
|
19608
|
+
* @param enableTimerScheduling Function that enables timer-related scheduling if `after`
|
|
19609
|
+
* or `minimum` parameters are setup on the `@loading` or `@placeholder` blocks.
|
|
19773
19610
|
*
|
|
19774
19611
|
* @codeGenApi
|
|
19775
19612
|
*/
|
|
19776
|
-
function ɵɵdefer(index, primaryTmplIndex, dependencyResolverFn, loadingTmplIndex, placeholderTmplIndex, errorTmplIndex, loadingConfigIndex, placeholderConfigIndex) {
|
|
19613
|
+
function ɵɵdefer(index, primaryTmplIndex, dependencyResolverFn, loadingTmplIndex, placeholderTmplIndex, errorTmplIndex, loadingConfigIndex, placeholderConfigIndex, enableTimerScheduling) {
|
|
19777
19614
|
const lView = getLView();
|
|
19778
19615
|
const tView = getTView();
|
|
19779
|
-
const tViewConsts = tView.consts;
|
|
19780
19616
|
const adjustedIndex = index + HEADER_OFFSET;
|
|
19781
19617
|
ɵɵtemplate(index, null, 0, 0);
|
|
19782
19618
|
if (tView.firstCreatePass) {
|
|
19783
|
-
const
|
|
19619
|
+
const tDetails = {
|
|
19784
19620
|
primaryTmplIndex,
|
|
19785
19621
|
loadingTmplIndex: loadingTmplIndex ?? null,
|
|
19786
19622
|
placeholderTmplIndex: placeholderTmplIndex ?? null,
|
|
19787
19623
|
errorTmplIndex: errorTmplIndex ?? null,
|
|
19788
|
-
placeholderBlockConfig:
|
|
19789
|
-
|
|
19790
|
-
null,
|
|
19791
|
-
loadingBlockConfig: loadingConfigIndex != null ?
|
|
19792
|
-
getConstant(tViewConsts, loadingConfigIndex) :
|
|
19793
|
-
null,
|
|
19624
|
+
placeholderBlockConfig: null,
|
|
19625
|
+
loadingBlockConfig: null,
|
|
19794
19626
|
dependencyResolverFn: dependencyResolverFn ?? null,
|
|
19795
19627
|
loadingState: DeferDependenciesLoadingState.NOT_STARTED,
|
|
19796
19628
|
loadingPromise: null,
|
|
19797
19629
|
};
|
|
19798
|
-
|
|
19630
|
+
enableTimerScheduling?.(tView, tDetails, placeholderConfigIndex, loadingConfigIndex);
|
|
19631
|
+
setTDeferBlockDetails(tView, adjustedIndex, tDetails);
|
|
19799
19632
|
}
|
|
19800
19633
|
const tNode = getCurrentTNode();
|
|
19801
19634
|
const lContainer = lView[adjustedIndex];
|
|
@@ -19804,8 +19637,12 @@ function ɵɵdefer(index, primaryTmplIndex, dependencyResolverFn, loadingTmplInd
|
|
|
19804
19637
|
// In client-only mode, this function is a noop.
|
|
19805
19638
|
populateDehydratedViewsInLContainer(lContainer, tNode, lView);
|
|
19806
19639
|
// Init instance-specific defer details and store it.
|
|
19807
|
-
const lDetails = [
|
|
19808
|
-
|
|
19640
|
+
const lDetails = [
|
|
19641
|
+
null,
|
|
19642
|
+
DeferBlockInternalState.Initial,
|
|
19643
|
+
null,
|
|
19644
|
+
null // LOADING_AFTER_CLEANUP_FN
|
|
19645
|
+
];
|
|
19809
19646
|
setLDeferBlockDetails(lView, adjustedIndex, lDetails);
|
|
19810
19647
|
}
|
|
19811
19648
|
/**
|
|
@@ -20231,6 +20068,24 @@ function getTemplateIndexForState(newState, hostLView, tNode) {
|
|
|
20231
20068
|
return null;
|
|
20232
20069
|
}
|
|
20233
20070
|
}
|
|
20071
|
+
/**
|
|
20072
|
+
* Returns a minimum amount of time that a given state should be rendered for,
|
|
20073
|
+
* taking into account `minimum` parameter value. If the `minimum` value is
|
|
20074
|
+
* not specified - returns `null`.
|
|
20075
|
+
*/
|
|
20076
|
+
function getMinimumDurationForState(tDetails, currentState) {
|
|
20077
|
+
if (currentState === DeferBlockState.Placeholder) {
|
|
20078
|
+
return tDetails.placeholderBlockConfig?.[MINIMUM_SLOT] ?? null;
|
|
20079
|
+
}
|
|
20080
|
+
else if (currentState === DeferBlockState.Loading) {
|
|
20081
|
+
return tDetails.loadingBlockConfig?.[MINIMUM_SLOT] ?? null;
|
|
20082
|
+
}
|
|
20083
|
+
return null;
|
|
20084
|
+
}
|
|
20085
|
+
/** Retrieves the value of the `after` parameter on the @loading block. */
|
|
20086
|
+
function getLoadingBlockAfter(tDetails) {
|
|
20087
|
+
return tDetails.loadingBlockConfig?.[LOADING_AFTER_SLOT] ?? null;
|
|
20088
|
+
}
|
|
20234
20089
|
/**
|
|
20235
20090
|
* Transitions a defer block to the new state. Updates the necessary
|
|
20236
20091
|
* data structures and renders corresponding block.
|
|
@@ -20241,6 +20096,7 @@ function getTemplateIndexForState(newState, hostLView, tNode) {
|
|
|
20241
20096
|
*/
|
|
20242
20097
|
function renderDeferBlockState(newState, tNode, lContainer) {
|
|
20243
20098
|
const hostLView = lContainer[PARENT];
|
|
20099
|
+
const hostTView = hostLView[TVIEW];
|
|
20244
20100
|
// Check if this view is not destroyed. Since the loading process was async,
|
|
20245
20101
|
// the view might end up being destroyed by the time rendering happens.
|
|
20246
20102
|
if (isDestroyed(hostLView))
|
|
@@ -20249,12 +20105,26 @@ function renderDeferBlockState(newState, tNode, lContainer) {
|
|
|
20249
20105
|
ngDevMode && assertTNodeForLView(tNode, hostLView);
|
|
20250
20106
|
const lDetails = getLDeferBlockDetails(hostLView, tNode);
|
|
20251
20107
|
ngDevMode && assertDefined(lDetails, 'Expected a defer block state defined');
|
|
20108
|
+
const currentState = lDetails[DEFER_BLOCK_STATE];
|
|
20109
|
+
if (isValidStateChange(currentState, newState) &&
|
|
20110
|
+
isValidStateChange(lDetails[NEXT_DEFER_BLOCK_STATE] ?? -1, newState)) {
|
|
20111
|
+
const tDetails = getTDeferBlockDetails(hostTView, tNode);
|
|
20112
|
+
const needsScheduling = getLoadingBlockAfter(tDetails) !== null ||
|
|
20113
|
+
getMinimumDurationForState(tDetails, DeferBlockState.Loading) !== null ||
|
|
20114
|
+
getMinimumDurationForState(tDetails, DeferBlockState.Placeholder);
|
|
20115
|
+
if (ngDevMode && needsScheduling) {
|
|
20116
|
+
assertDefined(applyDeferBlockStateWithSchedulingImpl, 'Expected scheduling function to be defined');
|
|
20117
|
+
}
|
|
20118
|
+
const applyStateFn = needsScheduling ? applyDeferBlockStateWithSchedulingImpl : applyDeferBlockState;
|
|
20119
|
+
applyStateFn(newState, lDetails, lContainer, tNode, hostLView);
|
|
20120
|
+
}
|
|
20121
|
+
}
|
|
20122
|
+
/**
|
|
20123
|
+
* Applies changes to the DOM to reflect a given state.
|
|
20124
|
+
*/
|
|
20125
|
+
function applyDeferBlockState(newState, lDetails, lContainer, tNode, hostLView) {
|
|
20252
20126
|
const stateTmplIndex = getTemplateIndexForState(newState, hostLView, tNode);
|
|
20253
|
-
|
|
20254
|
-
// with a number that is less than the next state. For example, if the current
|
|
20255
|
-
// state is "loading" (represented as `2`), we should not show a placeholder
|
|
20256
|
-
// (represented as `1`).
|
|
20257
|
-
if (lDetails[DEFER_BLOCK_STATE] < newState && stateTmplIndex !== null) {
|
|
20127
|
+
if (stateTmplIndex !== null) {
|
|
20258
20128
|
lDetails[DEFER_BLOCK_STATE] = newState;
|
|
20259
20129
|
const hostTView = hostLView[TVIEW];
|
|
20260
20130
|
const adjustedIndex = stateTmplIndex + HEADER_OFFSET;
|
|
@@ -20266,8 +20136,80 @@ function renderDeferBlockState(newState, tNode, lContainer) {
|
|
|
20266
20136
|
const dehydratedView = findMatchingDehydratedView(lContainer, tNode.tView.ssrId);
|
|
20267
20137
|
const embeddedLView = createAndRenderEmbeddedLView(hostLView, tNode, null, { dehydratedView });
|
|
20268
20138
|
addLViewToLContainer(lContainer, embeddedLView, viewIndex, shouldAddViewToDom(tNode, dehydratedView));
|
|
20139
|
+
markViewDirty(embeddedLView);
|
|
20269
20140
|
}
|
|
20270
20141
|
}
|
|
20142
|
+
/**
|
|
20143
|
+
* Extends the `applyDeferBlockState` with timer-based scheduling.
|
|
20144
|
+
* This function becomes available on a page if there are defer blocks
|
|
20145
|
+
* that use `after` or `minimum` parameters in the `@loading` or
|
|
20146
|
+
* `@placeholder` blocks.
|
|
20147
|
+
*/
|
|
20148
|
+
function applyDeferBlockStateWithScheduling(newState, lDetails, lContainer, tNode, hostLView) {
|
|
20149
|
+
const now = Date.now();
|
|
20150
|
+
const hostTView = hostLView[TVIEW];
|
|
20151
|
+
const tDetails = getTDeferBlockDetails(hostTView, tNode);
|
|
20152
|
+
if (lDetails[STATE_IS_FROZEN_UNTIL] === null || lDetails[STATE_IS_FROZEN_UNTIL] <= now) {
|
|
20153
|
+
lDetails[STATE_IS_FROZEN_UNTIL] = null;
|
|
20154
|
+
const loadingAfter = getLoadingBlockAfter(tDetails);
|
|
20155
|
+
const inLoadingAfterPhase = lDetails[LOADING_AFTER_CLEANUP_FN] !== null;
|
|
20156
|
+
if (newState === DeferBlockState.Loading && loadingAfter !== null && !inLoadingAfterPhase) {
|
|
20157
|
+
// Trying to render loading, but it has an `after` config,
|
|
20158
|
+
// so schedule an update action after a timeout.
|
|
20159
|
+
lDetails[NEXT_DEFER_BLOCK_STATE] = newState;
|
|
20160
|
+
const cleanupFn = scheduleDeferBlockUpdate(loadingAfter, lDetails, tNode, lContainer, hostLView);
|
|
20161
|
+
lDetails[LOADING_AFTER_CLEANUP_FN] = cleanupFn;
|
|
20162
|
+
}
|
|
20163
|
+
else {
|
|
20164
|
+
// If we transition to a complete or an error state and there is a pending
|
|
20165
|
+
// operation to render loading after a timeout - invoke a cleanup operation,
|
|
20166
|
+
// which stops the timer.
|
|
20167
|
+
if (newState > DeferBlockState.Loading && inLoadingAfterPhase) {
|
|
20168
|
+
lDetails[LOADING_AFTER_CLEANUP_FN]();
|
|
20169
|
+
lDetails[LOADING_AFTER_CLEANUP_FN] = null;
|
|
20170
|
+
lDetails[NEXT_DEFER_BLOCK_STATE] = null;
|
|
20171
|
+
}
|
|
20172
|
+
applyDeferBlockState(newState, lDetails, lContainer, tNode, hostLView);
|
|
20173
|
+
const duration = getMinimumDurationForState(tDetails, newState);
|
|
20174
|
+
if (duration !== null) {
|
|
20175
|
+
lDetails[STATE_IS_FROZEN_UNTIL] = now + duration;
|
|
20176
|
+
scheduleDeferBlockUpdate(duration, lDetails, tNode, lContainer, hostLView);
|
|
20177
|
+
}
|
|
20178
|
+
}
|
|
20179
|
+
}
|
|
20180
|
+
else {
|
|
20181
|
+
// We are still rendering the previous state.
|
|
20182
|
+
// Update the `NEXT_DEFER_BLOCK_STATE`, which would be
|
|
20183
|
+
// picked up once it's time to transition to the next state.
|
|
20184
|
+
lDetails[NEXT_DEFER_BLOCK_STATE] = newState;
|
|
20185
|
+
}
|
|
20186
|
+
}
|
|
20187
|
+
/**
|
|
20188
|
+
* Schedules an update operation after a specified timeout.
|
|
20189
|
+
*/
|
|
20190
|
+
function scheduleDeferBlockUpdate(timeout, lDetails, tNode, lContainer, hostLView) {
|
|
20191
|
+
const callback = () => {
|
|
20192
|
+
const nextState = lDetails[NEXT_DEFER_BLOCK_STATE];
|
|
20193
|
+
lDetails[STATE_IS_FROZEN_UNTIL] = null;
|
|
20194
|
+
lDetails[NEXT_DEFER_BLOCK_STATE] = null;
|
|
20195
|
+
if (nextState !== null) {
|
|
20196
|
+
renderDeferBlockState(nextState, tNode, lContainer);
|
|
20197
|
+
}
|
|
20198
|
+
};
|
|
20199
|
+
return scheduleTimerTrigger(timeout, callback, hostLView, true);
|
|
20200
|
+
}
|
|
20201
|
+
/**
|
|
20202
|
+
* Checks whether we can transition to the next state.
|
|
20203
|
+
*
|
|
20204
|
+
* We transition to the next state if the previous state was represented
|
|
20205
|
+
* with a number that is less than the next state. For example, if the current
|
|
20206
|
+
* state is "loading" (represented as `1`), we should not show a placeholder
|
|
20207
|
+
* (represented as `0`), but we can show a completed state (represented as `2`)
|
|
20208
|
+
* or an error state (represented as `3`).
|
|
20209
|
+
*/
|
|
20210
|
+
function isValidStateChange(currentState, newState) {
|
|
20211
|
+
return currentState < newState;
|
|
20212
|
+
}
|
|
20271
20213
|
/**
|
|
20272
20214
|
* Trigger prefetching of dependencies for a defer block.
|
|
20273
20215
|
*
|
|
@@ -20419,11 +20361,9 @@ function triggerDeferBlock(lView, tNode) {
|
|
|
20419
20361
|
if (!shouldTriggerDeferBlock(injector))
|
|
20420
20362
|
return;
|
|
20421
20363
|
const tDetails = getTDeferBlockDetails(tView, tNode);
|
|
20422
|
-
// Condition is triggered, try to render loading state and start downloading.
|
|
20423
|
-
// Note: if a block is in a loading, completed or an error state, this call would be a noop.
|
|
20424
|
-
renderDeferBlockState(DeferBlockState.Loading, tNode, lContainer);
|
|
20425
20364
|
switch (tDetails.loadingState) {
|
|
20426
20365
|
case DeferDependenciesLoadingState.NOT_STARTED:
|
|
20366
|
+
renderDeferBlockState(DeferBlockState.Loading, tNode, lContainer);
|
|
20427
20367
|
triggerResourceLoading(tDetails, lView);
|
|
20428
20368
|
// The `loadingState` might have changed to "loading".
|
|
20429
20369
|
if (tDetails.loadingState ===
|
|
@@ -20432,6 +20372,7 @@ function triggerDeferBlock(lView, tNode) {
|
|
|
20432
20372
|
}
|
|
20433
20373
|
break;
|
|
20434
20374
|
case DeferDependenciesLoadingState.IN_PROGRESS:
|
|
20375
|
+
renderDeferBlockState(DeferBlockState.Loading, tNode, lContainer);
|
|
20435
20376
|
renderDeferStateAfterResourceLoading(tDetails, tNode, lContainer);
|
|
20436
20377
|
break;
|
|
20437
20378
|
case DeferDependenciesLoadingState.COMPLETE:
|
|
@@ -27359,6 +27300,18 @@ function ɵɵgetComponentDepsFactory(type, rawImports) {
|
|
|
27359
27300
|
};
|
|
27360
27301
|
}
|
|
27361
27302
|
|
|
27303
|
+
/**
|
|
27304
|
+
* Sets the debug info for an Angular class.
|
|
27305
|
+
*
|
|
27306
|
+
* This runtime is guarded by ngDevMode flag.
|
|
27307
|
+
*/
|
|
27308
|
+
function ɵsetClassDebugInfo(type, debugInfo) {
|
|
27309
|
+
const def = getComponentDef(type);
|
|
27310
|
+
if (def !== null) {
|
|
27311
|
+
def.debugInfo = debugInfo;
|
|
27312
|
+
}
|
|
27313
|
+
}
|
|
27314
|
+
|
|
27362
27315
|
/**
|
|
27363
27316
|
* A mapping of the @angular/core API surface used in generated expressions to the actual symbols.
|
|
27364
27317
|
*
|
|
@@ -27497,6 +27450,7 @@ const angularCoreEnv = (() => ({
|
|
|
27497
27450
|
'ɵɵdeferPrefetchOnHover': ɵɵdeferPrefetchOnHover,
|
|
27498
27451
|
'ɵɵdeferPrefetchOnInteraction': ɵɵdeferPrefetchOnInteraction,
|
|
27499
27452
|
'ɵɵdeferPrefetchOnViewport': ɵɵdeferPrefetchOnViewport,
|
|
27453
|
+
'ɵɵdeferEnableTimerScheduling': ɵɵdeferEnableTimerScheduling,
|
|
27500
27454
|
'ɵɵrepeater': ɵɵrepeater,
|
|
27501
27455
|
'ɵɵrepeaterCreate': ɵɵrepeaterCreate,
|
|
27502
27456
|
'ɵɵrepeaterTrackByIndex': ɵɵrepeaterTrackByIndex,
|
|
@@ -27527,6 +27481,7 @@ const angularCoreEnv = (() => ({
|
|
|
27527
27481
|
'ɵɵsetNgModuleScope': ɵɵsetNgModuleScope,
|
|
27528
27482
|
'ɵɵregisterNgModuleType': registerNgModuleType,
|
|
27529
27483
|
'ɵɵgetComponentDepsFactory': ɵɵgetComponentDepsFactory,
|
|
27484
|
+
'ɵsetClassDebugInfo': ɵsetClassDebugInfo,
|
|
27530
27485
|
'ɵɵsanitizeHtml': ɵɵsanitizeHtml,
|
|
27531
27486
|
'ɵɵsanitizeStyle': ɵɵsanitizeStyle,
|
|
27532
27487
|
'ɵɵsanitizeResourceUrl': ɵɵsanitizeResourceUrl,
|
|
@@ -28743,7 +28698,7 @@ const ITS_JUST_ANGULAR = true;
|
|
|
28743
28698
|
*
|
|
28744
28699
|
* The following example illustrates how to configure a multi-provider using `APP_INITIALIZER` token
|
|
28745
28700
|
* and a function returning a promise.
|
|
28746
|
-
*
|
|
28701
|
+
* ### Example with NgModule-based application
|
|
28747
28702
|
* ```
|
|
28748
28703
|
* function initializeApp(): Promise<any> {
|
|
28749
28704
|
* return new Promise((resolve, reject) => {
|
|
@@ -28765,11 +28720,38 @@ const ITS_JUST_ANGULAR = true;
|
|
|
28765
28720
|
* export class AppModule {}
|
|
28766
28721
|
* ```
|
|
28767
28722
|
*
|
|
28723
|
+
* ### Example with standalone application
|
|
28724
|
+
* ```
|
|
28725
|
+
* export function initializeApp(http: HttpClient) {
|
|
28726
|
+
* return (): Promise<any> =>
|
|
28727
|
+
* firstValueFrom(
|
|
28728
|
+
* http
|
|
28729
|
+
* .get("https://someUrl.com/api/user")
|
|
28730
|
+
* .pipe(tap(user => { ... }))
|
|
28731
|
+
* );
|
|
28732
|
+
* }
|
|
28733
|
+
*
|
|
28734
|
+
* bootstrapApplication(App, {
|
|
28735
|
+
* providers: [
|
|
28736
|
+
* provideHttpClient(),
|
|
28737
|
+
* {
|
|
28738
|
+
* provide: APP_INITIALIZER,
|
|
28739
|
+
* useFactory: initializeApp,
|
|
28740
|
+
* multi: true,
|
|
28741
|
+
* deps: [HttpClient],
|
|
28742
|
+
* },
|
|
28743
|
+
* ],
|
|
28744
|
+
* });
|
|
28745
|
+
|
|
28746
|
+
* ```
|
|
28747
|
+
*
|
|
28748
|
+
*
|
|
28768
28749
|
* It's also possible to configure a multi-provider using `APP_INITIALIZER` token and a function
|
|
28769
28750
|
* returning an observable, see an example below. Note: the `HttpClient` in this example is used for
|
|
28770
28751
|
* demo purposes to illustrate how the factory function can work with other providers available
|
|
28771
28752
|
* through DI.
|
|
28772
28753
|
*
|
|
28754
|
+
* ### Example with NgModule-based application
|
|
28773
28755
|
* ```
|
|
28774
28756
|
* function initializeAppFactory(httpClient: HttpClient): () => Observable<any> {
|
|
28775
28757
|
* return () => httpClient.get("https://someUrl.com/api/user")
|
|
@@ -28792,6 +28774,27 @@ const ITS_JUST_ANGULAR = true;
|
|
|
28792
28774
|
* export class AppModule {}
|
|
28793
28775
|
* ```
|
|
28794
28776
|
*
|
|
28777
|
+
* ### Example with standalone application
|
|
28778
|
+
*
|
|
28779
|
+
* function initializeAppFactory(httpClient: HttpClient): () => Observable<any> {
|
|
28780
|
+
* return () => httpClient.get("https://someUrl.com/api/user")
|
|
28781
|
+
* .pipe(
|
|
28782
|
+
* tap(user => { ... })
|
|
28783
|
+
* );
|
|
28784
|
+
* }
|
|
28785
|
+
*
|
|
28786
|
+
* bootstrapApplication(App, {
|
|
28787
|
+
* providers: [
|
|
28788
|
+
* provideHttpClient(),
|
|
28789
|
+
* {
|
|
28790
|
+
* provide: APP_INITIALIZER,
|
|
28791
|
+
* useFactory: initializeApp,
|
|
28792
|
+
* multi: true,
|
|
28793
|
+
* deps: [HttpClient],
|
|
28794
|
+
* },
|
|
28795
|
+
* ],
|
|
28796
|
+
* });
|
|
28797
|
+
*
|
|
28795
28798
|
* @publicApi
|
|
28796
28799
|
*/
|
|
28797
28800
|
const APP_INITIALIZER = new InjectionToken('Application Initializer');
|
|
@@ -29049,6 +29052,147 @@ var MissingTranslationStrategy;
|
|
|
29049
29052
|
MissingTranslationStrategy[MissingTranslationStrategy["Ignore"] = 2] = "Ignore";
|
|
29050
29053
|
})(MissingTranslationStrategy || (MissingTranslationStrategy = {}));
|
|
29051
29054
|
|
|
29055
|
+
// A delay in milliseconds before the scan is run after onLoad, to avoid any
|
|
29056
|
+
// potential race conditions with other LCP-related functions. This delay
|
|
29057
|
+
// happens outside of the main JavaScript execution and will only effect the timing
|
|
29058
|
+
// on when the warning becomes visible in the console.
|
|
29059
|
+
const SCAN_DELAY = 200;
|
|
29060
|
+
const OVERSIZED_IMAGE_TOLERANCE = 1200;
|
|
29061
|
+
class ImagePerformanceWarning {
|
|
29062
|
+
constructor() {
|
|
29063
|
+
// Map of full image URLs -> original `ngSrc` values.
|
|
29064
|
+
this.window = null;
|
|
29065
|
+
this.observer = null;
|
|
29066
|
+
this.options = inject(IMAGE_CONFIG);
|
|
29067
|
+
}
|
|
29068
|
+
start() {
|
|
29069
|
+
if (typeof PerformanceObserver === 'undefined' ||
|
|
29070
|
+
(this.options?.disableImageSizeWarning && this.options?.disableImageLazyLoadWarning)) {
|
|
29071
|
+
return;
|
|
29072
|
+
}
|
|
29073
|
+
this.observer = this.initPerformanceObserver();
|
|
29074
|
+
const win = getDocument().defaultView;
|
|
29075
|
+
if (typeof win !== 'undefined') {
|
|
29076
|
+
this.window = win;
|
|
29077
|
+
// Wait to avoid race conditions where LCP image triggers
|
|
29078
|
+
// load event before it's recorded by the performance observer
|
|
29079
|
+
const waitToScan = () => {
|
|
29080
|
+
setTimeout(this.scanImages.bind(this), SCAN_DELAY);
|
|
29081
|
+
};
|
|
29082
|
+
this.window?.addEventListener('load', waitToScan);
|
|
29083
|
+
}
|
|
29084
|
+
}
|
|
29085
|
+
ngOnDestroy() {
|
|
29086
|
+
this.observer?.disconnect();
|
|
29087
|
+
}
|
|
29088
|
+
initPerformanceObserver() {
|
|
29089
|
+
if (typeof PerformanceObserver === 'undefined') {
|
|
29090
|
+
return null;
|
|
29091
|
+
}
|
|
29092
|
+
const observer = new PerformanceObserver((entryList) => {
|
|
29093
|
+
const entries = entryList.getEntries();
|
|
29094
|
+
if (entries.length === 0)
|
|
29095
|
+
return;
|
|
29096
|
+
// We use the latest entry produced by the `PerformanceObserver` as the best
|
|
29097
|
+
// signal on which element is actually an LCP one. As an example, the first image to load on
|
|
29098
|
+
// a page, by virtue of being the only thing on the page so far, is often a LCP candidate
|
|
29099
|
+
// and gets reported by PerformanceObserver, but isn't necessarily the LCP element.
|
|
29100
|
+
const lcpElement = entries[entries.length - 1];
|
|
29101
|
+
// Cast to `any` due to missing `element` on the `LargestContentfulPaint` type of entry.
|
|
29102
|
+
// See https://developer.mozilla.org/en-US/docs/Web/API/LargestContentfulPaint
|
|
29103
|
+
const imgSrc = lcpElement.element?.src ?? '';
|
|
29104
|
+
// Exclude `data:` and `blob:` URLs, since they are fetched resources.
|
|
29105
|
+
if (imgSrc.startsWith('data:') || imgSrc.startsWith('blob:'))
|
|
29106
|
+
return;
|
|
29107
|
+
this.lcpImageUrl = imgSrc;
|
|
29108
|
+
});
|
|
29109
|
+
observer.observe({ type: 'largest-contentful-paint', buffered: true });
|
|
29110
|
+
return observer;
|
|
29111
|
+
}
|
|
29112
|
+
scanImages() {
|
|
29113
|
+
const images = getDocument().querySelectorAll('img');
|
|
29114
|
+
let lcpElementFound, lcpElementLoadedCorrectly = false;
|
|
29115
|
+
images.forEach(image => {
|
|
29116
|
+
if (!this.options?.disableImageSizeWarning) {
|
|
29117
|
+
for (const image of images) {
|
|
29118
|
+
// Image elements using the NgOptimizedImage directive are excluded,
|
|
29119
|
+
// as that directive has its own version of this check.
|
|
29120
|
+
if (!image.getAttribute('ng-img') && this.isOversized(image)) {
|
|
29121
|
+
logOversizedImageWarning(image.src);
|
|
29122
|
+
}
|
|
29123
|
+
}
|
|
29124
|
+
}
|
|
29125
|
+
if (!this.options?.disableImageLazyLoadWarning && this.lcpImageUrl) {
|
|
29126
|
+
if (image.src === this.lcpImageUrl) {
|
|
29127
|
+
lcpElementFound = true;
|
|
29128
|
+
if (image.loading !== 'lazy' || image.getAttribute('ng-img')) {
|
|
29129
|
+
// This variable is set to true and never goes back to false to account
|
|
29130
|
+
// for the case where multiple images have the same src url, and some
|
|
29131
|
+
// have lazy loading while others don't.
|
|
29132
|
+
// Also ignore NgOptimizedImage because there's a different warning for that.
|
|
29133
|
+
lcpElementLoadedCorrectly = true;
|
|
29134
|
+
}
|
|
29135
|
+
}
|
|
29136
|
+
}
|
|
29137
|
+
});
|
|
29138
|
+
if (lcpElementFound && !lcpElementLoadedCorrectly && this.lcpImageUrl &&
|
|
29139
|
+
!this.options?.disableImageLazyLoadWarning) {
|
|
29140
|
+
logLazyLCPWarning(this.lcpImageUrl);
|
|
29141
|
+
}
|
|
29142
|
+
}
|
|
29143
|
+
isOversized(image) {
|
|
29144
|
+
if (!this.window) {
|
|
29145
|
+
return false;
|
|
29146
|
+
}
|
|
29147
|
+
const computedStyle = this.window.getComputedStyle(image);
|
|
29148
|
+
let renderedWidth = parseFloat(computedStyle.getPropertyValue('width'));
|
|
29149
|
+
let renderedHeight = parseFloat(computedStyle.getPropertyValue('height'));
|
|
29150
|
+
const boxSizing = computedStyle.getPropertyValue('box-sizing');
|
|
29151
|
+
const objectFit = computedStyle.getPropertyValue('object-fit');
|
|
29152
|
+
if (objectFit === `cover`) {
|
|
29153
|
+
// Object fit cover may indicate a use case such as a sprite sheet where
|
|
29154
|
+
// this warning does not apply.
|
|
29155
|
+
return false;
|
|
29156
|
+
}
|
|
29157
|
+
if (boxSizing === 'border-box') {
|
|
29158
|
+
const paddingTop = computedStyle.getPropertyValue('padding-top');
|
|
29159
|
+
const paddingRight = computedStyle.getPropertyValue('padding-right');
|
|
29160
|
+
const paddingBottom = computedStyle.getPropertyValue('padding-bottom');
|
|
29161
|
+
const paddingLeft = computedStyle.getPropertyValue('padding-left');
|
|
29162
|
+
renderedWidth -= parseFloat(paddingRight) + parseFloat(paddingLeft);
|
|
29163
|
+
renderedHeight -= parseFloat(paddingTop) + parseFloat(paddingBottom);
|
|
29164
|
+
}
|
|
29165
|
+
const intrinsicWidth = image.naturalWidth;
|
|
29166
|
+
const intrinsicHeight = image.naturalHeight;
|
|
29167
|
+
const recommendedWidth = this.window.devicePixelRatio * renderedWidth;
|
|
29168
|
+
const recommendedHeight = this.window.devicePixelRatio * renderedHeight;
|
|
29169
|
+
const oversizedWidth = (intrinsicWidth - recommendedWidth) >= OVERSIZED_IMAGE_TOLERANCE;
|
|
29170
|
+
const oversizedHeight = (intrinsicHeight - recommendedHeight) >= OVERSIZED_IMAGE_TOLERANCE;
|
|
29171
|
+
return oversizedWidth || oversizedHeight;
|
|
29172
|
+
}
|
|
29173
|
+
static { this.ɵfac = function ImagePerformanceWarning_Factory(t) { return new (t || ImagePerformanceWarning)(); }; }
|
|
29174
|
+
static { this.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: ImagePerformanceWarning, factory: ImagePerformanceWarning.ɵfac, providedIn: 'root' }); }
|
|
29175
|
+
}
|
|
29176
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ImagePerformanceWarning, [{
|
|
29177
|
+
type: Injectable,
|
|
29178
|
+
args: [{ providedIn: 'root' }]
|
|
29179
|
+
}], () => [], null); })();
|
|
29180
|
+
function logLazyLCPWarning(src) {
|
|
29181
|
+
console.warn(formatRuntimeError(-913 /* RuntimeErrorCode.IMAGE_PERFORMANCE_WARNING */, `An image with src ${src} is the Largest Contentful Paint (LCP) element ` +
|
|
29182
|
+
`but was given a "loading" value of "lazy", which can negatively impact` +
|
|
29183
|
+
`application loading performance. This warning can be addressed by ` +
|
|
29184
|
+
`changing the loading value of the LCP image to "eager", or by using the ` +
|
|
29185
|
+
`NgOptimizedImage directive's prioritization utilities. For more ` +
|
|
29186
|
+
`information about addressing or disabling this warning, see ` +
|
|
29187
|
+
`https://angular.io/errors/NG2965`));
|
|
29188
|
+
}
|
|
29189
|
+
function logOversizedImageWarning(src) {
|
|
29190
|
+
console.warn(formatRuntimeError(-913 /* RuntimeErrorCode.IMAGE_PERFORMANCE_WARNING */, `An image with src ${src} has intrinsic file dimensions much larger than its ` +
|
|
29191
|
+
`rendered size. This can negatively impact application loading performance. ` +
|
|
29192
|
+
`For more information about addressing or disabling this warning, see ` +
|
|
29193
|
+
`https://angular.io/errors/NG2965`));
|
|
29194
|
+
}
|
|
29195
|
+
|
|
29052
29196
|
/**
|
|
29053
29197
|
* *Internal* service that keeps track of pending tasks happening in the system
|
|
29054
29198
|
* during the initial rendering. No tasks are tracked after an initial
|
|
@@ -29299,7 +29443,35 @@ function handleInjectEvent(context, data) {
|
|
|
29299
29443
|
instantiatedTokenToDependencies.set(context.token, []);
|
|
29300
29444
|
}
|
|
29301
29445
|
const { token, value, flags } = data;
|
|
29302
|
-
|
|
29446
|
+
assertDefined(context.token, 'Injector profiler context token is undefined.');
|
|
29447
|
+
const dependencies = instantiatedTokenToDependencies.get(context.token);
|
|
29448
|
+
assertDefined(dependencies, 'Could not resolve dependencies for token.');
|
|
29449
|
+
if (context.injector instanceof NodeInjector) {
|
|
29450
|
+
dependencies.push({ token, value, flags, injectedIn: getNodeInjectorContext(context.injector) });
|
|
29451
|
+
}
|
|
29452
|
+
else {
|
|
29453
|
+
dependencies.push({ token, value, flags });
|
|
29454
|
+
}
|
|
29455
|
+
}
|
|
29456
|
+
/**
|
|
29457
|
+
*
|
|
29458
|
+
* Returns the LView and TNode associated with a NodeInjector. Returns undefined if the injector
|
|
29459
|
+
* is not a NodeInjector.
|
|
29460
|
+
*
|
|
29461
|
+
* @param injector
|
|
29462
|
+
* @returns {lView: LView, tNode: TNode}|undefined
|
|
29463
|
+
*/
|
|
29464
|
+
function getNodeInjectorContext(injector) {
|
|
29465
|
+
if (!(injector instanceof NodeInjector)) {
|
|
29466
|
+
throwError('getNodeInjectorContext must be called with a NodeInjector');
|
|
29467
|
+
}
|
|
29468
|
+
const lView = getNodeInjectorLView(injector);
|
|
29469
|
+
const tNode = getNodeInjectorTNode(injector);
|
|
29470
|
+
if (tNode === null) {
|
|
29471
|
+
return;
|
|
29472
|
+
}
|
|
29473
|
+
assertTNodeForLView(tNode, lView);
|
|
29474
|
+
return { lView, tNode };
|
|
29303
29475
|
}
|
|
29304
29476
|
/**
|
|
29305
29477
|
*
|
|
@@ -29428,14 +29600,10 @@ function getDependenciesFromInjectable(injector, token) {
|
|
|
29428
29600
|
if (instance === null) {
|
|
29429
29601
|
throw new Error(`Unable to determine instance of ${token} in given injector`);
|
|
29430
29602
|
}
|
|
29431
|
-
|
|
29432
|
-
if (injector instanceof NodeInjector) {
|
|
29433
|
-
diResolver = getNodeInjectorLView(injector);
|
|
29434
|
-
}
|
|
29435
|
-
const { resolverToTokenToDependencies } = getFrameworkDIDebugData();
|
|
29436
|
-
let dependencies = resolverToTokenToDependencies.get(diResolver)?.get?.(token) ?? [];
|
|
29603
|
+
const unformattedDependencies = getDependenciesForTokenInInjector(token, injector);
|
|
29437
29604
|
const resolutionPath = getInjectorResolutionPath(injector);
|
|
29438
|
-
dependencies =
|
|
29605
|
+
const dependencies = unformattedDependencies.map(dep => {
|
|
29606
|
+
// convert injection flags to booleans
|
|
29439
29607
|
const flags = dep.flags;
|
|
29440
29608
|
dep.flags = {
|
|
29441
29609
|
optional: (8 /* InternalInjectFlags.Optional */ & flags) === 8 /* InternalInjectFlags.Optional */,
|
|
@@ -29443,6 +29611,7 @@ function getDependenciesFromInjectable(injector, token) {
|
|
|
29443
29611
|
self: (2 /* InternalInjectFlags.Self */ & flags) === 2 /* InternalInjectFlags.Self */,
|
|
29444
29612
|
skipSelf: (4 /* InternalInjectFlags.SkipSelf */ & flags) === 4 /* InternalInjectFlags.SkipSelf */,
|
|
29445
29613
|
};
|
|
29614
|
+
// find the injector that provided the dependency
|
|
29446
29615
|
for (let i = 0; i < resolutionPath.length; i++) {
|
|
29447
29616
|
const injectorToCheck = resolutionPath[i];
|
|
29448
29617
|
// if skipSelf is true we skip the first injector
|
|
@@ -29475,10 +29644,42 @@ function getDependenciesFromInjectable(injector, token) {
|
|
|
29475
29644
|
break;
|
|
29476
29645
|
}
|
|
29477
29646
|
}
|
|
29478
|
-
|
|
29647
|
+
// injectedIn contains private fields, so we omit it from the response
|
|
29648
|
+
const formattedDependency = {
|
|
29649
|
+
value: dep.value,
|
|
29650
|
+
};
|
|
29651
|
+
if (dep.token)
|
|
29652
|
+
formattedDependency.token = dep.token;
|
|
29653
|
+
if (dep.flags)
|
|
29654
|
+
formattedDependency.flags = dep.flags;
|
|
29655
|
+
if (dep.providedIn)
|
|
29656
|
+
formattedDependency.providedIn = dep.providedIn;
|
|
29657
|
+
return formattedDependency;
|
|
29479
29658
|
});
|
|
29480
29659
|
return { instance, dependencies };
|
|
29481
29660
|
}
|
|
29661
|
+
function getDependenciesForTokenInInjector(token, injector) {
|
|
29662
|
+
const { resolverToTokenToDependencies } = getFrameworkDIDebugData();
|
|
29663
|
+
if (!(injector instanceof NodeInjector)) {
|
|
29664
|
+
return resolverToTokenToDependencies.get(injector)?.get?.(token) ?? [];
|
|
29665
|
+
}
|
|
29666
|
+
const lView = getNodeInjectorLView(injector);
|
|
29667
|
+
const tokenDependencyMap = resolverToTokenToDependencies.get(lView);
|
|
29668
|
+
const dependencies = tokenDependencyMap?.get(token) ?? [];
|
|
29669
|
+
// In the NodeInjector case, all injections for every node are stored in the same lView.
|
|
29670
|
+
// We use the injectedIn field of the dependency to filter out the dependencies that
|
|
29671
|
+
// do not come from the same node as the instance we're looking at.
|
|
29672
|
+
return dependencies.filter(dependency => {
|
|
29673
|
+
const dependencyNode = dependency.injectedIn?.tNode;
|
|
29674
|
+
if (dependencyNode === undefined) {
|
|
29675
|
+
return false;
|
|
29676
|
+
}
|
|
29677
|
+
const instanceNode = getNodeInjectorTNode(injector);
|
|
29678
|
+
assertTNode(dependencyNode);
|
|
29679
|
+
assertTNode(instanceNode);
|
|
29680
|
+
return dependencyNode === instanceNode;
|
|
29681
|
+
});
|
|
29682
|
+
}
|
|
29482
29683
|
/**
|
|
29483
29684
|
* Gets the class associated with an injector that contains a provider `imports` array in it's
|
|
29484
29685
|
* definition
|
|
@@ -29741,8 +29942,7 @@ function getInjectorMetadata(injector) {
|
|
|
29741
29942
|
const lView = getNodeInjectorLView(injector);
|
|
29742
29943
|
const tNode = getNodeInjectorTNode(injector);
|
|
29743
29944
|
assertTNodeForLView(tNode, lView);
|
|
29744
|
-
|
|
29745
|
-
return { type: 'element', source: lView[tNode.index][HOST] };
|
|
29945
|
+
return { type: 'element', source: getNativeByTNode(tNode, lView) };
|
|
29746
29946
|
}
|
|
29747
29947
|
if (injector instanceof R3Injector) {
|
|
29748
29948
|
return { type: 'environment', source: injector.source ?? null };
|
|
@@ -30316,7 +30516,7 @@ function publishDefaultGlobalUtils() {
|
|
|
30316
30516
|
* Sets the error for an invalid write to a signal to be an Angular `RuntimeError`.
|
|
30317
30517
|
*/
|
|
30318
30518
|
function publishSignalConfiguration() {
|
|
30319
|
-
setThrowInvalidWriteToSignalError(() => {
|
|
30519
|
+
setThrowInvalidWriteToSignalError$1(() => {
|
|
30320
30520
|
throw new RuntimeError(600 /* RuntimeErrorCode.SIGNAL_WRITE_FROM_ILLEGAL_CONTEXT */, ngDevMode &&
|
|
30321
30521
|
'Writing to signals is not allowed in a `computed` or an `effect` by default. ' +
|
|
30322
30522
|
'Use `allowSignalWrites` in the `CreateEffectOptions` to enable this inside effects.');
|
|
@@ -30443,6 +30643,10 @@ function internalCreateApplication(config) {
|
|
|
30443
30643
|
if (rootComponent !== undefined) {
|
|
30444
30644
|
appRef.bootstrap(rootComponent);
|
|
30445
30645
|
}
|
|
30646
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
30647
|
+
const imagePerformanceService = envInjector.get(ImagePerformanceWarning);
|
|
30648
|
+
imagePerformanceService.start();
|
|
30649
|
+
}
|
|
30446
30650
|
return appRef;
|
|
30447
30651
|
});
|
|
30448
30652
|
});
|
|
@@ -32939,114 +33143,645 @@ class IterableDiffers {
|
|
|
32939
33143
|
}
|
|
32940
33144
|
}
|
|
32941
33145
|
}
|
|
32942
|
-
function getTypeNameForDebugging(type) {
|
|
32943
|
-
return type['name'] || typeof type;
|
|
32944
|
-
}
|
|
32945
|
-
|
|
32946
|
-
function defaultKeyValueDiffersFactory() {
|
|
32947
|
-
return new KeyValueDiffers([new DefaultKeyValueDifferFactory()]);
|
|
32948
|
-
}
|
|
33146
|
+
function getTypeNameForDebugging(type) {
|
|
33147
|
+
return type['name'] || typeof type;
|
|
33148
|
+
}
|
|
33149
|
+
|
|
33150
|
+
function defaultKeyValueDiffersFactory() {
|
|
33151
|
+
return new KeyValueDiffers([new DefaultKeyValueDifferFactory()]);
|
|
33152
|
+
}
|
|
33153
|
+
/**
|
|
33154
|
+
* A repository of different Map diffing strategies used by NgClass, NgStyle, and others.
|
|
33155
|
+
*
|
|
33156
|
+
* @publicApi
|
|
33157
|
+
*/
|
|
33158
|
+
class KeyValueDiffers {
|
|
33159
|
+
/** @nocollapse */
|
|
33160
|
+
static { this.ɵprov = ɵɵdefineInjectable({ token: KeyValueDiffers, providedIn: 'root', factory: defaultKeyValueDiffersFactory }); }
|
|
33161
|
+
constructor(factories) {
|
|
33162
|
+
this.factories = factories;
|
|
33163
|
+
}
|
|
33164
|
+
static create(factories, parent) {
|
|
33165
|
+
if (parent) {
|
|
33166
|
+
const copied = parent.factories.slice();
|
|
33167
|
+
factories = factories.concat(copied);
|
|
33168
|
+
}
|
|
33169
|
+
return new KeyValueDiffers(factories);
|
|
33170
|
+
}
|
|
33171
|
+
/**
|
|
33172
|
+
* Takes an array of {@link KeyValueDifferFactory} and returns a provider used to extend the
|
|
33173
|
+
* inherited {@link KeyValueDiffers} instance with the provided factories and return a new
|
|
33174
|
+
* {@link KeyValueDiffers} instance.
|
|
33175
|
+
*
|
|
33176
|
+
* @usageNotes
|
|
33177
|
+
* ### Example
|
|
33178
|
+
*
|
|
33179
|
+
* The following example shows how to extend an existing list of factories,
|
|
33180
|
+
* which will only be applied to the injector for this component and its children.
|
|
33181
|
+
* This step is all that's required to make a new {@link KeyValueDiffer} available.
|
|
33182
|
+
*
|
|
33183
|
+
* ```
|
|
33184
|
+
* @Component({
|
|
33185
|
+
* viewProviders: [
|
|
33186
|
+
* KeyValueDiffers.extend([new ImmutableMapDiffer()])
|
|
33187
|
+
* ]
|
|
33188
|
+
* })
|
|
33189
|
+
* ```
|
|
33190
|
+
*/
|
|
33191
|
+
static extend(factories) {
|
|
33192
|
+
return {
|
|
33193
|
+
provide: KeyValueDiffers,
|
|
33194
|
+
useFactory: (parent) => {
|
|
33195
|
+
// if parent is null, it means that we are in the root injector and we have just overridden
|
|
33196
|
+
// the default injection mechanism for KeyValueDiffers, in such a case just assume
|
|
33197
|
+
// `defaultKeyValueDiffersFactory`.
|
|
33198
|
+
return KeyValueDiffers.create(factories, parent || defaultKeyValueDiffersFactory());
|
|
33199
|
+
},
|
|
33200
|
+
// Dependency technically isn't optional, but we can provide a better error message this way.
|
|
33201
|
+
deps: [[KeyValueDiffers, new SkipSelf(), new Optional()]]
|
|
33202
|
+
};
|
|
33203
|
+
}
|
|
33204
|
+
find(kv) {
|
|
33205
|
+
const factory = this.factories.find(f => f.supports(kv));
|
|
33206
|
+
if (factory) {
|
|
33207
|
+
return factory;
|
|
33208
|
+
}
|
|
33209
|
+
throw new RuntimeError(901 /* RuntimeErrorCode.NO_SUPPORTING_DIFFER_FACTORY */, ngDevMode && `Cannot find a differ supporting object '${kv}'`);
|
|
33210
|
+
}
|
|
33211
|
+
}
|
|
33212
|
+
|
|
33213
|
+
/**
|
|
33214
|
+
* Structural diffing for `Object`s and `Map`s.
|
|
33215
|
+
*/
|
|
33216
|
+
const keyValDiff = [new DefaultKeyValueDifferFactory()];
|
|
33217
|
+
/**
|
|
33218
|
+
* Structural diffing for `Iterable` types such as `Array`s.
|
|
33219
|
+
*/
|
|
33220
|
+
const iterableDiff = [new DefaultIterableDifferFactory()];
|
|
33221
|
+
const defaultIterableDiffers = new IterableDiffers(iterableDiff);
|
|
33222
|
+
const defaultKeyValueDiffers = new KeyValueDiffers(keyValDiff);
|
|
33223
|
+
|
|
33224
|
+
/**
|
|
33225
|
+
* @module
|
|
33226
|
+
* @description
|
|
33227
|
+
* Change detection enables data binding in Angular.
|
|
33228
|
+
*/
|
|
33229
|
+
|
|
33230
|
+
/**
|
|
33231
|
+
* This platform has to be included in any other platform
|
|
33232
|
+
*
|
|
33233
|
+
* @publicApi
|
|
33234
|
+
*/
|
|
33235
|
+
const platformCore = createPlatformFactory(null, 'core', []);
|
|
33236
|
+
|
|
33237
|
+
/**
|
|
33238
|
+
* Re-exported by `BrowserModule`, which is included automatically in the root
|
|
33239
|
+
* `AppModule` when you create a new app with the CLI `new` command. Eagerly injects
|
|
33240
|
+
* `ApplicationRef` to instantiate it.
|
|
33241
|
+
*
|
|
33242
|
+
* @publicApi
|
|
33243
|
+
*/
|
|
33244
|
+
class ApplicationModule {
|
|
33245
|
+
// Inject ApplicationRef to make it eager...
|
|
33246
|
+
constructor(appRef) { }
|
|
33247
|
+
static { this.ɵfac = function ApplicationModule_Factory(t) { return new (t || ApplicationModule)(ɵɵinject(ApplicationRef)); }; }
|
|
33248
|
+
static { this.ɵmod = /*@__PURE__*/ ɵɵdefineNgModule({ type: ApplicationModule }); }
|
|
33249
|
+
static { this.ɵinj = /*@__PURE__*/ ɵɵdefineInjector({}); }
|
|
33250
|
+
}
|
|
33251
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationModule, [{
|
|
33252
|
+
type: NgModule
|
|
33253
|
+
}], () => [{ type: ApplicationRef }], null); })();
|
|
33254
|
+
|
|
33255
|
+
/**
|
|
33256
|
+
* The default equality function used for `signal` and `computed`, which uses referential equality.
|
|
33257
|
+
*/
|
|
33258
|
+
function defaultEquals(a, b) {
|
|
33259
|
+
return Object.is(a, b);
|
|
33260
|
+
}
|
|
33261
|
+
|
|
33262
|
+
/**
|
|
33263
|
+
* The currently active consumer `ReactiveNode`, if running code in a reactive context.
|
|
33264
|
+
*
|
|
33265
|
+
* Change this via `setActiveConsumer`.
|
|
33266
|
+
*/
|
|
33267
|
+
let activeConsumer = null;
|
|
33268
|
+
let inNotificationPhase = false;
|
|
33269
|
+
/**
|
|
33270
|
+
* Symbol used to tell `Signal`s apart from other functions.
|
|
33271
|
+
*
|
|
33272
|
+
* This can be used to auto-unwrap signals in various cases, or to auto-wrap non-signal values.
|
|
33273
|
+
*/
|
|
33274
|
+
const SIGNAL = /* @__PURE__ */ Symbol('SIGNAL');
|
|
33275
|
+
function setActiveConsumer(consumer) {
|
|
33276
|
+
const prev = activeConsumer;
|
|
33277
|
+
activeConsumer = consumer;
|
|
33278
|
+
return prev;
|
|
33279
|
+
}
|
|
33280
|
+
function getActiveConsumer() {
|
|
33281
|
+
return activeConsumer;
|
|
33282
|
+
}
|
|
33283
|
+
function isInNotificationPhase() {
|
|
33284
|
+
return inNotificationPhase;
|
|
33285
|
+
}
|
|
33286
|
+
function isReactive(value) {
|
|
33287
|
+
return value[SIGNAL] !== undefined;
|
|
33288
|
+
}
|
|
33289
|
+
const REACTIVE_NODE = {
|
|
33290
|
+
version: 0,
|
|
33291
|
+
dirty: false,
|
|
33292
|
+
producerNode: undefined,
|
|
33293
|
+
producerLastReadVersion: undefined,
|
|
33294
|
+
producerIndexOfThis: undefined,
|
|
33295
|
+
nextProducerIndex: 0,
|
|
33296
|
+
liveConsumerNode: undefined,
|
|
33297
|
+
liveConsumerIndexOfThis: undefined,
|
|
33298
|
+
consumerAllowSignalWrites: false,
|
|
33299
|
+
consumerIsAlwaysLive: false,
|
|
33300
|
+
producerMustRecompute: () => false,
|
|
33301
|
+
producerRecomputeValue: () => { },
|
|
33302
|
+
consumerMarkedDirty: () => { },
|
|
33303
|
+
consumerOnSignalRead: () => { },
|
|
33304
|
+
};
|
|
33305
|
+
/**
|
|
33306
|
+
* Called by implementations when a producer's signal is read.
|
|
33307
|
+
*/
|
|
33308
|
+
function producerAccessed(node) {
|
|
33309
|
+
if (inNotificationPhase) {
|
|
33310
|
+
throw new Error(typeof ngDevMode !== 'undefined' && ngDevMode ?
|
|
33311
|
+
`Assertion error: signal read during notification phase` :
|
|
33312
|
+
'');
|
|
33313
|
+
}
|
|
33314
|
+
if (activeConsumer === null) {
|
|
33315
|
+
// Accessed outside of a reactive context, so nothing to record.
|
|
33316
|
+
return;
|
|
33317
|
+
}
|
|
33318
|
+
activeConsumer.consumerOnSignalRead(node);
|
|
33319
|
+
// This producer is the `idx`th dependency of `activeConsumer`.
|
|
33320
|
+
const idx = activeConsumer.nextProducerIndex++;
|
|
33321
|
+
assertConsumerNode(activeConsumer);
|
|
33322
|
+
if (idx < activeConsumer.producerNode.length && activeConsumer.producerNode[idx] !== node) {
|
|
33323
|
+
// There's been a change in producers since the last execution of `activeConsumer`.
|
|
33324
|
+
// `activeConsumer.producerNode[idx]` holds a stale dependency which will be be removed and
|
|
33325
|
+
// replaced with `this`.
|
|
33326
|
+
//
|
|
33327
|
+
// If `activeConsumer` isn't live, then this is a no-op, since we can replace the producer in
|
|
33328
|
+
// `activeConsumer.producerNode` directly. However, if `activeConsumer` is live, then we need
|
|
33329
|
+
// to remove it from the stale producer's `liveConsumer`s.
|
|
33330
|
+
if (consumerIsLive(activeConsumer)) {
|
|
33331
|
+
const staleProducer = activeConsumer.producerNode[idx];
|
|
33332
|
+
producerRemoveLiveConsumerAtIndex(staleProducer, activeConsumer.producerIndexOfThis[idx]);
|
|
33333
|
+
// At this point, the only record of `staleProducer` is the reference at
|
|
33334
|
+
// `activeConsumer.producerNode[idx]` which will be overwritten below.
|
|
33335
|
+
}
|
|
33336
|
+
}
|
|
33337
|
+
if (activeConsumer.producerNode[idx] !== node) {
|
|
33338
|
+
// We're a new dependency of the consumer (at `idx`).
|
|
33339
|
+
activeConsumer.producerNode[idx] = node;
|
|
33340
|
+
// If the active consumer is live, then add it as a live consumer. If not, then use 0 as a
|
|
33341
|
+
// placeholder value.
|
|
33342
|
+
activeConsumer.producerIndexOfThis[idx] =
|
|
33343
|
+
consumerIsLive(activeConsumer) ? producerAddLiveConsumer(node, activeConsumer, idx) : 0;
|
|
33344
|
+
}
|
|
33345
|
+
activeConsumer.producerLastReadVersion[idx] = node.version;
|
|
33346
|
+
}
|
|
33347
|
+
/**
|
|
33348
|
+
* Ensure this producer's `version` is up-to-date.
|
|
33349
|
+
*/
|
|
33350
|
+
function producerUpdateValueVersion(node) {
|
|
33351
|
+
if (consumerIsLive(node) && !node.dirty) {
|
|
33352
|
+
// A live consumer will be marked dirty by producers, so a clean state means that its version
|
|
33353
|
+
// is guaranteed to be up-to-date.
|
|
33354
|
+
return;
|
|
33355
|
+
}
|
|
33356
|
+
if (!node.producerMustRecompute(node) && !consumerPollProducersForChange(node)) {
|
|
33357
|
+
// None of our producers report a change since the last time they were read, so no
|
|
33358
|
+
// recomputation of our value is necessary, and we can consider ourselves clean.
|
|
33359
|
+
node.dirty = false;
|
|
33360
|
+
return;
|
|
33361
|
+
}
|
|
33362
|
+
node.producerRecomputeValue(node);
|
|
33363
|
+
// After recomputing the value, we're no longer dirty.
|
|
33364
|
+
node.dirty = false;
|
|
33365
|
+
}
|
|
33366
|
+
/**
|
|
33367
|
+
* Propagate a dirty notification to live consumers of this producer.
|
|
33368
|
+
*/
|
|
33369
|
+
function producerNotifyConsumers(node) {
|
|
33370
|
+
if (node.liveConsumerNode === undefined) {
|
|
33371
|
+
return;
|
|
33372
|
+
}
|
|
33373
|
+
// Prevent signal reads when we're updating the graph
|
|
33374
|
+
const prev = inNotificationPhase;
|
|
33375
|
+
inNotificationPhase = true;
|
|
33376
|
+
try {
|
|
33377
|
+
for (const consumer of node.liveConsumerNode) {
|
|
33378
|
+
if (!consumer.dirty) {
|
|
33379
|
+
consumerMarkDirty(consumer);
|
|
33380
|
+
}
|
|
33381
|
+
}
|
|
33382
|
+
}
|
|
33383
|
+
finally {
|
|
33384
|
+
inNotificationPhase = prev;
|
|
33385
|
+
}
|
|
33386
|
+
}
|
|
33387
|
+
/**
|
|
33388
|
+
* Whether this `ReactiveNode` in its producer capacity is currently allowed to initiate updates,
|
|
33389
|
+
* based on the current consumer context.
|
|
33390
|
+
*/
|
|
33391
|
+
function producerUpdatesAllowed() {
|
|
33392
|
+
return activeConsumer?.consumerAllowSignalWrites !== false;
|
|
33393
|
+
}
|
|
33394
|
+
function consumerMarkDirty(node) {
|
|
33395
|
+
node.dirty = true;
|
|
33396
|
+
producerNotifyConsumers(node);
|
|
33397
|
+
node.consumerMarkedDirty?.(node);
|
|
33398
|
+
}
|
|
33399
|
+
/**
|
|
33400
|
+
* Prepare this consumer to run a computation in its reactive context.
|
|
33401
|
+
*
|
|
33402
|
+
* Must be called by subclasses which represent reactive computations, before those computations
|
|
33403
|
+
* begin.
|
|
33404
|
+
*/
|
|
33405
|
+
function consumerBeforeComputation(node) {
|
|
33406
|
+
node && (node.nextProducerIndex = 0);
|
|
33407
|
+
return setActiveConsumer(node);
|
|
33408
|
+
}
|
|
33409
|
+
/**
|
|
33410
|
+
* Finalize this consumer's state after a reactive computation has run.
|
|
33411
|
+
*
|
|
33412
|
+
* Must be called by subclasses which represent reactive computations, after those computations
|
|
33413
|
+
* have finished.
|
|
33414
|
+
*/
|
|
33415
|
+
function consumerAfterComputation(node, prevConsumer) {
|
|
33416
|
+
setActiveConsumer(prevConsumer);
|
|
33417
|
+
if (!node || node.producerNode === undefined || node.producerIndexOfThis === undefined ||
|
|
33418
|
+
node.producerLastReadVersion === undefined) {
|
|
33419
|
+
return;
|
|
33420
|
+
}
|
|
33421
|
+
if (consumerIsLive(node)) {
|
|
33422
|
+
// For live consumers, we need to remove the producer -> consumer edge for any stale producers
|
|
33423
|
+
// which weren't dependencies after the recomputation.
|
|
33424
|
+
for (let i = node.nextProducerIndex; i < node.producerNode.length; i++) {
|
|
33425
|
+
producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]);
|
|
33426
|
+
}
|
|
33427
|
+
}
|
|
33428
|
+
// Truncate the producer tracking arrays.
|
|
33429
|
+
// Perf note: this is essentially truncating the length to `node.nextProducerIndex`, but
|
|
33430
|
+
// benchmarking has shown that individual pop operations are faster.
|
|
33431
|
+
while (node.producerNode.length > node.nextProducerIndex) {
|
|
33432
|
+
node.producerNode.pop();
|
|
33433
|
+
node.producerLastReadVersion.pop();
|
|
33434
|
+
node.producerIndexOfThis.pop();
|
|
33435
|
+
}
|
|
33436
|
+
}
|
|
33437
|
+
/**
|
|
33438
|
+
* Determine whether this consumer has any dependencies which have changed since the last time
|
|
33439
|
+
* they were read.
|
|
33440
|
+
*/
|
|
33441
|
+
function consumerPollProducersForChange(node) {
|
|
33442
|
+
assertConsumerNode(node);
|
|
33443
|
+
// Poll producers for change.
|
|
33444
|
+
for (let i = 0; i < node.producerNode.length; i++) {
|
|
33445
|
+
const producer = node.producerNode[i];
|
|
33446
|
+
const seenVersion = node.producerLastReadVersion[i];
|
|
33447
|
+
// First check the versions. A mismatch means that the producer's value is known to have
|
|
33448
|
+
// changed since the last time we read it.
|
|
33449
|
+
if (seenVersion !== producer.version) {
|
|
33450
|
+
return true;
|
|
33451
|
+
}
|
|
33452
|
+
// The producer's version is the same as the last time we read it, but it might itself be
|
|
33453
|
+
// stale. Force the producer to recompute its version (calculating a new value if necessary).
|
|
33454
|
+
producerUpdateValueVersion(producer);
|
|
33455
|
+
// Now when we do this check, `producer.version` is guaranteed to be up to date, so if the
|
|
33456
|
+
// versions still match then it has not changed since the last time we read it.
|
|
33457
|
+
if (seenVersion !== producer.version) {
|
|
33458
|
+
return true;
|
|
33459
|
+
}
|
|
33460
|
+
}
|
|
33461
|
+
return false;
|
|
33462
|
+
}
|
|
33463
|
+
/**
|
|
33464
|
+
* Disconnect this consumer from the graph.
|
|
33465
|
+
*/
|
|
33466
|
+
function consumerDestroy(node) {
|
|
33467
|
+
assertConsumerNode(node);
|
|
33468
|
+
if (consumerIsLive(node)) {
|
|
33469
|
+
// Drop all connections from the graph to this node.
|
|
33470
|
+
for (let i = 0; i < node.producerNode.length; i++) {
|
|
33471
|
+
producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]);
|
|
33472
|
+
}
|
|
33473
|
+
}
|
|
33474
|
+
// Truncate all the arrays to drop all connection from this node to the graph.
|
|
33475
|
+
node.producerNode.length = node.producerLastReadVersion.length = node.producerIndexOfThis.length =
|
|
33476
|
+
0;
|
|
33477
|
+
if (node.liveConsumerNode) {
|
|
33478
|
+
node.liveConsumerNode.length = node.liveConsumerIndexOfThis.length = 0;
|
|
33479
|
+
}
|
|
33480
|
+
}
|
|
32949
33481
|
/**
|
|
32950
|
-
*
|
|
33482
|
+
* Add `consumer` as a live consumer of this node.
|
|
32951
33483
|
*
|
|
32952
|
-
*
|
|
33484
|
+
* Note that this operation is potentially transitive. If this node becomes live, then it becomes
|
|
33485
|
+
* a live consumer of all of its current producers.
|
|
32953
33486
|
*/
|
|
32954
|
-
|
|
32955
|
-
|
|
32956
|
-
|
|
32957
|
-
|
|
32958
|
-
|
|
32959
|
-
|
|
32960
|
-
|
|
32961
|
-
if (parent) {
|
|
32962
|
-
const copied = parent.factories.slice();
|
|
32963
|
-
factories = factories.concat(copied);
|
|
33487
|
+
function producerAddLiveConsumer(node, consumer, indexOfThis) {
|
|
33488
|
+
assertProducerNode(node);
|
|
33489
|
+
assertConsumerNode(node);
|
|
33490
|
+
if (node.liveConsumerNode.length === 0) {
|
|
33491
|
+
// When going from 0 to 1 live consumers, we become a live consumer to our producers.
|
|
33492
|
+
for (let i = 0; i < node.producerNode.length; i++) {
|
|
33493
|
+
node.producerIndexOfThis[i] = producerAddLiveConsumer(node.producerNode[i], node, i);
|
|
32964
33494
|
}
|
|
32965
|
-
return new KeyValueDiffers(factories);
|
|
32966
33495
|
}
|
|
32967
|
-
|
|
32968
|
-
|
|
32969
|
-
|
|
32970
|
-
|
|
32971
|
-
|
|
32972
|
-
|
|
32973
|
-
|
|
32974
|
-
|
|
32975
|
-
|
|
32976
|
-
|
|
32977
|
-
|
|
32978
|
-
*
|
|
32979
|
-
* ```
|
|
32980
|
-
* @Component({
|
|
32981
|
-
* viewProviders: [
|
|
32982
|
-
* KeyValueDiffers.extend([new ImmutableMapDiffer()])
|
|
32983
|
-
* ]
|
|
32984
|
-
* })
|
|
32985
|
-
* ```
|
|
32986
|
-
*/
|
|
32987
|
-
static extend(factories) {
|
|
32988
|
-
return {
|
|
32989
|
-
provide: KeyValueDiffers,
|
|
32990
|
-
useFactory: (parent) => {
|
|
32991
|
-
// if parent is null, it means that we are in the root injector and we have just overridden
|
|
32992
|
-
// the default injection mechanism for KeyValueDiffers, in such a case just assume
|
|
32993
|
-
// `defaultKeyValueDiffersFactory`.
|
|
32994
|
-
return KeyValueDiffers.create(factories, parent || defaultKeyValueDiffersFactory());
|
|
32995
|
-
},
|
|
32996
|
-
// Dependency technically isn't optional, but we can provide a better error message this way.
|
|
32997
|
-
deps: [[KeyValueDiffers, new SkipSelf(), new Optional()]]
|
|
32998
|
-
};
|
|
33496
|
+
node.liveConsumerIndexOfThis.push(indexOfThis);
|
|
33497
|
+
return node.liveConsumerNode.push(consumer) - 1;
|
|
33498
|
+
}
|
|
33499
|
+
/**
|
|
33500
|
+
* Remove the live consumer at `idx`.
|
|
33501
|
+
*/
|
|
33502
|
+
function producerRemoveLiveConsumerAtIndex(node, idx) {
|
|
33503
|
+
assertProducerNode(node);
|
|
33504
|
+
assertConsumerNode(node);
|
|
33505
|
+
if (typeof ngDevMode !== 'undefined' && ngDevMode && idx >= node.liveConsumerNode.length) {
|
|
33506
|
+
throw new Error(`Assertion error: active consumer index ${idx} is out of bounds of ${node.liveConsumerNode.length} consumers)`);
|
|
32999
33507
|
}
|
|
33000
|
-
|
|
33001
|
-
|
|
33002
|
-
|
|
33003
|
-
|
|
33508
|
+
if (node.liveConsumerNode.length === 1) {
|
|
33509
|
+
// When removing the last live consumer, we will no longer be live. We need to remove
|
|
33510
|
+
// ourselves from our producers' tracking (which may cause consumer-producers to lose
|
|
33511
|
+
// liveness as well).
|
|
33512
|
+
for (let i = 0; i < node.producerNode.length; i++) {
|
|
33513
|
+
producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]);
|
|
33004
33514
|
}
|
|
33005
|
-
throw new RuntimeError(901 /* RuntimeErrorCode.NO_SUPPORTING_DIFFER_FACTORY */, ngDevMode && `Cannot find a differ supporting object '${kv}'`);
|
|
33006
33515
|
}
|
|
33516
|
+
// Move the last value of `liveConsumers` into `idx`. Note that if there's only a single
|
|
33517
|
+
// live consumer, this is a no-op.
|
|
33518
|
+
const lastIdx = node.liveConsumerNode.length - 1;
|
|
33519
|
+
node.liveConsumerNode[idx] = node.liveConsumerNode[lastIdx];
|
|
33520
|
+
node.liveConsumerIndexOfThis[idx] = node.liveConsumerIndexOfThis[lastIdx];
|
|
33521
|
+
// Truncate the array.
|
|
33522
|
+
node.liveConsumerNode.length--;
|
|
33523
|
+
node.liveConsumerIndexOfThis.length--;
|
|
33524
|
+
// If the index is still valid, then we need to fix the index pointer from the producer to this
|
|
33525
|
+
// consumer, and update it from `lastIdx` to `idx` (accounting for the move above).
|
|
33526
|
+
if (idx < node.liveConsumerNode.length) {
|
|
33527
|
+
const idxProducer = node.liveConsumerIndexOfThis[idx];
|
|
33528
|
+
const consumer = node.liveConsumerNode[idx];
|
|
33529
|
+
assertConsumerNode(consumer);
|
|
33530
|
+
consumer.producerIndexOfThis[idxProducer] = idx;
|
|
33531
|
+
}
|
|
33532
|
+
}
|
|
33533
|
+
function consumerIsLive(node) {
|
|
33534
|
+
return node.consumerIsAlwaysLive || (node?.liveConsumerNode?.length ?? 0) > 0;
|
|
33535
|
+
}
|
|
33536
|
+
function assertConsumerNode(node) {
|
|
33537
|
+
node.producerNode ??= [];
|
|
33538
|
+
node.producerIndexOfThis ??= [];
|
|
33539
|
+
node.producerLastReadVersion ??= [];
|
|
33540
|
+
}
|
|
33541
|
+
function assertProducerNode(node) {
|
|
33542
|
+
node.liveConsumerNode ??= [];
|
|
33543
|
+
node.liveConsumerIndexOfThis ??= [];
|
|
33007
33544
|
}
|
|
33008
33545
|
|
|
33009
33546
|
/**
|
|
33010
|
-
*
|
|
33547
|
+
* Create a computed signal which derives a reactive value from an expression.
|
|
33011
33548
|
*/
|
|
33012
|
-
|
|
33549
|
+
function createComputed(computation) {
|
|
33550
|
+
const node = Object.create(COMPUTED_NODE);
|
|
33551
|
+
node.computation = computation;
|
|
33552
|
+
const computed = () => {
|
|
33553
|
+
// Check if the value needs updating before returning it.
|
|
33554
|
+
producerUpdateValueVersion(node);
|
|
33555
|
+
// Record that someone looked at this signal.
|
|
33556
|
+
producerAccessed(node);
|
|
33557
|
+
if (node.value === ERRORED) {
|
|
33558
|
+
throw node.error;
|
|
33559
|
+
}
|
|
33560
|
+
return node.value;
|
|
33561
|
+
};
|
|
33562
|
+
computed[SIGNAL] = node;
|
|
33563
|
+
return computed;
|
|
33564
|
+
}
|
|
33013
33565
|
/**
|
|
33014
|
-
*
|
|
33566
|
+
* A dedicated symbol used before a computed value has been calculated for the first time.
|
|
33567
|
+
* Explicitly typed as `any` so we can use it as signal's value.
|
|
33015
33568
|
*/
|
|
33016
|
-
const
|
|
33017
|
-
const defaultIterableDiffers = new IterableDiffers(iterableDiff);
|
|
33018
|
-
const defaultKeyValueDiffers = new KeyValueDiffers(keyValDiff);
|
|
33019
|
-
|
|
33569
|
+
const UNSET = /* @__PURE__ */ Symbol('UNSET');
|
|
33020
33570
|
/**
|
|
33021
|
-
*
|
|
33022
|
-
*
|
|
33023
|
-
*
|
|
33571
|
+
* A dedicated symbol used in place of a computed signal value to indicate that a given computation
|
|
33572
|
+
* is in progress. Used to detect cycles in computation chains.
|
|
33573
|
+
* Explicitly typed as `any` so we can use it as signal's value.
|
|
33024
33574
|
*/
|
|
33025
|
-
|
|
33575
|
+
const COMPUTING = /* @__PURE__ */ Symbol('COMPUTING');
|
|
33026
33576
|
/**
|
|
33027
|
-
*
|
|
33028
|
-
*
|
|
33029
|
-
*
|
|
33577
|
+
* A dedicated symbol used in place of a computed signal value to indicate that a given computation
|
|
33578
|
+
* failed. The thrown error is cached until the computation gets dirty again.
|
|
33579
|
+
* Explicitly typed as `any` so we can use it as signal's value.
|
|
33030
33580
|
*/
|
|
33031
|
-
const
|
|
33581
|
+
const ERRORED = /* @__PURE__ */ Symbol('ERRORED');
|
|
33582
|
+
// Note: Using an IIFE here to ensure that the spread assignment is not considered
|
|
33583
|
+
// a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
|
|
33584
|
+
// TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
|
|
33585
|
+
const COMPUTED_NODE = /* @__PURE__ */ (() => {
|
|
33586
|
+
return {
|
|
33587
|
+
...REACTIVE_NODE,
|
|
33588
|
+
value: UNSET,
|
|
33589
|
+
dirty: true,
|
|
33590
|
+
error: null,
|
|
33591
|
+
equal: defaultEquals,
|
|
33592
|
+
producerMustRecompute(node) {
|
|
33593
|
+
// Force a recomputation if there's no current value, or if the current value is in the
|
|
33594
|
+
// process of being calculated (which should throw an error).
|
|
33595
|
+
return node.value === UNSET || node.value === COMPUTING;
|
|
33596
|
+
},
|
|
33597
|
+
producerRecomputeValue(node) {
|
|
33598
|
+
if (node.value === COMPUTING) {
|
|
33599
|
+
// Our computation somehow led to a cyclic read of itself.
|
|
33600
|
+
throw new Error('Detected cycle in computations.');
|
|
33601
|
+
}
|
|
33602
|
+
const oldValue = node.value;
|
|
33603
|
+
node.value = COMPUTING;
|
|
33604
|
+
const prevConsumer = consumerBeforeComputation(node);
|
|
33605
|
+
let newValue;
|
|
33606
|
+
try {
|
|
33607
|
+
newValue = node.computation();
|
|
33608
|
+
}
|
|
33609
|
+
catch (err) {
|
|
33610
|
+
newValue = ERRORED;
|
|
33611
|
+
node.error = err;
|
|
33612
|
+
}
|
|
33613
|
+
finally {
|
|
33614
|
+
consumerAfterComputation(node, prevConsumer);
|
|
33615
|
+
}
|
|
33616
|
+
if (oldValue !== UNSET && oldValue !== ERRORED && newValue !== ERRORED &&
|
|
33617
|
+
node.equal(oldValue, newValue)) {
|
|
33618
|
+
// No change to `valueVersion` - old and new values are
|
|
33619
|
+
// semantically equivalent.
|
|
33620
|
+
node.value = oldValue;
|
|
33621
|
+
return;
|
|
33622
|
+
}
|
|
33623
|
+
node.value = newValue;
|
|
33624
|
+
node.version++;
|
|
33625
|
+
},
|
|
33626
|
+
};
|
|
33627
|
+
})();
|
|
33628
|
+
|
|
33629
|
+
function defaultThrowError() {
|
|
33630
|
+
throw new Error();
|
|
33631
|
+
}
|
|
33632
|
+
let throwInvalidWriteToSignalErrorFn = defaultThrowError;
|
|
33633
|
+
function throwInvalidWriteToSignalError() {
|
|
33634
|
+
throwInvalidWriteToSignalErrorFn();
|
|
33635
|
+
}
|
|
33636
|
+
function setThrowInvalidWriteToSignalError(fn) {
|
|
33637
|
+
throwInvalidWriteToSignalErrorFn = fn;
|
|
33638
|
+
}
|
|
33032
33639
|
|
|
33033
33640
|
/**
|
|
33034
|
-
*
|
|
33035
|
-
* `AppModule` when you create a new app with the CLI `new` command. Eagerly injects
|
|
33036
|
-
* `ApplicationRef` to instantiate it.
|
|
33641
|
+
* If set, called after `WritableSignal`s are updated.
|
|
33037
33642
|
*
|
|
33038
|
-
*
|
|
33643
|
+
* This hook can be used to achieve various effects, such as running effects synchronously as part
|
|
33644
|
+
* of setting a signal.
|
|
33039
33645
|
*/
|
|
33040
|
-
|
|
33041
|
-
|
|
33042
|
-
|
|
33043
|
-
|
|
33044
|
-
|
|
33045
|
-
|
|
33646
|
+
let postSignalSetFn = null;
|
|
33647
|
+
/**
|
|
33648
|
+
* Create a `Signal` that can be set or updated directly.
|
|
33649
|
+
*/
|
|
33650
|
+
function createSignal(initialValue) {
|
|
33651
|
+
const node = Object.create(SIGNAL_NODE);
|
|
33652
|
+
node.value = initialValue;
|
|
33653
|
+
const getter = (() => {
|
|
33654
|
+
producerAccessed(node);
|
|
33655
|
+
return node.value;
|
|
33656
|
+
});
|
|
33657
|
+
getter[SIGNAL] = node;
|
|
33658
|
+
return getter;
|
|
33659
|
+
}
|
|
33660
|
+
function setPostSignalSetFn(fn) {
|
|
33661
|
+
const prev = postSignalSetFn;
|
|
33662
|
+
postSignalSetFn = fn;
|
|
33663
|
+
return prev;
|
|
33664
|
+
}
|
|
33665
|
+
function signalGetFn() {
|
|
33666
|
+
producerAccessed(this);
|
|
33667
|
+
return this.value;
|
|
33668
|
+
}
|
|
33669
|
+
function signalSetFn(node, newValue) {
|
|
33670
|
+
if (!producerUpdatesAllowed()) {
|
|
33671
|
+
throwInvalidWriteToSignalError();
|
|
33672
|
+
}
|
|
33673
|
+
if (!node.equal(node.value, newValue)) {
|
|
33674
|
+
node.value = newValue;
|
|
33675
|
+
signalValueChanged(node);
|
|
33676
|
+
}
|
|
33677
|
+
}
|
|
33678
|
+
function signalUpdateFn(node, updater) {
|
|
33679
|
+
if (!producerUpdatesAllowed()) {
|
|
33680
|
+
throwInvalidWriteToSignalError();
|
|
33681
|
+
}
|
|
33682
|
+
signalSetFn(node, updater(node.value));
|
|
33683
|
+
}
|
|
33684
|
+
function signalMutateFn(node, mutator) {
|
|
33685
|
+
if (!producerUpdatesAllowed()) {
|
|
33686
|
+
throwInvalidWriteToSignalError();
|
|
33687
|
+
}
|
|
33688
|
+
// Mutate bypasses equality checks as it's by definition changing the value.
|
|
33689
|
+
mutator(node.value);
|
|
33690
|
+
signalValueChanged(node);
|
|
33691
|
+
}
|
|
33692
|
+
// Note: Using an IIFE here to ensure that the spread assignment is not considered
|
|
33693
|
+
// a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
|
|
33694
|
+
// TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
|
|
33695
|
+
const SIGNAL_NODE = /* @__PURE__ */ (() => {
|
|
33696
|
+
return {
|
|
33697
|
+
...REACTIVE_NODE,
|
|
33698
|
+
equal: defaultEquals,
|
|
33699
|
+
value: undefined,
|
|
33700
|
+
};
|
|
33701
|
+
})();
|
|
33702
|
+
function signalValueChanged(node) {
|
|
33703
|
+
node.version++;
|
|
33704
|
+
producerNotifyConsumers(node);
|
|
33705
|
+
postSignalSetFn?.();
|
|
33706
|
+
}
|
|
33707
|
+
|
|
33708
|
+
function createWatch(fn, schedule, allowSignalWrites) {
|
|
33709
|
+
const node = Object.create(WATCH_NODE);
|
|
33710
|
+
if (allowSignalWrites) {
|
|
33711
|
+
node.consumerAllowSignalWrites = true;
|
|
33712
|
+
}
|
|
33713
|
+
node.fn = fn;
|
|
33714
|
+
node.schedule = schedule;
|
|
33715
|
+
const registerOnCleanup = (cleanupFn) => {
|
|
33716
|
+
node.cleanupFn = cleanupFn;
|
|
33717
|
+
};
|
|
33718
|
+
function isWatchNodeDestroyed(node) {
|
|
33719
|
+
return node.fn === null && node.schedule === null;
|
|
33720
|
+
}
|
|
33721
|
+
function destroyWatchNode(node) {
|
|
33722
|
+
if (!isWatchNodeDestroyed(node)) {
|
|
33723
|
+
consumerDestroy(node); // disconnect watcher from the reactive graph
|
|
33724
|
+
node.cleanupFn();
|
|
33725
|
+
// nullify references to the integration functions to mark node as destroyed
|
|
33726
|
+
node.fn = null;
|
|
33727
|
+
node.schedule = null;
|
|
33728
|
+
node.cleanupFn = NOOP_CLEANUP_FN;
|
|
33729
|
+
}
|
|
33730
|
+
}
|
|
33731
|
+
const run = () => {
|
|
33732
|
+
if (node.fn === null) {
|
|
33733
|
+
// trying to run a destroyed watch is noop
|
|
33734
|
+
return;
|
|
33735
|
+
}
|
|
33736
|
+
if (isInNotificationPhase()) {
|
|
33737
|
+
throw new Error(`Schedulers cannot synchronously execute watches while scheduling.`);
|
|
33738
|
+
}
|
|
33739
|
+
node.dirty = false;
|
|
33740
|
+
if (node.hasRun && !consumerPollProducersForChange(node)) {
|
|
33741
|
+
return;
|
|
33742
|
+
}
|
|
33743
|
+
node.hasRun = true;
|
|
33744
|
+
const prevConsumer = consumerBeforeComputation(node);
|
|
33745
|
+
try {
|
|
33746
|
+
node.cleanupFn();
|
|
33747
|
+
node.cleanupFn = NOOP_CLEANUP_FN;
|
|
33748
|
+
node.fn(registerOnCleanup);
|
|
33749
|
+
}
|
|
33750
|
+
finally {
|
|
33751
|
+
consumerAfterComputation(node, prevConsumer);
|
|
33752
|
+
}
|
|
33753
|
+
};
|
|
33754
|
+
node.ref = {
|
|
33755
|
+
notify: () => consumerMarkDirty(node),
|
|
33756
|
+
run,
|
|
33757
|
+
cleanup: () => node.cleanupFn(),
|
|
33758
|
+
destroy: () => destroyWatchNode(node),
|
|
33759
|
+
[SIGNAL]: node,
|
|
33760
|
+
};
|
|
33761
|
+
return node.ref;
|
|
33762
|
+
}
|
|
33763
|
+
const NOOP_CLEANUP_FN = () => { };
|
|
33764
|
+
// Note: Using an IIFE here to ensure that the spread assignment is not considered
|
|
33765
|
+
// a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
|
|
33766
|
+
// TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
|
|
33767
|
+
const WATCH_NODE = /* @__PURE__ */ (() => {
|
|
33768
|
+
return {
|
|
33769
|
+
...REACTIVE_NODE,
|
|
33770
|
+
consumerIsAlwaysLive: true,
|
|
33771
|
+
consumerAllowSignalWrites: false,
|
|
33772
|
+
consumerMarkedDirty: (node) => {
|
|
33773
|
+
if (node.schedule !== null) {
|
|
33774
|
+
node.schedule(node.ref);
|
|
33775
|
+
}
|
|
33776
|
+
},
|
|
33777
|
+
hasRun: false,
|
|
33778
|
+
cleanupFn: NOOP_CLEANUP_FN,
|
|
33779
|
+
};
|
|
33780
|
+
})();
|
|
33781
|
+
|
|
33782
|
+
function setAlternateWeakRefImpl(impl) {
|
|
33783
|
+
// TODO: remove this function
|
|
33046
33784
|
}
|
|
33047
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationModule, [{
|
|
33048
|
-
type: NgModule
|
|
33049
|
-
}], () => [{ type: ApplicationRef }], null); })();
|
|
33050
33785
|
|
|
33051
33786
|
/**
|
|
33052
33787
|
* A collection that tracks all serialized views (`ngh` DOM annotations)
|
|
@@ -33868,166 +34603,6 @@ function ɵɵngDeclarePipe(decl) {
|
|
|
33868
34603
|
// clang-format off
|
|
33869
34604
|
// clang-format on
|
|
33870
34605
|
|
|
33871
|
-
/**
|
|
33872
|
-
* Not public API, which guarantees `EffectScheduler` only ever comes from the application root
|
|
33873
|
-
* injector.
|
|
33874
|
-
*/
|
|
33875
|
-
const APP_EFFECT_SCHEDULER = new InjectionToken('', {
|
|
33876
|
-
providedIn: 'root',
|
|
33877
|
-
factory: () => inject(EffectScheduler),
|
|
33878
|
-
});
|
|
33879
|
-
/**
|
|
33880
|
-
* A scheduler which manages the execution of effects.
|
|
33881
|
-
*/
|
|
33882
|
-
class EffectScheduler {
|
|
33883
|
-
/** @nocollapse */
|
|
33884
|
-
static { this.ɵprov = ɵɵdefineInjectable({
|
|
33885
|
-
token: EffectScheduler,
|
|
33886
|
-
providedIn: 'root',
|
|
33887
|
-
factory: () => new ZoneAwareMicrotaskScheduler(),
|
|
33888
|
-
}); }
|
|
33889
|
-
}
|
|
33890
|
-
/**
|
|
33891
|
-
* An `EffectScheduler` which is capable of queueing scheduled effects per-zone, and flushing them
|
|
33892
|
-
* as an explicit operation.
|
|
33893
|
-
*/
|
|
33894
|
-
class ZoneAwareQueueingScheduler {
|
|
33895
|
-
constructor() {
|
|
33896
|
-
this.queuedEffectCount = 0;
|
|
33897
|
-
this.queues = new Map();
|
|
33898
|
-
}
|
|
33899
|
-
scheduleEffect(handle) {
|
|
33900
|
-
const zone = handle.creationZone;
|
|
33901
|
-
if (!this.queues.has(zone)) {
|
|
33902
|
-
this.queues.set(zone, new Set());
|
|
33903
|
-
}
|
|
33904
|
-
const queue = this.queues.get(zone);
|
|
33905
|
-
if (queue.has(handle)) {
|
|
33906
|
-
return;
|
|
33907
|
-
}
|
|
33908
|
-
this.queuedEffectCount++;
|
|
33909
|
-
queue.add(handle);
|
|
33910
|
-
}
|
|
33911
|
-
/**
|
|
33912
|
-
* Run all scheduled effects.
|
|
33913
|
-
*
|
|
33914
|
-
* Execution order of effects within the same zone is guaranteed to be FIFO, but there is no
|
|
33915
|
-
* ordering guarantee between effects scheduled in different zones.
|
|
33916
|
-
*/
|
|
33917
|
-
flush() {
|
|
33918
|
-
while (this.queuedEffectCount > 0) {
|
|
33919
|
-
for (const [zone, queue] of this.queues) {
|
|
33920
|
-
// `zone` here must be defined.
|
|
33921
|
-
if (zone === null) {
|
|
33922
|
-
this.flushQueue(queue);
|
|
33923
|
-
}
|
|
33924
|
-
else {
|
|
33925
|
-
zone.run(() => this.flushQueue(queue));
|
|
33926
|
-
}
|
|
33927
|
-
}
|
|
33928
|
-
}
|
|
33929
|
-
}
|
|
33930
|
-
flushQueue(queue) {
|
|
33931
|
-
for (const handle of queue) {
|
|
33932
|
-
queue.delete(handle);
|
|
33933
|
-
this.queuedEffectCount--;
|
|
33934
|
-
// TODO: what happens if this throws an error?
|
|
33935
|
-
handle.run();
|
|
33936
|
-
}
|
|
33937
|
-
}
|
|
33938
|
-
/** @nocollapse */
|
|
33939
|
-
static { this.ɵprov = ɵɵdefineInjectable({
|
|
33940
|
-
token: ZoneAwareQueueingScheduler,
|
|
33941
|
-
providedIn: 'root',
|
|
33942
|
-
factory: () => new ZoneAwareQueueingScheduler(),
|
|
33943
|
-
}); }
|
|
33944
|
-
}
|
|
33945
|
-
/**
|
|
33946
|
-
* A wrapper around `ZoneAwareQueueingScheduler` that schedules flushing via the microtask queue
|
|
33947
|
-
* when.
|
|
33948
|
-
*/
|
|
33949
|
-
class ZoneAwareMicrotaskScheduler {
|
|
33950
|
-
constructor() {
|
|
33951
|
-
this.hasQueuedFlush = false;
|
|
33952
|
-
this.delegate = new ZoneAwareQueueingScheduler();
|
|
33953
|
-
this.flushTask = () => {
|
|
33954
|
-
// Leave `hasQueuedFlush` as `true` so we don't queue another microtask if more effects are
|
|
33955
|
-
// scheduled during flushing. The flush of the `ZoneAwareQueueingScheduler` delegate is
|
|
33956
|
-
// guaranteed to empty the queue.
|
|
33957
|
-
this.delegate.flush();
|
|
33958
|
-
this.hasQueuedFlush = false;
|
|
33959
|
-
// This is a variable initialization, not a method.
|
|
33960
|
-
// tslint:disable-next-line:semicolon
|
|
33961
|
-
};
|
|
33962
|
-
}
|
|
33963
|
-
scheduleEffect(handle) {
|
|
33964
|
-
this.delegate.scheduleEffect(handle);
|
|
33965
|
-
if (!this.hasQueuedFlush) {
|
|
33966
|
-
queueMicrotask(this.flushTask);
|
|
33967
|
-
this.hasQueuedFlush = true;
|
|
33968
|
-
}
|
|
33969
|
-
}
|
|
33970
|
-
}
|
|
33971
|
-
/**
|
|
33972
|
-
* Core reactive node for an Angular effect.
|
|
33973
|
-
*
|
|
33974
|
-
* `EffectHandle` combines the reactive graph's `Watch` base node for effects with the framework's
|
|
33975
|
-
* scheduling abstraction (`EffectScheduler`) as well as automatic cleanup via `DestroyRef` if
|
|
33976
|
-
* available/requested.
|
|
33977
|
-
*/
|
|
33978
|
-
class EffectHandle {
|
|
33979
|
-
constructor(scheduler, effectFn, creationZone, destroyRef, errorHandler, allowSignalWrites) {
|
|
33980
|
-
this.scheduler = scheduler;
|
|
33981
|
-
this.effectFn = effectFn;
|
|
33982
|
-
this.creationZone = creationZone;
|
|
33983
|
-
this.errorHandler = errorHandler;
|
|
33984
|
-
this.watcher =
|
|
33985
|
-
watch((onCleanup) => this.runEffect(onCleanup), () => this.schedule(), allowSignalWrites);
|
|
33986
|
-
this.unregisterOnDestroy = destroyRef?.onDestroy(() => this.destroy());
|
|
33987
|
-
}
|
|
33988
|
-
runEffect(onCleanup) {
|
|
33989
|
-
try {
|
|
33990
|
-
this.effectFn(onCleanup);
|
|
33991
|
-
}
|
|
33992
|
-
catch (err) {
|
|
33993
|
-
this.errorHandler?.handleError(err);
|
|
33994
|
-
}
|
|
33995
|
-
}
|
|
33996
|
-
run() {
|
|
33997
|
-
this.watcher.run();
|
|
33998
|
-
}
|
|
33999
|
-
schedule() {
|
|
34000
|
-
this.scheduler.scheduleEffect(this);
|
|
34001
|
-
}
|
|
34002
|
-
notify() {
|
|
34003
|
-
this.watcher.notify();
|
|
34004
|
-
}
|
|
34005
|
-
destroy() {
|
|
34006
|
-
this.watcher.destroy();
|
|
34007
|
-
this.unregisterOnDestroy?.();
|
|
34008
|
-
// Note: if the effect is currently scheduled, it's not un-scheduled, and so the scheduler will
|
|
34009
|
-
// retain a reference to it. Attempting to execute it will be a no-op.
|
|
34010
|
-
}
|
|
34011
|
-
}
|
|
34012
|
-
/**
|
|
34013
|
-
* Create a global `Effect` for the given reactive function.
|
|
34014
|
-
*
|
|
34015
|
-
* @developerPreview
|
|
34016
|
-
*/
|
|
34017
|
-
function effect(effectFn, options) {
|
|
34018
|
-
!options?.injector && assertInInjectionContext(effect);
|
|
34019
|
-
const injector = options?.injector ?? inject(Injector);
|
|
34020
|
-
const errorHandler = injector.get(ErrorHandler, null, { optional: true });
|
|
34021
|
-
const destroyRef = options?.manualCleanup !== true ? injector.get(DestroyRef) : null;
|
|
34022
|
-
const handle = new EffectHandle(injector.get(APP_EFFECT_SCHEDULER), effectFn, (typeof Zone === 'undefined') ? null : Zone.current, destroyRef, errorHandler, options?.allowSignalWrites ?? false);
|
|
34023
|
-
// Effects start dirty.
|
|
34024
|
-
handle.notify();
|
|
34025
|
-
return handle;
|
|
34026
|
-
}
|
|
34027
|
-
|
|
34028
|
-
// clang-format off
|
|
34029
|
-
// clang-format on
|
|
34030
|
-
|
|
34031
34606
|
// This file exists to allow the set of reactivity exports to be modified in g3, as these APIs are
|
|
34032
34607
|
|
|
34033
34608
|
/**
|
|
@@ -34215,5 +34790,5 @@ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
|
34215
34790
|
* Generated bundle index. Do not edit.
|
|
34216
34791
|
*/
|
|
34217
34792
|
|
|
34218
|
-
export { ANIMATION_MODULE_TYPE, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, AfterRenderPhase, ApplicationInitStatus, ApplicationModule, ApplicationRef, Attribute, COMPILER_OPTIONS, CSP_NONCE, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Compiler, CompilerFactory, Component, ComponentFactory$1 as ComponentFactory, ComponentFactoryResolver$1 as ComponentFactoryResolver, ComponentRef$1 as ComponentRef, ContentChild, ContentChildren, DEFAULT_CURRENCY_CODE, DebugElement, DebugEventListener, DebugNode, DefaultIterableDiffer, DestroyRef, Directive, ENVIRONMENT_INITIALIZER, ElementRef, EmbeddedViewRef, EnvironmentInjector, ErrorHandler, EventEmitter, Host, HostBinding, HostListener, INJECTOR, Inject, InjectFlags, Injectable, InjectionToken, Injector, Input, IterableDiffers, KeyValueDiffers, LOCALE_ID, MissingTranslationStrategy, ModuleWithComponentFactories, NO_ERRORS_SCHEMA, NgModule, NgModuleFactory$1 as NgModuleFactory, NgModuleRef$1 as NgModuleRef, NgProbeToken, NgZone, Optional, Output, PACKAGE_ROOT_URL, PLATFORM_ID, PLATFORM_INITIALIZER, Pipe, PlatformRef, Query, QueryList, Renderer2, RendererFactory2, RendererStyleFlags2, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, TransferState, Type, VERSION, Version, ViewChild, ViewChildren, ViewContainerRef, ViewEncapsulation$1 as ViewEncapsulation, ViewRef, afterNextRender, afterRender, asNativeElements, assertInInjectionContext, assertPlatform, booleanAttribute, computed, createComponent, createEnvironmentInjector, createNgModule, createNgModuleRef, createPlatform, createPlatformFactory, defineInjectable, destroyPlatform, effect, enableProdMode, forwardRef, getDebugNode, getModuleFactory, getNgModuleById, getPlatform, importProvidersFrom, inject, isDevMode, isSignal, isStandalone, makeEnvironmentProviders, makeStateKey, mergeApplicationConfig, numberAttribute, platformCore, provideZoneChangeDetection, reflectComponentType, resolveForwardRef, runInInjectionContext, setTestabilityGetter, signal, untracked, ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS, AfterRenderEventManager as ɵAfterRenderEventManager, CONTAINER_HEADER_OFFSET as ɵCONTAINER_HEADER_OFFSET, ComponentFactory$1 as ɵComponentFactory, Console as ɵConsole, DEFAULT_LOCALE_ID as ɵDEFAULT_LOCALE_ID, DEFER_BLOCK_CONFIG as ɵDEFER_BLOCK_CONFIG, DEFER_BLOCK_DEPENDENCY_INTERCEPTOR as ɵDEFER_BLOCK_DEPENDENCY_INTERCEPTOR, DeferBlockBehavior as ɵDeferBlockBehavior, DeferBlockState as ɵDeferBlockState, ENABLED_SSR_FEATURES as ɵENABLED_SSR_FEATURES, EffectScheduler as ɵEffectScheduler, INJECTOR_SCOPE as ɵINJECTOR_SCOPE, IS_HYDRATION_DOM_REUSE_ENABLED as ɵIS_HYDRATION_DOM_REUSE_ENABLED, InitialRenderPendingTasks as ɵInitialRenderPendingTasks, LContext as ɵLContext, LifecycleHooksFeature as ɵLifecycleHooksFeature, LocaleDataIndex as ɵLocaleDataIndex, NG_COMP_DEF as ɵNG_COMP_DEF, NG_DIR_DEF as ɵNG_DIR_DEF, NG_ELEMENT_ID as ɵNG_ELEMENT_ID, NG_INJ_DEF as ɵNG_INJ_DEF, NG_MOD_DEF as ɵNG_MOD_DEF, NG_PIPE_DEF as ɵNG_PIPE_DEF, NG_PROV_DEF as ɵNG_PROV_DEF, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, NO_CHANGE as ɵNO_CHANGE, NgModuleFactory as ɵNgModuleFactory, NoopNgZone as ɵNoopNgZone, ReflectionCapabilities as ɵReflectionCapabilities, ComponentFactory as ɵRender3ComponentFactory, ComponentRef as ɵRender3ComponentRef, NgModuleRef as ɵRender3NgModuleRef, RuntimeError as ɵRuntimeError, SSR_CONTENT_INTEGRITY_MARKER as ɵSSR_CONTENT_INTEGRITY_MARKER, TESTABILITY as ɵTESTABILITY, TESTABILITY_GETTER as ɵTESTABILITY_GETTER, USE_RUNTIME_DEPS_TRACKER_FOR_JIT as ɵUSE_RUNTIME_DEPS_TRACKER_FOR_JIT, ViewRef$1 as ɵViewRef, XSS_SECURITY_URL as ɵXSS_SECURITY_URL, ZoneAwareQueueingScheduler as ɵZoneAwareQueueingScheduler, _sanitizeHtml as ɵ_sanitizeHtml, _sanitizeUrl as ɵ_sanitizeUrl, allowSanitizationBypassAndThrow as ɵallowSanitizationBypassAndThrow, annotateForHydration as ɵannotateForHydration, bypassSanitizationTrustHtml as ɵbypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl as ɵbypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript as ɵbypassSanitizationTrustScript, bypassSanitizationTrustStyle as ɵbypassSanitizationTrustStyle, bypassSanitizationTrustUrl as ɵbypassSanitizationTrustUrl, clearResolutionOfComponentResourcesQueue as ɵclearResolutionOfComponentResourcesQueue, compileComponent as ɵcompileComponent, compileDirective as ɵcompileDirective, compileNgModule as ɵcompileNgModule, compileNgModuleDefs as ɵcompileNgModuleDefs, compileNgModuleFactory as ɵcompileNgModuleFactory, compilePipe as ɵcompilePipe, convertToBitFlags as ɵconvertToBitFlags, createInjector as ɵcreateInjector, defaultIterableDiffers as ɵdefaultIterableDiffers, defaultKeyValueDiffers as ɵdefaultKeyValueDiffers, depsTracker as ɵdepsTracker, detectChanges as ɵdetectChanges, devModeEqual as ɵdevModeEqual, findLocaleData as ɵfindLocaleData, flushModuleScopingQueueAsMuchAsPossible as ɵflushModuleScopingQueueAsMuchAsPossible, formatRuntimeError as ɵformatRuntimeError, generateStandaloneInDeclarationsError as ɵgenerateStandaloneInDeclarationsError, getAsyncClassMetadata as ɵgetAsyncClassMetadata, getDebugNode as ɵgetDebugNode, getDeferBlocks as ɵgetDeferBlocks, getDirectives as ɵgetDirectives, getHostElement as ɵgetHostElement, getInjectableDef as ɵgetInjectableDef, getLContext as ɵgetLContext, getLocaleCurrencyCode as ɵgetLocaleCurrencyCode, getLocalePluralCase as ɵgetLocalePluralCase, getSanitizationBypassType as ɵgetSanitizationBypassType, ɵgetUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode, _global as ɵglobal, injectChangeDetectorRef as ɵinjectChangeDetectorRef, internalCreateApplication as ɵinternalCreateApplication, isBoundToModule as ɵisBoundToModule, isComponentDefPendingResolution as ɵisComponentDefPendingResolution, isEnvironmentProviders as ɵisEnvironmentProviders, isInjectable as ɵisInjectable, isNgModule as ɵisNgModule, isPromise as ɵisPromise, isSubscribable as ɵisSubscribable, noSideEffects as ɵnoSideEffects, patchComponentDefWithScope as ɵpatchComponentDefWithScope, publishDefaultGlobalUtils$1 as ɵpublishDefaultGlobalUtils, publishGlobalUtil as ɵpublishGlobalUtil, registerLocaleData as ɵregisterLocaleData, renderDeferBlockState as ɵrenderDeferBlockState, resetCompiledComponents as ɵresetCompiledComponents, resetJitOptions as ɵresetJitOptions, resolveComponentResources as ɵresolveComponentResources, restoreComponentResolutionQueue as ɵrestoreComponentResolutionQueue, setAllowDuplicateNgModuleIdsForTest as ɵsetAllowDuplicateNgModuleIdsForTest, setAlternateWeakRefImpl as ɵsetAlternateWeakRefImpl, setClassMetadata as ɵsetClassMetadata, setClassMetadataAsync as ɵsetClassMetadataAsync, setCurrentInjector as ɵsetCurrentInjector, setDocument as ɵsetDocument, setInjectorProfilerContext as ɵsetInjectorProfilerContext, setLocaleId as ɵsetLocaleId, ɵsetUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode, store as ɵstore, stringify as ɵstringify, transitiveScopesFor as ɵtransitiveScopesFor, triggerResourceLoading as ɵtriggerResourceLoading, unregisterAllLocaleData as ɵunregisterLocaleData, unwrapSafeValue as ɵunwrapSafeValue, whenStable as ɵwhenStable, withDomHydration as ɵwithDomHydration, ɵɵCopyDefinitionFeature, FactoryTarget as ɵɵFactoryTarget, ɵɵHostDirectivesFeature, ɵɵInheritDefinitionFeature, ɵɵInputTransformsFeature, ɵɵNgOnChangesFeature, ɵɵProvidersFeature, ɵɵStandaloneFeature, ɵɵadvance, ɵɵattribute, ɵɵattributeInterpolate1, ɵɵattributeInterpolate2, ɵɵattributeInterpolate3, ɵɵattributeInterpolate4, ɵɵattributeInterpolate5, ɵɵattributeInterpolate6, ɵɵattributeInterpolate7, ɵɵattributeInterpolate8, ɵɵattributeInterpolateV, ɵɵclassMap, ɵɵclassMapInterpolate1, ɵɵclassMapInterpolate2, ɵɵclassMapInterpolate3, ɵɵclassMapInterpolate4, ɵɵclassMapInterpolate5, ɵɵclassMapInterpolate6, ɵɵclassMapInterpolate7, ɵɵclassMapInterpolate8, ɵɵclassMapInterpolateV, ɵɵclassProp, ɵɵcomponentInstance, ɵɵconditional, ɵɵcontentQuery, ɵɵdefer, ɵɵdeferOnHover, ɵɵdeferOnIdle, ɵɵdeferOnImmediate, ɵɵdeferOnInteraction, ɵɵdeferOnTimer, ɵɵdeferOnViewport, ɵɵdeferPrefetchOnHover, ɵɵdeferPrefetchOnIdle, ɵɵdeferPrefetchOnImmediate, ɵɵdeferPrefetchOnInteraction, ɵɵdeferPrefetchOnTimer, ɵɵdeferPrefetchOnViewport, ɵɵdeferPrefetchWhen, ɵɵdeferWhen, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵdefineNgModule, ɵɵdefinePipe, ɵɵdirectiveInject, ɵɵdisableBindings, ɵɵelement, ɵɵelementContainer, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementStart, ɵɵenableBindings, ɵɵgetComponentDepsFactory, ɵɵgetCurrentView, ɵɵgetInheritedFactory, ɵɵhostProperty, ɵɵi18n, ɵɵi18nApply, ɵɵi18nAttributes, ɵɵi18nEnd, ɵɵi18nExp, ɵɵi18nPostprocess, ɵɵi18nStart, ɵɵinject, ɵɵinjectAttribute, ɵɵinvalidFactory, ɵɵinvalidFactoryDep, ɵɵlistener, ɵɵloadQuery, ɵɵnamespaceHTML, ɵɵnamespaceMathML, ɵɵnamespaceSVG, ɵɵnextContext, ɵɵngDeclareClassMetadata, ɵɵngDeclareComponent, ɵɵngDeclareDirective, ɵɵngDeclareFactory, ɵɵngDeclareInjectable, ɵɵngDeclareInjector, ɵɵngDeclareNgModule, ɵɵngDeclarePipe, ɵɵpipe, ɵɵpipeBind1, ɵɵpipeBind2, ɵɵpipeBind3, ɵɵpipeBind4, ɵɵpipeBindV, ɵɵprojection, ɵɵprojectionDef, ɵɵproperty, ɵɵpropertyInterpolate, ɵɵpropertyInterpolate1, ɵɵpropertyInterpolate2, ɵɵpropertyInterpolate3, ɵɵpropertyInterpolate4, ɵɵpropertyInterpolate5, ɵɵpropertyInterpolate6, ɵɵpropertyInterpolate7, ɵɵpropertyInterpolate8, ɵɵpropertyInterpolateV, ɵɵpureFunction0, ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunction5, ɵɵpureFunction6, ɵɵpureFunction7, ɵɵpureFunction8, ɵɵpureFunctionV, ɵɵqueryRefresh, ɵɵreference, registerNgModuleType as ɵɵregisterNgModuleType, ɵɵrepeater, ɵɵrepeaterCreate, ɵɵrepeaterTrackByIdentity, ɵɵrepeaterTrackByIndex, ɵɵresetView, ɵɵresolveBody, ɵɵresolveDocument, ɵɵresolveWindow, ɵɵrestoreView, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl, ɵɵsetComponentScope, ɵɵsetNgModuleScope, ɵɵstyleMap, ɵɵstyleMapInterpolate1, ɵɵstyleMapInterpolate2, ɵɵstyleMapInterpolate3, ɵɵstyleMapInterpolate4, ɵɵstyleMapInterpolate5, ɵɵstyleMapInterpolate6, ɵɵstyleMapInterpolate7, ɵɵstyleMapInterpolate8, ɵɵstyleMapInterpolateV, ɵɵstyleProp, ɵɵstylePropInterpolate1, ɵɵstylePropInterpolate2, ɵɵstylePropInterpolate3, ɵɵstylePropInterpolate4, ɵɵstylePropInterpolate5, ɵɵstylePropInterpolate6, ɵɵstylePropInterpolate7, ɵɵstylePropInterpolate8, ɵɵstylePropInterpolateV, ɵɵsyntheticHostListener, ɵɵsyntheticHostProperty, ɵɵtemplate, ɵɵtemplateRefExtractor, ɵɵtext, ɵɵtextInterpolate, ɵɵtextInterpolate1, ɵɵtextInterpolate2, ɵɵtextInterpolate3, ɵɵtextInterpolate4, ɵɵtextInterpolate5, ɵɵtextInterpolate6, ɵɵtextInterpolate7, ɵɵtextInterpolate8, ɵɵtextInterpolateV, ɵɵtrustConstantHtml, ɵɵtrustConstantResourceUrl, ɵɵvalidateIframeAttribute, ɵɵviewQuery };
|
|
34793
|
+
export { ANIMATION_MODULE_TYPE, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, AfterRenderPhase, ApplicationInitStatus, ApplicationModule, ApplicationRef, Attribute, COMPILER_OPTIONS, CSP_NONCE, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Compiler, CompilerFactory, Component, ComponentFactory$1 as ComponentFactory, ComponentFactoryResolver$1 as ComponentFactoryResolver, ComponentRef$1 as ComponentRef, ContentChild, ContentChildren, DEFAULT_CURRENCY_CODE, DebugElement, DebugEventListener, DebugNode, DefaultIterableDiffer, DestroyRef, Directive, ENVIRONMENT_INITIALIZER, ElementRef, EmbeddedViewRef, EnvironmentInjector, ErrorHandler, EventEmitter, Host, HostBinding, HostListener, INJECTOR, Inject, InjectFlags, Injectable, InjectionToken, Injector, Input, IterableDiffers, KeyValueDiffers, LOCALE_ID, MissingTranslationStrategy, ModuleWithComponentFactories, NO_ERRORS_SCHEMA, NgModule, NgModuleFactory$1 as NgModuleFactory, NgModuleRef$1 as NgModuleRef, NgProbeToken, NgZone, Optional, Output, PACKAGE_ROOT_URL, PLATFORM_ID, PLATFORM_INITIALIZER, Pipe, PlatformRef, Query, QueryList, Renderer2, RendererFactory2, RendererStyleFlags2, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, TransferState, Type, VERSION, Version, ViewChild, ViewChildren, ViewContainerRef, ViewEncapsulation$1 as ViewEncapsulation, ViewRef, afterNextRender, afterRender, asNativeElements, assertInInjectionContext, assertNotInReactiveContext, assertPlatform, booleanAttribute, computed, createComponent, createEnvironmentInjector, createNgModule, createNgModuleRef, createPlatform, createPlatformFactory, defineInjectable, destroyPlatform, effect, enableProdMode, forwardRef, getDebugNode, getModuleFactory, getNgModuleById, getPlatform, importProvidersFrom, inject, isDevMode, isSignal, isStandalone, makeEnvironmentProviders, makeStateKey, mergeApplicationConfig, numberAttribute, platformCore, provideZoneChangeDetection, reflectComponentType, resolveForwardRef, runInInjectionContext, setTestabilityGetter, signal, untracked, ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS, AfterRenderEventManager as ɵAfterRenderEventManager, CONTAINER_HEADER_OFFSET as ɵCONTAINER_HEADER_OFFSET, ComponentFactory$1 as ɵComponentFactory, Console as ɵConsole, DEFAULT_LOCALE_ID as ɵDEFAULT_LOCALE_ID, DEFER_BLOCK_CONFIG as ɵDEFER_BLOCK_CONFIG, DEFER_BLOCK_DEPENDENCY_INTERCEPTOR as ɵDEFER_BLOCK_DEPENDENCY_INTERCEPTOR, DeferBlockBehavior as ɵDeferBlockBehavior, DeferBlockState as ɵDeferBlockState, ENABLED_SSR_FEATURES as ɵENABLED_SSR_FEATURES, EffectScheduler as ɵEffectScheduler, IMAGE_CONFIG as ɵIMAGE_CONFIG, IMAGE_CONFIG_DEFAULTS as ɵIMAGE_CONFIG_DEFAULTS, INJECTOR_SCOPE as ɵINJECTOR_SCOPE, IS_HYDRATION_DOM_REUSE_ENABLED as ɵIS_HYDRATION_DOM_REUSE_ENABLED, InitialRenderPendingTasks as ɵInitialRenderPendingTasks, LContext as ɵLContext, LifecycleHooksFeature as ɵLifecycleHooksFeature, LocaleDataIndex as ɵLocaleDataIndex, NG_COMP_DEF as ɵNG_COMP_DEF, NG_DIR_DEF as ɵNG_DIR_DEF, NG_ELEMENT_ID as ɵNG_ELEMENT_ID, NG_INJ_DEF as ɵNG_INJ_DEF, NG_MOD_DEF as ɵNG_MOD_DEF, NG_PIPE_DEF as ɵNG_PIPE_DEF, NG_PROV_DEF as ɵNG_PROV_DEF, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, NO_CHANGE as ɵNO_CHANGE, NgModuleFactory as ɵNgModuleFactory, NoopNgZone as ɵNoopNgZone, ReflectionCapabilities as ɵReflectionCapabilities, ComponentFactory as ɵRender3ComponentFactory, ComponentRef as ɵRender3ComponentRef, NgModuleRef as ɵRender3NgModuleRef, RuntimeError as ɵRuntimeError, SSR_CONTENT_INTEGRITY_MARKER as ɵSSR_CONTENT_INTEGRITY_MARKER, TESTABILITY as ɵTESTABILITY, TESTABILITY_GETTER as ɵTESTABILITY_GETTER, USE_RUNTIME_DEPS_TRACKER_FOR_JIT as ɵUSE_RUNTIME_DEPS_TRACKER_FOR_JIT, ViewRef$1 as ɵViewRef, XSS_SECURITY_URL as ɵXSS_SECURITY_URL, ZoneAwareQueueingScheduler as ɵZoneAwareQueueingScheduler, _sanitizeHtml as ɵ_sanitizeHtml, _sanitizeUrl as ɵ_sanitizeUrl, allowSanitizationBypassAndThrow as ɵallowSanitizationBypassAndThrow, annotateForHydration as ɵannotateForHydration, bypassSanitizationTrustHtml as ɵbypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl as ɵbypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript as ɵbypassSanitizationTrustScript, bypassSanitizationTrustStyle as ɵbypassSanitizationTrustStyle, bypassSanitizationTrustUrl as ɵbypassSanitizationTrustUrl, clearResolutionOfComponentResourcesQueue as ɵclearResolutionOfComponentResourcesQueue, compileComponent as ɵcompileComponent, compileDirective as ɵcompileDirective, compileNgModule as ɵcompileNgModule, compileNgModuleDefs as ɵcompileNgModuleDefs, compileNgModuleFactory as ɵcompileNgModuleFactory, compilePipe as ɵcompilePipe, convertToBitFlags as ɵconvertToBitFlags, createInjector as ɵcreateInjector, defaultIterableDiffers as ɵdefaultIterableDiffers, defaultKeyValueDiffers as ɵdefaultKeyValueDiffers, depsTracker as ɵdepsTracker, detectChanges as ɵdetectChanges, devModeEqual as ɵdevModeEqual, findLocaleData as ɵfindLocaleData, flushModuleScopingQueueAsMuchAsPossible as ɵflushModuleScopingQueueAsMuchAsPossible, formatRuntimeError as ɵformatRuntimeError, generateStandaloneInDeclarationsError as ɵgenerateStandaloneInDeclarationsError, getAsyncClassMetadata as ɵgetAsyncClassMetadata, getDebugNode as ɵgetDebugNode, getDeferBlocks as ɵgetDeferBlocks, getDirectives as ɵgetDirectives, getHostElement as ɵgetHostElement, getInjectableDef as ɵgetInjectableDef, getLContext as ɵgetLContext, getLocaleCurrencyCode as ɵgetLocaleCurrencyCode, getLocalePluralCase as ɵgetLocalePluralCase, getSanitizationBypassType as ɵgetSanitizationBypassType, ɵgetUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode, _global as ɵglobal, injectChangeDetectorRef as ɵinjectChangeDetectorRef, internalCreateApplication as ɵinternalCreateApplication, isBoundToModule as ɵisBoundToModule, isComponentDefPendingResolution as ɵisComponentDefPendingResolution, isEnvironmentProviders as ɵisEnvironmentProviders, isInjectable as ɵisInjectable, isNgModule as ɵisNgModule, isPromise as ɵisPromise, isSubscribable as ɵisSubscribable, noSideEffects as ɵnoSideEffects, patchComponentDefWithScope as ɵpatchComponentDefWithScope, publishDefaultGlobalUtils$1 as ɵpublishDefaultGlobalUtils, publishGlobalUtil as ɵpublishGlobalUtil, registerLocaleData as ɵregisterLocaleData, renderDeferBlockState as ɵrenderDeferBlockState, resetCompiledComponents as ɵresetCompiledComponents, resetJitOptions as ɵresetJitOptions, resolveComponentResources as ɵresolveComponentResources, restoreComponentResolutionQueue as ɵrestoreComponentResolutionQueue, setAllowDuplicateNgModuleIdsForTest as ɵsetAllowDuplicateNgModuleIdsForTest, setAlternateWeakRefImpl as ɵsetAlternateWeakRefImpl, ɵsetClassDebugInfo, setClassMetadata as ɵsetClassMetadata, setClassMetadataAsync as ɵsetClassMetadataAsync, setCurrentInjector as ɵsetCurrentInjector, setDocument as ɵsetDocument, setInjectorProfilerContext as ɵsetInjectorProfilerContext, setLocaleId as ɵsetLocaleId, ɵsetUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode, store as ɵstore, stringify as ɵstringify, transitiveScopesFor as ɵtransitiveScopesFor, triggerResourceLoading as ɵtriggerResourceLoading, truncateMiddle as ɵtruncateMiddle, unregisterAllLocaleData as ɵunregisterLocaleData, unwrapSafeValue as ɵunwrapSafeValue, whenStable as ɵwhenStable, withDomHydration as ɵwithDomHydration, ɵɵCopyDefinitionFeature, FactoryTarget as ɵɵFactoryTarget, ɵɵHostDirectivesFeature, ɵɵInheritDefinitionFeature, ɵɵInputTransformsFeature, ɵɵNgOnChangesFeature, ɵɵProvidersFeature, ɵɵStandaloneFeature, ɵɵadvance, ɵɵattribute, ɵɵattributeInterpolate1, ɵɵattributeInterpolate2, ɵɵattributeInterpolate3, ɵɵattributeInterpolate4, ɵɵattributeInterpolate5, ɵɵattributeInterpolate6, ɵɵattributeInterpolate7, ɵɵattributeInterpolate8, ɵɵattributeInterpolateV, ɵɵclassMap, ɵɵclassMapInterpolate1, ɵɵclassMapInterpolate2, ɵɵclassMapInterpolate3, ɵɵclassMapInterpolate4, ɵɵclassMapInterpolate5, ɵɵclassMapInterpolate6, ɵɵclassMapInterpolate7, ɵɵclassMapInterpolate8, ɵɵclassMapInterpolateV, ɵɵclassProp, ɵɵcomponentInstance, ɵɵconditional, ɵɵcontentQuery, ɵɵdefer, ɵɵdeferEnableTimerScheduling, ɵɵdeferOnHover, ɵɵdeferOnIdle, ɵɵdeferOnImmediate, ɵɵdeferOnInteraction, ɵɵdeferOnTimer, ɵɵdeferOnViewport, ɵɵdeferPrefetchOnHover, ɵɵdeferPrefetchOnIdle, ɵɵdeferPrefetchOnImmediate, ɵɵdeferPrefetchOnInteraction, ɵɵdeferPrefetchOnTimer, ɵɵdeferPrefetchOnViewport, ɵɵdeferPrefetchWhen, ɵɵdeferWhen, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵdefineNgModule, ɵɵdefinePipe, ɵɵdirectiveInject, ɵɵdisableBindings, ɵɵelement, ɵɵelementContainer, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementStart, ɵɵenableBindings, ɵɵgetComponentDepsFactory, ɵɵgetCurrentView, ɵɵgetInheritedFactory, ɵɵhostProperty, ɵɵi18n, ɵɵi18nApply, ɵɵi18nAttributes, ɵɵi18nEnd, ɵɵi18nExp, ɵɵi18nPostprocess, ɵɵi18nStart, ɵɵinject, ɵɵinjectAttribute, ɵɵinvalidFactory, ɵɵinvalidFactoryDep, ɵɵlistener, ɵɵloadQuery, ɵɵnamespaceHTML, ɵɵnamespaceMathML, ɵɵnamespaceSVG, ɵɵnextContext, ɵɵngDeclareClassMetadata, ɵɵngDeclareComponent, ɵɵngDeclareDirective, ɵɵngDeclareFactory, ɵɵngDeclareInjectable, ɵɵngDeclareInjector, ɵɵngDeclareNgModule, ɵɵngDeclarePipe, ɵɵpipe, ɵɵpipeBind1, ɵɵpipeBind2, ɵɵpipeBind3, ɵɵpipeBind4, ɵɵpipeBindV, ɵɵprojection, ɵɵprojectionDef, ɵɵproperty, ɵɵpropertyInterpolate, ɵɵpropertyInterpolate1, ɵɵpropertyInterpolate2, ɵɵpropertyInterpolate3, ɵɵpropertyInterpolate4, ɵɵpropertyInterpolate5, ɵɵpropertyInterpolate6, ɵɵpropertyInterpolate7, ɵɵpropertyInterpolate8, ɵɵpropertyInterpolateV, ɵɵpureFunction0, ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunction5, ɵɵpureFunction6, ɵɵpureFunction7, ɵɵpureFunction8, ɵɵpureFunctionV, ɵɵqueryRefresh, ɵɵreference, registerNgModuleType as ɵɵregisterNgModuleType, ɵɵrepeater, ɵɵrepeaterCreate, ɵɵrepeaterTrackByIdentity, ɵɵrepeaterTrackByIndex, ɵɵresetView, ɵɵresolveBody, ɵɵresolveDocument, ɵɵresolveWindow, ɵɵrestoreView, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl, ɵɵsetComponentScope, ɵɵsetNgModuleScope, ɵɵstyleMap, ɵɵstyleMapInterpolate1, ɵɵstyleMapInterpolate2, ɵɵstyleMapInterpolate3, ɵɵstyleMapInterpolate4, ɵɵstyleMapInterpolate5, ɵɵstyleMapInterpolate6, ɵɵstyleMapInterpolate7, ɵɵstyleMapInterpolate8, ɵɵstyleMapInterpolateV, ɵɵstyleProp, ɵɵstylePropInterpolate1, ɵɵstylePropInterpolate2, ɵɵstylePropInterpolate3, ɵɵstylePropInterpolate4, ɵɵstylePropInterpolate5, ɵɵstylePropInterpolate6, ɵɵstylePropInterpolate7, ɵɵstylePropInterpolate8, ɵɵstylePropInterpolateV, ɵɵsyntheticHostListener, ɵɵsyntheticHostProperty, ɵɵtemplate, ɵɵtemplateRefExtractor, ɵɵtext, ɵɵtextInterpolate, ɵɵtextInterpolate1, ɵɵtextInterpolate2, ɵɵtextInterpolate3, ɵɵtextInterpolate4, ɵɵtextInterpolate5, ɵɵtextInterpolate6, ɵɵtextInterpolate7, ɵɵtextInterpolate8, ɵɵtextInterpolateV, ɵɵtrustConstantHtml, ɵɵtrustConstantResourceUrl, ɵɵvalidateIframeAttribute, ɵɵviewQuery };
|
|
34219
34794
|
//# sourceMappingURL=core.mjs.map
|