From 15dab7c5b26686d988eb6ebcb4bd4a645aa91f50 Mon Sep 17 00:00:00 2001 From: vsavkin Date: Wed, 10 Jun 2015 17:21:11 -0700 Subject: [PATCH] fix(ng_zone): updated zone not to run onTurnDown when invoking run synchronously from onTurnDone --- modules/angular2/src/core/zone/ng_zone.dart | 6 ++++- modules/angular2/src/core/zone/ng_zone.ts | 7 +++++- .../angular2/test/core/zone/ng_zone_spec.ts | 24 +++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/modules/angular2/src/core/zone/ng_zone.dart b/modules/angular2/src/core/zone/ng_zone.dart index 6415068fc9..0d1045cf4b 100644 --- a/modules/angular2/src/core/zone/ng_zone.dart +++ b/modules/angular2/src/core/zone/ng_zone.dart @@ -39,6 +39,8 @@ class NgZone { // }); // we should only check for the end of a turn once the top-level run ends int _nestedRun = 0; + bool _inVmTurnDone = false; + /** * Associates with this * @@ -143,12 +145,14 @@ class NgZone { } finally { _nestedRun--; // If there are no more pending microtasks and we are not in a recursive call, this is the end of a turn - if (_pendingMicrotasks == 0 && _nestedRun == 0) { + if (_pendingMicrotasks == 0 && _nestedRun == 0 && !_inVmTurnDone) { if (_onTurnDone != null && _hasExecutedCodeInInnerZone) { // Trigger onTurnDone at the end of a turn if _innerZone has executed some code try { + _inVmTurnDone = true; parent.run(_innerZone, _onTurnDone); } finally { + _inVmTurnDone = false; _hasExecutedCodeInInnerZone = false; } } diff --git a/modules/angular2/src/core/zone/ng_zone.ts b/modules/angular2/src/core/zone/ng_zone.ts index 1b5c800f5c..8a131d3389 100644 --- a/modules/angular2/src/core/zone/ng_zone.ts +++ b/modules/angular2/src/core/zone/ng_zone.ts @@ -39,6 +39,8 @@ export class NgZone { // This disabled flag is only here to please cjs tests _disabled: boolean; + _inVmTurnDone: boolean = false; + /** * Associates with this * @@ -166,11 +168,14 @@ export class NgZone { // _nestedRun will be 0 at the end of a macrotasks (it could be > 0 when there are // nested calls // to run()). - if (ngZone._pendingMicrotasks == 0 && ngZone._nestedRun == 0) { + if (ngZone._pendingMicrotasks == 0 && ngZone._nestedRun == 0 && + !this._inVmTurnDone) { if (ngZone._onTurnDone && ngZone._hasExecutedCodeInInnerZone) { try { + this._inVmTurnDone = true; parentRun.call(ngZone._innerZone, ngZone._onTurnDone); } finally { + this._inVmTurnDone = false; ngZone._hasExecutedCodeInInnerZone = false; } } diff --git a/modules/angular2/test/core/zone/ng_zone_spec.ts b/modules/angular2/test/core/zone/ng_zone_spec.ts index ad96ee6d4b..8cf5476b07 100644 --- a/modules/angular2/test/core/zone/ng_zone_spec.ts +++ b/modules/angular2/test/core/zone/ng_zone_spec.ts @@ -200,6 +200,30 @@ function commonTests() { }, 50); })); + it('should not run onTurnStart and onTurnDone for nested Zone.run invoked from onTurnDone', + inject([AsyncTestCompleter], (async) => { + _zone.initCallbacks({ + onTurnDone: () => { + _log.add('onTurnDone:started'); + _zone.run(() => _log.add('nested run')) + _log.add('onTurnDone:finished'); + } + }); + + macroTask(() => { + _zone.run(() => { + _log.add('start run'); + }); + }); + + macroTask(() => { + expect(_log.result()) + .toEqual( + 'start run; onTurnDone:started; nested run; onTurnDone:finished'); + async.done(); + }, 50); + })); + it('should call onTurnStart and onTurnDone before and after each top-level run', inject([AsyncTestCompleter], (async) => { macroTask(() => { _zone.run(_log.fn('run1')); });