From 56a0bf5e8dcd89a74025ca980dcf73ff204dda05 Mon Sep 17 00:00:00 2001 From: Pavel Jbanov Date: Fri, 21 Feb 2014 11:27:14 -0500 Subject: [PATCH] fix(scope): don't create own streams too eagerly --- lib/core/scope.dart | 9 ++++++++- test/core/scope_spec.dart | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/lib/core/scope.dart b/lib/core/scope.dart index 8d727ea10..6473a1215 100644 --- a/lib/core/scope.dart +++ b/lib/core/scope.dart @@ -161,6 +161,9 @@ class Scope { Scope _childHead, _childTail, _next, _prev; _Streams _streams; + /// Do not use. Exposes internal state for testing. + bool get hasOwnStreams => _streams != null && _streams._scope == this; + Scope(Object this.context, this.rootScope, this._parentScope, this._readWriteGroup, this._readOnlyGroup); @@ -595,13 +598,17 @@ class _Streams { static void _forceNewScopeStream(scope, _exceptionHandler) { _Streams streams = scope._streams; Scope scopeCursor = scope; + bool splitMode = false; while(scopeCursor != null) { _Streams cursorStreams = scopeCursor._streams; var hasStream = cursorStreams != null; var hasOwnStream = hasStream && cursorStreams._scope == scopeCursor; if (hasOwnStream) return; - if (streams == null || (hasStream && !hasOwnStream)) { + if (!splitMode && (streams == null || (hasStream && !hasOwnStream))) { + if (hasStream && !hasOwnStream) { + splitMode = true; + } streams = new _Streams(scopeCursor, _exceptionHandler, cursorStreams); } scopeCursor._streams = streams; diff --git a/test/core/scope_spec.dart b/test/core/scope_spec.dart index ff65dcb5b..72bb8430a 100644 --- a/test/core/scope_spec.dart +++ b/test/core/scope_spec.dart @@ -280,6 +280,46 @@ main() => describe('scope', () { d2.on(ScopeEvent.DESTROY).listen((_) => null); expect(root.apply).not.toThrow(); })); + + it('should not too eagerly create own streams', inject((RootScope root) { + var a = root.createChild({}); + var a2 = root.createChild({}); + var b = a.createChild({}); + var c = b.createChild({}); + var d = c.createChild({}); + var e = d.createChild({}); + + getStreamState() => [root.hasOwnStreams, a.hasOwnStreams, a2.hasOwnStreams, + b.hasOwnStreams, c.hasOwnStreams, d.hasOwnStreams, + e.hasOwnStreams]; + + expect(getStreamState()).toEqual([false, false, false, false, false, false, false]); + expect(root.apply).not.toThrow(); + + e.on(ScopeEvent.DESTROY).listen((_) => null); + expect(getStreamState()).toEqual([false, false, false, false, false, false, true]); + expect(root.apply).not.toThrow(); + + d.on(ScopeEvent.DESTROY).listen((_) => null); + expect(getStreamState()).toEqual([false, false, false, false, false, true, true]); + expect(root.apply).not.toThrow(); + + b.on(ScopeEvent.DESTROY).listen((_) => null); + expect(getStreamState()).toEqual([false, false, false, true, false, true, true]); + expect(root.apply).not.toThrow(); + + c.on(ScopeEvent.DESTROY).listen((_) => null); + expect(getStreamState()).toEqual([false, false, false, true, true, true, true]); + expect(root.apply).not.toThrow(); + + a.on(ScopeEvent.DESTROY).listen((_) => null); + expect(getStreamState()).toEqual([false, true, false, true, true, true, true]); + expect(root.apply).not.toThrow(); + + a2.on(ScopeEvent.DESTROY).listen((_) => null); + expect(getStreamState()).toEqual([true, true, true, true, true, true, true]); + expect(root.apply).not.toThrow(); + })); });