From 3dc647e382e1a9f0c41ea6271b45f80948bc8e64 Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Tue, 12 Dec 2023 14:44:52 -0800 Subject: [PATCH] fix(core): Multiple subscribers to ApplicationRef.isStable should all see values The behavior of `ApplicationRef.isStable` changed in 16.1 due to https://github.com/angular/angular/commit/28c68f709cdc930e12bac51a266e7bf790656034. This change added a `share` to the `isStable` observable, which prevents additional subscribers from getting a value until a new one emits. One solution to the problem would be `shareReplay(1)`. However, that would increase the bundle size since we do not use `shareReplay` elsewhere. Instead, we don't even really need to share the observable. The `Observable` available in `ApplicationRef.isStable` before the above commit was the zone stable observable, without a `share`. The new behavior adds only an additional observable to the stream, `hasPendingTasks` (a `BehaviorSubject`). The observables in this stream are not expensive to subscribe to. The only one with side effects is the `isStable` (because it subscribes to onStable), but that one already has the `share` operator on it. Omitting the `share` in `ApplicationRef` also means that applications on `zoneless` will not have to pay the cost of the operator when we make zones optional because the zone stable observable is the only place we use it. --- packages/core/src/application/application_ref.ts | 3 +-- packages/core/test/application_ref_spec.ts | 9 +++++++++ .../animations-standalone/bundle.golden_symbols.json | 3 --- .../test/bundling/animations/bundle.golden_symbols.json | 3 --- .../bundling/cyclic_import/bundle.golden_symbols.json | 3 --- .../core/test/bundling/defer/bundle.golden_symbols.json | 3 --- .../bundling/forms_reactive/bundle.golden_symbols.json | 3 --- .../forms_template_driven/bundle.golden_symbols.json | 3 --- .../test/bundling/hello_world/bundle.golden_symbols.json | 3 --- .../test/bundling/hydration/bundle.golden_symbols.json | 3 --- .../core/test/bundling/router/bundle.golden_symbols.json | 3 --- .../standalone_bootstrap/bundle.golden_symbols.json | 3 --- .../core/test/bundling/todo/bundle.golden_symbols.json | 3 --- 13 files changed, 10 insertions(+), 35 deletions(-) diff --git a/packages/core/src/application/application_ref.ts b/packages/core/src/application/application_ref.ts index fb66c6a63863e..74198a30a3cc2 100644 --- a/packages/core/src/application/application_ref.ts +++ b/packages/core/src/application/application_ref.ts @@ -10,7 +10,7 @@ import '../util/ng_jit_mode'; import {setThrowInvalidWriteToSignalError} from '@angular/core/primitives/signals'; import {Observable, of} from 'rxjs'; -import {distinctUntilChanged, first, share, switchMap} from 'rxjs/operators'; +import {distinctUntilChanged, first, switchMap} from 'rxjs/operators'; import {getCompilerFacade, JitCompilerUsage} from '../compiler/compiler_facade'; import {Console} from '../console'; @@ -351,7 +351,6 @@ export class ApplicationRef { .hasPendingTasks.pipe( switchMap(hasPendingTasks => hasPendingTasks ? of(false) : this.zoneIsStable), distinctUntilChanged(), - share(), ); private readonly _injector = inject(EnvironmentInjector); diff --git a/packages/core/test/application_ref_spec.ts b/packages/core/test/application_ref_spec.ts index 634579ea95fcc..c8d9feceb18cb 100644 --- a/packages/core/test/application_ref_spec.ts +++ b/packages/core/test/application_ref_spec.ts @@ -21,6 +21,7 @@ import type {ServerModule} from '@angular/platform-server'; import {ApplicationRef} from '../src/application/application_ref'; import {NoopNgZone} from '../src/zone/ng_zone'; import {ComponentFixtureNoNgZone, inject, TestBed, waitForAsync, withModule} from '../testing'; +import {take} from 'rxjs/operators'; let serverPlatformModule: Promise>|null = null; if (isNode) { @@ -795,6 +796,14 @@ describe('AppRef', () => { expectStableTexts(MacroMicroTaskComp, ['111']); })); + it('isStable can be subscribed to many times', async () => { + const appRef: ApplicationRef = TestBed.inject(ApplicationRef); + // Create stable subscription but do not unsubscribe before the second subscription is made + appRef.isStable.subscribe(); + await expectAsync(appRef.isStable.pipe(take(1)).toPromise()).toBeResolved(); + stableCalled = true; + }); + describe('unstable', () => { let unstableCalled = false; diff --git a/packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json b/packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json index 11f7b30996481..79e7b4160d532 100644 --- a/packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json +++ b/packages/core/test/bundling/animations-standalone/bundle.golden_symbols.json @@ -1406,9 +1406,6 @@ { "name": "setupStaticAttributes" }, - { - "name": "share" - }, { "name": "shareSubjectFactory" }, diff --git a/packages/core/test/bundling/animations/bundle.golden_symbols.json b/packages/core/test/bundling/animations/bundle.golden_symbols.json index 124ba0136e4fa..8ed6ea77716d7 100644 --- a/packages/core/test/bundling/animations/bundle.golden_symbols.json +++ b/packages/core/test/bundling/animations/bundle.golden_symbols.json @@ -1478,9 +1478,6 @@ { "name": "setupStaticAttributes" }, - { - "name": "share" - }, { "name": "shareSubjectFactory" }, diff --git a/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json b/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json index 55e65cac37d9e..919751bbf1f74 100644 --- a/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json +++ b/packages/core/test/bundling/cyclic_import/bundle.golden_symbols.json @@ -1178,9 +1178,6 @@ { "name": "setupStaticAttributes" }, - { - "name": "share" - }, { "name": "shareSubjectFactory" }, diff --git a/packages/core/test/bundling/defer/bundle.golden_symbols.json b/packages/core/test/bundling/defer/bundle.golden_symbols.json index ddca79c4fcaca..a85c231e2299f 100644 --- a/packages/core/test/bundling/defer/bundle.golden_symbols.json +++ b/packages/core/test/bundling/defer/bundle.golden_symbols.json @@ -2336,9 +2336,6 @@ { "name": "setupStaticAttributes" }, - { - "name": "share" - }, { "name": "shareSubjectFactory" }, diff --git a/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json b/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json index b0fd7b6f8a705..2597f240222d6 100644 --- a/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json +++ b/packages/core/test/bundling/forms_reactive/bundle.golden_symbols.json @@ -1649,9 +1649,6 @@ { "name": "setupStaticAttributes" }, - { - "name": "share" - }, { "name": "shareSubjectFactory" }, diff --git a/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json b/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json index 2591b047eb63e..7441ab2f4b3e3 100644 --- a/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json +++ b/packages/core/test/bundling/forms_template_driven/bundle.golden_symbols.json @@ -1625,9 +1625,6 @@ { "name": "setupStaticAttributes" }, - { - "name": "share" - }, { "name": "shareSubjectFactory" }, diff --git a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json index fd2cd41621779..34f3abe685304 100644 --- a/packages/core/test/bundling/hello_world/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hello_world/bundle.golden_symbols.json @@ -932,9 +932,6 @@ { "name": "setUpAttributes" }, - { - "name": "share" - }, { "name": "shareSubjectFactory" }, diff --git a/packages/core/test/bundling/hydration/bundle.golden_symbols.json b/packages/core/test/bundling/hydration/bundle.golden_symbols.json index cb900824fb866..f39ba4ebdf4a9 100644 --- a/packages/core/test/bundling/hydration/bundle.golden_symbols.json +++ b/packages/core/test/bundling/hydration/bundle.golden_symbols.json @@ -1280,9 +1280,6 @@ { "name": "setUpAttributes" }, - { - "name": "share" - }, { "name": "shareSubjectFactory" }, diff --git a/packages/core/test/bundling/router/bundle.golden_symbols.json b/packages/core/test/bundling/router/bundle.golden_symbols.json index 5e48e7f1e548e..9e438ea37a289 100644 --- a/packages/core/test/bundling/router/bundle.golden_symbols.json +++ b/packages/core/test/bundling/router/bundle.golden_symbols.json @@ -1970,9 +1970,6 @@ { "name": "shallowEqual" }, - { - "name": "share" - }, { "name": "shareSubjectFactory" }, diff --git a/packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json b/packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json index af4ea87644511..789274a735058 100644 --- a/packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json +++ b/packages/core/test/bundling/standalone_bootstrap/bundle.golden_symbols.json @@ -1031,9 +1031,6 @@ { "name": "setUpAttributes" }, - { - "name": "share" - }, { "name": "shareSubjectFactory" }, diff --git a/packages/core/test/bundling/todo/bundle.golden_symbols.json b/packages/core/test/bundling/todo/bundle.golden_symbols.json index 1e9b7f4283659..cc6a77eb5126a 100644 --- a/packages/core/test/bundling/todo/bundle.golden_symbols.json +++ b/packages/core/test/bundling/todo/bundle.golden_symbols.json @@ -1418,9 +1418,6 @@ { "name": "setupStaticAttributes" }, - { - "name": "share" - }, { "name": "shareSubjectFactory" },