aboutsummaryrefslogtreecommitdiffstats
path: root/src/ng/rootScope.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/ng/rootScope.js')
-rw-r--r--src/ng/rootScope.js33
1 files changed, 29 insertions, 4 deletions
diff --git a/src/ng/rootScope.js b/src/ng/rootScope.js
index a56abc5c..1bb12869 100644
--- a/src/ng/rootScope.js
+++ b/src/ng/rootScope.js
@@ -133,6 +133,7 @@ function $RootScopeProvider(){
this.$$asyncQueue = [];
this.$$postDigestQueue = [];
this.$$listeners = {};
+ this.$$listenerCount = {};
this.$$isolateBindings = {};
}
@@ -192,6 +193,7 @@ function $RootScopeProvider(){
}
child['this'] = child;
child.$$listeners = {};
+ child.$$listenerCount = {};
child.$parent = this;
child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;
child.$$prevSibling = this.$$childTail;
@@ -696,6 +698,8 @@ function $RootScopeProvider(){
this.$$destroyed = true;
if (this === $rootScope) return;
+ forEach(this.$$listenerCount, bind(null, decrementListenerCount, this));
+
if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
@@ -885,8 +889,18 @@ function $RootScopeProvider(){
}
namedListeners.push(listener);
+ var current = this;
+ do {
+ if (!current.$$listenerCount[name]) {
+ current.$$listenerCount[name] = 0;
+ }
+ current.$$listenerCount[name]++;
+ } while ((current = current.$parent));
+
+ var self = this;
return function() {
namedListeners[indexOf(namedListeners, listener)] = null;
+ decrementListenerCount(self, 1, name);
};
},
@@ -998,8 +1012,7 @@ function $RootScopeProvider(){
listeners, i, length;
//down while you can, then up and next sibling or up and next sibling until back at root
- do {
- current = next;
+ while ((current = next)) {
event.currentScope = current;
listeners = current.$$listeners[name] || [];
for (i=0, length = listeners.length; i<length; i++) {
@@ -1021,12 +1034,14 @@ function $RootScopeProvider(){
// Insanity Warning: scope depth-first traversal
// yes, this code is a bit crazy, but it works and we have tests to prove it!
// this piece should be kept in sync with the traversal in $digest
- if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {
+ // (though it differs due to having the extra check for $$listenerCount)
+ if (!(next = ((current.$$listenerCount[name] && current.$$childHead) ||
+ (current !== target && current.$$nextSibling)))) {
while(current !== target && !(next = current.$$nextSibling)) {
current = current.$parent;
}
}
- } while ((current = next));
+ }
return event;
}
@@ -1055,6 +1070,16 @@ function $RootScopeProvider(){
return fn;
}
+ function decrementListenerCount(current, count, name) {
+ do {
+ current.$$listenerCount[name] -= count;
+
+ if (current.$$listenerCount[name] === 0) {
+ delete current.$$listenerCount[name];
+ }
+ } while ((current = current.$parent));
+ }
+
/**
* function used as an initial value for watchers.
* because it's unique we can easily tell it apart from other values