@angular/core 16.0.0-next.5 → 16.0.0-next.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/rxjs-interop/index.mjs +9 -0
- package/esm2022/rxjs-interop/public_api.mjs +15 -0
- package/esm2022/rxjs-interop/rxjs-interop.mjs +5 -0
- package/esm2022/rxjs-interop/src/from_observable.mjs +46 -0
- package/esm2022/rxjs-interop/src/from_signal.mjs +36 -0
- package/esm2022/rxjs-interop/src/index.mjs +11 -0
- package/esm2022/rxjs-interop/src/take_until_destroyed.mjs +33 -0
- package/esm2022/src/application_ref.mjs +78 -17
- package/esm2022/src/core.mjs +2 -2
- package/esm2022/src/core_private_export.mjs +2 -2
- package/esm2022/src/core_reactivity_export_internal.mjs +1 -1
- package/esm2022/src/errors.mjs +3 -2
- package/esm2022/src/hydration/api.mjs +35 -2
- package/esm2022/src/hydration/cleanup.mjs +11 -19
- package/esm2022/src/linker/component_factory.mjs +1 -1
- package/esm2022/src/linker/template_ref.mjs +2 -2
- package/esm2022/src/linker/view_container_ref.mjs +2 -2
- package/esm2022/src/linker/view_ref.mjs +2 -2
- package/esm2022/src/render3/component_ref.mjs +13 -6
- package/esm2022/src/render3/instructions/element.mjs +2 -1
- package/esm2022/src/render3/instructions/element_container.mjs +1 -2
- package/esm2022/src/render3/instructions/shared.mjs +13 -10
- package/esm2022/src/render3/interfaces/view.mjs +16 -17
- package/esm2022/src/render3/ng_module_ref.mjs +9 -7
- package/esm2022/src/render3/reactive_lview_consumer.mjs +2 -1
- package/esm2022/src/render3/reactivity/effect.mjs +55 -45
- package/esm2022/src/sanitization/sanitization.mjs +3 -3
- package/esm2022/src/signals/index.mjs +2 -1
- package/esm2022/src/signals/src/api.mjs +1 -2
- package/esm2022/src/signals/src/computed.mjs +2 -1
- package/esm2022/src/signals/src/errors.mjs +18 -0
- package/esm2022/src/signals/src/graph.mjs +32 -8
- package/esm2022/src/signals/src/signal.mjs +12 -1
- package/esm2022/src/signals/src/watch.mjs +3 -2
- package/esm2022/src/util/ng_dev_mode.mjs +2 -1
- package/esm2022/src/version.mjs +1 -1
- package/esm2022/testing/src/logger.mjs +3 -3
- package/esm2022/testing/src/ng_zone_mock.mjs +3 -3
- package/esm2022/testing/src/test_bed_compiler.mjs +3 -4
- package/fesm2022/core.mjs +1077 -926
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/rxjs-interop.mjs +104 -0
- package/fesm2022/rxjs-interop.mjs.map +1 -0
- package/fesm2022/testing.mjs +524 -69
- package/fesm2022/testing.mjs.map +1 -1
- package/index.d.ts +142 -41
- package/package.json +7 -1
- package/rxjs-interop/index.d.ts +95 -0
- package/schematics/migrations/guard-and-resolve-interfaces/bundle.js +13 -13
- package/schematics/migrations/remove-module-id/bundle.js +14 -14
- package/schematics/ng-generate/standalone-migration/bundle.js +319 -319
- package/schematics/ng-generate/standalone-migration/bundle.js.map +1 -1
- package/testing/index.d.ts +1 -1
package/fesm2022/testing.mjs
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v16.0.0-next.
|
|
2
|
+
* @license Angular v16.0.0-next.6
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { getDebugNode, RendererFactory2 as RendererFactory2$1, InjectionToken as InjectionToken$1, ɵstringify, ɵReflectionCapabilities, Directive, Component, Pipe, NgModule, ɵgetInjectableDef, resolveForwardRef as resolveForwardRef$1, ɵNG_COMP_DEF, ɵRender3NgModuleRef, ApplicationInitStatus, LOCALE_ID as LOCALE_ID$1, ɵDEFAULT_LOCALE_ID, ɵsetLocaleId, ɵRender3ComponentFactory, ɵcompileComponent, ɵNG_DIR_DEF, ɵcompileDirective, ɵNG_PIPE_DEF, ɵcompilePipe, ɵNG_MOD_DEF, ɵtransitiveScopesFor, ɵpatchComponentDefWithScope, ɵNG_INJ_DEF, ɵcompileNgModuleDefs,
|
|
7
|
+
import { getDebugNode, RendererFactory2 as RendererFactory2$1, InjectionToken as InjectionToken$1, ɵstringify, ɵReflectionCapabilities, Directive, Component, Pipe, NgModule, ɵgetInjectableDef, resolveForwardRef as resolveForwardRef$1, ɵNG_COMP_DEF, ɵRender3NgModuleRef, ApplicationInitStatus, LOCALE_ID as LOCALE_ID$1, ɵDEFAULT_LOCALE_ID, ɵsetLocaleId, ɵRender3ComponentFactory, ɵcompileComponent, ɵNG_DIR_DEF, ɵcompileDirective, ɵNG_PIPE_DEF, ɵcompilePipe, ɵNG_MOD_DEF, ɵtransitiveScopesFor, ɵpatchComponentDefWithScope, ɵNG_INJ_DEF, ɵcompileNgModuleDefs, provideZoneChangeDetection, Compiler, COMPILER_OPTIONS, ɵNgModuleFactory, ɵisEnvironmentProviders, ModuleWithComponentFactories, ɵconvertToBitFlags, Injector as Injector$1, InjectFlags as InjectFlags$1, ɵsetAllowDuplicateNgModuleIdsForTest, ɵresetCompiledComponents, ɵsetUnknownElementStrictMode as ɵsetUnknownElementStrictMode$1, ɵsetUnknownPropertyStrictMode as ɵsetUnknownPropertyStrictMode$1, ɵgetUnknownElementStrictMode as ɵgetUnknownElementStrictMode$1, ɵgetUnknownPropertyStrictMode as ɵgetUnknownPropertyStrictMode$1, EnvironmentInjector as EnvironmentInjector$1, NgZone, ɵflushModuleScopingQueueAsMuchAsPossible } from '@angular/core';
|
|
8
8
|
import { ResourceLoader } from '@angular/compiler';
|
|
9
9
|
import { Subject, Subscription } from 'rxjs';
|
|
10
|
-
import { first } from 'rxjs/operators';
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* Wraps a test function in an asynchronous test zone. The test will automatically
|
|
@@ -838,7 +837,8 @@ const XSS_SECURITY_URL = 'https://g.co/ng/security#xss';
|
|
|
838
837
|
*
|
|
839
838
|
* Note: the `message` argument contains a descriptive error message as a string in development
|
|
840
839
|
* mode (when the `ngDevMode` is defined). In production mode (after tree-shaking pass), the
|
|
841
|
-
* `message` argument becomes `false`, thus we account for it in the typings and the runtime
|
|
840
|
+
* `message` argument becomes `false`, thus we account for it in the typings and the runtime
|
|
841
|
+
* logic.
|
|
842
842
|
*/
|
|
843
843
|
class RuntimeError extends Error {
|
|
844
844
|
constructor(code, message) {
|
|
@@ -1640,6 +1640,7 @@ function ngDevModeResetPerfCounters() {
|
|
|
1640
1640
|
hydratedComponents: 0,
|
|
1641
1641
|
dehydratedViewsRemoved: 0,
|
|
1642
1642
|
dehydratedViewsCleanupRuns: 0,
|
|
1643
|
+
componentsSkippedHydration: 0,
|
|
1643
1644
|
};
|
|
1644
1645
|
// Make sure to refer to ngDevMode as ['ngDevMode'] for closure.
|
|
1645
1646
|
const allowNgDevModeTrue = locationString.indexOf('ngDevMode=false') === -1;
|
|
@@ -3219,23 +3220,22 @@ const T_HOST = 6;
|
|
|
3219
3220
|
const CLEANUP = 7;
|
|
3220
3221
|
const CONTEXT = 8;
|
|
3221
3222
|
const INJECTOR$1 = 9;
|
|
3222
|
-
const
|
|
3223
|
+
const ENVIRONMENT = 10;
|
|
3223
3224
|
const RENDERER = 11;
|
|
3224
|
-
const
|
|
3225
|
-
const
|
|
3226
|
-
const CHILD_TAIL = 14;
|
|
3225
|
+
const CHILD_HEAD = 12;
|
|
3226
|
+
const CHILD_TAIL = 13;
|
|
3227
3227
|
// FIXME(misko): Investigate if the three declarations aren't all same thing.
|
|
3228
|
-
const DECLARATION_VIEW =
|
|
3229
|
-
const DECLARATION_COMPONENT_VIEW =
|
|
3230
|
-
const DECLARATION_LCONTAINER =
|
|
3231
|
-
const PREORDER_HOOK_FLAGS =
|
|
3232
|
-
const QUERIES =
|
|
3233
|
-
const ID =
|
|
3234
|
-
const EMBEDDED_VIEW_INJECTOR =
|
|
3235
|
-
const ON_DESTROY_HOOKS =
|
|
3236
|
-
const HYDRATION =
|
|
3237
|
-
const REACTIVE_TEMPLATE_CONSUMER =
|
|
3238
|
-
const REACTIVE_HOST_BINDING_CONSUMER =
|
|
3228
|
+
const DECLARATION_VIEW = 14;
|
|
3229
|
+
const DECLARATION_COMPONENT_VIEW = 15;
|
|
3230
|
+
const DECLARATION_LCONTAINER = 16;
|
|
3231
|
+
const PREORDER_HOOK_FLAGS = 17;
|
|
3232
|
+
const QUERIES = 18;
|
|
3233
|
+
const ID = 19;
|
|
3234
|
+
const EMBEDDED_VIEW_INJECTOR = 20;
|
|
3235
|
+
const ON_DESTROY_HOOKS = 21;
|
|
3236
|
+
const HYDRATION = 22;
|
|
3237
|
+
const REACTIVE_TEMPLATE_CONSUMER = 23;
|
|
3238
|
+
const REACTIVE_HOST_BINDING_CONSUMER = 24;
|
|
3239
3239
|
/**
|
|
3240
3240
|
* Size of LView's header. Necessary to adjust for it when setting slots.
|
|
3241
3241
|
*
|
|
@@ -3243,7 +3243,7 @@ const REACTIVE_HOST_BINDING_CONSUMER = 25;
|
|
|
3243
3243
|
* instruction index into `LView` index. All other indexes should be in the `LView` index space and
|
|
3244
3244
|
* there should be no need to refer to `HEADER_OFFSET` anywhere else.
|
|
3245
3245
|
*/
|
|
3246
|
-
const HEADER_OFFSET =
|
|
3246
|
+
const HEADER_OFFSET = 25;
|
|
3247
3247
|
// Note: This hack is necessary so we don't erroneously get a circular dependency
|
|
3248
3248
|
// failure based on types.
|
|
3249
3249
|
const unusedValueExportToPlacateAjd$4 = 1;
|
|
@@ -8356,7 +8356,7 @@ function validateAgainstEventAttributes(name) {
|
|
|
8356
8356
|
}
|
|
8357
8357
|
function getSanitizer() {
|
|
8358
8358
|
const lView = getLView();
|
|
8359
|
-
return lView && lView[
|
|
8359
|
+
return lView && lView[ENVIRONMENT].sanitizer;
|
|
8360
8360
|
}
|
|
8361
8361
|
|
|
8362
8362
|
/**
|
|
@@ -9787,7 +9787,7 @@ class Version {
|
|
|
9787
9787
|
/**
|
|
9788
9788
|
* @publicApi
|
|
9789
9789
|
*/
|
|
9790
|
-
const VERSION = new Version('16.0.0-next.
|
|
9790
|
+
const VERSION = new Version('16.0.0-next.6');
|
|
9791
9791
|
|
|
9792
9792
|
// This default value is when checking the hierarchy for a token.
|
|
9793
9793
|
//
|
|
@@ -10026,6 +10026,10 @@ let _nextReactiveId = 0;
|
|
|
10026
10026
|
* consumer).
|
|
10027
10027
|
*/
|
|
10028
10028
|
let activeConsumer = null;
|
|
10029
|
+
/**
|
|
10030
|
+
* Whether the graph is currently propagating change notifications.
|
|
10031
|
+
*/
|
|
10032
|
+
let inNotificationPhase = false;
|
|
10029
10033
|
function setActiveConsumer(consumer) {
|
|
10030
10034
|
const prev = activeConsumer;
|
|
10031
10035
|
activeConsumer = consumer;
|
|
@@ -10116,20 +10120,33 @@ class ReactiveNode {
|
|
|
10116
10120
|
* Notify all consumers of this producer that its value may have changed.
|
|
10117
10121
|
*/
|
|
10118
10122
|
producerMayHaveChanged() {
|
|
10119
|
-
|
|
10120
|
-
|
|
10121
|
-
|
|
10122
|
-
|
|
10123
|
-
|
|
10124
|
-
|
|
10123
|
+
// Prevent signal reads when we're updating the graph
|
|
10124
|
+
const prev = inNotificationPhase;
|
|
10125
|
+
inNotificationPhase = true;
|
|
10126
|
+
try {
|
|
10127
|
+
for (const [consumerId, edge] of this.consumers) {
|
|
10128
|
+
const consumer = edge.consumerNode.deref();
|
|
10129
|
+
if (consumer === undefined || consumer.trackingVersion !== edge.atTrackingVersion) {
|
|
10130
|
+
this.consumers.delete(consumerId);
|
|
10131
|
+
consumer?.producers.delete(this.id);
|
|
10132
|
+
continue;
|
|
10133
|
+
}
|
|
10134
|
+
consumer.onConsumerDependencyMayHaveChanged();
|
|
10125
10135
|
}
|
|
10126
|
-
|
|
10136
|
+
}
|
|
10137
|
+
finally {
|
|
10138
|
+
inNotificationPhase = prev;
|
|
10127
10139
|
}
|
|
10128
10140
|
}
|
|
10129
10141
|
/**
|
|
10130
10142
|
* Mark that this producer node has been accessed in the current reactive context.
|
|
10131
10143
|
*/
|
|
10132
10144
|
producerAccessed() {
|
|
10145
|
+
if (inNotificationPhase) {
|
|
10146
|
+
throw new Error(typeof ngDevMode !== 'undefined' && ngDevMode ?
|
|
10147
|
+
`Assertion error: signal read during notification phase` :
|
|
10148
|
+
'');
|
|
10149
|
+
}
|
|
10133
10150
|
if (activeConsumer === null) {
|
|
10134
10151
|
return;
|
|
10135
10152
|
}
|
|
@@ -10156,6 +10173,13 @@ class ReactiveNode {
|
|
|
10156
10173
|
get hasProducers() {
|
|
10157
10174
|
return this.producers.size > 0;
|
|
10158
10175
|
}
|
|
10176
|
+
/**
|
|
10177
|
+
* Whether this `ReactiveNode` in its producer capacity is currently allowed to initiate updates,
|
|
10178
|
+
* based on the current consumer context.
|
|
10179
|
+
*/
|
|
10180
|
+
get producerUpdatesAllowed() {
|
|
10181
|
+
return activeConsumer?.consumerAllowSignalWrites !== false;
|
|
10182
|
+
}
|
|
10159
10183
|
/**
|
|
10160
10184
|
* Checks if a `Producer` has a current value which is different than the value
|
|
10161
10185
|
* last seen at a specific version by a `Consumer` which recorded a dependency on
|
|
@@ -10203,6 +10227,7 @@ const NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;
|
|
|
10203
10227
|
class ReactiveLViewConsumer extends ReactiveNode {
|
|
10204
10228
|
constructor() {
|
|
10205
10229
|
super(...arguments);
|
|
10230
|
+
this.consumerAllowSignalWrites = false;
|
|
10206
10231
|
this._lView = null;
|
|
10207
10232
|
}
|
|
10208
10233
|
set lView(lView) {
|
|
@@ -11426,7 +11451,7 @@ function renderChildComponents(hostLView, components) {
|
|
|
11426
11451
|
renderComponent(hostLView, components[i]);
|
|
11427
11452
|
}
|
|
11428
11453
|
}
|
|
11429
|
-
function createLView(parentLView, tView, context, flags, host, tHostNode,
|
|
11454
|
+
function createLView(parentLView, tView, context, flags, host, tHostNode, environment, renderer, injector, embeddedViewInjector, hydrationInfo) {
|
|
11430
11455
|
const lView = tView.blueprint.slice();
|
|
11431
11456
|
lView[HOST] = host;
|
|
11432
11457
|
lView[FLAGS] = flags | 4 /* LViewFlags.CreationMode */ | 64 /* LViewFlags.Attached */ | 8 /* LViewFlags.FirstLViewPass */;
|
|
@@ -11438,11 +11463,10 @@ function createLView(parentLView, tView, context, flags, host, tHostNode, render
|
|
|
11438
11463
|
ngDevMode && tView.declTNode && parentLView && assertTNodeForLView(tView.declTNode, parentLView);
|
|
11439
11464
|
lView[PARENT] = lView[DECLARATION_VIEW] = parentLView;
|
|
11440
11465
|
lView[CONTEXT] = context;
|
|
11441
|
-
lView[
|
|
11442
|
-
ngDevMode && assertDefined(lView[
|
|
11466
|
+
lView[ENVIRONMENT] = (environment || parentLView && parentLView[ENVIRONMENT]);
|
|
11467
|
+
ngDevMode && assertDefined(lView[ENVIRONMENT], 'LViewEnvironment is required');
|
|
11443
11468
|
lView[RENDERER] = (renderer || parentLView && parentLView[RENDERER]);
|
|
11444
11469
|
ngDevMode && assertDefined(lView[RENDERER], 'Renderer is required');
|
|
11445
|
-
lView[SANITIZER] = sanitizer || parentLView && parentLView[SANITIZER] || null;
|
|
11446
11470
|
lView[INJECTOR$1] = injector || parentLView && parentLView[INJECTOR$1] || null;
|
|
11447
11471
|
lView[T_HOST] = tHostNode;
|
|
11448
11472
|
lView[ID] = getUniqueLViewId();
|
|
@@ -11621,10 +11645,11 @@ function refreshView(tView, lView, templateFn, context) {
|
|
|
11621
11645
|
const flags = lView[FLAGS];
|
|
11622
11646
|
if ((flags & 128 /* LViewFlags.Destroyed */) === 128 /* LViewFlags.Destroyed */)
|
|
11623
11647
|
return;
|
|
11624
|
-
enterView(lView);
|
|
11625
11648
|
// Check no changes mode is a dev only mode used to verify that bindings have not changed
|
|
11626
11649
|
// since they were assigned. We do not want to execute lifecycle hooks in that mode.
|
|
11627
11650
|
const isInCheckNoChangesPass = ngDevMode && isInCheckNoChangesMode();
|
|
11651
|
+
!isInCheckNoChangesPass && lView[ENVIRONMENT].effectManager?.flush();
|
|
11652
|
+
enterView(lView);
|
|
11628
11653
|
try {
|
|
11629
11654
|
resetPreOrderHookFlags(lView);
|
|
11630
11655
|
setBindingIndex(tView.bindingStartIndex);
|
|
@@ -12540,8 +12565,8 @@ function addComponentLogic(lView, hostTNode, def) {
|
|
|
12540
12565
|
const tView = getOrCreateComponentTView(def);
|
|
12541
12566
|
// Only component views should be added to the view tree directly. Embedded views are
|
|
12542
12567
|
// accessed through their containers because they may be removed / re-added later.
|
|
12543
|
-
const rendererFactory = lView[
|
|
12544
|
-
const componentView = addToViewTree(lView, createLView(lView, tView, null, def.onPush ? 32 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, native, hostTNode,
|
|
12568
|
+
const rendererFactory = lView[ENVIRONMENT].rendererFactory;
|
|
12569
|
+
const componentView = addToViewTree(lView, createLView(lView, tView, null, def.onPush ? 32 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, native, hostTNode, null, rendererFactory.createRenderer(native, def), null, null, null));
|
|
12545
12570
|
// Component view will always be created before any injected LContainers,
|
|
12546
12571
|
// so this is a regular element, wrap it with the component view
|
|
12547
12572
|
lView[hostTNode.index] = componentView;
|
|
@@ -12855,7 +12880,7 @@ function addToViewTree(lView, lViewOrLContainer) {
|
|
|
12855
12880
|
//// Change detection
|
|
12856
12881
|
///////////////////////////////
|
|
12857
12882
|
function detectChangesInternal(tView, lView, context, notifyErrorHandler = true) {
|
|
12858
|
-
const rendererFactory = lView[
|
|
12883
|
+
const rendererFactory = lView[ENVIRONMENT].rendererFactory;
|
|
12859
12884
|
// Check no changes mode is a dev only mode used to verify that bindings have not changed
|
|
12860
12885
|
// since they were assigned. We do not want to invoke renderer factory functions in that mode
|
|
12861
12886
|
// to avoid any possible side-effects.
|
|
@@ -12874,6 +12899,9 @@ function detectChangesInternal(tView, lView, context, notifyErrorHandler = true)
|
|
|
12874
12899
|
finally {
|
|
12875
12900
|
if (!checkNoChangesMode && rendererFactory.end)
|
|
12876
12901
|
rendererFactory.end();
|
|
12902
|
+
// One final flush of the effects queue to catch any effects created in `ngAfterViewInit` or
|
|
12903
|
+
// other post-order hooks.
|
|
12904
|
+
!checkNoChangesMode && lView[ENVIRONMENT].effectManager?.flush();
|
|
12877
12905
|
}
|
|
12878
12906
|
}
|
|
12879
12907
|
function checkNoChangesInternal(tView, lView, context, notifyErrorHandler = true) {
|
|
@@ -12996,6 +13024,433 @@ function textBindingInternal(lView, index, value) {
|
|
|
12996
13024
|
updateTextNode(lView[RENDERER], element, value);
|
|
12997
13025
|
}
|
|
12998
13026
|
|
|
13027
|
+
/**
|
|
13028
|
+
* `DestroyRef` lets you set callbacks to run for any cleanup or destruction behavior.
|
|
13029
|
+
* The scope of this destruction depends on where `DestroyRef` is injected. If `DestroyRef`
|
|
13030
|
+
* is injected in a component or directive, the callbacks run when that component or
|
|
13031
|
+
* directive is destroyed. Otherwise the callbacks run when a corresponding injector is destroyed.
|
|
13032
|
+
*
|
|
13033
|
+
* @publicApi
|
|
13034
|
+
*/
|
|
13035
|
+
class DestroyRef {
|
|
13036
|
+
/**
|
|
13037
|
+
* @internal
|
|
13038
|
+
* @nocollapse
|
|
13039
|
+
*/
|
|
13040
|
+
static { this.__NG_ELEMENT_ID__ = injectDestroyRef; }
|
|
13041
|
+
/**
|
|
13042
|
+
* @internal
|
|
13043
|
+
* @nocollapse
|
|
13044
|
+
*/
|
|
13045
|
+
static { this.__NG_ENV_ID__ = (injector) => injector; }
|
|
13046
|
+
}
|
|
13047
|
+
class NodeInjectorDestroyRef extends DestroyRef {
|
|
13048
|
+
constructor(_lView) {
|
|
13049
|
+
super();
|
|
13050
|
+
this._lView = _lView;
|
|
13051
|
+
}
|
|
13052
|
+
onDestroy(callback) {
|
|
13053
|
+
storeLViewOnDestroy(this._lView, callback);
|
|
13054
|
+
return () => removeLViewOnDestroy(this._lView, callback);
|
|
13055
|
+
}
|
|
13056
|
+
}
|
|
13057
|
+
function injectDestroyRef() {
|
|
13058
|
+
return new NodeInjectorDestroyRef(getLView());
|
|
13059
|
+
}
|
|
13060
|
+
|
|
13061
|
+
/**
|
|
13062
|
+
* Symbol used to tell `Signal`s apart from other functions.
|
|
13063
|
+
*
|
|
13064
|
+
* This can be used to auto-unwrap signals in various cases, or to auto-wrap non-signal values.
|
|
13065
|
+
*/
|
|
13066
|
+
const SIGNAL = Symbol('SIGNAL');
|
|
13067
|
+
/**
|
|
13068
|
+
* Checks if the given `value` function is a reactive `Signal`.
|
|
13069
|
+
*/
|
|
13070
|
+
function isSignal(value) {
|
|
13071
|
+
return value[SIGNAL] !== undefined;
|
|
13072
|
+
}
|
|
13073
|
+
/**
|
|
13074
|
+
* Converts `fn` into a marked signal function (where `isSignal(fn)` will be `true`), and
|
|
13075
|
+
* potentially add some set of extra properties (passed as an object record `extraApi`).
|
|
13076
|
+
*/
|
|
13077
|
+
function createSignalFromFunction(node, fn, extraApi = {}) {
|
|
13078
|
+
fn[SIGNAL] = node;
|
|
13079
|
+
// Copy properties from `extraApi` to `fn` to complete the desired API of the `Signal`.
|
|
13080
|
+
return Object.assign(fn, extraApi);
|
|
13081
|
+
}
|
|
13082
|
+
/**
|
|
13083
|
+
* The default equality function used for `signal` and `computed`, which treats objects and arrays
|
|
13084
|
+
* as never equal, and all other primitive values using identity semantics.
|
|
13085
|
+
*
|
|
13086
|
+
* This allows signals to hold non-primitive values (arrays, objects, other collections) and still
|
|
13087
|
+
* propagate change notification upon explicit mutation without identity change.
|
|
13088
|
+
*
|
|
13089
|
+
* @developerPreview
|
|
13090
|
+
*/
|
|
13091
|
+
function defaultEquals(a, b) {
|
|
13092
|
+
// `Object.is` compares two values using identity semantics which is desired behavior for
|
|
13093
|
+
// primitive values. If `Object.is` determines two values to be equal we need to make sure that
|
|
13094
|
+
// those don't represent objects (we want to make sure that 2 objects are always considered
|
|
13095
|
+
// "unequal"). The null check is needed for the special case of JavaScript reporting null values
|
|
13096
|
+
// as objects (`typeof null === 'object'`).
|
|
13097
|
+
return (a === null || typeof a !== 'object') && Object.is(a, b);
|
|
13098
|
+
}
|
|
13099
|
+
|
|
13100
|
+
/**
|
|
13101
|
+
* Create a computed `Signal` which derives a reactive value from an expression.
|
|
13102
|
+
*
|
|
13103
|
+
* @developerPreview
|
|
13104
|
+
*/
|
|
13105
|
+
function computed(computation, options) {
|
|
13106
|
+
const node = new ComputedImpl(computation, options?.equal ?? defaultEquals);
|
|
13107
|
+
// Casting here is required for g3, as TS inference behavior is slightly different between our
|
|
13108
|
+
// version/options and g3's.
|
|
13109
|
+
return createSignalFromFunction(node, node.signal.bind(node));
|
|
13110
|
+
}
|
|
13111
|
+
/**
|
|
13112
|
+
* A dedicated symbol used before a computed value has been calculated for the first time.
|
|
13113
|
+
* Explicitly typed as `any` so we can use it as signal's value.
|
|
13114
|
+
*/
|
|
13115
|
+
const UNSET = Symbol('UNSET');
|
|
13116
|
+
/**
|
|
13117
|
+
* A dedicated symbol used in place of a computed signal value to indicate that a given computation
|
|
13118
|
+
* is in progress. Used to detect cycles in computation chains.
|
|
13119
|
+
* Explicitly typed as `any` so we can use it as signal's value.
|
|
13120
|
+
*/
|
|
13121
|
+
const COMPUTING = Symbol('COMPUTING');
|
|
13122
|
+
/**
|
|
13123
|
+
* A dedicated symbol used in place of a computed signal value to indicate that a given computation
|
|
13124
|
+
* failed. The thrown error is cached until the computation gets dirty again.
|
|
13125
|
+
* Explicitly typed as `any` so we can use it as signal's value.
|
|
13126
|
+
*/
|
|
13127
|
+
const ERRORED = Symbol('ERRORED');
|
|
13128
|
+
/**
|
|
13129
|
+
* A computation, which derives a value from a declarative reactive expression.
|
|
13130
|
+
*
|
|
13131
|
+
* `Computed`s are both producers and consumers of reactivity.
|
|
13132
|
+
*/
|
|
13133
|
+
class ComputedImpl extends ReactiveNode {
|
|
13134
|
+
constructor(computation, equal) {
|
|
13135
|
+
super();
|
|
13136
|
+
this.computation = computation;
|
|
13137
|
+
this.equal = equal;
|
|
13138
|
+
/**
|
|
13139
|
+
* Current value of the computation.
|
|
13140
|
+
*
|
|
13141
|
+
* This can also be one of the special values `UNSET`, `COMPUTING`, or `ERRORED`.
|
|
13142
|
+
*/
|
|
13143
|
+
this.value = UNSET;
|
|
13144
|
+
/**
|
|
13145
|
+
* If `value` is `ERRORED`, the error caught from the last computation attempt which will
|
|
13146
|
+
* be re-thrown.
|
|
13147
|
+
*/
|
|
13148
|
+
this.error = null;
|
|
13149
|
+
/**
|
|
13150
|
+
* Flag indicating that the computation is currently stale, meaning that one of the
|
|
13151
|
+
* dependencies has notified of a potential change.
|
|
13152
|
+
*
|
|
13153
|
+
* It's possible that no dependency has _actually_ changed, in which case the `stale`
|
|
13154
|
+
* state can be resolved without recomputing the value.
|
|
13155
|
+
*/
|
|
13156
|
+
this.stale = true;
|
|
13157
|
+
this.consumerAllowSignalWrites = false;
|
|
13158
|
+
}
|
|
13159
|
+
onConsumerDependencyMayHaveChanged() {
|
|
13160
|
+
if (this.stale) {
|
|
13161
|
+
// We've already notified consumers that this value has potentially changed.
|
|
13162
|
+
return;
|
|
13163
|
+
}
|
|
13164
|
+
// Record that the currently cached value may be stale.
|
|
13165
|
+
this.stale = true;
|
|
13166
|
+
// Notify any consumers about the potential change.
|
|
13167
|
+
this.producerMayHaveChanged();
|
|
13168
|
+
}
|
|
13169
|
+
onProducerUpdateValueVersion() {
|
|
13170
|
+
if (!this.stale) {
|
|
13171
|
+
// The current value and its version are already up to date.
|
|
13172
|
+
return;
|
|
13173
|
+
}
|
|
13174
|
+
// The current value is stale. Check whether we need to produce a new one.
|
|
13175
|
+
if (this.value !== UNSET && this.value !== COMPUTING &&
|
|
13176
|
+
!this.consumerPollProducersForChange()) {
|
|
13177
|
+
// Even though we were previously notified of a potential dependency update, all of
|
|
13178
|
+
// our dependencies report that they have not actually changed in value, so we can
|
|
13179
|
+
// resolve the stale state without needing to recompute the current value.
|
|
13180
|
+
this.stale = false;
|
|
13181
|
+
return;
|
|
13182
|
+
}
|
|
13183
|
+
// The current value is stale, and needs to be recomputed. It still may not change -
|
|
13184
|
+
// that depends on whether the newly computed value is equal to the old.
|
|
13185
|
+
this.recomputeValue();
|
|
13186
|
+
}
|
|
13187
|
+
recomputeValue() {
|
|
13188
|
+
if (this.value === COMPUTING) {
|
|
13189
|
+
// Our computation somehow led to a cyclic read of itself.
|
|
13190
|
+
throw new Error('Detected cycle in computations.');
|
|
13191
|
+
}
|
|
13192
|
+
const oldValue = this.value;
|
|
13193
|
+
this.value = COMPUTING;
|
|
13194
|
+
// As we're re-running the computation, update our dependent tracking version number.
|
|
13195
|
+
this.trackingVersion++;
|
|
13196
|
+
const prevConsumer = setActiveConsumer(this);
|
|
13197
|
+
let newValue;
|
|
13198
|
+
try {
|
|
13199
|
+
newValue = this.computation();
|
|
13200
|
+
}
|
|
13201
|
+
catch (err) {
|
|
13202
|
+
newValue = ERRORED;
|
|
13203
|
+
this.error = err;
|
|
13204
|
+
}
|
|
13205
|
+
finally {
|
|
13206
|
+
setActiveConsumer(prevConsumer);
|
|
13207
|
+
}
|
|
13208
|
+
this.stale = false;
|
|
13209
|
+
if (oldValue !== UNSET && oldValue !== ERRORED && newValue !== ERRORED &&
|
|
13210
|
+
this.equal(oldValue, newValue)) {
|
|
13211
|
+
// No change to `valueVersion` - old and new values are
|
|
13212
|
+
// semantically equivalent.
|
|
13213
|
+
this.value = oldValue;
|
|
13214
|
+
return;
|
|
13215
|
+
}
|
|
13216
|
+
this.value = newValue;
|
|
13217
|
+
this.valueVersion++;
|
|
13218
|
+
}
|
|
13219
|
+
signal() {
|
|
13220
|
+
// Check if the value needs updating before returning it.
|
|
13221
|
+
this.onProducerUpdateValueVersion();
|
|
13222
|
+
// Record that someone looked at this signal.
|
|
13223
|
+
this.producerAccessed();
|
|
13224
|
+
if (this.value === ERRORED) {
|
|
13225
|
+
throw this.error;
|
|
13226
|
+
}
|
|
13227
|
+
return this.value;
|
|
13228
|
+
}
|
|
13229
|
+
}
|
|
13230
|
+
|
|
13231
|
+
function defaultThrowError() {
|
|
13232
|
+
throw new Error();
|
|
13233
|
+
}
|
|
13234
|
+
let throwInvalidWriteToSignalErrorFn = defaultThrowError;
|
|
13235
|
+
function throwInvalidWriteToSignalError() {
|
|
13236
|
+
throwInvalidWriteToSignalErrorFn();
|
|
13237
|
+
}
|
|
13238
|
+
function setThrowInvalidWriteToSignalError(fn) {
|
|
13239
|
+
throwInvalidWriteToSignalErrorFn = fn;
|
|
13240
|
+
}
|
|
13241
|
+
|
|
13242
|
+
class WritableSignalImpl extends ReactiveNode {
|
|
13243
|
+
constructor(value, equal) {
|
|
13244
|
+
super();
|
|
13245
|
+
this.value = value;
|
|
13246
|
+
this.equal = equal;
|
|
13247
|
+
this.consumerAllowSignalWrites = false;
|
|
13248
|
+
}
|
|
13249
|
+
onConsumerDependencyMayHaveChanged() {
|
|
13250
|
+
// This never happens for writable signals as they're not consumers.
|
|
13251
|
+
}
|
|
13252
|
+
onProducerUpdateValueVersion() {
|
|
13253
|
+
// Writable signal value versions are always up to date.
|
|
13254
|
+
}
|
|
13255
|
+
/**
|
|
13256
|
+
* Directly update the value of the signal to a new value, which may or may not be
|
|
13257
|
+
* equal to the previous.
|
|
13258
|
+
*
|
|
13259
|
+
* In the event that `newValue` is semantically equal to the current value, `set` is
|
|
13260
|
+
* a no-op.
|
|
13261
|
+
*/
|
|
13262
|
+
set(newValue) {
|
|
13263
|
+
if (!this.producerUpdatesAllowed) {
|
|
13264
|
+
throwInvalidWriteToSignalError();
|
|
13265
|
+
}
|
|
13266
|
+
if (!this.equal(this.value, newValue)) {
|
|
13267
|
+
this.value = newValue;
|
|
13268
|
+
this.valueVersion++;
|
|
13269
|
+
this.producerMayHaveChanged();
|
|
13270
|
+
}
|
|
13271
|
+
}
|
|
13272
|
+
/**
|
|
13273
|
+
* Derive a new value for the signal from its current value using the `updater` function.
|
|
13274
|
+
*
|
|
13275
|
+
* This is equivalent to calling `set` on the result of running `updater` on the current
|
|
13276
|
+
* value.
|
|
13277
|
+
*/
|
|
13278
|
+
update(updater) {
|
|
13279
|
+
if (!this.producerUpdatesAllowed) {
|
|
13280
|
+
throwInvalidWriteToSignalError();
|
|
13281
|
+
}
|
|
13282
|
+
this.set(updater(this.value));
|
|
13283
|
+
}
|
|
13284
|
+
/**
|
|
13285
|
+
* Calls `mutator` on the current value and assumes that it has been mutated.
|
|
13286
|
+
*/
|
|
13287
|
+
mutate(mutator) {
|
|
13288
|
+
if (!this.producerUpdatesAllowed) {
|
|
13289
|
+
throwInvalidWriteToSignalError();
|
|
13290
|
+
}
|
|
13291
|
+
// Mutate bypasses equality checks as it's by definition changing the value.
|
|
13292
|
+
mutator(this.value);
|
|
13293
|
+
this.valueVersion++;
|
|
13294
|
+
this.producerMayHaveChanged();
|
|
13295
|
+
}
|
|
13296
|
+
signal() {
|
|
13297
|
+
this.producerAccessed();
|
|
13298
|
+
return this.value;
|
|
13299
|
+
}
|
|
13300
|
+
}
|
|
13301
|
+
/**
|
|
13302
|
+
* Create a `Signal` that can be set or updated directly.
|
|
13303
|
+
*
|
|
13304
|
+
* @developerPreview
|
|
13305
|
+
*/
|
|
13306
|
+
function signal(initialValue, options) {
|
|
13307
|
+
const signalNode = new WritableSignalImpl(initialValue, options?.equal ?? defaultEquals);
|
|
13308
|
+
// Casting here is required for g3, as TS inference behavior is slightly different between our
|
|
13309
|
+
// version/options and g3's.
|
|
13310
|
+
const signalFn = createSignalFromFunction(signalNode, signalNode.signal.bind(signalNode), {
|
|
13311
|
+
set: signalNode.set.bind(signalNode),
|
|
13312
|
+
update: signalNode.update.bind(signalNode),
|
|
13313
|
+
mutate: signalNode.mutate.bind(signalNode),
|
|
13314
|
+
});
|
|
13315
|
+
return signalFn;
|
|
13316
|
+
}
|
|
13317
|
+
|
|
13318
|
+
/**
|
|
13319
|
+
* Execute an arbitrary function in a non-reactive (non-tracking) context. The executed function
|
|
13320
|
+
* can, optionally, return a value.
|
|
13321
|
+
*
|
|
13322
|
+
* @developerPreview
|
|
13323
|
+
*/
|
|
13324
|
+
function untracked(nonReactiveReadsFn) {
|
|
13325
|
+
const prevConsumer = setActiveConsumer(null);
|
|
13326
|
+
// We are not trying to catch any particular errors here, just making sure that the consumers
|
|
13327
|
+
// stack is restored in case of errors.
|
|
13328
|
+
try {
|
|
13329
|
+
return nonReactiveReadsFn();
|
|
13330
|
+
}
|
|
13331
|
+
finally {
|
|
13332
|
+
setActiveConsumer(prevConsumer);
|
|
13333
|
+
}
|
|
13334
|
+
}
|
|
13335
|
+
|
|
13336
|
+
const NOOP_CLEANUP_FN = () => { };
|
|
13337
|
+
/**
|
|
13338
|
+
* Watches a reactive expression and allows it to be scheduled to re-run
|
|
13339
|
+
* when any dependencies notify of a change.
|
|
13340
|
+
*
|
|
13341
|
+
* `Watch` doesn't run reactive expressions itself, but relies on a consumer-
|
|
13342
|
+
* provided scheduling operation to coordinate calling `Watch.run()`.
|
|
13343
|
+
*/
|
|
13344
|
+
class Watch extends ReactiveNode {
|
|
13345
|
+
constructor(watch, schedule, allowSignalWrites) {
|
|
13346
|
+
super();
|
|
13347
|
+
this.watch = watch;
|
|
13348
|
+
this.schedule = schedule;
|
|
13349
|
+
this.dirty = false;
|
|
13350
|
+
this.cleanupFn = NOOP_CLEANUP_FN;
|
|
13351
|
+
this.consumerAllowSignalWrites = allowSignalWrites;
|
|
13352
|
+
}
|
|
13353
|
+
notify() {
|
|
13354
|
+
if (!this.dirty) {
|
|
13355
|
+
this.schedule(this);
|
|
13356
|
+
}
|
|
13357
|
+
this.dirty = true;
|
|
13358
|
+
}
|
|
13359
|
+
onConsumerDependencyMayHaveChanged() {
|
|
13360
|
+
this.notify();
|
|
13361
|
+
}
|
|
13362
|
+
onProducerUpdateValueVersion() {
|
|
13363
|
+
// Watches are not producers.
|
|
13364
|
+
}
|
|
13365
|
+
/**
|
|
13366
|
+
* Execute the reactive expression in the context of this `Watch` consumer.
|
|
13367
|
+
*
|
|
13368
|
+
* Should be called by the user scheduling algorithm when the provided
|
|
13369
|
+
* `schedule` hook is called by `Watch`.
|
|
13370
|
+
*/
|
|
13371
|
+
run() {
|
|
13372
|
+
this.dirty = false;
|
|
13373
|
+
if (this.trackingVersion !== 0 && !this.consumerPollProducersForChange()) {
|
|
13374
|
+
return;
|
|
13375
|
+
}
|
|
13376
|
+
const prevConsumer = setActiveConsumer(this);
|
|
13377
|
+
this.trackingVersion++;
|
|
13378
|
+
try {
|
|
13379
|
+
this.cleanupFn();
|
|
13380
|
+
this.cleanupFn = this.watch() ?? NOOP_CLEANUP_FN;
|
|
13381
|
+
}
|
|
13382
|
+
finally {
|
|
13383
|
+
setActiveConsumer(prevConsumer);
|
|
13384
|
+
}
|
|
13385
|
+
}
|
|
13386
|
+
cleanup() {
|
|
13387
|
+
this.cleanupFn();
|
|
13388
|
+
}
|
|
13389
|
+
}
|
|
13390
|
+
|
|
13391
|
+
/**
|
|
13392
|
+
* Tracks all effects registered within a given application and runs them via `flush`.
|
|
13393
|
+
*/
|
|
13394
|
+
class EffectManager {
|
|
13395
|
+
constructor() {
|
|
13396
|
+
this.all = new Set();
|
|
13397
|
+
this.queue = new Map();
|
|
13398
|
+
}
|
|
13399
|
+
create(effectFn, destroyRef, allowSignalWrites) {
|
|
13400
|
+
const zone = Zone.current;
|
|
13401
|
+
const watch = new Watch(effectFn, (watch) => {
|
|
13402
|
+
if (!this.all.has(watch)) {
|
|
13403
|
+
return;
|
|
13404
|
+
}
|
|
13405
|
+
this.queue.set(watch, zone);
|
|
13406
|
+
}, allowSignalWrites);
|
|
13407
|
+
this.all.add(watch);
|
|
13408
|
+
// Effects start dirty.
|
|
13409
|
+
watch.notify();
|
|
13410
|
+
let unregisterOnDestroy;
|
|
13411
|
+
const destroy = () => {
|
|
13412
|
+
watch.cleanup();
|
|
13413
|
+
unregisterOnDestroy?.();
|
|
13414
|
+
this.all.delete(watch);
|
|
13415
|
+
this.queue.delete(watch);
|
|
13416
|
+
};
|
|
13417
|
+
unregisterOnDestroy = destroyRef?.onDestroy(destroy);
|
|
13418
|
+
return {
|
|
13419
|
+
destroy,
|
|
13420
|
+
};
|
|
13421
|
+
}
|
|
13422
|
+
flush() {
|
|
13423
|
+
if (this.queue.size === 0) {
|
|
13424
|
+
return;
|
|
13425
|
+
}
|
|
13426
|
+
for (const [watch, zone] of this.queue) {
|
|
13427
|
+
this.queue.delete(watch);
|
|
13428
|
+
zone.run(() => watch.run());
|
|
13429
|
+
}
|
|
13430
|
+
}
|
|
13431
|
+
get isQueueEmpty() {
|
|
13432
|
+
return this.queue.size === 0;
|
|
13433
|
+
}
|
|
13434
|
+
/** @nocollapse */
|
|
13435
|
+
static { this.ɵprov = ɵɵdefineInjectable({
|
|
13436
|
+
token: EffectManager,
|
|
13437
|
+
providedIn: 'root',
|
|
13438
|
+
factory: () => new EffectManager(),
|
|
13439
|
+
}); }
|
|
13440
|
+
}
|
|
13441
|
+
/**
|
|
13442
|
+
* Create a global `Effect` for the given reactive function.
|
|
13443
|
+
*
|
|
13444
|
+
* @developerPreview
|
|
13445
|
+
*/
|
|
13446
|
+
function effect(effectFn, options) {
|
|
13447
|
+
!options?.injector && assertInInjectionContext(effect);
|
|
13448
|
+
const injector = options?.injector ?? inject$1(Injector);
|
|
13449
|
+
const effectManager = injector.get(EffectManager);
|
|
13450
|
+
const destroyRef = options?.manualCleanup !== true ? injector.get(DestroyRef) : null;
|
|
13451
|
+
return effectManager.create(effectFn, destroyRef, !!options?.allowSignalWrites);
|
|
13452
|
+
}
|
|
13453
|
+
|
|
12999
13454
|
/**
|
|
13000
13455
|
* Compute the static styling (class/style) from `TAttributes`.
|
|
13001
13456
|
*
|
|
@@ -13463,6 +13918,12 @@ class ComponentFactory extends ComponentFactory$1 {
|
|
|
13463
13918
|
'Make sure that any injector used to create this component has a correct parent.');
|
|
13464
13919
|
}
|
|
13465
13920
|
const sanitizer = rootViewInjector.get(Sanitizer, null);
|
|
13921
|
+
const effectManager = rootViewInjector.get(EffectManager, null);
|
|
13922
|
+
const environment = {
|
|
13923
|
+
rendererFactory,
|
|
13924
|
+
sanitizer,
|
|
13925
|
+
effectManager,
|
|
13926
|
+
};
|
|
13466
13927
|
const hostRenderer = rendererFactory.createRenderer(null, this.componentDef);
|
|
13467
13928
|
// Determine a tag name used for creating host elements when this component is created
|
|
13468
13929
|
// dynamically. Default to 'div' if this component did not specify any tag name in its selector.
|
|
@@ -13474,7 +13935,7 @@ class ComponentFactory extends ComponentFactory$1 {
|
|
|
13474
13935
|
16 /* LViewFlags.CheckAlways */ | 256 /* LViewFlags.IsRoot */;
|
|
13475
13936
|
// Create the root view. Uses empty TView and ContentTemplate.
|
|
13476
13937
|
const rootTView = createTView(0 /* TViewType.Root */, null, null, 1, 0, null, null, null, null, null, null);
|
|
13477
|
-
const rootLView = createLView(null, rootTView, null, rootFlags, null, null,
|
|
13938
|
+
const rootLView = createLView(null, rootTView, null, rootFlags, null, null, environment, hostRenderer, rootViewInjector, null, null);
|
|
13478
13939
|
// rootView is the parent when bootstrapping
|
|
13479
13940
|
// TODO(misko): it looks like we are entering view here but we don't really need to as
|
|
13480
13941
|
// `renderView` does that. However as the code is written it is needed because
|
|
@@ -13497,7 +13958,7 @@ class ComponentFactory extends ComponentFactory$1 {
|
|
|
13497
13958
|
rootDirectives = [rootComponentDef];
|
|
13498
13959
|
}
|
|
13499
13960
|
const hostTNode = createRootComponentTNode(rootLView, hostRNode);
|
|
13500
|
-
const componentView = createRootComponentView(hostTNode, hostRNode, rootComponentDef, rootDirectives, rootLView,
|
|
13961
|
+
const componentView = createRootComponentView(hostTNode, hostRNode, rootComponentDef, rootDirectives, rootLView, environment, hostRenderer);
|
|
13501
13962
|
tElementNode = getTNode(rootTView, HEADER_OFFSET);
|
|
13502
13963
|
// TODO(crisbeto): in practice `hostRNode` should always be defined, but there are some tests
|
|
13503
13964
|
// where the renderer is mocked out and `undefined` is returned. We should update the tests so
|
|
@@ -13603,7 +14064,7 @@ function createRootComponentTNode(lView, rNode) {
|
|
|
13603
14064
|
*
|
|
13604
14065
|
* @returns Component view created
|
|
13605
14066
|
*/
|
|
13606
|
-
function createRootComponentView(tNode, hostRNode, rootComponentDef, rootDirectives, rootView,
|
|
14067
|
+
function createRootComponentView(tNode, hostRNode, rootComponentDef, rootDirectives, rootView, environment, hostRenderer) {
|
|
13607
14068
|
const tView = rootView[TVIEW];
|
|
13608
14069
|
applyRootComponentStyling(rootDirectives, tNode, hostRNode, hostRenderer);
|
|
13609
14070
|
// Hydration info is on the host element and needs to be retreived
|
|
@@ -13612,8 +14073,8 @@ function createRootComponentView(tNode, hostRNode, rootComponentDef, rootDirecti
|
|
|
13612
14073
|
if (hostRNode !== null) {
|
|
13613
14074
|
hydrationInfo = retrieveHydrationInfo(hostRNode, rootView[INJECTOR$1]);
|
|
13614
14075
|
}
|
|
13615
|
-
const viewRenderer = rendererFactory.createRenderer(hostRNode, rootComponentDef);
|
|
13616
|
-
const componentView = createLView(rootView, getOrCreateComponentTView(rootComponentDef), null, rootComponentDef.onPush ? 32 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, rootView[tNode.index], tNode,
|
|
14076
|
+
const viewRenderer = environment.rendererFactory.createRenderer(hostRNode, rootComponentDef);
|
|
14077
|
+
const componentView = createLView(rootView, getOrCreateComponentTView(rootComponentDef), null, rootComponentDef.onPush ? 32 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, rootView[tNode.index], tNode, environment, viewRenderer, null, null, hydrationInfo);
|
|
13617
14078
|
if (tView.firstCreatePass) {
|
|
13618
14079
|
markAsComponentHost(tView, tNode, rootDirectives.length - 1);
|
|
13619
14080
|
}
|
|
@@ -15822,6 +16283,7 @@ function locateOrCreateElementNodeImpl(tView, lView, tNode, renderer, name, inde
|
|
|
15822
16283
|
// Since this isn't hydratable, we need to empty the node
|
|
15823
16284
|
// so there's no duplicate content after render
|
|
15824
16285
|
clearElementContents(native);
|
|
16286
|
+
ngDevMode && ngDevMode.componentsSkippedHydration++;
|
|
15825
16287
|
}
|
|
15826
16288
|
else if (ngDevMode) {
|
|
15827
16289
|
// If this is not a component host, throw an error.
|
|
@@ -15878,7 +16340,6 @@ function ɵɵelementContainerStart(index, attrsIndex, localRefsIndex) {
|
|
|
15878
16340
|
elementContainerStartFirstCreatePass(adjustedIndex, tView, lView, attrsIndex, localRefsIndex) :
|
|
15879
16341
|
tView.data[adjustedIndex];
|
|
15880
16342
|
setCurrentTNode(tNode, true);
|
|
15881
|
-
ngDevMode && ngDevMode.rendererCreateComment++;
|
|
15882
16343
|
const comment = _locateOrCreateElementContainerNode(tView, lView, tNode, index);
|
|
15883
16344
|
lView[adjustedIndex] = comment;
|
|
15884
16345
|
if (wasLastNodeCreated()) {
|
|
@@ -22066,17 +22527,19 @@ function createNgModuleRefWithProviders(moduleType, parentInjector, additionalPr
|
|
|
22066
22527
|
return new NgModuleRef(moduleType, parentInjector, additionalProviders);
|
|
22067
22528
|
}
|
|
22068
22529
|
class EnvironmentNgModuleRefAdapter extends NgModuleRef$1 {
|
|
22069
|
-
constructor(
|
|
22530
|
+
constructor(config) {
|
|
22070
22531
|
super();
|
|
22071
22532
|
this.componentFactoryResolver = new ComponentFactoryResolver(this);
|
|
22072
22533
|
this.instance = null;
|
|
22073
22534
|
const injector = new R3Injector([
|
|
22074
|
-
...providers,
|
|
22535
|
+
...config.providers,
|
|
22075
22536
|
{ provide: NgModuleRef$1, useValue: this },
|
|
22076
22537
|
{ provide: ComponentFactoryResolver$1, useValue: this.componentFactoryResolver },
|
|
22077
|
-
], parent || getNullInjector(),
|
|
22538
|
+
], config.parent || getNullInjector(), config.debugName, new Set(['environment']));
|
|
22078
22539
|
this.injector = injector;
|
|
22079
|
-
|
|
22540
|
+
if (config.runEnvironmentInitializers) {
|
|
22541
|
+
injector.resolveInjectorInitializers();
|
|
22542
|
+
}
|
|
22080
22543
|
}
|
|
22081
22544
|
destroy() {
|
|
22082
22545
|
this.injector.destroy();
|
|
@@ -22099,7 +22562,7 @@ class EnvironmentNgModuleRefAdapter extends NgModuleRef$1 {
|
|
|
22099
22562
|
* @publicApi
|
|
22100
22563
|
*/
|
|
22101
22564
|
function createEnvironmentInjector(providers, parent, debugName = null) {
|
|
22102
|
-
const adapter = new EnvironmentNgModuleRefAdapter(providers, parent, debugName);
|
|
22565
|
+
const adapter = new EnvironmentNgModuleRefAdapter({ providers, parent, debugName, runEnvironmentInitializers: true });
|
|
22103
22566
|
return adapter.injector;
|
|
22104
22567
|
}
|
|
22105
22568
|
|
|
@@ -23367,7 +23830,7 @@ const R3TemplateRef = class TemplateRef extends ViewEngineTemplateRef {
|
|
|
23367
23830
|
*/
|
|
23368
23831
|
createEmbeddedViewImpl(context, injector, hydrationInfo) {
|
|
23369
23832
|
const embeddedTView = this._declarationTContainer.tView;
|
|
23370
|
-
const embeddedLView = createLView(this._declarationLView, embeddedTView, context, 16 /* LViewFlags.CheckAlways */, null, embeddedTView.declTNode, null, null, null,
|
|
23833
|
+
const embeddedLView = createLView(this._declarationLView, embeddedTView, context, 16 /* LViewFlags.CheckAlways */, null, embeddedTView.declTNode, null, null, null, injector || null, hydrationInfo || null);
|
|
23371
23834
|
const declarationLContainer = this._declarationLView[this._declarationTContainer.index];
|
|
23372
23835
|
ngDevMode && assertLContainer(declarationLContainer);
|
|
23373
23836
|
embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;
|
|
@@ -23469,24 +23932,17 @@ function cleanupLView(lView) {
|
|
|
23469
23932
|
* Walks over all views registered within the ApplicationRef and removes
|
|
23470
23933
|
* all dehydrated views from all `LContainer`s along the way.
|
|
23471
23934
|
*/
|
|
23472
|
-
function cleanupDehydratedViews(appRef
|
|
23473
|
-
|
|
23474
|
-
|
|
23475
|
-
|
|
23476
|
-
|
|
23477
|
-
|
|
23478
|
-
|
|
23479
|
-
|
|
23480
|
-
|
|
23481
|
-
const lView = getComponentLViewForHydration(viewRef);
|
|
23482
|
-
// An `lView` might be `null` if a `ViewRef` represents
|
|
23483
|
-
// an embedded view (not a component view).
|
|
23484
|
-
if (lView !== null && lView[HOST] !== null) {
|
|
23485
|
-
cleanupLView(lView);
|
|
23486
|
-
ngDevMode && ngDevMode.dehydratedViewsCleanupRuns++;
|
|
23487
|
-
}
|
|
23935
|
+
function cleanupDehydratedViews(appRef) {
|
|
23936
|
+
const viewRefs = appRef._views;
|
|
23937
|
+
for (const viewRef of viewRefs) {
|
|
23938
|
+
const lView = getComponentLViewForHydration(viewRef);
|
|
23939
|
+
// An `lView` might be `null` if a `ViewRef` represents
|
|
23940
|
+
// an embedded view (not a component view).
|
|
23941
|
+
if (lView !== null && lView[HOST] !== null) {
|
|
23942
|
+
cleanupLView(lView);
|
|
23943
|
+
ngDevMode && ngDevMode.dehydratedViewsCleanupRuns++;
|
|
23488
23944
|
}
|
|
23489
|
-
}
|
|
23945
|
+
}
|
|
23490
23946
|
}
|
|
23491
23947
|
|
|
23492
23948
|
/**
|
|
@@ -23570,7 +24026,7 @@ function findMatchingDehydratedView(lContainer, template) {
|
|
|
23570
24026
|
* (created by instantiating a `TemplateRef` with the `createEmbeddedView()` method).
|
|
23571
24027
|
*
|
|
23572
24028
|
* A view container instance can contain other view containers,
|
|
23573
|
-
* creating a [view hierarchy](guide/glossary#view-
|
|
24029
|
+
* creating a [view hierarchy](guide/glossary#view-hierarchy).
|
|
23574
24030
|
*
|
|
23575
24031
|
* @see `ComponentRef`
|
|
23576
24032
|
* @see `EmbeddedViewRef`
|
|
@@ -25903,9 +26359,8 @@ class TestBedCompiler {
|
|
|
25903
26359
|
ɵcompileNgModuleDefs(RootScopeModule, {
|
|
25904
26360
|
providers: [...this.rootProviderOverrides],
|
|
25905
26361
|
});
|
|
25906
|
-
const ngZone = new NgZone({ enableLongStackTrace: true });
|
|
25907
26362
|
const providers = [
|
|
25908
|
-
|
|
26363
|
+
provideZoneChangeDetection(),
|
|
25909
26364
|
{ provide: Compiler, useFactory: () => new R3TestCompiler(this) },
|
|
25910
26365
|
...this.providers,
|
|
25911
26366
|
...this.providerOverrides,
|