Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebUI: Replace getElements & getChildren #22220

Merged
merged 3 commits into from
Feb 4, 2025

Conversation

skomerko
Copy link
Contributor

This PR further reduces Mootools usage.

@skomerko skomerko changed the title WebUI: Replace getElements WebUI: Replace getElements & getChildren Jan 30, 2025
src/webui/www/private/scripts/dynamicTable.js Outdated Show resolved Hide resolved
src/webui/www/private/scripts/client.js Outdated Show resolved Hide resolved
src/webui/www/private/scripts/contextmenu.js Outdated Show resolved Hide resolved
src/webui/www/private/scripts/dynamicTable.js Outdated Show resolved Hide resolved
src/webui/www/private/scripts/dynamicTable.js Outdated Show resolved Hide resolved
@Chocobo1 Chocobo1 added the WebUI WebUI-related issues/changes label Jan 30, 2025
@skomerko skomerko force-pushed the webui-mootools-getelements branch from aa56054 to 7528e52 Compare February 1, 2025 08:46
@Chocobo1 Chocobo1 merged commit 9c2e698 into qbittorrent:master Feb 4, 2025
15 checks passed
@Chocobo1
Copy link
Member

Chocobo1 commented Feb 4, 2025

@skomerko
Thank you!

@@ -490,7 +490,8 @@ window.addEventListener("DOMContentLoaded", () => {
const categoryList = document.getElementById("categoryFilterList");
if (!categoryList)
return;
categoryList.getChildren().each(c => c.destroy());

[...categoryList.children].forEach((el) => { el.destroy(); });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, what exactly .destroy() does? That's not a native JS method (native has .remove() btw).

Also, if the only purpose of this loop is to just clear content of categoryList, simply setting categoryList.innerHTML = "" is wastly easier and more performant way.

Same applies for the rest usages of that construction.

Copy link
Contributor Author

@skomerko skomerko Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It removes event listeners, attributes etc. from children, self and detaches node it was called on from parent. There is also this PR #19969 (comment) so I decided to be careful and not touch it for now because I wasn't 100% sure if it's ok to do so.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. Event listeners should be removed along with elements, afaik. GC wipes everything not referenced inside the DOM tree or code.
https://stackoverflow.com/questions/12528049/if-a-dom-element-is-removed-are-its-listeners-also-removed-from-memory
So there should be a problematic point elsewhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. I actually found a memory leak that could explain it but wasn't 100% sure. Each context menu keeps its targets in an array and I noticed it's never cleaned up... I got a fix ready but haven't submitted it yet: master...skomerko:qBittorrent:webui-context-menu-leak

I'm not sure if it's the best way to fix it but it def works.

Copy link
Contributor

@HanabishiRecca HanabishiRecca Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh no. May I ask why this list/set is even kept around? It doesn't seem to be used anywhere.

Copy link
Contributor Author

@skomerko skomerko Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No idea, it was added like ~16 years ago :D So this memory leak probably been here since forever. But yeah it is completely unnecessary to keep references to target elements and not do anything with them. WeakSet would prevent duplicate listeners from being added to targets due to programmer error (e.g. running searchAndAddTargets n times, rather unlikey to happen but still..).

Copy link
Contributor

@HanabishiRecca HanabishiRecca Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WeakSet would prevent duplicate listeners from being added to targets due to programmer error

Why not just add some property for elements to track that? Like

addTarget(t) {
    if (t.hasEventListeners)
        return;

    // prevent long press from selecting this text
    t.style.userSelect = "none";
    t.hasEventListeners = true;
    this.setupEventListeners(t);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that's even better (I guess I was just looking for an excuse to finally use WeakSet some more:P). Want to make a PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I was just looking for an excuse to finally use WeakSet some more:P

WeakMap/WeakSet usage is almost never justified. And also slow in comparison with regular Map/Set or object properties.

Want to make a PR?

Nah, I'm too busy rn, and you are already onto it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
WebUI WebUI-related issues/changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants