aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorIgor Minar2010-10-12 05:36:38 +0800
committerMisko Hevery2010-10-13 04:37:46 +0800
commit70ff7a2639fc55936854ad04a6242a700ae71a02 (patch)
treebe82632c890b9734d50cd681737b6bad9a689d91 /src
parent7e47a2d016676f37287203f26689cce1ee1eaa0c (diff)
downloadangular.js-70ff7a2639fc55936854ad04a6242a700ae71a02.tar.bz2
fix memory leak caused by leftbehind $invalidWidgets references
- ng:switch should not clean up $invalidWidgets - $invalidWidgets should be clean up after each eval - add missing docs
Diffstat (limited to 'src')
-rw-r--r--src/services.js33
-rw-r--r--src/widgets.js2
2 files changed, 30 insertions, 5 deletions
diff --git a/src/services.js b/src/services.js
index 41755962..be73c6e9 100644
--- a/src/services.js
+++ b/src/services.js
@@ -157,18 +157,32 @@ angularService("$hover", function(browser, document) {
});
}, {inject:['$browser', '$document']});
+
+
+/* Keeps references to all invalid widgets found during validation. Can be queried to find if there
+ * are invalid widgets currently displayed
+ */
angularService("$invalidWidgets", function(){
var invalidWidgets = [];
+
+
+ /** Remove an element from the array of invalid widgets */
invalidWidgets.markValid = function(element){
var index = indexOf(invalidWidgets, element);
if (index != -1)
invalidWidgets.splice(index, 1);
};
+
+
+ /** Add an element to the array of invalid widgets */
invalidWidgets.markInvalid = function(element){
var index = indexOf(invalidWidgets, element);
if (index === -1)
invalidWidgets.push(element);
};
+
+
+ /** Return count of all invalid widgets that are currently visible */
invalidWidgets.visible = function() {
var count = 0;
foreach(invalidWidgets, function(widget){
@@ -176,24 +190,37 @@ angularService("$invalidWidgets", function(){
});
return count;
};
- invalidWidgets.clearOrphans = function() {
+
+
+ /* At the end of each eval removes all invalid widgets that are not part of the current DOM. */
+ this.$onEval(PRIORITY_LAST, function() {
for(var i = 0; i < invalidWidgets.length;) {
var widget = invalidWidgets[i];
if (isOrphan(widget[0])) {
- invalidWidgets.splice(i, 1);
+ invalidWidgets.splice(i, 1)
+ if (widget.dealoc) widget.dealoc();
} else {
i++;
}
}
- };
+ });
+
+
+ /**
+ * Traverses DOM element's (widget's) parents and considers the element to be an orphant if one of
+ * it's parents isn't the current window.document.
+ */
function isOrphan(widget) {
if (widget == window.document) return false;
var parent = widget.parentNode;
return !parent || isOrphan(parent);
}
+
return invalidWidgets;
});
+
+
function switchRouteMatcher(on, when, dstName) {
var regex = '^' + when.replace(/[\.\\\(\)\^\$]/g, "\$1") + '$',
params = [],
diff --git a/src/widgets.js b/src/widgets.js
index 127718ce..c1342943 100644
--- a/src/widgets.js
+++ b/src/widgets.js
@@ -324,8 +324,6 @@ var ngSwitch = angularWidget('ng:switch', function (element){
element.append(caseElement);
childScope.$tryEval(switchCase.change, element);
switchCase.template(caseElement, childScope);
- if (scope.$invalidWidgets)
- scope.$invalidWidgets.clearOrphans();
childScope.$init();
}
});