From 713d7c236029d78cb2e4f8a7c8ede3c8e14aa5d9 Mon Sep 17 00:00:00 2001 From: Vikram Subramanian Date: Thu, 10 Aug 2017 17:18:37 -0700 Subject: [PATCH] fix(core): make sure onStable runs in the right zone (#18706) Make sure the callbacks to the NgZone callbacks run in the right zone with or without the rxjs Zone patch - https://github.com/angular/zone.js/commit/1ed83d08ac2ce840c9669df27a18f0c35cb689c3. PR Close #18706 --- packages/core/src/application_ref.ts | 25 +++++--- .../core/testing/src/component_fixture.ts | 64 ++++++++++--------- 2 files changed, 49 insertions(+), 40 deletions(-) diff --git a/packages/core/src/application_ref.ts b/packages/core/src/application_ref.ts index a3dd39d563..bd446ed10e 100644 --- a/packages/core/src/application_ref.ts +++ b/packages/core/src/application_ref.ts @@ -455,17 +455,22 @@ export class ApplicationRef_ extends ApplicationRef { }); const isStable = new Observable((observer: Observer) => { - const stableSub: Subscription = this._zone.onStable.subscribe(() => { - NgZone.assertNotInAngularZone(); + // Create the subscription to onStable outside the Angular Zone so that + // the callback is run outside the Angular Zone. + let stableSub: Subscription; + this._zone.runOutsideAngular(() => { + stableSub = this._zone.onStable.subscribe(() => { + NgZone.assertNotInAngularZone(); - // Check whether there are no pending macro/micro tasks in the next tick - // to allow for NgZone to update the state. - scheduleMicroTask(() => { - if (!this._stable && !this._zone.hasPendingMacrotasks && - !this._zone.hasPendingMicrotasks) { - this._stable = true; - observer.next(true); - } + // Check whether there are no pending macro/micro tasks in the next tick + // to allow for NgZone to update the state. + scheduleMicroTask(() => { + if (!this._stable && !this._zone.hasPendingMacrotasks && + !this._zone.hasPendingMicrotasks) { + this._stable = true; + observer.next(true); + } + }); }); }); diff --git a/packages/core/testing/src/component_fixture.ts b/packages/core/testing/src/component_fixture.ts index fe83d7ff23..7c5da496f4 100644 --- a/packages/core/testing/src/component_fixture.ts +++ b/packages/core/testing/src/component_fixture.ts @@ -62,40 +62,44 @@ export class ComponentFixture { this.ngZone = ngZone; if (ngZone) { - this._onUnstableSubscription = - ngZone.onUnstable.subscribe({next: () => { this._isStable = false; }}); - this._onMicrotaskEmptySubscription = ngZone.onMicrotaskEmpty.subscribe({ - next: () => { - if (this._autoDetect) { - // Do a change detection run with checkNoChanges set to true to check - // there are no changes on the second run. - this.detectChanges(true); + // Create subscriptions outside the NgZone so that the callbacks run oustide + // of NgZone. + ngZone.runOutsideAngular(() => { + this._onUnstableSubscription = + ngZone.onUnstable.subscribe({next: () => { this._isStable = false; }}); + this._onMicrotaskEmptySubscription = ngZone.onMicrotaskEmpty.subscribe({ + next: () => { + if (this._autoDetect) { + // Do a change detection run with checkNoChanges set to true to check + // there are no changes on the second run. + this.detectChanges(true); + } } - } - }); - this._onStableSubscription = ngZone.onStable.subscribe({ - next: () => { - this._isStable = true; - // Check whether there is a pending whenStable() completer to resolve. - if (this._promise !== null) { - // If so check whether there are no pending macrotasks before resolving. - // Do this check in the next tick so that ngZone gets a chance to update the state of - // pending macrotasks. - scheduleMicroTask(() => { - if (!ngZone.hasPendingMacrotasks) { - if (this._promise !== null) { - this._resolve !(true); - this._resolve = null; - this._promise = null; + }); + this._onStableSubscription = ngZone.onStable.subscribe({ + next: () => { + this._isStable = true; + // Check whether there is a pending whenStable() completer to resolve. + if (this._promise !== null) { + // If so check whether there are no pending macrotasks before resolving. + // Do this check in the next tick so that ngZone gets a chance to update the state of + // pending macrotasks. + scheduleMicroTask(() => { + if (!ngZone.hasPendingMacrotasks) { + if (this._promise !== null) { + this._resolve !(true); + this._resolve = null; + this._promise = null; + } } - } - }); + }); + } } - } - }); + }); - this._onErrorSubscription = - ngZone.onError.subscribe({next: (error: any) => { throw error; }}); + this._onErrorSubscription = + ngZone.onError.subscribe({next: (error: any) => { throw error; }}); + }); } }