mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-12-27 02:08:19 +03:00
Fix JS memory leak
The memory leak can be reproduced easily by opening two web pages of qbittorrent so that the WebUI pages are updated with full_update = true. If you have a large number of torrents, such as 100 torrents, you can observe a rapid increase in memory usage. This is caused by the incorrect usage of dispose and empty methods in the js codes and none of them garbage collect the elements. If event listeners are added to the DOM elements, those DOM elements will not be garbage collected at all event if they are not referenced or out of the scope, which will cause memory leaks. If some elements are expected to be removed, the correct way is to use destroy method instead. https://github.com/mootools/mootools-core/blob/master/Docs/Element/Element.md#element-method-dispose-elementdispose https://github.com/mootools/mootools-core/blob/master/Docs/Element/Element.md#element-method-empty-elementempty https://github.com/mootools/mootools-core/blob/master/Docs/Element/Element.md#element-method-destroy-elementdestroy Closes #19034. PR #19969.
This commit is contained in:
parent
61fae3a3ee
commit
081eace057
7 changed files with 15 additions and 18 deletions
|
@ -453,7 +453,7 @@ window.addEvent('load', function() {
|
||||||
const categoryList = $('categoryFilterList');
|
const categoryList = $('categoryFilterList');
|
||||||
if (!categoryList)
|
if (!categoryList)
|
||||||
return;
|
return;
|
||||||
categoryList.empty();
|
categoryList.getChildren().each(c => c.destroy());
|
||||||
|
|
||||||
const create_link = function(hash, text, count) {
|
const create_link = function(hash, text, count) {
|
||||||
let display_name = text;
|
let display_name = text;
|
||||||
|
@ -540,8 +540,7 @@ window.addEvent('load', function() {
|
||||||
if (tagFilterList === null)
|
if (tagFilterList === null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (tagFilterList.firstChild !== null)
|
tagFilterList.getChildren().each(c => c.destroy());
|
||||||
tagFilterList.removeChild(tagFilterList.firstChild);
|
|
||||||
|
|
||||||
const createLink = function(hash, text, count) {
|
const createLink = function(hash, text, count) {
|
||||||
const html = '<a href="#" onclick="setTagFilter(' + hash + ');return false;">'
|
const html = '<a href="#" onclick="setTagFilter(' + hash + ');return false;">'
|
||||||
|
@ -594,8 +593,7 @@ window.addEvent('load', function() {
|
||||||
if (trackerFilterList === null)
|
if (trackerFilterList === null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (trackerFilterList.firstChild !== null)
|
trackerFilterList.getChildren().each(c => c.destroy());
|
||||||
trackerFilterList.removeChild(trackerFilterList.firstChild);
|
|
||||||
|
|
||||||
const createLink = function(hash, text, count) {
|
const createLink = function(hash, text, count) {
|
||||||
const html = '<a href="#" onclick="setTrackerFilter(' + hash + ');return false;">'
|
const html = '<a href="#" onclick="setTrackerFilter(' + hash + ');return false;">'
|
||||||
|
|
|
@ -444,7 +444,7 @@ window.qBittorrent.ContextMenu = (function() {
|
||||||
|
|
||||||
updateCategoriesSubMenu: function(category_list) {
|
updateCategoriesSubMenu: function(category_list) {
|
||||||
const categoryList = $('contextCategoryList');
|
const categoryList = $('contextCategoryList');
|
||||||
categoryList.empty();
|
categoryList.getChildren().each(c => c.destroy());
|
||||||
categoryList.appendChild(new Element('li', {
|
categoryList.appendChild(new Element('li', {
|
||||||
html: '<a href="javascript:torrentNewCategoryFN();"><img src="images/list-add.svg" alt="QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]</a>'
|
html: '<a href="javascript:torrentNewCategoryFN();"><img src="images/list-add.svg" alt="QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]</a>'
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -817,8 +817,7 @@ window.qBittorrent.DynamicTable = (function() {
|
||||||
let rowPos = rows.length;
|
let rowPos = rows.length;
|
||||||
|
|
||||||
while ((rowPos < trs.length) && (trs.length > 0)) {
|
while ((rowPos < trs.length) && (trs.length > 0)) {
|
||||||
trs[trs.length - 1].dispose();
|
trs.pop().destroy();
|
||||||
trs.pop();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -840,7 +839,7 @@ window.qBittorrent.DynamicTable = (function() {
|
||||||
this.selectedRows.erase(rowId);
|
this.selectedRows.erase(rowId);
|
||||||
const tr = this.getTrByRowId(rowId);
|
const tr = this.getTrByRowId(rowId);
|
||||||
if (tr !== null) {
|
if (tr !== null) {
|
||||||
tr.dispose();
|
tr.destroy();
|
||||||
this.rows.erase(rowId);
|
this.rows.erase(rowId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -852,8 +851,7 @@ window.qBittorrent.DynamicTable = (function() {
|
||||||
this.rows.empty();
|
this.rows.empty();
|
||||||
const trs = this.tableBody.getElements('tr');
|
const trs = this.tableBody.getElements('tr');
|
||||||
while (trs.length > 0) {
|
while (trs.length > 0) {
|
||||||
trs[trs.length - 1].dispose();
|
trs.pop().destroy();
|
||||||
trs.pop();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1550,7 +1548,7 @@ window.qBittorrent.DynamicTable = (function() {
|
||||||
|
|
||||||
if (!country_code) {
|
if (!country_code) {
|
||||||
if (td.getChildren('img').length > 0)
|
if (td.getChildren('img').length > 0)
|
||||||
td.getChildren('img')[0].dispose();
|
td.getChildren('img')[0].destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,8 +50,7 @@ window.qBittorrent.PropWebseeds = (function() {
|
||||||
|
|
||||||
removeRow: function(url) {
|
removeRow: function(url) {
|
||||||
if (this.rows.has(url)) {
|
if (this.rows.has(url)) {
|
||||||
const tr = this.rows.get(url);
|
this.rows.get(url).destroy();
|
||||||
tr.dispose();
|
|
||||||
this.rows.erase(url);
|
this.rows.erase(url);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -424,4 +424,6 @@
|
||||||
|
|
||||||
return exports();
|
return exports();
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
Object.freeze(window.qBittorrent.Log);
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1854,7 +1854,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||||
// Advanced Tab
|
// Advanced Tab
|
||||||
const updateNetworkInterfaces = function(default_iface, default_iface_name) {
|
const updateNetworkInterfaces = function(default_iface, default_iface_name) {
|
||||||
const url = 'api/v2/app/networkInterfaceList';
|
const url = 'api/v2/app/networkInterfaceList';
|
||||||
$('networkInterface').empty();
|
$('networkInterface').getChildren().each(c => c.destroy());
|
||||||
new Request.JSON({
|
new Request.JSON({
|
||||||
url: url,
|
url: url,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
|
@ -1881,7 +1881,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD
|
||||||
|
|
||||||
const updateInterfaceAddresses = function(iface, default_addr) {
|
const updateInterfaceAddresses = function(iface, default_addr) {
|
||||||
const url = 'api/v2/app/networkInterfaceAddressList';
|
const url = 'api/v2/app/networkInterfaceAddressList';
|
||||||
$('optionalIPAddressToBind').empty();
|
$('optionalIPAddressToBind').getChildren().each(c => c.destroy());
|
||||||
new Request.JSON({
|
new Request.JSON({
|
||||||
url: url,
|
url: url,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
|
|
|
@ -402,13 +402,13 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$('rssDetailsView').empty();
|
$('rssDetailsView').getChildren().each(c => c.destroy());
|
||||||
rssArticleTable.updateTable(false);
|
rssArticleTable.updateTable(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const showDetails = (feedUid, articleID) => {
|
const showDetails = (feedUid, articleID) => {
|
||||||
markArticleAsRead(pathByFeedId.get(feedUid), articleID);
|
markArticleAsRead(pathByFeedId.get(feedUid), articleID);
|
||||||
$('rssDetailsView').empty();
|
$('rssDetailsView').getChildren().each(c => c.destroy());
|
||||||
let article = feedData[feedUid].filter((article) => article.id === articleID)[0];
|
let article = feedData[feedUid].filter((article) => article.id === articleID)[0];
|
||||||
if (article) {
|
if (article) {
|
||||||
$('rssDetailsView').append((() => {
|
$('rssDetailsView').append((() => {
|
||||||
|
|
Loading…
Reference in a new issue